Initial commit
This commit is contained in:
commit
683aa50d2a
6 changed files with 178 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
target/
|
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "b64"
|
||||||
|
version = "0.1.0"
|
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "b64"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
36
src/decode.rs
Normal file
36
src/decode.rs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
pub use {
|
||||||
|
super::B64Alphabet,
|
||||||
|
std::{
|
||||||
|
io::{self, Read, Write, ErrorKind},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
Io(io::Error),
|
||||||
|
IllegalChar(char),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for Error {
|
||||||
|
fn from(value: io::Error) -> Self {
|
||||||
|
Self::Io(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<char> for Error {
|
||||||
|
fn from(value: char) -> Self {
|
||||||
|
Self::IllegalChar(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Decoder<R: Read, W: Write> {
|
||||||
|
reader: R,
|
||||||
|
writer: W,
|
||||||
|
alphabet: B64Alphabet,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
}
|
||||||
|
|
81
src/encode.rs
Normal file
81
src/encode.rs
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
pub use {
|
||||||
|
super::B64Alphabet,
|
||||||
|
std::{
|
||||||
|
fmt::{self, Write},
|
||||||
|
io::{self, Read, ErrorKind},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
Io(io::Error),
|
||||||
|
Fmt(fmt::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Io(e) => write!(f, "{e}"),
|
||||||
|
Self::Fmt(e) => write!(f, "{e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for Error {
|
||||||
|
fn from(value: io::Error) -> Self {
|
||||||
|
Self::Io(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<fmt::Error> for Error {
|
||||||
|
fn from(value: fmt::Error) -> Self {
|
||||||
|
Self::Fmt(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for Error {
|
||||||
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
|
match self {
|
||||||
|
Self::Fmt(e) => Some(e),
|
||||||
|
Self::Io(e) => Some(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Encoder<R: Read, W: Write> {
|
||||||
|
reader: R,
|
||||||
|
writer: W,
|
||||||
|
alphabet: B64Alphabet,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: Read, W: Write> Encoder<R, W> {
|
||||||
|
pub fn new(reader: R, writer: W, alphabet: B64Alphabet) -> Self {
|
||||||
|
Self { reader, writer, alphabet }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encode(&mut self) -> Result<(), Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: Read> Encoder<R, String> {
|
||||||
|
pub fn output(self) -> String {
|
||||||
|
self.writer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn encode() {
|
||||||
|
let mut encoder = Encoder {
|
||||||
|
reader: "Hello, World!".as_bytes(),
|
||||||
|
writer: String::new(),
|
||||||
|
alphabet: B64Alphabet::default(),
|
||||||
|
};
|
||||||
|
encoder.encode().unwrap();
|
||||||
|
assert_eq!(encoder.output(), "SGVsbG8sIFdvcmxkIQ==");
|
||||||
|
}
|
||||||
|
}
|
45
src/lib.rs
Normal file
45
src/lib.rs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
mod encode;
|
||||||
|
mod decode;
|
||||||
|
|
||||||
|
pub use {
|
||||||
|
encode::{Error as B64EncoderError, Encoder as B64Encoder},
|
||||||
|
decode::{Error as B64DecoderError, Decoder as B64Decoder},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct B64Alphabet {
|
||||||
|
items: [char; 64],
|
||||||
|
pad: char,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static B64_RFC4648_ALPHABET: B64Alphabet = B64Alphabet {
|
||||||
|
items: [
|
||||||
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
|
||||||
|
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
|
||||||
|
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
|
||||||
|
't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
|
'8', '9', '+', '/',
|
||||||
|
],
|
||||||
|
pad: '=',
|
||||||
|
};
|
||||||
|
|
||||||
|
impl Default for B64Alphabet {
|
||||||
|
fn default() -> Self {
|
||||||
|
B64_RFC4648_ALPHABET
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl B64Alphabet {
|
||||||
|
pub fn idx(&self, c: char) -> Option<usize> {
|
||||||
|
for (idx, x) in self.items.iter().enumerate() {
|
||||||
|
if *x == c {
|
||||||
|
return Some(idx)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pad(&self) -> char {
|
||||||
|
self.pad
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue