This commit is contained in:
william 2023-09-04 22:00:00 -04:00
commit 8b2d5fe5f0
9 changed files with 186 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
/Cargo.lock

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/uuid.iml" filepath="$PROJECT_DIR$/.idea/uuid.iml" />
</modules>
</component>
</project>

12
.idea/uuid.iml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

9
Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "uuid"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
getrandom = "0.2.10"

101
src/lib.rs Normal file
View File

@ -0,0 +1,101 @@
pub mod v4;
mod rng;
pub(crate) type Bytes = [u8; 16];
pub struct Uuid(Bytes);
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(u8)]
pub enum Variant {
NCS = 0u8,
Default = 0x80,
Microsoft = 0xc0,
Future = 0xe0,
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(u8)]
pub enum Version {
Nil = 0,
Time = 1,
DCE = 2,
MD5 = 3,
Random = 4,
SHA1 = 5,
Unknown = u8::MAX
}
impl Uuid {
pub fn new(version: Version) -> Self {
match version {
Version::Nil => Self::new_nil(),
Version::Random => Self::new_random(),
_ => panic!("Unsupported UUID version: {:?}", version)
}
}
pub fn new_nil() -> Self {
Uuid(Uuid::nil_bytes())
}
#[inline]
pub const fn as_bytes(&self) -> &[u8] {
&self.0
}
pub const fn get_variant(&self) -> Variant {
match self.as_bytes()[8] {
x if x & 0x80 == 0 => Variant::NCS,
x if x & 0x40 == 0 => Variant::Default,
x if x & 0x20 == 0 => Variant::Microsoft,
_ => Variant::Future
}
}
pub const fn get_version_num(&self) -> u8 {
self.as_bytes()[6] >> 4
}
pub const fn get_version(&self) -> Version {
match self.get_version_num() {
0 => Version::Nil,
1 => Version::Time,
2 => Version::DCE,
3 => Version::MD5,
4 => Version::Random,
5 => Version::SHA1,
_ => Version::Unknown
}
}
#[inline]
const fn nil_bytes() -> Bytes {
[0u8; 16]
}
#[inline]
fn set_variant(bytes: &mut Bytes, variant: Variant) {
let variant = variant as u8;
let byte = bytes[8] & 0xf;
bytes[8] = variant & byte;
}
#[inline]
fn set_version(bytes: &mut Bytes, version: Version) {
bytes[6] |= (version as u8) << 4;
}
}
impl Default for Uuid {
fn default() -> Self {
Uuid::new_nil()
}
}
// impl AsRef<Bytes> for Uuid {
// fn as_ref(&self) -> &Bytes {
// &self.0
// }
// }

10
src/rng.rs Normal file
View File

@ -0,0 +1,10 @@
use getrandom::getrandom;
use crate::Bytes;
pub(crate) fn get_random_bytes() -> Bytes {
let mut bytes = [0u8; 16];
getrandom(&mut bytes).expect("Failed to get random bytes for UUID");
bytes
}

30
src/v4.rs Normal file
View File

@ -0,0 +1,30 @@
use crate::rng::get_random_bytes;
use crate::{Uuid, Variant, Version};
impl Uuid {
pub fn new_v4() -> Self {
Uuid::new_random()
}
pub fn new_random() -> Self {
let mut bytes = get_random_bytes();
Uuid::set_variant(&mut bytes, Variant::Default);
Uuid::set_version(&mut bytes, Version::Random);
Uuid(bytes)
}
}
#[cfg(test)]
mod tests {
use crate::{Uuid, Variant};
#[test]
fn new_v4__variant() {
let uuid = Uuid::new_v4();
assert_eq!(uuid.get_variant(), Variant::Default);
}
}