Skip to content

Commit 1f0f123

Browse files
committed
provide msgpack serialization in std
1 parent 963653c commit 1f0f123

File tree

6 files changed

+147
-4
lines changed

6 files changed

+147
-4
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/std/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ serde = { workspace = true, features = ["std"] }
6262
serde-json-wasm = { version = "1.0.1", default-features = false, features = ["std"] }
6363
static_assertions = "1.1.0"
6464
thiserror = "1.0.26"
65+
rmp-serde = "=1.1.1"
6566

6667
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
6768
bech32 = "0.11.0"

packages/std/src/binary.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ mod tests {
503503
}
504504

505505
#[test]
506-
fn msgpack_deserialization_works() {
506+
fn msgpack_deserialize_from_valid_data() {
507507
// see: https://github.com/msgpack/msgpack/blob/8aa09e2/spec.md#bin-format-family
508508
let serialized = vec![196, 6, 0, 187, 61, 11, 250, 0];
509509
let expected = vec![0u8, 187, 61, 11, 250, 0];
@@ -512,6 +512,13 @@ mod tests {
512512
assert_eq!(expected, deserialized.as_slice());
513513
}
514514

515+
#[test]
516+
fn msgpack_deserialize_from_invalid_data() {
517+
let invalid_data = vec![0, 1, 2, 3, 4, 5];
518+
let res = rmp_serde::from_slice::<Binary>(&invalid_data);
519+
assert!(res.is_err());
520+
}
521+
515522
#[test]
516523
fn binary_implements_debug() {
517524
// Some data

packages/std/src/hex_binary.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ mod tests {
577577
}
578578

579579
#[test]
580-
fn msgpack_deserialization_works() {
580+
fn msgpack_deserialize_from_valid_data() {
581581
// see: https://github.com/msgpack/msgpack/blob/8aa09e2/spec.md#bin-format-family
582582
let serialized = vec![196, 6, 0, 187, 61, 11, 250, 0];
583583
let expected = vec![0u8, 187, 61, 11, 250, 0];
@@ -586,6 +586,13 @@ mod tests {
586586
assert_eq!(expected, deserialized.as_slice());
587587
}
588588

589+
#[test]
590+
fn msgpack_deserialize_from_invalid_data() {
591+
let invalid_data = vec![0, 1, 2, 3, 4, 5];
592+
let res = rmp_serde::from_slice::<HexBinary>(&invalid_data);
593+
assert!(res.is_err());
594+
}
595+
589596
#[test]
590597
fn hex_binary_implements_debug() {
591598
// Some data

packages/std/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ mod import_helpers;
2929
mod iterator;
3030
mod math;
3131
mod metadata;
32+
mod msgpack;
3233
mod never;
3334
mod pagination;
3435
mod panic;
@@ -82,6 +83,7 @@ pub use crate::math::{
8283
SignedDecimalRangeExceeded, Uint128, Uint256, Uint512, Uint64,
8384
};
8485
pub use crate::metadata::{DenomMetadata, DenomUnit};
86+
pub use crate::msgpack::{from_msgpack, to_msgpack_binary, to_msgpack_vec};
8587
pub use crate::never::Never;
8688
pub use crate::pagination::PageRequest;
8789
pub use crate::query::{

packages/std/src/msgpack.rs

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// This file simply re-exports some methods from serde_json
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 eg. serde-json-core more easily
5+
6+
use core::any::type_name;
7+
use serde::{de::DeserializeOwned, Serialize};
8+
9+
use crate::Binary;
10+
use 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+
pub fn from_msgpack<T: DeserializeOwned>(value: impl AsRef<[u8]>) -> StdResult<T> {
16+
rmp_serde::from_read(value.as_ref()).map_err(|e| StdError::parse_err(type_name::<T>(), e))
17+
}
18+
19+
/// Serializes the given data structure as a MessagePack byte vector.
20+
pub fn to_msgpack_vec<T>(data: &T) -> StdResult<Vec<u8>>
21+
where
22+
T: Serialize + ?Sized,
23+
{
24+
rmp_serde::to_vec(data).map_err(|e| StdError::serialize_err(type_name::<T>(), e))
25+
}
26+
27+
/// Serializes the given data structure as MessagePack bytes.
28+
pub fn to_msgpack_binary<T>(data: &T) -> StdResult<Binary>
29+
where
30+
T: Serialize + ?Sized,
31+
{
32+
to_msgpack_vec(data).map(Binary::new)
33+
}
34+
35+
#[cfg(test)]
36+
mod tests {
37+
use super::*;
38+
use serde::Deserialize;
39+
40+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
41+
#[serde(rename_all = "snake_case")]
42+
enum SomeMsg {
43+
Refund {},
44+
ReleaseAll {
45+
image: String,
46+
amount: u32,
47+
time: u64,
48+
karma: i32,
49+
},
50+
Cowsay {
51+
text: String,
52+
},
53+
}
54+
55+
fn refund_test_vector() -> (SomeMsg, &'static [u8]) {
56+
let msg = SomeMsg::Refund {};
57+
let serialized = &[129, 166, 114, 101, 102, 117, 110, 100, 144];
58+
(msg, serialized)
59+
}
60+
61+
fn release_all_test_vector() -> (SomeMsg, &'static [u8]) {
62+
let msg = SomeMsg::ReleaseAll {
63+
image: "foo".to_string(),
64+
amount: 42,
65+
time: 18446744073709551615,
66+
karma: -17,
67+
};
68+
let serialized = &[
69+
129, 171, 114, 101, 108, 101, 97, 115, 101, 95, 97, 108, 108, 148, 163, 102, 111, 111,
70+
42, 207, 255, 255, 255, 255, 255, 255, 255, 255, 239,
71+
];
72+
(msg, serialized)
73+
}
74+
75+
fn special_chars_test_vector() -> (SomeMsg, &'static [u8]) {
76+
let msg = SomeMsg::Cowsay {
77+
text: "foo\"bar\\\"bla".to_string(),
78+
};
79+
let serialized = &[
80+
129, 166, 99, 111, 119, 115, 97, 121, 129, 164, 116, 101, 120, 116, 172, 102, 111, 111,
81+
34, 98, 97, 114, 92, 34, 98, 108, 97,
82+
];
83+
(msg, serialized)
84+
}
85+
86+
#[test]
87+
fn to_msgpack_vec_works() {
88+
let (msg, expected) = refund_test_vector();
89+
let serialized = to_msgpack_vec(&msg).unwrap();
90+
assert_eq!(serialized, expected);
91+
92+
let (msg, expected) = release_all_test_vector();
93+
let serialized = to_msgpack_vec(&msg).unwrap();
94+
assert_eq!(serialized, expected);
95+
}
96+
97+
#[test]
98+
fn from_msgpack_works() {
99+
let (msg, serialized) = refund_test_vector();
100+
let deserialized: SomeMsg = from_msgpack(serialized).unwrap();
101+
assert_eq!(deserialized, msg);
102+
103+
let (msg, serialized) = release_all_test_vector();
104+
let deserialized: SomeMsg = from_msgpack(serialized).unwrap();
105+
assert_eq!(deserialized, msg);
106+
}
107+
108+
#[test]
109+
fn from_msgpack_or_binary() {
110+
let msg = SomeMsg::Refund {};
111+
let serialized: Binary = to_msgpack_binary(&msg).unwrap();
112+
113+
let parse_binary: SomeMsg = from_msgpack(&serialized).unwrap();
114+
assert_eq!(parse_binary, msg);
115+
116+
let parse_slice: SomeMsg = from_msgpack(serialized.as_slice()).unwrap();
117+
assert_eq!(parse_slice, msg);
118+
}
119+
120+
#[test]
121+
fn from_msgpack_works_for_special_chars() {
122+
let (msg, serialized) = special_chars_test_vector();
123+
let deserialized: SomeMsg = from_msgpack(serialized).unwrap();
124+
assert_eq!(deserialized, msg);
125+
}
126+
}

0 commit comments

Comments
 (0)