df_hyperliquid_core/utils/sign/
msgpack.rs1use std::borrow::Cow;
5
6use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
7
8use crate::utils::json::Json;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum Value {
12 Nil,
13 Bool(bool),
14 Uint(u64),
15 Int(i64),
17 Str(Cow<'static, str>),
18 Array(Vec<Value>),
19 Map(Map),
20}
21
22impl Value {
23 #[must_use]
24 pub fn array<V: Into<Value>>(items: impl IntoIterator<Item = V>) -> Value {
25 Value::Array(items.into_iter().map(Into::into).collect())
26 }
27
28 #[must_use]
29 pub fn to_msgpack(&self) -> Vec<u8> {
30 encode(self)
31 }
32
33 #[must_use]
36 pub fn to_json(&self) -> Json {
37 match self {
38 Value::Nil => Json::Null,
39 Value::Bool(value) => Json::Bool(*value),
40 Value::Uint(number) => Json::Number(number.to_string()),
41 Value::Int(number) => Json::Number(number.to_string()),
42 Value::Str(text) => Json::String(text.to_string()),
43 Value::Array(items) => Json::Array(items.iter().map(Value::to_json).collect()),
44 Value::Map(map) => map.to_json(),
45 }
46 }
47}
48
49#[derive(Debug, Clone, PartialEq, Eq, Default)]
51pub struct Map(Vec<(Cow<'static, str>, Value)>);
52
53impl Map {
54 #[must_use]
55 pub const fn new() -> Self {
56 Map(Vec::new())
57 }
58
59 #[must_use]
60 pub fn put(mut self, key: impl Into<Cow<'static, str>>, value: impl Into<Value>) -> Self {
61 self.0.push((key.into(), value.into()));
62 self
63 }
64
65 #[must_use]
66 pub fn put_some(self, key: impl Into<Cow<'static, str>>, value: Option<impl Into<Value>>) -> Self {
67 match value {
68 Some(value) => self.put(key, value),
69 None => self,
70 }
71 }
72
73 #[must_use]
74 pub fn len(&self) -> usize {
75 self.0.len()
76 }
77
78 #[must_use]
79 pub fn is_empty(&self) -> bool {
80 self.0.is_empty()
81 }
82
83 pub fn into_pairs(self) -> impl Iterator<Item = (Cow<'static, str>, Value)> {
85 self.0.into_iter()
86 }
87
88 pub fn keys(&self) -> impl Iterator<Item = &str> {
89 self.0.iter().map(|(key, _)| key.as_ref())
90 }
91
92 #[must_use]
93 pub fn get(&self, key: &str) -> Option<&Value> {
94 self.0.iter().find(|(stored, _)| stored == key).map(|(_, value)| value)
95 }
96
97 #[must_use]
98 pub fn to_msgpack(&self) -> Vec<u8> {
99 let mut out = Vec::new();
100 write_map(self, &mut out);
101 out
102 }
103
104 #[must_use]
105 pub fn to_json(&self) -> Json {
106 Json::Object(self.0.iter().map(|(key, value)| (key.to_string(), value.to_json())).collect())
107 }
108}
109
110impl From<Map> for Value {
111 fn from(map: Map) -> Value {
112 Value::Map(map)
113 }
114}
115
116impl From<bool> for Value {
117 fn from(value: bool) -> Value {
118 Value::Bool(value)
119 }
120}
121
122impl From<u64> for Value {
123 fn from(value: u64) -> Value {
124 Value::Uint(value)
125 }
126}
127
128impl From<u32> for Value {
129 fn from(value: u32) -> Value {
130 Value::Uint(u64::from(value))
131 }
132}
133
134impl From<i64> for Value {
135 fn from(value: i64) -> Value {
136 Value::Int(value)
137 }
138}
139
140impl From<&'static str> for Value {
141 fn from(value: &'static str) -> Value {
142 Value::Str(Cow::Borrowed(value))
143 }
144}
145
146impl From<String> for Value {
147 fn from(value: String) -> Value {
148 Value::Str(Cow::Owned(value))
149 }
150}
151
152impl From<Cow<'static, str>> for Value {
153 fn from(value: Cow<'static, str>) -> Value {
154 Value::Str(value)
155 }
156}
157
158impl From<Vec<Value>> for Value {
159 fn from(value: Vec<Value>) -> Value {
160 Value::Array(value)
161 }
162}
163
164#[must_use]
165pub fn encode(value: &Value) -> Vec<u8> {
166 let mut out = Vec::new();
167 write(value, &mut out);
168 out
169}
170
171pub fn write(value: &Value, out: &mut Vec<u8>) {
172 match value {
173 Value::Nil => out.push(0xc0),
174 Value::Bool(false) => out.push(0xc2),
175 Value::Bool(true) => out.push(0xc3),
176 Value::Uint(number) => write_uint(*number, out),
177 Value::Int(number) => write_int(*number, out),
178 Value::Str(text) => write_str(text, out),
179 Value::Array(items) => {
180 write_len(items.len(), 0x90, 0xdc, 0xdd, out);
181 for item in items {
182 write(item, out);
183 }
184 }
185 Value::Map(map) => write_map(map, out),
186 }
187}
188
189fn write_map(map: &Map, out: &mut Vec<u8>) {
190 write_len(map.0.len(), 0x80, 0xde, 0xdf, out);
191 for (key, value) in &map.0 {
192 write_str(key, out);
193 write(value, out);
194 }
195}
196
197fn write_len(len: usize, fixed: u8, wide16: u8, wide32: u8, out: &mut Vec<u8>) {
198 if len <= 15 {
199 out.push(fixed | len as u8);
200 } else if let Ok(len) = u16::try_from(len) {
201 out.push(wide16);
202 out.extend_from_slice(&len.to_be_bytes());
203 } else {
204 out.push(wide32);
205 out.extend_from_slice(&(len as u32).to_be_bytes());
206 }
207}
208
209fn write_str(text: &str, out: &mut Vec<u8>) {
210 let bytes = text.as_bytes();
211 if bytes.len() <= 31 {
212 out.push(0xa0 | bytes.len() as u8);
213 } else if let Ok(len) = u8::try_from(bytes.len()) {
214 out.push(0xd9);
215 out.push(len);
216 } else if let Ok(len) = u16::try_from(bytes.len()) {
217 out.push(0xda);
218 out.extend_from_slice(&len.to_be_bytes());
219 } else {
220 out.push(0xdb);
221 out.extend_from_slice(&(bytes.len() as u32).to_be_bytes());
222 }
223 out.extend_from_slice(bytes);
224}
225
226fn write_uint(number: u64, out: &mut Vec<u8>) {
227 if number <= 0x7f {
228 out.push(number as u8);
229 } else if let Ok(byte) = u8::try_from(number) {
230 out.push(0xcc);
231 out.push(byte);
232 } else if let Ok(short) = u16::try_from(number) {
233 out.push(0xcd);
234 out.extend_from_slice(&short.to_be_bytes());
235 } else if let Ok(word) = u32::try_from(number) {
236 out.push(0xce);
237 out.extend_from_slice(&word.to_be_bytes());
238 } else {
239 out.push(0xcf);
240 out.extend_from_slice(&number.to_be_bytes());
241 }
242}
243
244fn write_int(number: i64, out: &mut Vec<u8>) {
245 if let Ok(unsigned) = u64::try_from(number) {
246 write_uint(unsigned, out);
247 } else if number >= -32 {
248 out.push(number as u8);
249 } else if let Ok(byte) = i8::try_from(number) {
250 out.push(0xd0);
251 out.extend_from_slice(&byte.to_be_bytes());
252 } else if let Ok(short) = i16::try_from(number) {
253 out.push(0xd1);
254 out.extend_from_slice(&short.to_be_bytes());
255 } else if let Ok(word) = i32::try_from(number) {
256 out.push(0xd2);
257 out.extend_from_slice(&word.to_be_bytes());
258 } else {
259 out.push(0xd3);
260 out.extend_from_slice(&number.to_be_bytes());
261 }
262}
263
264impl Serialize for Value {
265 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
266 match self {
267 Value::Nil => serializer.serialize_unit(),
268 Value::Bool(value) => serializer.serialize_bool(*value),
269 Value::Uint(number) => serializer.serialize_u64(*number),
270 Value::Int(number) => serializer.serialize_i64(*number),
271 Value::Str(text) => serializer.serialize_str(text),
272 Value::Array(items) => {
273 let mut sequence = serializer.serialize_seq(Some(items.len()))?;
274 for item in items {
275 sequence.serialize_element(item)?;
276 }
277 sequence.end()
278 }
279 Value::Map(map) => map.serialize(serializer),
280 }
281 }
282}
283
284impl Serialize for Map {
285 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
286 let mut entries = serializer.serialize_map(Some(self.0.len()))?;
287 for (key, value) in &self.0 {
288 entries.serialize_entry(key.as_ref(), value)?;
289 }
290 entries.end()
291 }
292}
293
294#[cfg(test)]
295#[path = "tests/msgpack.rs"]
296mod tests;