From c329bc5c81877e58b3d7745a88b690a9ab657bba Mon Sep 17 00:00:00 2001 From: Astro Date: Wed, 21 Dec 2022 21:08:47 +0100 Subject: [PATCH] libticker: parse quoted props --- libticker/src/ics/mod.rs | 2 +- libticker/src/ics/tokenizer.rs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/libticker/src/ics/mod.rs b/libticker/src/ics/mod.rs index df66d1f..808f6a8 100644 --- a/libticker/src/ics/mod.rs +++ b/libticker/src/ics/mod.rs @@ -104,7 +104,7 @@ impl FromStr for Timestamp { NaiveDate::parse_from_str(s, "%Y%m%d") .map(Timestamp::Date) ) - .map_err(|e| format!("Cannot parse date: {:?}", e)) + .map_err(|e| format!("Cannot parse date {:?}: {:?}", s, e)) } } diff --git a/libticker/src/ics/tokenizer.rs b/libticker/src/ics/tokenizer.rs index ea22baf..afd49fb 100644 --- a/libticker/src/ics/tokenizer.rs +++ b/libticker/src/ics/tokenizer.rs @@ -11,6 +11,8 @@ enum LineState { Key, PropName, PropValue, + PropValueQuoted, + PropValueQuotedEnd, Value, ValueEscape, } @@ -111,6 +113,9 @@ impl Tokenizer { } self.line_state = LineState::Value; } + (LineState::PropValue, '"') if self.buffer.is_empty() => { + self.line_state = LineState::PropValueQuoted; + } (LineState::PropValue, ':') => { let buffer = replace(&mut self.buffer, vec![]); match String::from_utf8(buffer) { @@ -121,6 +126,20 @@ impl Tokenizer { } self.line_state = LineState::Value; } + (LineState::PropValueQuoted, '"') => { + let buffer = replace(&mut self.buffer, vec![]); + match String::from_utf8(buffer) { + Ok(s) => + f(Token::PropValue(s)), + Err(e) => + println!("UTF8 error: {:?}", e), + } + self.line_state = LineState::PropValueQuotedEnd; + } + (LineState::PropValueQuotedEnd, ':') => { + self.line_state = LineState::Value; + } + (LineState::PropValueQuotedEnd, _) => {} (LineState::Value, '\n') => { let buffer = replace(&mut self.buffer, vec![]); match String::from_utf8(buffer) { @@ -202,4 +221,19 @@ END:VEVENT Token::Key("SUMMARY".to_owned()), Token::Value("HelloWorld".to_owned()), ]); } + + #[test] + fn tokenize_quoted_prop() { + let mut t = Tokenizer::new(); + let mut tokens = vec![]; + t.feed(b"DTSTART;TZID=\"+02:00\":20221230T220000 + +", |token| tokens.push(token)); + assert_eq!(tokens, vec![ + Token::Key("DTSTART".to_owned()), + Token::PropName("TZID".to_owned()), + Token::PropValue("+02:00".to_owned()), + Token::Value("20221230T220000".to_owned()), + ]); + } }