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