Skip to content

Commit b1e808e

Browse files
committed
feat(lazer): add DynamicValue parsed type
1 parent 48521b5 commit b1e808e

File tree

6 files changed

+266
-146
lines changed

6 files changed

+266
-146
lines changed

Cargo.lock

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

lazer/publisher_sdk/rust/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ repository = "https://github.com/pyth-network/pyth-crosschain"
1010
pyth-lazer-protocol = { version = "0.9.0", path = "../../sdk/rust/protocol" }
1111
anyhow = "1.0.98"
1212
protobuf = "3.7.2"
13-
serde-value = "0.7.0"
1413
humantime = "2.2.0"
1514
tracing = "0.1.41"
15+
serde = { version = "1.0.219", features = ["derive"] }
16+
serde_json = "1.0.140"
17+
derive_more = { version = "2.0.1", features = ["from"] }
1618

1719
[build-dependencies]
1820
fs-err = "3.1.0"
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
use std::collections::BTreeMap;
2+
3+
use crate::protobuf::dynamic_value::{dynamic_value, DynamicValue as ProtobufDynamicValue};
4+
use ::protobuf::MessageField;
5+
use anyhow::{ensure, Context};
6+
use derive_more::From;
7+
use pyth_lazer_protocol::time::{DurationUs, TimestampUs};
8+
use serde::{
9+
ser::{SerializeMap, SerializeSeq},
10+
Serialize,
11+
};
12+
13+
#[derive(Debug, Clone, PartialEq, From)]
14+
pub enum DynamicValue {
15+
String(String),
16+
F64(f64),
17+
U64(u64),
18+
I64(i64),
19+
Bool(bool),
20+
Timestamp(TimestampUs),
21+
Duration(DurationUs),
22+
Bytes(Vec<u8>),
23+
List(Vec<DynamicValue>),
24+
Map(BTreeMap<String, DynamicValue>),
25+
}
26+
27+
impl From<DynamicValue> for ProtobufDynamicValue {
28+
fn from(value: DynamicValue) -> Self {
29+
let converted = match value {
30+
DynamicValue::Bool(value) => dynamic_value::Value::BoolValue(value),
31+
DynamicValue::U64(value) => dynamic_value::Value::UintValue(value),
32+
DynamicValue::I64(value) => dynamic_value::Value::IntValue(value),
33+
DynamicValue::F64(value) => dynamic_value::Value::DoubleValue(value),
34+
DynamicValue::String(value) => dynamic_value::Value::StringValue(value),
35+
DynamicValue::Bytes(value) => dynamic_value::Value::BytesValue(value),
36+
DynamicValue::Timestamp(value) => dynamic_value::Value::TimestampValue(value.into()),
37+
DynamicValue::Duration(value) => dynamic_value::Value::DurationValue(value.into()),
38+
DynamicValue::List(values) => dynamic_value::Value::List(values.into()),
39+
DynamicValue::Map(values) => dynamic_value::Value::Map(values.into()),
40+
};
41+
ProtobufDynamicValue {
42+
value: Some(converted),
43+
special_fields: Default::default(),
44+
}
45+
}
46+
}
47+
48+
impl From<&DynamicValue> for ProtobufDynamicValue {
49+
fn from(value: &DynamicValue) -> Self {
50+
let converted = match value {
51+
DynamicValue::Bool(value) => dynamic_value::Value::BoolValue(*value),
52+
DynamicValue::U64(value) => dynamic_value::Value::UintValue(*value),
53+
DynamicValue::I64(value) => dynamic_value::Value::IntValue(*value),
54+
DynamicValue::F64(value) => dynamic_value::Value::DoubleValue(*value),
55+
DynamicValue::String(value) => dynamic_value::Value::StringValue(value.clone()),
56+
DynamicValue::Bytes(value) => dynamic_value::Value::BytesValue(value.clone()),
57+
DynamicValue::Timestamp(value) => dynamic_value::Value::TimestampValue((*value).into()),
58+
DynamicValue::Duration(value) => dynamic_value::Value::DurationValue((*value).into()),
59+
DynamicValue::List(values) => dynamic_value::Value::List(values.into()),
60+
DynamicValue::Map(values) => dynamic_value::Value::Map(values.into()),
61+
};
62+
ProtobufDynamicValue {
63+
value: Some(converted),
64+
special_fields: Default::default(),
65+
}
66+
}
67+
}
68+
69+
impl From<BTreeMap<String, DynamicValue>> for dynamic_value::Map {
70+
fn from(values: BTreeMap<String, DynamicValue>) -> Self {
71+
let mut items = Vec::new();
72+
for (key, value) in values {
73+
items.push(dynamic_value::MapItem {
74+
key: Some(key),
75+
value: MessageField::some(value.into()),
76+
special_fields: Default::default(),
77+
})
78+
}
79+
dynamic_value::Map {
80+
items,
81+
special_fields: Default::default(),
82+
}
83+
}
84+
}
85+
86+
impl From<&BTreeMap<String, DynamicValue>> for dynamic_value::Map {
87+
fn from(values: &BTreeMap<String, DynamicValue>) -> Self {
88+
let mut items = Vec::new();
89+
for (key, value) in values {
90+
items.push(dynamic_value::MapItem {
91+
key: Some(key.clone()),
92+
value: MessageField::some(value.into()),
93+
special_fields: Default::default(),
94+
})
95+
}
96+
dynamic_value::Map {
97+
items,
98+
special_fields: Default::default(),
99+
}
100+
}
101+
}
102+
103+
impl From<Vec<DynamicValue>> for dynamic_value::List {
104+
fn from(values: Vec<DynamicValue>) -> Self {
105+
let mut items = Vec::new();
106+
for value in values {
107+
items.push(value.into());
108+
}
109+
dynamic_value::List {
110+
items,
111+
special_fields: Default::default(),
112+
}
113+
}
114+
}
115+
116+
impl From<&[DynamicValue]> for dynamic_value::List {
117+
fn from(values: &[DynamicValue]) -> Self {
118+
let mut items = Vec::new();
119+
for value in values {
120+
items.push(value.into());
121+
}
122+
dynamic_value::List {
123+
items,
124+
special_fields: Default::default(),
125+
}
126+
}
127+
}
128+
129+
impl From<&Vec<DynamicValue>> for dynamic_value::List {
130+
fn from(value: &Vec<DynamicValue>) -> Self {
131+
let value: &[DynamicValue] = value;
132+
value.into()
133+
}
134+
}
135+
136+
impl TryFrom<ProtobufDynamicValue> for DynamicValue {
137+
type Error = anyhow::Error;
138+
139+
fn try_from(value: ProtobufDynamicValue) -> Result<Self, Self::Error> {
140+
let value = value.value.context("missing DynamicValue.value")?;
141+
match value {
142+
dynamic_value::Value::StringValue(value) => Ok(DynamicValue::String(value)),
143+
dynamic_value::Value::DoubleValue(value) => Ok(DynamicValue::F64(value)),
144+
dynamic_value::Value::UintValue(value) => Ok(DynamicValue::U64(value)),
145+
dynamic_value::Value::IntValue(value) => Ok(DynamicValue::I64(value)),
146+
dynamic_value::Value::BoolValue(value) => Ok(DynamicValue::Bool(value)),
147+
dynamic_value::Value::BytesValue(value) => Ok(DynamicValue::Bytes(value)),
148+
dynamic_value::Value::DurationValue(value) => {
149+
let v: DurationUs = value.try_into()?;
150+
Ok(DynamicValue::Duration(v))
151+
}
152+
dynamic_value::Value::TimestampValue(ts) => {
153+
let ts = TimestampUs::try_from(&ts)?;
154+
Ok(DynamicValue::Timestamp(ts))
155+
}
156+
dynamic_value::Value::List(list) => Ok(DynamicValue::List(list.try_into()?)),
157+
dynamic_value::Value::Map(map) => Ok(DynamicValue::Map(map.try_into()?)),
158+
}
159+
}
160+
}
161+
162+
impl TryFrom<dynamic_value::Map> for BTreeMap<String, DynamicValue> {
163+
type Error = anyhow::Error;
164+
165+
fn try_from(value: dynamic_value::Map) -> Result<Self, Self::Error> {
166+
let mut output = BTreeMap::new();
167+
for item in value.items {
168+
let key = item.key.context("missing DynamicValue.MapItem.key")?;
169+
let value = item
170+
.value
171+
.into_option()
172+
.context("missing DynamicValue.MapItem.value")?
173+
.try_into()?;
174+
let old = output.insert(key, value);
175+
ensure!(old.is_none(), "duplicate DynamicValue.MapItem.key");
176+
}
177+
Ok(output)
178+
}
179+
}
180+
181+
impl TryFrom<dynamic_value::List> for Vec<DynamicValue> {
182+
type Error = anyhow::Error;
183+
184+
fn try_from(value: dynamic_value::List) -> Result<Self, Self::Error> {
185+
let mut output = Vec::new();
186+
for item in value.items {
187+
output.push(item.try_into()?);
188+
}
189+
Ok(output)
190+
}
191+
}
192+
193+
impl Serialize for DynamicValue {
194+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
195+
where
196+
S: serde::Serializer,
197+
{
198+
match self {
199+
DynamicValue::String(v) => serializer.serialize_str(v),
200+
DynamicValue::F64(v) => serializer.serialize_f64(*v),
201+
DynamicValue::U64(v) => serializer.serialize_u64(*v),
202+
DynamicValue::I64(v) => serializer.serialize_i64(*v),
203+
DynamicValue::Bool(v) => serializer.serialize_bool(*v),
204+
DynamicValue::Timestamp(v) => serializer.serialize_u64(v.as_micros()),
205+
DynamicValue::Duration(v) => {
206+
serializer.serialize_str(&humantime::format_duration((*v).into()).to_string())
207+
}
208+
DynamicValue::Bytes(v) => serializer.serialize_bytes(v),
209+
DynamicValue::List(v) => {
210+
let mut seq_serializer = serializer.serialize_seq(Some(v.len()))?;
211+
for element in v {
212+
seq_serializer.serialize_element(element)?;
213+
}
214+
seq_serializer.end()
215+
}
216+
DynamicValue::Map(map) => {
217+
let mut map_serializer = serializer.serialize_map(Some(map.len()))?;
218+
for (k, v) in map {
219+
map_serializer.serialize_entry(k, v)?;
220+
}
221+
map_serializer.end()
222+
}
223+
}
224+
}
225+
}

0 commit comments

Comments
 (0)