use std::collections::HashMap;
use borsh::{BorshDeserialize, BorshSerialize};
mod serde_json_value {
pub use de::deserialize_value;
pub use ser::serialize_value;
mod ser {
use borsh::{
io::{ErrorKind, Result, Write},
BorshSerialize,
};
use core::convert::TryFrom;
pub fn serialize_value<W: Write>(value: &serde_json::Value, writer: &mut W) -> Result<()> {
match value {
serde_json::Value::Null => 0_u8.serialize(writer),
serde_json::Value::Bool(b) => {
1_u8.serialize(writer)?;
b.serialize(writer)
}
serde_json::Value::Number(n) => {
2_u8.serialize(writer)?;
serialize_number(n, writer)
}
serde_json::Value::String(s) => {
3_u8.serialize(writer)?;
s.serialize(writer)
}
serde_json::Value::Array(a) => {
4_u8.serialize(writer)?;
serialize_array(a, writer)
}
serde_json::Value::Object(o) => {
5_u8.serialize(writer)?;
serialize_map(o, writer)
}
}
}
fn serialize_number<W: Write>(number: &serde_json::Number, writer: &mut W) -> Result<()> {
if let Some(u) = number.as_u64() {
0_u8.serialize(writer)?;
return u.serialize(writer);
}
if let Some(i) = number.as_i64() {
1_u8.serialize(writer)?;
return i.serialize(writer);
}
if let Some(f) = number.as_f64() {
2_u8.serialize(writer)?;
return f.serialize(writer);
}
unreachable!("number is neither a u64, i64, nor f64");
}
fn serialize_array<W: Write>(array: &Vec<serde_json::Value>, writer: &mut W) -> Result<()> {
writer.write_all(
&(u32::try_from(array.len()).map_err(|_| ErrorKind::InvalidData)?).to_le_bytes(),
)?;
for item in array {
serialize_value(&item, writer)?;
}
Ok(())
}
fn serialize_map<W: Write>(
map: &serde_json::Map<String, serde_json::Value>,
writer: &mut W,
) -> Result<()> {
u32::try_from(map.len())
.map_err(|_| ErrorKind::InvalidData)?
.serialize(writer)?;
for (key, value) in map {
key.serialize(writer)?;
serialize_value(&value, writer)?;
}
Ok(())
}
}
mod de {
use borsh::{
io::{Error, ErrorKind, Read, Result},
BorshDeserialize,
};
fn hint_cautious<T>(hint: u32) -> usize {
let el_size = core::mem::size_of::<T>() as u32;
core::cmp::max(core::cmp::min(hint, 4096 / el_size), 1) as usize
}
pub fn deserialize_value<R: Read>(reader: &mut R) -> Result<serde_json::Value> {
let flag: u8 = BorshDeserialize::deserialize_reader(reader)?;
match flag {
0 => Ok(serde_json::Value::Null),
1 => {
let b: bool = BorshDeserialize::deserialize_reader(reader)?;
Ok(serde_json::Value::Bool(b))
}
2 => {
let n: serde_json::Number = deserialize_number(reader)?;
Ok(serde_json::Value::Number(n))
}
3 => {
let s: String = BorshDeserialize::deserialize_reader(reader)?;
Ok(serde_json::Value::String(s))
}
4 => {
let a: Vec<serde_json::Value> = deserialize_array(reader)?;
Ok(serde_json::Value::Array(a))
}
5 => {
let o: serde_json::Map<_, _> = deserialize_map(reader)?;
Ok(serde_json::Value::Object(o))
}
_ => {
let msg = format!(
"Invalid JSON value representation: {}. The first byte must be 0-5",
flag
);
Err(Error::new(ErrorKind::InvalidData, msg))
}
}
}
fn deserialize_number<R: Read>(reader: &mut R) -> Result<serde_json::Number> {
let flag: u8 = BorshDeserialize::deserialize_reader(reader)?;
match flag {
0 => {
let u: u64 = BorshDeserialize::deserialize_reader(reader)?;
Ok(u.into())
}
1 => {
let i: i64 = BorshDeserialize::deserialize_reader(reader)?;
Ok(i.into())
}
2 => {
let f: f64 = BorshDeserialize::deserialize_reader(reader)?;
serde_json::Number::from_f64(f).ok_or_else(|| {
let msg = format!("Invalid JSON number: {}", f);
Error::new(ErrorKind::InvalidData, msg)
})
}
_ => {
let msg = format!(
"Invalid JSON number representation: {}. The first byte must be 0-2",
flag
);
Err(Error::new(ErrorKind::InvalidData, msg))
}
}
}
fn deserialize_array<R: Read>(reader: &mut R) -> Result<Vec<serde_json::Value>> {
let len = u32::deserialize_reader(reader)?;
let mut result = Vec::with_capacity(hint_cautious::<(String, serde_json::Value)>(len));
for _ in 0..len {
let value = deserialize_value(reader)?;
result.push(value);
}
Ok(result)
}
fn deserialize_map<R: Read>(
reader: &mut R,
) -> Result<serde_json::Map<String, serde_json::Value>> {
let vec: Vec<(String, serde_json::Value)> = {
let len = u32::deserialize_reader(reader)?;
let mut result =
Vec::with_capacity(hint_cautious::<(String, serde_json::Value)>(len));
for _ in 0..len {
let pair = {
let key = String::deserialize_reader(reader)?;
let value = deserialize_value(reader)?;
(key, value)
};
result.push(pair);
}
result
};
Ok(vec.into_iter().collect())
}
}
}
mod borsh_wrapper {
use borsh::{BorshDeserialize, BorshSerialize};
#[derive(Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
pub struct SerdeJsonBorshWrapper(
#[borsh(
serialize_with = "super::serde_json_value::serialize_value",
deserialize_with = "super::serde_json_value::deserialize_value"
)]
pub serde_json::Value,
);
impl From<serde_json::Value> for SerdeJsonBorshWrapper {
fn from(value: serde_json::Value) -> Self {
Self(value)
}
}
impl From<SerdeJsonBorshWrapper> for serde_json::Value {
fn from(value: SerdeJsonBorshWrapper) -> Self {
value.0
}
}
}
use borsh_wrapper::SerdeJsonBorshWrapper;
#[derive(Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
struct SerdeJsonAsField {
pub examples: HashMap<String, SerdeJsonBorshWrapper>,
}
fn main() {
let original = serde_json::json!({
"null": null,
"true": true,
"false": false,
"zero": 0,
"positive_integer": 12345,
"negative_integer": -88888,
"positive_float": 123.45,
"negative_float": -888.88,
"positive_max": 1.7976931348623157e+308,
"negative_max": -1.7976931348623157e+308,
"string": "Larry",
"array_of_nulls": [null, null, null],
"array_of_numbers": [0, -1, 1, 1.1, -1.1, 34798324],
"array_of_strings": ["Larry", "Jake", "Pumpkin"],
"array_of_arrays": [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
],
"array_of_objects": [
{
"name": "Larry",
"age": 30
},
{
"name": "Jake",
"age": 7
},
{
"name": "Pumpkin",
"age": 8
}
],
"object": {
"name": "Larry",
"age": 30,
"pets": [
{
"name": "Jake",
"age": 7
},
{
"name": "Pumpkin",
"age": 8
}
]
}
});
let mut examples = HashMap::new();
examples.insert("Larry Jake Pumpkin".into(), original.clone().into());
let complex_struct = SerdeJsonAsField { examples };
let serialized = borsh::to_vec(&complex_struct).unwrap();
let mut deserialized: SerdeJsonAsField = borsh::from_slice(&serialized).unwrap();
assert_eq!(complex_struct, deserialized);
let deserialized_value: serde_json::Value = deserialized
.examples
.remove("Larry Jake Pumpkin")
.expect("key present")
.into();
assert_eq!(original, deserialized_value);
let number = deserialized_value
.get("array_of_numbers")
.expect("has key")
.as_array()
.expect("is array")
.get(5)
.expect("has index")
.as_i64()
.expect("is i64");
assert_eq!(number, 34798324);
}