Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
[package]
authors = ["Dylan MacKenzie <ecstaticmorse@gmail.com>"]
name = "ksuid"
version = "0.1.0"
version = "0.3.0"
description = "A library for efficiently generating, parsing and serializing Segment.io KSUIDs"
repository = "https://github.com/ecstatic-morse/ksuid.git"
readme = "README.md"
keywords = ["uuid", "ksuid", "guid"]
license = "MIT"
edition = "2021"

[dependencies]
byteorder = "1.0.0"
rand = "0.3.15"
resize-slice = "0.1.2"
time = "0.1.37"
byteorder = "1.5.0"
rand = "0.8.5"
resize-slice = "0.1.3"
time = { version = "0.3.37", features = ["macros"] }

[dev-dependencies]
num = "0.1.39"
num = "0.4.3"

[features]
# Set on nightly to enable benchmarks
Expand Down
14 changes: 7 additions & 7 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
[package]
authors = ["Dylan MacKenzie <ecstaticmorse.gmail.com>"]
name = "ksuid-cli"
version = "0.1.0"
version = "0.1.1"
description = "A command line interface for generating, parsing, and serializing Segment.io KSUIDs"
repository = "https://github.com/ecstatic-morse/ksuid.git"
readme = "../README.md"
keywords = ["uuid", "ksuid", "guid"]
license = "MIT"
edition = "2021"

[dependencies]
docopt = "0.8.0"
ksuid = { version="0.1.0", path = ".." }
rand = "0.3.15"
serde = "1.0.8"
serde_derive = "1.0.8"
time = "0.1.37"
docopt = "1.1.1"
ksuid = { version="0.3.0", path = ".." }
rand = "0.8.5"
serde = "1.0.215"
serde_derive = "1.0.215"
9 changes: 2 additions & 7 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@ extern crate serde_derive;

extern crate docopt;
extern crate ksuid;
extern crate time;
extern crate rand;

use std::io::{self, Write};
use std::process::exit;

use ksuid::Ksuid;
use rand::Rng;

const USAGE: &str = "
ksuid
Expand Down Expand Up @@ -45,11 +43,8 @@ fn main() {
fn generate(args: Args) {
let out = io::stdout();
let mut locked = out.lock();

let mut rng = rand::thread_rng();

for _ in 0..args.flag_count {
writeln!(&mut locked, "{}", rng.gen::<Ksuid>().to_base62()).unwrap();
writeln!(&mut locked, "{}", Ksuid::generate().to_base62()).unwrap();
}
}

Expand Down Expand Up @@ -85,7 +80,7 @@ COMPONENTS:
" ,
ksuid.to_base62(),
ksuid.to_hex(),
time::at(ksuid.time()).rfc822(),
ksuid.time(),
ksuid.timestamp(),
ksuid.to_hex().chars().skip(8).collect::<String>());
}
Expand Down
45 changes: 24 additions & 21 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@ extern crate time;
mod base62;

use std::io;
use std::ascii::AsciiExt;

use byteorder::{ByteOrder, BigEndian};
use time::{Timespec, Duration};
use rand::{Rng, Rand};
use time::{OffsetDateTime, Duration};
use rand::Rng;
use rand::RngCore;

/// The KSUID epoch, 1.4 billion seconds after the UNIX epoch.
///
/// ```
/// # extern crate ksuid;
/// # extern crate time;
/// assert_eq!(ksuid::EPOCH, time::strptime("2014-5-13 16:53:20", "%Y-%m-%d %T").unwrap().to_timespec());
/// use time::macros::datetime;
/// assert_eq!(ksuid::get_epoch(), datetime!(2014-5-13 16:53:20).assume_utc());
/// ```
pub const EPOCH: Timespec = Timespec {sec: 1_400_000_000, nsec: 0};

const LEN: usize = 20;
const EMPTY: [u8; LEN] = [0; LEN];
Expand All @@ -44,6 +44,12 @@ const HEX_LEN: usize = 40;
const HEX_DIGITS: &[u8] = b"0123456789ABCDEF";
const MAX_BASE62_KSUID: &[u8] = b"aWgEPTl1tmebfsQzFP4bxwgy80V";

/// Returns an OffsetDateTime representing Ksuid's start time.
/// The crate "time" >= 2 returns a Result, making it incompatible with const.
pub fn get_epoch() -> OffsetDateTime {
OffsetDateTime::from_unix_timestamp(1_400_000_000).unwrap()
}

/// Get the numeric value corresponding to the given ASCII hex digit.
fn hex_digit(c: u8) -> io::Result<u8> {
HEX_DIGITS.iter()
Expand Down Expand Up @@ -82,19 +88,16 @@ impl Ksuid {
/// Create a new identifier with a current timestamp and the given payload.
pub fn with_payload(payload: [u8; 16]) -> Self {
// TODO: check for overflow in timestamp
let elapsed = time::get_time() - EPOCH;
let ts = elapsed.num_seconds() as u32;
let elapsed = OffsetDateTime::now_utc() - get_epoch();
let ts = elapsed.whole_seconds() as u32;
Self::new(ts, payload)
}

/// Create a new identifier with a current timestamp and randomly generated payload.
///
/// This function uses the thread local random number generator. this means that if you're
/// calling `generate()` in a loop, caching the generator can increase performance. See the
/// documentation of [`rand::random()`](https://doc.rust-lang.org/rand/rand/fn.random.html) for
/// an example.
pub fn generate() -> Self {
rand::random()
let mut data = [0u8; 16];
rand::thread_rng().fill_bytes(&mut data);
Self::with_payload(data)
}

/// Parse an identifier from its Base62-encoded string representation.
Expand Down Expand Up @@ -206,14 +209,14 @@ impl Ksuid {
}

/// The number of seconds after the UNIX epoch when this identifier was created.
pub fn time(&self) -> Timespec {
EPOCH + Duration::seconds(self.timestamp().into())
pub fn time(&self) -> OffsetDateTime {
get_epoch() + Duration::seconds(self.timestamp().into())
}

/// Set the timestamp of the identifier to the given time.
pub fn set_time(&mut self, time: Timespec) {
let dur = time - EPOCH;
self.set_timestamp(dur.num_seconds() as u32);
pub fn set_time(&mut self, time: OffsetDateTime) {
let dur = time - get_epoch();
self.set_timestamp(dur.whole_seconds() as u32);
}

/// The 16-byte random payload.
Expand All @@ -227,7 +230,8 @@ impl Ksuid {
}
}

impl Rand for Ksuid {
impl Ksuid {
#[allow(dead_code)]
fn rand<R: Rng>(rng: &mut R) -> Self {
Self::with_payload(rng.gen())
}
Expand Down Expand Up @@ -283,9 +287,8 @@ mod tests {

#[bench]
fn bench_gen_lock_rng(b: &mut test::Bencher) {
let mut rng = rand::thread_rng();
b.iter(|| {
rng.gen::<Ksuid>()
Ksuid::generate()
})
}
}