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
37crate::impl_meta_methods!(Base64);
38
39impl Validator for Base64 {
40 fn meta(&self) -> &Meta {
41 &self.meta
42 }
43
44 fn meta_mut(&mut self) -> &mut Meta {
45 &mut self.meta
46 }
47
48 fn check(&self, value: &mut Value) -> Result<(), Error> {
49 let text = as_str(value)?;
50 match base64::engine::general_purpose::STANDARD.decode(text) {
51 Ok(_) => Ok(()),
52 Err(_) => Err(Error::new(ErrorKind::Format { expected: "base64" })),
53 }
54 }
55}
56
57#[derive(Debug, Clone, Default)]
59pub struct Hex {
60 meta: Meta,
61}
62
63impl Hex {
64 pub fn new() -> Self {
65 Self {
66 meta: Meta::default(),
67 }
68 }
69
70 pub fn with_meta(mut self, meta: Meta) -> Self {
72 self.meta = meta;
73 self
74 }
75}
76
77crate::impl_meta_methods!(Hex);
78
79impl Validator for Hex {
80 fn meta(&self) -> &Meta {
81 &self.meta
82 }
83
84 fn meta_mut(&mut self) -> &mut Meta {
85 &mut self.meta
86 }
87
88 fn check(&self, value: &mut Value) -> Result<(), Error> {
89 let text = as_str(value)?;
90 let bytes = text.as_bytes();
91 if bytes.is_empty() || bytes.len() % 2 != 0 {
92 return Err(Error::new(ErrorKind::Format {
93 expected: "hexadecimal",
94 }));
95 }
96 for &byte in bytes {
97 if !byte.is_ascii_hexdigit() {
98 return Err(Error::new(ErrorKind::Format {
99 expected: "hexadecimal",
100 }));
101 }
102 }
103 Ok(())
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 fn base64_roundtrip() {
113 assert!(
114 Base64::new()
115 .validate(&mut Value::String("aGVsbG8=".into()))
116 .is_ok()
117 );
118 assert!(
119 Base64::new()
120 .validate(&mut Value::String("not base64!".into()))
121 .is_err()
122 );
123 }
124
125 #[test]
126 fn hex_digits() {
127 assert!(
128 Hex::new()
129 .validate(&mut Value::String("deadBEEF".into()))
130 .is_ok()
131 );
132 assert!(
133 Hex::new()
134 .validate(&mut Value::String("xyz".into()))
135 .is_err()
136 );
137 assert!(
138 Hex::new()
139 .validate(&mut Value::String("abc".into()))
140 .is_err()
141 );
142 }
143}