fidl_codec/
decode.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use fidl::encoding::{TransactionHeader, ALLOC_PRESENT_U32, ALLOC_PRESENT_U64};
6use nom::bytes::complete::take;
7use nom::combinator::{map, value, verify};
8use nom::multi::count;
9use nom::sequence::{pair, preceded, terminated};
10use nom::{IResult, Parser};
11
12use crate::error::{Error, Result};
13use crate::library;
14use crate::util::*;
15use crate::value::Value;
16
17use std::str;
18
19type DResult<'a, R> = IResult<&'a [u8], R, Error>;
20
21/// This represents an action that will yield a Value when given further bytes to process and
22/// handles to potentially consume. This is how we implement out-of-line data. The initial parse
23/// takes the inline data, and when we're ready, the Defer can be fed the remaining bytes to take
24/// the out of line data.
25enum Defer<'d> {
26    /// This Defer doesn't need any further processing. We can just offer up the value right now.
27    Complete(Value),
28
29    /// This Defer implements the actual deferred processing pattern described.
30    Action(
31        Box<
32            dyn for<'a> FnOnce(
33                    &'a [u8],
34                    &mut Vec<fidl::HandleInfo>,
35                    RecursionCounter,
36                ) -> DResult<'a, Value>
37                + 'd,
38        >,
39    ),
40}
41
42impl<'d> Defer<'d> {
43    /// Completes a deferred parse and returns the result.
44    fn complete<'a>(
45        self,
46        data: &'a [u8],
47        handles: &mut Vec<fidl::HandleInfo>,
48        counter: RecursionCounter,
49    ) -> DResult<'a, Value> {
50        match self {
51            Defer::Complete(v) => Ok((data, v)),
52            Defer::Action(act) => act(data, handles, counter),
53        }
54    }
55}
56
57impl<'d> From<Value> for Defer<'d> {
58    fn from(v: Value) -> Defer<'d> {
59        Defer::Complete(v)
60    }
61}
62
63fn take_u8(data: &[u8]) -> DResult<'_, u8> {
64    map(take(1usize), |x: &[u8]| x[0]).parse(data)
65}
66
67fn value_u8(data: &[u8]) -> DResult<'_, Value> {
68    map(take_u8, Value::U8).parse(data)
69}
70
71fn value_bool(data: &[u8]) -> DResult<'_, Value> {
72    map(verify(take_u8, |&x| x == 0 || x == 1), |x| Value::Bool(x != 0)).parse(data)
73}
74
75fn take_u16(data: &[u8]) -> DResult<'_, u16> {
76    map(take(2usize), |x: &[u8]| u16::from_le_bytes(x.try_into().unwrap())).parse(data)
77}
78
79fn value_u16(data: &[u8]) -> DResult<'_, Value> {
80    map(take_u16, Value::U16).parse(data)
81}
82
83fn take_u32(data: &[u8]) -> DResult<'_, u32> {
84    map(take(4usize), |x: &[u8]| u32::from_le_bytes(x.try_into().unwrap())).parse(data)
85}
86
87fn value_u32(data: &[u8]) -> DResult<'_, Value> {
88    map(take_u32, Value::U32).parse(data)
89}
90
91fn take_u64(data: &[u8]) -> DResult<'_, u64> {
92    map(take(8usize), |x: &[u8]| u64::from_le_bytes(x.try_into().unwrap())).parse(data)
93}
94
95fn value_u64(data: &[u8]) -> DResult<'_, Value> {
96    map(take_u64, Value::U64).parse(data)
97}
98
99fn take_i8(data: &[u8]) -> DResult<'_, i8> {
100    map(take(1usize), |x: &[u8]| i8::from_le_bytes([x[0]])).parse(data)
101}
102
103fn value_i8(data: &[u8]) -> DResult<'_, Value> {
104    map(take_i8, Value::I8).parse(data)
105}
106
107fn take_i16(data: &[u8]) -> DResult<'_, i16> {
108    map(take(2usize), |x: &[u8]| i16::from_le_bytes(x.try_into().unwrap())).parse(data)
109}
110
111fn value_i16(data: &[u8]) -> DResult<'_, Value> {
112    map(take_i16, Value::I16).parse(data)
113}
114
115fn take_i32(data: &[u8]) -> DResult<'_, i32> {
116    map(take(4usize), |x: &[u8]| i32::from_le_bytes(x.try_into().unwrap())).parse(data)
117}
118
119fn value_i32(data: &[u8]) -> DResult<'_, Value> {
120    map(take_i32, Value::I32).parse(data)
121}
122
123fn take_i64(data: &[u8]) -> DResult<'_, i64> {
124    map(take(8usize), |x: &[u8]| i64::from_le_bytes(x.try_into().unwrap())).parse(data)
125}
126
127fn value_i64(data: &[u8]) -> DResult<'_, Value> {
128    map(take_i64, Value::I64).parse(data)
129}
130
131fn take_f32(data: &[u8]) -> DResult<'_, f32> {
132    map(take(4usize), |x: &[u8]| f32::from_le_bytes(x.try_into().unwrap())).parse(data)
133}
134
135fn value_f32(data: &[u8]) -> DResult<'_, Value> {
136    map(take_f32, Value::F32).parse(data)
137}
138
139fn take_f64(data: &[u8]) -> DResult<'_, f64> {
140    map(take(8usize), |x: &[u8]| f64::from_le_bytes(x.try_into().unwrap())).parse(data)
141}
142
143fn value_f64(data: &[u8]) -> DResult<'_, Value> {
144    map(take_f64, Value::F64).parse(data)
145}
146
147fn transaction_header(data: &[u8]) -> DResult<'_, TransactionHeader> {
148    fidl::encoding::decode_transaction_header(data)
149        .map(|(a, b)| (b, a))
150        .map_err(|e| Error::DecodeError(format!("Invalid FIDL transaction header ({e:?})")).into())
151}
152
153fn take_padding(amount: usize) -> impl Fn(&[u8]) -> DResult<'_, ()> {
154    move |bytes| value((), verify(take(amount), |x: &[u8]| x.iter().all(|&x| x == 0))).parse(bytes)
155}
156
157fn decode_struct<'s>(
158    ns: &'s library::Namespace,
159    st: &'s library::Struct,
160    nullable: bool,
161) -> impl Fn(&[u8]) -> DResult<'_, Defer<'s>> {
162    move |bytes: &[u8]| {
163        if !nullable {
164            return decode_struct_nonnull(ns, st).parse(bytes);
165        }
166
167        let (bytes, presence) = take_u64(bytes)?;
168
169        if presence == 0 {
170            Ok((bytes, Defer::Complete(Value::Null)))
171        } else if presence != ALLOC_PRESENT_U64 {
172            Err(Error::DecodeError("Bad presence indicator".to_owned()).into())
173        } else {
174            Ok((
175                bytes,
176                Defer::Action(Box::new(
177                    move |bytes: &[u8],
178                          handles: &mut Vec<fidl::HandleInfo>,
179                          counter: RecursionCounter| {
180                        let counter = counter.next()?;
181                        let align = alignment_padding_for_size(st.size);
182                        let (bytes, defer) =
183                            terminated(decode_struct_nonnull(ns, st), take_padding(align))
184                                .parse(bytes)?;
185                        defer.complete(bytes, handles, counter)
186                    },
187                )),
188            ))
189        }
190    }
191}
192
193fn decode_struct_nonnull<'s>(
194    ns: &'s library::Namespace,
195    st: &'s library::Struct,
196) -> impl Fn(&[u8]) -> DResult<'_, Defer<'s>> {
197    move |mut bytes: &[u8]| {
198        let mut offset = 0;
199        let mut fields = Vec::new();
200
201        for member in &st.members {
202            let (remaining, result) =
203                preceded(take_padding(member.offset - offset), decode_type(ns, &member.ty))
204                    .parse(bytes)?;
205            fields.push((member.name.clone(), result));
206            bytes = remaining;
207            offset = member.offset + member.ty.inline_size(ns)?;
208        }
209
210        if offset < st.size {
211            let (remaining, _) = take_padding(st.size - offset).parse(bytes)?;
212            bytes = remaining;
213        }
214
215        Ok((
216            bytes,
217            Defer::Action(Box::new(
218                move |mut bytes: &[u8],
219                      handles: &mut Vec<fidl::HandleInfo>,
220                      counter: RecursionCounter| {
221                    let mut complete_fields = Vec::new();
222
223                    for (name, defer) in fields {
224                        let (remaining, value) = defer.complete(bytes, handles, counter)?;
225                        bytes = remaining;
226                        complete_fields.push((name, value))
227                    }
228
229                    Ok((bytes, Value::Object(complete_fields)))
230                },
231            )),
232        ))
233    }
234}
235
236fn decode_type<'t>(
237    ns: &'t library::Namespace,
238    ty: &'t library::Type,
239) -> impl Fn(&[u8]) -> DResult<'_, Defer<'t>> {
240    use library::Type;
241    move |b: &[u8]| {
242        match ty {
243            Type::Bool => value_bool(b),
244            Type::U8 => value_u8(b),
245            Type::U16 => value_u16(b),
246            Type::U32 => value_u32(b),
247            Type::U64 => value_u64(b),
248            Type::I8 => value_i8(b),
249            Type::I16 => value_i16(b),
250            Type::I32 => value_i32(b),
251            Type::I64 => value_i64(b),
252            Type::F32 => value_f32(b),
253            Type::F64 => value_f64(b),
254            Type::Array(ty, size) => return decode_array(ns, ty, *size).parse(b),
255            Type::Vector { ty, nullable, element_count } => {
256                return decode_vector(ns, ty, *nullable, *element_count).parse(b)
257            }
258            Type::String { nullable, byte_count } => {
259                return decode_string(*nullable, *byte_count).parse(b)
260            }
261            Type::Identifier { name, nullable } => {
262                return decode_identifier(ns, name, *nullable).parse(b)
263            }
264            Type::Handle { object_type, nullable, rights } => {
265                return decode_handle(*object_type, *nullable, *rights).parse(b)
266            }
267            Type::Endpoint { protocol, rights, nullable, role } => match role {
268                library::EndpointRole::Client => {
269                    return decode_client_end(protocol.clone(), *nullable, *rights).parse(b)
270                }
271                library::EndpointRole::Server => {
272                    return decode_server_end(protocol.clone(), *nullable, *rights).parse(b)
273                }
274            },
275            Type::UnknownString(s) => {
276                Err(Error::LibraryError(format!("Unresolved Type: {}", s)).into())
277            }
278            Type::Unknown(library::TypeInfo { identifier: s, .. }) => {
279                return Err(Error::LibraryError(format!(
280                    "Unresolved Type: {}",
281                    s.as_ref().map_or("<unidentified>", String::as_str)
282                ))
283                .into())
284            }
285            Type::FrameworkError => map(take_u32, |_| Value::Null).parse(b),
286        }
287        .map(|(x, y)| (x, Defer::Complete(y)))
288    }
289}
290
291/// Given a list of defers, complete them all and turn them into a list of complete values.
292fn complete_deferred_list<'a>(
293    bytes: &'a [u8],
294    handles: &mut Vec<fidl::HandleInfo>,
295    defers: Vec<Defer<'_>>,
296    counter: RecursionCounter,
297) -> DResult<'a, Value> {
298    let mut bytes = bytes;
299    let mut values = Vec::new();
300
301    for defer in defers {
302        let (next_bytes, value) = defer.complete(bytes, handles, counter)?;
303        bytes = next_bytes;
304        values.push(value)
305    }
306
307    Ok((bytes, Value::List(values)))
308}
309
310fn decode_array<'t>(
311    ns: &'t library::Namespace,
312    ty: &'t library::Type,
313    size: usize,
314) -> impl Fn(&[u8]) -> DResult<'_, Defer<'t>> {
315    move |bytes: &[u8]| {
316        let (bytes, defers) = count(decode_type(ns, ty), size).parse(bytes)?;
317
318        Ok((
319            bytes,
320            Defer::Action(Box::new(
321                move |bytes: &[u8],
322                      handles: &mut Vec<fidl::HandleInfo>,
323                      counter: RecursionCounter| {
324                    complete_deferred_list(bytes, handles, defers, counter)
325                },
326            )),
327        ))
328    }
329}
330
331fn decode_vector<'t>(
332    ns: &'t library::Namespace,
333    ty: &'t library::Type,
334    nullable: bool,
335    element_count: Option<usize>,
336) -> impl Fn(&[u8]) -> DResult<'_, Defer<'t>> {
337    move |bytes: &[u8]| {
338        let (bytes, (size, presence)) = pair(take_u64, take_u64).parse(bytes)?;
339        let size = size as usize;
340        let align = alignment_padding_for_size(size * ty.inline_size(ns)?);
341
342        if presence == 0 {
343            if nullable {
344                if size == 0 {
345                    Ok((bytes, Defer::Complete(Value::Null)))
346                } else {
347                    Err(Error::DecodeError("Absent vector had a size".to_owned()).into())
348                }
349            } else {
350                Err(Error::DecodeError("Missing non-nullable vector".to_owned()).into())
351            }
352        } else if presence != ALLOC_PRESENT_U64 {
353            Err(Error::DecodeError("Bad presence indicator".to_owned()).into())
354        } else if element_count.map(|x| x < size).unwrap_or(false) {
355            Err(Error::DecodeError("Vector too long".to_owned()).into())
356        } else {
357            Ok((
358                bytes,
359                Defer::Action(Box::new(
360                    move |bytes: &[u8],
361                          handles: &mut Vec<fidl::HandleInfo>,
362                          counter: RecursionCounter| {
363                        let counter = counter.next()?;
364                        let (bytes, defers) =
365                            terminated(count(decode_type(ns, ty), size), take_padding(align))
366                                .parse(bytes)?;
367
368                        complete_deferred_list(bytes, handles, defers, counter)
369                    },
370                )),
371            ))
372        }
373    }
374}
375
376fn decode_string(
377    nullable: bool,
378    byte_count: Option<usize>,
379) -> impl Fn(&[u8]) -> DResult<'_, Defer<'static>> {
380    move |bytes: &[u8]| {
381        let (bytes, (size, presence)) = pair(take_u64, take_u64).parse(bytes)?;
382        let size = size as usize;
383        let align = alignment_padding_for_size(size);
384
385        if presence == 0 {
386            if nullable {
387                if size == 0 {
388                    Ok((bytes, Defer::Complete(Value::Null)))
389                } else {
390                    Err(Error::DecodeError("Absent string had a size".to_owned()).into())
391                }
392            } else {
393                Err(Error::DecodeError("Missing non-nullable string".to_owned()).into())
394            }
395        } else if presence != ALLOC_PRESENT_U64 {
396            Err(Error::DecodeError("Bad presence indicator".to_owned()).into())
397        } else if byte_count.map(|x| x < size).unwrap_or(false) {
398            Err(Error::DecodeError("String too long".to_owned()).into())
399        } else {
400            Ok((
401                bytes,
402                Defer::Action(Box::new(
403                    move |bytes: &[u8],
404                          _: &mut Vec<fidl::HandleInfo>,
405                          counter: RecursionCounter| {
406                        let _counter = counter.next()?;
407                        let (bytes, data) =
408                            terminated(take(size), take_padding(align)).parse(bytes)?;
409
410                        match str::from_utf8(data) {
411                            Ok(x) => Ok((bytes, Value::String(x.to_owned()))),
412                            Err(x) => Err(Error::Utf8Error(x).into()),
413                        }
414                    },
415                )),
416            ))
417        }
418    }
419}
420
421fn decode_server_end(
422    interface: String,
423    nullable: bool,
424    rights: fidl::Rights,
425) -> impl Fn(&[u8]) -> DResult<'_, Defer<'static>> {
426    decode_handle_with(
427        interface,
428        nullable,
429        &|x, y| Value::ServerEnd(x.into(), y),
430        Some(fidl::ObjectType::CHANNEL),
431        rights,
432    )
433}
434
435fn decode_client_end(
436    interface: String,
437    nullable: bool,
438    rights: fidl::Rights,
439) -> impl Fn(&[u8]) -> DResult<'_, Defer<'static>> {
440    decode_handle_with(
441        interface,
442        nullable,
443        &|x, y| Value::ClientEnd(x.into(), y),
444        Some(fidl::ObjectType::CHANNEL),
445        rights,
446    )
447}
448
449fn decode_handle(
450    handle_type: fidl::ObjectType,
451    nullable: bool,
452    rights: fidl::Rights,
453) -> impl Fn(&[u8]) -> DResult<'_, Defer<'static>> {
454    decode_handle_with(handle_type, nullable, &Value::Handle, None, rights)
455}
456
457fn decode_handle_with<T: Clone + 'static>(
458    handle_type: T,
459    nullable: bool,
460    value_builder: &'static (impl Fn(fidl::Handle, T) -> Value + 'static),
461    constrain_type: Option<fidl::ObjectType>,
462    rights: fidl::Rights,
463) -> impl Fn(&[u8]) -> DResult<'_, Defer<'static>> {
464    move |bytes: &[u8]| {
465        let handle_type = handle_type.clone();
466        let (bytes, presence) = take_u32(bytes)?;
467
468        if presence == 0 {
469            if nullable {
470                Ok((bytes, Defer::Complete(Value::Null)))
471            } else {
472                Err(Error::DecodeError("Missing non-nullable handle".to_owned()).into())
473            }
474        } else if presence != ALLOC_PRESENT_U32 {
475            Err(Error::DecodeError("Bad presence indicator".to_owned()).into())
476        } else {
477            Ok((
478                bytes,
479                Defer::Action(Box::new(
480                    move |bytes: &[u8],
481                          handles: &mut Vec<fidl::HandleInfo>,
482                          _: RecursionCounter| {
483                        if !handles.is_empty() {
484                            if constrain_type.map(|x| x == handles[0].object_type).unwrap_or(true) {
485                                let handle = handles.remove(0);
486                                if !handle.rights.contains(rights)
487                                    && handle.rights != fidl::Rights::SAME_RIGHTS
488                                {
489                                    let missing = rights.clone().remove(handle.rights);
490                                    Err(Error::DecodeError(format!(
491                                        "Insufficient handle rights, need {missing:?}"
492                                    ))
493                                    .into())
494                                } else {
495                                    Ok((bytes, value_builder(handle.handle, handle_type)))
496                                }
497                            } else {
498                                Err(Error::DecodeError("Wrong handle type".to_owned()).into())
499                            }
500                        } else {
501                            Err(Error::DecodeError("Too few handles".to_owned()).into())
502                        }
503                    },
504                )),
505            ))
506        }
507    }
508}
509
510fn decode_enum<'e>(
511    ns: &'e library::Namespace,
512    en: &'e library::Enum,
513) -> impl Fn(&[u8]) -> DResult<'_, Defer<'e>> {
514    move |bytes: &[u8]| {
515        let (bytes, defer) = decode_type(ns, &en.ty).parse(bytes)?;
516        Ok((
517            bytes,
518            Defer::Action(Box::new(
519                move |bytes: &[u8],
520                      handles: &mut Vec<fidl::HandleInfo>,
521                      counter: RecursionCounter| {
522                    let (bytes, value) = defer.complete(bytes, handles, counter)?;
523
524                    for member in &en.members {
525                        if value == member.value || !en.strict {
526                            return Ok((bytes, Value::Enum(en.name.to_owned(), Box::new(value))));
527                        }
528                    }
529
530                    if en.strict {
531                        Err(Error::DecodeError("Unknown Enum Variant.".to_owned()).into())
532                    } else {
533                        Ok((bytes, Value::Enum(en.name.to_owned(), Box::new(value))))
534                    }
535                },
536            )),
537        ))
538    }
539}
540
541fn decode_bits<'b>(
542    ns: &'b library::Namespace,
543    bits: &'b library::Bits,
544) -> impl Fn(&[u8]) -> DResult<'_, Defer<'b>> {
545    move |bytes: &[u8]| {
546        let (bytes, defer) = decode_type(ns, &bits.ty).parse(bytes)?;
547        Ok((
548            bytes,
549            Defer::Action(Box::new(
550                move |bytes: &[u8],
551                      handles: &mut Vec<fidl::HandleInfo>,
552                      counter: RecursionCounter| {
553                    let (bytes, value) = defer.complete(bytes, handles, counter)?;
554
555                    let data = value.bits().ok_or_else(|| {
556                        Error::LibraryError("Bits with non-integer type.".to_owned())
557                    })?;
558
559                    if bits.strict && data != data & bits.mask {
560                        Err(Error::DecodeError("Invalid value for bits field.".to_owned()).into())
561                    } else {
562                        Ok((bytes, Value::Bits(bits.name.to_owned(), Box::new(value))))
563                    }
564                },
565            )),
566        ))
567    }
568}
569
570/// Contents of an envelope header.
571enum Envelope {
572    Present { bytes: u32, handles: u16 },
573    Inline { bytes: [u8; 4], handles: u16 },
574    Empty,
575}
576
577impl Envelope {
578    fn skip(&self) -> Defer<'static> {
579        let (envelope_bytes, envelope_handles) = match self {
580            Envelope::Present { bytes, handles } => (*bytes, *handles),
581            Envelope::Inline { handles, .. } => (0, *handles),
582            Envelope::Empty => return Defer::Complete(Value::Null),
583        };
584
585        Defer::Action(Box::new(
586            move |bytes: &[u8], handles: &mut Vec<fidl::HandleInfo>, counter: RecursionCounter| {
587                let _counter = counter.next()?;
588                if (envelope_bytes & 7u32) != 0 {
589                    return Err(Error::DecodeError("Invalid envelope size".to_owned()).into());
590                }
591                let envelope_bytes = envelope_bytes as usize;
592                let envelope_handles = envelope_handles as usize;
593
594                if envelope_handles > handles.len() {
595                    Err(Error::DecodeError("Insufficient handles for envelope".to_owned()).into())
596                } else if envelope_bytes > bytes.len() {
597                    Err(Error::DecodeError("Insufficient bytes for envelope".to_owned()).into())
598                } else {
599                    *handles = handles.split_off(envelope_handles);
600                    Ok((&bytes[envelope_bytes as usize..], Value::Null))
601                }
602            },
603        ))
604    }
605
606    fn decode_type<'s>(
607        &self,
608        ns: &'s library::Namespace,
609        ty: &'s library::Type,
610    ) -> Result<Defer<'s>> {
611        if let &Envelope::Empty = self {
612            Ok(self.skip())
613        } else if !ty.is_resolved(ns) {
614            Ok(self.skip())
615        } else if let Envelope::Inline { bytes, handles } = self {
616            let (padding, ret) = decode_type(ns, ty).parse(bytes)?;
617            take_padding(padding.len()).parse(padding)?;
618            let expect_handles = *handles as usize;
619            Ok(Defer::Action(Box::new(
620                move |bytes: &[u8],
621                      handles: &mut Vec<fidl::HandleInfo>,
622                      counter: RecursionCounter| {
623                    let handle_count = handles.len();
624                    let v = ret.complete(bytes, handles, counter)?;
625
626                    let handles_used = handle_count - handles.len();
627                    if handles_used != expect_handles {
628                        Err(Error::DecodeError("Wrong number of handles in envelope".to_owned())
629                            .into())
630                    } else {
631                        Ok(v)
632                    }
633                },
634            )))
635        } else if ty.inline_size(ns)? <= 4 {
636            Err(Error::DecodeError("Envelope should be inline".to_owned()))
637        } else {
638            let Envelope::Present { bytes, handles } = self else { unreachable!() };
639            let expect_bytes = *bytes as usize;
640            let expect_handles = *handles as usize;
641            Ok(Defer::Action(Box::new(
642                move |bytes: &[u8],
643                      handles: &mut Vec<fidl::HandleInfo>,
644                      counter: RecursionCounter| {
645                    let counter = counter.next()?;
646                    let bytes_start = bytes.len();
647                    let align = alignment_padding_for_size(ty.inline_size(ns)?);
648                    let (bytes, defer) =
649                        terminated(decode_type(ns, ty), take_padding(align)).parse(bytes)?;
650
651                    let handle_count = handles.len();
652                    let (bytes, value) = defer.complete(bytes, handles, counter)?;
653                    let handles_used = handle_count - handles.len();
654                    let bytes_used = bytes_start - bytes.len();
655                    if handles_used != expect_handles {
656                        Err(Error::DecodeError("Wrong number of handles in envelope".to_owned())
657                            .into())
658                    } else if bytes_used != expect_bytes {
659                        Err(Error::DecodeError("Wrong number of bytes in envelope".to_owned())
660                            .into())
661                    } else {
662                        Ok((bytes, value))
663                    }
664                },
665            )))
666        }
667    }
668
669    fn take<'a>(empty_ok: bool) -> impl Fn(&'a [u8]) -> DResult<'a, Envelope> {
670        move |bytes: &[u8]| {
671            let (bytes, (envelope_bytes, envelope_handles, envelope_flags)) =
672                (take_u32, take_u16, take_u16).parse(bytes)?;
673
674            if envelope_bytes == 0 && envelope_handles == 0 && envelope_flags == 0 {
675                if !empty_ok {
676                    Err(Error::DecodeError("Unexpected empty envelope.".to_owned()).into())
677                } else {
678                    Ok((bytes, Envelope::Empty))
679                }
680            } else if envelope_flags == 0 {
681                Ok((bytes, Envelope::Present { bytes: envelope_bytes, handles: envelope_handles }))
682            } else if envelope_flags == 1 {
683                Ok((
684                    bytes,
685                    Envelope::Inline {
686                        bytes: envelope_bytes.to_le_bytes(),
687                        handles: envelope_handles,
688                    },
689                ))
690            } else {
691                Err(Error::DecodeError("Unknown evelope flags.".to_owned()).into())
692            }
693        }
694    }
695}
696
697fn decode_union<'u>(
698    ns: &'u library::Namespace,
699    union: &'u library::TableOrUnion,
700    nullable: bool,
701) -> impl Fn(&[u8]) -> DResult<'_, Defer<'u>> {
702    move |bytes: &[u8]| {
703        let (bytes, (ordinal, envelope)) = (take_u64, Envelope::take(nullable)).parse(bytes)?;
704
705        match (ordinal, &envelope) {
706            (0, Envelope::Empty) => return Ok((bytes, envelope.skip())),
707            (0, _) => return Err(Error::DecodeError("Invalid Union block.".to_owned()).into()),
708            _ => (),
709        };
710
711        match union.members.get(&ordinal) {
712            None if union.strict => {
713                Err(Error::DecodeError("Invalid Union ordinal.".to_owned()).into())
714            }
715            None => Ok((bytes, envelope.skip())),
716            Some(member) => Ok((
717                bytes,
718                Defer::Action(Box::new(
719                    move |bytes: &[u8],
720                          handles: &mut Vec<fidl::HandleInfo>,
721                          counter: RecursionCounter| {
722                        let (bytes, inner) = envelope
723                            .decode_type(ns, &member.ty)?
724                            .complete(bytes, handles, counter)?;
725                        Ok((
726                            bytes,
727                            Value::Union(
728                                union.name.to_owned(),
729                                member.name.to_owned(),
730                                Box::new(inner),
731                            ),
732                        ))
733                    },
734                )),
735            )),
736        }
737    }
738}
739
740fn decode_table<'t>(
741    ns: &'t library::Namespace,
742    table: &'t library::TableOrUnion,
743) -> impl Fn(&[u8]) -> DResult<'_, Defer<'t>> {
744    move |bytes: &[u8]| {
745        let (bytes, (size, data_ptr)) = pair(take_u64, take_u64).parse(bytes)?;
746
747        if data_ptr != ALLOC_PRESENT_U64 {
748            return Err(Error::DecodeError("Bad presence indicator.".to_owned()).into());
749        }
750
751        Ok((
752            bytes,
753            Defer::Action(Box::new(
754                move |bytes: &[u8],
755                      handles: &mut Vec<fidl::HandleInfo>,
756                      counter: RecursionCounter| {
757                    let counter = counter.next()?;
758                    let (mut bytes, envelopes) =
759                        count(Envelope::take(true), size as usize).parse(bytes)?;
760
761                    let mut result = Vec::new();
762                    let mut expect_ord = 1u64;
763                    for envelope in envelopes {
764                        let member = table.members.get(&expect_ord);
765                        expect_ord += 1;
766
767                        let next_bytes = if let Some(member) = member {
768                            let (next_bytes, val) = envelope
769                                .decode_type(ns, &member.ty)?
770                                .complete(bytes, handles, counter)?;
771                            if !matches!(val, Value::Null) {
772                                result.push((member.name.clone(), val));
773                            }
774                            next_bytes
775                        } else {
776                            envelope.skip().complete(bytes, handles, counter)?.0
777                        };
778
779                        bytes = next_bytes;
780                    }
781
782                    Ok((bytes, Value::Object(result)))
783                },
784            )),
785        ))
786    }
787}
788
789fn decode_identifier<'s>(
790    ns: &'s library::Namespace,
791    name: &'s str,
792    nullable: bool,
793) -> impl Fn(&[u8]) -> DResult<'_, Defer<'s>> {
794    move |bytes: &[u8]| match ns.lookup(name)? {
795        library::LookupResult::Bits(b) => decode_bits(ns, b).parse(bytes),
796        library::LookupResult::Enum(e) => decode_enum(ns, e).parse(bytes),
797        library::LookupResult::Struct(s) => decode_struct(ns, s, nullable).parse(bytes),
798        library::LookupResult::Union(u) => decode_union(ns, u, nullable).parse(bytes),
799        library::LookupResult::Table(t) => decode_table(ns, t).parse(bytes),
800        library::LookupResult::Protocol(_) => Err(Error::DecodeError(format!(
801            "Protocol names cannot be used as identifiers: {}",
802            name
803        ))
804        .into()),
805    }
806}
807
808/// Decode a FIDL request or response, depending on the direction header.
809fn decode_message<'a>(
810    ns: &library::Namespace,
811    direction: Direction,
812    bytes: &'a [u8],
813    mut handles: Vec<fidl::HandleInfo>,
814) -> Result<(TransactionHeader, Value)> {
815    let (bytes, header) = transaction_header(bytes)?;
816
817    let (_, method) = ns.lookup_method_ordinal(header.ordinal)?;
818
819    let (message, has) = match direction {
820        Direction::Request => (method.request.as_ref(), method.has_request),
821        Direction::Response => (method.response.as_ref(), method.has_response),
822    };
823
824    if let Some(message) = message {
825        let (bytes, defer) = decode_type(ns, message).parse(bytes)?;
826        let (bytes, value) = defer.complete(bytes, &mut handles, RecursionCounter::new())?;
827
828        if !bytes.is_empty() && (bytes.len() >= 8 || bytes.iter().any(|x| *x != 0)) {
829            Err(Error::DecodeError(format!("{} bytes left over.", bytes.len())))
830        } else if !handles.is_empty() {
831            Err(Error::DecodeError(format!("{} handles left over.", handles.len())))
832        } else {
833            Ok((header, value))
834        }
835    } else if !has {
836        Err(Error::DecodeError(format!(
837            "Header indicates method {}, which has no {}.",
838            method.name,
839            direction.to_string()
840        )))
841    } else {
842        Ok((header, Value::Null))
843    }
844}
845
846/// Decode a FIDL request from a byte buffer and a list of handles.
847pub fn decode_request(
848    ns: &library::Namespace,
849    bytes: &[u8],
850    handles: Vec<fidl::HandleInfo>,
851) -> Result<(TransactionHeader, Value)> {
852    decode_message(ns, Direction::Request, bytes, handles)
853}
854
855/// Decode a FIDL response from a byte buffer and a list of handles.
856pub fn decode_response(
857    ns: &library::Namespace,
858    bytes: &[u8],
859    handles: Vec<fidl::HandleInfo>,
860) -> Result<(TransactionHeader, Value)> {
861    decode_message(ns, Direction::Response, bytes, handles)
862}
863
864/// Decode a FIDL value.
865pub fn decode<'a>(
866    ns: &library::Namespace,
867    ty: &str,
868    bytes: &'a [u8],
869    mut handles: Vec<fidl::HandleInfo>,
870) -> Result<Value> {
871    if bytes.len() % 8 != 0 {
872        return Err(Error::DecodeError("Unaligned encoded object".to_owned()));
873    }
874    let (bytes, defer) = decode_identifier(ns, ty, false).parse(bytes)?;
875    let (bytes, value) = defer.complete(bytes, &mut handles, RecursionCounter::new())?;
876    take_padding(bytes.len()).parse(bytes)?;
877
878    if !bytes.is_empty() && (bytes.len() >= 8 || bytes.iter().any(|x| *x != 0)) {
879        Err(Error::DecodeError(format!("{} bytes left over.", bytes.len())))
880    } else if !handles.is_empty() {
881        Err(Error::DecodeError(format!("{} handles left over.", handles.len())))
882    } else {
883        Ok(value)
884    }
885}