1use alloc::{borrow::Cow, string::ToString};
2use core::{fmt::Write, ops::Deref};
3
4use crate::{Serialize, SerializeOptions, XmlWriter};
5
6#[derive(Default, Debug, Clone)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub struct Text<'s>(Cow<'s, str>);
10
11impl<'s> Text<'s> {
12 pub fn to_owned(&self) -> Text<'static> {
13 self.clone().into_owned()
14 }
15
16 pub fn as_str(&self) -> &str {
17 &*self.0
18 }
19
20 pub fn set(&mut self, text: impl Into<Cow<'s, str>>) {
21 self.0 = text.into();
22 }
23
24 pub fn into_owned(self) -> Text<'static> {
25 Text(match self.0 {
26 Cow::Borrowed(b) => Cow::Owned(b.to_string()),
27 Cow::Owned(b) => Cow::Owned(b)
28 })
29 }
30}
31
32impl Deref for Text<'_> {
33 type Target = str;
34
35 fn deref(&self) -> &Self::Target {
36 &*self.0
37 }
38}
39
40impl<'s, T: Into<Cow<'s, str>>> From<T> for Text<'s> {
41 fn from(value: T) -> Self {
42 Self(value.into())
43 }
44}
45
46impl Serialize for Text<'_> {
47 fn serialize_xml<W: Write>(&self, writer: &mut XmlWriter<W>, _: &SerializeOptions) -> crate::Result<()> {
48 writer.text(&self.0)
49 }
50}
51
52pub fn text<'s>(s: impl Into<Cow<'s, str>>) -> Text<'s> {
54 Text(s.into())
55}
56
57#[cfg(test)]
58mod tests {
59 use super::text;
60 use crate::{Serialize, SerializeOptions};
61
62 #[test]
63 fn text_escapes() -> crate::Result<()> {
64 assert_eq!(text("One & two").serialize_to_string(&SerializeOptions::default())?, "One & two");
65 Ok(())
66 }
67}