use crate::{
Bytes, FromValue, Object, Shared, StaticString, ToValue, Tuple, TypeInfo, Value, Variant,
VariantData, VariantRtti, Vec, VmError, VmErrorKind,
};
use serde::{de, ser};
use std::cmp;
use std::fmt;
use std::hash;
use std::sync::Arc;
use std::vec;
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum Key {
Unit,
Byte(u8),
Char(char),
Bool(bool),
Integer(i64),
String(StringKey),
Bytes(Bytes),
Vec(vec::Vec<Key>),
Tuple(Box<[Key]>),
Option(Option<Box<Key>>),
Variant(VariantKey),
}
impl Key {
pub fn from_value(value: &Value) -> Result<Self, VmError> {
return Ok(match value {
Value::Unit => Self::Unit,
Value::Byte(b) => Self::Byte(*b),
Value::Char(c) => Self::Char(*c),
Value::Bool(b) => Self::Bool(*b),
Value::Integer(n) => Self::Integer(*n),
Value::String(s) => {
let s = s.borrow_ref()?;
Self::String(StringKey::String((**s).into()))
}
Value::StaticString(s) => Self::String(StringKey::StaticString(s.clone())),
Value::Option(option) => Self::Option(match &*option.borrow_ref()? {
Some(some) => Some(Box::new(Self::from_value(some)?)),
None => None,
}),
Value::Bytes(b) => {
let b = b.borrow_ref()?;
Self::Bytes((*b).clone())
}
Value::Vec(vec) => {
let vec = vec.borrow_ref()?;
let mut key_vec = vec::Vec::with_capacity(vec.len());
for value in &*vec {
key_vec.push(Self::from_value(value)?);
}
Self::Vec(key_vec)
}
Value::Tuple(tuple) => {
let tuple = tuple.borrow_ref()?;
Self::Tuple(tuple_from_value(&*tuple)?)
}
Value::Variant(variant) => {
let variant = variant.borrow_ref()?;
let data = match &variant.data {
VariantData::Unit => VariantKeyData::Unit,
VariantData::Tuple(tuple) => VariantKeyData::Tuple(tuple_from_value(tuple)?),
VariantData::Struct(object) => {
VariantKeyData::Struct(struct_from_value(object)?)
}
};
Key::Variant(VariantKey {
rtti: variant.rtti.clone(),
data,
})
}
value => {
return Err(VmError::from(VmErrorKind::KeyNotSupported {
actual: value.type_info()?,
}))
}
});
fn tuple_from_value(tuple: &Tuple) -> Result<Box<[Key]>, VmError> {
let mut output = vec::Vec::with_capacity(tuple.len());
for value in tuple {
output.push(Key::from_value(value)?);
}
Ok(output.into_boxed_slice())
}
fn struct_from_value(object: &Object) -> Result<Box<[(Box<str>, Key)]>, VmError> {
let mut output = vec::Vec::with_capacity(object.len());
for (key, value) in object {
output.push((key.as_str().into(), Key::from_value(value)?));
}
Ok(output.into_boxed_slice())
}
}
pub fn into_value(self) -> Value {
return match self {
Self::Unit => Value::Unit,
Self::Byte(b) => Value::Byte(b),
Self::Char(c) => Value::Char(c),
Self::Bool(b) => Value::Bool(b),
Self::Integer(n) => Value::Integer(n),
Self::String(s) => match s {
StringKey::String(s) => Value::String(Shared::new(String::from(s))),
StringKey::StaticString(s) => Value::StaticString(s),
},
Self::Bytes(b) => Value::Bytes(Shared::new(b)),
Self::Option(option) => Value::Option(Shared::new(match option {
Some(some) => Some(some.into_value()),
None => None,
})),
Self::Vec(vec) => {
let mut v = Vec::with_capacity(vec.len());
for value in vec {
v.push(value.into_value());
}
Value::Vec(Shared::new(v))
}
Self::Tuple(tuple) => Value::Tuple(Shared::new(tuple_into_value(tuple))),
Self::Variant(variant) => {
let data = match variant.data {
VariantKeyData::Unit => VariantData::Unit,
VariantKeyData::Tuple(tuple) => VariantData::Tuple(tuple_into_value(tuple)),
VariantKeyData::Struct(st) => VariantData::Struct(struct_into_value(st)),
};
Value::Variant(Shared::new(Variant {
rtti: variant.rtti,
data,
}))
}
};
fn tuple_into_value(data: Box<[Key]>) -> Tuple {
let mut t = vec::Vec::with_capacity(data.len());
for value in vec::Vec::from(data) {
t.push(value.into_value());
}
Tuple::from(t)
}
fn struct_into_value(data: Box<[(Box<str>, Key)]>) -> Object {
let mut object = Object::with_capacity(data.len());
for (key, value) in vec::Vec::from(data) {
object.insert(key.into(), value.into_value());
}
object
}
}
pub fn into_bool(self) -> Result<bool, Self> {
match self {
Self::Bool(value) => Ok(value),
value => Err(value),
}
}
pub fn type_info(&self) -> TypeInfo {
match self {
Self::Unit => TypeInfo::StaticType(crate::UNIT_TYPE),
Self::Byte(..) => TypeInfo::StaticType(crate::BYTE_TYPE),
Self::Char(..) => TypeInfo::StaticType(crate::CHAR_TYPE),
Self::Bool(..) => TypeInfo::StaticType(crate::BOOL_TYPE),
Self::String(..) => TypeInfo::StaticType(crate::STRING_TYPE),
Self::Bytes(..) => TypeInfo::StaticType(crate::BYTES_TYPE),
Self::Integer(..) => TypeInfo::StaticType(crate::INTEGER_TYPE),
Self::Vec(..) => TypeInfo::StaticType(crate::VEC_TYPE),
Self::Tuple(..) => TypeInfo::StaticType(crate::TUPLE_TYPE),
Self::Option(..) => TypeInfo::StaticType(crate::OPTION_TYPE),
Self::Variant(variant) => TypeInfo::Variant(variant.rtti.clone()),
}
}
}
impl fmt::Debug for Key {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Key::Unit => write!(f, "()"),
Key::Byte(b) => write!(f, "{:?}", b),
Key::Char(c) => write!(f, "{:?}", c),
Key::Bool(b) => write!(f, "{}", b),
Key::Integer(n) => write!(f, "{}", n),
Key::String(s) => write!(f, "{:?}", s),
Key::Bytes(b) => write!(f, "{:?}", b),
Key::Vec(vec) => write!(f, "{:?}", vec),
Key::Tuple(tuple) => write!(f, "{:?}", tuple),
Key::Option(opt) => write!(f, "{:?}", opt),
Key::Variant(variant) => write!(f, "{:?}", variant),
}
}
}
impl FromValue for Key {
fn from_value(value: Value) -> Result<Self, VmError> {
Key::from_value(&value)
}
}
impl ToValue for Key {
fn to_value(self) -> Result<Value, VmError> {
Ok(Key::into_value(self))
}
}
impl<'de> de::Deserialize<'de> for Key {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
deserializer.deserialize_any(KeyVisitor)
}
}
impl ser::Serialize for Key {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
use serde::ser::SerializeSeq as _;
match self {
Self::Unit => serializer.serialize_unit(),
Self::Bool(b) => serializer.serialize_bool(*b),
Self::Char(c) => serializer.serialize_char(*c),
Self::Byte(c) => serializer.serialize_u8(*c),
Self::Integer(integer) => serializer.serialize_i64(*integer),
Self::String(string) => serializer.serialize_str(string.as_str()),
Self::Bytes(bytes) => serializer.serialize_bytes(&*bytes),
Self::Vec(vec) => {
let mut serializer = serializer.serialize_seq(Some(vec.len()))?;
for value in &*vec {
serializer.serialize_element(value)?;
}
serializer.end()
}
Self::Tuple(tuple) => {
let mut serializer = serializer.serialize_seq(Some(tuple.len()))?;
for value in tuple.iter() {
serializer.serialize_element(value)?;
}
serializer.end()
}
Self::Option(option) => <Option<Box<Key>>>::serialize(option, serializer),
Self::Variant(..) => Err(ser::Error::custom("cannot serialize variants")),
}
}
}
struct KeyVisitor;
impl<'de> de::Visitor<'de> for KeyVisitor {
type Value = Key;
fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.write_str("any valid key")
}
#[inline]
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::String(StringKey::String(value.into())))
}
#[inline]
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::String(StringKey::String(value.into())))
}
#[inline]
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::Bytes(Bytes::from_vec(v.to_vec())))
}
#[inline]
fn visit_byte_buf<E>(self, v: vec::Vec<u8>) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::Bytes(Bytes::from_vec(v)))
}
#[inline]
fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::Integer(v as i64))
}
#[inline]
fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::Integer(v as i64))
}
#[inline]
fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::Integer(v as i64))
}
#[inline]
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::Integer(v))
}
#[inline]
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::Integer(v as i64))
}
#[inline]
fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::Integer(v as i64))
}
#[inline]
fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::Integer(v as i64))
}
#[inline]
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::Integer(v as i64))
}
#[inline]
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::Integer(v as i64))
}
#[inline]
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::Integer(v as i64))
}
#[inline]
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::Bool(v))
}
#[inline]
fn visit_none<E>(self) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::Unit)
}
#[inline]
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Key::Unit)
}
#[inline]
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where
V: de::SeqAccess<'de>,
{
let mut vec = if let Some(hint) = visitor.size_hint() {
vec::Vec::with_capacity(hint)
} else {
vec::Vec::new()
};
while let Some(elem) = visitor.next_element()? {
vec.push(elem);
}
Ok(Key::Vec(vec))
}
}
impl From<String> for Key {
fn from(value: String) -> Self {
Self::String(StringKey::String(value.into()))
}
}
impl From<i64> for Key {
fn from(value: i64) -> Self {
Self::Integer(value)
}
}
#[derive(Debug, Clone)]
pub enum StringKey {
String(Box<str>),
StaticString(Arc<StaticString>),
}
impl StringKey {
fn as_str(&self) -> &str {
match self {
Self::String(s) => s.as_ref(),
Self::StaticString(s) => s.as_str(),
}
}
}
impl cmp::PartialEq for StringKey {
fn eq(&self, other: &Self) -> bool {
self.as_str() == other.as_str()
}
}
impl cmp::Eq for StringKey {}
impl hash::Hash for StringKey {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.as_str().hash(state)
}
}
impl cmp::PartialOrd for StringKey {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.as_str().partial_cmp(other.as_str())
}
}
impl cmp::Ord for StringKey {
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.as_str().cmp(other.as_str())
}
}
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct VariantKey {
rtti: Arc<VariantRtti>,
data: VariantKeyData,
}
impl fmt::Debug for VariantKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.rtti.item)?;
match &self.data {
VariantKeyData::Unit => (),
VariantKeyData::Tuple(tuple) => {
let mut it = tuple.iter();
let last = it.next_back();
write!(f, "(")?;
for v in it {
write!(f, "{:?}, ", v)?;
}
if let Some(v) = last {
write!(f, "{:?}", v)?;
}
write!(f, ")")?;
}
VariantKeyData::Struct(st) => f
.debug_map()
.entries(st.iter().map(|(k, v)| (k, v)))
.finish()?,
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum VariantKeyData {
Unit,
Tuple(Box<[Key]>),
Struct(Box<[(Box<str>, Key)]>),
}