/* This file is part of jellything (https://codeberg.org/metamuffin/jellything) which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2026 metamuffin */ use crate::{Object, Tag, ValueStore}; use bytemuck::try_cast_vec; pub struct ObjectBuffer(pub Vec); impl ObjectBuffer { pub fn empty() -> Self { Self(vec![0]) } pub fn as_object<'a>(&'a self) -> Object<'a> { Object::load(&self.0).unwrap() } pub fn new(fields: &mut [(Tag, &dyn ValueStore)]) -> ObjectBuffer { let mut tags = Vec::new(); let mut offsets = Vec::new(); let mut values = Vec::new(); fields.sort_by_key(|(t, _)| t.0); let mut temp = Vec::new(); for (tag, val) in fields { tags.push(tag.0); let off = (values.len() as u32) << 2; if val.is_aligned() { offsets.push(off); val.store_aligned(&mut values); } else { temp.clear(); val.store_unaligned(&mut temp); let mut pad = 0; while temp.len() % 4 != 0 { pad += 1; temp.push(0); } offsets.push(off | pad); values.extend(bytemuck::cast_slice(&temp)); // ok bc. temp length is a whole number of dwords } } ObjectBuffer( [tags.len() as u32] .into_iter() .chain(tags) .chain(offsets) .chain(values) .collect(), ) } } impl From> for ObjectBuffer { fn from(value: Vec) -> Self { ObjectBuffer(try_cast_vec(value).unwrap_or_else(|(_, v)| { v.into_iter() .array_chunks() .map(u32::from_ne_bytes) .collect() })) } } #[inline] pub(super) fn pad_vec(temp: &mut Vec) -> u32 { let mut pad = 0; while temp.len() % 4 != 0 { pad += 1; temp.push(0); } pad }