Skip to content

Instantly share code, notes, and snippets.

@kiwiyou
Created February 26, 2020 10:56
Show Gist options
  • Save kiwiyou/1130c261cb10cb52911206ed3c6a1925 to your computer and use it in GitHub Desktop.
Save kiwiyou/1130c261cb10cb52911206ed3c6a1925 to your computer and use it in GitHub Desktop.
UUID Generator without collision
[package]
name = "ugen"
version = "0.1.0"
authors = ["kiwiyou <kiwiyou.dev@gmail.com>"]
edition = "2018"
[dependencies]
rand = "0.7"
clap = { git = "https://github.com/clap-rs/clap/" }
mod uuid;
use clap::Clap;
#[derive(Clap)]
#[clap(version = "1.0", author = "kiwiyou")]
struct UuidGenerator {
/// Count of UUIDs to generate
#[clap(short = "c")]
count: usize,
/// File to write generated UUIDs to
#[clap(short = "o")]
output: Option<String>,
}
fn main() {
let generator = UuidGenerator::parse();
let mut field = uuid::UniqueUuid::new();
let uuid_list = std::iter::repeat_with(|| field.generate()).take(generator.count);
if let Some(filename) = generator.output {
use std::fs::*;
use std::io::*;
let mut file = File::create(filename).unwrap();
for uuid in uuid_list {
writeln!(&mut file, "{}", uuid).unwrap();
}
} else {
for uuid in uuid_list {
println!("{}", uuid);
}
}
}
use rand::distributions::{Distribution, Uniform};
use rand::{rngs::ThreadRng, thread_rng, Rng};
pub struct UniqueUuid {
field: Vec<std::ops::RangeInclusive<u64>>,
rng: ThreadRng,
}
impl UniqueUuid {
pub fn new() -> Self {
Self {
field: vec![0..=std::u64::MAX],
rng: thread_rng(),
}
}
pub fn generate(&mut self) -> Uuid {
let field_selection = self.rng.gen_range(0, self.field.len());
let field = self.field.remove(field_selection);
let distribution = Uniform::new_inclusive(field.start(), field.end());
let random = distribution.sample(&mut self.rng);
if random > *field.start() {
self.field.push(*field.start()..=(random - 1));
}
if random < *field.end() {
self.field.push((random + 1)..=*field.end());
}
Uuid(random)
}
}
#[derive(Debug)]
pub struct Uuid(u64);
use std::fmt::{self, Display, Formatter};
impl Display for Uuid {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
let bytes = self.0.to_be_bytes();
f.write_fmt(format_args!(
"{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}",
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]
))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment