string_wrapper/
lib.rs

1//! provides `StringWrapper`, most useful for stack-based strings.
2#![deny(missing_docs)]
3
4#[cfg(feature="use_serde")]
5#[macro_use]
6extern crate serde_derive;
7#[cfg(feature="use_serde")]
8extern crate serde;
9
10use std::borrow;
11use std::fmt;
12use std::io::Write;
13use std::mem::transmute;
14use std::ops;
15use std::ptr;
16use std::str;
17use std::cmp;
18use std::hash;
19
20#[cfg(feature="use_serde")]
21use serde::de::Error;
22
23/// Like `String`, but with a fixed capacity and a generic backing bytes storage.
24///
25/// Use e.g. `StringWrapper<[u8; 4]>` to have a string without heap memory allocation.
26#[derive(Copy, Default)]
27pub struct StringWrapper<T>
28    where T: Buffer
29{
30    len: usize,
31    buffer: T,
32}
33
34/// Equivalent to `AsMut<[u8]> + AsRef<[u8]>` with the additional constraint that
35/// implementations must return the same slice from subsequent calls of `as_mut` and/or `as_ref`.
36pub unsafe trait Buffer {
37    /// Get the backing buffer as a slice.
38    fn as_ref(&self) -> &[u8];
39    /// Get the backing buffer as a mutable slice.
40    fn as_mut(&mut self) -> &mut [u8];
41}
42
43/// The OwnedBuffer trait is in support of StringWrapper::from_str, since we need to be able to
44/// allocate new buffers for it.
45///
46/// IMPLEMENTATION NOTE: There is currently no impl for Vec<u8>, because StringWrapper assumes a
47/// fixed capacity, and we don't have a way to know what size vec we should return.
48// Besides, I'm not sure what the value of Buffer for Vec is anyway, when you could just use
49// String...
50pub trait OwnedBuffer: Buffer {
51    /// Creature a new buffer that can be used to initialize a StringWrapper.
52    fn new() -> Self;
53}
54
55impl<T> StringWrapper<T>
56    where T: Buffer
57{
58    /// Create an empty string from its backing storage.
59    pub fn new(buffer: T) -> Self {
60        StringWrapper {
61            len: 0,
62            buffer: buffer,
63        }
64    }
65
66    /// Unsafely create a string from its components.
67    ///
68    /// Users must ensure that:
69    ///
70    /// * The buffer length is at least `len`
71    /// * The first `len` bytes of `buffer` are well-formed UTF-8.
72    pub unsafe fn from_raw_parts(buffer: T, len: usize) -> Self {
73        StringWrapper {
74            len: len,
75            buffer: buffer,
76        }
77    }
78
79    /// Consume the string and return the backing storage.
80    pub fn into_buffer(self) -> T {
81        self.buffer
82    }
83
84    /// View the backing storage as a bytes slice.
85    pub fn buffer(&self) -> &[u8] {
86        self.buffer.as_ref()
87    }
88
89
90    /// View the backing storage as a bytes slice.
91    ///
92    /// Users must ensure that the prefix bytes up to `self.len()` remains well-formed UTF-8.
93    pub unsafe fn buffer_mut(&mut self) -> &mut [u8] {
94        self.buffer.as_mut()
95    }
96
97    /// Return the number of bytes in the string.
98    pub fn len(&self) -> usize {
99        self.len
100    }
101
102    /// Return whether the string contains no bytes.
103    pub fn is_empty(&self) -> bool {
104        self.len == 0
105    }
106
107    /// Unsafely change the length in bytes of the string.
108    ///
109    /// Users must ensure that the string remains well-formed UTF-8.
110    pub unsafe fn set_len(&mut self, new_len: usize) {
111        self.len = new_len
112    }
113
114    /// Shortens a string to the specified length.
115    ///
116    /// Panics if `new_len` > current length, or if `new_len` is not a character boundary.
117    pub fn truncate(&mut self, new_len: usize) {
118        assert!(new_len <= self.len);
119        if new_len < self.len {
120            assert!(starts_well_formed_utf8_sequence(self.buffer.as_ref()[new_len]));
121        }
122        self.len = new_len;
123    }
124
125    /// Return the maximum number of bytes the string can hold.
126    pub fn capacity(&self) -> usize {
127        self.buffer.as_ref().len()
128    }
129
130    /// Return by how many bytes the string can grow.
131    pub fn extra_capacity(&self) -> usize {
132        self.capacity() - self.len
133    }
134
135    /// Return the slice of unused bytes after the string
136    pub fn extra_bytes_mut(&mut self) -> &mut [u8] {
137        &mut self.buffer.as_mut()[self.len..]
138    }
139
140    /// Append a code point to the string if the extra capacity is sufficient.
141    ///
142    /// Return `Ok` with the code point appended, or `Err` with the string unchanged.
143    pub fn push(&mut self, c: char) -> Result<(), ()> {
144        let new_len = self.len + c.len_utf8();
145        if new_len <= self.capacity() {
146            // FIXME: use `c.encode_utf8` once it’s stable.
147            write!(self.extra_bytes_mut(), "{}", c).unwrap();
148            self.len = new_len;
149            Ok(())
150        } else {
151            Err(())
152        }
153    }
154
155    /// Append a string slice to the string.
156    ///
157    /// Panics if the extra capacity is not sufficient.
158    pub fn push_str(&mut self, s: &str) {
159        copy_memory(s.as_bytes(), self.extra_bytes_mut());
160        self.len += s.len();
161    }
162
163    /// Append as much as possible of a string slice to the string.
164    ///
165    /// Return `Ok(())` if the extra capacity was sufficient,
166    /// or `Err(n)` where `n` is the number of bytes pushed.
167    /// `n` is within 3 bytes of the extra capacity.
168    pub fn push_partial_str(&mut self, s: &str) -> Result<(), usize> {
169        let mut i = self.extra_capacity();
170        let (s, result) = if i < s.len() {
171            // As long as `self` is well-formed,
172            // this loop does as most 3 iterations and `i` does not underflow.
173            while !starts_well_formed_utf8_sequence(s.as_bytes()[i]) {
174                i -= 1
175            }
176            (&s[..i], Err(i))
177        } else {
178            (s, Ok(()))
179        };
180        self.push_str(s);
181        result
182    }
183}
184
185impl<T: OwnedBuffer> StringWrapper<T> {
186    /// Copy a `&str` into a new `StringWrapper`. You may need to annotate the type of this call so
187    /// Rust knows which size of array you want to populate:
188    ///
189    /// # Panics
190    ///
191    /// Panics if the `&str` cannot fit into the buffer.
192    ///
193    /// # Examples
194    ///
195    /// ```
196    /// use string_wrapper::StringWrapper;
197    ///
198    /// let sw: StringWrapper<[u8; 32]> = StringWrapper::from_str("hello, world");
199    /// assert_eq!(format!("{}", sw), "hello, world");
200    /// ```
201    pub fn from_str(s: &str) -> StringWrapper<T> {
202        let buffer = T::new();
203        let mut sw = StringWrapper::new(buffer);
204        sw.push_str(s);
205        sw
206    }
207
208    /// Safely construct a new StringWrapper from a &str. Unlike `from_str`, this method doesn't
209    /// panic when the &str is too big to fit into the buffer.
210    ///
211    /// # Examples
212    ///
213    /// ```
214    /// use string_wrapper::StringWrapper;
215    ///
216    /// let sw: Option<StringWrapper<[u8; 3]>> = StringWrapper::from_str_safe("foo");
217    /// assert_eq!(format!("{}", sw.unwrap()), "foo");
218    /// ```
219    ///
220    /// ```
221    /// use string_wrapper::StringWrapper;
222    ///
223    /// let sw: Option<StringWrapper<[u8; 3]>> = StringWrapper::from_str_safe("foobar");
224    /// assert_eq!(sw, None);
225    /// ```
226    pub fn from_str_safe(s: &str) -> Option<StringWrapper<T>> {
227        let buffer = T::new();
228        let mut sw = StringWrapper::new(buffer);
229        match sw.push_partial_str(s) {
230            Ok(_) => Some(sw),
231            Err(_) => None,
232        }
233    }
234}
235
236fn starts_well_formed_utf8_sequence(byte: u8) -> bool {
237    // ASCII byte or "leading" byte
238    byte < 128 || byte >= 192
239}
240
241// FIXME: Use `std::slice::bytes::copy_memory` instead when it’s stable.
242/// Copies data from `src` to `dst`
243///
244/// Panics if the length of `dst` is less than the length of `src`.
245fn copy_memory(src: &[u8], dst: &mut [u8]) {
246    let len_src = src.len();
247    assert!(dst.len() >= len_src);
248    // `dst` is unaliasable, so we know statically it doesn't overlap
249    // with `src`.
250    unsafe {
251        ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), len_src);
252    }
253}
254
255impl<T> ops::Deref for StringWrapper<T>
256    where T: Buffer
257{
258    type Target = str;
259
260    fn deref(&self) -> &str {
261        unsafe { str::from_utf8_unchecked(&self.buffer.as_ref()[..self.len]) }
262    }
263}
264
265impl<T> ops::DerefMut for StringWrapper<T>
266    where T: Buffer
267{
268    fn deref_mut(&mut self) -> &mut str {
269        unsafe { transmute::<&mut [u8], &mut str>(&mut self.buffer.as_mut()[..self.len]) }
270    }
271}
272
273impl<T> borrow::Borrow<str> for StringWrapper<T>
274    where T: Buffer
275{
276    fn borrow(&self) -> &str {
277        self
278    }
279}
280
281impl<T> fmt::Display for StringWrapper<T>
282    where T: Buffer
283{
284    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
285        fmt::Display::fmt(&**self, f)
286    }
287}
288
289impl<T> fmt::Debug for StringWrapper<T>
290    where T: Buffer
291{
292    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
293        fmt::Debug::fmt(&**self, f)
294    }
295}
296
297impl<T: Buffer> PartialEq for StringWrapper<T> {
298    fn eq(&self, other: &Self) -> bool {
299        **self == **other
300    }
301}
302
303// We need to explicitly define Eq here, because the derive logic only impls it when T is also Eq.
304impl<T: Buffer> Eq for StringWrapper<T> {}
305
306// Likewise we need to implement Clone explicitly because std doesn't define it for arrays bigger
307// than 32 elements. We rely on cloning the slice of the array and then copying that into a new
308// buffer, which requires OwnedBuffer::new.
309impl<T: Buffer + Copy> Clone for StringWrapper<T> {
310    fn clone(&self) -> Self {
311        *self
312
313    }
314}
315
316impl<T: Buffer> PartialOrd for StringWrapper<T> {
317    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
318        Some(self.cmp(other))
319    }
320}
321
322impl<T: Buffer> hash::Hash for StringWrapper<T> {
323    fn hash<H: hash::Hasher>(&self, state: &mut H) {
324        (**self).hash(state)
325    }
326}
327
328impl<T: Buffer> Ord for StringWrapper<T> {
329    fn cmp(&self, other: &Self) -> cmp::Ordering {
330        (**self).cmp(&**other)
331    }
332}
333
334#[cfg(feature="use_serde")]
335impl<T: Buffer> serde::Serialize for StringWrapper<T> {
336    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
337        self.to_string().serialize(serializer)
338    }
339}
340
341#[cfg(feature="use_serde")]
342impl<'de, T: OwnedBuffer> serde::Deserialize<'de> for StringWrapper<T> {
343    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
344        let s: String = serde::Deserialize::deserialize(deserializer)?;
345        let sb = StringWrapper::from_str_safe(&s).ok_or_else(|| {
346                let buff = T::new();
347                let msg: String = format!("string that can fit into {} bytes", buff.as_ref().len());
348                D::Error::invalid_length(s.len(), &StringExpected(msg))
349            })?;
350        Ok(sb)
351    }
352}
353
354// It seems silly that I can't just pass a String to invalid_length, but there's no implementation
355// of Expected for String, so...
356#[cfg(feature="use_serde")]
357struct StringExpected(String);
358#[cfg(feature="use_serde")]
359impl serde::de::Expected for StringExpected {
360    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
361        fmt::Display::fmt(&self.0, formatter)
362    }
363}
364
365unsafe impl<'a, T: ?Sized + Buffer> Buffer for &'a mut T {
366    fn as_ref(&self) -> &[u8] {
367        (**self).as_ref()
368    }
369    fn as_mut(&mut self) -> &mut [u8] {
370        (**self).as_mut()
371    }
372}
373
374unsafe impl<'a, T: ?Sized + Buffer> Buffer for Box<T> {
375    fn as_ref(&self) -> &[u8] {
376        (**self).as_ref()
377    }
378    fn as_mut(&mut self) -> &mut [u8] {
379        (**self).as_mut()
380    }
381}
382
383unsafe impl Buffer for Vec<u8> {
384    fn as_ref(&self) -> &[u8] {
385        self
386    }
387    fn as_mut(&mut self) -> &mut [u8] {
388        self
389    }
390}
391
392unsafe impl Buffer for [u8] {
393    fn as_ref(&self) -> &[u8] {
394        self
395    }
396    fn as_mut(&mut self) -> &mut [u8] {
397        self
398    }
399}
400
401macro_rules! array_impl {
402    ($($N: expr)+) => {
403        $(
404            unsafe impl Buffer for [u8; $N] {
405                fn as_ref(&self) -> &[u8] { self }
406                fn as_mut(&mut self) -> &mut [u8] { self }
407            }
408
409            impl OwnedBuffer for [u8; $N] {
410                fn new() -> Self { [0u8; $N] }
411            }
412        )+
413    }
414}
415
416array_impl! {
417     0  1  2  3  4  5  6  7  8  9
418    10 11 12 13 14 15 16 17 18 19
419    20 21 22 23 24 25 26 27 28 29
420    30 31 32
421    64 128 256 512 1024
422    2 * 1024
423    4 * 1024
424    8 * 1024
425    16 * 1024
426    32 * 1024
427    64 * 1024
428    128 * 1024
429    256 * 1024
430    512 * 1024
431    1024 * 1024
432    2 * 1024 * 1024
433    4 * 1024 * 1024
434    8 * 1024 * 1024
435    16 * 1024 * 1024
436    32 * 1024 * 1024
437    64 * 1024 * 1024
438    128 * 1024 * 1024
439    256 * 1024 * 1024
440    512 * 1024 * 1024
441    1024 * 1024 * 1024
442    100 1_000 10_000 100_000 1_000_000
443    10_000_000 100_000_000 1_000_000_000
444}
445
446#[cfg(test)]
447mod tests {
448    use std;
449    use std::cmp;
450    use std::hash;
451
452    #[cfg(feature="use_serde")]
453    extern crate serde_json;
454
455    use StringWrapper;
456
457    #[test]
458    fn traits() {
459        // A simple way to ensure that Eq is implemented for StringWrapper
460        #[derive(Eq, PartialEq, Ord, PartialOrd)]
461        struct Foo {
462            x: StringWrapper<[u8; 64]>,
463        }
464    }
465
466    #[test]
467    fn eq() {
468        let mut s = StringWrapper::<[u8; 3]>::new(*b"000");
469        assert_eq!(s, s);
470        s.push_str("foo");
471        let mut s2 = StringWrapper::<[u8; 3]>::new(*b"000");
472        s2.push_str("foo");
473        assert_eq!(s, s2);
474
475        let mut s3 = StringWrapper::<[u8; 3]>::new(*b"000");
476        s3.push_str("bar");
477        assert!(s != s3);
478    }
479
480    #[test]
481    fn eq_only_to_length() {
482        let a = StringWrapper::<[u8; 5]>::new(*b"aaaaa");
483        let b = StringWrapper::<[u8; 5]>::new(*b"bbbbb");
484        assert_eq!(a, b);
485    }
486
487    #[test]
488    fn ord() {
489        let mut s = StringWrapper::<[u8; 3]>::new(*b"000");
490        let mut s2 = StringWrapper::<[u8; 3]>::new(*b"000");
491        s.push_str("a");
492        s2.push_str("b");
493        assert_eq!(s.partial_cmp(&s2), Some(cmp::Ordering::Less));
494        assert_eq!(s.cmp(&s2), cmp::Ordering::Less);
495    }
496
497    #[test]
498    fn ord_only_to_length() {
499        let mut s = StringWrapper::<[u8; 3]>::new(*b"000");
500        let mut s2 = StringWrapper::<[u8; 3]>::new(*b"111");
501        assert_eq!(s.partial_cmp(&s2), Some(cmp::Ordering::Equal));
502        assert_eq!(s.cmp(&s2), cmp::Ordering::Equal);
503
504        s.push_str("aa");
505        s2.push_str("aa");
506        assert_eq!(s.partial_cmp(&s2), Some(cmp::Ordering::Equal));
507        assert_eq!(s.cmp(&s2), cmp::Ordering::Equal);
508    }
509
510    #[cfg(test)]
511    fn hash<T: hash::Hash>(t: &T) -> u64 {
512        // who knows why this isn't in std
513        let mut h = std::collections::hash_map::DefaultHasher::new();
514        t.hash(&mut h);
515        hash::Hasher::finish(&h)
516    }
517
518    #[test]
519    fn hash_only_to_length() {
520        let mut s = StringWrapper::<[u8; 64]>::new([0u8; 64]);
521        let mut s2 = StringWrapper::<[u8; 64]>::new([1u8; 64]);
522        assert_eq!(hash(&s), hash(&s2));
523        s.push_str("a");
524        assert!(hash(&s) != hash(&s2));
525        s2.push_str("a");
526        assert_eq!(hash(&s), hash(&s2));
527    }
528
529    #[test]
530    fn from_str() {
531        let s: StringWrapper<[u8; 64]> = StringWrapper::from_str("OMG!");
532        let mut s2 = StringWrapper::new([0u8; 64]);
533        s2.push_str("OMG!");
534        assert_eq!(s, s2);
535    }
536
537    #[test]
538    fn it_works() {
539        let mut s = StringWrapper::new([0; 10]);
540        assert_eq!(&*s, "");
541        assert_eq!(s.len(), 0);
542        assert_eq!(s.capacity(), 10);
543        assert_eq!(s.extra_capacity(), 10);
544
545        assert_eq!(&*s, "");
546        assert_eq!(s.len(), 0);
547        assert_eq!(s.capacity(), 10);
548        assert_eq!(s.extra_capacity(), 10);
549
550        s.push_str("a");
551        assert_eq!(&*s, "a");
552        assert_eq!(s.len(), 1);
553        assert_eq!(s.capacity(), 10);
554        assert_eq!(s.extra_capacity(), 9);
555
556        assert_eq!(s.push('é'), Ok(()));
557        assert_eq!(&*s, "aé");
558        assert_eq!(s.len(), 3);
559        assert_eq!(s.capacity(), 10);
560        assert_eq!(s.extra_capacity(), 7);
561
562        assert_eq!(s.push_partial_str("~~~"), Ok(()));
563        assert_eq!(&*s, "aé~~~");
564        assert_eq!(s.len(), 6);
565        assert_eq!(s.capacity(), 10);
566        assert_eq!(s.extra_capacity(), 4);
567
568        assert_eq!(s.push_partial_str("hello"), Err(4));
569        assert_eq!(&*s, "aé~~~hell");
570        assert_eq!(s.len(), 10);
571        assert_eq!(s.capacity(), 10);
572        assert_eq!(s.extra_capacity(), 0);
573
574        s.truncate(6);
575        assert_eq!(&*s, "aé~~~");
576        assert_eq!(s.len(), 6);
577        assert_eq!(s.capacity(), 10);
578        assert_eq!(s.extra_capacity(), 4);
579
580        assert_eq!(s.push_partial_str("_🌠"), Err(1));
581        assert_eq!(&*s, "aé~~~_");
582        assert_eq!(s.len(), 7);
583        assert_eq!(s.capacity(), 10);
584        assert_eq!(s.extra_capacity(), 3);
585
586        assert_eq!(s.push('🌠'), Err(()));
587        assert_eq!(&*s, "aé~~~_");
588        assert_eq!(s.len(), 7);
589        assert_eq!(s.capacity(), 10);
590        assert_eq!(s.extra_capacity(), 3);
591
592
593        let buffer: [u8; 10] = s.clone().into_buffer();
594        assert_eq!(&buffer, b"a\xC3\xA9~~~_ell");
595        assert_eq!(format!("{}", s), "aé~~~_");
596        assert_eq!(format!("{:?}", s), r#""aé~~~_""#);
597
598        assert_eq!(s.push_partial_str("ô!?"), Err(3));
599        assert_eq!(&*s, "aé~~~_ô!");
600        assert_eq!(s.len(), 10);
601        assert_eq!(s.capacity(), 10);
602        assert_eq!(s.extra_capacity(), 0);
603    }
604
605    #[cfg(feature="use_serde")]
606    #[test]
607    fn test_serde() {
608        let mut s = StringWrapper::new([0u8; 64]);
609        s.push_str("foobar");
610        let json = serde_json::to_string(&s).unwrap();
611        assert_eq!(json, "\"foobar\"");
612        let s2 = serde_json::from_str(&json).unwrap();
613        assert_eq!(s, s2);
614    }
615
616    #[cfg(feature="use_serde")]
617    #[test]
618    fn deserialize_too_long() {
619        let json = "\"12345\"";
620        match serde_json::from_str::<StringWrapper<[u8; 3]>>(&json) {
621            Err(e) => {
622                assert_eq!(format!("{}", e),
623                           "invalid length 5, expected string that can fit into 3 bytes")
624            }
625            Ok(x) => panic!("Expected error, got success: {:?}", x),
626        }
627    }
628
629    #[test]
630    fn clone() {
631        let s = StringWrapper::new([0u8; 64]);
632        let y: StringWrapper<[u8; 64]> = s.clone();
633        println!("s: {}, y: {}", s, y);
634    }
635}