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