idle: Add the chrono dependency to actually parse dates.

This commit is contained in:
Emmanuel Gil Peyrot 2017-05-27 12:20:19 +01:00
parent dfdfd8cf71
commit 2c77c4f701
4 changed files with 73 additions and 6 deletions

View file

@ -18,3 +18,4 @@ sha-1 = "0.3.0"
sha2 = "0.5.0"
sha3 = "0.5.0"
blake2 = "0.5.0"
chrono = "0.3.1"

View file

@ -12,6 +12,7 @@ use std::string;
use base64;
use minidom;
use jid;
use chrono;
#[derive(Debug)]
pub enum Error {
@ -22,6 +23,7 @@ pub enum Error {
ParseIntError(num::ParseIntError),
ParseStringError(string::ParseError),
JidParseError(jid::JidParseError),
ChronoParseError(chrono::ParseError),
}
impl From<io::Error> for Error {
@ -59,3 +61,9 @@ impl From<jid::JidParseError> for Error {
Error::JidParseError(err)
}
}
impl From<chrono::ParseError> for Error {
fn from(err: chrono::ParseError) -> Error {
Error::ChronoParseError(err)
}
}

View file

@ -7,16 +7,15 @@
use std::convert::TryFrom;
use minidom::Element;
use chrono::prelude::*;
use error::Error;
use ns;
type Date = String;
#[derive(Debug, Clone)]
pub struct Idle {
pub since: Date,
pub since: DateTime<FixedOffset>,
}
impl TryFrom<Element> for Idle {
@ -29,7 +28,7 @@ impl TryFrom<Element> for Idle {
for _ in elem.children() {
return Err(Error::ParseError("Unknown child in idle element."));
}
let since = get_attr!(elem, "since", required);
let since = get_attr!(elem, "since", required, since, DateTime::parse_from_rfc3339(since)?);
Ok(Idle { since: since })
}
}
@ -38,7 +37,7 @@ impl Into<Element> for Idle {
fn into(self) -> Element {
Element::builder("idle")
.ns(ns::IDLE)
.attr("since", self.since.clone())
.attr("since", self.since.to_rfc3339())
.build()
}
}
@ -46,6 +45,7 @@ impl Into<Element> for Idle {
#[cfg(test)]
mod tests {
use super::*;
use std::error::Error as StdError;
#[test]
fn test_simple() {
@ -75,10 +75,67 @@ mod tests {
assert_eq!(message, "Required attribute 'since' missing.");
}
#[test]
fn test_invalid_date() {
// There is no thirteenth month.
let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-13-01T12:23:34Z'/>".parse().unwrap();
let error = Idle::try_from(elem).unwrap_err();
let message = match error {
Error::ChronoParseError(string) => string,
_ => panic!(),
};
assert_eq!(message.description(), "input is out of range");
// Timezone ≥24:00 arent allowed.
let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11:02+25:00'/>".parse().unwrap();
let error = Idle::try_from(elem).unwrap_err();
let message = match error {
Error::ChronoParseError(string) => string,
_ => panic!(),
};
assert_eq!(message.description(), "input is out of range");
// Timezone without the : separator arent allowed.
let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11:02+0100'/>".parse().unwrap();
let error = Idle::try_from(elem).unwrap_err();
let message = match error {
Error::ChronoParseError(string) => string,
_ => panic!(),
};
assert_eq!(message.description(), "input contains invalid characters");
// No seconds, error message could be improved.
let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11+01:00'/>".parse().unwrap();
let error = Idle::try_from(elem).unwrap_err();
let message = match error {
Error::ChronoParseError(string) => string,
_ => panic!(),
};
assert_eq!(message.description(), "input contains invalid characters");
// TODO: maybe well want to support this one, as per XEP-0082 §4.
let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='20170527T12:11:02+01:00'/>".parse().unwrap();
let error = Idle::try_from(elem).unwrap_err();
let message = match error {
Error::ChronoParseError(string) => string,
_ => panic!(),
};
assert_eq!(message.description(), "input contains invalid characters");
// No timezone.
let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-27T12:11:02'/>".parse().unwrap();
let error = Idle::try_from(elem).unwrap_err();
let message = match error {
Error::ChronoParseError(string) => string,
_ => panic!(),
};
assert_eq!(message.description(), "premature end of input");
}
#[test]
fn test_serialise() {
let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-21T20:19:55+01:00'/>".parse().unwrap();
let idle = Idle { since: Date::from("2017-05-21T20:19:55+01:00") };
let idle = Idle { since: DateTime::parse_from_rfc3339("2017-05-21T20:19:55+01:00").unwrap() };
let elem2 = idle.into();
assert_eq!(elem, elem2);
}

View file

@ -22,6 +22,7 @@ extern crate sha_1;
extern crate sha2;
extern crate sha3;
extern crate blake2;
extern crate chrono;
macro_rules! get_attr {
($elem:ident, $attr:tt, $type:tt) => (