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
|
/*
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) 2025 metamuffin <metamuffin.org>
*/
mod value;
pub use value::*;
use std::marker::PhantomData;
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Tag(pub u32);
pub struct TypedTag<T>(pub Tag, pub PhantomData<T>);
pub struct ObjectBuffer(pub Vec<u32>);
impl ObjectBuffer {
pub fn new() -> Self {
Self(vec![0])
}
pub fn as_object<'a>(&'a self) -> Object<'a> {
Object::load(&self.0).unwrap()
}
}
pub struct Object<'a> {
tags: &'a [u32],
offsets: &'a [u32],
values: &'a [u32],
}
impl<'a> Object<'a> {
pub fn load(buf: &'a [u32]) -> Option<Self> {
let nf = *buf.get(0)? as usize;
Some(Self {
tags: &buf[1..1 + nf],
offsets: &buf[1 + nf..1 + nf + nf],
values: &buf[1 + nf + nf..],
})
}
pub fn get_aligned(&self, tag: Tag) -> Option<&[u32]> {
let index = self.tags.binary_search(&tag.0).ok()?;
let start_raw = *self.offsets.get(index)?;
let end_raw = self
.offsets
.get(index)
.copied()
.unwrap_or((self.values.len() as u32) << 2);
let start = start_raw >> 2;
let end = end_raw >> 2;
Some(&self.values[start as usize..end as usize])
}
pub fn get_unaligned(&self, tag: Tag) -> Option<&[u8]> {
let index = self.tags.binary_search(&tag.0).ok()?;
let start_raw = *self.offsets.get(index)?;
let end_raw = self
.offsets
.get(index)
.copied()
.unwrap_or((self.values.len() as u32) << 2);
let start = (start_raw >> 2) * 4;
let padding = start_raw & 0b11;
let end = (end_raw >> 2) * 4 - padding;
let values_u8: &[u8] = bytemuck::cast_slice(self.values);
Some(&values_u8[start as usize..end as usize])
}
pub fn get_str(&self, tag: Tag) -> Option<&str> {
self.get_unaligned(tag).and_then(|b| str::from_utf8(b).ok())
}
pub fn get<'b: 'a, T: Value<'b>>(&'b self, tag: TypedTag<T>) -> Option<T> {
if T::ALIGNED {
T::load_aligned(self.get_aligned(tag.0)?)
} else {
T::load_unaligned(self.get_unaligned(tag.0)?)
}
}
}
|