summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHendrik Sollich <hendrik@hoodie.de>2017-04-21 19:33:47 +0200
committerMatthias Beyer <mail@beyermatthias.de>2019-04-26 22:43:12 +0200
commit98f8376d7767c9138d32ea272df52e8c725d5da4 (patch)
tree74a24a31a71a611431c63cdd562d6d3f5f7a2abd
parent286e5e54b1b6078e990984a83fa0e6bbb8ddbb1a (diff)
attempt at a parser
-rw-r--r--Cargo.toml2
-rw-r--r--examples/parse.rs10
-rw-r--r--src/components.rs7
-rw-r--r--src/lib.rs8
-rw-r--r--src/parse.rs237
-rw-r--r--src/properties.rs3
6 files changed, 264 insertions, 3 deletions
diff --git a/Cargo.toml b/Cargo.toml
index e98133f..38b7eb3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,12 +14,14 @@ readme = "README.md"
include = [
"Cargo.toml",
+ "README.md",
"src/*.rs",
]
[dependencies]
chrono = "0.4"
+nom = "2.1.0"
#error-chain = "*"
#vobject = {path="../hub/vobject"}
diff --git a/examples/parse.rs b/examples/parse.rs
new file mode 100644
index 0000000..2c17638
--- /dev/null
+++ b/examples/parse.rs
@@ -0,0 +1,10 @@
+extern crate chrono;
+extern crate icalendar;
+use chrono::*;
+use icalendar::*;
+
+fn main() {
+ let cal = include_str!("../invoicer.ics");
+ let parsed = parse::calendar(&cal);
+ println!("{:?}", parsed);
+}
diff --git a/src/components.rs b/src/components.rs
index b4efb91..a8440e1 100644
--- a/src/components.rs
+++ b/src/components.rs
@@ -22,6 +22,13 @@ struct InnerComponent{
multi_properties: Vec<Property>
}
+//impl<'a> Into<InnerComponent> for parse::Component<'a> {
+// fn into(self) -> InnerComponent {
+// unimplemented!()
+// }
+//}
+
+
impl InnerComponent {
/// End of builder pattern.
/// copies over everything
diff --git a/src/lib.rs b/src/lib.rs
index fe9ee3b..9cc58b0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -38,7 +38,7 @@
//! )
//! .done();
//!
-//! let todo = Todo::new().summary("Buy some milk").done();
+//! //let todo = Todo::new().summary("Buy some milk").done();
//!
//!
//! let mut calendar = Calendar::new();
@@ -57,6 +57,11 @@
missing_debug_implementations
)]
+extern crate chrono;
+extern crate uuid;
+#[macro_use]
+extern crate nom;
+
macro_rules! print_crlf {
() => (print!("\r\n"));
($fmt:expr) => (print!(concat!($fmt, "\r\n")));
@@ -79,6 +84,7 @@ macro_rules! write_crlf {
mod components;
mod properties;
mod calendar;
+pub mod parse;
//pub mod repeats;
pub use crate::properties::{Property, Parameter, Class, ValueType};
diff --git a/src/parse.rs b/src/parse.rs
new file mode 100644
index 0000000..832cdb6
--- /dev/null
+++ b/src/parse.rs
@@ -0,0 +1,237 @@
+#![allow(missing_docs, dead_code, unused_variables, unused_imports)]
+
+use std::str::from_utf8;
+use std::convert::Into;
+
+use nom;
+use nom::IResult::*;
+use nom::{alpha, alphanumeric, multispace, space, newline, line_ending};
+
+use crate::properties;
+
+////////// Parameters
+
+/// Zero-copy version of `properties::Parameter`
+#[derive(PartialEq, Debug, Clone)]
+struct Parameter<'a> {
+ key: &'a str,
+ val: &'a str
+}
+
+impl<'a> Into<properties::Parameter> for Parameter<'a> {
+ fn into(self) -> properties::Parameter {
+ properties::Parameter::new(self.key, self.val)
+ }
+}
+
+
+#[test]
+fn parse_parameter() {
+ assert_eq!(
+ parameter(b";KEY=VALUE"),
+ Done(&[][..], Parameter{key: "KEY", val: "VALUE"})
+ );
+ assert_eq!(
+ parameter(b"; KEY=VALUE"),
+ Done(&[][..], Parameter{key: "KEY", val: "VALUE"})
+ );
+ assert!( parameter(b";KEY").is_incomplete());
+ assert!( parameter(b";KEY=").is_incomplete());
+}
+
+named!(parameter(&[u8]) -> Parameter,
+ do_parse!(
+ tag!(";") >>
+ opt!(space) >>
+ key: map_res!(alpha, from_utf8) >>
+ tag!("=") >>
+ val: map_res!(alphanumeric, from_utf8) >>
+ (Parameter{key: key, val: val})
+ )
+ );
+
+// parameter list
+
+#[test]
+fn parse_parameter_list() {
+ assert_eq!(
+ parameter_list(b";KEY=VALUE"),
+ Done(&[][..], vec![Parameter{key: "KEY", val: "VALUE"}])
+ );
+
+ assert_eq!(
+ parameter_list(b";KEY=VALUE;DATE=TODAY"),
+ Done(&[][..], vec![
+ Parameter{key: "KEY", val: "VALUE"},
+ Parameter{key: "DATE", val:"TODAY"}
+ ])
+ );
+
+ assert_eq!(
+ parameter_list(b";KEY=VALUE;DATE=20170218"),
+ Done(&[][..], vec![
+ Parameter{key: "KEY", val: "VALUE"},
+ Parameter{key: "DATE", val:"20170218"}
+ ])
+ );
+}
+
+named!(parameter_list(&[u8]) -> Vec<Parameter>,
+ many0!(parameter)
+);
+
+
+
+////////// Properies
+
+/// Zero-copy version of `properties::Property`
+#[derive(PartialEq, Debug, Clone)]
+struct Property<'a> {
+ key: &'a str,
+ val: &'a str,
+ params: Vec<Parameter<'a>>
+}
+
+#[test]
+fn parse_propery() {
+ assert_eq!( property(b"KEY:VALUE\n"), Done(&[][..], Property{key: "KEY", val: "VALUE", params: vec![]} ));
+
+ assert_eq!(
+ property(b"KEY;foo=bar:VALUE\n"),
+ Done(&[][..], Property{key: "KEY", val: "VALUE", params: vec![
+ Parameter{key:"foo", val: "bar"}
+ ]})
+ );
+}
+
+named!(property(&[u8]) -> Property,
+ do_parse!(
+ opt!(multispace) >>
+ key: map_res!(alpha, from_utf8) >>
+ params: parameter_list >>
+ tag!(":") >>
+ val: map_res!(alphanumeric, from_utf8) >>
+ line_ending >>
+ (Property{key: key, val: val, params: params})
+ )
+);
+
+#[test]
+fn parse_propery_list() {
+
+ assert_eq!(
+ property_list(b"KEY;foo=bar:VALUE\n KEY;foo=bar; DATE=20170218:VALUE\n"),
+ Done(&[][..], vec![
+ Property{key: "KEY", val: "VALUE", params: vec![ Parameter{key:"foo", val: "bar"} ]},
+ Property{key: "KEY", val: "VALUE", params: vec![
+ Parameter{key:"foo", val: "bar"},
+ Parameter{key:"DATE", val: "20170218"},
+ ]}
+ ])
+ );
+ assert_eq!(
+ property_list(b"KEY;foo=bar:VALUE\nKEY;foo=bar;DATE=20170218:VALUE\n"),
+ Done(&[][..], vec![
+ Property{key: "KEY", val: "VALUE", params: vec![ Parameter{key:"foo", val: "bar"} ]},
+ Property{key: "KEY", val: "VALUE", params: vec![
+ Parameter{key:"foo", val: "bar"},
+ Parameter{key:"DATE", val: "20170218"},
+ ]}
+ ])
+ );
+ assert_eq!(
+ property_list(b""),
+ Done(&[][..], vec![ ]));
+}
+
+named!(property_list(&[u8]) -> Vec<Property>,
+ many0!(property)
+);
+
+////////// Components
+
+#[derive(PartialEq, Debug, Clone)]
+pub struct Component<'a> {
+ name: &'a str,
+ properties: Vec<Property<'a>>
+}
+
+#[test]
+#[ignore]
+fn parse_empty_component() {
+ assert_eq!(component(b"BEGIN:VEVENT\nEND:VEVENT\n"), Done(&[][..], Component{name: "VEVENT", properties: vec![]}));
+
+ assert_eq!(
+ component(b"BEGIN:VEVENT\n\nEND:VEVENT\n"),
+ Done(&[][..],
+ Component{name: "VEVENT", properties: vec![]}
+ ));
+ assert_eq!(
+ component(b"BEGIN:VEVENT\nEND:VEVENT\n"),
+ Done(&[][..],
+ Component{name: "VEVENT", properties: vec![]}
+ ));
+}
+
+#[test]
+fn parse_component() {
+ let sample_0 = b"BEGIN:VEVENT\nKEY;foo=bar:VALUE\nKEY;foo=bar;DATE=20170218:VALUE\nEND:VEVENT\n";
+ let sample_1 = b"BEGIN:VEVENT
+KEY;foo=bar:VALUE
+ KEY;foo=bar;DATE=20170218:VALUE
+END:VEVENT
+";
+
+ //assert_eq!(from_utf8(sample_0), from_utf8(sample_1));
+
+ let expectation = Component{name: "VEVENT", properties: vec![
+ Property{key: "KEY", val: "VALUE", params: vec![
+ Parameter{key:"foo", val: "bar"},
+ ]},
+ Property{key: "KEY", val: "VALUE", params: vec![
+ Parameter{key:"foo", val: "bar"},
+ Parameter{key:"DATE", val: "20170218"},
+ ]},
+ ]};
+
+ println!("expectation: {:#?}", expectation);
+ println!("vs reality : {:#?}", component(sample_1));
+
+ //assert_eq!(
+ // component(sample_1),
+ // Done(&[][..], expectation.clone()));
+
+ assert_eq!(
+ component(sample_1).unwrap().1,
+ expectation.clone());
+}
+
+named!{components(&[u8]) -> Vec<Component>,
+ many0!(component)
+}
+
+pub fn calendar(raw: &str) -> Vec<Component> {
+ let parsed = components(raw.as_bytes());
+ println!("{:?}", parsed);
+ if let Done(_, components) = parsed {
+ components
+ } else { vec![] }
+}
+
+named!(component(&[u8]) -> Component,
+ dbg!(
+ do_parse!(
+ tag!("BEGIN:") >> name: map_res!(alpha, from_utf8) >>
+ properties: many_till!(
+
+ do_parse!(p:property >> (p)),
+ tag!("END:")
+
+ ) >>
+ tag!(name) >>
+
+ (Component{name: name, properties: properties.0})
+ )
+ )
+ );
+
diff --git a/src/properties.rs b/src/properties.rs
index 0cd7efb..ae573de 100644
--- a/src/properties.rs
+++ b/src/properties.rs
@@ -10,7 +10,6 @@ pub struct Parameter {
}
impl Parameter {
-
/// Creates a new `Parameter`
pub fn new(key: &str, val: &str) -> Self {
Parameter {
@@ -21,7 +20,7 @@ impl Parameter {
}
//type EntryParameters = Vec<Parameter>;
-type EntryParameters = HashMap<String,Parameter>;
+pub type EntryParameters = HashMap<String,Parameter>;
#[derive(Debug)]
/// key-value pairs inside of `Component`s