diff options
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 62 |
1 files changed, 61 insertions, 1 deletions
@@ -1,3 +1,63 @@ +//! A partial implementation of recurrence rules as defined in the iCalendar RFC. +//! +//! This map implementation allows reads and writes to execute entirely in parallel, with no +//! implicit synchronization overhead. Reads never take locks on their critical path, and neither +//! do writes assuming there is a single writer (multi-writer is possible using a `Mutex`), which +//! significantly improves performance under contention. +//! +//! The trade-off exposed by this module is one of eventual consistency: writes are not visible to +//! readers except following explicit synchronization. Specifically, readers only see the +//! operations that preceeded the last call to `WriteHandle::refresh` by a writer. This lets +//! writers decide how stale they are willing to let reads get. They can refresh the map after +//! every write to emulate a regular concurrent `HashMap`, or they can refresh only occasionally to +//! reduce the synchronization overhead at the cost of stale reads. +//! +//! For read-heavy workloads, the scheme used by this module is particularly useful. Writers can +//! afford to refresh after every write, which provides up-to-date reads, and readers remain fast +//! as they do not need to ever take locks. +//! +//! The map is multi-value, meaning that every key maps to a *collection* of values. This +//! introduces some memory cost by adding a layer of indirection through a `Vec` for each value, +//! but enables more advanced use. This choice was made as it would not be possible to emulate such +//! functionality on top of the semantics of this map (think about it -- what would the operational +//! log contain?). +//! +//! To faciliate more advanced use-cases, each of the two maps also carry some customizeable +//! meta-information. The writers may update this at will, and when a refresh happens, the current +//! meta will also be made visible to readers. This could be useful, for example, to indicate what +//! time the refresh happened. +//! +//! # Examples +//! +//! RRule +//! +//! ``` +//! extern crate rrule; +//! extern crate chrono; +//! +//! use chrono::prelude::*; +//! use rrule::build_rrule; +//! +//! // Parse a RRule string, return a RRule type +//! let mut rrule = build_rrule("DTSTART:20120201T093000Z\nRRULE:FREQ=WEEKLY;INTERVAL=5;UNTIL=20130130T230000Z;BYDAY=MO,FR"); +//! assert_eq!(rrule.all().len(), 21); +//! ``` +//! +//! +//! RRuleSet +//! +//! ``` +//! extern crate rrule; +//! extern crate chrono; +//! +//! use chrono::prelude::*; +//! use rrule::build_rruleset; +//! +//! // Parse a RRuleSet string, return a RRuleSet type +//! let mut rrule = build_rruleset("DTSTART:20120201T023000Z\nRRULE:FREQ=MONTHLY;COUNT=5\nRDATE:20120701T023000Z,20120702T023000Z\nEXRULE:FREQ=MONTHLY;COUNT=2\nEXDATE:20120601T023000Z"); +//! assert_eq!(rrule.all().len(), 6); +//! ``` + extern crate chrono; extern crate chrono_tz; extern crate once_cell; @@ -20,5 +80,5 @@ mod rruleset; pub use crate::rrule::RRule; pub use crate::rruleset::RRuleSet; -pub use crate::rrulestr::build_rule; +pub use crate::rrulestr::{build_rrule, build_rruleset}; pub use crate::options::{Frequenzy, ParsedOptions, PartialOptions};
\ No newline at end of file |