@@ -5,16 +5,18 @@ use rquickjs::Ctx;
55use rquickjs:: FromJs ;
66use rquickjs:: IntoJs ;
77use rquickjs:: Value ;
8+ use serde_json:: json;
89use std:: collections:: BTreeMap ;
910
10- /// Akin to serde_json::Value with an extra case for binary data
11- #[ derive( Clone , Debug ) ]
11+ /// Akin to serde_json::Value with extra cases for date and binary data
12+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
1213pub enum JsonValue {
1314 Null ,
1415 Bool ( bool ) ,
1516 Number ( serde_json:: Number ) ,
1617 String ( String ) ,
1718 Bytes ( Vec < u8 > ) , // <= This case motivates the use of JsonValue vs serde_json::Value
19+ DateTime ( DateTime ) ,
1820 Array ( Vec < JsonValue > ) ,
1921 Object ( BTreeMap < String , JsonValue > ) ,
2022}
@@ -30,10 +32,6 @@ impl JsonValue {
3032 JsonValue :: String ( value. to_string ( ) )
3133 }
3234
33- fn number ( value : impl Into < serde_json:: Number > ) -> Self {
34- JsonValue :: Number ( value. into ( ) )
35- }
36-
3735 fn option ( value : Option < impl Into < JsonValue > > ) -> Self {
3836 value. map ( |v| v. into ( ) ) . unwrap_or ( JsonValue :: Null )
3937 }
@@ -69,10 +67,7 @@ impl From<Message> for JsonValue {
6967
7068impl From < DateTime > for JsonValue {
7169 fn from ( value : DateTime ) -> Self {
72- JsonValue :: object ( [
73- ( "seconds" , JsonValue :: number ( value. seconds ) ) ,
74- ( "nanoseconds" , JsonValue :: number ( value. nanoseconds ) ) ,
75- ] )
70+ JsonValue :: DateTime ( value)
7671 }
7772}
7873
@@ -101,6 +96,7 @@ impl From<JsonValue> for serde_json::Value {
10196 JsonValue :: Number ( n) => serde_json:: Value :: Number ( n) ,
10297 JsonValue :: String ( s) => serde_json:: Value :: String ( s) ,
10398 JsonValue :: Bytes ( b) => serde_json:: Value :: String ( format ! ( "0x {b:?}" ) ) ,
99+ JsonValue :: DateTime ( t) => json ! ( { "seconds" : t. seconds, "nanos" : t. nanoseconds } ) ,
104100 JsonValue :: Array ( a) => {
105101 serde_json:: Value :: Array ( a. into_iter ( ) . map ( serde_json:: Value :: from) . collect ( ) )
106102 }
@@ -131,15 +127,11 @@ impl TryFrom<BTreeMap<String, JsonValue>> for Message {
131127 . into ( ) )
132128 }
133129 } ;
134- let timestamp = value
135- . get ( "timestamp" )
136- . map ( |t| DateTime :: try_from ( t. clone ( ) ) )
137- . transpose ( ) ?;
138130
139131 Ok ( Message {
140132 topic : topic. to_owned ( ) ,
141133 payload,
142- timestamp,
134+ timestamp : None ,
143135 } )
144136 }
145137}
@@ -157,37 +149,6 @@ impl TryFrom<JsonValue> for Message {
157149 }
158150}
159151
160- impl TryFrom < JsonValue > for DateTime {
161- type Error = FlowError ;
162-
163- fn try_from ( value : JsonValue ) -> Result < Self , Self :: Error > {
164- let JsonValue :: Object ( object) = value else {
165- return Err (
166- anyhow:: anyhow!( "Expect a timestamp object with seconds and nanoseconds" ) . into ( ) ,
167- ) ;
168- } ;
169- DateTime :: try_from ( object)
170- }
171- }
172-
173- impl TryFrom < BTreeMap < String , JsonValue > > for DateTime {
174- type Error = FlowError ;
175-
176- fn try_from ( value : BTreeMap < String , JsonValue > ) -> Result < Self , Self :: Error > {
177- let Some ( JsonValue :: Number ( seconds) ) = value. get ( "seconds" ) else {
178- return Err ( anyhow:: anyhow!( "Missing timestamp seconds" ) . into ( ) ) ;
179- } ;
180- let Some ( JsonValue :: Number ( nanoseconds) ) = value. get ( "nanoseconds" ) else {
181- return Err ( anyhow:: anyhow!( "Missing timestamp nanoseconds" ) . into ( ) ) ;
182- } ;
183-
184- Ok ( DateTime {
185- seconds : seconds. as_u64 ( ) . unwrap_or_default ( ) ,
186- nanoseconds : nanoseconds. as_u64 ( ) . unwrap_or_default ( ) as u32 ,
187- } )
188- }
189- }
190-
191152impl TryFrom < JsonValue > for Vec < Message > {
192153 type Error = FlowError ;
193154
@@ -242,6 +203,12 @@ impl<'js> IntoJs<'js> for JsonValueRef<'_> {
242203 let bytes = rquickjs:: TypedArray :: new ( ctx. clone ( ) , value. clone ( ) ) ?;
243204 Ok ( bytes. into_value ( ) )
244205 }
206+ JsonValue :: DateTime ( value) => {
207+ let seconds = value. seconds ;
208+ let milliseconds = value. nanoseconds / 1_000_000 ;
209+ let time: Value < ' js > = ctx. eval ( format ! ( "new Date({seconds}{milliseconds:03})" ) ) ?;
210+ Ok ( time)
211+ }
245212 JsonValue :: Array ( values) => {
246213 let array = rquickjs:: Array :: new ( ctx. clone ( ) ) ?;
247214 for ( i, value) in values. iter ( ) . enumerate ( ) {
0 commit comments