blob: f73b22ea67b36f7d2681662fe395ac6c85147eb9 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
/*
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 <metamuffin.org>
*/
use crate::{Object, Tag, ValueStore};
use bytemuck::try_cast_vec;
#[derive(PartialEq, Eq, Hash)]
pub struct ObjectBuffer(pub Vec<u32>);
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<Vec<u8>> for ObjectBuffer {
fn from(value: Vec<u8>) -> 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<u8>) -> u32 {
let mut pad = 0;
while temp.len() % 4 != 0 {
pad += 1;
temp.push(0);
}
pad
}
|