mirror of
https://gitlab.com/xmpp-rs/xmpp-rs.git
synced 2024-07-12 22:21:53 +00:00
idle: Add the chrono dependency to actually parse dates.
This commit is contained in:
parent
dfdfd8cf71
commit
2c77c4f701
4 changed files with 73 additions and 6 deletions
|
@ -18,3 +18,4 @@ sha-1 = "0.3.0"
|
||||||
sha2 = "0.5.0"
|
sha2 = "0.5.0"
|
||||||
sha3 = "0.5.0"
|
sha3 = "0.5.0"
|
||||||
blake2 = "0.5.0"
|
blake2 = "0.5.0"
|
||||||
|
chrono = "0.3.1"
|
||||||
|
|
|
@ -12,6 +12,7 @@ use std::string;
|
||||||
use base64;
|
use base64;
|
||||||
use minidom;
|
use minidom;
|
||||||
use jid;
|
use jid;
|
||||||
|
use chrono;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
@ -22,6 +23,7 @@ pub enum Error {
|
||||||
ParseIntError(num::ParseIntError),
|
ParseIntError(num::ParseIntError),
|
||||||
ParseStringError(string::ParseError),
|
ParseStringError(string::ParseError),
|
||||||
JidParseError(jid::JidParseError),
|
JidParseError(jid::JidParseError),
|
||||||
|
ChronoParseError(chrono::ParseError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<io::Error> for Error {
|
impl From<io::Error> for Error {
|
||||||
|
@ -59,3 +61,9 @@ impl From<jid::JidParseError> for Error {
|
||||||
Error::JidParseError(err)
|
Error::JidParseError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<chrono::ParseError> for Error {
|
||||||
|
fn from(err: chrono::ParseError) -> Error {
|
||||||
|
Error::ChronoParseError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
69
src/idle.rs
69
src/idle.rs
|
@ -7,16 +7,15 @@
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use minidom::Element;
|
use minidom::Element;
|
||||||
|
use chrono::prelude::*;
|
||||||
|
|
||||||
use error::Error;
|
use error::Error;
|
||||||
|
|
||||||
use ns;
|
use ns;
|
||||||
|
|
||||||
type Date = String;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Idle {
|
pub struct Idle {
|
||||||
pub since: Date,
|
pub since: DateTime<FixedOffset>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<Element> for Idle {
|
impl TryFrom<Element> for Idle {
|
||||||
|
@ -29,7 +28,7 @@ impl TryFrom<Element> for Idle {
|
||||||
for _ in elem.children() {
|
for _ in elem.children() {
|
||||||
return Err(Error::ParseError("Unknown child in idle element."));
|
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 })
|
Ok(Idle { since: since })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +37,7 @@ impl Into<Element> for Idle {
|
||||||
fn into(self) -> Element {
|
fn into(self) -> Element {
|
||||||
Element::builder("idle")
|
Element::builder("idle")
|
||||||
.ns(ns::IDLE)
|
.ns(ns::IDLE)
|
||||||
.attr("since", self.since.clone())
|
.attr("since", self.since.to_rfc3339())
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +45,7 @@ impl Into<Element> for Idle {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::error::Error as StdError;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_simple() {
|
fn test_simple() {
|
||||||
|
@ -75,10 +75,67 @@ mod tests {
|
||||||
assert_eq!(message, "Required attribute 'since' missing.");
|
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 aren’t 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 aren’t 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 we’ll 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]
|
#[test]
|
||||||
fn test_serialise() {
|
fn test_serialise() {
|
||||||
let elem: Element = "<idle xmlns='urn:xmpp:idle:1' since='2017-05-21T20:19:55+01:00'/>".parse().unwrap();
|
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();
|
let elem2 = idle.into();
|
||||||
assert_eq!(elem, elem2);
|
assert_eq!(elem, elem2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ extern crate sha_1;
|
||||||
extern crate sha2;
|
extern crate sha2;
|
||||||
extern crate sha3;
|
extern crate sha3;
|
||||||
extern crate blake2;
|
extern crate blake2;
|
||||||
|
extern crate chrono;
|
||||||
|
|
||||||
macro_rules! get_attr {
|
macro_rules! get_attr {
|
||||||
($elem:ident, $attr:tt, $type:tt) => (
|
($elem:ident, $attr:tt, $type:tt) => (
|
||||||
|
|
Loading…
Reference in a new issue