44//! but may end up executing arbitrary caller code if the value is complex.
55//! They will also attempt to downcast erased types into a primitive where possible.
66
7- use std:: any:: TypeId ;
87use std:: fmt;
98
10- use super :: { Erased , Inner , Primitive , Visitor } ;
9+ use super :: { Inner , Primitive , Visitor } ;
1110use crate :: kv:: value:: { Error , Value } ;
1211
12+ mod primitive;
13+
14+ /// Attempt to capture a primitive from some generic value.
15+ ///
16+ /// If the value is a primitive type, then cast it here, avoiding needing to erase its value
17+ /// This makes `Value`s produced by `Value::from_*` more useful
18+ pub ( super ) fn try_from_primitive < ' v , T : ' static > ( value : & ' v T ) -> Option < Value < ' v > > {
19+ primitive:: from_any ( value) . map ( |primitive| Value {
20+ inner : Inner :: Primitive ( primitive) ,
21+ } )
22+ }
23+
1324impl < ' v > Value < ' v > {
1425 /// Try get a `usize` from this value.
1526 ///
@@ -203,8 +214,9 @@ impl<'v> Inner<'v> {
203214 Ok ( ( ) )
204215 }
205216
206- fn borrowed_str ( & mut self , v : & ' v str ) -> Result < ( ) , Error > {
207- self . 0 = Cast :: Primitive ( Primitive :: Str ( v) ) ;
217+ #[ cfg( feature = "std" ) ]
218+ fn str ( & mut self , s : & str ) -> Result < ( ) , Error > {
219+ self . 0 = Cast :: String ( s. to_owned ( ) ) ;
208220 Ok ( ( ) )
209221 }
210222
@@ -213,9 +225,8 @@ impl<'v> Inner<'v> {
213225 Ok ( ( ) )
214226 }
215227
216- #[ cfg( feature = "std" ) ]
217- fn str ( & mut self , v : & str ) -> Result < ( ) , Error > {
218- self . 0 = Cast :: String ( v. into ( ) ) ;
228+ fn borrowed_str ( & mut self , v : & ' v str ) -> Result < ( ) , Error > {
229+ self . 0 = Cast :: Primitive ( Primitive :: Str ( v) ) ;
219230 Ok ( ( ) )
220231 }
221232
@@ -231,24 +242,14 @@ impl<'v> Inner<'v> {
231242 }
232243 }
233244
234- // Try downcast an erased value first
235- // It also lets us avoid the Visitor infrastructure for simple primitives
236- let primitive = match self {
237- Inner :: Primitive ( value) => Some ( value) ,
238- Inner :: Fill ( value) => value. downcast_primitive ( ) ,
239- Inner :: Debug ( value) => value. downcast_primitive ( ) ,
240- Inner :: Display ( value) => value. downcast_primitive ( ) ,
241-
242- #[ cfg( feature = "sval" ) ]
243- Inner :: Sval ( value) => value. downcast_primitive ( ) ,
244- } ;
245-
246- primitive. map ( Cast :: Primitive ) . unwrap_or_else ( || {
245+ if let Inner :: Primitive ( value) = self {
246+ Cast :: Primitive ( value)
247+ } else {
247248 // If the erased value isn't a primitive then we visit it
248249 let mut cast = CastVisitor ( Cast :: Primitive ( Primitive :: None ) ) ;
249250 let _ = self . visit ( & mut cast) ;
250251 cast. 0
251- } )
252+ }
252253 }
253254}
254255
@@ -321,57 +322,6 @@ impl<'v> Primitive<'v> {
321322 }
322323}
323324
324- impl < ' v , T : ?Sized + ' static > Erased < ' v , T > {
325- // NOTE: This function is a perfect candidate for memoization
326- // The outcome could be stored in a `Cell<Primitive>`
327- fn downcast_primitive ( self ) -> Option < Primitive < ' v > > {
328- macro_rules! type_ids {
329- ( $( $value: ident : $ty: ty => $cast: expr, ) * ) => { {
330- struct TypeIds ;
331-
332- impl TypeIds {
333- fn downcast_primitive<' v, T : ?Sized >( & self , value: Erased <' v, T >) -> Option <Primitive <' v>> {
334- $(
335- if TypeId :: of:: <$ty>( ) == value. type_id {
336- let $value = unsafe { value. downcast_unchecked:: <$ty>( ) } ;
337- return Some ( Primitive :: from( $cast) ) ;
338- }
339- ) *
340-
341- None
342- }
343- }
344-
345- TypeIds
346- } } ;
347- }
348-
349- let type_ids = type_ids ! [
350- value: usize => * value as u64 ,
351- value: u8 => * value as u64 ,
352- value: u16 => * value as u64 ,
353- value: u32 => * value as u64 ,
354- value: u64 => * value,
355-
356- value: isize => * value as i64 ,
357- value: i8 => * value as i64 ,
358- value: i16 => * value as i64 ,
359- value: i32 => * value as i64 ,
360- value: i64 => * value,
361-
362- value: f32 => * value as f64 ,
363- value: f64 => * value,
364-
365- value: char => * value,
366- value: bool => * value,
367-
368- value: & str => * value,
369- ] ;
370-
371- type_ids. downcast_primitive ( self )
372- }
373- }
374-
375325#[ cfg( feature = "std" ) ]
376326mod std_support {
377327 use super :: * ;
0 commit comments