consensus_encoding: Loosen serde_as_consensus trait bounds
What changed, and why it matters
This commit relaxes the rules for which Rust types can be converted to and from serde serialization formats. Previously, a type had to support both encoding and decoding to be used in either direction. Now, types only need to support the direction actually being used. This is a straightforward API improvement with no security-relevant behavior change.
No security action required. Treat as a normal API ergonomics improvement.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change loosens trait bounds in serde_as_consensus helpers from T: Encode + Decode to T: Encode for serialization paths and T: Decode for deserialization paths. This is a non-breaking relaxation of bounds and does not alter serialization logic, parsing, or validation. It merely enables types that are only encodable or only decodable to use these helpers.
Changed components
consensus_encoding/src/serde_as_consensus.rsInspect captured patch +12 / −12
diff --git a/consensus_encoding/src/serde_as_consensus.rs b/consensus_encoding/src/serde_as_consensus.rs
index 32c5452a..2d7f757c 100644
--- a/consensus_encoding/src/serde_as_consensus.rs
+++ b/consensus_encoding/src/serde_as_consensus.rs
@@ -28,7 +28,7 @@ use crate::{Decode, Encode, Encoder as _};
/// * `S` - The serializer type
pub fn serialize<T, S>(value: &T, s: S) -> Result<S::Ok, S::Error>
where
- T: Encode + Decode,
+ T: Encode,
S: Serializer,
{
if s.is_human_readable() {
@@ -62,7 +62,7 @@ where
/// * `D` - The deserializer type
pub fn deserialize<'d, T, D>(d: D) -> Result<T, D::Error>
where
- T: Encode + Decode,
+ T: Decode,
D: Deserializer<'d>,
{
if d.is_human_readable() {
@@ -79,7 +79,7 @@ where
impl<'de, T> serde::de::Visitor<'de> for BytesVisitor<T>
where
- T: Encode + Decode,
+ T: Decode,
{
type Value = T;
@@ -161,12 +161,12 @@ pub mod opt {
#[allow(clippy::ref_option)] // API forced by serde.
pub fn serialize<T, S>(t: &Option<T>, s: S) -> Result<S::Ok, S::Error>
where
- T: Encode + Decode,
+ T: Encode,
S: Serializer,
{
struct AsConsensus<'a, T>(&'a T);
- impl<T: Encode + Decode> serde::Serialize for AsConsensus<'_, T> {
+ impl<T: Encode> serde::Serialize for AsConsensus<'_, T> {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
super::serialize(self.0, s)
}
@@ -180,14 +180,14 @@ pub mod opt {
pub fn deserialize<'d, T, D>(d: D) -> Result<Option<T>, D::Error>
where
- T: Encode + Decode,
+ T: Decode,
D: Deserializer<'d>,
{
struct OptVisitor<X>(PhantomData<X>);
impl<'de, X> de::Visitor<'de> for OptVisitor<X>
where
- X: Encode + Decode,
+ X: Decode,
{
type Value = Option<X>;
@@ -266,12 +266,12 @@ pub mod vec {
pub fn serialize<T, S>(v: &[T], s: S) -> Result<S::Ok, S::Error>
where
- T: Encode + Decode,
+ T: Encode,
S: Serializer,
{
struct AsConsensus<'a, T>(&'a T);
- impl<T: Encode + Decode> serde::Serialize for AsConsensus<'_, T> {
+ impl<T: Encode> serde::Serialize for AsConsensus<'_, T> {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
super::serialize(self.0, s)
}
@@ -282,14 +282,14 @@ pub mod vec {
pub fn deserialize<'d, T, D>(d: D) -> Result<Vec<T>, D::Error>
where
- T: Encode + Decode,
+ T: Decode,
D: Deserializer<'d>,
{
struct VecVisitor<X>(PhantomData<X>);
impl<'de, X> de::Visitor<'de> for VecVisitor<X>
where
- X: Encode + Decode,
+ X: Decode,
{
type Value = Vec<X>;
@@ -305,7 +305,7 @@ pub mod vec {
impl<'de, X> de::Deserialize<'de> for Wrap<X>
where
- X: Encode + Decode,
+ X: Decode,
{
fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
super::deserialize::<X, D>(d).map(Wrap)
Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.