linux_libc_auxv/aux_var/
serialized.rs

1use crate::aux_var::{AuxVarType, ParseAuxVarTypeError};
2use core::fmt::{Debug, Formatter};
3
4type AuxVarTypeRaw = usize;
5
6/// Serialized form of an [`AuxVar`] as used in the Linux ABI.
7///
8/// In memory, each entry is a `(usize, usize)`-pair. Depending on the `key`,
9/// the `value` might be a boolean, an integer, or a pointer into the
10/// _auxv data area_.
11///
12/// [`AuxVar`]: crate::AuxVar
13#[repr(C, packed)]
14#[derive(Clone, Copy, PartialEq, Eq)]
15pub struct AuxVarRaw {
16    /// Encoded variant of [`AuxVarType`].
17    key: AuxVarTypeRaw,
18    value: usize,
19}
20
21impl AuxVarRaw {
22    /// Creates a new struct.
23    pub fn new(key: impl Into<AuxVarTypeRaw>, val: usize) -> Self {
24        Self {
25            key: key.into(),
26            value: val,
27        }
28    }
29
30    /// Tries to parse the underlying raw value as [`AuxVarType`].
31    pub fn key(&self) -> Result<AuxVarType, ParseAuxVarTypeError> {
32        self.key.try_into()
33    }
34
35    /// Returns the raw value.
36    #[must_use]
37    pub const fn value(&self) -> usize {
38        self.value
39    }
40}
41
42impl Debug for AuxVarRaw {
43    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
44        if self.key().unwrap().value_in_data_area() {
45            write!(f, "{:?}: @ 0x{:x?}", self.key(), self.value())
46        } else {
47            write!(f, "{:?}: {:x?}", self.key(), self.value())
48        }
49    }
50}
51
52#[cfg(test)]
53mod tests {
54
55    use super::*;
56
57    #[test]
58    fn test_serialized_aux_entry_size() {
59        #[cfg(target_arch = "x86")]
60        assert_eq!(size_of::<AuxVarRaw>(), 8);
61        #[cfg(target_arch = "x86_64")]
62        assert_eq!(size_of::<AuxVarRaw>(), 16);
63
64        // Generic, on all platforms:
65        assert_eq!(size_of::<AuxVarRaw>(), 2 * size_of::<usize>());
66    }
67}