From 6af588cb2c990333b24b6ab5d4ef3db66cd46f4a Mon Sep 17 00:00:00 2001 From: bluss Date: Fri, 18 Sep 2015 00:52:17 +0200 Subject: [PATCH 1/3] ArrayString: Add PartialEq, Eq, Hash, and tests --- src/array_string.rs | 45 +++++++++++++++++++++++++++++++++------------ tests/tests.rs | 21 +++++++++++++++++++++ 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/src/array_string.rs b/src/array_string.rs index 9552013..d6b6089 100644 --- a/src/array_string.rs +++ b/src/array_string.rs @@ -1,6 +1,6 @@ use std::borrow::Borrow; use std::fmt; -use std::mem; +use std::hash::{Hash, Hasher}; use std::ops::Deref; use std::str; use std::slice; @@ -22,14 +22,6 @@ pub struct ArrayString> { len: A::Index, } -unsafe fn new_array>() -> A { - // Note: Returning an uninitialized value here only works - // if we can be sure the data is never used. The nullable pointer - // inside enum optimization conflicts with this this for example, - // so we need to be extra careful. See `NoDrop` enum. - mem::uninitialized() -} - impl> ArrayString { /// Create a new empty `ArrayString`. /// @@ -46,7 +38,7 @@ impl> ArrayString { pub fn new() -> ArrayString { unsafe { ArrayString { - xs: new_array(), + xs: ::new_array(), len: Index::from(0), } } @@ -150,6 +142,32 @@ impl> Deref for ArrayString { } } +impl> PartialEq for ArrayString { + fn eq(&self, rhs: &Self) -> bool { + **self == **rhs + } +} + +impl> PartialEq for ArrayString { + fn eq(&self, rhs: &str) -> bool { + &**self == rhs + } +} + +impl> PartialEq> for str { + fn eq(&self, rhs: &ArrayString) -> bool { + self == &**rhs + } +} + +impl> Eq for ArrayString { } + +impl> Hash for ArrayString { + fn hash(&self, h: &mut H) { + (**self).hash(h) + } +} + impl> Borrow for ArrayString { fn borrow(&self) -> &str { self } } @@ -158,7 +176,11 @@ impl> AsRef for ArrayString { fn as_ref(&self) -> &str { self } } -impl> fmt::Debug for ArrayString where A::Item: fmt::Debug { +impl> fmt::Debug for ArrayString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } +} + +impl> fmt::Display for ArrayString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } @@ -174,4 +196,3 @@ impl + Copy> Clone for ArrayString { *self } } - diff --git a/tests/tests.rs b/tests/tests.rs index ac3782f..a06b6e6 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1,8 +1,11 @@ extern crate arrayvec; use arrayvec::ArrayVec; +use arrayvec::ArrayString; use std::mem; +use std::collections::HashMap; + #[test] fn test_simple() { @@ -260,3 +263,21 @@ fn test_write() { assert_eq!(r, 5); assert_eq!(&v[..], &[1, 2, 3, 9, 9, 9, 9, 9]); } + +#[test] +fn test_string() { + let text = "hello world"; + let mut s = ArrayString::<[_; 16]>::new(); + s.push_str(text).unwrap(); + assert_eq!(&s, text); + assert_eq!(text, &s); + + // Make sure Hash / Eq / Borrow match up so we can use HashMap + let mut map = HashMap::new(); + map.insert(s, 1); + assert_eq!(map[text], 1); + + let mut t = ArrayString::<[_; 2]>::new(); + assert!(t.push_str(text).is_err()); + assert_eq!(&t, ""); +} From 90de29e6cbbcd015c1315137be4fd2d4d4ce1874 Mon Sep 17 00:00:00 2001 From: bluss Date: Fri, 18 Sep 2015 00:53:19 +0200 Subject: [PATCH 2/3] Remove zero from the Index trait --- src/array.rs | 5 ----- src/lib.rs | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/array.rs b/src/array.rs index aa3b7ae..e5ce1cc 100644 --- a/src/array.rs +++ b/src/array.rs @@ -15,14 +15,11 @@ pub unsafe trait Array { } pub trait Index : PartialEq + Copy { - fn zero() -> Self; fn to_usize(self) -> usize; fn from(usize) -> Self; } impl Index for u8 { - #[inline(always)] - fn zero() -> Self { 0 } #[inline(always)] fn to_usize(self) -> usize { self as usize } #[inline(always)] @@ -30,8 +27,6 @@ impl Index for u8 { } impl Index for u16 { - #[inline(always)] - fn zero() -> Self { 0 } #[inline(always)] fn to_usize(self) -> usize { self as usize } #[inline(always)] diff --git a/src/lib.rs b/src/lib.rs index 73d9324..de84109 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -96,7 +96,7 @@ impl ArrayVec { /// ``` pub fn new() -> ArrayVec { unsafe { - ArrayVec { xs: NoDrop::new(new_array()), len: Index::zero() } + ArrayVec { xs: NoDrop::new(new_array()), len: Index::from(0) } } } @@ -440,7 +440,7 @@ impl IntoIterator for ArrayVec { type Item = A::Item; type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { - IntoIter { index: Index::zero(), v: self, } + IntoIter { index: Index::from(0), v: self, } } } From 7b47f1e891de9d5d6e62875cb7129eb2652626f7 Mon Sep 17 00:00:00 2001 From: bluss Date: Fri, 18 Sep 2015 01:00:55 +0200 Subject: [PATCH 3/3] Use no public fields for CapacityError --- src/array_string.rs | 6 +++--- src/lib.rs | 10 +++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/array_string.rs b/src/array_string.rs index d6b6089..154b74c 100644 --- a/src/array_string.rs +++ b/src/array_string.rs @@ -70,7 +70,7 @@ impl> ArrayString { /// let overflow = string.push('c'); /// /// assert_eq!(&string[..], "ab"); - /// assert_eq!(overflow.err().map(|e| e.element), Some('c')); + /// assert_eq!(overflow.unwrap_err().element(), 'c'); /// ``` pub fn push(&mut self, c: char) -> Result<(), CapacityError> { use std::fmt::Write; @@ -93,8 +93,8 @@ impl> ArrayString { /// let overflow2 = string.push_str("ef"); /// /// assert_eq!(&string[..], "ad"); - /// assert_eq!(overflow1.err().map(|e| e.element), Some("bc")); - /// assert_eq!(overflow2.err().map(|e| e.element), Some("ef")); + /// assert_eq!(overflow1.unwrap_err().element(), "bc"); + /// assert_eq!(overflow2.unwrap_err().element(), "ef"); /// ``` pub fn push_str<'a>(&mut self, s: &'a str) -> Result<(), CapacityError<&'a str>> { use std::io::Write; diff --git a/src/lib.rs b/src/lib.rs index de84109..148861f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,19 +36,23 @@ unsafe fn new_array() -> A { mem::uninitialized() } +/// Error value indicating insufficient capacity #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] pub struct CapacityError { - _unused: (), - pub element: T, + element: T, } impl CapacityError { fn new(element: T) -> CapacityError { CapacityError { - _unused: (), element: element, } } + + /// Extract the overflowing element + pub fn element(self) -> T { + self.element + } } /// A vector with a fixed capacity.