use alloc::boxed::Box;
use alloc::collections::{BTreeMap, BTreeSet};
use alloc::string::String;
use alloc::vec::Vec;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ValueType {
Bool,
U8,
U16,
U32,
U64,
S8,
S16,
S32,
S64,
F32,
F64,
Char,
String,
List(Box<ValueType>),
Option(Box<ValueType>),
Result {
ok: Box<ValueType>,
err: Box<ValueType>,
},
Record(String), Variant(String), Tuple(Vec<ValueType>),
Flags,
}
impl core::fmt::Display for ValueType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
ValueType::Bool => write!(f, "bool"),
ValueType::U8 => write!(f, "u8"),
ValueType::U16 => write!(f, "u16"),
ValueType::U32 => write!(f, "u32"),
ValueType::U64 => write!(f, "u64"),
ValueType::S8 => write!(f, "s8"),
ValueType::S16 => write!(f, "s16"),
ValueType::S32 => write!(f, "s32"),
ValueType::S64 => write!(f, "s64"),
ValueType::F32 => write!(f, "f32"),
ValueType::F64 => write!(f, "f64"),
ValueType::Char => write!(f, "char"),
ValueType::String => write!(f, "string"),
ValueType::List(inner) => write!(f, "list<{}>", inner),
ValueType::Option(inner) => write!(f, "option<{}>", inner),
ValueType::Result { ok, err } => write!(f, "result<{}, {}>", ok, err),
ValueType::Record(name) => write!(f, "{}", name),
ValueType::Variant(name) => write!(f, "{}", name),
ValueType::Tuple(types) => {
write!(f, "tuple<")?;
for (i, t) in types.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", t)?;
}
write!(f, ">")
}
ValueType::Flags => write!(f, "flags"),
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Value {
Bool(bool),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
S8(i8),
S16(i16),
S32(i32),
S64(i64),
F32(f32),
F64(f64),
Char(char),
String(String),
List {
elem_type: ValueType,
items: Vec<Value>,
},
Option {
inner_type: ValueType,
value: Option<Box<Value>>,
},
Result {
ok_type: ValueType,
err_type: ValueType,
value: core::result::Result<Box<Value>, Box<Value>>,
},
Record {
type_name: String,
fields: Vec<(String, Value)>,
},
Variant {
type_name: String,
case_name: String,
tag: usize,
payload: Vec<Value>,
},
Tuple(Vec<Value>),
Flags(u64),
}
impl Value {
pub fn sym(s: impl Into<String>) -> Self {
Value::Variant {
type_name: String::from("expr"),
case_name: String::from("sym"),
tag: 0,
payload: alloc::vec![Value::String(s.into())],
}
}
pub fn num(n: i64) -> Self {
Value::Variant {
type_name: String::from("expr"),
case_name: String::from("num"),
tag: 1,
payload: alloc::vec![Value::S64(n)],
}
}
pub fn lst(items: Vec<Value>) -> Self {
Value::Variant {
type_name: String::from("expr"),
case_name: String::from("lst"),
tag: 4,
payload: alloc::vec![Value::List {
elem_type: ValueType::Variant(String::from("expr")),
items,
}],
}
}
pub fn infer_type(&self) -> ValueType {
match self {
Value::Bool(_) => ValueType::Bool,
Value::U8(_) => ValueType::U8,
Value::U16(_) => ValueType::U16,
Value::U32(_) => ValueType::U32,
Value::U64(_) => ValueType::U64,
Value::S8(_) => ValueType::S8,
Value::S16(_) => ValueType::S16,
Value::S32(_) => ValueType::S32,
Value::S64(_) => ValueType::S64,
Value::F32(_) => ValueType::F32,
Value::F64(_) => ValueType::F64,
Value::Char(_) => ValueType::Char,
Value::String(_) => ValueType::String,
Value::List { elem_type, .. } => ValueType::List(Box::new(elem_type.clone())),
Value::Option { inner_type, .. } => ValueType::Option(Box::new(inner_type.clone())),
Value::Result {
ok_type, err_type, ..
} => ValueType::Result {
ok: Box::new(ok_type.clone()),
err: Box::new(err_type.clone()),
},
Value::Record { type_name, .. } => ValueType::Record(type_name.clone()),
Value::Variant { type_name, .. } => ValueType::Variant(type_name.clone()),
Value::Tuple(items) => ValueType::Tuple(items.iter().map(|v| v.infer_type()).collect()),
Value::Flags(_) => ValueType::Flags,
}
}
}
impl core::fmt::Display for Value {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Value::Bool(v) => write!(f, "{}", v),
Value::U8(v) => write!(f, "{}u8", v),
Value::U16(v) => write!(f, "{}u16", v),
Value::U32(v) => write!(f, "{}u32", v),
Value::U64(v) => write!(f, "{}u64", v),
Value::S8(v) => write!(f, "{}s8", v),
Value::S16(v) => write!(f, "{}s16", v),
Value::S32(v) => write!(f, "{}s32", v),
Value::S64(v) => write!(f, "{}s64", v),
Value::F32(v) => {
let s = alloc::format!("{}", v);
if v.is_finite() && !s.contains('.') {
write!(f, "{}.0f32", s)
} else {
write!(f, "{}f32", s)
}
}
Value::F64(v) => {
let s = alloc::format!("{}", v);
if v.is_finite() && !s.contains('.') {
write!(f, "{}.0f64", s)
} else {
write!(f, "{}f64", s)
}
}
Value::Char(v) => match v {
'\n' => write!(f, "'\\n'"),
'\r' => write!(f, "'\\r'"),
'\t' => write!(f, "'\\t'"),
'\\' => write!(f, "'\\\\'"),
'\'' => write!(f, "'\\''"),
c => write!(f, "'{}'", c),
},
Value::String(v) => {
write!(f, "\"")?;
for c in v.chars() {
match c {
'"' => write!(f, "\\\"")?,
'\\' => write!(f, "\\\\")?,
'\n' => write!(f, "\\n")?,
'\r' => write!(f, "\\r")?,
'\t' => write!(f, "\\t")?,
c => write!(f, "{}", c)?,
}
}
write!(f, "\"")
}
Value::Tuple(items) => {
write!(f, "(")?;
for (i, item) in items.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", item)?;
}
write!(f, ")")
}
Value::List { elem_type, items } => {
if items.is_empty() {
write!(f, "[]<{}>", elem_type)
} else {
write!(f, "[")?;
for (i, item) in items.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", item)?;
}
write!(f, "]")
}
}
Value::Option { inner_type, value } => match value {
Some(v) => write!(f, "some<{}>({})", inner_type, v),
None => write!(f, "none<{}>", inner_type),
},
Value::Result {
ok_type,
err_type,
value,
} => match value {
Ok(v) => write!(f, "ok<{}, {}>({})", ok_type, err_type, v),
Err(v) => write!(f, "err<{}, {}>({})", ok_type, err_type, v),
},
Value::Record { type_name, fields } => {
if type_name.is_empty() {
write!(f, "{{")?;
} else {
write!(f, "{}{{", type_name)?;
}
for (i, (name, value)) in fields.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}: {}", name, value)?;
}
write!(f, "}}")
}
Value::Variant {
type_name,
case_name,
payload,
..
} => {
write!(f, "{}::{}", type_name, case_name)?;
if !payload.is_empty() {
write!(f, "(")?;
for (i, v) in payload.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", v)?;
}
write!(f, ")")?;
}
Ok(())
}
Value::Flags(v) => write!(f, "flags(0x{:x})", v),
}
}
}
impl From<bool> for Value {
fn from(v: bool) -> Self {
Value::Bool(v)
}
}
impl From<u8> for Value {
fn from(v: u8) -> Self {
Value::U8(v)
}
}
impl From<u16> for Value {
fn from(v: u16) -> Self {
Value::U16(v)
}
}
impl From<u32> for Value {
fn from(v: u32) -> Self {
Value::U32(v)
}
}
impl From<u64> for Value {
fn from(v: u64) -> Self {
Value::U64(v)
}
}
impl From<i8> for Value {
fn from(v: i8) -> Self {
Value::S8(v)
}
}
impl From<i16> for Value {
fn from(v: i16) -> Self {
Value::S16(v)
}
}
impl From<i32> for Value {
fn from(v: i32) -> Self {
Value::S32(v)
}
}
impl From<i64> for Value {
fn from(v: i64) -> Self {
Value::S64(v)
}
}
impl From<f32> for Value {
fn from(v: f32) -> Self {
Value::F32(v)
}
}
impl From<f64> for Value {
fn from(v: f64) -> Self {
Value::F64(v)
}
}
impl From<char> for Value {
fn from(v: char) -> Self {
Value::Char(v)
}
}
impl From<String> for Value {
fn from(v: String) -> Self {
Value::String(v)
}
}
impl From<&str> for Value {
fn from(v: &str) -> Self {
Value::String(String::from(v))
}
}
pub trait KnownValueType {
fn known_value_type() -> ValueType;
}
macro_rules! known_primitive {
($t:ty, $vt:expr) => {
impl KnownValueType for $t {
fn known_value_type() -> ValueType {
$vt
}
}
};
}
known_primitive!(bool, ValueType::Bool);
known_primitive!(u8, ValueType::U8);
known_primitive!(u16, ValueType::U16);
known_primitive!(u32, ValueType::U32);
known_primitive!(u64, ValueType::U64);
known_primitive!(i8, ValueType::S8);
known_primitive!(i16, ValueType::S16);
known_primitive!(i32, ValueType::S32);
known_primitive!(i64, ValueType::S64);
known_primitive!(f32, ValueType::F32);
known_primitive!(f64, ValueType::F64);
known_primitive!(char, ValueType::Char);
known_primitive!(String, ValueType::String);
impl<T: KnownValueType> KnownValueType for Vec<T> {
fn known_value_type() -> ValueType {
ValueType::List(Box::new(T::known_value_type()))
}
}
impl<T: KnownValueType> KnownValueType for Option<T> {
fn known_value_type() -> ValueType {
ValueType::Option(Box::new(T::known_value_type()))
}
}
impl<T: KnownValueType, E: KnownValueType> KnownValueType for core::result::Result<T, E> {
fn known_value_type() -> ValueType {
ValueType::Result {
ok: Box::new(T::known_value_type()),
err: Box::new(E::known_value_type()),
}
}
}
impl<T: KnownValueType> KnownValueType for Box<T> {
fn known_value_type() -> ValueType {
T::known_value_type()
}
}
impl KnownValueType for () {
fn known_value_type() -> ValueType {
ValueType::Tuple(Vec::new())
}
}
impl KnownValueType for Value {
fn known_value_type() -> ValueType {
ValueType::String
}
}
impl<A: KnownValueType> KnownValueType for (A,) {
fn known_value_type() -> ValueType {
ValueType::Tuple(alloc::vec![A::known_value_type()])
}
}
impl<A: KnownValueType, B: KnownValueType> KnownValueType for (A, B) {
fn known_value_type() -> ValueType {
ValueType::Tuple(alloc::vec![A::known_value_type(), B::known_value_type()])
}
}
impl<A: KnownValueType, B: KnownValueType, C: KnownValueType> KnownValueType for (A, B, C) {
fn known_value_type() -> ValueType {
ValueType::Tuple(alloc::vec![
A::known_value_type(),
B::known_value_type(),
C::known_value_type()
])
}
}
impl<A: KnownValueType, B: KnownValueType, C: KnownValueType, D: KnownValueType> KnownValueType
for (A, B, C, D)
{
fn known_value_type() -> ValueType {
ValueType::Tuple(alloc::vec![
A::known_value_type(),
B::known_value_type(),
C::known_value_type(),
D::known_value_type()
])
}
}
impl<T: Into<Value> + KnownValueType> From<Vec<T>> for Value {
fn from(v: Vec<T>) -> Self {
let items: Vec<Value> = v.into_iter().map(Into::into).collect();
Value::List {
elem_type: T::known_value_type(),
items,
}
}
}
impl<T: Into<Value> + KnownValueType, const N: usize> From<[T; N]> for Value {
fn from(v: [T; N]) -> Self {
let items: Vec<Value> = v.into_iter().map(Into::into).collect();
Value::List {
elem_type: T::known_value_type(),
items,
}
}
}
impl<T: TryFrom<Value, Error = ConversionError>, const N: usize> TryFrom<Value> for [T; N] {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::List { items, .. } => {
if items.len() != N {
return Err(ConversionError::WrongFieldCount {
expected: N,
got: items.len(),
});
}
let vec: Vec<T> = items
.into_iter()
.enumerate()
.map(|(i, item)| {
T::try_from(item).map_err(|e| ConversionError::IndexError(i, Box::new(e)))
})
.collect::<Result<Vec<T>, _>>()?;
vec.try_into().map_err(|_| {
ConversionError::ExpectedList(String::from("array conversion failed"))
})
}
other => Err(ConversionError::ExpectedList(format!("{:?}", other))),
}
}
}
impl<T: Into<Value> + KnownValueType> From<Option<T>> for Value {
fn from(v: Option<T>) -> Self {
Value::Option {
inner_type: T::known_value_type(),
value: v.map(|x| Box::new(x.into())),
}
}
}
impl<T: Into<Value>> From<Box<T>> for Value {
fn from(v: Box<T>) -> Self {
(*v).into()
}
}
use crate::ConversionError;
impl TryFrom<Value> for bool {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::Bool(x) => Ok(x),
other => Err(ConversionError::TypeMismatch {
expected: String::from("bool"),
got: format!("{:?}", other),
}),
}
}
}
impl TryFrom<Value> for u8 {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::U8(x) => Ok(x),
other => Err(ConversionError::TypeMismatch {
expected: String::from("u8"),
got: format!("{:?}", other),
}),
}
}
}
impl TryFrom<Value> for u16 {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::U16(x) => Ok(x),
other => Err(ConversionError::TypeMismatch {
expected: String::from("u16"),
got: format!("{:?}", other),
}),
}
}
}
impl TryFrom<Value> for u32 {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::U32(x) => Ok(x),
other => Err(ConversionError::TypeMismatch {
expected: String::from("u32"),
got: format!("{:?}", other),
}),
}
}
}
impl TryFrom<Value> for u64 {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::U64(x) => Ok(x),
other => Err(ConversionError::TypeMismatch {
expected: String::from("u64"),
got: format!("{:?}", other),
}),
}
}
}
impl TryFrom<Value> for i8 {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::S8(x) => Ok(x),
other => Err(ConversionError::TypeMismatch {
expected: String::from("i8"),
got: format!("{:?}", other),
}),
}
}
}
impl TryFrom<Value> for i16 {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::S16(x) => Ok(x),
other => Err(ConversionError::TypeMismatch {
expected: String::from("i16"),
got: format!("{:?}", other),
}),
}
}
}
impl TryFrom<Value> for i32 {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::S32(x) => Ok(x),
other => Err(ConversionError::TypeMismatch {
expected: String::from("i32"),
got: format!("{:?}", other),
}),
}
}
}
impl TryFrom<Value> for i64 {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::S64(x) => Ok(x),
other => Err(ConversionError::TypeMismatch {
expected: String::from("i64"),
got: format!("{:?}", other),
}),
}
}
}
impl TryFrom<Value> for f32 {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::F32(x) => Ok(x),
other => Err(ConversionError::TypeMismatch {
expected: String::from("f32"),
got: format!("{:?}", other),
}),
}
}
}
impl TryFrom<Value> for f64 {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::F64(x) => Ok(x),
other => Err(ConversionError::TypeMismatch {
expected: String::from("f64"),
got: format!("{:?}", other),
}),
}
}
}
impl TryFrom<Value> for char {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::Char(x) => Ok(x),
other => Err(ConversionError::TypeMismatch {
expected: String::from("char"),
got: format!("{:?}", other),
}),
}
}
}
impl TryFrom<Value> for String {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::String(x) => Ok(x),
other => Err(ConversionError::TypeMismatch {
expected: String::from("String"),
got: format!("{:?}", other),
}),
}
}
}
impl<T: TryFrom<Value, Error = ConversionError>> TryFrom<Value> for Vec<T> {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::List { items, .. } => items
.into_iter()
.enumerate()
.map(|(i, item)| {
T::try_from(item).map_err(|e| ConversionError::IndexError(i, Box::new(e)))
})
.collect(),
other => Err(ConversionError::ExpectedList(format!("{:?}", other))),
}
}
}
impl<T: Into<Value> + KnownValueType + Ord> From<BTreeSet<T>> for Value {
fn from(v: BTreeSet<T>) -> Self {
let items: Vec<Value> = v.into_iter().map(Into::into).collect();
Value::List {
elem_type: T::known_value_type(),
items,
}
}
}
impl<T: TryFrom<Value, Error = ConversionError> + Ord> TryFrom<Value> for BTreeSet<T> {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::List { items, .. } => items
.into_iter()
.enumerate()
.map(|(i, item)| {
T::try_from(item).map_err(|e| ConversionError::IndexError(i, Box::new(e)))
})
.collect(),
other => Err(ConversionError::ExpectedList(format!("{:?}", other))),
}
}
}
impl<K: Into<Value> + KnownValueType + Ord, V: Into<Value> + KnownValueType> From<BTreeMap<K, V>>
for Value
{
fn from(v: BTreeMap<K, V>) -> Self {
let items: Vec<Value> = v
.into_iter()
.map(|(k, v)| Value::Tuple(Vec::from([k.into(), v.into()])))
.collect();
Value::List {
elem_type: ValueType::Tuple(alloc::vec![K::known_value_type(), V::known_value_type()]),
items,
}
}
}
impl<
K: TryFrom<Value, Error = ConversionError> + Ord,
V: TryFrom<Value, Error = ConversionError>,
> TryFrom<Value> for BTreeMap<K, V>
{
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::List { items, .. } => items
.into_iter()
.enumerate()
.map(|(i, item)| match item {
Value::Tuple(mut fields) if fields.len() == 2 => {
let v_val = fields.pop().unwrap();
let k_val = fields.pop().unwrap();
let k = K::try_from(k_val)
.map_err(|e| ConversionError::IndexError(i, Box::new(e)))?;
let v = V::try_from(v_val)
.map_err(|e| ConversionError::IndexError(i, Box::new(e)))?;
Ok((k, v))
}
other => Err(ConversionError::ExpectedTuple(format!("{:?}", other))),
})
.collect(),
other => Err(ConversionError::ExpectedList(format!("{:?}", other))),
}
}
}
pub trait FromValue: Sized {
fn from_value(v: Value) -> Result<Self, ConversionError>;
}
impl<T: TryFrom<Value, Error = ConversionError>> FromValue for T {
fn from_value(v: Value) -> Result<Self, ConversionError> {
T::try_from(v)
}
}
impl FromValue for Value {
fn from_value(v: Value) -> Result<Self, ConversionError> {
Ok(v)
}
}
impl<T: FromValue> FromValue for Option<T> {
fn from_value(v: Value) -> Result<Self, ConversionError> {
match v {
Value::Option { value: None, .. } => Ok(None),
Value::Option {
value: Some(inner), ..
} => {
let value = T::from_value(*inner)?;
Ok(Some(value))
}
other => Err(ConversionError::ExpectedOption(format!("{:?}", other))),
}
}
}
impl<T: FromValue, E: FromValue> FromValue for core::result::Result<T, E> {
fn from_value(v: Value) -> Result<Self, ConversionError> {
match v {
Value::Result {
value: Ok(inner), ..
} => {
let value = T::from_value(*inner)
.map_err(|e| ConversionError::PayloadError(Box::new(e)))?;
Ok(Ok(value))
}
Value::Result {
value: Err(inner), ..
} => {
let value = E::from_value(*inner)
.map_err(|e| ConversionError::PayloadError(Box::new(e)))?;
Ok(Err(value))
}
Value::Variant {
tag: 0, payload, ..
} if !payload.is_empty() => {
let value = T::from_value(payload.into_iter().next().unwrap())
.map_err(|e| ConversionError::PayloadError(Box::new(e)))?;
Ok(Ok(value))
}
Value::Variant {
tag: 1, payload, ..
} if !payload.is_empty() => {
let value = E::from_value(payload.into_iter().next().unwrap())
.map_err(|e| ConversionError::PayloadError(Box::new(e)))?;
Ok(Err(value))
}
Value::Variant { tag, .. } => Err(ConversionError::UnknownTag { tag, max: 1 }),
other => Err(ConversionError::ExpectedVariant(format!("{:?}", other))),
}
}
}
impl From<()> for Value {
fn from(_: ()) -> Self {
Value::Tuple(Vec::new())
}
}
impl TryFrom<Value> for () {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::Tuple(items) if items.is_empty() => Ok(()),
other => Err(ConversionError::ExpectedTuple(format!("{:?}", other))),
}
}
}
impl<A: Into<Value>> From<(A,)> for Value {
fn from((a,): (A,)) -> Self {
Value::Tuple(alloc::vec![a.into()])
}
}
impl<A: TryFrom<Value, Error = ConversionError>> TryFrom<Value> for (A,) {
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::Tuple(mut items) if items.len() == 1 => {
let a = A::try_from(items.remove(0))
.map_err(|e| ConversionError::IndexError(0, Box::new(e)))?;
Ok((a,))
}
other => Err(ConversionError::ExpectedTuple(format!("{:?}", other))),
}
}
}
impl<A: Into<Value>, B: Into<Value>> From<(A, B)> for Value {
fn from((a, b): (A, B)) -> Self {
Value::Tuple(alloc::vec![a.into(), b.into()])
}
}
impl<A: TryFrom<Value, Error = ConversionError>, B: TryFrom<Value, Error = ConversionError>>
TryFrom<Value> for (A, B)
{
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::Tuple(mut items) if items.len() == 2 => {
let b = B::try_from(items.remove(1))
.map_err(|e| ConversionError::IndexError(1, Box::new(e)))?;
let a = A::try_from(items.remove(0))
.map_err(|e| ConversionError::IndexError(0, Box::new(e)))?;
Ok((a, b))
}
other => Err(ConversionError::ExpectedTuple(format!("{:?}", other))),
}
}
}
impl<A: Into<Value>, B: Into<Value>, C: Into<Value>> From<(A, B, C)> for Value {
fn from((a, b, c): (A, B, C)) -> Self {
Value::Tuple(alloc::vec![a.into(), b.into(), c.into()])
}
}
impl<
A: TryFrom<Value, Error = ConversionError>,
B: TryFrom<Value, Error = ConversionError>,
C: TryFrom<Value, Error = ConversionError>,
> TryFrom<Value> for (A, B, C)
{
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::Tuple(mut items) if items.len() == 3 => {
let c = C::try_from(items.remove(2))
.map_err(|e| ConversionError::IndexError(2, Box::new(e)))?;
let b = B::try_from(items.remove(1))
.map_err(|e| ConversionError::IndexError(1, Box::new(e)))?;
let a = A::try_from(items.remove(0))
.map_err(|e| ConversionError::IndexError(0, Box::new(e)))?;
Ok((a, b, c))
}
other => Err(ConversionError::ExpectedTuple(format!("{:?}", other))),
}
}
}
impl<A: Into<Value>, B: Into<Value>, C: Into<Value>, D: Into<Value>> From<(A, B, C, D)> for Value {
fn from((a, b, c, d): (A, B, C, D)) -> Self {
Value::Tuple(alloc::vec![a.into(), b.into(), c.into(), d.into()])
}
}
impl<
A: TryFrom<Value, Error = ConversionError>,
B: TryFrom<Value, Error = ConversionError>,
C: TryFrom<Value, Error = ConversionError>,
D: TryFrom<Value, Error = ConversionError>,
> TryFrom<Value> for (A, B, C, D)
{
type Error = ConversionError;
fn try_from(v: Value) -> Result<Self, Self::Error> {
match v {
Value::Tuple(mut items) if items.len() == 4 => {
let d = D::try_from(items.remove(3))
.map_err(|e| ConversionError::IndexError(3, Box::new(e)))?;
let c = C::try_from(items.remove(2))
.map_err(|e| ConversionError::IndexError(2, Box::new(e)))?;
let b = B::try_from(items.remove(1))
.map_err(|e| ConversionError::IndexError(1, Box::new(e)))?;
let a = A::try_from(items.remove(0))
.map_err(|e| ConversionError::IndexError(0, Box::new(e)))?;
Ok((a, b, c, d))
}
other => Err(ConversionError::ExpectedTuple(format!("{:?}", other))),
}
}
}
impl<T: Into<Value> + KnownValueType, E: Into<Value> + KnownValueType>
From<core::result::Result<T, E>> for Value
{
fn from(r: core::result::Result<T, E>) -> Self {
let ok_type = T::known_value_type();
let err_type = E::known_value_type();
let value = match r {
Ok(v) => Ok(Box::new(v.into())),
Err(e) => Err(Box::new(e.into())),
};
Value::Result {
ok_type,
err_type,
value,
}
}
}
use alloc::format;