1
- use std:: num:: TryFromIntError ;
2
-
3
1
use chrono:: { DateTime , NaiveDate , Utc } ;
4
2
use rust_decimal:: Decimal ;
5
3
6
- use super :: Plaintext ;
4
+ use super :: { Plaintext , PlaintextNullVariant } ;
7
5
use crate :: encryption:: errors:: TypeParseError ;
8
6
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
+
9
13
macro_rules! impl_try_from_plaintext {
10
14
( $( $ty: ty => $variant: ident) ,* ) => {
11
15
$(
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 > {
16
18
match value {
17
19
Plaintext :: $variant( Some ( ref v) ) => Ok ( v. to_owned( ) . into( ) ) ,
18
20
_ => Err ( TypeParseError ( concat!( "Cannot convert type to " , stringify!( $ty) ) . to_string( ) ) ) ,
19
21
}
20
22
}
21
23
}
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
- }
33
24
) *
34
25
} ;
35
26
}
@@ -49,46 +40,113 @@ impl_try_from_plaintext! {
49
40
String => Utf8Str
50
41
}
51
42
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
+
52
88
#[ cfg( test) ]
53
89
mod tests {
54
90
use super :: * ;
55
91
56
92
#[ test]
57
93
fn test_conversion ( ) {
58
94
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( ) ,
60
96
"Hello" . to_string( ) ,
61
97
) ;
62
98
63
- assert ! ( !bool :: try_from ( Plaintext :: Boolean ( Some ( false ) ) ) . unwrap( ) ) ;
99
+ assert ! ( !bool :: try_from_plaintext ( & Plaintext :: Boolean ( Some ( false ) ) ) . unwrap( ) ) ;
64
100
65
- assert ! ( bool :: try_from ( Plaintext :: Boolean ( Some ( true ) ) ) . unwrap( ) ) ;
101
+ assert ! ( bool :: try_from_plaintext ( & Plaintext :: Boolean ( Some ( true ) ) ) . unwrap( ) ) ;
66
102
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
+ ) ;
70
115
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
+ ) ;
72
120
73
121
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( ) ,
75
123
Decimal :: new( 10 , 0 ) ,
76
124
) ;
77
125
78
126
assert_eq ! (
79
- NaiveDate :: try_from ( Plaintext :: NaiveDate ( Some (
127
+ NaiveDate :: try_from_plaintext ( & Plaintext :: NaiveDate ( Some (
80
128
NaiveDate :: from_ymd_opt( 2020 , 1 , 1 ) . expect( "Expected date to create" )
81
129
) ) )
82
130
. unwrap( ) ,
83
131
NaiveDate :: from_ymd_opt( 2020 , 1 , 1 ) . expect( "Expected date to create" )
84
132
) ;
85
133
86
134
assert_eq ! (
87
- DateTime :: <Utc >:: try_from ( Plaintext :: Timestamp ( Some (
135
+ DateTime :: <Utc >:: try_from_plaintext ( & Plaintext :: Timestamp ( Some (
88
136
DateTime :: <Utc >:: from_timestamp( 1000 , 0 ) . expect( "Expected timestamp to create" )
89
137
) ) )
90
138
. unwrap( ) ,
91
139
( DateTime :: from_timestamp( 1000 , 0 ) . expect( "Expected timestamp to create" ) ) ,
92
140
) ;
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
+ ) ;
93
151
}
94
152
}
0 commit comments