num_format/
buffer.rs

1use core::borrow::Borrow;
2use core::fmt;
3use core::ops::Deref;
4use core::str;
5
6use crate::constants::MAX_BUF_LEN;
7use crate::format::Format;
8use crate::to_formatted_str::ToFormattedStr;
9
10/// <b><u>A key type</u></b>. Represents a stack-allocated buffer you can use to get a
11/// formatted `&str` without heap allocation.
12///
13/// # Example
14/// ```
15/// use num_format::{Buffer, Locale};
16///
17/// fn main() {
18///     // Create a stack-allocated buffer...
19///     let mut buf = Buffer::default();
20///
21///     // Write "1,000,000" into the buffer...
22///     buf.write_formatted(&1000000, &Locale::en);
23///
24///     // Get a view into the buffer as a &str...
25///     let s = buf.as_str();
26///
27///     // Do what you want with the &str...
28///     assert_eq!("1,000,000", s);
29///
30///     // No need to clear the buffer before further calls to `write_formatted`...
31///     buf.write_formatted(&1000000, &Locale::fr);
32///     assert_eq!("1\u{202f}000\u{202f}000", buf.as_str());
33/// }
34/// ```
35#[derive(Copy, Clone)]
36pub struct Buffer {
37    pub(crate) inner: [u8; MAX_BUF_LEN],
38    pub(crate) pos: usize,
39    pub(crate) end: usize,
40}
41
42impl Buffer {
43    /// Constructs a new, stack-allocated buffer.
44    #[inline(always)]
45    pub fn new() -> Buffer {
46        Buffer {
47            inner: [0; MAX_BUF_LEN],
48            pos: MAX_BUF_LEN,
49            end: MAX_BUF_LEN,
50        }
51    }
52
53    /// Returns a `&[u8]` view into the buffer.
54    #[inline(always)]
55    pub fn as_bytes(&self) -> &[u8] {
56        &self.inner[self.pos..self.end]
57    }
58
59    /// Returns a `&str` view into the buffer.
60    #[inline(always)]
61    pub fn as_str(&self) -> &str {
62        unsafe { str::from_utf8_unchecked(self.as_bytes()) }
63    }
64
65    /// Returns `true` if the buffer is empty; `false` otherwise.
66    #[inline(always)]
67    pub fn is_empty(&self) -> bool {
68        self.len() == 0
69    }
70
71    /// Returns the length (in bytes) of the buffer.
72    #[inline(always)]
73    pub fn len(&self) -> usize {
74        self.end - self.pos
75    }
76
77    /// Writes the provided number into the buffer using the provided format.
78    #[inline(always)]
79    pub fn write_formatted<F, N>(&mut self, n: &N, format: &F) -> usize
80    where
81        F: Format,
82        N: ToFormattedStr,
83    {
84        n.read_to_buffer(self, format)
85    }
86
87    #[inline(always)]
88    pub(crate) fn as_mut_ptr(&mut self) -> *mut u8 {
89        self.inner.as_mut_ptr()
90    }
91
92    #[inline(always)]
93    pub(crate) fn write_with_itoa<N: itoa::Integer>(&mut self, n: N) -> usize {
94        let mut itoa_buf = itoa::Buffer::new();
95
96        let s = itoa_buf.format(n);
97        let s_len = s.len();
98
99        self.pos = MAX_BUF_LEN - s_len;
100        self.end = MAX_BUF_LEN;
101
102        let dst = &mut self.inner[self.pos..self.end];
103        dst.copy_from_slice(s.as_bytes());
104
105        s_len
106    }
107}
108
109impl AsRef<str> for Buffer {
110    #[inline(always)]
111    fn as_ref(&self) -> &str {
112        self.as_str()
113    }
114}
115
116impl Borrow<str> for Buffer {
117    #[inline(always)]
118    fn borrow(&self) -> &str {
119        self.as_str()
120    }
121}
122
123impl fmt::Debug for Buffer {
124    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125        write!(f, "{}", self.as_str())
126    }
127}
128
129impl Default for Buffer {
130    /// Same as the [`new`] method.
131    ///
132    /// [`new`]: struct.Buffer.html#method.new
133    #[inline(always)]
134    fn default() -> Buffer {
135        Buffer::new()
136    }
137}
138
139impl Deref for Buffer {
140    type Target = str;
141
142    #[inline(always)]
143    fn deref(&self) -> &Self::Target {
144        self.as_str()
145    }
146}
147
148impl fmt::Display for Buffer {
149    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150        write!(f, "{}", self.as_str())
151    }
152}
153
154#[cfg(feature = "with-serde")]
155mod serialization {
156    use serde::{de, ser};
157
158    use super::*;
159
160    impl ser::Serialize for Buffer {
161        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
162        where
163            S: ser::Serializer,
164        {
165            serializer.serialize_bytes(self.as_bytes())
166        }
167    }
168
169    impl<'de> de::Deserialize<'de> for Buffer {
170        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
171        where
172            D: de::Deserializer<'de>,
173        {
174            struct BufferVisitor;
175
176            impl<'de> de::Visitor<'de> for BufferVisitor {
177                type Value = Buffer;
178
179                fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180                    write!(f, "bytes of maximum length {}", MAX_BUF_LEN)
181                }
182
183                fn visit_seq<V>(self, mut seq: V) -> Result<Buffer, V::Error>
184                where
185                    V: de::SeqAccess<'de>,
186                {
187                    let mut inner: [u8; MAX_BUF_LEN] = [0; MAX_BUF_LEN];
188                    let mut index = 0;
189                    while let Some(value) = seq.next_element()? {
190                        if index < MAX_BUF_LEN {
191                            inner[index] = value;
192                            index += 1;
193                        } else {
194                            return Err(de::Error::invalid_length(index, &self));
195                        }
196                    }
197                    Ok(Buffer {
198                        inner,
199                        pos: 0,
200                        end: index,
201                    })
202                }
203            }
204
205            deserializer.deserialize_bytes(BufferVisitor)
206        }
207    }
208
209    #[cfg(test)]
210    mod tests {
211        use arrayvec::ArrayString;
212
213        use crate::constants::MAX_BUF_LEN;
214        use crate::{Buffer, Locale};
215
216        #[test]
217        fn test_buffer_serialization() {
218            let mut buf = Buffer::new();
219            let _ = buf.write_formatted(&1_000, &Locale::en);
220            let s = serde_json::to_string(&buf).unwrap();
221            assert_eq!(&s, "[49,44,48,48,48]");
222        }
223
224        #[test]
225        fn test_buffer_deserialization() {
226            // should pass
227            let buf: Buffer = serde_json::from_str("[49,44,48,48,48]").unwrap();
228            assert_eq!(0, buf.pos);
229            assert_eq!(5, buf.end);
230            assert_eq!(&[49, 44, 48, 48, 48], buf.as_bytes());
231            assert_eq!("1,000", buf.as_str());
232
233            // should fail
234            let mut should_fail = ArrayString::<1024>::new();
235            should_fail.push_str("[0");
236            for _ in 0..MAX_BUF_LEN {
237                should_fail.push_str(",0");
238            }
239            should_fail.push(']');
240            let result: Result<Buffer, serde_json::Error> = serde_json::from_str(&should_fail);
241            if result.is_ok() {
242                panic!("was somehow able to deserialize bytes that were too long")
243            }
244        }
245    }
246}