Skip to content

Commit

Permalink
Implement std::hash::Hash for Ksuid structs. (#7)
Browse files Browse the repository at this point in the history
Co-authored-by: Aurelien Somename <aurelien.somename@gmail.com>
  • Loading branch information
aurelien-clu and Aurelien Somename authored Jan 4, 2024
1 parent 082ba13 commit a3fc564
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
//! All rights reserved to the [Svix webhooks service](https://www.svix.com).
use core::fmt;
use std::hash::{Hash, Hasher};
use std::{error, str::FromStr};

use byteorder::{BigEndian, ByteOrder};
Expand Down Expand Up @@ -355,6 +356,12 @@ impl fmt::Display for Ksuid {
}
}

impl Hash for Ksuid {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}

/// K-Sortable Unique ID (Ms accuracy)
///
/// This one has Ms accuracy compared to the normal one that has second accuracy
Expand Down Expand Up @@ -493,6 +500,12 @@ impl fmt::Display for KsuidMs {
}
}

impl Hash for KsuidMs {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}

#[cfg(feature = "serde")]
impl Serialize for Ksuid {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
Expand Down
54 changes: 54 additions & 0 deletions tests/integration.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use serde::Deserialize;
#[cfg(feature = "serde")]
use serde::Serialize;
use std::collections::HashSet;
use std::hash::{Hash, Hasher};
use std::{
fs::File,
io::{self, BufRead},
Expand Down Expand Up @@ -103,6 +105,58 @@ fn test_ordering() -> Result<(), String> {
Ok(())
}

#[test]
fn test_hash() {
// given
let mut set = HashSet::new();
let ksuid1 = Ksuid::new(None, None);
let ksuid2 = Ksuid::new(None, None);
// when
set.insert(ksuid1.clone());

Check warning on line 115 in tests/integration.rs

View workflow job for this annotation

GitHub Actions / check

using `clone` on type `Ksuid` which implements the `Copy` trait
set.insert(ksuid2.clone());

Check warning on line 116 in tests/integration.rs

View workflow job for this annotation

GitHub Actions / check

using `clone` on type `Ksuid` which implements the `Copy` trait
// then
assert_eq!(set.len(), 2);
assert!(set.contains(&ksuid1));
assert!(set.contains(&ksuid2));
}

#[test]
fn test_hash_ms() {
// given
let mut set = HashSet::new();
let ksuidms1 = KsuidMs::new(None, None);
let ksuidms2 = KsuidMs::new(None, None);
// when
set.insert(ksuidms1.clone());

Check warning on line 130 in tests/integration.rs

View workflow job for this annotation

GitHub Actions / check

using `clone` on type `KsuidMs` which implements the `Copy` trait
set.insert(ksuidms2.clone());

Check warning on line 131 in tests/integration.rs

View workflow job for this annotation

GitHub Actions / check

using `clone` on type `KsuidMs` which implements the `Copy` trait
// then
assert_eq!(set.len(), 2);
assert!(set.contains(&ksuidms1));
assert!(set.contains(&ksuidms2));
}

#[test]
fn test_hash_are_deterministic() {
let cases: Vec<(&str, u64)> = vec![
("000000pryYUMiBILyxOCoroLz6w", 7055508431330265589),
("02GY99XXwBHbeBundUPJoqYpvet", 3000553476947541532),
("04X6IIDacKaayM4WWom0flpf3mY", 15766199744355542564),
];

for case in cases {
// given
let id_as_str = case.0;
let expected_hash = case.1;
// when
let ksuid = Ksuid::from_str(id_as_str).expect("valid id");
let mut hasher = std::collections::hash_map::DefaultHasher::new();
ksuid.hash(&mut hasher);
let hashed = hasher.finish();
// then
assert_eq!(hashed, expected_hash);
}
}

#[cfg(feature = "serde")]
#[derive(Serialize, Deserialize)]
struct TestKsuid {
Expand Down

0 comments on commit a3fc564

Please sign in to comment.