ixc_schema 0.0.4

Interchain SDK Schema
Documentation
use ixc_schema_macros::SchemaValue;
use crate::decoder::Decoder;
use crate::decoder::DecodeError;
use crate::encoder::{EncodeError, Encoder};
use crate::kind::Kind;
use crate::types::{ReferenceableType, Type};

#[derive(Debug, Clone, Eq, PartialEq)]
#[non_exhaustive]
pub struct EnumType<'a> {
    pub name: &'a str,
    pub values: &'a [EnumValueDefinition<'a>],
    pub numeric_kind: Kind,
    pub sealed: bool,
}

#[derive(Debug, Clone, Default, PartialEq, Eq, SchemaValue)]
#[non_exhaustive]
pub struct EnumValueDefinition<'a> {
    pub name: &'a str,
    pub value: i32,
}

impl<'a> EnumValueDefinition<'a> {
    pub const fn new(name: &'a str, value: i32) -> Self {
        Self {
            name,
            value,
        }
    }
}

pub unsafe trait EnumSchema:
ReferenceableType + TryFrom<Self::NumericType> + Into<Self::NumericType> + Clone
{
    const NAME: &'static str;
    const VALUES: &'static [EnumValueDefinition<'static>];
    const SEALED: bool;
    type NumericType: EnumNumericType;
    const ENUM_TYPE: EnumType<'static> = to_enum_type::<Self>();
}

pub const fn to_enum_type<E: EnumSchema>() -> EnumType<'static> {
    EnumType {
        name: E::NAME,
        values: E::VALUES,
        numeric_kind: E::NumericType::KIND,
        sealed: E::SEALED,
    }
}

trait EnumNumericType: Type {}
impl EnumNumericType for i32 {}
impl EnumNumericType for u16 {}
impl EnumNumericType for i16 {}
impl EnumNumericType for u8 {}
impl EnumNumericType for i8 {}

fn encode_enum<E: EnumSchema>(x: &E, encoder: &mut dyn Encoder)
                              -> Result<(), EncodeError>
where
    E::NumericType: Into<i32>,
{
    let value = encoder.encode_i32(E::into(x.clone()).into());
    value
}

fn decode_enum<E: EnumSchema>(decoder: &mut dyn Decoder) -> Result<E, DecodeError>
where
    E::NumericType: From<i32>,
{
    let x = decoder.decode_enum(&E::ENUM_TYPE)?;
    E::try_from(x.into())
        .map_err(|_| DecodeError::InvalidData)
}