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