encre_css/utils/
buffer.rs

1//! Defines the buffer containing the CSS generated.
2use std::{
3    fmt::{self, Write},
4    ops::{Deref, RangeBounds},
5};
6
7/// A buffer storing the CSS generated and managing the indentation of the next lines.
8#[derive(Debug)]
9pub struct Buffer {
10    inner: String,
11    indentation: String,
12}
13
14impl Buffer {
15    /// Create a new `Buffer` with a minimal capacity.
16    pub(crate) fn with_capacity(capacity: usize) -> Self {
17        Self {
18            inner: String::with_capacity(capacity),
19            indentation: String::new(),
20        }
21    }
22
23    /// Returns the length of the buffer.
24    pub(crate) fn len(&self) -> usize {
25        self.inner.len()
26    }
27
28    /// Returns whether the next line written will have at least one level of indentation.
29    pub(crate) fn replace_range<R: RangeBounds<usize>>(&mut self, range: R, replace_with: &str) {
30        self.inner.replace_range(range, replace_with);
31    }
32
33    /// Returns whether the next line written will have at least one level of indentation.
34    pub fn is_unindented(&mut self) -> bool {
35        self.indentation.is_empty()
36    }
37
38    /// Indent the next lines using two spaces.
39    pub fn indent(&mut self) {
40        let _ = write!(self.indentation, "  ");
41    }
42
43    /// Un-indent the next lines by two spaces.
44    pub fn unindent(&mut self) {
45        self.indentation.truncate(self.indentation.len() - 2);
46    }
47
48    /// Push a new line which will be indented, in the buffer.
49    pub fn line<T: fmt::Display>(&mut self, val: T) {
50        writeln!(self.inner, "{}{}", self.indentation, val)
51            .expect("writing to a String can't fail");
52    }
53
54    /// Push a list of lines which will be indented, in the buffer.
55    pub fn lines<T: fmt::Display>(&mut self, lines: impl IntoIterator<Item = T>) {
56        lines.into_iter().for_each(|l| {
57            writeln!(self.inner, "{}{}", self.indentation, l)
58                .expect("writing to a String can't fail");
59        });
60    }
61
62    /// Push a raw string in the buffer.
63    pub fn raw(&mut self, raw: &str) {
64        self.inner.push_str(raw);
65    }
66
67    /// Returns the underlying buffer.
68    pub fn into_inner(self) -> String {
69        self.inner
70    }
71}
72
73impl Deref for Buffer {
74    type Target = str;
75
76    fn deref(&self) -> &Self::Target {
77        &self.inner
78    }
79}