cuicui_chirp/parser/ast/
build.rs1use std::marker::PhantomData;
2
3use super::{as_usize, header, Ast};
4
5pub(in crate::parser) struct AstBuilder {
6 ast: Vec<header::Block>,
7 #[cfg(not(feature = "more_unsafe"))]
8 zero_header: Vec<(usize, &'static str)>,
9}
10pub(in crate::parser) struct Buffer<'a, const N: usize>(pub(super) &'a mut [header::Block; N]);
11
12impl AstBuilder {
13 pub fn new() -> Self {
14 Self {
15 ast: Vec::with_capacity(128),
16 #[cfg(not(feature = "more_unsafe"))]
17 zero_header: Vec::new(),
18 }
19 }
20 pub fn write_header<T, const N: usize>(&mut self, writer: T)
21 where
22 T: std::fmt::Debug + for<'a> WriteHeader<Buffer<'a> = Buffer<'a, N>>,
23 {
24 let header = self.reserve_header::<T>();
25 self.write(header, writer);
26 }
27 pub fn reserve_header<T: WriteHeader>(&mut self) -> AstBuilderHead<T> {
28 let index = self.ast.len();
29 self.ast.extend((0..T::SIZE).map(|_| header::Block(0)));
30 #[cfg(not(feature = "more_unsafe"))]
31 {
32 self.zero_header.push((index, std::any::type_name::<T>()));
33 }
34 AstBuilderHead { index, p: PhantomData }
35 }
36 #[cfg_attr(feature = "more_unsafe", allow(unused_mut))]
37 pub fn write<T, const N: usize>(&mut self, mut head: AstBuilderHead<T>, writer: T)
38 where
39 T: std::fmt::Debug + for<'a> WriteHeader<Buffer<'a> = Buffer<'a, N>>,
40 {
41 #[cfg(not(feature = "more_unsafe"))]
42 {
43 self.zero_header.pop();
44 }
45 let (start, end) = (head.index, head.index + as_usize(T::SIZE));
46 bevy::log::trace!("{start} - {writer:?}");
47 writer.write_header(Buffer((&mut self.ast[start..end]).try_into().unwrap()));
48 }
49 pub fn build(self) -> Ast {
50 #[cfg(not(feature = "more_unsafe"))]
51 {
52 for (index, name) in &self.zero_header {
53 bevy::log::error!(
54 "{index} - {name}: Created header that never was initialized. \
55 This is a cuicui_chirp bug, please open an issue at\n\n\
56 https://github.com/nicopap/cuicui_layout/issues/new\n",
57 );
58 }
59 assert!(
60 self.zero_header.is_empty(),
61 "Proceeding would be unsound, aborting.."
62 );
63 }
64 Ast(self.ast.into())
65 }
66}
67
68pub(in crate::parser) struct AstBuilderHead<T: WriteHeader> {
69 index: usize,
70 p: PhantomData<T>,
71}
72
73pub(in crate::parser) trait WriteHeader: Sized {
74 const SIZE: u32;
75 type Buffer<'a>;
76
77 fn write_header(self, builder: Self::Buffer<'_>);
78}