Skip to content

Commit

Permalink
Draft of 3.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
OSA413 committed Jul 26, 2024
1 parent 00768c1 commit 2870da4
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 96 deletions.
16 changes: 2 additions & 14 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "uuid-by-string"
description = "Generating uuid-hash from string"
version = "2.0.5"
version = "3.0.0"
edition = "2021"
authors = ["Oleg \"OSA413\" Sokolov", "Danakt Saushkin"]
repository = "https://github.com/OSA413/uuid-by-string"
Expand All @@ -16,19 +16,7 @@ keywords = [

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
default=[]
namespaces=["default"]

[dependencies]
md-5 = "0.10.6"
regex = "1.10.2"
sha1 = "0.10.6"

[[test]]
name = "default"
required-features = []

[[test]]
name = "namespaces"
required-features = ["namespaces"]
sha1 = "0.10.6"
14 changes: 4 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
uuid-by-string
[![NPM](https://img.shields.io/crates/v/uuid-by-string)](https://crates.io/crates/uuid-by-string)
[![Crates.io](https://img.shields.io/crates/v/uuid-by-string)](https://crates.io/crates/uuid-by-string)
[![Downloads](https://img.shields.io/crates/dr/uuid-by-string)](https://crates.io/crates/uuid-by-string)
=======================
Generates the [RFC-4122](https://tools.ietf.org/html/rfc4122#section-4.3) Name-Based UUID. Supports 3 and 5 versions of UUID with and without a namespace.
Generates the [RFC-4122](https://tools.ietf.org/html/rfc4122#section-4.3) Name-Based UUID. Supports 3 and 5 versions of UUID with and without (non-standard, see below) a namespace.

## 🚨 Warning: Don't use unless explicitly necessary (see [replacement](#replacement)) 🚨

**Note**: generating UUID v3 and v5 without a namespace is **non-standard** (the RFC-4122 covers only the case when you concatenate the namespace with the name, so if you want a reproducable result in other progrmming langiages you need to generate UUID with some namespace, e.g. [nil](https://en.wikipedia.org/wiki/Universally_unique_identifier#Special_UUIDs))

Expand Down Expand Up @@ -34,7 +36,6 @@ The string `hello world` will always return `2aae6c35-c94f-5fb4-95db-e95f408b9ce

You can specify the UUID version. Available versions is 3 and 5 according to [RFC-4122](https://tools.ietf.org/html/rfc4122#section-4.3). The version is responsible for the hashing algorithm: version 3 uses MD5, and version 5 uses SHA-1. UUIDv5 is used by default if version is not specified.


```rust
use uuid_by_string::generate_uuid::{generate_uuid_v3, generate_uuid_v5};

Expand Down Expand Up @@ -63,13 +64,6 @@ let uuid = Uuid::new_v3(&Uuid::nil(), b"Hello world!");
let uuid = Uuid::new_v5(&Uuid::nil(), b"Hello world!");
```

Since generating a UUID v3 and v5 without namespace is non-standard you either have to stick with this library or rely on your own implementation of the following methods of this library:
```
generate_uuid
generate_uuid_v3
generate_uuid_v5
```

More info about replacement:
* https://docs.rs/uuid/
* https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.new_v3
Expand Down
6 changes: 2 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
pub mod generate_uuid;

#[cfg(feature = "namespaces")]
pub mod generate_uuid_with_namespace;
pub mod uuid;
pub mod uuid_no_namespace;
14 changes: 8 additions & 6 deletions src/generate_uuid_with_namespace.rs → src/uuid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ mod common;
#[path="./for_namespace.rs"]
mod for_namespace;

pub fn generate_uuid_with_namespace(target: &str, namespace: &str) -> Result<String, &'static str> {
generate_uuid_with_namespace_v5(target, namespace)
const NIL_UUID: &str = "00000000-0000-0000-0000-000000000000";

pub fn generate(target: &str, namespace: Option<&str>) -> Result<String, &'static str> {
generate_v5(target, namespace)
}

pub fn generate_uuid_with_namespace_v3(target: &str, namespace: &str) -> Result<String, &'static str> {
pub fn generate_v3(target: &str, namespace: Option<&str>) -> Result<String, &'static str> {
let target_char_buffer = target.as_bytes();
let namespace_char_buffer = for_namespace::parse_uuid(namespace);
let namespace_char_buffer = for_namespace::parse_uuid(namespace.unwrap_or(NIL_UUID));

match namespace_char_buffer {
Err(x) => return Err(x),
Expand All @@ -22,9 +24,9 @@ pub fn generate_uuid_with_namespace_v3(target: &str, namespace: &str) -> Result<
return Ok(common::hash_to_uuid(result, 3));
}

pub fn generate_uuid_with_namespace_v5(target: &str, namespace: &str) -> Result<String, &'static str> {
pub fn generate_v5(target: &str, namespace: Option<&str>) -> Result<String, &'static str> {
let target_char_buffer = target.as_bytes();
let namespace_char_buffer = for_namespace::parse_uuid(namespace);
let namespace_char_buffer = for_namespace::parse_uuid(namespace.unwrap_or(NIL_UUID));

match namespace_char_buffer {
Err(x) => return Err(x),
Expand Down
12 changes: 8 additions & 4 deletions src/generate_uuid.rs → src/uuid_no_namespace.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
#[path="./common.rs"]
mod common;

pub fn generate_uuid(target: &str) -> String {
generate_uuid_v5(target)
#[deprecated = "Generating UUID v3 and v5 is non-standard, see RFC-4122"]
pub fn generate(target: &str) -> String {
#[allow(deprecated)]
generate_v5(target)
}

pub fn generate_uuid_v3(target: &str) -> String {
#[deprecated = "Generating UUID v3 and v5 is non-standard, see RFC-4122"]
pub fn generate_v3(target: &str) -> String {
let target_char_buffer = target.as_bytes();
let buffer = target_char_buffer.to_vec();
let result = common::md5_hash(buffer);
return common::hash_to_uuid(result, 3);
}

pub fn generate_uuid_v5(target: &str) -> String {
#[deprecated = "Generating UUID v3 and v5 is non-standard, see RFC-4122"]
pub fn generate_v5(target: &str) -> String {
let target_char_buffer = target.as_bytes();
let buffer = target_char_buffer.to_vec();
let result = common::sha1_hash(buffer);
Expand Down
38 changes: 0 additions & 38 deletions tests/default.rs

This file was deleted.

70 changes: 50 additions & 20 deletions tests/namespaces.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use uuid_by_string::generate_uuid_with_namespace::{generate_uuid_with_namespace_v3, generate_uuid_with_namespace_v5};
use uuid_by_string::uuid;

mod common {
pub mod japanese_text;
Expand All @@ -9,39 +9,69 @@ use crate::common::{japanese_text::JAPANESE_TEXT, long_text::LONG_TEXT};

#[test]
fn hello_world() {
assert_eq!(generate_uuid_with_namespace_v3("hello world", "d3486ae9-136e-5856-bc42-212385ea7970"), Ok("c8aeb76a-1204-3f07-995e-5c5fa3494b7f".to_owned()));
assert_eq!(generate_uuid_with_namespace_v3("hello world", "D3486AE9-136e-5856-bc42-212385ea7970"), Ok("c8aeb76a-1204-3f07-995e-5c5fa3494b7f".to_owned()));
assert_eq!(generate_uuid_with_namespace_v5("hello world", "d3486ae9-136e-5856-bc42-212385ea7970"), Ok("1825ed38-348f-5b46-99de-fd84b83aba5e".to_owned()));
assert_eq!(generate_uuid_with_namespace_v5("hello world", "D3486AE9-136e-5856-bc42-212385ea7970"), Ok("1825ed38-348f-5b46-99de-fd84b83aba5e".to_owned()));
assert_eq!(uuid::generate_v3("hello world", Some("d3486ae9-136e-5856-bc42-212385ea7970")), Ok("c8aeb76a-1204-3f07-995e-5c5fa3494b7f".to_owned()));
assert_eq!(uuid::generate_v3("hello world", Some("D3486AE9-136e-5856-bc42-212385ea7970")), Ok("c8aeb76a-1204-3f07-995e-5c5fa3494b7f".to_owned()));
assert_eq!(uuid::generate_v5("hello world", Some("d3486ae9-136e-5856-bc42-212385ea7970")), Ok("1825ed38-348f-5b46-99de-fd84b83aba5e".to_owned()));
assert_eq!(uuid::generate_v5("hello world", Some("D3486AE9-136e-5856-bc42-212385ea7970")), Ok("1825ed38-348f-5b46-99de-fd84b83aba5e".to_owned()));
}

#[test]
fn hello_world_default() {
assert_eq!(uuid::generate_v3("hello world", None), Ok("c72c207b-0847-386d-bdbc-2e5def81cf81".to_owned()));
assert_eq!(uuid::generate_v5("hello world", None), Ok("191333f6-c83e-5b3b-bdb0-bd483ad1bcb7".to_owned()));
}

#[test]
fn namespace_reject_invalid_uuid() {
assert_eq!(generate_uuid_with_namespace_v3("hello world", ""), Err("Invalid UUID"));
assert_eq!(generate_uuid_with_namespace_v3("hello world", "Lorem ipsum"), Err("Invalid UUID"));
assert_eq!(generate_uuid_with_namespace_v5("hello world", "123"), Err("Invalid UUID"));
assert_eq!(uuid::generate_v3("hello world", Some("")), Err("Invalid UUID"));
assert_eq!(uuid::generate_v3("hello world", Some("Lorem ipsum")), Err("Invalid UUID"));
assert_eq!(uuid::generate_v5("hello world", Some("123")), Err("Invalid UUID"));
}

#[test]
fn hello_world_again() {
assert_eq!(generate_uuid_with_namespace_v3("Hello world!", "d3486ae9-136e-5856-bc42-212385ea7970"), Ok("5928d9ca-9acd-3608-a6dc-24ebd0c49283".to_owned()));
assert_eq!(generate_uuid_with_namespace_v5("Hello world!", "d3486ae9-136e-5856-bc42-212385ea7970"), Ok("6c85afc9-ff2a-56d9-b451-75a825751bed".to_owned()));
assert_eq!(uuid::generate_v3("Hello world!", Some("d3486ae9-136e-5856-bc42-212385ea7970")), Ok("5928d9ca-9acd-3608-a6dc-24ebd0c49283".to_owned()));
assert_eq!(uuid::generate_v5("Hello world!", Some("d3486ae9-136e-5856-bc42-212385ea7970")), Ok("6c85afc9-ff2a-56d9-b451-75a825751bed".to_owned()));
}

#[test]
fn hello_world_again_default() {
assert_eq!(uuid::generate_v3("Hello world!", None), Ok("f7c44786-7e81-386b-a7a5-95ef58bcb389".to_owned()));
assert_eq!(uuid::generate_v5("Hello world!", None), Ok("ec74fa6c-5be6-5388-8cb3-d91001210130".to_owned()));
}

#[test]
fn should_generate_uuid_v3_from_string_with_namespace() {
assert_eq!(generate_uuid_with_namespace_v3("", "d3486ae9-136e-5856-bc42-212385ea7970"), Ok("c9d82834-1d69-3199-81e0-ccf73cedd3b9".to_owned()));
assert_eq!(generate_uuid_with_namespace_v3("Hello world!", "d3486ae9-136e-5856-bc42-212385ea7970"), Ok("5928d9ca-9acd-3608-a6dc-24ebd0c49283".to_owned()));
assert_eq!(generate_uuid_with_namespace_v3("Lorem ipsum", "d3486ae9-136e-5856-bc42-212385ea7970"), Ok("254f8a36-7528-3566-87ee-55a1cfef1be2".to_owned()));
assert_eq!(generate_uuid_with_namespace_v3(JAPANESE_TEXT, "d3486ae9-136e-5856-bc42-212385ea7970"), Ok("53fb63e9-0855-398e-b5e1-322bb5296c50".to_owned()));
assert_eq!(generate_uuid_with_namespace_v3(LONG_TEXT, "d3486ae9-136e-5856-bc42-212385ea7970"), Ok("d1c2812d-10d2-3cf4-9fa9-236cec2dd3cf".to_owned()));
assert_eq!(uuid::generate_v3("", Some("d3486ae9-136e-5856-bc42-212385ea7970")), Ok("c9d82834-1d69-3199-81e0-ccf73cedd3b9".to_owned()));
assert_eq!(uuid::generate_v3("Hello world!", Some("d3486ae9-136e-5856-bc42-212385ea7970")), Ok("5928d9ca-9acd-3608-a6dc-24ebd0c49283".to_owned()));
assert_eq!(uuid::generate_v3("Lorem ipsum", Some("d3486ae9-136e-5856-bc42-212385ea7970")), Ok("254f8a36-7528-3566-87ee-55a1cfef1be2".to_owned()));
assert_eq!(uuid::generate_v3(JAPANESE_TEXT, Some("d3486ae9-136e-5856-bc42-212385ea7970")), Ok("53fb63e9-0855-398e-b5e1-322bb5296c50".to_owned()));
assert_eq!(uuid::generate_v3(LONG_TEXT, Some("d3486ae9-136e-5856-bc42-212385ea7970")), Ok("d1c2812d-10d2-3cf4-9fa9-236cec2dd3cf".to_owned()));
}

#[test]
fn should_generate_uuid_v5_from_string_with_namespace() {
assert_eq!(generate_uuid_with_namespace_v5("", "d3486ae9-136e-5856-bc42-212385ea7970"), Ok("6d72c664-05f7-5ae7-8653-ee9ebed25b00".to_owned()));
assert_eq!(generate_uuid_with_namespace_v5("Hello world!", "d3486ae9-136e-5856-bc42-212385ea7970"), Ok("6c85afc9-ff2a-56d9-b451-75a825751bed".to_owned()));
assert_eq!(generate_uuid_with_namespace_v5("Lorem ipsum", "d3486ae9-136e-5856-bc42-212385ea7970"), Ok("a359b647-73dd-52b9-ac27-6119382182db".to_owned()));
assert_eq!(generate_uuid_with_namespace_v5(JAPANESE_TEXT, "d3486ae9-136e-5856-bc42-212385ea7970"), Ok("a7928b1a-03e8-5a2e-adf9-dee22ea1d1d5".to_owned()));
assert_eq!(generate_uuid_with_namespace_v5(LONG_TEXT, "d3486ae9-136e-5856-bc42-212385ea7970"), Ok("5daf5b6d-b5e8-5e22-96c4-71e0fd8c4540".to_owned()));
assert_eq!(uuid::generate_v5("", Some("d3486ae9-136e-5856-bc42-212385ea7970")), Ok("6d72c664-05f7-5ae7-8653-ee9ebed25b00".to_owned()));
assert_eq!(uuid::generate_v5("Hello world!", Some("d3486ae9-136e-5856-bc42-212385ea7970")), Ok("6c85afc9-ff2a-56d9-b451-75a825751bed".to_owned()));
assert_eq!(uuid::generate_v5("Lorem ipsum", Some("d3486ae9-136e-5856-bc42-212385ea7970")), Ok("a359b647-73dd-52b9-ac27-6119382182db".to_owned()));
assert_eq!(uuid::generate_v5(JAPANESE_TEXT, Some("d3486ae9-136e-5856-bc42-212385ea7970")), Ok("a7928b1a-03e8-5a2e-adf9-dee22ea1d1d5".to_owned()));
assert_eq!(uuid::generate_v5(LONG_TEXT, Some("d3486ae9-136e-5856-bc42-212385ea7970")), Ok("5daf5b6d-b5e8-5e22-96c4-71e0fd8c4540".to_owned()));
}

#[test]
fn should_generate_uuid_v3_from_string_with_default_namespace() {
assert_eq!(uuid::generate_v3("", None), Ok("4ae71336-e44b-39bf-b9d2-752e234818a5".to_owned()));
assert_eq!(uuid::generate_v3("Hello world!", None), Ok("f7c44786-7e81-386b-a7a5-95ef58bcb389".to_owned()));
assert_eq!(uuid::generate_v3("Lorem ipsum", None), Ok("7e7c264e-35a5-3e17-97c9-6467e3b4359c".to_owned()));
assert_eq!(uuid::generate_v3(JAPANESE_TEXT, None), Ok("8c085e86-f500-3556-b08e-3fe16c7d7724".to_owned()));
assert_eq!(uuid::generate_v3(LONG_TEXT, None), Ok("0d12c6ed-bc6d-356f-8932-ee6ab1262870".to_owned()));
}

#[test]
fn should_generate_uuid_v5_from_string_with_default_namespace() {
assert_eq!(uuid::generate_v5("", None), Ok("e129f27c-5103-5c5c-844b-cdf0a15e160d".to_owned()));
assert_eq!(uuid::generate_v5("Hello world!", None), Ok("ec74fa6c-5be6-5388-8cb3-d91001210130".to_owned()));
assert_eq!(uuid::generate_v5("Lorem ipsum", None), Ok("e09defe7-e8dd-5995-a741-57669517728a".to_owned()));
assert_eq!(uuid::generate_v5(JAPANESE_TEXT, None), Ok("583709b5-7c35-5f81-8a64-136786bda678".to_owned()));
assert_eq!(uuid::generate_v5(LONG_TEXT, None), Ok("57cccf14-e652-5428-8013-4380d74a86e6".to_owned()));
}
39 changes: 39 additions & 0 deletions tests/no_namespace.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#![allow(deprecated)]
use uuid_by_string::uuid_no_namespace;

mod common {
pub mod japanese_text;
pub mod long_text;
}

use crate::common::{japanese_text::JAPANESE_TEXT, long_text::LONG_TEXT};

#[test]
fn hello_world() {
assert_eq!(uuid_no_namespace::generate_v3("hello world"), "5eb63bbb-e01e-3ed0-93cb-22bb8f5acdc3");
assert_eq!(uuid_no_namespace::generate_v5("hello world"), "2aae6c35-c94f-5fb4-95db-e95f408b9ce9");
}

#[test]
fn hello_world_again() {
assert_eq!(uuid_no_namespace::generate_v3("Hello world!"), "86fb269d-190d-3c85-b6e0-468ceca42a20");
assert_eq!(uuid_no_namespace::generate_v5("Hello world!"), "d3486ae9-136e-5856-bc42-212385ea7970");
}

#[test]
fn should_generate_uuid_v3_from_string() {
assert_eq!(uuid_no_namespace::generate_v3(""), "d41d8cd9-8f00-3204-a980-0998ecf8427e");
assert_eq!(uuid_no_namespace::generate_v3("Hello world!"), "86fb269d-190d-3c85-b6e0-468ceca42a20");
assert_eq!(uuid_no_namespace::generate_v3("Lorem ipsum"), "0956d2fb-d5d5-3298-84a4-d21ed2f76e0c");
assert_eq!(uuid_no_namespace::generate_v3(JAPANESE_TEXT), "20b085c2-2e91-324f-89c2-648fc03ee626");
assert_eq!(uuid_no_namespace::generate_v3(LONG_TEXT), "34e58612-20fa-3978-bbe1-656b34ab2f2f");
}

#[test]
fn should_generate_uuid_v5_from_string() {
assert_eq!(uuid_no_namespace::generate_v5(""), "da39a3ee-5e6b-5b0d-b255-bfef95601890");
assert_eq!(uuid_no_namespace::generate_v5("Hello world!"), "d3486ae9-136e-5856-bc42-212385ea7970");
assert_eq!(uuid_no_namespace::generate_v5("Lorem ipsum"), "94912be8-b3fb-57d4-961e-a50e5948c629");
assert_eq!(uuid_no_namespace::generate_v5(JAPANESE_TEXT), "ae49974d-2750-5eb2-b004-24bf83a04950");
assert_eq!(uuid_no_namespace::generate_v5(LONG_TEXT), "c81386c7-744f-5af9-8899-cfdd14664aa7");
}

0 comments on commit 2870da4

Please sign in to comment.