1use alloc::boxed::Box;
2use alloc::string::String;
3use alloc::vec::Vec;
4use core::fmt;
5use core::str::FromStr;
6
7use crate::helper::{compare_encodings, Helper, NestingLevel};
8use crate::parse::{ErrorKind, ParseError, Parser};
9use crate::Encoding;
10
11#[derive(Clone, Debug, PartialEq, Eq, Hash)]
29#[non_exhaustive] pub enum EncodingBox {
31 Char,
33 Short,
35 Int,
37 Long,
39 LongLong,
41 UChar,
43 UShort,
45 UInt,
47 ULong,
49 ULongLong,
51 Float,
53 Double,
55 LongDouble,
57 FloatComplex,
59 DoubleComplex,
61 LongDoubleComplex,
63 Bool,
65 Void,
67 String,
69 Object,
71 Block,
73 Class,
75 Sel,
77 Unknown,
79 BitField(u8, Option<Box<(u64, Self)>>),
81 Pointer(Box<Self>),
83 Atomic(Box<Self>),
85 Array(u64, Box<Self>),
87 Struct(String, Vec<Self>),
89 Union(String, Vec<Self>),
91 None,
93}
94
95impl EncodingBox {
96 pub const C_LONG: Self = match Encoding::C_LONG {
98 Encoding::Long => Self::Long,
99 Encoding::LongLong => Self::LongLong,
100 _ => unreachable!(),
101 };
102
103 pub const C_ULONG: Self = match Encoding::C_ULONG {
105 Encoding::ULong => Self::ULong,
106 Encoding::ULongLong => Self::ULongLong,
107 _ => unreachable!(),
108 };
109
110 pub fn from_start_of_str(s: &mut &str) -> Result<Self, ParseError> {
122 let mut parser = Parser::new(s);
123 parser.strip_leading_qualifiers();
124
125 match parser.parse_encoding_or_none() {
126 Err(ErrorKind::Unknown(b'0'..=b'9')) => {
127 let remaining = parser.remaining();
128 *s = remaining;
129
130 Ok(EncodingBox::None)
131 }
132 Err(err) => Err(ParseError::new(parser, err)),
133 Ok(encoding) => {
134 let remaining = parser.remaining();
135 *s = remaining;
136
137 Ok(encoding)
138 }
139 }
140 }
141}
142
143impl fmt::Display for EncodingBox {
145 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146 Helper::from_box(self).fmt(f, NestingLevel::new())
147 }
148}
149
150impl PartialEq<Encoding> for EncodingBox {
151 fn eq(&self, other: &Encoding) -> bool {
152 compare_encodings(self, other, NestingLevel::new(), true)
153 }
154}
155
156impl PartialEq<EncodingBox> for Encoding {
157 fn eq(&self, other: &EncodingBox) -> bool {
158 other.eq(self)
159 }
160}
161
162impl FromStr for EncodingBox {
163 type Err = ParseError;
164
165 fn from_str(s: &str) -> Result<Self, Self::Err> {
166 let mut parser = Parser::new(s);
167 parser.strip_leading_qualifiers();
168
169 parser
170 .parse_encoding_or_none()
171 .and_then(|enc| parser.expect_empty().map(|()| enc))
172 .map_err(|err| ParseError::new(parser, err))
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179 use alloc::string::ToString;
180 use alloc::vec;
181
182 #[test]
183 fn eq_encodings() {
184 let enc1 = Encoding::Char;
185 let enc2 = EncodingBox::Char;
186 let enc3 = EncodingBox::String;
187 assert_eq!(enc1, enc2);
188 assert_ne!(enc1, enc3);
189 }
190
191 #[test]
192 fn eq_complex_encodings() {
193 let enc1 = Encoding::Atomic(&Encoding::Struct(
194 "test",
195 &[Encoding::Array(2, &Encoding::Int)],
196 ));
197 let enc2 = EncodingBox::Atomic(Box::new(EncodingBox::Struct(
198 "test".to_string(),
199 vec![EncodingBox::Array(2, Box::new(EncodingBox::Int))],
200 )));
201 let enc3 = EncodingBox::Atomic(Box::new(EncodingBox::Struct(
202 "test".to_string(),
203 vec![EncodingBox::Array(2, Box::new(EncodingBox::Char))],
204 )));
205 assert_eq!(enc1, enc2);
206 assert_ne!(enc1, enc3);
207 }
208
209 #[test]
210 fn struct_nested_in_pointer() {
211 let enc1 = EncodingBox::Struct("test".to_string(), vec![EncodingBox::Char]);
212 let enc2 = EncodingBox::Struct("test".to_string(), vec![EncodingBox::Int]);
213 const ENC3A: Encoding = Encoding::Struct("test", &[Encoding::Char]);
214 assert_ne!(enc1, enc2);
215 assert!(ENC3A.equivalent_to_box(&enc1));
216 assert!(!ENC3A.equivalent_to_box(&enc2));
217
218 let enc1 = EncodingBox::Pointer(Box::new(enc1));
219 let enc2 = EncodingBox::Pointer(Box::new(enc2));
220 const ENC3B: Encoding = Encoding::Pointer(&ENC3A);
221 assert_ne!(enc1, enc2);
222 assert!(ENC3B.equivalent_to_box(&enc1));
223 assert!(!ENC3B.equivalent_to_box(&enc2));
224
225 let enc1 = EncodingBox::Pointer(Box::new(enc1));
226 let enc2 = EncodingBox::Pointer(Box::new(enc2));
227 const ENC3C: Encoding = Encoding::Pointer(&ENC3B);
228 assert_ne!(enc1, enc2);
229 assert!(ENC3C.equivalent_to_box(&enc1));
230 assert!(ENC3C.equivalent_to_box(&enc2), "now they're equivalent");
231 }
232
233 #[test]
234 fn parse_atomic_struct() {
235 let expected = EncodingBox::Atomic(Box::new(EncodingBox::Atomic(Box::new(
236 EncodingBox::Struct("a".into(), vec![]),
237 ))));
238 let actual = EncodingBox::from_str("AA{a=}").unwrap();
239 assert_eq!(expected, actual);
240 assert_eq!(expected.to_string(), "AA{a}");
241
242 let actual = EncodingBox::from_str("AA{a}").unwrap();
243 assert_eq!(expected, actual);
244 assert_eq!(expected.to_string(), "AA{a}");
245 }
246
247 #[test]
248 fn parse_part_of_string() {
249 let mut s = "{a}cb0i16";
250
251 let expected = EncodingBox::Struct("a".into(), vec![]);
252 let actual = EncodingBox::from_start_of_str(&mut s).unwrap();
253 assert_eq!(expected, actual);
254
255 let expected = EncodingBox::Char;
256 let actual = EncodingBox::from_start_of_str(&mut s).unwrap();
257 assert_eq!(expected, actual);
258
259 let expected = EncodingBox::BitField(16, Some(Box::new((0, EncodingBox::Int))));
260 let actual = EncodingBox::from_start_of_str(&mut s).unwrap();
261 assert_eq!(expected, actual);
262
263 assert_eq!(s, "");
264 }
265}