use aws_smithy_xml::decode::{try_data, Document, ScopedDecoder, XmlDecodeError};
use std::collections::HashMap;
#[derive(Eq, PartialEq, Debug)]
enum FooEnum {
Unknown(String),
}
impl<'a> From<&'a str> for FooEnum {
fn from(s: &'a str) -> Self {
Self::Unknown(s.to_string())
}
}
#[derive(Eq, PartialEq, Debug)]
struct FlatXmlMap {
my_map: HashMap<String, FooEnum>,
}
#[derive(Eq, PartialEq, Debug)]
struct XmlMap {
values: HashMap<String, FooEnum>,
}
#[derive(Eq, PartialEq, Debug)]
struct XmlAttribute {
foo: String,
bar: String,
}
fn deserialize_xml_attribute(inp: &str) -> Result<XmlAttribute, XmlDecodeError> {
let mut doc = Document::new(inp);
let mut root = doc.root_element()?;
#[allow(unused_assignments)]
#[allow(clippy::blacklisted_name)]
let mut foo: Option<String> = None;
let mut bar: Option<String> = None;
foo = root.start_el().attr("foo").map(|attr| attr.to_string());
while let Some(mut tag) = root.next_tag() {
if tag.start_el().matches("bar") {
bar = Some(try_data(&mut tag)?.to_string());
}
}
Ok(XmlAttribute {
foo: foo.ok_or_else(|| XmlDecodeError::custom("missing foo"))?,
bar: bar.ok_or_else(|| XmlDecodeError::custom("missing bar"))?,
})
}
fn deserialize_flat_xml_map(inp: &str) -> Result<FlatXmlMap, XmlDecodeError> {
let mut doc = Document::new(inp);
let mut root = doc.root_element()?;
let mut my_map: Option<HashMap<String, FooEnum>> = None;
while let Some(mut tag) = root.next_tag() {
if tag.start_el().matches("myMap") {
let mut _my_map = my_map.unwrap_or_default();
deserialize_foo_enum_map_entry(&mut tag, &mut _my_map)?;
my_map = Some(_my_map);
}
}
Ok(FlatXmlMap {
my_map: my_map.unwrap(),
})
}
fn deserialize_xml_map(inp: &str) -> Result<XmlMap, XmlDecodeError> {
let mut doc = Document::new(inp);
let mut root = doc.root_element()?;
let mut my_map: Option<HashMap<String, FooEnum>> = None;
while let Some(mut tag) = root.next_tag() {
if tag.start_el().matches("values") {
my_map = Some(deserialize_foo_enum_map(&mut tag)?);
}
}
Ok(XmlMap {
values: my_map.ok_or_else(|| XmlDecodeError::custom("missing map"))?,
})
}
fn deserialize_foo_enum_map(
decoder: &mut ScopedDecoder,
) -> Result<HashMap<String, FooEnum>, XmlDecodeError> {
let mut out: HashMap<String, FooEnum> = HashMap::new();
while let Some(mut tag) = decoder.next_tag() {
if tag.start_el().matches("entry") {
deserialize_foo_enum_map_entry(&mut tag, &mut out)?;
}
}
Ok(out)
}
fn deserialize_foo_enum_map_entry(
decoder: &mut ScopedDecoder,
out: &mut HashMap<String, FooEnum>,
) -> Result<(), XmlDecodeError> {
let mut k: Option<String> = None;
let mut v: Option<FooEnum> = None;
while let Some(mut tag) = decoder.next_tag() {
match tag.start_el() {
s if s.matches("key") => k = Some(try_data(&mut tag)?.to_string()),
s if s.matches("value") => v = Some(FooEnum::from(try_data(&mut tag)?.as_ref())),
_ => {}
}
}
match (k, v) {
(Some(k), Some(v)) => {
out.insert(k, v);
}
_ => return Err(XmlDecodeError::custom("missing key value in map")),
}
Ok(())
}
#[test]
fn deserialize_map_test() {
let xml = r#"<Foo>
<values>
<entry>
<key>example-key1</key>
<ignore><this><key>hello</key></this></ignore>
<value>example1</value>
</entry>
<entry>
<key>example-key2</key>
<value>example2</value>
</entry>
</values>
</Foo>"#;
let mut out = HashMap::new();
out.insert("example-key1".to_string(), FooEnum::from("example1"));
out.insert("example-key2".to_string(), FooEnum::from("example2"));
assert_eq!(
deserialize_xml_map(xml).expect("valid"),
XmlMap { values: out }
)
}
pub fn deserialize_nested_string_list(
decoder: &mut ScopedDecoder,
) -> Result<std::vec::Vec<std::vec::Vec<std::string::String>>, XmlDecodeError> {
let mut out = std::vec::Vec::new();
while let Some(mut tag) = decoder.next_tag() {
match tag.start_el() {
s if s.matches("member") => {
out.push(deserialize_string_list(&mut tag)?);
}
_ => {}
}
}
Ok(out)
}
pub fn deserialize_string_list(
decoder: &mut ScopedDecoder,
) -> Result<std::vec::Vec<std::string::String>, XmlDecodeError> {
let mut out = std::vec::Vec::new();
while let Some(mut tag) = decoder.next_tag() {
match dbg!(tag.start_el()) {
s if s.matches("member") => {
out.push(dbg!({
aws_smithy_xml::decode::try_data(&mut tag)?.to_string()
}));
}
_ => {}
};
}
println!("done");
Ok(out)
}
#[test]
fn test_nested_string_list() {
let xml = r#"
<nestedStringList>
<member>
<member>foo</member>
<member>bar</member>
</member>
<member>
<member>baz</member>
<member>qux</member>
</member>
</nestedStringList>
"#;
let mut doc = Document::new(xml);
let mut root = doc.root_element().unwrap();
assert_eq!(
deserialize_nested_string_list(&mut root).unwrap(),
vec![vec!["foo", "bar"], vec!["baz", "qux"]]
);
}
#[test]
fn deserialize_flat_map_test() {
let xml = r#"<FlattenedXmlMapInputOutput>
<myMap>
<key>foo</key>
<value>Foo</value>
</myMap>
<myMap>
<key>baz</key>
<value>Baz</value>
</myMap>
</FlattenedXmlMapInputOutput>"#;
let mut out = HashMap::new();
out.insert("foo".to_string(), FooEnum::from("Foo"));
out.insert("baz".to_string(), FooEnum::from("Baz"));
assert_eq!(
deserialize_flat_xml_map(xml).unwrap(),
FlatXmlMap { my_map: out }
)
}
#[test]
fn test_deserialize_xml_attribute() {
let xml = r#"<MyStructure foo="example">
<bar>examplebar</bar>
</MyStructure>"#;
assert_eq!(
deserialize_xml_attribute(xml).expect("valid"),
XmlAttribute {
foo: "example".to_string(),
bar: "examplebar".to_string()
}
);
}