/* 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, ObjectBuffer, Tag}; pub trait Value<'a>: ValueStore + Sized { const ALIGNED: bool; fn load_aligned(buf: &'a [u32]) -> Option { let _ = buf; None } fn load_unaligned(buf: &'a [u8]) -> Option { let _ = buf; None } } pub trait ValueStore { fn is_aligned(&self) -> bool; fn store_aligned(&self, _buf: &mut Vec) {} fn store_unaligned(&self, _buf: &mut Vec) {} fn size(&self) -> usize; } impl<'a> Value<'a> for &'a str { const ALIGNED: bool = false; fn load_unaligned(buf: &'a [u8]) -> Option { str::from_utf8(buf).ok() } } impl ValueStore for &str { fn is_aligned(&self) -> bool { false } fn store_unaligned(&self, buf: &mut Vec) { buf.extend(self.as_bytes()); } fn size(&self) -> usize { self.len() } } impl Value<'_> for u32 { const ALIGNED: bool = true; fn load_aligned(buf: &[u32]) -> Option { buf.get(0).copied().map(u32::from_be) } } impl ValueStore for u32 { fn is_aligned(&self) -> bool { true } fn store_aligned(&self, buf: &mut Vec) { buf.push(self.to_be()); } fn size(&self) -> usize { 4 } } impl Value<'_> for Tag { const ALIGNED: bool = true; fn load_aligned(buf: &[u32]) -> Option { buf.get(0).copied().map(u32::from_be).map(Tag) } } impl ValueStore for Tag { fn is_aligned(&self) -> bool { true } fn store_aligned(&self, buf: &mut Vec) { buf.push(self.0.to_be()); } fn size(&self) -> usize { 4 } } impl Value<'_> for u64 { const ALIGNED: bool = false; fn load_aligned(buf: &[u32]) -> Option { let hi = u32::from_be(*buf.get(0)?) as u64; let lo = u32::from_be(*buf.get(1)?) as u64; Some(hi << 32 | lo) } } impl ValueStore for u64 { fn is_aligned(&self) -> bool { true } fn store_aligned(&self, buf: &mut Vec) { buf.push(((self >> 32) as u32).to_be()); buf.push((*self as u32).to_be()); } fn size(&self) -> usize { 8 } } impl Value<'_> for f64 { const ALIGNED: bool = false; fn load_aligned(buf: &[u32]) -> Option { u32::load_aligned(buf).map(|x| x as f64) } } impl ValueStore for f64 { fn is_aligned(&self) -> bool { true } fn store_aligned(&self, buf: &mut Vec) { (*self as u64).store_aligned(buf); } fn size(&self) -> usize { 8 } } impl Value<'_> for i64 { const ALIGNED: bool = false; fn load_aligned(buf: &[u32]) -> Option { u32::load_aligned(buf).map(|x| x as i64) } } impl ValueStore for i64 { fn is_aligned(&self) -> bool { true } fn store_aligned(&self, buf: &mut Vec) { (*self as u64).store_aligned(buf); } fn size(&self) -> usize { 8 } } impl<'a> Value<'a> for Object<'a> { const ALIGNED: bool = true; fn load_aligned(buf: &'a [u32]) -> Option { Self::load(buf) } } impl ValueStore for Object<'_> { fn is_aligned(&self) -> bool { true } fn store_aligned(&self, buf: &mut Vec) { buf.extend(self.tags); buf.extend(self.offsets); buf.extend(self.values); } fn size(&self) -> usize { (self.tags.len() + self.offsets.len() + self.values.len()) * size_of::() } } impl ValueStore for ObjectBuffer { fn is_aligned(&self) -> bool { true } fn store_aligned(&self, buf: &mut Vec) { buf.extend(&self.0); } fn size(&self) -> usize { self.0.len() * 4 } } impl<'a> Value<'a> for &'a [u8] { const ALIGNED: bool = false; fn load_unaligned(buf: &'a [u8]) -> Option { Some(buf) } } impl ValueStore for &[u8] { fn is_aligned(&self) -> bool { false } fn store_unaligned(&self, buf: &mut Vec) { buf.extend(*self); } fn size(&self) -> usize { self.len() } }