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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
/*
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, TypedTag, ValueMarker, value::ValueSer};
use bytemuck::{try_cast_slice, try_cast_vec};
use core::marker::Sized;
use log::trace;
use std::borrow::Cow;
pub type OBB = ObjectBufferBuilder;
#[derive(Default)]
pub struct ObjectBufferBuilder(Vec<(Tag, u32, Vec<u32>)>);
impl ObjectBufferBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn push<'a, T: ValueMarker<'a> + ?Sized>(&mut self, tag: TypedTag<T>, value: T::Inner) {
let tyb = (T::Inner::TYPE as u32) << 2;
if T::Inner::TYPE.is_aligned() {
let mut buf = Vec::new();
value.store_aligned(&mut buf);
self.0.push((tag.0, tyb, buf));
} else {
let mut buf = Vec::new();
value.store_unaligned(&mut buf);
let pad = pad_vec(&mut buf);
self.0.push((tag.0, tyb | pad, vec_u8_to_u32(buf)));
}
}
pub fn with<'a, T: ValueMarker<'a> + ?Sized>(
mut self,
tag: TypedTag<T>,
value: T::Inner,
) -> Self {
self.push(tag, value);
self
}
pub fn finish(mut self) -> Box<Object> {
let mut tags = Vec::new();
let mut offsets = Vec::new();
let mut values = Vec::new();
self.0.sort_by_key(|(t, _, _)| t.0);
for (tag, mut off, buf) in self.0 {
tags.push(tag.0);
off |= (values.len() as u32) << 5;
offsets.push(off);
values.extend(buf);
}
vec_to_ob(
[tags.len() as u32]
.into_iter()
.chain(tags)
.chain(offsets)
.chain(values)
.collect(),
)
}
}
pub fn vec_to_ob(v: Vec<u32>) -> Box<Object> {
//? safe way to do this?
unsafe { std::mem::transmute(v.into_boxed_slice()) }
}
pub const fn slice_to_ob(v: &[u32]) -> &Object {
//? safe way to do this?
unsafe { std::mem::transmute(v) }
}
#[inline]
pub(super) fn pad_vec(temp: &mut Vec<u8>) -> u32 {
let mut pad = 0;
while !temp.len().is_multiple_of(4) {
pad += 1;
temp.push(0);
}
pad
}
pub fn vec_u8_to_u32(value: Vec<u8>) -> Vec<u32> {
try_cast_vec(value).unwrap_or_else(|(_, v)| {
trace!("encountered unalined vec");
v.into_iter()
.array_chunks()
.map(u32::from_ne_bytes)
.collect()
})
}
pub fn slice_u8_to_u32<'a>(value: &'a [u8]) -> Cow<'a, [u32]> {
try_cast_slice(value)
.map(Cow::Borrowed)
.unwrap_or_else(|_| {
trace!("encountered unalined slice");
Cow::Owned(
value
.iter()
.copied()
.array_chunks()
.map(u32::from_ne_bytes)
.collect(),
)
})
}
|