liminal_sdk/types.rs
1use alloc::borrow::Cow;
2
3/// Schema metadata supplied by user-defined message types.
4///
5/// The SDK uses this metadata to let concrete channel implementations validate
6/// outbound payloads against the channel's declared type. The trait that returns
7/// this value is intentionally metadata-only: it does not parse schemas or run
8/// validation itself.
9#[derive(Clone, Debug, PartialEq, Eq)]
10pub struct SchemaMetadata {
11 /// Stable message schema name.
12 pub name: Cow<'static, str>,
13 /// Stable message schema version.
14 pub version: Cow<'static, str>,
15 /// Encoded schema definition bytes.
16 pub schema: Cow<'static, [u8]>,
17}
18
19impl SchemaMetadata {
20 /// Creates schema metadata from a name, version, and schema bytes.
21 #[must_use]
22 pub fn new(
23 name: impl Into<Cow<'static, str>>,
24 version: impl Into<Cow<'static, str>>,
25 schema: impl Into<Cow<'static, [u8]>>,
26 ) -> Self {
27 Self {
28 name: name.into(),
29 version: version.into(),
30 schema: schema.into(),
31 }
32 }
33}
34
35/// Compile-time marker for message types that declare schema metadata.
36///
37/// Publishing methods require this trait in addition to [`serde::Serialize`].
38/// That bound ensures a type that is merely serializable cannot be published to
39/// a typed liminal channel unless it also declares the schema metadata needed by
40/// the bus for publish-time validation.
41///
42/// Implement the trait manually today:
43///
44/// ```
45/// use liminal_sdk::{SchemaMetadata, SchemaValidate};
46/// use serde::Serialize;
47///
48/// #[derive(Serialize)]
49/// struct Created {
50/// id: String,
51/// }
52///
53/// impl SchemaValidate for Created {
54/// fn schema_metadata() -> SchemaMetadata {
55/// SchemaMetadata::new(
56/// "example.created",
57/// "1",
58/// br#"{"type":"object","required":["id"]}"#.as_slice(),
59/// )
60/// }
61/// }
62/// ```
63///
64/// A future `#[derive(SchemaValidate)]` macro is expected to generate this same
65/// implementation for supported schema-generation workflows. This crate does
66/// not provide a blanket implementation for all serializable types because doing
67/// so would remove the compile-time enforcement required by typed channels.
68pub trait SchemaValidate {
69 /// Returns this message type's schema metadata.
70 #[must_use]
71 fn schema_metadata() -> SchemaMetadata;
72}