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}