imessage_database/util/
typedstream.rs1use crabstep::{OutputData, PropertyIterator, deserializer::iter::Property};
6
7#[derive(Debug)]
9pub struct TypeLengthPair {
10 pub type_index: i64,
12 pub length: u64,
14}
15
16#[inline(always)]
19pub fn as_type_length_pair<'a>(property: &'a mut Property<'a, 'a>) -> Option<TypeLengthPair> {
20 if let Property::Group(group) = property {
21 let mut iter = group.iter();
22 if let Some(Property::Primitive(OutputData::SignedInteger(type_index))) = iter.next()
23 && let Some(Property::Primitive(OutputData::UnsignedInteger(length))) = iter.next()
24 {
25 return Some(TypeLengthPair {
26 type_index: *type_index,
27 length: *length,
28 });
29 }
30 }
31
32 None
33}
34
35#[must_use]
38#[inline(always)]
39pub fn as_signed_integer(property: &Property<'_, '_>) -> Option<i64> {
40 if let Property::Group(group) = property {
41 let mut iter = group.iter();
42 let val = iter.next()?;
43 if let Property::Primitive(OutputData::SignedInteger(value)) = val {
44 return Some(*value);
45 } else if let Property::Object { name, data, .. } = val
46 && *name == "NSNumber"
47 {
48 let mut data_iter = data.clone();
50 return as_signed_integer(&data_iter.next()?);
51 }
52 }
53 None
54}
55
56#[must_use]
59#[inline(always)]
60pub fn as_unsigned_integer<'a>(property: &'a Property<'a, 'a>) -> Option<u64> {
61 if let Property::Group(group) = property {
62 let mut iter = group.iter();
63 let val = iter.next()?;
64 if let Property::Primitive(OutputData::UnsignedInteger(value)) = val {
65 return Some(*value);
66 } else if let Property::Object { name, data, .. } = val
67 && *name == "NSNumber"
68 {
69 let mut data_iter = data.clone();
71 return as_unsigned_integer(&data_iter.next()?);
72 }
73 }
74 None
75}
76
77#[must_use]
80#[inline(always)]
81pub fn as_float<'a>(property: &'a Property<'a, 'a>) -> Option<f64> {
82 if let Property::Group(group) = property {
83 let mut iter = group.iter();
84 let val = iter.next()?;
85 if let Property::Primitive(OutputData::Double(value)) = val {
86 return Some(*value);
87 } else if let Property::Object { name, data, .. } = val
88 && *name == "NSNumber"
89 {
90 let mut data_iter = data.clone();
92 return as_float(&data_iter.next()?);
93 }
94 }
95 None
96}
97
98#[inline(always)]
101pub fn as_nsstring<'a>(property: &'a mut Property<'a, 'a>) -> Option<&'a str> {
102 if let Property::Group(group) = property {
103 let mut iter = group.iter_mut();
104 if let Some(Property::Object { name, data, .. }) = iter.next()
105 && (*name == "NSString" || *name == "NSAttributedString" || *name == "NSMutableString")
106 && let Some(Property::Group(prim)) = data.next()
107 && let Some(Property::Primitive(OutputData::String(s))) = prim.first()
108 {
109 return Some(s);
110 }
111 }
112 None
113}
114
115#[inline(always)]
118pub fn as_ns_dictionary<'a>(
119 property: &'a mut Property<'a, 'a>,
120) -> Option<&'a mut PropertyIterator<'a, 'a>> {
121 if let Property::Group(group) = property {
122 let mut iter = group.iter_mut();
123 if let Some(Property::Object {
124 class: _,
125 name,
126 data,
127 }) = iter.next()
128 && *name == "NSDictionary"
129 {
130 return Some(data);
131 }
132 }
133
134 None
135}
136
137#[inline(always)]
141pub fn as_nsurl<'a>(property: &'a mut Property<'a, 'a>) -> Option<&'a str> {
142 if let Property::Group(groups) = property {
144 for level1 in groups.iter_mut() {
145 if let Property::Object {
147 name,
148 data: url_data,
149 ..
150 } = level1
151 {
152 if *name != "NSURL" {
153 continue;
154 }
155 for level2 in url_data {
157 if let Property::Group(mut inner) = level2 {
158 for level3 in &mut inner {
159 if let Property::Object {
161 name,
162 data: str_data,
163 ..
164 } = level3
165 {
166 if *name != "NSString" {
167 continue;
168 }
169 for level4 in str_data {
171 if let Property::Group(bottom) = level4 {
172 for p in bottom {
173 if let Property::Primitive(OutputData::String(s)) = p {
174 return Some(s);
175 }
176 }
177 }
178 }
179 }
180 }
181 }
182 }
183 }
184 }
185 }
186 None
187}