Code generation for Conjure definitions.
Examples
Code generation via a build script, assuming we have a service-api.conjure.json
file in the crate root:
build.rs:
use std::env;
use std::path::Path;
fn main() {
let input = "service-api.conjure.json";
let output = Path::new(&env::var_os("OUT_DIR").unwrap()).join("service_api");
println!("cargo:rerun-if-changed={}", input);
conjure_codegen::Config::new()
.run_rustfmt(false)
.strip_prefix("com.foobar.service".to_string())
.generate_files(input, output)
.unwrap();
}
src/lib.rs:
mod service_api {
include!(concat!(env!("OUT_DIR"), "/service_api/mod.rs"));
}
Types
Builtin
Builtin types map directly to existing Rust types:
Conjure | Rust |
---|---|
string |
String |
datetime |
chrono::DateTime<Utc> |
integer |
i32 |
double |
f64 |
safelong |
conjure_object::SafeLong |
binary |
serde_bytes::ByteBuf |
any |
serde_value::Value |
boolean |
bool |
uuid |
uuid::Uuid |
rid |
conjure_object::ResourceIdentifier |
bearertoken |
conjure_object::BearerToken |
optional<T> |
Option<T> |
list<T> |
Vec<T> |
set<T> |
BTreeSet<T> |
map<K, V> |
BTreeMap<K, V> |
Many of these are exposed by the conjure-object
crate, which is a required dependency of crates containing the
generated code.
Objects
Conjure objects turn into Rust structs along with builders used to construct them:
# use ;
let object = builder
.string
.integer
.double_value
.optional_item
.items
.alias
.build;
assert_eq!;
assert_eq!;
Objects with 3 or fewer fields also have an explicit constructor:
# use BooleanExample;
let object = new;
assert_eq!;
The generated structs implement Debug
, Clone
, PartialEq
, PartialOrd
, Serialize
, and Deserialize
. They
also implement Eq
, Ord
, and Hash
if they do not contain a double
value, and Copy
if they consist entirely
of copyable primitive types.
Unions
Conjure unions turn into Rust enums. By default, unions are extensible through an additional Unknown
variant.
This allows unions to be forward-compatible by allowing clients to deserialize variants they don't yet know about
and reserialize them properly:
# use UnionTypeExample;
# let union_value = If;
match union_value
The generated enums implement Debug
, Clone
, PartialEq
, PartialOrd
, Serialize
, and Deserialize
. They
also implement Eq
, Ord
, and Hash
if they do not contain a double
value. Union variants which are themselves
unions are boxed in the generated enum to avoid self-referential type definitions.
Enums
Conjure enums turn into Rust enums. By default, enums are extensible. This allows enums to be forward-compatible by allowing clients to deserialize variants they don't yet know about and reserialize them properly:
# use EnumExample;
# let enum_value = One;
match enum_value
The generated enums implement Debug
, Clone
, PartialEq
, Eq
, PartialOrd
, Ord
, Hash
, Display
,
Serialize
, and Deserialize
.
Aliases
Conjure aliases turn into Rust newtype structs that act like their inner value:
# use StringAliasExample;
let alias_value = StringAliasExample;
assert!;
The generated structs implement Deref
, DerefMut
, Debug
, Clone
, PartialEq
, PartialOrd
, Serialize
, and
Deserialize
. They also implement Eq
, Ord
, and Hash
if they do not contain a double
value, Copy
if they
wrap a copyable primitive type, Default
if they wrap a type implementing Default
, and Display
if they wrap a
type implementing Display
.