1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use std::{fmt, ops::Deref};

use crate::FrontVec;

pub struct FrontString {
    /// Must always contain valid UTF8 sequence of bytes.
    buf: FrontVec<u8>,
}

impl FrontString {
    pub fn new() -> Self {
        Self::with_capacity(0)
    }

    pub fn with_capacity(capacity: usize) -> Self {
        Self {
            buf: FrontVec::with_capacity(capacity),
        }
    }

    pub fn capacity(&self) -> usize {
        self.buf.capacity()
    }

    pub fn push_char_front(&mut self, ch: char) {
        let mut buf = [0; 4];
        let bytes = ch.encode_utf8(&mut buf).bytes();
        self.buf.extend_front(bytes);
    }

    pub fn pop_char_front(&mut self) -> Option<char> {
        self.chars().next().map(|first_char: char| {
            // Pop off all of first_char's bytes.
            for _ in 0..first_char.len_utf8() {
                // SAFETY:
                // TODO[safety argument omitted]
                unsafe {
                    self.buf.pop_front().unwrap_unchecked();
                }
            }

            first_char
        })
    }

    pub fn push_str_front<S: AsRef<str>>(&mut self, s: S) {
        self.buf.extend_front(s.as_ref().bytes());
    }

    /// Shortens the `FrontString`, keeping the **last** `len` bytes and
    /// dropping the rest.
    /// If `len` is greater than the current length, this has no effect.
    /// Note that this method has no effect on the allocated capacity of the
    /// `FrontString`.
    ///
    /// # Panics
    /// Panics if `new_len` does not lie on a `char` boundary.
    pub fn truncate(&mut self, new_len: usize) {
        let new_len = usize::min(self.len(), new_len);

        if !self.is_char_boundary(new_len) {
            panic!("new length is not on a char boundary");
        }

        self.buf.truncate(new_len);
    }
}

impl From<&str> for FrontString {
    fn from(s: &str) -> Self {
        let mut fs = FrontString::new();
        fs.push_str_front(s);
        fs
    }
}

impl From<String> for FrontString {
    fn from(s: String) -> Self {
        // SAFETY:
        //  1. A String is valid utf8 bytes.
        //  2. The Vec<u8> produced from a String contains valid utf8 bytes.
        //  3. A FrontVec<u8> produced from the Vec<u8> contains valid utf8 bytes.
        //  4. Therefore Self contains valid utf8 bytes.
        let byte_vec: Vec<u8> = s.into();
        Self {
            buf: byte_vec.into(),
        }
    }
}

impl Deref for FrontString {
    type Target = str;

    fn deref(&self) -> &Self::Target {
        let byte_slice = self.buf.as_ref();
        // SAFETY: Because `self.buf` always contains valid UTF8, this is safe.
        unsafe { std::str::from_utf8_unchecked(byte_slice) }
    }
}

impl AsRef<str> for FrontString {
    fn as_ref(&self) -> &str {
        self.deref()
    }
}

impl AsRef<[u8]> for FrontString {
    fn as_ref(&self) -> &[u8] {
        self.buf.as_ref()
    }
}

impl<S: AsRef<str>> PartialEq<S> for FrontString {
    fn eq(&self, other: &S) -> bool {
        <Self as AsRef<str>>::as_ref(self) == other.as_ref()
    }
}

impl Eq for FrontString {}

impl fmt::Debug for FrontString {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let slice: &str = self.as_ref();
        write!(f, "{slice:?}")
    }
}

impl fmt::Display for FrontString {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let slice: &str = self.as_ref();
        write!(f, "{slice}")
    }
}

impl Default for FrontString {
    fn default() -> Self {
        FrontString::new()
    }
}

impl Clone for FrontString {
    fn clone(&self) -> Self {
        Self {
            buf: self.buf.clone(),
        }
    }
}