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