use bytes::Bytes;
use crate::{
codec::Wire,
error::Result,
msgpack::{Decoder, Encoder, Integer, Kind},
};
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Nil,
Bool(bool),
Int(Integer),
Float(f64),
Str(String),
Bin(Bytes),
Array(Vec<Value>),
Map(Vec<(Value, Value)>),
Ext(i8, Bytes),
}
impl From<&str> for Value {
fn from(value: &str) -> Self {
Value::Str(value.to_owned())
}
}
impl From<i64> for Value {
fn from(value: i64) -> Self {
Value::Int(if value < 0 {
Integer::Signed(value)
} else {
Integer::Unsigned(value as u64)
})
}
}
impl From<f64> for Value {
fn from(value: f64) -> Self {
Value::Float(value)
}
}
impl From<bool> for Value {
fn from(value: bool) -> Self {
Value::Bool(value)
}
}
impl Wire for Value {
fn encode(&self, encoder: &mut Encoder) {
match self {
Value::Nil => encoder.nil(),
Value::Bool(value) => encoder.bool(*value),
Value::Int(Integer::Signed(value)) => encoder.int(*value),
Value::Int(Integer::Unsigned(value)) => encoder.uint(*value),
Value::Float(value) => encoder.float(*value),
Value::Str(value) => encoder.str(value),
Value::Bin(value) => encoder.bin(value),
Value::Array(items) => {
encoder.array_len(items.len());
for item in items {
item.encode(encoder);
}
}
Value::Map(entries) => {
encoder.map_len(entries.len());
for (key, value) in entries {
key.encode(encoder);
value.encode(encoder);
}
}
Value::Ext(code, data) => encoder.ext(*code, data),
}
}
fn decode(decoder: &mut Decoder<'_>) -> Result<Self> {
Ok(match decoder.peek_kind()? {
Kind::Nil => {
decoder.take_nil()?;
Value::Nil
}
Kind::Bool => Value::Bool(decoder.bool()?),
Kind::Int => Value::Int(decoder.integer()?),
Kind::Float => Value::Float(decoder.float()?),
Kind::Str => Value::Str(decoder.str()?.to_owned()),
Kind::Bin => Value::Bin(decoder.bin()?),
Kind::Array => {
let len = decoder.array_len()?;
let mut items = Vec::with_capacity(len.min(4096));
for _ in 0..len {
items.push(Value::decode(decoder)?);
}
Value::Array(items)
}
Kind::Map => {
let len = decoder.map_len()?;
let mut entries = Vec::with_capacity(len.min(4096));
for _ in 0..len {
let key = Value::decode(decoder)?;
entries.push((key, Value::decode(decoder)?));
}
Value::Map(entries)
}
Kind::Ext => {
let (code, data) = decoder.ext()?;
Value::Ext(code, data)
}
})
}
}