Remove indirection through Visitor

This commit is contained in:
Dirkjan Ochtman 2022-09-06 23:54:36 +02:00
parent 4b0d5a7698
commit 01c896a9b2
4 changed files with 119 additions and 207 deletions

View File

@ -47,7 +47,7 @@ impl Deserializer {
xml_generics.params.push(xml.into());
let (_, ty_generics, where_clause) = input.generics.split_for_impl();
let (xml_impl_generics, xml_ty_generics, xml_where_clause) = xml_generics.split_for_impl();
let (xml_impl_generics, _, _) = xml_generics.split_for_impl();
let mut namespaces_map = quote!(let mut namespaces_map = std::collections::HashMap::new(););
for (k, v) in container_meta.ns.prefixes.iter() {
@ -109,7 +109,7 @@ impl Deserializer {
let out = quote!(
impl #xml_impl_generics FromXml<'xml> for #ident #ty_generics #where_clause {
fn deserialize<'cx>(deserializer: &'cx mut ::instant_xml::Deserializer<'cx, 'xml>) -> Result<Self, ::instant_xml::Error> {
use ::instant_xml::de::{Deserializer, Id, Visitor, Node};
use ::instant_xml::de::{Deserializer, Id, Node};
use ::instant_xml::Error;
use ::core::marker::PhantomData;
@ -123,69 +123,52 @@ impl Deserializer {
__Ignore,
}
struct StructVisitor #xml_ty_generics {
marker: PhantomData<#ident #ty_generics>,
lifetime: PhantomData<&'xml ()>,
}
#declare_values
loop {
let node = match deserializer.next() {
Some(result) => result?,
None => break,
};
impl #xml_impl_generics Visitor<'xml> for StructVisitor #xml_ty_generics #xml_where_clause {
type Value = #ident #ty_generics;
fn visit_struct<'cx>(
deserializer: &'cx mut Deserializer<'cx, 'xml>,
) -> Result<Self::Value, Error> {
#declare_values
loop {
let node = match deserializer.next() {
Some(result) => result?,
None => break,
match node {
Node::Attribute(attr) => {
let id = deserializer.attribute_id(&attr)?;
let field = {
#attributes_consts
match id {
#attributes_names
_ => __Attributes::__Ignore
}
};
match node {
Node::Attribute(attr) => {
let id = deserializer.attribute_id(&attr)?;
let field = {
#attributes_consts
match id {
#attributes_names
_ => __Attributes::__Ignore
}
};
match field {
#attr_type_match
__Attributes::__Ignore => {}
}
}
Node::Open(data) => {
let id = deserializer.element_id(&data)?;
let element = {
#elements_consts
match id {
#elements_names
_ => __Elements::__Ignore
}
};
match element {
#elem_type_match
__Elements::__Ignore => {
let mut nested = deserializer.nested(data);
nested.ignore()?;
}
}
}
_ => return Err(Error::UnexpectedState),
match field {
#attr_type_match
__Attributes::__Ignore => {}
}
}
Node::Open(data) => {
let id = deserializer.element_id(&data)?;
let element = {
#elements_consts
match id {
#elements_names
_ => __Elements::__Ignore
}
};
Ok(Self::Value {
#return_val
})
match element {
#elem_type_match
__Elements::__Ignore => {
let mut nested = deserializer.nested(data);
nested.ignore()?;
}
}
}
_ => return Err(Error::UnexpectedState),
}
}
StructVisitor::visit_struct(deserializer)
Ok(Self { #return_val })
}
const KIND: ::instant_xml::de::Kind = ::instant_xml::de::Kind::Element(::instant_xml::de::Id {

View File

@ -267,20 +267,6 @@ impl<'xml> Iterator for Context<'xml> {
}
}
pub trait Visitor<'xml>: Sized {
type Value;
fn visit_str(_value: &'xml str) -> Result<Self::Value, Error> {
unimplemented!();
}
fn visit_struct<'cx>(
_deserializer: &'cx mut Deserializer<'cx, 'xml>,
) -> Result<Self::Value, Error> {
unimplemented!();
}
}
#[derive(Debug)]
pub enum Node<'xml> {
Attribute(Attribute<'xml>),

View File

@ -1,49 +1,51 @@
use std::borrow::Cow;
use std::fmt;
use std::marker::PhantomData;
use std::str::FromStr;
use crate::de::{Kind, Node, Visitor};
use crate::de::{Kind, Node};
use crate::ser::FieldAttribute;
use crate::{Deserializer, Error, FromXml, Serializer, ToXml};
// Deserializer
struct FromStrToVisitor<T: FromStr>(PhantomData<T>)
where
T: FromStr,
<T as FromStr>::Err: std::fmt::Display;
struct FromXmlStr<T: FromStr>(Option<T>);
impl<'xml, T: 'xml> Visitor<'xml> for FromStrToVisitor<T>
where
T: FromStr,
<T as FromStr>::Err: std::fmt::Display,
{
type Value = T;
impl<'xml, T: FromStr> FromXml<'xml> for FromXmlStr<T> {
fn deserialize(deserializer: &mut Deserializer<'_, 'xml>) -> Result<Self, Error> {
let (value, element) = match deserializer.next() {
Some(Ok(Node::AttributeValue(s))) => (s, false),
Some(Ok(Node::Element(s))) => (s, true),
Some(Ok(_)) => return Err(Error::ExpectedScalar),
Some(Err(e)) => return Err(e),
None => return Ok(Self(None)),
};
fn visit_str(value: &str) -> Result<Self::Value, Error> {
match FromStr::from_str(value) {
Ok(v) => Ok(v),
Err(e) => Err(Error::Other(e.to_string())),
let value = match T::from_str(value) {
Ok(value) => value,
Err(_) => return Err(Error::UnexpectedValue),
};
if element {
match deserializer.next() {
Some(Ok(_)) => return Err(Error::UnexpectedState),
Some(Err(e)) => return Err(e),
_ => {}
}
}
Ok(Self(Some(value)))
}
}
struct BoolVisitor;
impl<'xml> Visitor<'xml> for BoolVisitor {
type Value = bool;
fn visit_str(value: &str) -> Result<Self::Value, Error> {
FromStrToVisitor::<Self::Value>::visit_str(value)
}
const KIND: Kind = Kind::Scalar;
}
impl<'xml> FromXml<'xml> for bool {
const KIND: Kind = Kind::Scalar;
fn deserialize(deserializer: &mut Deserializer<'_, 'xml>) -> Result<Self, Error> {
deserialize_scalar::<BoolVisitor>(deserializer)
fn deserialize<'cx>(deserializer: &'cx mut Deserializer<'cx, 'xml>) -> Result<Self, Error> {
FromXmlStr::<Self>::deserialize(deserializer)?
.0
.ok_or(Error::MissingValue)
}
const KIND: Kind = Kind::Scalar;
}
// Serializer
@ -89,31 +91,15 @@ macro_rules! to_xml_for_number {
};
}
struct NumberVisitor<T>
where
T: FromStr,
<T as FromStr>::Err: std::fmt::Display,
{
marker: PhantomData<T>,
}
impl<'xml, T: 'xml> Visitor<'xml> for NumberVisitor<T>
where
T: FromStr,
<T as FromStr>::Err: std::fmt::Display,
{
type Value = T;
fn visit_str(value: &str) -> Result<Self::Value, Error> {
FromStrToVisitor::<Self::Value>::visit_str(value)
}
}
macro_rules! from_xml_for_number {
($typ:ty) => {
impl<'xml> FromXml<'xml> for $typ {
fn deserialize(deserializer: &mut Deserializer) -> Result<Self, Error> {
deserialize_scalar::<NumberVisitor<$typ>>(deserializer)
fn deserialize<'cx>(
deserializer: &'cx mut Deserializer<'cx, 'xml>,
) -> Result<Self, Error> {
FromXmlStr::<Self>::deserialize(deserializer)?
.0
.ok_or(Error::MissingValue)
}
const KIND: Kind = Kind::Scalar;
@ -134,90 +120,66 @@ from_xml_for_number!(usize);
from_xml_for_number!(f32);
from_xml_for_number!(f64);
struct StringVisitor;
impl<'xml> Visitor<'xml> for StringVisitor {
type Value = String;
fn visit_str(value: &str) -> Result<Self::Value, Error> {
Ok(escape_back(value).into_owned())
impl<'xml> FromXml<'xml> for char {
fn deserialize<'cx>(deserializer: &'cx mut Deserializer<'cx, 'xml>) -> Result<Self, Error> {
FromXmlStr::<Self>::deserialize(deserializer)?
.0
.ok_or(Error::MissingValue)
}
const KIND: Kind = Kind::Scalar;
}
impl<'xml> FromXml<'xml> for String {
fn deserialize<'cx>(deserializer: &'cx mut Deserializer<'cx, 'xml>) -> Result<Self, Error> {
Ok(<Cow<'xml, str> as FromXml<'xml>>::deserialize(deserializer)?.into_owned())
}
const KIND: Kind = Kind::Scalar;
fn deserialize(deserializer: &mut Deserializer) -> Result<Self, Error> {
deserialize_scalar::<StringVisitor>(deserializer)
}
}
struct CharVisitor;
impl<'xml> Visitor<'xml> for CharVisitor {
type Value = char;
fn visit_str(value: &str) -> Result<Self::Value, Error> {
match value.len() {
1 => Ok(value.chars().next().expect("char type")),
_ => Err(Error::Other("Expected char type".to_string())),
}
}
}
impl<'xml> FromXml<'xml> for char {
const KIND: Kind = Kind::Scalar;
fn deserialize(deserializer: &mut Deserializer) -> Result<Self, Error> {
deserialize_scalar::<CharVisitor>(deserializer)
}
}
struct StrVisitor;
impl<'a> Visitor<'a> for StrVisitor {
type Value = &'a str;
fn visit_str(value: &'a str) -> Result<Self::Value, Error> {
match escape_back(value) {
Cow::Owned(v) => Err(Error::Other(format!("Unsupported char: {}", v))),
Cow::Borrowed(v) => Ok(v),
}
}
}
impl<'xml> FromXml<'xml> for &'xml str {
fn deserialize<'cx>(deserializer: &'cx mut Deserializer<'cx, 'xml>) -> Result<Self, Error> {
Ok(
match <Cow<'xml, str> as FromXml<'xml>>::deserialize(deserializer)? {
Cow::Borrowed(s) => s,
Cow::Owned(_) => return Err(Error::UnexpectedValue),
},
)
}
const KIND: Kind = Kind::Scalar;
fn deserialize(deserializer: &mut Deserializer<'_, 'xml>) -> Result<Self, Error> {
deserialize_scalar::<StrVisitor>(deserializer)
}
}
struct CowStrVisitor;
impl<'a> Visitor<'a> for CowStrVisitor {
type Value = Cow<'a, str>;
fn visit_str(value: &'a str) -> Result<Self::Value, Error> {
Ok(escape_back(value))
}
}
impl<'xml> FromXml<'xml> for Cow<'xml, str> {
const KIND: Kind = Kind::Scalar;
fn deserialize(deserializer: &mut Deserializer<'_, 'xml>) -> Result<Self, Error> {
deserialize_scalar::<CowStrVisitor>(deserializer)
let (value, element) = match deserializer.next() {
Some(Ok(Node::AttributeValue(s))) => (s, false),
Some(Ok(Node::Element(s))) => (s, true),
Some(Ok(_)) => return Err(Error::ExpectedScalar),
Some(Err(e)) => return Err(e),
None => return Err(Error::MissingValue),
};
let value = escape_back(value);
if element {
match deserializer.next() {
Some(Ok(_)) => return Err(Error::UnexpectedState),
Some(Err(e)) => return Err(e),
_ => {}
}
}
Ok(value)
}
const KIND: Kind = Kind::Scalar;
}
impl<'xml, T> FromXml<'xml> for Option<T>
where
T: FromXml<'xml>,
{
const KIND: Kind = <T>::KIND;
fn deserialize<'cx>(deserializer: &'cx mut Deserializer<'cx, 'xml>) -> Result<Self, Error> {
match <T>::deserialize(deserializer) {
Ok(v) => Ok(Some(v)),
@ -228,6 +190,8 @@ where
fn missing_value() -> Result<Self, Error> {
Ok(None)
}
const KIND: Kind = <T>::KIND;
}
fn escape_back(input: &str) -> Cow<'_, str> {
@ -362,27 +326,6 @@ impl<T: ToXml> ToXml for Option<T> {
}
}
fn deserialize_scalar<'xml, V: Visitor<'xml>>(
deserializer: &mut Deserializer<'_, 'xml>,
) -> Result<V::Value, Error>
where
V::Value: FromXml<'xml>,
{
let value = match deserializer.next() {
Some(Ok(Node::AttributeValue(s))) => return V::visit_str(s),
Some(Ok(Node::Element(s))) => V::visit_str(s)?,
Some(Ok(_)) => return Err(Error::ExpectedScalar),
Some(Err(e)) => return Err(e),
None => return <V::Value as FromXml<'_>>::missing_value(),
};
match deserializer.next() {
Some(Ok(_)) => Err(Error::UnexpectedState),
Some(Err(e)) => Err(e),
None => Ok(value),
}
}
fn escape(input: &str) -> Result<Cow<'_, str>, Error> {
let mut result = String::with_capacity(input.len());
let mut last_end = 0;

View File

@ -30,7 +30,7 @@ fn escape_back() {
from_str(
"<StructSpecialEntities xmlns=\"URI\"><string>&lt;&gt;&amp;&quot;&apos;adsad&quot;</string><str>str&amp;</str></StructSpecialEntities>"
),
Err::<StructSpecialEntities, _>(Error::Other("Unsupported char: str&".to_string()))
Err::<StructSpecialEntities, _>(Error::UnexpectedValue)
);
// Borrowed