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(target_arch = "wasm32")]
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(target_arch = "wasm32"))]
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 type Error: std::error::Error + Send + Sync + 'static;
45
46 /// Returns a list of all tables hosted by this handler.
47 fn get_hosted_tables(&self) -> VirtualServerFuture<'_, Result<Vec<HostedTable>, Self::Error>>;
48
49 /// Returns the schema (column names and types) for a table.
50 fn table_schema(
51 &self,
52 table_id: &str,
53 ) -> VirtualServerFuture<'_, Result<IndexMap<String, ColumnType>, Self::Error>>;
54
55 /// Returns the number of rows in a table.
56 fn table_size(&self, table_id: &str) -> VirtualServerFuture<'_, Result<u32, Self::Error>>;
57
58 /// Creates a new view on a table with the given configuration.
59 ///
60 /// The handler may modify the configuration to reflect any adjustments
61 /// made during view creation.
62 fn table_make_view(
63 &mut self,
64 view_id: &str,
65 view_id: &str,
66 config: &mut ViewConfigUpdate,
67 ) -> VirtualServerFuture<'_, Result<String, Self::Error>>;
68
69 /// Deletes a view and releases its resources.
70 fn view_delete(&self, view_id: &str) -> VirtualServerFuture<'_, Result<(), Self::Error>>;
71
72 /// Retrieves data from a view within the specified viewport.
73 fn view_get_data(
74 &self,
75 view_id: &str,
76 config: &ViewConfig,
77 viewport: &ViewPort,
78 ) -> VirtualServerFuture<'_, Result<VirtualDataSlice, Self::Error>>;
79
80 // Optional
81
82 /// Return the column count of a `Table`
83 fn table_column_size(
84 &self,
85 table_id: &str,
86 ) -> VirtualServerFuture<'_, Result<u32, Self::Error>> {
87 let fut = self.table_schema(table_id);
88 Box::pin(async move { Ok(fut.await?.len() as u32) })
89 }
90
91 /// Returns the number of rows in a `View`.
92 fn view_size(&self, view_id: &str) -> VirtualServerFuture<'_, Result<u32, Self::Error>> {
93 Box::pin(self.table_size(view_id))
94 }
95
96 /// Return the column count of a `View`
97 fn view_column_size(
98 &self,
99 view_id: &str,
100 config: &ViewConfig,
101 ) -> VirtualServerFuture<'_, Result<u32, Self::Error>> {
102 let fut = self.view_schema(view_id, config);
103 Box::pin(async move { Ok(fut.await?.len() as u32) })
104 }
105
106 /// Returns the schema of a view after applying its configuration.
107 fn view_schema(
108 &self,
109 view_id: &str,
110 _config: &ViewConfig,
111 ) -> VirtualServerFuture<'_, Result<IndexMap<String, ColumnType>, Self::Error>> {
112 Box::pin(self.table_schema(view_id))
113 }
114
115 /// Validates an expression against a table and returns its result type.
116 ///
117 /// Default implementation returns `Float` for all expressions.
118 fn table_validate_expression(
119 &self,
120 _table_id: &str,
121 _expression: &str,
122 ) -> VirtualServerFuture<'_, Result<ColumnType, Self::Error>> {
123 Box::pin(async { Ok(ColumnType::Float) })
124 }
125
126 /// Returns the features supported by this handler.
127 ///
128 /// Default implementation returns default features.
129 fn get_features(&self) -> VirtualServerFuture<'_, Result<Features<'_>, Self::Error>> {
130 Box::pin(async { Ok(Features::default()) })
131 }
132
133 /// Creates a new input port on a table.
134 ///
135 /// Default implementation returns port ID 0.
136 fn table_make_port(
137 &self,
138 _req: &TableMakePortReq,
139 ) -> VirtualServerFuture<'_, Result<u32, Self::Error>> {
140 Box::pin(async { Ok(0) })
141 }
142
143 // Unused
144
145 /// Creates a new table with the given data.
146 ///
147 /// Default implementation panics with "not implemented".
148 fn make_table(
149 &mut self,
150 _table_id: &str,
151 _data: &crate::proto::MakeTableData,
152 ) -> VirtualServerFuture<'_, Result<(), Self::Error>> {
153 Box::pin(async { unimplemented!("make_table not implemented") })
154 }
155}