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)
}
}
}