From 7851fdae1e6569711207c1ab1b03c88ba6db5cb3 Mon Sep 17 00:00:00 2001 From: Philippe Loctaux Date: Sun, 5 Mar 2023 23:27:34 +0100 Subject: [PATCH] id: added id create for handling ID needs --- crates/id/Cargo.toml | 9 +++++++ crates/id/src/lib.rs | 12 +++++++++ crates/id/src/user.rs | 63 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 crates/id/Cargo.toml create mode 100644 crates/id/src/lib.rs create mode 100644 crates/id/src/user.rs diff --git a/crates/id/Cargo.toml b/crates/id/Cargo.toml new file mode 100644 index 0000000..8975ca9 --- /dev/null +++ b/crates/id/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "id" +version = "0.0.0" +edition = "2021" + +[dependencies] +thiserror = { workspace = true } +nanoid = "0.4.0" +nanoid-dictionary = "0.4.3" diff --git a/crates/id/src/lib.rs b/crates/id/src/lib.rs new file mode 100644 index 0000000..46e215d --- /dev/null +++ b/crates/id/src/lib.rs @@ -0,0 +1,12 @@ +mod user; + +// error +#[derive(thiserror::Error)] +// the rest +#[derive(Debug)] +pub enum Error { + #[error("Invalid {0} ID")] + Invalid(&'static str), +} + +pub use user::UserID; diff --git a/crates/id/src/user.rs b/crates/id/src/user.rs new file mode 100644 index 0000000..5a3c69f --- /dev/null +++ b/crates/id/src/user.rs @@ -0,0 +1,63 @@ +use super::Error; +use nanoid::nanoid; +use nanoid_dictionary::NOLOOKALIKES; +use std::fmt::{Display, Formatter}; +use std::str::FromStr; + +const LENGTH: usize = 15; + +#[derive(Debug, Clone, PartialEq)] +pub struct UserID(pub String); + +impl Display for UserID { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl Default for UserID { + fn default() -> Self { + Self(nanoid!(LENGTH, NOLOOKALIKES)) + } +} + +impl FromStr for UserID { + type Err = Error; + + fn from_str(s: &str) -> Result { + if s.len() == LENGTH && s.chars().all(|c| NOLOOKALIKES.contains(&c)) { + Ok(Self(s.to_string())) + } else { + Err(Error::Invalid("User")) + } + } +} + +#[cfg(test)] +mod tests { + use super::{UserID, LENGTH}; + use std::str::FromStr; + + #[test] + fn invalid_length() { + assert!(UserID::from_str("test").is_err()); + } + + #[test] + fn invalid_characters() { + let value = "11lI0Oouv5Ss2ZZ"; + assert_eq!(value.len(), LENGTH); + + assert!(UserID::from_str(value).is_err()); + } + + #[test] + fn valid() { + let value = "nqWxagcdTGGXUgn"; + let id = UserID::from_str(value); + assert!(id.is_ok()); + + let id = id.unwrap(); + assert_eq!(id.0, value); + } +}