xmelt 0.2.0

A serialization/deserialization framework for XML
Documentation
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().ok_or_else(|| Error::Message(format!("Node text is null, expected text when deserialising {} in `{}`.", ::std::any::type_name::<Self>(), context.path())))?,
			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);