azure_core/
xml.rs
1use crate::error::{ErrorKind, ResultExt};
2use bytes::Bytes;
3pub use quick_xml::serde_helpers::text_content;
4use quick_xml::{
5 de::{from_reader, from_str},
6 se::{to_string, to_string_with_root},
7};
8use serde::de::DeserializeOwned;
9
10const UTF8_BOM: [u8; 3] = [0xEF, 0xBB, 0xBF];
12
13pub fn read_xml_str<T>(body: &str) -> crate::Result<T>
15where
16 T: DeserializeOwned,
17{
18 from_str(body).with_context(ErrorKind::DataConversion, || {
19 let t = core::any::type_name::<T>();
20 format!("failed to deserialize the following xml into a {t}\n{body}")
21 })
22}
23
24pub fn read_xml<T>(body: &[u8]) -> crate::Result<T>
26where
27 T: DeserializeOwned,
28{
29 from_reader(slice_bom(body)).with_context(ErrorKind::DataConversion, || {
30 let t = core::any::type_name::<T>();
31 let xml = std::str::from_utf8(body).unwrap_or("<XML IS NOT UTF-8>");
32 format!("failed to deserialize the following xml into a {t}\n{xml}")
33 })
34}
35
36pub fn to_xml<T>(value: &T) -> crate::Result<Bytes>
37where
38 T: serde::Serialize,
39{
40 let value = to_string(value).with_context(ErrorKind::DataConversion, || {
41 let t = core::any::type_name::<T>();
42 format!("failed to serialize {t} into xml")
43 })?;
44 Ok(Bytes::from(value))
45}
46
47pub fn to_xml_with_root<T>(root_tag: &str, value: &T) -> crate::Result<Bytes>
48where
49 T: serde::Serialize,
50{
51 let value =
52 to_string_with_root(root_tag, value).with_context(ErrorKind::DataConversion, || {
53 let t = core::any::type_name::<T>();
54 format!("failed to serialize {t} into xml")
55 })?;
56 Ok(Bytes::from(value))
57}
58
59fn slice_bom(bytes: &[u8]) -> &[u8] {
61 if bytes.len() > 3 && bytes[0..3] == UTF8_BOM {
62 &bytes[3..]
63 } else {
64 bytes
65 }
66}
67
68#[cfg(test)]
69mod test {
70 use super::*;
71 use serde::Deserialize;
72
73 #[test]
74 fn test_slice_bom() {
75 let bytes = &[0xEF, 0xBB, 0xBF, 7];
76 assert_eq!(&[7], slice_bom(bytes));
77
78 let bytes = &[8];
79 assert_eq!(&[8], slice_bom(bytes));
80 }
81
82 #[test]
83 fn reading_xml() -> crate::Result<()> {
84 #[derive(Deserialize, PartialEq, Debug)]
85 #[serde(rename = "Foo")]
86 struct Test {
87 x: String,
88 }
89 let test = Test {
90 x: "Hello, world!".into(),
91 };
92 let xml = br#"<?xml version="1.0" encoding="utf-8"?><Foo><x>Hello, world!</x></Foo>"#;
93 assert_eq!(test, read_xml(xml)?);
94
95 let error = read_xml::<Test>(&xml[..xml.len() - 2]).unwrap_err();
96 assert!(format!("{error}").contains("reading_xml::Test"));
97
98 let xml = r#"<?xml version="1.0" encoding="utf-8"?><Foo><x>Hello, world!</x></Foo>"#;
99 assert_eq!(test, read_xml_str(xml)?);
100
101 let error = read_xml_str::<Test>(&xml[..xml.len() - 2]).unwrap_err();
102 assert!(format!("{error}").contains("reading_xml::Test"));
103 Ok(())
104 }
105}