Rust libraries and tools to help with interoperability and testing of serialization formats based on Serde.

Overview

The repository zefchain/serde-reflection is based on Facebook's repository novifinancial/serde-reflection.

We are now maintaining the project here and will continue releasing updates to crates.io under the same package names.

serde-reflection: Format Description and Code Generation for Serde

Build Status License License

This project aims to bring the features of a traditional IDL to Rust and Serde.

  • serde-reflection is a library to extract Serde data formats serde-reflection on crates.io Documentation (latest release)

  • serde-generate is a library and a tool to generate type definitions and provide (de)serialization in other programming languages serde-generate on crates.io Documentation (latest release)

  • serde-name is a minimal library to compute Serde names at runtime serde-name on crates.io Documentation (latest release)

The code in this repository is still under active development.

Quick Start

See this example to transfer data from Rust to Python using the Bincode format.

Use Cases

Data Format Specifications

The Serde library is an essential component of the Rust ecosystem that provides (de)serialization of Rust data structures in many encodings. In practice, Serde implements the (de)serialization of user data structures using derive macros #[derive(Serialize, Deserialize)].

serde-reflection analyzes the result of Serde macros to turn Rust type definitions into a representation of their Serde data layout. For instance, the following definition

#[derive(Serialize, Deserialize)]
enum Foo { A(u64), B, C }

entails a registry containing one data format and represented as follows in YAML syntax:

---
Foo:
  ENUM:
    0:
      A:
        NEWTYPE:
          U64
    1:
      B: UNIT
    2:
      C: UNIT

This format summarizes how a value of type Foo would be encoded by Serde in any encoding. For instance, in Bincode, we deduce that Foo::B is encoded as a 32-bit integer 1.

One difficulty often associated with Serde is that small modifications in Rust may silently change the specifications of the protocol. For instance, changing enum Foo { A(u64), B, C } into enum Foo { A(u64), C, B } does not break Rust compilation but it changes the serialization of Foo::B.

Thanks to serde-reflection, one can now solve this issue simply by committing Serde formats as a file in the version control system (VCS) and adding a non-regression test (real-life example).

Language Interoperability

The data formats extracted by serde-reflection also serve as basis for code generation with the library and tool serde-generate.

For instance, the definition of Foo above translates into C++ as follows: (omitting methods)

struct Foo {
    struct A {
        uint64_t value;
    };
    struct B {};
    struct C {};
    std::variant<A, B, C> value;
};

To provide (de)serialization, the code generated by serde-generate is completed by runtime libraries in each target language and for each supported binary encoding.

Currently, serde-generate generates type definitions and supports Bincode and BCS serialization in the following programming languages:

  • C++
  • Java
  • Python
  • Rust
  • Go
  • C#
  • Swift
  • OCaml
  • Typescript (in progress)
  • Dart (in progress)

Benefits

In addition to ensuring an optimal developer experience in Rust, the modular approach based on Serde and serde-reflection makes it easy to experiment with new binary encodings. We believe that this approach can greatly facilitate the implementation of distributed protocols and storage protocols in Rust.

This project was initially motivated by the need for canonical serialization and cryptographic hashing in the Diem project (formerly known as "Libra"). In this context, serde-name has been used to provide predictable cryptographic seeds for Rust containers.

Related projects

Schemars

Schemars is the equivalent of serde-reflection for JSON Schemas.

Borsh

Borsh is a canonical encoding format similar to BCS. The Rust implementation uses its own derive macros (not Serde). Implementations for other languages use reflection (or templates) rather than code generation.

Contributing

See the CONTRIBUTING file for how to help out.

License

This project is available under the terms of either the Apache 2.0 license or the MIT license.

Comments
  • Modify the Dart enum generation to match other usage of c_style_enum

    Modify the Dart enum generation to match other usage of c_style_enum

    Summary

    The C# implementation of enum generation looks at all variants of an enum and, if all are of type Unit, it then generates a native enum and otherwise generates a class. The current Dart implementation simply generates all classes if c_style_enums = false or all enums if c_style_enums = true.

    This PR changes the Dart logic to match C# (the only other language that currently implements the c_style_enums config. dart.rs will now generate all classes if c_style_enums = false and if it is true it will generate native Dart enums unless the enum contains data, then it will generate a class.

    Test Plan

    A test was added that verifies that when c_style_enums is enabled the generator will generate native Dart enums for the simple case but generate classes for data-containing enums.

    opened by jerel 3
  • Make the handling of i128/u128 compatible with the Dart web platform

    Make the handling of i128/u128 compatible with the Dart web platform

    Summary

    The 128 bit type implementations used a 64 bit number which isn't allowed on the Dart web platform (32 bits is the max supported). This switches from the BigInt from which takes a number to the parse function which uses a string to create a BigInt instance.

    Test Plan

    from and parse are identical except that parse can throw an exception, in our usage it can never throw because the value is static.

    opened by jerel 2
  • [Feature Request] Efficient byte arrays in Go

    [Feature Request] Efficient byte arrays in Go

    πŸš€ Feature Request

    Motivation

    Code generation is inefficient for static size byte arrays

    Hash:
      NEWTYPESTRUCT:
        TUPLEARRAY:
          CONTENT: U8
          SIZE: 32
    

    generates

    type Hash [32]uint8
    
    func (obj *Hash) Serialize(serializer serde.Serializer) error {
    	if err := serializer.IncreaseContainerDepth(); err != nil {
    		return err
    	}
    	if err := serialize_array32_u8_array((([32]uint8)(*obj)), serializer); err != nil {
    		return err
    	}
    	serializer.DecreaseContainerDepth()
    	return nil
    }
    
    func serialize_array32_u8_array(value [32]uint8, serializer serde.Serializer) error {
    	for _, item := range value {
    		if err := serializer.SerializeU8(item); err != nil {
    			return err
    		}
    	}
    	return nil
    }
    

    Pitch

    Describe the solution you'd like

    • Extend serde Go interface to be aware of byte arrays
    • Implement bincode serde for byte arrays with a single function call

    Describe alternatives you've considered

    none

    Are you willing to open a pull request? (See CONTRIBUTING)

    Maybe later

    Additional context

    enhancement 
    opened by terorie 2
  • Dart utf8

    Dart utf8

    Summary

    Initial implementation of the Dart runtime handled string ser/de with [utf-16] code units. This had the appearance of working as long as the given character was < 128. This PR switches to utf-8 encode/decode to fix this bug.

    Test Plan

    A test is included with Japanese text which causes the current implementation to fail.

    opened by jerel 2
  • add copyWith utility method to Dart classes

    add copyWith utility method to Dart classes

    Summary

    Add the common copyWith utility method to generated Dart classes.

    Uses this method for allowing nullable properties to be set to null.

    Additionally, I noticed some incorrect formatting of the operator == method output while inspecting the code. I added a fix for that, but I can split into a separate PR if that is preferable.

    Example other_types.dart output
      part of example_types;
    
    @immutable
    class OtherTypes {
      const OtherTypes({
        required this.fString,
        required this.fBytes,
        this.fOption,
        required this.fUnit,
        required this.fSeq,
        required this.fTuple,
        required this.fStringmap,
        required this.fIntset,
        required this.fNestedSeq,
      });
    
      OtherTypes.deserialize(BinaryDeserializer deserializer) :
        fString = deserializer.deserializeString(),
        fBytes = deserializer.deserializeBytes(),
        fOption = TraitHelpers.deserializeOptionStruct(deserializer),
        fUnit = deserializer.deserializeUnit(),
        fSeq = TraitHelpers.deserializeVectorStruct(deserializer),
        fTuple = TraitHelpers.deserializeTuple2U8U16(deserializer),
        fStringmap = TraitHelpers.deserializeMapStrToU32(deserializer),
        fIntset = TraitHelpers.deserializeMapU64ToUnit(deserializer),
        fNestedSeq = TraitHelpers.deserializeVectorVectorStruct(deserializer);
    
      static OtherTypes bincodeDeserialize(Uint8List input) {
        final deserializer = BincodeDeserializer(input);
        final value = OtherTypes.deserialize(deserializer);
        if (deserializer.offset < input.length) {
          throw Exception('Some input bytes were not read');
        }
        return value;
      }
    
      static OtherTypes bcsDeserialize(Uint8List input) {
        final deserializer = BcsDeserializer(input);
        final value = OtherTypes.deserialize(deserializer);
        if (deserializer.offset < input.length) {
          throw Exception('Some input bytes were not read');
        }
        return value;
      }
    
      final String fString;
      final Bytes fBytes;
      final Struct? fOption;
      final Unit fUnit;
      final List<Struct> fSeq;
      final Tuple2<int, int> fTuple;
      final Map<String, int> fStringmap;
      final Map<Uint64, Unit> fIntset;
      final List<List<Struct>> fNestedSeq;
    
      OtherTypes copyWith({
        String? fString,
        Bytes? fBytes,
        Struct? Function()? fOption,
        Unit? fUnit,
        List<Struct>? fSeq,
        Tuple2<int, int>? fTuple,
        Map<String, int>? fStringmap,
        Map<Uint64, Unit>? fIntset,
        List<List<Struct>>? fNestedSeq,
      }) {
        return OtherTypes(
          fString: fString ?? this.fString,
          fBytes: fBytes ?? this.fBytes,
          fOption: fOption == null ? this.fOption : fOption(),
          fUnit: fUnit ?? this.fUnit,
          fSeq: fSeq ?? this.fSeq,
          fTuple: fTuple ?? this.fTuple,
          fStringmap: fStringmap ?? this.fStringmap,
          fIntset: fIntset ?? this.fIntset,
          fNestedSeq: fNestedSeq ?? this.fNestedSeq,
        );
      }
    
      void serialize(BinarySerializer serializer) {
        serializer.serializeString(fString);
        serializer.serializeBytes(fBytes);
        TraitHelpers.serializeOptionStruct(fOption, serializer);
        serializer.serializeUnit(fUnit);
        TraitHelpers.serializeVectorStruct(fSeq, serializer);
        TraitHelpers.serializeTuple2U8U16(fTuple, serializer);
        TraitHelpers.serializeMapStrToU32(fStringmap, serializer);
        TraitHelpers.serializeMapU64ToUnit(fIntset, serializer);
        TraitHelpers.serializeVectorVectorStruct(fNestedSeq, serializer);
      }
    
      Uint8List bincodeSerialize() {
          final serializer = BincodeSerializer();
          serialize(serializer);
          return serializer.bytes;
      }
    
      Uint8List bcsSerialize() {
          final serializer = BcsSerializer();
          serialize(serializer);
          return serializer.bytes;
      }
    
      @override
      bool operator ==(Object other) {
        if (identical(this, other)) return true;
        if (other.runtimeType != runtimeType) return false;
    
        return other is OtherTypes
          && fString == other.fString
          && fBytes == other.fBytes
          && fOption == other.fOption
          && fUnit == other.fUnit
          && listEquals(fSeq, other.fSeq)
          && fTuple == other.fTuple
          && mapEquals(fStringmap, other.fStringmap)
          && mapEquals(fIntset, other.fIntset)
          && listEquals(fNestedSeq, other.fNestedSeq);
      }
    
      @override
      int get hashCode => Object.hash(
            fString,
            fBytes,
            fOption,
            fUnit,
            fSeq,
            fTuple,
            fStringmap,
            fIntset,
            fNestedSeq,
          );
    
      @override
      String toString() {
        String? fullString;
    
        assert(() {
          fullString = '$runtimeType('
            'fString: $fString, '
            'fBytes: $fBytes, '
            'fOption: $fOption, '
            'fUnit: $fUnit, '
            'fSeq: $fSeq, '
            'fTuple: $fTuple, '
            'fStringmap: $fStringmap, '
            'fIntset: $fIntset, '
            'fNestedSeq: $fNestedSeq'
            ')';
          return true;
        }());
    
        return fullString ?? 'OtherTypes';
      }
    }
    

    Test Plan

    I'm not sure if this needs separate tests outside of analyze still passing. To verify my code worked, I logged out the path for one of the test projects and checked the output. I'm not sure if there is a better way to inspect generated code.

    cc: @jerel

    opened by kturney 1
  • [serde generate][Swift] Enum variants should be camelCased

    [serde generate][Swift] Enum variants should be camelCased

    πŸš€ Feature Request

    When generating code, enum variants should be expressed in the native preferred format. In Swift, that is camelCased, as opposed to Rust's UpperCamelCased.

    Motivation

    Swift types generated with serde-generate feel out of place since they start with a capital letter. It's minor, but the code would be closer to a first class citizen if they were properly camelCased.

    enhancement 
    opened by agg23 1
  • Bump regex from 1.5.4 to 1.5.5

    Bump regex from 1.5.4 to 1.5.5

    Bumps regex from 1.5.4 to 1.5.5.

    Changelog

    Sourced from regex's changelog.

    1.5.5 (2022-03-08)

    This releases fixes a security bug in the regex compiler. This bug permits a vector for a denial-of-service attack in cases where the regex being compiled is untrusted. There are no known problems where the regex is itself trusted, including in cases of untrusted haystacks.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • [swift] Write enum variants as camelCase

    [swift] Write enum variants as camelCase

    Summary

    Changes Swift enum variants to be expressed in camelCase, rather than Rust's UpperCamelCase. Addresses #10

    Test Plan

    Swift tests are passing. It would be nice to have better testing in general on the generated code, as the coverage for a change like this is very small (as you can see in the test structure, it was a single character change), but I didn't want to try to write new tests unprompted, given how complicated the current testing setup appears to be.

    opened by agg23 0
  • Fix a few glitches in the ocaml codegen

    Fix a few glitches in the ocaml codegen

    Summary

    • Add missing to_caml_case()
    • Also test if field names are Ocaml keywords
    • Prefix enum variants with the name of the enum (this is a bit sad in Ocaml but hard to avoid because Rust works like this)

    Test Plan

    CI

    curl https://raw.githubusercontent.com/aptos-labs/aptos-core/master/testsuite/generate-format/tests/staged/aptos.yaml > aptos.yaml
    
    rm -rf test
    
    cargo run --bin serdegen -- --language ocaml --with-runtimes serde bcs --target-source-dir test -- aptos.yaml
    
    (cd test && dune build)
    
    opened by ma2bd 0
  • [Feature Request] Minimize dependencies

    [Feature Request] Minimize dependencies

    πŸš€ Feature Request

    Motivation

    cargo tree currently reports the following dependencies for serde-generate:

    serde-generate v0.24.0
    β”œβ”€β”€ bcs v0.1.4
    β”‚   β”œβ”€β”€ serde v1.0.148
    β”‚   β”‚   └── serde_derive v1.0.148 (proc-macro)
    β”‚   β”‚       β”œβ”€β”€ proc-macro2 v1.0.47
    β”‚   β”‚       β”‚   └── unicode-ident v1.0.5
    β”‚   β”‚       β”œβ”€β”€ quote v1.0.21
    β”‚   β”‚       β”‚   └── proc-macro2 v1.0.47 (*)
    β”‚   β”‚       └── syn v1.0.104
    β”‚   β”‚           β”œβ”€β”€ proc-macro2 v1.0.47 (*)
    β”‚   β”‚           β”œβ”€β”€ quote v1.0.21 (*)
    β”‚   β”‚           └── unicode-ident v1.0.5
    β”‚   └── thiserror v1.0.37
    β”‚       └── thiserror-impl v1.0.37 (proc-macro)
    β”‚           β”œβ”€β”€ proc-macro2 v1.0.47 (*)
    β”‚           β”œβ”€β”€ quote v1.0.21 (*)
    β”‚           └── syn v1.0.104 (*)
    β”œβ”€β”€ bincode v1.3.3
    β”‚   └── serde v1.0.148 (*)
    β”œβ”€β”€ heck v0.3.3
    β”‚   └── unicode-segmentation v1.10.0
    β”œβ”€β”€ include_dir v0.6.2
    β”‚   β”œβ”€β”€ glob v0.3.0
    β”‚   β”œβ”€β”€ include_dir_impl v0.6.2 (proc-macro)
    β”‚   β”‚   β”œβ”€β”€ anyhow v1.0.66
    β”‚   β”‚   β”œβ”€β”€ proc-macro-hack v0.5.19 (proc-macro)
    β”‚   β”‚   β”œβ”€β”€ proc-macro2 v1.0.47 (*)
    β”‚   β”‚   β”œβ”€β”€ quote v1.0.21 (*)
    β”‚   β”‚   └── syn v1.0.104 (*)
    β”‚   └── proc-macro-hack v0.5.19 (proc-macro)
    β”œβ”€β”€ maplit v1.0.2
    β”œβ”€β”€ phf v0.10.1
    β”‚   β”œβ”€β”€ phf_macros v0.10.0 (proc-macro)
    β”‚   β”‚   β”œβ”€β”€ phf_generator v0.10.0
    β”‚   β”‚   β”‚   β”œβ”€β”€ phf_shared v0.10.0
    β”‚   β”‚   β”‚   β”‚   └── siphasher v0.3.10
    β”‚   β”‚   β”‚   └── rand v0.8.5
    β”‚   β”‚   β”‚       β”œβ”€β”€ libc v0.2.137
    β”‚   β”‚   β”‚       β”œβ”€β”€ rand_chacha v0.3.1
    β”‚   β”‚   β”‚       β”‚   β”œβ”€β”€ ppv-lite86 v0.2.17
    β”‚   β”‚   β”‚       β”‚   └── rand_core v0.6.4
    β”‚   β”‚   β”‚       β”‚       └── getrandom v0.2.8
    β”‚   β”‚   β”‚       β”‚           β”œβ”€β”€ cfg-if v1.0.0
    β”‚   β”‚   β”‚       β”‚           └── libc v0.2.137
    β”‚   β”‚   β”‚       └── rand_core v0.6.4 (*)
    β”‚   β”‚   β”œβ”€β”€ phf_shared v0.10.0 (*)
    β”‚   β”‚   β”œβ”€β”€ proc-macro-hack v0.5.19 (proc-macro)
    β”‚   β”‚   β”œβ”€β”€ proc-macro2 v1.0.47 (*)
    β”‚   β”‚   β”œβ”€β”€ quote v1.0.21 (*)
    β”‚   β”‚   └── syn v1.0.104 (*)
    β”‚   β”œβ”€β”€ phf_shared v0.10.0 (*)
    β”‚   └── proc-macro-hack v0.5.19 (proc-macro)
    β”œβ”€β”€ serde v1.0.148 (*)
    β”œβ”€β”€ serde-reflection v0.3.6
    β”‚   β”œβ”€β”€ once_cell v1.16.0
    β”‚   β”œβ”€β”€ serde v1.0.148 (*)
    β”‚   └── thiserror v1.0.37 (*)
    β”œβ”€β”€ serde_bytes v0.11.8
    β”‚   └── serde v1.0.148 (*)
    β”œβ”€β”€ serde_yaml v0.8.26
    β”‚   β”œβ”€β”€ indexmap v1.9.2
    β”‚   β”‚   └── hashbrown v0.12.3
    β”‚   β”‚   [build-dependencies]
    β”‚   β”‚   └── autocfg v1.1.0
    β”‚   β”œβ”€β”€ ryu v1.0.11
    β”‚   β”œβ”€β”€ serde v1.0.148 (*)
    β”‚   └── yaml-rust v0.4.5
    β”‚       └── linked-hash-map v0.5.6
    β”œβ”€β”€ structopt v0.3.26
    β”‚   β”œβ”€β”€ clap v2.34.0
    β”‚   β”‚   β”œβ”€β”€ ansi_term v0.12.1
    β”‚   β”‚   β”œβ”€β”€ atty v0.2.14
    β”‚   β”‚   β”‚   └── libc v0.2.137
    β”‚   β”‚   β”œβ”€β”€ bitflags v1.3.2
    β”‚   β”‚   β”œβ”€β”€ strsim v0.8.0
    β”‚   β”‚   β”œβ”€β”€ textwrap v0.11.0
    β”‚   β”‚   β”‚   └── unicode-width v0.1.10
    β”‚   β”‚   β”œβ”€β”€ unicode-width v0.1.10
    β”‚   β”‚   └── vec_map v0.8.2
    β”‚   β”œβ”€β”€ lazy_static v1.4.0
    β”‚   └── structopt-derive v0.4.18 (proc-macro)
    β”‚       β”œβ”€β”€ heck v0.3.3 (*)
    β”‚       β”œβ”€β”€ proc-macro-error v1.0.4
    β”‚       β”‚   β”œβ”€β”€ proc-macro-error-attr v1.0.4 (proc-macro)
    β”‚       β”‚   β”‚   β”œβ”€β”€ proc-macro2 v1.0.47 (*)
    β”‚       β”‚   β”‚   └── quote v1.0.21 (*)
    β”‚       β”‚   β”‚   [build-dependencies]
    β”‚       β”‚   β”‚   └── version_check v0.9.4
    β”‚       β”‚   β”œβ”€β”€ proc-macro2 v1.0.47 (*)
    β”‚       β”‚   β”œβ”€β”€ quote v1.0.21 (*)
    β”‚       β”‚   └── syn v1.0.104 (*)
    β”‚       β”‚   [build-dependencies]
    β”‚       β”‚   └── version_check v0.9.4
    β”‚       β”œβ”€β”€ proc-macro2 v1.0.47 (*)
    β”‚       β”œβ”€β”€ quote v1.0.21 (*)
    β”‚       └── syn v1.0.104 (*)
    └── textwrap v0.13.4
        β”œβ”€β”€ smawk v0.3.1
        └── unicode-width v0.1.10
    

    Ideally serde-generate would provide an API that put dependencies behind different feature flags, so that not everything is required if only a small part of the crate is used.

    Especially that includes the following dependencies:

    • structopt as that's not needed if serde-generate is used as dependency
    • bcs and bincode as sometimes you want to use one or the other
    • serde_yaml as it's not always required to build a yaml representation of the corresponding types

    I'm not sure about other dependencies like textwrap, heck, serde_bytes, include_dir, maplit and phf.

    Pitch

    Describe the solution you'd like Put parts of the API behind feature flags, so that users can choose what to use + what gate corresponding dependencies on these flags.

    Describe alternatives you've considered

    Do not change anything and pull in potentially unneeded dependencies.

    Are you willing to open a pull request? (See CONTRIBUTING)

    I would be willing to contribute a PR for that

    Additional context

    enhancement 
    opened by weiznich 0
  • [Feature Request] Minimize dependencies of `serde-generate`

    [Feature Request] Minimize dependencies of `serde-generate`

    πŸš€ Feature Request

    Motivation

    cargo tree currently reports the following dependencies for serde-generate:

    serde-generate v0.24.0
    β”œβ”€β”€ bcs v0.1.4
    β”‚   β”œβ”€β”€ serde v1.0.148
    β”‚   β”‚   └── serde_derive v1.0.148 (proc-macro)
    β”‚   β”‚       β”œβ”€β”€ proc-macro2 v1.0.47
    β”‚   β”‚       β”‚   └── unicode-ident v1.0.5
    β”‚   β”‚       β”œβ”€β”€ quote v1.0.21
    β”‚   β”‚       β”‚   └── proc-macro2 v1.0.47 (*)
    β”‚   β”‚       └── syn v1.0.104
    β”‚   β”‚           β”œβ”€β”€ proc-macro2 v1.0.47 (*)
    β”‚   β”‚           β”œβ”€β”€ quote v1.0.21 (*)
    β”‚   β”‚           └── unicode-ident v1.0.5
    β”‚   └── thiserror v1.0.37
    β”‚       └── thiserror-impl v1.0.37 (proc-macro)
    β”‚           β”œβ”€β”€ proc-macro2 v1.0.47 (*)
    β”‚           β”œβ”€β”€ quote v1.0.21 (*)
    β”‚           └── syn v1.0.104 (*)
    β”œβ”€β”€ bincode v1.3.3
    β”‚   └── serde v1.0.148 (*)
    β”œβ”€β”€ heck v0.3.3
    β”‚   └── unicode-segmentation v1.10.0
    β”œβ”€β”€ include_dir v0.6.2
    β”‚   β”œβ”€β”€ glob v0.3.0
    β”‚   β”œβ”€β”€ include_dir_impl v0.6.2 (proc-macro)
    β”‚   β”‚   β”œβ”€β”€ anyhow v1.0.66
    β”‚   β”‚   β”œβ”€β”€ proc-macro-hack v0.5.19 (proc-macro)
    β”‚   β”‚   β”œβ”€β”€ proc-macro2 v1.0.47 (*)
    β”‚   β”‚   β”œβ”€β”€ quote v1.0.21 (*)
    β”‚   β”‚   └── syn v1.0.104 (*)
    β”‚   └── proc-macro-hack v0.5.19 (proc-macro)
    β”œβ”€β”€ maplit v1.0.2
    β”œβ”€β”€ phf v0.10.1
    β”‚   β”œβ”€β”€ phf_macros v0.10.0 (proc-macro)
    β”‚   β”‚   β”œβ”€β”€ phf_generator v0.10.0
    β”‚   β”‚   β”‚   β”œβ”€β”€ phf_shared v0.10.0
    β”‚   β”‚   β”‚   β”‚   └── siphasher v0.3.10
    β”‚   β”‚   β”‚   └── rand v0.8.5
    β”‚   β”‚   β”‚       β”œβ”€β”€ libc v0.2.137
    β”‚   β”‚   β”‚       β”œβ”€β”€ rand_chacha v0.3.1
    β”‚   β”‚   β”‚       β”‚   β”œβ”€β”€ ppv-lite86 v0.2.17
    β”‚   β”‚   β”‚       β”‚   └── rand_core v0.6.4
    β”‚   β”‚   β”‚       β”‚       └── getrandom v0.2.8
    β”‚   β”‚   β”‚       β”‚           β”œβ”€β”€ cfg-if v1.0.0
    β”‚   β”‚   β”‚       β”‚           └── libc v0.2.137
    β”‚   β”‚   β”‚       └── rand_core v0.6.4 (*)
    β”‚   β”‚   β”œβ”€β”€ phf_shared v0.10.0 (*)
    β”‚   β”‚   β”œβ”€β”€ proc-macro-hack v0.5.19 (proc-macro)
    β”‚   β”‚   β”œβ”€β”€ proc-macro2 v1.0.47 (*)
    β”‚   β”‚   β”œβ”€β”€ quote v1.0.21 (*)
    β”‚   β”‚   └── syn v1.0.104 (*)
    β”‚   β”œβ”€β”€ phf_shared v0.10.0 (*)
    β”‚   └── proc-macro-hack v0.5.19 (proc-macro)
    β”œβ”€β”€ serde v1.0.148 (*)
    β”œβ”€β”€ serde-reflection v0.3.6
    β”‚   β”œβ”€β”€ once_cell v1.16.0
    β”‚   β”œβ”€β”€ serde v1.0.148 (*)
    β”‚   └── thiserror v1.0.37 (*)
    β”œβ”€β”€ serde_bytes v0.11.8
    β”‚   └── serde v1.0.148 (*)
    β”œβ”€β”€ serde_yaml v0.8.26
    β”‚   β”œβ”€β”€ indexmap v1.9.2
    β”‚   β”‚   └── hashbrown v0.12.3
    β”‚   β”‚   [build-dependencies]
    β”‚   β”‚   └── autocfg v1.1.0
    β”‚   β”œβ”€β”€ ryu v1.0.11
    β”‚   β”œβ”€β”€ serde v1.0.148 (*)
    β”‚   └── yaml-rust v0.4.5
    β”‚       └── linked-hash-map v0.5.6
    β”œβ”€β”€ structopt v0.3.26
    β”‚   β”œβ”€β”€ clap v2.34.0
    β”‚   β”‚   β”œβ”€β”€ ansi_term v0.12.1
    β”‚   β”‚   β”œβ”€β”€ atty v0.2.14
    β”‚   β”‚   β”‚   └── libc v0.2.137
    β”‚   β”‚   β”œβ”€β”€ bitflags v1.3.2
    β”‚   β”‚   β”œβ”€β”€ strsim v0.8.0
    β”‚   β”‚   β”œβ”€β”€ textwrap v0.11.0
    β”‚   β”‚   β”‚   └── unicode-width v0.1.10
    β”‚   β”‚   β”œβ”€β”€ unicode-width v0.1.10
    β”‚   β”‚   └── vec_map v0.8.2
    β”‚   β”œβ”€β”€ lazy_static v1.4.0
    β”‚   └── structopt-derive v0.4.18 (proc-macro)
    β”‚       β”œβ”€β”€ heck v0.3.3 (*)
    β”‚       β”œβ”€β”€ proc-macro-error v1.0.4
    β”‚       β”‚   β”œβ”€β”€ proc-macro-error-attr v1.0.4 (proc-macro)
    β”‚       β”‚   β”‚   β”œβ”€β”€ proc-macro2 v1.0.47 (*)
    β”‚       β”‚   β”‚   └── quote v1.0.21 (*)
    β”‚       β”‚   β”‚   [build-dependencies]
    β”‚       β”‚   β”‚   └── version_check v0.9.4
    β”‚       β”‚   β”œβ”€β”€ proc-macro2 v1.0.47 (*)
    β”‚       β”‚   β”œβ”€β”€ quote v1.0.21 (*)
    β”‚       β”‚   └── syn v1.0.104 (*)
    β”‚       β”‚   [build-dependencies]
    β”‚       β”‚   └── version_check v0.9.4
    β”‚       β”œβ”€β”€ proc-macro2 v1.0.47 (*)
    β”‚       β”œβ”€β”€ quote v1.0.21 (*)
    β”‚       └── syn v1.0.104 (*)
    └── textwrap v0.13.4
        β”œβ”€β”€ smawk v0.3.1
        └── unicode-width v0.1.10
    

    Ideally serde-generate would provide an API that put dependencies behind different feature flags, so that not everything is required if only a small part of the crate is used.

    Especially that includes the following dependencies:

    • structopt as that's not needed if serde-generate is used as dependency
    • bcs and bincode as sometimes you want to use one or the other
    • serde_yaml as it's not always required to build a yaml representation of the corresponding types

    I'm not sure about other dependencies like textwrap, heck, serde_bytes, include_dir, maplit and phf.

    Pitch

    Describe the solution you'd like Put parts of the API behind feature flags, so that users can choose what to use + what gate corresponding dependencies on these flags.

    Describe alternatives you've considered

    Do not change anything and pull in potentially unneeded dependencies.

    Are you willing to open a pull request? (See CONTRIBUTING)

    I would be willing to contribute a PR for that

    Additional context

    enhancement 
    opened by weiznich 0
  • [Bug] Error will be reported when

    [Bug] Error will be reported when "chrono" type is defined

    πŸ› Bug

    #[derive(Serialize, Deserialize, Default)] pub struct A { pub created_at: chrono::NaiveDateTime, pub xxx: i64, }

    let mut tracer = serde_reflection::Tracer::new(serde_reflection::TracerConfig::default()); let mut samples = serde_reflection::Samples::new(); tracer.trace_type::(&mut samples).unwrap(); let registry = tracer.registry().unwrap(); serde_json::to_string_pretty(&registry).unwrap_or_default();

    error message alert: on an Err value: Custom("Failed to deserialize value: "premature end of input"")'

    bug 
    opened by guoyucode 1
  • [Bug] Swift types prefixed by module name

    [Bug] Swift types prefixed by module name

    πŸ› Bug

    Generated swift code, which includes types that reference each other, prefixes local references with module name provided to CodeGeneratorConfig. The code fails to compile with an error "Cannot find type '' in scope".

    The problem can be worked around by searching and replacing the module name followed by "." (e.g. "module.") with an empty string, effectively stripping the namespacing out of the generated code.

    To reproduce

    Types to be traced

    #[derive(Serialize, Deserialize)]
    pub struct Request {
        pub uuid: Vec<u8>,
        pub body: RequestBody,
    }
    
    #[derive(Serialize, Deserialize)]
    pub enum RequestBody {
       // ... variants
    }
    

    Tracing and generating build.rs script

    use rmm::{Request, RequestBody};
    use serde_reflection::{Tracer, TracerConfig};
    use std::{fs::File, io::Write, path::PathBuf};
    
    fn main() {
        let mut tracer = Tracer::new(TracerConfig::default());
        tracer.trace_simple_type::<Request>().unwrap();
        tracer.trace_simple_type::<RequestBody>().unwrap();
        let registry = tracer.registry().unwrap();
    
        // Create Swift definitions.
        let mut source = Vec::new();
        let config = serde_generate::CodeGeneratorConfig::new("shared".to_string())
            .with_encodings(vec![serde_generate::Encoding::Bincode]);
    
        let generator = serde_generate::swift::CodeGenerator::new(&config);
        generator.output(&mut source, &registry).unwrap();
    
        let path = "./generated/shared_types.swift";
        let mut output = File::create(path).unwrap();
        write!(output, "{}", out).unwrap();
    }
    
    

    Relevant part of the generated Swift code

    public struct Response: Hashable {
        @Indirect public var uuid: [UInt8]
        @Indirect public var body: shared.ResponseBody // "Error: Cannot find type 'shared' in scope"
    
        (...)
    

    Removing shared. from the above resolves the problem.

    Expected Behavior

    Generated Swift code should compile without errors.

    System information

    Serde reflection v0.3.6 Serde generate v0.24.0

    bug 
    opened by charypar 1
  • [Feature Request] Improved tracing algorithm in serde_reflection::trace_type

    [Feature Request] Improved tracing algorithm in serde_reflection::trace_type

    πŸš€ Feature Request

    serde_reflection::trace_type relies on a few ideas and heuristics that it might be time to revisit.

    Notably, we use the current table of formats tracer.registry to guide the tracing in most decision points -- with the exception of tracer.incomplete_enums that is also used to decide how to trace enum variants.

    This approach was a natural starting point but it is not ideal in the long run for a few reasons:

    Calling trace_value before trace_type may update the registry in an incomplete way and defeat further tracing with trace_type. We don't have an easy way to detect non-termination if the base case of enums is not the first variant. We cannot call trace_type_once<T> repeatedly and hope to make progress in finding variants that are deeper that T. (For instance, after one tracing call on struct T(option<S>) we are not going to look into S ever again because it has a format: https://github.com/novifinancial/serde-reflection/blob/master/serde-reflection/src/de.rs#L199)

    Moving this issue across from https://github.com/novifinancial/serde-reflection/issues/104

    enhancement 
    opened by jerel 2
  • [Dart] Remove unnecessary

    [Dart] Remove unnecessary "Item" suffix from enum variant names

    Summary

    My original implementation of Dart followed one of the other language's enum implementations in that it appended Item to the name of each variant. After using it for a while it turns out it's rather annoying and seems to be wholly unnecessary as the enum name is prepended to each variant when generating class based enums and this seems to avoid any chance of collision. Considering that Dart is still considered "under development" I figured it was a good time to walk this back.

    For Rust enum:

    enum Choice {
      A,
      B,
      C
    }
    

    Current output:

    abstract class Choice {}
    
    class ChoiceAItem extends Choice {}
    class ChoiceBItem extends Choice {}
    class ChoiceCItem extends Choice {} 
    

    This PR's output:

    abstract class Choice {}
    
    class ChoiceA extends Choice {}
    class ChoiceB extends Choice {}
    class ChoiceC extends Choice {} 
    

    Test Plan

    Uses existing test.

    opened by jerel 1
Owner
Zefchain Labs
Zefchain Labs
Esri JSON struct definitions and serde integration.

serde_esri Esri JSON parsing library. This crate provides representations of Esri JSON objects with serde::Deserialize and serde::Serialize trait impl

Josiah Parry 5 Nov 23, 2023
Serialize/Deserialize tch-rs types with serde

tch-serde: Serialize/Deserialize tch-rs types with serde This crate provides {ser,de}ialization methods for tch-rs common types. docs.rs | crates.io U

null 4 Apr 3, 2022
This library implements a type macro for a zero-sized type that is Serde deserializable only from one specific value.

Monostate This library implements a type macro for a zero-sized type that is Serde deserializable only from one specific value. [dependencies] monosta

David Tolnay 125 Dec 26, 2022
An auxiliary library for the serde crate.

An auxiliary library for the serde crate.

Victor Polevoy 98 Jan 2, 2023
Serde serializatsiya va deserializatsiyasi yordamida qilingan VCard JSON generatori

Vicardi Serde serializatsiya va deserializatsiyasi yordamida qilingan VCard JSON generatori Haqida Bizning CCTLD tomonidan ishlab chiqilgan sistema IC

UZINFOCOM 6 Dec 20, 2022
Tools for working with Twitter JSON data

Twitter stream user info extractor This project lets you parse JSON data from the Twitter API or other sources to extract some basic user information,

Travis Brown 4 Apr 21, 2022
A node package based on jsonschema-rs for performing JSON schema validation

A node package based on jsonschema-rs for performing JSON schema validation.

dxd 49 Dec 18, 2022
A easy and declarative way to test JSON input in Rust.

assert_json A easy and declarative way to test JSON input in Rust. assert_json is a Rust macro heavily inspired by serde json macro. Instead of creati

Charles Vandevoorde 8 Dec 5, 2022
Jsonptr - Data structures and logic for resolving, assigning, and deleting by JSON Pointers

jsonptr - JSON Pointers for Rust Data structures and logic for resolving, assigning, and deleting by JSON Pointers (RFC 6901). Usage Resolve JSON Poin

Chance 38 Aug 28, 2022
Read and write ID3 tags with machine-readable input and output

ID3-JSON This project's goal is to provide an easy way to read and write ID3 tags with a consistent input and output. The existing tools I've found re

Andrew Radev 4 Jan 7, 2023
JSON parser which picks up values directly without performing tokenization in Rust

Pikkr JSON parser which picks up values directly without performing tokenization in Rust Abstract Pikkr is a JSON parser which picks up values directl

Pikkr 615 Dec 29, 2022
Strongly typed JSON library for Rust

Serde JSON   Serde is a framework for serializing and deserializing Rust data structures efficiently and generically. [dependencies] serde_json = "1.0

null 3.6k Jan 5, 2023
Rust port of simdjson

SIMD Json for Rust   Rust port of extremely fast simdjson JSON parser with serde compatibility. readme (for real!) simdjson version Currently tracking

null 737 Dec 30, 2022
JSON implementation in Rust

json-rust Parse and serialize JSON with ease. Changelog - Complete Documentation - Cargo - Repository Why? JSON is a very loose format where anything

Maciej Hirsz 500 Dec 21, 2022
Rust port of gjson,get JSON value by dotpath syntax

A-JSON Read JSON values quickly - Rust JSON Parser change name to AJSON, see issue Inspiration comes from gjson in golang Installation Add it to your

Chen Jiaju 90 Dec 6, 2022
Get JSON values quickly - JSON parser for Rust

get json values quickly GJSON is a Rust crate that provides a fast and simple way to get values from a json document. It has features such as one line

Josh Baker 160 Dec 29, 2022
This library is a pull parser for CommonMark, written in Rust

This library is a pull parser for CommonMark, written in Rust. It comes with a simple command-line tool, useful for rendering to HTML, and is also designed to be easy to use from as a library.

Raph Levien 1.5k Jan 1, 2023
A rust script to convert a better bibtex json file from Zotero into nice organised notes in Obsidian

Zotero to Obsidian script This is a script that takes a better bibtex JSON file exported by Zotero and generates an organised collection of reference

Sashin Exists 3 Oct 9, 2022
Fontdue - The fastest font renderer in the world, written in pure rust.

Fontdue is a simple, no_std (does not use the standard library for portability), pure Rust, TrueType (.ttf/.ttc) & OpenType (.otf) font rasterizer and layout tool. It strives to make interacting with fonts as fast as possible, and currently has the lowest end to end latency for a font rasterizer.

Joe C 1k Jan 2, 2023