1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright 2020 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0

//! The Value enum, a loosely typed way of representing any valid bin_prot value.
//!
//! Since bin_prot is not a self describing format, deserializing to a loosely typed value required
//! a supplimentary file that describes the layout of the binary (see layout/)

use serde::Deserialize;

mod enum_data;
mod index;
#[cfg(feature = "loose_deserialization")]
pub mod layout;
pub mod ser;
mod visitor;

pub use self::index::Index;
pub use enum_data::EnumData;

use visitor::ValueVisitor;

#[derive(Clone, Debug, PartialEq)]
/// Recursive enum that can define any BinProt serializable type
pub enum Value {
    /// Unit type
    Unit,
    /// Variable length natural integer
    Nat0(u32),
    /// Boolean
    Bool(bool),
    /// String
    String(Vec<u8>),
    /// Char
    Char(u8),
    /// Variable length integer
    Int(i64),
    /// Float
    Float(f64),
    /// Option
    Option(Option<Box<Value>>),
    /// records/structs
    Record(Vec<(String, Value)>),
    /// Tuples (fixed length list)
    Tuple(Vec<Value>),
    /// Sum/enum types
    Sum {
        /// summand/variant name
        name: String,
        /// summand index
        index: u8,
        /// value wrapped by variant
        value: Box<Value>,
    },
    /// Polymorphic Variant (Polyvar) types
    Polyvar {
        /// Polyvar variant name
        name: String,
        /// Polyvar variant tag (e.g. hash)
        tag: u32,
        /// value wrapped by variant
        value: Box<Value>,
    },
    /// List of types (variable length)
    List(Vec<Value>),
}

impl Default for Value {
    fn default() -> Value {
        Value::Unit
    }
}

// Ensure the value visitor is always used when deserializing to a Value (see visitor.rs)
//
// This will always request `deserialize_any` be called since the Value implementation
// does not describe its own structure. Attempting to deserialize into Value from a
// non-self describing format will result in an error
impl<'de> Deserialize<'de> for Value {
    #[inline]
    fn deserialize<D>(deserializer: D) -> Result<Value, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        deserializer.deserialize_any(ValueVisitor)
    }
}

impl Value {
    /// Inner reveals an Option variant as a Rust Option type
    /// Calling inner on a non-option variant results in a panic
    pub fn inner(&self) -> Option<Self> {
        if let Value::Option(inner) = self {
            inner.clone().map(|e| *e)
        } else {
            panic!("Called inner on a non-option variant {:?}", self)
        }
    }
}