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