shuck_format/
formatter.rs1use crate::buffer::{Buffer, VecBuffer};
2use crate::format_element::{Document, FormatElement};
3use crate::printer::{Printed, Printer, PrinterOptions};
4
5pub type FormatResult<T> = Result<T, FormatError>;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct FormatError {
9 message: String,
10}
11
12impl FormatError {
13 #[must_use]
14 pub fn new(message: impl Into<String>) -> Self {
15 Self {
16 message: message.into(),
17 }
18 }
19}
20
21impl std::fmt::Display for FormatError {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 f.write_str(&self.message)
24 }
25}
26
27impl std::error::Error for FormatError {}
28
29pub trait FormatContext {
30 type Options: FormatOptions;
31
32 fn options(&self) -> &Self::Options;
33
34 fn source_length_hint(&self) -> usize {
35 0
36 }
37}
38
39pub trait FormatOptions {
40 fn as_print_options(&self) -> PrinterOptions;
41}
42
43pub trait Format<Context> {
44 fn fmt(&self, formatter: &mut Formatter<Context>) -> FormatResult<()>;
45}
46
47impl<Context, T> Format<Context> for &T
48where
49 T: Format<Context>,
50{
51 fn fmt(&self, formatter: &mut Formatter<Context>) -> FormatResult<()> {
52 (*self).fmt(formatter)
53 }
54}
55
56impl<Context, T> Format<Context> for Option<T>
57where
58 T: Format<Context>,
59{
60 fn fmt(&self, formatter: &mut Formatter<Context>) -> FormatResult<()> {
61 if let Some(value) = self {
62 value.fmt(formatter)?;
63 }
64 Ok(())
65 }
66}
67
68impl<Context> Format<Context> for Document {
69 fn fmt(&self, formatter: &mut Formatter<Context>) -> FormatResult<()> {
70 formatter.write_document(self.clone());
71 Ok(())
72 }
73}
74
75impl<Context> Format<Context> for FormatElement {
76 fn fmt(&self, formatter: &mut Formatter<Context>) -> FormatResult<()> {
77 formatter.write_element(self.clone());
78 Ok(())
79 }
80}
81
82pub struct Formatter<Context> {
83 context: Context,
84 buffer: VecBuffer,
85}
86
87impl<Context> Formatter<Context>
88where
89 Context: FormatContext,
90{
91 #[must_use]
92 pub fn new(context: Context) -> Self {
93 let capacity = estimate_document_capacity(context.source_length_hint());
94 Self {
95 context,
96 buffer: VecBuffer::with_capacity(capacity),
97 }
98 }
99}
100
101impl<Context> Formatter<Context> {
102 #[must_use]
103 pub fn context(&self) -> &Context {
104 &self.context
105 }
106
107 pub fn context_mut(&mut self) -> &mut Context {
108 &mut self.context
109 }
110
111 pub fn write_element(&mut self, element: FormatElement) {
112 self.buffer.write_element(element);
113 }
114
115 pub fn write_document(&mut self, document: Document) {
116 self.buffer.write_elements(document.into_vec());
117 }
118
119 #[must_use]
120 pub fn finish(self) -> Formatted<Context> {
121 Formatted {
122 context: self.context,
123 document: Document::from_elements(self.buffer.into_vec()),
124 }
125 }
126}
127
128impl<Context> Buffer for Formatter<Context> {
129 fn write_element(&mut self, element: FormatElement) {
130 Formatter::write_element(self, element);
131 }
132
133 fn elements(&self) -> &[FormatElement] {
134 self.buffer.elements()
135 }
136}
137
138#[derive(Debug, Clone)]
139pub struct Formatted<Context> {
140 context: Context,
141 document: Document,
142}
143
144impl<Context> Formatted<Context>
145where
146 Context: FormatContext,
147{
148 pub fn print(&self) -> FormatResult<Printed> {
149 let printer = Printer::new(self.context.options().as_print_options());
150 printer
151 .print_with_capacity(&self.document, self.context.source_length_hint())
152 .map_err(|err| FormatError::new(err.to_string()))
153 }
154
155 #[must_use]
156 pub fn context(&self) -> &Context {
157 &self.context
158 }
159
160 #[must_use]
161 pub fn document(&self) -> &Document {
162 &self.document
163 }
164}
165
166fn estimate_document_capacity(source_length_hint: usize) -> usize {
167 source_length_hint / 2
168}
169
170#[derive(Debug, Clone, Default, PartialEq, Eq)]
171pub struct SimpleFormatOptions {
172 pub printer_options: PrinterOptions,
173}
174
175impl FormatOptions for SimpleFormatOptions {
176 fn as_print_options(&self) -> PrinterOptions {
177 self.printer_options
178 }
179}
180
181#[derive(Debug, Clone, Default, PartialEq, Eq)]
182pub struct SimpleFormatContext {
183 pub options: SimpleFormatOptions,
184}
185
186impl SimpleFormatContext {
187 #[must_use]
188 pub fn new(options: SimpleFormatOptions) -> Self {
189 Self { options }
190 }
191}
192
193impl FormatContext for SimpleFormatContext {
194 type Options = SimpleFormatOptions;
195
196 fn options(&self) -> &Self::Options {
197 &self.options
198 }
199}