1- use std:: { cmp:: Ordering , collections:: BTreeMap , ops:: { Add , Div , Mul , Neg , Rem , Sub } } ;
1+ use std:: { cmp:: Ordering , collections:: { BTreeMap , btree_map :: Entry } , ops:: { Add , Div , Mul , Neg , Rem , Sub } } ;
22
3- use jaq_all:: jaq_core:: { Error , ops} ;
3+ use jaq_all:: jaq_core:: { Error , Exn , ops} ;
44
55use crate :: { RpcValue , Value } ;
66
@@ -157,23 +157,38 @@ impl jaq_all::jaq_std::ValT for RpcValue {
157157 }
158158
159159 fn as_f64 ( & self ) -> Option < f64 > {
160- todo ! ( "{}" , fn_name:: uninstantiated!( ) ) ;
160+ if let Value :: Double ( double) = self . value {
161+ Some ( double)
162+ } else {
163+ None
164+ }
161165 }
162166
163167 fn is_utf8_str ( & self ) -> bool {
164- todo ! ( "{}" , fn_name :: uninstantiated! ( ) ) ;
168+ self . is_string ( )
165169 }
166170
167171 fn as_bytes ( & self ) -> Option < & [ u8 ] > {
168- todo ! ( "{}" , fn_name:: uninstantiated!( ) ) ;
172+ if let Value :: String ( str) = & self . value {
173+ Some ( str. as_bytes ( ) )
174+ } else {
175+ None
176+ }
169177 }
170178
171- fn as_sub_str ( & self , _sub : & [ u8 ] ) -> Self {
172- todo ! ( "{}" , fn_name:: uninstantiated!( ) ) ;
179+ fn as_sub_str ( & self , sub : & [ u8 ] ) -> Self {
180+ if matches ! ( & self . value, Value :: String ( _) ) {
181+ // We do not have any fancy bytes handling, so we will just believe that the sub range
182+ // is a substring of self, and create a string out of it.
183+ String :: from_utf8_lossy ( sub) . to_string ( ) . into ( )
184+ } else {
185+ // jaq-json panics here, but I don't really like that, so if self is not a String, let's just give null.
186+ RpcValue :: null ( )
187+ }
173188 }
174189
175- fn from_utf8_bytes ( _b : impl AsRef < [ u8 ] > + Send + ' static ) -> Self {
176- todo ! ( "{}" , fn_name :: uninstantiated! ( ) ) ;
190+ fn from_utf8_bytes ( b : impl AsRef < [ u8 ] > + Send + ' static ) -> Self {
191+ String :: from_utf8_lossy ( b . as_ref ( ) ) . to_string ( ) . into ( )
177192 }
178193}
179194
@@ -241,25 +256,99 @@ impl jaq_all::jaq_core::ValT for RpcValue {
241256 }
242257 }
243258
244- fn range ( self , _range : jaq_all:: jaq_core:: val:: Range < & Self > ) -> ValR {
245- todo ! ( "{}" , fn_name:: uninstantiated!( ) ) ;
259+ fn range ( self , range : jaq_all:: jaq_core:: val:: Range < & Self > ) -> ValR {
260+ let start = range. start . map_or ( 0 , RpcValue :: as_usize) ;
261+ let end = range. end . map_or ( 0 , RpcValue :: as_usize) ;
262+ match & self . value {
263+ Value :: String ( str) => {
264+ let bytes = str. as_bytes ( ) ;
265+ bytes. get ( start..end) . map ( |bytes| String :: from_utf8_lossy ( bytes) . to_string ( ) . into ( ) ) . ok_or_else ( || Error :: typ ( self , ".." ) )
266+ }
267+ Value :: List ( lst) => {
268+ lst
269+ . get ( start..end)
270+ . map ( |new_range| new_range. to_vec ( ) . into ( ) )
271+ . ok_or_else ( || Error :: typ ( self , ".." ) )
272+ }
273+ _ => Err ( Error :: typ ( self , "" ) ) ,
274+ }
246275 }
247276
248- fn map_values < I : Iterator < Item = ValX > > (
249- self ,
250- _opt : jaq_all:: jaq_core:: path:: Opt ,
251- _f : impl Fn ( Self ) -> I ,
277+ fn map_values < I : Iterator < Item = ValX > > ( self , opt : jaq_all:: jaq_core:: path:: Opt , f : impl Fn ( Self ) -> I ,
252278 ) -> ValX {
253- todo ! ( "{}" , fn_name:: uninstantiated!( ) ) ;
279+ match self . value {
280+ Value :: List ( lst) => {
281+ lst
282+ . into_iter ( )
283+ . flat_map ( f)
284+ . collect :: < Result < Vec < _ > , _ > > ( )
285+ . map ( Into :: into)
286+ }
287+ Value :: Map ( map) => {
288+ map
289+ . into_iter ( )
290+ . filter_map ( |( k, v) | f ( v)
291+ . next ( )
292+ . map ( |v| Ok ( ( k, v?) ) ) )
293+ . collect :: < Result < BTreeMap < _ , _ > , _ > > ( )
294+ . map ( Into :: into)
295+ }
296+ v => opt. fail ( RpcValue { meta : None , value : v } , |v| jaq_all:: jaq_core:: Exn :: from ( Error :: typ ( v, "" ) ) ) ,
297+ }
254298 }
255299
256300 fn map_index < I : Iterator < Item = ValX > > (
257301 self ,
258- _index : & Self ,
259- _opt : jaq_all:: jaq_core:: path:: Opt ,
260- _f : impl Fn ( Self ) -> I ,
302+ index : & Self ,
303+ opt : jaq_all:: jaq_core:: path:: Opt ,
304+ f : impl Fn ( Self ) -> I ,
261305 ) -> ValX {
262- todo ! ( "{}" , fn_name:: uninstantiated!( ) ) ;
306+ if let ( Value :: String ( ..) | Value :: List ( ..) , Value :: Map ( o) ) = ( & self . value , & index. value ) {
307+ let range = o. get ( "start" ) ..o. get ( "end" ) ;
308+ return self . map_range ( range, opt, f) ;
309+ }
310+ match self . value {
311+ Value :: Map ( map) => {
312+ let mut map = * map;
313+ let Value :: String ( index) = & index. value else {
314+ return opt. fail ( RpcValue { meta : None , value : index. value . clone ( ) } , |v| jaq_all:: jaq_core:: Exn :: from ( Error :: typ ( v, "" ) ) )
315+ } ;
316+ match map. entry ( index. to_string ( ) ) {
317+ Entry :: Occupied ( mut e) => {
318+ let v = e. get_mut ( ) ;
319+ match f ( v. clone ( ) ) . next ( ) . transpose ( ) ? {
320+ Some ( y) => e. insert ( y) ,
321+ None => e. remove ( ) ,
322+ } ;
323+ } ,
324+ Entry :: Vacant ( e) => {
325+ if let Some ( y) = f ( RpcValue :: null ( ) ) . next ( ) . transpose ( ) ? {
326+ e. insert ( y) ;
327+ }
328+ } ,
329+ }
330+ Ok ( map. into ( ) )
331+ } ,
332+ #[ expect( clippy:: cast_possible_truncation, reason = "For now, we hope that usizes are 64-bit" ) ]
333+ Value :: List ( lst) => {
334+ let mut lst = * lst;
335+ let Value :: UInt ( index) = & index. value else {
336+ return opt. fail ( RpcValue { meta : None , value : index. value . clone ( ) } , |v| jaq_all:: jaq_core:: Exn :: from ( Error :: typ ( v, "" ) ) )
337+ } ;
338+ let Some ( x) = lst. get ( * index as usize ) else {
339+ return opt. fail ( lst. into ( ) , |oof| Exn :: from ( Error :: typ ( oof, "" ) ) ) ;
340+ } ;
341+
342+ if let Some ( y) = f ( x. clone ( ) ) . next ( ) . transpose ( ) ? {
343+ lst. insert ( * index as usize , y) ;
344+ } else {
345+ lst. remove ( * index as usize ) ;
346+ }
347+
348+ Ok ( lst. into ( ) )
349+ } ,
350+ v => opt. fail ( RpcValue { meta : None , value : v } , |v| jaq_all:: jaq_core:: Exn :: from ( Error :: typ ( v, "" ) ) ) ,
351+ }
263352 }
264353
265354 fn map_range < I : Iterator < Item = ValX > > (
@@ -268,7 +357,7 @@ impl jaq_all::jaq_core::ValT for RpcValue {
268357 _opt : jaq_all:: jaq_core:: path:: Opt ,
269358 _f : impl Fn ( Self ) -> I ,
270359 ) -> ValX {
271- todo ! ( "{}" , fn_name :: uninstantiated! ( ) ) ;
360+ todo ! ( )
272361 }
273362
274363 fn as_bool ( & self ) -> bool {
0 commit comments