1use super::{flatten, indent, line_suffix, offside, r#break, sequence, Document};
2use alloc::{alloc::Allocator, boxed::Box, str, vec::Vec};
3
4#[derive(Clone, Debug)]
6pub struct Builder<A: Allocator> {
7 allocator: A,
8}
9
10impl<'a, A: Allocator + Clone + 'a> Builder<A> {
11 pub fn new(allocator: A) -> Self {
13 Self { allocator }
14 }
15
16 pub fn allocator(&self) -> &A {
18 &self.allocator
19 }
20
21 pub fn r#break(&self, value: impl Into<Document<'a>>) -> Document<'a> {
23 r#break(self.allocate(value.into()))
24 }
25
26 pub fn flatten(&self, value: impl Into<Document<'a>>) -> Document<'a> {
28 flatten(self.allocate(value.into()))
29 }
30
31 pub fn indent(&self, value: impl Into<Document<'a>>) -> Document<'a> {
33 indent(self.allocate(value.into()))
34 }
35
36 pub fn offside(&self, value: impl Into<Document<'a>>, soft: bool) -> Document<'a> {
38 offside(self.allocate(value.into()), soft)
39 }
40
41 pub fn sequence(
43 &self,
44 values: impl IntoIterator<Item = impl Into<Document<'a>>>,
45 ) -> Document<'a> {
46 sequence(self.allocate_slice(values.into_iter().map(Into::into)))
47 }
48
49 pub fn strings<'b>(&self, values: impl IntoIterator<Item = &'b str>) -> Document<'a> {
51 self.allocate_str(values).into()
52 }
53
54 pub fn line_suffixes<'b>(&self, values: impl IntoIterator<Item = &'b str>) -> Document<'a> {
56 line_suffix(self.allocate_str(values))
57 }
58
59 pub fn allocate<T>(&self, value: T) -> &'a T {
61 Box::leak(Box::new_in(value, self.allocator.clone()))
62 }
63
64 pub fn allocate_slice<T>(&self, values: impl IntoIterator<Item = T>) -> &'a [T] {
66 let mut vec = Vec::new_in(self.allocator.clone());
67
68 vec.extend(values);
69
70 Vec::leak(vec)
71 }
72
73 pub fn allocate_str<'b>(&self, values: impl IntoIterator<Item = &'b str>) -> &'a str {
75 let mut vec = Vec::new_in(self.allocator.clone());
76
77 for value in values {
78 vec.extend(value.as_bytes().iter().copied());
79 }
80
81 str::from_utf8(Vec::leak(vec)).expect("utf-8 string")
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 use crate::offside;
89 use alloc::alloc::Global;
90
91 #[test]
92 fn build_offside() {
93 let builder = Builder::new(Global);
94
95 assert_eq!(builder.offside("foo", false), offside(&"foo".into(), false));
96 }
97}