use super::*;
pub type DynRestriction<'freeze, T> = Box<dyn crate::Restriction2<<T as crate::Freeze<'freeze>>::Kind>>;
pub trait Freeze<'freeze> {
type Kind: Restriction + for<'kind> Storage<'kind>;
fn de<I>(value: I, restrictions: &Vec<DynRestriction<'freeze, Self>>, context: Context) -> Result<Self, Error>
where
Self: Sized + 'freeze,
I: Into<Value<'freeze>>
;
fn accept(ns: Option<&str>, name: &str, hint: QName<'_>) -> bool where Self: Sized {
hint.eq(ns, name)
}
fn as_kind<'a>(&'a self) -> <Self::Kind as Storage<'a>>::Inner {
unimplemented!();
}
}
impl<'freeze> Freeze<'freeze> for () {
type Kind = SimpleType;
fn de<I>(value: I, restrictions: &Vec<DynRestriction<'freeze, Self>>, context: Context) -> Result<(), Error>
where
Self: Sized + 'freeze,
I: Into<Value<'freeze>>
{
Ok(())
}
fn as_kind<'a>(&'a self) -> <Self::Kind as Storage<'a>>::Inner {
*self
}
}
impl<'freeze> Freeze<'freeze> for &'freeze str {
type Kind = TextType;
fn de<I>(value: I, restrictions: &Vec<DynRestriction<'freeze, Self>>, context: Context) -> Result<Self, Error>
where
Self: Sized + 'freeze,
I: Into<Value<'freeze>>
{
let text = match value.into() {
Value::Text(text) => text,
Value::Node(node) => node.text().ok_or_else(|| Error::Message(format!("Node text is null, expected text when deserialising {}.", ::std::any::type_name::<Self>())))?,
};
Ok(text)
}
fn as_kind<'a>(&'a self) -> <Self::Kind as Storage<'a>>::Inner {
self
}
}
impl<'freeze> Freeze<'freeze> for String {
type Kind = TextType;
fn de<I>(value: I, restrictions: &Vec<DynRestriction<'freeze, Self>>, context: Context) -> Result<Self, Error>
where
Self: Sized + 'freeze,
I: Into<Value<'freeze>>
{
let text = match value.into() {
Value::Text(text) => text,
Value::Node(node) => node.text().unwrap_or(""),
};
let text = text.to_owned();
restrictions.into_iter().map(|r| r.validate(text.as_kind())).collect::<Result<(), String>>()?;
Ok(text)
}
fn as_kind<'a>(&'a self) -> <Self::Kind as Storage<'a>>::Inner {
self
}
}
impl<'freeze> Freeze<'freeze> for roxmltree::Node<'freeze, 'freeze> {
type Kind = ComplexType;
fn de<I>(value: I, restrictions: &Vec<DynRestriction<'freeze, Self>>, context: Context) -> Result<Self, Error>
where
Self: Sized + 'freeze,
I: Into<Value<'freeze>>
{
let node = value.into().as_node().ok_or_else(|| Error::Message(format!("Struct `roxmltree::Node` can only be built from a node in {}.", context.path())))?;
Ok(node)
}
fn as_kind<'a>(&'a self) -> <Self::Kind as Storage<'a>>::Inner {
()
}
}
macro_rules! freeze_xsd_type_impl {
($type:ty, $xsd_kind:ty) => {
impl<'freeze> Freeze<'freeze> for $type {
type Kind = $xsd_kind;
fn de<I>(value: I, restrictions: &Vec<DynRestriction<'freeze, Self>>, context: Context) -> Result<$type, Error>
where
Self: Sized + 'freeze,
I: Into<Value<'freeze>>
{
let text = match value.into() {
Value::Text(text) => text,
Value::Node(node) => node.text().ok_or_else(|| Error::Message(format!("Node text is null, expected text when deserialising {}.", ::std::any::type_name::<Self>())))?,
};
xsd_types::ParseXsd::parse_xsd(text).map_err(|e| Error::ParseError(format!("Value {text} cannot be parsed as {}.", ::std::any::type_name::<$type>())))
}
fn as_kind<'a>(&'a self) -> <Self::Kind as Storage<'a>>::Inner {
todo!()
}
}
}
}
freeze_xsd_type_impl!(xsd_types::QNameBuf, TextType);
freeze_xsd_type_impl!(xsd_types::Base64BinaryBuf, SimpleType);
freeze_xsd_type_impl!(xsd_types::HexBinaryBuf, SimpleType);
freeze_xsd_type_impl!(xsd_types::Boolean, SimpleType);
freeze_xsd_type_impl!(xsd_types::Date, SimpleType);
freeze_xsd_type_impl!(xsd_types::DateTime, SimpleType);
freeze_xsd_type_impl!(xsd_types::DateTimeStamp, SimpleType);
freeze_xsd_type_impl!(xsd_types::DayTimeDuration, SimpleType);
freeze_xsd_type_impl!(xsd_types::Decimal, SimpleType);
freeze_xsd_type_impl!(xsd_types::Double, NumericType);
freeze_xsd_type_impl!(xsd_types::Duration, SimpleType);
freeze_xsd_type_impl!(xsd_types::Float, NumericType);
freeze_xsd_type_impl!(xsd_types::GDay, SimpleType);
freeze_xsd_type_impl!(xsd_types::GMonth, SimpleType);
freeze_xsd_type_impl!(xsd_types::GMonthDay, SimpleType);
freeze_xsd_type_impl!(xsd_types::GYear, SimpleType);
freeze_xsd_type_impl!(xsd_types::GYearMonth, SimpleType);
freeze_xsd_type_impl!(xsd_types::IdBuf, SimpleType);
freeze_xsd_type_impl!(xsd_types::IdRefBuf, SimpleType);
freeze_xsd_type_impl!(xsd_types::Integer, SimpleType);
freeze_xsd_type_impl!(xsd_types::LanguageBuf, SimpleType);
freeze_xsd_type_impl!(xsd_types::NCNameBuf, SimpleType);
freeze_xsd_type_impl!(xsd_types::NMTokenBuf, SimpleType);
freeze_xsd_type_impl!(xsd_types::NameBuf, TextType);
freeze_xsd_type_impl!(xsd_types::NegativeInteger, SimpleType);
freeze_xsd_type_impl!(xsd_types::NonNegativeInteger, SimpleType);
freeze_xsd_type_impl!(xsd_types::NonPositiveInteger, SimpleType);
freeze_xsd_type_impl!(xsd_types::NormalizedString, SimpleType);
freeze_xsd_type_impl!(xsd_types::PositiveInteger, SimpleType);
freeze_xsd_type_impl!(xsd_types::Time, SimpleType);
freeze_xsd_type_impl!(xsd_types::TokenBuf, SimpleType);
freeze_xsd_type_impl!(xsd_types::YearMonthDuration, SimpleType);
freeze_xsd_type_impl!(xsd_types::AnyUriBuf, SimpleType);
freeze_xsd_type_impl!(xsd_types::Byte, SimpleType);
freeze_xsd_type_impl!(xsd_types::Int, SimpleType);
freeze_xsd_type_impl!(xsd_types::Long, SimpleType);
freeze_xsd_type_impl!(xsd_types::Short, SimpleType);
freeze_xsd_type_impl!(xsd_types::UnsignedByte, SimpleType);
freeze_xsd_type_impl!(xsd_types::UnsignedInt, SimpleType);
freeze_xsd_type_impl!(xsd_types::UnsignedLong, SimpleType);
freeze_xsd_type_impl!(xsd_types::UnsignedShort, SimpleType);
macro_rules! freeze_native_type {
($native:ty, $parser:ty, $map:expr, $xsd_kind:ty, $storage:expr) => {
impl<'freeze> Freeze<'freeze> for $native {
type Kind = $xsd_kind;
fn de<I>(value: I, restrictions: &Vec<DynRestriction<'freeze, Self>>, context: Context) -> Result<Self, Error>
where
Self: Sized + 'freeze,
I: Into<Value<'freeze>>
{
let xsd_value: $parser = Freeze::de(value, restrictions, context)?;
Ok($map(xsd_value))
}
fn as_kind<'a>(&'a self) -> <Self::Kind as Storage<'a>>::Inner {
$storage(self)
}
}
}
}
freeze_native_type!(bool, xsd_types::Boolean, |v: xsd_types::Boolean| v.0, SimpleType, |x| ());
freeze_native_type!(f32, xsd_types::Float, |v: xsd_types::Float| v.into_f32(), NumericType, |x: &f32| *x as f64);
freeze_native_type!(f64, xsd_types::Double, |v: xsd_types::Double| v.into_f64(), NumericType, |x: &f64| *x);