From 266b00a00a6a245464b6a4918f98ea55fcba286b Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Thu, 17 Sep 2020 08:09:23 +0300 Subject: feat: add an initial ChunkId implementation --- src/chunkid.rs | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 8 +----- 2 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 src/chunkid.rs (limited to 'src') diff --git a/src/chunkid.rs b/src/chunkid.rs new file mode 100644 index 0000000..f3af7cf --- /dev/null +++ b/src/chunkid.rs @@ -0,0 +1,83 @@ +use std::fmt; +use std::str::FromStr; +use uuid::Uuid; + +/// An identifier for a chunk. +/// +/// An identifier is chosen randomly in such a way that even in +/// extremely large numbers of identifiers the likelihood of duplicate +/// identifiers is so small it can be ignored. The current +/// implementation uses UUID4 and provides a 122-bit random number. +/// For a discussion on collision likelihood, see +/// . +/// +/// We also need to be able to re-create identifiers from stored +/// values. When an identifier is formatted as a string and parsed +/// back, the result is the same value. +/// +/// Because every identifier is meant to be different, there is no +/// default value, since default values should be identical. +#[derive(Debug, PartialEq)] +pub struct ChunkId { + id: String, +} + +#[allow(clippy::new_without_default)] +impl ChunkId { + /// Construct a new, random identifier. + pub fn new() -> Self { + ChunkId { + id: Uuid::new_v4().to_string(), + } + } +} + +impl fmt::Display for ChunkId { + /// Format an identifier for display. + /// + /// The output can be parsed to re-created an identical identifier. + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.id) + } +} + +impl FromStr for ChunkId { + type Err = (); + + /// Parse a string representation of an identifier. + fn from_str(s: &str) -> Result { + Ok(ChunkId { id: s.to_string() }) + } +} + +#[cfg(test)] +mod test { + use super::ChunkId; + + #[test] + fn displayable() { + let id = ChunkId::new(); + assert_ne!(format!("{}", id), "") + } + + #[test] + fn never_the_same() { + let id1 = ChunkId::new(); + let id2 = ChunkId::new(); + assert_ne!(id1, id2); + } + + #[test] + fn recreatable() { + let id_str = "xyzzy"; // it doesn't matter what the string representation is + let id: ChunkId = id_str.parse().unwrap(); + assert_eq!(format!("{}", id), id_str); + } + + #[test] + fn survives_round_trip() { + let id = ChunkId::new(); + let id_str = format!("{}", id); + assert_eq!(id, id_str.parse().unwrap()); + } +} diff --git a/src/lib.rs b/src/lib.rs index 31e1bb2..dd83e5b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1 @@ -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - assert_eq!(2 + 2, 4); - } -} +pub mod chunkid; -- cgit v1.2.1