dcrypt_utils/
data_conversion.rs1#[cfg(all(not(feature = "std"), feature = "alloc"))]
8extern crate alloc;
9#[cfg(all(not(feature = "std"), feature = "alloc"))]
10use alloc::{format, string::String, vec::Vec};
11
12#[cfg(feature = "std")]
13use std::{format, string::String, vec::Vec};
14
15pub fn hex_to_bytes(s: &str) -> Result<Vec<u8>, String> {
23 hex::decode(s).map_err(|e| format!("Hex decoding failed for input string '{}': {}", s, e))
24}
25
26pub fn bytes_to_hex(b: &[u8]) -> String {
34 hex::encode(b)
35}
36
37pub fn base64_to_bytes(s: &str) -> Result<Vec<u8>, String> {
46 use base64::{engine::general_purpose::STANDARD, Engine as _};
47 STANDARD
48 .decode(s)
49 .map_err(|e| format!("Base64 decoding failed for input string '{}': {}", s, e))
50}
51
52pub fn bytes_to_base64(b: &[u8]) -> String {
61 use base64::{engine::general_purpose::STANDARD, Engine as _};
62 STANDARD.encode(b)
63}
64
65pub fn base64url_nopad_to_bytes(s: &str) -> Result<Vec<u8>, String> {
73 use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _};
74 URL_SAFE_NO_PAD.decode(s).map_err(|e| {
75 format!(
76 "Base64 (URL-safe, no pad) decoding failed for '{}': {}",
77 s, e
78 )
79 })
80}
81
82pub fn bytes_to_base64url_nopad(b: &[u8]) -> String {
90 use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _};
91 URL_SAFE_NO_PAD.encode(b)
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn test_hex_conversions() {
100 let bytes = vec![0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];
101 let hex_string = "0123456789abcdef";
102
103 assert_eq!(bytes_to_hex(&bytes), hex_string);
104 assert_eq!(hex_to_bytes(hex_string).unwrap(), bytes);
105
106 assert_eq!(bytes_to_hex(&[]), "");
107 assert_eq!(hex_to_bytes("").unwrap(), Vec::<u8>::new());
108
109 assert!(hex_to_bytes("invalid hex").is_err());
110 assert!(hex_to_bytes("0g").is_err()); assert!(hex_to_bytes("012").is_err()); }
113
114 #[test]
115 fn test_base64_standard_conversions() {
116 let original_str = "Hello, DCRYPT! This is a test string.";
117 let bytes = original_str.as_bytes();
118 let base64_string = "SGVsbG8sIERDUllQVCEgVGhpcyBpcyBhIHRlc3Qgc3RyaW5nLg==";
119
120 assert_eq!(bytes_to_base64(bytes), base64_string);
121 assert_eq!(base64_to_bytes(base64_string).unwrap(), bytes);
122
123 assert_eq!(bytes_to_base64(&[]), "");
124 assert_eq!(base64_to_bytes("").unwrap(), Vec::<u8>::new());
125
126 assert!(base64_to_bytes("invalid base64 char !@#").is_err());
127 assert!(
128 base64_to_bytes("SGVsbG8sIERCWVBUISEgVGhpcyBpcyBhIHRlc3Qgc3RyaW5nLg").is_err(),
129 "Missing padding should fail strict decode"
130 );
131 }
133
134 #[test]
135 fn test_base64url_nopad_conversions() {
136 let bytes1 = vec![0xfb, 0xfb, 0xff]; let base64url_string1 = "-_v_";
139 assert_eq!(bytes_to_base64url_nopad(&bytes1), base64url_string1);
140 assert_eq!(base64url_nopad_to_bytes(base64url_string1).unwrap(), bytes1);
141
142 let original_str = "Many hands make light work.";
143 let bytes = original_str.as_bytes();
144 let base64url_nopad_string = "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu"; assert_eq!(bytes_to_base64url_nopad(bytes), base64url_nopad_string);
147 assert_eq!(
148 base64url_nopad_to_bytes(base64url_nopad_string).unwrap(),
149 bytes
150 );
151
152 assert_eq!(bytes_to_base64url_nopad(&[]), "");
153 assert_eq!(base64url_nopad_to_bytes("").unwrap(), Vec::<u8>::new());
154
155 assert!(
156 base64url_nopad_to_bytes("invalid base64 char +/=").is_err(),
157 "Standard chars should fail URL-safe"
158 );
159 }
160}