@@ -14,6 +14,9 @@ use typespec::error::{ErrorKind, Result, ResultExt};
1414/// The UTF8 [byte order marker](https://en.wikipedia.org/wiki/Byte_order_mark).
1515const UTF8_BOM : [ u8 ; 3 ] = [ 0xEF , 0xBB , 0xBF ] ;
1616
17+ /// The XML declaration used when serializing.
18+ const DECLARATION : & [ u8 ; 38 ] = br#"<?xml version="1.0" encoding="utf-8"?>"# ;
19+
1720/// Reads XML from bytes.
1821pub fn read_xml_str < T > ( body : & str ) -> Result < T >
1922where
3841}
3942
4043/// Serializes a type to bytes.
44+ ///
45+ /// Automatically includes the XML declaration.
4146pub fn to_xml < T > ( value : & T ) -> Result < Bytes >
4247where
4348 T : serde:: Serialize ,
@@ -46,10 +51,15 @@ where
4651 let t = core:: any:: type_name :: < T > ( ) ;
4752 format ! ( "failed to serialize {t} into xml" )
4853 } ) ?;
49- Ok ( Bytes :: from ( value) )
54+ let mut buf = bytes:: BytesMut :: with_capacity ( DECLARATION . len ( ) + value. len ( ) ) ;
55+ buf. extend_from_slice ( DECLARATION ) ;
56+ buf. extend_from_slice ( value. as_bytes ( ) ) ;
57+ Ok ( buf. into ( ) )
5058}
5159
5260/// Serializes a type to bytes with a specified root tag.
61+ ///
62+ /// Automatically includes the XML declaration.
5363pub fn to_xml_with_root < T > ( root_tag : & str , value : & T ) -> Result < Bytes >
5464where
5565 T : serde:: Serialize ,
5969 let t = core:: any:: type_name :: < T > ( ) ;
6070 format ! ( "failed to serialize {t} into xml" )
6171 } ) ?;
62- Ok ( Bytes :: from ( value) )
72+ let mut buf = bytes:: BytesMut :: with_capacity ( DECLARATION . len ( ) + value. len ( ) ) ;
73+ buf. extend_from_slice ( DECLARATION ) ;
74+ buf. extend_from_slice ( value. as_bytes ( ) ) ;
75+ Ok ( buf. into ( ) )
6376}
6477
6578/// Returns bytes without the UTF-8 BOM.
@@ -74,7 +87,7 @@ fn slice_bom(bytes: &[u8]) -> &[u8] {
7487#[ cfg( test) ]
7588mod test {
7689 use super :: * ;
77- use serde:: Deserialize ;
90+ use serde:: { Deserialize , Serialize } ;
7891
7992 #[ test]
8093 fn test_slice_bom ( ) {
@@ -85,27 +98,53 @@ mod test {
8598 assert_eq ! ( & [ 8 ] , slice_bom( bytes) ) ;
8699 }
87100
101+ #[ derive( Deserialize , Serialize , PartialEq , Debug ) ]
102+ #[ serde( rename = "Foo" ) ]
103+ struct Test {
104+ x : String ,
105+ }
106+
88107 #[ test]
89108 fn reading_xml ( ) -> Result < ( ) > {
90- #[ derive( Deserialize , PartialEq , Debug ) ]
91- #[ serde( rename = "Foo" ) ]
92- struct Test {
93- x : String ,
94- }
95109 let test = Test {
96110 x : "Hello, world!" . into ( ) ,
97111 } ;
98112 let xml = br#"<?xml version="1.0" encoding="utf-8"?><Foo><x>Hello, world!</x></Foo>"# ;
99113 assert_eq ! ( test, read_xml( xml) ?) ;
100114
101115 let error = read_xml :: < Test > ( & xml[ ..xml. len ( ) - 2 ] ) . unwrap_err ( ) ;
102- assert ! ( format!( "{error}" ) . contains( "reading_xml ::Test" ) ) ;
116+ assert ! ( format!( "{error}" ) . contains( "typespec_client_core::xml::test ::Test" ) ) ;
103117
104118 let xml = r#"<?xml version="1.0" encoding="utf-8"?><Foo><x>Hello, world!</x></Foo>"# ;
105119 assert_eq ! ( test, read_xml_str( xml) ?) ;
106120
107121 let error = read_xml_str :: < Test > ( & xml[ ..xml. len ( ) - 2 ] ) . unwrap_err ( ) ;
108- assert ! ( format!( "{error}" ) . contains( "reading_xml::Test" ) ) ;
122+ assert ! ( format!( "{error}" ) . contains( "typespec_client_core::xml::test::Test" ) ) ;
123+ Ok ( ( ) )
124+ }
125+
126+ #[ test]
127+ fn writing_xml ( ) -> Result < ( ) > {
128+ assert_eq ! (
129+ br#"<?xml version="1.0" encoding="utf-8"?><Foo><x>Hello, world!</x></Foo>"# ,
130+ to_xml( & Test {
131+ x: "Hello, world!" . to_string( )
132+ } ) ?
133+ . to_vec( )
134+ . as_slice( )
135+ ) ;
136+
137+ assert_eq ! (
138+ br#"<?xml version="1.0" encoding="utf-8"?><Bob><x>Hello, world!</x></Bob>"# ,
139+ to_xml_with_root(
140+ "Bob" ,
141+ & Test {
142+ x: "Hello, world!" . to_string( )
143+ }
144+ ) ?
145+ . to_vec( )
146+ . as_slice( )
147+ ) ;
109148 Ok ( ( ) )
110149 }
111150}
0 commit comments