@@ 87,10 87,10 @@ where
nanosecond += 10u32.pow(8 - p as u32) * (c as u8 - b'0') as u32;
}
chars.next();
+ p += 1;
}
_ => break,
}
- p += 1;
}
}
'Z' | 'z' => break,
@@ 113,14 113,11 @@ where
return Err(Rfc3339Error::OffsetOutOfRange(offset_minutes));
}
}
- _ => break,
+ '\t' => break,
+ _ => return Err(Rfc3339Error::ExpectedTab),
};
}
- if let Some(c) = chars.next() {
- return Err(Rfc3339Error::UnexpectedChar(c));
- }
-
Ok(Datetime {
year,
month,
@@ 172,11 169,11 @@ fn next_time_sep(chars: &mut impl Iterator<Item = char>) -> Result<(), Rfc3339Er
#[derive(Debug)]
pub enum Rfc3339Error {
UnexpectedEnd,
- UnexpectedChar(char),
ExpectedDigit,
ExpectedDash,
ExpectedColon,
ExpectedTimeSep,
+ ExpectedTab,
MonthOutOfRange(u8),
DayOutOfRange(u8),
HourOutOfRange(u8),
@@ 193,11 190,11 @@ impl Display for Rfc3339Error {
use Rfc3339Error::*;
match self {
UnexpectedEnd => write!(f, "unexpected end of string"),
- UnexpectedChar(c) => write!(f, "unexpected char `{}`", c),
ExpectedDigit => write!(f, "expected digit"),
ExpectedDash => write!(f, "expected dash"),
ExpectedColon => write!(f, "expected colon"),
ExpectedTimeSep => write!(f, "expected time separator"),
+ ExpectedTab => write!(f, "expected tab"),
MonthOutOfRange(m) => write!(f, "month out of range: {}", m),
DayOutOfRange(d) => write!(f, "day out of range: {}", d),
HourOutOfRange(h) => write!(f, "hour out of range: {}", h),
@@ 1,3 1,32 @@
mod dt;
+use std::{
+ error::Error,
+ io::{BufRead, BufReader, Read},
+};
+
pub use dt::Datetime;
+
+#[derive(Debug)]
+pub struct Twt {
+ pub datetime: Datetime,
+ pub body: String,
+}
+
+pub fn parse_twts<R: Read>(r: R) -> Result<Vec<Twt>, Box<dyn Error>> {
+ BufReader::new(r)
+ .lines()
+ .filter(|line| line.as_ref().map(|line| !line.is_empty()).unwrap_or(true))
+ .map(|line| parse_line(&line?))
+ .collect()
+}
+
+pub fn parse_line(line: &str) -> Result<Twt, Box<dyn Error>> {
+ let mut chars = line.chars();
+ let dt = dt::parse_datetime(&mut chars)?;
+
+ Ok(Twt {
+ datetime: dt,
+ body: chars.collect(),
+ })
+}
@@ 1,3 1,13 @@
+use twtxt::parse_twts;
+
+const TEST: &str = "
+2016-02-04T13:30:00+01:00\tYou can really go crazy here! ┐(゚∀゚)┌
+2016-02-03T23:05:00+01:00\t@<example http://example.org/twtxt.txt> welcome to twtxt!
+2016-02-01T11:00:00+01:00\tThis is just another example.
+2015-12-12T12:00:00+01:00\tFiat lux!
+";
+
fn main() {
- println!("Hello, world!");
+ let twt = parse_twts(TEST.as_bytes()).unwrap();
+ println!("{:?}", twt);
}