pub fn to_b64(data: &[u8]) -> String {
use base64::Engine;
base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(data)
}
pub fn to_json_b64<D>(data: &D) -> crate::error::Result<String>
where
D: serde::Serialize,
{
serde_json::to_string(data)
.map(|data| to_b64(data.as_bytes()))
.map_err(crate::error::Error::from)
}
pub fn from_b64(data: &str) -> crate::error::Result<String> {
use base64::Engine;
base64::prelude::BASE64_URL_SAFE_NO_PAD.decode(data)
.map_err(crate::error::Error::from)
.map(String::from_utf8)?
.map_err(crate::error::Error::from)
}
pub fn from_json_b64<D>(data: &str) -> crate::error::Result<D>
where
D: serde::de::DeserializeOwned,
{
let data = from_b64(data)?;
serde_json::from_str(&data)
.map_err(crate::error::Error::from)
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
struct TestDataStruct {
name: String,
age: u16,
}
#[test]
fn to_b64_success() {
let data = b"test";
let encoded = to_b64(data);
assert_eq!("dGVzdA", encoded);
}
#[test]
fn to_json_b64_success() {
let data = TestDataStruct {
name: String::from("test"),
age: 16,
};
let encoded = to_json_b64(&data);
assert!(encoded.is_ok(), "Should be ok");
assert_eq!("eyJuYW1lIjoidGVzdCIsImFnZSI6MTZ9", encoded.unwrap());
}
#[test]
fn from_b64_success() {
let data = "dGVzdA";
let decoded = from_b64(data);
assert!(decoded.is_ok(), "Should be ok");
assert_eq!("test", decoded.unwrap());
}
#[test]
fn from_b64_fail() {
let data = "NOT_AN_ACTUAL_DATA=/";
let decoded = from_b64(data);
match decoded {
Err(err) => match err {
crate::error::Error::B64DecodeError(_) => (),
_ => panic!("Decoded isn't a B64DecodeError"),
},
_ => panic!("Decoded isn't a error"),
}
}
#[test]
fn from_json_b64_success() {
let data = r#"eyJuYW1lIjoidGVzdCIsImFnZSI6MTZ9"#;
let decoded = from_json_b64::<TestDataStruct>(data);
assert!(decoded.is_ok(), "Should be ok");
assert_eq!(TestDataStruct { name: String::from("test"), age: 16 }, decoded.unwrap());
}
#[test]
fn from_json_b64_fail_serde() {
let data = "eyJuYW1lIjoidGVzdCIsImFnZSI6ImFzZCJ9";
let decoded = from_json_b64::<TestDataStruct>(data);
match decoded {
Err(err) => match err {
crate::error::Error::SerdeJsonError(_) => (),
_ => panic!("Decoded isn't a SerdeJsonError"),
},
_ => panic!("Decoded isn't a error"),
}
}
#[test]
fn from_json_b64_fail_b64() {
let data = "eyJu/YW1lIjoidGVzdCIsImFnZSI6ImFzZCJ9";
let decoded = from_json_b64::<TestDataStruct>(data);
match decoded {
Err(err) => match err {
crate::error::Error::B64DecodeError(_) => (),
_ => panic!("Decoded isn't a B64DecodeError"),
},
_ => panic!("Decoded isn't a error"),
}
}
}