1use alloc::{
16 borrow::{Cow, ToOwned},
17 boxed::Box,
18};
19
20use crate::error::Error;
21use crate::rxml_util::Item;
22use crate::AsXml;
23
24use core::fmt;
25
26use bytes::BytesMut;
27
28pub struct OptionAsXml<T: Iterator>(Option<T>);
30
31impl<T: Iterator> OptionAsXml<T> {
32 pub fn new(inner: Option<T>) -> Self {
38 Self(inner)
39 }
40}
41
42impl<'x, T: Iterator<Item = Result<Item<'x>, Error>>> Iterator for OptionAsXml<T> {
43 type Item = Result<Item<'x>, Error>;
44
45 fn next(&mut self) -> Option<Self::Item> {
46 self.0.as_mut()?.next()
47 }
48}
49
50impl<T: AsXml> AsXml for Option<T> {
53 type ItemIter<'x>
54 = OptionAsXml<T::ItemIter<'x>>
55 where
56 T: 'x;
57
58 fn as_xml_iter(&self) -> Result<Self::ItemIter<'_>, Error> {
59 match self {
60 Some(ref value) => Ok(OptionAsXml(Some(T::as_xml_iter(value)?))),
61 None => Ok(OptionAsXml(None)),
62 }
63 }
64}
65
66pub struct BoxAsXml<T: Iterator>(Box<T>);
68
69impl<'x, T: Iterator<Item = Result<Item<'x>, Error>>> Iterator for BoxAsXml<T> {
70 type Item = Result<Item<'x>, Error>;
71
72 fn next(&mut self) -> Option<Self::Item> {
73 self.0.next()
74 }
75}
76
77impl<T: AsXml> AsXml for Box<T> {
79 type ItemIter<'x>
80 = BoxAsXml<T::ItemIter<'x>>
81 where
82 T: 'x;
83
84 fn as_xml_iter(&self) -> Result<Self::ItemIter<'_>, Error> {
85 Ok(BoxAsXml(Box::new(T::as_xml_iter(self)?)))
86 }
87}
88
89impl<T: AsXml, E> AsXml for Result<T, E>
91where
92 for<'a> Error: From<&'a E>,
93{
94 type ItemIter<'x>
95 = T::ItemIter<'x>
96 where
97 Self: 'x;
98
99 fn as_xml_iter(&self) -> Result<Self::ItemIter<'_>, Error> {
100 match self {
101 Self::Ok(v) => Ok(v.as_xml_iter()?),
102 Self::Err(e) => Err(e.into()),
103 }
104 }
105}
106
107pub struct PrintRawXml<'x, T>(pub &'x T);
109
110impl<T: AsXml> fmt::Display for PrintRawXml<'_, T> {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 let iter = match self.0.as_xml_iter() {
113 Ok(iter) => iter,
114 Err(err) => return write!(f, "<failed to serialize PrintRawXml: {:?}>", err),
115 };
116 let mut writer = rxml::writer::Encoder::new();
117 let mut buf = BytesMut::new();
118 for item in iter {
119 let item = match item {
120 Ok(item) => item,
121 Err(err) => return write!(f, "<failed to serialize PrintRawXml: {:?}>", err),
122 };
123 if let Err(err) = writer.encode(item.as_rxml_item(), &mut buf) {
124 return write!(f, "<failed to serialize PrintRawXml: {:?}>", err);
125 }
126 }
127 write!(f, "{}", core::str::from_utf8(&buf).unwrap())
130 }
131}
132
133pub trait AsXmlDyn {
138 fn as_xml_dyn_iter<'x>(
141 &'x self,
142 ) -> Result<Box<dyn Iterator<Item = Result<Item<'x>, Error>> + 'x>, Error>;
143}
144
145impl<T: AsXml> AsXmlDyn for T {
146 fn as_xml_dyn_iter<'x>(
149 &'x self,
150 ) -> Result<Box<dyn Iterator<Item = Result<Item<'x>, Error>> + 'x>, Error> {
151 <T as AsXml>::as_xml_dyn_iter(self)
152 }
153}
154
155impl<'a, T: AsXml + ToOwned + ?Sized + 'a> AsXml for Cow<'a, T> {
156 type ItemIter<'x>
157 = T::ItemIter<'x>
158 where
159 Self: 'x;
160
161 fn as_xml_iter(&self) -> Result<Self::ItemIter<'_>, Error> {
162 T::as_xml_iter(&*self)
163 }
164}
165
166#[cfg(test)]
167mod tests {
168 use super::*;
169
170 use alloc::{borrow::Cow, vec};
171
172 #[test]
173 fn option_as_xml_terminates_immediately_for_none() {
174 let mut iter = OptionAsXml::<core::iter::Empty<_>>(None);
175 match iter.next() {
176 None => (),
177 other => panic!("unexpected item: {:?}", other),
178 }
179 }
180
181 #[test]
182 fn option_as_xml_passes_values_from_inner_some() {
183 let inner = vec![
184 Ok(Item::Text(Cow::Borrowed("hello world"))),
185 Ok(Item::ElementFoot),
186 ];
187 let mut iter = OptionAsXml(Some(inner.into_iter()));
188 match iter.next() {
189 Some(Ok(Item::Text(text))) => {
190 assert_eq!(text, "hello world");
191 }
192 other => panic!("unexpected item: {:?}", other),
193 }
194 match iter.next() {
195 Some(Ok(Item::ElementFoot)) => (),
196 other => panic!("unexpected item: {:?}", other),
197 }
198 match iter.next() {
199 None => (),
200 other => panic!("unexpected item: {:?}", other),
201 }
202 }
203
204 #[test]
205 fn box_as_xml_passes_values_from_inner() {
206 let inner = vec![
207 Ok(Item::Text(Cow::Borrowed("hello world"))),
208 Ok(Item::ElementFoot),
209 ];
210 let mut iter = BoxAsXml(Box::new(inner.into_iter()));
211 match iter.next() {
212 Some(Ok(Item::Text(text))) => {
213 assert_eq!(text, "hello world");
214 }
215 other => panic!("unexpected item: {:?}", other),
216 }
217 match iter.next() {
218 Some(Ok(Item::ElementFoot)) => (),
219 other => panic!("unexpected item: {:?}", other),
220 }
221 match iter.next() {
222 None => (),
223 other => panic!("unexpected item: {:?}", other),
224 }
225 }
226}