epserde 0.12.6

ε-serde is an ε-copy (i.e., almost zero-copy) serialization/deserialization framework
Documentation
/*
 * SPDX-FileCopyrightText: 2023 Inria
 * SPDX-FileCopyrightText: 2023 Sebastiano Vigna
 *
 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
 */

//! Helpers for serialization.

use super::{SerInner, WriteWithNames};
use crate::ser;
use crate::traits::*;

pub fn check_zero_copy<V: SerInner>() {
    if !V::IS_ZERO_COPY {
        panic!(
            "Cannot serialize type {} declared as zero-copy as it is not zero-copy",
            core::any::type_name::<V>()
        );
    }
}

/// Serialize a zero-copy structure checking [that the type is actually
/// zero-copy](SerInner::IS_ZERO_COPY) and [aligning the stream
/// beforehand](WriteWithNames::align).
///
/// This function makes the appropriate checks, write the necessary padding and
/// then calls [`ser_zero_unchecked`].
pub fn ser_zero<V: ZeroCopy>(backend: &mut impl WriteWithNames, value: &V) -> ser::Result<()> {
    check_zero_copy::<V>();
    backend.align::<V>()?;
    ser_zero_unchecked(backend, value)
}

/// Serialize a zero-copy structure without checking [that the type is actually
/// zero-copy](SerInner::IS_ZERO_COPY) and without [aligning the
/// stream](WriteWithNames::align).
///
/// Note that this method uses a single [`write_all`](super::WriteNoStd::write_all)
/// call to write the entire structure.
pub fn ser_zero_unchecked<V: ZeroCopy>(
    backend: &mut impl WriteWithNames,
    value: &V,
) -> ser::Result<()> {
    let buffer = unsafe {
        core::slice::from_raw_parts(value as *const V as *const u8, core::mem::size_of::<V>())
    };
    backend.write_bytes::<V>(buffer)
}

/// Serialize a slice of zero-copy structures by encoding
/// its length first, and then its bytes properly [aligned](WriteWithNames::align).
///
/// Note that this method uses a single `write_all`
/// call to write the entire slice.
///
/// Here we check [that the type is actually zero-copy](SerInner::IS_ZERO_COPY).
pub fn ser_slice_zero<V: ZeroCopy>(
    backend: &mut impl WriteWithNames,
    data: &[V],
) -> ser::Result<()> {
    check_zero_copy::<V>();

    let len = data.len();
    backend.write("len", &len)?;
    let num_bytes = core::mem::size_of_val(data);
    let buffer = unsafe { core::slice::from_raw_parts(data.as_ptr() as *const u8, num_bytes) };
    backend.align::<V>()?;
    backend.write_bytes::<V>(buffer)
}

/// Serialize a slice of deep-copy structures by encoding
/// its length first, and then the contents item by item.
pub fn ser_slice_deep<V: SerInner>(
    backend: &mut impl WriteWithNames,
    data: &[V],
) -> ser::Result<()> {
    let len = data.len();
    backend.write("len", &len)?;
    for item in data.iter() {
        backend.write("item", item)?;
    }
    Ok(())
}