+3
-1
@@ -1,5 +1,7 @@
|
|||||||
language: rust
|
language: rust
|
||||||
sudo: false
|
sudo: false
|
||||||
|
env:
|
||||||
|
- FEATURES='serde-1'
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- rust: 1.12.0
|
- rust: 1.12.0
|
||||||
@@ -15,7 +17,7 @@ matrix:
|
|||||||
- NODROP_FEATURES='use_needs_drop'
|
- NODROP_FEATURES='use_needs_drop'
|
||||||
- rust: nightly
|
- rust: nightly
|
||||||
env:
|
env:
|
||||||
- FEATURES='use_union'
|
- FEATURES='serde use_union'
|
||||||
- NODROP_FEATURES='use_union'
|
- NODROP_FEATURES='use_union'
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
|
|||||||
@@ -19,7 +19,16 @@ version = "0.1.8"
|
|||||||
path = "nodrop"
|
path = "nodrop"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
|
[dependencies.serde]
|
||||||
|
version = "1.0"
|
||||||
|
optional = true
|
||||||
|
default-features = false
|
||||||
|
|
||||||
|
[dev-dependencies.serde_test]
|
||||||
|
version = "1.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = ["odds/std", "nodrop/std"]
|
std = ["odds/std", "nodrop/std"]
|
||||||
use_union = ["nodrop/use_union"]
|
use_union = ["nodrop/use_union"]
|
||||||
|
serde-1 = ["serde"]
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ use array::Index;
|
|||||||
use CapacityError;
|
use CapacityError;
|
||||||
use odds::char::encode_utf8;
|
use odds::char::encode_utf8;
|
||||||
|
|
||||||
|
#[cfg(feature="serde-1")]
|
||||||
|
use serde::{Serialize, Deserialize, Serializer, Deserializer};
|
||||||
|
|
||||||
/// A string with a fixed capacity.
|
/// A string with a fixed capacity.
|
||||||
///
|
///
|
||||||
/// The `ArrayString` is a string backed by a fixed size array. It keeps track
|
/// The `ArrayString` is a string backed by a fixed size array. It keeps track
|
||||||
@@ -324,3 +327,48 @@ impl<A: Array<Item=u8>> Ord for ArrayString<A> {
|
|||||||
(**self).cmp(&**rhs)
|
(**self).cmp(&**rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature="serde-1")]
|
||||||
|
impl<A: Array<Item=u8>> Serialize for ArrayString<A> {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where S: Serializer
|
||||||
|
{
|
||||||
|
serializer.serialize_str(&*self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature="serde-1")]
|
||||||
|
impl<'de, A: Array<Item=u8>> Deserialize<'de> for ArrayString<A> {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where D: Deserializer<'de>
|
||||||
|
{
|
||||||
|
use serde::de::{self, Visitor};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
struct ArrayStringVisitor<A: Array<Item=u8>>(PhantomData<A>);
|
||||||
|
|
||||||
|
impl<'de, A: Array<Item=u8>> Visitor<'de> for ArrayStringVisitor<A> {
|
||||||
|
type Value = ArrayString<A>;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(formatter, "a string no more than {} bytes long", A::capacity())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||||
|
where E: de::Error,
|
||||||
|
{
|
||||||
|
ArrayString::from(v).map_err(|_| E::invalid_length(v.len(), &self))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||||
|
where E: de::Error,
|
||||||
|
{
|
||||||
|
let s = try!(str::from_utf8(v).map_err(|_| E::invalid_value(de::Unexpected::Bytes(v), &self)));
|
||||||
|
|
||||||
|
ArrayString::from(s).map_err(|_| E::invalid_length(s.len(), &self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_str(ArrayStringVisitor::<A>(PhantomData))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+50
@@ -18,6 +18,8 @@
|
|||||||
#![cfg_attr(not(feature="std"), no_std)]
|
#![cfg_attr(not(feature="std"), no_std)]
|
||||||
extern crate odds;
|
extern crate odds;
|
||||||
extern crate nodrop;
|
extern crate nodrop;
|
||||||
|
#[cfg(feature="serde-1")]
|
||||||
|
extern crate serde;
|
||||||
|
|
||||||
#[cfg(not(feature="std"))]
|
#[cfg(not(feature="std"))]
|
||||||
extern crate core as std;
|
extern crate core as std;
|
||||||
@@ -46,6 +48,9 @@ use std::any::Any; // core but unused
|
|||||||
|
|
||||||
use nodrop::NoDrop;
|
use nodrop::NoDrop;
|
||||||
|
|
||||||
|
#[cfg(feature="serde-1")]
|
||||||
|
use serde::{Serialize, Deserialize, Serializer, Deserializer};
|
||||||
|
|
||||||
mod array;
|
mod array;
|
||||||
mod array_string;
|
mod array_string;
|
||||||
|
|
||||||
@@ -850,6 +855,51 @@ impl<A: Array<Item=u8>> io::Write for ArrayVec<A> {
|
|||||||
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature="serde-1")]
|
||||||
|
impl<T: Serialize, A: Array<Item=T>> Serialize for ArrayVec<A> {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where S: Serializer
|
||||||
|
{
|
||||||
|
serializer.collect_seq(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature="serde-1")]
|
||||||
|
impl<'de, T: Deserialize<'de>, A: Array<Item=T>> Deserialize<'de> for ArrayVec<A> {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where D: Deserializer<'de>
|
||||||
|
{
|
||||||
|
use serde::de::{Visitor, SeqAccess, Error};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
struct ArrayVecVisitor<'de, T: Deserialize<'de>, A: Array<Item=T>>(PhantomData<(&'de (), T, A)>);
|
||||||
|
|
||||||
|
impl<'de, T: Deserialize<'de>, A: Array<Item=T>> Visitor<'de> for ArrayVecVisitor<'de, T, A> {
|
||||||
|
type Value = ArrayVec<A>;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(formatter, "an array with no more than {} items", A::capacity())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_seq<SA>(self, mut seq: SA) -> Result<Self::Value, SA::Error>
|
||||||
|
where SA: SeqAccess<'de>,
|
||||||
|
{
|
||||||
|
let mut values = ArrayVec::<A>::new();
|
||||||
|
|
||||||
|
while let Some(value) = try!(seq.next_element()) {
|
||||||
|
if let Some(_) = values.push(value) {
|
||||||
|
return Err(SA::Error::invalid_length(A::capacity() + 1, &self));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(values)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_seq(ArrayVecVisitor::<T, A>(PhantomData))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Error value indicating insufficient capacity
|
/// Error value indicating insufficient capacity
|
||||||
#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
|
#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
|
||||||
pub struct CapacityError<T = ()> {
|
pub struct CapacityError<T = ()> {
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
#![cfg(feature = "serde-1")]
|
||||||
|
extern crate arrayvec;
|
||||||
|
extern crate serde_test;
|
||||||
|
|
||||||
|
mod array_vec {
|
||||||
|
use arrayvec::ArrayVec;
|
||||||
|
|
||||||
|
use serde_test::{Token, assert_tokens, assert_de_tokens_error};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ser_de_empty() {
|
||||||
|
let vec = ArrayVec::<[u32; 0]>::new();
|
||||||
|
|
||||||
|
assert_tokens(&vec, &[
|
||||||
|
Token::Seq { len: Some(0) },
|
||||||
|
Token::SeqEnd,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ser_de() {
|
||||||
|
let mut vec = ArrayVec::<[u32; 3]>::new();
|
||||||
|
vec.push(20);
|
||||||
|
vec.push(55);
|
||||||
|
vec.push(123);
|
||||||
|
|
||||||
|
assert_tokens(&vec, &[
|
||||||
|
Token::Seq { len: Some(3) },
|
||||||
|
Token::U32(20),
|
||||||
|
Token::U32(55),
|
||||||
|
Token::U32(123),
|
||||||
|
Token::SeqEnd,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_de_too_large() {
|
||||||
|
assert_de_tokens_error::<ArrayVec<[u32; 2]>>(&[
|
||||||
|
Token::Seq { len: Some(3) },
|
||||||
|
Token::U32(13),
|
||||||
|
Token::U32(42),
|
||||||
|
Token::U32(68),
|
||||||
|
], "invalid length 3, expected an array with no more than 2 items");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod array_string {
|
||||||
|
use arrayvec::ArrayString;
|
||||||
|
|
||||||
|
use serde_test::{Token, assert_tokens, assert_de_tokens_error};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ser_de_empty() {
|
||||||
|
let string = ArrayString::<[u8; 0]>::new();
|
||||||
|
|
||||||
|
assert_tokens(&string, &[
|
||||||
|
Token::Str(""),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ser_de() {
|
||||||
|
let string = ArrayString::<[u8; 9]>::from("1234 abcd")
|
||||||
|
.expect("expected exact specified capacity to be enough");
|
||||||
|
|
||||||
|
assert_tokens(&string, &[
|
||||||
|
Token::Str("1234 abcd"),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_de_too_large() {
|
||||||
|
assert_de_tokens_error::<ArrayString<[u8; 2]>>(&[
|
||||||
|
Token::Str("afd")
|
||||||
|
], "invalid length 3, expected a string no more than 2 bytes long");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user