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