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
166impl<'a, T: AsXml + ?Sized + 'a> AsXml for &'a T {
167 type ItemIter<'x>
168 = T::ItemIter<'x>
169 where
170 Self: 'x;
171
172 fn as_xml_iter(&self) -> Result<Self::ItemIter<'_>, Error> {
173 T::as_xml_iter(&*self)
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180
181 use alloc::{borrow::Cow, vec};
182
183 #[test]
184 fn option_as_xml_terminates_immediately_for_none() {
185 let mut iter = OptionAsXml::<core::iter::Empty<_>>(None);
186 match iter.next() {
187 None => (),
188 other => panic!("unexpected item: {:?}", other),
189 }
190 }
191
192 #[test]
193 fn option_as_xml_passes_values_from_inner_some() {
194 let inner = vec![
195 Ok(Item::Text(Cow::Borrowed("hello world"))),
196 Ok(Item::ElementFoot),
197 ];
198 let mut iter = OptionAsXml(Some(inner.into_iter()));
199 match iter.next() {
200 Some(Ok(Item::Text(text))) => {
201 assert_eq!(text, "hello world");
202 }
203 other => panic!("unexpected item: {:?}", other),
204 }
205 match iter.next() {
206 Some(Ok(Item::ElementFoot)) => (),
207 other => panic!("unexpected item: {:?}", other),
208 }
209 match iter.next() {
210 None => (),
211 other => panic!("unexpected item: {:?}", other),
212 }
213 }
214
215 #[test]
216 fn box_as_xml_passes_values_from_inner() {
217 let inner = vec![
218 Ok(Item::Text(Cow::Borrowed("hello world"))),
219 Ok(Item::ElementFoot),
220 ];
221 let mut iter = BoxAsXml(Box::new(inner.into_iter()));
222 match iter.next() {
223 Some(Ok(Item::Text(text))) => {
224 assert_eq!(text, "hello world");
225 }
226 other => panic!("unexpected item: {:?}", other),
227 }
228 match iter.next() {
229 Some(Ok(Item::ElementFoot)) => (),
230 other => panic!("unexpected item: {:?}", other),
231 }
232 match iter.next() {
233 None => (),
234 other => panic!("unexpected item: {:?}", other),
235 }
236 }
237}