kore_contract_sdk/
value_wrapper.rs

1// Copyright 2025 Kore Ledger
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4use std::io::{Read, Write};
5
6use borsh::{BorshDeserialize, BorshSerialize};
7use serde::{Deserialize, Serialize};
8use serde_json::{Map, Number, Value};
9
10/// Wrapper for `serde_json::Value` that implements `BorshSerialize` and `BorshDeserialize`.
11#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
12pub struct ValueWrapper(pub Value);
13
14/// Borsh serialization implementation for `ValueWrapper`.
15impl BorshSerialize for ValueWrapper {
16    #[inline]
17    fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
18        match &self.0 {
19            Value::Bool(data) => {
20                BorshSerialize::serialize(&0u8, writer)?;
21                BorshSerialize::serialize(&data, writer)
22            }
23            Value::Number(data) => {
24                BorshSerialize::serialize(&1u8, writer)?;
25                'data: {
26                    if data.is_f64() {
27                        let Some(data) = data.as_f64() else {
28                            break 'data;
29                        };
30                        BorshSerialize::serialize(&0u8, writer)?;
31                        return BorshSerialize::serialize(&data, writer);
32                    } else if data.is_i64() {
33                        let Some(data) = data.as_i64() else {
34                            break 'data;
35                        };
36                        BorshSerialize::serialize(&1u8, writer)?;
37                        return BorshSerialize::serialize(&data, writer);
38                    } else if data.is_u64() {
39                        let Some(data) = data.as_u64() else {
40                            break 'data;
41                        };
42                        BorshSerialize::serialize(&2u8, writer)?;
43                        return BorshSerialize::serialize(&data, writer);
44                    }
45                }
46                Err(std::io::Error::new(
47                    std::io::ErrorKind::InvalidData,
48                    "Invalid number type",
49                ))
50            }
51            Value::String(data) => {
52                BorshSerialize::serialize(&2u8, writer)?;
53                BorshSerialize::serialize(&data, writer)
54            }
55            Value::Array(data) => {
56                BorshSerialize::serialize(&3u8, writer)?;
57                BorshSerialize::serialize(&(data.len() as u32), writer)?;
58                for element in data {
59                    let element = ValueWrapper(element.to_owned());
60                    BorshSerialize::serialize(&element, writer)?;
61                }
62                Ok(())
63            }
64            Value::Object(data) => {
65                BorshSerialize::serialize(&4u8, writer)?;
66                BorshSerialize::serialize(&(data.len() as u32), writer)?;
67                for (key, value) in data {
68                    BorshSerialize::serialize(&key, writer)?;
69                    let value = ValueWrapper(value.to_owned());
70                    BorshSerialize::serialize(&value, writer)?;
71                }
72                Ok(())
73            }
74            Value::Null => BorshSerialize::serialize(&5u8, writer),
75        }
76    }
77}
78
79/// Borsh deserialization implementation for `ValueWrapper`.
80impl BorshDeserialize for ValueWrapper {
81    #[inline]
82    fn deserialize_reader<R: Read>(reader: &mut R) -> std::io::Result<Self> {
83        let order: u8 = BorshDeserialize::deserialize_reader(reader)?;
84        match order {
85            0 => {
86                let data: bool = BorshDeserialize::deserialize_reader(reader)?;
87                Ok(ValueWrapper(Value::Bool(data)))
88            }
89            1 => {
90                let internal_order: u8 =
91                    BorshDeserialize::deserialize_reader(reader)?;
92                match internal_order {
93                    0 => {
94                        let data: f64 =
95                            BorshDeserialize::deserialize_reader(reader)?;
96                        let Some(data_f64) = Number::from_f64(data) else {
97                            return Err(std::io::Error::new(
98                                std::io::ErrorKind::InvalidInput,
99                                format!("Invalid f64 Number: {}", data),
100                            ));
101                        };
102                        Ok(ValueWrapper(Value::Number(data_f64)))
103                    }
104                    1 => {
105                        let data: i64 =
106                            BorshDeserialize::deserialize_reader(reader)?;
107                        Ok(ValueWrapper(Value::Number(Number::from(data))))
108                    }
109                    2 => {
110                        let data: u64 =
111                            BorshDeserialize::deserialize_reader(reader)?;
112                        Ok(ValueWrapper(Value::Number(Number::from(data))))
113                    }
114                    _ => Err(std::io::Error::new(
115                        std::io::ErrorKind::InvalidInput,
116                        format!(
117                            "Invalid Number representation: {}",
118                            internal_order
119                        ),
120                    )),
121                }
122            }
123            2 => {
124                let data: String =
125                    BorshDeserialize::deserialize_reader(reader)?;
126                Ok(ValueWrapper(Value::String(data)))
127            }
128            3 => {
129                let len = u32::deserialize_reader(reader)?;
130                if len == 0 {
131                    Ok(ValueWrapper(Value::Array(Vec::new())))
132                } else {
133                    let mut result = Vec::with_capacity(len as usize);
134                    for _ in 0..len {
135                        result
136                            .push(ValueWrapper::deserialize_reader(reader)?.0);
137                    }
138                    Ok(ValueWrapper(Value::Array(result)))
139                }
140            }
141            4 => {
142                let len = u32::deserialize_reader(reader)?;
143                let mut result = Map::new();
144                for _ in 0..len {
145                    let key = String::deserialize_reader(reader)?;
146                    let value = ValueWrapper::deserialize_reader(reader)?;
147                    result.insert(key, value.0);
148                }
149                Ok(ValueWrapper(Value::Object(result)))
150            }
151            5 => Ok(ValueWrapper(Value::Null)),
152            _ => Err(std::io::Error::new(
153                std::io::ErrorKind::InvalidInput,
154                format!("Invalid Value representation: {}", order),
155            )),
156        }
157    }
158}
159#[cfg(test)]
160mod tests {
161    use super::*;
162
163    #[test]
164    fn test_value_wrapper() {
165        let value = ValueWrapper(Value::String("test".to_owned()));
166        let vec = borsh::to_vec(&value).unwrap();
167        let value2: ValueWrapper = BorshDeserialize::try_from_slice(&vec).unwrap();
168        assert_eq!(value, value2);
169    }
170}