fidl_codec/
encode.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
5#[cfg(feature = "fdomain")]
6use fdomain_client::{AsHandleRef as _, HandleOp};
7#[cfg(feature = "fdomain")]
8use fidl::encoding::HandleFor as _;
9use fidl::encoding::{AtRestFlags, DynamicFlags, MAGIC_NUMBER_INITIAL};
10#[cfg(not(feature = "fdomain"))]
11use fidl::{AsHandleRef as _, HandleOp};
12
13#[cfg(feature = "fdomain")]
14use HandleOp as HandleDisposition;
15#[cfg(not(feature = "fdomain"))]
16use fidl::HandleDisposition;
17
18use fidl_constants::{ALLOC_ABSENT_U32, ALLOC_ABSENT_U64, ALLOC_PRESENT_U32, ALLOC_PRESENT_U64};
19
20use std::collections::HashMap;
21
22use crate::error::{Error, Result};
23use crate::library;
24use crate::util::*;
25use crate::value::Value;
26
27/// Callback used to encode out-of-line data after in-line data has been returned.
28type DeferCallback<'n, 't> = dyn FnOnce(&mut EncodeBuffer<'n>, RecursionCounter) -> Result<()> + 't;
29
30/// Turn a list of callbacks into one callback that calls each of the list in sequence.
31fn combine_calls<'n: 't, 't>(calls: Vec<Box<DeferCallback<'n, 't>>>) -> Box<DeferCallback<'n, 't>> {
32    Box::new(move |this, counter| {
33        for call in calls {
34            call(this, counter)?;
35        }
36
37        Ok(())
38    })
39}
40
41enum HandleType<'s> {
42    ClientEnd(&'s str),
43    ServerEnd(&'s str),
44    Bare,
45}
46
47///  Buffer containing a partially or fully encoded value.
48struct EncodeBuffer<'n> {
49    ns: &'n library::Namespace,
50    bytes: Vec<u8>,
51    handles: Vec<HandleDisposition<'static>>,
52}
53
54impl<'n> EncodeBuffer<'n> {
55    /// Pad the output buffer so the next thing we add will be aligned to 8 bytes.
56    fn align_8(&mut self) {
57        self.bytes
58            .extend(std::iter::repeat(0u8).take(alignment_padding_for_size(self.bytes.len())));
59    }
60
61    fn encode_transaction<'n_i: 't, 't>(
62        ns: &'n_i library::Namespace,
63        txid: u32,
64        protocol_name: &str,
65        direction: Direction,
66        method_name: &str,
67        value: Value,
68    ) -> Result<(Vec<u8>, Vec<HandleDisposition<'static>>)> {
69        let mut buf = EncodeBuffer { ns, bytes: Vec::new(), handles: Vec::new() };
70
71        let protocol = match ns.lookup(protocol_name)? {
72            library::LookupResult::Protocol(i) => Ok(i),
73            _ => Err(Error::LibraryError(format!("Could not find protocol '{}'.", protocol_name))),
74        }?;
75
76        let method = protocol.methods.get(method_name).ok_or_else(|| {
77            Error::LibraryError(format!(
78                "Could not find method '{}' on protocol '{}'",
79                method_name, protocol_name
80            ))
81        })?;
82
83        let (ty, has) = match direction {
84            Direction::Request => {
85                if !method.has_response && txid != 0 {
86                    return Err(Error::EncodeError(
87                        "Non-zero transaction ID for one-way method.".to_owned(),
88                    ));
89                }
90                (method.request.as_ref(), method.has_request)
91            }
92            Direction::Response => (method.response.as_ref(), method.has_response),
93        };
94
95        let dynamic_flags =
96            if method.strict { DynamicFlags::empty() } else { DynamicFlags::FLEXIBLE };
97
98        if !has {
99            return Err(Error::LibraryError(format!(
100                "Method '{}' on protocol '{}' has no {}",
101                method_name,
102                protocol_name,
103                direction.to_string()
104            )));
105        }
106
107        buf.bytes.extend(&txid.to_le_bytes());
108        buf.bytes.extend(&AtRestFlags::USE_V2_WIRE_FORMAT.bits().to_le_bytes());
109        buf.bytes.push(dynamic_flags.bits());
110        buf.bytes.push(MAGIC_NUMBER_INITIAL);
111        buf.bytes.extend(&method.ordinal.to_le_bytes());
112
113        if let Some(ty) = ty {
114            buf.encode_type(ty, value)?(&mut buf, RecursionCounter::new())?
115        } else if !matches!(value, Value::Null) {
116            return Err(Error::EncodeError("Value must be null.".to_owned()));
117        } else {
118        };
119        buf.align_8();
120        Ok((buf.bytes, buf.handles))
121    }
122
123    fn encode_struct_nonnull<'t>(
124        &mut self,
125        st: &'n library::Struct,
126        value: Value,
127        start_offset: usize,
128    ) -> Result<Box<DeferCallback<'n, 't>>>
129    where
130        'n: 't,
131    {
132        let start_offset = self.bytes.len() - start_offset;
133
134        let values = match value {
135            Value::Object(s) => Ok(s),
136            _ => Err(Error::EncodeError("Value is not a struct.".to_owned())),
137        }?;
138
139        let mut values = {
140            let mut map = HashMap::with_capacity(values.len());
141
142            for (k, v) in values {
143                map.insert(k, v);
144            }
145
146            map
147        };
148
149        let mut calls = Vec::new();
150
151        for member in &st.members {
152            let value = values.remove(&member.name).unwrap_or(Value::Null);
153            self.bytes.extend(
154                std::iter::repeat(0u8).take(member.offset - (self.bytes.len() - start_offset)),
155            );
156            calls.push(self.encode_type(&member.ty, value)?);
157        }
158
159        if let Some((name, _)) = values.into_iter().next() {
160            Err(Error::EncodeError(format!("Unknown struct member: {}", name)))
161        } else {
162            self.bytes
163                .extend(std::iter::repeat(0u8).take(st.size - (self.bytes.len() - start_offset)));
164            Ok(combine_calls(calls))
165        }
166    }
167
168    fn encode_type<'t>(
169        &mut self,
170        ty: &'n library::Type,
171        value: Value,
172    ) -> Result<Box<DeferCallback<'n, 't>>>
173    where
174        'n: 't,
175    {
176        use library::Type::*;
177
178        match ty {
179            Unknown(_) | UnknownString(_) => {
180                return Err(Error::LibraryError("Unknown type".to_owned()));
181            }
182            Bool => self.encode_raw(if bool::try_from(value)? { &[1u8] } else { &[0u8] }),
183            U8 => self.encode_raw(&u8::try_from(value)?.to_le_bytes()),
184            U16 => self.encode_raw(&u16::try_from(value)?.to_le_bytes()),
185            U32 => self.encode_raw(&u32::try_from(value)?.to_le_bytes()),
186            U64 => self.encode_raw(&u64::try_from(value)?.to_le_bytes()),
187            I8 => self.encode_raw(&i8::try_from(value)?.to_le_bytes()),
188            I16 => self.encode_raw(&i16::try_from(value)?.to_le_bytes()),
189            I32 => self.encode_raw(&i32::try_from(value)?.to_le_bytes()),
190            I64 => self.encode_raw(&i64::try_from(value)?.to_le_bytes()),
191            F32 => self.encode_raw(&f32::try_from(value)?.to_le_bytes()),
192            F64 => self.encode_raw(&f64::try_from(value)?.to_le_bytes()),
193            Array(ty, size) => self.encode_array(ty, *size, value),
194            Vector { ty, nullable, element_count } => {
195                self.encode_vector(ty, *nullable, value, *element_count)
196            }
197            String { nullable, byte_count } => self.encode_string(*nullable, value, *byte_count),
198            Handle { object_type, rights, nullable } => {
199                self.encode_handle(*object_type, *rights, HandleType::Bare, *nullable, value)
200            }
201            FrameworkError => self.encode_raw(&[0, 0, 0, 0]),
202            Endpoint { role, protocol, rights, nullable } => self.encode_handle(
203                fidl::ObjectType::CHANNEL,
204                Some(rights.unwrap_or(fidl::Rights::CHANNEL_DEFAULT)),
205                match role {
206                    library::EndpointRole::Client => HandleType::ClientEnd(protocol),
207                    library::EndpointRole::Server => HandleType::ServerEnd(protocol),
208                },
209                *nullable,
210                value,
211            ),
212            Identifier { name, nullable } => self.encode_identifier(name.clone(), *nullable, value),
213        }
214    }
215
216    fn encode_raw<'t>(&mut self, data: &[u8]) -> Result<Box<DeferCallback<'n, 't>>>
217    where
218        'n: 't,
219    {
220        self.bytes.extend(data);
221        Ok(Box::new(|_, _| Ok(())))
222    }
223
224    fn encode_array<'t>(
225        &mut self,
226        ty: &'n library::Type,
227        size: usize,
228        value: Value,
229    ) -> Result<Box<DeferCallback<'n, 't>>>
230    where
231        'n: 't,
232    {
233        let values = if let Value::List(v) = value {
234            Ok(v)
235        } else {
236            Err(Error::EncodeError("Expected a list".to_owned()))
237        }?;
238
239        if values.len() != size {
240            return Err(Error::EncodeError(format!("Expected list of length {}", size)));
241        }
242
243        let mut calls = Vec::with_capacity(size);
244
245        for value in values {
246            calls.push(self.encode_type(ty, value)?);
247        }
248
249        Ok(combine_calls(calls))
250    }
251
252    fn encode_vector<'t>(
253        &mut self,
254        ty: &'n library::Type,
255        nullable: bool,
256        value: Value,
257        element_count: Option<usize>,
258    ) -> Result<Box<DeferCallback<'n, 't>>>
259    where
260        'n: 't,
261    {
262        let values = match (value, nullable) {
263            (Value::Null, true) => Ok(None),
264            (Value::Null, false) => {
265                Err(Error::EncodeError("Got null for non-nullable list".to_owned()))
266            }
267            (Value::List(v), _) => Ok(Some(v)),
268            _ => Err(Error::EncodeError("Expected a list".to_owned())),
269        }?;
270
271        if let Some(values) = values {
272            if element_count.map(|x| x < values.len()).unwrap_or(false) {
273                return Err(Error::EncodeError("Vector exceeded max size".to_owned()));
274            }
275
276            self.bytes.extend(&(values.len() as u64).to_le_bytes());
277            self.bytes.extend(&ALLOC_PRESENT_U64.to_le_bytes());
278            Ok(Box::new(move |this, counter| {
279                let counter = counter.next()?;
280                let mut calls = Vec::with_capacity(values.len());
281
282                for value in values {
283                    calls.push(this.encode_type(ty, value)?);
284                }
285
286                this.align_8();
287
288                for call in calls {
289                    call(this, counter)?;
290                }
291
292                Ok(())
293            }))
294        } else {
295            self.bytes.extend(std::iter::repeat(0u8).take(16));
296            Ok(Box::new(|_, _| Ok(())))
297        }
298    }
299
300    fn encode_string<'t>(
301        &mut self,
302        nullable: bool,
303        value: Value,
304        byte_count: Option<usize>,
305    ) -> Result<Box<DeferCallback<'n, 't>>>
306    where
307        'n: 't,
308    {
309        let string = match (value, nullable) {
310            (Value::Null, true) => Ok(None),
311            (Value::Null, false) => {
312                Err(Error::EncodeError("Got null for non-nullable string".to_owned()))
313            }
314            (Value::String(s), _) => Ok(Some(s)),
315            _ => Err(Error::EncodeError("Expected a string".to_owned())),
316        }?;
317
318        if let Some(string) = string {
319            if byte_count.map(|x| x < string.len()).unwrap_or(false) {
320                return Err(Error::EncodeError("String exceeded max size".to_owned()));
321            }
322
323            self.bytes.extend(&(string.len() as u64).to_le_bytes());
324            self.bytes.extend(&ALLOC_PRESENT_U64.to_le_bytes());
325            Ok(Box::new(move |this, counter| {
326                let _counter = counter.next()?;
327                this.bytes.extend(string.as_bytes());
328                this.align_8();
329                Ok(())
330            }))
331        } else {
332            self.bytes.extend(std::iter::repeat(0u8).take(16));
333            Ok(Box::new(|_, _| Ok(())))
334        }
335    }
336
337    fn encode_handle<'t>(
338        &mut self,
339        object_type: fidl::ObjectType,
340        rights: Option<fidl::Rights>,
341        expect: HandleType<'_>,
342        nullable: bool,
343        value: Value,
344    ) -> Result<Box<DeferCallback<'n, 't>>>
345    where
346        'n: 't,
347    {
348        let (handle, handle_rights) = match (value, nullable, expect) {
349            (Value::Null, true, _) => Ok((None, None)),
350            (Value::Handle(h, _, _), true, _) if h.is_invalid() => Ok((None, None)),
351            (Value::ServerEnd(h, _, _), true, _) if h.as_handle_ref().is_invalid() => {
352                Ok((None, None))
353            }
354            (Value::ClientEnd(h, _, _), true, _) if h.as_handle_ref().is_invalid() => {
355                Ok((None, None))
356            }
357            (Value::Handle(h, _, _), false, _) if h.is_invalid() => {
358                Err(Error::EncodeError("Got invalid handle for non-nullable handle".to_owned()))
359            }
360            (Value::ServerEnd(h, _, _), false, _) if h.as_handle_ref().is_invalid() => {
361                Err(Error::EncodeError("Got invalid handle for non-nullable handle".to_owned()))
362            }
363            (Value::ClientEnd(h, _, _), false, _) if h.as_handle_ref().is_invalid() => {
364                Err(Error::EncodeError("Got invalid handle for non-nullable handle".to_owned()))
365            }
366            (Value::Null, false, _) => {
367                Err(Error::EncodeError("Got null for non-nullable handle".to_owned()))
368            }
369            (Value::Handle(h, s, r), _, _) => {
370                if s != object_type && s != fidl::ObjectType::NONE {
371                    Err(Error::EncodeError(format!(
372                        "Expected object type {object_type:?} got {s:?}"
373                    )))
374                } else {
375                    Ok((Some(h), r))
376                }
377            }
378            (Value::ServerEnd(h, s, r), _, HandleType::ServerEnd(expect))
379            | (Value::ClientEnd(h, s, r), _, HandleType::ClientEnd(expect)) => {
380                if expect != s {
381                    Err(Error::EncodeError(format!(
382                        "Expected endpoint for protocol {expect}, got one for {s}"
383                    )))
384                } else if object_type != fidl::ObjectType::CHANNEL {
385                    Err(Error::EncodeError(format!(
386                        "Expected object type {object_type:?} got channel for protocol {s}"
387                    )))
388                } else {
389                    Ok((Some(h.into()), r))
390                }
391            }
392            (Value::ServerEnd(_, s, _), _, HandleType::ClientEnd(expect))
393            | (Value::ClientEnd(_, s, _), _, HandleType::ServerEnd(expect)) => {
394                if expect != s {
395                    Err(Error::EncodeError(format!(
396                        "Expected endpoint for protocol {expect}, got one for {s}"
397                    )))
398                } else if object_type != fidl::ObjectType::CHANNEL {
399                    Err(Error::EncodeError(format!(
400                        "Expected object type {object_type:?} got channel for protocol {s}"
401                    )))
402                } else {
403                    Err(Error::EncodeError(format!("Got wrong end of channel for {expect}")))
404                }
405            }
406            (Value::ServerEnd(h, s, r), _, HandleType::Bare)
407            | (Value::ClientEnd(h, s, r), _, HandleType::Bare) => {
408                if object_type != fidl::ObjectType::CHANNEL {
409                    Err(Error::EncodeError(format!(
410                        "Expected object type {object_type:?} got channel for protocol {s}"
411                    )))
412                } else {
413                    Ok((Some(h.into()), r))
414                }
415            }
416            _ => Err(Error::EncodeError("Expected a handle".to_owned())),
417        }?;
418
419        let encoded_rights = match (handle_rights, rights) {
420            (Some(_), Some(rights)) => rights,
421            (Some(handle_rights), None) => handle_rights,
422            (None, Some(rights)) => rights,
423            (None, None) => fidl::Rights::SAME_RIGHTS,
424        };
425
426        if let Some(handle) = handle {
427            #[cfg(feature = "fdomain")]
428            let handle_op = HandleOp::Move(handle, encoded_rights);
429            #[cfg(not(feature = "fdomain"))]
430            let handle_op = HandleOp::Move(handle);
431            self.bytes.extend(&ALLOC_PRESENT_U32.to_le_bytes());
432            Ok(Box::new(move |this, _| {
433                #[cfg(feature = "fdomain")]
434                {
435                    let _ = object_type;
436                    this.handles.push(handle_op);
437                }
438                #[cfg(not(feature = "fdomain"))]
439                this.handles.push(HandleDisposition::new(
440                    handle_op,
441                    object_type,
442                    encoded_rights,
443                    fidl::Status::OK,
444                ));
445                Ok(())
446            }))
447        } else {
448            self.bytes.extend(&ALLOC_ABSENT_U32.to_le_bytes());
449            Ok(Box::new(|_, _| Ok(())))
450        }
451    }
452
453    fn encode_identifier<'t>(
454        &mut self,
455        name: String,
456        nullable: bool,
457        value: Value,
458    ) -> Result<Box<DeferCallback<'n, 't>>>
459    where
460        'n: 't,
461    {
462        use library::LookupResult::*;
463        match (self.ns.lookup(&name)?, nullable) {
464            (Bits(b), false) => self.encode_bits(b, value),
465            (Enum(e), false) => self.encode_enum(e, value),
466            (Table(t), false) => self.encode_table(t, value),
467            (Struct(s), nullable) => self.encode_struct(s, nullable, value),
468            (Union(u), nullable) => self.encode_union(u, nullable, value),
469            (Protocol(_), _) => Err(Error::LibraryError(format!(
470                "Protocol names cannot be used as identifiers: {}",
471                name
472            ))),
473            _ => Err(Error::LibraryError(format!("Type {} shouldn't be nullable", name))),
474        }
475    }
476
477    fn encode_bits<'t>(
478        &mut self,
479        bits: &'n library::Bits,
480        value: Value,
481    ) -> Result<Box<DeferCallback<'n, 't>>>
482    where
483        'n: 't,
484    {
485        let value = match value {
486            Value::Bits(name, inner) => {
487                if name == bits.name {
488                    *inner
489                } else {
490                    return Err(Error::EncodeError(format!(
491                        "Expected {}, got {}",
492                        bits.name, name
493                    )));
494                }
495            }
496            _ => value,
497        };
498
499        // If we can't get the bits, this is probably the wrong type of value. Use 0 so we ignore
500        // the mask check and let encode_type return the error message.
501        let data = u64::try_from(&value).unwrap_or(0);
502
503        if bits.strict && data & !bits.mask != 0 {
504            Err(Error::EncodeError(format!("Invalid bits set on {}", bits.name)))
505        } else {
506            self.encode_type(&bits.ty, value)
507        }
508    }
509
510    fn encode_enum<'t>(
511        &mut self,
512        en: &'n library::Enum,
513        value: Value,
514    ) -> Result<Box<DeferCallback<'n, 't>>>
515    where
516        'n: 't,
517    {
518        let value = match value {
519            Value::Enum(name, inner) => {
520                if name == en.name {
521                    *inner
522                } else {
523                    return Err(Error::EncodeError(format!("Expected {}, got {}", en.name, name)));
524                }
525            }
526            _ => value,
527        };
528
529        for item in &en.members {
530            if !en.strict || item.value.cast_equals(&value) {
531                return self.encode_type(&en.ty, value);
532            }
533        }
534
535        Err(Error::EncodeError("Invalid enum variant".to_owned()))
536    }
537
538    fn encode_struct<'t>(
539        &mut self,
540        st: &'n library::Struct,
541        nullable: bool,
542        value: Value,
543    ) -> Result<Box<DeferCallback<'n, 't>>>
544    where
545        'n: 't,
546    {
547        let value = match (value, nullable) {
548            (Value::Null, true) => Ok(None),
549            (Value::Null, false) => Err(Error::EncodeError("Struct can't be null".to_owned())),
550            (value, _) => Ok(Some(value)),
551        }?;
552
553        if let Some(value) = value {
554            if nullable {
555                self.bytes.extend(&ALLOC_PRESENT_U64.to_le_bytes());
556                Ok(Box::new(move |this, counter| {
557                    let counter = counter.next()?;
558                    let call = this.encode_struct_nonnull(st, value, 0)?;
559                    this.align_8();
560                    call(this, counter)
561                }))
562            } else {
563                self.encode_struct_nonnull(st, value, 0)
564            }
565        } else {
566            self.bytes.extend(&ALLOC_ABSENT_U64.to_le_bytes());
567            Ok(Box::new(|_, _| Ok(())))
568        }
569    }
570
571    fn encode_envelope<'t>(
572        &mut self,
573        ty: &'n library::Type,
574        value: Value,
575    ) -> Result<Box<DeferCallback<'n, 't>>>
576    where
577        'n: 't,
578    {
579        let header_pos = self.bytes.len();
580        self.bytes.extend(&[0u8; 8]);
581
582        if let Value::Null = value {
583            Ok(Box::new(|_, _| Ok(())))
584        } else {
585            Ok(Box::new(move |this, counter| {
586                let counter = counter.next()?;
587                let start = this.bytes.len();
588                let handle_start = this.handles.len();
589
590                let header = if ty.inline_size(this.ns)? > 4 {
591                    let call = this.encode_type(ty, value)?;
592
593                    this.align_8();
594                    call(this, counter)?;
595                    let size = (this.bytes.len() - start) as u32;
596                    let handle_count = (this.handles.len() - handle_start) as u16;
597
598                    debug_assert!(size > 0 || handle_count > 0);
599                    let mut header = Vec::new();
600                    header.extend(&size.to_le_bytes());
601                    header.extend(&handle_count.to_le_bytes());
602                    header.extend(&0u16.to_le_bytes());
603                    header
604                } else {
605                    let mut header_buf =
606                        EncodeBuffer { ns: this.ns, bytes: Vec::new(), handles: Vec::new() };
607                    header_buf.encode_type(ty, value)?(&mut header_buf, counter)?;
608                    let EncodeBuffer { bytes: mut header, handles, .. } = header_buf;
609                    header.resize(4, 0);
610                    header.extend(&(handles.len() as u16).to_le_bytes());
611                    header.extend(&1u16.to_le_bytes());
612                    this.handles.extend(handles);
613                    header
614                };
615
616                this.bytes.splice(header_pos..(header_pos + header.len()), header.into_iter());
617                Ok(())
618            }))
619        }
620    }
621
622    fn encode_union<'t>(
623        &mut self,
624        union: &'n library::TableOrUnion,
625        nullable: bool,
626        value: Value,
627    ) -> Result<Box<DeferCallback<'n, 't>>>
628    where
629        'n: 't,
630    {
631        let entry = match value {
632            Value::Null => Ok(None),
633            Value::Union(u, n, b) if *u == union.name => Ok(Some((n, *b))),
634            _ => Err(Error::EncodeError(format!("Expected {}", union.name))),
635        }?;
636
637        if let Some((variant, value)) = entry {
638            for member in union.members.values() {
639                if *member.name == *variant {
640                    self.bytes.extend(&member.ordinal.to_le_bytes());
641                    return self.encode_envelope(&member.ty, value);
642                }
643            }
644
645            Err(Error::EncodeError(format!("Unrecognized union variant: '{}'", variant)))
646        } else if nullable {
647            self.bytes.extend(std::iter::repeat(0u8).take(16));
648            Ok(Box::new(|_, _| Ok(())))
649        } else {
650            Err(Error::EncodeError("Got null for non-nullable Union".to_owned()))
651        }
652    }
653
654    fn encode_table<'t>(
655        &mut self,
656        table: &'n library::TableOrUnion,
657        value: Value,
658    ) -> Result<Box<DeferCallback<'n, 't>>>
659    where
660        'n: 't,
661    {
662        let values = match value {
663            Value::Object(values) => Ok(values),
664            _ => Err(Error::EncodeError(format!("Could not convert to {}", table.name))),
665        }?;
666
667        let mut values_array = Vec::new();
668        for (value_name, value) in values {
669            for (&ord, member) in &table.members {
670                let array_idx = usize::try_from(ord - 1).unwrap();
671                if values_array.len() <= array_idx {
672                    values_array.resize_with(array_idx + 1, || None);
673                }
674                if *member.name == value_name {
675                    values_array[array_idx] = Some((&member.ty, value));
676                    break;
677                }
678            }
679        }
680
681        while values_array.last().map(|x| x.is_none()).unwrap_or(false) {
682            values_array.pop();
683        }
684
685        self.bytes.extend(&(values_array.len() as u64).to_le_bytes());
686        self.bytes.extend(&ALLOC_PRESENT_U64.to_le_bytes());
687
688        Ok(Box::new(move |this, counter| {
689            let counter = counter.next()?;
690            let mut calls = Vec::with_capacity(values_array.len());
691
692            for slot in values_array.into_iter() {
693                if let Some((ty, item)) = slot {
694                    calls.push(this.encode_envelope(ty, item)?);
695                } else {
696                    this.bytes.extend(&ALLOC_ABSENT_U64.to_le_bytes());
697                }
698            }
699
700            for call in calls {
701                call(this, counter)?;
702            }
703
704            Ok(())
705        }))
706    }
707}
708
709/// Serialize a value into a FIDL request.
710pub fn encode_request(
711    ns: &library::Namespace,
712    txid: u32,
713    protocol_name: &str,
714    method_name: &str,
715    value: Value,
716) -> Result<(Vec<u8>, Vec<HandleDisposition<'static>>)> {
717    EncodeBuffer::encode_transaction(
718        ns,
719        txid,
720        protocol_name,
721        Direction::Request,
722        method_name,
723        value,
724    )
725}
726
727/// Serialize a value into a FIDL response.
728pub fn encode_response(
729    ns: &library::Namespace,
730    txid: u32,
731    protocol_name: &str,
732    method_name: &str,
733    value: Value,
734) -> Result<(Vec<u8>, Vec<HandleDisposition<'static>>)> {
735    EncodeBuffer::encode_transaction(
736        ns,
737        txid,
738        protocol_name,
739        Direction::Response,
740        method_name,
741        value,
742    )
743}
744
745/// Serialize a value into a FIDL serialized value.
746pub fn encode(
747    ns: &library::Namespace,
748    type_name: &str,
749    nullable: bool,
750    value: Value,
751) -> Result<(Vec<u8>, Vec<HandleDisposition<'static>>)> {
752    let mut buf = EncodeBuffer { ns, bytes: Vec::new(), handles: Vec::new() };
753    let cb = buf.encode_identifier(type_name.to_owned(), nullable, value)?;
754    buf.align_8();
755    cb(&mut buf, RecursionCounter::new()).map(|_| (buf.bytes, buf.handles))
756}