tanzim_validate/
encoding.rs1use crate::error::{Error, ErrorKind};
2use crate::{Meta, Validator};
3use base64::Engine;
4use tanzim_value::{Value, ValueType};
5
6fn as_str(value: &mut Value) -> Result<&str, Error> {
8 match value {
9 Value::String(text) => Ok(text),
10 other => Err(Error::new(ErrorKind::Type {
11 expected: ValueType::String,
12 found: other.type_name(),
13 })),
14 }
15}
16
17#[derive(Debug, Clone, Default)]
19pub struct Base64 {
20 meta: Meta,
21}
22
23impl Base64 {
24 pub fn new() -> Self {
25 Self {
26 meta: Meta::default(),
27 }
28 }
29
30 pub fn with_meta(mut self, meta: Meta) -> Self {
32 self.meta = meta;
33 self
34 }
35}
36
37impl Validator for Base64 {
38 fn meta(&self) -> &Meta {
39 &self.meta
40 }
41
42 fn meta_mut(&mut self) -> &mut Meta {
43 &mut self.meta
44 }
45
46 fn check(&self, value: &mut Value) -> Result<(), Error> {
47 let text = as_str(value)?;
48 match base64::engine::general_purpose::STANDARD.decode(text) {
49 Ok(_) => Ok(()),
50 Err(_) => Err(Error::new(ErrorKind::Format { expected: "base64" })),
51 }
52 }
53}
54
55#[derive(Debug, Clone, Default)]
57pub struct Hex {
58 meta: Meta,
59}
60
61impl Hex {
62 pub fn new() -> Self {
63 Self {
64 meta: Meta::default(),
65 }
66 }
67
68 pub fn with_meta(mut self, meta: Meta) -> Self {
70 self.meta = meta;
71 self
72 }
73}
74
75impl Validator for Hex {
76 fn meta(&self) -> &Meta {
77 &self.meta
78 }
79
80 fn meta_mut(&mut self) -> &mut Meta {
81 &mut self.meta
82 }
83
84 fn check(&self, value: &mut Value) -> Result<(), Error> {
85 let text = as_str(value)?;
86 let bytes = text.as_bytes();
87 if bytes.is_empty() || bytes.len() % 2 != 0 {
88 return Err(Error::new(ErrorKind::Format {
89 expected: "hexadecimal",
90 }));
91 }
92 for &byte in bytes {
93 if !byte.is_ascii_hexdigit() {
94 return Err(Error::new(ErrorKind::Format {
95 expected: "hexadecimal",
96 }));
97 }
98 }
99 Ok(())
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106
107 #[test]
108 fn base64_roundtrip() {
109 assert!(
110 Base64::new()
111 .validate(&mut Value::String("aGVsbG8=".into()))
112 .is_ok()
113 );
114 assert!(
115 Base64::new()
116 .validate(&mut Value::String("not base64!".into()))
117 .is_err()
118 );
119 }
120
121 #[test]
122 fn hex_digits() {
123 assert!(
124 Hex::new()
125 .validate(&mut Value::String("deadBEEF".into()))
126 .is_ok()
127 );
128 assert!(
129 Hex::new()
130 .validate(&mut Value::String("xyz".into()))
131 .is_err()
132 );
133 assert!(
134 Hex::new()
135 .validate(&mut Value::String("abc".into()))
136 .is_err()
137 );
138 }
139}