2024-09-03 01:39:48 +08:00
|
|
|
use std::collections::BTreeMap;
|
|
|
|
use std::sync::RwLock;
|
|
|
|
|
2024-10-28 21:09:48 +08:00
|
|
|
use super::metadata::{FieldIdMapWithMetadata, Metadata};
|
2024-10-04 00:08:09 +08:00
|
|
|
use super::MutFieldIdMapper;
|
2024-10-28 21:09:48 +08:00
|
|
|
use crate::FieldId;
|
2024-09-03 01:39:48 +08:00
|
|
|
|
|
|
|
/// A fields ids map that can be globally updated to add fields
|
2024-09-03 18:01:01 +08:00
|
|
|
#[derive(Debug, Clone)]
|
2024-09-03 01:39:48 +08:00
|
|
|
pub struct GlobalFieldsIdsMap<'indexing> {
|
2024-10-28 21:09:48 +08:00
|
|
|
global: &'indexing RwLock<FieldIdMapWithMetadata>,
|
2024-09-03 01:39:48 +08:00
|
|
|
local: LocalFieldsIdsMap,
|
|
|
|
}
|
|
|
|
|
2024-09-03 18:01:01 +08:00
|
|
|
#[derive(Debug, Clone)]
|
2024-11-21 22:00:11 +08:00
|
|
|
struct LocalFieldsIdsMap {
|
2024-09-03 01:39:48 +08:00
|
|
|
names_ids: BTreeMap<String, FieldId>,
|
|
|
|
ids_names: BTreeMap<FieldId, String>,
|
2024-10-28 21:09:48 +08:00
|
|
|
metadata: BTreeMap<FieldId, Metadata>,
|
2024-09-03 01:39:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl LocalFieldsIdsMap {
|
2024-10-28 21:09:48 +08:00
|
|
|
fn new(global: &RwLock<FieldIdMapWithMetadata>) -> Self {
|
2024-09-03 01:39:48 +08:00
|
|
|
let global = global.read().unwrap();
|
2024-10-28 21:09:48 +08:00
|
|
|
Self {
|
|
|
|
names_ids: global.as_fields_ids_map().names_ids.clone(),
|
|
|
|
ids_names: global.as_fields_ids_map().ids_names.clone(),
|
|
|
|
metadata: global.iter_id_metadata().collect(),
|
|
|
|
}
|
2024-09-03 01:39:48 +08:00
|
|
|
}
|
|
|
|
|
2024-10-28 21:09:48 +08:00
|
|
|
fn insert(&mut self, name: &str, field_id: FieldId, metadata: Metadata) {
|
2024-09-03 01:39:48 +08:00
|
|
|
self.names_ids.insert(name.to_owned(), field_id);
|
|
|
|
self.ids_names.insert(field_id, name.to_owned());
|
2024-10-28 21:09:48 +08:00
|
|
|
self.metadata.insert(field_id, metadata);
|
2024-09-03 01:39:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn name(&self, id: FieldId) -> Option<&str> {
|
|
|
|
self.ids_names.get(&id).map(String::as_str)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn id(&self, name: &str) -> Option<FieldId> {
|
|
|
|
self.names_ids.get(name).copied()
|
|
|
|
}
|
2024-10-28 21:09:48 +08:00
|
|
|
|
|
|
|
fn id_with_metadata(&self, name: &str) -> Option<(FieldId, Metadata)> {
|
|
|
|
let id = self.id(name)?;
|
|
|
|
Some((id, self.metadata(id).unwrap()))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn metadata(&self, id: FieldId) -> Option<Metadata> {
|
|
|
|
self.metadata.get(&id).copied()
|
|
|
|
}
|
2024-09-03 01:39:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'indexing> GlobalFieldsIdsMap<'indexing> {
|
2024-10-28 21:09:48 +08:00
|
|
|
pub fn new(global: &'indexing RwLock<FieldIdMapWithMetadata>) -> Self {
|
2024-09-03 01:39:48 +08:00
|
|
|
Self { local: LocalFieldsIdsMap::new(global), global }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the field id related to a field name, it will create a new field id if the
|
|
|
|
/// name is not already known. Returns `None` if the maximum field id as been reached.
|
|
|
|
pub fn id_or_insert(&mut self, name: &str) -> Option<FieldId> {
|
2024-10-28 21:09:48 +08:00
|
|
|
self.id_with_metadata_or_insert(name).map(|(fid, _meta)| fid)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn id_with_metadata_or_insert(&mut self, name: &str) -> Option<(FieldId, Metadata)> {
|
|
|
|
if let Some(entry) = self.local.id_with_metadata(name) {
|
|
|
|
return Some(entry);
|
2024-09-03 01:39:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
// optimistically lookup the global map
|
|
|
|
let global = self.global.read().unwrap();
|
|
|
|
|
2024-10-28 21:09:48 +08:00
|
|
|
if let Some((field_id, metadata)) = global.id_with_metadata(name) {
|
|
|
|
self.local.insert(name, field_id, metadata);
|
|
|
|
return Some((field_id, metadata));
|
2024-09-03 01:39:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
let mut global = self.global.write().unwrap();
|
|
|
|
|
2024-10-28 21:09:48 +08:00
|
|
|
if let Some((field_id, metadata)) = global.id_with_metadata(name) {
|
|
|
|
self.local.insert(name, field_id, metadata);
|
|
|
|
return Some((field_id, metadata));
|
2024-09-03 01:39:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
let field_id = global.insert(name)?;
|
2024-10-28 21:09:48 +08:00
|
|
|
let metadata = global.metadata(field_id).unwrap();
|
|
|
|
self.local.insert(name, field_id, metadata);
|
|
|
|
Some((field_id, metadata))
|
2024-09-03 01:39:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get the name of a field based on its id.
|
|
|
|
pub fn name(&mut self, id: FieldId) -> Option<&str> {
|
|
|
|
if self.local.name(id).is_none() {
|
|
|
|
let global = self.global.read().unwrap();
|
|
|
|
|
2024-10-28 21:09:48 +08:00
|
|
|
let (name, metadata) = global.name_with_metadata(id)?;
|
|
|
|
self.local.insert(name, id, metadata);
|
2024-09-03 01:39:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
self.local.name(id)
|
|
|
|
}
|
2024-10-04 00:08:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'indexing> MutFieldIdMapper for GlobalFieldsIdsMap<'indexing> {
|
|
|
|
fn insert(&mut self, name: &str) -> Option<FieldId> {
|
|
|
|
self.id_or_insert(name)
|
|
|
|
}
|
2024-09-03 01:39:48 +08:00
|
|
|
}
|