ssml/
text.rs

1use alloc::{borrow::Cow, string::ToString};
2use core::{fmt::Write, ops::Deref};
3
4use crate::{Serialize, SerializeOptions, XmlWriter};
5
6/// A non-marked-up string of text for use as a spoken element.
7#[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
52/// Creates a spoken [`Text`] element from a string.
53pub 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 &amp; two");
65		Ok(())
66	}
67}