aboutsummaryrefslogtreecommitdiff
path: root/src/codec.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/codec.rs')
-rw-r--r--src/codec.rs56
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>()
+}