shapely_core/
scalar_contents.rs

1use crate::Scalar;
2use std::borrow::Cow;
3use std::fmt::{self, Display, Formatter};
4
5/// Represents the contents of a scalar value with a lifetime.
6/// This allows safe access to the actual values stored in memory.
7#[derive(Debug, PartialEq)]
8#[non_exhaustive]
9pub enum ScalarContents<'a> {
10    /// A string value
11    String(Cow<'a, str>),
12
13    /// A byte array
14    Bytes(Cow<'a, [u8]>),
15
16    /// An i8 value
17    I8(i8),
18
19    /// An i16 value
20    I16(i16),
21
22    /// An i32 value
23    I32(i32),
24
25    /// An i64 value
26    I64(i64),
27
28    /// An i128 value
29    I128(i128),
30
31    /// A u8 value
32    U8(u8),
33
34    /// A u16 value
35    U16(u16),
36
37    /// A u32 value
38    U32(u32),
39
40    /// A u64 value
41    U64(u64),
42
43    /// A u128 value
44    U128(u128),
45
46    /// An f32 value
47    F32(f32),
48
49    /// An f64 value
50    F64(f64),
51
52    /// A boolean value
53    Boolean(bool),
54
55    /// Nothing (unit type)
56    Nothing,
57
58    /// Unknown scalar type
59    Unknown,
60}
61
62impl Display for ScalarContents<'_> {
63    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
64        match self {
65            ScalarContents::String(s) => write!(f, "\"{}\"", s.escape_debug()),
66            ScalarContents::Bytes(b) => {
67                write!(f, "b\"")?;
68                for &byte in b.iter().take(64) {
69                    write!(f, "\\x{:02x}", byte)?;
70                }
71                if b.len() > 64 {
72                    write!(f, "...")?;
73                }
74                write!(f, "\"")
75            }
76            ScalarContents::I8(v) => write!(f, "{}", v),
77            ScalarContents::I16(v) => write!(f, "{}", v),
78            ScalarContents::I32(v) => write!(f, "{}", v),
79            ScalarContents::I64(v) => write!(f, "{}", v),
80            ScalarContents::I128(v) => write!(f, "{}", v),
81            ScalarContents::U8(v) => write!(f, "{}", v),
82            ScalarContents::U16(v) => write!(f, "{}", v),
83            ScalarContents::U32(v) => write!(f, "{}", v),
84            ScalarContents::U64(v) => write!(f, "{}", v),
85            ScalarContents::U128(v) => write!(f, "{}", v),
86            ScalarContents::F32(v) => write!(f, "{}", v),
87            ScalarContents::F64(v) => write!(f, "{}", v),
88            ScalarContents::Boolean(v) => write!(f, "{}", v),
89            ScalarContents::Nothing => write!(f, "()"),
90            ScalarContents::Unknown => write!(f, "<unknown>"),
91        }
92    }
93}
94
95impl Scalar {
96    /// Get the contents of a scalar value from a memory location.
97    ///
98    /// # Safety
99    ///
100    /// This function is unsafe because it reads from raw memory.
101    /// The caller must ensure that:
102    /// 1. The pointer points to a valid, initialized value of the correct type
103    /// 2. The memory is properly aligned for the type
104    /// 3. The memory is not mutated while the returned ScalarContents is in use
105    pub unsafe fn get_contents<'a>(&self, ptr: *const u8) -> ScalarContents<'a> {
106        // In Rust 2024, unsafe operations need to be in an unsafe block
107        // even if they're in an unsafe function
108        unsafe {
109            match self {
110                Scalar::String => {
111                    // Cast the pointer to a reference to String
112                    let string_ref = &*(ptr as *const String);
113                    ScalarContents::String(Cow::Borrowed(string_ref.as_str()))
114                }
115                Scalar::Bytes => {
116                    // Cast the pointer to a reference to Vec<u8>
117                    let bytes_ref = &*(ptr as *const Vec<u8>);
118                    ScalarContents::Bytes(Cow::Borrowed(bytes_ref.as_slice()))
119                }
120                Scalar::I8 => ScalarContents::I8(*(ptr as *const i8)),
121                Scalar::I16 => ScalarContents::I16(*(ptr as *const i16)),
122                Scalar::I32 => ScalarContents::I32(*(ptr as *const i32)),
123                Scalar::I64 => ScalarContents::I64(*(ptr as *const i64)),
124                Scalar::I128 => ScalarContents::I128(*(ptr as *const i128)),
125                Scalar::U8 => ScalarContents::U8(*ptr),
126                Scalar::U16 => ScalarContents::U16(*(ptr as *const u16)),
127                Scalar::U32 => ScalarContents::U32(*(ptr as *const u32)),
128                Scalar::U64 => ScalarContents::U64(*(ptr as *const u64)),
129                Scalar::U128 => ScalarContents::U128(*(ptr as *const u128)),
130                Scalar::F32 => ScalarContents::F32(*(ptr as *const f32)),
131                Scalar::F64 => ScalarContents::F64(*(ptr as *const f64)),
132                Scalar::Boolean => ScalarContents::Boolean(*(ptr as *const bool)),
133                Scalar::Nothing => ScalarContents::Nothing,
134            }
135        }
136    }
137}
138
139#[cfg(test)]
140mod tests {
141    use super::*;
142
143    #[test]
144    fn test_scalar_contents_display() {
145        assert_eq!(
146            format!("{}", ScalarContents::String(Cow::Borrowed("hello"))),
147            "\"hello\""
148        );
149        assert_eq!(format!("{}", ScalarContents::I32(42)), "42");
150        assert_eq!(format!("{}", ScalarContents::Boolean(true)), "true");
151        assert_eq!(format!("{}", ScalarContents::Nothing), "()");
152    }
153}