// Copyright (C) Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use codec::{Encode, Output}; cfg_if::cfg_if! { if #[cfg(feature = "std")] { use codec::{Decode, Error, Input}; /// On `std` the `StringBuf` used by [`DecodeDifferent`] is just a `String`. pub type StringBuf = String; } else { extern crate alloc; use alloc::vec::Vec; /// On `no_std` we do not support `Decode` and thus `StringBuf` is just `&'static str`. /// So, if someone tries to decode this stuff on `no_std`, they will get a compilation error. pub type StringBuf = &'static str; } } /// A type that decodes to a different type than it encodes. /// The user needs to make sure that both types use the same encoding. /// /// For example a `&'static [ &'static str ]` can be decoded to a `Vec`. #[derive(Clone)] pub enum DecodeDifferent where B: 'static, O: 'static, { /// Encodable variant of the value (doesn't need to be decodeable). Encode(B), /// Encodable & decodeable variant of the value. Decoded(O), } impl Encode for DecodeDifferent where B: Encode + 'static, O: Encode + 'static, { fn encode_to(&self, dest: &mut W) { match self { DecodeDifferent::Encode(b) => b.encode_to(dest), DecodeDifferent::Decoded(o) => o.encode_to(dest), } } } impl codec::EncodeLike for DecodeDifferent where B: Encode + 'static, O: Encode + 'static, { } #[cfg(feature = "std")] impl Decode for DecodeDifferent where B: 'static, O: Decode + 'static, { fn decode(input: &mut I) -> Result { ::decode(input).map(|val| DecodeDifferent::Decoded(val)) } } impl PartialEq for DecodeDifferent where B: Encode + Eq + PartialEq + 'static, O: Encode + Eq + PartialEq + 'static, { fn eq(&self, other: &Self) -> bool { self.encode() == other.encode() } } impl Eq for DecodeDifferent where B: Encode + Eq + PartialEq + 'static, O: Encode + Eq + PartialEq + 'static, { } impl core::fmt::Debug for DecodeDifferent where B: core::fmt::Debug + Eq + 'static, O: core::fmt::Debug + Eq + 'static, { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { match self { DecodeDifferent::Encode(b) => b.fmt(f), DecodeDifferent::Decoded(o) => o.fmt(f), } } } #[cfg(feature = "std")] impl serde::Serialize for DecodeDifferent where B: serde::Serialize + 'static, O: serde::Serialize + 'static, { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { match self { DecodeDifferent::Encode(b) => b.serialize(serializer), DecodeDifferent::Decoded(o) => o.serialize(serializer), } } } /// An array type that decodes as a `Vec`. pub type DecodeDifferentArray = DecodeDifferent<&'static [B], Vec>; /// A string type that decodes as a [`StringBuf`]. pub type DecodeDifferentStr = DecodeDifferent<&'static str, StringBuf>; /// Newtype wrapper for support encoding functions (actual the result of the function). #[derive(Clone, Eq)] pub struct FnEncode(pub fn() -> E) where E: Encode + 'static; impl Encode for FnEncode { fn encode_to(&self, dest: &mut W) { self.0().encode_to(dest); } } impl codec::EncodeLike for FnEncode {} impl PartialEq for FnEncode { fn eq(&self, other: &Self) -> bool { self.0().eq(&other.0()) } } impl core::fmt::Debug for FnEncode { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { self.0().fmt(f) } } #[cfg(feature = "std")] impl serde::Serialize for FnEncode { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { self.0().serialize(serializer) } }