1+ use base64:: Engine ;
12use serde_cbor:: value:: { Value , from_value} ;
23use std:: convert:: TryFrom ;
34
45use crate :: {
56 error:: RadError ,
67 hash_functions:: { self , RadonHashFunctions } ,
7- types:: { RadonType , bytes:: RadonBytes , string:: RadonString } ,
8+ types:: {
9+ RadonType ,
10+ bytes:: { RadonBytes , RadonBytesEncoding } ,
11+ integer:: RadonInteger ,
12+ string:: RadonString ,
13+ } ,
814} ;
915
10- pub fn to_string ( input : & RadonBytes ) -> Result < RadonString , RadError > {
11- RadonString :: try_from ( Value :: Text ( hex:: encode ( input. value ( ) ) ) )
16+ pub fn as_integer ( input : & RadonBytes ) -> Result < RadonInteger , RadError > {
17+ let input_value_len = input. value ( ) . len ( ) ;
18+ match input_value_len {
19+ 1 ..=16 => {
20+ let mut bytes_array = [ 0u8 ; 16 ] ;
21+ bytes_array[ 16 - input_value_len..] . copy_from_slice ( & input. value ( ) ) ;
22+ Ok ( RadonInteger :: from ( i128:: from_be_bytes ( bytes_array) ) )
23+ }
24+ 17 .. => Err ( RadError :: ParseInt {
25+ message : "Input buffer too big" . to_string ( ) ,
26+ } ) ,
27+ _ => Err ( RadError :: EmptyArray ) ,
28+ }
1229}
1330
1431pub fn hash ( input : & RadonBytes , args : & [ Value ] ) -> Result < RadonBytes , RadError > {
@@ -27,14 +44,70 @@ pub fn hash(input: &RadonBytes, args: &[Value]) -> Result<RadonBytes, RadError>
2744
2845 Ok ( RadonBytes :: from ( digest) )
2946}
47+
48+ pub fn length ( input : & RadonBytes ) -> RadonInteger {
49+ RadonInteger :: from ( input. value ( ) . len ( ) as i128 )
50+ }
51+
52+ pub fn slice ( input : & RadonBytes , args : & [ Value ] ) -> Result < RadonBytes , RadError > {
53+ let wrong_args = || RadError :: WrongArguments {
54+ input_type : RadonString :: radon_type_name ( ) ,
55+ operator : "BytesSlice" . to_string ( ) ,
56+ args : args. to_vec ( ) ,
57+ } ;
58+ let end_index = input. value ( ) . len ( ) ;
59+ if end_index > 0 {
60+ let start_index = from_value :: < i64 > ( args[ 0 ] . clone ( ) )
61+ . unwrap_or_default ( )
62+ . rem_euclid ( end_index as i64 ) as usize ;
63+ let mut slice = input. value ( ) . as_slice ( ) . split_at ( start_index) . 1 . to_vec ( ) ;
64+ if args. len ( ) == 2 {
65+ let end_index = from_value :: < i64 > ( args[ 1 ] . clone ( ) )
66+ . unwrap_or_default ( )
67+ . rem_euclid ( end_index as i64 ) as usize ;
68+ slice. truncate ( end_index - start_index) ;
69+ }
70+ Ok ( RadonBytes :: from ( slice) )
71+ } else {
72+ Err ( wrong_args ( ) )
73+ }
74+ }
75+
76+ pub fn to_string ( input : & RadonBytes , args : & Option < Vec < Value > > ) -> Result < RadonString , RadError > {
77+ let wrong_args = || RadError :: WrongArguments {
78+ input_type : RadonString :: radon_type_name ( ) ,
79+ operator : "Stringify" . to_string ( ) ,
80+ args : args. to_owned ( ) . unwrap_or_default ( ) . to_vec ( ) ,
81+ } ;
82+ let mut bytes_encoding = RadonBytesEncoding :: Hex ;
83+ if let Some ( args) = args {
84+ if !args. is_empty ( ) {
85+ let arg = args. first ( ) . ok_or_else ( wrong_args) ?. to_owned ( ) ;
86+ let bytes_encoding_u8 = from_value :: < u8 > ( arg) . map_err ( |_| wrong_args ( ) ) ?;
87+ bytes_encoding =
88+ RadonBytesEncoding :: try_from ( bytes_encoding_u8) . map_err ( |_| wrong_args ( ) ) ?;
89+ }
90+ }
91+ match bytes_encoding {
92+ RadonBytesEncoding :: Hex => RadonString :: try_from ( Value :: Text ( hex:: encode ( input. value ( ) ) ) ) ,
93+ RadonBytesEncoding :: Base64 => RadonString :: try_from ( Value :: Text (
94+ base64:: engine:: general_purpose:: STANDARD . encode ( input. value ( ) ) ,
95+ ) ) ,
96+ RadonBytesEncoding :: Utf8 => Ok ( RadonString :: from (
97+ String :: from_utf8 ( input. value ( ) . to_vec ( ) ) . unwrap_or_default ( ) ,
98+ ) ) ,
99+ }
100+ }
101+
30102#[ cfg( test) ]
31103mod tests {
32104 use super :: * ;
33105
34106 #[ test]
35107 fn test_bytes_to_string ( ) {
36108 let input = RadonBytes :: from ( vec ! [ 0x01 , 0x02 , 0x03 ] ) ;
37- let output = to_string ( & input) . unwrap ( ) . value ( ) ;
109+ let valid_args = Some ( vec ! [ Value :: from( 0x00 ) ] ) ;
110+ let output = to_string ( & input, & valid_args) . unwrap ( ) . value ( ) ;
38111
39112 let valid_expected = "010203" . to_string ( ) ;
40113
0 commit comments