summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2020-09-17 08:09:23 +0300
committerLars Wirzenius <liw@liw.fi>2020-09-17 08:09:23 +0300
commit266b00a00a6a245464b6a4918f98ea55fcba286b (patch)
tree68683d2fcd01d6bf11cd16783248ce08fae8b8e6 /src
parent80e9c8f81da572278dd5f5218e6db23cd2900d0e (diff)
downloadobnam2-266b00a00a6a245464b6a4918f98ea55fcba286b.tar.gz
feat: add an initial ChunkId implementation
Diffstat (limited to 'src')
-rw-r--r--src/chunkid.rs83
-rw-r--r--src/lib.rs8
2 files changed, 84 insertions, 7 deletions
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
+/// <https://en.wikipedia.org/wiki/Universally_unique_identifier#Collisions>.
+///
+/// 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<Self, Self::Err> {
+ 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;