cosmwasm_std/
msgpack.rs

1// This file mostly re-exports some methods from rmp-serde
2// The reason is two fold:
3// 1. To easily ensure that all calling libraries use the same version (minimize code size)
4// 2. To allow us to switch out to another MessagePack library if needed
5
6use serde::{de::DeserializeOwned, Serialize};
7
8use crate::{Binary, StdResult};
9
10/// Deserializes the given MessagePack bytes to a data structure.
11///
12/// Errors if the input is not valid MessagePack or cannot be deserialized to the given type.
13///
14/// ## Examples
15///
16/// Encoding and decoding an enum using MessagePack.
17///
18/// ```
19/// use cosmwasm_schema::cw_serde;
20/// use cosmwasm_std::{to_msgpack_binary, from_msgpack};
21///
22/// #[cw_serde]
23/// enum MyPacket {
24///     Cowsay {
25///         text: String,
26///     },
27/// }
28///
29/// let packet = MyPacket::Cowsay { text: "hi".to_string() };
30/// let encoded = to_msgpack_binary(&packet).unwrap();
31/// let decoded: MyPacket  = from_msgpack(&encoded).unwrap();
32/// assert_eq!(decoded, packet);
33pub fn from_msgpack<T: DeserializeOwned>(value: impl AsRef<[u8]>) -> StdResult<T> {
34    Ok(rmp_serde::from_read(value.as_ref())?)
35}
36
37/// Serializes the given data structure as a MessagePack byte vector.
38///
39/// ## Examples
40///
41/// Encoding and decoding an enum using MessagePack.
42///
43/// ```
44/// use cosmwasm_schema::cw_serde;
45/// use cosmwasm_std::{to_msgpack_vec, from_msgpack};
46///
47/// #[cw_serde]
48/// enum MyPacket {
49///     Cowsay {
50///         text: String,
51///     },
52/// }
53///
54/// let packet = MyPacket::Cowsay { text: "hi".to_string() };
55/// let encoded = to_msgpack_vec(&packet).unwrap();
56/// let decoded: MyPacket  = from_msgpack(&encoded).unwrap();
57/// assert_eq!(decoded, packet);
58pub fn to_msgpack_vec<T>(data: &T) -> StdResult<Vec<u8>>
59where
60    T: Serialize + ?Sized,
61{
62    Ok(rmp_serde::to_vec_named(data)?)
63}
64
65/// Serializes the given data structure as MessagePack bytes.
66///
67/// ## Examples
68///
69/// Encoding and decoding an enum using MessagePack.
70///
71/// ```
72/// use cosmwasm_schema::cw_serde;
73/// use cosmwasm_std::{to_msgpack_binary, from_msgpack};
74///
75/// #[cw_serde]
76/// enum MyPacket {
77///     Cowsay {
78///         text: String,
79///     },
80/// }
81///
82/// let packet = MyPacket::Cowsay { text: "hi".to_string() };
83/// let encoded = to_msgpack_binary(&packet).unwrap();
84/// let decoded: MyPacket  = from_msgpack(&encoded).unwrap();
85/// assert_eq!(decoded, packet);
86/// ```
87pub fn to_msgpack_binary<T>(data: &T) -> StdResult<Binary>
88where
89    T: Serialize + ?Sized,
90{
91    to_msgpack_vec(data).map(Binary::new)
92}
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97    use crate::{Int128, Int256, Int512, Int64, Uint128, Uint256, Uint512, Uint64};
98    use serde::Deserialize;
99
100    #[derive(Serialize, Deserialize, Debug, PartialEq)]
101    #[serde(rename_all = "snake_case")]
102    enum SomeMsg {
103        Refund {},
104        ReleaseAll {
105            image: String,
106            amount: u32,
107            time: u64,
108            karma: i32,
109        },
110        Cowsay {
111            text: String,
112        },
113    }
114
115    fn refund_test_vector() -> (SomeMsg, &'static [u8]) {
116        let msg = SomeMsg::Refund {};
117        let serialized = &[129, 166, 114, 101, 102, 117, 110, 100, 128];
118        (msg, serialized)
119    }
120
121    fn release_all_test_vector() -> (SomeMsg, &'static [u8]) {
122        let msg = SomeMsg::ReleaseAll {
123            image: "foo".to_string(),
124            amount: 42,
125            time: 18446744073709551615,
126            karma: -17,
127        };
128        let serialized = &[
129            129, 171, 114, 101, 108, 101, 97, 115, 101, 95, 97, 108, 108, 132, 165, 105, 109, 97,
130            103, 101, 163, 102, 111, 111, 166, 97, 109, 111, 117, 110, 116, 42, 164, 116, 105, 109,
131            101, 207, 255, 255, 255, 255, 255, 255, 255, 255, 165, 107, 97, 114, 109, 97, 239,
132        ];
133        (msg, serialized)
134    }
135
136    fn special_chars_test_vector() -> (SomeMsg, &'static [u8]) {
137        let msg = SomeMsg::Cowsay {
138            text: "foo\"bar\\\"bla🦴👁🦶🏻".to_string(),
139        };
140        let serialized = &[
141            129, 166, 99, 111, 119, 115, 97, 121, 129, 164, 116, 101, 120, 116, 188, 102, 111, 111,
142            34, 98, 97, 114, 92, 34, 98, 108, 97, 240, 159, 166, 180, 240, 159, 145, 129, 240, 159,
143            166, 182, 240, 159, 143, 187,
144        ];
145
146        (msg, serialized)
147    }
148
149    #[test]
150    fn to_msgpack_vec_works() {
151        let (msg, expected) = refund_test_vector();
152        let serialized = to_msgpack_vec(&msg).unwrap();
153        assert_eq!(serialized, expected);
154
155        let (msg, expected) = release_all_test_vector();
156        let serialized = to_msgpack_vec(&msg).unwrap();
157        assert_eq!(serialized, expected);
158    }
159
160    #[test]
161    fn from_msgpack_works() {
162        let (msg, serialized) = refund_test_vector();
163        let deserialized: SomeMsg = from_msgpack(serialized).unwrap();
164        assert_eq!(deserialized, msg);
165
166        let (msg, serialized) = release_all_test_vector();
167        let deserialized: SomeMsg = from_msgpack(serialized).unwrap();
168        assert_eq!(deserialized, msg);
169    }
170
171    #[test]
172    fn from_msgpack_or_binary() {
173        let msg = SomeMsg::Refund {};
174        let serialized: Binary = to_msgpack_binary(&msg).unwrap();
175
176        let parse_binary: SomeMsg = from_msgpack(&serialized).unwrap();
177        assert_eq!(parse_binary, msg);
178
179        let parse_slice: SomeMsg = from_msgpack(serialized.as_slice()).unwrap();
180        assert_eq!(parse_slice, msg);
181    }
182
183    #[test]
184    fn from_msgpack_works_for_special_chars() {
185        let (msg, serialized) = special_chars_test_vector();
186        let deserialized: SomeMsg = from_msgpack(serialized).unwrap();
187        assert_eq!(deserialized, msg);
188    }
189
190    #[test]
191    fn deserialize_modified_field_order() {
192        // field order doesn't matter since we encode field names
193
194        #[derive(Serialize, Deserialize, Debug, PartialEq)]
195        struct TestV1 {
196            a: String,
197            b: u32,
198            c: u64,
199        }
200
201        #[derive(Serialize, Deserialize, Debug, PartialEq)]
202        struct TestV2 {
203            b: u32,
204            c: u64,
205            a: String,
206        }
207
208        let v1 = TestV1 {
209            a: "foo".to_string(),
210            b: 42,
211            c: 18446744073709551615,
212        };
213
214        let v2: TestV2 = from_msgpack(to_msgpack_vec(&v1).unwrap()).unwrap();
215        assert_eq!(
216            v2,
217            TestV2 {
218                b: 42,
219                c: 18446744073709551615,
220                a: "foo".to_string()
221            }
222        );
223    }
224
225    #[test]
226    fn deserialize_new_fields() {
227        // new fields can be added at the end
228
229        #[derive(Serialize, Deserialize, Debug, PartialEq)]
230        struct TestV1 {
231            a: String,
232        }
233
234        #[derive(Serialize, Deserialize, Debug, PartialEq)]
235        struct TestV2 {
236            a: String,
237            #[serde(default)]
238            b: u32,
239        }
240
241        let v1 = TestV1 {
242            a: "foo".to_string(),
243        };
244        let v2: TestV2 = from_msgpack(to_msgpack_vec(&v1).unwrap()).unwrap();
245
246        assert_eq!(
247            v2,
248            TestV2 {
249                a: "foo".to_string(),
250                b: 0
251            }
252        );
253    }
254
255    #[test]
256    fn deserialize_new_fields_in_the_middle() {
257        // fields can be added even in the middle
258        #[derive(Serialize, Deserialize, Debug, PartialEq)]
259        struct TestV1 {
260            a: String,
261            b: u32,
262        }
263
264        #[derive(Serialize, Deserialize, Debug, PartialEq)]
265        struct TestV2 {
266            a: String,
267            #[serde(default)]
268            c: u8,
269            b: u32,
270        }
271
272        let v1 = TestV1 {
273            a: "foo".to_string(),
274            b: 999999,
275        };
276        let v2: TestV2 = from_msgpack(to_msgpack_vec(&v1).unwrap()).unwrap();
277
278        assert_eq!(
279            v2,
280            TestV2 {
281                a: "foo".to_string(),
282                c: 0,
283                b: 999999,
284            }
285        );
286    }
287
288    #[test]
289    fn msgpack_serialization_for_boolean_types() {
290        // "Bool format family stores false or true in 1 byte."
291        let serialized = to_msgpack_vec(&false).unwrap();
292        assert_eq!(serialized, [0xc2]);
293        let serialized = to_msgpack_vec(&true).unwrap();
294        assert_eq!(serialized, [0xc3]);
295    }
296
297    #[test]
298    fn msgpack_serialization_for_integer_types() {
299        // primitive integers up to 64bit
300        // similar to VARINT in protobuf or number in JSON, the encoding does not contain integer size
301        {
302            // "positive fixint stores 7-bit positive integer"
303            let serialized = to_msgpack_vec(&0u8).unwrap();
304            assert_eq!(serialized, [0]);
305            let serialized = to_msgpack_vec(&0u16).unwrap();
306            assert_eq!(serialized, [0]);
307            let serialized = to_msgpack_vec(&0u32).unwrap();
308            assert_eq!(serialized, [0]);
309            let serialized = to_msgpack_vec(&0u64).unwrap();
310            assert_eq!(serialized, [0]);
311            let serialized = to_msgpack_vec(&0i64).unwrap();
312            assert_eq!(serialized, [0]);
313            let serialized = to_msgpack_vec(&7u8).unwrap();
314            assert_eq!(serialized, [7]);
315            let serialized = to_msgpack_vec(&7u16).unwrap();
316            assert_eq!(serialized, [7]);
317            let serialized = to_msgpack_vec(&7u32).unwrap();
318            assert_eq!(serialized, [7]);
319            let serialized = to_msgpack_vec(&7u64).unwrap();
320            assert_eq!(serialized, [7]);
321            let serialized = to_msgpack_vec(&127u32).unwrap();
322            assert_eq!(serialized, [127]);
323
324            // "negative fixint stores 5-bit negative integer"
325            let serialized = to_msgpack_vec(&-1i32).unwrap();
326            assert_eq!(serialized, [255]);
327            let serialized = to_msgpack_vec(&-1i64).unwrap();
328            assert_eq!(serialized, [255]);
329            let serialized = to_msgpack_vec(&-10i64).unwrap();
330            assert_eq!(serialized, [246]);
331            let serialized = to_msgpack_vec(&-24i64).unwrap();
332            assert_eq!(serialized, [232]);
333
334            // "uint 8 stores an 8-bit unsigned integer"
335            let serialized = to_msgpack_vec(&128u32).unwrap();
336            assert_eq!(serialized, [0xcc, 128]);
337            let serialized = to_msgpack_vec(&237u32).unwrap();
338            assert_eq!(serialized, [0xcc, 237]);
339
340            // "uint 16 stores a 16-bit big-endian unsigned integer"
341            let serialized = to_msgpack_vec(&1000u32).unwrap();
342            assert_eq!(serialized, [0xcd, 3, 232]);
343
344            // "uint 32 stores a 32-bit big-endian unsigned integer"
345            let serialized = to_msgpack_vec(&u32::MAX).unwrap();
346            assert_eq!(serialized, [0xce, 255, 255, 255, 255]);
347
348            // "uint 64 stores a 64-bit big-endian unsigned integer"
349            let serialized = to_msgpack_vec(&575747839886u64).unwrap();
350            assert_eq!(serialized, [0xcf, 0, 0, 0, 134, 13, 62, 215, 142]);
351            let serialized = to_msgpack_vec(&u64::MAX).unwrap();
352            assert_eq!(serialized, [0xcf, 255, 255, 255, 255, 255, 255, 255, 255]);
353
354            // "int 8 stores an 8-bit signed integer"
355            let serialized = to_msgpack_vec(&i8::MIN).unwrap();
356            assert_eq!(serialized, [0xd0, 128]);
357            let serialized = to_msgpack_vec(&-111i8).unwrap();
358            assert_eq!(serialized, [0xd0, 145]);
359
360            // "int 16 stores a 16-bit big-endian signed integer"
361            let serialized = to_msgpack_vec(&i16::MIN).unwrap();
362            assert_eq!(serialized, [0xd1, 128, 0]);
363
364            // "int 32 stores a 32-bit big-endian signed integer"
365            let serialized = to_msgpack_vec(&i32::MIN).unwrap();
366            assert_eq!(serialized, [0xd2, 128, 0, 0, 0]);
367
368            // "int 64 stores a 64-bit big-endian signed integer"
369            let serialized = to_msgpack_vec(&i64::MIN).unwrap();
370            assert_eq!(serialized, [0xd3, 128, 0, 0, 0, 0, 0, 0, 0]);
371        }
372
373        // u128/i128
374        // cannot be serialized as integers in messagepack due to the limitation
375        // "a value of an Integer object is limited from -(2^63) upto (2^64)-1"
376        {
377            // encoded as 16 bytes big endian
378            // i.e. takes 18 bytes of storage
379            assert_eq!(
380                to_msgpack_vec(&0u128).unwrap(),
381                [0xc4, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
382            );
383            assert_eq!(
384                to_msgpack_vec(&1u128).unwrap(),
385                [0xc4, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
386            );
387            assert_eq!(
388                to_msgpack_vec(&17u128).unwrap(),
389                [0xc4, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17]
390            );
391            assert_eq!(
392                to_msgpack_vec(&u128::MAX).unwrap(),
393                [
394                    0xc4, 16, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
395                    255, 255
396                ]
397            );
398
399            assert_eq!(
400                to_msgpack_vec(&0i128).unwrap(),
401                [0xc4, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
402            );
403            assert_eq!(
404                to_msgpack_vec(&1i128).unwrap(),
405                [0xc4, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
406            );
407            assert_eq!(
408                to_msgpack_vec(&17i128).unwrap(),
409                [0xc4, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17]
410            );
411            assert_eq!(
412                to_msgpack_vec(&-1i128).unwrap(),
413                [
414                    0xc4, 16, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
415                    255, 255
416                ]
417            );
418            assert_eq!(
419                to_msgpack_vec(&i128::MIN).unwrap(),
420                [0xc4, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
421            );
422            assert_eq!(
423                to_msgpack_vec(&i128::MAX).unwrap(),
424                [
425                    0xc4, 16, 127, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
426                    255, 255
427                ]
428            );
429        }
430
431        // Uint64/Uint128/Uint256/Uint512
432        {
433            let s = to_msgpack_vec(&Uint64::zero()).unwrap();
434            assert_eq!(s, [0b10100000 ^ 1, b'0']); // string of lengths 1 with value "0"
435            let s = to_msgpack_vec(&Uint128::zero()).unwrap();
436            assert_eq!(s, [0b10100000 ^ 1, b'0']); // string of lengths 1 with value "0"
437            let s = to_msgpack_vec(&Uint256::zero()).unwrap();
438            assert_eq!(s, [0b10100000 ^ 1, b'0']); // string of lengths 1 with value "0"
439            let s = to_msgpack_vec(&Uint512::zero()).unwrap();
440            assert_eq!(s, [0b10100000 ^ 1, b'0']); // string of lengths 1 with value "0"
441
442            let s = to_msgpack_vec(&Uint64::one()).unwrap();
443            assert_eq!(s, [0b10100000 ^ 1, b'1']); // string of lengths 1 with value "1"
444            let s = to_msgpack_vec(&Uint128::one()).unwrap();
445            assert_eq!(s, [0b10100000 ^ 1, b'1']); // string of lengths 1 with value "1"
446            let s = to_msgpack_vec(&Uint256::one()).unwrap();
447            assert_eq!(s, [0b10100000 ^ 1, b'1']); // string of lengths 1 with value "1"
448            let s = to_msgpack_vec(&Uint512::one()).unwrap();
449            assert_eq!(s, [0b10100000 ^ 1, b'1']); // string of lengths 1 with value "1"
450
451            let s = to_msgpack_vec(&Uint64::MAX).unwrap();
452            assert_eq!(
453                s,
454                [
455                    0b10100000 ^ 20,
456                    b'1',
457                    b'8',
458                    b'4',
459                    b'4',
460                    b'6',
461                    b'7',
462                    b'4',
463                    b'4',
464                    b'0',
465                    b'7',
466                    b'3',
467                    b'7',
468                    b'0',
469                    b'9',
470                    b'5',
471                    b'5',
472                    b'1',
473                    b'6',
474                    b'1',
475                    b'5'
476                ]
477            ); // string of lengths 1 with value "1"
478        }
479
480        // Int64/Int128/Int256/Int512
481        {
482            let s = to_msgpack_vec(&Int64::zero()).unwrap();
483            assert_eq!(s, [0b10100000 ^ 1, b'0']); // string of lengths 1 with value "0"
484            let s = to_msgpack_vec(&Int128::zero()).unwrap();
485            assert_eq!(s, [0b10100000 ^ 1, b'0']); // string of lengths 1 with value "0"
486            let s = to_msgpack_vec(&Int256::zero()).unwrap();
487            assert_eq!(s, [0b10100000 ^ 1, b'0']); // string of lengths 1 with value "0"
488            let s = to_msgpack_vec(&Int512::zero()).unwrap();
489            assert_eq!(s, [0b10100000 ^ 1, b'0']); // string of lengths 1 with value "0"
490
491            let s = to_msgpack_vec(&Int64::one()).unwrap();
492            assert_eq!(s, [0b10100000 ^ 1, b'1']); // string of lengths 1 with value "1"
493            let s = to_msgpack_vec(&Int128::one()).unwrap();
494            assert_eq!(s, [0b10100000 ^ 1, b'1']); // string of lengths 1 with value "1"
495            let s = to_msgpack_vec(&Int256::one()).unwrap();
496            assert_eq!(s, [0b10100000 ^ 1, b'1']); // string of lengths 1 with value "1"
497            let s = to_msgpack_vec(&Int512::one()).unwrap();
498            assert_eq!(s, [0b10100000 ^ 1, b'1']); // string of lengths 1 with value "1"
499
500            let s = to_msgpack_vec(&Int64::from(15i32)).unwrap();
501            assert_eq!(s, [0b10100000 ^ 2, b'1', b'5']); // string of lengths 2 with value "15"
502            let s = to_msgpack_vec(&Int128::from(15i32)).unwrap();
503            assert_eq!(s, [0b10100000 ^ 2, b'1', b'5']); // string of lengths 2 with value "15"
504            let s = to_msgpack_vec(&Int256::from(15i32)).unwrap();
505            assert_eq!(s, [0b10100000 ^ 2, b'1', b'5']); // string of lengths 2 with value "15"
506            let s = to_msgpack_vec(&Int512::from(15i32)).unwrap();
507            assert_eq!(s, [0b10100000 ^ 2, b'1', b'5']); // string of lengths 2 with value "15"
508
509            let s = to_msgpack_vec(&Int64::from(-1i64)).unwrap();
510            assert_eq!(s, [0b10100000 ^ 2, b'-', b'1']); // string of lengths 2 with value "-1"
511            let s = to_msgpack_vec(&Int128::from(-1i64)).unwrap();
512            assert_eq!(s, [0b10100000 ^ 2, b'-', b'1']); // string of lengths 2 with value "-1"
513            let s = to_msgpack_vec(&Int256::from(-1i64)).unwrap();
514            assert_eq!(s, [0b10100000 ^ 2, b'-', b'1']); // string of lengths 2 with value "-1"
515            let s = to_msgpack_vec(&Int512::from(-1i64)).unwrap();
516            assert_eq!(s, [0b10100000 ^ 2, b'-', b'1']); // string of lengths 2 with value "-1"
517        }
518    }
519}