use alloc::{vec, vec::Vec};
use crate::models::{class::Class, output_data::OutputData};
#[derive(Debug, PartialEq)]
pub enum DataGroup<'a> {
One(OutputData<'a>),
Values(Vec<OutputData<'a>>),
}
impl<'a> DataGroup<'a> {
#[must_use]
pub fn as_slice(&self) -> &[OutputData<'a>] {
match self {
Self::One(value) => core::slice::from_ref(value),
Self::Values(values) => values,
}
}
#[must_use]
pub fn len(&self) -> usize {
self.as_slice().len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.as_slice().is_empty()
}
}
#[derive(Debug, PartialEq)]
pub enum ObjectData<'a> {
Empty,
Inline(OutputData<'a>),
Groups(Vec<DataGroup<'a>>),
}
impl<'a> ObjectData<'a> {
#[inline]
pub(crate) fn push(&mut self, group: DataGroup<'a>) {
match self {
ObjectData::Groups(groups) => groups.push(group),
ObjectData::Empty => {
*self = match group {
DataGroup::One(value) => ObjectData::Inline(value),
group => ObjectData::Groups(vec![group]),
}
}
ObjectData::Inline(_) => {
let ObjectData::Inline(first) = core::mem::replace(self, ObjectData::Empty) else {
unreachable!()
};
*self = ObjectData::Groups(vec![DataGroup::One(first), group]);
}
}
}
#[cfg(test)]
pub(crate) fn from_groups(mut groups: Vec<Vec<OutputData<'a>>>) -> Self {
if groups.is_empty() {
ObjectData::Empty
} else if groups.len() == 1 && groups[0].len() == 1 {
ObjectData::Inline(groups.pop().unwrap().pop().unwrap())
} else {
ObjectData::Groups(
groups
.into_iter()
.map(|mut group| {
if group.len() == 1 {
DataGroup::One(group.pop().unwrap())
} else {
DataGroup::Values(group)
}
})
.collect(),
)
}
}
#[must_use]
pub fn group_count(&self) -> usize {
match self {
ObjectData::Empty => 0,
ObjectData::Inline(_) => 1,
ObjectData::Groups(groups) => groups.len(),
}
}
}
#[derive(Debug, PartialEq)]
pub enum Archived<'a> {
Object {
class: usize,
data: ObjectData<'a>,
},
Class(Class),
Placeholder,
Type(usize),
}