Skip to main content

shuck_format/
formatter.rs

1use 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}