1+ use std:: { collections:: BTreeMap , time:: Duration } ;
2+
3+ use :: protobuf:: MessageField ;
4+ use anyhow:: { bail, ensure, Context } ;
5+ use humantime:: format_duration;
6+ use protobuf:: dynamic_value:: { dynamic_value, DynamicValue } ;
7+ use pyth_lazer_protocol:: router:: TimestampUs ;
8+
19pub mod transaction_envelope {
210 pub use crate :: protobuf:: transaction_envelope:: * ;
311}
@@ -17,3 +25,137 @@ pub mod governance_instruction {
1725mod protobuf {
1826 include ! ( concat!( env!( "OUT_DIR" ) , "/protobuf/mod.rs" ) ) ;
1927}
28+
29+ impl DynamicValue {
30+ pub fn try_option_from_serde ( value : serde_value:: Value ) -> anyhow:: Result < Option < Self > > {
31+ match value {
32+ serde_value:: Value :: Option ( value) => {
33+ if let Some ( value) = value {
34+ Ok ( Some ( ( * value) . try_into ( ) ?) )
35+ } else {
36+ Ok ( None )
37+ }
38+ }
39+ value => Ok ( Some ( value. try_into ( ) ?) ) ,
40+ }
41+ }
42+
43+ pub fn to_timestamp ( & self ) -> anyhow:: Result < TimestampUs > {
44+ let value = self . value . as_ref ( ) . context ( "missing DynamicValue.value" ) ?;
45+ match value {
46+ dynamic_value:: Value :: TimestampValue ( ts) => Ok ( ts. try_into ( ) ?) ,
47+ _ => bail ! ( "expected timestamp, got {:?}" , self ) ,
48+ }
49+ }
50+
51+ pub fn to_duration ( & self ) -> anyhow:: Result < Duration > {
52+ let value = self . value . as_ref ( ) . context ( "missing DynamicValue.value" ) ?;
53+ match value {
54+ dynamic_value:: Value :: DurationValue ( duration) => Ok ( duration. clone ( ) . into ( ) ) ,
55+ _ => bail ! ( "expected duration, got {:?}" , self ) ,
56+ }
57+ }
58+ }
59+
60+ impl TryFrom < serde_value:: Value > for DynamicValue {
61+ type Error = anyhow:: Error ;
62+
63+ fn try_from ( value : serde_value:: Value ) -> Result < Self , Self :: Error > {
64+ let converted = match value {
65+ serde_value:: Value :: Bool ( value) => dynamic_value:: Value :: BoolValue ( value) ,
66+ serde_value:: Value :: U8 ( value) => dynamic_value:: Value :: UintValue ( value. into ( ) ) ,
67+ serde_value:: Value :: U16 ( value) => dynamic_value:: Value :: UintValue ( value. into ( ) ) ,
68+ serde_value:: Value :: U32 ( value) => dynamic_value:: Value :: UintValue ( value. into ( ) ) ,
69+ serde_value:: Value :: U64 ( value) => dynamic_value:: Value :: UintValue ( value) ,
70+ serde_value:: Value :: I8 ( value) => dynamic_value:: Value :: IntValue ( value. into ( ) ) ,
71+ serde_value:: Value :: I16 ( value) => dynamic_value:: Value :: IntValue ( value. into ( ) ) ,
72+ serde_value:: Value :: I32 ( value) => dynamic_value:: Value :: IntValue ( value. into ( ) ) ,
73+ serde_value:: Value :: I64 ( value) => dynamic_value:: Value :: IntValue ( value) ,
74+ serde_value:: Value :: F32 ( value) => dynamic_value:: Value :: DoubleValue ( value. into ( ) ) ,
75+ serde_value:: Value :: F64 ( value) => dynamic_value:: Value :: DoubleValue ( value) ,
76+ serde_value:: Value :: Char ( value) => dynamic_value:: Value :: StringValue ( value. to_string ( ) ) ,
77+ serde_value:: Value :: String ( value) => dynamic_value:: Value :: StringValue ( value) ,
78+ serde_value:: Value :: Bytes ( value) => dynamic_value:: Value :: BytesValue ( value) ,
79+ serde_value:: Value :: Seq ( values) => {
80+ let mut items = Vec :: new ( ) ;
81+ for value in values {
82+ items. push ( value. try_into ( ) ?) ;
83+ }
84+ dynamic_value:: Value :: List ( dynamic_value:: List {
85+ items,
86+ special_fields : Default :: default ( ) ,
87+ } )
88+ }
89+ serde_value:: Value :: Map ( values) => {
90+ let mut items = Vec :: new ( ) ;
91+ for ( key, value) in values {
92+ let key = match key {
93+ serde_value:: Value :: String ( key) => key,
94+ _ => bail ! ( "unsupported key type: expected string, got {:?}" , key) ,
95+ } ;
96+ items. push ( dynamic_value:: MapItem {
97+ key : Some ( key) ,
98+ value : MessageField :: some ( value. try_into ( ) ?) ,
99+ special_fields : Default :: default ( ) ,
100+ } )
101+ }
102+ dynamic_value:: Value :: Map ( dynamic_value:: Map {
103+ items,
104+ special_fields : Default :: default ( ) ,
105+ } )
106+ }
107+ serde_value:: Value :: Unit
108+ | serde_value:: Value :: Option ( _)
109+ | serde_value:: Value :: Newtype ( _) => bail ! ( "unsupported type: {:?}" , value) ,
110+ } ;
111+ Ok ( DynamicValue {
112+ value : Some ( converted) ,
113+ special_fields : Default :: default ( ) ,
114+ } )
115+ }
116+ }
117+
118+ impl TryFrom < DynamicValue > for serde_value:: Value {
119+ type Error = anyhow:: Error ;
120+
121+ fn try_from ( value : DynamicValue ) -> Result < Self , Self :: Error > {
122+ let value = value. value . context ( "missing DynamicValue.value" ) ?;
123+ match value {
124+ dynamic_value:: Value :: StringValue ( value) => Ok ( serde_value:: Value :: String ( value) ) ,
125+ dynamic_value:: Value :: DoubleValue ( value) => Ok ( serde_value:: Value :: F64 ( value) ) ,
126+ dynamic_value:: Value :: UintValue ( value) => Ok ( serde_value:: Value :: U64 ( value) ) ,
127+ dynamic_value:: Value :: IntValue ( value) => Ok ( serde_value:: Value :: I64 ( value) ) ,
128+ dynamic_value:: Value :: BoolValue ( value) => Ok ( serde_value:: Value :: Bool ( value) ) ,
129+ dynamic_value:: Value :: BytesValue ( value) => Ok ( serde_value:: Value :: Bytes ( value) ) ,
130+ dynamic_value:: Value :: DurationValue ( duration) => {
131+ let s: Duration = duration. into ( ) ;
132+ Ok ( serde_value:: Value :: String ( format_duration ( s) . to_string ( ) ) )
133+ }
134+ dynamic_value:: Value :: TimestampValue ( ts) => {
135+ let ts = TimestampUs :: try_from ( & ts) ?;
136+ Ok ( serde_value:: Value :: U64 ( ts. 0 ) )
137+ }
138+ dynamic_value:: Value :: List ( list) => {
139+ let mut output = Vec :: new ( ) ;
140+ for item in list. items {
141+ output. push ( item. try_into ( ) ?) ;
142+ }
143+ Ok ( serde_value:: Value :: Seq ( output) . into ( ) )
144+ }
145+ dynamic_value:: Value :: Map ( map) => {
146+ let mut output = BTreeMap :: new ( ) ;
147+ for item in map. items {
148+ let key = item. key . context ( "missing DynamicValue.MapItem.key" ) ?;
149+ let value = item
150+ . value
151+ . into_option ( )
152+ . context ( "missing DynamicValue.MapItem.value" ) ?
153+ . try_into ( ) ?;
154+ let old = output. insert ( serde_value:: Value :: String ( key) , value) ;
155+ ensure ! ( old. is_none( ) , "duplicate DynamicValue.MapItem.key" ) ;
156+ }
157+ Ok ( serde_value:: Value :: Map ( output) . into ( ) )
158+ }
159+ }
160+ }
161+ }
0 commit comments