pub use bytes::Bytes;
pub use smol_str::SmolStr;
use std::any::TypeId;
use thiserror::Error;
mod field_mask;
mod instance;
mod owned;
mod primatives;
mod typed;
mod value;
pub use field_mask::*;
pub use instance::*;
pub use owned::*;
pub use primatives::*;
pub use typed::*;
pub use value::*;
#[cfg(test)]
mod tests;
#[derive(Error, Debug)]
pub enum Error {
#[error("{0} not found")]
NotFound(SmolStr),
#[error("type error expected {expected} found {found}")]
TypeError { expected: SmolStr, found: SmolStr },
}
pub trait FromValue<'a, 's>: Sized {
fn from_value(value: &Value<'a, 's>) -> Option<Self>;
}
pub trait IntoInner<T> {
fn into_inner(self) -> Result<T, Error>;
}
impl<'val, 'ty, 'r, T: Typed<'ty> + Sized + 'ty> FromValue<'val, 'ty> for &'r T
where
'val: 'r,
'ty: 'val,
{
fn from_value(value: &Value<'val, 'ty>) -> Option<Self> {
match value.0 {
ValueInner::String(s) => s.as_inst().downcast_ref::<T>(),
ValueInner::Bytes(b) => b.as_inst().downcast_ref::<T>(),
ValueInner::Vec(v) => v.as_inst().downcast_ref::<T>(),
ValueInner::HashMap(h) => h.as_inst().downcast_ref::<T>(),
ValueInner::Struct(s) => s.as_inst().downcast_ref::<T>(),
ValueInner::Enum(s) => s.as_inst().downcast_ref::<T>(),
ValueInner::Option(s) => s.as_inst().downcast_ref::<T>(),
_ => None,
}
}
}
pub trait IntoValue {
fn into_value<'val, 'ty>(self) -> Value<'val, 'ty>;
}
impl<'ty, T: Instance<'ty> + Typed<'ty> + 'ty> IntoInner<T> for OwnedValue<'ty> {
fn into_inner(self) -> Result<T, Error> {
let inst = match self {
OwnedValue::Vec(s) => s.into_boxed_instance(),
OwnedValue::HashMap(s) => s.into_boxed_instance(),
OwnedValue::Enum(s) => s.into_boxed_instance(),
OwnedValue::Struct(s) => s.into_boxed_instance(),
OwnedValue::Option(s) => s.into_boxed_instance(),
OwnedValue::String(s) => Box::new(s),
OwnedValue::Bytes(s) => Box::new(s),
_ => {
return Err(Error::TypeError {
expected: "instance".into(),
found: format!("{:?}", self).into(),
});
}
};
let inst = inst.downcast::<T>().ok_or_else(|| Error::TypeError {
expected: "instance".into(),
found: "other".into(),
})?;
Ok(*inst)
}
}
impl<'val, 'ty> FromValue<'val, 'ty> for &'val (dyn OptionInstance<'ty> + 'ty) {
fn from_value(value: &Value<'val, 'ty>) -> Option<Self> {
if let ValueInner::Option(o) = value.0 {
Some(o)
} else {
None
}
}
}
impl<'val, 'ty> FromValue<'val, 'ty> for &'val str {
fn from_value(value: &Value<'val, 'ty>) -> Option<&'val str> {
if let ValueInner::Str(s) = value.0 {
Some(s)
} else {
None
}
}
}
#[derive(Clone, PartialEq, Debug)]
pub enum ValueTy {
U8,
U16,
U32,
U64,
I8,
I16,
I32,
I64,
F32,
F64,
Bool,
Str,
String,
Bytes,
VecInstance,
Vec(Box<ValueTy>),
StructInstance,
Struct(TypeId),
HashMapInstance,
HashMap(Box<ValueTy>),
Enum(TypeId),
Option(Box<ValueTy>),
}
impl<'ty, T: Typed<'ty> + Clone + 'ty> Instance<'ty> for Option<T> {
fn name(&self) -> SmolStr {
format!("Option<{:?}>", T::ty()).into()
}
fn as_inst(&self) -> &(dyn Instance<'ty> + 'ty) {
self
}
}
impl<'ty, T: Typed<'ty> + Clone + 'ty> OptionInstance<'ty> for Option<T> {
fn value<'val>(&'val self) -> Option<Value<'val, 'ty>>
where
'ty: 'val,
{
self.as_ref().map(|val| val.as_value())
}
fn boxed_clone(&self) -> Box<dyn OptionInstance<'ty> + 'ty> {
Box::new(self.clone())
}
fn into_boxed_instance(self: Box<Self>) -> Box<dyn Instance<'ty> + 'ty> {
self
}
}