fidl_codec/
value.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 crate::error::{Error, Result};
6use crate::handle::{Channel, NullableHandle};
7use fidl_data_zx::{ObjType as ObjectType, Rights};
8
9/// An empty type.
10#[derive(Debug)]
11pub enum Forbid {}
12
13impl std::fmt::Display for Forbid {
14    fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15        unreachable!()
16    }
17}
18
19/// Our internal neutral form for FIDL values.
20#[derive(Debug)]
21pub enum Value<OutOfLine = Forbid> {
22    Null,
23    Bool(bool),
24    U8(u8),
25    U16(u16),
26    U32(u32),
27    U64(u64),
28    I8(i8),
29    I16(i16),
30    I32(i32),
31    I64(i64),
32    F32(f32),
33    F64(f64),
34    String(String),
35    Object(Vec<(String, Self)>),
36    Bits(String, Box<Self>),
37    Enum(String, Box<Self>),
38    Union(String, String, Box<Self>),
39    List(Vec<Self>),
40    ServerEnd(Channel, String, Option<Rights>),
41    ClientEnd(Channel, String, Option<Rights>),
42    Handle(NullableHandle, ObjectType, Option<Rights>),
43    OutOfLine(OutOfLine),
44}
45
46impl Value {
47    /// Get this value as a u64 if it is any integer type. Useful for treating values as bit masks,
48    /// as we'd like to for the Bits type.
49    pub fn bits(&self) -> Option<u64> {
50        match self {
51            Value::U8(x) => Some(*x as u64),
52            Value::U16(x) => Some(*x as u64),
53            Value::U32(x) => Some(*x as u64),
54            Value::U64(x) => Some(*x),
55            Value::I8(x) => Some(u8::from_le_bytes(x.to_le_bytes()) as u64),
56            Value::I16(x) => Some(u16::from_le_bytes(x.to_le_bytes()) as u64),
57            Value::I32(x) => Some(u32::from_le_bytes(x.to_le_bytes()) as u64),
58            Value::I64(x) => Some(u64::from_le_bytes(x.to_le_bytes())),
59            _ => None,
60        }
61    }
62
63    /// See if this value is equal to another. Unlike our PartialEq implementation, this will
64    /// upcast numeric types and compare them.
65    pub(crate) fn cast_equals(&self, other: &Value) -> bool {
66        match self {
67            Value::U8(x) => u8::try_from(other).map(|y| *x == y).unwrap_or(false),
68            Value::U16(x) => u16::try_from(other).map(|y| *x == y).unwrap_or(false),
69            Value::U32(x) => u32::try_from(other).map(|y| *x == y).unwrap_or(false),
70            Value::U64(x) => u64::try_from(other).map(|y| *x == y).unwrap_or(false),
71            Value::I8(x) => i8::try_from(other).map(|y| *x == y).unwrap_or(false),
72            Value::I16(x) => i16::try_from(other).map(|y| *x == y).unwrap_or(false),
73            Value::I32(x) => i32::try_from(other).map(|y| *x == y).unwrap_or(false),
74            Value::I64(x) => i64::try_from(other).map(|y| *x == y).unwrap_or(false),
75            Value::F32(x) => f32::try_from(other).map(|y| *x == y).unwrap_or(false),
76            Value::F64(x) => f64::try_from(other).map(|y| *x == y).unwrap_or(false),
77            _ => self == other,
78        }
79    }
80
81    /// Cast a `Value<Forbid>` to a `Value<T>` for any `T`
82    pub fn upcast<T>(self) -> Value<T> {
83        match self {
84            Value::Null => Value::Null,
85            Value::Bool(a) => Value::Bool(a),
86            Value::U8(a) => Value::U8(a),
87            Value::U16(a) => Value::U16(a),
88            Value::U32(a) => Value::U32(a),
89            Value::U64(a) => Value::U64(a),
90            Value::I8(a) => Value::I8(a),
91            Value::I16(a) => Value::I16(a),
92            Value::I32(a) => Value::I32(a),
93            Value::I64(a) => Value::I64(a),
94            Value::F32(a) => Value::F32(a),
95            Value::F64(a) => Value::F64(a),
96            Value::String(a) => Value::String(a),
97            Value::Object(a) => {
98                Value::Object(a.into_iter().map(|(a, b)| (a, b.upcast())).collect())
99            }
100            Value::Bits(a, b) => Value::Bits(a, Box::new(b.upcast())),
101            Value::Enum(a, b) => Value::Enum(a, Box::new(b.upcast())),
102            Value::Union(a, b, c) => Value::Union(a, b, Box::new(c.upcast())),
103            Value::List(a) => Value::List(a.into_iter().map(Value::upcast).collect()),
104            Value::ServerEnd(a, b, c) => Value::ServerEnd(a, b, c),
105            Value::ClientEnd(a, b, c) => Value::ClientEnd(a, b, c),
106            Value::Handle(a, b, c) => Value::Handle(a, b, c),
107        }
108    }
109}
110
111impl PartialEq for Value {
112    fn eq(&self, other: &Self) -> bool {
113        match (self, other) {
114            (Self::Bool(l0), Self::Bool(r0)) => l0 == r0,
115            (Self::U8(l0), Self::U8(r0)) => l0 == r0,
116            (Self::U16(l0), Self::U16(r0)) => l0 == r0,
117            (Self::U32(l0), Self::U32(r0)) => l0 == r0,
118            (Self::U64(l0), Self::U64(r0)) => l0 == r0,
119            (Self::I8(l0), Self::I8(r0)) => l0 == r0,
120            (Self::I16(l0), Self::I16(r0)) => l0 == r0,
121            (Self::I32(l0), Self::I32(r0)) => l0 == r0,
122            (Self::I64(l0), Self::I64(r0)) => l0 == r0,
123            (Self::F32(l0), Self::F32(r0)) => l0 == r0,
124            (Self::F64(l0), Self::F64(r0)) => l0 == r0,
125            (Self::String(l0), Self::String(r0)) => l0 == r0,
126            (Self::Object(l0), Self::Object(r0)) => {
127                let mut values = std::collections::HashMap::new();
128                for (k, v) in l0 {
129                    if values.insert(k, v).is_some() {
130                        return false;
131                    }
132                }
133                for (k, v) in r0 {
134                    let Some(other) = values.remove(&k) else {
135                        return false;
136                    };
137
138                    if v != other {
139                        return false;
140                    }
141                }
142                true
143            }
144            (Self::Bits(l0, l1), Self::Bits(r0, r1)) => l0 == r0 && l1 == r1,
145            (Self::Enum(l0, l1), Self::Enum(r0, r1)) => l0 == r0 && l1 == r1,
146            (Self::Union(l0, l1, l2), Self::Union(r0, r1, r2)) => l0 == r0 && l1 == r1 && l2 == r2,
147            (Self::List(l0), Self::List(r0)) => l0 == r0,
148            (Self::ServerEnd(l0, l1, l2), Self::ServerEnd(r0, r1, r2)) => {
149                l0 == r0 && l1 == r1 && l2 == r2
150            }
151            (Self::ClientEnd(l0, l1, l2), Self::ClientEnd(r0, r1, r2)) => {
152                l0 == r0 && l1 == r1 && l2 == r2
153            }
154            (Self::Handle(l0, l1, l2), Self::Handle(r0, r1, r2)) => {
155                l0 == r0 && l1 == r1 && l2 == r2
156            }
157            _ => core::mem::discriminant(self) == core::mem::discriminant(other),
158        }
159    }
160}
161
162impl From<&str> for Value {
163    fn from(v: &str) -> Value {
164        Value::from(v.to_owned())
165    }
166}
167
168impl From<String> for Value {
169    fn from(v: String) -> Value {
170        Value::String(v)
171    }
172}
173
174impl From<bool> for Value {
175    fn from(v: bool) -> Value {
176        Value::Bool(v)
177    }
178}
179
180impl From<u8> for Value {
181    fn from(v: u8) -> Value {
182        Value::U8(v)
183    }
184}
185
186impl From<u16> for Value {
187    fn from(v: u16) -> Value {
188        Value::U16(v)
189    }
190}
191
192impl From<u32> for Value {
193    fn from(v: u32) -> Value {
194        Value::U32(v)
195    }
196}
197
198impl From<u64> for Value {
199    fn from(v: u64) -> Value {
200        Value::U64(v)
201    }
202}
203
204impl From<i8> for Value {
205    fn from(v: i8) -> Value {
206        Value::I8(v)
207    }
208}
209
210impl From<i16> for Value {
211    fn from(v: i16) -> Value {
212        Value::I16(v)
213    }
214}
215
216impl From<i32> for Value {
217    fn from(v: i32) -> Value {
218        Value::I32(v)
219    }
220}
221
222impl From<i64> for Value {
223    fn from(v: i64) -> Value {
224        Value::I64(v)
225    }
226}
227
228impl From<f32> for Value {
229    fn from(v: f32) -> Value {
230        Value::F32(v)
231    }
232}
233
234impl From<f64> for Value {
235    fn from(v: f64) -> Value {
236        Value::F64(v)
237    }
238}
239
240impl<T> From<Vec<T>> for Value
241where
242    Value: From<T>,
243{
244    fn from(v: Vec<T>) -> Value {
245        Value::List(v.into_iter().map(Value::from).collect())
246    }
247}
248
249impl<T> From<Option<T>> for Value
250where
251    Value: From<T>,
252{
253    fn from(v: Option<T>) -> Value {
254        v.map(Value::from).unwrap_or(Value::Null)
255    }
256}
257
258impl<A> FromIterator<A> for Value
259where
260    Value: From<A>,
261{
262    fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Value {
263        iter.into_iter().collect::<Vec<_>>().into()
264    }
265}
266
267macro_rules! try_from_int {
268    ($int:ident) => {
269        impl TryFrom<&mut Value> for $int {
270            type Error = $crate::error::Error;
271
272            fn try_from(value: &mut Value) -> Result<$int> {
273                Self::try_from(&*value)
274            }
275        }
276
277        impl TryFrom<&Value> for $int {
278            type Error = $crate::error::Error;
279
280            fn try_from(value: &Value) -> Result<$int> {
281                match value {
282                    Value::U8(x) => $int::try_from(*x).ok(),
283                    Value::U16(x) => $int::try_from(*x).ok(),
284                    Value::U32(x) => $int::try_from(*x).ok(),
285                    Value::U64(x) => $int::try_from(*x).ok(),
286                    Value::I8(x) => $int::try_from(*x).ok(),
287                    Value::I16(x) => $int::try_from(*x).ok(),
288                    Value::I32(x) => $int::try_from(*x).ok(),
289                    Value::I64(x) => $int::try_from(*x).ok(),
290                    _ => None,
291                }
292                .ok_or(Error::ValueError(format!("Cannot convert to {}", stringify!($int))))
293            }
294        }
295
296        impl TryFrom<Value> for $int {
297            type Error = $crate::error::Error;
298
299            fn try_from(value: Value) -> Result<$int> {
300                $int::try_from(&value)
301            }
302        }
303    };
304}
305
306try_from_int!(u8);
307try_from_int!(u16);
308try_from_int!(u32);
309try_from_int!(u64);
310try_from_int!(i8);
311try_from_int!(i16);
312try_from_int!(i32);
313try_from_int!(i64);
314
315impl TryFrom<&mut Value> for bool {
316    type Error = crate::error::Error;
317
318    fn try_from(value: &mut Value) -> Result<bool> {
319        bool::try_from(&*value)
320    }
321}
322
323impl TryFrom<&Value> for bool {
324    type Error = crate::error::Error;
325
326    fn try_from(value: &Value) -> Result<bool> {
327        match value {
328            Value::Bool(x) => Ok(*x),
329            Value::U8(x) => Ok(*x != 0),
330            Value::U16(x) => Ok(*x != 0),
331            Value::U32(x) => Ok(*x != 0),
332            Value::U64(x) => Ok(*x != 0),
333            Value::I8(x) => Ok(*x != 0),
334            Value::I16(x) => Ok(*x != 0),
335            Value::I32(x) => Ok(*x != 0),
336            Value::I64(x) => Ok(*x != 0),
337            _ => Err(Error::ValueError(format!("Cannot convert {} to bool", value))),
338        }
339    }
340}
341
342impl TryFrom<Value> for bool {
343    type Error = Error;
344
345    fn try_from(value: Value) -> Result<bool> {
346        bool::try_from(&value)
347    }
348}
349
350impl TryFrom<&mut Value> for f32 {
351    type Error = crate::error::Error;
352
353    fn try_from(value: &mut Value) -> Result<f32> {
354        f32::try_from(&*value)
355    }
356}
357
358impl TryFrom<&Value> for f32 {
359    type Error = Error;
360
361    fn try_from(value: &Value) -> Result<f32> {
362        match value {
363            Value::U8(x) => Ok(*x as f32),
364            Value::U16(x) => Ok(*x as f32),
365            Value::U32(x) => Ok(*x as f32),
366            Value::U64(x) => Ok(*x as f32),
367            Value::I8(x) => Ok(*x as f32),
368            Value::I16(x) => Ok(*x as f32),
369            Value::I32(x) => Ok(*x as f32),
370            Value::I64(x) => Ok(*x as f32),
371            Value::F32(x) => Ok(*x),
372            Value::F64(x) => Ok(*x as f32),
373            _ => Err(Error::ValueError(format!("Cannot convert {} to f32", value))),
374        }
375    }
376}
377
378impl TryFrom<Value> for f32 {
379    type Error = Error;
380
381    fn try_from(value: Value) -> Result<f32> {
382        f32::try_from(&value)
383    }
384}
385
386impl TryFrom<&mut Value> for f64 {
387    type Error = crate::error::Error;
388
389    fn try_from(value: &mut Value) -> Result<f64> {
390        f64::try_from(&*value)
391    }
392}
393
394impl TryFrom<&Value> for f64 {
395    type Error = Error;
396
397    fn try_from(value: &Value) -> Result<f64> {
398        match value {
399            Value::U8(x) => Ok(*x as f64),
400            Value::U16(x) => Ok(*x as f64),
401            Value::U32(x) => Ok(*x as f64),
402            Value::U64(x) => Ok(*x as f64),
403            Value::I8(x) => Ok(*x as f64),
404            Value::I16(x) => Ok(*x as f64),
405            Value::I32(x) => Ok(*x as f64),
406            Value::I64(x) => Ok(*x as f64),
407            Value::F32(x) => Ok(*x as f64),
408            Value::F64(x) => Ok(*x),
409            _ => Err(Error::ValueError(format!("Cannot convert {} to f32", value))),
410        }
411    }
412}
413
414impl TryFrom<Value> for f64 {
415    type Error = Error;
416
417    fn try_from(value: Value) -> Result<f64> {
418        f64::try_from(&value)
419    }
420}
421
422macro_rules! write_list {
423    ($f:ident, $pattern:pat, $members:expr, $element:expr, $open:expr, $close:expr) => {{
424        $open;
425        let mut first = true;
426        for $pattern in $members {
427            if !first {
428                write!($f, ", ")?
429            } else {
430                first = false;
431                write!($f, " ")?;
432            }
433
434            $element;
435        }
436
437        if !first {
438            write!($f, "{}", " ")?;
439        }
440
441        write!($f, "{}", $close)
442    }};
443}
444
445impl<T: std::fmt::Display> std::fmt::Display for Value<T> {
446    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
447        use Value::*;
448        match self {
449            Null => write!(f, "null"),
450            Bool(true) => write!(f, "true"),
451            Bool(false) => write!(f, "false"),
452            U8(x) => write!(f, "{}u8", x),
453            U16(x) => write!(f, "{}u16", x),
454            U32(x) => write!(f, "{}u32", x),
455            U64(x) => write!(f, "{}u64", x),
456            I8(x) => write!(f, "{}i8", x),
457            I16(x) => write!(f, "{}i16", x),
458            I32(x) => write!(f, "{}i32", x),
459            I64(x) => write!(f, "{}i64", x),
460            F32(x) => write!(f, "{}f32", x),
461            F64(x) => write!(f, "{}f64", x),
462            String(x) => write!(f, "\"{}\"", x),
463            Object(members) => write_list!(
464                f,
465                (name, value),
466                members,
467                write!(f, "\"{}\": {}", name, value)?,
468                write!(f, "{}", "{")?,
469                "}"
470            ),
471            Bits(ty, value) => write!(f, "{}({})", ty, value),
472            Enum(ty, value) => write!(f, "{}({})", ty, value),
473            Union(name, field, value) => write!(f, "{}::{}({})", name, field, value),
474            List(values) => {
475                write_list!(f, value, values, write!(f, "{}", value)?, write!(f, "[")?, "]")
476            }
477            ServerEnd(_, ty, _) => write!(f, "ServerEnd<{ty}>"),
478            ClientEnd(_, ty, _) => write!(f, "ClientEnd<{ty}>"),
479            Handle(_, ty, _) => write!(f, "<{:?}>", ty),
480            OutOfLine(t) => write!(f, "{t}"),
481        }
482    }
483}
484
485/// Helper macro for constructing `Value` objects. Object body is similar to a Rust struct body, and
486/// field values are automatically converted to `Value` via the `From` trait.
487#[macro_export]
488macro_rules! vobject {
489    ($name:ident $($tokens:tt)*) => {{
490        vobject!((stringify!($name)) $($tokens)*)
491    }};
492    (($name:expr) $($tokens:tt)*) => {{
493        #[allow(unused_mut)]
494        let mut items = Vec::<(String, $crate::value::Value)>::new();
495        vobject!(~private items | ($name) $($tokens)*);
496        $crate::value::Value::Struct(items)
497    }};
498    () => {{ $crate::value::Value::Struct(Vec::new()) }};
499
500    (~private $items:path | $name:ident $($tokens:tt)*) => {
501        vobject!(~private $items | (stringify!($name)) $($tokens)*);
502    };
503    (~private $items:path | ($name:expr) : $value:expr , $($excess:tt)*) => {
504        $items.push(($name.to_string(), $crate::value::Value::from($value)));
505        vobject!(~private $items | $($excess)*);
506    };
507    (~private $items:path | ($name:expr) : $value:expr) => {
508        vobject!(~private $items | ($name) : $value ,);
509    };
510    (~private $items:path |) => {};
511}
512
513/// Helper macro for constructing `Value::Union` values.
514#[macro_export]
515macro_rules! vunion {
516    ($name:expr, $variant:expr, $value:expr) => {{ $crate::value::Value::Union($name.to_owned(), $variant.to_owned(), Box::new($value.into())) }};
517}