1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
use std::collections::HashMap; pub const HEADER_TYPE_URI: &'static str = "urn:lozizol:header"; pub const ASSIGN_TYPE_URI: &'static str = "urn:lozizol:type"; pub const DELETE_TYPE_URI: &'static str = "urn:lozizol:deleted"; pub const HEADER_TYPE_ID: &usize = &111; pub const ASSIGN_TYPE_ID: &usize = &1; pub const DELETE_TYPE_ID: &usize = &0; #[derive(Debug, Clone)] pub struct TypeAssignments { id_map: HashMap<usize, String>, uri_map: HashMap<String, usize>, id_next: usize, initialized: bool, } impl Default for TypeAssignments { fn default() -> Self { Self { id_map: HashMap::new(), uri_map: HashMap::new(), id_next: 2, initialized: false, } } } impl TypeAssignments { pub fn initialize(&mut self) { self.clear(); self.set(*DELETE_TYPE_ID, DELETE_TYPE_URI.into()); self.set(*ASSIGN_TYPE_ID, ASSIGN_TYPE_URI.into()); self.set(*HEADER_TYPE_ID, HEADER_TYPE_URI.into()); self.initialized = true; } pub fn clear(&mut self) { self.id_map.clear(); self.uri_map.clear(); self.id_next = 2; self.initialized = false; } pub fn set(&mut self, id: usize, uri: String) { self.id_map.insert(id, uri.clone()); self.uri_map.insert(uri, id); } pub fn unset(&mut self, id: &usize) { if let Some(uri) = self.id_map.get(id) { self.uri_map.remove(uri); self.id_map.remove(id); } } pub fn is_initialized(&self) -> bool { self.initialized } pub fn is_empty(&self) -> bool { self.id_map.is_empty() } pub fn get_id(&self, uri: &str) -> Option<&usize> { if !self.is_initialized() { match uri { self::DELETE_TYPE_URI => Some(DELETE_TYPE_ID), self::ASSIGN_TYPE_URI => Some(ASSIGN_TYPE_ID), self::HEADER_TYPE_URI => Some(HEADER_TYPE_ID), _ => None, } } else { self.uri_map.get(uri) } } pub fn get_uri(&self, id: &usize) -> Option<&str> { if !self.is_initialized() { match id { self::DELETE_TYPE_ID => Some(DELETE_TYPE_URI), self::ASSIGN_TYPE_ID => Some(ASSIGN_TYPE_URI), self::HEADER_TYPE_ID => Some(HEADER_TYPE_URI), _ => None, } } else { self.id_map.get(id).map(String::as_str) } } pub fn reserve(&mut self) -> TypeReservation { while self.id_map.contains_key(&self.id_next) { self.id_next += 1; } TypeReservation { store: self } } } pub struct TypeReservation<'a> { store: &'a mut TypeAssignments, } impl<'a> TypeReservation<'a> { pub fn assigned_type_id(&self) -> &usize { &self.store.id_next } pub fn type_assignment_type_id(&self) -> &usize { self.store .get_id(ASSIGN_TYPE_URI) .expect("type assignment ID not set") } pub fn store(self, uri: String) -> &'a usize { self.store.set(self.store.id_next, uri); &self.store.id_next } }