From fdfa0e64b5123af2cdabad6c9e9be96736254062 Mon Sep 17 00:00:00 2001 From: haerdib Date: Tue, 20 Jun 2023 09:06:08 +0200 Subject: [PATCH 01/26] make it no-std compatible add rust toolchain file add rust toolchain file reorder imports fix cargo check fix rust ci fix cargo check fix ci fix clippy fix bits features add From impl fix scale bits fix import scale bits remove unnecessary changes make feature error_in_core no_std only --- .github/workflows/rust.yml | 28 +++++++++++++++ scale-encode/Cargo.toml | 15 ++++---- scale-encode/src/error/context.rs | 6 ++-- scale-encode/src/error/mod.rs | 44 +++++++++++++---------- scale-encode/src/impls/bits.rs | 1 + scale-encode/src/impls/composite.rs | 9 +++-- scale-encode/src/impls/mod.rs | 36 ++++++++++++------- scale-encode/src/impls/primitive_types.rs | 3 +- scale-encode/src/impls/variant.rs | 1 + scale-encode/src/lib.rs | 31 +++++++++------- 10 files changed, 119 insertions(+), 55 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index a9c89d7..7974383 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -71,6 +71,34 @@ jobs: # we run tests using BitVec which doesn't. args: --all-features --target wasm32-unknown-unknown + + no_std: + name: Check no_std build + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + # no_std version currently needs nightly due to error_in_core feature + - name: Install Rust nightly toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + target: aarch64-unknown-none + override: true + + - name: Rust Cache + uses: Swatinem/rust-cache@v1.3.0 + + - name: Check no_std build + uses: actions-rs/cargo@v1.0.3 + with: + command: check + # The aarch64-unknown-none doesn't support `std`, so this + # will fail if the crate is not no_std compatible. + args: --no-default-features --target aarch64-unknown-none --features bits,derive,primitive-types + fmt: name: Cargo fmt runs-on: ubuntu-latest diff --git a/scale-encode/Cargo.toml b/scale-encode/Cargo.toml index 81e16cf..5524b70 100644 --- a/scale-encode/Cargo.toml +++ b/scale-encode/Cargo.toml @@ -14,22 +14,25 @@ keywords.workspace = true include.workspace = true [features] -default = ["derive", "primitive-types", "bits"] +default = ["std", "derive", "primitive-types", "bits"] -# Include the derive proc macro +# Activates std feature. +std = ["scale-info/std"] + +# Include the derive proc macro. derive = ["dep:scale-encode-derive"] -# impls for key primitive-types +# impls for key primitive-types. primitive-types = ["dep:primitive-types"] # impls for Bits. bits = ["dep:scale-bits"] [dependencies] -scale-info = { version = "2.7.0", features = ["bit-vec"] } -thiserror = "1.0.37" +scale-info = { version = "2.7.0", default-features = false, features = ["bit-vec"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "full"] } -scale-bits = { version = "0.3.0", default-features = false, features = ["scale-info"], optional = true } +derive_more = { version = "0.99.5" } +scale-bits = { default-features = false, features = ["scale-info"], git = "https://github.com/haerdib/scale-bits.git", branch = "bh/no-std", optional = true } scale-encode-derive = { workspace = true, optional = true } primitive-types = { version = "0.12.0", optional = true, default-features = false } smallvec = "1.10.0" diff --git a/scale-encode/src/error/context.rs b/scale-encode/src/error/context.rs index a209801..f51d881 100644 --- a/scale-encode/src/error/context.rs +++ b/scale-encode/src/error/context.rs @@ -16,7 +16,7 @@ //! This module provides a [`Context`] type, which tracks the path //! that we're attempting to encode to aid in error reporting. -use std::borrow::Cow; +use alloc::{borrow::Cow, vec::Vec}; /// A cheaply clonable opaque context which allows us to track the current /// location into a type that we're trying to encode, to aid in @@ -55,8 +55,8 @@ impl<'a> Path<'a> { } } -impl<'a> std::fmt::Display for Path<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl<'a> core::fmt::Display for Path<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { for (idx, loc) in self.0.iter().enumerate() { if idx != 0 { f.write_str(".")?; diff --git a/scale-encode/src/error/mod.rs b/scale-encode/src/error/mod.rs index 84a05c0..251077b 100644 --- a/scale-encode/src/error/mod.rs +++ b/scale-encode/src/error/mod.rs @@ -16,13 +16,21 @@ //! An error that is emitted whenever some encoding fails. mod context; -use std::borrow::Cow; -use std::fmt::Display; - pub use context::{Context, Location}; +use alloc::{borrow::Cow, boxed::Box, string::String}; +use core::fmt::Display; +use derive_more::From; + +// Error in core is currently only available as nightly feature. Therefore, we +// differentiate here between std and no_std environments. +#[cfg(not(feature = "std"))] +use core::error::Error as StdError; +#[cfg(feature = "std")] +use std::error::Error as StdError; + /// An error produced while attempting to encode some type. -#[derive(Debug, thiserror::Error)] +#[derive(Debug, From)] pub struct Error { context: Context, kind: ErrorKind, @@ -83,21 +91,19 @@ impl Error { } impl Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let path = self.context.path(); let kind = &self.kind; - write!(f, "Error at {path}: {kind}") + write!(f, "Error at {path}: {kind:?}") } } /// The underlying nature of the error. -#[derive(Debug, thiserror::Error)] +#[derive(Debug)] pub enum ErrorKind { /// Cannot find a given type. - #[error("Cannot find type with ID {0}")] TypeNotFound(u32), /// Cannot encode the actual type given into the target type ID. - #[error("Cannot encode {actual:?} into type with ID {expected}")] WrongShape { /// The actual kind we have to encode actual: Kind, @@ -105,7 +111,6 @@ pub enum ErrorKind { expected: u32, }, /// The types line up, but the expected length of the target type is different from the length of the input value. - #[error("Cannot encode to type; expected length {expected_len} but got length {actual_len}")] WrongLength { /// Length we have actual_len: usize, @@ -113,7 +118,6 @@ pub enum ErrorKind { expected_len: usize, }, /// We cannot encode the number given into the target type; it's out of range. - #[error("Number {value} is out of range for target type {expected}")] NumberOutOfRange { /// A string represenatation of the numeric value that was out of range. value: String, @@ -121,7 +125,6 @@ pub enum ErrorKind { expected: u32, }, /// Cannot find a variant with a matching name on the target type. - #[error("Variant {name} does not exist on type with ID {expected}")] CannotFindVariant { /// Variant name we can't find in the expected type. name: String, @@ -129,21 +132,25 @@ pub enum ErrorKind { expected: u32, }, /// Cannot find a field on our source type that's needed for the target type. - #[error("Field {name} does not exist in our source struct")] CannotFindField { /// Name of the field which was not provided. name: String, }, /// A custom error. - #[error("Custom error: {0}")] Custom(CustomError), } -type CustomError = Box; +impl From for ErrorKind { + fn from(err: CustomError) -> ErrorKind { + ErrorKind::Custom(err) + } +} + +type CustomError = Box; /// The kind of type that we're trying to encode. #[allow(missing_docs)] -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, derive_more::Display)] pub enum Kind { Struct, Tuple, @@ -160,12 +167,13 @@ pub enum Kind { mod test { use super::*; - #[derive(thiserror::Error, Debug)] + #[derive(Debug, derive_more::Display)] enum MyError { - #[error("Foo!")] Foo, } + impl StdError for MyError {} + #[test] fn custom_error() { // Just a compile-time check that we can ergonomically provide an arbitrary custom error: diff --git a/scale-encode/src/impls/bits.rs b/scale-encode/src/impls/bits.rs index 83ee940..b36cb98 100644 --- a/scale-encode/src/impls/bits.rs +++ b/scale-encode/src/impls/bits.rs @@ -17,6 +17,7 @@ use crate::{ error::{Error, ErrorKind, Kind}, EncodeAsType, }; +use alloc::vec::Vec; use scale_info::TypeDef; impl EncodeAsType for scale_bits::Bits { diff --git a/scale-encode/src/impls/composite.rs b/scale-encode/src/impls/composite.rs index e8ee818..92887ee 100644 --- a/scale-encode/src/impls/composite.rs +++ b/scale-encode/src/impls/composite.rs @@ -17,8 +17,13 @@ use crate::{ error::{Error, ErrorKind, Kind, Location}, EncodeAsFields, EncodeAsType, Field, FieldIter, }; +use alloc::{string::ToString, vec::Vec}; use scale_info::{PortableRegistry, TypeDef}; -use std::collections::HashMap; + +#[cfg(not(feature = "std"))] +use alloc::collections::BTreeMap as MapType; +#[cfg(feature = "std")] +use std::collection::HashMap as MapType; /// This type represents named or unnamed composite values, and can be used /// to help generate `EncodeAsType` impls. It's primarily used by the exported @@ -156,7 +161,7 @@ where // then encode to the target type by matching the names. If fields are // named, we don't even mind if the number of fields doesn't line up; // we just ignore any fields we provided that aren't needed. - let source_fields_by_name: HashMap<&str, &dyn EncodeAsType> = vals_iter + let source_fields_by_name: MapType<&str, &dyn EncodeAsType> = vals_iter .map(|(name, val)| (name.unwrap_or(""), val)) .collect(); diff --git a/scale-encode/src/impls/mod.rs b/scale-encode/src/impls/mod.rs index 96624b4..cae2fa8 100644 --- a/scale-encode/src/impls/mod.rs +++ b/scale-encode/src/impls/mod.rs @@ -25,20 +25,30 @@ mod variant; pub use composite::Composite; pub use variant::Variant; -use crate::error::{Error, ErrorKind, Kind}; -use crate::{EncodeAsFields, EncodeAsType, FieldIter}; +use crate::{ + error::{Error, ErrorKind, Kind}, + EncodeAsFields, EncodeAsType, FieldIter, +}; +use alloc::{ + borrow::ToOwned, + boxed::Box, + collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}, + rc::Rc, + string::{String, ToString}, + sync::Arc, + vec::Vec, +}; use codec::{Compact, Encode}; -use core::num::{ - NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroU128, NonZeroU16, - NonZeroU32, NonZeroU64, NonZeroU8, +use core::{ + marker::PhantomData, + num::{ + NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroU128, NonZeroU16, + NonZeroU32, NonZeroU64, NonZeroU8, + }, + ops::{Range, RangeInclusive}, + time::Duration, }; -use core::ops::{Range, RangeInclusive}; use scale_info::{PortableRegistry, TypeDef, TypeDefPrimitive}; -use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}; -use std::marker::PhantomData; -use std::rc::Rc; -use std::sync::Arc; -use std::time::Duration; impl EncodeAsType for bool { fn encode_as_type_to( @@ -102,7 +112,7 @@ where } } -impl<'a, T> EncodeAsType for std::borrow::Cow<'a, T> +impl<'a, T> EncodeAsType for alloc::borrow::Cow<'a, T> where T: 'a + EncodeAsType + ToOwned + ?Sized, { @@ -943,7 +953,7 @@ mod test { #[test] fn hxxx_types_roundtrip_ok() { - use ::primitive_types::{H128, H160, H256, H384, H512, H768}; + use super::primitive_types::{H128, H160, H256, H384, H512, H768}; // Check that Hxxx types roundtirp to themselves or to byte sequences fn test_hxxx(bytes: impl IntoIterator + Clone) { diff --git a/scale-encode/src/impls/primitive_types.rs b/scale-encode/src/impls/primitive_types.rs index 737bc39..176d5db 100644 --- a/scale-encode/src/impls/primitive_types.rs +++ b/scale-encode/src/impls/primitive_types.rs @@ -14,7 +14,8 @@ // limitations under the License. use crate::{error::Error, EncodeAsType}; -use primitive_types::{H128, H160, H256, H384, H512, H768}; +use alloc::vec::Vec; +pub use primitive_types::{H128, H160, H256, H384, H512, H768}; macro_rules! impl_encode { ($($ty:ty),*) => {$( diff --git a/scale-encode/src/impls/variant.rs b/scale-encode/src/impls/variant.rs index c29e671..4792142 100644 --- a/scale-encode/src/impls/variant.rs +++ b/scale-encode/src/impls/variant.rs @@ -17,6 +17,7 @@ use crate::{ error::{Error, ErrorKind, Kind}, EncodeAsFields, EncodeAsType, Field, }; +use alloc::{string::ToString, vec::Vec}; use codec::Encode; use scale_info::{PortableRegistry, TypeDef}; diff --git a/scale-encode/src/lib.rs b/scale-encode/src/lib.rs index 5a7597d..a3f7ff8 100644 --- a/scale-encode/src/lib.rs +++ b/scale-encode/src/lib.rs @@ -13,6 +13,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#![cfg_attr(not(feature = "std"), no_std, feature(error_in_core))] + /*! `parity-scale-codec` provides an `Encode` trait which allows types to SCALE encode themselves based on their shape. This crate builds on this, and allows types to encode themselves based on [`scale_info`] type information. It @@ -149,6 +151,10 @@ pub use error::Error; pub use crate::impls::{Composite, Variant}; pub use scale_info::PortableRegistry; +extern crate alloc; + +use alloc::vec::Vec; + /// This trait signals that some static type can possibly be SCALE encoded given some /// `type_id` and [`PortableRegistry`] which dictates the expected encoding. pub trait EncodeAsType { @@ -232,18 +238,6 @@ impl<'a> Field<'a> { pub trait FieldIter<'a>: Iterator> {} impl<'a, T> FieldIter<'a> for T where T: Iterator> {} -#[cfg(test)] -mod test { - use super::*; - - // Confirm object safety of EncodeAsFields; we want this. - // (doesn't really need to run; compile time only.) - #[test] - fn is_object_safe() { - fn _foo(_input: Box) {} - } -} - /// The `EncodeAsType` derive macro can be used to implement `EncodeAsType` /// on structs and enums whose fields all implement `EncodeAsType`. /// @@ -313,3 +307,16 @@ mod test { /// behaviour and provide your own trait bounds instead using this option. #[cfg(feature = "derive")] pub use scale_encode_derive::EncodeAsType; + +#[cfg(test)] +mod test { + use super::*; + use alloc::boxed::Box; + + // Confirm object safety of EncodeAsFields; we want this. + // (doesn't really need to run; compile time only.) + #[test] + fn is_object_safe() { + fn _foo(_input: Box) {} + } +} From 26b47f8bb960f5ac313db4f1f1aa9dd8446f3438 Mon Sep 17 00:00:00 2001 From: haerdib Date: Tue, 20 Jun 2023 17:03:16 +0200 Subject: [PATCH 02/26] use scale-bits from crates --- scale-encode/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scale-encode/Cargo.toml b/scale-encode/Cargo.toml index 5524b70..938417c 100644 --- a/scale-encode/Cargo.toml +++ b/scale-encode/Cargo.toml @@ -32,7 +32,7 @@ bits = ["dep:scale-bits"] scale-info = { version = "2.7.0", default-features = false, features = ["bit-vec"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "full"] } derive_more = { version = "0.99.5" } -scale-bits = { default-features = false, features = ["scale-info"], git = "https://github.com/haerdib/scale-bits.git", branch = "bh/no-std", optional = true } +scale-bits = { version = "0.4.0", default-features = false, features = ["scale-info"], optional = true } scale-encode-derive = { workspace = true, optional = true } primitive-types = { version = "0.12.0", optional = true, default-features = false } smallvec = "1.10.0" From 8ddb735977e352f9cbf58d97d1a1eb0d29429a16 Mon Sep 17 00:00:00 2001 From: haerdib Date: Tue, 20 Jun 2023 17:50:28 +0200 Subject: [PATCH 03/26] fix hashmap import --- scale-encode/src/impls/composite.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scale-encode/src/impls/composite.rs b/scale-encode/src/impls/composite.rs index 92887ee..6136136 100644 --- a/scale-encode/src/impls/composite.rs +++ b/scale-encode/src/impls/composite.rs @@ -23,7 +23,7 @@ use scale_info::{PortableRegistry, TypeDef}; #[cfg(not(feature = "std"))] use alloc::collections::BTreeMap as MapType; #[cfg(feature = "std")] -use std::collection::HashMap as MapType; +use std::collections::HashMap as MapType; /// This type represents named or unnamed composite values, and can be used /// to help generate `EncodeAsType` impls. It's primarily used by the exported From c75b767e379efa8ff3cd19dfb99be88b6f8071ea Mon Sep 17 00:00:00 2001 From: haerdib Date: Tue, 20 Jun 2023 18:05:28 +0200 Subject: [PATCH 04/26] remove derive from no-std fix derive input remove -no features from stable toolchain ci do not check tests test CI --- .github/workflows/rust.yml | 9 +-------- scale-encode/Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 7974383..0d95f1b 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -39,12 +39,6 @@ jobs: command: check args: --all-targets --all-features --workspace - - name: Check no features - uses: actions-rs/cargo@v1.0.3 - with: - command: check - args: --all-targets --no-default-features --workspace - wasm: name: Check WASM compatibility runs-on: ubuntu-latest @@ -71,7 +65,6 @@ jobs: # we run tests using BitVec which doesn't. args: --all-features --target wasm32-unknown-unknown - no_std: name: Check no_std build runs-on: ubuntu-latest @@ -97,7 +90,7 @@ jobs: command: check # The aarch64-unknown-none doesn't support `std`, so this # will fail if the crate is not no_std compatible. - args: --no-default-features --target aarch64-unknown-none --features bits,derive,primitive-types + args: +nightly --no-default-features --features bits,primitive-types fmt: name: Cargo fmt diff --git a/scale-encode/Cargo.toml b/scale-encode/Cargo.toml index 938417c..f224c54 100644 --- a/scale-encode/Cargo.toml +++ b/scale-encode/Cargo.toml @@ -19,8 +19,8 @@ default = ["std", "derive", "primitive-types", "bits"] # Activates std feature. std = ["scale-info/std"] -# Include the derive proc macro. -derive = ["dep:scale-encode-derive"] +# Include the derive proc macro. This is only availbale in std. +derive = ["dep:scale-encode-derive", "std"] # impls for key primitive-types. primitive-types = ["dep:primitive-types"] From fec8ef7bb8930d7fa8e2f4646bc1fef3fa9d42c1 Mon Sep 17 00:00:00 2001 From: haerdib Date: Tue, 20 Jun 2023 18:55:29 +0200 Subject: [PATCH 05/26] remove obsolete full feature remove nightly add verbose flag fix ci fix verbose test ci debug use rustup show ci should fail now test stop testing and submit --- .github/workflows/rust.yml | 14 +++++++------- scale-encode/Cargo.toml | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 0d95f1b..4a33740 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -72,14 +72,14 @@ jobs: - name: Checkout sources uses: actions/checkout@v2 + # Set default target arch to ensure the toolchain for no-std + # environments is used. + - name: Rust create rust-toolchain.toml + run: echo -e "[toolchain]\nchannel = \"nightly\"\ntargets = [\"aarch64-unknown-none\"]\nprofile = \"minimal\"" > rust-toolchain.toml + # no_std version currently needs nightly due to error_in_core feature - name: Install Rust nightly toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: nightly - target: aarch64-unknown-none - override: true + run: rustup show - name: Rust Cache uses: Swatinem/rust-cache@v1.3.0 @@ -90,7 +90,7 @@ jobs: command: check # The aarch64-unknown-none doesn't support `std`, so this # will fail if the crate is not no_std compatible. - args: +nightly --no-default-features --features bits,primitive-types + args: --no-default-features --features bits,primitive-types fmt: name: Cargo fmt diff --git a/scale-encode/Cargo.toml b/scale-encode/Cargo.toml index f224c54..501c961 100644 --- a/scale-encode/Cargo.toml +++ b/scale-encode/Cargo.toml @@ -30,7 +30,7 @@ bits = ["dep:scale-bits"] [dependencies] scale-info = { version = "2.7.0", default-features = false, features = ["bit-vec"] } -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "full"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } derive_more = { version = "0.99.5" } scale-bits = { version = "0.4.0", default-features = false, features = ["scale-info"], optional = true } scale-encode-derive = { workspace = true, optional = true } @@ -41,7 +41,7 @@ smallvec = "1.10.0" bitvec = "1.0.1" scale-info = { version = "2.3.0", features = ["bit-vec", "derive"] } scale-encode-derive = { workspace = true } -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "full", "bit-vec"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "bit-vec"] } trybuild = "1.0.72" # enable scale-info feature for testing: primitive-types = { version = "0.12.0", default-features = false, features = ["scale-info"] } From 3723e0671eb5786e787cfc4a01c5461bf143afd6 Mon Sep 17 00:00:00 2001 From: haerdib Date: Wed, 21 Jun 2023 09:37:43 +0200 Subject: [PATCH 06/26] move pub use context back below --- scale-encode/src/error/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scale-encode/src/error/mod.rs b/scale-encode/src/error/mod.rs index 251077b..3443fa6 100644 --- a/scale-encode/src/error/mod.rs +++ b/scale-encode/src/error/mod.rs @@ -16,8 +16,6 @@ //! An error that is emitted whenever some encoding fails. mod context; -pub use context::{Context, Location}; - use alloc::{borrow::Cow, boxed::Box, string::String}; use core::fmt::Display; use derive_more::From; @@ -29,6 +27,8 @@ use core::error::Error as StdError; #[cfg(feature = "std")] use std::error::Error as StdError; +pub use context::{Context, Location}; + /// An error produced while attempting to encode some type. #[derive(Debug, From)] pub struct Error { From 702b892388be5f344d09cc7598c98e43d4df45af Mon Sep 17 00:00:00 2001 From: haerdib Date: Wed, 21 Jun 2023 10:00:26 +0200 Subject: [PATCH 07/26] fix ci comment --- .github/workflows/rust.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 4a33740..cc73324 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -72,8 +72,8 @@ jobs: - name: Checkout sources uses: actions/checkout@v2 - # Set default target arch to ensure the toolchain for no-std - # environments is used. + # Set default target aarch64-unknown-none because it doesn't support `std`. + # So this will fail if the crate is not no_std compatible. - name: Rust create rust-toolchain.toml run: echo -e "[toolchain]\nchannel = \"nightly\"\ntargets = [\"aarch64-unknown-none\"]\nprofile = \"minimal\"" > rust-toolchain.toml @@ -88,8 +88,6 @@ jobs: uses: actions-rs/cargo@v1.0.3 with: command: check - # The aarch64-unknown-none doesn't support `std`, so this - # will fail if the crate is not no_std compatible. args: --no-default-features --features bits,primitive-types fmt: From 83fb4eb514a163f7c3c76e46778c2e8773f24b58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bigna=20H=C3=A4rdi?= Date: Thu, 22 Jun 2023 11:03:44 +0200 Subject: [PATCH 08/26] Update scale-encode/Cargo.toml Co-authored-by: James Wilson --- scale-encode/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scale-encode/Cargo.toml b/scale-encode/Cargo.toml index 501c961..54cf4af 100644 --- a/scale-encode/Cargo.toml +++ b/scale-encode/Cargo.toml @@ -19,7 +19,7 @@ default = ["std", "derive", "primitive-types", "bits"] # Activates std feature. std = ["scale-info/std"] -# Include the derive proc macro. This is only availbale in std. +# Include the derive proc macro. This is only available in std. derive = ["dep:scale-encode-derive", "std"] # impls for key primitive-types. From 8f1228c61aed4781e39e9e680fec216a32ee292a Mon Sep 17 00:00:00 2001 From: haerdib Date: Thu, 22 Jun 2023 11:11:49 +0200 Subject: [PATCH 09/26] remove rustup show --- .github/workflows/rust.yml | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index cc73324..a500d88 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -72,14 +72,19 @@ jobs: - name: Checkout sources uses: actions/checkout@v2 - # Set default target aarch64-unknown-none because it doesn't support `std`. - # So this will fail if the crate is not no_std compatible. - - name: Rust create rust-toolchain.toml - run: echo -e "[toolchain]\nchannel = \"nightly\"\ntargets = [\"aarch64-unknown-none\"]\nprofile = \"minimal\"" > rust-toolchain.toml - - # no_std version currently needs nightly due to error_in_core feature + # no_std version currently needs nightly due to error_in_core feature - name: Install Rust nightly toolchain - run: rustup show + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + target: aarch64-unknown-none + override: true + + # Ensure cargo is run on the no_std target architecture. Specifying `--target` does not work here, + # because it automatically actives dev-dependencies, which are not no-std compatible. + - name: Rust create rust-toolchain.toml + run: echo -e "[toolchain]\nchannel = \"nightly\"\ntargets = [\"aarch64-unknown-none\"]" > rust-toolchain.toml - name: Rust Cache uses: Swatinem/rust-cache@v1.3.0 From ab19bd321c9515d7e2852e8ab195d8806ee39a86 Mon Sep 17 00:00:00 2001 From: haerdib Date: Thu, 22 Jun 2023 11:24:21 +0200 Subject: [PATCH 10/26] fix comment --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index a500d88..95345c1 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -82,7 +82,7 @@ jobs: override: true # Ensure cargo is run on the no_std target architecture. Specifying `--target` does not work here, - # because it automatically actives dev-dependencies, which are not no-std compatible. + # because it automatically activates dev-dependencies, which are not no_std compatible. - name: Rust create rust-toolchain.toml run: echo -e "[toolchain]\nchannel = \"nightly\"\ntargets = [\"aarch64-unknown-none\"]" > rust-toolchain.toml From 7f4d8e1609935d38917d3399e9201216dff30115 Mon Sep 17 00:00:00 2001 From: haerdib Date: Thu, 22 Jun 2023 11:49:37 +0200 Subject: [PATCH 11/26] remove error_in_core --- .github/workflows/rust.yml | 13 +++++++++---- scale-encode/src/error/mod.rs | 23 ++++++++++++++--------- scale-encode/src/lib.rs | 2 +- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 95345c1..a618a89 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -39,6 +39,12 @@ jobs: command: check args: --all-targets --all-features --workspace + - name: Check no features + uses: actions-rs/cargo@v1.0.3 + with: + command: check + args: --all-targets --no-default-features --workspace + wasm: name: Check WASM compatibility runs-on: ubuntu-latest @@ -72,19 +78,18 @@ jobs: - name: Checkout sources uses: actions/checkout@v2 - # no_std version currently needs nightly due to error_in_core feature - - name: Install Rust nightly toolchain + - name: Install Rust stable toolchain uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly + toolchain: stable target: aarch64-unknown-none override: true # Ensure cargo is run on the no_std target architecture. Specifying `--target` does not work here, # because it automatically activates dev-dependencies, which are not no_std compatible. - name: Rust create rust-toolchain.toml - run: echo -e "[toolchain]\nchannel = \"nightly\"\ntargets = [\"aarch64-unknown-none\"]" > rust-toolchain.toml + run: echo -e "[toolchain]\ntargets = [\"aarch64-unknown-none\"]" > rust-toolchain.toml - name: Rust Cache uses: Swatinem/rust-cache@v1.3.0 diff --git a/scale-encode/src/error/mod.rs b/scale-encode/src/error/mod.rs index 3443fa6..a9abf9f 100644 --- a/scale-encode/src/error/mod.rs +++ b/scale-encode/src/error/mod.rs @@ -20,13 +20,6 @@ use alloc::{borrow::Cow, boxed::Box, string::String}; use core::fmt::Display; use derive_more::From; -// Error in core is currently only available as nightly feature. Therefore, we -// differentiate here between std and no_std environments. -#[cfg(not(feature = "std"))] -use core::error::Error as StdError; -#[cfg(feature = "std")] -use std::error::Error as StdError; - pub use context::{Context, Location}; /// An error produced while attempting to encode some type. @@ -146,7 +139,11 @@ impl From for ErrorKind { } } -type CustomError = Box; +#[cfg(feature = "std")] +type CustomError = Box; + +#[cfg(not(feature = "std"))] +type CustomError = Box; /// The kind of type that we're trying to encode. #[allow(missing_docs)] @@ -172,7 +169,15 @@ mod test { Foo, } - impl StdError for MyError {} + #[cfg(feature = "std")] + impl std::error::Error for MyError {} + + #[cfg(not(feature = "no_std"))] + impl Into for MyError { + fn into(self) -> CustomError { + Box::new(self) + } + } #[test] fn custom_error() { diff --git a/scale-encode/src/lib.rs b/scale-encode/src/lib.rs index a3f7ff8..fdb6862 100644 --- a/scale-encode/src/lib.rs +++ b/scale-encode/src/lib.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![cfg_attr(not(feature = "std"), no_std, feature(error_in_core))] +#![cfg_attr(not(feature = "std"), no_std)] /*! `parity-scale-codec` provides an `Encode` trait which allows types to SCALE encode themselves based on their shape. From 8a664feafccb2b25bc78e828bc845c7e4e1da201 Mon Sep 17 00:00:00 2001 From: haerdib Date: Thu, 22 Jun 2023 11:52:30 +0200 Subject: [PATCH 12/26] fix feature = std --- scale-encode/src/error/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scale-encode/src/error/mod.rs b/scale-encode/src/error/mod.rs index a9abf9f..7d2989a 100644 --- a/scale-encode/src/error/mod.rs +++ b/scale-encode/src/error/mod.rs @@ -172,7 +172,7 @@ mod test { #[cfg(feature = "std")] impl std::error::Error for MyError {} - #[cfg(not(feature = "no_std"))] + #[cfg(not(feature = "std"))] impl Into for MyError { fn into(self) -> CustomError { Box::new(self) From fdc784174c5bc4e51eb69333db382fbf72046255 Mon Sep 17 00:00:00 2001 From: haerdib Date: Thu, 22 Jun 2023 12:01:27 +0200 Subject: [PATCH 13/26] remove derive_from --- scale-encode/Cargo.toml | 1 - scale-encode/src/error/mod.rs | 27 ++++++++++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/scale-encode/Cargo.toml b/scale-encode/Cargo.toml index 54cf4af..5514492 100644 --- a/scale-encode/Cargo.toml +++ b/scale-encode/Cargo.toml @@ -31,7 +31,6 @@ bits = ["dep:scale-bits"] [dependencies] scale-info = { version = "2.7.0", default-features = false, features = ["bit-vec"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -derive_more = { version = "0.99.5" } scale-bits = { version = "0.4.0", default-features = false, features = ["scale-info"], optional = true } scale-encode-derive = { workspace = true, optional = true } primitive-types = { version = "0.12.0", optional = true, default-features = false } diff --git a/scale-encode/src/error/mod.rs b/scale-encode/src/error/mod.rs index 7d2989a..b16aeeb 100644 --- a/scale-encode/src/error/mod.rs +++ b/scale-encode/src/error/mod.rs @@ -18,12 +18,11 @@ mod context; use alloc::{borrow::Cow, boxed::Box, string::String}; use core::fmt::Display; -use derive_more::From; pub use context::{Context, Location}; /// An error produced while attempting to encode some type. -#[derive(Debug, From)] +#[derive(Debug)] pub struct Error { context: Context, kind: ErrorKind, @@ -87,7 +86,7 @@ impl Display for Error { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let path = self.context.path(); let kind = &self.kind; - write!(f, "Error at {path}: {kind:?}") + write!(f, "Error at {path}: {kind}") } } @@ -139,6 +138,12 @@ impl From for ErrorKind { } } +impl Display for ErrorKind { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{self:?}") + } +} + #[cfg(feature = "std")] type CustomError = Box; @@ -147,7 +152,7 @@ type CustomError = Box; /// The kind of type that we're trying to encode. #[allow(missing_docs)] -#[derive(Copy, Clone, PartialEq, Eq, Debug, derive_more::Display)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Kind { Struct, Tuple, @@ -160,15 +165,27 @@ pub enum Kind { Number, } +impl Display for Kind { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{self:?}") + } +} + #[cfg(test)] mod test { use super::*; - #[derive(Debug, derive_more::Display)] + #[derive(Debug)] enum MyError { Foo, } + impl Display for MyError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{self:?}") + } + } + #[cfg(feature = "std")] impl std::error::Error for MyError {} From 907af1f42b6a2d7ab6d947e324b3b8d4ea217b11 Mon Sep 17 00:00:00 2001 From: haerdib Date: Thu, 22 Jun 2023 12:16:42 +0200 Subject: [PATCH 14/26] allow derive --- .github/workflows/rust.yml | 2 +- scale-encode/Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index a618a89..54a7ac0 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -98,7 +98,7 @@ jobs: uses: actions-rs/cargo@v1.0.3 with: command: check - args: --no-default-features --features bits,primitive-types + args: --no-default-features --features bits,primitive-types,derive fmt: name: Cargo fmt diff --git a/scale-encode/Cargo.toml b/scale-encode/Cargo.toml index 5514492..3060ac3 100644 --- a/scale-encode/Cargo.toml +++ b/scale-encode/Cargo.toml @@ -19,8 +19,8 @@ default = ["std", "derive", "primitive-types", "bits"] # Activates std feature. std = ["scale-info/std"] -# Include the derive proc macro. This is only available in std. -derive = ["dep:scale-encode-derive", "std"] +# Include the derive proc macro. +derive = ["dep:scale-encode-derive"] # impls for key primitive-types. primitive-types = ["dep:primitive-types"] From ed3f02b5b591198c940fad5f2e5cb0bd89ffe940 Mon Sep 17 00:00:00 2001 From: haerdib Date: Thu, 22 Jun 2023 14:29:33 +0200 Subject: [PATCH 15/26] change to BTreeMaps --- scale-encode/src/impls/composite.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/scale-encode/src/impls/composite.rs b/scale-encode/src/impls/composite.rs index 6136136..9edc148 100644 --- a/scale-encode/src/impls/composite.rs +++ b/scale-encode/src/impls/composite.rs @@ -17,14 +17,10 @@ use crate::{ error::{Error, ErrorKind, Kind, Location}, EncodeAsFields, EncodeAsType, Field, FieldIter, }; +use alloc::collections::BTreeMap; use alloc::{string::ToString, vec::Vec}; use scale_info::{PortableRegistry, TypeDef}; -#[cfg(not(feature = "std"))] -use alloc::collections::BTreeMap as MapType; -#[cfg(feature = "std")] -use std::collections::HashMap as MapType; - /// This type represents named or unnamed composite values, and can be used /// to help generate `EncodeAsType` impls. It's primarily used by the exported /// macros to do just that. @@ -161,7 +157,7 @@ where // then encode to the target type by matching the names. If fields are // named, we don't even mind if the number of fields doesn't line up; // we just ignore any fields we provided that aren't needed. - let source_fields_by_name: MapType<&str, &dyn EncodeAsType> = vals_iter + let source_fields_by_name: BTreeMap<&str, &dyn EncodeAsType> = vals_iter .map(|(name, val)| (name.unwrap_or(""), val)) .collect(); From 6f3e30dc59a41dd15de93937627c641c1ea4176b Mon Sep 17 00:00:00 2001 From: haerdib Date: Thu, 22 Jun 2023 14:31:19 +0200 Subject: [PATCH 16/26] remove pub from primitive_types --- scale-encode/src/impls/mod.rs | 2 +- scale-encode/src/impls/primitive_types.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scale-encode/src/impls/mod.rs b/scale-encode/src/impls/mod.rs index cae2fa8..7613570 100644 --- a/scale-encode/src/impls/mod.rs +++ b/scale-encode/src/impls/mod.rs @@ -953,7 +953,7 @@ mod test { #[test] fn hxxx_types_roundtrip_ok() { - use super::primitive_types::{H128, H160, H256, H384, H512, H768}; + use ::primitive_types::{H128, H160, H256, H384, H512, H768}; // Check that Hxxx types roundtirp to themselves or to byte sequences fn test_hxxx(bytes: impl IntoIterator + Clone) { diff --git a/scale-encode/src/impls/primitive_types.rs b/scale-encode/src/impls/primitive_types.rs index 176d5db..2d68eeb 100644 --- a/scale-encode/src/impls/primitive_types.rs +++ b/scale-encode/src/impls/primitive_types.rs @@ -15,7 +15,7 @@ use crate::{error::Error, EncodeAsType}; use alloc::vec::Vec; -pub use primitive_types::{H128, H160, H256, H384, H512, H768}; +use primitive_types::{H128, H160, H256, H384, H512, H768}; macro_rules! impl_encode { ($($ty:ty),*) => {$( From 9bd423cbb5a69eec2d936aebc58d3b350083b32a Mon Sep 17 00:00:00 2001 From: haerdib Date: Thu, 22 Jun 2023 14:31:36 +0200 Subject: [PATCH 17/26] add pub mod ext --- scale-encode/src/lib.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scale-encode/src/lib.rs b/scale-encode/src/lib.rs index fdb6862..651f322 100644 --- a/scale-encode/src/lib.rs +++ b/scale-encode/src/lib.rs @@ -141,6 +141,8 @@ assert_encodes_to( */ #![deny(missing_docs)] +extern crate alloc; + mod impls; pub mod error; @@ -151,7 +153,11 @@ pub use error::Error; pub use crate::impls::{Composite, Variant}; pub use scale_info::PortableRegistry; -extern crate alloc; +/// Re-exports of external crates. +pub mod ext { + #[cfg(feature = "primitive-types")] + pub use primitive_types; +} use alloc::vec::Vec; From 947c719e7c09b79c367761e218ef3d50240b7bab Mon Sep 17 00:00:00 2001 From: haerdib Date: Thu, 22 Jun 2023 14:35:24 +0200 Subject: [PATCH 18/26] make tests no-std compatible --- .github/workflows/rust.yml | 9 +++------ scale-encode/Cargo.toml | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 54a7ac0..c4d26b2 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -86,11 +86,6 @@ jobs: target: aarch64-unknown-none override: true - # Ensure cargo is run on the no_std target architecture. Specifying `--target` does not work here, - # because it automatically activates dev-dependencies, which are not no_std compatible. - - name: Rust create rust-toolchain.toml - run: echo -e "[toolchain]\ntargets = [\"aarch64-unknown-none\"]" > rust-toolchain.toml - - name: Rust Cache uses: Swatinem/rust-cache@v1.3.0 @@ -98,7 +93,9 @@ jobs: uses: actions-rs/cargo@v1.0.3 with: command: check - args: --no-default-features --features bits,primitive-types,derive + # The aarch64-unknown-none doesn't support `std`, so this + # will fail if the crate is not no_std compatible. + args: --no-default-features --target aarch64-unknown-none --features bits,primitive-types,derive fmt: name: Cargo fmt diff --git a/scale-encode/Cargo.toml b/scale-encode/Cargo.toml index 3060ac3..802ad52 100644 --- a/scale-encode/Cargo.toml +++ b/scale-encode/Cargo.toml @@ -37,8 +37,8 @@ primitive-types = { version = "0.12.0", optional = true, default-features = fals smallvec = "1.10.0" [dev-dependencies] -bitvec = "1.0.1" -scale-info = { version = "2.3.0", features = ["bit-vec", "derive"] } +bitvec = { version = "1.0.1", default-features = false } +scale-info = { version = "2.3.0", features = ["bit-vec", "derive"], default-features = false } scale-encode-derive = { workspace = true } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "bit-vec"] } trybuild = "1.0.72" From 8fd404303e67f8f9b64ff25c1486041b65ddb180 Mon Sep 17 00:00:00 2001 From: haerdib Date: Fri, 23 Jun 2023 10:59:54 +0200 Subject: [PATCH 19/26] remove std from tests --- scale-encode/src/impls/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scale-encode/src/impls/mod.rs b/scale-encode/src/impls/mod.rs index 7613570..5b41058 100644 --- a/scale-encode/src/impls/mod.rs +++ b/scale-encode/src/impls/mod.rs @@ -538,8 +538,8 @@ mod test { use super::*; use crate::{EncodeAsFields, Field}; use codec::Decode; + use core::fmt::Debug; use scale_info::TypeInfo; - use std::fmt::Debug; /// Given a type definition, return type ID and registry representing it. fn make_type() -> (u32, PortableRegistry) { @@ -696,7 +696,7 @@ mod test { assert_encodes_like_codec(-1234); assert_encodes_like_codec(100_000_000_000_000u128); assert_encodes_like_codec(()); - assert_encodes_like_codec(std::marker::PhantomData::<()>); + assert_encodes_like_codec(core::marker::PhantomData::<()>); assert_encodes_like_codec([1, 2, 3, 4, 5]); assert_encodes_like_codec([1u8, 2, 3, 4, 5]); assert_encodes_like_codec(vec![1, 2, 3, 4, 5]); @@ -711,7 +711,7 @@ mod test { // These don't impl TypeInfo so we have to provide the target type to encode to & compare with: assert_value_roundtrips_to(Arc::new("hi"), "hi".to_string()); assert_value_roundtrips_to(Rc::new("hi"), "hi".to_string()); - // encodes_like_codec(std::time::Duration::from_millis(123456)); + // encodes_like_codec(core::time::Duration::from_millis(123456)); } #[test] From 600fd94b720886a1ab42e1831fb3a52b56638eb1 Mon Sep 17 00:00:00 2001 From: haerdib Date: Fri, 23 Jun 2023 11:06:16 +0200 Subject: [PATCH 20/26] use Vec from scale-encode in derive --- scale-encode-derive/src/lib.rs | 14 ++++++-------- scale-encode/Cargo.toml | 2 +- scale-encode/src/lib.rs | 3 +-- scale-encode/tests/macros/pass_derive_generics.rs | 8 ++++---- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/scale-encode-derive/src/lib.rs b/scale-encode-derive/src/lib.rs index fbaef43..8ca9c3f 100644 --- a/scale-encode-derive/src/lib.rs +++ b/scale-encode-derive/src/lib.rs @@ -81,7 +81,7 @@ fn generate_enum_impl( // long variable names to prevent conflict with struct field names: __encode_as_type_type_id: u32, __encode_as_type_types: &#path_to_scale_encode::PortableRegistry, - __encode_as_type_out: &mut Vec + __encode_as_type_out: &mut #path_to_scale_encode::Vec ) -> Result<(), #path_to_scale_encode::Error> { match self { #( #match_arms, )* @@ -113,7 +113,7 @@ fn generate_struct_impl( // long variable names to prevent conflict with struct field names: __encode_as_type_type_id: u32, __encode_as_type_types: &#path_to_scale_encode::PortableRegistry, - __encode_as_type_out: &mut Vec + __encode_as_type_out: &mut #path_to_scale_encode::Vec ) -> Result<(), #path_to_scale_encode::Error> { let #path_to_type #matcher = self; #composite.encode_as_type_to( @@ -129,7 +129,7 @@ fn generate_struct_impl( // long variable names to prevent conflict with struct field names: __encode_as_type_fields: &mut dyn #path_to_scale_encode::FieldIter<'_>, __encode_as_type_types: &#path_to_scale_encode::PortableRegistry, - __encode_as_type_out: &mut Vec + __encode_as_type_out: &mut #path_to_scale_encode::Vec ) -> Result<(), #path_to_scale_encode::Error> { let #path_to_type #matcher = self; #composite.encode_as_fields_to( @@ -193,15 +193,13 @@ fn fields_to_matcher_and_composite( ) } syn::Fields::Unnamed(fields) => { - let field_idents: Vec = fields + let field_idents = fields .unnamed .iter() .enumerate() - .map(|(idx, _)| format_ident!("_{idx}")) - .collect(); - let match_body = field_idents.iter().map(|i| quote!(#i)); + .map(|(idx, _)| format_ident!("_{idx}")); + let match_body = field_idents.clone().map(|i| quote!(#i)); let tuple_body = field_idents - .iter() .map(|i| quote!((None as Option<&'static str>, #i as &dyn #path_to_scale_encode::EncodeAsType))); ( diff --git a/scale-encode/Cargo.toml b/scale-encode/Cargo.toml index 802ad52..b1f6cd3 100644 --- a/scale-encode/Cargo.toml +++ b/scale-encode/Cargo.toml @@ -29,7 +29,7 @@ primitive-types = ["dep:primitive-types"] bits = ["dep:scale-bits"] [dependencies] -scale-info = { version = "2.7.0", default-features = false, features = ["bit-vec"] } +scale-info = { version = "2.7.0", default-features = false, features = ["bit-vec"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } scale-bits = { version = "0.4.0", default-features = false, features = ["scale-info"], optional = true } scale-encode-derive = { workspace = true, optional = true } diff --git a/scale-encode/src/lib.rs b/scale-encode/src/lib.rs index 651f322..130ab49 100644 --- a/scale-encode/src/lib.rs +++ b/scale-encode/src/lib.rs @@ -147,6 +147,7 @@ mod impls; pub mod error; +pub use alloc::vec::Vec; pub use error::Error; // Useful types to help implement EncodeAsType/Fields with: @@ -159,8 +160,6 @@ pub mod ext { pub use primitive_types; } -use alloc::vec::Vec; - /// This trait signals that some static type can possibly be SCALE encoded given some /// `type_id` and [`PortableRegistry`] which dictates the expected encoding. pub trait EncodeAsType { diff --git a/scale-encode/tests/macros/pass_derive_generics.rs b/scale-encode/tests/macros/pass_derive_generics.rs index 164cc5b..6bb8e5e 100644 --- a/scale-encode/tests/macros/pass_derive_generics.rs +++ b/scale-encode/tests/macros/pass_derive_generics.rs @@ -21,20 +21,20 @@ struct NotEncodeAsType; #[derive(EncodeAsType)] enum Bar { Wibble(bool, T, U, V), - Wobble + Wobble, } // This impls EncodeAsType ok; we set no default trait bounds. #[derive(EncodeAsType)] #[encode_as_type(trait_bounds = "")] enum NoTraitBounds { - Wibble(std::marker::PhantomData), + Wibble(core::marker::PhantomData), } // Structs (and const bounds) impl EncodeAsType OK. #[derive(EncodeAsType)] struct MyStruct { - array: [Bar; V] + array: [Bar; V], } fn can_encode_as_type() {} @@ -44,4 +44,4 @@ fn main() { can_encode_as_type::>(); can_encode_as_type::>(); can_encode_as_type::>(); -} \ No newline at end of file +} From e1d30c4b3cf57159ed5d1eec6864538289a6eba3 Mon Sep 17 00:00:00 2001 From: haerdib Date: Fri, 23 Jun 2023 11:06:32 +0200 Subject: [PATCH 21/26] fix tests in bits --- scale-encode/src/impls/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/scale-encode/src/impls/mod.rs b/scale-encode/src/impls/mod.rs index 5b41058..8c66d50 100644 --- a/scale-encode/src/impls/mod.rs +++ b/scale-encode/src/impls/mod.rs @@ -537,6 +537,7 @@ where mod test { use super::*; use crate::{EncodeAsFields, Field}; + use alloc::vec; use codec::Decode; use core::fmt::Debug; use scale_info::TypeInfo; From 356c5e139285a3f3d87903fa6d0afcda1574a12c Mon Sep 17 00:00:00 2001 From: haerdib Date: Fri, 23 Jun 2023 11:33:42 +0200 Subject: [PATCH 22/26] add cargo test no-std to CI --- .github/workflows/rust.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index c4d26b2..37e4a33 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -164,6 +164,12 @@ jobs: command: test args: --all-targets --workspace + - name: Cargo test no_std + uses: actions-rs/cargo@v1.0.3 + with: + command: test + args: --all-targets --workspace --no-default-features --features bits,primitive-types + - name: Cargo test docs uses: actions-rs/cargo@v1.0.3 with: From d7e7d7ea01922a708c8ca35b6832e510dbf16276 Mon Sep 17 00:00:00 2001 From: haerdib Date: Fri, 23 Jun 2023 11:34:10 +0200 Subject: [PATCH 23/26] add testing/no_std crate --- Cargo.toml | 3 ++- testing/no_std/Cargo.toml | 16 ++++++++++++++++ testing/no_std/README.md | 1 + testing/no_std/src/lib.rs | 29 +++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 testing/no_std/Cargo.toml create mode 100644 testing/no_std/README.md create mode 100644 testing/no_std/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 6314e13..5694499 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,8 @@ [workspace] members = [ "scale-encode", - "scale-encode-derive" + "scale-encode-derive", + "testing/no_std", ] [workspace.package] diff --git a/testing/no_std/Cargo.toml b/testing/no_std/Cargo.toml new file mode 100644 index 0000000..00979c0 --- /dev/null +++ b/testing/no_std/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "test-no-std" +description = "Testing no_std build of scale-encode" +readme = "README.md" + +version.workspace = true +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +homepage.workspace = true +keywords.workspace = true +include.workspace = true + +[dependencies] +scale-encode = { path = "../../scale-encode", default-features = false, features = ["primitive-types", "derive", "bits"] } diff --git a/testing/no_std/README.md b/testing/no_std/README.md new file mode 100644 index 0000000..7ed0fe1 --- /dev/null +++ b/testing/no_std/README.md @@ -0,0 +1 @@ +test no_std build of scale-encode and scale-encode-derive diff --git a/testing/no_std/src/lib.rs b/testing/no_std/src/lib.rs new file mode 100644 index 0000000..4c9e33e --- /dev/null +++ b/testing/no_std/src/lib.rs @@ -0,0 +1,29 @@ +#![no_std] +extern crate alloc; + +use alloc::string::String; +use scale_encode::EncodeAsType; + +struct NotEncodeAsType; + +// Enums with generic params can impl EncodeAsType. +#[derive(EncodeAsType)] +enum Bar { + Wibble(bool, T, U, V), + Wobble, +} + +// This impls EncodeAsType ok; we set no default trait bounds. +#[derive(EncodeAsType)] +#[encode_as_type(trait_bounds = "")] +enum NoTraitBounds { + Wibble(core::marker::PhantomData), +} + +// Structs (and const bounds) impl EncodeAsType OK. +#[derive(EncodeAsType)] +struct MyStruct { + array: [Bar; V], +} + +fn can_encode_as_type() {} From 6b35c0cd4c9f22dd874966dc62f23ee64c1eafea Mon Sep 17 00:00:00 2001 From: haerdib Date: Fri, 23 Jun 2023 11:47:55 +0200 Subject: [PATCH 24/26] fix clippy --- testing/no_std/src/lib.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/testing/no_std/src/lib.rs b/testing/no_std/src/lib.rs index 4c9e33e..9eba032 100644 --- a/testing/no_std/src/lib.rs +++ b/testing/no_std/src/lib.rs @@ -1,14 +1,13 @@ #![no_std] extern crate alloc; -use alloc::string::String; use scale_encode::EncodeAsType; -struct NotEncodeAsType; +pub struct NotEncodeAsType; // Enums with generic params can impl EncodeAsType. #[derive(EncodeAsType)] -enum Bar { +pub enum Bar { Wibble(bool, T, U, V), Wobble, } @@ -16,14 +15,14 @@ enum Bar { // This impls EncodeAsType ok; we set no default trait bounds. #[derive(EncodeAsType)] #[encode_as_type(trait_bounds = "")] -enum NoTraitBounds { +pub enum NoTraitBounds { Wibble(core::marker::PhantomData), } // Structs (and const bounds) impl EncodeAsType OK. #[derive(EncodeAsType)] -struct MyStruct { +pub struct MyStruct { array: [Bar; V], } -fn can_encode_as_type() {} +pub fn can_encode_as_type() {} From 5d6006e6350ed2f349bfcb5240d7f74caa0cb718 Mon Sep 17 00:00:00 2001 From: haerdib Date: Fri, 23 Jun 2023 16:08:48 +0200 Subject: [PATCH 25/26] add doc hidden to pub use Vec --- scale-encode/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scale-encode/src/lib.rs b/scale-encode/src/lib.rs index 130ab49..86450b5 100644 --- a/scale-encode/src/lib.rs +++ b/scale-encode/src/lib.rs @@ -147,7 +147,10 @@ mod impls; pub mod error; +// This is exported for generated derive code to use, to be compatible with std or no-std as needed. +#[doc(hidden)] pub use alloc::vec::Vec; + pub use error::Error; // Useful types to help implement EncodeAsType/Fields with: From aa61b91e5bd4d129ae74853e29741757abd21055 Mon Sep 17 00:00:00 2001 From: haerdib Date: Fri, 23 Jun 2023 16:09:26 +0200 Subject: [PATCH 26/26] impl more verbose Display for ErrorKind --- scale-encode/src/error/mod.rs | 37 ++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/scale-encode/src/error/mod.rs b/scale-encode/src/error/mod.rs index b16aeeb..43cf0d8 100644 --- a/scale-encode/src/error/mod.rs +++ b/scale-encode/src/error/mod.rs @@ -140,7 +140,36 @@ impl From for ErrorKind { impl Display for ErrorKind { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "{self:?}") + match self { + ErrorKind::TypeNotFound(id) => write!(f, "Cannot find type with ID {id}"), + ErrorKind::WrongShape { actual, expected } => { + write!(f, "Cannot encode {actual:?} into type with ID {expected}") + } + ErrorKind::WrongLength { + actual_len, + expected_len, + } => { + write!(f, "Cannot encode to type; expected length {expected_len} but got length {actual_len}") + } + ErrorKind::NumberOutOfRange { value, expected } => { + write!( + f, + "Number {value} is out of range for target type {expected}" + ) + } + ErrorKind::CannotFindVariant { name, expected } => { + write!( + f, + "Variant {name} does not exist on type with ID {expected}" + ) + } + ErrorKind::CannotFindField { name } => { + write!(f, "Field {name} does not exist in our source struct") + } + ErrorKind::Custom(custom_error) => { + write!(f, "Custom error: {custom_error:?}") + } + } } } @@ -165,12 +194,6 @@ pub enum Kind { Number, } -impl Display for Kind { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "{self:?}") - } -} - #[cfg(test)] mod test { use super::*;