use std::borrow::Cow;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::mem::replace;
use std::ops::{Deref, DerefMut};
use std::str::from_utf8;
#[cfg(feature = "quick-xml")]
use quick_xml::{
escape::{escape, unescape},
events::{BytesText, Event},
};
#[cfg(feature = "quick-xml")]
use crate::quick_xml::{
DeserializeHelper, Deserializer, DeserializerArtifact, DeserializerEvent, DeserializerOutput,
DeserializerResult, Error, ErrorKind, SerializeHelper, Serializer, WithDeserializer,
WithSerializer,
};
#[derive(Default, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Text(pub String);
impl Text {
#[must_use]
pub fn new<S: Into<String>>(value: S) -> Self {
Self(value.into())
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
}
impl Display for Text {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
self.0.fmt(f)
}
}
impl<X> From<X> for Text
where
X: Into<String>,
{
fn from(value: X) -> Self {
Self::new(value)
}
}
impl Deref for Text {
type Target = String;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Text {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl WithSerializer for Text {
type Serializer<'x> = TextSerializer<'x>;
fn serializer<'ser>(
&'ser self,
name: Option<&'ser str>,
is_root: bool,
) -> Result<Self::Serializer<'ser>, crate::quick_xml::Error> {
let _name = name;
let _is_root = is_root;
Ok(TextSerializer::Emit { value: self })
}
}
impl WithDeserializer for Text {
type Deserializer = TextDeserializer;
}
#[derive(Debug)]
pub enum TextSerializer<'ser> {
Emit {
value: &'ser Text,
},
Done,
}
impl<'ser> Serializer<'ser> for TextSerializer<'ser> {
fn next(&mut self, helper: &mut SerializeHelper) -> Option<Result<Event<'ser>, Error>> {
let _helper = helper;
match replace(self, Self::Done) {
Self::Emit { value } => {
Some(Ok(Event::Text(BytesText::from_escaped(escape(&value.0)))))
}
Self::Done => None,
}
}
}
#[derive(Debug)]
pub enum TextDeserializer {
Init,
Text {
value: Text,
},
}
impl<'de> Deserializer<'de, Text> for TextDeserializer {
fn init(helper: &mut DeserializeHelper, event: Event<'de>) -> DeserializerResult<'de, Text> {
Self::Init.next(helper, event)
}
fn next(
self,
helper: &mut DeserializeHelper,
event: Event<'de>,
) -> DeserializerResult<'de, Text> {
let _reader = helper;
let text: Cow<'de, str> = match event {
Event::Text(x) => {
let t = x.decode()?;
let u = unescape(&t)?;
Cow::Owned(u.into_owned())
}
Event::CData(x) => x.decode()?,
Event::GeneralRef(x) => {
let x = from_utf8(x.as_ref())?;
let s = format!("&{x};");
let u = unescape(&s)?;
Cow::Owned(u.into_owned())
}
event @ (Event::Start(_) | Event::Empty(_) | Event::End(_)) => {
let artifact = match self {
Self::Init => DeserializerArtifact::None,
Self::Text { value } => DeserializerArtifact::Data(value),
};
return Ok(DeserializerOutput {
event: DeserializerEvent::Continue(event),
artifact,
allow_any: false,
});
}
event => {
let artifact = match self {
Self::Init => DeserializerArtifact::None,
Self::Text { value } => {
DeserializerArtifact::Deserializer(Self::Text { value })
}
};
return Ok(DeserializerOutput {
event: DeserializerEvent::Break(event),
artifact,
allow_any: false,
});
}
};
let mut value = match self {
Self::Init => Text::default(),
Self::Text { value } => value,
};
value.0.push_str(&text);
Ok(DeserializerOutput {
event: DeserializerEvent::None,
artifact: DeserializerArtifact::Deserializer(Self::Text { value }),
allow_any: false,
})
}
fn finish(self, helper: &mut DeserializeHelper) -> Result<Text, Error> {
let _reader = helper;
match self {
Self::Init => Err(ErrorKind::MissingContent.into()),
Self::Text { value } => Ok(value),
}
}
}