@@ -63,6 +63,13 @@ impl std::fmt::Display for NodeStr<'_> {
6363 }
6464}
6565
66+ #[ cfg( feature = "serde" ) ]
67+ impl serde:: Serialize for NodeStr < ' _ > {
68+ fn serialize < S : serde:: Serializer > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > {
69+ serializer. serialize_str ( self )
70+ }
71+ }
72+
6673impl PartialEq for NodeStr < ' _ > {
6774 #[ inline]
6875 fn eq ( & self , other : & Self ) -> bool {
@@ -387,6 +394,18 @@ pub enum ValueRef<'a> {
387394 Jid ( JidRef < ' a > ) ,
388395}
389396
397+ #[ cfg( feature = "serde" ) ]
398+ impl serde:: Serialize for ValueRef < ' _ > {
399+ fn serialize < S : serde:: Serializer > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > {
400+ match self {
401+ ValueRef :: String ( s) => {
402+ serializer. serialize_newtype_variant ( "NodeValue" , 0 , "String" , & * * s)
403+ }
404+ ValueRef :: Jid ( j) => serializer. serialize_newtype_variant ( "NodeValue" , 1 , "Jid" , j) ,
405+ }
406+ }
407+ }
408+
390409impl < ' a > ValueRef < ' a > {
391410 /// String view of the value. Borrows from `self`.
392411 /// - String variant: borrows the inner str — zero copy
@@ -451,6 +470,23 @@ pub enum NodeContentRef<'a> {
451470 Nodes ( Box < NodeVec < ' a > > ) ,
452471}
453472
473+ #[ cfg( feature = "serde" ) ]
474+ impl serde:: Serialize for NodeContentRef < ' _ > {
475+ fn serialize < S : serde:: Serializer > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > {
476+ match self {
477+ NodeContentRef :: Bytes ( b) => {
478+ serializer. serialize_newtype_variant ( "NodeContent" , 0 , "Bytes" , b. as_ref ( ) )
479+ }
480+ NodeContentRef :: String ( s) => {
481+ serializer. serialize_newtype_variant ( "NodeContent" , 1 , "String" , & * * s)
482+ }
483+ NodeContentRef :: Nodes ( nodes) => {
484+ serializer. serialize_newtype_variant ( "NodeContent" , 2 , "Nodes" , nodes. as_slice ( ) )
485+ }
486+ }
487+ }
488+ }
489+
454490impl NodeContent {
455491 /// Convert an owned NodeContent to a borrowed NodeContentRef.
456492 pub fn as_content_ref ( & self ) -> NodeContentRef < ' _ > {
@@ -569,6 +605,32 @@ impl Node {
569605 }
570606}
571607
608+ /// Wrapper that serializes `AttrsRef` with the same newtype-struct framing
609+ /// that serde's derive produces for `Attrs(Vec<...>)`. Without this, binary
610+ /// formats (bincode, postcard, etc.) would see a bare sequence instead of a
611+ /// newtype struct wrapper.
612+ #[ cfg( feature = "serde" ) ]
613+ struct AttrsRefWrapper < ' a , ' b > ( & ' b AttrsRef < ' a > ) ;
614+
615+ #[ cfg( feature = "serde" ) ]
616+ impl serde:: Serialize for AttrsRefWrapper < ' _ , ' _ > {
617+ fn serialize < S : serde:: Serializer > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > {
618+ serializer. serialize_newtype_struct ( "Attrs" , self . 0 )
619+ }
620+ }
621+
622+ #[ cfg( feature = "serde" ) ]
623+ impl serde:: Serialize for NodeRef < ' _ > {
624+ fn serialize < S : serde:: Serializer > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > {
625+ use serde:: ser:: SerializeStruct ;
626+ let mut s = serializer. serialize_struct ( "Node" , 3 ) ?;
627+ s. serialize_field ( "tag" , & * self . tag ) ?;
628+ s. serialize_field ( "attrs" , & AttrsRefWrapper ( & self . attrs ) ) ?;
629+ s. serialize_field ( "content" , & self . content ) ?;
630+ s. end ( )
631+ }
632+ }
633+
572634impl < ' a > NodeRef < ' a > {
573635 pub fn new ( tag : NodeStr < ' a > , attrs : AttrsRef < ' a > , content : Option < NodeContentRef < ' a > > ) -> Self {
574636 Self {
@@ -810,8 +872,116 @@ impl OwnedNodeRef {
810872 }
811873}
812874
875+ #[ cfg( feature = "serde" ) ]
876+ impl serde:: Serialize for OwnedNodeRef {
877+ fn serialize < S : serde:: Serializer > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > {
878+ self . get ( ) . serialize ( serializer)
879+ }
880+ }
881+
813882impl std:: fmt:: Debug for OwnedNodeRef {
814883 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
815884 self . inner . get ( ) . fmt ( f)
816885 }
817886}
887+
888+ #[ cfg( test) ]
889+ #[ cfg( feature = "serde" ) ]
890+ mod serde_tests {
891+ use super :: * ;
892+ use crate :: jid:: { Jid , Server } ;
893+
894+ #[ test]
895+ fn node_ref_serializes_same_as_node ( ) {
896+ let node = Node :: new (
897+ Cow :: Borrowed ( "message" ) ,
898+ Attrs ( vec ! [
899+ ( Cow :: Borrowed ( "type" ) , NodeValue :: String ( "text" . into( ) ) ) ,
900+ ( Cow :: Borrowed ( "from" ) , NodeValue :: Jid ( Jid :: pn( "5550199999" ) ) ) ,
901+ ] ) ,
902+ Some ( NodeContent :: String ( "hello" . into ( ) ) ) ,
903+ ) ;
904+ let node_ref = node. as_node_ref ( ) ;
905+
906+ let owned_json = serde_json:: to_value ( & node) . unwrap ( ) ;
907+ let ref_json = serde_json:: to_value ( & node_ref) . unwrap ( ) ;
908+ assert_eq ! ( owned_json, ref_json) ;
909+ }
910+
911+ #[ test]
912+ fn nested_nodes_serialize_same ( ) {
913+ let child = Node :: new ( Cow :: Borrowed ( "item" ) , Attrs :: new ( ) , None ) ;
914+ let parent = Node :: new (
915+ Cow :: Borrowed ( "list" ) ,
916+ Attrs :: new ( ) ,
917+ Some ( NodeContent :: Nodes ( vec ! [ child] ) ) ,
918+ ) ;
919+ let parent_ref = parent. as_node_ref ( ) ;
920+
921+ assert_eq ! (
922+ serde_json:: to_value( & parent) . unwrap( ) ,
923+ serde_json:: to_value( & parent_ref) . unwrap( ) ,
924+ ) ;
925+ }
926+
927+ #[ test]
928+ fn bytes_content_serializes_same ( ) {
929+ let node = Node :: new (
930+ Cow :: Borrowed ( "iq" ) ,
931+ Attrs ( vec ! [ ( Cow :: Borrowed ( "id" ) , NodeValue :: String ( "1" . into( ) ) ) ] ) ,
932+ Some ( NodeContent :: Bytes ( vec ! [ 0xDE , 0xAD ] ) ) ,
933+ ) ;
934+ let node_ref = node. as_node_ref ( ) ;
935+
936+ let owned_json = serde_json:: to_value ( & node) . unwrap ( ) ;
937+ let ref_json = serde_json:: to_value ( & node_ref) . unwrap ( ) ;
938+ assert_eq ! ( owned_json, ref_json) ;
939+ }
940+
941+ #[ test]
942+ fn value_ref_matches_node_value ( ) {
943+ let string_val = NodeValue :: String ( "hello" . into ( ) ) ;
944+ let string_ref = ValueRef :: String ( NodeStr :: Borrowed ( "hello" ) ) ;
945+ assert_eq ! (
946+ serde_json:: to_value( & string_val) . unwrap( ) ,
947+ serde_json:: to_value( & string_ref) . unwrap( ) ,
948+ ) ;
949+
950+ let jid = Jid {
951+ user : "5550199999" . into ( ) ,
952+ server : Server :: Group ,
953+ agent : 1 ,
954+ device : 2 ,
955+ integrator : 3 ,
956+ } ;
957+ let jid_val = NodeValue :: Jid ( jid. clone ( ) ) ;
958+ let jid_ref_val = ValueRef :: Jid ( JidRef {
959+ user : NodeStr :: Borrowed ( "5550199999" ) ,
960+ server : Server :: Group ,
961+ agent : 1 ,
962+ device : 2 ,
963+ integrator : 3 ,
964+ } ) ;
965+ assert_eq ! (
966+ serde_json:: to_value( & jid_val) . unwrap( ) ,
967+ serde_json:: to_value( & jid_ref_val) . unwrap( ) ,
968+ ) ;
969+ }
970+
971+ #[ test]
972+ fn owned_node_ref_serializes_same_as_owned ( ) {
973+ let node = Node :: new (
974+ Cow :: Borrowed ( "iq" ) ,
975+ Attrs ( vec ! [ ( Cow :: Borrowed ( "id" ) , NodeValue :: String ( "abc" . into( ) ) ) ] ) ,
976+ Some ( NodeContent :: String ( "payload" . into ( ) ) ) ,
977+ ) ;
978+
979+ let bytes = crate :: marshal:: marshal ( & node) . unwrap ( ) ;
980+ // marshal writes a leading format byte that unmarshal_ref doesn't expect
981+ let owned_ref = OwnedNodeRef :: new ( Bytes :: from ( bytes[ 1 ..] . to_vec ( ) ) ) . unwrap ( ) ;
982+
983+ let from_ref = serde_json:: to_value ( & owned_ref) . unwrap ( ) ;
984+ let from_owned = serde_json:: to_value ( owned_ref. to_owned_node ( ) ) . unwrap ( ) ;
985+ assert_eq ! ( from_ref, from_owned) ;
986+ }
987+ }
0 commit comments