Merge pull request #116 from bluss/maybe-uninit-for-0.5
Update ArrayString to use union and prepare for 0.5
This commit is contained in:
+18
-19
@@ -4,43 +4,42 @@ env:
|
||||
- FEATURES='serde-1'
|
||||
matrix:
|
||||
include:
|
||||
- rust: 1.20.0
|
||||
- rust: stable
|
||||
env:
|
||||
- NODEFAULT=1
|
||||
- NODROP_FEATURES='use_needs_drop'
|
||||
- rust: 1.22.1
|
||||
- rust: 1.24.1
|
||||
env:
|
||||
- FEATURES='array-sizes-33-128 array-sizes-129-255'
|
||||
- rust: stable
|
||||
- rust: stable
|
||||
env:
|
||||
- FEATURES='serde-1'
|
||||
- rust: stable
|
||||
env:
|
||||
- FEATURES='array-sizes-33-128 array-sizes-129-255'
|
||||
- rust: beta
|
||||
- rust: nightly
|
||||
env:
|
||||
- NODEFAULT=1
|
||||
- ARRAYVECTEST_ENSURE_UNION=1
|
||||
- rust: nightly
|
||||
env:
|
||||
- NODROP_FEATURES='use_needs_drop'
|
||||
- FEATURES='serde'
|
||||
- ARRAYVECTEST_ENSURE_UNION=1
|
||||
- rust: nightly
|
||||
env:
|
||||
- FEATURES='serde use_union'
|
||||
- NODROP_FEATURES='use_union'
|
||||
- FEATURES='serde-1'
|
||||
- ARRAYVECTEST_ENSURE_UNION=1
|
||||
- rust: nightly
|
||||
env:
|
||||
- FEATURES='array-sizes-33-128 array-sizes-129-255'
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- 0.4
|
||||
script:
|
||||
- |
|
||||
([ ! -z "$NODROP_FEATURES" ] || cargo build --verbose --features "$FEATURES") &&
|
||||
([ "$NODEFAULT" != 1 ] || cargo build --verbose --no-default-features) &&
|
||||
([ ! -z "$NODROP_FEATURES" ] || cargo test --verbose --features "$FEATURES") &&
|
||||
([ ! -z "$NODROP_FEATURES" ] || cargo test --release --verbose --features "$FEATURES") &&
|
||||
([ ! -z "$NODROP_FEATURES" ] || cargo bench --verbose --features "$FEATURES" -- --test) &&
|
||||
([ ! -z "$NODROP_FEATURES" ] || cargo doc --verbose --features "$FEATURES") &&
|
||||
([ "$NODEFAULT" != 1 ] || cargo build --verbose --manifest-path=nodrop/Cargo.toml --no-default-features) &&
|
||||
cargo test --verbose --manifest-path=nodrop/Cargo.toml --features "$NODROP_FEATURES" &&
|
||||
cargo bench --verbose --manifest-path=nodrop/Cargo.toml --features "$NODROP_FEATURES" -- --test
|
||||
cargo build -v --no-default-features &&
|
||||
cargo build -v --features "$FEATURES" &&
|
||||
cargo test -v --features "$FEATURES" &&
|
||||
cargo test -v --release --features "$FEATURES" &&
|
||||
cargo bench -v --features "$FEATURES" --no-run &&
|
||||
cargo doc -v --features "$FEATURES" &&
|
||||
cargo build -v --manifest-path=nodrop/Cargo.toml &&
|
||||
cargo test -v --manifest-path=nodrop/Cargo.toml
|
||||
|
||||
@@ -44,9 +44,6 @@ serde-1 = ["serde"]
|
||||
array-sizes-33-128 = []
|
||||
array-sizes-129-255 = []
|
||||
|
||||
# has no effect
|
||||
use_union = []
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["serde-1"]
|
||||
|
||||
|
||||
+4
-6
@@ -15,14 +15,14 @@
|
||||
pub unsafe trait Array {
|
||||
/// The array’s element type
|
||||
type Item;
|
||||
/// The smallest type that can index and tell the length of the array.
|
||||
#[doc(hidden)]
|
||||
/// The smallest index type that indexes the array.
|
||||
type Index: Index;
|
||||
/// The array's element capacity
|
||||
const CAPACITY: usize;
|
||||
#[doc(hidden)]
|
||||
fn as_ptr(&self) -> *const Self::Item;
|
||||
#[doc(hidden)]
|
||||
fn as_mut_ptr(&mut self) -> *mut Self::Item;
|
||||
#[doc(hidden)]
|
||||
fn capacity() -> usize;
|
||||
}
|
||||
|
||||
@@ -91,14 +91,12 @@ macro_rules! fix_array_impl {
|
||||
unsafe impl<T> Array for [T; $len] {
|
||||
type Item = T;
|
||||
type Index = $index_type;
|
||||
const CAPACITY: usize = $len;
|
||||
#[doc(hidden)]
|
||||
#[inline(always)]
|
||||
fn as_ptr(&self) -> *const T { self as *const _ as *const _ }
|
||||
#[doc(hidden)]
|
||||
#[inline(always)]
|
||||
fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _}
|
||||
#[doc(hidden)]
|
||||
#[inline(always)]
|
||||
fn capacity() -> usize { $len }
|
||||
}
|
||||
)
|
||||
|
||||
+83
-39
@@ -2,7 +2,6 @@ use std::borrow::Borrow;
|
||||
use std::cmp;
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::str;
|
||||
@@ -17,6 +16,8 @@ use char::encode_utf8;
|
||||
#[cfg(feature="serde-1")]
|
||||
use serde::{Serialize, Deserialize, Serializer, Deserializer};
|
||||
|
||||
use super::MaybeUninitCopy;
|
||||
|
||||
/// A string with a fixed capacity.
|
||||
///
|
||||
/// The `ArrayString` is a string backed by a fixed size array. It keeps track
|
||||
@@ -25,20 +26,25 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer};
|
||||
/// The string is a contiguous value that you can store directly on the stack
|
||||
/// if needed.
|
||||
#[derive(Copy)]
|
||||
pub struct ArrayString<A: Array<Item=u8>> {
|
||||
// FIXME: Use Copyable union for xs when we can
|
||||
xs: A,
|
||||
pub struct ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
xs: MaybeUninitCopy<A>,
|
||||
len: A::Index,
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8>> Default for ArrayString<A> {
|
||||
impl<A> Default for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
/// Return an empty `ArrayString`
|
||||
fn default() -> ArrayString<A> {
|
||||
ArrayString::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8>> ArrayString<A> {
|
||||
impl<A> ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
/// Create a new empty `ArrayString`.
|
||||
///
|
||||
/// Capacity is inferred from the type parameter.
|
||||
@@ -54,8 +60,7 @@ impl<A: Array<Item=u8>> ArrayString<A> {
|
||||
pub fn new() -> ArrayString<A> {
|
||||
unsafe {
|
||||
ArrayString {
|
||||
// FIXME: Use Copyable union for xs when we can
|
||||
xs: mem::zeroed(),
|
||||
xs: MaybeUninitCopy::uninitialized(),
|
||||
len: Index::from(0),
|
||||
}
|
||||
}
|
||||
@@ -91,11 +96,12 @@ impl<A: Array<Item=u8>> ArrayString<A> {
|
||||
/// let string = ArrayString::from_byte_string(b"hello world").unwrap();
|
||||
/// ```
|
||||
pub fn from_byte_string(b: &A) -> Result<Self, Utf8Error> {
|
||||
let mut arraystr = Self::new();
|
||||
let s = try!(str::from_utf8(b.as_slice()));
|
||||
let _result = arraystr.try_push_str(s);
|
||||
debug_assert!(_result.is_ok());
|
||||
Ok(arraystr)
|
||||
let len = str::from_utf8(b.as_slice())?.len();
|
||||
debug_assert_eq!(len, A::capacity());
|
||||
Ok(ArrayString {
|
||||
xs: MaybeUninitCopy::from(*b),
|
||||
len: Index::from(A::capacity()),
|
||||
})
|
||||
}
|
||||
|
||||
/// Return the capacity of the `ArrayString`.
|
||||
@@ -213,7 +219,7 @@ impl<A: Array<Item=u8>> ArrayString<A> {
|
||||
return Err(CapacityError::new(s));
|
||||
}
|
||||
unsafe {
|
||||
let dst = self.xs.as_mut_ptr().offset(self.len() as isize);
|
||||
let dst = self.xs.ptr_mut().offset(self.len() as isize);
|
||||
let src = s.as_ptr();
|
||||
ptr::copy_nonoverlapping(src, dst, s.len());
|
||||
let newl = self.len() + s.len();
|
||||
@@ -307,8 +313,8 @@ impl<A: Array<Item=u8>> ArrayString<A> {
|
||||
let next = idx + ch.len_utf8();
|
||||
let len = self.len();
|
||||
unsafe {
|
||||
ptr::copy(self.xs.as_ptr().offset(next as isize),
|
||||
self.xs.as_mut_ptr().offset(idx as isize),
|
||||
ptr::copy(self.xs.ptr().offset(next as isize),
|
||||
self.xs.ptr_mut().offset(idx as isize),
|
||||
len - next);
|
||||
self.set_len(len - (next - idx));
|
||||
}
|
||||
@@ -342,75 +348,99 @@ impl<A: Array<Item=u8>> ArrayString<A> {
|
||||
|
||||
/// Return a mutable slice of the whole string’s buffer
|
||||
unsafe fn raw_mut_bytes(&mut self) -> &mut [u8] {
|
||||
slice::from_raw_parts_mut(self.xs.as_mut_ptr(), self.capacity())
|
||||
slice::from_raw_parts_mut(self.xs.ptr_mut(), self.capacity())
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8>> Deref for ArrayString<A> {
|
||||
impl<A> Deref for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
type Target = str;
|
||||
#[inline]
|
||||
fn deref(&self) -> &str {
|
||||
unsafe {
|
||||
let sl = slice::from_raw_parts(self.xs.as_ptr(), self.len.to_usize());
|
||||
let sl = slice::from_raw_parts(self.xs.ptr(), self.len.to_usize());
|
||||
str::from_utf8_unchecked(sl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8>> DerefMut for ArrayString<A> {
|
||||
impl<A> DerefMut for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut str {
|
||||
unsafe {
|
||||
let sl = slice::from_raw_parts_mut(self.xs.as_mut_ptr(), self.len.to_usize());
|
||||
let sl = slice::from_raw_parts_mut(self.xs.ptr_mut(), self.len.to_usize());
|
||||
str::from_utf8_unchecked_mut(sl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8>> PartialEq for ArrayString<A> {
|
||||
impl<A> PartialEq for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
fn eq(&self, rhs: &Self) -> bool {
|
||||
**self == **rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8>> PartialEq<str> for ArrayString<A> {
|
||||
impl<A> PartialEq<str> for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
fn eq(&self, rhs: &str) -> bool {
|
||||
&**self == rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8>> PartialEq<ArrayString<A>> for str {
|
||||
impl<A> PartialEq<ArrayString<A>> for str
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
fn eq(&self, rhs: &ArrayString<A>) -> bool {
|
||||
self == &**rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8>> Eq for ArrayString<A> { }
|
||||
impl<A> Eq for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{ }
|
||||
|
||||
impl<A: Array<Item=u8>> Hash for ArrayString<A> {
|
||||
impl<A> Hash for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
fn hash<H: Hasher>(&self, h: &mut H) {
|
||||
(**self).hash(h)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8>> Borrow<str> for ArrayString<A> {
|
||||
impl<A> Borrow<str> for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
fn borrow(&self) -> &str { self }
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8>> AsRef<str> for ArrayString<A> {
|
||||
impl<A> AsRef<str> for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
fn as_ref(&self) -> &str { self }
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8>> fmt::Debug for ArrayString<A> {
|
||||
impl<A> fmt::Debug for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) }
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8>> fmt::Display for ArrayString<A> {
|
||||
impl<A> fmt::Display for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) }
|
||||
}
|
||||
|
||||
/// `Write` appends written data to the end of the string.
|
||||
impl<A: Array<Item=u8>> fmt::Write for ArrayString<A> {
|
||||
impl<A> fmt::Write for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
fn write_char(&mut self, c: char) -> fmt::Result {
|
||||
self.try_push(c).map_err(|_| fmt::Error)
|
||||
}
|
||||
@@ -420,7 +450,9 @@ impl<A: Array<Item=u8>> fmt::Write for ArrayString<A> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8> + Copy> Clone for ArrayString<A> {
|
||||
impl<A> Clone for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
fn clone(&self) -> ArrayString<A> {
|
||||
*self
|
||||
}
|
||||
@@ -431,7 +463,9 @@ impl<A: Array<Item=u8> + Copy> Clone for ArrayString<A> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8>> PartialOrd for ArrayString<A> {
|
||||
impl<A> PartialOrd for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
fn partial_cmp(&self, rhs: &Self) -> Option<cmp::Ordering> {
|
||||
(**self).partial_cmp(&**rhs)
|
||||
}
|
||||
@@ -441,7 +475,9 @@ impl<A: Array<Item=u8>> PartialOrd for ArrayString<A> {
|
||||
fn ge(&self, rhs: &Self) -> bool { **self >= **rhs }
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8>> PartialOrd<str> for ArrayString<A> {
|
||||
impl<A> PartialOrd<str> for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
fn partial_cmp(&self, rhs: &str) -> Option<cmp::Ordering> {
|
||||
(**self).partial_cmp(rhs)
|
||||
}
|
||||
@@ -451,7 +487,9 @@ impl<A: Array<Item=u8>> PartialOrd<str> for ArrayString<A> {
|
||||
fn ge(&self, rhs: &str) -> bool { &**self >= rhs }
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8>> PartialOrd<ArrayString<A>> for str {
|
||||
impl<A> PartialOrd<ArrayString<A>> for str
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
fn partial_cmp(&self, rhs: &ArrayString<A>) -> Option<cmp::Ordering> {
|
||||
self.partial_cmp(&**rhs)
|
||||
}
|
||||
@@ -461,7 +499,9 @@ impl<A: Array<Item=u8>> PartialOrd<ArrayString<A>> for str {
|
||||
fn ge(&self, rhs: &ArrayString<A>) -> bool { self >= &**rhs }
|
||||
}
|
||||
|
||||
impl<A: Array<Item=u8>> Ord for ArrayString<A> {
|
||||
impl<A> Ord for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
fn cmp(&self, rhs: &Self) -> cmp::Ordering {
|
||||
(**self).cmp(&**rhs)
|
||||
}
|
||||
@@ -469,7 +509,9 @@ impl<A: Array<Item=u8>> Ord for ArrayString<A> {
|
||||
|
||||
#[cfg(feature="serde-1")]
|
||||
/// Requires crate feature `"serde-1"`
|
||||
impl<A: Array<Item=u8>> Serialize for ArrayString<A> {
|
||||
impl<A> Serialize for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer
|
||||
{
|
||||
@@ -479,7 +521,9 @@ impl<A: Array<Item=u8>> Serialize for ArrayString<A> {
|
||||
|
||||
#[cfg(feature="serde-1")]
|
||||
/// Requires crate feature `"serde-1"`
|
||||
impl<'de, A: Array<Item=u8>> Deserialize<'de> for ArrayString<A> {
|
||||
impl<'de, A> Deserialize<'de> for ArrayString<A>
|
||||
where A: Array<Item=u8> + Copy
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: Deserializer<'de>
|
||||
{
|
||||
@@ -488,7 +532,7 @@ impl<'de, A: Array<Item=u8>> Deserialize<'de> for ArrayString<A> {
|
||||
|
||||
struct ArrayStringVisitor<A: Array<Item=u8>>(PhantomData<A>);
|
||||
|
||||
impl<'de, A: Array<Item=u8>> Visitor<'de> for ArrayStringVisitor<A> {
|
||||
impl<'de, A: Copy + Array<Item=u8>> Visitor<'de> for ArrayStringVisitor<A> {
|
||||
type Value = ArrayString<A>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
||||
+4
-4
@@ -16,7 +16,7 @@
|
||||
//!
|
||||
//! ## Rust Version
|
||||
//!
|
||||
//! This version of arrayvec requires Rust 1.13 or later.
|
||||
//! This version of arrayvec requires Rust 1.24 or later.
|
||||
//!
|
||||
#![doc(html_root_url="https://docs.rs/arrayvec/0.4/")]
|
||||
#![cfg_attr(not(feature="std"), no_std)]
|
||||
@@ -56,7 +56,10 @@ mod maybe_uninit;
|
||||
#[path="maybe_uninit_nodrop.rs"]
|
||||
mod maybe_uninit;
|
||||
|
||||
mod maybe_uninit_copy;
|
||||
|
||||
use maybe_uninit::MaybeUninit;
|
||||
use maybe_uninit_copy::MaybeUninitCopy;
|
||||
|
||||
#[cfg(feature="serde-1")]
|
||||
use serde::{Serialize, Deserialize, Serializer, Deserializer};
|
||||
@@ -614,9 +617,6 @@ impl<A: Array> ArrayVec<A> {
|
||||
///
|
||||
/// Return an `Ok` value with the array if length equals capacity,
|
||||
/// return an `Err` with self otherwise.
|
||||
///
|
||||
/// `Note:` This function may incur unproportionally large overhead
|
||||
/// to move the array out, its performance is not optimal.
|
||||
pub fn into_inner(self) -> Result<A, Self> {
|
||||
if self.len() < self.capacity() {
|
||||
Err(self)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
use array::Array;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub union MaybeUninitCopy<T>
|
||||
where T: Copy
|
||||
{
|
||||
empty: (),
|
||||
value: T,
|
||||
}
|
||||
|
||||
impl<T> MaybeUninitCopy<T>
|
||||
where T: Copy
|
||||
{
|
||||
/// Create a new MaybeUninit with uninitialized interior
|
||||
pub unsafe fn uninitialized() -> Self {
|
||||
Self { empty: () }
|
||||
}
|
||||
|
||||
/// Create a new MaybeUninit from the value `v`.
|
||||
pub fn from(value: T) -> Self {
|
||||
Self { value }
|
||||
}
|
||||
|
||||
// Raw pointer casts written so that we don't reference or access the
|
||||
// uninitialized interior value
|
||||
|
||||
/// Return a raw pointer to the start of the interior array
|
||||
pub fn ptr(&self) -> *const T::Item
|
||||
where T: Array
|
||||
{
|
||||
self as *const _ as *const T::Item
|
||||
}
|
||||
|
||||
/// Return a mut raw pointer to the start of the interior array
|
||||
pub fn ptr_mut(&mut self) -> *mut T::Item
|
||||
where T: Array
|
||||
{
|
||||
self as *mut _ as *mut T::Item
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user