Skip to main content

pyth_lazer_protocol/
dynamic_value.rs

1use std::collections::BTreeMap;
2
3use crate::time::{DurationUs, TimestampUs};
4use anyhow::bail;
5use derive_more::From;
6use serde::ser::{SerializeMap, SerializeSeq};
7use serde::Serialize;
8
9#[derive(Debug, Clone, PartialEq, From)]
10pub enum DynamicValue {
11    String(String),
12    F64(f64),
13    U64(u64),
14    I64(i64),
15    Bool(bool),
16    Timestamp(TimestampUs),
17    Duration(DurationUs),
18    Bytes(Vec<u8>),
19    List(Vec<DynamicValue>),
20    Map(BTreeMap<String, DynamicValue>),
21}
22
23impl Serialize for DynamicValue {
24    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
25    where
26        S: serde::Serializer,
27    {
28        match self {
29            DynamicValue::String(v) => serializer.serialize_str(v),
30            DynamicValue::F64(v) => serializer.serialize_f64(*v),
31            DynamicValue::U64(v) => serializer.serialize_u64(*v),
32            DynamicValue::I64(v) => serializer.serialize_i64(*v),
33            DynamicValue::Bool(v) => serializer.serialize_bool(*v),
34            DynamicValue::Timestamp(v) => serializer.serialize_u64(v.as_micros()),
35            DynamicValue::Duration(v) => {
36                serializer.serialize_str(&humantime::format_duration((*v).into()).to_string())
37            }
38            DynamicValue::Bytes(v) => serializer.serialize_str(&hex::encode(v)),
39            DynamicValue::List(v) => {
40                let mut seq_serializer = serializer.serialize_seq(Some(v.len()))?;
41                for element in v {
42                    seq_serializer.serialize_element(element)?;
43                }
44                seq_serializer.end()
45            }
46            DynamicValue::Map(map) => {
47                let mut map_serializer = serializer.serialize_map(Some(map.len()))?;
48                for (k, v) in map {
49                    map_serializer.serialize_entry(k, v)?;
50                }
51                map_serializer.end()
52            }
53        }
54    }
55}
56
57impl DynamicValue {
58    pub fn is_str(&self, field_name: &str) -> anyhow::Result<()> {
59        match self {
60            DynamicValue::String(_) => Ok(()),
61            _ => bail!("invalid value type for {field_name}: expected String, got {self:?}"),
62        }
63    }
64}