34个版本 (19个稳定版)

2.11.3 2024年5月8日
2.11.1 2024年3月25日
2.10.0 2023年10月20日
2.9.0 2023年7月3日
0.3.0 2020年7月3日

19 in 编码

Download history 105758/week @ 2024-05-03 119261/week @ 2024-05-10 110150/week @ 2024-05-17 116822/week @ 2024-05-24 117620/week @ 2024-05-31 111174/week @ 2024-06-07 110194/week @ 2024-06-14 119684/week @ 2024-06-21 97295/week @ 2024-06-28 97813/week @ 2024-07-05 113964/week @ 2024-07-12 120987/week @ 2024-07-19 118527/week @ 2024-07-26 128970/week @ 2024-08-02 130596/week @ 2024-08-09 93164/week @ 2024-08-16

每月491,338次下载
用于 1,163 个crate (480直接)

Apache-2.0

170KB
3K SLoC

scale-info · build 最新版本

一个用于描述Rust类型,专注于提供关于SCALE可编码类型结构的信息的库。

这些定义为第三方工具(例如UI客户端)提供了关于如何解码类型的信息,而不依赖于语言。

其核心是 TypeInfo 特性

pub trait TypeInfo {
    type Identity: ?Sized + 'static;
    fn type_info() -> Type;
}

实现此特性的类型将构建并返回一个 Type 结构体

pub struct Type<T: Form = MetaForm> {
    /// The unique path to the type. Can be empty for built-in types
    path: Path<T>,
    /// The generic type parameters of the type in use. Empty for non generic types
    type_params: Vec<T::Type>,
    /// The actual type definition
    type_def: TypeDef<T>,
}

类型定义为以下之一

pub enum TypeDef<T: Form = MetaForm> {
    /// A composite type (e.g. a struct or a tuple)
    Composite(TypeDefComposite<T>),
    /// A variant type (e.g. an enum)
    Variant(TypeDefVariant<T>),
    /// A sequence type with runtime known length.
    Sequence(TypeDefSequence<T>),
    /// An array type with compile-time known length.
    Array(TypeDefArray<T>),
    /// A tuple type.
    Tuple(TypeDefTuple<T>),
    /// A Rust primitive type.
    Primitive(TypeDefPrimitive),
}

内置类型定义

以下“内置”类型具有预定义的 TypeInfo 定义

  • 原始类型: boolcharstru8u16u32u64u128i8i16i32i64i128

  • 序列:由实现了 T 的元素组成的可变大小序列,其中 T 实现了 TypeInfo。例如:[T]&[T]&mut [T]Vec<T>

  • 数组:对于任何实现了 TypeInfoT,其固定大小的 [T: $n],其中 $n 是预定义大小之一。

  • 元组:由最多10个字段组成的元组,这些字段的类型实现了 TypeInfo

用户定义类型

有两种用户定义类型:CompositeVariant

两者在其定义中都使用了 PathField 类型。

字段

表示用户定义类型的基本构建块是定义字段类型及其可选名称的 Field 结构体。用户定义类型的构建器强制执行不变性,即所有字段都有名称(例如,结构体)或所有字段都是未命名的(例如,元组)。

路径

类型的路径是一系列标识符的唯一序列。Rust 类型通常从命名空间和标识符构造路径,例如 foo::bar::Baz 转换为路径 ["foo", "bar", "Baz"]

复合类型

复合数据类型 由一系列 Fields 组成。

结构体 由一组 命名 字段表示,在构建期间强制执行。

struct Foo<T> {
    bar: T,
    data: u64,
}

impl<T> TypeInfo for Foo<T>
where
    T: TypeInfo + 'static,
{
    type Identity = Self;

    fn type_info() -> Type {
        Type::builder()
            .path(Path::new("Foo", module_path!()))
            .type_params(vec![MetaType::new::<T>()])
            .composite(Fields::named()
                .field(|f| f.ty::<T>().name("bar").type_name("T"))
                .field(|f| f.ty::<u64>().name("data").type_name("u64"))
            )
    }
}

元组 由一组 未命名 字段表示,在构建期间强制执行。

struct Foo(u32, bool);

impl TypeInfo for Foo {
    type Identity = Self;

    fn type_info() -> Type {
        Type::builder()
            .path(Path::new("Foo", module_path!()))
            .composite(Fields::unnamed()
                .field(|f| f.ty::<u32>().type_name("u32"))
                .field(|f| f.ty::<bool>().type_name("bool"))
            )
    }
}

变体

变体类型 也称为枚举或标记联合,由一系列变体组成。变体可以具有未命名字段、命名字段或没有字段。

enum Foo<T>{
    A(T),
    B { f: u32 },
    C,
}

impl<T> TypeInfo for Foo<T>
where
    T: TypeInfo + 'static,
{
    type Identity = Self;

    fn type_info() -> Type {
        Type::builder()
            .path(Path::new("Foo", module_path!()))
            .type_params(vec![MetaType::new::<T>()])
            .variant(
                Variants::new()
                   .variant("A", |v| v.fields(Fields::unnamed().field(|f| f.ty::<T>())))
                   .variant("B", |v| v.fields(Fields::named().field(|f| f.ty::<u32>().name("f").type_name("u32"))))
                   .variant_unit("C")
            )
    }
}

如果没有变体包含字段,则可以显式设置区分符,由构建器在构建期间强制执行。

enum Foo {
    A,
    B,
    C = 33,
}

impl TypeInfo for Foo {
    type Identity = Self;

    fn type_info() -> Type {
        Type::builder()
            .path(Path::new("Foo", module_path!()))
            .variant(
                Variants::new()
                    .variant("A", |v| v.index(1))
                    .variant("B", |v| v.index(2))
                    .variant("C", |v| v.index(33))
            )
    }
}

注册表

类型信息在所谓的类型注册表(Registry)中提供。类型定义在那里注册,并与唯一的ID关联,外部可以引用这些ID,从而提供一种轻量级的方法来减少开销,而不是使用类型标识符。

所有具体的 TypeInfo 结构体有两种形式

  • 一种元形式(MetaType),充当与其他形式之间的桥梁
  • 一种适合序列化的便携式形式。

还必须实现 IntoPortable 特性,以便使用类型注册表的实例准备类型定义以进行序列化。

转换后,所有类型定义都存储在类型注册表中。请注意,类型注册表应作为元数据结构的一部分进行序列化,其中注册的类型被利用,以便允许消费者解析类型。

编码

类型注册表可以编码为:

  • JSON(启用“serde”功能)。
  • SCALE自身(使用parity-scale-codec)。

功能

以下可选的cargo功能可用:

  • serde包括对类型注册表进行JSON序列化和反序列化的支持。请参阅示例这里
  • derive重新导出scale-info-derive包。

已知问题

当为具有泛型紧凑字段的类型派生TypeInfo,例如:

#[derive(Encode, TypeInfo)]
struct Foo<S> { #[codec(compact)] a: S }

当使用此泛型类型且没有正确的界限时,您可能会遇到以下错误:

error[E0275]: overflow evaluating the requirement `_::_parity_scale_codec::Compact<_>: Decode`

有关更多信息,请参阅https://github.com/paritytech/scale-info/issues/65

资源

依赖项

~1.6–2.7MB
~56K SLoC