diff --git a/Cargo.lock b/Cargo.lock index cde4149a9..f6db1d61f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7083,6 +7083,8 @@ dependencies = [ "parity-scale-codec", "sails-reflect-hash", "scale-info", + "serde", + "serde_json", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 674c4fcd7..bea95197e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -106,8 +106,8 @@ proc-macro2 = { version = "1", default-features = false } rustdoc-types = "=0.56.0" quote = "1.0" scale-info = { version = "2.11", default-features = false } -serde = "1.0" -serde-json = { package = "serde_json", version = "1.0" } +serde = { version = "1.0", default-features = false } +serde-json = { package = "serde_json", version = "1.0", default-features = false } spin = { version = "0.9", default-features = false, features = ["spin_mutex"] } syn = "2.0" thiserror = { version = "2.0", default-features = false } diff --git a/rs/idl-gen/tests/snapshots/generator__program_idl_works_with_empty_ctors.snap b/rs/idl-gen/tests/snapshots/generator__program_idl_works_with_empty_ctors.snap index 9787b7d1b..1848244cc 100644 --- a/rs/idl-gen/tests/snapshots/generator__program_idl_works_with_empty_ctors.snap +++ b/rs/idl-gen/tests/snapshots/generator__program_idl_works_with_empty_ctors.snap @@ -2,6 +2,7 @@ source: rs/idl-gen/tests/generator.rs expression: idl --- + !@sails: 0.10.2 service Service@0xd42ae9a4dc1efdf0 { diff --git a/rs/idl-gen/tests/snapshots/generator__program_idl_works_with_multiple_services.snap b/rs/idl-gen/tests/snapshots/generator__program_idl_works_with_multiple_services.snap index ba9a977c0..f2217526d 100644 --- a/rs/idl-gen/tests/snapshots/generator__program_idl_works_with_multiple_services.snap +++ b/rs/idl-gen/tests/snapshots/generator__program_idl_works_with_multiple_services.snap @@ -2,6 +2,7 @@ source: rs/idl-gen/tests/generator.rs expression: idl --- + !@sails: 0.10.2 service Service@0xd42ae9a4dc1efdf0 { diff --git a/rs/idl-gen/tests/snapshots/generator__program_idl_works_with_non_empty_ctors.snap b/rs/idl-gen/tests/snapshots/generator__program_idl_works_with_non_empty_ctors.snap index c8dcd8dfc..d07fd666f 100644 --- a/rs/idl-gen/tests/snapshots/generator__program_idl_works_with_non_empty_ctors.snap +++ b/rs/idl-gen/tests/snapshots/generator__program_idl_works_with_non_empty_ctors.snap @@ -2,6 +2,7 @@ source: rs/idl-gen/tests/generator.rs expression: idl --- + !@sails: 0.10.2 service Test@0xd42ae9a4dc1efdf0 { diff --git a/rs/idl-gen/tests/snapshots/generator__service_idl_works_with_base_services.snap b/rs/idl-gen/tests/snapshots/generator__service_idl_works_with_base_services.snap index a9816665b..84437f0d2 100644 --- a/rs/idl-gen/tests/snapshots/generator__service_idl_works_with_base_services.snap +++ b/rs/idl-gen/tests/snapshots/generator__service_idl_works_with_base_services.snap @@ -2,6 +2,7 @@ source: rs/idl-gen/tests/generator.rs expression: idl --- + !@sails: 0.10.2 service B@0x256fb43427bef08e { diff --git a/rs/idl-gen/tests/snapshots/generator__service_idl_works_with_basics.snap b/rs/idl-gen/tests/snapshots/generator__service_idl_works_with_basics.snap index 293b71ed6..e6040d545 100644 --- a/rs/idl-gen/tests/snapshots/generator__service_idl_works_with_basics.snap +++ b/rs/idl-gen/tests/snapshots/generator__service_idl_works_with_basics.snap @@ -2,6 +2,7 @@ source: rs/idl-gen/tests/generator.rs expression: idl --- + !@sails: 0.10.2 service TestServiceMeta@0xd42ae9a4dc1efdf0 { diff --git a/rs/idl-meta/Cargo.toml b/rs/idl-meta/Cargo.toml index d3edc22ec..b1584b471 100644 --- a/rs/idl-meta/Cargo.toml +++ b/rs/idl-meta/Cargo.toml @@ -12,8 +12,10 @@ rust-version.workspace = true [dependencies] askama = { workspace = true, optional = true, features = ["alloc", "derive"] } keccak-const.workspace = true +parity-scale-codec.workspace = true +serde = { workspace = true, features = ["alloc", "derive"], optional = true } +serde-json = { workspace = true, features = ["alloc"], optional = true } scale-info.workspace = true -parity-scale-codec = { workspace = true, features = ["derive"] } [dev-dependencies] gprimitives.workspace = true @@ -23,8 +25,13 @@ sails-reflect-hash.workspace = true [features] default = ["ast"] ast = [] +serde = ["dep:serde", "dep:serde-json", "ast"] templates = ["dep:askama", "ast"] +[[test]] +name = "serde" +required-features = ["serde"] + [[test]] name = "templates" required-features = ["templates"] diff --git a/rs/idl-meta/src/ast.rs b/rs/idl-meta/src/ast.rs index 025466087..e624039fb 100644 --- a/rs/idl-meta/src/ast.rs +++ b/rs/idl-meta/src/ast.rs @@ -10,6 +10,8 @@ use core::{ fmt::{Display, Write}, str::FromStr, }; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; // -------------------------------- IDL model --------------------------------- @@ -25,9 +27,19 @@ use core::{ derive(askama::Template), template(path = "idl.askama", escape = "none") )] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct IdlDoc { + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub globals: Vec<(String, Option)>, + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))] pub program: Option, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub services: Vec, } @@ -44,18 +56,48 @@ pub struct IdlDoc { derive(askama::Template), template(path = "program.askama", escape = "none") )] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct ProgramUnit { pub name: String, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub ctors: Vec, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub services: Vec, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub types: Vec, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub docs: Vec, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub annotations: Vec<(String, Option)>, } #[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct ServiceIdent { pub name: String, + #[cfg_attr( + feature = "serde", + serde( + default, + skip_serializing_if = "Option::is_none", + with = "serde_opt_str" + ) + )] pub interface_id: Option, } @@ -100,11 +142,22 @@ impl FromStr for ServiceIdent { /// - an optional low-level `route` (transport / path) used by the runtime, /// - may contain documentation comments and annotations. #[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct ServiceExpo { + #[cfg_attr(feature = "serde", serde(flatten))] pub name: ServiceIdent, + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))] pub route: Option, pub route_idx: u8, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub docs: Vec, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub annotations: Vec<(String, Option)>, } @@ -115,10 +168,20 @@ pub struct ServiceExpo { /// - `params` are the IDL-level arguments, /// - may contain documentation comments and annotations. #[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct CtorFunc { pub name: String, + #[cfg_attr(feature = "serde", serde(default))] pub params: Vec, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub docs: Vec, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub annotations: Vec<(String, Option)>, } @@ -136,13 +199,39 @@ pub struct CtorFunc { derive(askama::Template), template(path = "service.askama", escape = "none") )] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct ServiceUnit { + #[cfg_attr(feature = "serde", serde(flatten))] pub name: ServiceIdent, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub extends: Vec, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub funcs: Vec, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub events: Vec, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub types: Vec, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub docs: Vec, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub annotations: Vec<(String, Option)>, } @@ -163,18 +252,34 @@ impl ServiceUnit { /// - `is_query` marks read-only / query functions as defined by the spec; /// - may contain documentation comments and annotations. #[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct ServiceFunc { pub name: String, + #[cfg_attr(feature = "serde", serde(default))] pub params: Vec, pub output: TypeDecl, + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))] pub throws: Option, pub kind: FunctionKind, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub docs: Vec, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub annotations: Vec<(String, Option)>, } /// Function kind based on mutability. #[derive(Debug, Default, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "lowercase") +)] pub enum FunctionKind { #[default] Command, @@ -196,8 +301,10 @@ impl ServiceFunc { /// Stores the parameter name as written in IDL and its fully resolved type /// (`TypeDecl`), preserving declaration order. #[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct FuncParam { pub name: String, + #[cfg_attr(feature = "serde", serde(rename = "type"))] pub type_decl: TypeDecl, } @@ -225,6 +332,11 @@ pub type ServiceEvent = EnumVariant; /// - user-defined types with generics (`UserDefined`), /// - bare generic parameters (`T`). #[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "lowercase", tag = "kind") +)] pub enum TypeDecl { /// Slice type `[T]`. Slice { item: Box }, @@ -239,10 +351,15 @@ pub enum TypeDecl { /// - generic type parameter (e.g. `T`) used in type definitions. Named { name: String, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] generics: Vec, }, /// Built-in primitive type from `PrimitiveType`. - Primitive(PrimitiveType), + #[cfg_attr(feature = "serde", serde(untagged))] + Primitive(#[cfg_attr(feature = "serde", serde(with = "serde_str"))] PrimitiveType), } impl TypeDecl { @@ -454,11 +571,25 @@ impl core::str::FromStr for PrimitiveType { derive(askama::Template), template(path = "type.askama", escape = "none") )] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Type { pub name: String, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub type_params: Vec, + #[cfg_attr(feature = "serde", serde(flatten))] pub def: TypeDef, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub docs: Vec, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub annotations: Vec<(String, Option)>, } @@ -468,12 +599,14 @@ pub struct Type { /// - `ty` is an optional concrete type bound / substitution; `None` means that /// the parameter is left generic at this level. #[derive(Debug, PartialEq, Eq, Hash, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct TypeParameter { /// The name of the generic type parameter e.g. "T". pub name: String, /// The concrete type for the type parameter. /// /// `None` if the type parameter is skipped. + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))] pub ty: Option, } @@ -490,6 +623,11 @@ impl Display for TypeParameter { /// - `Struct` - record / tuple / unit structs; /// - `Enum` - tagged unions with variants that may carry payloads. #[derive(Debug, Clone, PartialEq)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(rename_all = "lowercase", tag = "kind") +)] pub enum TypeDef { Struct(StructDef), Enum(EnumDef), @@ -507,7 +645,9 @@ pub enum TypeDef { derive(askama::Template), template(path = "struct_def.askama", escape = "none") )] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct StructDef { + #[cfg_attr(feature = "serde", serde(default))] pub fields: Vec, } @@ -541,10 +681,21 @@ impl StructDef { derive(askama::Template), template(path = "field.askama", escape = "none") )] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct StructField { + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))] pub name: Option, + #[cfg_attr(feature = "serde", serde(rename = "type"))] pub type_decl: TypeDecl, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub docs: Vec, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub annotations: Vec<(String, Option)>, } @@ -553,7 +704,9 @@ pub struct StructField { /// Stores the ordered list of `EnumVariant` items that form a tagged union. /// Each variant may be unit-like, classic (named fields) or tuple-like. #[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct EnumDef { + #[cfg_attr(feature = "serde", serde(default))] pub variants: Vec, } @@ -568,9 +721,73 @@ pub struct EnumDef { derive(askama::Template), template(path = "variant.askama", escape = "none") )] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct EnumVariant { pub name: String, + #[cfg_attr(feature = "serde", serde(flatten))] pub def: StructDef, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub docs: Vec, + #[cfg_attr( + feature = "serde", + serde(default, skip_serializing_if = "Vec::is_empty") + )] pub annotations: Vec<(String, Option)>, } + +#[cfg(feature = "serde")] +mod serde_str { + use super::*; + use core::str::FromStr; + use serde::{Deserializer, Serializer}; + + pub(super) fn serialize(value: &T, serializer: S) -> Result + where + T: Display, + S: Serializer, + { + serializer.collect_str(value) + } + + pub(super) fn deserialize<'de, T, D>(deserializer: D) -> Result + where + T: FromStr, + ::Err: Display, + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + T::from_str(s.as_str()).map_err(serde::de::Error::custom) + } +} + +#[cfg(feature = "serde")] +mod serde_opt_str { + use super::*; + use core::str::FromStr; + use serde::{Deserializer, Serializer}; + + pub(super) fn serialize(value: &Option, serializer: S) -> Result + where + T: Display, + S: Serializer, + { + match value { + Some(value) => serializer.collect_str(value), + None => serializer.serialize_none(), + } + } + + pub(super) fn deserialize<'de, T, D>(deserializer: D) -> Result, D::Error> + where + T: FromStr, + ::Err: Display, + D: Deserializer<'de>, + { + let opt = Option::::deserialize(deserializer)?; + opt.map(|s| T::from_str(s.as_str()).map_err(serde::de::Error::custom)) + .transpose() + } +} diff --git a/rs/idl-meta/tests/fixture/mod.rs b/rs/idl-meta/tests/fixture/mod.rs index 5210b3a93..78f8050ad 100644 --- a/rs/idl-meta/tests/fixture/mod.rs +++ b/rs/idl-meta/tests/fixture/mod.rs @@ -418,14 +418,14 @@ pub fn program_unit() -> ProgramUnit { annotations: vec![], }, ServiceExpo { - name: "Counter".parse().unwrap(), + name: "Counter@0x579d6daba41b7d82".parse().unwrap(), route: None, route_idx: 2, docs: vec![], annotations: vec![], }, ServiceExpo { - name: "Counter".parse().unwrap(), + name: "Counter@0x579d6daba41b7d82".parse().unwrap(), route: Some("Counter2".to_string()), route_idx: 3, docs: vec!["Another Counter service".to_owned()], diff --git a/rs/idl-meta/tests/serde.rs b/rs/idl-meta/tests/serde.rs new file mode 100644 index 000000000..1c0ec2463 --- /dev/null +++ b/rs/idl-meta/tests/serde.rs @@ -0,0 +1,48 @@ +use sails_idl_meta::*; + +mod fixture; + +#[test] +fn type_enum() { + let ty = fixture::enum_variants_type(); + let serialized = serde_json::to_string_pretty(&ty).unwrap(); + let value: Type = serde_json::from_str(&serialized).unwrap(); + + assert_eq!(ty, value); + insta::assert_snapshot!(serialized); +} + +#[test] +fn service_unit() { + let service = fixture::this_that_service(); + let serialized = serde_json::to_string_pretty(&service).unwrap(); + let value: ServiceUnit = serde_json::from_str(&serialized).unwrap(); + + assert_eq!(service, value); + insta::assert_snapshot!(serialized); +} + +#[test] +fn program_unit() { + let prg = fixture::program_unit(); + let serialized = serde_json::to_string_pretty(&prg).unwrap(); + let value: ProgramUnit = serde_json::from_str(&serialized).unwrap(); + + assert_eq!(prg, value); + insta::assert_snapshot!(serialized); +} + +#[test] +fn idl_doc() { + let doc = IdlDoc { + globals: fixture::globals(), + program: Some(fixture::program_unit()), + services: vec![fixture::counter_service(), fixture::this_that_service()], + }; + + let serialized = serde_json::to_string_pretty(&doc).unwrap(); + let value: IdlDoc = serde_json::from_str(&serialized).unwrap(); + + assert_eq!(doc, value); + insta::assert_snapshot!(serialized); +} diff --git a/rs/idl-meta/tests/snapshots/serde__idl_doc.snap b/rs/idl-meta/tests/snapshots/serde__idl_doc.snap new file mode 100644 index 000000000..efc2aa458 --- /dev/null +++ b/rs/idl-meta/tests/snapshots/serde__idl_doc.snap @@ -0,0 +1,373 @@ +--- +source: rs/idl-meta/tests/serde.rs +expression: serialized +--- +{ + "globals": [ + [ + "sails", + "0.1.0" + ], + [ + "include", + "ownable.idl" + ], + [ + "include", + "git://github.com/some_repo/tippable.idl" + ] + ], + "program": { + "name": "Demo", + "ctors": [ + { + "name": "Create", + "params": [ + { + "name": "counter", + "type": { + "kind": "named", + "name": "Option", + "generics": [ + "u32" + ] + } + }, + { + "name": "dog_position", + "type": { + "kind": "named", + "name": "Option", + "generics": [ + { + "kind": "tuple", + "types": [ + "i32", + "i32" + ] + } + ] + } + } + ], + "docs": [ + "Program constructor (called once at the very beginning of the program lifetime)" + ] + }, + { + "name": "Default", + "params": [], + "docs": [ + "Another program constructor", + "(called once at the very beginning of the program lifetime)" + ] + } + ], + "services": [ + { + "name": "Ping", + "route_idx": 1 + }, + { + "name": "Counter", + "interface_id": "0x579d6daba41b7d82", + "route_idx": 2 + }, + { + "name": "Counter", + "interface_id": "0x579d6daba41b7d82", + "route": "Counter2", + "route_idx": 3, + "docs": [ + "Another Counter service" + ] + } + ], + "types": [ + { + "name": "DoThatParam", + "kind": "struct", + "fields": [ + { + "name": "p1", + "type": "u32" + }, + { + "name": "p2", + "type": "ActorId" + }, + { + "name": "p3", + "type": { + "kind": "named", + "name": "ManyVariants" + } + } + ] + }, + { + "name": "TupleStruct", + "kind": "struct", + "fields": [ + { + "type": "u32" + } + ] + }, + { + "name": "UnitStruct", + "kind": "struct", + "fields": [] + } + ], + "docs": [ + "Demo Program" + ] + }, + "services": [ + { + "name": "Counter", + "funcs": [ + { + "name": "Add", + "params": [ + { + "name": "value", + "type": "u32" + } + ], + "output": "u32", + "kind": "command", + "docs": [ + "Add a value to the counter" + ] + }, + { + "name": "Sub", + "params": [ + { + "name": "value", + "type": "u32" + } + ], + "output": "u32", + "kind": "command", + "docs": [ + "Substract a value from the counter" + ] + }, + { + "name": "Value", + "params": [], + "output": "u32", + "kind": "query", + "docs": [ + "Get the current value" + ], + "annotations": [ + [ + "query", + null + ] + ] + } + ], + "events": [ + { + "name": "Added", + "fields": [ + { + "type": "u32" + } + ], + "docs": [ + "Emitted when a new value is added to the counter" + ] + }, + { + "name": "Subtracted", + "fields": [ + { + "type": "u32" + } + ], + "docs": [ + "Emitted when a value is subtracted from the counter" + ] + } + ] + }, + { + "name": "ThisThat", + "funcs": [ + { + "name": "DoThis", + "params": [ + { + "name": "p1", + "type": "u32" + }, + { + "name": "p2", + "type": "String" + }, + { + "name": "p3", + "type": { + "kind": "tuple", + "types": [ + { + "kind": "named", + "name": "Option", + "generics": [ + "H160" + ] + }, + { + "kind": "named", + "name": "NonZero", + "generics": [ + "u8" + ] + } + ] + } + }, + { + "name": "p4", + "type": { + "kind": "named", + "name": "TupleStruct" + } + } + ], + "output": { + "kind": "tuple", + "types": [ + "String", + "u32" + ] + }, + "throws": { + "kind": "tuple", + "types": [ + "String" + ] + }, + "kind": "command", + "docs": [ + "Some func", + "With multiline doc" + ] + } + ], + "types": [ + { + "name": "DoThatParam", + "kind": "struct", + "fields": [ + { + "name": "p1", + "type": "u32", + "docs": [ + "Parametr p1: u32" + ] + }, + { + "name": "p2", + "type": "ActorId" + }, + { + "name": "p3", + "type": { + "kind": "named", + "name": "ManyVariants" + } + } + ] + }, + { + "name": "ManyVariants", + "kind": "enum", + "variants": [ + { + "name": "One", + "fields": [] + }, + { + "name": "Two", + "fields": [ + { + "type": "u32" + } + ] + }, + { + "name": "Three", + "fields": [ + { + "type": { + "kind": "named", + "name": "Option", + "generics": [ + "u32" + ] + } + } + ] + }, + { + "name": "Four", + "fields": [ + { + "name": "a", + "type": "u32" + }, + { + "name": "b", + "type": { + "kind": "named", + "name": "Option", + "generics": [ + "u16" + ] + } + } + ] + }, + { + "name": "Five", + "fields": [ + { + "type": "String" + }, + { + "type": "H256", + "annotations": [ + [ + "key", + "value" + ] + ] + } + ] + }, + { + "name": "Six", + "fields": [ + { + "type": { + "kind": "tuple", + "types": [ + "u32" + ] + } + } + ] + } + ] + } + ] + } + ] +} diff --git a/rs/idl-meta/tests/snapshots/serde__program_unit.snap b/rs/idl-meta/tests/snapshots/serde__program_unit.snap new file mode 100644 index 000000000..11c9f2305 --- /dev/null +++ b/rs/idl-meta/tests/snapshots/serde__program_unit.snap @@ -0,0 +1,111 @@ +--- +source: rs/idl-meta/tests/serde.rs +expression: serialized +--- +{ + "name": "Demo", + "ctors": [ + { + "name": "Create", + "params": [ + { + "name": "counter", + "type": { + "kind": "named", + "name": "Option", + "generics": [ + "u32" + ] + } + }, + { + "name": "dog_position", + "type": { + "kind": "named", + "name": "Option", + "generics": [ + { + "kind": "tuple", + "types": [ + "i32", + "i32" + ] + } + ] + } + } + ], + "docs": [ + "Program constructor (called once at the very beginning of the program lifetime)" + ] + }, + { + "name": "Default", + "params": [], + "docs": [ + "Another program constructor", + "(called once at the very beginning of the program lifetime)" + ] + } + ], + "services": [ + { + "name": "Ping", + "route_idx": 1 + }, + { + "name": "Counter", + "interface_id": "0x579d6daba41b7d82", + "route_idx": 2 + }, + { + "name": "Counter", + "interface_id": "0x579d6daba41b7d82", + "route": "Counter2", + "route_idx": 3, + "docs": [ + "Another Counter service" + ] + } + ], + "types": [ + { + "name": "DoThatParam", + "kind": "struct", + "fields": [ + { + "name": "p1", + "type": "u32" + }, + { + "name": "p2", + "type": "ActorId" + }, + { + "name": "p3", + "type": { + "kind": "named", + "name": "ManyVariants" + } + } + ] + }, + { + "name": "TupleStruct", + "kind": "struct", + "fields": [ + { + "type": "u32" + } + ] + }, + { + "name": "UnitStruct", + "kind": "struct", + "fields": [] + } + ], + "docs": [ + "Demo Program" + ] +} diff --git a/rs/idl-meta/tests/snapshots/serde__service_unit.snap b/rs/idl-meta/tests/snapshots/serde__service_unit.snap new file mode 100644 index 000000000..9fb8cba55 --- /dev/null +++ b/rs/idl-meta/tests/snapshots/serde__service_unit.snap @@ -0,0 +1,176 @@ +--- +source: rs/idl-meta/tests/serde.rs +expression: serialized +--- +{ + "name": "ThisThat", + "funcs": [ + { + "name": "DoThis", + "params": [ + { + "name": "p1", + "type": "u32" + }, + { + "name": "p2", + "type": "String" + }, + { + "name": "p3", + "type": { + "kind": "tuple", + "types": [ + { + "kind": "named", + "name": "Option", + "generics": [ + "H160" + ] + }, + { + "kind": "named", + "name": "NonZero", + "generics": [ + "u8" + ] + } + ] + } + }, + { + "name": "p4", + "type": { + "kind": "named", + "name": "TupleStruct" + } + } + ], + "output": { + "kind": "tuple", + "types": [ + "String", + "u32" + ] + }, + "throws": { + "kind": "tuple", + "types": [ + "String" + ] + }, + "kind": "command", + "docs": [ + "Some func", + "With multiline doc" + ] + } + ], + "types": [ + { + "name": "DoThatParam", + "kind": "struct", + "fields": [ + { + "name": "p1", + "type": "u32", + "docs": [ + "Parametr p1: u32" + ] + }, + { + "name": "p2", + "type": "ActorId" + }, + { + "name": "p3", + "type": { + "kind": "named", + "name": "ManyVariants" + } + } + ] + }, + { + "name": "ManyVariants", + "kind": "enum", + "variants": [ + { + "name": "One", + "fields": [] + }, + { + "name": "Two", + "fields": [ + { + "type": "u32" + } + ] + }, + { + "name": "Three", + "fields": [ + { + "type": { + "kind": "named", + "name": "Option", + "generics": [ + "u32" + ] + } + } + ] + }, + { + "name": "Four", + "fields": [ + { + "name": "a", + "type": "u32" + }, + { + "name": "b", + "type": { + "kind": "named", + "name": "Option", + "generics": [ + "u16" + ] + } + } + ] + }, + { + "name": "Five", + "fields": [ + { + "type": "String" + }, + { + "type": "H256", + "annotations": [ + [ + "key", + "value" + ] + ] + } + ] + }, + { + "name": "Six", + "fields": [ + { + "type": { + "kind": "tuple", + "types": [ + "u32" + ] + } + } + ] + } + ] + } + ] +} diff --git a/rs/idl-meta/tests/snapshots/serde__type_enum.snap b/rs/idl-meta/tests/snapshots/serde__type_enum.snap new file mode 100644 index 000000000..7bd7fe651 --- /dev/null +++ b/rs/idl-meta/tests/snapshots/serde__type_enum.snap @@ -0,0 +1,142 @@ +--- +source: rs/idl-meta/tests/serde.rs +expression: serialized +--- +{ + "name": "SomeType", + "type_params": [ + { + "name": "T1" + }, + { + "name": "T2" + } + ], + "kind": "enum", + "variants": [ + { + "name": "Unit", + "fields": [], + "docs": [ + "Unit-like Variant" + ] + }, + { + "name": "Tuple", + "fields": [ + { + "type": "u32" + } + ], + "docs": [ + "Tuple-like Variant" + ] + }, + { + "name": "TupleWithDocs", + "fields": [ + { + "type": { + "kind": "named", + "name": "Option", + "generics": [ + "u32" + ] + }, + "docs": [ + "Some docs" + ] + }, + { + "type": { + "kind": "tuple", + "types": [ + "u32", + "u32" + ] + }, + "docs": [ + "Some docs" + ] + } + ], + "docs": [ + "Tuple-like Variant with field docs" + ] + }, + { + "name": "Struct", + "fields": [ + { + "name": "p1", + "type": { + "kind": "named", + "name": "Option", + "generics": [ + "u32" + ] + } + }, + { + "name": "p2", + "type": { + "kind": "tuple", + "types": [ + "u32", + "u32" + ] + } + } + ], + "docs": [ + "Struct-like Variant" + ] + }, + { + "name": "GenericStruct", + "fields": [ + { + "name": "p1", + "type": { + "kind": "named", + "name": "Option", + "generics": [ + { + "kind": "named", + "name": "T1" + } + ] + } + }, + { + "name": "p2", + "type": { + "kind": "tuple", + "types": [ + { + "kind": "named", + "name": "T2" + }, + { + "kind": "named", + "name": "T2" + } + ] + } + } + ], + "docs": [ + "Generic Struct-like Variant" + ] + } + ], + "docs": [ + "SomeType Enum" + ], + "annotations": [ + [ + "rusttype", + "sails-idl-meta::SomeType" + ] + ] +} diff --git a/rs/idl-meta/tests/snapshots/templates__idl_globals.snap b/rs/idl-meta/tests/snapshots/templates__idl_globals.snap index a4c91bb5b..d6aa5a506 100644 --- a/rs/idl-meta/tests/snapshots/templates__idl_globals.snap +++ b/rs/idl-meta/tests/snapshots/templates__idl_globals.snap @@ -2,6 +2,7 @@ source: rs/idl-meta/tests/templates.rs expression: idl --- + !@sails: 0.1.0 !@include: ownable.idl !@include: git://github.com/some_repo/tippable.idl diff --git a/rs/idl-meta/tests/snapshots/templates__idl_program.snap b/rs/idl-meta/tests/snapshots/templates__idl_program.snap index ac0edb503..56c3eb34a 100644 --- a/rs/idl-meta/tests/snapshots/templates__idl_program.snap +++ b/rs/idl-meta/tests/snapshots/templates__idl_program.snap @@ -2,6 +2,7 @@ source: rs/idl-meta/tests/templates.rs expression: idl --- + !@sails: 0.1.0 !@include: ownable.idl !@include: git://github.com/some_repo/tippable.idl @@ -17,9 +18,9 @@ program Demo { } services { Ping, - Counter, + Counter@0x579d6daba41b7d82, /// Another Counter service - Counter: Counter2, + Counter@0x579d6daba41b7d82: Counter2, } types { struct DoThatParam { diff --git a/rs/idl-meta/tests/snapshots/templates__idl_service.snap b/rs/idl-meta/tests/snapshots/templates__idl_service.snap index 06782fed0..05dba8490 100644 --- a/rs/idl-meta/tests/snapshots/templates__idl_service.snap +++ b/rs/idl-meta/tests/snapshots/templates__idl_service.snap @@ -2,6 +2,7 @@ source: rs/idl-meta/tests/templates.rs expression: idl --- + !@sails: 0.1.0 !@include: ownable.idl !@include: git://github.com/some_repo/tippable.idl diff --git a/rs/idl-meta/tests/snapshots/templates__type_enum.snap b/rs/idl-meta/tests/snapshots/templates__type_enum.snap index 29a128277..70ccad6e1 100644 --- a/rs/idl-meta/tests/snapshots/templates__type_enum.snap +++ b/rs/idl-meta/tests/snapshots/templates__type_enum.snap @@ -2,6 +2,7 @@ source: rs/idl-meta/tests/templates.rs expression: idl --- + /// SomeType Enum @rusttype: sails-idl-meta::SomeType enum SomeType {