Skip to main content

tpack_core/
schema.rs

1use alloc::{borrow::Cow, boxed::Box, string::String, sync::Arc, vec::Vec};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum EnvelopeMode {
5    FullSchema,
6    FullSchemaWithId,
7    SchemaRef,
8}
9
10impl EnvelopeMode {
11    pub fn tag(self) -> u8 {
12        match self {
13            EnvelopeMode::FullSchema => 0x00,
14            EnvelopeMode::FullSchemaWithId => 0x01,
15            EnvelopeMode::SchemaRef => 0x02,
16        }
17    }
18}
19
20#[derive(Debug, Clone, PartialEq, Eq, Hash)]
21pub struct SchemaId<'de>(pub Cow<'de, [u8]>);
22
23impl<'de> SchemaId<'de> {
24    pub fn borrowed(bytes: &'de [u8]) -> Self {
25        Self(Cow::Borrowed(bytes))
26    }
27
28    pub fn owned(bytes: Vec<u8>) -> Self {
29        Self(Cow::Owned(bytes))
30    }
31
32    pub fn as_bytes(&self) -> &[u8] {
33        self.0.as_ref()
34    }
35}
36
37#[derive(Debug, Clone, PartialEq)]
38pub struct Message<'de> {
39    pub envelope: Envelope<'de>,
40    pub schema: Arc<Schema>,
41    pub value: crate::TpackValue<'de>,
42}
43
44#[derive(Debug, Clone, PartialEq)]
45pub struct Envelope<'de> {
46    pub mode: EnvelopeMode,
47    pub schema_id: Option<SchemaId<'de>>,
48    pub used_cached_schema: bool,
49}
50
51#[derive(Debug, Clone, PartialEq, Eq)]
52pub struct Schema {
53    pub root: TypeDescriptor,
54}
55
56impl Schema {
57    pub fn new(root: TypeDescriptor) -> Self {
58        Self { root }
59    }
60}
61
62#[derive(Debug, Clone, PartialEq, Eq)]
63pub enum TypeDescriptor {
64    Null,
65    Bool,
66    I8,
67    I16,
68    I32,
69    I64,
70    U8,
71    U16,
72    U32,
73    U64,
74    F32,
75    F64,
76    Decimal,
77    DecimalFixed {
78        precision: u64,
79        scale: u64,
80    },
81    String {
82        max_len: Option<u64>,
83    },
84    Bytes {
85        max_len: Option<u64>,
86    },
87    Date,
88    Time,
89    DateTime,
90    DateTimeTz,
91    Timestamp(TimestampPrecision),
92    Duration,
93    BigInt,
94    BigUInt,
95    CalendarInterval,
96    Struct(Vec<Field>),
97    List {
98        max_count: Option<u64>,
99        element: Box<TypeDescriptor>,
100    },
101    Map {
102        max_count: Option<u64>,
103        key: Box<TypeDescriptor>,
104        value: Box<TypeDescriptor>,
105    },
106    Union(Vec<Variant>),
107    Enum(Vec<String>),
108    Optional(Box<TypeDescriptor>),
109    Extension {
110        authority: String,
111        type_name: String,
112        schema_params: Vec<u8>,
113    },
114}
115
116impl TypeDescriptor {
117    pub fn is_composite(&self) -> bool {
118        matches!(
119            self,
120            Self::Struct(_)
121                | Self::List { .. }
122                | Self::Map { .. }
123                | Self::Union(_)
124                | Self::Enum(_)
125                | Self::Optional(_)
126        )
127    }
128
129    pub fn struct_field(&self, field_id: u64) -> Option<&Field> {
130        match self {
131            Self::Struct(fields) => fields.iter().find(|field| field.id == field_id),
132            _ => None,
133        }
134    }
135
136    pub fn list_element(&self) -> Option<&TypeDescriptor> {
137        match self {
138            Self::List { element, .. } => Some(element.as_ref()),
139            _ => None,
140        }
141    }
142
143    pub fn map_key_value(&self) -> Option<(&TypeDescriptor, &TypeDescriptor)> {
144        match self {
145            Self::Map { key, value, .. } => Some((key.as_ref(), value.as_ref())),
146            _ => None,
147        }
148    }
149
150    pub fn union_variant(&self, index: u64) -> Option<&Variant> {
151        match self {
152            Self::Union(variants) => usize::try_from(index)
153                .ok()
154                .and_then(|index| variants.get(index)),
155            _ => None,
156        }
157    }
158
159    pub fn optional_inner(&self) -> Option<&TypeDescriptor> {
160        match self {
161            Self::Optional(inner) => Some(inner.as_ref()),
162            _ => None,
163        }
164    }
165
166    pub fn type_label(&self) -> &'static str {
167        match self {
168            Self::Null => "Null",
169            Self::Bool => "Bool",
170            Self::I8 => "I8",
171            Self::I16 => "I16",
172            Self::I32 => "I32",
173            Self::I64 => "I64",
174            Self::U8 => "U8",
175            Self::U16 => "U16",
176            Self::U32 => "U32",
177            Self::U64 => "U64",
178            Self::F32 => "F32",
179            Self::F64 => "F64",
180            Self::Decimal => "Decimal",
181            Self::DecimalFixed { .. } => "Decimal(P,S)",
182            Self::String { .. } => "String",
183            Self::Bytes { .. } => "Bytes",
184            Self::Date => "Date",
185            Self::Time => "Time",
186            Self::DateTime => "DateTime",
187            Self::DateTimeTz => "DateTimeTZ",
188            Self::Timestamp(_) => "Timestamp(P)",
189            Self::Duration => "Duration",
190            Self::BigInt => "BigInt",
191            Self::BigUInt => "BigUInt",
192            Self::CalendarInterval => "CalendarInterval",
193            Self::Struct(_) => "Struct",
194            Self::List { .. } => "List",
195            Self::Map { .. } => "Map",
196            Self::Union(_) => "Union",
197            Self::Enum(_) => "Enum",
198            Self::Optional(_) => "Optional",
199            Self::Extension { .. } => "Extension",
200        }
201    }
202}
203
204#[derive(Debug, Clone, PartialEq, Eq)]
205pub struct Field {
206    pub id: u64,
207    pub name: String,
208    pub ty: TypeDescriptor,
209}
210
211impl Field {
212    pub fn new(id: u64, name: impl Into<String>, ty: TypeDescriptor) -> Self {
213        Self {
214            id,
215            name: name.into(),
216            ty,
217        }
218    }
219}
220
221#[derive(Debug, Clone, PartialEq, Eq)]
222pub struct Variant {
223    pub name: String,
224    pub ty: TypeDescriptor,
225}
226
227impl Variant {
228    pub fn new(name: impl Into<String>, ty: TypeDescriptor) -> Self {
229        Self {
230            name: name.into(),
231            ty,
232        }
233    }
234}
235
236#[derive(Debug, Clone, Copy, PartialEq, Eq)]
237pub enum TimestampPrecision {
238    Seconds,
239    Milliseconds,
240    Microseconds,
241    Nanoseconds,
242}
243
244impl TimestampPrecision {
245    pub fn tag(self) -> u8 {
246        match self {
247            TimestampPrecision::Seconds => 0,
248            TimestampPrecision::Milliseconds => 1,
249            TimestampPrecision::Microseconds => 2,
250            TimestampPrecision::Nanoseconds => 3,
251        }
252    }
253}
254
255#[derive(Debug, Clone, Copy, PartialEq, Eq)]
256pub struct Duration {
257    pub seconds: i64,
258    pub nanos: i64,
259}
260
261#[derive(Debug, Clone, Copy, PartialEq, Eq)]
262pub struct CalendarInterval {
263    pub months: i64,
264    pub days: i64,
265    pub nanos: i64,
266}
267
268#[derive(Debug, Clone, Copy, PartialEq, Eq)]
269pub struct Decimal {
270    pub scale: i64,
271    pub coefficient: i64,
272}