Skip to main content

vortex_layout/
reader_context.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use std::any::Any;
5use std::sync::Arc;
6
7use vortex_session::registry::Id;
8use vortex_utils::aliases::hash_map::HashMap;
9
10/// Per-reader-tree dependency context, threaded through [`crate::VTable::new_reader`].
11///
12/// Holds an [`Id`]-keyed registry of `Arc<dyn Any>` values. Ancestors publish via
13/// [`Self::with`]; descendants retrieve via [`Self::get`]. This is a *read-only* channel
14/// from the descendant's perspective — they can only consume what an ancestor chose to
15/// publish.
16///
17/// [`Self::with`] returns a derived context that copies the existing map and inserts or
18/// replaces one entry — original unchanged, so concurrent reader-tree constructions each
19/// derive their own context without races. Contexts are cheap to clone via internal `Arc`
20/// and can be captured by lazy children helpers.
21#[derive(Clone, Default)]
22pub struct LayoutReaderContext {
23    values: Arc<HashMap<Id, Arc<dyn Any + Send + Sync>>>,
24}
25
26impl std::fmt::Debug for LayoutReaderContext {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        f.debug_struct("LayoutReaderContext")
29            .field("ids", &self.values.keys().collect::<Vec<_>>())
30            .finish()
31    }
32}
33
34impl LayoutReaderContext {
35    /// Creates a new, empty context.
36    pub fn new() -> Self {
37        Self::default()
38    }
39
40    /// Returns a new context that publishes `value` under `id`.
41    ///
42    /// The original context is unchanged. If a value was already published under the
43    /// same `id`, the new one replaces it in the returned context — so two ancestors
44    /// using the same well-known static id give descendants "nearest ancestor wins".
45    pub fn with<T: Any + Send + Sync>(&self, id: Id, value: Arc<T>) -> Self {
46        let mut values = HashMap::clone(&self.values);
47        values.insert(id, value);
48        Self {
49            values: Arc::new(values),
50        }
51    }
52
53    /// Returns the value published under `id`, downcast to `T`. Returns `None` if no
54    /// ancestor published under that id, or if the published value is not a `T`.
55    pub fn get<T: Any + Send + Sync>(&self, id: Id) -> Option<Arc<T>> {
56        self.values
57            .get(&id)
58            .and_then(|v| Arc::clone(v).downcast::<T>().ok())
59    }
60}