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