use crate::size::SIZE_STACK;
#[cfg_attr(
feature = "derive",
doc = r#"
When "derive" feature is enabled, proc-macro `alkahest(Formula)` is also available.
```
# use alkahest::*;
/// Formula for serializing unit structures.
#[alkahest(Formula)]
struct UnitFormula;
# #[cfg(feature = "alloc")]
/// Formula for serializing tuple structures with fields
/// that are serializable with `u8` and `String` formulas.
#[alkahest(Formula)]
struct TupleFormula(u8, String);
# #[cfg(feature = "alloc")]
/// Formula for serializing structures with fields
/// that are serializable with `TupleFormula` and `Vec<usize>` formulas.
#[alkahest(Formula)]
struct StructFormula {
a: TupleFormula,
b: Vec<u32>,
}
# #[cfg(feature = "alloc")]
/// Formula for serializing enums.
#[alkahest(Formula)]
enum EnumFormula {
A,
B(StructFormula),
C { y: String },
}
```
Names of the formula variants and fields are important for `Serialize` and `Deserialize` proc-macros.
"#
)]
pub trait Formula {
const MAX_STACK_SIZE: Option<usize>;
const EXACT_SIZE: bool;
const HEAPLESS: bool;
}
pub trait BareFormula: Formula {}
#[inline(always)]
#[track_caller]
pub(crate) const fn unwrap_size(a: Option<usize>) -> usize {
let (arr, idx) = match a {
None => ([0], 1), Some(a) => ([a], 0),
};
arr[idx]
}
#[must_use]
#[inline(always)]
#[doc(hidden)]
pub const fn sum_size(a: Option<usize>, b: Option<usize>) -> Option<usize> {
match (a, b) {
(None, _) | (_, None) => None,
(Some(a), Some(b)) => Some(a + b),
}
}
#[must_use]
#[inline(always)]
#[doc(hidden)]
pub const fn max_size(a: Option<usize>, b: Option<usize>) -> Option<usize> {
match (a, b) {
(Some(_), None) | (None, _) => None,
(Some(a), Some(b)) if a > b => Some(a),
(Some(_), Some(b)) => Some(b),
}
}
#[inline(always)]
pub(crate) const fn repeat_size(a: Option<usize>, n: usize) -> Option<usize> {
match a {
None => None,
Some(a) => Some(a * n),
}
}
#[must_use]
#[inline(always)]
pub const fn reference_size<F>() -> usize
where
F: Formula + ?Sized,
{
if F::EXACT_SIZE {
SIZE_STACK
} else {
SIZE_STACK * 2
}
}