1use crate::seqstring::{global_bytes, global_string};
27use crate::stack::{Stack, pop, push};
28use crate::value::Value;
29
30use base64::prelude::*;
31
32#[unsafe(no_mangle)]
39pub unsafe extern "C" fn patch_seq_base64_encode(stack: Stack) -> Stack {
40 assert!(!stack.is_null(), "base64-encode: stack is empty");
41
42 let (stack, value) = unsafe { pop(stack) };
43
44 match value {
45 Value::String(s) => {
46 let encoded = BASE64_STANDARD.encode(s.as_bytes());
47 unsafe { push(stack, Value::String(global_string(encoded))) }
48 }
49 _ => panic!("base64-encode: expected String on stack, got {:?}", value),
50 }
51}
52
53#[unsafe(no_mangle)]
62pub unsafe extern "C" fn patch_seq_base64_decode(stack: Stack) -> Stack {
63 assert!(!stack.is_null(), "base64-decode: stack is empty");
64
65 let (stack, value) = unsafe { pop(stack) };
66
67 match value {
68 Value::String(s) => match BASE64_STANDARD.decode(s.as_bytes()) {
72 Ok(bytes) => {
73 let stack = unsafe { push(stack, Value::String(global_bytes(bytes))) };
74 unsafe { push(stack, Value::Bool(true)) }
75 }
76 Err(_) => {
77 let stack = unsafe { push(stack, Value::String(global_string(String::new()))) };
79 unsafe { push(stack, Value::Bool(false)) }
80 }
81 },
82 _ => panic!("base64-decode: expected String on stack, got {:?}", value),
83 }
84}
85
86#[unsafe(no_mangle)]
96pub unsafe extern "C" fn patch_seq_base64url_encode(stack: Stack) -> Stack {
97 assert!(!stack.is_null(), "base64url-encode: stack is empty");
98
99 let (stack, value) = unsafe { pop(stack) };
100
101 match value {
102 Value::String(s) => {
103 let encoded = BASE64_URL_SAFE_NO_PAD.encode(s.as_bytes());
104 unsafe { push(stack, Value::String(global_string(encoded))) }
105 }
106 _ => panic!(
107 "base64url-encode: expected String on stack, got {:?}",
108 value
109 ),
110 }
111}
112
113#[unsafe(no_mangle)]
122pub unsafe extern "C" fn patch_seq_base64url_decode(stack: Stack) -> Stack {
123 assert!(!stack.is_null(), "base64url-decode: stack is empty");
124
125 let (stack, value) = unsafe { pop(stack) };
126
127 match value {
128 Value::String(s) => match BASE64_URL_SAFE_NO_PAD.decode(s.as_bytes()) {
129 Ok(bytes) => {
130 let stack = unsafe { push(stack, Value::String(global_bytes(bytes))) };
131 unsafe { push(stack, Value::Bool(true)) }
132 }
133 Err(_) => {
134 let stack = unsafe { push(stack, Value::String(global_string(String::new()))) };
135 unsafe { push(stack, Value::Bool(false)) }
136 }
137 },
138 _ => panic!(
139 "base64url-decode: expected String on stack, got {:?}",
140 value
141 ),
142 }
143}
144
145#[unsafe(no_mangle)]
154pub unsafe extern "C" fn patch_seq_hex_encode(stack: Stack) -> Stack {
155 assert!(!stack.is_null(), "hex-encode: stack is empty");
156
157 let (stack, value) = unsafe { pop(stack) };
158
159 match value {
160 Value::String(s) => {
161 let encoded = hex::encode(s.as_bytes());
162 unsafe { push(stack, Value::String(global_string(encoded))) }
163 }
164 _ => panic!("hex-encode: expected String on stack, got {:?}", value),
165 }
166}
167
168#[unsafe(no_mangle)]
178pub unsafe extern "C" fn patch_seq_hex_decode(stack: Stack) -> Stack {
179 assert!(!stack.is_null(), "hex-decode: stack is empty");
180
181 let (stack, value) = unsafe { pop(stack) };
182
183 match value {
184 Value::String(s) => match hex::decode(s.as_bytes()) {
187 Ok(bytes) => {
188 let stack = unsafe { push(stack, Value::String(global_bytes(bytes))) };
189 unsafe { push(stack, Value::Bool(true)) }
190 }
191 Err(_) => {
192 let stack = unsafe { push(stack, Value::String(global_string(String::new()))) };
194 unsafe { push(stack, Value::Bool(false)) }
195 }
196 },
197 _ => panic!("hex-decode: expected String on stack, got {:?}", value),
198 }
199}
200
201#[cfg(test)]
202mod tests;