The format is based on Keep a Changelog.
- chore(deps): bump syn from 1.0 to 2.0 (#60)
- chore(deps): bump primitives types from 0.12.0 to 0.13.1 (#61)
- chore(deps): chore(deps): bump derive_more from 0.99 to 1.0.0 (#62)
Yanked because primitives-types
is re-exported from this crate and thus is a breaking change.
Useful visitor errors can be hidden in some cases when a skip_decoding
error is also emitted. This patch release fixes that.
- Don't hide visitor error when a skip_decode error is also emitted (#58)
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.
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
Composite
type handed back in the visitor'svisit_composite()
method now exposes the name and path of the composite type being decoded, if one was provided.
scale-info
was still being pulled in viascale-type-resolver
; this has now been fixed
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:
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;
// ...
}
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.
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.
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.
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
DecodeAsType
a proper super-trait ofIntoVisitor
, meaning it can be used anywhereIntoVisitor
is. Previously, usingDecodeAsType
in some places also required that you add a bound likeB: IntoVisitor, <B::Visitor as Visitor>::Error: Into<scale_decode::Error
, ie theError
type needed to explicitly be declared as convertible in the way thatDecodeAsType
requires. - 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
.
- Change how compact encoding is handled:
visit_compact_*
functions are removed from theVisitor
trait, 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 + Display
onno_std
orError
onstd
.Error::custom()
now accepts anything implementing these traits rather than depending onInto<Error>
(#31).
- Add support for
no_std
(+alloc) builds (#26). Thankyou @haerdib!
- Change
DecodeAsFields
again; remove the generic iterator parameter and use&mut dyn FieldIter
instead. This Simplifies the call signatures in a bunch of places and is consistent with howscale-encode
works. - Use
smallvec
instead of our own stack allocated vec.
- Change
DecodeAsFields
to accept an iterator of fields to decode into. This makes it more flexible in what it is able to decode. This bleeds into various other types, which inherit a generic parameter to represent this iterator that is used to drive decoding.
This release shifts scale-decode
to being a mirror of a new scale-encode
crate, and:
- Adds a new
IntoVisitor
trait that types can implement if there is aVisitor
which can be used to decode into them. - Adds a new
DecodeAsType
trait to mirror theEncodeAsType
trait there; any type that implementsIntoVisitor
automatically implementsDecodeAsType
. - Adds a new
DecodeAsFields
trait to mirrorEncodeAsFields
, implemented for tuple and struct types. - Moves the
Visitor
trait into a sub module and re-works the interface to allow zero copy decoding, allow more concise implementations of it, and provide a fallback escape hatch to allow for more arbitraryDecodeAsType
implementations from it. - Implements
DecodeAsType
(viaVisitor
andIntoVisitor
impls) andDecodeAsFields
on common types. - Adds a
DecodeAsType
derive macro to auto-generate impls on custom struct and enum types.
Any Visitor
impls will need to be updated to use the refined Visitor
trait; this should be fairly mechanical
(check out the examples and follow the compiler guidance to do this). Otherwise, the rest of the changes are
additive and just make it easier to implement this trait and obtain a DecodeAsType
implementation, if desired.
- Add DecodeAsType backed by Visitor impls for standard types. (#11)
This release removes bitvec
and the 32bit feature flag needed to play nicely with it and leans on scale-bits
instead
to decode bit sequences. We add a CI check to ensure that it can be compiled to WASM.
- Use scale-bits to handle bit sequences (#5
This release makes the following changes:
- All
visit_
functions are now handed aTypeId
too, which is just a wrapper around au32
corresponding to the type being decoded in the given PortableRegistry. Useful if you'd like to look up more details about the type in the registry or just store the ID somewhere. visit_compact_
functions are now handed avisitor::Compact
struct which one can obtain the compact encoded value from, or view the path to the compact encoded value via a.locations()
method, in case the compact value is actually nested within named/unnamed structs. The TypeId provided is always the outermost type of the Compact value, and so one can also discover this information by manual traversal (but since we have to traverse anyway..).- The
Variant
type has been simplified and largely just allows access to the underlyingComposite
type to decode. - The
Composite
type now provides direct access to the (yet-to-be-decoded)fields
, and offers separatedecode_item
anddecode_item_with_name
methods to make decoding into named or unnamed shapes a little easier. Visitor
related types are now exported directly from thevisitor
module rather than avisitor::types
module.- Lifetimes have been made more precise to avoid unnecessary lifetime related errors.
- TypeIds, more info for compact encoded values and tidy up (#1)
- Remove
remaining()
functions from visitor structs; thelen()
calls now return the items left to decode. - Fix clippy and doc links.
Initial release containging a decode
function, Visitor
trait to implement, and an
IgnoreVisitor
impl to skip over SCALE bytes instead of decode them into some type.