1use std::collections::BTreeMap;
9use std::sync::atomic;
10use std::sync::atomic::AtomicU64;
11
12use super::IdMapWrite;
13use crate::errors::NotFoundError;
14use crate::id::Group;
15use crate::id::Id;
16use crate::id::VertexName;
17use crate::ops::IdConvert;
18use crate::ops::Persist;
19use crate::ops::PrefixLookup;
20use crate::Result;
21use crate::VerLink;
22
23pub struct MemIdMap {
27 core: CoreMemIdMap,
28 map_id: String,
29 map_version: VerLink,
30}
31
32#[derive(Default, Clone)]
35pub(crate) struct CoreMemIdMap {
36 id2name: BTreeMap<Id, VertexName>,
37 name2id: BTreeMap<VertexName, Id>,
38}
39
40impl MemIdMap {
41 pub fn new() -> Self {
43 Self {
44 core: Default::default(),
45 map_id: format!("mem:{}", next_id()),
46 map_version: VerLink::new(),
47 }
48 }
49}
50
51impl Clone for MemIdMap {
52 fn clone(&self) -> Self {
53 Self {
54 core: self.core.clone(),
55 map_id: self.map_id.clone(),
56 map_version: self.map_version.clone(),
57 }
58 }
59}
60
61impl CoreMemIdMap {
62 pub fn lookup_vertex_id(&self, name: &VertexName) -> Option<Id> {
63 self.name2id.get(&name).copied()
64 }
65
66 pub fn lookup_vertex_name(&self, id: Id) -> Option<VertexName> {
67 self.id2name.get(&id).cloned()
68 }
69
70 pub fn lookup_vertexes_by_hex_prefix(
71 &self,
72 hex_prefix: &[u8],
73 limit: usize,
74 ) -> Result<Vec<VertexName>> {
75 let start = VertexName::from_hex(hex_prefix)?;
76 let mut result = Vec::new();
77 for (vertex, _) in self.name2id.range(start..) {
78 if !vertex.to_hex().as_bytes().starts_with(hex_prefix) {
79 break;
80 }
81 result.push(vertex.clone());
82 if result.len() >= limit {
83 break;
84 }
85 }
86 Ok(result)
87 }
88
89 pub fn has_vertex_name(&self, name: &VertexName) -> bool {
90 self.name2id.contains_key(name)
91 }
92
93 pub fn has_vertex_id(&self, id: Id) -> bool {
94 self.id2name.contains_key(&id)
95 }
96
97 pub fn insert_vertex_id_name(&mut self, id: Id, vertex_name: VertexName) {
98 self.name2id.insert(vertex_name.clone(), id);
99 self.id2name.insert(id, vertex_name);
100 }
101
102 pub fn remove_range(&mut self, low: Id, high: Id) -> Result<Vec<VertexName>> {
103 let to_remove: Vec<(Id, VertexName)> = self
104 .id2name
105 .range(low..=high)
106 .map(|(i, n)| (*i, n.clone()))
107 .collect();
108 for (id, name) in &to_remove {
109 self.id2name.remove(id);
110 self.name2id.remove(name);
111 }
112 Ok(to_remove.into_iter().map(|(_, v)| v).collect())
113 }
114}
115
116#[async_trait::async_trait]
117impl IdConvert for MemIdMap {
118 async fn vertex_id(&self, name: VertexName) -> Result<Id> {
119 self.core
120 .lookup_vertex_id(&name)
121 .ok_or_else(|| name.not_found_error())
122 }
123 async fn vertex_id_with_max_group(
124 &self,
125 name: &VertexName,
126 max_group: Group,
127 ) -> Result<Option<Id>> {
128 let optional_id = self.core.name2id.get(name).and_then(|id| {
129 if id.group() <= max_group {
130 Some(*id)
131 } else {
132 None
133 }
134 });
135 Ok(optional_id)
136 }
137 async fn vertex_name(&self, id: Id) -> Result<VertexName> {
138 self.core
139 .lookup_vertex_name(id)
140 .ok_or_else(|| id.not_found_error())
141 }
142 async fn contains_vertex_name(&self, name: &VertexName) -> Result<bool> {
143 Ok(self.core.has_vertex_name(name))
144 }
145
146 async fn contains_vertex_id_locally(&self, ids: &[Id]) -> Result<Vec<bool>> {
147 Ok(ids
148 .iter()
149 .copied()
150 .map(|id| self.core.has_vertex_id(id))
151 .collect())
152 }
153 async fn contains_vertex_name_locally(&self, names: &[VertexName]) -> Result<Vec<bool>> {
154 Ok(names
155 .iter()
156 .map(|name| self.core.has_vertex_name(name))
157 .collect())
158 }
159
160 fn map_id(&self) -> &str {
161 &self.map_id
162 }
163
164 fn map_version(&self) -> &VerLink {
165 &self.map_version
166 }
167}
168
169#[async_trait::async_trait]
171impl IdMapWrite for MemIdMap {
172 async fn insert(&mut self, id: Id, name: &[u8]) -> Result<()> {
173 let vertex_name = VertexName::copy_from(name);
174 self.core.insert_vertex_id_name(id, vertex_name);
175 self.map_version.bump();
176 Ok(())
177 }
178 async fn remove_range(&mut self, low: Id, high: Id) -> Result<Vec<VertexName>> {
179 self.map_version = VerLink::new();
180 self.core.remove_range(low, high)
181 }
182}
183
184impl Persist for MemIdMap {
185 type Lock = ();
186
187 fn lock(&mut self) -> Result<Self::Lock> {
188 Ok(())
189 }
190
191 fn reload(&mut self, _lock: &Self::Lock) -> Result<()> {
192 Ok(())
193 }
194
195 fn persist(&mut self, _lock: &Self::Lock) -> Result<()> {
196 Ok(())
197 }
198}
199
200#[async_trait::async_trait]
201impl PrefixLookup for MemIdMap {
202 async fn vertexes_by_hex_prefix(
203 &self,
204 hex_prefix: &[u8],
205 limit: usize,
206 ) -> Result<Vec<VertexName>> {
207 self.core.lookup_vertexes_by_hex_prefix(hex_prefix, limit)
208 }
209}
210
211fn next_id() -> u64 {
212 static ID: AtomicU64 = AtomicU64::new(0);
213 ID.fetch_add(1, atomic::Ordering::AcqRel)
214}