Skip to main content

perspective_client/virtual_server/
handler.rs

1// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2// ┃ ██████ ██████ ██████       █      █      █      █      █ █▄  ▀███ █       ┃
3// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█  ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄  ▀█ █ ▀▀▀▀▀ ┃
4// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄   █ ▄▄▄▄▄ ┃
5// ┃ █      ██████ █  ▀█▄       █ ██████      █      ███▌▐███ ███████▄ █       ┃
6// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7// ┃ Copyright (c) 2017, the Perspective Authors.                              ┃
8// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9// ┃ This file is part of the Perspective library, distributed under the terms ┃
10// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
13use std::future::Future;
14use std::pin::Pin;
15
16use indexmap::IndexMap;
17
18use super::data::VirtualDataSlice;
19use super::features::Features;
20use crate::config::{ViewConfig, ViewConfigUpdate};
21use crate::proto::{ColumnType, HostedTable, TableMakePortReq, ViewPort};
22
23#[cfg(feature = "sendable")]
24pub type VirtualServerFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a>>;
25
26/// A boxed future that conditionally implements `Send` based on the target
27/// architecture.
28///
29/// This only compiles on wasm, except for `rust-analyzer` and `metadata`
30/// generation, so this type exists to tryck the compiler
31#[cfg(not(feature = "sendable"))]
32pub type VirtualServerFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
33
34/// Handler trait for implementing virtual server backends.
35///
36/// This trait defines the interface that must be implemented to provide
37/// a custom data source for the Perspective virtual server. Implementors
38/// handle table and view operations, translating them to their underlying
39/// data store.
40pub trait VirtualServerHandler {
41    // Required
42
43    /// The error type returned by handler methods.
44    #[cfg(not(feature = "sendable"))]
45    type Error: std::error::Error + Send + Sync + 'static;
46
47    #[cfg(feature = "sendable")]
48    type Error: std::error::Error + 'static;
49
50    /// Returns a list of all tables hosted by this handler.
51    fn get_hosted_tables(&self) -> VirtualServerFuture<'_, Result<Vec<HostedTable>, Self::Error>>;
52
53    /// Returns the schema (column names and types) for a table.
54    fn table_schema(
55        &self,
56        table_id: &str,
57    ) -> VirtualServerFuture<'_, Result<IndexMap<String, ColumnType>, Self::Error>>;
58
59    /// Returns the number of rows in a table.
60    fn table_size(&self, table_id: &str) -> VirtualServerFuture<'_, Result<u32, Self::Error>>;
61
62    /// Creates a new view on a table with the given configuration.
63    ///
64    /// The handler may modify the configuration to reflect any adjustments
65    /// made during view creation.
66    fn table_make_view(
67        &mut self,
68        view_id: &str,
69        view_id: &str,
70        config: &mut ViewConfigUpdate,
71    ) -> VirtualServerFuture<'_, Result<String, Self::Error>>;
72
73    /// Deletes a view and releases its resources.
74    fn view_delete(&self, view_id: &str) -> VirtualServerFuture<'_, Result<(), Self::Error>>;
75
76    /// Retrieves data from a view within the specified viewport.
77    fn view_get_data(
78        &self,
79        view_id: &str,
80        config: &ViewConfig,
81        schema: &IndexMap<String, ColumnType>,
82        viewport: &ViewPort,
83    ) -> VirtualServerFuture<'_, Result<VirtualDataSlice, Self::Error>>;
84
85    // Optional
86
87    /// Return the column count of a `Table`
88    fn table_column_size(
89        &self,
90        table_id: &str,
91    ) -> VirtualServerFuture<'_, Result<u32, Self::Error>> {
92        let fut = self.table_schema(table_id);
93        Box::pin(async move { Ok(fut.await?.len() as u32) })
94    }
95
96    /// Returns the number of rows in a `View`.
97    fn view_size(&self, view_id: &str) -> VirtualServerFuture<'_, Result<u32, Self::Error>> {
98        Box::pin(self.table_size(view_id))
99    }
100
101    /// Return the column count of a `View`
102    fn view_column_size(
103        &self,
104        view_id: &str,
105        config: &ViewConfig,
106    ) -> VirtualServerFuture<'_, Result<u32, Self::Error>> {
107        let fut = self.view_schema(view_id, config);
108        Box::pin(async move { Ok(fut.await?.len() as u32) })
109    }
110
111    /// Returns the schema of a view after applying its configuration.
112    fn view_schema(
113        &self,
114        view_id: &str,
115        _config: &ViewConfig,
116    ) -> VirtualServerFuture<'_, Result<IndexMap<String, ColumnType>, Self::Error>> {
117        Box::pin(self.table_schema(view_id))
118    }
119
120    /// Validates an expression against a table and returns its result type.
121    ///
122    /// Default implementation returns `Float` for all expressions.
123    fn table_validate_expression(
124        &self,
125        _table_id: &str,
126        _expression: &str,
127    ) -> VirtualServerFuture<'_, Result<ColumnType, Self::Error>> {
128        Box::pin(async { Ok(ColumnType::Float) })
129    }
130
131    /// Returns the features supported by this handler.
132    ///
133    /// Default implementation returns default features.
134    fn get_features(&self) -> VirtualServerFuture<'_, Result<Features<'_>, Self::Error>> {
135        Box::pin(async { Ok(Features::default()) })
136    }
137
138    /// Creates a new input port on a table.
139    ///
140    /// Default implementation returns port ID 0.
141    fn table_make_port(
142        &self,
143        _req: &TableMakePortReq,
144    ) -> VirtualServerFuture<'_, Result<u32, Self::Error>> {
145        Box::pin(async { Ok(0) })
146    }
147
148    // Unused
149
150    /// Creates a new table with the given data.
151    ///
152    /// Default implementation panics with "not implemented".
153    fn make_table(
154        &mut self,
155        _table_id: &str,
156        _data: &crate::proto::MakeTableData,
157    ) -> VirtualServerFuture<'_, Result<(), Self::Error>> {
158        Box::pin(async { unimplemented!("make_table not implemented") })
159    }
160}