1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0

//! This crate aims to compile the data formats extracted from Rust by [`serde_reflection`](https://crates.io/crates/serde_reflection)
//! into type definitions for other programming languages.
//!
//! ## Supported Languages
//!
//! The following target languages are currently supported:
//!
//! * C++ 17
//! * Java 8
//! * Python 3
//! * Rust 2018
//!
//! In progress:
//! * Go >= 1.13
//!
//! ## Supported Encodings
//!
//! Type definitions in a target language are meant to be used together with a runtime library that
//! provides (de)serialization in a particular [Serde encoding format](https://serde.rs/#data-formats).
//!
//! This crate provides easy-to-deploy runtime libraries for the following binary formats, in all supported languages:
//!
//! * [Bincode](https://docs.rs/bincode/1.3.1/bincode/),
//! * [Libra Canonical Serialization](https://libra.github.io/libra/libra_canonical_serialization/index.html) ("LCS" for short).
//!
//! ## Quick Start with Python and Bincode
//!
//! In the following example, we transfer a `Test` value from Rust to Python using [`bincode`](https://docs.rs/bincode/1.3.1/bincode/).
//! ```
//! use serde::{Deserialize, Serialize};
//! use serde_reflection::{Registry, Samples, Tracer, TracerConfig};
//! use std::io::Write;
//!
//! #[derive(Serialize, Deserialize)]
//! struct Test {
//!     a: Vec<u64>,
//!     b: (u32, u32),
//! }
//!
//! # fn main() -> Result<(), std::io::Error> {
//! // Obtain the Serde format of `Test`. (In practice, formats are more often read from a file.)
//! let mut tracer = Tracer::new(TracerConfig::default());
//! tracer.trace_type::<Test>(&Samples::new()).unwrap();
//! let registry = tracer.registry().unwrap();
//!
//! // Create Python class definitions.
//! let mut source = Vec::new();
//! let inner = serde_generate::CodeGeneratorConfig::new("testing".to_string());
//! let config = serde_generate::python3::CodeGenerator::new(&inner);
//! config.output(&mut source, &registry)?;
//!
//! assert_eq!(
//! #  "\n".to_string() + &
//!     String::from_utf8_lossy(&source),
//!     r#"
//! ## pyre-strict
//! from dataclasses import dataclass
//! import typing
//! import serde_types as st
//!
//! @dataclass
//! class Test:
//!     a: typing.Sequence[st.uint64]
//!     b: typing.Tuple[st.uint32, st.uint32]
//!
//! "#.to_string());
//!
//! // Append some test code to demonstrate Bincode deserialization
//! // using the runtime in `serde_generate/runtime/python/bincode`.
//! writeln!(
//!     source,
//!     r#"
//! import bincode
//!
//! value, _ = bincode.deserialize(bytes.fromhex("{}"), Test)
//! assert value == Test(a=[4, 6], b=(3, 5))
//! "#,
//!     hex::encode(&bincode::serialize(&Test { a: vec![4, 6], b: (3, 5) }).unwrap()),
//! )?;
//!
//! // Execute the Python code.
//! let mut child = std::process::Command::new("python3")
//!     .arg("-")
//!     .env("PYTHONPATH", std::env::var("PYTHONPATH").unwrap_or_default() + ":runtime/python")
//!     .stdin(std::process::Stdio::piped())
//!     .spawn()?;
//! child.stdin.as_mut().unwrap().write_all(&source)?;
//! let output = child.wait_with_output()?;
//! assert!(output.status.success());
//! # Ok(())
//! # }
//! ```
//!
//! ## Binary Tool
//!
//! In addition to a Rust library, this crate provides a binary tool `serdegen` to process Serde formats
//! saved on disk.
//!
//! Assuming that a `serde_reflection::Registry` object has been serialized in a YAML file `test.yaml`,
//! the following command will generate Python class definitions and write them into `test.py`:
//! ```bash
//! cargo run -p serde-generate -- --language python3 test.yaml > test.py
//! ```
//!
//! To create a python module `test` and install the bincode runtime in a directory `$DEST`, you may run:
//! ```bash
//! cargo run -p serde-generate -- --language python3 --with-runtimes serde bincode --module-name test --target-source-dir "$DEST" test.yaml
//! ```
//!
//! See the help message of the tool with `--help` for more options.
//!
//! Note: Outside of this repository, you may install the tool with `cargo install serde-generate` then use `$HOME/.cargo/bin/serdegen`.

/// Dependency analysis and topological sort for Serde formats.
pub mod analyzer;
/// Support for code-generation in C++
pub mod cpp;
/// Utility function to generate indented text
pub mod golang;
/// Support for code-generation in Go
pub mod indent;
/// Support for code-generation in Java
pub mod java;
/// Support for code-generation in Python 3
pub mod python3;
/// Support for code-generation in Rust
pub mod rust;

#[doc(hidden)]
/// Utility functions to help testing code generators.
pub mod test_utils;

/// Common logic for codegen.
mod common;
/// Common configuration objects and traits used in public APIs.
mod config;

pub use config::*;