Skip to main content

icydb_core/db/data/persisted_row/
codec.rs

1//! Module: db::data::persisted_row::codec
2//! Defines the persisted scalar row-slot encoding and borrowed decoding helpers
3//! used by runtime row access.
4
5use crate::{
6    db::data::{
7        decode_account, decode_blob_field_by_kind_bytes, decode_bool_field_by_kind_bytes,
8        decode_date_field_by_kind_bytes, decode_decimal, decode_decimal_field_by_kind_bytes,
9        decode_duration_field_by_kind_bytes, decode_float32_field_by_kind_bytes,
10        decode_float64_field_by_kind_bytes, decode_int, decode_int_big_field_by_kind_bytes,
11        decode_int128, decode_int128_field_by_kind_bytes, decode_list_field_items,
12        decode_list_item, decode_map_entry, decode_map_field_entries, decode_nat, decode_nat128,
13        decode_nat128_field_by_kind_bytes, decode_optional_storage_key_field_bytes,
14        decode_storage_key_binary_value_bytes, decode_structural_field_by_kind_bytes,
15        decode_structural_value_storage_blob_bytes, decode_structural_value_storage_bool_bytes,
16        decode_structural_value_storage_bytes, decode_structural_value_storage_date_bytes,
17        decode_structural_value_storage_duration_bytes,
18        decode_structural_value_storage_float32_bytes,
19        decode_structural_value_storage_float64_bytes, decode_structural_value_storage_i64_bytes,
20        decode_structural_value_storage_principal_bytes,
21        decode_structural_value_storage_subaccount_bytes,
22        decode_structural_value_storage_timestamp_bytes, decode_structural_value_storage_u64_bytes,
23        decode_structural_value_storage_ulid_bytes, decode_structural_value_storage_unit_bytes,
24        decode_text, decode_text_field_by_kind_bytes, decode_uint_big_field_by_kind_bytes,
25        encode_account, encode_blob_field_by_kind_bytes, encode_bool_field_by_kind_bytes,
26        encode_date_field_by_kind_bytes, encode_decimal, encode_decimal_field_by_kind_bytes,
27        encode_duration_field_by_kind_bytes, encode_float32_field_by_kind_bytes,
28        encode_float64_field_by_kind_bytes, encode_int, encode_int_big_field_by_kind_bytes,
29        encode_int128, encode_int128_field_by_kind_bytes, encode_list_field_items,
30        encode_list_item, encode_map_entry, encode_map_field_entries, encode_nat, encode_nat128,
31        encode_nat128_field_by_kind_bytes, encode_storage_key_binary_value_bytes,
32        encode_storage_key_field_bytes, encode_structural_field_by_kind_bytes,
33        encode_structural_value_storage_blob_bytes, encode_structural_value_storage_bool_bytes,
34        encode_structural_value_storage_bytes, encode_structural_value_storage_date_bytes,
35        encode_structural_value_storage_duration_bytes,
36        encode_structural_value_storage_float32_bytes,
37        encode_structural_value_storage_float64_bytes, encode_structural_value_storage_i64_bytes,
38        encode_structural_value_storage_null_bytes,
39        encode_structural_value_storage_principal_bytes,
40        encode_structural_value_storage_subaccount_bytes,
41        encode_structural_value_storage_timestamp_bytes, encode_structural_value_storage_u64_bytes,
42        encode_structural_value_storage_ulid_bytes, encode_structural_value_storage_unit_bytes,
43        encode_text, encode_text_field_by_kind_bytes, encode_uint_big_field_by_kind_bytes,
44        structural_value_storage_bytes_are_null, supports_storage_key_binary_kind,
45    },
46    error::InternalError,
47    model::field::{FieldKind, FieldStorageDecode, ScalarCodec},
48    traits::{
49        Collection, FieldTypeMeta, PersistedByKindCodec, PersistedFieldMetaCodec,
50        PersistedStructuredFieldCodec, RuntimeValueDecode, RuntimeValueEncode,
51    },
52    types::{
53        Account, Blob, Date, Decimal, Duration, Float32, Float64, Int, Int128, Nat, Nat128,
54        Principal, Subaccount, Timestamp, Ulid, Unit,
55    },
56    value::{StorageKey, Value},
57};
58use std::collections::{BTreeMap, BTreeSet};
59use std::str;
60
61const SCALAR_SLOT_PREFIX: u8 = 0xFF;
62const SCALAR_SLOT_TAG_NULL: u8 = 0;
63const SCALAR_SLOT_TAG_VALUE: u8 = 1;
64
65const SCALAR_BOOL_PAYLOAD_LEN: usize = 1;
66const SCALAR_WORD32_PAYLOAD_LEN: usize = 4;
67const SCALAR_WORD64_PAYLOAD_LEN: usize = 8;
68const SCALAR_ULID_PAYLOAD_LEN: usize = 16;
69const SCALAR_SUBACCOUNT_PAYLOAD_LEN: usize = 32;
70
71const SCALAR_BOOL_FALSE_TAG: u8 = 0;
72const SCALAR_BOOL_TRUE_TAG: u8 = 1;
73
74///
75/// ScalarValueRef
76///
77/// ScalarValueRef is the borrowed-or-copy scalar payload view returned by the
78/// slot-reader fast path.
79/// It preserves cheap references for text/blob payloads while keeping fixed
80/// width scalar wrappers as copy values.
81///
82
83#[derive(Clone, Copy, Debug)]
84pub enum ScalarValueRef<'a> {
85    Blob(&'a [u8]),
86    Bool(bool),
87    Date(Date),
88    Duration(Duration),
89    Float32(Float32),
90    Float64(Float64),
91    Int(i64),
92    Principal(Principal),
93    Subaccount(Subaccount),
94    Text(&'a str),
95    Timestamp(Timestamp),
96    Uint(u64),
97    Ulid(Ulid),
98    Unit,
99}
100
101impl ScalarValueRef<'_> {
102    /// Materialize this scalar view into the runtime `Value` enum.
103    #[must_use]
104    pub fn into_value(self) -> Value {
105        match self {
106            Self::Blob(value) => Value::Blob(value.to_vec()),
107            Self::Bool(value) => Value::Bool(value),
108            Self::Date(value) => Value::Date(value),
109            Self::Duration(value) => Value::Duration(value),
110            Self::Float32(value) => Value::Float32(value),
111            Self::Float64(value) => Value::Float64(value),
112            Self::Int(value) => Value::Int(value),
113            Self::Principal(value) => Value::Principal(value),
114            Self::Subaccount(value) => Value::Subaccount(value),
115            Self::Text(value) => Value::Text(value.to_owned()),
116            Self::Timestamp(value) => Value::Timestamp(value),
117            Self::Uint(value) => Value::Uint(value),
118            Self::Ulid(value) => Value::Ulid(value),
119            Self::Unit => Value::Unit,
120        }
121    }
122}
123
124///
125/// ScalarSlotValueRef
126///
127/// ScalarSlotValueRef preserves the distinction between a missing slot and an
128/// explicitly persisted `NULL` scalar payload.
129/// The outer `Option` from `SlotReader::get_scalar` therefore still means
130/// "slot absent".
131///
132
133#[derive(Clone, Copy, Debug)]
134pub enum ScalarSlotValueRef<'a> {
135    Null,
136    Value(ScalarValueRef<'a>),
137}
138
139///
140/// PersistedScalar
141///
142/// PersistedScalar defines the canonical binary payload codec for one scalar
143/// leaf type.
144/// Derive-generated persisted-row materializers and writers use this trait to
145/// avoid routing scalar fields back through a generic structural envelope.
146///
147
148pub trait PersistedScalar: Sized {
149    /// Canonical scalar codec identifier used by schema/runtime metadata.
150    const CODEC: ScalarCodec;
151
152    /// Encode this scalar value into its codec-specific payload bytes.
153    fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError>;
154
155    /// Decode this scalar value from its codec-specific payload bytes.
156    fn decode_scalar_payload(bytes: &[u8], field_name: &'static str)
157    -> Result<Self, InternalError>;
158}
159
160/// Encode one persisted slot payload using the stricter schema-owned `ByKind`
161/// storage contract.
162pub fn encode_persisted_slot_payload_by_kind<T>(
163    value: &T,
164    kind: FieldKind,
165    field_name: &'static str,
166) -> Result<Vec<u8>, InternalError>
167where
168    T: PersistedByKindCodec,
169{
170    value.encode_persisted_slot_payload_by_kind(kind, field_name)
171}
172
173/// Encode one persisted scalar slot payload using the canonical scalar envelope.
174pub fn encode_persisted_scalar_slot_payload<T>(
175    value: &T,
176    field_name: &'static str,
177) -> Result<Vec<u8>, InternalError>
178where
179    T: PersistedScalar,
180{
181    let payload = value.encode_scalar_payload()?;
182    let mut encoded = Vec::with_capacity(payload.len() + 2);
183    encoded.push(SCALAR_SLOT_PREFIX);
184    encoded.push(SCALAR_SLOT_TAG_VALUE);
185    encoded.extend_from_slice(&payload);
186
187    if encoded.len() < 2 {
188        return Err(InternalError::persisted_row_field_encode_failed(
189            field_name,
190            "scalar payload envelope underflow",
191        ));
192    }
193
194    Ok(encoded)
195}
196
197/// Encode one optional persisted scalar slot payload preserving explicit `NULL`.
198pub fn encode_persisted_option_scalar_slot_payload<T>(
199    value: &Option<T>,
200    field_name: &'static str,
201) -> Result<Vec<u8>, InternalError>
202where
203    T: PersistedScalar,
204{
205    match value {
206        Some(value) => encode_persisted_scalar_slot_payload(value, field_name),
207        None => Ok(vec![SCALAR_SLOT_PREFIX, SCALAR_SLOT_TAG_NULL]),
208    }
209}
210
211// Decode one `ByKind` structural persisted payload, preserving the explicit
212// null sentinel instead of forcing each wrapper to repeat the same branch.
213fn decode_persisted_structural_slot_payload_by_kind<T>(
214    bytes: &[u8],
215    kind: FieldKind,
216    field_name: &'static str,
217) -> Result<Option<T>, InternalError>
218where
219    T: PersistedByKindCodec,
220{
221    T::decode_persisted_option_slot_payload_by_kind(bytes, kind, field_name)
222}
223
224/// Decode one persisted slot payload using the stricter schema-owned `ByKind`
225/// storage contract.
226pub fn decode_persisted_slot_payload_by_kind<T>(
227    bytes: &[u8],
228    kind: FieldKind,
229    field_name: &'static str,
230) -> Result<T, InternalError>
231where
232    T: PersistedByKindCodec,
233{
234    decode_persisted_structural_slot_payload_by_kind(bytes, kind, field_name)?.ok_or_else(|| {
235        InternalError::persisted_row_field_decode_failed(
236            field_name,
237            "unexpected null for non-nullable field",
238        )
239    })
240}
241
242/// Decode one optional persisted slot payload preserving the explicit null
243/// sentinel under the stricter schema-owned `ByKind` storage contract.
244pub fn decode_persisted_option_slot_payload_by_kind<T>(
245    bytes: &[u8],
246    kind: FieldKind,
247    field_name: &'static str,
248) -> Result<Option<T>, InternalError>
249where
250    T: PersistedByKindCodec,
251{
252    decode_persisted_structural_slot_payload_by_kind(bytes, kind, field_name)
253}
254
255macro_rules! impl_persisted_by_kind_direct_leaf {
256    ($($ty:ty => { encode: $encode:expr, decode: $decode:expr }),* $(,)?) => {
257        $(
258            impl PersistedByKindCodec for $ty {
259                fn encode_persisted_slot_payload_by_kind(
260                    &self,
261                    kind: FieldKind,
262                    field_name: &'static str,
263                ) -> Result<Vec<u8>, InternalError> {
264                    ($encode)(self, kind, field_name)
265                }
266
267                fn decode_persisted_option_slot_payload_by_kind(
268                    bytes: &[u8],
269                    kind: FieldKind,
270                    field_name: &'static str,
271                ) -> Result<Option<Self>, InternalError> {
272                    ($decode)(bytes, kind, field_name)
273                }
274            }
275        )*
276    };
277}
278
279macro_rules! impl_persisted_by_kind_scalar_leaf {
280    ($($ty:ty => { encode: $encode:ident, decode: $decode:ident }),* $(,)?) => {
281        impl_persisted_by_kind_direct_leaf!(
282            $(
283                $ty => {
284                    encode: |value: &$ty, kind: FieldKind, field_name: &'static str| {
285                        $encode(*value, kind, field_name)
286                    },
287                    decode: |bytes: &[u8], kind: FieldKind, field_name: &'static str| {
288                        $decode(bytes, kind)
289                            .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))
290                    }
291                }
292            ),*
293        );
294    };
295}
296
297macro_rules! impl_persisted_by_kind_ref_leaf {
298    ($($ty:ty => { encode: $encode:ident, decode: $decode:ident }),* $(,)?) => {
299        impl_persisted_by_kind_direct_leaf!(
300            $(
301                $ty => {
302                    encode: |value: &$ty, kind: FieldKind, field_name: &'static str| {
303                        $encode(value, kind, field_name)
304                    },
305                    decode: |bytes: &[u8], kind: FieldKind, field_name: &'static str| {
306                        $decode(bytes, kind)
307                            .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))
308                    }
309                }
310            ),*
311        );
312    };
313}
314
315macro_rules! impl_persisted_by_kind_value_leaf {
316    ($($ty:ty => { encode: $encode:ident, decode: $decode:ident }),* $(,)?) => {
317        impl_persisted_by_kind_direct_leaf!(
318            $(
319                $ty => {
320                    encode: |value: &$ty, kind: FieldKind, field_name: &'static str| {
321                        $encode(*value, kind, field_name)
322                    },
323                    decode: |bytes: &[u8], kind: FieldKind, field_name: &'static str| {
324                        $decode(bytes, kind)
325                            .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))
326                    }
327                }
328            ),*
329        );
330    };
331}
332
333macro_rules! impl_persisted_by_kind_storage_int_leaf {
334    ($($ty:ty),* $(,)?) => {
335        impl_persisted_by_kind_direct_leaf!(
336            $(
337                $ty => {
338                    encode: |value: &$ty, kind: FieldKind, field_name: &'static str| {
339                        encode_storage_key_field_bytes(StorageKey::Int(i64::from(*value)), kind, field_name)
340                    },
341                    decode: |bytes: &[u8], kind: FieldKind, field_name: &'static str| {
342                        let Some(key) = decode_optional_storage_key_field_bytes(bytes, kind)
343                            .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?
344                        else {
345                            return Ok(None);
346                        };
347
348                        let StorageKey::Int(value) = key else {
349                            return Err(InternalError::persisted_row_field_decode_failed(
350                                field_name,
351                                format!("field kind {kind:?} did not decode as storage int"),
352                            ));
353                        };
354
355                        <$ty>::try_from(value).map(Some).map_err(|_| {
356                            InternalError::persisted_row_field_decode_failed(
357                                field_name,
358                                format!("field kind {kind:?} did not decode as storage int"),
359                            )
360                        })
361                    }
362                }
363            ),*
364        );
365    };
366}
367
368macro_rules! impl_persisted_by_kind_storage_uint_leaf {
369    ($($ty:ty),* $(,)?) => {
370        impl_persisted_by_kind_direct_leaf!(
371            $(
372                $ty => {
373                    encode: |value: &$ty, kind: FieldKind, field_name: &'static str| {
374                        encode_storage_key_field_bytes(StorageKey::Uint(u64::from(*value)), kind, field_name)
375                    },
376                    decode: |bytes: &[u8], kind: FieldKind, field_name: &'static str| {
377                        let Some(key) = decode_optional_storage_key_field_bytes(bytes, kind)
378                            .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?
379                        else {
380                            return Ok(None);
381                        };
382
383                        let StorageKey::Uint(value) = key else {
384                            return Err(InternalError::persisted_row_field_decode_failed(
385                                field_name,
386                                format!("field kind {kind:?} did not decode as storage uint"),
387                            ));
388                        };
389
390                        <$ty>::try_from(value).map(Some).map_err(|_| {
391                            InternalError::persisted_row_field_decode_failed(
392                                field_name,
393                                format!("field kind {kind:?} did not decode as storage uint"),
394                            )
395                        })
396                    }
397                }
398            ),*
399        );
400    };
401}
402
403macro_rules! impl_persisted_by_kind_storage_leaf {
404    ($($ty:ty => { variant: $variant:ident, label: $label:literal }),* $(,)?) => {
405        impl_persisted_by_kind_direct_leaf!(
406            $(
407                $ty => {
408                    encode: |value: &$ty, kind: FieldKind, field_name: &'static str| {
409                        encode_storage_key_field_bytes(StorageKey::$variant(*value), kind, field_name)
410                    },
411                    decode: |bytes: &[u8], kind: FieldKind, field_name: &'static str| {
412                        let Some(key) = decode_optional_storage_key_field_bytes(bytes, kind)
413                            .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?
414                        else {
415                            return Ok(None);
416                        };
417
418                        match key {
419                            StorageKey::$variant(value) => Ok(Some(value)),
420                            _ => Err(InternalError::persisted_row_field_decode_failed(
421                                field_name,
422                                format!("field kind {kind:?} did not decode as {}", $label),
423                            )),
424                        }
425                    }
426                }
427            ),*
428        );
429    };
430}
431
432macro_rules! impl_persisted_by_kind_storage_unit_leaf {
433    ($ty:ty) => {
434        impl_persisted_by_kind_direct_leaf!(
435            $ty => {
436                encode: |_: &$ty, kind: FieldKind, field_name: &'static str| {
437                    encode_storage_key_field_bytes(StorageKey::Unit, kind, field_name)
438                },
439                decode: |bytes: &[u8], kind: FieldKind, field_name: &'static str| {
440                    let Some(key) = decode_optional_storage_key_field_bytes(bytes, kind)
441                        .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?
442                    else {
443                        return Ok(None);
444                    };
445
446                    match key {
447                        StorageKey::Unit => Ok(Some(Unit)),
448                        _ => Err(InternalError::persisted_row_field_decode_failed(
449                            field_name,
450                            format!("field kind {kind:?} did not decode as storage unit"),
451                        )),
452                    }
453                }
454            }
455        );
456    };
457}
458
459impl_persisted_by_kind_scalar_leaf!(
460    bool => { encode: encode_bool_field_by_kind_bytes, decode: decode_bool_field_by_kind_bytes },
461    Float32 => { encode: encode_float32_field_by_kind_bytes, decode: decode_float32_field_by_kind_bytes },
462    Float64 => { encode: encode_float64_field_by_kind_bytes, decode: decode_float64_field_by_kind_bytes },
463    Int128 => { encode: encode_int128_field_by_kind_bytes, decode: decode_int128_field_by_kind_bytes },
464    Nat128 => { encode: encode_nat128_field_by_kind_bytes, decode: decode_nat128_field_by_kind_bytes }
465);
466
467impl_persisted_by_kind_ref_leaf!(
468    String => { encode: encode_text_field_by_kind_bytes, decode: decode_text_field_by_kind_bytes },
469    Blob => { encode: encode_blob_field_by_kind_bytes, decode: decode_blob_field_by_kind_bytes },
470    Int => { encode: encode_int_big_field_by_kind_bytes, decode: decode_int_big_field_by_kind_bytes },
471    Nat => { encode: encode_uint_big_field_by_kind_bytes, decode: decode_uint_big_field_by_kind_bytes }
472);
473
474impl_persisted_by_kind_value_leaf!(
475    Date => { encode: encode_date_field_by_kind_bytes, decode: decode_date_field_by_kind_bytes },
476    Decimal => { encode: encode_decimal_field_by_kind_bytes, decode: decode_decimal_field_by_kind_bytes },
477    Duration => { encode: encode_duration_field_by_kind_bytes, decode: decode_duration_field_by_kind_bytes }
478);
479
480impl_persisted_by_kind_storage_int_leaf!(i8, i16, i32, i64);
481impl_persisted_by_kind_storage_uint_leaf!(u8, u16, u32, u64);
482impl_persisted_by_kind_storage_leaf!(
483    Account => { variant: Account, label: "storage account" },
484    Timestamp => { variant: Timestamp, label: "storage timestamp" },
485    Principal => { variant: Principal, label: "storage principal" },
486    Subaccount => { variant: Subaccount, label: "storage subaccount" },
487    Ulid => { variant: Ulid, label: "storage ulid" }
488);
489impl_persisted_by_kind_storage_unit_leaf!(Unit);
490
491// Encode one explicit by-kind owner through the current field-kind structural
492// contract.
493fn encode_explicit_by_kind_value(
494    kind: FieldKind,
495    value: &Value,
496    field_name: &'static str,
497) -> Result<Vec<u8>, InternalError> {
498    if supports_storage_key_binary_kind(kind) {
499        return encode_storage_key_binary_value_bytes(kind, value, field_name)?.ok_or_else(|| {
500            InternalError::persisted_row_field_encode_failed(
501                field_name,
502                "storage-key binary lane rejected a supported field kind",
503            )
504        });
505    }
506
507    encode_structural_field_by_kind_bytes(kind, value, field_name)
508        .map_err(|err| InternalError::persisted_row_field_encode_failed(field_name, err))
509}
510
511// Decode one explicit by-kind owner through the current field-kind structural
512// contract.
513fn decode_explicit_by_kind_value(
514    bytes: &[u8],
515    kind: FieldKind,
516    field_name: &'static str,
517) -> Result<Option<Value>, InternalError> {
518    let value = if supports_storage_key_binary_kind(kind) {
519        decode_storage_key_binary_value_bytes(bytes, kind)
520            .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?
521            .ok_or_else(|| {
522                InternalError::persisted_row_field_decode_failed(
523                    field_name,
524                    "storage-key binary lane rejected a supported field kind",
525                )
526            })?
527    } else {
528        decode_structural_field_by_kind_bytes(bytes, kind)
529            .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?
530    };
531
532    if matches!(value, Value::Null) {
533        return Ok(None);
534    }
535
536    Ok(Some(value))
537}
538
539impl<T> PersistedByKindCodec for Box<T>
540where
541    T: PersistedByKindCodec,
542{
543    fn encode_persisted_slot_payload_by_kind(
544        &self,
545        kind: FieldKind,
546        field_name: &'static str,
547    ) -> Result<Vec<u8>, InternalError> {
548        self.as_ref()
549            .encode_persisted_slot_payload_by_kind(kind, field_name)
550    }
551
552    fn decode_persisted_option_slot_payload_by_kind(
553        bytes: &[u8],
554        kind: FieldKind,
555        field_name: &'static str,
556    ) -> Result<Option<Self>, InternalError> {
557        T::decode_persisted_option_slot_payload_by_kind(bytes, kind, field_name)
558            .map(|value| value.map(Self::new))
559    }
560}
561
562impl<T> PersistedByKindCodec for Option<T>
563where
564    T: PersistedByKindCodec,
565{
566    fn encode_persisted_slot_payload_by_kind(
567        &self,
568        kind: FieldKind,
569        field_name: &'static str,
570    ) -> Result<Vec<u8>, InternalError> {
571        match self {
572            Some(value) => value.encode_persisted_slot_payload_by_kind(kind, field_name),
573            None => encode_explicit_by_kind_value(kind, &Value::Null, field_name),
574        }
575    }
576
577    fn decode_persisted_option_slot_payload_by_kind(
578        bytes: &[u8],
579        kind: FieldKind,
580        field_name: &'static str,
581    ) -> Result<Option<Self>, InternalError> {
582        match decode_explicit_by_kind_value(bytes, kind, field_name)? {
583            None => Ok(Some(None)),
584            Some(_) => T::decode_persisted_option_slot_payload_by_kind(bytes, kind, field_name)
585                .map(|value| value.map(Some)),
586        }
587    }
588}
589
590// Encode one explicit by-kind wrapper owner through its value-surface
591// Decode one nested by-kind payload and require that it materializes a real
592// value rather than an incompatible null for this owner type.
593fn decode_required_nested_by_kind<T>(
594    bytes: &[u8],
595    kind: FieldKind,
596    field_name: &'static str,
597    label: &'static str,
598) -> Result<T, InternalError>
599where
600    T: PersistedByKindCodec,
601{
602    T::decode_persisted_option_slot_payload_by_kind(bytes, kind, field_name)?.ok_or_else(|| {
603        InternalError::persisted_row_field_decode_failed(
604            field_name,
605            format!(
606                "{label} payload did not decode as {}",
607                std::any::type_name::<T>()
608            ),
609        )
610    })
611}
612
613// Encode one collection wrapper through recursive by-kind item ownership
614// instead of re-entering the generic runtime `Value` bridge.
615fn encode_direct_by_kind_collection<C, T>(
616    values: &C,
617    kind: FieldKind,
618    field_name: &'static str,
619) -> Result<Vec<u8>, InternalError>
620where
621    C: Collection<Item = T>,
622    T: PersistedByKindCodec,
623{
624    let (FieldKind::List(inner) | FieldKind::Set(inner)) = kind else {
625        return Err(InternalError::persisted_row_field_encode_failed(
626            field_name,
627            format!("field kind {kind:?} does not accept collection payloads"),
628        ));
629    };
630
631    let item_bytes = values
632        .iter()
633        .map(|item| item.encode_persisted_slot_payload_by_kind(*inner, field_name))
634        .collect::<Result<Vec<_>, _>>()?;
635    let item_slices = item_bytes.iter().map(Vec::as_slice).collect::<Vec<_>>();
636
637    encode_list_field_items(item_slices.as_slice(), kind, field_name)
638}
639
640// Decode one collection wrapper through recursive by-kind item ownership
641// instead of re-entering the generic runtime `Value` bridge.
642fn decode_direct_by_kind_collection<T>(
643    bytes: &[u8],
644    kind: FieldKind,
645    field_name: &'static str,
646) -> Result<Vec<T>, InternalError>
647where
648    T: PersistedByKindCodec,
649{
650    let (FieldKind::List(inner) | FieldKind::Set(inner)) = kind else {
651        return Err(InternalError::persisted_row_field_decode_failed(
652            field_name,
653            format!("field kind {kind:?} does not accept collection payloads"),
654        ));
655    };
656
657    let item_bytes = decode_list_field_items(bytes, kind)
658        .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?;
659
660    item_bytes
661        .iter()
662        .map(|item| decode_required_nested_by_kind(item.as_slice(), *inner, field_name, "item"))
663        .collect()
664}
665
666// Encode one map wrapper through recursive by-kind key/value ownership instead
667// of re-entering the generic runtime `Value` bridge.
668fn encode_direct_by_kind_map<K, V>(
669    entries: &BTreeMap<K, V>,
670    kind: FieldKind,
671    field_name: &'static str,
672) -> Result<Vec<u8>, InternalError>
673where
674    K: Ord + PersistedByKindCodec,
675    V: PersistedByKindCodec,
676{
677    let FieldKind::Map {
678        key,
679        value: value_kind,
680    } = kind
681    else {
682        return Err(InternalError::persisted_row_field_encode_failed(
683            field_name,
684            format!("field kind {kind:?} does not accept map payloads"),
685        ));
686    };
687
688    let entry_bytes = entries
689        .iter()
690        .map(|(entry_key, entry_value)| {
691            let key_bytes = entry_key.encode_persisted_slot_payload_by_kind(*key, field_name)?;
692            let value_bytes =
693                entry_value.encode_persisted_slot_payload_by_kind(*value_kind, field_name)?;
694
695            Ok((key_bytes, value_bytes))
696        })
697        .collect::<Result<Vec<_>, InternalError>>()?;
698    let entry_slices = entry_bytes
699        .iter()
700        .map(|(key_bytes, value_bytes)| (key_bytes.as_slice(), value_bytes.as_slice()))
701        .collect::<Vec<_>>();
702
703    encode_map_field_entries(entry_slices.as_slice(), kind, field_name)
704}
705
706// Decode one map wrapper through recursive by-kind key/value ownership instead
707// of re-entering the generic runtime `Value` bridge.
708fn decode_direct_by_kind_map<K, V>(
709    bytes: &[u8],
710    kind: FieldKind,
711    field_name: &'static str,
712) -> Result<BTreeMap<K, V>, InternalError>
713where
714    K: Ord + PersistedByKindCodec,
715    V: PersistedByKindCodec,
716{
717    let FieldKind::Map {
718        key,
719        value: value_kind,
720    } = kind
721    else {
722        return Err(InternalError::persisted_row_field_decode_failed(
723            field_name,
724            format!("field kind {kind:?} does not accept map payloads"),
725        ));
726    };
727
728    let entry_bytes = decode_map_field_entries(bytes, kind)
729        .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?;
730    let mut decoded = BTreeMap::new();
731    for (key_bytes, value_bytes) in entry_bytes {
732        let decoded_key =
733            decode_required_nested_by_kind(key_bytes.as_slice(), *key, field_name, "map key")?;
734        let decoded_value = decode_required_nested_by_kind(
735            value_bytes.as_slice(),
736            *value_kind,
737            field_name,
738            "map value",
739        )?;
740        decoded.insert(decoded_key, decoded_value);
741    }
742
743    Ok(decoded)
744}
745
746impl<T> PersistedByKindCodec for Vec<T>
747where
748    T: PersistedByKindCodec,
749{
750    fn encode_persisted_slot_payload_by_kind(
751        &self,
752        kind: FieldKind,
753        field_name: &'static str,
754    ) -> Result<Vec<u8>, InternalError> {
755        encode_direct_by_kind_collection(self, kind, field_name)
756    }
757
758    fn decode_persisted_option_slot_payload_by_kind(
759        bytes: &[u8],
760        kind: FieldKind,
761        field_name: &'static str,
762    ) -> Result<Option<Self>, InternalError> {
763        decode_direct_by_kind_collection(bytes, kind, field_name).map(Some)
764    }
765}
766
767impl<T> PersistedByKindCodec for BTreeSet<T>
768where
769    T: Ord + PersistedByKindCodec,
770{
771    fn encode_persisted_slot_payload_by_kind(
772        &self,
773        kind: FieldKind,
774        field_name: &'static str,
775    ) -> Result<Vec<u8>, InternalError> {
776        encode_direct_by_kind_collection(self, kind, field_name)
777    }
778
779    fn decode_persisted_option_slot_payload_by_kind(
780        bytes: &[u8],
781        kind: FieldKind,
782        field_name: &'static str,
783    ) -> Result<Option<Self>, InternalError> {
784        decode_direct_by_kind_collection::<T>(bytes, kind, field_name)
785            .map(|values| Some(values.into_iter().collect()))
786    }
787}
788
789impl<K, V> PersistedByKindCodec for BTreeMap<K, V>
790where
791    K: Ord + PersistedByKindCodec,
792    V: PersistedByKindCodec,
793{
794    fn encode_persisted_slot_payload_by_kind(
795        &self,
796        kind: FieldKind,
797        field_name: &'static str,
798    ) -> Result<Vec<u8>, InternalError> {
799        encode_direct_by_kind_map(self, kind, field_name)
800    }
801
802    fn decode_persisted_option_slot_payload_by_kind(
803        bytes: &[u8],
804        kind: FieldKind,
805        field_name: &'static str,
806    ) -> Result<Option<Self>, InternalError> {
807        decode_direct_by_kind_map(bytes, kind, field_name).map(Some)
808    }
809}
810
811/// Decode one persisted slot payload using the field type's own runtime field
812/// metadata.
813pub fn decode_persisted_slot_payload_by_meta<T>(
814    bytes: &[u8],
815    field_name: &'static str,
816) -> Result<T, InternalError>
817where
818    T: PersistedFieldMetaCodec,
819{
820    T::decode_persisted_slot_payload_by_meta(bytes, field_name)
821}
822
823/// Decode one optional persisted slot payload using the inner field type's own
824/// runtime field metadata.
825pub fn decode_persisted_option_slot_payload_by_meta<T>(
826    bytes: &[u8],
827    field_name: &'static str,
828) -> Result<Option<T>, InternalError>
829where
830    T: PersistedFieldMetaCodec,
831{
832    T::decode_persisted_option_slot_payload_by_meta(bytes, field_name)
833}
834
835macro_rules! impl_persisted_structured_signed_scalar_codec {
836    ($($ty:ty),* $(,)?) => {
837        $(
838            impl PersistedStructuredFieldCodec for $ty {
839                fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
840                    Ok(encode_structural_value_storage_i64_bytes(i64::from(*self)))
841                }
842
843                fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
844                    let value = decode_structural_value_storage_i64_bytes(bytes)
845                        .map_err(InternalError::persisted_row_decode_failed)?;
846
847                    <$ty>::try_from(value).map_err(|_| {
848                        InternalError::persisted_row_decode_failed(format!(
849                            "value payload does not match {}",
850                            std::any::type_name::<$ty>()
851                        ))
852                    })
853                }
854            }
855        )*
856    };
857}
858
859macro_rules! impl_persisted_structured_unsigned_scalar_codec {
860    ($($ty:ty),* $(,)?) => {
861        $(
862            impl PersistedStructuredFieldCodec for $ty {
863                fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
864                    Ok(encode_structural_value_storage_u64_bytes(u64::from(*self)))
865                }
866
867                fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
868                    let value = decode_structural_value_storage_u64_bytes(bytes)
869                        .map_err(InternalError::persisted_row_decode_failed)?;
870
871                    <$ty>::try_from(value).map_err(|_| {
872                        InternalError::persisted_row_decode_failed(format!(
873                            "value payload does not match {}",
874                            std::any::type_name::<$ty>()
875                        ))
876                    })
877                }
878            }
879        )*
880    };
881}
882
883impl PersistedStructuredFieldCodec for bool {
884    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
885        Ok(encode_structural_value_storage_bool_bytes(*self))
886    }
887
888    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
889        decode_structural_value_storage_bool_bytes(bytes)
890            .map_err(InternalError::persisted_row_decode_failed)
891    }
892}
893
894impl PersistedStructuredFieldCodec for String {
895    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
896        Ok(encode_text(self))
897    }
898
899    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
900        decode_text(bytes).map_err(InternalError::persisted_row_decode_failed)
901    }
902}
903
904impl PersistedStructuredFieldCodec for Blob {
905    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
906        Ok(encode_structural_value_storage_blob_bytes(self.as_slice()))
907    }
908
909    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
910        decode_structural_value_storage_blob_bytes(bytes)
911            .map(Self::from)
912            .map_err(InternalError::persisted_row_decode_failed)
913    }
914}
915
916impl PersistedStructuredFieldCodec for Account {
917    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
918        encode_account(*self)
919    }
920
921    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
922        decode_account(bytes).map_err(InternalError::persisted_row_decode_failed)
923    }
924}
925
926impl PersistedStructuredFieldCodec for Decimal {
927    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
928        Ok(encode_decimal(*self))
929    }
930
931    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
932        decode_decimal(bytes).map_err(InternalError::persisted_row_decode_failed)
933    }
934}
935
936impl PersistedStructuredFieldCodec for Float32 {
937    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
938        Ok(encode_structural_value_storage_float32_bytes(*self))
939    }
940
941    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
942        decode_structural_value_storage_float32_bytes(bytes)
943            .map_err(InternalError::persisted_row_decode_failed)
944    }
945}
946
947impl PersistedStructuredFieldCodec for Float64 {
948    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
949        Ok(encode_structural_value_storage_float64_bytes(*self))
950    }
951
952    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
953        decode_structural_value_storage_float64_bytes(bytes)
954            .map_err(InternalError::persisted_row_decode_failed)
955    }
956}
957
958impl PersistedStructuredFieldCodec for Principal {
959    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
960        encode_structural_value_storage_principal_bytes(*self)
961    }
962
963    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
964        decode_structural_value_storage_principal_bytes(bytes)
965            .map_err(InternalError::persisted_row_decode_failed)
966    }
967}
968
969impl PersistedStructuredFieldCodec for Subaccount {
970    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
971        Ok(encode_structural_value_storage_subaccount_bytes(*self))
972    }
973
974    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
975        decode_structural_value_storage_subaccount_bytes(bytes)
976            .map_err(InternalError::persisted_row_decode_failed)
977    }
978}
979
980impl PersistedStructuredFieldCodec for Timestamp {
981    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
982        Ok(encode_structural_value_storage_timestamp_bytes(*self))
983    }
984
985    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
986        decode_structural_value_storage_timestamp_bytes(bytes)
987            .map_err(InternalError::persisted_row_decode_failed)
988    }
989}
990
991impl PersistedStructuredFieldCodec for Date {
992    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
993        Ok(encode_structural_value_storage_date_bytes(*self))
994    }
995
996    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
997        decode_structural_value_storage_date_bytes(bytes)
998            .map_err(InternalError::persisted_row_decode_failed)
999    }
1000}
1001
1002impl PersistedStructuredFieldCodec for Duration {
1003    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
1004        Ok(encode_structural_value_storage_duration_bytes(*self))
1005    }
1006
1007    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
1008        decode_structural_value_storage_duration_bytes(bytes)
1009            .map_err(InternalError::persisted_row_decode_failed)
1010    }
1011}
1012
1013impl PersistedStructuredFieldCodec for Ulid {
1014    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
1015        Ok(encode_structural_value_storage_ulid_bytes(*self))
1016    }
1017
1018    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
1019        decode_structural_value_storage_ulid_bytes(bytes)
1020            .map_err(InternalError::persisted_row_decode_failed)
1021    }
1022}
1023
1024impl PersistedStructuredFieldCodec for Int128 {
1025    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
1026        Ok(encode_int128(*self))
1027    }
1028
1029    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
1030        decode_int128(bytes).map_err(InternalError::persisted_row_decode_failed)
1031    }
1032}
1033
1034impl PersistedStructuredFieldCodec for Nat128 {
1035    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
1036        Ok(encode_nat128(*self))
1037    }
1038
1039    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
1040        decode_nat128(bytes).map_err(InternalError::persisted_row_decode_failed)
1041    }
1042}
1043
1044impl PersistedStructuredFieldCodec for Int {
1045    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
1046        Ok(encode_int(self))
1047    }
1048
1049    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
1050        decode_int(bytes).map_err(InternalError::persisted_row_decode_failed)
1051    }
1052}
1053
1054impl PersistedStructuredFieldCodec for Nat {
1055    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
1056        Ok(encode_nat(self))
1057    }
1058
1059    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
1060        decode_nat(bytes).map_err(InternalError::persisted_row_decode_failed)
1061    }
1062}
1063
1064impl PersistedStructuredFieldCodec for Unit {
1065    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
1066        Ok(encode_structural_value_storage_unit_bytes())
1067    }
1068
1069    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
1070        decode_structural_value_storage_unit_bytes(bytes)
1071            .map(|()| Self)
1072            .map_err(InternalError::persisted_row_decode_failed)
1073    }
1074}
1075
1076// `Value` remains an explicit runtime/dynamic escape hatch for callers that
1077// intentionally want to persist one already-materialized runtime union.
1078// This is not a generic fallback: normal typed persistence should use
1079// `PersistedStructuredFieldCodec` or `PersistedByKindCodec` on the concrete
1080// field type instead of routing through `Value`.
1081impl PersistedStructuredFieldCodec for Value {
1082    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
1083        encode_structural_value_storage_bytes(self)
1084            .map_err(InternalError::persisted_row_encode_failed)
1085    }
1086
1087    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
1088        decode_structural_value_storage_bytes(bytes)
1089            .map_err(InternalError::persisted_row_decode_failed)
1090    }
1091}
1092
1093// Encode one meta-owned runtime value through the field type's declared
1094// storage lane instead of assuming direct structured payload bytes.
1095fn encode_runtime_value_payload_by_meta<T>(
1096    value: &T,
1097    field_name: &'static str,
1098) -> Result<Vec<u8>, InternalError>
1099where
1100    T: FieldTypeMeta + RuntimeValueEncode,
1101{
1102    let runtime_value = value.to_value();
1103
1104    match T::STORAGE_DECODE {
1105        FieldStorageDecode::ByKind => {
1106            encode_explicit_by_kind_value(T::KIND, &runtime_value, field_name)
1107        }
1108        FieldStorageDecode::Value => encode_structural_value_storage_bytes(&runtime_value)
1109            .map_err(|err| InternalError::persisted_row_field_encode_failed(field_name, err)),
1110    }
1111}
1112
1113// Decode one meta-owned runtime value through the field type's declared
1114// storage lane before reconstructing the concrete typed owner.
1115fn decode_runtime_value_payload_by_meta<T>(
1116    bytes: &[u8],
1117    field_name: &'static str,
1118) -> Result<T, InternalError>
1119where
1120    T: FieldTypeMeta + RuntimeValueDecode,
1121{
1122    let runtime_value = match T::STORAGE_DECODE {
1123        FieldStorageDecode::ByKind => decode_explicit_by_kind_value(bytes, T::KIND, field_name)?
1124            .ok_or_else(|| {
1125                InternalError::persisted_row_field_decode_failed(
1126                    field_name,
1127                    "unexpected null for non-nullable field",
1128                )
1129            })?,
1130        FieldStorageDecode::Value => decode_structural_value_storage_bytes(bytes)
1131            .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?,
1132    };
1133
1134    T::from_value(&runtime_value).ok_or_else(|| {
1135        InternalError::persisted_row_field_decode_failed(
1136            field_name,
1137            format!("payload does not match {}", std::any::type_name::<T>()),
1138        )
1139    })
1140}
1141
1142// Encode one optional meta-owned runtime value while preserving the field
1143// type's declared null representation.
1144fn encode_runtime_value_option_payload_by_meta<T>(
1145    value: Option<&T>,
1146    field_name: &'static str,
1147) -> Result<Vec<u8>, InternalError>
1148where
1149    T: FieldTypeMeta + RuntimeValueEncode,
1150{
1151    match value {
1152        Some(value) => encode_runtime_value_payload_by_meta(value, field_name),
1153        None => match T::STORAGE_DECODE {
1154            FieldStorageDecode::ByKind => {
1155                encode_explicit_by_kind_value(T::KIND, &Value::Null, field_name)
1156            }
1157            FieldStorageDecode::Value => Ok(encode_structural_value_storage_null_bytes()),
1158        },
1159    }
1160}
1161
1162// Decode one optional meta-owned runtime value while preserving the field
1163// type's declared null representation.
1164fn decode_runtime_value_option_payload_by_meta<T>(
1165    bytes: &[u8],
1166    field_name: &'static str,
1167) -> Result<Option<T>, InternalError>
1168where
1169    T: FieldTypeMeta + RuntimeValueDecode,
1170{
1171    let runtime_value = match T::STORAGE_DECODE {
1172        FieldStorageDecode::ByKind => decode_explicit_by_kind_value(bytes, T::KIND, field_name)?,
1173        FieldStorageDecode::Value => Some(
1174            decode_structural_value_storage_bytes(bytes)
1175                .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?,
1176        ),
1177    };
1178
1179    let Some(runtime_value) = runtime_value else {
1180        return Ok(None);
1181    };
1182
1183    if matches!(runtime_value, Value::Null) {
1184        return Ok(None);
1185    }
1186
1187    T::from_value(&runtime_value).map(Some).ok_or_else(|| {
1188        InternalError::persisted_row_field_decode_failed(
1189            field_name,
1190            format!("payload does not match {}", std::any::type_name::<T>()),
1191        )
1192    })
1193}
1194
1195// The field-meta lane is entirely selected by `FieldTypeMeta`, so one blanket
1196// impl keeps generated/runtime/container owners on the same storage contract
1197// instead of re-emitting identical per-type forwarding bodies.
1198impl<T> PersistedFieldMetaCodec for T
1199where
1200    T: FieldTypeMeta + RuntimeValueEncode + RuntimeValueDecode,
1201{
1202    fn encode_persisted_slot_payload_by_meta(
1203        &self,
1204        field_name: &'static str,
1205    ) -> Result<Vec<u8>, InternalError> {
1206        encode_runtime_value_payload_by_meta(self, field_name)
1207    }
1208
1209    fn decode_persisted_slot_payload_by_meta(
1210        bytes: &[u8],
1211        field_name: &'static str,
1212    ) -> Result<Self, InternalError> {
1213        decode_runtime_value_payload_by_meta(bytes, field_name)
1214    }
1215
1216    fn encode_persisted_option_slot_payload_by_meta(
1217        value: &Option<Self>,
1218        field_name: &'static str,
1219    ) -> Result<Vec<u8>, InternalError> {
1220        encode_runtime_value_option_payload_by_meta(value.as_ref(), field_name)
1221    }
1222
1223    fn decode_persisted_option_slot_payload_by_meta(
1224        bytes: &[u8],
1225        field_name: &'static str,
1226    ) -> Result<Option<Self>, InternalError> {
1227        decode_runtime_value_option_payload_by_meta(bytes, field_name)
1228    }
1229}
1230
1231impl_persisted_structured_signed_scalar_codec!(i8, i16, i32, i64);
1232impl_persisted_structured_unsigned_scalar_codec!(u8, u16, u32, u64);
1233
1234impl<T> PersistedStructuredFieldCodec for Vec<T>
1235where
1236    T: PersistedStructuredFieldCodec,
1237{
1238    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
1239        let item_payloads = self
1240            .iter()
1241            .map(PersistedStructuredFieldCodec::encode_persisted_structured_payload)
1242            .collect::<Result<Vec<_>, _>>()?;
1243        let item_slices = item_payloads.iter().map(Vec::as_slice).collect::<Vec<_>>();
1244
1245        Ok(encode_list_item(item_slices.as_slice()))
1246    }
1247
1248    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
1249        let item_bytes =
1250            decode_list_item(bytes).map_err(InternalError::persisted_row_decode_failed)?;
1251
1252        item_bytes
1253            .into_iter()
1254            .map(T::decode_persisted_structured_payload)
1255            .collect()
1256    }
1257}
1258
1259impl<T> PersistedStructuredFieldCodec for Option<T>
1260where
1261    T: PersistedStructuredFieldCodec,
1262{
1263    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
1264        match self {
1265            Some(value) => value.encode_persisted_structured_payload(),
1266            None => Ok(encode_structural_value_storage_null_bytes()),
1267        }
1268    }
1269
1270    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
1271        if structural_value_storage_bytes_are_null(bytes)
1272            .map_err(InternalError::persisted_row_decode_failed)?
1273        {
1274            return Ok(None);
1275        }
1276
1277        T::decode_persisted_structured_payload(bytes).map(Some)
1278    }
1279}
1280
1281impl<T> PersistedStructuredFieldCodec for Box<T>
1282where
1283    T: PersistedStructuredFieldCodec,
1284{
1285    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
1286        self.as_ref().encode_persisted_structured_payload()
1287    }
1288
1289    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
1290        T::decode_persisted_structured_payload(bytes).map(Self::new)
1291    }
1292}
1293
1294impl<T> PersistedStructuredFieldCodec for BTreeSet<T>
1295where
1296    T: Ord + PersistedStructuredFieldCodec,
1297{
1298    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
1299        let item_payloads = self
1300            .iter()
1301            .map(PersistedStructuredFieldCodec::encode_persisted_structured_payload)
1302            .collect::<Result<Vec<_>, _>>()?;
1303        let item_slices = item_payloads.iter().map(Vec::as_slice).collect::<Vec<_>>();
1304
1305        Ok(encode_list_item(item_slices.as_slice()))
1306    }
1307
1308    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
1309        let item_bytes =
1310            decode_list_item(bytes).map_err(InternalError::persisted_row_decode_failed)?;
1311        let mut out = Self::new();
1312        for item_bytes in item_bytes {
1313            let item = T::decode_persisted_structured_payload(item_bytes)?;
1314            if !out.insert(item) {
1315                return Err(InternalError::persisted_row_decode_failed(format!(
1316                    "value payload does not match BTreeSet<{}>",
1317                    std::any::type_name::<T>()
1318                )));
1319            }
1320        }
1321
1322        Ok(out)
1323    }
1324}
1325
1326impl<K, V> PersistedStructuredFieldCodec for BTreeMap<K, V>
1327where
1328    K: Ord + PersistedStructuredFieldCodec,
1329    V: PersistedStructuredFieldCodec,
1330{
1331    fn encode_persisted_structured_payload(&self) -> Result<Vec<u8>, InternalError> {
1332        let entry_payloads = self
1333            .iter()
1334            .map(|(key, value)| {
1335                Ok((
1336                    key.encode_persisted_structured_payload()?,
1337                    value.encode_persisted_structured_payload()?,
1338                ))
1339            })
1340            .collect::<Result<Vec<_>, InternalError>>()?;
1341        let entry_slices = entry_payloads
1342            .iter()
1343            .map(|(key_bytes, value_bytes)| (key_bytes.as_slice(), value_bytes.as_slice()))
1344            .collect::<Vec<_>>();
1345
1346        Ok(encode_map_entry(entry_slices.as_slice()))
1347    }
1348
1349    fn decode_persisted_structured_payload(bytes: &[u8]) -> Result<Self, InternalError> {
1350        let entry_bytes =
1351            decode_map_entry(bytes).map_err(InternalError::persisted_row_decode_failed)?;
1352        let mut out = Self::new();
1353        for (key_bytes, value_bytes) in entry_bytes {
1354            let key = K::decode_persisted_structured_payload(key_bytes)?;
1355            let value = V::decode_persisted_structured_payload(value_bytes)?;
1356
1357            if let Some((previous_key, _)) = out.last_key_value()
1358                && key <= *previous_key
1359            {
1360                return Err(InternalError::persisted_row_decode_failed(format!(
1361                    "value payload does not match BTreeMap<{}, {}>",
1362                    std::any::type_name::<K>(),
1363                    std::any::type_name::<V>()
1364                )));
1365            }
1366            if out.insert(key, value).is_some() {
1367                return Err(InternalError::persisted_row_decode_failed(format!(
1368                    "value payload does not match BTreeMap<{}, {}>",
1369                    std::any::type_name::<K>(),
1370                    std::any::type_name::<V>()
1371                )));
1372            }
1373        }
1374
1375        Ok(out)
1376    }
1377}
1378
1379/// Decode one persisted custom-schema payload through the direct structured
1380/// field codec owner.
1381pub fn decode_persisted_custom_slot_payload<T>(
1382    bytes: &[u8],
1383    field_name: &'static str,
1384) -> Result<T, InternalError>
1385where
1386    T: PersistedStructuredFieldCodec,
1387{
1388    T::decode_persisted_structured_payload(bytes)
1389        .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))
1390}
1391
1392/// Decode one persisted repeated custom-schema payload through the `Vec<T>`
1393/// structured codec owner.
1394pub fn decode_persisted_custom_many_slot_payload<T>(
1395    bytes: &[u8],
1396    field_name: &'static str,
1397) -> Result<Vec<T>, InternalError>
1398where
1399    Vec<T>: PersistedStructuredFieldCodec,
1400{
1401    <Vec<T>>::decode_persisted_structured_payload(bytes)
1402        .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))
1403}
1404
1405/// Encode one custom-schema field payload through the direct structured field
1406/// codec owner.
1407pub fn encode_persisted_custom_slot_payload<T>(
1408    value: &T,
1409    field_name: &'static str,
1410) -> Result<Vec<u8>, InternalError>
1411where
1412    T: PersistedStructuredFieldCodec,
1413{
1414    value
1415        .encode_persisted_structured_payload()
1416        .map_err(|err| InternalError::persisted_row_field_encode_failed(field_name, err))
1417}
1418
1419/// Encode one repeated custom-schema payload through the `Vec<T>` structured
1420/// codec owner.
1421pub fn encode_persisted_custom_many_slot_payload<T>(
1422    values: &[T],
1423    field_name: &'static str,
1424) -> Result<Vec<u8>, InternalError>
1425where
1426    T: Clone,
1427    Vec<T>: PersistedStructuredFieldCodec,
1428{
1429    values
1430        .to_vec()
1431        .encode_persisted_structured_payload()
1432        .map_err(|err| InternalError::persisted_row_field_encode_failed(field_name, err))
1433}
1434
1435/// Encode one persisted slot payload using the field type's own runtime field
1436/// metadata.
1437pub fn encode_persisted_slot_payload_by_meta<T>(
1438    value: &T,
1439    field_name: &'static str,
1440) -> Result<Vec<u8>, InternalError>
1441where
1442    T: PersistedFieldMetaCodec,
1443{
1444    value.encode_persisted_slot_payload_by_meta(field_name)
1445}
1446
1447/// Encode one optional persisted slot payload using the inner field type's own
1448/// runtime field metadata.
1449pub fn encode_persisted_option_slot_payload_by_meta<T>(
1450    value: &Option<T>,
1451    field_name: &'static str,
1452) -> Result<Vec<u8>, InternalError>
1453where
1454    T: PersistedFieldMetaCodec,
1455{
1456    T::encode_persisted_option_slot_payload_by_meta(value, field_name)
1457}
1458
1459/// Decode one persisted scalar slot payload using the canonical scalar envelope.
1460pub fn decode_persisted_scalar_slot_payload<T>(
1461    bytes: &[u8],
1462    field_name: &'static str,
1463) -> Result<T, InternalError>
1464where
1465    T: PersistedScalar,
1466{
1467    let payload = decode_scalar_slot_payload_body(bytes, field_name)?.ok_or_else(|| {
1468        InternalError::persisted_row_field_decode_failed(
1469            field_name,
1470            "unexpected null for non-nullable scalar field",
1471        )
1472    })?;
1473
1474    T::decode_scalar_payload(payload, field_name)
1475}
1476
1477/// Decode one optional persisted scalar slot payload preserving explicit `NULL`.
1478pub fn decode_persisted_option_scalar_slot_payload<T>(
1479    bytes: &[u8],
1480    field_name: &'static str,
1481) -> Result<Option<T>, InternalError>
1482where
1483    T: PersistedScalar,
1484{
1485    let Some(payload) = decode_scalar_slot_payload_body(bytes, field_name)? else {
1486        return Ok(None);
1487    };
1488
1489    T::decode_scalar_payload(payload, field_name).map(Some)
1490}
1491
1492// Encode one scalar slot value into the canonical prefixed scalar envelope.
1493pub(super) fn encode_scalar_slot_value(value: ScalarSlotValueRef<'_>) -> Vec<u8> {
1494    match value {
1495        ScalarSlotValueRef::Null => vec![SCALAR_SLOT_PREFIX, SCALAR_SLOT_TAG_NULL],
1496        ScalarSlotValueRef::Value(value) => {
1497            let mut encoded = Vec::new();
1498            encoded.push(SCALAR_SLOT_PREFIX);
1499            encoded.push(SCALAR_SLOT_TAG_VALUE);
1500
1501            match value {
1502                ScalarValueRef::Blob(bytes) => encoded.extend_from_slice(bytes),
1503                ScalarValueRef::Bool(value) => encoded.push(u8::from(value)),
1504                ScalarValueRef::Date(value) => {
1505                    encoded.extend_from_slice(&value.as_days_since_epoch().to_le_bytes());
1506                }
1507                ScalarValueRef::Duration(value) => {
1508                    encoded.extend_from_slice(&value.as_millis().to_le_bytes());
1509                }
1510                ScalarValueRef::Float32(value) => {
1511                    encoded.extend_from_slice(&value.get().to_bits().to_le_bytes());
1512                }
1513                ScalarValueRef::Float64(value) => {
1514                    encoded.extend_from_slice(&value.get().to_bits().to_le_bytes());
1515                }
1516                ScalarValueRef::Int(value) => encoded.extend_from_slice(&value.to_le_bytes()),
1517                ScalarValueRef::Principal(value) => encoded.extend_from_slice(value.as_slice()),
1518                ScalarValueRef::Subaccount(value) => encoded.extend_from_slice(&value.to_bytes()),
1519                ScalarValueRef::Text(value) => encoded.extend_from_slice(value.as_bytes()),
1520                ScalarValueRef::Timestamp(value) => {
1521                    encoded.extend_from_slice(&value.as_millis().to_le_bytes());
1522                }
1523                ScalarValueRef::Uint(value) => encoded.extend_from_slice(&value.to_le_bytes()),
1524                ScalarValueRef::Ulid(value) => encoded.extend_from_slice(&value.to_bytes()),
1525                ScalarValueRef::Unit => {}
1526            }
1527
1528            encoded
1529        }
1530    }
1531}
1532
1533// Split one scalar slot envelope into `NULL` vs payload bytes.
1534fn decode_scalar_slot_payload_body<'a>(
1535    bytes: &'a [u8],
1536    field_name: &'static str,
1537) -> Result<Option<&'a [u8]>, InternalError> {
1538    let Some((&prefix, rest)) = bytes.split_first() else {
1539        return Err(InternalError::persisted_row_field_decode_failed(
1540            field_name,
1541            "empty scalar payload",
1542        ));
1543    };
1544    if prefix != SCALAR_SLOT_PREFIX {
1545        return Err(InternalError::persisted_row_field_decode_failed(
1546            field_name,
1547            format!(
1548                "scalar payload prefix mismatch: expected slot envelope prefix byte 0x{SCALAR_SLOT_PREFIX:02X}, found 0x{prefix:02X}",
1549            ),
1550        ));
1551    }
1552    let Some((&tag, payload)) = rest.split_first() else {
1553        return Err(InternalError::persisted_row_field_decode_failed(
1554            field_name,
1555            "truncated scalar payload tag",
1556        ));
1557    };
1558
1559    match tag {
1560        SCALAR_SLOT_TAG_NULL => {
1561            if !payload.is_empty() {
1562                return Err(InternalError::persisted_row_field_decode_failed(
1563                    field_name,
1564                    "null scalar payload has trailing bytes",
1565                ));
1566            }
1567
1568            Ok(None)
1569        }
1570        SCALAR_SLOT_TAG_VALUE => Ok(Some(payload)),
1571        _ => Err(InternalError::persisted_row_field_decode_failed(
1572            field_name,
1573            format!("invalid scalar payload tag {tag}"),
1574        )),
1575    }
1576}
1577
1578// Decode one scalar slot view using the field-declared scalar codec.
1579#[expect(clippy::too_many_lines)]
1580pub(super) fn decode_scalar_slot_value<'a>(
1581    bytes: &'a [u8],
1582    codec: ScalarCodec,
1583    field_name: &'static str,
1584) -> Result<ScalarSlotValueRef<'a>, InternalError> {
1585    let Some(payload) = decode_scalar_slot_payload_body(bytes, field_name)? else {
1586        return Ok(ScalarSlotValueRef::Null);
1587    };
1588
1589    let value = match codec {
1590        ScalarCodec::Blob => ScalarValueRef::Blob(payload),
1591        ScalarCodec::Bool => {
1592            let [value] = payload else {
1593                return Err(
1594                    InternalError::persisted_row_field_payload_exact_len_required(
1595                        field_name,
1596                        "bool",
1597                        SCALAR_BOOL_PAYLOAD_LEN,
1598                    ),
1599                );
1600            };
1601            match *value {
1602                SCALAR_BOOL_FALSE_TAG => ScalarValueRef::Bool(false),
1603                SCALAR_BOOL_TRUE_TAG => ScalarValueRef::Bool(true),
1604                _ => {
1605                    return Err(InternalError::persisted_row_field_payload_invalid_byte(
1606                        field_name, "bool", *value,
1607                    ));
1608                }
1609            }
1610        }
1611        ScalarCodec::Date => {
1612            let bytes: [u8; SCALAR_WORD32_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
1613                InternalError::persisted_row_field_payload_exact_len_required(
1614                    field_name,
1615                    "date",
1616                    SCALAR_WORD32_PAYLOAD_LEN,
1617                )
1618            })?;
1619            ScalarValueRef::Date(Date::from_days_since_epoch(i32::from_le_bytes(bytes)))
1620        }
1621        ScalarCodec::Duration => {
1622            let bytes: [u8; SCALAR_WORD64_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
1623                InternalError::persisted_row_field_payload_exact_len_required(
1624                    field_name,
1625                    "duration",
1626                    SCALAR_WORD64_PAYLOAD_LEN,
1627                )
1628            })?;
1629            ScalarValueRef::Duration(Duration::from_millis(u64::from_le_bytes(bytes)))
1630        }
1631        ScalarCodec::Float32 => {
1632            let bytes: [u8; SCALAR_WORD32_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
1633                InternalError::persisted_row_field_payload_exact_len_required(
1634                    field_name,
1635                    "float32",
1636                    SCALAR_WORD32_PAYLOAD_LEN,
1637                )
1638            })?;
1639            let value = f32::from_bits(u32::from_le_bytes(bytes));
1640            let value = Float32::try_new(value).ok_or_else(|| {
1641                InternalError::persisted_row_field_payload_non_finite(field_name, "float32")
1642            })?;
1643            ScalarValueRef::Float32(value)
1644        }
1645        ScalarCodec::Float64 => {
1646            let bytes: [u8; SCALAR_WORD64_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
1647                InternalError::persisted_row_field_payload_exact_len_required(
1648                    field_name,
1649                    "float64",
1650                    SCALAR_WORD64_PAYLOAD_LEN,
1651                )
1652            })?;
1653            let value = f64::from_bits(u64::from_le_bytes(bytes));
1654            let value = Float64::try_new(value).ok_or_else(|| {
1655                InternalError::persisted_row_field_payload_non_finite(field_name, "float64")
1656            })?;
1657            ScalarValueRef::Float64(value)
1658        }
1659        ScalarCodec::Int64 => {
1660            let bytes: [u8; SCALAR_WORD64_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
1661                InternalError::persisted_row_field_payload_exact_len_required(
1662                    field_name,
1663                    "int",
1664                    SCALAR_WORD64_PAYLOAD_LEN,
1665                )
1666            })?;
1667            ScalarValueRef::Int(i64::from_le_bytes(bytes))
1668        }
1669        ScalarCodec::Principal => ScalarValueRef::Principal(
1670            Principal::try_from_bytes(payload)
1671                .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))?,
1672        ),
1673        ScalarCodec::Subaccount => {
1674            let bytes: [u8; SCALAR_SUBACCOUNT_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
1675                InternalError::persisted_row_field_payload_exact_len_required(
1676                    field_name,
1677                    "subaccount",
1678                    SCALAR_SUBACCOUNT_PAYLOAD_LEN,
1679                )
1680            })?;
1681            ScalarValueRef::Subaccount(Subaccount::from_array(bytes))
1682        }
1683        ScalarCodec::Text => {
1684            let value = str::from_utf8(payload).map_err(|err| {
1685                InternalError::persisted_row_field_text_payload_invalid_utf8(field_name, err)
1686            })?;
1687            ScalarValueRef::Text(value)
1688        }
1689        ScalarCodec::Timestamp => {
1690            let bytes: [u8; SCALAR_WORD64_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
1691                InternalError::persisted_row_field_payload_exact_len_required(
1692                    field_name,
1693                    "timestamp",
1694                    SCALAR_WORD64_PAYLOAD_LEN,
1695                )
1696            })?;
1697            ScalarValueRef::Timestamp(Timestamp::from_millis(i64::from_le_bytes(bytes)))
1698        }
1699        ScalarCodec::Uint64 => {
1700            let bytes: [u8; SCALAR_WORD64_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
1701                InternalError::persisted_row_field_payload_exact_len_required(
1702                    field_name,
1703                    "uint",
1704                    SCALAR_WORD64_PAYLOAD_LEN,
1705                )
1706            })?;
1707            ScalarValueRef::Uint(u64::from_le_bytes(bytes))
1708        }
1709        ScalarCodec::Ulid => {
1710            let bytes: [u8; SCALAR_ULID_PAYLOAD_LEN] = payload.try_into().map_err(|_| {
1711                InternalError::persisted_row_field_payload_exact_len_required(
1712                    field_name,
1713                    "ulid",
1714                    SCALAR_ULID_PAYLOAD_LEN,
1715                )
1716            })?;
1717            ScalarValueRef::Ulid(Ulid::from_bytes(bytes))
1718        }
1719        ScalarCodec::Unit => {
1720            if !payload.is_empty() {
1721                return Err(InternalError::persisted_row_field_payload_must_be_empty(
1722                    field_name, "unit",
1723                ));
1724            }
1725            ScalarValueRef::Unit
1726        }
1727    };
1728
1729    Ok(ScalarSlotValueRef::Value(value))
1730}
1731
1732macro_rules! impl_persisted_scalar_signed {
1733    ($($ty:ty),* $(,)?) => {
1734        $(
1735            impl PersistedScalar for $ty {
1736                const CODEC: ScalarCodec = ScalarCodec::Int64;
1737
1738                fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
1739                    Ok(i64::from(*self).to_le_bytes().to_vec())
1740                }
1741
1742                fn decode_scalar_payload(
1743                    bytes: &[u8],
1744                    field_name: &'static str,
1745                ) -> Result<Self, InternalError> {
1746                    let raw: [u8; SCALAR_WORD64_PAYLOAD_LEN] = bytes.try_into().map_err(|_| {
1747                        InternalError::persisted_row_field_payload_exact_len_required(
1748                            field_name,
1749                            "int",
1750                            SCALAR_WORD64_PAYLOAD_LEN,
1751                        )
1752                    })?;
1753                    <$ty>::try_from(i64::from_le_bytes(raw)).map_err(|_| {
1754                        InternalError::persisted_row_field_payload_out_of_range(
1755                            field_name,
1756                            "integer",
1757                        )
1758                    })
1759                }
1760            }
1761        )*
1762    };
1763}
1764
1765macro_rules! impl_persisted_scalar_unsigned {
1766    ($($ty:ty),* $(,)?) => {
1767        $(
1768            impl PersistedScalar for $ty {
1769                const CODEC: ScalarCodec = ScalarCodec::Uint64;
1770
1771                fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
1772                    Ok(u64::from(*self).to_le_bytes().to_vec())
1773                }
1774
1775                fn decode_scalar_payload(
1776                    bytes: &[u8],
1777                    field_name: &'static str,
1778                ) -> Result<Self, InternalError> {
1779                    let raw: [u8; SCALAR_WORD64_PAYLOAD_LEN] = bytes.try_into().map_err(|_| {
1780                        InternalError::persisted_row_field_payload_exact_len_required(
1781                            field_name,
1782                            "uint",
1783                            SCALAR_WORD64_PAYLOAD_LEN,
1784                        )
1785                    })?;
1786                    <$ty>::try_from(u64::from_le_bytes(raw)).map_err(|_| {
1787                        InternalError::persisted_row_field_payload_out_of_range(
1788                            field_name,
1789                            "unsigned",
1790                        )
1791                    })
1792                }
1793            }
1794        )*
1795    };
1796}
1797
1798impl_persisted_scalar_signed!(i8, i16, i32, i64);
1799impl_persisted_scalar_unsigned!(u8, u16, u32, u64);
1800
1801impl PersistedScalar for bool {
1802    const CODEC: ScalarCodec = ScalarCodec::Bool;
1803
1804    fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
1805        Ok(vec![u8::from(*self)])
1806    }
1807
1808    fn decode_scalar_payload(
1809        bytes: &[u8],
1810        field_name: &'static str,
1811    ) -> Result<Self, InternalError> {
1812        let [value] = bytes else {
1813            return Err(
1814                InternalError::persisted_row_field_payload_exact_len_required(
1815                    field_name,
1816                    "bool",
1817                    SCALAR_BOOL_PAYLOAD_LEN,
1818                ),
1819            );
1820        };
1821
1822        match *value {
1823            SCALAR_BOOL_FALSE_TAG => Ok(false),
1824            SCALAR_BOOL_TRUE_TAG => Ok(true),
1825            _ => Err(InternalError::persisted_row_field_payload_invalid_byte(
1826                field_name, "bool", *value,
1827            )),
1828        }
1829    }
1830}
1831
1832impl PersistedScalar for String {
1833    const CODEC: ScalarCodec = ScalarCodec::Text;
1834
1835    fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
1836        Ok(self.as_bytes().to_vec())
1837    }
1838
1839    fn decode_scalar_payload(
1840        bytes: &[u8],
1841        field_name: &'static str,
1842    ) -> Result<Self, InternalError> {
1843        str::from_utf8(bytes).map(str::to_owned).map_err(|err| {
1844            InternalError::persisted_row_field_text_payload_invalid_utf8(field_name, err)
1845        })
1846    }
1847}
1848
1849impl PersistedScalar for Vec<u8> {
1850    const CODEC: ScalarCodec = ScalarCodec::Blob;
1851
1852    fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
1853        Ok(self.clone())
1854    }
1855
1856    fn decode_scalar_payload(
1857        bytes: &[u8],
1858        _field_name: &'static str,
1859    ) -> Result<Self, InternalError> {
1860        Ok(bytes.to_vec())
1861    }
1862}
1863
1864impl PersistedScalar for Blob {
1865    const CODEC: ScalarCodec = ScalarCodec::Blob;
1866
1867    fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
1868        Ok(self.to_vec())
1869    }
1870
1871    fn decode_scalar_payload(
1872        bytes: &[u8],
1873        _field_name: &'static str,
1874    ) -> Result<Self, InternalError> {
1875        Ok(Self::from(bytes))
1876    }
1877}
1878
1879impl PersistedScalar for Ulid {
1880    const CODEC: ScalarCodec = ScalarCodec::Ulid;
1881
1882    fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
1883        Ok(self.to_bytes().to_vec())
1884    }
1885
1886    fn decode_scalar_payload(
1887        bytes: &[u8],
1888        field_name: &'static str,
1889    ) -> Result<Self, InternalError> {
1890        Self::try_from_bytes(bytes)
1891            .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))
1892    }
1893}
1894
1895impl PersistedScalar for Timestamp {
1896    const CODEC: ScalarCodec = ScalarCodec::Timestamp;
1897
1898    fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
1899        Ok(self.as_millis().to_le_bytes().to_vec())
1900    }
1901
1902    fn decode_scalar_payload(
1903        bytes: &[u8],
1904        field_name: &'static str,
1905    ) -> Result<Self, InternalError> {
1906        let raw: [u8; SCALAR_WORD64_PAYLOAD_LEN] = bytes.try_into().map_err(|_| {
1907            InternalError::persisted_row_field_payload_exact_len_required(
1908                field_name,
1909                "timestamp",
1910                SCALAR_WORD64_PAYLOAD_LEN,
1911            )
1912        })?;
1913
1914        Ok(Self::from_millis(i64::from_le_bytes(raw)))
1915    }
1916}
1917
1918impl PersistedScalar for Date {
1919    const CODEC: ScalarCodec = ScalarCodec::Date;
1920
1921    fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
1922        Ok(self.as_days_since_epoch().to_le_bytes().to_vec())
1923    }
1924
1925    fn decode_scalar_payload(
1926        bytes: &[u8],
1927        field_name: &'static str,
1928    ) -> Result<Self, InternalError> {
1929        let raw: [u8; SCALAR_WORD32_PAYLOAD_LEN] = bytes.try_into().map_err(|_| {
1930            InternalError::persisted_row_field_payload_exact_len_required(
1931                field_name,
1932                "date",
1933                SCALAR_WORD32_PAYLOAD_LEN,
1934            )
1935        })?;
1936
1937        Ok(Self::from_days_since_epoch(i32::from_le_bytes(raw)))
1938    }
1939}
1940
1941impl PersistedScalar for Duration {
1942    const CODEC: ScalarCodec = ScalarCodec::Duration;
1943
1944    fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
1945        Ok(self.as_millis().to_le_bytes().to_vec())
1946    }
1947
1948    fn decode_scalar_payload(
1949        bytes: &[u8],
1950        field_name: &'static str,
1951    ) -> Result<Self, InternalError> {
1952        let raw: [u8; SCALAR_WORD64_PAYLOAD_LEN] = bytes.try_into().map_err(|_| {
1953            InternalError::persisted_row_field_payload_exact_len_required(
1954                field_name,
1955                "duration",
1956                SCALAR_WORD64_PAYLOAD_LEN,
1957            )
1958        })?;
1959
1960        Ok(Self::from_millis(u64::from_le_bytes(raw)))
1961    }
1962}
1963
1964impl PersistedScalar for Float32 {
1965    const CODEC: ScalarCodec = ScalarCodec::Float32;
1966
1967    fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
1968        Ok(self.get().to_bits().to_le_bytes().to_vec())
1969    }
1970
1971    fn decode_scalar_payload(
1972        bytes: &[u8],
1973        field_name: &'static str,
1974    ) -> Result<Self, InternalError> {
1975        let raw: [u8; SCALAR_WORD32_PAYLOAD_LEN] = bytes.try_into().map_err(|_| {
1976            InternalError::persisted_row_field_payload_exact_len_required(
1977                field_name,
1978                "float32",
1979                SCALAR_WORD32_PAYLOAD_LEN,
1980            )
1981        })?;
1982        let value = f32::from_bits(u32::from_le_bytes(raw));
1983
1984        Self::try_new(value).ok_or_else(|| {
1985            InternalError::persisted_row_field_payload_non_finite(field_name, "float32")
1986        })
1987    }
1988}
1989
1990impl PersistedScalar for Float64 {
1991    const CODEC: ScalarCodec = ScalarCodec::Float64;
1992
1993    fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
1994        Ok(self.get().to_bits().to_le_bytes().to_vec())
1995    }
1996
1997    fn decode_scalar_payload(
1998        bytes: &[u8],
1999        field_name: &'static str,
2000    ) -> Result<Self, InternalError> {
2001        let raw: [u8; SCALAR_WORD64_PAYLOAD_LEN] = bytes.try_into().map_err(|_| {
2002            InternalError::persisted_row_field_payload_exact_len_required(
2003                field_name,
2004                "float64",
2005                SCALAR_WORD64_PAYLOAD_LEN,
2006            )
2007        })?;
2008        let value = f64::from_bits(u64::from_le_bytes(raw));
2009
2010        Self::try_new(value).ok_or_else(|| {
2011            InternalError::persisted_row_field_payload_non_finite(field_name, "float64")
2012        })
2013    }
2014}
2015
2016impl PersistedScalar for Principal {
2017    const CODEC: ScalarCodec = ScalarCodec::Principal;
2018
2019    fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
2020        self.to_bytes()
2021            .map_err(|err| InternalError::persisted_row_field_encode_failed("principal", err))
2022    }
2023
2024    fn decode_scalar_payload(
2025        bytes: &[u8],
2026        field_name: &'static str,
2027    ) -> Result<Self, InternalError> {
2028        Self::try_from_bytes(bytes)
2029            .map_err(|err| InternalError::persisted_row_field_decode_failed(field_name, err))
2030    }
2031}
2032
2033impl PersistedScalar for Subaccount {
2034    const CODEC: ScalarCodec = ScalarCodec::Subaccount;
2035
2036    fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
2037        Ok(self.to_bytes().to_vec())
2038    }
2039
2040    fn decode_scalar_payload(
2041        bytes: &[u8],
2042        field_name: &'static str,
2043    ) -> Result<Self, InternalError> {
2044        let raw: [u8; SCALAR_SUBACCOUNT_PAYLOAD_LEN] = bytes.try_into().map_err(|_| {
2045            InternalError::persisted_row_field_payload_exact_len_required(
2046                field_name,
2047                "subaccount",
2048                SCALAR_SUBACCOUNT_PAYLOAD_LEN,
2049            )
2050        })?;
2051
2052        Ok(Self::from_array(raw))
2053    }
2054}
2055
2056impl PersistedScalar for () {
2057    const CODEC: ScalarCodec = ScalarCodec::Unit;
2058
2059    fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
2060        Ok(Vec::new())
2061    }
2062
2063    fn decode_scalar_payload(
2064        bytes: &[u8],
2065        field_name: &'static str,
2066    ) -> Result<Self, InternalError> {
2067        if !bytes.is_empty() {
2068            return Err(InternalError::persisted_row_field_payload_must_be_empty(
2069                field_name, "unit",
2070            ));
2071        }
2072
2073        Ok(())
2074    }
2075}
2076
2077impl PersistedScalar for Unit {
2078    const CODEC: ScalarCodec = ScalarCodec::Unit;
2079
2080    fn encode_scalar_payload(&self) -> Result<Vec<u8>, InternalError> {
2081        Ok(Vec::new())
2082    }
2083
2084    fn decode_scalar_payload(
2085        bytes: &[u8],
2086        field_name: &'static str,
2087    ) -> Result<Self, InternalError> {
2088        if !bytes.is_empty() {
2089            return Err(InternalError::persisted_row_field_payload_must_be_empty(
2090                field_name, "unit",
2091            ));
2092        }
2093
2094        Ok(Self)
2095    }
2096}