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