parent
5e24e96ffe
commit
c26dab4150
@ -0,0 +1,133 @@
|
|||||||
|
//! Conversion formats
|
||||||
|
use super::*;
|
||||||
|
use std::{
|
||||||
|
ops::Deref,
|
||||||
|
borrow::Borrow,
|
||||||
|
fmt,
|
||||||
|
error,
|
||||||
|
};
|
||||||
|
use regex::{
|
||||||
|
Regex,
|
||||||
|
};
|
||||||
|
|
||||||
|
const BASE64_VALIDATE_RE_STR: &'static str = r#"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"#;
|
||||||
|
|
||||||
|
lazy_static!{
|
||||||
|
static ref BASE64_CONV_TABLE: smallmap::Map<char, char> = smallmap![
|
||||||
|
{'/' => 'ł'},
|
||||||
|
{'+' => 'þ'},
|
||||||
|
{'=' => 'ø'},
|
||||||
|
];
|
||||||
|
static ref BASE64_CONV_TABLE_REV: smallmap::Map<char, char> = BASE64_CONV_TABLE.clone().reverse();
|
||||||
|
|
||||||
|
static ref BASE64_VALIDATE_REGEX: Regex = Regex::new(BASE64_VALIDATE_RE_STR).expect("Failed to compile base64 validation regex");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Base64Error<T>(T);
|
||||||
|
|
||||||
|
impl<T> error::Error for Base64Error<T>
|
||||||
|
where T: AsRef<str> + fmt::Debug{}
|
||||||
|
impl<T> fmt::Display for Base64Error<T>
|
||||||
|
where T: AsRef<str>
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||||
|
{
|
||||||
|
write!(f, "invalid base64: {:?}", self.0.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// A string of modified base64, appropriate for URL paths etc.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
pub struct ModifiedBase64String(String);
|
||||||
|
|
||||||
|
impl fmt::Display for ModifiedBase64String
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||||
|
{
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModifiedBase64String
|
||||||
|
{
|
||||||
|
fn from_base64_unchecked(string: &str) -> Self
|
||||||
|
{
|
||||||
|
Self(conv_str(&BASE64_CONV_TABLE, string).collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consume into a normal base64 string
|
||||||
|
pub fn into_base64(self) -> String
|
||||||
|
{
|
||||||
|
conv_char_iter(&BASE64_CONV_TABLE_REV, self.0.chars()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Try to convert a base64 string into a modified base64 string
|
||||||
|
pub fn try_from_base64<T: AsRef<str>>(base64: T) -> Result<Self, Base64Error<T>>
|
||||||
|
{
|
||||||
|
let string = base64.as_ref();
|
||||||
|
if BASE64_VALIDATE_REGEX.is_match(string) {
|
||||||
|
Ok(Self::from_base64_unchecked(string))
|
||||||
|
} else {
|
||||||
|
Err(Base64Error(base64))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// As a string slice
|
||||||
|
#[inline(always)] pub fn as_str(&self) -> &str
|
||||||
|
{
|
||||||
|
self.0.as_str()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encode from a slice
|
||||||
|
pub fn encode(slice: impl AsRef<[u8]>) -> Self
|
||||||
|
{
|
||||||
|
Self::from_base64_unchecked(base64::encode(slice.as_ref()).as_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consume into decoded bytes, write those bytes into the provided buffer
|
||||||
|
pub fn decode(self, output: &mut Vec<u8>)
|
||||||
|
{
|
||||||
|
base64::decode_config_buf(self.into_base64(), base64::STANDARD, output).expect("modified base64 string contained invalid formatted data")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consume into decoded bytes, return those bytes as a new `Vec<u8>`
|
||||||
|
pub fn decode_new(self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
base64::decode(self.into_base64()).expect("modified base64 string contained invalid formatted data")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for ModifiedBase64String
|
||||||
|
{
|
||||||
|
type Target = str;
|
||||||
|
#[inline] fn deref(&self) -> &Self::Target {
|
||||||
|
self.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<str> for ModifiedBase64String
|
||||||
|
{
|
||||||
|
#[inline] fn as_ref(&self) -> &str
|
||||||
|
{
|
||||||
|
self.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Convert this string with a specified char map. Returns a `char` yielding iterator.
|
||||||
|
#[inline] pub fn conv_str<'a, 'b>(table: &'b smallmap::Map<char, char>, string: &'a (impl AsRef<str> + ?Sized)) -> CharSubstituteIter<'b, std::str::Chars<'a>>
|
||||||
|
where 'b: 'a
|
||||||
|
{
|
||||||
|
conv_char_iter(table, string.as_ref().chars())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert this iterator of chars with this char swapping map
|
||||||
|
#[inline] pub fn conv_char_iter<T, I>(table: &smallmap::Map<char, char>, iter: I) -> CharSubstituteIter<I::IntoIter, T>
|
||||||
|
where I: IntoIterator<Item=T>,
|
||||||
|
T: From<char> + smallmap::Collapse,
|
||||||
|
char: Borrow<T>
|
||||||
|
{
|
||||||
|
iter.replace_chars(table)
|
||||||
|
}
|
@ -1,120 +0,0 @@
|
|||||||
//! Conversion formats
|
|
||||||
use super::*;
|
|
||||||
use std::{
|
|
||||||
ops::Deref,
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A string of modified base64, appropriate for URL paths etc.
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
|
|
||||||
pub struct ModifiedBase64String(String);
|
|
||||||
|
|
||||||
impl ModifiedBase64String
|
|
||||||
{
|
|
||||||
/// Get as a reference
|
|
||||||
#[inline(always)] pub fn as_str(&self) -> &ModifiedBase64
|
|
||||||
{
|
|
||||||
ModifiedBase64::new_unchecked(&self.0[..])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get as a mutable reference
|
|
||||||
#[inline(always)] fn as_mut_str(&mut self) -> &mut ModifiedBase64
|
|
||||||
{
|
|
||||||
ModifiedBase64::new_unchecked_mut(&mut self.0[..])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Consume into regular base64 string
|
|
||||||
pub fn into_base64(mut self) -> String
|
|
||||||
{
|
|
||||||
self.as_mut_str().unmodify();
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create from a refular base64 string
|
|
||||||
pub fn from_base64(mut string: String) -> Self
|
|
||||||
{
|
|
||||||
ModifiedBase64::modify(&mut string[..]);
|
|
||||||
Self(string)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsRef<ModifiedBase64> for ModifiedBase64String
|
|
||||||
{
|
|
||||||
#[inline] fn as_ref(&self) -> &ModifiedBase64
|
|
||||||
{
|
|
||||||
self.as_str()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl Deref for ModifiedBase64String
|
|
||||||
{
|
|
||||||
type Target = ModifiedBase64;
|
|
||||||
|
|
||||||
#[inline] fn deref(&self) -> &Self::Target {
|
|
||||||
self.as_str()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A string slice of modified base64, appropriate for URL paths etc.
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize)]
|
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct ModifiedBase64(str);
|
|
||||||
|
|
||||||
impl ModifiedBase64
|
|
||||||
{
|
|
||||||
#[inline(always)] fn new_unchecked<'a>(from: &'a str) -> &'a ModifiedBase64
|
|
||||||
{
|
|
||||||
unsafe {
|
|
||||||
std::mem::transmute(from)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)] fn new_unchecked_mut<'a>(from: &'a mut str) -> &'a mut ModifiedBase64
|
|
||||||
{
|
|
||||||
unsafe {
|
|
||||||
std::mem::transmute(from)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the underlying string slice
|
|
||||||
#[inline] pub fn as_str(&self) -> &str
|
|
||||||
{
|
|
||||||
unsafe {
|
|
||||||
std::mem::transmute::<&'_ Self, &'_ str>(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the underlying string slice as a mutable reference.
|
|
||||||
///
|
|
||||||
/// # This is not safe to expose in the API.
|
|
||||||
#[inline] fn as_mut_str(&mut self) -> &mut str
|
|
||||||
{
|
|
||||||
unsafe {
|
|
||||||
std::mem::transmute::<&'_ mut Self, &'_ mut str>(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unmodify(&mut self) -> &mut str
|
|
||||||
{
|
|
||||||
todo!();
|
|
||||||
|
|
||||||
self.as_mut_str()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Modify this base64 string into a mutable reference to self
|
|
||||||
pub fn modify(base64: &mut str) -> &mut Self
|
|
||||||
{
|
|
||||||
todo!();
|
|
||||||
|
|
||||||
Self::new_unchecked_mut(base64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsRef<ModifiedBase64> for ModifiedBase64
|
|
||||||
{
|
|
||||||
#[inline(always)] fn as_ref(&self) -> &ModifiedBase64
|
|
||||||
{
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in new issue