1pub mod errors;
4pub mod injector;
5pub mod manifest;
6pub mod page;
7pub mod procedure;
8pub mod server;
9
10pub use errors::SeamError;
12pub use procedure::{BoxFuture, BoxStream, ProcedureDef, SubscriptionDef};
13pub use seam_macros::{seam_procedure, seam_subscription, SeamType};
14pub use server::SeamServer;
15
16pub trait SeamType {
19 fn jtd_schema() -> serde_json::Value;
20}
21
22macro_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}