parent
d9fc959738
commit
745a3a61d5
@ -0,0 +1,27 @@
|
||||
|
||||
pub trait JoinStrsExt: Sized
|
||||
{
|
||||
/// Join an iterator of `str` with a seperator
|
||||
fn join(self, with: &str) -> String;
|
||||
}
|
||||
|
||||
impl<T,I> JoinStrsExt for I
|
||||
where I: Iterator<Item=T>,
|
||||
T: AsRef<str>
|
||||
{
|
||||
fn join(self, with: &str) -> String
|
||||
{
|
||||
let mut output = String::new();
|
||||
let mut first=true;
|
||||
for string in self
|
||||
{
|
||||
if !first {
|
||||
output.push_str(with);
|
||||
}
|
||||
let string = string.as_ref();
|
||||
output.push_str(string);
|
||||
first=false;
|
||||
}
|
||||
output
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Loli
|
||||
{
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
use super::*;
|
||||
use std::{
|
||||
str,
|
||||
io::{
|
||||
self,
|
||||
Write,
|
||||
},
|
||||
};
|
||||
|
||||
const HEADER_BASE64_JPEG: &'static str = "/9j/";
|
||||
const HEADER_BASE64_PNG: &'static str = "iVBO";
|
||||
const HEADER_BASE64_GIF: &'static str = "R0lG";
|
||||
|
||||
/// An image type header
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
pub enum ImageType
|
||||
{
|
||||
Png,
|
||||
Jpeg,
|
||||
Gif,
|
||||
}
|
||||
|
||||
impl Default for ImageType
|
||||
{
|
||||
fn default() -> Self
|
||||
{
|
||||
Self::Jpeg
|
||||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for ImageType
|
||||
{
|
||||
type Err = error::Error;
|
||||
|
||||
/// Determine image type from base64
|
||||
fn from_str(from: &str) -> Result<Self, Self::Err>
|
||||
{
|
||||
if from.len() > 4 {
|
||||
Ok(match &from[..4] {
|
||||
HEADER_BASE64_GIF => Self::Gif,
|
||||
HEADER_BASE64_PNG => Self::Png,
|
||||
HEADER_BASE64_JPEG => Self::Jpeg,
|
||||
_ => return Err(error::Error::UnknownFormat),
|
||||
})
|
||||
} else {
|
||||
Err(error::Error::InvalidFormat)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate the required data size from base64 input size
|
||||
pub const fn data_size(base64: usize) -> usize
|
||||
{
|
||||
((4 * base64 / 3) + 3) & !3
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
use super::*;
|
||||
use std::{
|
||||
error,
|
||||
fmt,
|
||||
io,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error
|
||||
{
|
||||
/// Image format could not be determined.
|
||||
UnknownFormat,
|
||||
/// Image is not valid
|
||||
InvalidFormat,
|
||||
/// Image decode failedb
|
||||
DecodeError,
|
||||
|
||||
// Internals
|
||||
/// IO error
|
||||
IO(io::Error),
|
||||
/// Failed to format text
|
||||
Formatter(fmt::Error),
|
||||
/// Something bad
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl error::Error for Error
|
||||
{
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)>
|
||||
{
|
||||
Some(match &self {
|
||||
Self::IO(io) => io,
|
||||
Self::Formatter(fmt) => fmt,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||
{
|
||||
write!(f, "loli module: ")?;
|
||||
match self {
|
||||
Self::UnknownFormat => write!(f, "could not determine image format"),
|
||||
Self::InvalidFormat => write!(f, "image is not valid"),
|
||||
Self::DecodeError => write!(f, "image decode failed"),
|
||||
Self::IO(io) => write!(f, "io: {}", io),
|
||||
Self::Formatter(fmt) => write!(f, "formatting: {}", fmt),
|
||||
_ => write!(f, "unknown error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error
|
||||
{
|
||||
fn from(er: io::Error) -> Self
|
||||
{
|
||||
Self::IO(er)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<fmt::Error> for Error
|
||||
{
|
||||
fn from(er: fmt::Error) -> Self
|
||||
{
|
||||
Self::Formatter(er)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<base64::DecodeError> for Error
|
||||
{
|
||||
fn from(_er: base64::DecodeError) -> Self
|
||||
{
|
||||
Self::DecodeError
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
|
||||
pub mod error;
|
||||
pub mod encoding;
|
||||
|
||||
/// Attempt to decode an image
|
||||
pub fn decode<S, W>(input: S, mut output: W) -> Result<usize, error::Error>
|
||||
where S: AsRef<[u8]>,
|
||||
W: AsMut<[u8]>
|
||||
{
|
||||
let input_bytes = input.as_ref();
|
||||
let output_bytes = output.as_mut();
|
||||
|
||||
Ok(base64::decode_config_slice(input_bytes, base64::STANDARD, output_bytes)?)
|
||||
}
|
||||
|
||||
/// Calculate the size for a base64 inpue
|
||||
pub fn calc_size<T>(input: T) -> usize
|
||||
where T: AsRef<[u8]>
|
||||
{
|
||||
encoding::data_size(input.as_ref().len())
|
||||
}
|
||||
|
||||
/// Try to get the image format from a `str` slice.
|
||||
pub fn attempt_get_format<T>(input: T) -> Result<encoding::ImageType, error::Error>
|
||||
where T: AsRef<str>
|
||||
{
|
||||
input.as_ref().parse()
|
||||
}
|
Loading…
Reference in new issue