1use crate::{
6 db::data::{
7 decode_storage_key_binary_value_bytes, decode_structural_field_by_kind_bytes,
8 decode_structural_value_storage_bytes, encode_storage_key_binary_value_bytes,
9 encode_structural_field_by_kind_bytes, encode_structural_value_storage_bytes,
10 supports_storage_key_binary_kind,
11 },
12 error::InternalError,
13 model::field::{FieldKind, ScalarCodec},
14 traits::{FieldTypeMeta, FieldValue, field_value_vec_from_value},
15 types::{Blob, Date, Duration, Float32, Float64, Principal, Subaccount, Timestamp, Ulid, Unit},
16 value::Value,
17};
18use std::str;
19
20const SCALAR_SLOT_PREFIX: u8 = 0xFF;
21const SCALAR_SLOT_TAG_NULL: u8 = 0;
22const SCALAR_SLOT_TAG_VALUE: u8 = 1;
23
24const SCALAR_BOOL_PAYLOAD_LEN: usize = 1;
25const SCALAR_WORD32_PAYLOAD_LEN: usize = 4;
26const SCALAR_WORD64_PAYLOAD_LEN: usize = 8;
27const SCALAR_ULID_PAYLOAD_LEN: usize = 16;
28const SCALAR_SUBACCOUNT_PAYLOAD_LEN: usize = 32;
29
30const SCALAR_BOOL_FALSE_TAG: u8 = 0;
31const SCALAR_BOOL_TRUE_TAG: u8 = 1;
32
33#[derive(Clone, Copy, Debug)]
43pub enum ScalarValueRef<'a> {
44 Blob(&'a [u8]),
45 Bool(bool),
46 Date(Date),
47 Duration(Duration),
48 Float32(Float32),
49 Float64(Float64),
50 Int(i64),
51 Principal(Principal),
52 Subaccount(Subaccount),
53 Text(&'a str),
54 Timestamp(Timestamp),
55 Uint(u64),
56 Ulid(Ulid),
57 Unit,
58}
59
60impl ScalarValueRef<'_> {
61 #[must_use]
63 pub fn into_value(self) -> Value {
64 match self {
65 Self::Blob(value) => Value::Blob(value.to_vec()),
66 Self::Bool(value) => Value::Bool(value),
67 Self::Date(value) => Value::Date(value),
68 Self::Duration(value) => Value::Duration(value),
69 Self::Float32(value) => Value::Float32(value),
70 Self::Float64(value) => Value::Float64(value),
71 Self::Int(value) => Value::Int(value),
72 Self::Principal(value) => Value::Principal(value),
73 Self::Subaccount(value) => Value::Subaccount(value),
74 Self::Text(value) => Value::Text(value.to_owned()),
75 Self::Timestamp(value) => Value::Timestamp(value),
76 Self::Uint(value) => Value::Uint(value),
77 Self::Ulid(value) => Value::Ulid(value),
78 Self::Unit => Value::Unit,
79 }
80 }
81}
82
83#[derive(Clone, Copy, Debug)]
93pub enum ScalarSlotValueRef<'a> {
94 Null,
95 Value(ScalarValueRef<'a>),
96}
97
98pub trait PersistedScalar: Sized {
108 const CODEC: ScalarCodec;
110
111 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError>;
113
114 fn decode_scalar_payload(bytes: &[u8], field_name: &'static str)
116 -> Result<Self, InternalError>;
117}
118
119pub fn encode_persisted_slot_payload_by_kind<T>(
122 value: &T,
123 kind: FieldKind,
124 field_name: &'static str,
125) -> Result<Vec<u8>, InternalError>
126where
127 T: FieldValue,
128{
129 if supports_storage_key_binary_kind(kind) {
130 return encode_storage_key_binary_value_bytes(kind, &value.to_value(), field_name)?
131 .ok_or_else(|| {
132 InternalError::persisted_row_field_encode_failed(
133 field_name,
134 "storage-key binary lane rejected a supported field kind",
135 )
136 });
137 }
138
139 encode_structural_field_by_kind_bytes(kind, &value.to_value(), field_name)
140 .map_err(|err| InternalError::persisted_row_field_encode_failed(field_name, err))
141}
142
143pub fn encode_persisted_scalar_slot_payload<T>(
145 value: &T,
146 field_name: &'static str,
147) -> Result<Vec<u8>, InternalError>
148where
149 T: PersistedScalar,
150{
151 let payload = value.encode_scalar_payload()?;
152 let mut encoded = Vec::with_capacity(payload.len() + 2);
153 encoded.push(SCALAR_SLOT_PREFIX);
154 encoded.push(SCALAR_SLOT_TAG_VALUE);
155 encoded.extend_from_slice(&payload);
156
157 if encoded.len() < 2 {
158 return Err(InternalError::persisted_row_field_encode_failed(
159 field_name,
160 "scalar payload envelope underflow",
161 ));
162 }
163
164 Ok(encoded)
165}
166
167pub fn encode_persisted_option_scalar_slot_payload<T>(
169 value: &Option<T>,
170 field_name: &'static str,
171) -> Result<Vec<u8>, InternalError>
172where
173 T: PersistedScalar,
174{
175 match value {
176 Some(value) => encode_persisted_scalar_slot_payload(value, field_name),
177 None => Ok(vec![SCALAR_SLOT_PREFIX, SCALAR_SLOT_TAG_NULL]),
178 }
179}
180
181fn decode_persisted_structural_slot_payload_by_kind<T>(
184 bytes: &[u8],
185 kind: FieldKind,
186 field_name: &'static str,
187) -> Result<Option<T>, InternalError>
188where
189 T: FieldValue,
190{
191 let value = if supports_storage_key_binary_kind(kind) {
192 decode_storage_key_binary_value_bytes(bytes, kind)
193 .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?
194 .ok_or_else(|| {
195 InternalError::persisted_row_field_decode_failed(
196 field_name,
197 "storage-key binary lane rejected a supported field kind",
198 )
199 })?
200 } else {
201 decode_structural_field_by_kind_bytes(bytes, kind)
202 .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?
203 };
204
205 if matches!(value, Value::Null) {
206 return Ok(None);
207 }
208
209 T::from_value(&value).map(Some).ok_or_else(|| {
210 InternalError::persisted_row_field_decode_failed(
211 field_name,
212 format!(
213 "value payload does not match {}",
214 std::any::type_name::<T>()
215 ),
216 )
217 })
218}
219
220pub fn decode_persisted_slot_payload_by_kind<T>(
223 bytes: &[u8],
224 kind: FieldKind,
225 field_name: &'static str,
226) -> Result<T, InternalError>
227where
228 T: FieldValue,
229{
230 let value = if supports_storage_key_binary_kind(kind) {
231 decode_storage_key_binary_value_bytes(bytes, kind)
232 .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?
233 .ok_or_else(|| {
234 InternalError::persisted_row_field_decode_failed(
235 field_name,
236 "storage-key binary lane rejected a supported field kind",
237 )
238 })?
239 } else {
240 decode_structural_field_by_kind_bytes(bytes, kind)
241 .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?
242 };
243
244 T::from_value(&value).ok_or_else(|| {
245 InternalError::persisted_row_field_decode_failed(
246 field_name,
247 format!(
248 "value payload does not match {}",
249 std::any::type_name::<T>()
250 ),
251 )
252 })
253}
254
255pub fn decode_persisted_non_null_slot_payload_by_kind<T>(
258 bytes: &[u8],
259 kind: FieldKind,
260 field_name: &'static str,
261) -> Result<T, InternalError>
262where
263 T: FieldValue,
264{
265 decode_persisted_structural_slot_payload_by_kind(bytes, kind, field_name)?.ok_or_else(|| {
266 InternalError::persisted_row_field_decode_failed(
267 field_name,
268 "unexpected null for non-nullable field",
269 )
270 })
271}
272
273pub fn decode_persisted_option_slot_payload_by_kind<T>(
276 bytes: &[u8],
277 kind: FieldKind,
278 field_name: &'static str,
279) -> Result<Option<T>, InternalError>
280where
281 T: FieldValue,
282{
283 decode_persisted_structural_slot_payload_by_kind(bytes, kind, field_name)
284}
285
286pub fn decode_persisted_slot_payload_by_meta<T>(
289 bytes: &[u8],
290 field_name: &'static str,
291) -> Result<T, InternalError>
292where
293 T: FieldTypeMeta + FieldValue,
294{
295 match T::STORAGE_DECODE {
296 crate::model::field::FieldStorageDecode::ByKind => {
297 decode_persisted_non_null_slot_payload_by_kind(bytes, T::KIND, field_name)
298 }
299 crate::model::field::FieldStorageDecode::Value => {
300 decode_persisted_custom_slot_payload(bytes, field_name)
301 }
302 }
303}
304
305pub fn decode_persisted_option_slot_payload_by_meta<T>(
308 bytes: &[u8],
309 field_name: &'static str,
310) -> Result<Option<T>, InternalError>
311where
312 T: FieldTypeMeta + FieldValue,
313{
314 match T::STORAGE_DECODE {
315 crate::model::field::FieldStorageDecode::ByKind => {
316 decode_persisted_option_slot_payload_by_kind(bytes, T::KIND, field_name)
317 }
318 crate::model::field::FieldStorageDecode::Value => {
319 decode_persisted_custom_slot_payload(bytes, field_name)
320 }
321 }
322}
323
324fn decode_persisted_value_payload_as<T, F>(
327 bytes: &[u8],
328 field_name: &'static str,
329 mismatch: impl FnOnce() -> String,
330 decode: F,
331) -> Result<T, InternalError>
332where
333 F: FnOnce(&Value) -> Option<T>,
334{
335 let value = decode_structural_value_storage_bytes(bytes)
336 .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?;
337
338 decode(&value)
339 .ok_or_else(|| InternalError::persisted_row_field_decode_failed(field_name, mismatch()))
340}
341
342fn encode_persisted_value_payload(
345 value: Value,
346 field_name: &'static str,
347) -> Result<Vec<u8>, InternalError> {
348 encode_structural_value_storage_bytes(&value)
349 .map_err(|err| InternalError::persisted_row_field_encode_failed(field_name, err))
350}
351
352pub fn decode_persisted_custom_slot_payload<T>(
355 bytes: &[u8],
356 field_name: &'static str,
357) -> Result<T, InternalError>
358where
359 T: FieldValue,
360{
361 decode_persisted_value_payload_as(
362 bytes,
363 field_name,
364 || {
365 format!(
366 "value payload does not match {}",
367 std::any::type_name::<T>()
368 )
369 },
370 T::from_value,
371 )
372}
373
374pub fn decode_persisted_custom_many_slot_payload<T>(
377 bytes: &[u8],
378 field_name: &'static str,
379) -> Result<Vec<T>, InternalError>
380where
381 T: FieldValue,
382{
383 decode_persisted_value_payload_as(
384 bytes,
385 field_name,
386 || {
387 format!(
388 "value payload does not match Vec<{}>",
389 std::any::type_name::<T>()
390 )
391 },
392 field_value_vec_from_value::<T>,
393 )
394}
395
396pub fn encode_persisted_custom_slot_payload<T>(
399 value: &T,
400 field_name: &'static str,
401) -> Result<Vec<u8>, InternalError>
402where
403 T: FieldValue,
404{
405 encode_persisted_value_payload(value.to_value(), field_name)
406}
407
408pub fn encode_persisted_custom_many_slot_payload<T>(
410 values: &[T],
411 field_name: &'static str,
412) -> Result<Vec<u8>, InternalError>
413where
414 T: FieldValue,
415{
416 encode_persisted_value_payload(
417 Value::List(values.iter().map(FieldValue::to_value).collect()),
418 field_name,
419 )
420}
421
422pub fn encode_persisted_slot_payload_by_meta<T>(
425 value: &T,
426 field_name: &'static str,
427) -> Result<Vec<u8>, InternalError>
428where
429 T: FieldTypeMeta + FieldValue,
430{
431 match T::STORAGE_DECODE {
432 crate::model::field::FieldStorageDecode::ByKind => {
433 encode_persisted_slot_payload_by_kind(value, T::KIND, field_name)
434 }
435 crate::model::field::FieldStorageDecode::Value => {
436 encode_persisted_custom_slot_payload(value, field_name)
437 }
438 }
439}
440
441pub fn encode_persisted_option_slot_payload_by_meta<T>(
444 value: &Option<T>,
445 field_name: &'static str,
446) -> Result<Vec<u8>, InternalError>
447where
448 T: FieldTypeMeta + FieldValue,
449{
450 match T::STORAGE_DECODE {
451 crate::model::field::FieldStorageDecode::ByKind => {
452 encode_persisted_slot_payload_by_kind(value, T::KIND, field_name)
453 }
454 crate::model::field::FieldStorageDecode::Value => {
455 encode_persisted_custom_slot_payload(value, field_name)
456 }
457 }
458}
459
460pub fn decode_persisted_scalar_slot_payload<T>(
462 bytes: &[u8],
463 field_name: &'static str,
464) -> Result<T, InternalError>
465where
466 T: PersistedScalar,
467{
468 let payload = decode_scalar_slot_payload_body(bytes, field_name)?.ok_or_else(|| {
469 InternalError::persisted_row_field_decode_failed(
470 field_name,
471 "unexpected null for non-nullable scalar field",
472 )
473 })?;
474
475 T::decode_scalar_payload(payload, field_name)
476}
477
478pub fn decode_persisted_option_scalar_slot_payload<T>(
480 bytes: &[u8],
481 field_name: &'static str,
482) -> Result<Option<T>, InternalError>
483where
484 T: PersistedScalar,
485{
486 let Some(payload) = decode_scalar_slot_payload_body(bytes, field_name)? else {
487 return Ok(None);
488 };
489
490 T::decode_scalar_payload(payload, field_name).map(Some)
491}
492
493pub(super) fn encode_scalar_slot_value(value: ScalarSlotValueRef<'_>) -> Vec<u8> {
495 match value {
496 ScalarSlotValueRef::Null => vec![SCALAR_SLOT_PREFIX, SCALAR_SLOT_TAG_NULL],
497 ScalarSlotValueRef::Value(value) => {
498 let mut encoded = Vec::new();
499 encoded.push(SCALAR_SLOT_PREFIX);
500 encoded.push(SCALAR_SLOT_TAG_VALUE);
501
502 match value {
503 ScalarValueRef::Blob(bytes) => encoded.extend_from_slice(bytes),
504 ScalarValueRef::Bool(value) => encoded.push(u8::from(value)),
505 ScalarValueRef::Date(value) => {
506 encoded.extend_from_slice(&value.as_days_since_epoch().to_le_bytes());
507 }
508 ScalarValueRef::Duration(value) => {
509 encoded.extend_from_slice(&value.as_millis().to_le_bytes());
510 }
511 ScalarValueRef::Float32(value) => {
512 encoded.extend_from_slice(&value.get().to_bits().to_le_bytes());
513 }
514 ScalarValueRef::Float64(value) => {
515 encoded.extend_from_slice(&value.get().to_bits().to_le_bytes());
516 }
517 ScalarValueRef::Int(value) => encoded.extend_from_slice(&value.to_le_bytes()),
518 ScalarValueRef::Principal(value) => encoded.extend_from_slice(value.as_slice()),
519 ScalarValueRef::Subaccount(value) => encoded.extend_from_slice(&value.to_bytes()),
520 ScalarValueRef::Text(value) => encoded.extend_from_slice(value.as_bytes()),
521 ScalarValueRef::Timestamp(value) => {
522 encoded.extend_from_slice(&value.as_millis().to_le_bytes());
523 }
524 ScalarValueRef::Uint(value) => encoded.extend_from_slice(&value.to_le_bytes()),
525 ScalarValueRef::Ulid(value) => encoded.extend_from_slice(&value.to_bytes()),
526 ScalarValueRef::Unit => {}
527 }
528
529 encoded
530 }
531 }
532}
533
534fn decode_scalar_slot_payload_body<'a>(
536 bytes: &'a [u8],
537 field_name: &'static str,
538) -> Result<Option<&'a [u8]>, InternalError> {
539 let Some((&prefix, rest)) = bytes.split_first() else {
540 return Err(InternalError::persisted_row_field_decode_failed(
541 field_name,
542 "empty scalar payload",
543 ));
544 };
545 if prefix != SCALAR_SLOT_PREFIX {
546 return Err(InternalError::persisted_row_field_decode_failed(
547 field_name,
548 format!(
549 "scalar payload prefix mismatch: expected slot envelope prefix byte 0x{SCALAR_SLOT_PREFIX:02X}, found 0x{prefix:02X}",
550 ),
551 ));
552 }
553 let Some((&tag, payload)) = rest.split_first() else {
554 return Err(InternalError::persisted_row_field_decode_failed(
555 field_name,
556 "truncated scalar payload tag",
557 ));
558 };
559
560 match tag {
561 SCALAR_SLOT_TAG_NULL => {
562 if !payload.is_empty() {
563 return Err(InternalError::persisted_row_field_decode_failed(
564 field_name,
565 "null scalar payload has trailing bytes",
566 ));
567 }
568
569 Ok(None)
570 }
571 SCALAR_SLOT_TAG_VALUE => Ok(Some(payload)),
572 _ => Err(InternalError::persisted_row_field_decode_failed(
573 field_name,
574 format!("invalid scalar payload tag {tag}"),
575 )),
576 }
577}
578
579#[expect(clippy::too_many_lines)]
581pub(super) fn decode_scalar_slot_value<'a>(
582 bytes: &'a [u8],
583 codec: ScalarCodec,
584 field_name: &'static str,
585) -> Result<ScalarSlotValueRef<'a>, InternalError> {
586 let Some(payload) = decode_scalar_slot_payload_body(bytes, field_name)? else {
587 return Ok(ScalarSlotValueRef::Null);
588 };
589
590 let value = match codec {
591 ScalarCodec::Blob => ScalarValueRef::Blob(payload),
592 ScalarCodec::Bool => {
593 let [value] = payload else {
594 return Err(
595 InternalError::persisted_row_field_payload_exact_len_required(
596 field_name,
597 "bool",
598 SCALAR_BOOL_PAYLOAD_LEN,
599 ),
600 );
601 };
602 match *value {
603 SCALAR_BOOL_FALSE_TAG => ScalarValueRef::Bool(false),
604 SCALAR_BOOL_TRUE_TAG => ScalarValueRef::Bool(true),
605 _ => {
606 return Err(InternalError::persisted_row_field_payload_invalid_byte(
607 field_name, "bool", *value,
608 ));
609 }
610 }
611 }
612 ScalarCodec::Date => {
613 let bytes: [u8; SCALAR_WORD32_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
614 InternalError::persisted_row_field_payload_exact_len_required(
615 field_name,
616 "date",
617 SCALAR_WORD32_PAYLOAD_LEN,
618 )
619 })?;
620 ScalarValueRef::Date(Date::from_days_since_epoch(i32::from_le_bytes(bytes)))
621 }
622 ScalarCodec::Duration => {
623 let bytes: [u8; SCALAR_WORD64_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
624 InternalError::persisted_row_field_payload_exact_len_required(
625 field_name,
626 "duration",
627 SCALAR_WORD64_PAYLOAD_LEN,
628 )
629 })?;
630 ScalarValueRef::Duration(Duration::from_millis(u64::from_le_bytes(bytes)))
631 }
632 ScalarCodec::Float32 => {
633 let bytes: [u8; SCALAR_WORD32_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
634 InternalError::persisted_row_field_payload_exact_len_required(
635 field_name,
636 "float32",
637 SCALAR_WORD32_PAYLOAD_LEN,
638 )
639 })?;
640 let value = f32::from_bits(u32::from_le_bytes(bytes));
641 let value = Float32::try_new(value).ok_or_else(|| {
642 InternalError::persisted_row_field_payload_non_finite(field_name, "float32")
643 })?;
644 ScalarValueRef::Float32(value)
645 }
646 ScalarCodec::Float64 => {
647 let bytes: [u8; SCALAR_WORD64_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
648 InternalError::persisted_row_field_payload_exact_len_required(
649 field_name,
650 "float64",
651 SCALAR_WORD64_PAYLOAD_LEN,
652 )
653 })?;
654 let value = f64::from_bits(u64::from_le_bytes(bytes));
655 let value = Float64::try_new(value).ok_or_else(|| {
656 InternalError::persisted_row_field_payload_non_finite(field_name, "float64")
657 })?;
658 ScalarValueRef::Float64(value)
659 }
660 ScalarCodec::Int64 => {
661 let bytes: [u8; SCALAR_WORD64_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
662 InternalError::persisted_row_field_payload_exact_len_required(
663 field_name,
664 "int",
665 SCALAR_WORD64_PAYLOAD_LEN,
666 )
667 })?;
668 ScalarValueRef::Int(i64::from_le_bytes(bytes))
669 }
670 ScalarCodec::Principal => ScalarValueRef::Principal(
671 Principal::try_from_bytes(payload)
672 .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?,
673 ),
674 ScalarCodec::Subaccount => {
675 let bytes: [u8; SCALAR_SUBACCOUNT_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
676 InternalError::persisted_row_field_payload_exact_len_required(
677 field_name,
678 "subaccount",
679 SCALAR_SUBACCOUNT_PAYLOAD_LEN,
680 )
681 })?;
682 ScalarValueRef::Subaccount(Subaccount::from_array(bytes))
683 }
684 ScalarCodec::Text => {
685 let value = str::from_utf8(payload).map_err(|err| {
686 InternalError::persisted_row_field_text_payload_invalid_utf8(field_name, err)
687 })?;
688 ScalarValueRef::Text(value)
689 }
690 ScalarCodec::Timestamp => {
691 let bytes: [u8; SCALAR_WORD64_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
692 InternalError::persisted_row_field_payload_exact_len_required(
693 field_name,
694 "timestamp",
695 SCALAR_WORD64_PAYLOAD_LEN,
696 )
697 })?;
698 ScalarValueRef::Timestamp(Timestamp::from_millis(i64::from_le_bytes(bytes)))
699 }
700 ScalarCodec::Uint64 => {
701 let bytes: [u8; SCALAR_WORD64_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
702 InternalError::persisted_row_field_payload_exact_len_required(
703 field_name,
704 "uint",
705 SCALAR_WORD64_PAYLOAD_LEN,
706 )
707 })?;
708 ScalarValueRef::Uint(u64::from_le_bytes(bytes))
709 }
710 ScalarCodec::Ulid => {
711 let bytes: [u8; SCALAR_ULID_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
712 InternalError::persisted_row_field_payload_exact_len_required(
713 field_name,
714 "ulid",
715 SCALAR_ULID_PAYLOAD_LEN,
716 )
717 })?;
718 ScalarValueRef::Ulid(Ulid::from_bytes(bytes))
719 }
720 ScalarCodec::Unit => {
721 if !payload.is_empty() {
722 return Err(InternalError::persisted_row_field_payload_must_be_empty(
723 field_name, "unit",
724 ));
725 }
726 ScalarValueRef::Unit
727 }
728 };
729
730 Ok(ScalarSlotValueRef::Value(value))
731}
732
733macro_rules! impl_persisted_scalar_signed {
734 ($($ty:ty),* $(,)?) => {
735 $(
736 impl PersistedScalar for $ty {
737 const CODEC: ScalarCodec = ScalarCodec::Int64;
738
739 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
740 Ok(i64::from(*self).to_le_bytes().to_vec())
741 }
742
743 fn decode_scalar_payload(
744 bytes: &[u8],
745 field_name: &'static str,
746 ) -> Result<Self, InternalError> {
747 let raw: [u8; SCALAR_WORD64_PAYLOAD_LEN] = bytes.try_into().map_err(|_| {
748 InternalError::persisted_row_field_payload_exact_len_required(
749 field_name,
750 "int",
751 SCALAR_WORD64_PAYLOAD_LEN,
752 )
753 })?;
754 <$ty>::try_from(i64::from_le_bytes(raw)).map_err(|_| {
755 InternalError::persisted_row_field_payload_out_of_range(
756 field_name,
757 "integer",
758 )
759 })
760 }
761 }
762 )*
763 };
764}
765
766macro_rules! impl_persisted_scalar_unsigned {
767 ($($ty:ty),* $(,)?) => {
768 $(
769 impl PersistedScalar for $ty {
770 const CODEC: ScalarCodec = ScalarCodec::Uint64;
771
772 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
773 Ok(u64::from(*self).to_le_bytes().to_vec())
774 }
775
776 fn decode_scalar_payload(
777 bytes: &[u8],
778 field_name: &'static str,
779 ) -> Result<Self, InternalError> {
780 let raw: [u8; SCALAR_WORD64_PAYLOAD_LEN] = bytes.try_into().map_err(|_| {
781 InternalError::persisted_row_field_payload_exact_len_required(
782 field_name,
783 "uint",
784 SCALAR_WORD64_PAYLOAD_LEN,
785 )
786 })?;
787 <$ty>::try_from(u64::from_le_bytes(raw)).map_err(|_| {
788 InternalError::persisted_row_field_payload_out_of_range(
789 field_name,
790 "unsigned",
791 )
792 })
793 }
794 }
795 )*
796 };
797}
798
799impl_persisted_scalar_signed!(i8, i16, i32, i64);
800impl_persisted_scalar_unsigned!(u8, u16, u32, u64);
801
802impl PersistedScalar for bool {
803 const CODEC: ScalarCodec = ScalarCodec::Bool;
804
805 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
806 Ok(vec![u8::from(*self)])
807 }
808
809 fn decode_scalar_payload(
810 bytes: &[u8],
811 field_name: &'static str,
812 ) -> Result<Self, InternalError> {
813 let [value] = bytes else {
814 return Err(
815 InternalError::persisted_row_field_payload_exact_len_required(
816 field_name,
817 "bool",
818 SCALAR_BOOL_PAYLOAD_LEN,
819 ),
820 );
821 };
822
823 match *value {
824 SCALAR_BOOL_FALSE_TAG => Ok(false),
825 SCALAR_BOOL_TRUE_TAG => Ok(true),
826 _ => Err(InternalError::persisted_row_field_payload_invalid_byte(
827 field_name, "bool", *value,
828 )),
829 }
830 }
831}
832
833impl PersistedScalar for String {
834 const CODEC: ScalarCodec = ScalarCodec::Text;
835
836 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
837 Ok(self.as_bytes().to_vec())
838 }
839
840 fn decode_scalar_payload(
841 bytes: &[u8],
842 field_name: &'static str,
843 ) -> Result<Self, InternalError> {
844 str::from_utf8(bytes).map(str::to_owned).map_err(|err| {
845 InternalError::persisted_row_field_text_payload_invalid_utf8(field_name, err)
846 })
847 }
848}
849
850impl PersistedScalar for Vec<u8> {
851 const CODEC: ScalarCodec = ScalarCodec::Blob;
852
853 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
854 Ok(self.clone())
855 }
856
857 fn decode_scalar_payload(
858 bytes: &[u8],
859 _field_name: &'static str,
860 ) -> Result<Self, InternalError> {
861 Ok(bytes.to_vec())
862 }
863}
864
865impl PersistedScalar for Blob {
866 const CODEC: ScalarCodec = ScalarCodec::Blob;
867
868 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
869 Ok(self.to_vec())
870 }
871
872 fn decode_scalar_payload(
873 bytes: &[u8],
874 _field_name: &'static str,
875 ) -> Result<Self, InternalError> {
876 Ok(Self::from(bytes))
877 }
878}
879
880impl PersistedScalar for Ulid {
881 const CODEC: ScalarCodec = ScalarCodec::Ulid;
882
883 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
884 Ok(self.to_bytes().to_vec())
885 }
886
887 fn decode_scalar_payload(
888 bytes: &[u8],
889 field_name: &'static str,
890 ) -> Result<Self, InternalError> {
891 Self::try_from_bytes(bytes)
892 .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))
893 }
894}
895
896impl PersistedScalar for Timestamp {
897 const CODEC: ScalarCodec = ScalarCodec::Timestamp;
898
899 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
900 Ok(self.as_millis().to_le_bytes().to_vec())
901 }
902
903 fn decode_scalar_payload(
904 bytes: &[u8],
905 field_name: &'static str,
906 ) -> Result<Self, InternalError> {
907 let raw: [u8; SCALAR_WORD64_PAYLOAD_LEN] = bytes.try_into().map_err(|_| {
908 InternalError::persisted_row_field_payload_exact_len_required(
909 field_name,
910 "timestamp",
911 SCALAR_WORD64_PAYLOAD_LEN,
912 )
913 })?;
914
915 Ok(Self::from_millis(i64::from_le_bytes(raw)))
916 }
917}
918
919impl PersistedScalar for Date {
920 const CODEC: ScalarCodec = ScalarCodec::Date;
921
922 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
923 Ok(self.as_days_since_epoch().to_le_bytes().to_vec())
924 }
925
926 fn decode_scalar_payload(
927 bytes: &[u8],
928 field_name: &'static str,
929 ) -> Result<Self, InternalError> {
930 let raw: [u8; SCALAR_WORD32_PAYLOAD_LEN] = bytes.try_into().map_err(|_| {
931 InternalError::persisted_row_field_payload_exact_len_required(
932 field_name,
933 "date",
934 SCALAR_WORD32_PAYLOAD_LEN,
935 )
936 })?;
937
938 Ok(Self::from_days_since_epoch(i32::from_le_bytes(raw)))
939 }
940}
941
942impl PersistedScalar for Duration {
943 const CODEC: ScalarCodec = ScalarCodec::Duration;
944
945 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
946 Ok(self.as_millis().to_le_bytes().to_vec())
947 }
948
949 fn decode_scalar_payload(
950 bytes: &[u8],
951 field_name: &'static str,
952 ) -> Result<Self, InternalError> {
953 let raw: [u8; SCALAR_WORD64_PAYLOAD_LEN] = bytes.try_into().map_err(|_| {
954 InternalError::persisted_row_field_payload_exact_len_required(
955 field_name,
956 "duration",
957 SCALAR_WORD64_PAYLOAD_LEN,
958 )
959 })?;
960
961 Ok(Self::from_millis(u64::from_le_bytes(raw)))
962 }
963}
964
965impl PersistedScalar for Float32 {
966 const CODEC: ScalarCodec = ScalarCodec::Float32;
967
968 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
969 Ok(self.get().to_bits().to_le_bytes().to_vec())
970 }
971
972 fn decode_scalar_payload(
973 bytes: &[u8],
974 field_name: &'static str,
975 ) -> Result<Self, InternalError> {
976 let raw: [u8; SCALAR_WORD32_PAYLOAD_LEN] = bytes.try_into().map_err(|_| {
977 InternalError::persisted_row_field_payload_exact_len_required(
978 field_name,
979 "float32",
980 SCALAR_WORD32_PAYLOAD_LEN,
981 )
982 })?;
983 let value = f32::from_bits(u32::from_le_bytes(raw));
984
985 Self::try_new(value).ok_or_else(|| {
986 InternalError::persisted_row_field_payload_non_finite(field_name, "float32")
987 })
988 }
989}
990
991impl PersistedScalar for Float64 {
992 const CODEC: ScalarCodec = ScalarCodec::Float64;
993
994 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
995 Ok(self.get().to_bits().to_le_bytes().to_vec())
996 }
997
998 fn decode_scalar_payload(
999 bytes: &[u8],
1000 field_name: &'static str,
1001 ) -> Result<Self, InternalError> {
1002 let raw: [u8; SCALAR_WORD64_PAYLOAD_LEN] = bytes.try_into().map_err(|_| {
1003 InternalError::persisted_row_field_payload_exact_len_required(
1004 field_name,
1005 "float64",
1006 SCALAR_WORD64_PAYLOAD_LEN,
1007 )
1008 })?;
1009 let value = f64::from_bits(u64::from_le_bytes(raw));
1010
1011 Self::try_new(value).ok_or_else(|| {
1012 InternalError::persisted_row_field_payload_non_finite(field_name, "float64")
1013 })
1014 }
1015}
1016
1017impl PersistedScalar for Principal {
1018 const CODEC: ScalarCodec = ScalarCodec::Principal;
1019
1020 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
1021 self.to_bytes()
1022 .map_err(|err| InternalError::persisted_row_field_encode_failed("principal", err))
1023 }
1024
1025 fn decode_scalar_payload(
1026 bytes: &[u8],
1027 field_name: &'static str,
1028 ) -> Result<Self, InternalError> {
1029 Self::try_from_bytes(bytes)
1030 .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))
1031 }
1032}
1033
1034impl PersistedScalar for Subaccount {
1035 const CODEC: ScalarCodec = ScalarCodec::Subaccount;
1036
1037 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
1038 Ok(self.to_bytes().to_vec())
1039 }
1040
1041 fn decode_scalar_payload(
1042 bytes: &[u8],
1043 field_name: &'static str,
1044 ) -> Result<Self, InternalError> {
1045 let raw: [u8; SCALAR_SUBACCOUNT_PAYLOAD_LEN] = bytes.try_into().map_err(|_| {
1046 InternalError::persisted_row_field_payload_exact_len_required(
1047 field_name,
1048 "subaccount",
1049 SCALAR_SUBACCOUNT_PAYLOAD_LEN,
1050 )
1051 })?;
1052
1053 Ok(Self::from_array(raw))
1054 }
1055}
1056
1057impl PersistedScalar for () {
1058 const CODEC: ScalarCodec = ScalarCodec::Unit;
1059
1060 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
1061 Ok(Vec::new())
1062 }
1063
1064 fn decode_scalar_payload(
1065 bytes: &[u8],
1066 field_name: &'static str,
1067 ) -> Result<Self, InternalError> {
1068 if !bytes.is_empty() {
1069 return Err(InternalError::persisted_row_field_payload_must_be_empty(
1070 field_name, "unit",
1071 ));
1072 }
1073
1074 Ok(())
1075 }
1076}
1077
1078impl PersistedScalar for Unit {
1079 const CODEC: ScalarCodec = ScalarCodec::Unit;
1080
1081 fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
1082 Ok(Vec::new())
1083 }
1084
1085 fn decode_scalar_payload(
1086 bytes: &[u8],
1087 field_name: &'static str,
1088 ) -> Result<Self, InternalError> {
1089 if !bytes.is_empty() {
1090 return Err(InternalError::persisted_row_field_payload_must_be_empty(
1091 field_name, "unit",
1092 ));
1093 }
1094
1095 Ok(Self)
1096 }
1097}