summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHendrik Sollich <hoodie@users.noreply.github.com>2017-04-21 19:41:38 +0200
committerGitHub <noreply@github.com>2017-04-21 19:41:38 +0200
commite383e3a80120439c9cf5c1b93155dde820e698d4 (patch)
treeac67899f7bbfdb2410fbb05b8d0e3269000bbdd7
parent4feb36a8643d375305a3e87eda3697f12c1ee123 (diff)
parentb25578868f47b5d83a7b5d6dd76526daf8bf83fc (diff)
Merge pull request #1 from gnuish/master
Comply to RFC Section 3.1 (content lines)
-rw-r--r--src/calendar.rs14
-rw-r--r--src/components.rs12
-rw-r--r--src/lib.rs21
-rw-r--r--src/properties.rs60
4 files changed, 87 insertions, 20 deletions
diff --git a/src/calendar.rs b/src/calendar.rs
index b904999..a6c3660 100644
--- a/src/calendar.rs
+++ b/src/calendar.rs
@@ -73,17 +73,15 @@ impl Calendar {
/// Writes `Calendar` into a `Writer` using `std::fmt`.
fn fmt_write<W: fmt::Write>(&self, out: &mut W) -> Result<(), fmt::Error> {
- writeln!(out, "BEGIN:VCALENDAR")?;
- writeln!(out, "VERSION:2.0")?;
- writeln!(out, "PRODID:ICALENDAR-RS")?;
- writeln!(out, "CALSCALE:GREGORIAN")?;
- writeln!(out, "\n")?;
+ write_crlf!(out, "BEGIN:VCALENDAR")?;
+ write_crlf!(out, "VERSION:2.0")?;
+ write_crlf!(out, "PRODID:ICALENDAR-RS")?;
+ write_crlf!(out, "CALSCALE:GREGORIAN")?;
for component in &self.components {
component.fmt_write(out)?;
- write!(out, "\n")?;
}
- writeln!(out, "END:VCALENDAR")?;
+ write_crlf!(out, "END:VCALENDAR")?;
Ok(())
}
@@ -92,7 +90,7 @@ impl Calendar {
pub fn print(&self) -> Result<(), fmt::Error> {
let mut out = String::new();
try!(self.fmt_write(&mut out));
- println!("{}", out);
+ print_crlf!("{}", out);
Ok(())
}
}
diff --git a/src/components.rs b/src/components.rs
index 8e9b3fa..0b3ac15 100644
--- a/src/components.rs
+++ b/src/components.rs
@@ -126,10 +126,10 @@ pub trait Component {
/// Writes `Component` into a `Writer` using `std::fmt`.
fn fmt_write<W: fmt::Write>(&self, out: &mut W) -> Result<(), fmt::Error> {
- writeln!(out, "BEGIN:{}", Self::component_kind())?;
+ write_crlf!(out, "BEGIN:{}", Self::component_kind())?;
let now = UTC::now().format("%Y%m%dT%H%M%S");
- writeln!(out, "DTSTAMP:{}", now)?;
- writeln!(out, "UID:{}", Uuid::new_v4())?;
+ write_crlf!(out, "DTSTAMP:{}", now)?;
+ write_crlf!(out, "UID:{}", Uuid::new_v4())?;
for property in self.properties().values() {
property.fmt_write(out)?;
@@ -139,7 +139,7 @@ pub trait Component {
property.fmt_write(out)?;
}
- writeln!(out, "END:{}", Self::component_kind())?;
+ write_crlf!(out, "END:{}", Self::component_kind())?;
Ok(())
}
@@ -222,7 +222,7 @@ pub trait Component {
self
}
- /// Defindes the relative priority.
+ /// Defines the relative priority.
///
/// Ranges from 0 to 10, larger values will be truncated
fn priority(&mut self, priority:u32) -> &mut Self {
@@ -235,7 +235,7 @@ pub trait Component {
fn print(&self) -> Result<(), fmt::Error> {
let mut out = String::new();
try!(self.fmt_write(&mut out));
- println!("{}", out);
+ print_crlf!("{}", out);
Ok(())
}
diff --git a/src/lib.rs b/src/lib.rs
index ffcdb98..f124dda 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -15,6 +15,7 @@
//! # extern crate icalendar;
//! # use chrono::*;
//! # use icalendar::*;
+//! # fn main() {
//! let event = Event::new()
//! .summary("test event")
//! .description("here I have something really important to do")
@@ -44,7 +45,7 @@
//! calendar.add(event);
//! calendar.add(todo);
//! calendar.add(bday);
-//!
+//! # }
//! ```
#![warn(missing_docs,
@@ -60,6 +61,24 @@ extern crate chrono;
extern crate uuid;
//extern crate vobject;
+macro_rules! print_crlf {
+ () => (print!("\r\n"));
+ ($fmt:expr) => (print!(concat!($fmt, "\r\n")));
+ ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\r\n"), $($arg)*));
+}
+
+macro_rules! write_crlf {
+ ($dst:expr) => (
+ write!($dst, "\r\n")
+ );
+ ($dst:expr, $fmt:expr) => (
+ write!($dst, concat!($fmt, "\r\n"))
+ );
+ ($dst:expr, $fmt:expr, $($arg:tt)*) => (
+ write!($dst, concat!($fmt, "\r\n"), $($arg)*)
+ );
+}
+
//pub mod period;
mod components;
mod properties;
diff --git a/src/properties.rs b/src/properties.rs
index 8348cb5..3ab8a6a 100644
--- a/src/properties.rs
+++ b/src/properties.rs
@@ -1,4 +1,4 @@
-use std::fmt;
+use std::fmt::{self, Write};
use std::mem;
use std::collections::HashMap;
use std::convert::Into;
@@ -71,12 +71,16 @@ impl Property {
}
/// Writes this Property to `out`
- pub fn fmt_write<W: fmt::Write>(&self, out: &mut W) -> Result<(), fmt::Error> {
- try!(write!(out, "{}", self.key));
+ pub fn fmt_write<W: Write>(&self, out: &mut W) -> Result<(), fmt::Error> {
+ // A nice starting capacity for the majority of content lines
+ let mut line = String::with_capacity(150);
+
+ try!(write!(line, "{}", self.key));
for &Parameter { ref key, ref value } in self.parameters.values() {
- try!(write!(out, ";{}={}", key, value));
+ try!(write!(line, ";{}={}", key, value));
}
- try!(writeln!(out, ":{}", self.value));
+ try!(write!(line, ":{}", self.value));
+ try!(write_crlf!(out, "{}", fold_line(line)));
Ok(())
}
}
@@ -255,3 +259,49 @@ impl Into<Property> for TodoStatus {
//impl Into<Property> for Attendee {
//}
+
+// Fold a content line as described in RFC 5545, Section 3.1
+fn fold_line(line: String) -> String {
+ let limit = 75;
+ let len = line.len();
+ let mut ret = String::with_capacity(len + (len / limit * 3));
+ let mut bytes_remaining = len;
+
+ let mut pos = 0;
+ let mut next_pos = limit;
+ while bytes_remaining > limit {
+ while line.is_char_boundary(next_pos) == false {
+ next_pos -= 1;
+ }
+ ret.push_str(&line[pos..next_pos]);
+ ret.push_str("\r\n ");
+
+ bytes_remaining -= next_pos - pos;
+ pos = next_pos;
+ next_pos += limit;
+ }
+
+ ret.push_str(&line[len - bytes_remaining..]);
+ ret
+}
+
+#[cfg(test)]
+mod tests {
+ use std::string::String;
+ use super::*;
+
+ #[test]
+ fn fold_line_short() {
+ let line = String::from("This is a short line");
+ assert_eq!(line.clone(), fold_line(line));
+ }
+
+ #[test]
+ fn fold_line_folds_on_char_boundary() {
+ let line = String::from("Content lines shouldn't be folded in the middle \
+ of a UTF-8 character. 老虎.");
+ let expected = String::from("Content lines shouldn't be folded in the middle \
+ of a UTF-8 character. 老\r\n 虎.");
+ assert_eq!(expected, fold_line(line));
+ }
+}