iota_graphql_rpc/types/
base64.rs1use std::str::FromStr;
6
7use async_graphql::*;
8use fastcrypto::encoding::{Base64 as FastCryptoBase64, Encoding as FastCryptoEncoding};
9
10#[derive(Clone, Debug, PartialEq, Eq)]
11pub(crate) struct Base64(pub(crate) Vec<u8>);
12
13#[Scalar]
15impl ScalarType for Base64 {
16 fn parse(value: Value) -> InputValueResult<Self> {
17 match value {
18 Value::String(s) => Ok(Base64(
19 FastCryptoBase64::decode(&s)
20 .map_err(|r| InputValueError::custom(format!("{r}")))?,
21 )),
22 _ => Err(InputValueError::expected_type(value)),
23 }
24 }
25
26 fn to_value(&self) -> Value {
27 Value::String(FastCryptoBase64::encode(self.0.clone()))
28 }
29}
30
31impl FromStr for Base64 {
32 type Err = InputValueError<String>;
33
34 fn from_str(s: &str) -> Result<Self, Self::Err> {
35 Ok(Base64(
36 FastCryptoBase64::decode(s).map_err(|_| InputValueError::custom("Invalid Base64"))?,
37 ))
38 }
39}
40
41impl From<&Vec<u8>> for Base64 {
42 fn from(bytes: &Vec<u8>) -> Self {
43 Base64(bytes.clone())
44 }
45}
46
47impl From<&[u8]> for Base64 {
48 fn from(bytes: &[u8]) -> Self {
49 Base64(bytes.to_vec())
50 }
51}
52
53impl From<Vec<u8>> for Base64 {
54 fn from(bytes: Vec<u8>) -> Self {
55 Base64(bytes)
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use async_graphql::Value;
62
63 use super::*;
64
65 fn assert_input_value_error<T, U>(result: Result<T, InputValueError<U>>) {
66 match result {
67 Err(InputValueError { .. }) => {}
68 _ => panic!("Expected InputValueError"),
69 }
70 }
71
72 #[test]
73 fn test_parse_valid_base64() {
74 let input = Value::String("SGVsbG8gd29ybGQ=".to_string());
75 let parsed = <Base64 as ScalarType>::parse(input).unwrap();
76 assert_eq!(parsed.0, b"Hello world");
77 }
78
79 #[test]
80 fn test_parse_invalid_base64() {
81 let input = Value::String("SGVsbG8gd29ybGQ@".to_string());
82 let parsed = <Base64 as ScalarType>::parse(input);
83 assert_input_value_error(parsed);
84 }
85
86 #[test]
87 fn test_parse_invalid_boolean_value() {
88 let input = Value::Boolean(true);
89 let parsed = <Base64 as ScalarType>::parse(input);
90 assert_input_value_error(parsed);
91 }
92
93 #[test]
94 fn test_parse_invalid_number() {
95 let input = Value::Number(1.into());
96 let parsed = <Base64 as ScalarType>::parse(input);
97 assert_input_value_error(parsed);
98 }
99
100 #[test]
101 fn test_to_value() {
102 let base64 = Base64(b"Hello world".to_vec());
103 let value = <Base64 as ScalarType>::to_value(&base64);
104 assert_eq!(value, Value::String("SGVsbG8gd29ybGQ=".to_string()));
105 }
106
107 #[test]
108 fn test_from_str_valid() {
109 let base64_str = "SGVsbG8gd29ybGQ=";
110 let base64 = Base64::from_str(base64_str).unwrap();
111 assert_eq!(base64.0, b"Hello world");
112 }
113
114 #[test]
115 fn test_from_str_invalid() {
116 let base64_str = "SGVsbG8gd29ybGQ@";
117 let result = Base64::from_str(base64_str);
118 assert_input_value_error(result);
119 }
120
121 #[test]
122 fn test_from_vec_reference() {
123 let vec = vec![1, 2, 3, 4, 5];
124 let base64 = Base64::from(&vec);
125 assert_eq!(base64.0, vec);
126 }
127
128 #[test]
129 fn test_from_vec() {
130 let vec = vec![1, 2, 3, 4, 5];
131 let base64 = Base64::from(vec.clone());
132 assert_eq!(base64.0, vec);
133 }
134}