use crate::{
Any, Bytes, FnPtr, Future, Generator, GeneratorState, Hash, OwnedMut, OwnedRef, RawOwnedMut,
RawOwnedRef, Shared, StaticString, Tuple, ValueError, ValueErrorKind, ValueType, ValueTypeInfo,
};
use std::any;
use std::fmt;
use std::sync::Arc;
pub type Object<T> = crate::collections::HashMap<String, T>;
#[derive(Debug)]
pub struct TypedTuple {
pub(crate) hash: Hash,
pub(crate) tuple: Box<[Value]>,
}
impl TypedTuple {
pub fn type_info(&self) -> ValueTypeInfo {
ValueTypeInfo::Type(self.hash)
}
}
#[derive(Debug)]
pub struct VariantTuple {
pub(crate) enum_hash: Hash,
pub(crate) hash: Hash,
pub(crate) tuple: Box<[Value]>,
}
impl VariantTuple {
pub fn type_info(&self) -> ValueTypeInfo {
ValueTypeInfo::Type(self.enum_hash)
}
}
#[derive(Debug)]
pub struct TypedObject {
pub hash: Hash,
pub object: Object<Value>,
}
impl TypedObject {
pub fn type_info(&self) -> ValueTypeInfo {
ValueTypeInfo::Type(self.hash)
}
}
#[derive(Debug)]
pub struct VariantObject {
pub enum_hash: Hash,
pub hash: Hash,
pub object: Object<Value>,
}
impl VariantObject {
pub fn type_info(&self) -> ValueTypeInfo {
ValueTypeInfo::Type(self.enum_hash)
}
}
#[derive(Clone)]
pub enum Value {
Unit,
Bool(bool),
Byte(u8),
Char(char),
Integer(i64),
Float(f64),
Type(Hash),
StaticString(Arc<StaticString>),
String(Shared<String>),
Bytes(Shared<Bytes>),
Vec(Shared<Vec<Value>>),
Tuple(Shared<Tuple>),
Object(Shared<Object<Value>>),
Future(Shared<Future>),
Generator(Shared<Generator>),
GeneratorState(Shared<GeneratorState>),
Option(Shared<Option<Value>>),
Result(Shared<Result<Value, Value>>),
TypedTuple(Shared<TypedTuple>),
VariantTuple(Shared<VariantTuple>),
TypedObject(Shared<TypedObject>),
VariantObject(Shared<VariantObject>),
FnPtr(Shared<FnPtr>),
Any(Shared<Any>),
}
impl Value {
pub fn vec(vec: Vec<Value>) -> Self {
Self::Vec(Shared::new(vec))
}
pub fn tuple(vec: Vec<Value>) -> Self {
Self::Tuple(Shared::new(Tuple::from(vec)))
}
pub fn typed_tuple(hash: Hash, vec: Vec<Value>) -> Self {
Self::TypedTuple(Shared::new(TypedTuple {
hash,
tuple: vec.into_boxed_slice(),
}))
}
pub fn variant_tuple(enum_hash: Hash, hash: Hash, vec: Vec<Value>) -> Self {
Self::VariantTuple(Shared::new(VariantTuple {
enum_hash,
hash,
tuple: vec.into_boxed_slice(),
}))
}
#[inline]
pub fn into_unit(self) -> Result<(), ValueError> {
match self {
Value::Unit => Ok(()),
actual => Err(ValueError::from(ValueErrorKind::ExpectedUnit {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_bool(self) -> Result<bool, ValueError> {
match self {
Self::Bool(b) => Ok(b),
actual => Err(ValueError::from(ValueErrorKind::ExpectedBoolean {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_byte(self) -> Result<u8, ValueError> {
match self {
Self::Byte(b) => Ok(b),
actual => Err(ValueError::from(ValueErrorKind::ExpectedByte {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_char(self) -> Result<char, ValueError> {
match self {
Self::Char(c) => Ok(c),
actual => Err(ValueError::from(ValueErrorKind::ExpectedChar {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_integer(self) -> Result<i64, ValueError> {
match self {
Self::Integer(integer) => Ok(integer),
actual => Err(ValueError::from(ValueErrorKind::ExpectedInteger {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_float(self) -> Result<f64, ValueError> {
match self {
Self::Float(float) => Ok(float),
actual => Err(ValueError::from(ValueErrorKind::ExpectedFloat {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_result(self) -> Result<Shared<Result<Value, Value>>, ValueError> {
match self {
Self::Result(result) => Ok(result),
actual => Err(ValueError::from(ValueErrorKind::ExpectedResult {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_future(self) -> Result<Shared<Future>, ValueError> {
match self {
Value::Future(future) => Ok(future),
actual => Err(ValueError::from(ValueErrorKind::ExpectedFuture {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_generator(self) -> Result<Shared<Generator>, ValueError> {
match self {
Value::Generator(generator) => Ok(generator),
actual => Err(ValueError::from(ValueErrorKind::ExpectedGenerator {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_generator_state(self) -> Result<Shared<GeneratorState>, ValueError> {
match self {
Value::GeneratorState(state) => Ok(state),
actual => Err(ValueError::from(ValueErrorKind::ExpectedGeneratorState {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_option(self) -> Result<Shared<Option<Value>>, ValueError> {
match self {
Self::Option(option) => Ok(option),
actual => Err(ValueError::from(ValueErrorKind::ExpectedOption {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_string(self) -> Result<Shared<String>, ValueError> {
match self {
Self::String(string) => Ok(string),
actual => Err(ValueError::from(ValueErrorKind::ExpectedString {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_bytes(self) -> Result<Shared<Bytes>, ValueError> {
match self {
Self::Bytes(bytes) => Ok(bytes),
actual => Err(ValueError::from(ValueErrorKind::ExpectedBytes {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_vec(self) -> Result<Shared<Vec<Value>>, ValueError> {
match self {
Self::Vec(vec) => Ok(vec),
actual => Err(ValueError::from(ValueErrorKind::ExpectedVec {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_tuple(self) -> Result<Shared<Tuple>, ValueError> {
match self {
Self::Tuple(tuple) => Ok(tuple),
actual => Err(ValueError::from(ValueErrorKind::ExpectedTuple {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_object(self) -> Result<Shared<Object<Value>>, ValueError> {
match self {
Self::Object(object) => Ok(object),
actual => Err(ValueError::from(ValueErrorKind::ExpectedObject {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_fn_ptr(self) -> Result<Shared<FnPtr>, ValueError> {
match self {
Self::FnPtr(fn_ptr) => Ok(fn_ptr),
actual => Err(ValueError::from(ValueErrorKind::ExpectedFnPtr {
actual: actual.type_info()?,
})),
}
}
#[inline]
pub fn into_any(self) -> Result<Shared<Any>, ValueError> {
match self {
Self::Any(any) => Ok(any),
actual => Err(ValueError::from(ValueErrorKind::ExpectedAny {
expected: any::type_name::<Any>(),
actual: actual.type_info()?,
})),
}
}
#[inline]
pub unsafe fn unsafe_into_any_ref<T>(self) -> Result<(*const T, RawOwnedRef), ValueError>
where
T: any::Any,
{
match self {
Self::Any(any) => {
let any = any.downcast_owned_ref::<T>()?;
let (data, guard) = OwnedRef::into_raw(any);
Ok((data, guard))
}
actual => Err(ValueError::from(ValueErrorKind::ExpectedAny {
expected: any::type_name::<T>(),
actual: actual.type_info()?,
})),
}
}
#[inline]
pub unsafe fn unsafe_into_any_mut<T>(self) -> Result<(*mut T, RawOwnedMut), ValueError>
where
T: any::Any,
{
match self {
Self::Any(any) => {
let any = any.downcast_owned_mut::<T>()?;
let (data, guard) = OwnedMut::into_raw(any);
Ok((data, guard))
}
actual => Err(ValueError::from(ValueErrorKind::ExpectedAny {
expected: any::type_name::<T>(),
actual: actual.type_info()?,
})),
}
}
pub fn value_type(&self) -> Result<ValueType, ValueError> {
Ok(match self {
Self::Unit => ValueType::StaticType(crate::UNIT_TYPE),
Self::Bool(..) => ValueType::StaticType(crate::BOOL_TYPE),
Self::Byte(..) => ValueType::StaticType(crate::BYTE_TYPE),
Self::Char(..) => ValueType::StaticType(crate::CHAR_TYPE),
Self::Integer(..) => ValueType::StaticType(crate::INTEGER_TYPE),
Self::Float(..) => ValueType::StaticType(crate::FLOAT_TYPE),
Self::StaticString(..) => ValueType::StaticType(crate::STRING_TYPE),
Self::String(..) => ValueType::StaticType(crate::STRING_TYPE),
Self::Bytes(..) => ValueType::StaticType(crate::BYTES_TYPE),
Self::Vec(..) => ValueType::StaticType(crate::VEC_TYPE),
Self::Tuple(..) => ValueType::StaticType(crate::TUPLE_TYPE),
Self::Object(..) => ValueType::StaticType(crate::OBJECT_TYPE),
Self::Future(..) => ValueType::StaticType(crate::FUTURE_TYPE),
Self::Generator(..) => ValueType::StaticType(crate::GENERATOR_TYPE),
Self::GeneratorState(..) => ValueType::StaticType(crate::GENERATOR_STATE_TYPE),
Self::Result(..) => ValueType::StaticType(crate::RESULT_TYPE),
Self::Option(..) => ValueType::StaticType(crate::OPTION_TYPE),
Self::FnPtr(..) => ValueType::StaticType(crate::FN_PTR_TYPE),
Self::Type(hash) => ValueType::Type(*hash),
Self::TypedObject(object) => ValueType::Type(object.borrow_ref()?.hash),
Self::VariantObject(object) => {
let object = object.borrow_ref()?;
ValueType::Type(object.enum_hash)
}
Self::TypedTuple(tuple) => ValueType::Type(tuple.borrow_ref()?.hash),
Self::VariantTuple(tuple) => {
let tuple = tuple.borrow_ref()?;
ValueType::Type(tuple.enum_hash)
}
Self::Any(any) => ValueType::Type(any.borrow_ref()?.type_hash()),
})
}
pub fn type_info(&self) -> Result<ValueTypeInfo, ValueError> {
Ok(match self {
Self::Unit => ValueTypeInfo::StaticType(crate::UNIT_TYPE),
Self::Bool(..) => ValueTypeInfo::StaticType(crate::BOOL_TYPE),
Self::Byte(..) => ValueTypeInfo::StaticType(crate::BYTE_TYPE),
Self::Char(..) => ValueTypeInfo::StaticType(crate::CHAR_TYPE),
Self::Integer(..) => ValueTypeInfo::StaticType(crate::INTEGER_TYPE),
Self::Float(..) => ValueTypeInfo::StaticType(crate::STRING_TYPE),
Self::StaticString(..) => ValueTypeInfo::StaticType(crate::STRING_TYPE),
Self::String(..) => ValueTypeInfo::StaticType(crate::STRING_TYPE),
Self::Bytes(..) => ValueTypeInfo::StaticType(crate::BYTES_TYPE),
Self::Vec(..) => ValueTypeInfo::StaticType(crate::VEC_TYPE),
Self::Tuple(..) => ValueTypeInfo::StaticType(crate::TUPLE_TYPE),
Self::Object(..) => ValueTypeInfo::StaticType(crate::OBJECT_TYPE),
Self::Future(..) => ValueTypeInfo::StaticType(crate::FUTURE_TYPE),
Self::Generator(..) => ValueTypeInfo::StaticType(crate::GENERATOR_TYPE),
Self::GeneratorState(..) => ValueTypeInfo::StaticType(crate::GENERATOR_STATE_TYPE),
Self::Option(..) => ValueTypeInfo::StaticType(crate::OPTION_TYPE),
Self::Result(..) => ValueTypeInfo::StaticType(crate::RESULT_TYPE),
Self::FnPtr(..) => ValueTypeInfo::StaticType(crate::FN_PTR_TYPE),
Self::Type(hash) => ValueTypeInfo::Type(*hash),
Self::TypedObject(object) => object.borrow_ref()?.type_info(),
Self::VariantObject(object) => object.borrow_ref()?.type_info(),
Self::TypedTuple(tuple) => tuple.borrow_ref()?.type_info(),
Self::VariantTuple(tuple) => tuple.borrow_ref()?.type_info(),
Self::Any(any) => ValueTypeInfo::Any(any.borrow_ref()?.type_name()),
})
}
}
impl fmt::Debug for Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Value::Unit => {
write!(f, "()")?;
}
Value::Bool(value) => {
write!(f, "{:?}", value)?;
}
Value::Byte(value) => {
write!(f, "{:?}", value)?;
}
Value::Char(value) => {
write!(f, "{:?}", value)?;
}
Value::Integer(value) => {
write!(f, "{:?}", value)?;
}
Value::Float(value) => {
write!(f, "{:?}", value)?;
}
Value::Type(value) => {
write!(f, "Type({})", value)?;
}
Value::StaticString(value) => {
write!(f, "{:?}", value)?;
}
Value::String(value) => {
write!(f, "{:?}", value)?;
}
Value::Bytes(value) => {
write!(f, "{:?}", value)?;
}
Value::Vec(value) => {
write!(f, "{:?}", value)?;
}
Value::Tuple(value) => {
write!(f, "{:?}", value)?;
}
Value::Object(value) => {
write!(f, "{:?}", value)?;
}
Value::Future(value) => {
write!(f, "{:?}", value)?;
}
Value::Generator(value) => {
write!(f, "{:?}", value)?;
}
Value::GeneratorState(value) => {
write!(f, "{:?}", value)?;
}
Value::Option(value) => {
write!(f, "{:?}", value)?;
}
Value::Result(value) => {
write!(f, "{:?}", value)?;
}
Value::TypedTuple(value) => {
write!(f, "{:?}", value)?;
}
Value::VariantTuple(value) => {
write!(f, "{:?}", value)?;
}
Value::TypedObject(value) => {
write!(f, "{:?}", value)?;
}
Value::VariantObject(value) => {
write!(f, "{:?}", value)?;
}
Value::FnPtr(value) => {
write!(f, "{:?}", value)?;
}
Value::Any(value) => {
write!(f, "{:?}", value)?;
}
}
Ok(())
}
}
impl From<()> for Value {
fn from((): ()) -> Self {
Self::Unit
}
}
macro_rules! from_impl {
($ty:ty, $variant:ident) => {
impl From<$ty> for Value {
fn from(value: $ty) -> Self {
Self::$variant(value)
}
}
};
}
from_impl!(u8, Byte);
from_impl!(bool, Bool);
from_impl!(char, Char);
from_impl!(i64, Integer);
from_impl!(f64, Float);
from_impl!(Arc<StaticString>, StaticString);
macro_rules! from_shared_impl {
(Shared<$ty:ty>, $variant:ident) => {
from_impl!(Shared<$ty>, $variant);
impl From<$ty> for Value {
fn from(value: $ty) -> Self {
Self::$variant(Shared::new(value))
}
}
};
}
from_shared_impl!(Shared<Bytes>, Bytes);
from_impl!(Shared<Vec<Value>>, Vec);
from_shared_impl!(Shared<Tuple>, Tuple);
from_impl!(Shared<Object<Value>>, Object);
from_shared_impl!(Shared<Future>, Future);
from_shared_impl!(Shared<Generator>, Generator);
from_shared_impl!(Shared<GeneratorState>, GeneratorState);
from_impl!(Shared<Option<Value>>, Option);
from_impl!(Shared<Result<Value, Value>>, Result);
from_shared_impl!(Shared<TypedTuple>, TypedTuple);
from_shared_impl!(Shared<VariantTuple>, VariantTuple);
from_shared_impl!(Shared<TypedObject>, TypedObject);
from_shared_impl!(Shared<VariantObject>, VariantObject);
from_shared_impl!(Shared<FnPtr>, FnPtr);
from_shared_impl!(Shared<Any>, Any);
#[derive(Debug, Clone, Copy)]
pub enum Integer {
U8(u8),
U16(u16),
U32(u32),
U64(u64),
U128(u128),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
I128(i128),
Isize(isize),
Usize(usize),
}
impl fmt::Display for Integer {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Self::U8(n) => write!(fmt, "{}u8", n),
Self::U16(n) => write!(fmt, "{}u16", n),
Self::U32(n) => write!(fmt, "{}u32", n),
Self::U64(n) => write!(fmt, "{}u64", n),
Self::U128(n) => write!(fmt, "{}u128", n),
Self::I8(n) => write!(fmt, "{}i8", n),
Self::I16(n) => write!(fmt, "{}i16", n),
Self::I32(n) => write!(fmt, "{}i32", n),
Self::I64(n) => write!(fmt, "{}i64", n),
Self::I128(n) => write!(fmt, "{}i128", n),
Self::Isize(n) => write!(fmt, "{}isize", n),
Self::Usize(n) => write!(fmt, "{}usize", n),
}
}
}
#[cfg(test)]
mod tests {
use super::Value;
#[test]
fn test_size() {
assert_eq! {
std::mem::size_of::<Value>(),
16,
};
}
}