Releases: paritytech/scale-decode
v0.16.0
v0.15.0
0.15.0 - 2024-11-08
This release makes scale-decode entirely no_std which is now using core::error::Error instead of std::error::Error as it was using before behind
the std feature. Because of that the std feature is now removed and the MSRV is bumped to 1.81.0.
v0.13.2
v0.13.0
0.13.0 - 2023-05-15
This minor release avoids a couple of panics in the case of invalid bytes being interpreted as BitVecs or strings.
A small API change was made to accommodate this, such that the Str::bytes_after now returns a result rather than just the bytes.
Fixed
v0.12.0
0.12.0 - 2024-04-29
Update the scale-type-resolver dependency to 0.2.0 (and bump scale-bits for the same reason).
The main changes here are:
- Type IDs are now passed by value rather than reference.
- The
Compositetype handed back in the visitor'svisit_composite()method now exposes the name and path of the composite type being decoded, if one was provided.
v0.11.1
v0.11.0
0.11.0 - 2023-02-09
Up until now, this crate depended heavily on scale_info to provide the type information that we used to drive our decoding of types. This release removes the explicit dependency on scale-info, and instead depends on scale-type-resolver, which offers a generic TypeResolver trait whose implementations are able to provide the information needed to decode types (see this PR for more details). So now, the traits and types in scale-decode have been made generic over which TypeResolver is used to help decode things. scale-info::PortableRegistry is one such implementation of TypeResolver, and so can continue to be used in a similar way to before.
The main breaking changes are:
Visitor trait
The scale_decode::Visitor trait now has an additional associated type, TypeResolver.
The simplest change to recover the previous behaviour is to just continue to use scale_info::PortableRegistry for this task, as was the case implicitly before:
struct MyVisitor;
impl Visitor for MyVisitor {
// ...
type TypeResolver = scale_info::PortableRegistry;
// ...
}A better change is to make your Visitor impls generic over what is used to resolve types unless you need a specific resolver:
struct MyVisitor<R>(PhantomData<R>);
impl <R> MyVisitor<R> {
pub fn new() -> Self {
Self(PhantomData)
}
}
impl <R: TypeResolver> Visitor for MyVisitor<R> {
// ...
type TypeResolver = R;
// ...
}IntoVisitor trait
scale_decode::IntoVisitor is implemented on all types that have an associated Visitor that we can use to decode it. It used to look like this:
pub trait IntoVisitor {
type Visitor: for<'scale, 'resolver> visitor::Visitor<
Value<'scale, 'resolver> = Self,
Error = Error,
>;
fn into_visitor() -> Self::Visitor;
}Now it looks like this:
pub trait IntoVisitor {
type AnyVisitor<R: TypeResolver>: for<'scale, 'resolver> visitor::Visitor<
Value<'scale, 'resolver> = Self,
Error = Error,
TypeResolver = R,
>;
fn into_visitor<R: TypeResolver>() -> Self::AnyVisitor<R>;
}What this means is that if you want to implement IntoVisitor for some type, then your Visitor must be able to accept any valid TypeResolver. This allows DecodeAsType to also be generic over which TypeResolver is provided.
DecodeAsType
This trait previously was specific to scale_info::PortableRegistry and looked something like this:
pub trait DecodeAsType: Sized + IntoVisitor {
fn decode_as_type<R: TypeResolver>(
input: &mut &[u8],
type_id: u32,
types: &scale_info::PortableRegistry,
) -> Result<Self, Error> {
// ...
}Now, it is generic over which type resolver to use (and as a side effect, requires a reference to the type_id now, because it may not be Copy any more):
pub trait DecodeAsType: Sized + IntoVisitor {
fn decode_as_type<R: TypeResolver>(
input: &mut &[u8],
type_id: &R::TypeId,
types: &R,
) -> Result<Self, Error> {
// ...
}This is automatically implemented for all types which implement IntoVisitor, as before.
Composite and Variant paths
Mostly, the changes just exist to make things generic over the TypeResolver. One consequence of this is that Composite and Variant types no longer know their path, because currently TypeResolver doesn't provide that information (since it's not necessary to the actual encoding/decoding of types). If there is demand for this, we can consider allowing TypeResolver impls to optionally provide these extra details.
v0.10.0
0.10.0 - 2023-11-10
This release changes IntoVisitor to require that the corresponding Visitor implements scale_decode::Error, rather than allowing the error to be anything that can be converted into a scale_decode::Error. This has the following advantages:
- It makes
DecodeAsTypea proper super-trait ofIntoVisitor, meaning it can be used anywhereIntoVisitoris. Previously, usingDecodeAsTypein some places also required that you add a bound likeB: IntoVisitor, <B::Visitor as Visitor>::Error: Into<scale_decode::Error, ie theErrortype needed to explicitly be declared as convertible in the way thatDecodeAsTyperequires. - It simplifies the code.
- It makes it a bit easier to understand how to correctly make a type implement
DecodeAsType.
The main drawback is that if your Visitor implementation doesn't have Error = scale_decode::Error, then it can no longer be used with IntoVisitor. To work around this, a new adapter type, scale_decode::visitor::VisitorWithCrateError(your_visitor) has been added; any visitor wrapped in this type whose error implements Into<scale_decode::Error> will now implement Visitor with Error = scale_decode::Error.
v0.9.0
0.9.0 - 2023-08-02
- Change how compact encoding is handled:
visit_compact_*functions are removed from theVisitortrait, and
compact encoding is now handled recursively and should now work in more cases (such as nested structs with compact
encoded values inside) (#32). - Improve custom error handling: custom errors now require
Debug + Displayonno_stdorErroronstd.
Error::custom()now accepts anything implementing these traits rather than depending onInto<Error>
(#31).