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