changeset 79:2128123b9406

Format (oops!) and make some fun and/or stupid conversions available.
author Paul Fisher <paul@pfish.zone>
date Sun, 08 Jun 2025 04:21:58 -0400
parents 002adfb98c5c
children 5aa1a010f1e8
files src/conv.rs src/libpam/answer.rs src/libpam/memory.rs src/libpam/question.rs
diffstat 4 files changed, 52 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/src/conv.rs	Sun Jun 08 03:48:40 2025 -0400
+++ b/src/conv.rs	Sun Jun 08 04:21:58 2025 -0400
@@ -160,55 +160,47 @@
 );
 
 /// Owned binary data.
-///
-/// You can take ownership of the stored data by destructuring it:
-/// 
-/// ```
-/// # use nonstick::BinaryData;
-/// # let binary_data = BinaryData::new(vec![99, 88, 77], 66);
-/// let (data, data_type) = binary_data.into();
-/// ```
 #[derive(Debug, Default, PartialEq)]
 pub struct BinaryData {
-    data: Vec<u8>,
-    data_type: u8,
+    /// The data.
+    pub data: Vec<u8>,
+    /// A tag describing the type of the data, to use how you please.
+    pub data_type: u8,
 }
 
 impl BinaryData {
     /// Creates a `BinaryData` with the given contents and type.
     pub fn new(data: impl Into<Vec<u8>>, data_type: u8) -> Self {
-        Self { data: data.into(), data_type }
+        Self {
+            data: data.into(),
+            data_type,
+        }
+    }
+}
+
+impl<IV: Into<Vec<u8>>> From<(IV, u8)> for BinaryData {
+    /// Makes a new BinaryData from borrowed data.
+    fn from((data, data_type): (IV, u8)) -> Self {
+        Self {
+            data: data.into(),
+            data_type,
+        }
     }
 }
 
 impl From<BinaryData> for (Vec<u8>, u8) {
+    /// Easy destructuring.
     fn from(value: BinaryData) -> Self {
         (value.data, value.data_type)
     }
 }
 
-impl From<(&'_[u8], u8)> for BinaryData {
-    fn from((data, data_type): (&'_[u8], u8)) -> Self {
-        Self {
-            data: data.to_vec(),
-            data_type,
-        }
-    }
-}
-
-impl<'a> From<&'a BinaryData> for (&'a[u8], u8) {
+impl<'a> From<&'a BinaryData> for (&'a [u8], u8) {
     fn from(value: &'a BinaryData) -> Self {
         (&value.data, value.data_type)
     }
 }
 
-impl From<BinaryData> for Vec<u8> {
-    /// Takes ownership of the data stored herein.
-    fn from(value: BinaryData) -> Self {
-        value.data
-    }
-}
-
 q_and_a!(
     InfoMsg<'a, Q = &'a str, A = ()>,
     Message::Info,
@@ -517,7 +509,7 @@
         conv.communicate(&[radio.message(), bin.message()]);
 
         assert_eq!("zero", radio.answer().unwrap());
-        assert_eq!(BinaryData::new(vec![5, 5, 5], 5), bin.answer().unwrap());
+        assert_eq!(BinaryData::from(([5, 5, 5], 5)), bin.answer().unwrap());
     }
 
     fn test_mux() {
@@ -546,7 +538,7 @@
                         }
                         Message::BinaryPrompt(prompt) => {
                             assert_eq!((&[1, 2, 3][..], 69), prompt.question());
-                            prompt.set_answer(Ok(BinaryData::new(vec![3, 2, 1], 42)))
+                            prompt.set_answer(Ok(BinaryData::from((&[3, 2, 1], 42))))
                         }
                         Message::RadioPrompt(ask) => {
                             assert_eq!("radio?", ask.question());
--- a/src/libpam/answer.rs	Sun Jun 08 03:48:40 2025 -0400
+++ b/src/libpam/answer.rs	Sun Jun 08 04:21:58 2025 -0400
@@ -232,8 +232,8 @@
     use super::{Answer, Answers, BinaryAnswer, TextAnswer};
     use crate::conv::{BinaryQAndA, ErrorMsg, InfoMsg, MaskedQAndA, QAndA, RadioQAndA};
     use crate::libpam::conversation::OwnedMessage;
+    use crate::libpam::memory;
     use crate::BinaryData;
-    use crate::libpam::memory;
 
     #[test]
     fn test_round_trip() {
@@ -295,7 +295,7 @@
     #[test]
     fn test_text_answer() {
         let answer_ptr: *mut Answer = memory::calloc(1);
-        let answer = unsafe {&mut *answer_ptr};
+        let answer = unsafe { &mut *answer_ptr };
         TextAnswer::fill(answer, "hello").unwrap();
         let zeroth_text = unsafe { TextAnswer::upcast(answer) };
         let data = zeroth_text.contents().expect("valid");
@@ -310,7 +310,7 @@
     fn test_binary_answer() {
         let answer_ptr: *mut Answer = memory::calloc(1);
         let answer = unsafe { &mut *answer_ptr };
-        let real_data = BinaryData::new(vec![1, 2, 3, 4, 5, 6, 7, 8], 9);
+        let real_data = BinaryData::new([1, 2, 3, 4, 5, 6, 7, 8], 9);
         BinaryAnswer::fill(answer, (&real_data).into()).expect("alloc should succeed");
         let bin_answer = unsafe { BinaryAnswer::upcast(answer) };
         assert_eq!(real_data, bin_answer.data().into());
@@ -324,9 +324,8 @@
     fn test_binary_answer_too_big() {
         let big_data: Vec<u8> = vec![0xFFu8; 10_000_000_000];
         let answer_ptr: *mut Answer = memory::calloc(1);
-        let answer = unsafe {&mut*answer_ptr};
-        BinaryAnswer::fill(answer, (&big_data, 100))
-            .expect_err("this is too big!");
+        let answer = unsafe { &mut *answer_ptr };
+        BinaryAnswer::fill(answer, (&big_data, 100)).expect_err("this is too big!");
         answer.free_contents();
         unsafe { memory::free(answer) }
     }
--- a/src/libpam/memory.rs	Sun Jun 08 03:48:40 2025 -0400
+++ b/src/libpam/memory.rs	Sun Jun 08 04:21:58 2025 -0400
@@ -87,6 +87,7 @@
     if data.contains(&0) {
         return Err(ErrorCode::ConversationError);
     }
+    // +1 for the null terminator
     let data_alloc: *mut c_char = calloc(data.len() + 1);
     // SAFETY: we just allocated this and we have enough room.
     unsafe {
@@ -158,29 +159,37 @@
     }
 }
 
-impl<'a> From<&'a CBinaryData> for (&'a[u8], u8) {
+impl<'a> From<&'a CBinaryData> for (&'a [u8], u8) {
     fn from(value: &'a CBinaryData) -> Self {
-        (unsafe { slice::from_raw_parts(value.data.as_ptr(), value.length()) },
-            value.data_type        )
+        (
+            unsafe { slice::from_raw_parts(value.data.as_ptr(), value.length()) },
+            value.data_type,
+        )
+    }
+}
+
+impl From<&'_ CBinaryData> for BinaryData {
+    fn from(value: &'_ CBinaryData) -> Self {
+        // This is a dumb trick but I like it because it is simply the presence
+        // of `.map(|z: (_, _)| z)` in the middle of this that gives
+        // type inference the hint it needs to make this work.
+        let [ret] = [value].map(Into::into).map(|z: (_, _)| z).map(Into::into);
+        ret
     }
 }
 
 impl From<Option<&'_ CBinaryData>> for BinaryData {
     fn from(value: Option<&CBinaryData>) -> Self {
-        // This is a dumb trick but I like it because it is simply the presence
-        // of `.map(|(x, y)| (x, y))` in the middle of this that gives
-        // type inference the hint it needs to make this work.
-        value
-            .map(Into::into)
-            .map(|(data, data_type)| (data, data_type))
-            .map(Into::into)
-            .unwrap_or_default()
+        value.map(Into::into).unwrap_or_default()
     }
 }
 
 #[cfg(test)]
 mod tests {
-    use super::{free, ErrorCode, CString, copy_pam_string, malloc_str, option_cstr, prompt_ptr, zero_c_string};
+    use super::{
+        copy_pam_string, free, malloc_str, option_cstr, prompt_ptr, zero_c_string, CString,
+        ErrorCode,
+    };
     #[test]
     fn test_strings() {
         let str = malloc_str("hello there").unwrap();
--- a/src/libpam/question.rs	Sun Jun 08 03:48:40 2025 -0400
+++ b/src/libpam/question.rs	Sun Jun 08 04:21:58 2025 -0400
@@ -317,13 +317,10 @@
         Message::RadioPrompt(p) => alloc(Style::RadioType, p.question()),
         Message::Error(p) => alloc(Style::ErrorMsg, p.question()),
         Message::Info(p) => alloc(Style::TextInfo, p.question()),
-        Message::BinaryPrompt(p) => {
-            let q = p.question();
-            Ok((
-                Style::BinaryPrompt,
-                CBinaryData::alloc(q)?.cast(),
-            ))
-        }
+        Message::BinaryPrompt(p) => Ok((
+            Style::BinaryPrompt,
+            CBinaryData::alloc(p.question())?.cast(),
+        )),
     }
 }