1use crate::amf0::type_marker::TypeMarker;
3use nom::Parser;
4
5use crate::PADDING;
6#[cfg(feature = "amf3")]
7use crate::amf3;
8use crate::nom_utils::{AMFResult, take_str};
9use crate::types::{
10 ClassDefinition, ECMAArrayObjectValue, Element, ObjectId, ObjectValue, Reference, Value,
11};
12use nom::Err;
13use nom::bytes::complete::{tag, take};
14use nom::combinator::{map, map_res};
15use nom::error::{ErrorKind, make_error};
16use nom::multi::{many_m_n, many0};
17use nom::number::complete::{be_f64, be_u8, be_u16, be_u32};
18use std::convert::{TryFrom, TryInto};
19
20pub(crate) fn parse_string(i: &[u8]) -> AMFResult<'_, &str> {
21 let (i, length) = be_u16(i)?;
22 take_str(i, length)
23}
24
25fn parse_element_number(i: &[u8]) -> AMFResult<'_, Value> {
26 let (i, v) = be_f64(i)?;
27 Ok((i, Value::Number(v)))
28}
29
30fn parse_element_bool(i: &[u8]) -> AMFResult<'_, Value> {
31 let (i, v) = be_u8(i)?;
32 Ok((i, Value::Bool(v > 0)))
33}
34
35fn parse_element_string(i: &[u8]) -> AMFResult<'_, Value> {
36 let (i, v) = parse_string(i)?;
37 Ok((i, Value::String(v.to_string())))
38}
39
40fn parse_element_date(i: &[u8]) -> AMFResult<'_, Value> {
41 let (i, millis) = be_f64(i)?;
42 let (i, time_zone) = be_u16(i)?;
43
44 Ok((
45 i,
46 Value::Date {
47 time: millis,
48 timezone_or_utc: Some(time_zone),
49 },
50 ))
51}
52
53fn parse_long_string_internal(i: &[u8]) -> AMFResult<'_, &str> {
54 let (i, length) = be_u32(i)?;
55 map_res(take(length), std::str::from_utf8).parse(i)
56}
57
58fn parse_element_long_string(i: &[u8]) -> AMFResult<'_, Value> {
59 let (i, str) = parse_long_string_internal(i)?;
60 Ok((i, Value::String(str.to_string())))
61}
62
63fn parse_element_xml(i: &[u8]) -> AMFResult<'_, Value> {
64 let (i, content) = parse_long_string_internal(i)?;
65 Ok((
66 i,
67 Value::XML {
68 value: content.to_string(),
69 is_string: true,
70 },
71 ))
72}
73
74fn read_type_marker(i: &[u8]) -> AMFResult<'_, TypeMarker> {
75 let (i, type_) = be_u8(i)?;
76 Ok((
77 i,
78 TypeMarker::try_from(type_).unwrap_or(TypeMarker::Unsupported),
79 ))
80}
81
82#[derive(Default)]
84pub struct AMF0Decoder {
85 cache: Vec<Value>,
87
88 #[cfg(feature = "amf3")]
89 amf3_decoder: amf3::read::AMF3Decoder,
90}
91
92impl AMF0Decoder {
93 fn parse_element_reference<'a>(&self, i: &'a [u8]) -> AMFResult<'a, Value> {
94 let (i, reference_index) = be_u16(i)?;
95
96 Ok((i, Value::Reference(Reference(reference_index))))
97 }
98
99 fn parse_element_ecma_array<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
100 let (i, array_length) = be_u32(i)?;
101 map(
102 |i| self.parse_array_element(i),
103 move |elms: Vec<Element>| Value::ECMAArray {
104 id: ObjectId::INVALID,
105 data: ECMAArrayObjectValue {
106 dense: Vec::new(),
107 elements: elms,
108 length: array_length,
109 },
110 },
111 )
112 .parse(i)
113 }
114
115 fn parse_element_typed_object<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
116 let (i, name) = parse_string(i)?;
117
118 map(
119 |i| self.parse_array_element(i),
120 move |elms: Vec<Element>| Value::Object {
121 id: ObjectId::INVALID,
122 data: ObjectValue {
123 elements: elms,
124 class_definition: Some(ClassDefinition::default_with_name(name.to_string())),
125 },
126 },
127 )
128 .parse(i)
129 }
130
131 fn parse_element_object<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
132 let (i, v) = self.parse_array_element(i)?;
133 Ok((
134 i,
135 Value::Object {
136 id: ObjectId::INVALID,
137 data: ObjectValue {
138 elements: v,
139 class_definition: None,
140 },
141 },
142 ))
143 }
144
145 #[cfg(fuzzing)]
146 pub fn fuzz_parse_element_array<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
148 self.parse_element_strict_array(i)
149 }
150
151 fn parse_element_strict_array<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
153 let (i, length) = be_u32(i)?;
154
155 let length_usize = length
156 .try_into()
157 .map_err(|_| Err::Error(make_error(i, ErrorKind::Digit)))?;
158
159 if i.len() < length_usize {
161 return Err(Err::Error(make_error(i, ErrorKind::TooLarge)));
162 }
163
164 let (i, elements) =
166 many_m_n(length_usize, length_usize, |i| self.parse_single_element(i)).parse(i)?;
167
168 Ok((
169 i,
170 Value::StrictArray {
171 id: ObjectId::INVALID,
172 values: elements,
173 },
174 ))
175 }
176
177 fn parse_array_element<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Vec<Element>> {
178 let mut out = Vec::new();
179
180 let mut i = i;
181 loop {
182 let (k, _) = parse_string(i)?;
183 let (k, next_type) = read_type_marker(k)?;
184 if next_type == TypeMarker::ObjectEnd {
185 i = k;
186 break;
187 }
188
189 let (j, e) = self.parse_element(i)?;
190 i = j;
191
192 out.push(e.clone());
193 }
194
195 Ok((i, out))
196 }
197
198 fn parse_element_amf3<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
199 #[cfg(feature = "amf3")]
200 {
201 let (i, x) = self.amf3_decoder.parse_single_element(i)?;
202 Ok((i, Value::AMF3(Box::new(x))))
203 }
204 #[cfg(not(feature = "amf3"))]
205 {
206 Ok((i, Value::Unsupported))
207 }
208 }
209
210 pub fn parse_single_element<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Value> {
212 let (i, type_) = read_type_marker(i)?;
214
215 self.cache.push(Value::Undefined);
216
217 let (i, v) = match type_ {
218 TypeMarker::Number => parse_element_number(i),
219 TypeMarker::Boolean => parse_element_bool(i),
220 TypeMarker::String => parse_element_string(i),
221 TypeMarker::Object => {
222 let (i, v) = self.parse_element_object(i)?;
223 Ok((i, v))
224 }
225 TypeMarker::Null => Ok((i, (Value::Null))),
226 TypeMarker::Undefined => Ok((i, (Value::Undefined))),
227 TypeMarker::Reference => {
228 let (i, v) = self.parse_element_reference(i)?;
229 Ok((i, v))
230 }
231 TypeMarker::ECMAArray => {
232 let (i, v) = self.parse_element_ecma_array(i)?;
233 Ok((i, v))
234 }
235 TypeMarker::StrictArray => {
236 let (i, v) = self.parse_element_strict_array(i)?;
237 Ok((i, v))
238 }
239 TypeMarker::Date => parse_element_date(i),
240 TypeMarker::LongString => parse_element_long_string(i),
241 TypeMarker::Unsupported => Ok((i, (Value::Unsupported))),
242 TypeMarker::Xml => parse_element_xml(i),
243 TypeMarker::TypedObject => {
244 let (i, v) = self.parse_element_typed_object(i)?;
245 Ok((i, v))
246 }
247 TypeMarker::AMF3 => self.parse_element_amf3(i),
248 TypeMarker::MovieClip | TypeMarker::RecordSet | TypeMarker::ObjectEnd => Err(
249 Err::Error(crate::errors::Error::UnsupportedType(type_ as u8)),
250 ),
251 }?;
252
253 Ok((i, v))
254 }
255
256 fn parse_element<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Element> {
257 let (i, name) = parse_string(i)?;
258
259 map(
260 |i| self.parse_single_element(i),
261 move |v| Element {
262 name: name.to_string(),
263 value: v,
264 },
265 )
266 .parse(i)
267 }
268
269 fn parse_element_and_padding<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Element> {
270 let (i, e) = self.parse_element(i)?;
271 let (i, _) = tag(PADDING.as_slice())(i)?;
272
273 Ok((i, e))
274 }
275
276 pub fn parse_body<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Vec<Element>> {
278 many0(|i| self.parse_element_and_padding(i)).parse(i)
279 }
280}