1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
use std::error::Error; pub trait CustomDecoder: std::fmt::Debug { fn decode(&self, encoding: &str, input: &[u8]) -> Result<Vec<u8>, InputError>; } type DecodeFn = Box<dyn Fn(&str, &[u8]) -> Result<Vec<u8>, InputError>>; pub struct RustFnBasedCustomDecoder { pub(crate) f: DecodeFn, } impl RustFnBasedCustomDecoder { pub fn new(f: DecodeFn) -> Self { Self { f } } } impl CustomDecoder for RustFnBasedCustomDecoder { fn decode(&self, encoding: &str, input: &[u8]) -> Result<Vec<u8>, InputError> { let f = &self.f; f(encoding, input) } } impl std::fmt::Debug for RustFnBasedCustomDecoder { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("RustFnBasedCustomDecoder").finish() } } #[derive(Debug)] pub enum InputError { UnableToRecognizeEncoding, UnsupportdEncoding(String), DecodingError(String), } impl std::fmt::Display for InputError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:?}", self) } } impl Error for InputError {} pub fn decode_input( input: &[u8], enc: &str, decoder: &Option<Box<dyn CustomDecoder>>, ) -> Result<Vec<u8>, InputError> { match &enc.to_uppercase()[..] { "UTF-8" | "ASCII-8BIT" | "BINARY" => Ok(input.to_vec()), enc => { if let Some(f) = &decoder { f.decode(enc, input) } else { Err(InputError::UnsupportdEncoding(enc.to_owned())) } } } }