### Install cargo-typify via Cargo Source: https://github.com/oxidecomputer/typify/blob/main/cargo-typify/README.md Provides the command to install the `cargo-typify` utility globally using Rust's package manager, `cargo`. This tool is essential for schema-to-code generation. ```console cargo install cargo-typify ``` -------------------------------- ### Install rustfmt Component Source: https://github.com/oxidecomputer/typify/blob/main/cargo-typify/README.md Shows how to install the `rustfmt` component using `rustup`. `rustfmt` is a required dependency for `cargo-typify` to format the generated Rust code correctly. ```console rustup component add rustfmt ``` -------------------------------- ### Typify Rust Macro: Declarative Crate Policy Configuration Source: https://github.com/oxidecomputer/typify/blob/main/README.md This Rust macro example demonstrates a declarative way to configure `typify`'s behavior for importing types. It specifies the schema source, sets the policy for unknown crates to `Allow`, and defines specific crate versions to be used, simplifying the integration of external types. ```Rust typify::import_types!( schema = "schema.json", unknown_crates = Allow, crates = { "oxnet" = "1.0.0" } ) ``` -------------------------------- ### Specify Custom Map Types in Typify Settings Source: https://github.com/oxidecomputer/typify/blob/main/README.md Provides examples of fully qualified Rust paths used to configure Typify's type generation to use alternative map types, such as `BTreeMap` or `IndexMap`, via the `TypeSpaceSettings::with_map_type` function for enhanced flexibility. ```Rust ::std::collections::BTreeMap ``` ```Rust ::indexmap::IndexMap ``` -------------------------------- ### JSON Schema for Bounded Integer Example Source: https://github.com/oxidecomputer/typify/blob/main/README.md An example JSON schema demonstrating a bounded integer type with `minimum` and `maximum` constraints. This snippet highlights a known limitation where `typify` currently does not enforce these value constraints in the generated Rust types, meaning the Rust type will not inherently restrict values to this range. ```json { "type": "integer", "minimum": 1, "maximum": 6 } ``` -------------------------------- ### Cargo Typify Options Reference Source: https://github.com/oxidecomputer/typify/blob/main/cargo-typify/README.md Comprehensive documentation for the command-line arguments of the `cargo typify` tool, outlining how to control output, enable/disable builder pattern generation, and add custom derive macros to generated types. ```APIDOC cargo typify --help: See for a complete list of options. --output : Overrides the default output file. Default: Replaces input file extension with .rs. Special Value: Use '-' for stdout. --no-builder: Disables struct builder generation. Default: --builder (builder generation is enabled by default). --additional-derive : Adds the specified derive macro to all generated types. Usage: May be specified more than once to add multiple derives. ``` -------------------------------- ### Typify CLI: Configuring Crate Policy and Versions Source: https://github.com/oxidecomputer/typify/blob/main/README.md This console command illustrates how to use the `cargo typify` CLI tool to control the handling of unknown crates and specify exact versions for known crates. The `--unknown-crates allow` flag permits the use of types from unlisted crates, while `--crate oxnet@1.0.0` explicitly includes a specific crate version. ```Console $ cargo typify --unknown-crates allow --crate oxnet@1.0.0 ... ``` -------------------------------- ### Format Rust Code with prettyplease Source: https://github.com/oxidecomputer/typify/blob/main/README.md Shows how to format generated Rust code using `prettyplease`. This approach is ideal for `build.rs` scripts where `rustfmt` might not be available as a transitive dependency, ensuring self-contained formatting within the build process. ```rust prettyplease::unparse(&syn::parse2::(typespace.to_stream())?) ``` -------------------------------- ### Instantiate Rust Struct Using Generated Builder Source: https://github.com/oxidecomputer/typify/blob/main/cargo-typify/README.md This Rust code snippet demonstrates how to instantiate a struct using the builder pattern generated by `cargo typify`. The builder allows for method chaining to set fields, improving readability and enabling optional field setting before final construction via `try_into()`. ```rust let xy: MyStruct = MyStruct::builder().x_coord(x).y_coord(y).try_into(); ``` -------------------------------- ### Command-line Interface for `cargo typify` Source: https://github.com/oxidecomputer/typify/blob/main/cargo-typify/tests/outputs/help.txt Provides an overview of the `cargo typify` command, its arguments, and various options for configuring Rust code generation from JSON Schema. This tool is essential for automating the creation of Rust data structures based on schema definitions. ```APIDOC Usage: cargo typify [OPTIONS] Arguments: Description: The input file to read from Options: -b, --builder Description: Whether to include a builder-style interface, this is the default -B, --no-builder Description: Inverse of `--builder`. When set the builder-style interface will not be included -a, --additional-derive Description: Add an additional derive macro to apply to all defined types -o, --output Description: The output file to write to. If not specified, the input file name will be used with a `.rs` extension. If `-` is specified, the output will be written to stdout. --crate Description: Specify each crate@version that can be assumed to be in use for types found in the schema with the x-rust-type extension --map-type Description: Specify the map like type to use --unknown-crates Description: Specify the policy unknown crates found in schemas with the x-rust-type extension Possible values: generate, allow, deny -h, --help Description: Print help (see a summary with '-h') -V, --version Description: Print version ``` -------------------------------- ### Format Rust Code with rustfmt-wrapper Source: https://github.com/oxidecomputer/typify/blob/main/README.md Demonstrates how to format generated Rust code using `rustfmt-wrapper`. This method is suitable for code intended to be checked into a repository alongside hand-written code, often used in `xtask` or standalone code generators like `cargo-typify`. ```rust rustfmt_wrapper::rustfmt(typespace.to_stream().to_string())? ``` -------------------------------- ### Typify Rust Builder: Programmatic Crate Policy Configuration Source: https://github.com/oxidecomputer/typify/blob/main/README.md This Rust code snippet shows how to programmatically configure `typify`'s type space settings using the `TypeSpaceSettings` builder. It demonstrates setting a policy to allow unknown crates and adding a specific crate with its version, providing fine-grained control over type generation and reuse. ```Rust let mut settings = typify::TypeSpaceSettings::default(); settings.with_unknown_crates(typify::UnknownPolicy::Allow) .with_crate("oxnet", typify::CrateVers::Version("1.0.0".parse().unwrap())); ``` -------------------------------- ### Convert JSON Schema to Rust Code Source: https://github.com/oxidecomputer/typify/blob/main/cargo-typify/README.md Illustrates the primary usage of `cargo-typify` to generate Rust type definitions from a specified JSON Schema file, `my_types.json`. ```console $ cargo typify my_types.json ``` -------------------------------- ### Generate Rust Types with `import_types!` Macro Source: https://github.com/oxidecomputer/typify/blob/main/README.md Demonstrates how to use the `import_types!` macro to directly generate Rust types from a JSON Schema file within a Rust program, simplifying type integration during compilation. ```Rust import_types!("types.json") ``` -------------------------------- ### JSON Schema: `x-rust-type` with Generic Type Parameters Source: https://github.com/oxidecomputer/typify/blob/main/README.md This JSON schema illustrates how the `x-rust-type` extension can specify generic type parameters using the `parameters` array. Each element in this array is a schema reference, allowing `typify` to correctly generate or reuse Rust types with their corresponding generic arguments, such as `util::Sprocket`. ```JSON { "$defs": { "Sprocket": { "type": "object", "properties": { .. }, "x-rust-type": { "crate": "util", "version": "0.1.0", "path": "util::Sprocket", "parameters": [ { "$ref": "#/$defs/Gizmo" } ] } }, "Gizmo": { "type": "object", "properties": { .. }, "x-rust-type": { "crate": "util", "version": "0.1.0", "path": "util::Gizmo" } } } } ``` -------------------------------- ### JSON Schema: `x-rust-type` Extension for Rust Type Metadata Source: https://github.com/oxidecomputer/typify/blob/main/README.md This JSON schema snippet demonstrates the `x-rust-type` extension, which embeds metadata about the original Rust type. It includes the crate name, version requirements, and the full module path, allowing `typify` to reuse existing Rust types instead of generating new ones. ```JSON { "type": "object", "properties": { .. }, "x-rust-type": { "crate": "crate-o-types", "version": "1.0.0", "path": "crate_o_types::some_mod::SomeType" } } ``` -------------------------------- ### x-rust-type Extension Schema Definition Source: https://github.com/oxidecomputer/typify/blob/main/README.md Defines the JSON schema for the `x-rust-type` extension, which allows mapping Rust types within JSON schemas. It specifies required fields like `crate`, `path`, and `version` for Rust dependency and type identification, along with optional `parameters` for generic type arguments. ```json { "description": "schema for the x-rust-type extension", "type": "object", "properties": { "crate": { "type": "string", "pattern": "^[a-zA-Z0-9_-]+$" }, "version": { "description": "semver requirements per a Cargo.toml dependencies entry", "type": "string" }, "path": { "type": "string", "pattern": "^[a-zA-Z0-9_]+(::[a-zA-Z0-9+]+)*$" }, "parameters": { "type": "array", "items": { "$ref": "#/definitions/Schema" } } }, "required": [ "crate", "path", "version" ] } ``` -------------------------------- ### JSON Schema Definition for UUID String Format Source: https://github.com/oxidecomputer/typify/blob/main/README.md Illustrates a JSON Schema definition for a string type with a 'uuid' format. Typify recognizes this format and translates it into a `uuid::Uuid` Rust type, requiring the `uuid` crate as a dependency. ```JSON Schema { "type": "string", "format": "uuid" } ``` -------------------------------- ### Convert TypeSpace to String Without Formatting Source: https://github.com/oxidecomputer/typify/blob/main/README.md Illustrates the direct conversion of a `TypeSpace` object to a string without any additional formatting. This method is generally not recommended unless the generated code will never be human-readable, as it lacks standard Rust code style. ```rust typespace.to_stream().to_string() ``` -------------------------------- ### Generate Rust Types from JSON Schema using Typify Source: https://github.com/oxidecomputer/typify/blob/main/cargo-typify/README.md This Rust code is automatically generated by the `typify` tool from the `id-or-name.json` schema. It defines the `IdOrName` enum, which can hold either a `uuid::Uuid` or a `Name` struct, and the `Name` struct, which wraps a `String`. The generated code includes various trait implementations like `FromStr`, `TryFrom`, `Display`, `Deref`, and `serde::Deserialize` to ensure type safety, validation, and ease of use in Rust, reflecting the constraints defined in the original JSON schema. ```rust #![allow(clippy::redundant_closure_call)] #![allow(clippy::needless_lifetimes)] #![allow(clippy::match_single_binding)] #![allow(clippy::clone_on_copy)] #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] #[serde(untagged)] pub enum IdOrName { Id(uuid::Uuid), Name(Name), } impl From<&IdOrName> for IdOrName { fn from(value: &IdOrName) -> Self { value.clone() } } impl std::str::FromStr for IdOrName { type Err = &'static str; fn from_str(value: &str) -> Result { if let Ok(v) = value.parse() { Ok(Self::Id(v)) } else if let Ok(v) = value.parse() { Ok(Self::Name(v)) } else { Err("string conversion failed for all variants") } } } impl std::convert::TryFrom<&str> for IdOrName { type Error = &'static str; fn try_from(value: &str) -> Result { value.parse() } } impl std::convert::TryFrom<&String> for IdOrName { type Error = &'static str; fn try_from(value: &String) -> Result { value.parse() } } impl std::convert::TryFrom for IdOrName { type Error = &'static str; fn try_from(value: String) -> Result { value.parse() } } impl ::std::fmt::Display for IdOrName { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Id(x) => x.fmt(f), Self::Name(x) => x.fmt(f), } } } impl From for IdOrName { fn from(value: uuid::Uuid) -> Self { Self::Id(value) } } impl From for IdOrName { fn from(value: Name) -> Self { Self::Name(value) } } #[doc = "Names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID though they may contain a UUID."] #[derive(Clone, Debug, Serialize)] pub struct Name(String); impl std::ops::Deref for Name { type Target = String; fn deref(&self) -> &String { &self.0 } } impl From for String { fn from(value: Name) -> Self { value.0 } } impl From<&Name> for Name { fn from(value: &Name) -> Self { value.clone() } } impl std::str::FromStr for Name { type Err = &'static str; fn from_str(value: &str) -> Result { if value.len() > 63usize { return Err("longer than 63 characters"); } if regress::Regex::new("^(?![0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$)^[a-z][a-z0-9-]*[a-zA-Z0-9]$") .unwrap() .find(value) .is_none() { return Err("doesn't match pattern \"^(?![0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$)^[a-z][a-z0-9-]*[a-zA-Z0-9]$\""); } Ok(Self(value.to_string())) } } impl std::convert::TryFrom<&str> for Name { type Error = &'static str; fn try_from(value: &str) -> Result { value.parse() } } impl std::convert::TryFrom<&String> for Name { type Error = &'static str; fn try_from(value: &String) -> Result { value.parse() } } impl std::convert::TryFrom for Name { type Error = &'static str; fn try_from(value: String) -> Result { value.parse() } } impl<'de> serde::Deserialize<'de> for Name { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { String::deserialize(deserializer)? .parse() .map_err(|e: &'static str| ::custom(e.to_string())) } } ``` -------------------------------- ### Define IdOrName and Name JSON Schemas Source: https://github.com/oxidecomputer/typify/blob/main/cargo-typify/README.md This JSON schema defines two primary types: `IdOrName` and `Name`. `IdOrName` is a `oneOf` type, allowing it to be either a UUID (Id) or a custom `Name`. The `Name` type specifies a string with strict pattern matching for valid characters, length constraints, and ensures it cannot be a UUID. ```json { "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "IdOrName": { "oneOf": [ { "title": "Id", "allOf": [ { "type": "string", "format": "uuid" } ] }, { "title": "Name", "allOf": [ { "$ref": "#/definitions/Name" } ] } ] }, "Name": { "title": "A name unique within the parent collection", "description": "Names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID though they may contain a UUID.", "type": "string", "pattern": "^(?![0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$)^[a-z][a-z0-9-]*[a-zA-Z0-9]$", "maxLength": 63 } } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.