@@ -4,8 +4,9 @@ extern crate std;
44
55use ciborium:: cbor;
66use ciborium:: tag:: Required ;
7- use ciborium:: value:: CanonicalValue ;
7+ use ciborium:: value:: { canonical_into_writer , canonical_value , CanonicalValue , Value } ;
88use rand:: prelude:: * ;
9+ use serde:: { Deserialize , Serialize } ;
910use std:: collections:: BTreeMap ;
1011
1112macro_rules! cval {
@@ -109,3 +110,94 @@ fn tagged_option() {
109110 let output = ciborium:: de:: from_reader ( & bytes[ ..] ) . unwrap ( ) ;
110111 assert_eq ! ( opt, output) ;
111112}
113+
114+ #[ test]
115+ fn canonical_value_example ( ) {
116+ let map = Value :: Map ( vec ! [
117+ ( val!( false ) , val!( 2 ) ) ,
118+ ( val!( [ -1 ] ) , val!( 5 ) ) ,
119+ ( val!( -1 ) , val!( 1 ) ) ,
120+ ( val!( 10 ) , val!( 0 ) ) ,
121+ ( val!( 100 ) , val!( 3 ) ) ,
122+ ( val!( [ 100 ] ) , val!( 7 ) ) ,
123+ ( val!( "z" ) , val!( 4 ) ) ,
124+ ( val!( "aa" ) , val!( 6 ) ) ,
125+ ] ) ;
126+
127+ let mut bytes = Vec :: new ( ) ;
128+ canonical_into_writer ( & map, & mut bytes) . unwrap ( ) ;
129+ assert_eq ! (
130+ hex:: encode( & bytes) ,
131+ "a80a002001f402186403617a048120056261610681186407"
132+ ) ;
133+
134+ let canonical = canonical_value ( map) ;
135+ let bytes = ciborium:: ser:: into_vec ( & canonical) . unwrap ( ) ;
136+
137+ assert_eq ! (
138+ hex:: encode( & bytes) ,
139+ "a80a002001f402186403617a048120056261610681186407"
140+ ) ;
141+ }
142+
143+ #[ test]
144+ fn canonical_value_nested_structures ( ) {
145+ // Create nested structure with unsorted maps
146+ let nested = Value :: Array ( vec ! [
147+ Value :: Map ( vec![ ( val!( "b" ) , val!( 2 ) ) , ( val!( "a" ) , val!( 1 ) ) ] ) ,
148+ Value :: Tag (
149+ 1 ,
150+ Box :: new( Value :: Map ( vec![
151+ ( val!( 100 ) , val!( "high" ) ) ,
152+ ( val!( 10 ) , val!( "low" ) ) ,
153+ ] ) ) ,
154+ ) ,
155+ ] ) ;
156+
157+ let canonical = canonical_value ( nested) ;
158+
159+ if let Value :: Array ( elements) = canonical {
160+ // Check first map is sorted
161+ if let Value :: Map ( entries) = & elements[ 0 ] {
162+ assert_eq ! ( entries[ 0 ] . 0 , val!( "a" ) ) ;
163+ assert_eq ! ( entries[ 1 ] . 0 , val!( "b" ) ) ;
164+ }
165+
166+ // Check tagged map is sorted
167+ if let Value :: Tag ( _, inner) = & elements[ 1 ] {
168+ if let Value :: Map ( entries) = inner. as_ref ( ) {
169+ assert_eq ! ( entries[ 0 ] . 0 , val!( 10 ) ) ;
170+ assert_eq ! ( entries[ 1 ] . 0 , val!( 100 ) ) ;
171+ }
172+ }
173+ } else {
174+ panic ! ( "Expected Array value" ) ;
175+ }
176+ }
177+
178+ #[ test]
179+ fn canonical_value_struct ( ) {
180+ #[ derive( Clone , Debug , Deserialize , Serialize ) ]
181+ struct T1 {
182+ a : u32 ,
183+ b : u32 ,
184+ c : u32 ,
185+ }
186+
187+ #[ derive( Clone , Debug , Deserialize , Serialize ) ]
188+ struct T2 {
189+ c : u32 ,
190+ b : u32 ,
191+ a : u32 ,
192+ }
193+
194+ let t1 = T1 { a : 1 , b : 2 , c : 3 } ;
195+ let t2 = T2 { c : 3 , b : 2 , a : 1 } ;
196+
197+ let mut bytes1 = Vec :: new ( ) ;
198+ canonical_into_writer ( & t1, & mut bytes1) . unwrap ( ) ;
199+
200+ let mut bytes2 = Vec :: new ( ) ;
201+ canonical_into_writer ( & t2, & mut bytes2) . unwrap ( ) ;
202+ assert_eq ! ( bytes1, bytes2) ;
203+ }
0 commit comments