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