Mercurial > crates > nonstick
comparison src/libpam/conversation.rs @ 78:002adfb98c5c
Rename files, reorder structs, remove annoying BorrowedBinaryData type.
This is basically a cleanup change. Also it adds tests.
- Renames the files with Questions and Answers to question and answer.
- Reorders the structs in those files to put the important ones first.
- Removes the BorrowedBinaryData type. It was a bad idea all along.
Instead, we just use (&[u8], u8).
- Adds some tests because I just can't help myself.
| author | Paul Fisher <paul@pfish.zone> |
|---|---|
| date | Sun, 08 Jun 2025 03:48:40 -0400 |
| parents | 351bdc13005e |
| children | 5aa1a010f1e8 |
comparison
equal
deleted
inserted
replaced
| 77:351bdc13005e | 78:002adfb98c5c |
|---|---|
| 1 use crate::conv::{ | 1 use crate::conv::{ |
| 2 BinaryQAndA, Conversation, ErrorMsg, InfoMsg, MaskedQAndA, Message, QAndA, | 2 BinaryQAndA, Conversation, ErrorMsg, InfoMsg, MaskedQAndA, Message, QAndA, RadioQAndA, |
| 3 RadioQAndA, | |
| 4 }; | 3 }; |
| 4 use crate::libpam::answer::{Answer, Answers, BinaryAnswer, TextAnswer}; | |
| 5 use crate::libpam::memory::Immovable; | 5 use crate::libpam::memory::Immovable; |
| 6 use crate::libpam::message::{Indirect, Questions}; | 6 use crate::libpam::question::{Indirect, Questions}; |
| 7 use crate::libpam::response::{Answer, Answers, BinaryAnswer, TextAnswer}; | |
| 8 use crate::ErrorCode; | 7 use crate::ErrorCode; |
| 9 use crate::Result; | 8 use crate::Result; |
| 10 use std::ffi::c_int; | 9 use std::ffi::c_int; |
| 11 use std::iter; | 10 use std::iter; |
| 12 use std::marker::PhantomData; | 11 use std::marker::PhantomData; |
| 74 let answers_ptr = answers.as_mut().ok_or(ErrorCode::ConversationError)?; | 73 let answers_ptr = answers.as_mut().ok_or(ErrorCode::ConversationError)?; |
| 75 | 74 |
| 76 // Build our owned list of Q&As from the questions we've been asked | 75 // Build our owned list of Q&As from the questions we've been asked |
| 77 let messages: Vec<OwnedMessage> = indirect | 76 let messages: Vec<OwnedMessage> = indirect |
| 78 .iter(count as usize) | 77 .iter(count as usize) |
| 79 .map(OwnedMessage::try_from) | 78 .map(TryInto::try_into) |
| 80 .collect::<Result<_>>() | 79 .collect::<Result<_>>() |
| 81 .map_err(|_| ErrorCode::ConversationError)?; | 80 .map_err(|_| ErrorCode::ConversationError)?; |
| 82 // Borrow all those Q&As and ask them | 81 // Borrow all those Q&As and ask them |
| 83 let borrowed: Vec<Message> = messages.iter().map(Into::into).collect(); | 82 let borrowed: Vec<Message> = messages.iter().map(Into::into).collect(); |
| 84 conv.communicate(&borrowed); | 83 conv.communicate(&borrowed); |
| 93 } | 92 } |
| 94 | 93 |
| 95 impl Conversation for LibPamConversation<'_> { | 94 impl Conversation for LibPamConversation<'_> { |
| 96 fn communicate(&mut self, messages: &[Message]) { | 95 fn communicate(&mut self, messages: &[Message]) { |
| 97 let internal = || { | 96 let internal = || { |
| 98 let mut msgs_to_send = Questions::alloc(messages.len()); | 97 let questions = Questions::new(messages)?; |
| 99 for (dst, src) in iter::zip(msgs_to_send.iter_mut(), messages.iter()) { | |
| 100 dst.fill(src).map_err(|_| ErrorCode::ConversationError)? | |
| 101 } | |
| 102 let mut response_pointer = std::ptr::null_mut(); | 98 let mut response_pointer = std::ptr::null_mut(); |
| 103 // SAFETY: We're calling into PAM with valid everything. | 99 // SAFETY: We're calling into PAM with valid everything. |
| 104 let result = unsafe { | 100 let result = unsafe { |
| 105 (self.callback)( | 101 (self.callback)( |
| 106 messages.len() as c_int, | 102 messages.len() as c_int, |
| 107 msgs_to_send.indirect(), | 103 questions.indirect(), |
| 108 &mut response_pointer, | 104 &mut response_pointer, |
| 109 self.appdata, | 105 self.appdata, |
| 110 ) | 106 ) |
| 111 }; | 107 }; |
| 112 ErrorCode::result_from(result)?; | 108 ErrorCode::result_from(result)?; |
| 126 } | 122 } |
| 127 } | 123 } |
| 128 } | 124 } |
| 129 | 125 |
| 130 /// Like [`Message`], but this time we own the contents. | 126 /// Like [`Message`], but this time we own the contents. |
| 127 #[derive(Debug)] | |
| 131 pub enum OwnedMessage<'a> { | 128 pub enum OwnedMessage<'a> { |
| 132 MaskedPrompt(MaskedQAndA<'a>), | 129 MaskedPrompt(MaskedQAndA<'a>), |
| 133 Prompt(QAndA<'a>), | 130 Prompt(QAndA<'a>), |
| 134 RadioPrompt(RadioQAndA<'a>), | 131 RadioPrompt(RadioQAndA<'a>), |
| 135 BinaryPrompt(BinaryQAndA<'a>), | 132 BinaryPrompt(BinaryQAndA<'a>), |
| 155 /// # Safety | 152 /// # Safety |
| 156 /// | 153 /// |
| 157 /// You are responsible for ensuring that the src-dst pair matches. | 154 /// You are responsible for ensuring that the src-dst pair matches. |
| 158 unsafe fn convert(msg: &Message, resp: &mut Answer) { | 155 unsafe fn convert(msg: &Message, resp: &mut Answer) { |
| 159 macro_rules! fill_text { | 156 macro_rules! fill_text { |
| 160 ($dst:ident, $src:ident) => {{let text_resp = unsafe {TextAnswer::upcast($src)}; | 157 ($dst:ident, $src:ident) => {{ |
| 161 $dst.set_answer(text_resp.contents().map(Into::into));}} | 158 let text_resp = unsafe { TextAnswer::upcast($src) }; |
| 162 } | 159 $dst.set_answer(text_resp.contents().map(Into::into)); |
| 160 }}; | |
| 161 } | |
| 163 match *msg { | 162 match *msg { |
| 164 Message::MaskedPrompt(qa) => fill_text!(qa, resp), | 163 Message::MaskedPrompt(qa) => fill_text!(qa, resp), |
| 165 Message::Prompt(qa) => fill_text!(qa, resp), | 164 Message::Prompt(qa) => fill_text!(qa, resp), |
| 166 Message::RadioPrompt(qa) => fill_text!(qa, resp), | 165 Message::RadioPrompt(qa) => fill_text!(qa, resp), |
| 167 Message::Error(m) => m.set_answer(Ok(())), | 166 Message::Error(m) => m.set_answer(Ok(())), |
