gull/
lib.rs

1#![allow(clippy::new_without_default)]
2#![allow(clippy::needless_borrow)]
3
4/*!
5
6[![Crates.io][crates-badge]][crates-url]
7[![Docs.rs][docs-badge]][docs-url]
8![Rust CI](https://github.com/aaronabramov/gull/workflows/Rust%20CI/badge.svg)
9
10[crates-badge]: https://img.shields.io/crates/v/gull.svg
11[crates-url]: https://crates.io/crates/gull
12[docs-badge]: https://docs.rs/gull/badge.svg
13[docs-url]: https://docs.rs/gull
14
15![gull_header](https://user-images.githubusercontent.com/940133/94375072-8dfb7380-00d6-11eb-8611-a2d8d794ef3b.png)
16
17`Gull` is a tool that takes abstract static type definitions and generates
18static types definitions into multiple languages.
19Currently supported languages: Rust, Hack (PHP), Flow (unstable)
20
21The core assumption is that serializing this type to JSON in any language
22produces a JSON string that can be safely parsed into the same type in another
23language.
24
25The goal is to generate user friendly types that can be used in application logic
26directly. It also copies all associated documentation for each type or struct field
27to every single destination target.
28
29NOTE: This is not an RPC framework and does not support any kind of message passing.
30It only generates types and fully relies on languages implementations of JSON
31serialization while being agnostic to how these strings are passed between environments.
32Resulting JSON strings can be passed through a tmp file on a filesystem, intermediate storage
33in a database, STDIO, JSON string over http or any other RPC protocols (e.g. Thrift) or any
34other methods.
35
36
37Example:
38
39```
40use gull::prelude::*;
41use k9::snapshot;
42
43let mut declarations = Declarations::new();
44
45declarations.add(TypeDeclaration {
46    name: "Frame",
47    docs: "Frame represents a tuple of an Timestamp (RFC3339) and an ID",
48    config: vec![TypeDeclarationConfig::RustAttribute("#[derive(Copy, Clone)]")],
49    generic_params: vec![],
50    value: DeclarationValue::TTuple(TTuple {
51        items: vec![
52            TupleItem::TPrimitive(TPrimitive::String),
53            TupleItem::TPrimitive(TPrimitive::Ti64),
54        ],
55    }),
56});
57
58snapshot!(
59        declarations.codegen_rust().unwrap().trim(),
60        "
61#[derive(Copy, Clone)]
62/// Frame represents a tuple of an Timestamp (RFC3339) and an ID
63pub type Frame = (String, i64);
64"
65);
66
67snapshot!(
68        declarations.codegen_hack().unwrap().trim(),
69        "
70<?hh
71
72// Frame represents a tuple of an Timestamp (RFC3339) and an ID
73type Frame = (string, int);
74"
75);
76
77snapshot!(
78        declarations.codegen_flow().unwrap().trim(),
79        "
80// Frame represents a tuple of an Timestamp (RFC3339) and an ID
81export type Frame = [string, number];
82"
83    );
84```
85
86for more examples see `gull/e2e/basic_codegen_test.rs`
87
88These types can be safely passed across the boundaries when de\serialized to
89and from JSON.
90
91```dont_run
92// In rust
93use generated_types::Frame;
94let thing: Frame = ("2020-01-01:00:00:00Z", 1);
95let json = serde_json::to_string(&thing).unwrap();
96write_to_file("/tmp/my_thing.json", &json);
97
98// in JS
99import type {Frame} from './generated_types.js';
100const getFrame = (file_path: string): Frame => {
101    return JSON.parse(read_file(file_path));
102}
103const json: Frame = getFrame("/tmp/my_thing.json");
104
105```
106 */
107
108mod codegen;
109mod definitions;
110
111pub mod generator;
112#[cfg(feature = "sign_source")]
113pub mod sign_source;
114
115pub use generator::write_generated;
116// pub use macros::EnumSerialization;
117
118pub mod prelude {
119    pub use crate::codegen::*;
120    pub use crate::definitions::builders::*;
121    pub use crate::definitions::declarations::*;
122    pub use crate::definitions::*;
123    pub use crate::generator::*;
124}
125
126#[cfg(test)]
127mod e2e;