mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-02 16:21:42 +00:00
Remove context_deserialize and import from crates.io (#8172)
Use the recently published `context_deserialize` and remove it from Lighthouse Co-Authored-By: Mac L <mjladson@pm.me> Co-Authored-By: Michael Sproul <michael@sigmaprime.io>
This commit is contained in:
46
Cargo.lock
generated
46
Cargo.lock
generated
@@ -2076,22 +2076,21 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
|
||||
[[package]]
|
||||
name = "context_deserialize"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c5f9ea0a0ae2de4943f5ca71590b6dbd0b952475f0a0cafb30a470cec78c8b9"
|
||||
dependencies = [
|
||||
"context_deserialize_derive",
|
||||
"milhouse",
|
||||
"serde",
|
||||
"ssz_types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "context_deserialize_derive"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c57b2db1e4e3ed804dcc49894a144b68fe6c754b8f545eb1dda7ad3c7dbe7e6"
|
||||
dependencies = [
|
||||
"context_deserialize",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
@@ -3258,9 +3257,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ethereum_hashing"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c853bd72c9e5787f8aafc3df2907c2ed03cff3150c3acd94e2e53a98ab70a8ab"
|
||||
checksum = "5aa93f58bb1eb3d1e556e4f408ef1dac130bad01ac37db4e7ade45de40d1c86a"
|
||||
dependencies = [
|
||||
"cpufeatures",
|
||||
"ring",
|
||||
@@ -3282,12 +3281,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ethereum_ssz"
|
||||
version = "0.9.1"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0dcddb2554d19cde19b099fadddde576929d7a4d0c1cd3512d1fd95cf174375c"
|
||||
checksum = "7e8cd8c4f47dfb947dbfe3cdf2945ae1da808dbedc592668658e827a12659ba1"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"arbitrary",
|
||||
"context_deserialize",
|
||||
"ethereum_serde_utils",
|
||||
"itertools 0.13.0",
|
||||
"serde",
|
||||
@@ -3298,9 +3298,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ethereum_ssz_derive"
|
||||
version = "0.9.1"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a657b6b3b7e153637dc6bdc6566ad9279d9ee11a15b12cfb24a2e04360637e9f"
|
||||
checksum = "78d247bc40823c365a62e572441a8f8b12df03f171713f06bc76180fcd56ab71"
|
||||
dependencies = [
|
||||
"darling 0.20.11",
|
||||
"proc-macro2",
|
||||
@@ -5858,12 +5858,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "milhouse"
|
||||
version = "0.7.0"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bdb104e38d3a8c5ffb7e9d2c43c522e6bcc34070edbadba565e722f0dee56c7"
|
||||
checksum = "259dd9da2ae5e0278b95da0b7ecef9c18c309d0a2d9e6db57ed33b9e8910c5e7"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"arbitrary",
|
||||
"context_deserialize",
|
||||
"educe",
|
||||
"ethereum_hashing",
|
||||
"ethereum_ssz",
|
||||
@@ -8539,11 +8540,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ssz_types"
|
||||
version = "0.12.2"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "704671195db617afa3d919da8f220f2535f20d0fa8dad96a1c27a38a5f8f6e9c"
|
||||
checksum = "1fc20a89bab2dabeee65e9c9eb96892dc222c23254b401e1319b85efd852fa31"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
"context_deserialize",
|
||||
"ethereum_serde_utils",
|
||||
"ethereum_ssz",
|
||||
"itertools 0.14.0",
|
||||
@@ -9441,9 +9443,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tree_hash"
|
||||
version = "0.10.0"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee44f4cef85f88b4dea21c0b1f58320bdf35715cf56d840969487cff00613321"
|
||||
checksum = "2db21caa355767db4fd6129876e5ae278a8699f4a6959b1e3e7aff610b532d52"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"ethereum_hashing",
|
||||
@@ -9454,11 +9456,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tree_hash_derive"
|
||||
version = "0.10.0"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bee2ea1551f90040ab0e34b6fb7f2fa3bad8acc925837ac654f2c78a13e3089"
|
||||
checksum = "711cc655fcbb48384a87dc2bf641b991a15c5ad9afc3caa0b1ab1df3b436f70f"
|
||||
dependencies = [
|
||||
"darling 0.20.11",
|
||||
"darling 0.21.3",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.110",
|
||||
|
||||
21
Cargo.toml
21
Cargo.toml
@@ -47,8 +47,6 @@ members = [
|
||||
"common/validator_dir",
|
||||
"common/warp_utils",
|
||||
"common/workspace_members",
|
||||
"consensus/context_deserialize/context_deserialize",
|
||||
"consensus/context_deserialize/context_deserialize_derive",
|
||||
"consensus/fixed_bytes",
|
||||
"consensus/fork_choice",
|
||||
"consensus/int_to_bytes",
|
||||
@@ -122,10 +120,7 @@ clap = { version = "4.5.4", features = ["derive", "cargo", "wrap_help"] }
|
||||
clap_utils = { path = "common/clap_utils" }
|
||||
compare_fields = "0.1"
|
||||
console-subscriber = "0.4"
|
||||
context_deserialize = { path = "consensus/context_deserialize/context_deserialize", features = [
|
||||
"all",
|
||||
] }
|
||||
context_deserialize_derive = { path = "consensus/context_deserialize/context_deserialize_derive" }
|
||||
context_deserialize = "0.2"
|
||||
criterion = "0.5"
|
||||
delay_map = "0.4"
|
||||
deposit_contract = { path = "common/deposit_contract" }
|
||||
@@ -143,10 +138,10 @@ eth2_key_derivation = { path = "crypto/eth2_key_derivation" }
|
||||
eth2_keystore = { path = "crypto/eth2_keystore" }
|
||||
eth2_network_config = { path = "common/eth2_network_config" }
|
||||
eth2_wallet = { path = "crypto/eth2_wallet" }
|
||||
ethereum_hashing = "0.7.0"
|
||||
ethereum_hashing = "0.8.0"
|
||||
ethereum_serde_utils = "0.8.0"
|
||||
ethereum_ssz = "0.9.0"
|
||||
ethereum_ssz_derive = "0.9.0"
|
||||
ethereum_ssz = { version = "0.10.0", features = ["context_deserialize"] }
|
||||
ethereum_ssz_derive = "0.10.0"
|
||||
execution_layer = { path = "beacon_node/execution_layer" }
|
||||
exit-future = "0.2"
|
||||
filesystem = { path = "common/filesystem" }
|
||||
@@ -183,7 +178,7 @@ malloc_utils = { path = "common/malloc_utils" }
|
||||
maplit = "1"
|
||||
merkle_proof = { path = "consensus/merkle_proof" }
|
||||
metrics = { path = "common/metrics" }
|
||||
milhouse = { version = "0.7", default-features = false }
|
||||
milhouse = { version = "0.9", default-features = false, features = ["context_deserialize"] }
|
||||
mockall = "0.13"
|
||||
mockall_double = "0.3"
|
||||
mockito = "1.5.0"
|
||||
@@ -232,7 +227,7 @@ slashing_protection = { path = "validator_client/slashing_protection" }
|
||||
slot_clock = { path = "common/slot_clock" }
|
||||
smallvec = { version = "1.11.2", features = ["arbitrary"] }
|
||||
snap = "1"
|
||||
ssz_types = "0.12.2"
|
||||
ssz_types = { version = "0.14.0", features = ["context_deserialize"] }
|
||||
state_processing = { path = "consensus/state_processing" }
|
||||
store = { path = "beacon_node/store" }
|
||||
strum = { version = "0.24", features = ["derive"] }
|
||||
@@ -257,8 +252,8 @@ tracing-core = "0.1"
|
||||
tracing-log = "0.2"
|
||||
tracing-opentelemetry = "0.31.0"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
|
||||
tree_hash = "0.10.0"
|
||||
tree_hash_derive = "0.10.0"
|
||||
tree_hash = "0.12.0"
|
||||
tree_hash_derive = "0.12.0"
|
||||
types = { path = "consensus/types" }
|
||||
url = "2"
|
||||
uuid = { version = "0.8", features = ["serde", "v4"] }
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
[package]
|
||||
name = "context_deserialize"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
default = ["derive"]
|
||||
derive = ["dep:context_deserialize_derive"]
|
||||
milhouse = ["dep:milhouse"]
|
||||
ssz = ["dep:ssz_types"]
|
||||
all = ["derive", "milhouse", "ssz"]
|
||||
|
||||
[dependencies]
|
||||
context_deserialize_derive = { version = "0.1.0", path = "../context_deserialize_derive", optional = true }
|
||||
milhouse = { workspace = true, optional = true }
|
||||
serde = { workspace = true }
|
||||
ssz_types = { workspace = true, optional = true }
|
||||
@@ -1,103 +0,0 @@
|
||||
use crate::ContextDeserialize;
|
||||
use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor};
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
|
||||
impl<'de, C, T> ContextDeserialize<'de, T> for Arc<C>
|
||||
where
|
||||
C: ContextDeserialize<'de, T>,
|
||||
{
|
||||
fn context_deserialize<D>(deserializer: D, context: T) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Ok(Arc::new(C::context_deserialize(deserializer, context)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, T, C> ContextDeserialize<'de, C> for Vec<T>
|
||||
where
|
||||
T: ContextDeserialize<'de, C>,
|
||||
C: Clone,
|
||||
{
|
||||
fn context_deserialize<D>(deserializer: D, context: C) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
// Our Visitor, which owns one copy of the context T
|
||||
struct ContextVisitor<C, T> {
|
||||
context: T,
|
||||
_marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<'de, C, T> Visitor<'de> for ContextVisitor<C, T>
|
||||
where
|
||||
C: ContextDeserialize<'de, T>,
|
||||
T: Clone,
|
||||
{
|
||||
type Value = Vec<C>;
|
||||
|
||||
fn expecting(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
fmt.write_str("a sequence of context‐deserialized elements")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Vec<C>, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
let mut out = Vec::with_capacity(seq.size_hint().unwrap_or(0));
|
||||
// for each element, we clone the context and hand it to the seed
|
||||
while let Some(elem) = seq.next_element_seed(ContextSeed {
|
||||
context: self.context.clone(),
|
||||
_marker: PhantomData,
|
||||
})? {
|
||||
out.push(elem);
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
}
|
||||
|
||||
// A little seed that hands the deserializer + context into C::context_deserialize
|
||||
struct ContextSeed<T, C> {
|
||||
context: C,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'de, T, C> DeserializeSeed<'de> for ContextSeed<T, C>
|
||||
where
|
||||
T: ContextDeserialize<'de, C>,
|
||||
C: Clone,
|
||||
{
|
||||
type Value = T;
|
||||
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<T, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
T::context_deserialize(deserializer, self.context)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_seq(ContextVisitor {
|
||||
context,
|
||||
_marker: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! trivial_deserialize {
|
||||
($($t:ty),* $(,)?) => {
|
||||
$(
|
||||
impl<'de, T> ContextDeserialize<'de, T> for $t {
|
||||
fn context_deserialize<D>(deserializer: D, _context: T) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
<$t>::deserialize(deserializer)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
trivial_deserialize!(bool, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64);
|
||||
@@ -1,45 +0,0 @@
|
||||
use crate::ContextDeserialize;
|
||||
use milhouse::{List, Value, Vector};
|
||||
use serde::de::Deserializer;
|
||||
use ssz_types::typenum::Unsigned;
|
||||
|
||||
impl<'de, C, T, N> ContextDeserialize<'de, C> for List<T, N>
|
||||
where
|
||||
T: ContextDeserialize<'de, C> + Value,
|
||||
N: Unsigned,
|
||||
C: Clone,
|
||||
{
|
||||
fn context_deserialize<D>(deserializer: D, context: C) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
// First deserialize as a Vec.
|
||||
// This is not the most efficient implementation as it allocates a temporary Vec. In future
|
||||
// we could write a more performant implementation using `List::builder()`.
|
||||
let vec = Vec::<T>::context_deserialize(deserializer, context)?;
|
||||
|
||||
// Then convert to List, which will check the length.
|
||||
List::new(vec)
|
||||
.map_err(|e| serde::de::Error::custom(format!("Failed to create List: {:?}", e)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, C, T, N> ContextDeserialize<'de, C> for Vector<T, N>
|
||||
where
|
||||
T: ContextDeserialize<'de, C> + Value,
|
||||
N: Unsigned,
|
||||
C: Clone,
|
||||
{
|
||||
fn context_deserialize<D>(deserializer: D, context: C) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
// First deserialize as a List
|
||||
let list = List::<T, N>::context_deserialize(deserializer, context)?;
|
||||
|
||||
// Then convert to Vector, which will check the length
|
||||
Vector::try_from(list).map_err(|e| {
|
||||
serde::de::Error::custom(format!("Failed to convert List to Vector: {:?}", e))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
mod core;
|
||||
|
||||
#[cfg(feature = "milhouse")]
|
||||
mod milhouse;
|
||||
|
||||
#[cfg(feature = "ssz")]
|
||||
mod ssz;
|
||||
@@ -1,51 +0,0 @@
|
||||
use crate::ContextDeserialize;
|
||||
use serde::{
|
||||
de::{Deserializer, Error},
|
||||
Deserialize,
|
||||
};
|
||||
use ssz_types::{
|
||||
length::{Fixed, Variable},
|
||||
typenum::Unsigned,
|
||||
Bitfield, FixedVector,
|
||||
};
|
||||
|
||||
impl<'de, C, T, N> ContextDeserialize<'de, C> for FixedVector<T, N>
|
||||
where
|
||||
T: ContextDeserialize<'de, C>,
|
||||
N: Unsigned,
|
||||
C: Clone,
|
||||
{
|
||||
fn context_deserialize<D>(deserializer: D, context: C) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let vec = Vec::<T>::context_deserialize(deserializer, context)?;
|
||||
FixedVector::new(vec).map_err(|e| D::Error::custom(format!("{:?}", e)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, C, N> ContextDeserialize<'de, C> for Bitfield<Variable<N>>
|
||||
where
|
||||
N: Unsigned + Clone,
|
||||
{
|
||||
fn context_deserialize<D>(deserializer: D, _context: C) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Bitfield::<Variable<N>>::deserialize(deserializer)
|
||||
.map_err(|e| D::Error::custom(format!("{:?}", e)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, C, N> ContextDeserialize<'de, C> for Bitfield<Fixed<N>>
|
||||
where
|
||||
N: Unsigned + Clone,
|
||||
{
|
||||
fn context_deserialize<D>(deserializer: D, _context: C) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Bitfield::<Fixed<N>>::deserialize(deserializer)
|
||||
.map_err(|e| D::Error::custom(format!("{:?}", e)))
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
mod impls;
|
||||
|
||||
#[cfg(feature = "derive")]
|
||||
pub use context_deserialize_derive::context_deserialize;
|
||||
|
||||
use serde::de::Deserializer;
|
||||
|
||||
/// General-purpose deserialization trait that accepts extra context `C`.
|
||||
pub trait ContextDeserialize<'de, C>: Sized {
|
||||
fn context_deserialize<D>(deserializer: D, context: C) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
[package]
|
||||
name = "context_deserialize_derive"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
quote = { workspace = true }
|
||||
syn = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
context_deserialize = { path = "../context_deserialize" }
|
||||
serde = { workspace = true }
|
||||
serde_json = "1.0"
|
||||
@@ -1,118 +0,0 @@
|
||||
extern crate proc_macro;
|
||||
extern crate quote;
|
||||
extern crate syn;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{
|
||||
parse_macro_input, AttributeArgs, DeriveInput, GenericParam, LifetimeDef, Meta, NestedMeta,
|
||||
WhereClause,
|
||||
};
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn context_deserialize(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let args = parse_macro_input!(attr as AttributeArgs);
|
||||
let input = parse_macro_input!(item as DeriveInput);
|
||||
let ident = &input.ident;
|
||||
|
||||
let mut ctx_types = Vec::new();
|
||||
let mut explicit_where: Option<WhereClause> = None;
|
||||
|
||||
for meta in args {
|
||||
match meta {
|
||||
NestedMeta::Meta(Meta::Path(p)) => {
|
||||
ctx_types.push(p);
|
||||
}
|
||||
NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("bound") => {
|
||||
if let syn::Lit::Str(lit_str) = &nv.lit {
|
||||
let where_string = format!("where {}", lit_str.value());
|
||||
match syn::parse_str::<WhereClause>(&where_string) {
|
||||
Ok(where_clause) => {
|
||||
explicit_where = Some(where_clause);
|
||||
}
|
||||
Err(err) => {
|
||||
return syn::Error::new_spanned(
|
||||
lit_str,
|
||||
format!("Invalid where clause '{}': {}", lit_str.value(), err),
|
||||
)
|
||||
.to_compile_error()
|
||||
.into();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return syn::Error::new_spanned(
|
||||
&nv,
|
||||
"Expected a string literal for `bound` value",
|
||||
)
|
||||
.to_compile_error()
|
||||
.into();
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return syn::Error::new_spanned(
|
||||
&meta,
|
||||
"Expected paths or `bound = \"...\"` in #[context_deserialize(...)]",
|
||||
)
|
||||
.to_compile_error()
|
||||
.into();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ctx_types.is_empty() {
|
||||
return quote! {
|
||||
compile_error!("Usage: #[context_deserialize(Type1, Type2, ..., bound = \"...\")]");
|
||||
}
|
||||
.into();
|
||||
}
|
||||
|
||||
let original_generics = input.generics.clone();
|
||||
|
||||
// Clone and clean generics for impl use (remove default params)
|
||||
let mut impl_generics = input.generics.clone();
|
||||
for param in impl_generics.params.iter_mut() {
|
||||
if let GenericParam::Type(ty) = param {
|
||||
ty.eq_token = None;
|
||||
ty.default = None;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure 'de lifetime exists in impl generics
|
||||
let has_de = impl_generics
|
||||
.lifetimes()
|
||||
.any(|LifetimeDef { lifetime, .. }| lifetime.ident == "de");
|
||||
|
||||
if !has_de {
|
||||
impl_generics.params.insert(0, syn::parse_quote! { 'de });
|
||||
}
|
||||
|
||||
let (_, ty_generics, _) = original_generics.split_for_impl();
|
||||
let (impl_gens, _, _) = impl_generics.split_for_impl();
|
||||
|
||||
// Generate: no `'de` applied to the type name
|
||||
let mut impls = quote! {};
|
||||
for ctx in ctx_types {
|
||||
impls.extend(quote! {
|
||||
impl #impl_gens context_deserialize::ContextDeserialize<'de, #ctx>
|
||||
for #ident #ty_generics
|
||||
#explicit_where
|
||||
{
|
||||
fn context_deserialize<D>(
|
||||
deserializer: D,
|
||||
_context: #ctx,
|
||||
) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::de::Deserializer<'de>,
|
||||
{
|
||||
<Self as serde::Deserialize>::deserialize(deserializer)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
quote! {
|
||||
#input
|
||||
#impls
|
||||
}
|
||||
.into()
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
use context_deserialize::{context_deserialize, ContextDeserialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[test]
|
||||
fn test_context_deserialize_derive() {
|
||||
type TestContext = ();
|
||||
|
||||
#[context_deserialize(TestContext)]
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct Test {
|
||||
field: String,
|
||||
}
|
||||
|
||||
let test = Test {
|
||||
field: "test".to_string(),
|
||||
};
|
||||
let serialized = serde_json::to_string(&test).unwrap();
|
||||
let deserialized =
|
||||
Test::context_deserialize(&mut serde_json::Deserializer::from_str(&serialized), ())
|
||||
.unwrap();
|
||||
assert_eq!(test, deserialized);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_context_deserialize_derive_multiple_types() {
|
||||
#[allow(dead_code)]
|
||||
struct TestContext1(u64);
|
||||
#[allow(dead_code)]
|
||||
struct TestContext2(String);
|
||||
|
||||
// This will derive:
|
||||
// - ContextDeserialize<TestContext1> for Test
|
||||
// - ContextDeserialize<TestContext2> for Test
|
||||
// by just leveraging the Deserialize impl
|
||||
#[context_deserialize(TestContext1, TestContext2)]
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct Test {
|
||||
field: String,
|
||||
}
|
||||
|
||||
let test = Test {
|
||||
field: "test".to_string(),
|
||||
};
|
||||
let serialized = serde_json::to_string(&test).unwrap();
|
||||
let deserialized = Test::context_deserialize(
|
||||
&mut serde_json::Deserializer::from_str(&serialized),
|
||||
TestContext1(1),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(test, deserialized);
|
||||
|
||||
let deserialized = Test::context_deserialize(
|
||||
&mut serde_json::Deserializer::from_str(&serialized),
|
||||
TestContext2("2".to_string()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(test, deserialized);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_context_deserialize_derive_bound() {
|
||||
use std::fmt::Debug;
|
||||
|
||||
struct TestContext;
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct Inner {
|
||||
value: u64,
|
||||
}
|
||||
|
||||
#[context_deserialize(
|
||||
TestContext,
|
||||
bound = "T: Serialize + for<'a> Deserialize<'a> + Debug + PartialEq"
|
||||
)]
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct Wrapper<T> {
|
||||
inner: T,
|
||||
}
|
||||
|
||||
let val = Wrapper {
|
||||
inner: Inner { value: 42 },
|
||||
};
|
||||
|
||||
let serialized = serde_json::to_string(&val).unwrap();
|
||||
let deserialized = Wrapper::<Inner>::context_deserialize(
|
||||
&mut serde_json::Deserializer::from_str(&serialized),
|
||||
TestContext,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(val, deserialized);
|
||||
}
|
||||
Reference in New Issue
Block a user