diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..d8c2032 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[alias] +xtask = "run --manifest-path ./xtask/Cargo.toml --" diff --git a/README.md b/README.md index 6b7a46c..c6799a9 100644 --- a/README.md +++ b/README.md @@ -107,8 +107,15 @@ to update `last_modified_on`. Some clients use `last_modified_on` to decide whet update to an event or recurrence or not. To ensure the client will publish the event, set `last_modified_on` to a value in the future (a few days past the current date should be enough). -On Linux, you can get the current time in the right format in UTC with the command -`TZ=UTC date -u +"%Y-%m-%dT%H:%M:%S.%2NZ"`. +## How do I generate a UID for a new event? + +To generate a UID, run: + +```sh +cargo xtask generate-uid +``` + +Use the printed value as the `uid` for the event. ## How do I remove an event? If the event isn't recurring, then you don't need to remove it, it'll just stay in the calendar diff --git a/xtask/Cargo.lock b/xtask/Cargo.lock new file mode 100644 index 0000000..5b5f481 --- /dev/null +++ b/xtask/Cargo.lock @@ -0,0 +1,39 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "calendar-xtask" +version = "0.0.0" +dependencies = [ + "getrandom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.162" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml new file mode 100644 index 0000000..0e43fc4 --- /dev/null +++ b/xtask/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "calendar-xtask" +version = "0.0.0" +edition = "2021" +license = "MIT OR Apache-2.0" +publish = false + +[dependencies] +getrandom = { version = "0.2.15", default-features = false } diff --git a/xtask/rustfmt.toml b/xtask/rustfmt.toml new file mode 100644 index 0000000..2a35f02 --- /dev/null +++ b/xtask/rustfmt.toml @@ -0,0 +1 @@ +use_small_heuristics = "Max" diff --git a/xtask/src/main.rs b/xtask/src/main.rs new file mode 100644 index 0000000..9178ad3 --- /dev/null +++ b/xtask/src/main.rs @@ -0,0 +1,50 @@ +use std::process::ExitCode; + +/// Generate a UID for an RFC 5545 iCalendar event. +/// +/// The iCalender (IETF) RFC 5545 requires, in section 3.8.4.7, that +/// the `UID` be a: +/// +/// > ...persistent, globally unique identifier for the calendar +/// > component. +/// +/// In this context, "globally unique" means that the identifier must +/// not collide with any other identifier for any other calendar event +/// across all calendars, ever. +/// +/// To achieve this, we'll generate a hexidecimal encoding of 160 +/// randomly-generated bits. +fn print_uid() { + const UID_LEN: usize = 20; + let mut xs = [0u8; UID_LEN]; + getrandom::getrandom(&mut xs).unwrap(); + xs.iter().for_each(|x| print!("{x:02x}")); + println!(); +} + +fn print_usage() { + const USAGE: &str = "\ +Usage: cargo xtask [OPTIONS] COMMAND + +Commands: + generate-uid, uid Generate an event UID + +Options: + -h Print help +"; + println!("{USAGE}"); +} + +fn main() -> ExitCode { + let mut args = std::env::args(); + let _arg0 = args.next().unwrap(); + match args.next() { + Some(x) if x == "-h" => print_usage(), + Some(x) if x == "generate-uid" || x == "uid" => print_uid(), + _ => { + print_usage(); + return ExitCode::FAILURE; + } + } + ExitCode::SUCCESS +}