1use super::types::{
4 DataType, DateTimeValue, DateValue, DecimalValue, TimeValue, TimeWithTimeZoneValue, Value,
5};
6use super::ColumnId;
7use crate::error::HematiteError;
8
9#[derive(Debug, Clone)]
10pub struct Column {
11 pub id: ColumnId,
12 pub name: String,
13 pub data_type: DataType,
14 pub character_set: Option<String>,
15 pub collation: Option<String>,
16 pub nullable: bool,
17 pub primary_key: bool,
18 pub auto_increment: bool,
19 pub default_value: Option<Value>,
20}
21
22impl Column {
23 pub fn new(id: ColumnId, name: String, data_type: DataType) -> Self {
24 Self {
25 id,
26 name,
27 data_type,
28 character_set: None,
29 collation: None,
30 nullable: true,
31 primary_key: false,
32 auto_increment: false,
33 default_value: None,
34 }
35 }
36
37 pub fn nullable(mut self, nullable: bool) -> Self {
38 self.nullable = nullable;
39 self
40 }
41
42 pub fn primary_key(mut self, primary_key: bool) -> Self {
43 self.primary_key = primary_key;
44 if primary_key {
45 self.nullable = false;
46 }
47 self
48 }
49
50 pub fn auto_increment(mut self, auto_increment: bool) -> Self {
51 self.auto_increment = auto_increment;
52 if auto_increment {
53 self.nullable = false;
54 }
55 self
56 }
57
58 pub fn default_value(mut self, value: Value) -> Self {
59 self.default_value = Some(value);
60 self
61 }
62
63 pub fn character_set(mut self, character_set: Option<String>) -> Self {
64 self.character_set = character_set;
65 self
66 }
67
68 pub fn collation(mut self, collation: Option<String>) -> Self {
69 self.collation = collation;
70 self
71 }
72
73 pub fn validate_value(&self, value: &Value) -> bool {
74 if value.is_null() {
75 return self.nullable;
76 }
77
78 if !value.is_compatible_with(self.data_type.clone()) {
79 return false;
80 }
81
82 match (&self.data_type, value) {
83 (DataType::Int8, Value::Integer(value)) => i8::try_from(*value).is_ok(),
84 (DataType::Int16, Value::Integer(value)) => i16::try_from(*value).is_ok(),
85 (DataType::UInt8, Value::UInteger(value)) => u8::try_from(*value).is_ok(),
86 (DataType::UInt16, Value::UInteger(value)) => u16::try_from(*value).is_ok(),
87 (DataType::Char(length), Value::Text(text)) => text.chars().count() == *length as usize,
88 (DataType::VarChar(length), Value::Text(text)) => {
89 text.chars().count() <= *length as usize
90 }
91 (DataType::Binary(length), Value::Blob(bytes)) => bytes.len() == *length as usize,
92 (DataType::VarBinary(length), Value::Blob(bytes)) => bytes.len() <= *length as usize,
93 (DataType::Enum(values), Value::Enum(value)) => values.contains(value),
94 (DataType::Decimal { precision, scale }, Value::Decimal(value)) => {
95 value.fits_precision_scale(*precision, *scale)
96 }
97 _ => true,
98 }
99 }
100
101 pub fn get_default_or_null(&self) -> Value {
102 match &self.default_value {
103 Some(value) => value.clone(),
104 None => {
105 if self.nullable {
106 Value::Null
107 } else {
108 match &self.data_type {
109 DataType::Int8 | DataType::Int16 | DataType::Int => Value::Integer(0),
110 DataType::Int64 => Value::BigInt(0),
111 DataType::Int128 => Value::Int128(0),
112 DataType::UInt8 | DataType::UInt16 | DataType::UInt => Value::UInteger(0),
113 DataType::UInt64 => Value::UBigInt(0),
114 DataType::UInt128 => Value::UInt128(0),
115 DataType::Text => Value::Text(String::new()),
116 DataType::Char(length) => Value::Text(pad_text_to_char_length("", *length)),
117 DataType::VarChar(_) => Value::Text(String::new()),
118 DataType::Binary(length) => Value::Blob(vec![0; *length as usize]),
119 DataType::VarBinary(_) | DataType::Blob => Value::Blob(Vec::new()),
120 DataType::Enum(values) => {
121 Value::Enum(values.first().cloned().unwrap_or_default())
122 }
123 DataType::Boolean => Value::Boolean(false),
124 DataType::Float32 => Value::Float32(0.0),
125 DataType::Float => Value::Float(0.0),
126 DataType::Decimal { .. } => Value::Decimal(DecimalValue::zero()),
127 DataType::Date => Value::Date(DateValue::epoch()),
128 DataType::Time => Value::Time(TimeValue::midnight()),
129 DataType::DateTime => Value::DateTime(DateTimeValue::epoch()),
130 DataType::TimeWithTimeZone => {
131 Value::TimeWithTimeZone(TimeWithTimeZoneValue::utc_midnight())
132 }
133 DataType::IntervalYearMonth | DataType::IntervalDaySecond => {
134 panic!("interval runtime types are not valid column data types")
135 }
136 }
137 }
138 }
139 }
140 }
141
142 pub fn size(&self) -> usize {
143 self.data_type.size()
144 }
145
146 pub fn serialize(&self, buffer: &mut Vec<u8>) -> Result<(), HematiteError> {
147 buffer.extend_from_slice(&self.id.as_u32().to_le_bytes());
148
149 let name_bytes = self.name.as_bytes();
150 buffer.extend_from_slice(&(name_bytes.len() as u32).to_le_bytes());
151 buffer.extend_from_slice(name_bytes);
152
153 write_data_type(buffer, &self.data_type);
154
155 let mut flags = 0;
156 if self.nullable {
157 flags |= 0x01;
158 }
159 if self.primary_key {
160 flags |= 0x02;
161 }
162 if self.auto_increment {
163 flags |= 0x04;
164 }
165 if self.character_set.is_some() {
166 flags |= 0x08;
167 }
168 if self.collation.is_some() {
169 flags |= 0x10;
170 }
171 buffer.push(flags);
172
173 if let Some(character_set) = &self.character_set {
174 write_string(buffer, character_set);
175 }
176 if let Some(collation) = &self.collation {
177 write_string(buffer, collation);
178 }
179 write_optional_value(buffer, self.default_value.as_ref());
180 Ok(())
181 }
182
183 pub fn deserialize(buffer: &[u8], offset: &mut usize) -> Result<Self, HematiteError> {
184 if *offset + 4 > buffer.len() {
185 return Err(HematiteError::CorruptedData(
186 "Invalid column data".to_string(),
187 ));
188 }
189
190 let id = ColumnId::new(u32::from_le_bytes(
191 buffer[*offset..*offset + 4]
192 .try_into()
193 .map_err(|_| HematiteError::CorruptedData("Invalid column id".to_string()))?,
194 ));
195 *offset += 4;
196
197 let name_len = read_u32(buffer, offset, "column name length")? as usize;
198 if *offset + name_len > buffer.len() {
199 return Err(HematiteError::CorruptedData(
200 "Invalid column name".to_string(),
201 ));
202 }
203 let name =
204 String::from_utf8(buffer[*offset..*offset + name_len].to_vec()).map_err(|_| {
205 HematiteError::CorruptedData("Invalid UTF-8 in column name".to_string())
206 })?;
207 *offset += name_len;
208
209 let data_type = read_data_type(buffer, offset)?;
210
211 if *offset >= buffer.len() {
212 return Err(HematiteError::CorruptedData(
213 "Invalid column flags".to_string(),
214 ));
215 }
216 let flags = buffer[*offset];
217 *offset += 1;
218 let nullable = (flags & 0x01) != 0;
219 let primary_key = (flags & 0x02) != 0;
220 let auto_increment = (flags & 0x04) != 0;
221 let character_set = if (flags & 0x08) != 0 {
222 Some(read_string(buffer, offset, "column character set")?)
223 } else {
224 None
225 };
226 let collation = if (flags & 0x10) != 0 {
227 Some(read_string(buffer, offset, "column collation")?)
228 } else {
229 None
230 };
231
232 let default_value = read_optional_value(buffer, offset)?;
233
234 Ok(Self {
235 id,
236 name,
237 data_type,
238 character_set,
239 collation,
240 nullable,
241 primary_key,
242 auto_increment,
243 default_value,
244 })
245 }
246}
247
248pub(crate) fn pad_text_to_char_length(value: &str, length: u32) -> String {
249 let char_count = value.chars().count();
250 if char_count >= length as usize {
251 value.to_string()
252 } else {
253 let mut padded = String::with_capacity(value.len() + (length as usize - char_count));
254 padded.push_str(value);
255 padded.push_str(&" ".repeat(length as usize - char_count));
256 padded
257 }
258}
259
260pub(crate) fn pad_binary_to_length(value: &[u8], length: u32) -> Vec<u8> {
261 let mut padded = value.to_vec();
262 padded.resize(length as usize, 0);
263 padded
264}
265
266pub(crate) fn normalize_text_for_collation(value: &str, collation: Option<&str>) -> String {
267 if collation_is_nocase(collation) {
268 value.to_lowercase()
269 } else {
270 value.to_string()
271 }
272}
273
274pub(crate) fn collation_is_nocase(collation: Option<&str>) -> bool {
275 let Some(collation) = collation else {
276 return false;
277 };
278 let normalized = collation.to_ascii_lowercase();
279 normalized == "nocase" || normalized.ends_with("_nocase")
280}
281
282fn write_data_type(buffer: &mut Vec<u8>, data_type: &DataType) {
283 match data_type {
284 DataType::Int8 => buffer.push(0),
285 DataType::Int16 => buffer.push(1),
286 DataType::Int => buffer.push(2),
287 DataType::Int64 => buffer.push(3),
288 DataType::UInt8 => buffer.push(22),
289 DataType::UInt16 => buffer.push(23),
290 DataType::Int128 => buffer.push(24),
291 DataType::UInt => buffer.push(25),
292 DataType::UInt64 => buffer.push(26),
293 DataType::UInt128 => buffer.push(27),
294 DataType::Text => buffer.push(4),
295 DataType::Char(length) => {
296 buffer.push(5);
297 buffer.extend_from_slice(&length.to_le_bytes());
298 }
299 DataType::VarChar(length) => {
300 buffer.push(6);
301 buffer.extend_from_slice(&length.to_le_bytes());
302 }
303 DataType::Binary(length) => {
304 buffer.push(7);
305 buffer.extend_from_slice(&length.to_le_bytes());
306 }
307 DataType::VarBinary(length) => {
308 buffer.push(8);
309 buffer.extend_from_slice(&length.to_le_bytes());
310 }
311 DataType::Enum(values) => {
312 buffer.push(9);
313 buffer.extend_from_slice(&(values.len() as u32).to_le_bytes());
314 for value in values {
315 buffer.extend_from_slice(&(value.len() as u32).to_le_bytes());
316 buffer.extend_from_slice(value.as_bytes());
317 }
318 }
319 DataType::Boolean => buffer.push(10),
320 DataType::Float => buffer.push(11),
321 DataType::Float32 => buffer.push(12),
322 DataType::Decimal { precision, scale } => {
323 buffer.push(14);
324 write_optional_u32(buffer, *precision);
325 write_optional_u32(buffer, *scale);
326 }
327 DataType::Blob => buffer.push(16),
328 DataType::Date => buffer.push(17),
329 DataType::Time => buffer.push(18),
330 DataType::DateTime => buffer.push(19),
331 DataType::TimeWithTimeZone => buffer.push(21),
332 DataType::IntervalYearMonth | DataType::IntervalDaySecond => {
333 panic!("interval runtime types cannot be serialized as column data types")
334 }
335 }
336}
337
338fn read_data_type(buffer: &[u8], offset: &mut usize) -> Result<DataType, HematiteError> {
339 if *offset >= buffer.len() {
340 return Err(HematiteError::CorruptedData(
341 "Invalid column data type".to_string(),
342 ));
343 }
344
345 let tag = buffer[*offset];
346 *offset += 1;
347
348 Ok(match tag {
349 0 => DataType::Int8,
350 1 => DataType::Int16,
351 2 => DataType::Int,
352 3 => DataType::Int64,
353 22 => DataType::UInt8,
354 23 => DataType::UInt16,
355 4 => DataType::Text,
356 5 => DataType::Char(read_u32(buffer, offset, "CHAR length")?),
357 6 => DataType::VarChar(read_u32(buffer, offset, "VARCHAR length")?),
358 7 => DataType::Binary(read_u32(buffer, offset, "BINARY length")?),
359 8 => DataType::VarBinary(read_u32(buffer, offset, "VARBINARY length")?),
360 9 => {
361 let count = read_u32(buffer, offset, "ENUM value count")? as usize;
362 let mut values = Vec::with_capacity(count);
363 for _ in 0..count {
364 let len = read_u32(buffer, offset, "ENUM value length")? as usize;
365 let bytes = read_fixed(buffer, offset, len, "ENUM value")?;
366 let value = String::from_utf8(bytes.to_vec()).map_err(|_| {
367 HematiteError::CorruptedData("Invalid UTF-8 in ENUM value".to_string())
368 })?;
369 values.push(value);
370 }
371 DataType::Enum(values)
372 }
373 10 => DataType::Boolean,
374 11 => DataType::Float,
375 12 => DataType::Float32,
376 14 => DataType::Decimal {
377 precision: read_optional_u32(buffer, offset, "DECIMAL precision")?,
378 scale: read_optional_u32(buffer, offset, "DECIMAL scale")?,
379 },
380 16 => DataType::Blob,
381 17 => DataType::Date,
382 18 => DataType::Time,
383 19 => DataType::DateTime,
384 21 => DataType::TimeWithTimeZone,
385 24 => DataType::Int128,
386 25 => DataType::UInt,
387 26 => DataType::UInt64,
388 27 => DataType::UInt128,
389 _ => {
390 return Err(HematiteError::CorruptedData(
391 "Invalid data type".to_string(),
392 ))
393 }
394 })
395}
396
397fn write_optional_u32(buffer: &mut Vec<u8>, value: Option<u32>) {
398 buffer.extend_from_slice(&value.unwrap_or(u32::MAX).to_le_bytes());
399}
400
401fn write_string(buffer: &mut Vec<u8>, value: &str) {
402 buffer.extend_from_slice(&(value.len() as u32).to_le_bytes());
403 buffer.extend_from_slice(value.as_bytes());
404}
405
406fn read_optional_u32(
407 buffer: &[u8],
408 offset: &mut usize,
409 label: &str,
410) -> Result<Option<u32>, HematiteError> {
411 let value = read_u32(buffer, offset, label)?;
412 if value == u32::MAX {
413 Ok(None)
414 } else {
415 Ok(Some(value))
416 }
417}
418
419fn read_u32(buffer: &[u8], offset: &mut usize, label: &str) -> Result<u32, HematiteError> {
420 if *offset + 4 > buffer.len() {
421 return Err(HematiteError::CorruptedData(format!("Invalid {label}")));
422 }
423 let value = u32::from_le_bytes(
424 buffer[*offset..*offset + 4]
425 .try_into()
426 .map_err(|_| HematiteError::CorruptedData(format!("Invalid {label}")))?,
427 );
428 *offset += 4;
429 Ok(value)
430}
431
432fn read_string(buffer: &[u8], offset: &mut usize, label: &str) -> Result<String, HematiteError> {
433 let len = read_u32(buffer, offset, label)? as usize;
434 let bytes = read_fixed(buffer, offset, len, label)?;
435 String::from_utf8(bytes.to_vec())
436 .map_err(|_| HematiteError::CorruptedData(format!("Invalid UTF-8 in {label}")))
437}
438
439fn write_optional_value(buffer: &mut Vec<u8>, value: Option<&Value>) {
440 match value {
441 None => buffer.push(255),
442 Some(Value::Integer(value)) => {
443 buffer.push(0);
444 buffer.extend_from_slice(&value.to_le_bytes());
445 }
446 Some(Value::Text(value)) => {
447 buffer.push(1);
448 buffer.extend_from_slice(&(value.len() as u32).to_le_bytes());
449 buffer.extend_from_slice(value.as_bytes());
450 }
451 Some(Value::Enum(value)) => {
452 buffer.push(10);
453 buffer.extend_from_slice(&(value.len() as u32).to_le_bytes());
454 buffer.extend_from_slice(value.as_bytes());
455 }
456 Some(Value::Boolean(value)) => {
457 buffer.push(2);
458 buffer.push(u8::from(*value));
459 }
460 Some(Value::Float(value)) => {
461 buffer.push(3);
462 buffer.extend_from_slice(&value.to_le_bytes());
463 }
464 Some(Value::Float32(value)) => {
465 buffer.push(20);
466 buffer.extend_from_slice(&value.to_le_bytes());
467 }
468 Some(Value::BigInt(value)) => {
469 buffer.push(4);
470 buffer.extend_from_slice(&value.to_le_bytes());
471 }
472 Some(Value::Int128(value)) => {
473 buffer.push(16);
474 buffer.extend_from_slice(&value.to_le_bytes());
475 }
476 Some(Value::UInteger(value)) => {
477 buffer.push(17);
478 buffer.extend_from_slice(&value.to_le_bytes());
479 }
480 Some(Value::UBigInt(value)) => {
481 buffer.push(18);
482 buffer.extend_from_slice(&value.to_le_bytes());
483 }
484 Some(Value::UInt128(value)) => {
485 buffer.push(19);
486 buffer.extend_from_slice(&value.to_le_bytes());
487 }
488 Some(Value::Decimal(value)) => {
489 buffer.push(5);
490 let text = value.to_string();
491 buffer.extend_from_slice(&(text.len() as u32).to_le_bytes());
492 buffer.extend_from_slice(text.as_bytes());
493 }
494 Some(Value::Blob(value)) => {
495 buffer.push(6);
496 buffer.extend_from_slice(&(value.len() as u32).to_le_bytes());
497 buffer.extend_from_slice(value);
498 }
499 Some(Value::Date(value)) => {
500 buffer.push(7);
501 buffer.extend_from_slice(&value.days_since_epoch().to_le_bytes());
502 }
503 Some(Value::Time(value)) => {
504 buffer.push(11);
505 buffer.extend_from_slice(&value.seconds_since_midnight().to_le_bytes());
506 }
507 Some(Value::DateTime(value)) => {
508 buffer.push(8);
509 buffer.extend_from_slice(&value.seconds_since_epoch().to_le_bytes());
510 }
511 Some(Value::TimeWithTimeZone(value)) => {
512 buffer.push(13);
513 buffer.extend_from_slice(&value.seconds_since_midnight().to_le_bytes());
514 buffer.extend_from_slice(&value.offset_minutes().to_le_bytes());
515 }
516 Some(Value::IntervalYearMonth(value)) => {
517 buffer.push(14);
518 buffer.extend_from_slice(&value.total_months().to_le_bytes());
519 }
520 Some(Value::IntervalDaySecond(value)) => {
521 buffer.push(15);
522 buffer.extend_from_slice(&value.total_seconds().to_le_bytes());
523 }
524 Some(Value::Null) => buffer.push(9),
525 }
526}
527
528fn read_optional_value(buffer: &[u8], offset: &mut usize) -> Result<Option<Value>, HematiteError> {
529 if *offset >= buffer.len() {
530 return Err(HematiteError::CorruptedData(
531 "Invalid default value".to_string(),
532 ));
533 }
534
535 let tag = buffer[*offset];
536 *offset += 1;
537 Ok(match tag {
538 0 => {
539 let value = i32::from_le_bytes(
540 read_fixed(buffer, offset, 4, "default integer")?
541 .try_into()
542 .unwrap(),
543 );
544 Some(Value::Integer(value))
545 }
546 1 => {
547 let len = read_u32(buffer, offset, "default text length")? as usize;
548 let bytes = read_fixed(buffer, offset, len, "default text")?;
549 let text = String::from_utf8(bytes.to_vec()).map_err(|_| {
550 HematiteError::CorruptedData("Invalid UTF-8 in default text".to_string())
551 })?;
552 Some(Value::Text(text))
553 }
554 10 => {
555 let len = read_u32(buffer, offset, "default enum length")? as usize;
556 let bytes = read_fixed(buffer, offset, len, "default enum")?;
557 let text = String::from_utf8(bytes.to_vec()).map_err(|_| {
558 HematiteError::CorruptedData("Invalid UTF-8 in default enum".to_string())
559 })?;
560 Some(Value::Enum(text))
561 }
562 2 => {
563 let value = read_fixed(buffer, offset, 1, "default boolean")?[0] != 0;
564 Some(Value::Boolean(value))
565 }
566 3 => {
567 let value = f64::from_le_bytes(
568 read_fixed(buffer, offset, 8, "default float")?
569 .try_into()
570 .unwrap(),
571 );
572 Some(Value::Float(value))
573 }
574 20 => {
575 let value = f32::from_le_bytes(
576 read_fixed(buffer, offset, 4, "default float32")?
577 .try_into()
578 .unwrap(),
579 );
580 Some(Value::Float32(value))
581 }
582 4 => {
583 let value = i64::from_le_bytes(
584 read_fixed(buffer, offset, 8, "default bigint")?
585 .try_into()
586 .unwrap(),
587 );
588 Some(Value::BigInt(value))
589 }
590 5 => {
591 let len = read_u32(buffer, offset, "default decimal length")? as usize;
592 let bytes = read_fixed(buffer, offset, len, "default decimal")?;
593 let text = String::from_utf8(bytes.to_vec()).map_err(|_| {
594 HematiteError::CorruptedData("Invalid UTF-8 in default decimal".to_string())
595 })?;
596 Some(Value::Decimal(DecimalValue::parse(&text).map_err(
597 |_| HematiteError::CorruptedData("Invalid default decimal".to_string()),
598 )?))
599 }
600 6 => {
601 let len = read_u32(buffer, offset, "default blob length")? as usize;
602 Some(Value::Blob(
603 read_fixed(buffer, offset, len, "default blob")?.to_vec(),
604 ))
605 }
606 16 => {
607 let value = i128::from_le_bytes(
608 read_fixed(buffer, offset, 16, "default int128")?
609 .try_into()
610 .unwrap(),
611 );
612 Some(Value::Int128(value))
613 }
614 17 => {
615 let value = u32::from_le_bytes(
616 read_fixed(buffer, offset, 4, "default uint")?
617 .try_into()
618 .unwrap(),
619 );
620 Some(Value::UInteger(value))
621 }
622 18 => {
623 let value = u64::from_le_bytes(
624 read_fixed(buffer, offset, 8, "default uint64")?
625 .try_into()
626 .unwrap(),
627 );
628 Some(Value::UBigInt(value))
629 }
630 19 => {
631 let value = u128::from_le_bytes(
632 read_fixed(buffer, offset, 16, "default uint128")?
633 .try_into()
634 .unwrap(),
635 );
636 Some(Value::UInt128(value))
637 }
638 7 => {
639 let days = i32::from_le_bytes(
640 read_fixed(buffer, offset, 4, "default date")?
641 .try_into()
642 .unwrap(),
643 );
644 Some(Value::Date(DateValue::from_days_since_epoch(days)))
645 }
646 11 => {
647 let seconds = u32::from_le_bytes(
648 read_fixed(buffer, offset, 4, "default time")?
649 .try_into()
650 .unwrap(),
651 );
652 Some(Value::Time(TimeValue::from_seconds_since_midnight(seconds)))
653 }
654 8 => {
655 let seconds = i64::from_le_bytes(
656 read_fixed(buffer, offset, 8, "default datetime")?
657 .try_into()
658 .unwrap(),
659 );
660 Some(Value::DateTime(DateTimeValue::from_seconds_since_epoch(
661 seconds,
662 )))
663 }
664 13 => {
665 let seconds = u32::from_le_bytes(
666 read_fixed(buffer, offset, 4, "default time with time zone seconds")?
667 .try_into()
668 .unwrap(),
669 );
670 let offset_minutes = i16::from_le_bytes(
671 read_fixed(buffer, offset, 2, "default time with time zone offset")?
672 .try_into()
673 .unwrap(),
674 );
675 Some(Value::TimeWithTimeZone(TimeWithTimeZoneValue::from_parts(
676 seconds,
677 offset_minutes,
678 )))
679 }
680 14 => {
681 let total_months = i32::from_le_bytes(
682 read_fixed(buffer, offset, 4, "default interval year to month")?
683 .try_into()
684 .unwrap(),
685 );
686 Some(Value::IntervalYearMonth(
687 crate::catalog::types::IntervalYearMonthValue::new(total_months),
688 ))
689 }
690 15 => {
691 let total_seconds = i64::from_le_bytes(
692 read_fixed(buffer, offset, 8, "default interval day to second")?
693 .try_into()
694 .unwrap(),
695 );
696 Some(Value::IntervalDaySecond(
697 crate::catalog::types::IntervalDaySecondValue::new(total_seconds),
698 ))
699 }
700 9 => Some(Value::Null),
701 255 => None,
702 _ => {
703 return Err(HematiteError::CorruptedData(
704 "Invalid default value type".to_string(),
705 ))
706 }
707 })
708}
709
710fn read_fixed<'a>(
711 buffer: &'a [u8],
712 offset: &mut usize,
713 len: usize,
714 label: &str,
715) -> Result<&'a [u8], HematiteError> {
716 if *offset + len > buffer.len() {
717 return Err(HematiteError::CorruptedData(format!("Invalid {label}")));
718 }
719 let slice = &buffer[*offset..*offset + len];
720 *offset += len;
721 Ok(slice)
722}