1use std::fmt::Display;
5use std::sync::Arc;
6
7use itertools::Itertools;
8use parking_lot::RwLock;
9use vortex_error::VortexExpect;
10use vortex_error::VortexResult;
11use vortex_error::vortex_bail;
12use vortex_error::vortex_err;
13use vortex_session::registry::Registry;
14
15use crate::vtable::ArrayVTable;
16
17pub type ArrayContext = VTableContext<ArrayVTable>;
18
19#[derive(Debug, Clone)]
22pub struct VTableContext<T>(Arc<RwLock<Vec<T>>>);
23
24impl<T: Clone + Eq> VTableContext<T> {
25 pub fn new(encodings: Vec<T>) -> Self {
26 Self(Arc::new(RwLock::new(encodings)))
27 }
28
29 pub fn try_from_registry<'a>(
30 registry: &Registry<T>,
31 ids: impl IntoIterator<Item = &'a str>,
32 ) -> VortexResult<Self>
33 where
34 T: Display,
35 {
36 let items: Vec<T> = ids
37 .into_iter()
38 .map(|id| {
39 registry
40 .find(id)
41 .ok_or_else(|| vortex_err!("Registry missing encoding with id {}", id))
42 })
43 .try_collect()?;
44 if items.len() > u16::MAX as usize {
45 vortex_bail!(
46 "Cannot create VTableContext: registry has more than u16::MAX ({}) items",
47 u16::MAX
48 );
49 }
50 Ok(Self::new(items))
51 }
52
53 pub fn empty() -> Self {
54 Self(Arc::new(RwLock::new(Vec::new())))
55 }
56
57 pub fn with(self, encoding: T) -> Self {
58 {
59 let mut write = self.0.write();
60 if write.iter().all(|e| e != &encoding) {
61 write.push(encoding);
62 }
63 }
64 self
65 }
66
67 pub fn with_many<E: IntoIterator<Item = T>>(self, items: E) -> Self {
68 items.into_iter().fold(self, |ctx, e| ctx.with(e))
69 }
70
71 pub fn encodings(&self) -> Vec<T> {
72 self.0.read().clone()
73 }
74
75 pub fn encoding_idx(&self, encoding: &T) -> u16 {
81 let mut write = self.0.write();
82 if let Some(idx) = write.iter().position(|e| e == encoding) {
83 return u16::try_from(idx).vortex_expect("Cannot have more than u16::MAX encodings");
84 }
85 assert!(
86 write.len() < u16::MAX as usize,
87 "Cannot have more than u16::MAX encodings"
88 );
89 write.push(encoding.clone());
90 u16::try_from(write.len() - 1).vortex_expect("checked already")
91 }
92
93 pub fn lookup_encoding(&self, idx: u16) -> Option<T> {
95 self.0.read().get(idx as usize).cloned()
96 }
97}