Support deserialization into byte arrays for BLOB's via serde_bytes.
This commit is contained in:
parent
70f4c53854
commit
41dd989866
@ -20,6 +20,7 @@ Enhancements
|
|||||||
|
|
||||||
* Added `into_array` and `into_typed_array` for `Dynamic`.
|
* Added `into_array` and `into_typed_array` for `Dynamic`.
|
||||||
* Added `FnPtr::call` and `FnPtr::call_within_context` to simplify calling a function pointer.
|
* Added `FnPtr::call` and `FnPtr::call_within_context` to simplify calling a function pointer.
|
||||||
|
* BLob's can now be deserialized (using `from_dynamic`) into `Vec<u8>` via [`serde_bytes`](https://crates.io/crates/serde_bytes).
|
||||||
|
|
||||||
Deprecated and Gated API's
|
Deprecated and Gated API's
|
||||||
--------------------------
|
--------------------------
|
||||||
|
@ -22,6 +22,9 @@ num-traits = { version = "0.2", default-features = false }
|
|||||||
smartstring = { version = "0.2.8", default-features = false }
|
smartstring = { version = "0.2.8", default-features = false }
|
||||||
rhai_codegen = { version = "1.2", path = "codegen", default-features = false }
|
rhai_codegen = { version = "1.2", path = "codegen", default-features = false }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
serde_bytes = "0.11"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["ahash/std", "num-traits/std"]
|
default = ["ahash/std", "num-traits/std"]
|
||||||
unchecked = [] # unchecked arithmetic
|
unchecked = [] # unchecked arithmetic
|
||||||
|
@ -10,7 +10,7 @@ use std::prelude::v1::*;
|
|||||||
use std::{any::type_name, fmt};
|
use std::{any::type_name, fmt};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
use crate::Array;
|
use crate::{Array, Blob};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
use crate::Map;
|
use crate::Map;
|
||||||
@ -154,7 +154,7 @@ impl<'de> Deserializer<'de> for &mut DynamicDeserializer<'de> {
|
|||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Union::Array(_, _, _) => self.deserialize_seq(visitor),
|
Union::Array(_, _, _) => self.deserialize_seq(visitor),
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Union::Blob(_, _, _) => self.deserialize_seq(visitor),
|
Union::Blob(_, _, _) => self.deserialize_bytes(visitor),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Union::Map(_, _, _) => self.deserialize_map(visitor),
|
Union::Map(_, _, _) => self.deserialize_map(visitor),
|
||||||
Union::FnPtr(_, _, _) => self.type_error(),
|
Union::FnPtr(_, _, _) => self.type_error(),
|
||||||
@ -357,12 +357,20 @@ impl<'de> Deserializer<'de> for &mut DynamicDeserializer<'de> {
|
|||||||
self.deserialize_str(visitor)
|
self.deserialize_str(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_bytes<V: Visitor<'de>>(self, _: V) -> Result<V::Value, Box<EvalAltResult>> {
|
fn deserialize_bytes<V: Visitor<'de>>(
|
||||||
self.type_error()
|
self,
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Box<EvalAltResult>> {
|
||||||
|
self.value
|
||||||
|
.downcast_ref::<Blob>()
|
||||||
|
.map_or_else(|| self.type_error(), |x| visitor.visit_bytes(x))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_byte_buf<V: Visitor<'de>>(self, _: V) -> Result<V::Value, Box<EvalAltResult>> {
|
fn deserialize_byte_buf<V: Visitor<'de>>(
|
||||||
self.type_error()
|
self,
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Box<EvalAltResult>> {
|
||||||
|
self.deserialize_bytes(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_option<V: Visitor<'de>>(
|
fn deserialize_option<V: Visitor<'de>>(
|
||||||
@ -402,7 +410,7 @@ impl<'de> Deserializer<'de> for &mut DynamicDeserializer<'de> {
|
|||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
return self.value.downcast_ref::<Array>().map_or_else(
|
return self.value.downcast_ref::<Array>().map_or_else(
|
||||||
|| self.type_error(),
|
|| self.type_error(),
|
||||||
|arr| _visitor.visit_seq(IterateArray::new(arr.iter())),
|
|arr| _visitor.visit_seq(IterateDynamicArray::new(arr.iter())),
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(feature = "no_index")]
|
#[cfg(feature = "no_index")]
|
||||||
@ -497,20 +505,21 @@ impl<'de> Deserializer<'de> for &mut DynamicDeserializer<'de> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// `SeqAccess` implementation for arrays.
|
/// `SeqAccess` implementation for arrays.
|
||||||
struct IterateArray<'a, ITER: Iterator<Item = &'a Dynamic>> {
|
struct IterateDynamicArray<'a, ITER: Iterator<Item = &'a Dynamic>> {
|
||||||
/// Iterator for a stream of [`Dynamic`][crate::Dynamic] values.
|
/// Iterator for a stream of [`Dynamic`][crate::Dynamic] values.
|
||||||
iter: ITER,
|
iter: ITER,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
impl<'a, ITER: Iterator<Item = &'a Dynamic>> IterateDynamicArray<'a, ITER> {
|
||||||
impl<'a, ITER: Iterator<Item = &'a Dynamic>> IterateArray<'a, ITER> {
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(iter: ITER) -> Self {
|
pub fn new(iter: ITER) -> Self {
|
||||||
Self { iter }
|
Self { iter }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a: 'de, 'de, ITER: Iterator<Item = &'a Dynamic>> SeqAccess<'de> for IterateArray<'a, ITER> {
|
impl<'a: 'de, 'de, ITER: Iterator<Item = &'a Dynamic>> SeqAccess<'de>
|
||||||
|
for IterateDynamicArray<'a, ITER>
|
||||||
|
{
|
||||||
type Error = Box<EvalAltResult>;
|
type Error = Box<EvalAltResult>;
|
||||||
|
|
||||||
fn next_element_seed<T: DeserializeSeed<'de>>(
|
fn next_element_seed<T: DeserializeSeed<'de>>(
|
||||||
|
@ -257,11 +257,11 @@ impl Serializer for &mut DynamicSerializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_str(self, v: &str) -> Result<Self::Ok, Box<EvalAltResult>> {
|
fn serialize_str(self, v: &str) -> Result<Self::Ok, Box<EvalAltResult>> {
|
||||||
Ok(v.to_string().into())
|
Ok(v.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Box<EvalAltResult>> {
|
fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Box<EvalAltResult>> {
|
||||||
Ok(Dynamic::from(v.to_vec()))
|
Ok(v.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_none(self) -> Result<Self::Ok, Box<EvalAltResult>> {
|
fn serialize_none(self) -> Result<Self::Ok, Box<EvalAltResult>> {
|
||||||
|
@ -2109,6 +2109,9 @@ impl Dynamic {
|
|||||||
v.try_cast::<T>().ok_or_else(|| typ)
|
v.try_cast::<T>().ok_or_else(|| typ)
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
|
Union::Blob(_, _, _) if TypeId::of::<T>() == TypeId::of::<u8>() => {
|
||||||
|
Ok(self.cast::<Vec<T>>())
|
||||||
|
}
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
Union::Shared(cell, _, _) => {
|
Union::Shared(cell, _, _) => {
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
|
@ -775,3 +775,23 @@ fn test_serde_optional() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
fn test_serde_blob() -> Result<(), Box<EvalAltResult>> {
|
||||||
|
let engine = Engine::new();
|
||||||
|
|
||||||
|
let r = engine.eval::<Dynamic>(
|
||||||
|
"
|
||||||
|
let x = blob(10);
|
||||||
|
for i in range(0, 10) { x[i] = i; }
|
||||||
|
x
|
||||||
|
",
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let r = from_dynamic::<serde_bytes::ByteBuf>(&r)?;
|
||||||
|
|
||||||
|
assert_eq!(r.to_vec(), vec![0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user