decode message tag values

This commit is contained in:
jesopo 2023-03-21 23:09:57 +00:00
parent f262cbc463
commit a3b9eca823
2 changed files with 49 additions and 12 deletions

View File

@ -36,6 +36,33 @@ impl<'a> TakeWord<'a> for &'a [u8] {
} }
} }
fn tag_decode(value: &mut String) {
let mut i = 0;
let mut escaped = false;
while let Some(char) = value.chars().nth(i) {
if escaped {
escaped = false;
let replace = match char {
':' => ';',
's' => ' ',
'r' => '\r',
'n' => '\n',
_ => char,
};
value.replace_range(i - 1..i, &replace.to_string());
value.remove(i);
// the above replace loses one character from the string, so no `i += 1`
} else {
// backslash
if char == 0x5c as char {
escaped = true;
}
i += 1;
}
}
}
pub fn tokenise(mut line: &[u8]) -> Result<Line, Error> { pub fn tokenise(mut line: &[u8]) -> Result<Line, Error> {
let tags = match line.first() { let tags = match line.first() {
Some(b'@') => { Some(b'@') => {
@ -43,18 +70,20 @@ pub fn tokenise(mut line: &[u8]) -> Result<Line, Error> {
let mut tags_map = HashMap::new(); let mut tags_map = HashMap::new();
while !tags.is_empty() { while !tags.is_empty() {
let mut keyvalue = tags.take_word(b';'); let mut tag_key_value = tags.take_word(b';');
let tag = keyvalue.take_word(b'='); let tag_key = String::from_utf8(tag_key_value.take_word(b'=').to_vec())
tags_map.insert( .map_err(|_| Error::TagKeyDecode)?;
String::from_utf8(tag.to_vec()).map_err(|_| Error::TagKeyDecode)?, let tag_value = match tag_key_value {
match keyvalue { b"" | b"=" => None,
b"" | b"=" => None, _ => {
_ => Some( let mut tag_value = String::from_utf8(tag_key_value.to_vec())
String::from_utf8(keyvalue.to_vec()) .map_err(|_| Error::TagValueDecode)?;
.map_err(|_| Error::TagValueDecode)?, tag_decode(&mut tag_value);
), Some(tag_value)
}, }
); };
tags_map.insert(tag_key, tag_value);
} }
Some(tags_map) Some(tags_map)

View File

@ -19,3 +19,11 @@ fn basic() {
assert_eq!(tags["tag2"], None); assert_eq!(tags["tag2"], None);
assert_eq!(tags["tag3"], None); assert_eq!(tags["tag3"], None);
} }
#[test]
fn complex_tags() {
let line = tokenise(b"@tag1=\\:a COMMAND").unwrap();
let tags = line.tags.unwrap();
assert_eq!(tags["tag1"], Some(";a".to_string()));
}