mirror of
https://github.com/rust-embedded/heapless.git
synced 2026-04-25 17:32:01 +00:00
Serde support
This commit is contained in:
@@ -28,3 +28,8 @@ scoped_threadpool = "0.1.8"
|
||||
[dependencies]
|
||||
generic-array = "0.11.0"
|
||||
hash32 = "0.1.0"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
10
ci/script.sh
10
ci/script.sh
@@ -3,7 +3,7 @@ set -euxo pipefail
|
||||
main() {
|
||||
cargo check --target $TARGET
|
||||
if [ $TRAVIS_RUST_VERSION = nightly ]; then
|
||||
cargo check --target $TARGET --features 'const-fn smaller-atomics'
|
||||
cargo check --target $TARGET --features 'serde const-fn smaller-atomics'
|
||||
fi
|
||||
|
||||
if [ $TARGET = x86_64-unknown-linux-gnu ]; then
|
||||
@@ -11,17 +11,17 @@ main() {
|
||||
cargo test --target $TARGET --release
|
||||
|
||||
if [ $TRAVIS_RUST_VERSION = nightly ]; then
|
||||
cargo test --target $TARGET --features 'const-fn smaller-atomics'
|
||||
cargo test --target $TARGET --release --features 'const-fn smaller-atomics'
|
||||
cargo test --target $TARGET --features 'serde const-fn smaller-atomics'
|
||||
cargo test --target $TARGET --release --features 'serde const-fn smaller-atomics'
|
||||
|
||||
export RUSTFLAGS="-Z sanitizer=thread"
|
||||
export RUST_TEST_THREADS=1
|
||||
export TSAN_OPTIONS="suppressions=$(pwd)/blacklist.txt"
|
||||
|
||||
cargo test --test tsan --target $TARGET
|
||||
cargo test --test tsan --target $TARGET --features 'const-fn smaller-atomics'
|
||||
cargo test --test tsan --target $TARGET --features 'serde const-fn smaller-atomics'
|
||||
cargo test --test tsan --target $TARGET --release
|
||||
cargo test --test tsan --target $TARGET --release --features 'const-fn smaller-atomics'
|
||||
cargo test --test tsan --target $TARGET --release --features 'serde const-fn smaller-atomics'
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
288
src/de.rs
Normal file
288
src/de.rs
Normal file
@@ -0,0 +1,288 @@
|
||||
use core::fmt;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use generic_array::{typenum::PowerOfTwo, ArrayLength};
|
||||
use hash32::{BuildHasherDefault, Hash, Hasher};
|
||||
use serde::de::{self, Deserialize, Deserializer, Error, MapAccess, SeqAccess};
|
||||
|
||||
use super::binary_heap::Kind as BinaryHeapKind;
|
||||
use super::indexmap::{Bucket, Pos};
|
||||
use BinaryHeap;
|
||||
use IndexMap;
|
||||
use IndexSet;
|
||||
use LinearMap;
|
||||
use String;
|
||||
use Vec;
|
||||
|
||||
// Sequential containers
|
||||
|
||||
impl<'de, T, N, KIND> Deserialize<'de> for BinaryHeap<T, N, KIND>
|
||||
where
|
||||
T: Ord + Deserialize<'de>,
|
||||
N: ArrayLength<T>,
|
||||
KIND: BinaryHeapKind,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct ValueVisitor<'de, T, N, KIND>(PhantomData<(&'de (), T, N, KIND)>);
|
||||
|
||||
impl<'de, T, N, KIND> de::Visitor<'de> for ValueVisitor<'de, T, N, KIND>
|
||||
where
|
||||
T: Ord + Deserialize<'de>,
|
||||
N: ArrayLength<T>,
|
||||
KIND: BinaryHeapKind,
|
||||
{
|
||||
type Value = BinaryHeap<T, N, KIND>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a sequence")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
let mut values = BinaryHeap::new();
|
||||
|
||||
while let Some(value) = seq.next_element()? {
|
||||
if values.push(value).is_err() {
|
||||
return Err(A::Error::invalid_length(values.capacity() + 1, &self))?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(values)
|
||||
}
|
||||
}
|
||||
deserializer.deserialize_seq(ValueVisitor(PhantomData))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, T, N, S> Deserialize<'de> for IndexSet<T, N, BuildHasherDefault<S>>
|
||||
where
|
||||
T: Eq + Hash + Deserialize<'de>,
|
||||
S: Hasher + Default,
|
||||
N: ArrayLength<Bucket<T, ()>> + ArrayLength<Option<Pos>> + PowerOfTwo,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct ValueVisitor<'de, T, N, S>(PhantomData<(&'de (), T, N, S)>);
|
||||
|
||||
impl<'de, T, N, S> de::Visitor<'de> for ValueVisitor<'de, T, N, S>
|
||||
where
|
||||
T: Eq + Hash + Deserialize<'de>,
|
||||
S: Hasher + Default,
|
||||
N: ArrayLength<Bucket<T, ()>> + ArrayLength<Option<Pos>> + PowerOfTwo,
|
||||
{
|
||||
type Value = IndexSet<T, N, BuildHasherDefault<S>>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a sequence")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
let mut values = IndexSet::new();
|
||||
|
||||
while let Some(value) = seq.next_element()? {
|
||||
if values.insert(value).is_err() {
|
||||
return Err(A::Error::invalid_length(values.capacity() + 1, &self))?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(values)
|
||||
}
|
||||
}
|
||||
deserializer.deserialize_seq(ValueVisitor(PhantomData))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, T, N> Deserialize<'de> for Vec<T, N>
|
||||
where
|
||||
N: ArrayLength<T>,
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct ValueVisitor<'de, T, N>(PhantomData<(&'de (), T, N)>);
|
||||
|
||||
impl<'de, T, N> de::Visitor<'de> for ValueVisitor<'de, T, N>
|
||||
where
|
||||
N: ArrayLength<T>,
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
type Value = Vec<T, N>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a sequence")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
let mut values = Vec::new();
|
||||
|
||||
while let Some(value) = seq.next_element()? {
|
||||
if values.push(value).is_err() {
|
||||
return Err(A::Error::invalid_length(values.capacity() + 1, &self))?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(values)
|
||||
}
|
||||
}
|
||||
deserializer.deserialize_seq(ValueVisitor(PhantomData))
|
||||
}
|
||||
}
|
||||
|
||||
// Dictionaries
|
||||
|
||||
impl<'de, K, V, N, S> Deserialize<'de> for IndexMap<K, V, N, BuildHasherDefault<S>>
|
||||
where
|
||||
K: Eq + Hash + Deserialize<'de>,
|
||||
V: Deserialize<'de>,
|
||||
N: ArrayLength<Bucket<K, V>> + ArrayLength<Option<Pos>> + PowerOfTwo,
|
||||
S: Default + Hasher,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct ValueVisitor<'de, K, V, N, S>(PhantomData<(&'de (), K, V, N, S)>);
|
||||
|
||||
impl<'de, K, V, N, S> de::Visitor<'de> for ValueVisitor<'de, K, V, N, S>
|
||||
where
|
||||
K: Eq + Hash + Deserialize<'de>,
|
||||
V: Deserialize<'de>,
|
||||
N: ArrayLength<Bucket<K, V>> + ArrayLength<Option<Pos>> + PowerOfTwo,
|
||||
S: Default + Hasher,
|
||||
{
|
||||
type Value = IndexMap<K, V, N, BuildHasherDefault<S>>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a map")
|
||||
}
|
||||
|
||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: MapAccess<'de>,
|
||||
{
|
||||
let mut values = IndexMap::new();
|
||||
|
||||
while let Some((key, value)) = map.next_entry()? {
|
||||
if values.insert(key, value).is_err() {
|
||||
return Err(A::Error::invalid_length(values.capacity() + 1, &self))?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(values)
|
||||
}
|
||||
}
|
||||
deserializer.deserialize_seq(ValueVisitor(PhantomData))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, K, V, N> Deserialize<'de> for LinearMap<K, V, N>
|
||||
where
|
||||
K: Eq + Deserialize<'de>,
|
||||
V: Deserialize<'de>,
|
||||
N: ArrayLength<(K, V)>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct ValueVisitor<'de, K, V, N>(PhantomData<(&'de (), K, V, N)>);
|
||||
|
||||
impl<'de, K, V, N> de::Visitor<'de> for ValueVisitor<'de, K, V, N>
|
||||
where
|
||||
K: Eq + Deserialize<'de>,
|
||||
V: Deserialize<'de>,
|
||||
N: ArrayLength<(K, V)>,
|
||||
{
|
||||
type Value = LinearMap<K, V, N>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a map")
|
||||
}
|
||||
|
||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: MapAccess<'de>,
|
||||
{
|
||||
let mut values = LinearMap::new();
|
||||
|
||||
while let Some((key, value)) = map.next_entry()? {
|
||||
if values.insert(key, value).is_err() {
|
||||
return Err(A::Error::invalid_length(values.capacity() + 1, &self))?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(values)
|
||||
}
|
||||
}
|
||||
deserializer.deserialize_seq(ValueVisitor(PhantomData))
|
||||
}
|
||||
}
|
||||
|
||||
// String containers
|
||||
|
||||
impl<'de, N> Deserialize<'de> for String<N>
|
||||
where
|
||||
N: ArrayLength<u8>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct ValueVisitor<'de, N>(PhantomData<(&'de (), N)>);
|
||||
|
||||
impl<'de, N> de::Visitor<'de> for ValueVisitor<'de, N>
|
||||
where
|
||||
N: ArrayLength<u8>,
|
||||
{
|
||||
type Value = String<N>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
formatter,
|
||||
"a string no more than {} bytes long",
|
||||
N::to_u64()
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
let mut s = String::new();
|
||||
s.push_str(v)
|
||||
.map_err(|_| E::invalid_length(v.len(), &self))?;
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
let mut bytes = Vec::new();
|
||||
if bytes.extend_from_slice(v).is_err() {
|
||||
return Err(E::invalid_value(de::Unexpected::Bytes(v), &self));
|
||||
}
|
||||
|
||||
String::from_utf8(bytes)
|
||||
.map_err(|_| E::invalid_value(de::Unexpected::Bytes(v), &self))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_str(ValueVisitor::<'de, N>(PhantomData))
|
||||
}
|
||||
}
|
||||
@@ -89,6 +89,9 @@ extern crate hash32;
|
||||
#[cfg(test)]
|
||||
extern crate std;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
extern crate serde;
|
||||
|
||||
#[macro_use]
|
||||
mod const_fn;
|
||||
|
||||
@@ -108,6 +111,11 @@ mod linear_map;
|
||||
mod string;
|
||||
mod vec;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
mod de;
|
||||
#[cfg(feature = "serde")]
|
||||
mod ser;
|
||||
|
||||
pub mod binary_heap;
|
||||
pub mod spsc;
|
||||
|
||||
|
||||
121
src/ser.rs
Normal file
121
src/ser.rs
Normal file
@@ -0,0 +1,121 @@
|
||||
use hash32::{BuildHasher, Hash};
|
||||
|
||||
use generic_array::{typenum::PowerOfTwo, ArrayLength};
|
||||
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
|
||||
|
||||
use super::binary_heap::Kind as BinaryHeapKind;
|
||||
use super::indexmap::{Bucket, Pos};
|
||||
use BinaryHeap;
|
||||
use IndexMap;
|
||||
use IndexSet;
|
||||
use LinearMap;
|
||||
use String;
|
||||
use Vec;
|
||||
|
||||
// Sequential containers
|
||||
|
||||
impl<T, N, KIND> Serialize for BinaryHeap<T, N, KIND>
|
||||
where
|
||||
T: Ord + Serialize,
|
||||
N: ArrayLength<T>,
|
||||
KIND: BinaryHeapKind,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut seq = serializer.serialize_seq(Some(self.len()))?;
|
||||
for element in self {
|
||||
seq.serialize_element(element)?;
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, N, S> Serialize for IndexSet<T, N, S>
|
||||
where
|
||||
T: Eq + Hash + Serialize,
|
||||
S: BuildHasher,
|
||||
N: ArrayLength<Bucket<T, ()>> + ArrayLength<Option<Pos>> + PowerOfTwo,
|
||||
{
|
||||
fn serialize<SER>(&self, serializer: SER) -> Result<SER::Ok, SER::Error>
|
||||
where
|
||||
SER: Serializer,
|
||||
{
|
||||
let mut seq = serializer.serialize_seq(Some(self.len()))?;
|
||||
for element in self {
|
||||
seq.serialize_element(element)?;
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, N> Serialize for Vec<T, N>
|
||||
where
|
||||
T: Serialize,
|
||||
N: ArrayLength<T>,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut seq = serializer.serialize_seq(Some(self.len()))?;
|
||||
for element in self {
|
||||
seq.serialize_element(element)?;
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
}
|
||||
|
||||
// Dictionaries
|
||||
|
||||
impl<K, V, N, S> Serialize for IndexMap<K, V, N, S>
|
||||
where
|
||||
K: Eq + Hash + Serialize,
|
||||
N: ArrayLength<Bucket<K, V>> + ArrayLength<Option<Pos>>,
|
||||
S: BuildHasher,
|
||||
V: Serialize,
|
||||
{
|
||||
fn serialize<SER>(&self, serializer: SER) -> Result<SER::Ok, SER::Error>
|
||||
where
|
||||
SER: Serializer,
|
||||
{
|
||||
let mut map = serializer.serialize_map(Some(self.len()))?;
|
||||
for (k, v) in self {
|
||||
map.serialize_entry(k, v)?;
|
||||
}
|
||||
map.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, N> Serialize for LinearMap<K, V, N>
|
||||
where
|
||||
N: ArrayLength<(K, V)>,
|
||||
K: Eq + Serialize,
|
||||
V: Serialize,
|
||||
{
|
||||
fn serialize<SER>(&self, serializer: SER) -> Result<SER::Ok, SER::Error>
|
||||
where
|
||||
SER: Serializer,
|
||||
{
|
||||
let mut map = serializer.serialize_map(Some(self.len()))?;
|
||||
for (k, v) in self {
|
||||
map.serialize_entry(k, v)?;
|
||||
}
|
||||
map.end()
|
||||
}
|
||||
}
|
||||
|
||||
// String containers
|
||||
|
||||
impl<N> Serialize for String<N>
|
||||
where
|
||||
N: ArrayLength<u8>,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&*self)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user