Init
This commit is contained in:
commit
8b2d5fe5f0
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
/Cargo.lock
|
|
@ -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
|
|
@ -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>
|
|
@ -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>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -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"
|
|
@ -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
|
||||
// }
|
||||
// }
|
|
@ -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
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue