fidl_codec/
library.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 serde::de::{Deserialize as DeserializeIface, Deserializer};
6use serde_derive::Deserialize;
7use std::collections::HashMap;
8
9use std::sync::{Arc, Weak};
10
11use crate::error::{Error, Result};
12use crate::value::Value;
13
14/// Trait for deserialized structs that have a `name` field. Basically gives us a structural type
15/// for "Has a String field named 'name'."
16trait Named {
17    fn name(&self) -> String;
18}
19
20impl<T: Named> Named for Arc<T> {
21    fn name(&self) -> String {
22        Arc::as_ref(self).name()
23    }
24}
25
26macro_rules! named {
27    ($ident:ty) => {
28        impl Named for $ident {
29            fn name(&self) -> String {
30                self.name.clone()
31            }
32        }
33    };
34}
35
36/// Deserializer helper for fidl::ObjectType
37fn object_type<'de, D: Deserializer<'de>>(
38    deserializer: D,
39) -> std::result::Result<Option<fidl::ObjectType>, D::Error> {
40    Ok(Option::<u32>::deserialize(deserializer)?.map(|x| fidl::ObjectType::from_raw(x)))
41}
42
43/// Deserializer helper for composed protocols
44fn composed_protocols<'de, D: Deserializer<'de>>(
45    deserializer: D,
46) -> std::result::Result<Vec<String>, D::Error> {
47    #[derive(Deserialize)]
48    struct ComposedProtocol {
49        name: String,
50    }
51    Ok(Vec::<ComposedProtocol>::deserialize(deserializer)?.into_iter().map(|x| x.name).collect())
52}
53
54/// Deserializer helper for fidl::ObjectType
55fn rights<'de, D: Deserializer<'de>>(
56    deserializer: D,
57) -> std::result::Result<Option<fidl::Rights>, D::Error> {
58    if let Some(rights) = Option::<u32>::deserialize(deserializer)? {
59        Ok(Some(fidl::Rights::from_bits_truncate(rights)))
60    } else {
61        Ok(None)
62    }
63}
64
65/// Deserializer helper that gets a list of values, but then packs them into a hashmap by name.
66fn hash_by_name<'de, D: Deserializer<'de>, T: Named + DeserializeIface<'de>>(
67    deserializer: D,
68) -> std::result::Result<HashMap<String, T>, D::Error> {
69    let mut ret = HashMap::new();
70    for item in Vec::<T>::deserialize(deserializer)? {
71        ret.insert(item.name().clone(), item);
72    }
73    Ok(ret)
74}
75
76/// Same as `hash_by_name` but wraps the inserted values in an Arc.
77fn hash_by_name_arc<'de, D: Deserializer<'de>, T: Named + DeserializeIface<'de>>(
78    deserializer: D,
79) -> std::result::Result<HashMap<String, Arc<T>>, D::Error> {
80    let mut ret = HashMap::new();
81    for item in Vec::<T>::deserialize(deserializer)? {
82        ret.insert(item.name().clone(), Arc::new(item));
83    }
84    Ok(ret)
85}
86
87/// Deserializer helper that gets a list of TableOrUnionMembers, but then packs them into a
88/// hashmap by ordinal.
89fn hash_by_ordinal<'de, D: Deserializer<'de>>(
90    deserializer: D,
91) -> std::result::Result<HashMap<u64, TableOrUnionMember>, D::Error> {
92    let mut ret = HashMap::new();
93    for item in Vec::<TableOrUnionMember>::deserialize(deserializer)? {
94        ret.insert(item.ordinal, item);
95    }
96    Ok(ret)
97}
98
99/// Gets the size for a struct declaration by stripping away a field shape object.
100fn extract_struct_size<'de, D: Deserializer<'de>>(
101    deserializer: D,
102) -> std::result::Result<usize, D::Error> {
103    Ok(TypeShape::deserialize(deserializer)?.inline_size)
104}
105
106/// Gets the offset for a struct member by stripping away a field shape object.
107fn extract_member_offset<'de, D: Deserializer<'de>>(
108    deserializer: D,
109) -> std::result::Result<usize, D::Error> {
110    Ok(MemberShape::deserialize(deserializer)?.offset)
111}
112
113#[derive(Deserialize)]
114struct Module {
115    name: String,
116    #[serde(deserialize_with = "hash_by_name")]
117    bits_declarations: HashMap<String, Bits>,
118    #[serde(deserialize_with = "hash_by_name")]
119    enum_declarations: HashMap<String, Enum>,
120    #[serde(deserialize_with = "hash_by_name")]
121    protocol_declarations: HashMap<String, Protocol>,
122    #[serde(deserialize_with = "hash_by_name")]
123    table_declarations: HashMap<String, TableOrUnion>,
124    #[serde(deserialize_with = "hash_by_name")]
125    struct_declarations: HashMap<String, Struct>,
126    #[serde(deserialize_with = "hash_by_name")]
127    union_declarations: HashMap<String, TableOrUnion>,
128    declarations: HashMap<String, String>,
129}
130
131#[derive(Deserialize)]
132pub struct TableOrUnion {
133    pub name: String,
134    pub strict: bool,
135    #[serde(deserialize_with = "hash_by_ordinal")]
136    pub members: HashMap<u64, TableOrUnionMember>,
137}
138named!(TableOrUnion);
139
140#[derive(Deserialize)]
141pub struct TableOrUnionMember {
142    pub name: String,
143    #[serde(rename = "type")]
144    pub ty: Type,
145    pub ordinal: u64,
146}
147
148#[derive(Deserialize)]
149#[serde(try_from = "EnumExpanded")]
150pub struct Enum {
151    pub name: String,
152    pub ty: Type,
153    pub strict: bool,
154    pub members: Vec<ValueMember>,
155}
156named!(Enum);
157
158#[derive(Deserialize)]
159#[serde(try_from = "BitsExpanded")]
160pub struct Bits {
161    pub name: String,
162    pub ty: Type,
163    pub strict: bool,
164    pub mask: u64,
165    pub members: Vec<ValueMember>,
166}
167named!(Bits);
168
169pub struct ValueMember {
170    pub name: String,
171    pub value: Value,
172}
173
174#[derive(Deserialize)]
175struct EnumExpanded {
176    name: String,
177    #[serde(rename = "type")]
178    ty: String,
179    strict: bool,
180    members: Vec<ValueMemberExpanded>,
181}
182
183#[derive(Deserialize)]
184struct BitsExpanded {
185    name: String,
186    #[serde(rename = "type")]
187    ty: Type,
188    strict: bool,
189    members: Vec<ValueMemberExpanded>,
190    mask: String,
191}
192
193// We want to un-nest some of the nonsense in the bits declarations. this is how.
194#[derive(Deserialize)]
195struct ValueMemberExpanded {
196    name: String,
197    value: ValueBlock,
198}
199
200#[derive(Deserialize)]
201struct ValueBlock {
202    value: String,
203}
204
205#[derive(Debug)]
206// Note: The inner members are used as part of the `Debug` impl to provide
207// additional context about the error. Prefix them with `_` to avoid dead code
208// warnings as they're unused elsewhere.
209enum ValueConvertError {
210    FloatError { _error: std::num::ParseFloatError },
211    IntError { _error: std::num::ParseIntError },
212    BadPrimitive { _error: String },
213}
214
215impl From<std::num::ParseFloatError> for ValueConvertError {
216    fn from(item: std::num::ParseFloatError) -> ValueConvertError {
217        ValueConvertError::FloatError { _error: item }
218    }
219}
220
221impl From<std::num::ParseIntError> for ValueConvertError {
222    fn from(item: std::num::ParseIntError) -> ValueConvertError {
223        ValueConvertError::IntError { _error: item }
224    }
225}
226
227impl std::fmt::Display for ValueConvertError {
228    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
229        std::fmt::Debug::fmt(self, f)
230    }
231}
232
233fn convert_expanded_value_member(
234    ty: &Type,
235    container: &str,
236    members: Vec<ValueMemberExpanded>,
237) -> std::result::Result<Vec<ValueMember>, ValueConvertError> {
238    type ConverterType = dyn Fn(String) -> std::result::Result<Value, ValueConvertError>;
239
240    let converter = match ty {
241        Type::U8 => (&|x: String| Ok(Value::U8(x.parse::<u8>()?))) as &ConverterType,
242        Type::U16 => (&|x: String| Ok(Value::U16(x.parse::<u16>()?))) as &ConverterType,
243        Type::U32 => (&|x: String| Ok(Value::U32(x.parse::<u32>()?))) as &ConverterType,
244        Type::U64 => (&|x: String| Ok(Value::U64(x.parse::<u64>()?))) as &ConverterType,
245        Type::I8 => (&|x: String| Ok(Value::I8(x.parse::<i8>()?))) as &ConverterType,
246        Type::I16 => (&|x: String| Ok(Value::I16(x.parse::<i16>()?))) as &ConverterType,
247        Type::I32 => (&|x: String| Ok(Value::I32(x.parse::<i32>()?))) as &ConverterType,
248        Type::I64 => (&|x: String| Ok(Value::I64(x.parse::<i64>()?))) as &ConverterType,
249        Type::F32 => (&|x: String| Ok(Value::F32(x.parse::<f32>()?))) as &ConverterType,
250        Type::F64 => (&|x: String| Ok(Value::F64(x.parse::<f64>()?))) as &ConverterType,
251        _ => return Err(ValueConvertError::BadPrimitive { _error: container.to_owned() }),
252    };
253
254    let mut result = Vec::new();
255
256    for member in members {
257        result.push(ValueMember { name: member.name, value: converter(member.value.value)? });
258    }
259
260    Ok(result)
261}
262
263impl TryFrom<EnumExpanded> for Enum {
264    type Error = ValueConvertError;
265
266    fn try_from(exp: EnumExpanded) -> std::result::Result<Enum, Self::Error> {
267        let (name, ty, strict, members) = (exp.name, exp.ty.into(), exp.strict, exp.members);
268        let members = convert_expanded_value_member(&ty, &name, members)?;
269        Ok(Enum { name, ty, strict, members })
270    }
271}
272
273impl TryFrom<BitsExpanded> for Bits {
274    type Error = ValueConvertError;
275
276    fn try_from(exp: BitsExpanded) -> std::result::Result<Bits, Self::Error> {
277        let (name, ty, strict, members, mask) =
278            (exp.name, exp.ty, exp.strict, exp.members, exp.mask);
279        let members = convert_expanded_value_member(&ty, &name, members)?;
280        let mask = mask.parse::<u64>()?;
281        Ok(Bits { name, ty, strict, members, mask })
282    }
283}
284
285#[derive(Deserialize)]
286pub struct Protocol {
287    pub name: String,
288    #[serde(deserialize_with = "hash_by_name_arc")]
289    pub methods: HashMap<String, Arc<Method>>,
290    #[serde(deserialize_with = "composed_protocols")]
291    pub composed_protocols: Vec<String>,
292}
293named!(Protocol);
294
295#[derive(Debug, Clone, Deserialize)]
296pub struct Struct {
297    pub name: String,
298    pub members: Vec<Member>,
299    #[serde(rename = "type_shape_v2", deserialize_with = "extract_struct_size")]
300    pub size: usize,
301}
302named!(Struct);
303
304#[derive(Debug, Clone, Deserialize)]
305pub struct Member {
306    pub name: String,
307    #[serde(rename = "type")]
308    pub ty: Type,
309    #[serde(rename = "field_shape_v2", deserialize_with = "extract_member_offset")]
310    pub offset: usize,
311}
312named!(Member);
313
314#[derive(Deserialize)]
315struct MemberShape {
316    offset: usize,
317}
318
319#[derive(Deserialize)]
320struct TypeShape {
321    inline_size: usize,
322}
323
324#[derive(Debug, Deserialize)]
325pub struct Method {
326    pub name: String,
327    pub ordinal: u64,
328    pub strict: bool,
329    pub has_request: bool,
330    #[serde(rename = "maybe_request_payload")]
331    pub request: Option<Type>,
332    pub has_response: bool,
333    #[serde(rename = "maybe_response_payload")]
334    pub response: Option<Type>,
335}
336named!(Method);
337
338#[derive(Clone, Deserialize, Debug)]
339#[serde(from = "TypeInfo")]
340pub enum Type {
341    Unknown(TypeInfo),
342    UnknownString(String),
343    FrameworkError,
344    Identifier { name: String, nullable: bool },
345    Bool,
346    U8,
347    U16,
348    U32,
349    U64,
350    I8,
351    I16,
352    I32,
353    I64,
354    F32,
355    F64,
356    Array(Box<Type>, usize),
357    Vector { ty: Box<Type>, nullable: bool, element_count: Option<usize> },
358    String { nullable: bool, byte_count: Option<usize> },
359    Handle { object_type: fidl::ObjectType, rights: fidl::Rights, nullable: bool },
360    Endpoint { role: EndpointRole, protocol: String, rights: fidl::Rights, nullable: bool },
361}
362
363impl Type {
364    pub fn inline_size(&self, ns: &Namespace) -> Result<usize> {
365        use Type::*;
366
367        match self {
368            Bool | U8 | I8 => Ok(1),
369            U16 | I16 => Ok(2),
370            FrameworkError | U32 | I32 | F32 | Handle { .. } | Endpoint { .. } => Ok(4),
371            U64 | I64 | F64 => Ok(8),
372            Vector { .. } | String { .. } => Ok(16),
373            Array(a, b) => Ok(a.inline_size(ns)? * b),
374            Identifier { name, nullable } => match ns.lookup(name)? {
375                LookupResult::Bits(b) => b.ty.inline_size(ns),
376                LookupResult::Enum(e) => e.ty.inline_size(ns),
377                LookupResult::Struct(s) => Ok(if *nullable { 8 } else { s.size }),
378                LookupResult::Table(_) => Ok(16),
379                LookupResult::Union(_) => Ok(16),
380                LookupResult::Protocol(_) => Err(Error::LibraryError(format!(
381                    "Protocol names cannot be used as identifiers: {}",
382                    name
383                ))),
384            },
385            Unknown(_) | UnknownString(_) => {
386                Err(Error::LibraryError("Cannot get size for unknown type.".to_owned()))
387            }
388        }
389    }
390
391    pub fn is_resolved(&self, ns: &Namespace) -> bool {
392        match self {
393            Type::Unknown(_) | Type::UnknownString(_) => false,
394            Type::Identifier { name, .. } => ns.lookup(name).is_ok(),
395            _ => true,
396        }
397    }
398}
399
400#[derive(Clone, Deserialize, Debug)]
401pub struct TypeInfo {
402    #[serde(rename = "kind_v2")]
403    pub kind: TypeKind,
404    #[serde(default)]
405    #[serde(rename = "obj_type")]
406    #[serde(deserialize_with = "object_type")]
407    pub object_type: Option<fidl::ObjectType>,
408    #[serde(default)]
409    #[serde(deserialize_with = "rights")]
410    pub rights: Option<fidl::Rights>,
411    pub identifier: Option<String>,
412    pub protocol: Option<String>,
413    pub role: Option<EndpointRole>,
414    pub subtype: Option<String>,
415    pub element_type: Box<Option<TypeInfo>>,
416    pub element_count: Option<usize>,
417    pub maybe_element_count: Option<usize>,
418    #[serde(default)]
419    pub nullable: bool,
420}
421
422#[derive(Clone, Deserialize, Debug)]
423#[serde(rename_all = "lowercase")]
424pub enum TypeKind {
425    Primitive,
426    Vector,
427    Array,
428    Handle,
429    Identifier,
430    String,
431    Endpoint,
432    Internal,
433
434    #[serde(untagged)]
435    Unknown(String),
436}
437
438#[derive(Clone, Deserialize, Debug)]
439#[serde(rename_all = "lowercase")]
440pub enum EndpointRole {
441    Client,
442    Server,
443}
444
445impl From<TypeInfo> for Type {
446    fn from(info: TypeInfo) -> Type {
447        let nullable = info.nullable;
448
449        match info.kind {
450            TypeKind::Primitive => {
451                let subtype = if let Some(x) = info.subtype.clone() {
452                    x
453                } else {
454                    return Type::Unknown(info);
455                };
456                match subtype.into() {
457                    Type::UnknownString(_) => Type::Unknown(info),
458                    ty @ _ => ty,
459                }
460            }
461            TypeKind::Vector => match *info.element_type {
462                Some(t) => Type::Vector {
463                    ty: Box::new(t.into()),
464                    nullable,
465                    element_count: info.maybe_element_count,
466                },
467                _ => Type::Unknown(info),
468            },
469            TypeKind::Array => {
470                if info.element_type.is_some() && info.element_count.is_some() {
471                    Type::Array(
472                        Box::new(info.element_type.unwrap().into()),
473                        info.element_count.unwrap(),
474                    )
475                } else {
476                    Type::Unknown(info)
477                }
478            }
479            TypeKind::Handle => {
480                if let Some(object_type) = info.object_type {
481                    Type::Handle {
482                        object_type,
483                        rights: info.rights.unwrap_or(fidl::Rights::SAME_RIGHTS),
484                        nullable,
485                    }
486                } else {
487                    Type::Unknown(info)
488                }
489            }
490            TypeKind::Identifier => {
491                if let Some(identifier) = info.identifier {
492                    Type::Identifier { name: identifier, nullable }
493                } else {
494                    Type::Unknown(info)
495                }
496            }
497            TypeKind::String => Type::String { nullable, byte_count: info.maybe_element_count },
498            TypeKind::Endpoint => {
499                let Some(role) = info.role.clone() else { return Type::Unknown(info) };
500                let Some(protocol) = info.protocol.clone() else { return Type::Unknown(info) };
501                Type::Endpoint {
502                    role,
503                    protocol,
504                    rights: info.rights.unwrap_or(fidl::Rights::CHANNEL_DEFAULT),
505                    nullable: info.nullable,
506                }
507            }
508            TypeKind::Internal => {
509                if info.subtype.as_deref() == Some("framework_error") {
510                    Type::FrameworkError
511                } else {
512                    Type::Unknown(info)
513                }
514            }
515            TypeKind::Unknown(_) => Type::Unknown(info),
516        }
517    }
518}
519
520impl From<&str> for Type {
521    fn from(name: &str) -> Type {
522        match name.as_ref() {
523            "bool" => Type::Bool,
524            "uint8" => Type::U8,
525            "uint16" => Type::U16,
526            "uint32" => Type::U32,
527            "uint64" => Type::U64,
528            "int8" => Type::I8,
529            "int16" => Type::I16,
530            "int32" => Type::I32,
531            "int64" => Type::I64,
532            "float32" => Type::F32,
533            "float64" => Type::F64,
534            _ => Type::UnknownString(name.to_owned()),
535        }
536    }
537}
538
539impl From<String> for Type {
540    fn from(name: String) -> Type {
541        name.as_str().into()
542    }
543}
544
545pub enum LookupResult<'a> {
546    Bits(&'a Bits),
547    Enum(&'a Enum),
548    Protocol(&'a Protocol),
549    Struct(&'a Struct),
550    Table(&'a TableOrUnion),
551    Union(&'a TableOrUnion),
552}
553
554/// A collection of loaded modules.
555pub struct Namespace {
556    modules: HashMap<String, Module>,
557    methods_by_ordinal: HashMap<u64, (String, Weak<Method>)>,
558}
559
560impl Namespace {
561    /// Create a new, empty namespace.
562    pub fn new() -> Self {
563        Namespace { modules: HashMap::new(), methods_by_ordinal: HashMap::new() }
564    }
565
566    /// Load a module from the text of its FIDL JSON file.
567    pub fn load(&mut self, data: &str) -> Result<()> {
568        let new_mod: Module = serde_json::from_str(data)?;
569
570        for protocol in new_mod.protocol_declarations.values() {
571            for method in protocol.methods.values() {
572                self.methods_by_ordinal
573                    .insert(method.ordinal, (protocol.name(), Arc::downgrade(method)));
574            }
575        }
576
577        self.modules.insert(new_mod.name.clone(), new_mod);
578        Ok(())
579    }
580
581    /// Look up a name in the loaded modules.
582    pub fn lookup(&self, name: &str) -> Result<LookupResult<'_>> {
583        let halves: Vec<_> = name.split('/').collect();
584
585        if halves.len() != 2 {
586            return Err(Error::LibraryError(format!(
587                "Wrong number of path components in {}, expected 2",
588                name
589            )));
590        }
591
592        let module: &Module = match self.modules.get(halves[0]) {
593            Some(x) => x,
594            None => return Err(Error::LibraryError(format!("Module {} not found!", halves[0]))),
595        };
596
597        match module.declarations.get(name).map(|x| x.as_ref()) {
598            Some("bits") => match module.bits_declarations.get(name) {
599                Some(x) => Ok(LookupResult::Bits(x)),
600                None => {
601                    Err(Error::LibraryError(format!("{} not found in bits declarations!", name)))
602                }
603            },
604            Some("enum") => match module.enum_declarations.get(name) {
605                Some(x) => Ok(LookupResult::Enum(x)),
606                None => {
607                    Err(Error::LibraryError(format!("{} not found in enum declarations!", name)))
608                }
609            },
610            Some("protocol") => match module.protocol_declarations.get(name) {
611                Some(x) => Ok(LookupResult::Protocol(x)),
612                None => Err(Error::LibraryError(format!(
613                    "{} not found in protocol declarations!",
614                    name
615                ))),
616            },
617            Some("struct") => match module.struct_declarations.get(name) {
618                Some(x) => Ok(LookupResult::Struct(x)),
619                None => {
620                    Err(Error::LibraryError(format!("{} not found in struct declarations!", name)))
621                }
622            },
623            Some("table") => match module.table_declarations.get(name) {
624                Some(x) => Ok(LookupResult::Table(x)),
625                None => {
626                    Err(Error::LibraryError(format!("{} not found in table declarations!", name)))
627                }
628            },
629            Some("union") => match module.union_declarations.get(name) {
630                Some(x) => Ok(LookupResult::Union(x)),
631                None => {
632                    Err(Error::LibraryError(format!("{} not found in union declarations!", name)))
633                }
634            },
635            Some(x) => Err(Error::LibraryError(format!("{} has unknown type {}!", name, x))),
636            None => Err(Error::LibraryError(format!("{} not found in {}!", name, module.name))),
637        }
638    }
639
640    /// Return whether a protocol inherits from another.
641    pub fn inherits(&self, a: &str, b: &str) -> bool {
642        if a == b {
643            return true;
644        }
645
646        let Ok(LookupResult::Protocol(protocol)) = self.lookup(a) else {
647            return false;
648        };
649
650        for composed_protocol in protocol.composed_protocols.iter() {
651            if self.inherits(composed_protocol, b) {
652                return true;
653            }
654        }
655
656        false
657    }
658
659    /// Look up a method ordinal in the loaded modules.
660    pub fn lookup_method_ordinal(&self, ordinal: u64) -> Result<(String, Arc<Method>)> {
661        self.methods_by_ordinal
662            .get(&ordinal)
663            .and_then(|(x, y)| y.upgrade().map(|y| (x.clone(), y)))
664            .ok_or_else(|| Error::LibraryError(format!("No method with ordinal {}", ordinal)))
665    }
666}