1- use std:: num:: TryFromIntError ;
2-
31use chrono:: { DateTime , NaiveDate , Utc } ;
42use rust_decimal:: Decimal ;
53
6- use super :: Plaintext ;
4+ use super :: { Plaintext , PlaintextNullVariant } ;
75use crate :: encryption:: errors:: TypeParseError ;
86
7+ /// Trait for converting `Plaintext` to `Self`
8+ pub trait TryFromPlaintext : Sized {
9+ /// Try to convert `value` to `Self`
10+ fn try_from_plaintext ( value : & Plaintext ) -> Result < Self , TypeParseError > ;
11+ }
12+
913macro_rules! impl_try_from_plaintext {
1014 ( $( $ty: ty => $variant: ident) ,* ) => {
1115 $(
12- impl TryFrom <Plaintext > for $ty {
13- type Error = TypeParseError ;
14-
15- fn try_from( value: Plaintext ) -> Result <Self , Self :: Error > {
16+ impl TryFromPlaintext for $ty {
17+ fn try_from_plaintext( value: & Plaintext ) -> Result <Self , TypeParseError > {
1618 match value {
1719 Plaintext :: $variant( Some ( ref v) ) => Ok ( v. to_owned( ) . into( ) ) ,
1820 _ => Err ( TypeParseError ( concat!( "Cannot convert type to " , stringify!( $ty) ) . to_string( ) ) ) ,
1921 }
2022 }
2123 }
22-
23- impl TryFrom <Plaintext > for Option <$ty> {
24- type Error = TypeParseError ;
25-
26- fn try_from( value: Plaintext ) -> Result <Self , Self :: Error > {
27- match value {
28- Plaintext :: $variant( ref x) => Ok ( x. clone( ) . into( ) ) ,
29- _ => Err ( TypeParseError ( concat!( "Cannot convert type to " , stringify!( $ty) ) . to_string( ) ) ) ,
30- }
31- }
32- }
3324 ) *
3425 } ;
3526}
@@ -49,46 +40,113 @@ impl_try_from_plaintext! {
4940 String => Utf8Str
5041}
5142
43+ /// Blanket implementation of `Option<T>` for all `T` that implements `TryFromPlaintext`.
44+ impl < T > TryFromPlaintext for Option < T >
45+ where
46+ T : TryFromPlaintext + PlaintextNullVariant ,
47+ {
48+ /// Returns an error if the `Plaintext` variant of `value` and `<T as PlaintextNullVariant>::null()` doesn't match
49+ /// or if `TryFromPlaintext::try_from_plaintext` returns an error.
50+ /// Returns `None` if the inner `Option` in `value` is `None`
51+ /// Returns `Ok(Some(Self))` if `Plaintext` value was successfully be converted
52+ fn try_from_plaintext ( value : & Plaintext ) -> Result < Self , TypeParseError > {
53+ match ( value, T :: null ( ) ) {
54+ // Return OK(None) if the inner value is None
55+ ( Plaintext :: BigInt ( None ) , Plaintext :: BigInt ( _) )
56+ | ( Plaintext :: BigUInt ( None ) , Plaintext :: BigUInt ( _) )
57+ | ( Plaintext :: Boolean ( None ) , Plaintext :: Boolean ( _) )
58+ | ( Plaintext :: Decimal ( None ) , Plaintext :: Decimal ( _) )
59+ | ( Plaintext :: Float ( None ) , Plaintext :: Float ( _) )
60+ | ( Plaintext :: Int ( None ) , Plaintext :: Int ( _) )
61+ | ( Plaintext :: NaiveDate ( None ) , Plaintext :: NaiveDate ( _) )
62+ | ( Plaintext :: SmallInt ( None ) , Plaintext :: SmallInt ( _) )
63+ | ( Plaintext :: Timestamp ( None ) , Plaintext :: Timestamp ( _) )
64+ | ( Plaintext :: Utf8Str ( None ) , Plaintext :: Utf8Str ( _) ) => Ok ( None ) ,
65+
66+ // Return Result<Some(T))> if the inner value is Some
67+ ( Plaintext :: BigInt ( Some ( _) ) , Plaintext :: BigInt ( _) )
68+ | ( Plaintext :: BigUInt ( Some ( _) ) , Plaintext :: BigUInt ( _) )
69+ | ( Plaintext :: Boolean ( Some ( _) ) , Plaintext :: Boolean ( _) )
70+ | ( Plaintext :: Decimal ( Some ( _) ) , Plaintext :: Decimal ( _) )
71+ | ( Plaintext :: Float ( Some ( _) ) , Plaintext :: Float ( _) )
72+ | ( Plaintext :: Int ( Some ( _) ) , Plaintext :: Int ( _) )
73+ | ( Plaintext :: NaiveDate ( Some ( _) ) , Plaintext :: NaiveDate ( _) )
74+ | ( Plaintext :: SmallInt ( Some ( _) ) , Plaintext :: SmallInt ( _) )
75+ | ( Plaintext :: Timestamp ( Some ( _) ) , Plaintext :: Timestamp ( _) )
76+ | ( Plaintext :: Utf8Str ( Some ( _) ) , Plaintext :: Utf8Str ( _) ) => {
77+ T :: try_from_plaintext ( value) . map ( Some )
78+ }
79+ // Return type error if the expected variant for T and value doesn't match
80+ _ => Err ( TypeParseError ( format ! (
81+ "Cannot convert type to {}" ,
82+ std:: any:: type_name:: <Self >( )
83+ ) ) ) ,
84+ }
85+ }
86+ }
87+
5288#[ cfg( test) ]
5389mod tests {
5490 use super :: * ;
5591
5692 #[ test]
5793 fn test_conversion ( ) {
5894 assert_eq ! (
59- String :: try_from ( Plaintext :: Utf8Str ( Some ( "Hello" . to_string( ) ) ) ) . unwrap( ) ,
95+ String :: try_from_plaintext ( & Plaintext :: Utf8Str ( Some ( "Hello" . to_string( ) ) ) ) . unwrap( ) ,
6096 "Hello" . to_string( ) ,
6197 ) ;
6298
63- assert ! ( !bool :: try_from ( Plaintext :: Boolean ( Some ( false ) ) ) . unwrap( ) ) ;
99+ assert ! ( !bool :: try_from_plaintext ( & Plaintext :: Boolean ( Some ( false ) ) ) . unwrap( ) ) ;
64100
65- assert ! ( bool :: try_from ( Plaintext :: Boolean ( Some ( true ) ) ) . unwrap( ) ) ;
101+ assert ! ( bool :: try_from_plaintext ( & Plaintext :: Boolean ( Some ( true ) ) ) . unwrap( ) ) ;
66102
67- assert_eq ! ( i64 :: try_from( Plaintext :: BigInt ( Some ( 10 ) ) ) . unwrap( ) , 10 ) ;
68- assert_eq ! ( i32 :: try_from( Plaintext :: Int ( Some ( 10 ) ) ) . unwrap( ) , 10 ) ;
69- assert_eq ! ( i16 :: try_from( Plaintext :: SmallInt ( Some ( 10 ) ) ) . unwrap( ) , 10 ) ;
103+ assert_eq ! (
104+ i64 :: try_from_plaintext( & Plaintext :: BigInt ( Some ( 10 ) ) ) . unwrap( ) ,
105+ 10
106+ ) ;
107+ assert_eq ! (
108+ i32 :: try_from_plaintext( & Plaintext :: Int ( Some ( 10 ) ) ) . unwrap( ) ,
109+ 10
110+ ) ;
111+ assert_eq ! (
112+ i16 :: try_from_plaintext( & Plaintext :: SmallInt ( Some ( 10 ) ) ) . unwrap( ) ,
113+ 10
114+ ) ;
70115
71- assert_eq ! ( f64 :: try_from( Plaintext :: from( 10_f64 ) ) . unwrap( ) , 10. ) ;
116+ assert_eq ! (
117+ f64 :: try_from_plaintext( & Plaintext :: from( 10_f64 ) ) . unwrap( ) ,
118+ 10.
119+ ) ;
72120
73121 assert_eq ! (
74- Decimal :: try_from ( Plaintext :: Decimal ( Some ( Decimal :: new( 10 , 0 ) ) ) ) . unwrap( ) ,
122+ Decimal :: try_from_plaintext ( & Plaintext :: Decimal ( Some ( Decimal :: new( 10 , 0 ) ) ) ) . unwrap( ) ,
75123 Decimal :: new( 10 , 0 ) ,
76124 ) ;
77125
78126 assert_eq ! (
79- NaiveDate :: try_from ( Plaintext :: NaiveDate ( Some (
127+ NaiveDate :: try_from_plaintext ( & Plaintext :: NaiveDate ( Some (
80128 NaiveDate :: from_ymd_opt( 2020 , 1 , 1 ) . expect( "Expected date to create" )
81129 ) ) )
82130 . unwrap( ) ,
83131 NaiveDate :: from_ymd_opt( 2020 , 1 , 1 ) . expect( "Expected date to create" )
84132 ) ;
85133
86134 assert_eq ! (
87- DateTime :: <Utc >:: try_from ( Plaintext :: Timestamp ( Some (
135+ DateTime :: <Utc >:: try_from_plaintext ( & Plaintext :: Timestamp ( Some (
88136 DateTime :: <Utc >:: from_timestamp( 1000 , 0 ) . expect( "Expected timestamp to create" )
89137 ) ) )
90138 . unwrap( ) ,
91139 ( DateTime :: from_timestamp( 1000 , 0 ) . expect( "Expected timestamp to create" ) ) ,
92140 ) ;
141+
142+ assert_eq ! (
143+ Option :: <i64 >:: try_from_plaintext( & Plaintext :: BigInt ( Some ( 42 ) ) ) . unwrap( ) ,
144+ Some ( 42 )
145+ ) ;
146+
147+ assert_eq ! (
148+ Option :: <i64 >:: try_from_plaintext( & Plaintext :: BigInt ( None ) ) . unwrap( ) ,
149+ None ,
150+ ) ;
93151 }
94152}
0 commit comments