comparison libpam-sys/src/structs.rs @ 109:bb465393621f

Minor cleanup and reorg. - Use those nice new macros we just implemented. - Straighten out the macro file. - Move the `BinaryPayload` into `structs.rs`, leaving helpers behind.
author Paul Fisher <paul@pfish.zone>
date Sat, 28 Jun 2025 02:49:35 -0400
parents libpam-sys/src/helpers.rs@49d9e2b5c189
children
comparison
equal deleted inserted replaced
108:e97534be35e3 109:bb465393621f
1 use core::marker::{PhantomData, PhantomPinned};
2 use core::slice;
3
4 /// The structure of the "binary message" payload for the `PAM_BINARY_PROMPT`
5 /// extension from Linux-PAM.
6 pub struct BinaryPayload {
7 /// The total byte size of the message, including this header,
8 /// as a u32 in network byte order (big endian).
9 pub total_bytes_u32be: [u8; 4],
10 /// A tag used to provide some kind of hint as to what the data is.
11 /// Its meaning is undefined.
12 pub data_type: u8,
13 /// Where the data itself would start, used as a marker to make this
14 /// not [`Unpin`] (since it is effectively an intrusive data structure
15 /// pointing to immediately after itself).
16 pub _marker: PhantomData<PhantomPinned>,
17 }
18
19 impl BinaryPayload {
20 /// The most data it's possible to put into a [`BinaryPayload`].
21 pub const MAX_SIZE: usize = (u32::MAX - 5) as usize;
22
23 /// Fills in the provided buffer with the given data.
24 ///
25 /// This uses [`copy_from_slice`](slice::copy_from_slice) internally,
26 /// so `buf` must be exactly 5 bytes longer than `data`, or this function
27 /// will panic.
28 pub fn fill(buf: &mut [u8], data_type: u8, data: &[u8]) {
29 let ptr: *mut Self = buf.as_mut_ptr().cast();
30 // SAFETY: We're given a slice, which always has a nonzero pointer.
31 let me = unsafe { ptr.as_mut().unwrap_unchecked() };
32 me.total_bytes_u32be = u32::to_be_bytes(buf.len() as u32);
33 me.data_type = data_type;
34 buf[5..].copy_from_slice(data)
35 }
36
37 /// The size of the message contained in the buffer.
38 fn len(&self) -> usize {
39 self.total_bytes().saturating_sub(5)
40 }
41
42 /// The total storage needed for the message, including header.
43 pub fn total_bytes(&self) -> usize {
44 u32::from_be_bytes(self.total_bytes_u32be) as usize
45 }
46
47 /// Gets the contents of the BinaryMessage stored at the given pointer.
48 ///
49 /// The returned data slice is borrowed from where the pointer points to.
50 ///
51 /// # Safety
52 ///
53 /// - The pointer must point to a valid `BinaryPayload`.
54 /// - The borrowed data must not outlive the validity of this pointer.
55 pub unsafe fn contents<'a>(ptr: *const Self) -> (u8, &'a [u8]) {
56 let header: &Self = ptr.as_ref().unwrap_unchecked();
57 let typ = header.data_type;
58 (
59 typ,
60 slice::from_raw_parts(ptr.cast::<u8>().offset(5), header.len()),
61 )
62 }
63 }