diff --git a/hostnames_allocator/Cargo.toml b/hostnames_allocator/Cargo.toml index 5bfcc96..7686d19 100644 --- a/hostnames_allocator/Cargo.toml +++ b/hostnames_allocator/Cargo.toml @@ -6,5 +6,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +lazy_static = "1.4.0" +regex = "1.10.2" + [dev-dependencies] itertools = "0.11.0" diff --git a/hostnames_allocator/src/hostnames_allocator.rs b/hostnames_allocator/src/hostnames_allocator.rs new file mode 100644 index 0000000..0248560 --- /dev/null +++ b/hostnames_allocator/src/hostnames_allocator.rs @@ -0,0 +1,36 @@ +use std::collections::HashMap; + +use lazy_static::lazy_static; +use regex::Regex; + +use crate::ranged_number_allocator::RangedNumberAllocator; + +pub struct HostnamesAllocator { + allocators_by_type: HashMap, +} + +lazy_static! { + static ref HOST_NAME_REGEX: Regex = Regex::new(r"^(\D+)(\d+)$").unwrap(); +} + +impl HostnamesAllocator { + pub fn new() -> HostnamesAllocator { + HostnamesAllocator { allocators_by_type: HashMap::new() } + } + + fn get_allocator_for_host_type(&mut self, host_type: &str) -> &mut RangedNumberAllocator { + self.allocators_by_type.entry(host_type.into()).or_insert_with(|| RangedNumberAllocator::new()) + } + + pub fn allocate(&mut self, host_type: &str) -> String { + let allocator = self.get_allocator_for_host_type(host_type); + let number = allocator.allocate(); + return format!("{host_type}{number}"); + } + + pub fn free(&mut self, host_name: &str) { + let (_, [host_type, host_number]) = HOST_NAME_REGEX.captures(host_name).unwrap().extract(); + let allocator = self.get_allocator_for_host_type(host_type); + allocator.remove(host_number.parse().unwrap()); + } +} diff --git a/hostnames_allocator/src/lib.rs b/hostnames_allocator/src/lib.rs index 09cb3ae..a5d94c5 100644 --- a/hostnames_allocator/src/lib.rs +++ b/hostnames_allocator/src/lib.rs @@ -1,3 +1,4 @@ #![feature(btree_cursors)] +pub mod hostnames_allocator; pub mod ranged_number_allocator; diff --git a/hostnames_allocator/tests/hostnames_allocator.rs b/hostnames_allocator/tests/hostnames_allocator.rs new file mode 100644 index 0000000..b00aeb7 --- /dev/null +++ b/hostnames_allocator/tests/hostnames_allocator.rs @@ -0,0 +1,19 @@ +extern crate hostnames_allocator; + +use hostnames_allocator::hostnames_allocator::HostnamesAllocator; + +#[test] +fn allocator_allocates_hostnames() { + let mut allocator = HostnamesAllocator::new(); + assert_eq!(allocator.allocate("gateway"), "gateway1"); + assert_eq!(allocator.allocate("gateway"), "gateway2"); + assert_eq!(allocator.allocate("gateway"), "gateway3"); + assert_eq!(allocator.allocate("proxy"), "proxy1"); + assert_eq!(allocator.allocate("proxy"), "proxy2"); + allocator.free("gateway2"); + allocator.free("gateway5"); + assert_eq!(allocator.allocate("proxy"), "proxy3"); + assert_eq!(allocator.allocate("gateway"), "gateway2"); + assert_eq!(allocator.allocate("gateway"), "gateway4"); + assert_eq!(allocator.allocate("gateway"), "gateway5"); +}