Skip to main content

interstice_abi/schema/
table.rs

1use std::collections::HashMap;
2
3use crate::{IntersticeTypeDef, Row, interstice_type_def::FieldDef, validate_value_detailed};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Deserialize, Serialize)]
7pub struct TableSchema {
8    pub name: String,
9    pub type_name: String,
10    pub visibility: TableVisibility,
11    pub fields: Vec<FieldDef>,
12    pub primary_key: FieldDef,
13    pub primary_key_auto_inc: bool,
14    pub indexes: Vec<IndexSchema>,
15    pub persistence: PersistenceKind,
16}
17
18#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
19pub enum TableVisibility {
20    Public,
21    Private,
22}
23
24#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
25pub enum PersistenceKind {
26    Logged,
27    Stateful,
28    Ephemeral,
29}
30
31#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
32pub enum IndexType {
33    Hash,
34    BTree,
35}
36
37#[derive(Debug, Clone, Deserialize, Serialize)]
38pub struct IndexSchema {
39    pub field_name: String,
40    pub index_type: IndexType,
41    pub unique: bool,
42    pub auto_inc: bool,
43}
44
45impl TableSchema {
46    pub fn validate_row(
47        &self,
48        row: &Row,
49        type_definitions: &HashMap<String, IntersticeTypeDef>,
50    ) -> Result<(), String> {
51        // For auto-inc primary keys the host assigns the value, so the WASM sends a
52        // placeholder (Void). Skip primary key validation in that case.
53        if !self.primary_key_auto_inc {
54            validate_value_detailed(&row.primary_key, &self.primary_key.field_type, type_definitions)
55                .map_err(|e| format!("primary key '{}': {}", self.primary_key.name, e))?;
56        }
57        if row.entries.len() != self.fields.len() {
58            return Err(format!(
59                "field count mismatch: expected {}, got {}",
60                self.fields.len(),
61                row.entries.len()
62            ));
63        }
64        for (entry, ty) in row.entries.iter().zip(self.fields.iter()) {
65            validate_value_detailed(entry, &ty.field_type, type_definitions)
66                .map_err(|e| format!("field '{}': {}", ty.name, e))?;
67        }
68        Ok(())
69    }
70}