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::Vertex;
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, Vertex>,
37 name2id: BTreeMap<Vertex, 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: &Vertex) -> Option<Id> {
63 self.name2id.get(name).copied()
64 }
65
66 pub fn lookup_vertex_name(&self, id: Id) -> Option<&Vertex> {
67 self.id2name.get(&id)
68 }
69
70 pub fn lookup_vertexes_by_hex_prefix(
71 &self,
72 hex_prefix: &[u8],
73 limit: usize,
74 ) -> Result<Vec<Vertex>> {
75 let start = Vertex::from_hex(hex_prefix)?;
76 let mut result = Vec::new();
77 for (vertex, id) in self.name2id.range(start..) {
78 if result.len() >= limit {
79 break;
80 }
81 if id.is_virtual() && hex_prefix.len() != vertex.as_ref().len() * 2 {
82 continue;
84 }
85 if !vertex.to_hex().as_bytes().starts_with(hex_prefix) {
86 break;
87 }
88 result.push(vertex.clone());
89 }
90 Ok(result)
91 }
92
93 pub fn lookup_range(&self, low: Id, high: Id) -> impl Iterator<Item = (&Id, &Vertex)> {
94 self.id2name.range(low..=high)
95 }
96
97 pub fn has_vertex_name(&self, name: &Vertex) -> bool {
98 self.name2id.contains_key(name)
99 }
100
101 pub fn has_vertex_id(&self, id: Id) -> bool {
102 self.id2name.contains_key(&id)
103 }
104
105 pub fn insert_vertex_id_name(&mut self, id: Id, vertex_name: Vertex) {
106 self.name2id.insert(vertex_name.clone(), id);
107 self.id2name.insert(id, vertex_name);
108 }
109
110 pub fn remove_range(&mut self, low: Id, high: Id) -> Result<Vec<Vertex>> {
111 let to_remove: Vec<(Id, Vertex)> = self
112 .id2name
113 .range(low..=high)
114 .map(|(i, n)| (*i, n.clone()))
115 .collect();
116 for (id, name) in &to_remove {
117 self.id2name.remove(id);
118 self.name2id.remove(name);
119 }
120 Ok(to_remove.into_iter().map(|(_, v)| v).collect())
121 }
122}
123
124#[async_trait::async_trait]
125impl IdConvert for MemIdMap {
126 async fn vertex_id(&self, name: Vertex) -> Result<Id> {
127 self.core
128 .lookup_vertex_id(&name)
129 .ok_or_else(|| name.not_found_error())
130 }
131 async fn vertex_id_with_max_group(
132 &self,
133 name: &Vertex,
134 max_group: Group,
135 ) -> Result<Option<Id>> {
136 let optional_id = self.core.name2id.get(name).and_then(|id| {
137 if id.group() <= max_group {
138 Some(*id)
139 } else {
140 None
141 }
142 });
143 Ok(optional_id)
144 }
145 async fn vertex_name(&self, id: Id) -> Result<Vertex> {
146 self.core
147 .lookup_vertex_name(id)
148 .cloned()
149 .ok_or_else(|| id.not_found_error())
150 }
151 async fn contains_vertex_name(&self, name: &Vertex) -> Result<bool> {
152 Ok(self.core.has_vertex_name(name))
153 }
154
155 async fn contains_vertex_id_locally(&self, ids: &[Id]) -> Result<Vec<bool>> {
156 Ok(ids
157 .iter()
158 .copied()
159 .map(|id| self.core.has_vertex_id(id))
160 .collect())
161 }
162 async fn contains_vertex_name_locally(&self, names: &[Vertex]) -> Result<Vec<bool>> {
163 Ok(names
164 .iter()
165 .map(|name| self.core.has_vertex_name(name))
166 .collect())
167 }
168
169 fn map_id(&self) -> &str {
170 &self.map_id
171 }
172
173 fn map_version(&self) -> &VerLink {
174 &self.map_version
175 }
176}
177
178#[async_trait::async_trait]
180impl IdMapWrite for MemIdMap {
181 async fn insert(&mut self, id: Id, name: &[u8]) -> Result<()> {
182 let vertex_name = Vertex::copy_from(name);
183 self.core.insert_vertex_id_name(id, vertex_name);
184 self.map_version.bump();
185 Ok(())
186 }
187 async fn remove_range(&mut self, low: Id, high: Id) -> Result<Vec<Vertex>> {
188 if !(low.is_virtual() && high.is_virtual()) {
189 self.map_version = VerLink::new();
190 }
191 self.core.remove_range(low, high)
192 }
193}
194
195impl Persist for MemIdMap {
196 type Lock = ();
197
198 fn lock(&mut self) -> Result<Self::Lock> {
199 Ok(())
200 }
201
202 fn reload(&mut self, _lock: &Self::Lock) -> Result<()> {
203 Ok(())
204 }
205
206 fn persist(&mut self, _lock: &Self::Lock) -> Result<()> {
207 Ok(())
208 }
209}
210
211#[async_trait::async_trait]
212impl PrefixLookup for MemIdMap {
213 async fn vertexes_by_hex_prefix(&self, hex_prefix: &[u8], limit: usize) -> Result<Vec<Vertex>> {
214 self.core.lookup_vertexes_by_hex_prefix(hex_prefix, limit)
215 }
216}
217
218fn next_id() -> u64 {
219 static ID: AtomicU64 = AtomicU64::new(0);
220 ID.fetch_add(1, atomic::Ordering::AcqRel)
221}