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