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)]
18pub fn as_type_length_pair<'a>(property: &'a mut Property<'a, 'a>) -> Option<TypeLengthPair> {
19 if let Property::Group(group) = property {
20 let mut iter = group.iter();
21 if let Some(Property::Primitive(OutputData::SignedInteger(type_index))) = iter.next() {
22 if let Some(Property::Primitive(OutputData::UnsignedInteger(length))) = iter.next() {
23 return Some(TypeLengthPair {
24 type_index: *type_index,
25 length: *length,
26 });
27 }
28 }
29 }
30
31 None
32}
33
34#[must_use]
36#[inline(always)]
37pub fn as_signed_integer(property: &Property<'_, '_>) -> Option<i64> {
38 if let Property::Group(group) = property {
39 let mut iter = group.iter();
40 let val = iter.next()?;
41 if let Property::Primitive(OutputData::SignedInteger(value)) = val {
42 return Some(*value);
43 } else if let Property::Object { name, data, .. } = val {
44 if *name == "NSNumber" {
45 let mut data_iter = data.clone();
47 return as_signed_integer(&data_iter.next()?);
48 }
49 }
50 }
51 None
52}
53
54#[must_use]
56#[inline(always)]
57pub fn as_unsigned_integer<'a>(property: &'a Property<'a, 'a>) -> Option<u64> {
58 if let Property::Group(group) = property {
59 let mut iter = group.iter();
60 let val = iter.next()?;
61 if let Property::Primitive(OutputData::UnsignedInteger(value)) = val {
62 return Some(*value);
63 } else if let Property::Object { name, data, .. } = val {
64 if *name == "NSNumber" {
65 let mut data_iter = data.clone();
67 return as_unsigned_integer(&data_iter.next()?);
68 }
69 }
70 }
71 None
72}
73
74#[must_use]
76#[inline(always)]
77pub fn as_float<'a>(property: &'a Property<'a, 'a>) -> Option<f64> {
78 if let Property::Group(group) = property {
79 let mut iter = group.iter();
80 let val = iter.next()?;
81 if let Property::Primitive(OutputData::Double(value)) = val {
82 return Some(*value);
83 } else if let Property::Object { name, data, .. } = val {
84 if *name == "NSNumber" {
85 let mut data_iter = data.clone();
87 return as_float(&data_iter.next()?);
88 }
89 }
90 }
91 None
92}
93
94#[inline(always)]
96pub fn as_nsstring<'a>(property: &'a mut Property<'a, 'a>) -> Option<&'a str> {
97 if let Property::Group(group) = property {
98 let mut iter = group.iter_mut();
99 if let Some(Property::Object { name, data, .. }) = iter.next() {
100 if *name == "NSString" || *name == "NSAttributedString" || *name == "NSMutableString" {
101 if let Some(Property::Group(prim)) = data.next() {
102 if let Some(Property::Primitive(OutputData::String(s))) = prim.first() {
103 return Some(s);
104 }
105 }
106 }
107 }
108 }
109 None
110}
111
112#[inline(always)]
114pub fn as_ns_dictionary<'a>(
115 property: &'a mut Property<'a, 'a>,
116) -> Option<&'a mut PropertyIterator<'a, 'a>> {
117 if let Property::Group(group) = property {
118 let mut iter = group.iter_mut();
119 if let Some(Property::Object {
120 class: _,
121 name,
122 data,
123 }) = iter.next()
124 {
125 if *name == "NSDictionary" {
126 return Some(data);
127 }
128 }
129 }
130
131 None
132}
133
134#[inline(always)]
137pub fn as_nsurl<'a>(property: &'a mut Property<'a, 'a>) -> Option<&'a str> {
138 if let Property::Group(groups) = property {
140 for level1 in groups.iter_mut() {
141 if let Property::Object {
143 name,
144 data: url_data,
145 ..
146 } = level1
147 {
148 if *name != "NSURL" {
149 continue;
150 }
151 for level2 in url_data {
153 if let Property::Group(mut inner) = level2 {
154 for level3 in &mut inner {
155 if let Property::Object {
157 name,
158 data: str_data,
159 ..
160 } = level3
161 {
162 if *name != "NSString" {
163 continue;
164 }
165 for level4 in str_data {
167 if let Property::Group(bottom) = level4 {
168 for p in bottom {
169 if let Property::Primitive(OutputData::String(s)) = p {
170 return Some(s);
171 }
172 }
173 }
174 }
175 }
176 }
177 }
178 }
179 }
180 }
181 }
182 None
183}