Skip to main content

seam_server/
lib.rs

1/* packages/server/core/rust/src/lib.rs */
2
3pub mod errors;
4pub mod injector;
5pub mod manifest;
6pub mod page;
7pub mod procedure;
8pub mod server;
9
10// Re-exports for ergonomic use
11pub use errors::SeamError;
12pub use procedure::{BoxFuture, BoxStream, ProcedureDef, SubscriptionDef};
13pub use seam_macros::{seam_procedure, seam_subscription, SeamType};
14pub use server::SeamServer;
15
16/// Trait for types that can describe themselves as a JTD schema.
17/// Derive with `#[derive(SeamType)]` or implement manually.
18pub trait SeamType {
19  fn jtd_schema() -> serde_json::Value;
20}
21
22// -- Primitive SeamType impls --
23
24macro_rules! impl_seam_type_primitive {
25  ($rust_ty:ty, $jtd:expr) => {
26    impl SeamType for $rust_ty {
27      fn jtd_schema() -> serde_json::Value {
28        serde_json::json!({ "type": $jtd })
29      }
30    }
31  };
32}
33
34impl_seam_type_primitive!(String, "string");
35impl_seam_type_primitive!(bool, "boolean");
36impl_seam_type_primitive!(i8, "int8");
37impl_seam_type_primitive!(i16, "int16");
38impl_seam_type_primitive!(i32, "int32");
39impl_seam_type_primitive!(u8, "uint8");
40impl_seam_type_primitive!(u16, "uint16");
41impl_seam_type_primitive!(u32, "uint32");
42impl_seam_type_primitive!(f32, "float32");
43impl_seam_type_primitive!(f64, "float64");
44
45impl<T: SeamType> SeamType for Vec<T> {
46  fn jtd_schema() -> serde_json::Value {
47    serde_json::json!({ "elements": T::jtd_schema() })
48  }
49}
50
51impl<T: SeamType> SeamType for Option<T> {
52  fn jtd_schema() -> serde_json::Value {
53    let mut schema = T::jtd_schema();
54    if let Some(obj) = schema.as_object_mut() {
55      obj.insert("nullable".to_string(), serde_json::Value::Bool(true));
56    }
57    schema
58  }
59}
60
61impl<T: SeamType> SeamType for std::collections::HashMap<String, T> {
62  fn jtd_schema() -> serde_json::Value {
63    serde_json::json!({ "values": T::jtd_schema() })
64  }
65}
66
67impl<T: SeamType> SeamType for std::collections::BTreeMap<String, T> {
68  fn jtd_schema() -> serde_json::Value {
69    serde_json::json!({ "values": T::jtd_schema() })
70  }
71}
72
73#[cfg(test)]
74extern crate self as seam_server;
75
76#[cfg(test)]
77mod tests {
78  use super::*;
79
80  #[test]
81  fn primitive_schemas() {
82    assert_eq!(String::jtd_schema(), serde_json::json!({"type": "string"}));
83    assert_eq!(bool::jtd_schema(), serde_json::json!({"type": "boolean"}));
84    assert_eq!(i32::jtd_schema(), serde_json::json!({"type": "int32"}));
85    assert_eq!(u32::jtd_schema(), serde_json::json!({"type": "uint32"}));
86    assert_eq!(f64::jtd_schema(), serde_json::json!({"type": "float64"}));
87  }
88
89  #[test]
90  fn vec_schema() {
91    assert_eq!(Vec::<String>::jtd_schema(), serde_json::json!({"elements": {"type": "string"}}),);
92  }
93
94  #[test]
95  fn option_schema() {
96    assert_eq!(
97      Option::<String>::jtd_schema(),
98      serde_json::json!({"type": "string", "nullable": true}),
99    );
100  }
101
102  #[test]
103  fn hashmap_schema() {
104    assert_eq!(
105      std::collections::HashMap::<String, f64>::jtd_schema(),
106      serde_json::json!({"values": {"type": "float64"}}),
107    );
108  }
109
110  #[derive(SeamType)]
111  #[allow(dead_code)]
112  enum Role {
113    Admin,
114    Member,
115    Guest,
116  }
117
118  #[test]
119  fn enum_schema() {
120    assert_eq!(Role::jtd_schema(), serde_json::json!({"enum": ["admin", "member", "guest"]}),);
121  }
122}