11#![ allow( dead_code) ]
22
3- use super :: error:: { exception_already_thrown, ExceptionThrown } ;
3+ use super :: error:: { exception_already_thrown, ExcResult , ExceptionThrown , ExceptionValue , Throwable , TypeError } ;
44use super :: from_value:: { cast, FromValue } ;
5+ use core:: cell:: RefCell ;
56use core:: fmt;
67use core:: iter:: { repeat_n, RepeatN } ;
8+ use core:: marker:: PhantomData ;
79use core:: mem:: MaybeUninit ;
810use derive_more:: From ;
911use spacetimedb_sats:: de:: { self , ArrayVisitor , DeserializeSeed , ProductVisitor , SliceVisitor , SumVisitor } ;
1012use spacetimedb_sats:: { i256, u256} ;
1113use std:: borrow:: { Borrow , Cow } ;
14+ use std:: rc:: Rc ;
1215use v8:: { Array , Global , HandleScope , Local , Name , Object , Uint8Array , Value } ;
1316
17+ /// Returns a `KeyCache` for the current `scope`.
18+ ///
19+ /// Creates the cache in the scope if it doesn't exist yet.
20+ pub ( super ) fn get_or_create_key_cache ( scope : & mut HandleScope < ' _ > ) -> Rc < RefCell < KeyCache > > {
21+ let context = scope. get_current_context ( ) ;
22+ context. get_slot :: < RefCell < KeyCache > > ( ) . unwrap_or_else ( || {
23+ let cache = Rc :: default ( ) ;
24+ context. set_slot ( Rc :: clone ( & cache) ) ;
25+ cache
26+ } )
27+ }
28+
29+ /// Deserializes a `T` from `val` in `scope`, using `seed` for any context needed.
30+ pub ( super ) fn deserialize_js_seed < ' de , T : DeserializeSeed < ' de > > (
31+ scope : & mut HandleScope < ' de > ,
32+ val : Local < ' _ , Value > ,
33+ seed : T ,
34+ ) -> ExcResult < T :: Output > {
35+ let key_cache = get_or_create_key_cache ( scope) ;
36+ let key_cache = & mut * key_cache. borrow_mut ( ) ;
37+ let de = Deserializer :: new ( scope, val, key_cache) ;
38+ seed. deserialize ( de) . map_err ( |e| e. throw ( scope) )
39+ }
40+
41+ /// Deserializes a `T` from `val` in `scope`.
42+ pub ( super ) fn deserialize_js < ' de , T : de:: Deserialize < ' de > > (
43+ scope : & mut HandleScope < ' de > ,
44+ val : Local < ' _ , Value > ,
45+ ) -> ExcResult < T > {
46+ deserialize_js_seed ( scope, val, PhantomData )
47+ }
48+
1449/// Deserializes from V8 values.
15- pub ( super ) struct Deserializer < ' this , ' scope > {
50+ struct Deserializer < ' this , ' scope > {
1651 common : DeserializerCommon < ' this , ' scope > ,
1752 input : Local < ' scope , Value > ,
1853}
1954
2055impl < ' this , ' scope > Deserializer < ' this , ' scope > {
2156 /// Creates a new deserializer from `input` in `scope`.
22- pub fn new ( scope : & ' this mut HandleScope < ' scope > , input : Local < ' _ , Value > , key_cache : & ' this mut KeyCache ) -> Self {
57+ fn new ( scope : & ' this mut HandleScope < ' scope > , input : Local < ' _ , Value > , key_cache : & ' this mut KeyCache ) -> Self {
2358 let input = Local :: new ( scope, input) ;
2459 let common = DeserializerCommon { scope, key_cache } ;
2560 Deserializer { input, common }
@@ -47,12 +82,22 @@ impl<'scope> DeserializerCommon<'_, 'scope> {
4782
4883/// The possible errors that [`Deserializer`] can produce.
4984#[ derive( Debug , From ) ]
50- pub ( super ) enum Error < ' scope > {
51- Value ( Local < ' scope , Value > ) ,
52- Exception ( ExceptionThrown ) ,
85+ enum Error < ' scope > {
86+ Unthrown ( ExceptionValue < ' scope > ) ,
87+ Thrown ( ExceptionThrown ) ,
5388 Custom ( String ) ,
5489}
5590
91+ impl < ' scope > Throwable < ' scope > for Error < ' scope > {
92+ fn throw ( self , scope : & mut HandleScope < ' scope > ) -> ExceptionThrown {
93+ match self {
94+ Self :: Unthrown ( exception) => exception. throw ( scope) ,
95+ Self :: Thrown ( thrown) => thrown,
96+ Self :: Custom ( msg) => TypeError ( msg) . throw ( scope) ,
97+ }
98+ }
99+ }
100+
56101impl de:: Error for Error < ' _ > {
57102 fn custom ( msg : impl fmt:: Display ) -> Self {
58103 Self :: Custom ( msg. to_string ( ) )
@@ -102,7 +147,7 @@ impl KeyCache {
102147}
103148
104149// Creates an interned [`v8::String`].
105- pub ( super ) fn v8_interned_string < ' scope > ( scope : & mut HandleScope < ' scope > , field : & str ) -> Local < ' scope , v8:: String > {
150+ fn v8_interned_string < ' scope > ( scope : & mut HandleScope < ' scope > , field : & str ) -> Local < ' scope , v8:: String > {
106151 // Internalized v8 strings are significantly faster than "normal" v8 strings
107152 // since v8 deduplicates re-used strings minimizing new allocations
108153 // see: https://github.com/v8/v8/blob/14ac92e02cc3db38131a57e75e2392529f405f2f/include/v8.h#L3165-L3171
@@ -126,7 +171,7 @@ fn deref_local<'scope, T>(local: Local<'scope, T>) -> &'scope T {
126171macro_rules! deserialize_primitive {
127172 ( $dmethod: ident, $t: ty) => {
128173 fn $dmethod( self ) -> Result <$t, Self :: Error > {
129- FromValue :: from_value( self . input, self . common. scope) . map_err( Error :: Value )
174+ FromValue :: from_value( self . input, self . common. scope) . map_err( Error :: Unthrown )
130175 }
131176 } ;
132177}
@@ -287,7 +332,7 @@ impl<'de, 'scope: 'de> de::NamedProductAccess<'de> for ProductAccess<'_, 'scope>
287332 Ok ( None )
288333 }
289334
290- fn get_field_value_seed < T : de :: DeserializeSeed < ' de > > ( & mut self , seed : T ) -> Result < T :: Output , Self :: Error > {
335+ fn get_field_value_seed < T : DeserializeSeed < ' de > > ( & mut self , seed : T ) -> Result < T :: Output , Self :: Error > {
291336 let common = self . common . reborrow ( ) ;
292337 // Extract the field's value.
293338 let input = self
@@ -336,7 +381,7 @@ impl<'de, 'this, 'scope: 'de> de::SumAccess<'de> for SumAccess<'this, 'scope> {
336381impl < ' de , ' this , ' scope : ' de > de:: VariantAccess < ' de > for Deserializer < ' this , ' scope > {
337382 type Error = Error < ' scope > ;
338383
339- fn deserialize_seed < T : de :: DeserializeSeed < ' de > > ( self , seed : T ) -> Result < T :: Output , Self :: Error > {
384+ fn deserialize_seed < T : DeserializeSeed < ' de > > ( self , seed : T ) -> Result < T :: Output , Self :: Error > {
340385 seed. deserialize ( self )
341386 }
342387}
0 commit comments