diff options
Diffstat (limited to 'src/codec.rs')
-rw-r--r-- | src/codec.rs | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/src/codec.rs b/src/codec.rs new file mode 100644 index 0000000..3bba1c6 --- /dev/null +++ b/src/codec.rs @@ -0,0 +1,56 @@ +#![warn(clippy::pedantic)] + +use std::collections::HashSet; +use std::convert::TryFrom; + +use super::context::Context; +use super::error::Error; +use super::percent_encoded_character_decoder::PercentEncodedCharacterDecoder; + +pub fn decode_element<T>( + element: T, + allowed_characters: &'static HashSet<char>, + context: Context +) -> Result<Vec<u8>, Error> + where T: AsRef<str> +{ + let mut decoding_pec = false; + let mut pec_decoder = PercentEncodedCharacterDecoder::new(); + element + .as_ref() + .chars() + .filter_map(|c| { + if decoding_pec { + pec_decoder + .next(c) + .map_err(Into::into) + .transpose() + .map(|c| { + decoding_pec = false; + c + }) + } else if c == '%' { + decoding_pec = true; + None + } else if allowed_characters.contains(&c) { + Some(Ok(c as u8)) + } else { + Some(Err(Error::IllegalCharacter(context))) + } + }) + .collect() +} + +pub fn encode_element( + element: &[u8], + allowed_characters: &HashSet<char> +) -> String { + element.iter() + .map(|ci| { + match char::try_from(*ci) { + Ok(c) if allowed_characters.contains(&c) => c.to_string(), + _ => format!("%{:X}", ci), + } + }) + .collect::<String>() +} |