Showing preview only (3,099K chars total). Download the full file or copy to clipboard to get everything.
Repository: specta-rs/specta
Branch: main
Commit: a580a9865656
Files: 279
Total size: 2.9 MB
Directory structure:
gitextract_unw2xfqn/
├── .github/
│ ├── FUNDING.yml
│ ├── dependabot.yml
│ ├── features.js
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── .rustfmt.toml
├── .taplo.toml
├── AGENTS.md
├── Cargo.toml
├── LICENSE
├── README.md
├── examples/
│ ├── basic-ts/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ ├── collect/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ └── scratchpad/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── specta/
│ ├── Cargo.toml
│ ├── build.rs
│ └── src/
│ ├── collect.rs
│ ├── datatype/
│ │ ├── attributes.rs
│ │ ├── enum.rs
│ │ ├── fields.rs
│ │ ├── function.rs
│ │ ├── generic.rs
│ │ ├── list.rs
│ │ ├── literal.rs
│ │ ├── map.rs
│ │ ├── named.rs
│ │ ├── primitive.rs
│ │ ├── reference.rs
│ │ ├── struct.rs
│ │ └── tuple.rs
│ ├── datatype.rs
│ ├── docs.md
│ ├── format.rs
│ ├── function/
│ │ ├── arg.rs
│ │ ├── result.rs
│ │ └── specta_fn.rs
│ ├── function.rs
│ ├── internal.rs
│ ├── lib.rs
│ ├── type/
│ │ ├── impls.rs
│ │ ├── legacy_impls.rs
│ │ └── macros.rs
│ ├── type.rs
│ └── types.rs
├── specta-go/
│ ├── Cargo.toml
│ ├── bindings.go
│ └── src/
│ ├── error.rs
│ ├── go.rs
│ ├── lib.rs
│ ├── primitives.rs
│ └── reserved_names.rs
├── specta-jsonschema/
│ ├── Cargo.toml
│ ├── examples/
│ │ └── jsonschema.rs
│ ├── src/
│ │ ├── error.rs
│ │ ├── import.rs
│ │ ├── json_schema.rs
│ │ ├── layout.rs
│ │ ├── lib.rs
│ │ ├── primitives.rs
│ │ └── schema_version.rs
│ └── tests/
│ └── basic.rs
├── specta-kotlin/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
├── specta-macros/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ ├── lib.rs
│ ├── specta.rs
│ ├── type/
│ │ ├── attr/
│ │ │ ├── container.rs
│ │ │ ├── field.rs
│ │ │ ├── legacy.rs
│ │ │ ├── mod.rs
│ │ │ ├── rustc.rs
│ │ │ └── variant.rs
│ │ ├── enum.rs
│ │ ├── field.rs
│ │ ├── generics.rs
│ │ ├── mod.rs
│ │ ├── serde.rs
│ │ └── struct.rs
│ └── utils.rs
├── specta-openapi/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
├── specta-serde/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ ├── error.rs
│ ├── inflection.rs
│ ├── lib.rs
│ ├── parser.rs
│ ├── phased.rs
│ ├── repr.rs
│ └── validate.rs
├── specta-swift/
│ ├── Cargo.toml
│ ├── README.md
│ ├── Types.swift
│ ├── examples/
│ │ ├── README.md
│ │ ├── advanced_unions.rs
│ │ ├── basic_types.rs
│ │ ├── comments_example.rs
│ │ ├── comprehensive_demo.rs
│ │ ├── configuration_options.rs
│ │ ├── generated/
│ │ │ ├── AdvancedUnions.swift
│ │ │ ├── BasicTypes.swift
│ │ │ ├── CamelCase.swift
│ │ │ ├── CombinedConfig.swift
│ │ │ ├── CommentsExample.swift
│ │ │ ├── ComprehensiveDemo.swift
│ │ │ ├── CustomHeader.swift
│ │ │ ├── CustomTypes.swift
│ │ │ ├── DefaultConfig.swift
│ │ │ ├── OptionalType.swift
│ │ │ ├── PascalCase.swift
│ │ │ ├── ProtocolGenerics.swift
│ │ │ ├── QuestionMark.swift
│ │ │ ├── SimpleTypes.swift
│ │ │ ├── SnakeCase.swift
│ │ │ ├── Spaces2.swift
│ │ │ ├── Spaces4.swift
│ │ │ ├── SpecialTypes.swift
│ │ │ ├── StringEnums.swift
│ │ │ ├── Tabs.swift
│ │ │ ├── TypealiasGenerics.swift
│ │ │ ├── WithProtocols.swift
│ │ │ └── WithSerde.swift
│ │ ├── simple_usage.rs
│ │ ├── special_types.rs
│ │ └── string_enums.rs
│ ├── src/
│ │ ├── error.rs
│ │ ├── lib.rs
│ │ ├── primitives.rs
│ │ └── swift.rs
│ └── tests/
│ ├── Cargo.toml
│ ├── advanced_unions.rs
│ ├── basic.rs
│ ├── common_types.rs
│ ├── comprehensive.rs
│ ├── multiline_comments.rs
│ ├── string_enum_implementation.rs
│ ├── string_enum_test.rs
│ ├── struct_reuse_test.rs
│ ├── struct_variants.rs
│ ├── unions.rs
│ ├── uuid_simple.rs
│ └── uuid_test.rs
├── specta-tags/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
├── specta-typescript/
│ ├── Cargo.toml
│ ├── bindings.ts
│ └── src/
│ ├── branded.rs
│ ├── error.rs
│ ├── exporter.rs
│ ├── jsdoc.rs
│ ├── legacy.rs
│ ├── lib.rs
│ ├── map_keys.rs
│ ├── opaque.rs
│ ├── primitives.rs
│ ├── references.rs
│ ├── reserved_names.rs
│ ├── types.rs
│ └── typescript.rs
├── specta-util/
│ ├── Cargo.toml
│ └── src/
│ ├── array.rs
│ ├── lib.rs
│ ├── remapper.rs
│ └── selection.rs
├── specta-zod/
│ ├── Cargo.toml
│ └── src/
│ ├── error.rs
│ ├── lib.rs
│ ├── opaque.rs
│ ├── primitives.rs
│ ├── references.rs
│ ├── reserved_names.rs
│ ├── types.rs
│ └── zod.rs
└── tests/
├── Cargo.toml
└── tests/
├── bound.rs
├── errors.rs
├── functions.rs
├── jsdoc.rs
├── layouts.rs
├── legacy_impls.rs
├── macro/
│ ├── compile_error.rs
│ └── compile_error.stderr
├── mod.rs
├── references.rs
├── serde_conversions.rs
├── serde_identifiers.rs
├── serde_other.rs
├── snapshots/
│ ├── test__bound__bound-associated-type-issue-138.snap
│ ├── test__jsdoc__export-many-raw.snap
│ ├── test__jsdoc__export-many-serde.snap
│ ├── test__jsdoc__export-many-serde_phases.snap
│ ├── test__jsdoc__export-raw.snap
│ ├── test__jsdoc__export-serde.snap
│ ├── test__jsdoc__export-serde_phases.snap
│ ├── test__jsdoc__inline-raw.snap
│ ├── test__jsdoc__inline-serde.snap
│ ├── test__jsdoc__inline-serde_phases.snap
│ ├── test__jsdoc__jsdoc-export-to-files-both.snap
│ ├── test__jsdoc__jsdoc-export-to-files-raw.snap
│ ├── test__jsdoc__jsdoc-export-to-files-serde.snap
│ ├── test__jsdoc__jsdoc-export-to-files-serde_phases.snap
│ ├── test__jsdoc__jsdoc-export-to-flatfile-raw.snap
│ ├── test__jsdoc__jsdoc-export-to-flatfile-serde.snap
│ ├── test__jsdoc__jsdoc-export-to-flatfile-serde_phases.snap
│ ├── test__jsdoc__jsdoc-export-to-moduleprefixedname-raw.snap
│ ├── test__jsdoc__jsdoc-export-to-moduleprefixedname-serde.snap
│ ├── test__jsdoc__jsdoc-export-to-moduleprefixedname-serde_phases.snap
│ ├── test__jsdoc__jsdoc-export-to-namespaces-raw.snap
│ ├── test__jsdoc__jsdoc-export-to-namespaces-serde.snap
│ ├── test__jsdoc__jsdoc-export-to-namespaces-serde_phases.snap
│ ├── test__jsdoc__primitives-many-inline-raw.snap
│ ├── test__jsdoc__primitives-many-inline-serde.snap
│ ├── test__jsdoc__primitives-many-inline-serde_phases.snap
│ ├── test__jsdoc__reference-raw.snap
│ ├── test__jsdoc__reference-serde.snap
│ ├── test__jsdoc__reference-serde_phases.snap
│ ├── test__layouts__layouts-duplicate-files.snap
│ ├── test__layouts__layouts-duplicate-module-prefixed.snap
│ ├── test__layouts__layouts-duplicate-namespaces.snap
│ ├── test__layouts__layouts-empty-module-path-files.snap
│ ├── test__layouts__layouts-empty-module-path-flat.snap
│ ├── test__layouts__layouts-empty-module-path-module-prefixed.snap
│ ├── test__layouts__layouts-empty-module-path-namespaces.snap
│ ├── test__layouts__layouts-non-duplicate-default.snap
│ ├── test__layouts__layouts-non-duplicate-files.snap
│ ├── test__layouts__layouts-non-duplicate-flat.snap
│ ├── test__layouts__layouts-non-duplicate-module-prefixed.snap
│ ├── test__layouts__layouts-non-duplicate-namespaces.snap
│ ├── test__legacy_impls__legacy_impls.snap
│ ├── test__serde_conversions__serde-conversions-format-phases-exports-field-only-phased-override.snap
│ ├── test__serde_conversions__serde-conversions-format-phases-splits-container-and-dependents.snap
│ ├── test__serde_identifiers__serde-identifiers-field-typescript.snap
│ ├── test__serde_identifiers__serde-identifiers-variant-typescript.snap
│ ├── test__serde_other__serde-other-adjacent-tag-typescript.snap
│ ├── test__serde_other__serde-other-internal-tag-typescript.snap
│ ├── test__swift__swift-export-raw.snap
│ ├── test__swift__swift-export-serde.snap
│ ├── test__swift__swift-export-serde_phases.snap
│ ├── test__types__serde-default-container-typescript.snap
│ ├── test__types__serde-default-field-typescript.snap
│ ├── test__types__serde-mixed-untagged-phased-typescript.snap
│ ├── test__types__serde-mixed-untagged-struct-typescript.snap
│ ├── test__types__serde-mixed-untagged-typescript.snap
│ ├── test__typescript__export-many-raw.snap
│ ├── test__typescript__export-many-serde.snap
│ ├── test__typescript__export-many-serde_phases.snap
│ ├── test__typescript__export-raw.snap
│ ├── test__typescript__export-serde.snap
│ ├── test__typescript__export-serde_phases.snap
│ ├── test__typescript__inline-raw.snap
│ ├── test__typescript__inline-serde.snap
│ ├── test__typescript__inline-serde_phases.snap
│ ├── test__typescript__reference-raw.snap
│ ├── test__typescript__reference-serde.snap
│ ├── test__typescript__reference-serde_phases.snap
│ ├── test__typescript__ts-export-raw.snap
│ ├── test__typescript__ts-export-serde.snap
│ ├── test__typescript__ts-export-serde_phases.snap
│ ├── test__typescript__ts-export-to-files-raw.snap
│ ├── test__typescript__ts-export-to-files-serde.snap
│ ├── test__typescript__ts-export-to-files-serde_phases.snap
│ ├── test__typescript__ts-export-to-flatfile-raw.snap
│ ├── test__typescript__ts-export-to-flatfile-serde.snap
│ ├── test__typescript__ts-export-to-flatfile-serde_phases.snap
│ ├── test__typescript__ts-export-to-moduleprefixedname-raw.snap
│ ├── test__typescript__ts-export-to-moduleprefixedname-serde.snap
│ ├── test__typescript__ts-export-to-moduleprefixedname-serde_phases.snap
│ ├── test__typescript__ts-export-to-namespaces-raw.snap
│ ├── test__typescript__ts-export-to-namespaces-serde.snap
│ └── test__typescript__ts-export-to-namespaces-serde_phases.snap
├── swift.rs
├── types.rs
├── typescript.rs
├── utils.rs
└── zod.rs
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
github: [oscartbeaumont]
custom: ["https://paypal.me/oscartbeaumont"]
================================================
FILE: .github/dependabot.yml
================================================
version: 2
multi-ecosystem-groups:
specta-deps:
schedule:
interval: "weekly"
updates:
- package-ecosystem: "github-actions"
directory: "/"
multi-ecosystem-group: "specta-deps"
patterns: ["*"]
- package-ecosystem: "cargo"
directory: "/"
multi-ecosystem-group: "specta-deps"
patterns: ["*"]
================================================
FILE: .github/features.js
================================================
// This script generates the documentation for the Cargo features from the comments in the `Cargo.toml` file.
// It dumps the result into the `src/docs.md` file. This means the docs are readable in the published version of the crate and also allows the docs to be broken into a separate file (unlike `document-features`)
const fs = require("fs");
const path = require("path");
const START_MARKER = "[//]: # (FEATURE_FLAGS_START)";
const END_MARKER = "[//]: # (FEATURE_FLAGS_END)";
const docsPath = path.join(__dirname, "..", "src", "docs.md");
const cargoToml = fs.readFileSync(
path.join(__dirname, "..", "Cargo.toml"),
"utf8"
);
const docs = fs.readFileSync(docsPath, "utf8");
if (!docs.includes(START_MARKER) || !docs.includes(END_MARKER))
throw new Error("Missing markers in 'docs.md'");
const lines = cargoToml.split("\n").map((line) => line.trim());
const featuresIndex = lines.indexOf("[features]");
if (featuresIndex === -1)
throw new Error("Missing '[features]' in 'Cargo.toml'");
const featuresPart = lines.slice(featuresIndex + 1);
const endIndex = featuresPart.findIndex(
(line) => line.startsWith("[") && line.endsWith("]")
);
const featuresLine = featuresPart.slice(0, endIndex);
let comments = "";
let group = null;
let result = {};
for (const line of featuresLine) {
if (line == "") {
continue;
}
if (line.startsWith("##!")) {
group = "";
result[group] = {};
} else if (line.startsWith("##")) {
comments += line.slice(2).trim() + "\n";
} else if (line.startsWith("#!")) {
group = line.substring(2).trim();
result[group] = {};
} else if (line.startsWith("#")) {
continue;
} else {
const parts = line.split("=");
if (parts.length !== 2) throw new Error(`Invalid feature line: '${line}'`);
if (group !== null) {
result[group][parts[0].trim()] = comments;
comments = "";
}
}
}
let markdown_result = Object.entries(result)
.map(
([name, deps]) =>
`${name}\n\n${Object.entries(deps)
.map(
([name, comment]) =>
`- \`${name}\` - ${comment.replace("\n", " ").trim()}`
)
.join("\n")}`
)
.join("\n\n");
const resultDocs = docs.replace(
docs.substring(
docs.indexOf(START_MARKER),
docs.lastIndexOf(END_MARKER) + END_MARKER.length
),
START_MARKER + "\n" + markdown_result + "\n\n" + END_MARKER
);
fs.writeFileSync(docsPath, resultDocs);
================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
on:
workflow_dispatch:
push:
branches:
- main
pull_request:
env:
CARGO_TERM_COLOR: always
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
- name: Setup
if: matrix.os == 'ubuntu-latest'
run: sudo apt-get update && sudo apt-get install libgtk-3-dev webkit2gtk-4.1 libayatana-appindicator3-dev
- name: Install Rust toolchain
run: rustup toolchain install stable --profile minimal
- name: Rust cache
uses: Swatinem/rust-cache@v2
- name: Build
run: cargo build --all-features
- name: Run tests
run: cargo test --all-features
clippy:
runs-on: ubuntu-latest
permissions:
contents: read
checks: write
pull-requests: write
steps:
- uses: actions/checkout@v6
- name: Setup
run: sudo apt-get update && sudo apt-get install libgtk-3-dev webkit2gtk-4.1 libayatana-appindicator3-dev
- name: Install Rust toolchain
run: rustup toolchain install stable --profile minimal --component clippy
- name: Rust cache
uses: Swatinem/rust-cache@v2
- uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features
================================================
FILE: .gitignore
================================================
# Generated by Cargo
# will have compiled files and executables
target/
test-target/
# These are backup files generated by rustfmt
**/*.rs.bk
# System Files
.DS_Store
# Node
node_modules
.pnpm-debug.log*
*.tsbuildinfo
/packages/*/dist
/bindings.ts
/bindings2.ts
/tests/.temp
# Used by examples as a place to export files.
/specta-typescript/out
================================================
FILE: .rustfmt.toml
================================================
# https://github.com/specta-rs/specta/pull/222
================================================
FILE: .taplo.toml
================================================
[formatting]
column_width = 150
================================================
FILE: AGENTS.md
================================================
Specta is a Rust library for easily exporting Rust types to other languages (TypeScript, Swift, Rust, OpenAPI, etc.). It's a workspace with multiple crates:
```
specta/
├── specta/ # Core library
├── specta-macros/ # Macros for the core library
├── specta-typescript/ # TypeScript exporter (stable)
├── specta-swift/ # Swift exporter (stable)
├── specta-openapi/ # OpenAPI (partial)
├── specta-serde/ # Serde utilities
├── specta-util/ # Utilities for end-users. Less semver guarantees.
├── tests/ # Integration tests
├── Cargo.toml # Workspace manifest
```
Specta is format agnostic so the `specta` and `specta-macros` crate should avoid hardcoding serde-specific behaviors.
We use `insta` for snapshot testing
Use Rust 2024 edition
Document feature gates with `#[cfg_attr(docsrs, doc(cfg(feature = "...")))]`
Prefer to put tests in the dedicated crate
Don't run `cargo doc --open` as it opens a browser you can't read. Maybe prefer a web fetch to https://docs.rs/{crate_name}
Prefer Rust module guidelines including using `module.rs` instead of `module/mod.rs`
When testing bugs create a unit test to ensure it's fixed. If I give you a GitHub link can you include it in comments.
Don't use `/tmp` for temporary projects in should stay within the workspace.
You are a senior engineer. You should follow Clippy and Rust best practices. Write code that is concise and readable. Make use of Rust's method chaining where it would result in cleaner code.
================================================
FILE: Cargo.toml
================================================
[workspace]
members = ["specta", "specta-*", "tests", "examples/*"]
resolver = "2"
[workspace.lints.rust]
unsafe_code = { level = "warn", priority = -1 } # ctor requires unsafe but is an optional feature
missing_docs = { level = "warn", priority = -1 }
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(is_nightly)'] }
[workspace.lints.clippy]
all = { level = "warn", priority = -1 }
cargo = { level = "warn", priority = -1 }
unwrap_used = { level = "warn", priority = -1 }
panic = { level = "warn", priority = -1 }
todo = { level = "warn", priority = -1 }
panic_in_result_fn = { level = "warn", priority = -1 }
multiple_crate_versions = { level = "allow", priority = 0 }
# I hate these. For internal code I don't care.
too_many_arguments = { level = "allow", priority = 0 }
type_complexity = { level = "allow", priority = 0 }
[profile.dev.package]
insta.opt-level = 3
similar.opt-level = 3
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2022 Oscar Beaumont
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
<div align="center">
<img height="150" src=".github/logo.png" alt="Specta Logo"></img>
<h1>Specta</h1>
<p><b>Easily export your Rust types to other languages</b></p>
<a href="https://discord.com/invite/5M6fpszrry"><img src="https://img.shields.io/discord/1011665225809924136?style=flat-square" alt="Discord"></a>
<a href="https://crates.io/crates/specta"><img src="https://img.shields.io/crates/d/specta?style=flat-square" alt="Crates.io"></a>
<a href="https://crates.io/crates/specta"><img src="https://img.shields.io/crates/v/specta.svg?style=flat-square"
alt="crates.io" /></a>
<a href="https://docs.rs/specta"><img src="https://img.shields.io/badge/docs-latest-blue.svg?style=flat-square" alt="docs.rs" /></a>
<a href="/LICENSE.md"><img src="https://img.shields.io/crates/l/specta?style=flat-square" alt="License"></a>
</div>
<br>
## Features
- Export structs and enums to multiple languages
- Get function types to use in libraries like [tauri-specta](https://github.com/specta-rs/tauri-specta)
- Supports wide range of common crates in Rust ecosystem
- Supports type inference - can determine type of `fn demo() -> impl Type`
## Language Support
| Language | Status | Exporter | Features |
| --------------- | -------------- | ----------------------------------------------------------------- | ------------------------------------------------- |
| **TypeScript** | ✅ **Stable** | [`specta-typescript`](https://crates.io/crates/specta-typescript) | Full type support, generics, unions |
| **Swift** | ✅ **Stable** | [`specta-swift`](https://crates.io/crates/specta-swift) | Idiomatic Swift, custom Codable, Duration support |
| **Rust** | 🚧 **Partial** | [`specta-rust`](https://crates.io/crates/specta-rust) | Basic types work, structs/enums in progress |
| **OpenAPI** | 🚧 **Partial** | [`specta-openapi`](https://crates.io/crates/specta-openapi) | Primitives work, complex types in progress |
| **Go** | 🚧 **Planned** | [`specta-go`](https://crates.io/crates/specta-go) | Go structs and interfaces |
| **Kotlin** | 🚧 **Planned** | [`specta-kotlin`](https://crates.io/crates/specta-kotlin) | Kotlin data classes and sealed classes |
| **JSON Schema** | 🚧 **Planned** | [`specta-jsonschema`](https://crates.io/crates/specta-jsonschema) | JSON Schema generation |
| **Zod** | 🚧 **Planned** | [`specta-zod`](https://crates.io/crates/specta-zod) | Zod schema validation |
| **Python** | 🚧 **Planned** | `specta-python` | Python dataclasses and type hints |
| **C#** | 🚧 **Planned** | `specta-csharp` | C# classes and enums |
| **Java** | 🚧 **Planned** | `specta-java` | Java POJOs and enums |
### Legend
- ✅ **Stable**: Production-ready with comprehensive test coverage
- 🚧 **Partial**: Basic functionality implemented, complex types in progress
- 🚧 **Planned**: In development or planned for future release
## Implementation Status
The Specta ecosystem is actively developed with varying levels of completeness:
- **Production Ready (2)**: TypeScript and Swift exporters are fully functional with comprehensive test coverage
- **Partially Implemented (2)**: Rust and OpenAPI exporters have basic functionality working, with complex types in progress
- **Planned (7)**: Go, Kotlin, JSON Schema, Zod, Python, C#, and Java exporters are in development
For the most up-to-date status of each exporter, check the individual crate documentation and issue trackers.
## Ecosystem
Specta can be used in your application either directly or through a library which simplifies the process of using it.
- [rspc](https://github.com/specta-rs/rspc) - Easily building end-to-end typesafe APIs
- [tauri-specta](https://github.com/specta-rs/tauri-specta) - Typesafe Tauri commands and events
- [TauRPC](https://github.com/MatsDK/TauRPC) - Tauri extension to give you a fully-typed IPC layer.
## Usage
Add the [`specta`](https://docs.rs/specta) crate along with any Specta language exporter crate:
```bash
# Core Specta library
cargo add specta
# Language exporters (choose one or more)
cargo add specta_typescript # TypeScript (stable)
cargo add specta_swift # Swift (stable)
cargo add specta_rust # Rust (partial - basic types)
cargo add specta_openapi # OpenAPI/Swagger (partial - primitives)
# cargo add specta_go # Go (planned)
# cargo add specta_kotlin # Kotlin (planned)
# cargo add specta_jsonschema # JSON Schema (planned)
# cargo add specta_zod # Zod schemas (planned)
```
Then you can use Specta like following:
### TypeScript Example
```rust
use specta::{Type, Types};
use specta_typescript::Typescript;
#[derive(Type)]
pub struct TypeOne {
pub a: String,
pub b: GenericType<i32>,
#[serde(rename = "cccccc")]
pub c: MyEnum,
}
#[derive(Type)]
pub struct GenericType<A> {
pub my_field: String,
pub generic: A,
}
#[derive(Type)]
pub enum MyEnum {
A,
B,
C,
}
fn main() {
let types = Types::default()
// You don't need to specify `GenericType` or `MyEnum` because they are referenced by `TypeOne`
.register::<TypeOne>();
Typescript::default()
.export_to("./bindings.ts", &types)
.unwrap();
// if you need more control over file saving
assert_eq!(
Typescript::default().export(&types).unwrap(),
r#"// This file has been generated by Specta. DO NOT EDIT.
export type GenericType<A> = { my_field: string; generic: A };
export type MyEnum = "A" | "B" | "C";
export type TypeOne = { a: string; b: GenericType<number>; cccccc: MyEnum };
"#
);
}
```
### Multi-Language Export Example
You can export the same types to multiple languages:
```rust
use specta::{Type, Types};
use specta_typescript::Typescript;
use specta_swift::Swift;
#[derive(Type)]
pub struct User {
pub id: u32,
pub name: String,
pub email: Option<String>,
}
fn main() {
let types = Types::default()
.register::<User>();
// Export to TypeScript (stable)
Typescript::default()
.export_to("./types.ts", &types)
.unwrap();
// Export to Swift (stable)
Swift::default()
.export_to("./Types.swift", &types)
.unwrap();
// Note: Other exporters are in development
}
```
A common use case is to export all types for which `specta::Type` is derived into a single file:
```rust
//! NOTE: This example requires the `export` feature on the `specta` crate
use specta::Type;
use specta_typescript::Typescript;
#[derive(Type)]
pub enum MyEither<L, R> {
Left(L),
Right(R),
}
#[derive(Type)]
pub struct GenericType<A> {
pub my_field: String,
pub generic: A,
}
#[derive(Type)]
pub enum MyEnum {
A,
B,
C,
}
#[derive(Type)]
#[specta(collect = false)]
pub struct DontExportMe {
field: String,
}
fn main() {
Typescript::default()
.export_to("./bindings.ts", &specta::export())
.unwrap();
}
```
Check out the [docs](https://docs.rs/specta) for more information.
## Motivation
This library was originally created to power the type exporting functionality of [rspc](https://rspc.dev),
but after building it we realized that it could be useful for other projects as well so we decided to move it into a dedicated library.
A huge thanks to [Brendonovich](https://github.com/brendonovich) for doing a heap of early development on this library.
================================================
FILE: examples/basic-ts/Cargo.toml
================================================
[package]
name = "example-basic-ts"
version = "0.0.0"
edition = "2024"
publish = false
[dependencies]
specta = { path = "../../specta", features = ["derive"] }
specta-typescript = { path = "../../specta-typescript" }
specta-serde = { path = "../../specta-serde" }
serde = { version = "1", features = ["derive"] }
serde_with = { version = "3", features = ["macros"] }
serde_repr = "0.1.20"
================================================
FILE: examples/basic-ts/src/main.rs
================================================
use serde::{Deserialize, Serialize};
use specta::{Type, Types};
use specta_typescript::Typescript;
// Specta works by deriving `Type` for the Rust types you want to export.
//
// `Serialize` and `Deserialize` are not required by Specta itself, but they are
// common in real applications and allow Specta to understand serde attributes
// when exporting through `specta_serde::Format` below.
#[derive(Serialize, Deserialize, Type)]
pub struct User {
id: u32,
name: String,
// Serde attributes are respected when using `specta_serde::Format`.
// This field will be exported to TypeScript as `emailAddress`.
#[serde(rename = "emailAddress")]
email_address: String,
// Optional Rust values become `T | null` in TypeScript.
avatar_url: Option<String>,
}
#[derive(Serialize, Deserialize, Type)]
pub struct Post {
id: u32,
title: String,
author: User,
tags: Vec<String>,
status: PostStatus,
}
#[derive(Serialize, Deserialize, Type)]
#[serde(rename_all = "camelCase")]
pub enum PostStatus {
Draft,
InReview,
Published,
}
fn main() {
// Register every root type you want to export. Specta automatically follows
// references, so registering `Post` is enough to include `User` and
// `PostStatus`, but registering roots explicitly is often clearer in apps.
let types = Types::default()
.register::<User>()
.register::<Post>()
.register::<PostStatus>();
// Export the registered Rust types as TypeScript definitions.
//
// `specta_serde::Format` tells Specta to apply serde's wire-format rules,
// such as `rename`, `rename_all`, `tag`, `untagged`, and `flatten`.
//
// You can also use `specta_serde::FormatPhases` to allow types to be
// narrowed based on if your serializing or deserializing.
let output = Typescript::default()
.export(&types, specta_serde::Format)
.expect("failed to export TypeScript types");
println!("{output}");
}
================================================
FILE: examples/collect/Cargo.toml
================================================
[package]
name = "example-collect"
version = "0.0.0"
edition = "2024"
publish = false
[dependencies]
specta = { path = "../../specta", features = ["derive", "collect"] }
specta-typescript = { path = "../../specta-typescript" }
specta-serde = { path = "../../specta-serde" }
================================================
FILE: examples/collect/src/main.rs
================================================
#![allow(unused)]
use specta::Type;
use specta_typescript::Typescript;
#[derive(Type)]
pub struct User {
id: String,
name: String,
}
#[derive(Type)]
pub struct Post {
id: String,
author: User,
comments: Vec<Comment>,
}
#[derive(Type)]
pub struct Comment {
body: String,
}
// This type can still derive `Type`, but it is left out of `specta::collect()`.
#[derive(Type)]
#[specta(collect = false)]
pub struct InternalMetrics {
latency_ms: u64,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let output = Typescript::default().export(&specta::collect(), specta_serde::Format)?;
println!("{output}");
Ok(())
}
================================================
FILE: examples/scratchpad/Cargo.toml
================================================
[package]
name = "example-scratchpad"
version = "0.0.0"
edition = "2024"
publish = false
[dependencies]
specta = { path = "../../specta", features = ["derive"] }
specta-typescript = { path = "../../specta-typescript" }
specta-serde = { path = "../../specta-serde" }
serde = { version = "1", features = ["derive"] }
================================================
FILE: examples/scratchpad/src/main.rs
================================================
//! A playground for quickly reproducing issue.
#![allow(warnings)]
use specta::Types;
fn main() {
let mut types = Types::default();
let out = specta_typescript::Typescript::new()
.export(&types, specta_serde::PhasesFormat)
.unwrap();
println!("{}", out);
}
================================================
FILE: specta/Cargo.toml
================================================
[package]
name = "specta"
description = "Easily export your Rust types to other languages"
version = "2.0.0-rc.24"
authors = ["Oscar Beaumont <oscar@otbeaumont.me>"]
edition = "2024"
license = "MIT"
include = ["/src", "/examples", "/build.rs", "/LICENCE", "/README.md"]
repository = "https://github.com/specta-rs/specta"
documentation = "https://docs.rs/specta/latest/specta"
keywords = ["async", "specta", "rspc", "typescript", "typesafe"]
categories = ["web-programming", "asynchronous"]
readme = "../README.md"
# /bin/sh RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features
[package.metadata."docs.rs"]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
# Run `node ./.github/features.js` to update the docs
[features]
default = ["std"]
#! Core Features
## Enable support for the Rust standard library. Enabled by default.
std = []
## Derive macros
derive = ["dep:specta-macros"]
## Support for collecting up a global type map
collect = ["dep:small_ctor", "specta-macros/DO_NOT_USE_collect"]
#! Features
## Support for exporting the types of Rust functions.
function = ["specta-macros?/DO_NOT_USE_function", "dep:paste"]
#! Compatibility
## Support for [serde-json](https://github.com/serde-rs/json)
serde_json = ["dep:serde_json"]
## Support for [serde_yaml](https://github.com/dtolnay/serde-yaml)
serde_yaml = ["dep:serde_yaml"]
## Support for [toml](https://github.com/toml-rs/toml)
toml = ["dep:toml", "std"]
#! External types
## [uuid](https://docs.rs/uuid) crate
uuid = ["dep:uuid"]
## [uuid](https://docs.rs/ulid) crate
ulid = ["dep:ulid"]
## [chrono](https://docs.rs/chrono) crate
chrono = ["dep:chrono"]
## [time](https://docs.rs/time) crate
time = ["dep:time"]
# [jiff](https://docs.rs/jiff) crate
jiff = ["dep:jiff"]
## [bigdecimal](https://docs.rs/bigdecimal) crate
bigdecimal = ["dep:bigdecimal"]
## [rust_decimal](https://docs.rs/rust_decimal) crate
rust_decimal = ["dep:rust_decimal"]
## [indexmap](https://docs.rs/indexmap) crate
indexmap = ["dep:indexmap"]
## [ordered-float](https://docs.rs/ordered-float) crate
ordered-float = ["dep:ordered-float"]
## [heapless](https://docs.rs/heapless) crate
heapless = ["dep:heapless"]
## [semver](https://docs.rs/semver) crate
semver = ["dep:semver"]
## [smol_str](https://docs.rs/smol_str) crate
smol_str = ["dep:smol_str"]
## [arrayvec](https://docs.rs/arrayvec) crate
arrayvec = ["dep:arrayvec"]
## [smallvec](https://docs.rs/smallvec) crate
smallvec = ["dep:smallvec"]
## [ipnetwork](https://docs.rs/ipnetwork) crate
ipnetwork = ["dep:ipnetwork"]
## [mac_address](https://docs.rs/mac_address) crate
mac_address = ["dep:mac_address"]
## [bit-vec](https://docs.rs/bit-vec) crate
bit-vec = ["dep:bit-vec"]
## [bson](https://docs.rs/bson) crate
bson = ["dep:bson"]
## [bytes](https://docs.rs/bytes) crate
bytes = ["dep:bytes"]
## [uhlc](https://docs.rs/uhlc) crate
uhlc = ["dep:uhlc"]
## [bytesize](https://docs.rs/bytesize) crate
bytesize = ["dep:bytesize"]
## [glam](https://docs.rs/glam) crate
glam = ["dep:glam"]
## [tokio](https://docs.rs/tokio) crate
tokio = ["dep:tokio"]
## [url](https://docs.rs/url) crate
url = ["dep:url"]
## [either](https://docs.rs/either) crate
either = ["dep:either"]
## [error-stack](https://docs.rs/error-stack) crate
error-stack = ["dep:error-stack"]
# [bevy_ecs](https://docs.rs/bevy_ecs) crate
bevy_ecs = ["dep:bevy_ecs"]
# [bevy_input](https://docs.rs/bevy_input) crate
bevy_input = ["dep:bevy_input", "dep:bevy_ecs", "dep:glam", "smol_str"]
# [camino](https://docs.rs/camino) crate
camino = ["dep:camino"]
## [geojson](https://docs.rs/geojson) crate
geojson = ["dep:geojson", "serde_json"]
[lints]
workspace = true
[dependencies]
specta-macros = { version = "=2.0.0-rc.24", optional = true, path = "../specta-macros" }
paste = { version = "1", optional = true }
small_ctor = { version = "0.1.2", optional = true }
# TODO: To be deprecated
serde_json = { version = "1", optional = true, default-features = false, features = ["std"] }
serde_yaml = { version = "0.9", optional = true, default-features = false, features = [] }
toml = { version = "1.1", optional = true, default-features = false, features = ["serde"] }
ulid = { version = "1", optional = true, default-features = false, features = [] }
uuid = { version = "1", optional = true, default-features = false, features = [
] } # TODO: Downgraded for Bevy (argh)
chrono = { version = "0.4", optional = true, default-features = false, features = ["clock"] }
time = { version = "0.3", optional = true, default-features = false, features = [] }
bigdecimal = { version = "0.4", optional = true, default-features = false, features = [] }
rust_decimal = { version = "1", optional = true, default-features = false, features = [] }
indexmap = { version = "2", optional = true, default-features = false, features = [
"std",
] } # TODO: Don't require `std`
ordered-float = { version = ">=3, <6", optional = true, default-features = false }
heapless = { version = ">=0.7, <0.10", optional = true, default-features = false, features = [] }
semver = { version = "1", optional = true, default-features = false, features = [] }
smol_str = { version = "0.3", optional = true, default-features = false, features = [] }
arrayvec = { version = ">=0.6, <0.8", optional = true, default-features = false, features = [] }
smallvec = { version = "1", optional = true, default-features = false, features = [] }
ipnetwork = { version = "0.21", optional = true, default-features = false, features = [] }
mac_address = { version = "1", optional = true, default-features = false, features = [] }
bit-vec = { version = "0.9", optional = true, default-features = false, features = [] }
bson = { version = "3", optional = true, default-features = false, features = ["compat-3-0-0"] }
bytes = { version = "1", optional = true, default-features = false, features = [] }
uhlc = { version = "0.9", optional = true, default-features = false, features = [] }
bytesize = { version = "2", optional = true, default-features = false, features = [] }
glam = { version = "0.32", optional = true, default-features = false, features = ["std"] }
tokio = { version = "1", optional = true, default-features = false, features = ["sync"] }
url = { version = "2", optional = true, default-features = false }
either = { version = "1", optional = true, default-features = false }
error-stack = { version = "0.7", optional = true, default-features = false }
bevy_ecs = { version = "0.18", optional = true, default-features = false, features = ["std"] }
bevy_input = { version = "0.18", optional = true, default-features = false, features = [
"std",
"bevy_reflect",
"keyboard",
"mouse",
"touch",
"gestures",
"gamepad",
] }
jiff = { version = "0.2", optional = true, default-features = false }
camino = { version = "1", optional = true, default-features = false }
geojson = { version = "1.0", optional = true, default-features = false }
[build-dependencies]
rustc_version = "0.4.1"
[dev-dependencies]
specta-serde = { path = "../specta-serde" }
specta-typescript = { path = "../specta-typescript" }
================================================
FILE: specta/build.rs
================================================
//! Build script for configuring nightly-only cfg flags.
//!
//! This build script enables the `is_nightly` cfg when running on a nightly
//! compiler (or when `RUSTC_BOOTSTRAP` is set) so crate code can conditionally
//! compile nightly-specific behavior.
//!
//! It would be nice if this was built into Cargo 😅
fn main() {
let is_nightly = std::env::var("RUSTC_BOOTSTRAP").is_ok()
|| rustc_version::version_meta()
.map(|m| m.channel == rustc_version::Channel::Nightly)
.unwrap_or(false);
if is_nightly {
println!("cargo:rustc-cfg=is_nightly");
}
}
================================================
FILE: specta/src/collect.rs
================================================
use std::sync::{Mutex, OnceLock, PoisonError};
use crate::{Type, Types};
// Global type store for collecting custom types to export.
//
// We intentionally store functions over a `Types` directly to ensure any internal panics aren't done in CTOR.
#[allow(clippy::type_complexity)]
static TYPES: OnceLock<Mutex<Vec<fn(&mut Types)>>> = OnceLock::new();
/// Get the global type store containing all automatically collected types.
///
/// All types with the [`Type`](macro@crate::Type) macro will automatically be registered here unless they have been explicitly disabled with `#[specta(collect = false)]`.
///
/// Note that when enabling the `export` feature, you will not be able to enable the `unsafe_code` lint as [`small_ctor`] (which is used internally) is marked unsafe.
///
/// # Example
///
/// ```no_run
/// use specta::Type;
/// use specta_typescript::Typescript;
///
/// #[derive(Type)]
/// pub struct User {
/// id: String,
/// name: String,
/// }
///
/// #[derive(Type)]
/// pub struct Post {
/// id: String,
/// author: User,
/// comments: Vec<Comment>,
/// }
///
/// #[derive(Type)]
/// pub struct Comment {
/// body: String,
/// }
///
/// // This type can still derive `Type`, but it is left out of `specta::collect()`.
/// #[derive(Type)]
/// #[specta(collect = false)]
/// pub struct InternalMetrics {
/// latency_ms: u64,
/// }
///
/// fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let output = Typescript::default().export(&specta::collect(), specta_serde::Format)?;
///
/// println!("{output}");
///
/// Ok(())
/// }
/// ```
pub fn collect() -> Types {
let types = TYPES
.get_or_init(Default::default)
.lock()
.unwrap_or_else(PoisonError::into_inner);
let mut map = Types::default();
for export in types.iter() {
export(&mut map);
}
map
}
#[doc(hidden)]
pub mod internal {
use super::*;
// Called within ctor functions to register a type.
pub fn register<T: Type>() {
TYPES
.get_or_init(Default::default)
.lock()
.unwrap_or_else(PoisonError::into_inner)
.push(|types| {
// The side-effect of this is registering the type.
T::definition(types);
});
}
// We expose this for the macros
#[cfg(feature = "collect")]
pub use small_ctor;
}
================================================
FILE: specta/src/datatype/attributes.rs
================================================
use std::{
any::Any,
borrow::Cow,
collections::{HashMap, hash_map::DefaultHasher},
fmt,
hash::{Hash, Hasher},
sync::Arc,
};
trait DynAttributeValue: Send + Sync {
fn value_any(&self) -> &dyn Any;
fn eq_dyn(&self, other: &dyn DynAttributeValue) -> bool;
fn hash_dyn(&self, state: &mut dyn Hasher);
fn fmt_dyn(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
}
struct NamedAttributeValue<T>(T);
impl<T> DynAttributeValue for NamedAttributeValue<T>
where
T: Any + Clone + Eq + Hash + fmt::Debug + Send + Sync + 'static,
{
fn value_any(&self) -> &dyn Any {
&self.0
}
fn eq_dyn(&self, other: &dyn DynAttributeValue) -> bool {
other
.value_any()
.downcast_ref::<T>()
.is_some_and(|other| self.0 == *other)
}
fn hash_dyn(&self, state: &mut dyn Hasher) {
let mut hasher = DefaultHasher::new();
self.0.hash(&mut hasher);
state.write_u64(hasher.finish());
}
fn fmt_dyn(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
/// A named map of type-erased metadata attached to datatype nodes.
///
/// `Attributes` is primarily used by advanced consumers that need to inspect
/// metadata recorded on [`DataType`](super::DataType) nodes at runtime. Each
/// entry is stored under a string key and can later be retrieved either as a
/// raw [`Any`] value or by downcasting to the original type.
///
/// Stored values must be owned and implement [`Clone`], [`Eq`], [`Hash`], and
/// [`fmt::Debug`] so attributes remain comparable, hashable, and printable as
/// part of the surrounding datatype graph.
///
#[derive(Default)]
pub struct Attributes(HashMap<Cow<'static, str>, Arc<dyn DynAttributeValue>>);
impl Clone for Attributes {
fn clone(&self) -> Self {
Self(
self.0
.iter()
.map(|(key, value)| (key.clone(), value.clone()))
.collect(),
)
}
}
impl Attributes {
/// Returns the number of stored attribute entries.
pub fn len(&self) -> usize {
self.0.len()
}
/// Returns `true` when the collection has no entries.
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
/// Inserts or replaces an attribute value.
///
/// Values are stored in a type-erased form, but they must still implement
/// [`Clone`], [`Eq`], [`Hash`], and [`fmt::Debug`] so the containing
/// [`Attributes`] remains cloneable, comparable, hashable, and printable.
///
pub fn insert<T>(&mut self, key: impl Into<Cow<'static, str>>, value: T)
where
T: Any + Clone + Eq + Hash + fmt::Debug + Send + Sync + 'static,
{
self.0
.insert(key.into(), Arc::new(NamedAttributeValue(value)));
}
/// Extends `self` with entries from `other`.
///
/// If both collections contain the same key, the value from `other`
/// replaces the existing entry in `self`.
///
pub fn extend(&mut self, other: Self) {
self.0.extend(other.0);
}
/// Removes the entry under `key`, returning `true` when an entry was
/// present.
///
pub fn remove(&mut self, key: &str) -> bool {
self.0.remove(key).is_some()
}
/// Returns `true` if an attribute entry is present for `key`.
pub fn contains_key(&self, key: &str) -> bool {
self.0.contains_key(key)
}
/// Returns the raw type-erased value for a named attribute.
///
/// This is useful when the expected type is not known until runtime.
/// Prefer [`Attributes::get_named_as`] when you know the concrete type.
///
pub fn get_named(&self, key: &str) -> Option<&dyn Any> {
self.0.get(key).map(|value| value.value_any())
}
/// Returns a typed reference to the named attribute value.
///
/// Returns `None` when the key is missing or when the stored value has a
/// different type than `T`.
///
pub fn get_named_as<T: Any + 'static>(&self, key: &str) -> Option<&T> {
self.0
.get(key)
.and_then(|value| value.value_any().downcast_ref::<T>())
}
}
impl PartialEq for Attributes {
fn eq(&self, other: &Self) -> bool {
self.0.len() == other.0.len()
&& self.0.iter().all(|(key, value)| {
other
.0
.get(key)
.is_some_and(|other| value.eq_dyn(other.as_ref()))
})
}
}
impl Eq for Attributes {}
impl Hash for Attributes {
fn hash<H: Hasher>(&self, state: &mut H) {
let mut entries = self
.0
.iter()
.map(|(key, value)| {
let mut hasher = DefaultHasher::new();
key.hash(&mut hasher);
value.hash_dyn(&mut hasher);
hasher.finish()
})
.collect::<Vec<_>>();
entries.sort_unstable();
self.0.len().hash(state);
entries.hash(state);
}
}
impl fmt::Debug for Attributes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut entries = self.0.iter().collect::<Vec<_>>();
entries.sort_by(|(left, _), (right, _)| left.cmp(right));
let mut map = f.debug_map();
for (key, value) in entries {
map.entry(key, &fmt::from_fn(|f| value.fmt_dyn(f)));
}
map.finish()
}
}
================================================
FILE: specta/src/datatype/enum.rs
================================================
use std::borrow::Cow;
use crate::datatype::Field;
use super::{Attributes, DataType, Deprecated, Fields, NamedFields, UnnamedFields};
/// Runtime representation of a Rust [`enum`](https://doc.rust-lang.org/std/keyword.enum.html).
///
/// Enums are configured with a set of variants, each with a name and a type.
/// The variants can be either unit variants (no fields), tuple variants (fields in a tuple), or struct variants (fields in a struct).
///
/// Each variant has a name and one of the layouts described by [`Fields`].
/// Format integrations may use [`Enum::attributes`] to record representation
/// metadata, such as Serde's enum representation attributes.
#[derive(Default, Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct Enum {
/// Named variants in source order.
pub variants: Vec<(Cow<'static, str>, Variant)>,
/// Macro attributes applied to the enum container.
pub attributes: Attributes,
}
impl From<Enum> for DataType {
fn from(t: Enum) -> Self {
Self::Enum(t)
}
}
/// Runtime representation of a single enum variant.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct Variant {
/// Whether the variant was skipped with an attribute such as
/// `#[serde(skip)]` or `#[specta(skip)]`.
///
/// You might think, well why not apply this in the macro and just not emit the variant?
/// Well in Serde `A(String)` and `A(#[serde(skip)] (), String)` export as different Typescript types so the exporter needs runtime knowledge of this.
pub skip: bool,
/// Documentation comments for the variant.
pub docs: Cow<'static, str>,
/// Deprecated metadata for the variant.
pub deprecated: Option<Deprecated>,
/// The type of the variant.
pub fields: Fields,
/// Runtime attributes for this variant.
pub attributes: Attributes,
}
impl Variant {
/// Constructs a unit enum variant.
pub fn unit() -> Self {
Self {
skip: false,
docs: "".into(),
deprecated: None,
fields: Fields::Unit,
attributes: Attributes::default(),
}
}
/// Starts building a struct enum variant with named fields.
pub fn named() -> VariantBuilder<NamedFields> {
VariantBuilder {
v: Self {
skip: false,
docs: "".into(),
deprecated: None,
fields: Fields::Named(NamedFields {
fields: Default::default(),
}),
attributes: Attributes::default(),
},
variant: NamedFields { fields: vec![] },
}
}
/// Starts building a tuple enum variant with unnamed fields.
pub fn unnamed() -> VariantBuilder<UnnamedFields> {
VariantBuilder {
v: Self {
skip: false,
docs: "".into(),
deprecated: None,
fields: Fields::Unnamed(UnnamedFields {
fields: Default::default(),
}),
attributes: Attributes::default(),
},
variant: UnnamedFields {
fields: Default::default(),
},
}
}
}
/// Builder for constructing [`Variant`] values.
#[derive(Debug, Clone)]
pub struct VariantBuilder<V = ()> {
pub(crate) v: Variant,
pub(crate) variant: V,
}
impl<T> VariantBuilder<T> {
/// Marks the variant as skipped.
pub fn skip(mut self) -> Self {
self.v.skip = true;
self
}
/// Sets documentation for the variant.
pub fn docs(mut self, docs: Cow<'static, str>) -> Self {
self.v.docs = docs;
self
}
/// Sets deprecation metadata for the variant.
pub fn deprecated(mut self, reason: Deprecated) -> Self {
self.v.deprecated = Some(reason);
self
}
/// Sets runtime attributes on the variant.
pub fn attributes(mut self, attributes: Attributes) -> Self {
self.v.attributes = attributes;
self
}
/// Sets runtime attributes on the variant in-place.
pub fn attributes_mut(&mut self, attributes: Attributes) {
self.v.attributes = attributes;
}
}
impl VariantBuilder<UnnamedFields> {
/// Adds an unnamed field to the variant.
pub fn field(mut self, field: Field) -> Self {
self.variant.fields.push(field);
self
}
/// Adds an unnamed field to the variant and returns the updated builder.
pub fn field_mut(mut self, field: Field) -> Self {
self.variant.fields.push(field);
self
}
/// Finalizes the unnamed variant builder into a [`Variant`].
pub fn build(mut self) -> Variant {
self.v.fields = Fields::Unnamed(self.variant);
self.v
}
}
impl VariantBuilder<NamedFields> {
/// Adds a named field to the variant.
pub fn field(mut self, name: impl Into<Cow<'static, str>>, field: Field) -> Self {
self.variant.fields.push((name.into(), field));
self
}
/// Adds a named field to the variant and returns the updated builder.
pub fn field_mut(mut self, name: impl Into<Cow<'static, str>>, field: Field) -> Self {
self.variant.fields.push((name.into(), field));
self
}
/// Finalizes the named variant builder into a [`Variant`].
pub fn build(mut self) -> Variant {
self.v.fields = Fields::Named(self.variant);
self.v
}
}
impl From<VariantBuilder<NamedFields>> for Variant {
fn from(val: VariantBuilder<NamedFields>) -> Self {
val.build()
}
}
================================================
FILE: specta/src/datatype/fields.rs
================================================
//! Field types are used by both enums and structs.
use crate::datatype::Struct;
use super::{Attributes, DataType, Deprecated};
use std::borrow::Cow;
/// Field layout for a struct or enum variant.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Fields {
/// Unit struct.
///
/// Represented in Rust as `pub struct Unit;` and in TypeScript as `null`.
Unit,
/// Struct with unnamed fields.
///
/// Represented in Rust as `pub struct Unit();` and in TypeScript as `[]`.
Unnamed(UnnamedFields),
/// Struct with named fields.
///
/// Represented in Rust as `pub struct Unit {}` and in TypeScript as `{}`.
Named(NamedFields),
}
/// Metadata for a struct field or enum variant field.
#[derive(Default, Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct Field {
/// Whether the field was marked optional, for example with
/// `#[specta(optional)]`.
pub optional: bool,
/// Deprecated attribute for the field.
pub deprecated: Option<Deprecated>,
/// Documentation comments for the field.
pub docs: Cow<'static, str>,
/// Runtime attributes for this field.
pub attributes: Attributes,
/// Type for the field.
///
/// This is `None` when the field was skipped with an attribute such as
/// `#[serde(skip)]` or `#[specta(skip)]`. Exporters should preserve enough
/// information to distinguish skipped fields from absent fields because some
/// serialization formats still let skipped fields affect layout.
///
/// You might think, well why not apply this in the macro and just not emit the variant?
/// Well in Serde `A(String)` and `A(#[serde(skip)] (), String)` export as different Typescript types so the exporter needs runtime knowledge of this.
pub ty: Option<DataType>,
}
impl Field {
/// Constructs a new non-optional field with the given type.
///
/// Use [`Field::default`] to construct skipped-field metadata where `ty` is
/// initially `None`.
pub fn new(ty: DataType) -> Self {
Field {
optional: false,
deprecated: None,
docs: "".into(),
ty: Some(ty),
attributes: Attributes::default(),
}
}
}
/// Fields for an unnamed tuple struct or tuple enum variant.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct UnnamedFields {
/// Field metadata in source order.
pub fields: Vec<Field>,
}
/// Fields for a named struct or struct enum variant.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct NamedFields {
/// Field names and metadata in source order.
pub fields: Vec<(Cow<'static, str>, Field)>,
}
#[derive(Debug, Clone)]
/// Builder for constructing [`DataType::Struct`] values.
///
/// The type parameter tracks whether the builder is currently collecting named
/// or unnamed fields.
pub struct StructBuilder<F = ()> {
pub(crate) fields: F,
}
impl StructBuilder<NamedFields> {
/// Adds a named field and returns the updated builder.
pub fn field(mut self, name: impl Into<Cow<'static, str>>, field: Field) -> Self {
self.fields.fields.push((name.into(), field));
self
}
/// Adds a named field in-place.
pub fn field_mut(&mut self, name: impl Into<Cow<'static, str>>, field: Field) {
self.fields.fields.push((name.into(), field));
}
/// Finalizes this builder into a [`DataType::Struct`] with named fields.
pub fn build(self) -> DataType {
DataType::Struct(Struct {
fields: Fields::Named(self.fields),
attributes: Default::default(),
})
}
}
impl StructBuilder<UnnamedFields> {
/// Adds an unnamed field and returns the updated builder.
pub fn field(mut self, field: Field) -> Self {
self.fields.fields.push(field);
self
}
/// Adds an unnamed field in-place.
pub fn field_mut(&mut self, field: Field) {
self.fields.fields.push(field);
}
/// Finalizes this builder into a [`DataType::Struct`] with unnamed fields.
pub fn build(self) -> DataType {
DataType::Struct(Struct {
fields: Fields::Unnamed(self.fields),
attributes: Default::default(),
})
}
}
================================================
FILE: specta/src/datatype/function.rs
================================================
use std::borrow::Cow;
use super::{DataType, Deprecated};
/// Runtime type information for a function annotated with `#[specta]`.
///
/// Values are produced by [`fn_datatype!`](crate::function::fn_datatype) and
/// [`collect_functions!`](crate::function::collect_functions). Function metadata
/// is intentionally separate from [`Types`](crate::Types): the function's
/// argument and result datatypes reference entries collected into the `Types`
/// value passed to those macros.
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct Function {
/// Whether the function is async.
pub asyncness: bool,
/// The function's name.
pub name: Cow<'static, str>,
/// The name and type of each of the function's arguments.
pub args: Vec<(Cow<'static, str>, DataType)>,
/// The return type of the function.
pub result: Option<DataType>,
/// The function's documentation. Detects both `///` and `#[doc = ...]` style documentation.
pub docs: Cow<'static, str>,
/// The deprecated status of the function.
pub deprecated: Option<Deprecated>,
}
impl Function {
/// Whether the function is async.
pub fn asyncness(&self) -> bool {
self.asyncness
}
/// The function's name.
pub fn name(&self) -> &str {
&self.name
}
/// The name and type of each of the function's arguments.
pub fn args(&self) -> &[(Cow<'static, str>, DataType)] {
&self.args
}
/// The return type of the function.
pub fn result(&self) -> Option<&DataType> {
self.result.as_ref()
}
}
================================================
FILE: specta/src/datatype/generic.rs
================================================
use std::borrow::Cow;
use crate::datatype::DataType;
/// Reference to a named generic parameter.
///
/// Exporters usually render this as the generic name, such as `T`.
///
/// # Invariants
///
/// A `Generic` should only appear inside the canonical `ty` field of the
/// [`NamedDataType`](crate::datatype::NamedDataType) that declares it. Ordinary
/// [`Type::definition`](crate::Type::definition) results should use concrete
/// datatypes or references with instantiated generics.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Generic(Cow<'static, str>);
impl Generic {
/// Builds a new generic parameter reference with the given source-level name.
///
/// The same name must appear in the parent [`GenericDefinition`] list.
pub const fn new(name: Cow<'static, str>) -> Self {
Self(name)
}
/// The source-level name of this generic parameter.
pub fn name(&self) -> &Cow<'static, str> {
&self.0
}
/// Get a stable reference identifier for this generic parameter.
pub fn reference(&self) -> Self {
self.clone()
}
}
impl From<Generic> for DataType {
fn from(v: Generic) -> Self {
DataType::Generic(v)
}
}
/// Metadata describing a generic parameter declared by a
/// [`NamedDataType`](crate::datatype::NamedDataType).
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct GenericDefinition {
/// The source-level name of the generic parameter.
pub name: Cow<'static, str>,
/// An optional default type for the generic parameter.
pub default: Option<DataType>,
}
impl GenericDefinition {
/// Constructs metadata for a generic parameter.
pub const fn new(name: Cow<'static, str>, default: Option<DataType>) -> Self {
Self { name, default }
}
/// Get a stable reference identifier for this generic parameter.
pub fn reference(&self) -> Generic {
Generic::new(self.name.clone())
}
}
================================================
FILE: specta/src/datatype/list.rs
================================================
use super::DataType;
/// Sequential collection type, such as [`Vec`](std::vec::Vec), arrays, slices,
/// or set-like collections.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct List {
/// Type of each element in the list.
pub ty: Box<DataType>,
/// Fixed number of elements when known.
///
/// `None` represents a variable-length collection.
pub length: Option<usize>,
/// Whether elements are expected to be unique, as with set-like types.
pub unique: bool,
}
impl List {
/// Create a new list of a given type.
pub fn new(ty: DataType) -> Self {
Self {
ty: Box::new(ty),
length: None,
unique: false,
}
}
}
impl From<List> for DataType {
fn from(t: List) -> Self {
Self::List(t)
}
}
================================================
FILE: specta/src/datatype/literal.rs
================================================
//! This works but isn't being shipped for now as we don't need it for const generics anymore.
//! Also it suffers from the following concerns:
//! - For a floating point number if it's a `NaN` or `Infinity` or `-Infinity` we should yield an error in the Typescript exporter as we can't export it to a Typescript type.
//! - What do we do about bigint primitives. Mainly Tauri Specta/TauRPC need to be able to deal with this somehow?
//!
use std::{
any::Any,
borrow::Cow,
fmt,
hash::{self, Hash},
sync::Arc,
};
use crate::{
Type, Types,
datatype::{DataType, Reference},
};
/// A type-erased literal value stored inside an opaque [`Reference`].
#[derive(Clone)]
pub struct Literal(Arc<dyn LiteralType>);
impl Literal {
/// Construct a literal [`DataType`] from a concrete value.
///
/// T can be any of [`i8`], [`i16`], [`i32`], [`i64`], [`i128`], [`isize`], [`u8`], [`u16`], [`u32`], [`u64`], [`u128`], [`usize`], [`f32`], [`f64`], [`bool`], [`char`], [`&'static str`], [`String`], [`Cow<'static, str>`].
///
/// On nightly, [`f16`] and [`f128`] are also supported.
pub fn new<T: LiteralType>(value: T) -> DataType {
DataType::Reference(Reference::opaque(Literal::from(value)))
}
/// Returns the underlying datatype represented by this literal value.
pub fn definition(&self, types: &mut Types) -> DataType {
self.0.definition(types)
}
/// Attempt to downcast the stored literal to a concrete type.
pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
self.0.as_any().downcast_ref::<T>()
}
}
/// Trait used by type-erased literal values.
///
/// Sealed so we can add implementations in minor releases
pub trait LiteralType: Any + Send + Sync + 'static {
/// Returns the underlying datatype represented by this literal value.
fn definition(&self, types: &mut Types) -> DataType;
fn eq_dyn(&self, other: &dyn LiteralType) -> bool;
fn hash_dyn(&self, state: &mut dyn hash::Hasher);
fn fmt_dyn(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
fn as_any(&self) -> &dyn Any;
}
impl<T: LiteralType> From<T> for Literal {
fn from(value: T) -> Self {
Self(Arc::new(value))
}
}
impl fmt::Debug for Literal {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt_dyn(f)
}
}
impl PartialEq for Literal {
fn eq(&self, other: &Self) -> bool {
self.0.eq_dyn(other.0.as_ref())
}
}
impl Eq for Literal {}
impl hash::Hash for Literal {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.0.hash_dyn(state)
}
}
macro_rules! impl_literal_type {
($($ty:ty),+ $(,)?) => {
$(
impl LiteralType for $ty {
fn definition(&self, types: &mut Types) -> DataType {
<$ty as Type>::definition(types)
}
fn eq_dyn(&self, other: &dyn LiteralType) -> bool {
other.as_any().downcast_ref::<Self>() == Some(self)
}
fn hash_dyn(&self, mut state: &mut dyn hash::Hasher) {
Hash::hash(self, &mut state);
}
fn fmt_dyn(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
fn as_any(&self) -> &dyn Any {
self
}
}
)+
};
}
impl_literal_type!(
i8,
i16,
i32,
i64,
i128,
isize,
u8,
u16,
u32,
u64,
u128,
usize,
bool,
char,
&'static str,
String,
Cow<'static, str>,
);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum FloatKey<Bits> {
NegInfinity,
NegZero,
Finite(Bits),
Infinity,
NaN,
}
trait FloatLiteral: Copy + PartialEq + Type + fmt::Debug + Send + Sync + 'static {
type Bits: Copy + Eq + Hash;
const INFINITY: Self;
const NEG_INFINITY: Self;
const NEG_ZERO_BITS: Self::Bits;
fn is_nan(self) -> bool;
fn is_negative_zero(self) -> bool;
fn to_bits(self) -> Self::Bits;
}
impl<T: FloatLiteral> From<T> for FloatKey<T::Bits> {
fn from(value: T) -> Self {
if value.is_nan() {
Self::NaN
} else if value == T::INFINITY {
Self::Infinity
} else if value == T::NEG_INFINITY {
Self::NegInfinity
} else if value.is_negative_zero() {
Self::NegZero
} else {
Self::Finite(value.to_bits())
}
}
}
macro_rules! impl_float_literal {
($ty:ty, $bits:ty) => {
impl FloatLiteral for $ty {
type Bits = $bits;
const INFINITY: Self = <$ty>::INFINITY;
const NEG_INFINITY: Self = <$ty>::NEG_INFINITY;
const NEG_ZERO_BITS: Self::Bits = (-0.0 as $ty).to_bits();
fn is_nan(self) -> bool {
self.is_nan()
}
fn is_negative_zero(self) -> bool {
self.to_bits() == Self::NEG_ZERO_BITS
}
fn to_bits(self) -> Self::Bits {
self.to_bits()
}
}
impl LiteralType for $ty {
fn definition(&self, types: &mut Types) -> DataType {
<$ty as Type>::definition(types)
}
fn eq_dyn(&self, other: &dyn LiteralType) -> bool {
other
.as_any()
.downcast_ref::<Self>()
.is_some_and(|other| FloatKey::from(*self) == FloatKey::from(*other))
}
fn hash_dyn(&self, mut state: &mut dyn hash::Hasher) {
FloatKey::from(*self).hash(&mut state);
}
fn fmt_dyn(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
fn as_any(&self) -> &dyn Any {
self
}
}
};
}
impl_float_literal!(f32, u32);
impl_float_literal!(f64, u64);
#[cfg(is_nightly)]
impl_float_literal!(f16, u16);
#[cfg(is_nightly)]
impl_float_literal!(f128, u128);
================================================
FILE: specta/src/datatype/map.rs
================================================
use super::DataType;
/// Key-value collection type, such as [`HashMap`](std::collections::HashMap) or
/// another map-like container.
///
/// The first datatype is the key type and the second datatype is the value type.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Map(Box<(DataType, DataType)>);
impl Map {
/// Create a new map with the given key and value types.
pub fn new(key_ty: DataType, value_ty: DataType) -> Self {
Self(Box::new((key_ty, value_ty)))
}
/// The type of the map keys.
pub fn key_ty(&self) -> &DataType {
&self.0.0
}
/// Get a mutable reference to the type of the map keys.
pub fn key_ty_mut(&mut self) -> &mut DataType {
&mut self.0.0
}
/// Set the type of the map keys.
pub fn set_key_ty(&mut self, key_ty: DataType) {
self.0.0 = key_ty;
}
/// The type of the map values.
pub fn value_ty(&self) -> &DataType {
&self.0.1
}
/// Get a mutable reference to the type of the map values.
pub fn value_ty_mut(&mut self) -> &mut DataType {
&mut self.0.1
}
/// Set the type of the map values.
pub fn set_value_ty(&mut self, value_ty: DataType) {
self.0.1 = value_ty;
}
}
impl From<Map> for DataType {
fn from(t: Map) -> Self {
Self::Map(t)
}
}
================================================
FILE: specta/src/datatype/named.rs
================================================
use std::{
borrow::Cow,
hash::{DefaultHasher, Hash, Hasher},
mem,
panic::{self, AssertUnwindSafe, Location},
ptr,
sync::Arc,
};
use crate::{
Types,
datatype::{
DataType, Generic, NamedReference, NamedReferenceType, Reference,
generic::GenericDefinition, reference::NamedId,
},
};
/// Resolves any named types created by `func` as inline references.
/// This is emitted when `#[specta(inline)]` is used on a field so the inner fields `Type` implementation knows to inline.
pub fn inline<R>(types: &mut Types, func: impl FnOnce(&mut Types) -> R) -> R {
let prev = mem::replace(&mut types.should_inline, true);
let result = panic::catch_unwind(AssertUnwindSafe(|| func(types)));
types.should_inline = prev;
match result {
Ok(result) => result,
Err(payload) => panic::resume_unwind(payload),
}
}
/// Named datatype with its own export identity.
///
/// Exporters commonly render these as top-level declarations, such as
/// `export type MyType = ...` in TypeScript. Other datatypes refer back to a
/// named datatype through [`Reference::Named`].
///
/// # Invariants
///
/// The `id` is the stable identity used by [`Types`] and [`NamedReference`]. The
/// human-readable `name` alone is not guaranteed to be globally unique.
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct NamedDataType {
/// Stable identity for resolving references to this datatype.
pub(crate) id: NamedId,
/// Exported type name.
pub name: Cow<'static, str>,
/// Documentation comments attached to the source type.
pub docs: Cow<'static, str>,
/// Deprecation metadata attached to the source type.
pub deprecated: Option<Deprecated>,
/// Rust module path where the source type was defined.
pub module_path: Cow<'static, str>,
/// Source location where this named datatype was created.
pub location: Location<'static>,
/// Generic parameters declared by this named datatype.
pub generics: Cow<'static, [GenericDefinition]>,
/// The generalised datatype of this specific named data type.
/// This is what will be used for creating `export Type = ...;` statements.
///
/// This will be `None` for types which are container inlined as they aren't exported.
pub ty: Option<DataType>,
}
impl NamedDataType {
/// Constructs a new named datatype and register it into the [`Types`] collection.
#[track_caller]
pub fn new(
name: impl Into<Cow<'static, str>>,
types: &mut Types,
build: impl FnOnce(&mut Types, &mut NamedDataType),
) -> Self {
let location = Location::caller();
let mut ndt = Self {
id: NamedId::Dynamic(Arc::new(())),
name: name.into(),
docs: Cow::Borrowed(""),
deprecated: None,
module_path: file_path_to_module_path(location.file())
.map(Into::into)
.unwrap_or(Cow::Borrowed("virtual")),
location: location.to_owned(),
generics: Cow::Borrowed(&[]),
ty: None,
};
build(types, &mut ndt);
types.types.insert(ndt.id.clone(), Some(ndt.clone()));
types.len += 1;
ndt
}
/// Initializes a named type using a static sentinel as its identity.
///
/// This is used by `#[derive(Type)]` and the built-in `Type` implementation macros and must be used carefully.
///
/// <div class="warning">
///
/// **WARNING:** Do not call this outside of `specta` as its signature and behavior may change in minor releases!!!!
///
/// </div>
///
/// This registers the canonical [`NamedDataType`] for `sentinel` at most once, then returns a
/// use-site [`Reference`]. During first registration, `None` is inserted into [`Types`] before
/// `build_ndt` runs so recursive named lookups can observe that the type is already being
/// resolved instead of re-entering `build_ndt` (which would stack overflow).
///
/// The returned reference depends on the current inline context:
///
/// - When not inlining, this returns [`NamedReferenceType::Reference`] with
/// `instantiation_generics` as the concrete generic arguments for this use site.
/// - When inlining, this calls `build_ty` and returns [`NamedReferenceType::Inline`] containing
/// the resulting datatype.
/// - If inline expansion recursively reaches the same sentinel and generic arguments, this
/// returns [`NamedReferenceType::Recursive`] so exporters can avoid infinite expansion.
///
/// `has_const_param` only affects the temporary resolution context used while `build_ndt`
/// builds the canonical named type. That context controls implementations such as fixed-size
/// arrays, so they intentionally don't become part of the global type identity
/// (We don't want one call-sites const generic in the shared datatype on the `NamedDataType`).
///
/// `passthrough` is for wrapper/container types whose own definition is inline but whose inner
/// type should only see the caller's inline context. When passthrough expansion recursively
/// reaches the same wrapper, it clears `Types::should_inline` before calling `build_ty` so the
/// inner named type can break the cycle with a reference.
///
/// `build_ndt` fills metadata and, for exported named types, `NamedDataType::ty`. `build_ty`
/// builds the datatype used by inline references. If `build_ndt` panics, this removes the
/// placeholder entry and restores the previous resolution context before resuming the panic.
#[doc(hidden)]
#[track_caller]
pub fn init_with_sentinel(
sentinel: &'static str,
instantiation_generics: &[(Generic, DataType)],
has_const_param: bool,
passthrough: bool,
types: &mut Types,
build_ndt: fn(&mut Types, &mut NamedDataType),
mut build_ty: fn(&mut Types) -> DataType,
) -> Reference {
let id = NamedId::Static(sentinel);
let location = Location::caller().to_owned();
let caller_inline = types.should_inline;
let mut inline = caller_inline || passthrough;
// If we have never encountered this type, register it to type map
if !types.types.contains_key(&id) {
let mut ndt = NamedDataType {
id: id.clone(),
location,
// `build_ndt` will just override all of this.
generics: Cow::Borrowed(&[]),
ty: None,
name: Cow::Borrowed(""),
docs: Cow::Borrowed(""),
deprecated: None,
module_path: Cow::Borrowed(""),
};
types.types.insert(id.clone(), None);
let prev_inline = mem::replace(&mut types.should_inline, false);
let prev_has_const_params = mem::replace(&mut types.has_const_params, has_const_param);
let result = panic::catch_unwind(AssertUnwindSafe(|| build_ndt(types, &mut ndt)));
types.should_inline = prev_inline;
types.has_const_params = prev_has_const_params;
if let Err(payload) = result {
if types.types.contains_key(&id) {
types.types.remove(&id);
}
panic::resume_unwind(payload);
};
// We patch the Tauri `Type` implementation.
let is_tauri_type =
ndt.name == "TAURI_CHANNEL" && ndt.module_path.starts_with("tauri::");
if is_tauri_type {
ndt.ty = None;
inline = true;
build_ty = |_| {
unreachable!("Specta `build_ty` shouldn't be callable with `tauri::Channel`")
}
}
types.types.insert(id.clone(), Some(ndt));
types.len += 1;
// We patch the Tauri `Type` implementation.
if is_tauri_type {
return Reference::Named(NamedReference {
id,
inner: NamedReferenceType::Reference {
generics: instantiation_generics.to_owned(),
},
});
}
}
if inline {
let hash = {
let mut h = DefaultHasher::new();
sentinel.hash(&mut h);
ptr::hash(sentinel, &mut h);
for (generic_r, generic) in instantiation_generics {
generic_r.hash(&mut h);
generic.hash(&mut h);
}
h.finish()
};
if types.stack.contains(&hash) {
// For container inline types we wanna passthrough instead of rejecting on the container.
if passthrough {
let prev_inline = mem::replace(&mut types.should_inline, false);
let result = panic::catch_unwind(AssertUnwindSafe(|| build_ty(types)));
types.should_inline = prev_inline;
match result {
Ok(DataType::Reference(reference)) => return reference,
Ok(_) => {}
Err(payload) => panic::resume_unwind(payload),
}
}
return Reference::Named(NamedReference {
id,
inner: NamedReferenceType::Recursive,
});
}
// Say for `Box<T>` if we put `#[specta(inline)]` on it we will,
// naively inline the `Box` instead of `T`.
//
// "wrapper" types enable this to properly to passthrough inline to the inner type's resolution.
let child_inline = passthrough && caller_inline;
let prev_inline = (types.should_inline != child_inline)
.then(|| mem::replace(&mut types.should_inline, child_inline));
types.stack.push(hash);
let result = panic::catch_unwind(AssertUnwindSafe(|| build_ty(types)));
if let Some(prev_inline) = prev_inline {
types.should_inline = prev_inline;
};
types.stack.pop();
let dt = match result {
Ok(DataType::Reference(reference)) if passthrough && !caller_inline => {
return reference;
}
Ok(dt) => Box::new(dt),
Err(payload) => panic::resume_unwind(payload),
};
Reference::Named(NamedReference {
id,
inner: NamedReferenceType::Inline { dt },
})
} else {
Reference::Named(NamedReference {
id,
inner: NamedReferenceType::Reference {
generics: instantiation_generics.to_owned(),
},
})
}
}
/// Constructs a [`Reference`] to this named datatype.
/// The reference returned by this will error in the language exporter if `Self.ty` is `None` as the type can't generate a named export.
pub fn reference(&self, generics: Vec<(Generic, DataType)>) -> Reference {
Reference::Named(NamedReference {
id: self.id.clone(),
inner: NamedReferenceType::Reference { generics },
})
}
}
/// Runtime representation of Rust's `#[deprecated]` metadata.
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct Deprecated {
/// Optional deprecation note or replacement guidance.
pub note: Option<Cow<'static, str>>,
/// Optional version where the item became deprecated.
pub since: Option<Cow<'static, str>>,
}
impl Deprecated {
/// Constructs deprecation metadata without details.
///
/// Corresponds to `#[deprecated]`.
pub const fn new() -> Self {
Self {
note: None,
since: None,
}
}
/// Constructs deprecation metadata with a note.
///
/// Corresponds to `#[deprecated = "Use something else"]`.
pub fn with_note(note: Cow<'static, str>) -> Self {
Self {
note: Some(note),
since: None,
}
}
/// Constructs deprecation metadata with a note and optional `since` version.
///
/// Corresponds to `#[deprecated(since = "1.0.0", note = "Use something else")]`.
pub fn with_since_note(since: Option<Cow<'static, str>>, note: Cow<'static, str>) -> Self {
Self {
note: Some(note),
since,
}
}
}
fn file_path_to_module_path(file_path: &str) -> Option<String> {
let normalized = file_path.replace('\\', "/");
// Try different prefixes
let (prefix, path) = if let Some(p) = normalized.strip_prefix("src/") {
("crate", p)
} else if let Some(p) = normalized.strip_prefix("tests/") {
("tests", p)
} else {
return None;
};
let path = path.strip_suffix(".rs")?;
let path = path.strip_suffix("/mod").unwrap_or(path);
let module_path = path.replace('/', "::");
if module_path.is_empty() {
Some(prefix.to_string())
} else {
Some(format!("{}::{}", prefix, module_path))
}
}
#[cfg(test)]
mod tests {
use super::file_path_to_module_path;
#[test]
fn file_path_to_module_path_supports_unix_and_windows_separators() {
assert_eq!(
file_path_to_module_path("src/datatype/named.rs"),
Some("crate::datatype::named".to_string())
);
assert_eq!(
file_path_to_module_path("src\\datatype\\named.rs"),
Some("crate::datatype::named".to_string())
);
assert_eq!(
file_path_to_module_path("tests/tests/types.rs"),
Some("tests::tests::types".to_string())
);
assert_eq!(
file_path_to_module_path("tests\\tests\\types.rs"),
Some("tests::tests::types".to_string())
);
}
}
================================================
FILE: specta/src/datatype/primitive.rs
================================================
use super::DataType;
/// Rust built-in primitive type.
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Primitive {
/// [`i8`] primitive.
i8,
/// [`i16`] primitive.
i16,
/// [`i32`] primitive.
i32,
/// [`i64`] primitive.
i64,
/// [`i128`] primitive.
i128,
/// [`isize`] primitive.
isize,
/// [`u8`] primitive.
u8,
/// [`u16`] primitive.
u16,
/// [`u32`] primitive.
u32,
/// [`u64`] primitive.
u64,
/// [`u128`] primitive.
u128,
/// [`usize`] primitive.
usize,
/// [`f16`] primitive (nightly-only).
f16,
/// [`f32`] primitive.
f32,
/// [`f64`] primitive.
f64,
/// [`f128`] primitive (nightly-only).
f128,
/// [`bool`] primitive.
bool,
/// [`char`] primitive.
char,
/// [`str`] primitive.
str,
}
impl From<Primitive> for DataType {
fn from(t: Primitive) -> Self {
Self::Primitive(t)
}
}
================================================
FILE: specta/src/datatype/reference.rs
================================================
use std::{
any::{Any, TypeId},
fmt, hash,
sync::Arc,
};
use crate::datatype::Generic;
use super::DataType;
/// Reference to another datatype.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Reference {
/// Reference to a named type collected in a [`Types`](crate::Types).
///
/// This can either render as a named reference, such as `TypeName<T>`, or as
/// an inlined datatype depending on [`NamedReference::inner`].
Named(NamedReference),
/// Reference to an opaque exporter-specific type.
Opaque(OpaqueReference),
}
/// Reference to a [`NamedDataType`](crate::datatype::NamedDataType).
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct NamedReference {
pub(crate) id: NamedId,
/// How this named type should be referenced at the use site.
pub inner: NamedReferenceType,
}
/// Use-site representation for a [`NamedReference`].
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum NamedReferenceType {
/// Recursive reference encountered while resolving an inline type.
///
/// Exporters can use this marker to avoid infinitely expanding recursive
/// inline definitions that they would stack overflow resolving.
Recursive,
/// Inline the contained datatype at the reference site.
/// These are emitted when `#[specta(inline)]` is used on a field or container.
#[non_exhaustive]
Inline {
/// Datatype to render in place of the named reference.
dt: Box<DataType>,
},
/// Render a reference to the named datatype.
#[non_exhaustive]
Reference {
/// Concrete generic arguments for this use site.
generics: Vec<(Generic, DataType)>,
},
}
/// Reference to a type not understood by Specta's core datatype model.
///
/// These are implemented by the language exporter to implement cool features like
/// [`specta_typescript::branded!`](https://docs.rs/specta-typescript/latest/specta_typescript/macro.branded.html),
/// [`specta_typescript::define`](https://docs.rs/specta-typescript/latest/specta_typescript/fn.define.html), and more.
///
/// # Invariants
///
/// Equality and hashing are delegated to the stored opaque state. If two opaque
/// references should be distinct, their state values must compare and hash
/// distinctly.
///
/// This is an advanced feature designed for language exporters and framework
/// integrations. Most end users should prefer ordinary [`DataType`] variants.
#[derive(Clone)]
pub struct OpaqueReference(Arc<dyn DynOpaqueReference>);
trait DynOpaqueReference: Any + Send + Sync {
fn type_name(&self) -> &'static str;
fn hash(&self, hasher: &mut dyn hash::Hasher);
fn eq(&self, other: &dyn Any) -> bool;
fn as_any(&self) -> &dyn Any;
}
#[derive(Debug)]
struct OpaqueReferenceInner<T>(T);
impl<T: hash::Hash + Eq + Send + Sync + 'static> DynOpaqueReference for OpaqueReferenceInner<T> {
fn type_name(&self) -> &'static str {
std::any::type_name::<T>()
}
fn hash(&self, mut hasher: &mut dyn hash::Hasher) {
self.0.hash(&mut hasher)
}
fn eq(&self, other: &dyn Any) -> bool {
other
.downcast_ref::<T>()
.map(|other| self.0 == *other)
.unwrap_or_default()
}
fn as_any(&self) -> &dyn Any {
&self.0
}
}
impl fmt::Debug for OpaqueReference {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("OpaqueReference")
.field(&self.0.type_name())
.finish()
}
}
impl PartialEq for OpaqueReference {
fn eq(&self, other: &Self) -> bool {
self.0.eq(other.0.as_any())
}
}
impl Eq for OpaqueReference {}
impl hash::Hash for OpaqueReference {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.0.hash(state)
}
}
impl OpaqueReference {
/// Returns the Rust type name of the stored opaque state.
pub fn type_name(&self) -> &'static str {
self.0.type_name()
}
/// Returns the [`TypeId`] of the stored opaque state.
pub fn type_id(&self) -> TypeId {
self.0.as_any().type_id()
}
/// Attempts to downcast the opaque state to `T`.
pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
self.0.as_any().downcast_ref::<T>()
}
}
impl Reference {
/// Constructs a new reference to an opaque type.
///
/// An opaque type cannot be represented with the core [`DataType`] model and
/// requires specific exporter integration.
///
/// Opaque [`Reference`]s are compared using the state's [`PartialEq`]
/// implementation. For example, `Reference::opaque(()) ==
/// Reference::opaque(())`, so unique references need unique state.
pub fn opaque<T: hash::Hash + Eq + Send + Sync + 'static>(state: T) -> Self {
Self::Opaque(OpaqueReference(Arc::new(OpaqueReferenceInner(state))))
}
/// Returns whether two references point to the same underlying type.
///
/// This differs from [`Eq`], [`PartialEq`], and [`Hash`] because those compare
/// the full [`Reference`] which includes generic arguments and inline state.
pub fn ty_eq(&self, other: &Reference) -> bool {
match (self, other) {
(Reference::Named(a), Reference::Named(b)) => a.id == b.id,
(Reference::Opaque(a), Reference::Opaque(b)) => *a == *b,
_ => false,
}
}
}
impl From<Reference> for DataType {
fn from(r: Reference) -> Self {
Self::Reference(r)
}
}
/// Unique identifier for a [NamedDataType].
///
/// For static types (from derive macros), we use a unique string based on the
/// type's module path and name. For dynamic types, we use an Arc pointer.
#[derive(Clone)]
pub(crate) enum NamedId {
// A unique string identifying the type (module_path::TypeName).
Static(&'static str),
Dynamic(Arc<()>),
}
impl PartialEq for NamedId {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(NamedId::Static(a), NamedId::Static(b)) => a == b,
(NamedId::Dynamic(a), NamedId::Dynamic(b)) => Arc::ptr_eq(a, b),
_ => false,
}
}
}
impl Eq for NamedId {}
impl hash::Hash for NamedId {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
match self {
NamedId::Static(s) => s.hash(state),
NamedId::Dynamic(p) => std::ptr::hash(Arc::as_ptr(p), state),
}
}
}
impl fmt::Debug for NamedId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
NamedId::Static(s) => write!(f, "s:{}", s),
NamedId::Dynamic(p) => write!(f, "d{:p}", Arc::as_ptr(p)),
}
}
}
================================================
FILE: specta/src/datatype/struct.rs
================================================
use crate::datatype::{Attributes, DataType, Fields};
use super::StructBuilder;
use super::{NamedFields, UnnamedFields};
/// Runtime representation of a Rust [`struct`](https://doc.rust-lang.org/std/keyword.struct.html).
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct Struct {
/// Field layout for the struct.
pub fields: Fields,
/// Runtime attributes attached to the struct container.
pub attributes: Attributes,
}
// Do not implement `Default` for `Struct` as it's unclear what that would be. `Unit`, yes but still.
impl Struct {
/// Construct a new unit struct.
pub fn unit() -> Self {
Self {
fields: Fields::Unit,
attributes: Default::default(),
}
}
/// Starts building a struct with named fields.
pub fn named() -> StructBuilder<NamedFields> {
StructBuilder {
fields: NamedFields {
fields: Default::default(),
},
}
}
/// Starts building a tuple struct with unnamed fields.
pub fn unnamed() -> StructBuilder<UnnamedFields> {
StructBuilder {
fields: UnnamedFields {
fields: Default::default(),
},
}
}
}
impl From<Struct> for DataType {
fn from(t: Struct) -> Self {
Self::Struct(t)
}
}
================================================
FILE: specta/src/datatype/tuple.rs
================================================
use super::DataType;
/// Represents a Rust [tuple](https://doc.rust-lang.org/std/primitive.tuple.html) type.
///
/// The empty tuple `()` is represented as a tuple with no elements. Exporters may
/// render that specially, such as `null` in the TypeScript exporter.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct Tuple {
/// Datatypes for each tuple element, in source order.
pub elements: Vec<DataType>,
}
impl Tuple {
/// Create a new tuple with the given elements.
pub fn new(elements: Vec<DataType>) -> Self {
Self { elements }
}
}
impl From<Tuple> for DataType {
fn from(t: Tuple) -> Self {
Self::Tuple(t)
}
}
================================================
FILE: specta/src/datatype.rs
================================================
//! Types related to working with [`DataType`]. Exposed for advanced users.
mod attributes;
mod r#enum;
mod fields;
mod function;
mod generic;
mod list;
mod map;
mod named;
mod primitive;
mod reference;
mod r#struct;
mod tuple;
pub use attributes::Attributes;
pub use r#enum::{Enum, Variant, VariantBuilder};
pub use fields::{Field, Fields, NamedFields, StructBuilder, UnnamedFields};
pub use function::Function;
pub use generic::{Generic, Generic as GenericReference, GenericDefinition};
pub use list::List;
// pub use literal::Literal;
pub use map::Map;
pub use named::{Deprecated, NamedDataType, inline};
pub use primitive::Primitive;
pub use reference::{NamedReference, NamedReferenceType, OpaqueReference, Reference};
pub use r#struct::Struct;
pub use tuple::Tuple;
pub(crate) use reference::NamedId;
/// Runtime type-erased representation of a Rust type.
///
/// A language exporter takes this general format and converts it into a language specific syntax.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum DataType {
/// A primitive scalar type like integers, floats, booleans, chars, or strings.
Primitive(Primitive),
/// A sequential collection type.
List(List),
/// A map/dictionary type.
Map(Map),
/// A struct type with named, unnamed, or unit fields.
Struct(Struct),
/// An enum type.
Enum(Enum),
/// A tuple type.
Tuple(Tuple),
/// A nullable wrapper around another type.
Nullable(Box<DataType>),
/// A structural intersection of multiple object-like types.
Intersection(Vec<DataType>),
/// A placeholder for a generic type defined on the parent [`NamedDataType`].
/// Rendered as `T`. These should never be returned from [`Type::definition`](crate::Type::definition), they should only appear in [`NamedDataType`]'s `ty` field.
Generic(Generic),
/// A reference to another named or opaque type.
Reference(Reference),
}
================================================
FILE: specta/src/docs.md
================================================
Easily export your Rust types to other languages.
Specta provides a system for type introspection and a set of language exporters which allow you to export your Rust types to other languages!
**Get started** by checking out the language exporter's, start with [Typescript](https://docs.rs/specta-typescript).
## Features
- Export structs and enums to [Typescript](https://www.typescriptlang.org)
- Get function types to use in libraries like [tauri-specta](https://github.com/specta-rs/tauri-specta)
- Supports wide range of common crates in Rust ecosystem
- Supports type inference - can determine type of `fn demo() -> impl Type`.
## Ecosystem
Specta can be used in your application either directly or through a library which simplifies the process of using it.
- [rspc](https://github.com/specta-rs/rspc) - A framework for building typesafe web backends in Rust
- [tauri-specta](https://github.com/specta-rs/tauri-specta) - Completely typesafe Tauri commands
- [TauRPC](https://github.com/MatsDK/TauRPC) - Typesafe IPC layer for Tauri applications
- [orpc-rs](https://github.com/ahonn/orpc-rs) - Rust implementation of [oRPC](https://orpc.dev) — type-safe RPC with first-class Tauri support.
## Languages
Specta is designed to be able to export from Rust to any other language.
| Language | Status |
| ------------------------------------------------------ | ------------- |
| [specta-typescript](https://docs.rs/specta-typescript) | **stable** |
| [specta-go](https://docs.rs/specta-go) | alpha |
| [specta-swift](https://docs.rs/specta-swift) | alpha |
| [specta-openapi](https://docs.rs/specta-openapi) | wip |
| [specta-jsonschema](https://docs.rs/specta-jsonschema) | wip |
| [specta-zod](https://docs.rs/specta-zod) | wip |
| [specta-kotlin](https://docs.rs/specta-kotlin) | _coming soon_ |
| specta-jsdoc | _coming soon_ |
| specta-rust | _coming soon_ |
| specta-valibot | _coming soon_ |
## Formats
Specta is format agnostic. Format-specific behavior is handled by companion
crates before handing transformed types to language exporters.
| Format | Status |
| ------ | ------------- |
| [specta-serde](https://docs.rs/specta-serde) | **stable** |
## Feature flags
[//]: # (FEATURE_FLAGS_START)
- `function` - Support for exporting the types of Rust functions.
- `collect` - Support for collecting up a global type map
Languages
- `typescript` - Support for [TypeScript](https://www.typescriptlang.org) language exporting
- `js_doc` - Support for [JSDoc](https://jsdoc.app) exporting helpers. Also requires `typescript` feature to be enabled.
Compatibility
- `serde` - Support for [serde](https://serde.rs)
- `serde_json` - Support for [serde-json](https://github.com/serde-rs/json)
- `serde_yaml` - Support for [serde_yaml](https://github.com/dtolnay/serde-yaml)
- `toml` - Support for [toml](https://github.com/toml-rs/toml)
- `tauri` - Support for [Tauri](https://tauri.app). This is required when using the `#[specta]` attribute with Tauri Commands.
External types
- `ulid` - [ulid](https://docs.rs/ulid) crate
- `uuid` - [uuid](https://docs.rs/uuid) crate
- `chrono` - [chrono](https://docs.rs/chrono) crate
- `time` - [time](https://docs.rs/time) crate
- `jiff` - [jiff](https://docs.rs/jiff) crate
- `bigdecimal` - [bigdecimal](https://docs.rs/bigdecimal) crate
- `rust_decimal` - [rust_decimal](https://docs.rs/rust_decimal) crate
- `indexmap` - [indexmap](https://docs.rs/indexmap) crate
- `ordered-float` - [ordered-float](https://docs.rs/ordered-float) crate
- `heapless` - [heapless](https://docs.rs/heapless) crate
- `semver` - [semver](https://docs.rs/semver) crate
- `smol_str` - [smol_str](https://docs.rs/smol_str) crate
- `arrayvec` - [arrayvec](https://docs.rs/arrayvec) crate
- `smallvec` - [smallvec](https://docs.rs/smallvec) crate
- `ipnetwork` - [ipnetwork](https://docs.rs/ipnetwork) crate
- `mac_address` - [mac_address](https://docs.rs/mac_address) crate
- `bit-vec` - [bit-vec](https://docs.rs/bit-vec) crate
- `bson` - [bson](https://docs.rs/bson) crate
- `uhlc` - [uhlc](https://docs.rs/uhlc) crate
- `bytesize` - [bytesize](https://docs.rs/bytesize) crate
- `glam` - [glam](https://docs.rs/glam) crate
- `tokio` - [tokio](https://docs.rs/tokio) crate
- `url` - [url](https://docs.rs/url) crate
- `either` - [either](https://docs.rs/either) crate
- `bevy_ecs` - [bevy_ecs](https://docs.rs/bevy_ecs) crate
[//]: # (FEATURE_FLAGS_END)
## Alternatives
#### Why not ts-rs?
[ts-rs](https://github.com/Aleph-Alpha/ts-rs) is a great library,
but it has a few limitations which became a problem when I was building [rspc](https://github.com/specta-rs/rspc).
Namely it deals with types individually which means it is not possible to export a type and all of the other types it depends on.
#### Why not Typeshare?
[Typeshare](https://github.com/1Password/typeshare) is also great, but its approach is fundamentally different.
While Specta uses traits and runtime information, Typeshare statically analyzes your Rust
files.
This results in a loss of information and lack of compatibility with types from other crates.
================================================
FILE: specta/src/format.rs
================================================
use std::{borrow::Cow, error};
use crate::{Types, datatype::DataType};
/// Error type returned by [`Format`] callbacks.
pub type FormatError = Box<dyn error::Error + Send + Sync + 'static>;
/// The format is used to inform Specta how the Serialize/Deserialization layer handles types.
///
/// This allows them to rewrite the collected types and encountered datatypes to apply format-specific macro attributes or behaviour.
///
/// Currently we have support for:
/// - [serde](https://docs.rs/specta) via [`specta-serde`](https://docs.rs/specta-serde)
///
pub trait Format {
/// Apply a map function to the full [`Types`] collection.
///
/// Returns [`Cow::Borrowed`] when no changes are needed, or
/// [`Cow::Owned`] when the formatter produces a transformed collection.
fn map_types(&'_ self, types: &Types) -> std::result::Result<Cow<'_, Types>, FormatError>;
/// Map an individual [`DataType`] with access to the surrounding [`Types`].
///
/// Returns [`Cow::Borrowed`] when no changes are needed, or
/// [`Cow::Owned`] when the formatter produces a transformed datatype.
fn map_type(
&'_ self,
types: &Types,
dt: &DataType,
) -> std::result::Result<Cow<'_, DataType>, FormatError>;
}
impl<T: Format + ?Sized> Format for &T {
fn map_types(&'_ self, types: &Types) -> std::result::Result<Cow<'_, Types>, FormatError> {
(**self).map_types(types)
}
fn map_type(
&'_ self,
types: &Types,
dt: &DataType,
) -> std::result::Result<Cow<'_, DataType>, FormatError> {
(**self).map_type(types, dt)
}
}
impl<T: Format + ?Sized> Format for Box<T> {
fn map_types(&'_ self, types: &Types) -> std::result::Result<Cow<'_, Types>, FormatError> {
(**self).map_types(types)
}
fn map_type(
&'_ self,
types: &Types,
dt: &DataType,
) -> std::result::Result<Cow<'_, DataType>, FormatError> {
(**self).map_type(types, dt)
}
}
// Assert dyn-safety
const _: Option<&dyn Format> = None;
================================================
FILE: specta/src/function/arg.rs
================================================
use crate::{Type, Types, datatype::DataType};
/// Implemented by types that can be used as an argument in a function annotated with
/// [`specta`](crate::specta).
pub trait FunctionArg {
/// Gets the type of an argument as a [`DataType`].
///
/// Some argument types should be ignored (eg. when doing dependency injection),
/// so the value is optional.
fn to_datatype(types: &mut Types) -> Option<DataType>;
}
impl<T: Type> FunctionArg for T {
fn to_datatype(types: &mut Types) -> Option<DataType> {
Some(T::definition(types))
}
}
================================================
FILE: specta/src/function/result.rs
================================================
use std::future::Future;
use crate::{Type, Types, datatype::DataType};
/// Implemented by types that can be returned from a function annotated with
/// [`specta`](crate::specta).
pub trait FunctionResult<TMarker> {
/// Gets the function return type as a [`DataType`].
fn to_datatype(types: &mut Types) -> DataType;
}
#[doc(hidden)]
pub enum FunctionValueMarker {}
impl<T: Type> FunctionResult<FunctionValueMarker> for T {
fn to_datatype(types: &mut Types) -> DataType {
T::definition(types)
}
}
#[doc(hidden)]
pub enum FunctionFutureMarker {}
impl<F> FunctionResult<FunctionFutureMarker> for F
where
F: Future,
F::Output: Type,
{
fn to_datatype(types: &mut Types) -> DataType {
F::Output::definition(types)
}
}
================================================
FILE: specta/src/function/specta_fn.rs
================================================
use std::borrow::Cow;
use crate::{
Types,
datatype::{Deprecated, Function},
};
use super::{FunctionArg, FunctionResult};
/// Implemented by functions that can be annotated with [`specta`](crate::specta).
///
/// This trait is sealed as it won't need to be used externally.
pub trait SpectaFn<TMarker> {
/// Gets the type of a function as a [`Function`](crate::datatype::Function).
fn to_datatype(
asyncness: bool,
name: Cow<'static, str>,
types: &mut Types,
fields: &[Cow<'static, str>],
docs: Cow<'static, str>,
deprecated: Option<Deprecated>,
no_return_type: bool,
) -> Function;
}
impl<TResult, TResultMarker> SpectaFn<TResultMarker> for fn() -> TResult
where
TResult: FunctionResult<TResultMarker>,
{
fn to_datatype(
asyncness: bool,
name: Cow<'static, str>,
types: &mut Types,
_fields: &[Cow<'static, str>],
docs: Cow<'static, str>,
deprecated: Option<Deprecated>,
no_return_type: bool,
) -> Function {
Function {
asyncness,
name,
args: vec![],
result: (!no_return_type).then(|| TResult::to_datatype(types)),
docs,
deprecated,
}
}
}
macro_rules! impl_typed_command {
( impl $($i:ident),* ) => {
paste::paste! {
impl<
TResult,
TResultMarker,
$($i: FunctionArg),*
> SpectaFn<TResultMarker> for fn($($i),*) -> TResult
where
TResult: FunctionResult<TResultMarker>,
{
fn to_datatype(
asyncness: bool,
name: Cow<'static, str>,
types: &mut Types,
fields: &[Cow<'static, str>],
docs: Cow<'static, str>,
deprecated: Option<Deprecated>,
no_return_type: bool,
) -> Function {
let mut fields = fields.into_iter();
Function {
asyncness,
name,
docs,
deprecated,
args: [$(
fields
.next()
.map_or_else(
|| None,
|field| $i::to_datatype(types).map(|ty| (field.clone(), ty))
)
),*,]
.into_iter()
.filter_map(|v| v)
.collect::<Vec<_>>(),
result: (!no_return_type).then(|| TResult::to_datatype(types)),
}
}
}
}
};
( $i2:ident $(, $i:ident)* ) => {
impl_typed_command!(impl $i2 $(, $i)* );
impl_typed_command!($($i),*);
};
() => {};
}
impl_typed_command!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
================================================
FILE: specta/src/function.rs
================================================
//! Support for collecting Rust function signatures.
//!
//! Specta does not export callable functions by itself. Instead, it records the
//! names, arguments, return types, docs, and deprecation metadata needed by
//! framework crates to generate bindings for their own function or command
//! systems.
mod arg;
mod result;
mod specta_fn;
pub use arg::FunctionArg;
pub use result::FunctionResult;
#[doc(hidden)]
pub use result::{FunctionFutureMarker, FunctionValueMarker};
pub(crate) use specta_fn::SpectaFn;
/// Returns a [`Function`](crate::datatype::Function) for a given function that has been annotated with
/// the `#[specta]` attribute.
///
/// # Examples
///
/// ```rust
/// use specta::{*, datatype::*, function::fn_datatype};
///
/// #[specta]
/// fn some_function(name: String, age: i32) -> bool {
/// true
/// }
///
/// fn main() {
/// let typ = fn_datatype!(some_function)(&mut Types::default());
///
/// assert_eq!(typ.name(), "some_function");
/// assert_eq!(typ.args().len(), 2);
/// assert_eq!(typ.result(), Some(&DataType::Primitive(Primitive::bool)));
/// }
/// ```
///
/// # Recursion limit reached while expanding the macro `fn_datatype`
///
/// This macro requires recursion internally to correctly function so you may run into the recursion limit. From my testing you can have 31 path segments before you hit the recursion limit. The size of the segment or the amount of generics in the segment should not affect this limit.
///
/// If your having issues with this limit you can increase your [`recursion_limit`](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute) by adding `#![recursion_limit = "1024"]` to your `main.rs`. If your able to hit this limit in other scenarios please [let us know](https://github.com/specta-rs/tauri-specta/issues/114) and we can apply some potential optimizations.
///
#[doc(hidden)]
#[macro_export]
macro_rules! _fn_datatype {
// Hide distracting implementation details from the generated rustdoc.
($($json:tt)*) => {
$crate::function::_fn_datatype_internal!($($json)*)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! _fn_datatype_internal {
([$($path:tt)*] [$($full:tt)*] [$last:tt]) => {
$crate::internal::paste! {
$($path)* [<__specta__fn__ $last>]!(@export_fn; $($full)*)
}
};
([$($path:tt)*] [$($full:tt)*] [$($last:tt)?] $t:tt :: <$($g:path),*> $($rest:tt)*) => {
$crate::function::fn_datatype!([$($path)* $($last)*] [$($full)* $t::<$($g),*>] [$t] $($rest)*)
};
([$($path:tt)*] [$($full:tt)*] [$($last:tt)?] $t:tt $($rest:tt)*) => {
$crate::function::fn_datatype!([$($path)* $($last)*] [$($full)* $t] [$t] $($rest)*)
};
() => {{
compile_error!("fn_datatype must be provided a function path as an argument");
}};
($($rest:tt)*) => {
$crate::function::fn_datatype!([] [] [] $($rest)*)
};
}
/// Collects function types into a [`Vec`],
/// and all downstream types into a [`Types`](crate::Types) instance.
///
/// Specifying a `types` argument allows a custom [`Types`](crate::Types) to be used.
///
/// # Examples
///
/// ```rust
/// use specta::*;
///
/// #[specta]
/// fn some_function(name: String, age: i32) -> bool {
/// true
/// }
///
/// fn main() {
/// let functions = function::collect_functions);
/// }
/// ````
#[doc(hidden)]
#[macro_export]
macro_rules! _collect_functions {
($(,)?) => {{
fn export(_: &mut $crate::Types) -> Vec<$crate::datatype::Function> {
vec![]
}
export
}};
($($b:tt $(:: $($p:ident)? $(<$($g:path),*>)? )* ),* $(,)?) => {{
fn export(types: &mut $crate::Types) -> Vec<$crate::datatype::Function> {
vec![
$($crate::function::fn_datatype!($b $($(::$p)? $(::<$($g),*>)? )* )(types)),*
]
}
export
}};
}
#[doc(inline)]
pub use _collect_functions as collect_functions;
#[doc(inline)]
pub use _fn_datatype as fn_datatype;
#[doc(hidden)]
pub use _fn_datatype_internal;
================================================
FILE: specta/src/internal.rs
================================================
//! This module contains functions that are public for the sole reason of the macros.
//!
//! They will not be documented and may go through breaking changes without a major version bump!
//!
//! DO NOT USE THEM! You have been warned!
#[cfg(feature = "function")]
pub use paste::paste;
#[cfg(feature = "function")]
mod functions {
use std::borrow::Cow;
use crate::{Types, datatype::Deprecated, datatype::Function, function::SpectaFn};
#[doc(hidden)]
/// A helper for exporting a command to a [`CommandDataType`].
/// You shouldn't use this directly and instead should use [`fn_datatype!`](crate::fn_datatype).
pub fn get_fn_datatype<TMarker, T: SpectaFn<TMarker>>(
_: T,
asyncness: bool,
name: Cow<'static, str>,
types: &mut Types,
fields: &[Cow<'static, str>],
docs: Cow<'static, str>,
deprecated: Option<Deprecated>,
no_return_type: bool,
) -> Function {
T::to_datatype(
asyncness,
name,
types,
fields,
docs,
deprecated,
no_return_type,
)
}
}
#[cfg(feature = "function")]
pub use functions::*;
================================================
FILE: specta/src/lib.rs
================================================
#![doc = include_str!("./docs.md")]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc(
html_logo_url = "https://github.com/specta-rs/specta/raw/main/.github/logo-128.png",
html_favicon_url = "https://github.com/specta-rs/specta/raw/main/.github/logo-128.png"
)]
#![cfg_attr(is_nightly, feature(f16))]
#![cfg_attr(is_nightly, feature(f128))]
#[cfg(feature = "collect")]
#[cfg_attr(docsrs, doc(cfg(feature = "collect")))]
#[doc(hidden)]
pub mod collect;
pub mod datatype;
mod format;
#[cfg(feature = "function")]
#[cfg_attr(docsrs, doc(cfg(feature = "function")))]
pub mod function;
#[doc(hidden)]
pub mod internal;
mod r#type;
mod types;
#[doc(inline)]
pub use format::{Format, FormatError};
#[doc(inline)]
pub use r#type::Type;
#[doc(inline)]
pub use types::Types;
#[doc(inline)]
#[cfg(feature = "collect")]
#[cfg_attr(docsrs, doc(cfg(feature = "collect")))]
pub use collect::collect;
#[doc(inline)]
#[cfg(feature = "derive")]
#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
pub use specta_macros::Type;
#[doc(hidden)]
#[cfg(feature = "derive")]
#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
pub use specta_macros::parse_type_from_lit;
#[doc(inline)]
#[cfg(all(feature = "derive", feature = "function"))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "derive", feature = "function"))))]
pub use specta_macros::specta;
// TODO(v3): Remove this. This must be kept for Specta v1 as Tauri v2 depends on it.
#[doc(hidden)]
#[deprecated(note = "Migrate from `TypeMap` to `Types`")]
pub type TypeMap = Types;
================================================
FILE: specta/src/type/impls.rs
================================================
use std::marker::PhantomData;
use crate::{
Type, Types,
datatype::{self, DataType, List},
r#type::macros::*,
};
impl_primitives!(
i8 i16 i32 i64 i128 isize
u8 u16 u32 u64 u128 usize
f32 f64
bool char
str
);
#[cfg(is_nightly)]
#[cfg_attr(docsrs, doc(cfg(is_nightly)))]
impl Type for f16 {
fn definition(_: &mut Types) -> DataType {
DataType::Primitive(datatype::Primitive::f16)
}
}
#[cfg(is_nightly)]
#[cfg_attr(docsrs, doc(cfg(is_nightly)))]
impl Type for f128 {
fn definition(_: &mut Types) -> DataType {
DataType::Primitive(datatype::Primitive::f128)
}
}
// Technically we only support 12-tuples but the `T13` is required due to how the macro works
impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
#[allow(dead_code)]
pub(crate) struct PrimitiveSet<T>(PhantomData<T>);
impl<T: Type> Type for PrimitiveSet<T> {
fn definition(types: &mut Types) -> DataType {
let mut l = List::new(<T as Type>::definition(types));
l.unique = true;
DataType::List(l)
}
}
#[allow(dead_code)]
pub(crate) struct PrimitiveMap<K, V>(PhantomData<K>, PhantomData<V>);
impl<K: Type, V: Type> Type for PrimitiveMap<K, V> {
fn definition(types: &mut Types) -> DataType {
DataType::Map(crate::datatype::Map::new(
K::definition(types),
V::definition(types),
))
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
const _: () = {
use crate::datatype::{Enum, Field};
impl_ndt!(
std::string::String as str = inline;
// Non-unique sets
std::vec::Vec<T> as [T] = passthrough;
std::collections::VecDeque<T> as [T] = passthrough;
std::collections::BinaryHeap<T> as [T] = passthrough;
std::collections::LinkedList<T> as [T] = passthrough;
// Unique sets
std::collections::HashSet<T> as PrimitiveSet<T> = passthrough;
std::collections::BTreeSet<T> as PrimitiveSet<T> = passthrough;
// Maps
std::collections::HashMap<K, V> as PrimitiveMap<K, V> = passthrough;
std::collections::BTreeMap<K, V> as PrimitiveMap<K, V> = passthrough;
// Containers
std::boxed::Box<T> where { T: Type + ?Sized } as T = passthrough;
std::rc::Rc<T> where { T: Type + ?Sized } as T = passthrough;
std::sync::Arc<T> where { T: Type + ?Sized } as T = passthrough;
std::cell::Cell<T> where { T: Type + ?Sized } as T = passthrough;
std::cell::RefCell<T> where { T: Type + ?Sized } as T = passthrough;
std::sync::Mutex<T> where { T: Type + ?Sized } as T = passthrough;
std::sync::RwLock<T> where { T: Type + ?Sized } as T = passthrough;
std::ffi::CString as str = inline;
std::ffi::CStr as str = inline;
std::ffi::OsString as str = inline;
std::ffi::OsStr as str = inline;
std::path::Path as str = inline;
std::path::PathBuf as str = inline;
std::net::IpAddr as str = inline;
std::net::Ipv4Addr as str = inline;
std::net::Ipv6Addr as str = inline;
std::net::SocketAddr as str = inline;
std::net::SocketAddrV4 as str = inline;
std::net::SocketAddrV6 as str = inline;
std::sync::atomic::AtomicBool as bool = inline;
std::sync::atomic::AtomicI8 as i8 = inline;
std::sync::atomic::AtomicI16 as i16 = inline;
std::sync::atomic::AtomicI32 as i32 = inline;
std::sync::atomic::AtomicIsize as isize = inline;
std::sync::atomic::AtomicU8 as u8 = inline;
std::sync::atomic::AtomicU16 as u16 = inline;
std::sync::atomic::AtomicU32 as u32 = inline;
std::sync::atomic::AtomicUsize as usize = inline;
std::sync::atomic::AtomicI64 as i64 = inline;
std::sync::atomic::AtomicU64 as u64 = inline;
std::num::NonZeroU8 as u8 = inline;
std::num::NonZeroU16 as u16 = inline;
std::num::NonZeroU32 as u32 = inline;
std::num::NonZeroU64 as u64 = inline;
std::num::NonZeroUsize as usize = inline;
std::num::NonZeroI8 as i8 = inline;
std::num::NonZeroI16 as i16 = inline;
std::num::NonZeroI32 as i32 = inline;
std::num::NonZeroI64 as i64 = inline;
std::num::NonZeroIsize as isize = inline;
std::num::NonZeroU128 as u128 = inline;
std::num::NonZeroI128 as i128 = inline;
// Serde are cringe so this is how it is :(
std::ops::Range<T> as BaseRange<T> = named;
std::ops::RangeInclusive<T> as BaseRange<T> = named;
std::time::SystemTime as BaseSystemTime = named;
std::time::Duration as BaseDuration = named;
std::convert::Infallible as BaseInfallible = inline;
std::marker::PhantomData<T> as () = inline;
std::borrow::Cow<'a, T> where { T: Type + ?Sized + ToOwned + 'a } as T = inline;
std::result::Result<T, E> as BaseResult<T, E> = named;
);
struct BaseInfallible;
impl Type for BaseInfallible {
fn definition(_: &mut Types) -> DataType {
// Serde does no support `Infallible` as it can't be constructed as a `&self` method is uncallable on it.
DataType::Enum(Enum::default())
}
}
struct BaseSystemTime;
impl Type for BaseSystemTime {
fn definition(types: &mut Types) -> DataType {
datatype::Struct::named()
.field(
"duration_since_epoch",
Field::new(<i64 as crate::Type>::definition(types)),
)
.field(
"duration_since_unix_epoch",
Field::new(<u32 as crate::Type>::definition(types)),
)
.build()
}
}
struct BaseDuration;
impl Type for BaseDuration {
fn definition(types: &mut Types) -> DataType {
datatype::Struct::named()
.field("secs", Field::new(<u64 as crate::Type>::definition(types)))
.field("nanos", Field::new(<u32 as crate::Type>::definition(types)))
.build()
}
}
struct BaseRange<T>(PhantomData<T>);
impl<T: Type> Type for BaseRange<T> {
fn definition(types: &mut Types) -> DataType {
let ty = T::definition(types);
datatype::Struct::named()
.field("start", Field::new(ty.clone()))
.field("end", Field::new(ty))
.build()
}
}
struct BaseResult<T, E>(PhantomData<T>, PhantomData<E>);
impl<T: Type, E: Type> Type for BaseResult<T, E> {
fn definition(types: &mut Types) -> DataType {
datatype::Struct::named()
.field("ok", Field::new(<T as Type>::definition(types)))
.field("err", Field::new(<E as Type>::definition(types)))
.build()
}
}
};
#[cfg(feature = "tokio")]
#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
impl_ndt!(
tokio::sync::Mutex<T> where { T: Type + ?Sized } as T = passthrough;
tokio::sync::RwLock<T> where { T: Type + ?Sized } as T = passthrough;
);
impl<T: Type + ?Sized> Type for &T {
fn definition(types: &mut Types) -> DataType {
T::definition(types)
}
}
impl<T: Type> Type for [T] {
fn definition(types: &mut Types) -> DataType {
let mut l = List::new(<T as Type>::definition(types));
l.unique = false;
DataType::List(l)
}
}
impl<const N: usize, T: Type> Type for [T; N] {
fn definition(types: &mut Types) -> DataType {
let mut l = List::new(T::definition(types));
// Refer to the documentation for `Types::has_const_params` to understand this.
// If you wanna force this use `specta_utils::FixedArray<N, T>` instead.
if !types.has_const_params {
l.length = Some(N);
}
DataType::List(l)
}
}
impl<T: Type> Type for Option<T> {
fn definition(types: &mut Types) -> DataType {
DataType::Nullable(Box::new(T::definition(types)))
}
}
================================================
FILE: specta/src/type/legacy_impls.rs
================================================
use crate::{Type, Types};
#[allow(unused_imports)]
use crate::{datatype::*, r#type::impls::*, r#type::macros::impl_ndt};
// `String` requires `std` feature, while `str` does not.
// We can't use `str` in a lot of places because it's not `Sized`, so this bridges that.
#[allow(unused)]
pub struct String;
impl Type for String {
fn definition(types: &mut Types) -> DataType {
str::definition(types)
}
}
#[cfg(feature = "indexmap")]
#[cfg_attr(docsrs, doc(cfg(feature = "indexmap")))]
const _: () = {
impl_ndt!(
indexmap::IndexSet<T> as PrimitiveSet<T> = passthrough;
indexmap::IndexMap<K, V> as PrimitiveMap<K, V> = passthrough;
);
};
#[cfg(feature = "ordered-float")]
#[cfg_attr(docsrs, doc(cfg(feature = "ordered-float")))]
impl_ndt!(
ordered_float::OrderedFloat<T> where { T: Type + ordered_float::FloatCore } as T = inline;
ordered_float::NotNan<T> where { T: Type + ordered_float::FloatCore } as T = inline;
);
#[cfg(feature = "heapless")]
#[cfg_attr(docsrs, doc(cfg(feature = "heapless")))]
const _: () = {
impl_ndt!(
// Sequential containers
heapless::Vec<T> <T, const N: usize, LenT> where { T: Type, LenT: heapless::LenType } as [T; N] = passthrough;
heapless::Deque<T> <T, const N: usize> where { T: Type } as [T; N] = passthrough;
heapless::HistoryBuf<T> <T, const N: usize> where { T: Type } as [T; N] = passthrough;
heapless::BinaryHeap<T, K> <T, K, const N: usize> where { T: Type + Ord, K: heapless::binary_heap::Kind } as [T; N] = passthrough;
// Sets
heapless::IndexSet<T, S> <T, S, const N: usize> where { T: Type + Eq + core::hash::Hash, S: core::hash::BuildHasher } as PrimitiveSet<T> = passthrough;
// Maps
heapless::IndexMap<K, V, S> <K, V, S, const N: usize> where { K: Type + Eq + core::hash::Hash, V: Type, S: core::hash::BuildHasher } as PrimitiveMap<K, V> = passthrough;
heapless::LinearMap<K, V> <K, V, const N: usize> where { K: Type + Eq, V: Type } as PrimitiveMap<K, V> = passthrough;
// String container
heapless::String <const N: usize, LenT> where { LenT: heapless::LenType } as str = inline;
);
};
#[cfg(feature = "semver")]
#[cfg_attr(docsrs, doc(cfg(feature = "semver")))]
impl_ndt!(
semver::Version as str = inline;
semver::VersionReq as str = inline;
semver::Comparator as str = inline;
);
#[cfg(feature = "smol_str")]
#[cfg_attr(docsrs, doc(cfg(feature = "smol_str")))]
impl_ndt!(smol_str::SmolStr as str = inline);
#[cfg(feature = "arrayvec")]
#[cfg_attr(docsrs, doc(cfg(feature = "arrayvec")))]
impl_ndt!(
arrayvec::ArrayString <const N: usize> as str = inline;
arrayvec::ArrayVec<T> <T, const N: usize> as [T; N] = passthrough;
);
#[cfg(feature = "smallvec")]
#[cfg_attr(docsrs, doc(cfg(feature = "smallvec")))]
impl_ndt!(smallvec::SmallVec<T> where { T: smallvec::Array + Type } as [T] = passthrough);
#[cfg(feature = "bytes")]
#[cfg_attr(docsrs, doc(cfg(feature = "bytes")))]
impl_ndt!(
bytes::Bytes as [u8] = inline;
bytes::BytesMut as [u8] = inline;
);
#[cfg(feature = "serde_json")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde_json")))]
const _: () = {
use serde_json::{Map, Number, Value};
impl_ndt!(
serde_json::Map<K, V> as PrimitiveMap<K, V> = passthrough;
serde_json::Value as SerdeValue = inline;
serde_json::Number as SerdeNumber = inline;
);
struct SerdeValue;
impl Type for SerdeValue {
fn definition(types: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
("Null".into(), Variant::unit()),
(
"Bool".into(),
Variant::unnamed()
.field(Field::new(bool::definition(types)))
.build(),
),
(
"Number".into(),
Variant::unnamed()
.field(Field::new(Number::definition(types)))
.build(),
),
(
"String".into(),
Variant::unnamed()
.field(Field::new(str::definition(types)))
.build(),
),
(
"Array".into(),
Variant::unnamed()
.field(Field::new(Vec::<Value>::definition(types)))
.build(),
),
(
"Object".into(),
Variant::unnamed()
.field(Field::new(Map::<String, Value>::definition(types)))
.build(),
),
],
attributes: Default::default(),
})
}
}
struct SerdeNumber;
impl Type for SerdeNumber {
fn definition(_: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
(
"f64".into(),
Variant::unnamed()
.field(Field::new(DataType::Primitive(Primitive::f64)))
.build(),
),
(
"i64".into(),
Variant::unnamed()
.field(Field::new(DataType::Primitive(Primitive::i64)))
.build(),
),
(
"u64".into(),
Variant::unnamed()
.field(Field::new(DataType::Primitive(Primitive::u64)))
.build(),
),
],
attributes: Attributes::default(),
})
}
}
};
#[cfg(feature = "serde_yaml")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde_yaml")))]
const _: () = {
use serde_yaml::{Mapping, Number, Value, value::TaggedValue};
impl_ndt!(
serde_yaml::Mapping as PrimitiveMap<Value, Value> = passthrough;
serde_yaml::Value as SerdeYamlValue = inline;
serde_yaml::Number as SerdeYamlNumber = inline;
serde_yaml::value::TaggedValue as SerdeYamlTaggedValue = inline;
);
struct SerdeYamlValue;
impl Type for SerdeYamlValue {
fn definition(types: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
("Null".into(), Variant::unit()),
(
"Bool".into(),
Variant::unnamed()
.field(Field::new(bool::definition(types)))
.build(),
),
(
"Number".into(),
Variant::unnamed()
.field(Field::new(Number::definition(types)))
.build(),
),
(
"String".into(),
Variant::unnamed()
.field(Field::new(str::definition(types)))
.build(),
),
(
"Sequence".into(),
Variant::unnamed()
.field(Field::new(Vec::<Value>::definition(types)))
.build(),
),
(
"Mapping".into(),
Variant::unnamed()
.field(Field::new(Mapping::definition(types)))
.build(),
),
(
"Tagged".into(),
Variant::unnamed()
.field(Field::new(Box::<TaggedValue>::definition(types)))
.build(),
),
],
attributes: Attributes::default(),
})
}
}
struct SerdeYamlNumber;
impl Type for SerdeYamlNumber {
fn definition(_: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
(
"f64".into(),
Variant::unnamed()
.field(Field::new(DataType::Primitive(Primitive::f64)))
.build(),
),
(
"i64".into(),
Variant::unnamed()
.field(Field::new(DataType::Primitive(Primitive::i64)))
.build(),
),
(
"u64".into(),
Variant::unnamed()
.field(Field::new(DataType::Primitive(Primitive::u64)))
.build(),
),
],
attributes: Attributes::default(),
})
}
}
struct SerdeYamlTaggedValue;
impl Type for SerdeYamlTaggedValue {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field("tag", Field::new(str::definition(types)))
.field("value", Field::new(Value::definition(types)))
.build()
}
}
};
#[cfg(feature = "toml")]
#[cfg_attr(docsrs, doc(cfg(feature = "toml")))]
const _: () = {
use toml::{Value, value};
impl_ndt!(
toml::map::Map<K, V> as PrimitiveMap<K, V> = passthrough;
toml::value::Datetime as TomlDatetime = inline;
toml::Value as TomlValue = inline;
);
struct TomlDatetime;
impl Type for TomlDatetime {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field("v", Field::new(str::definition(types)))
.build()
}
}
struct TomlValue;
impl Type for TomlValue {
fn definition(types: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
(
"String".into(),
Variant::unnamed()
.field(Field::new(str::definition(types)))
.build(),
),
(
"Integer".into(),
Variant::unnamed()
.field(Field::new(i64::definition(types)))
.build(),
),
(
"Float".into(),
Variant::unnamed()
.field(Field::new(f64::definition(types)))
.build(),
),
(
"Boolean".into(),
Variant::unnamed()
.field(Field::new(bool::definition(types)))
.build(),
),
(
"Datetime".into(),
Variant::unnamed()
.field(Field::new(value::Datetime::definition(types)))
.build(),
),
(
"Array".into(),
Variant::unnamed()
.field(Field::new(Vec::<Value>::definition(types)))
.build(),
),
(
"Table".into(),
Variant::unnamed()
.field(Field::new(toml::map::Map::<String, Value>::definition(
types,
)))
.build(),
),
],
attributes: Attributes::default(),
})
}
}
};
#[cfg(feature = "ulid")]
#[cfg_attr(docsrs, doc(cfg(feature = "ulid")))]
impl_ndt!(ulid::Ulid as str = inline);
#[cfg(feature = "uuid")]
#[cfg_attr(docsrs, doc(cfg(feature = "uuid")))]
impl_ndt!(
uuid::Uuid as str = inline;
uuid::fmt::Braced as str = inline;
uuid::fmt::Hyphenated as str = inline;
uuid::fmt::Simple as str = inline;
uuid::fmt::Urn as str = inline;
);
#[cfg(feature = "chrono")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
#[allow(deprecated)]
const _: () = {
impl_ndt!(
chrono::NaiveDateTime as str = inline;
chrono::NaiveDate as str = inline;
chrono::NaiveTime as str = inline;
chrono::Duration as str = inline;
chrono::FixedOffset as str = inline;
chrono::Utc as str = inline;
chrono::Local as str = inline;
chrono::Weekday as str = inline;
chrono::Month as str = inline;
chrono::Date<T> where { T: Type + chrono::TimeZone } as str = inline;
chrono::DateTime<T> where { T: Type + chrono::TimeZone } as str = inline;
);
};
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
impl_ndt!(
time::PrimitiveDateTime as str = inline;
time::OffsetDateTime as str = inline;
time::Date as str = inline;
time::UtcDateTime as str = inline;
time::Time as str = inline;
time::Duration as str = inline;
time::UtcOffset as str = inline;
time::Weekday as str = inline;
time::Month as str = inline;
);
#[cfg(feature = "jiff")]
#[cfg_attr(docsrs, doc(cfg(feature = "jiff")))]
impl_ndt!(
jiff::Timestamp as str = inline;
jiff::Zoned as str = inline;
jiff::SignedDuration as str = inline;
jiff::civil::Date as str = inline;
jiff::civil::Time as str = inline;
jiff::civil::DateTime as str = inline;
jiff::civil::ISOWeekDate as str = inline;
jiff::tz::TimeZone as str = inline;
);
#[cfg(feature = "bigdecimal")]
#[cfg_attr(docsrs, doc(cfg(feature = "bigdecimal")))]
impl_ndt!(bigdecimal::BigDecimal as str = inline);
// This assumes the `serde-with-str` feature is enabled. Check #26 for more info.
#[cfg(feature = "rust_decimal")]
#[cfg_attr(docsrs, doc(cfg(feature = "rust_decimal")))]
impl_ndt!(rust_decimal::Decimal as str = inline);
#[cfg(feature = "ipnetwork")]
#[cfg_attr(docsrs, doc(cfg(feature = "ipnetwork")))]
impl_ndt!(
ipnetwork::IpNetwork as str = inline;
ipnetwork::Ipv4Network as str = inline;
ipnetwork::Ipv6Network as str = inline;
);
#[cfg(feature = "mac_address")]
#[cfg_attr(docsrs, doc(cfg(feature = "mac_address")))]
impl_ndt!(mac_address::MacAddress as str = inline);
#[cfg(feature = "bson")]
#[cfg_attr(docsrs, doc(cfg(feature = "bson")))]
const _: () = {
impl_ndt!(
bson::oid::ObjectId as BsonObjectId = inline;
bson::Decimal128 as BsonDecimal128 = inline;
bson::DateTime as BsonDateTime = inline;
bson::Uuid as str = inline;
bson::Timestamp as BsonTimestamp = inline;
bson::Binary as BsonBinary = inline;
bson::Regex as BsonRegex = inline;
bson::JavaScriptCodeWithScope as BsonJavaScriptCodeWithScope = inline;
bson::DbPointer as BsonDbPointer = inline;
bson::Document as PrimitiveMap<String, bson::Bson> = inline;
bson::Bson as Bson = inline;
bson::Utf8Lossy<T> as T = passthrough;
bson::RawBsonRef<'a,> as Bson = inline;
);
struct BsonObjectId;
impl Type for BsonObjectId {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field("$oid", Field::new(str::definition(types)))
.build()
}
}
struct BsonDecimal128;
impl Type for BsonDecimal128 {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field("$numberDecimal", Field::new(str::definition(types)))
.build()
}
}
struct BsonDateTime;
impl Type for BsonDateTime {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field("$date", Field::new(str::definition(types)))
.build()
}
}
struct BsonTimestamp;
impl Type for BsonTimestamp {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field(
"$timestamp",
Field::new(
Struct::named()
.field("t", Field::new(u32::definition(types)))
.field("i", Field::new(u32::definition(types)))
.build(),
),
)
.build()
}
}
struct BsonBinary;
impl Type for BsonBinary {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field(
"$binary",
Field::new(
Struct::named()
.field("base64", Field::new(str::definition(types)))
.field("subType", Field::new(str::definition(types)))
.build(),
),
)
.build()
}
}
struct BsonRegex;
impl Type for BsonRegex {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field("$regex", Field::new(str::definition(types)))
.field("$options", Field::new(str::definition(types)))
.build()
}
}
struct BsonJavaScriptCode;
impl Type for BsonJavaScriptCode {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field("$code", Field::new(str::definition(types)))
.build()
}
}
struct BsonJavaScriptCodeWithScope;
impl Type for BsonJavaScriptCodeWithScope {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field("$code", Field::new(str::definition(types)))
.field("$scope", Field::new(bson::Document::definition(types)))
.build()
}
}
struct BsonDbPointer;
impl Type for BsonDbPointer {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field(
"$dbPointer",
Field::new(
Struct::named()
.field("$ref", Field::new(str::definition(types)))
.field("$id", Field::new(bson::oid::ObjectId::definition(types)))
.build(),
),
)
.build()
}
}
struct Bson;
impl Type for Bson {
fn definition(types: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
(
"Double".into(),
Variant::unnamed()
.field(Field::new(f64::definition(types)))
.build(),
),
(
"String".into(),
Variant::unnamed()
.field(Field::new(str::definition(types)))
.build(),
),
(
"Array".into(),
Variant::unnamed()
.field(Field::new(Vec::<bson::Bson>::definition(types)))
.build(),
),
(
"Document".into(),
Variant::unnamed()
.field(Field::new(bson::Document::definition(types)))
.build(),
),
(
"Boolean".into(),
Variant::unnamed()
.field(Field::new(bool::definition(types)))
.build(),
),
("Null".into(), Variant::unit()),
(
"RegularExpression".into(),
Variant::unnamed()
.field(Field::new(bson::Regex::definition(types)))
.build(),
),
(
"JavaScriptCode".into(),
Variant::unnamed()
.field(Field::new(BsonJavaScriptCode::definition(types)))
.build(),
),
(
"JavaScriptCodeWithScope".into(),
Variant::unnamed()
.field(Field::new(bson::JavaScriptCodeWithScope::definition(types)))
.build(),
),
(
"Int32".into(),
Variant::unnamed()
.field(Field::new(i32::definition(types)))
.build(),
),
(
"Int64".into(),
Variant::unnamed()
.field(Field::new(i64::definition(types)))
.build(),
),
(
"Timestamp".into(),
Variant::unnamed()
.field(Field::new(bson::Timestamp::definition(types)))
.build(),
),
(
"Binary".into(),
Variant::unnamed()
.field(Field::new(bson::Binary::definition(types)))
.build(),
),
(
"ObjectId".into(),
Variant::unnamed()
.field(Field::new(bson::oid::ObjectId::definition(types)))
.build(),
),
(
"DateTime".into(),
Variant::unnamed()
.field(Field::new(bson::DateTime::definition(types)))
.build(),
),
(
"Symbol".into(),
Variant::unnamed()
.field(Field::new(
Struct::named()
.field("$symbol", Field::new(str::definition(types)))
.build(),
))
.build(),
),
(
"Decimal128".into(),
Variant::unnamed()
.field(Field::new(bson::Decimal128::definition(types)))
.build(),
),
(
"Undefined".into(),
Variant::unnamed()
.field(Field::new(
Struct::named()
.field("$undefined", Field::new(bool::definition(types)))
.build(),
))
.build(),
),
(
"MaxKey".into(),
Variant::unnamed()
.field(Field::new(
Struct::named()
.field("$maxKey", Field::new(u8::definition(types)))
.build(),
))
.build(),
),
(
"MinKey".into(),
Variant::unnamed()
.field(Field::new(
Struct::named()
.field("$minKey", Field::new(u8::definition(types)))
.build(),
))
.build(),
),
(
"DbPointer".into(),
Variant::unnamed()
.field(Field::new(bson::DbPointer::definition(types)))
.build(),
),
],
attributes: Attributes::default(),
})
}
}
};
// Technically this can be u64 for formats not marked as human readable in Serde.
// but we have no way of inspecting that as it's runtime. This is the most common output.
#[cfg(feature = "bytesize")]
#[cfg_attr(docsrs, doc(cfg(feature = "bytesize")))]
impl_ndt!(bytesize::ByteSize as String = inline);
#[cfg(feature = "uhlc")]
#[cfg_attr(docsrs, doc(cfg(feature = "uhlc")))]
const _: () = {
impl_ndt!(
uhlc::NTP64 as u64 = inline;
uhlc::ID as std::num::NonZeroU128 = inline;
uhlc::Timestamp as UhlcTimestamp = inline;
);
struct UhlcTimestamp;
impl Type for UhlcTimestamp {
fn definition(types: &mut Types) -> DataType {
DataType::Struct(Struct {
fields: Fields::Named(NamedFields {
fields: vec![
(
"time".into(),
Field {
optional: false,
deprecated: None,
docs: Default::default(),
ty: Some(uhlc::NTP64::definition(types)),
attributes: Attributes::default(),
},
),
(
"id".into(),
Field {
optional: false,
deprecated: None,
docs: Default::default(),
ty: Some(uhlc::ID::definition(types)),
attributes: Attributes::default(),
},
),
],
}),
attributes: Attributes::default(),
})
}
}
};
#[cfg(feature = "glam")]
#[cfg_attr(docsrs, doc(cfg(feature = "glam")))]
impl_ndt!(
// Affines
glam::Affine2 as [f32; 6] = inline;
glam::Affine3A as [f32; 12] = inline;
glam::DAffine2 as [f64; 6] = inline;
glam::DAffine3 as [f64; 12] = inline;
// Matrices
glam::Mat2 as [f32; 4] = inline;
glam::Mat3 as [f32; 9] = inline;
glam::Mat3A as [f32; 9] = inline;
glam::Mat4 as [f32; 16] = inline;
glam::DMat2 as [f64; 4] = inline;
glam::DMat3 as [f64; 9] = inline;
glam::DMat4 as [f64; 16] = inline;
// Quaternions
glam::Quat as [f32; 4] = inline;
glam::DQuat as [f64; 4] = inline;
// Vectors
glam::Vec2 as [f32; 2] = inline;
glam::Vec3 as [f32; 3] = inline;
glam::Vec3A as [f32; 3] = inline;
glam::Vec4 as [f32; 4] = inline;
glam::DVec2 as [f64; 2] = inline;
glam::DVec3 as [f64; 3] = inline;
glam::DVec4 as [f64; 4] = inline;
// Implementation for https://docs.rs/glam/latest/glam/bool/index.html
glam::BVec2 as [bool; 2] = inline;
glam::BVec3 as [bool; 3] = inline;
glam::BVec3A as [bool; 3] = inline;
glam::BVec4 as [bool; 4] = inline;
glam::BVec4A as [bool; 4] = inline;
// Implementations for https://docs.rs/glam/latest/glam/i8/index.html
glam::I8Vec2 as [i8; 2] = inline;
glam::I8Vec3 as [i8; 3] = inline;
glam::I8Vec4 as [i8; 4] = inline;
// Implementations for https://docs.rs/glam/latest/glam/u8/index.html
glam::U8Vec2 as [u8; 2] = inline;
glam::U8Vec3 as [u8; 3] = inline;
glam::U8Vec4 as [u8; 4] = inline;
// Implementations for https://docs.rs/glam/latest/glam/i16/index.html
glam::I16Vec2 as [i16; 2] = inline;
glam::I16Vec3 as [i16; 3] = inline;
glam::I16Vec4 as [i16; 4] = inline;
// Implementations for https://docs.rs/glam/latest/glam/u16/index.html
glam::U16Vec2 as [u16; 2] = inline;
glam::U16Vec3 as [u16; 3] = inline;
glam::U16Vec4 as [u16; 4] = inline;
// Implementations for https://docs.rs/glam/latest/glam/u32/index.html
glam::UVec2 as [u32; 2] = inline;
glam::UVec3 as [u32; 3] = inline;
glam::UVec4 as [u32; 4] = inline;
// Implementations for https://docs.rs/glam/latest/glam/i32/index.html
glam::IVec2 as [i32; 2] = inline;
glam::IVec3 as [i32; 3] = inline;
glam::IVec4 as [i32; 4] = inline;
// Implementation for https://docs.rs/glam/latest/glam/i64/index.html
glam::I64Vec2 as [i64; 2] = inline;
glam::I64Vec3 as [i64; 3] = inline;
glam::I64Vec4 as [i64; 4] = inline;
// Implementation for https://docs.rs/glam/latest/glam/u64/index.html
glam::U64Vec2 as [u64; 2] = inline;
glam::U64Vec3 as [u64; 3] = inline;
glam::U64Vec4 as [u64; 4] = inline;
// implementation for https://docs.rs/glam/latest/glam/usize/index.html
glam::USizeVec2 as [usize; 2] = inline;
glam::USizeVec3 as [usize; 3] = inline;
glam::USizeVec4 as [usize; 4] = inline;
// implementation for https://docs.rs/glam/latest/glam/isize/index.html
glam::ISizeVec2 as [isize; 2] = inline;
glam::ISizeVec3 as [isize; 3] = inline;
glam::ISizeVec4 as [isize; 4] = inline;
);
#[cfg(feature = "url")]
#[cfg_attr(docsrs, doc(cfg(feature = "url")))]
const _: () = {
impl_ndt!(
url::Url as str = inline;
url::Host as UrlHost = inline;
);
struct UrlHost;
impl Type for UrlHost {
fn definition(types: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
(
"Domain".into(),
Variant::unnamed()
.field(Field::new(String::definition(types)))
.build(),
),
(
"Ipv4".into(),
Variant::unnamed()
.field(Field::new(std::net::Ipv4Addr::definition(types)))
.build(),
),
(
"Ipv6".into(),
Variant::unnamed()
.field(Field::new(std::net::Ipv6Addr::definition(types)))
.build(),
),
],
attributes: Attributes::default(),
})
}
}
};
#[cfg(feature = "either")]
#[cfg_attr(docsrs, doc(cfg(feature = "either")))]
const _: () = {
impl_ndt!(either::Either<L, R> as Either<L, R> = inline);
struct Either<L, R>(std::marker::PhantomData<(L, R)>);
impl<L: Type, R: Type> Type for Either<L, R> {
fn definition(types: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
(
"Left".into(),
Variant::unnamed()
.field(Field::new(L::definition(types)))
.build(),
),
(
"Right".into(),
Variant::unnamed()
.field(Field::new(R::definition(types)))
.build(),
),
],
attributes: Attributes::default(),
})
}
}
};
#[cfg(feature = "error-stack")]
#[cfg_attr(docsrs, doc(cfg(feature = "error-stack")))]
const _: () = {
impl_ndt!(
"error_stack" ErrorStackContext as ErrorStackContextInner = named;
error_stack::Report<> <C> where { C: std::error::Error + Send + Sync + 'static } as ReportInner = named;
);
impl<C: std::error::Error + Send + Sync + 'static> Type for error_stack::Report<[C]> {
fn definition(types: &mut Types) -> DataType {
error_stack::Report::<C>::definition(types)
}
}
struct ErrorStackContext;
struct ErrorStackContextInner;
impl Type for ErrorStackContextInner {
fn definition(types: &mut Types) -> DataType {
let attachments = DataType::List(List::new(String::definition(types)));
let sources = DataType::List(List::new(ErrorStackContext::definition(types)));
Struct::named()
.field("context", Field::new(String::definition(types)))
.field("attachments", Field::new(attachments))
.field("sources", Field::new(sources))
.build()
}
}
struct ReportInner;
impl Type for ReportInner {
fn definition(types: &mut Types) -> DataType {
DataType::List(List::new(ErrorStackContext::definition(types)))
}
}
};
#[cfg(feature = "bevy_ecs")]
#[cfg_attr(docsrs, doc(cfg(feature = "bevy_ecs")))]
impl_ndt!(
bevy_ecs::entity::Entity as u64 = named;
bevy_ecs::name::Name as str = named;
bevy_ecs::hierarchy::ChildOf as bevy_ecs::entity::Entity = named;
bevy_ecs::entity::EntityHashMap<V> where { V: Type } as PrimitiveMap<bevy_ecs::entity::Entity, V> = named;
bevy_ecs::entity::EntityHashSet as PrimitiveSet<bevy_ecs::entity::Entity> = named;
bevy_ecs::entity::EntityIndexMap<V> where { V: Type } as PrimitiveMap<bevy_ecs::entity::Entity, V> = named;
bevy_ecs::entity::EntityIndexSet as PrimitiveSet<bevy_ecs::entity::Entity> = named;
);
#[cfg(feature = "bevy_input")]
#[cfg_attr(docsrs, doc(cfg(feature = "bevy_input")))]
const _: () = {
impl_ndt!(
bevy_input::ButtonState as BevyButtonState = named;
bevy_input::keyboard::KeyboardInput as BevyKeyboardInput = named;
bevy_input::keyboard::KeyboardFocusLost as BevyKeyboardFocusLost = named;
bevy_input::keyboard::NativeKeyCode as str = named;
bevy_input::keyboard::KeyCode as str = named;
bevy_input::keyboard::NativeKey as str = named;
bevy_input::keyboard::Key as str = named;
bevy_input::mouse::MouseButtonInput as BevyMouseButtonInput = named;
bevy_input::mouse::MouseButton as BevyMouseButton = named;
bevy_input::mouse::MouseMotion as BevyMouseMotion = named;
bevy_input::mouse::MouseScrollUnit as BevyMouseScrollUnit = named;
bevy_input::mouse::MouseWheel as BevyMouseWheel = named;
bevy_input::mouse::AccumulatedMouseMotion as BevyAccumulatedMouseMotion = named;
bevy_input::mouse::AccumulatedMouseScroll as BevyAccumulatedMouseScroll = named;
bevy_input::touch::TouchInput as BevyTouchInput = named;
bevy_input::touch::ForceTouch as BevyForceTouch = named;
bevy_input::touch::TouchPhase as BevyTouchPhase = named;
bevy_input::gestures::PinchGesture as f32 = named;
bevy_input::gestures::RotationGesture as f32 = named;
bevy_input::gestures::DoubleTapGesture as BevyDoubleTapGesture = named;
bevy_input::gestures::PanGesture as [f32; 2] = named;
bevy_input::gamepad::GamepadEvent as BevyGamepadEvent = named;
bevy_input::gamepad::RawGamepadEvent as BevyRawGamepadEvent = named;
bevy_input::gamepad::RawGamepadButtonChangedEvent as BevyRawGamepadButtonChangedEvent = named;
bevy_input::gamepad::RawGamepadAxisChangedEvent as BevyRawGamepadAxisChangedEvent = named;
bevy_input::gamepad::GamepadConnectionEvent as BevyGamepadConnectionEvent = named;
bevy_input::gamepad::GamepadButtonStateChangedEvent as BevyGamepadButtonStateChangedEvent = named;
bevy_input::gamepad::GamepadButtonChangedEvent as BevyGamepadButtonChangedEvent = named;
bevy_input::gamepad::GamepadAxisChangedEvent as BevyGamepadAxisChangedEvent = named;
bevy_input::gamepad::GamepadButton as BevyGamepadButton = named;
bevy_input::gamepad::GamepadAxis as BevyGamepadAxis = named;
bevy_input::gamepad::GamepadConnection as BevyGamepadConnection = named;
);
struct BevyButtonState;
impl Type for BevyButtonState {
fn definition(_: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
("Pressed".into(), Variant::unit()),
("Released".into(), Variant::unit()),
],
attributes: Attributes::default(),
})
}
}
struct BevyKeyboardFocusLost;
impl Type for BevyKeyboardFocusLost {
fn definition(_: &mut Types) -> DataType {
DataType::Struct(Struct {
fields: Fields::Unit,
attributes: Attributes::default(),
})
}
}
struct BevyKeyboardInput;
impl Type for BevyKeyboardInput {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field(
"key_code",
Field::new(bevy_input::keyboard::KeyCode::definition(types)),
)
.field(
"logical_key",
Field::new(bevy_input::keyboard::Key::definition(types)),
)
.field(
"state",
Field::new(bevy_input::ButtonState::definition(types)),
)
.field(
"text",
Field::new(Option::<smol_str::SmolStr>::definition(types)),
)
.field("repeat", Field::new(bool::definition(types)))
.field(
"window",
Field::new(bevy_ecs::entity::Entity::definition(types)),
)
.build()
}
}
struct BevyMouseButtonInput;
impl Type for BevyMouseButtonInput {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field(
"button",
Field::new(bevy_input::mouse::MouseButton::definition(types)),
)
.field(
"state",
Field::new(bevy_input::ButtonState::definition(types)),
)
.field(
"window",
Field::new(bevy_ecs::entity::Entity::definition(types)),
)
.build()
}
}
struct BevyMouseButton;
impl Type for BevyMouseButton {
fn definition(types: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
("Left".into(), Variant::unit()),
("Right".into(), Variant::unit()),
("Middle".into(), Variant::unit()),
("Back".into(), Variant::unit()),
("Forward".into(), Variant::unit()),
(
"Other".into(),
Variant::unnamed()
.field(Field::new(u16::definition(types)))
.build(),
),
],
attributes: Attributes::default(),
})
}
}
struct BevyMouseMotion;
impl Type for BevyMouseMotion {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field("delta", Field::new(<[f32; 2]>::definition(types)))
.build()
}
}
struct BevyMouseScrollUnit;
impl Type for BevyMouseScrollUnit {
fn definition(_: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
("Line".into(), Variant::unit()),
("Pixel".into(), Variant::unit()),
],
attributes: Attributes::default(),
})
}
}
struct BevyMouseWheel;
impl Type for BevyMouseWheel {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field(
"unit",
Field::new(bevy_input::mouse::MouseScrollUnit::definition(types)),
)
.field("x", Field::new(f32::definition(types)))
.field("y", Field::new(f32::definition(types)))
.field(
"window",
Field::new(bevy_ecs::entity::Entity::definition(types)),
)
.field(
"phase",
Field::new(bevy_input::touch::TouchPhase::definition(types)),
)
.build()
}
}
struct BevyAccumulatedMouseMotion;
impl Type for BevyAccumulatedMouseMotion {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field("delta", Field::new(<[f32; 2]>::definition(types)))
.build()
}
}
struct BevyAccumulatedMouseScroll;
impl Type for BevyAccumulatedMouseScroll {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field(
"unit",
Field::new(bevy_input::mouse::MouseScrollUnit::definition(types)),
)
.field("delta", Field::new(<[f32; 2]>::definition(types)))
.build()
}
}
struct BevyTouchInput;
impl Type for BevyTouchInput {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field(
"phase",
Field::new(bevy_input::touch::TouchPhase::definition(types)),
)
.field("position", Field::new(<[f32; 2]>::definition(types)))
.field(
"window",
Field::new(bevy_ecs::entity::Entity::definition(types)),
)
.field(
"force",
Field::new(Option::<bevy_input::touch::ForceTouch>::definition(types)),
)
.field("id", Field::new(u64::definition(types)))
.build()
}
}
struct BevyForceTouch;
impl Type for BevyForceTouch {
fn definition(types: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
(
"Calibrated".into(),
Variant::named()
.field("force", Field::new(f64::definition(types)))
.field("max_possible_force", Field::new(f64::definition(types)))
.field(
"altitude_angle",
Field::new(Option::<f64>::definition(types)),
)
.build(),
),
(
"Normalized".into(),
Variant::unnamed()
.field(Field::new(f64::definition(types)))
.build(),
),
],
attributes: Attributes::default(),
})
}
}
struct BevyTouchPhase;
impl Type for BevyTouchPhase {
fn definition(_: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
("Started".into(), Variant::unit()),
("Moved".into(), Variant::unit()),
("Ended".into(), Variant::unit()),
("Canceled".into(), Variant::unit()),
],
attributes: Attributes::default(),
})
}
}
struct BevyDoubleTapGesture;
impl Type for BevyDoubleTapGesture {
fn definition(_: &mut Types) -> DataType {
DataType::Struct(Struct {
fields: Fields::Unit,
attributes: Attributes::default(),
})
}
}
struct BevyGamepadEvent;
impl Type for BevyGamepadEvent {
fn definition(types: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
(
"Connection".into(),
Variant::unnamed()
.field(Field::new(
bevy_input::gamepad::GamepadConnectionEvent::definition(types),
))
.build(),
),
(
"Button".into(),
Variant::unnamed()
.field(Field::new(
bevy_input::gamepad::GamepadButtonChangedEvent::definition(types),
))
.build(),
),
(
"Axis".into(),
Variant::unnamed()
.field(Field::new(
bevy_input::gamepad::GamepadAxisChangedEvent::definition(types),
))
.build(),
),
],
attributes: Attributes::default(),
})
}
}
struct BevyRawGamepadEvent;
impl Type for BevyRawGamepadEvent {
fn definition(types: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
(
"Connection".into(),
Variant::unnamed()
.field(Field::new(
bevy_input::gamepad::GamepadConnectionEvent::definition(types),
))
.build(),
),
(
"Button".into(),
Variant::unnamed()
.field(Field::new(
bevy_input::gamepad::RawGamepadButtonChangedEvent::definition(
types,
),
))
.build(),
),
(
"Axis".into(),
Variant::unnamed()
.field(Field::new(
bevy_input::gamepad::RawGamepadAxisChangedEvent::definition(types),
))
.build(),
),
],
attributes: Attributes::default(),
})
}
}
struct BevyRawGamepadButtonChangedEvent;
impl Type for BevyRawGamepadButtonChangedEvent {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field(
"gamepad",
Field::new(bevy_ecs::entity::Entity::definition(types)),
)
.field(
"button",
Field::new(bevy_input::gamepad::GamepadButton::definition(types)),
)
.field("value", Field::new(f32::definition(types)))
.build()
}
}
struct BevyRawGamepadAxisChangedEvent;
impl Type for BevyRawGamepadAxisChangedEvent {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field(
"gamepad",
Field::new(bevy_ecs::entity::Entity::definition(types)),
)
.field(
"axis",
Field::new(bevy_input::gamepad::GamepadAxis::definition(types)),
)
.field("value", Field::new(f32::definition(types)))
.build()
}
}
struct BevyGamepadConnectionEvent;
impl Type for BevyGamepadConnectionEvent {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field(
"gamepad",
Field::new(bevy_ecs::entity::Entity::definition(types)),
)
.field(
"connection",
Field::new(bevy_input::gamepad::GamepadConnection::definition(types)),
)
.build()
}
}
struct BevyGamepadButtonStateChangedEvent;
impl Type for BevyGamepadButtonStateChangedEvent {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field(
"entity",
Field::new(bevy_ecs::entity::Entity::definition(types)),
)
.field(
"button",
Field::new(bevy_input::gamepad::GamepadButton::definition(types)),
)
.field(
"state",
Field::new(bevy_input::ButtonState::definition(types)),
)
.build()
}
}
struct BevyGamepadButtonChangedEvent;
impl Type for BevyGamepadButtonChangedEvent {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field(
"entity",
Field::new(bevy_ecs::entity::Entity::definition(types)),
)
.field(
"button",
Field::new(bevy_input::gamepad::GamepadButton::definition(types)),
)
.field(
"state",
Field::new(bevy_input::ButtonState::definition(types)),
)
.field("value", Field::new(f32::definition(types)))
.build()
}
}
struct BevyGamepadAxisChangedEvent;
impl Type for BevyGamepadAxisChangedEvent {
fn definition(types: &mut Types) -> DataType {
Struct::named()
.field(
"entity",
Field::new(bevy_ecs::entity::Entity::definition(types)),
)
.field(
"axis",
Field::new(bevy_input::gamepad::GamepadAxis::definition(types)),
)
.field("value", Field::new(f32::definition(types)))
.build()
}
}
struct BevyGamepadButton;
impl Type for BevyGamepadButton {
fn definition(types: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
("South".into(), Variant::unit()),
("East".into(), Variant::unit()),
("North".into(), Variant::unit()),
("West".into(), Variant::unit()),
("C".into(), Variant::unit()),
("Z".into(), Variant::unit()),
("LeftTrigger".into(), Variant::unit()),
("LeftTrigger2".into(), Variant::unit()),
("RightTrigger".into(), Variant::unit()),
("RightTrigger2".into(), Variant::unit()),
("Select".into(), Variant::unit()),
("Start".into(), Variant::unit()),
("Mode".into(), Variant::unit()),
("LeftThumb".into(), Variant::unit()),
("RightThumb".into(), Variant::unit()),
("DPadUp".into(), Variant::unit()),
("DPadDown".into(), Variant::unit()),
("DPadLeft".into(), Variant::unit()),
("DPadRight".into(), Variant::unit()),
(
"Other".into(),
Variant::unnamed()
.field(Field::new(u8::definition(types)))
.build(),
),
],
attributes: Attributes::default(),
})
}
}
struct BevyGamepadAxis;
impl Type for BevyGamepadAxis {
fn definition(types: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
("LeftStickX".into(), Variant::unit()),
("LeftStickY".into(), Variant::unit()),
("LeftZ".into(), Variant::unit()),
("RightStickX".into(), Variant::unit()),
("RightStickY".into(), Variant::unit()),
("RightZ".into(), Variant::unit()),
(
"Other".into(),
Variant::unnamed()
.field(Field::new(u8::definition(types)))
.build(),
),
],
attributes: Attributes::default(),
})
}
}
struct BevyGamepadConnection;
impl Type for BevyGamepadConnection {
fn definition(types: &mut Types) -> DataType {
DataType::Enum(Enum {
variants: vec![
(
"Connected".into(),
Variant::named()
.field("name", Field::new(String::definition(types)))
.field("vendor_id", Field::new(Option::<u16>::definition(types)))
.field("product_id", Field::new(Option::<u16>::definition(types)))
.build(),
),
("Disconnected".into(), Variant::unit()),
],
attributes: Attributes::default(),
})
}
}
};
#[cfg(feature = "camino")]
#[cfg_attr(docsrs, doc(cfg(feature = "camino")))]
impl_ndt!(
camino::Utf8Path as str = inline;
camino::Utf8PathBuf as str = inline;
);
#[cfg(feature = "geojson")]
#[cfg_attr(docsrs, doc(cfg(feature = "geojson")))]
const _: () = {
impl_ndt!(
geojson::Position as [f64] = inline;
geojson::GeoJson as GeoJson = inline;
geojson::GeometryValue as GeoJsonGeometryValue = inline;
geojson::Geometry as GeoJsonGeometry = inline;
geojson::Feature as GeoJsonFeature = inline;
geojson::FeatureCollection as GeoJsonFeatureCollection = inline;
geojson::feature::Id as GeoJsonFeatureId = inline;
);
struct GeoJson;
impl Type for GeoJson {
fn definition(types: &mut Types) -> DataType {
let mut attributes = Attributes::default();
attributes.insert("serde:container:untagged", true);
DataType::Enum(Enum {
variants: vec![
(
"Geometry".into(),
Variant::unnamed()
.field(Field::new(geojson::Geometry::definition(types)))
.build(),
),
(
"Feature".into(),
Variant::unnamed()
.field(Field::new(geojson::Feature::definition(types)))
.build(),
),
(
"FeatureCollection".into(),
Variant::unnamed()
.field(Field::new(geojson::FeatureCollection::definition(types)))
.build(),
),
],
attributes,
})
}
}
struct GeoJsonGeometryValue;
impl Type for GeoJsonGeometryValue {
fn definition(types: &mut Types) -> DataType {
let mut attributes = Attributes::default();
attributes.insert("serde:container:tag", std::string::String::from("type"));
DataType::Enum(Enum {
variants: vec![
(
"Point".into(),
Variant::named()
.field(
"coordinates",
Field::new(geojson::PointType::definition(types)),
)
.build(),
),
(
"MultiPoint".into(),
Variant::named()
.field(
"coordinates",
Field::new(Vec::<geojson::PointType>::definition(types)),
)
.build(),
),
(
"LineString".into(),
Variant::named()
.field(
"coordinates",
Field::new(geojson::LineStringType::definition(types)),
)
.build(),
),
(
"MultiLineString".into(),
Variant::named()
.field(
"coordinates",
Field::new(Vec::<geojson::LineStringType>::definition(types)),
)
.build(),
),
(
"Polygon".into(),
Variant::named()
.field(
"coordinates",
Field::new(geojson::PolygonType::definition(types)),
)
.build(),
),
(
"MultiPolygon".into(),
Variant::named()
.field(
"coordinates",
Field::new(Vec::<geojson::PolygonType>::definition(types)),
)
.build(),
),
(
"GeometryCollection".into(),
Variant::named()
.field(
"geometries",
Field::new(Vec::<geojson::Geometry>::definition(types)),
)
.build(),
),
],
attributes,
})
}
}
struct GeoJsonGeometry;
impl Type for GeoJsonGeometry {
fn definition(types: &mut Types) -> DataType {
let mut value = Field::new(geojson::GeometryValue::definition(types));
value.attributes.insert("serde:field:flatten", true);
let mut foreign_members = Field::new(Option::<geojson::JsonObject>::definition(types));
foreign_members
.attributes
.insert("serde:field:flatten", true);
Struct::named()
.field(
"bbox",
Field::new(Option::<geojson::Bbox>::definition(types)),
)
.field("value", value)
.field("foreign_members", foreign_members)
.build()
}
}
struct GeoJsonFeature;
impl Type for GeoJsonFeature {
fn definition(types: &mut Types) -> DataType {
let mut attributes = Attributes::default();
attributes.insert("serde:container:tag", std::string::String::from("type"));
let mut foreign_members = Field::new(Option::<geojson::JsonObject>::definition(types));
foreign_members
.attributes
.insert("serde:field:flatten", true);
DataType::Struct(Struct {
fields: Fields::Named(NamedFields {
fields: vec![
(
"bbox".into(),
Field::new(Option::<geojson::Bbox>::definition(types)),
),
(
"geometry".into(),
Field::new(Option::<geojson::Geometry>::definition(types)),
),
(
"id".into(),
Field::new(Option::<geojson::feature::Id>::definition(types)),
),
(
"properties".into(),
Field::new(Option::<geojson::JsonObject>::definition(types)),
),
("foreign_members".into(), foreign_members),
],
}),
attributes,
})
}
}
struct GeoJsonFeatureCollection;
impl Type for GeoJsonFeatureCollection {
fn definition(types: &mut Types) -> DataType {
let mut attributes = Attributes::default();
attributes.insert("serde:container:tag", std::string::String::from("type"));
let mut foreign_members = Field::new(Option::<geojson::JsonObject>::definition(types));
foreign_members
.attributes
.insert("serde:field:flatten", true);
DataType::Struct(Struct {
fields: Fields::Named(NamedFields {
fields: vec![
(
"bbox".into(),
Field::new(Option::<geojson::Bbox>::definition(types)),
),
(
"features".into(),
Field::new(Vec::<geojson::Feature>::definition(types)),
),
("foreign_members".into(), foreign_members),
],
}),
attributes,
})
}
}
struct GeoJsonFeatureId;
impl Type for GeoJsonFeatureId {
fn definition(types: &mut Types) -> DataType {
let mut attributes = Attributes::default();
attributes.insert("serde:container:untagged", true);
DataType::Enum(Enum {
variants: vec![
(
"String".into(),
Variant::unnamed()
.field(Field::new(str::definition(types)))
.build(),
),
(
"Number".into(),
Variant::unnamed()
.field(Field::new(serde_json::Number::definition(types)))
.build(),
),
],
attributes,
})
}
}
};
================================================
FILE: specta/src/type/macros.rs
================================================
macro_rules! _impl_primitives {
($($i:ident)+) => {$(
impl Type for $i {
fn definition(_: &mut Types) -> DataType {
DataType::Primitive(datatype::Primitive::$i)
}
}
)+};
}
macro_rules! _impl_tuple {
( impl $($i:ident),* ) => {
#[allow(non_snake_case)]
impl<$($i: Type),*> Type for ($($i,)*) {
fn definition(_types: &mut Types) -> DataType {
DataType::Tuple(datatype::Tuple {
elements: vec![$(<$i as Type>::definition(_types)),*],
})
}
}
};
( $i2:ident $(, $i:ident)* ) => {
impl_tuple!(impl $($i),* );
impl_tuple!($($i),*);
};
() => {};
}
macro_rules! _impl_ndt {
() => {};
// Multiple types
(
$module_path:literal $ty:ident
$(< $( $lifetime:lifetime, )* $( $generic:ident ),* $(,)? >)?
$( where { $($bounds:tt)* } )?
as $as_ty:ty = $kind:ident;
$($rest:tt)*
) => {
impl_ndt!(@single
$module_path $ty
$(< $( $lifetime, )* $( $generic ),* >)?
$( where { $($bounds)* } )?
as $as_ty = $kind
);
impl_ndt!($($rest)*);
};
(
$head:ident :: $( $tail:ident )::+ < $( $specta_generic:ident ),* $(,)? >
< $( $impl_generic:ident ),+ $(,)? >
$( where { $($bounds:tt)* } )?
as $as_ty:ty = $kind:ident;
$($rest:tt)*
) => {
impl_ndt!(@single
$head :: $( $tail )::+ < $( $specta_generic ),* >
< $( $impl_generic ),* >
$( where { $($bounds)* } )?
as $as_ty = $kind
);
impl_ndt!($($rest)*);
};
(
$head:ident :: $( $tail:ident )::+ < $( $specta_generic:ident ),* $(,)? >
< $first_impl_generic:ident, $second_impl_generic:ident, $third_impl_generic:ident, $( const $const_generic:ident : $const_ty:ty ),+ $(,)? >
$( where { $($bounds:tt)* } )?
as $as_ty:ty = $kind:ident;
$($rest:tt)*
) => {
impl_ndt!(@single
$head :: $( $tail )::+ < $( $specta_generic ),* >
< $first_impl_generic, $second_impl_generic, $third_impl_generic, $( const $const_generic : $const_ty ),* >
$( where { $($bounds)* } )?
as $as_ty = $kind
);
impl_ndt!($($rest)*);
};
(
$head:ident :: $( $tail:ident )::+ < $( $specta_generic:ident ),* $(,)? >
< $first_impl_generic:ident, $second_impl_generic:ident, $( const $const_generic:ident : $const_ty:ty ),+ $(,)? >
$( where { $($bounds:tt)* } )?
as $as_ty:ty = $kind:ident;
$($rest:tt)*
) => {
impl_ndt!(@single
$head :: $( $tail )::+ < $( $specta_generic ),* >
< $first_impl_generic, $second_impl_generic, $( const $const_generic : $const_ty ),* >
$( where { $($bounds)* } )?
as $as_ty = $kind
);
impl_ndt!($($rest)*);
};
(
$head:ident :: $( $tail:ident )::+ < $( $specta_generic:ident ),* $(,)? >
< $first_impl_generic:ident, $( const $const_generic:ident : $const_ty:ty ),+, $( $rest_impl_generic:ident ),+ $(,)? >
$( where { $($bounds:tt)* } )?
as $as_ty:ty = $kind:ident;
$($rest:tt)*
) => {
impl_ndt!(@single
$head :: $( $tail )::+ < $( $specta_generic ),* >
< $first_impl_generic, $( const $const_generic : $const_ty, )* $( $rest_impl_generic ),* >
$( where { $($bounds)* } )?
as $as_ty = $kind
);
impl_ndt!($($rest)*);
};
(
$head:ident :: $( $tail:ident )::+ < $( $specta_generic:ident ),* $(,)? >
< $impl_generic:ident, $( const $const_generic:ident : $const_ty:ty ),+ $(,)? >
$( where { $($bounds:tt)* } )?
as $as_ty:ty = $kind:ident;
$($rest:tt)*
) => {
impl_ndt!(@single
$head :: $( $tail )::+ < $( $specta_generic ),* >
< $impl_generic, $( const $const_generic : $const_ty ),* >
$( where { $($bounds)* } )?
as $as_ty = $kind
);
impl_ndt!($($rest)*);
};
(
$head:ident :: $( $tail:ident )::+ < $( const $const_generic:ident : $const_ty:ty ),+ $(,)? >
$( where { $($bounds:tt)* } )?
as $as_ty:ty = $kind:ident;
$($rest:tt)*
) => {
impl_ndt!(@single
$head :: $( $tail )::+ < $( const $const_generic : $const_ty ),* >
$( where { $($bounds)* } )?
as $as_ty = $kind
);
impl_ndt!($($rest)*);
};
(
$head:ident :: $( $tail:ident )::+ < $( const $const_generic:ident : $const_ty:ty ),+, $( $rest_impl_generic:ident ),+ $(,)? >
$( where { $($bounds:tt)* } )?
as $as_ty:ty = $kind:ident;
$($rest:tt)*
) => {
impl_ndt!(@single
$head :: $( $tail )::+ < $( const $const_generic : $const_ty, )* $( $rest_impl_generic ),* >
$( where { $($bounds)* } )?
as $as_ty = $kind
);
impl_ndt!($($rest)*);
};
(
$head:ident :: $( $tail:ident )::+ < $impl_generic:ident, $( const $const_generic:ident : $const_ty:ty ),+ $(,)? >
$( where { $($bounds:tt)* } )?
as $as_ty:ty = $kind:ident;
$($rest:tt)*
) => {
impl_ndt!(@single
$head :: $( $tail )::+ < $impl_generic, $( const $const_generic : $const_ty ),* >
$( where { $($bounds)* } )?
as $as_ty = $kind
);
impl_ndt!($($rest)*);
};
(
$(
$head:ident :: $( $tail:ident )::+
$(< $( $lifetime:lifetime, )* $( $generic:ident ),* $(,)? >)?
$( where { $($bounds:tt)* } )?
as $as_ty:ty = $kind:ident
);+ $(;)?
) => {
$(
impl_ndt!(@single
$head :: $( $tail )::+
$(< $( $lifetime, )* $( $generic ),* >)?
$( where { $($bounds)* } )?
as $as_ty = $kind
);
)+
};
// Single type
(@single $module_path:literal $ty:ident $(< $( $lifetime:lifetime, )* $( $generic:ident ),* $(,)? >)? $( where { $($bounds:tt)* } )? as $as_ty:ty = inline) => {
impl_ndt!(@kind inline $module_path $ty $(< $( $lifetime, )* $( $generic ),* >)? $( where { $($bounds)* } )? as $as_ty);
};
(@single $module_path:literal $ty:ident $(< $( $lifetime:lifetime, )* $( $generic:ident ),* $(,)? >)? $( where { $($bounds:tt)* } )? as $as_ty:ty = passthrough) => {
impl_ndt!(@kind passthrough $module_path $ty $(< $( $lifetime, )* $( $generic ),* >)? $( where { $($bounds)* } )? as $as_ty);
};
(@single $module_path:literal $ty:ident $(< $( $lifetime:lifetime, )* $( $generic:ident ),* $(,)? >)? $( where { $($bounds:tt)* } )? as $as_ty:ty = named) => {
impl_ndt!(@kind named $module_path $ty $(< $( $lifetime, )* $( $generic ),* >)? $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $( $specta_generic:ident ),* $(,)? > < $( $impl_generic:ident ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = inline) => {
impl_ndt!(true, false [$( $specta_generic ),*] [$( $impl_generic, )*] [$head :: $( $tail )::+] [< $( $specta_generic ),* >] [< $( $impl_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $( $specta_generic:ident ),* $(,)? > < $( $impl_generic:ident ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = passthrough) => {
impl_ndt!(false, true [$( $specta_generic ),*] [$( $impl_generic, )*] [$head :: $( $tail )::+] [< $( $specta_generic ),* >] [< $( $impl_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $( $specta_generic:ident ),* $(,)? > < $( $impl_generic:ident ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = named) => {
impl_ndt!(false, false [$( $specta_generic ),*] [$( $impl_generic, )*] [$head :: $( $tail )::+] [< $( $specta_generic ),* >] [< $( $impl_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $( $specta_generic:ident ),* $(,)? > < $first_impl_generic:ident, $second_impl_generic:ident, $third_impl_generic:ident, $( const $const_generic:ident : $const_ty:ty ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = inline) => {
impl_ndt!(true, false [$( $specta_generic ),*] [$first_impl_generic, $second_impl_generic, $third_impl_generic, $( const $const_generic : $const_ty, )*] [$head :: $( $tail )::+] [< $( $specta_generic ),* >] [< $first_impl_generic, $second_impl_generic, $third_impl_generic, $( $const_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $( $specta_generic:ident ),* $(,)? > < $first_impl_generic:ident, $second_impl_generic:ident, $third_impl_generic:ident, $( const $const_generic:ident : $const_ty:ty ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = passthrough) => {
impl_ndt!(false, true [$( $specta_generic ),*] [$first_impl_generic, $second_impl_generic, $third_impl_generic, $( const $const_generic : $const_ty, )*] [$head :: $( $tail )::+] [< $( $specta_generic ),* >] [< $first_impl_generic, $second_impl_generic, $third_impl_generic, $( $const_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $( $specta_generic:ident ),* $(,)? > < $first_impl_generic:ident, $second_impl_generic:ident, $( const $const_generic:ident : $const_ty:ty ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = inline) => {
impl_ndt!(true, false [$( $specta_generic ),*] [$first_impl_generic, $second_impl_generic, $( const $const_generic : $const_ty, )*] [$head :: $( $tail )::+] [< $( $specta_generic ),* >] [< $first_impl_generic, $second_impl_generic, $( $const_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $( $specta_generic:ident ),* $(,)? > < $first_impl_generic:ident, $second_impl_generic:ident, $( const $const_generic:ident : $const_ty:ty ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = passthrough) => {
impl_ndt!(false, true [$( $specta_generic ),*] [$first_impl_generic, $second_impl_generic, $( const $const_generic : $const_ty, )*] [$head :: $( $tail )::+] [< $( $specta_generic ),* >] [< $first_impl_generic, $second_impl_generic, $( $const_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $( $specta_generic:ident ),* $(,)? > < $first_impl_generic:ident, $( const $const_generic:ident : $const_ty:ty ),+, $( $rest_impl_generic:ident ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = inline) => {
impl_ndt!(true, false [$( $specta_generic ),*] [$first_impl_generic, $( const $const_generic : $const_ty, )* $( $rest_impl_generic, )*] [$head :: $( $tail )::+] [< $( $specta_generic ),* >] [< $first_impl_generic, $( $const_generic, )* $( $rest_impl_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $( $specta_generic:ident ),* $(,)? > < $first_impl_generic:ident, $( const $const_generic:ident : $const_ty:ty ),+, $( $rest_impl_generic:ident ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = passthrough) => {
impl_ndt!(false, true [$( $specta_generic ),*] [$first_impl_generic, $( const $const_generic : $const_ty, )* $( $rest_impl_generic, )*] [$head :: $( $tail )::+] [< $( $specta_generic ),* >] [< $first_impl_generic, $( $const_generic, )* $( $rest_impl_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $( $specta_generic:ident ),* $(,)? > < $impl_generic:ident, $( const $const_generic:ident : $const_ty:ty ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = inline) => {
impl_ndt!(true, false [$( $specta_generic ),*] [$impl_generic, $( const $const_generic : $const_ty, )*] [$head :: $( $tail )::+] [< $( $specta_generic ),* >] [< $impl_generic, $( $const_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $( $specta_generic:ident ),* $(,)? > < $impl_generic:ident, $( const $const_generic:ident : $const_ty:ty ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = passthrough) => {
impl_ndt!(false, true [$( $specta_generic ),*] [$impl_generic, $( const $const_generic : $const_ty, )*] [$head :: $( $tail )::+] [< $( $specta_generic ),* >] [< $impl_generic, $( $const_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $( const $const_generic:ident : $const_ty:ty ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = inline) => {
impl_ndt!(true, false [] [$( const $const_generic : $const_ty, )*] [$head :: $( $tail )::+] [] [< $( $const_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $( const $const_generic:ident : $const_ty:ty ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = passthrough) => {
impl_ndt!(false, true [] [$( const $const_generic : $const_ty, )*] [$head :: $( $tail )::+] [] [< $( $const_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $( const $const_generic:ident : $const_ty:ty ),+, $( $rest_impl_generic:ident ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = inline) => {
impl_ndt!(true, false [] [$( const $const_generic : $const_ty, )* $( $rest_impl_generic, )*] [$head :: $( $tail )::+] [] [< $( $const_generic, )* $( $rest_impl_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $( const $const_generic:ident : $const_ty:ty ),+, $( $rest_impl_generic:ident ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = passthrough) => {
impl_ndt!(false, true [] [$( const $const_generic : $const_ty, )* $( $rest_impl_generic, )*] [$head :: $( $tail )::+] [] [< $( $const_generic, )* $( $rest_impl_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $impl_generic:ident, $( const $const_generic:ident : $const_ty:ty ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = inline) => {
impl_ndt!(true, false [$impl_generic] [$impl_generic, $( const $const_generic : $const_ty, )*] [$head :: $( $tail )::+] [< $impl_generic >] [< $impl_generic, $( $const_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ < $impl_generic:ident, $( const $const_generic:ident : $const_ty:ty ),+ $(,)? > $( where { $($bounds:tt)* } )? as $as_ty:ty = passthrough) => {
impl_ndt!(false, true [$impl_generic] [$impl_generic, $( const $const_generic : $const_ty, )*] [$head :: $( $tail )::+] [< $impl_generic >] [< $impl_generic, $( $const_generic ),* >] $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ $(< $( $lifetime:lifetime, )* $( $generic:ident ),* $(,)? >)? $( where { $($bounds:tt)* } )? as $as_ty:ty = inline) => {
impl_ndt!(@kind inline $head :: $( $tail )::+ $(< $( $lifetime, )* $( $generic ),* >)? $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ $(< $( $lifetime:lifetime, )* $( $generic:ident ),* $(,)? >)? $( where { $($bounds:tt)* } )? as $as_ty:ty = passthrough) => {
impl_ndt!(@kind passthrough $head :: $( $tail )::+ $(< $( $lifetime, )* $( $generic ),* >)? $( where { $($bounds)* } )? as $as_ty);
};
(@single $head:ident :: $( $tail:ident )::+ $(< $( $lifetime:lifetime, )* $( $generic:ident ),* $(,)? >)? $( where { $($bounds:tt)* } )? as $as_ty:ty = named) => {
impl_ndt!(@kind named $head :: $( $tail )::+ $(< $( $lifetime, )* $( $generic ),* >)? $( where { $($bounds)* } )? as $as_ty);
};
(@kind inline $($tokens:tt)*) => {
impl_ndt!(true, false $($tokens)*);
};
(@kind passthrough $($tokens:tt)*) => {
impl_ndt!(false, true $($tokens)*);
};
(@kind named $($tokens:tt)*) => {
impl_ndt!(false, false $($tokens)*);
};
// Base implementation. Providing a where clause opts out of automatic Type bounds so
// callers can use non-Specta impl generics.
($inline:literal, $container:literal $module_path:literal $ty:ident $(< $( $lifetime:lifetime, )* $( $generic:ident ),* $(,)? >)? where { $($bounds:tt)* } as $as_ty:ty) => {
impl<$( $( $lifetime, )* $( $generic ),* )?> Type for $ty $(< $( $lifetime, )* $( $generic ),* >)?
where
$($bounds)*
{
fn definition(types: &mut Types) -> DataType {
use $crate::datatype;
impl_ndt!(@definition_body false stringify!($ty $(< $( $generic ),* >)?), [$( $( $generic ),* )?], [$ty $(< $( $generic ),* >)?], $module_path, $inline, $container, $as_ty, types)
}
}
};
($inline:literal, $container:literal $module_path:literal $ty:ident $(< $( $lifetime:lifetime, )* $( $generic:ident ),* $(,)? >)? as $as_ty:ty) => {
impl<$( $( $lifetime, )* $( $generic ),* )?> Type for $ty $(< $( $lifetime, )* $( $generic ),* >)?
where
$(
$( $generic: Type, )*
)?
{
fn definition(types: &mut Types) -> DataType {
use $crate::datatype;
impl_ndt!(@definition_body true stringify!($ty $(< $( $generic ),* >)?), [$( $( $generic ),* )?], [$ty $(< $( $generic ),* >)?], $module_path, $inline, $container, $as_ty, types)
}
}
};
($inline:literal, $container:literal $head:ident :: $( $tail:ident )::+ $(< $( $lifetime:lifetime, )* $( $generic:ident ),* $(,)? >)? where { $($bounds:tt)* } as $as_ty:ty) => {
impl<$( $( $lifetime, )* $( $generic ),* )?> Type for $head :: $( $tail )::+ $(< $( $lifetime, )* $( $generic ),* >)?
where
$($bounds)*
{
fn definition(types: &mut Types) -> DataType {
use $crate::datatype;
impl_ndt!(@definition_body false stringify!($head::$( $tail )::+ $(< $( $generic ),* >)?), [$( $( $generic ),* )?], [$head :: $( $tail )::+ $(< $( $generic ),* >)?], impl_ndt!(@module_path $head :: $( $tail )::+), $inline, $container, $as_ty, types)
}
}
};
($inline:literal, $container:literal $head:ident :: $( $tail:ident )::+ $(< $( $lifetime:lifetime, )* $( $generic:ident ),* $(,)? >)? as $as_ty:ty) => {
impl<$( $( $lifetime, )* $( $generic ),* )?> Type for $head :: $( $tail )::+ $(< $( $lifetime, )* $( $generic ),* >)?
where
$(
$( $generic: Type, )*
)?
{
fn definition(types: &mut Types) -> DataType {
use $crate::datatype;
impl_ndt!(@definition_body true stringify!($head::$( $tail )::+ $(< $( $generic ),* >)?), [$( $( $generic ),* )?], [$head :: $( $tail )::+ $(< $( $generic ),* >)?], impl_ndt!(@module_path $head :: $( $tail )::+), $inline, $container, $as_ty, types)
}
}
};
// Base implementation for types with const generics. Const generics are part of the Rust
// implementation but not Specta generic definitions.
($inline:literal, $container:literal [$($generic:ident),*] [$($impl_generics:tt)*] [$($ty:tt)*] [$($specta_generics:tt)*] [$($ty_generics:tt)*] where { $($bounds:tt)* } as $as_ty:ty) => {
impl<$($impl_generics)*> Type for $($ty)* $($ty_generics)*
where
$($bounds)*
{
fn definition(types: &mut Types) -> DataType {
use $crate::datatype;
impl_ndt!(@definition_body_const false stringify!($($ty)* $($ty_generics)*), [$($generic),*], [$($ty)* $($specta_generics)*], impl_ndt!(@module_path $($ty)*), $inline, $container, $as_ty, types)
}
}
};
($inline:literal, $container:literal [$($generic:ident),*] [$($impl_generics:tt)*] [$($ty:tt)*] [$($specta_generics:tt)*] [$($ty_generics:tt)*] as $as_ty:ty) => {
impl<$($impl_generics)*> Type for $($ty)* $($ty_generics)*
where
$($generic: Type,)*
{
fn definition(types: &mut Types) -> DataType {
use $crate::datatype;
impl_ndt!(@definition_body_const true stringify!($($ty)* $($ty_generics)*), [$($generic),*], [$($ty)* $($specta_generics)*], impl_ndt!(@module_path $($ty)*), $inline, $container, $as_ty, types)
}
}
};
(@definition_body $typed_generics:tt $sentinel:expr, [$($generic:ident),*], [$($type_name:tt)*], $module_path:expr, $inline:literal, $container:literal, $
gitextract_unw2xfqn/
├── .github/
│ ├── FUNDING.yml
│ ├── dependabot.yml
│ ├── features.js
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── .rustfmt.toml
├── .taplo.toml
├── AGENTS.md
├── Cargo.toml
├── LICENSE
├── README.md
├── examples/
│ ├── basic-ts/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ ├── collect/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ └── main.rs
│ └── scratchpad/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── specta/
│ ├── Cargo.toml
│ ├── build.rs
│ └── src/
│ ├── collect.rs
│ ├── datatype/
│ │ ├── attributes.rs
│ │ ├── enum.rs
│ │ ├── fields.rs
│ │ ├── function.rs
│ │ ├── generic.rs
│ │ ├── list.rs
│ │ ├── literal.rs
│ │ ├── map.rs
│ │ ├── named.rs
│ │ ├── primitive.rs
│ │ ├── reference.rs
│ │ ├── struct.rs
│ │ └── tuple.rs
│ ├── datatype.rs
│ ├── docs.md
│ ├── format.rs
│ ├── function/
│ │ ├── arg.rs
│ │ ├── result.rs
│ │ └── specta_fn.rs
│ ├── function.rs
│ ├── internal.rs
│ ├── lib.rs
│ ├── type/
│ │ ├── impls.rs
│ │ ├── legacy_impls.rs
│ │ └── macros.rs
│ ├── type.rs
│ └── types.rs
├── specta-go/
│ ├── Cargo.toml
│ ├── bindings.go
│ └── src/
│ ├── error.rs
│ ├── go.rs
│ ├── lib.rs
│ ├── primitives.rs
│ └── reserved_names.rs
├── specta-jsonschema/
│ ├── Cargo.toml
│ ├── examples/
│ │ └── jsonschema.rs
│ ├── src/
│ │ ├── error.rs
│ │ ├── import.rs
│ │ ├── json_schema.rs
│ │ ├── layout.rs
│ │ ├── lib.rs
│ │ ├── primitives.rs
│ │ └── schema_version.rs
│ └── tests/
│ └── basic.rs
├── specta-kotlin/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
├── specta-macros/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ ├── lib.rs
│ ├── specta.rs
│ ├── type/
│ │ ├── attr/
│ │ │ ├── container.rs
│ │ │ ├── field.rs
│ │ │ ├── legacy.rs
│ │ │ ├── mod.rs
│ │ │ ├── rustc.rs
│ │ │ └── variant.rs
│ │ ├── enum.rs
│ │ ├── field.rs
│ │ ├── generics.rs
│ │ ├── mod.rs
│ │ ├── serde.rs
│ │ └── struct.rs
│ └── utils.rs
├── specta-openapi/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
├── specta-serde/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ ├── error.rs
│ ├── inflection.rs
│ ├── lib.rs
│ ├── parser.rs
│ ├── phased.rs
│ ├── repr.rs
│ └── validate.rs
├── specta-swift/
│ ├── Cargo.toml
│ ├── README.md
│ ├── Types.swift
│ ├── examples/
│ │ ├── README.md
│ │ ├── advanced_unions.rs
│ │ ├── basic_types.rs
│ │ ├── comments_example.rs
│ │ ├── comprehensive_demo.rs
│ │ ├── configuration_options.rs
│ │ ├── generated/
│ │ │ ├── AdvancedUnions.swift
│ │ │ ├── BasicTypes.swift
│ │ │ ├── CamelCase.swift
│ │ │ ├── CombinedConfig.swift
│ │ │ ├── CommentsExample.swift
│ │ │ ├── ComprehensiveDemo.swift
│ │ │ ├── CustomHeader.swift
│ │ │ ├── CustomTypes.swift
│ │ │ ├── DefaultConfig.swift
│ │ │ ├── OptionalType.swift
│ │ │ ├── PascalCase.swift
│ │ │ ├── ProtocolGenerics.swift
│ │ │ ├── QuestionMark.swift
│ │ │ ├── SimpleTypes.swift
│ │ │ ├── SnakeCase.swift
│ │ │ ├── Spaces2.swift
│ │ │ ├── Spaces4.swift
│ │ │ ├── SpecialTypes.swift
│ │ │ ├── StringEnums.swift
│ │ │ ├── Tabs.swift
│ │ │ ├── TypealiasGenerics.swift
│ │ │ ├── WithProtocols.swift
│ │ │ └── WithSerde.swift
│ │ ├── simple_usage.rs
│ │ ├── special_types.rs
│ │ └── string_enums.rs
│ ├── src/
│ │ ├── error.rs
│ │ ├── lib.rs
│ │ ├── primitives.rs
│ │ └── swift.rs
│ └── tests/
│ ├── Cargo.toml
│ ├── advanced_unions.rs
│ ├── basic.rs
│ ├── common_types.rs
│ ├── comprehensive.rs
│ ├── multiline_comments.rs
│ ├── string_enum_implementation.rs
│ ├── string_enum_test.rs
│ ├── struct_reuse_test.rs
│ ├── struct_variants.rs
│ ├── unions.rs
│ ├── uuid_simple.rs
│ └── uuid_test.rs
├── specta-tags/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
├── specta-typescript/
│ ├── Cargo.toml
│ ├── bindings.ts
│ └── src/
│ ├── branded.rs
│ ├── error.rs
│ ├── exporter.rs
│ ├── jsdoc.rs
│ ├── legacy.rs
│ ├── lib.rs
│ ├── map_keys.rs
│ ├── opaque.rs
│ ├── primitives.rs
│ ├── references.rs
│ ├── reserved_names.rs
│ ├── types.rs
│ └── typescript.rs
├── specta-util/
│ ├── Cargo.toml
│ └── src/
│ ├── array.rs
│ ├── lib.rs
│ ├── remapper.rs
│ └── selection.rs
├── specta-zod/
│ ├── Cargo.toml
│ └── src/
│ ├── error.rs
│ ├── lib.rs
│ ├── opaque.rs
│ ├── primitives.rs
│ ├── references.rs
│ ├── reserved_names.rs
│ ├── types.rs
│ └── zod.rs
└── tests/
├── Cargo.toml
└── tests/
├── bound.rs
├── errors.rs
├── functions.rs
├── jsdoc.rs
├── layouts.rs
├── legacy_impls.rs
├── macro/
│ ├── compile_error.rs
│ └── compile_error.stderr
├── mod.rs
├── references.rs
├── serde_conversions.rs
├── serde_identifiers.rs
├── serde_other.rs
├── snapshots/
│ ├── test__bound__bound-associated-type-issue-138.snap
│ ├── test__jsdoc__export-many-raw.snap
│ ├── test__jsdoc__export-many-serde.snap
│ ├── test__jsdoc__export-many-serde_phases.snap
│ ├── test__jsdoc__export-raw.snap
│ ├── test__jsdoc__export-serde.snap
│ ├── test__jsdoc__export-serde_phases.snap
│ ├── test__jsdoc__inline-raw.snap
│ ├── test__jsdoc__inline-serde.snap
│ ├── test__jsdoc__inline-serde_phases.snap
│ ├── test__jsdoc__jsdoc-export-to-files-both.snap
│ ├── test__jsdoc__jsdoc-export-to-files-raw.snap
│ ├── test__jsdoc__jsdoc-export-to-files-serde.snap
│ ├── test__jsdoc__jsdoc-export-to-files-serde_phases.snap
│ ├── test__jsdoc__jsdoc-export-to-flatfile-raw.snap
│ ├── test__jsdoc__jsdoc-export-to-flatfile-serde.snap
│ ├── test__jsdoc__jsdoc-export-to-flatfile-serde_phases.snap
│ ├── test__jsdoc__jsdoc-export-to-moduleprefixedname-raw.snap
│ ├── test__jsdoc__jsdoc-export-to-moduleprefixedname-serde.snap
│ ├── test__jsdoc__jsdoc-export-to-moduleprefixedname-serde_phases.snap
│ ├── test__jsdoc__jsdoc-export-to-namespaces-raw.snap
│ ├── test__jsdoc__jsdoc-export-to-namespaces-serde.snap
│ ├── test__jsdoc__jsdoc-export-to-namespaces-serde_phases.snap
│ ├── test__jsdoc__primitives-many-inline-raw.snap
│ ├── test__jsdoc__primitives-many-inline-serde.snap
│ ├── test__jsdoc__primitives-many-inline-serde_phases.snap
│ ├── test__jsdoc__reference-raw.snap
│ ├── test__jsdoc__reference-serde.snap
│ ├── test__jsdoc__reference-serde_phases.snap
│ ├── test__layouts__layouts-duplicate-files.snap
│ ├── test__layouts__layouts-duplicate-module-prefixed.snap
│ ├── test__layouts__layouts-duplicate-namespaces.snap
│ ├── test__layouts__layouts-empty-module-path-files.snap
│ ├── test__layouts__layouts-empty-module-path-flat.snap
│ ├── test__layouts__layouts-empty-module-path-module-prefixed.snap
│ ├── test__layouts__layouts-empty-module-path-namespaces.snap
│ ├── test__layouts__layouts-non-duplicate-default.snap
│ ├── test__layouts__layouts-non-duplicate-files.snap
│ ├── test__layouts__layouts-non-duplicate-flat.snap
│ ├── test__layouts__layouts-non-duplicate-module-prefixed.snap
│ ├── test__layouts__layouts-non-duplicate-namespaces.snap
│ ├── test__legacy_impls__legacy_impls.snap
│ ├── test__serde_conversions__serde-conversions-format-phases-exports-field-only-phased-override.snap
│ ├── test__serde_conversions__serde-conversions-format-phases-splits-container-and-dependents.snap
│ ├── test__serde_identifiers__serde-identifiers-field-typescript.snap
│ ├── test__serde_identifiers__serde-identifiers-variant-typescript.snap
│ ├── test__serde_other__serde-other-adjacent-tag-typescript.snap
│ ├── test__serde_other__serde-other-internal-tag-typescript.snap
│ ├── test__swift__swift-export-raw.snap
│ ├── test__swift__swift-export-serde.snap
│ ├── test__swift__swift-export-serde_phases.snap
│ ├── test__types__serde-default-container-typescript.snap
│ ├── test__types__serde-default-field-typescript.snap
│ ├── test__types__serde-mixed-untagged-phased-typescript.snap
│ ├── test__types__serde-mixed-untagged-struct-typescript.snap
│ ├── test__types__serde-mixed-untagged-typescript.snap
│ ├── test__typescript__export-many-raw.snap
│ ├── test__typescript__export-many-serde.snap
│ ├── test__typescript__export-many-serde_phases.snap
│ ├── test__typescript__export-raw.snap
│ ├── test__typescript__export-serde.snap
│ ├── test__typescript__export-serde_phases.snap
│ ├── test__typescript__inline-raw.snap
│ ├── test__typescript__inline-serde.snap
│ ├── test__typescript__inline-serde_phases.snap
│ ├── test__typescript__reference-raw.snap
│ ├── test__typescript__reference-serde.snap
│ ├── test__typescript__reference-serde_phases.snap
│ ├── test__typescript__ts-export-raw.snap
│ ├── test__typescript__ts-export-serde.snap
│ ├── test__typescript__ts-export-serde_phases.snap
│ ├── test__typescript__ts-export-to-files-raw.snap
│ ├── test__typescript__ts-export-to-files-serde.snap
│ ├── test__typescript__ts-export-to-files-serde_phases.snap
│ ├── test__typescript__ts-export-to-flatfile-raw.snap
│ ├── test__typescript__ts-export-to-flatfile-serde.snap
│ ├── test__typescript__ts-export-to-flatfile-serde_phases.snap
│ ├── test__typescript__ts-export-to-moduleprefixedname-raw.snap
│ ├── test__typescript__ts-export-to-moduleprefixedname-serde.snap
│ ├── test__typescript__ts-export-to-moduleprefixedname-serde_phases.snap
│ ├── test__typescript__ts-export-to-namespaces-raw.snap
│ ├── test__typescript__ts-export-to-namespaces-serde.snap
│ └── test__typescript__ts-export-to-namespaces-serde_phases.snap
├── swift.rs
├── types.rs
├── typescript.rs
├── utils.rs
└── zod.rs
SYMBOL INDEX (1691 symbols across 129 files)
FILE: .github/features.js
constant START_MARKER (line 7) | const START_MARKER = "[//]: # (FEATURE_FLAGS_START)";
constant END_MARKER (line 8) | const END_MARKER = "[//]: # (FEATURE_FLAGS_END)";
FILE: examples/basic-ts/src/main.rs
type User (line 11) | pub struct User {
type Post (line 25) | pub struct Post {
type PostStatus (line 35) | pub enum PostStatus {
function main (line 41) | fn main() {
FILE: examples/collect/src/main.rs
type User (line 7) | pub struct User {
type Post (line 13) | pub struct Post {
type Comment (line 20) | pub struct Comment {
type InternalMetrics (line 27) | pub struct InternalMetrics {
function main (line 31) | fn main() -> Result<(), Box<dyn std::error::Error>> {
FILE: examples/scratchpad/src/main.rs
function main (line 6) | fn main() {
FILE: specta-go/bindings.go
type MyType (line 3) | type MyType struct
FILE: specta-go/src/error.rs
type Error (line 7) | pub enum Error {
method fmt (line 36) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method from (line 57) | fn from(e: io::Error) -> Self {
method from (line 63) | fn from(e: fmt::Error) -> Self {
method format (line 69) | pub(crate) fn format(message: &'static str, source: specta::FormatErro...
FILE: specta-go/src/go.rs
type Layout (line 15) | pub enum Layout {
type Go (line 26) | pub struct Go {
method new (line 46) | pub fn new() -> Self {
method package_name (line 51) | pub fn package_name(mut self, name: impl Into<String>) -> Self {
method header (line 57) | pub fn header(mut self, header: impl Into<Cow<'static, str>>) -> Self {
method export (line 63) | pub fn export(&self, types: &Types, format: impl Format) -> Result<Str...
method export_to (line 102) | pub fn export_to(
method default (line 35) | fn default() -> Self {
function format_types (line 121) | fn format_types<'a>(
function map_datatype_format (line 134) | fn map_datatype_format(
function map_datatype_format_children (line 156) | fn map_datatype_format_children(
function map_datatype_fields (line 207) | fn map_datatype_fields(
function map_types_for_datatype_format (line 234) | fn map_types_for_datatype_format<'a>(
FILE: specta-go/src/primitives.rs
type GoContext (line 15) | pub struct GoContext {
method add_import (line 20) | pub fn add_import(&mut self, import: &str) {
function export (line 25) | pub fn export(
function struct_fields (line 135) | fn struct_fields(
function enum_variants (line 202) | fn enum_variants(
function datatype (line 262) | fn datatype(
function to_pascal_case (line 397) | fn to_pascal_case(s: &str) -> String {
FILE: specta-go/src/reserved_names.rs
constant RESERVED_GO_NAMES (line 2) | pub(crate) const RESERVED_GO_NAMES: &[&str] = &[
FILE: specta-jsonschema/examples/jsonschema.rs
type User (line 9) | pub struct User {
type Role (line 17) | pub enum Role {
type Post (line 25) | pub struct Post {
function main (line 33) | fn main() {
FILE: specta-jsonschema/src/error.rs
type Error (line 4) | pub enum Error {
method format (line 41) | pub(crate) fn format(message: &'static str, source: specta::FormatErro...
FILE: specta-jsonschema/src/import.rs
function from_schema (line 8) | pub fn from_schema(schema: &Schema) -> Result<DataType, Error> {
function value_to_datatype (line 28) | fn value_to_datatype(value: &Value) -> Result<DataType, Error> {
function schema_object_to_datatype (line 33) | fn schema_object_to_datatype(obj: &JsonMap<String, Value>) -> Result<Dat...
function instance_type_to_datatype (line 78) | fn instance_type_to_datatype(
function instance_type_name_to_datatype (line 105) | fn instance_type_name_to_datatype(
function handle_any_of (line 218) | fn handle_any_of(schemas: &[Value]) -> Result<DataType, Error> {
FILE: specta-jsonschema/src/json_schema.rs
type JsonSchema (line 8) | pub struct JsonSchema {
method new (line 32) | pub fn new() -> Self {
method schema_version (line 37) | pub fn schema_version(mut self, version: SchemaVersion) -> Self {
method layout (line 43) | pub fn layout(mut self, layout: Layout) -> Self {
method title (line 49) | pub fn title(mut self, title: impl Into<String>) -> Self {
method description (line 55) | pub fn description(mut self, description: impl Into<String>) -> Self {
method export (line 61) | pub fn export(&self, types: &Types, format: impl Format) -> Result<Str...
method export_as_value (line 67) | pub fn export_as_value(&self, types: &Types, format: impl Format) -> R...
method export_to (line 81) | pub fn export_to(
method export_single_file (line 105) | fn export_single_file(&self, types: &Types) -> Result<Value, Error> {
method export_files (line 138) | fn export_files(&self, base_path: &Path, types: &Types) -> Result<(), ...
method default (line 20) | fn default() -> Self {
function format_types (line 187) | fn format_types<'a>(
FILE: specta-jsonschema/src/layout.rs
type Layout (line 3) | pub enum Layout {
method default (line 15) | fn default() -> Self {
FILE: specta-jsonschema/src/lib.rs
function to_ast (line 135) | pub fn to_ast(schema: &schemars::Schema) -> Result<specta::datatype::Dat...
FILE: specta-jsonschema/src/primitives.rs
function export (line 9) | pub fn export(js: &JsonSchema, types: &Types, ndt: &NamedDataType) -> Re...
function datatype_to_schema (line 18) | pub fn datatype_to_schema(
function primitive_to_schema (line 126) | fn primitive_to_schema(p: &Primitive) -> Value {
function struct_to_schema (line 155) | fn struct_to_schema(js: &JsonSchema, types: &Types, s: &Struct) -> Resul...
function enum_to_schema (line 213) | fn enum_to_schema(js: &JsonSchema, types: &Types, e: &Enum) -> Result<Va...
function variant_to_schema (line 238) | fn variant_to_schema(
function tuple_to_schema (line 332) | fn tuple_to_schema(js: &JsonSchema, types: &Types, t: &Tuple) -> Result<...
FILE: specta-jsonschema/src/schema_version.rs
type SchemaVersion (line 5) | pub enum SchemaVersion {
method uri (line 16) | pub fn uri(&self) -> &'static str {
method definitions_key (line 26) | pub fn definitions_key(&self) -> &'static str {
method default (line 35) | fn default() -> Self {
FILE: specta-jsonschema/tests/basic.rs
type User (line 10) | struct User {
type Status (line 17) | enum Status {
function test_basic_export (line 24) | fn test_basic_export() {
function test_schema_version (line 37) | fn test_schema_version() {
function test_primitives (line 50) | fn test_primitives() {
function test_nullable (line 68) | fn test_nullable() {
function test_enum (line 79) | fn test_enum() {
function test_export_uses_format (line 91) | fn test_export_uses_format() {
function test_export_to_uses_format (line 108) | fn test_export_to_uses_format() {
FILE: specta-macros/src/lib.rs
function derive_type (line 203) | pub fn derive_type(input: proc_macro::TokenStream) -> proc_macro::TokenS...
function parse_type_from_lit (line 212) | pub fn parse_type_from_lit(input: proc_macro::TokenStream) -> proc_macro...
function specta (line 235) | pub fn specta(
FILE: specta-macros/src/specta.rs
function unraw (line 15) | fn unraw(s: &str) -> &str {
type RenameAllRule (line 24) | enum RenameAllRule {
method parse (line 36) | fn parse(value: &str, span: proc_macro2::Span) -> syn::Result<Self> {
method apply (line 53) | fn apply(self, input: &str) -> String {
type FunctionNameAttrs (line 67) | struct FunctionNameAttrs {
function parse_name_attrs (line 72) | fn parse_name_attrs(
function attribute (line 99) | pub fn attribute(
FILE: specta-macros/src/type/attr/container.rs
type ContainerAttr (line 11) | pub struct ContainerAttr {
method from_attrs (line 28) | pub fn from_attrs(attrs: &mut Vec<Attribute>) -> Result<Self> {
FILE: specta-macros/src/type/attr/field.rs
type FieldAttr (line 8) | pub struct FieldAttr {
method from_attrs (line 17) | pub fn from_attrs(attrs: &mut Vec<Attribute>) -> Result<Self> {
FILE: specta-macros/src/type/attr/legacy.rs
type Scope (line 2) | pub enum Scope {
method as_str (line 9) | fn as_str(self) -> &'static str {
function migration_hint (line 18) | pub fn migration_hint(scope: Scope, key: &str) -> Option<String> {
FILE: specta-macros/src/type/attr/rustc.rs
type Deprecated (line 10) | pub struct Deprecated {
method new (line 16) | pub const fn new() -> Self {
method with_note (line 23) | pub fn with_note(note: Cow<'static, str>) -> Self {
method with_since_note (line 30) | pub fn with_since_note(since: Option<Cow<'static, str>>, note: Cow<'st...
type RustCAttr (line 39) | pub struct RustCAttr {
method from_attrs (line 45) | pub fn from_attrs(attrs: &mut Vec<Attribute>) -> Result<Self> {
function deprecated_as_tokens (line 118) | pub(crate) fn deprecated_as_tokens(Deprecated { note, since }: Deprecate...
FILE: specta-macros/src/type/attr/variant.rs
type VariantAttr (line 8) | pub struct VariantAttr {
method from_attrs (line 16) | pub fn from_attrs(attrs: &mut Vec<Attribute>) -> Result<Self> {
FILE: specta-macros/src/type/enum.rs
function parse_enum (line 10) | pub fn parse_enum(
function parse_variant_type_override (line 197) | fn parse_variant_type_override(attrs: &[syn::Attribute]) -> syn::Result<...
FILE: specta-macros/src/type/field.rs
function construct_field (line 12) | pub fn construct_field(
function construct_field_with_variant_skip (line 29) | pub fn construct_field_with_variant_skip(
FILE: specta-macros/src/type/generics.rs
type UsedTypeParams (line 16) | pub struct UsedTypeParams {
function generics_with_ident_and_bounds_only (line 22) | pub fn generics_with_ident_and_bounds_only(generics: &Generics) -> Optio...
function generics_with_ident_only_and_const_ty (line 51) | pub fn generics_with_ident_only_and_const_ty(
function type_where_clause (line 83) | pub fn type_where_clause(
function generics_with_ident_only (line 105) | pub fn generics_with_ident_only(generics: &Generics) -> Option<TokenStre...
function type_with_inferred_lifetimes (line 118) | pub fn type_with_inferred_lifetimes(ty: &Type) -> Type {
type InferredLifetimeVisitor (line 124) | struct InferredLifetimeVisitor;
method visit_lifetime_mut (line 127) | fn visit_lifetime_mut(&mut self, lifetime: &mut syn::Lifetime) {
function all_type_param_idents (line 132) | pub fn all_type_param_idents(generics: &Generics) -> Vec<syn::Ident> {
function used_type_params (line 145) | pub fn used_type_params(
function field_is_skipped (line 234) | fn field_is_skipped(field: &syn::Field) -> syn::Result<bool> {
function variant_is_skipped (line 239) | fn variant_is_skipped(variant: &syn::Variant) -> syn::Result<bool> {
function has_associated_type_usage (line 244) | pub fn has_associated_type_usage(used_generic_types: &UsedTypeParams) ->...
function used_direct_type_params (line 248) | pub fn used_direct_type_params<'a>(
function used_associated_type_paths (line 259) | pub fn used_associated_type_paths(used_generic_types: &UsedTypeParams) -...
function add_type_to_where_clause (line 267) | pub fn add_type_to_where_clause(
function merge_custom_bounds (line 301) | fn merge_custom_bounds(
type GenericTypeUseVisitor (line 322) | struct GenericTypeUseVisitor<'a> {
function visit_type_path (line 330) | fn visit_type_path(&mut self, node: &syn::TypePath) {
function visit_type (line 360) | fn visit_type(&mut self, node: &syn::Type) {
FILE: specta-macros/src/type/mod.rs
type AttributeScope (line 26) | pub(super) enum AttributeScope {
function build_runtime_attributes (line 32) | pub(super) fn build_runtime_attributes(
function derive (line 67) | pub fn derive(input: proc_macro::TokenStream) -> syn::Result<proc_macro:...
FILE: specta-macros/src/type/serde.rs
type ConversionType (line 8) | struct ConversionType {
type RenameRule (line 14) | enum RenameRule {
method parse (line 26) | fn parse(lit: &LitStr) -> Result<Self> {
method as_str (line 45) | fn as_str(self) -> &'static str {
type ContainerAttrs (line 60) | struct ContainerAttrs {
type VariantAttrs (line 80) | struct VariantAttrs {
type FieldAttrs (line 96) | struct FieldAttrs {
function lower_runtime_attributes (line 110) | pub(super) fn lower_runtime_attributes(
function parse_container_attrs (line 125) | fn parse_container_attrs(attrs: &[Attribute]) -> Result<Option<Container...
function parse_variant_attrs (line 141) | fn parse_variant_attrs(attrs: &[Attribute]) -> Result<Option<VariantAttr...
function parse_field_attrs (line 157) | fn parse_field_attrs(attrs: &[Attribute]) -> Result<Option<FieldAttrs>> {
function parse_container_meta (line 173) | fn parse_container_meta(target: &mut ContainerAttrs, meta: ParseNestedMe...
function parse_variant_meta (line 218) | fn parse_variant_meta(target: &mut VariantAttrs, meta: ParseNestedMeta<'...
function parse_field_meta (line 258) | fn parse_field_meta(target: &mut FieldAttrs, meta: ParseNestedMeta<'_>) ...
function parse_rename (line 295) | fn parse_rename(
function parse_rename_all (line 318) | fn parse_rename_all(
function parse_default_assignment (line 342) | fn parse_default_assignment(meta: &ParseNestedMeta<'_>) -> Result<String> {
function parse_conversion_assignment (line 350) | fn parse_conversion_assignment(meta: &ParseNestedMeta<'_>) -> Result<Con...
function parse_string_assignment (line 359) | fn parse_string_assignment(meta: &ParseNestedMeta<'_>) -> Result<String> {
function parse_lit_str (line 363) | fn parse_lit_str(meta: &ParseNestedMeta<'_>) -> Result<LitStr> {
function lower_container_attrs (line 367) | fn lower_container_attrs(crate_ref: &TokenStream, attrs: ContainerAttrs)...
function lower_variant_attrs (line 425) | fn lower_variant_attrs(_crate_ref: &TokenStream, attrs: VariantAttrs) ->...
function lower_field_attrs (line 475) | fn lower_field_attrs(_crate_ref: &TokenStream, attrs: FieldAttrs) -> Tok...
function push_opt_string (line 520) | fn push_opt_string(inserts: &mut Vec<TokenStream>, key: &str, value: &Op...
function push_vec_string (line 526) | fn push_vec_string(inserts: &mut Vec<TokenStream>, key: &str, value: &[S...
function push_bool (line 537) | fn push_bool(inserts: &mut Vec<TokenStream>, key: &str, value: bool) {
function push_opt_rename_rule (line 543) | fn push_opt_rename_rule(inserts: &mut Vec<TokenStream>, key: &str, value...
function push_opt_conversion (line 550) | fn push_opt_conversion(
FILE: specta-macros/src/type/struct.rs
function decode_field_attrs (line 11) | pub fn decode_field_attrs<'a>(
function parse_struct (line 67) | pub fn parse_struct(
FILE: specta-macros/src/utils.rs
type AttributeValue (line 12) | pub enum AttributeValue {
method span (line 26) | fn span(&self) -> Span {
method parse (line 37) | fn parse(input: ParseStream) -> Result<Self> {
type Attribute (line 52) | pub struct Attribute {
method value_span (line 64) | pub fn value_span(&self) -> Span {
method parse_string (line 71) | pub fn parse_string(&self) -> Result<String> {
method parse_bool (line 81) | pub fn parse_bool(&self) -> Result<bool> {
method parse_path (line 91) | pub fn parse_path(&self) -> Result<Path> {
method parse_type (line 102) | pub fn parse_type(&self) -> Result<Type> {
type AttrExtract (line 122) | pub trait AttrExtract {
method extract (line 123) | fn extract(&mut self, source: &str, key: &str) -> Option<Attribute>;
method extract_all (line 124) | fn extract_all(&mut self, source: &str, key: &str) -> Vec<Attribute>;
method extract (line 128) | fn extract(&mut self, source: &str, key: &str) -> Option<Attribute> {
method extract_all (line 162) | fn extract_all(&mut self, source: &str, key: &str) -> Vec<Attribute> {
type NestedAttributeList (line 210) | struct NestedAttributeList {
method parse (line 215) | fn parse(input: ParseStream) -> Result<Self> {
function parse_attrs (line 262) | pub fn parse_attrs(attrs: &[syn::Attribute]) -> syn::Result<Vec<Attribut...
function parse_attrs_with_filter (line 268) | pub fn parse_attrs_with_filter(
function unraw_raw_ident (line 326) | pub fn unraw_raw_ident(ident: &Ident) -> String {
function format_fn_wrapper (line 336) | pub fn format_fn_wrapper(function: &Ident) -> Ident {
FILE: specta-openapi/src/lib.rs
function to_openapi (line 62) | pub fn to_openapi(typ: &DataType) -> ReferenceOr<Schema> {
FILE: specta-serde/src/error.rs
type Error (line 5) | pub struct Error {
method invalid_usage_of_skip (line 64) | pub(crate) fn invalid_usage_of_skip(
method invalid_internally_tagged_enum (line 76) | pub(crate) fn invalid_internally_tagged_enum(
method invalid_enum_representation (line 90) | pub(crate) fn invalid_enum_representation(reason: impl Into<Cow<'stati...
method invalid_external_tagged_variant (line 98) | pub(crate) fn invalid_external_tagged_variant(variant: impl Into<Strin...
method invalid_adjacent_tagged_variant (line 106) | pub(crate) fn invalid_adjacent_tagged_variant(variant: impl Into<Strin...
method invalid_internally_tagged_variant (line 114) | pub(crate) fn invalid_internally_tagged_variant(
method incompatible_rename (line 126) | pub(crate) fn incompatible_rename(
method incompatible_conversion (line 142) | pub(crate) fn incompatible_conversion(
method invalid_conversion_usage (line 158) | pub(crate) fn invalid_conversion_usage(
method unsupported_serde_custom_codec (line 170) | pub(crate) fn unsupported_serde_custom_codec(
method invalid_phased_type_usage (line 182) | pub(crate) fn invalid_phased_type_usage(
method invalid_rename_rule (line 194) | pub(crate) fn invalid_rename_rule(
method fmt (line 208) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 275) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type ErrorKind (line 10) | enum ErrorKind {
FILE: specta-serde/src/inflection.rs
type RenameRule (line 11) | pub enum RenameRule {
method from_str (line 50) | pub fn from_str(rename_all_str: &str) -> Result<Self, ParseError<'_>> {
method apply_to_variant (line 62) | pub fn apply_to_variant(self, variant: &str) -> String {
method apply_to_field (line 87) | pub fn apply_to_field(self, field: &str) -> String {
method or (line 118) | pub fn or(self, rule_b: Self) -> Self {
type ParseError (line 126) | pub struct ParseError<'a> {
method fmt (line 131) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
FILE: specta-serde/src/lib.rs
type Phase (line 132) | pub enum Phase {
type Format (line 153) | pub struct Format;
method map_types (line 156) | fn map_types(&'_ self, types: &Types) -> Result<Cow<'_, Types>, Format...
method map_type (line 204) | fn map_type(&'_ self, types: &Types, dt: &DataType) -> Result<Cow<'_, ...
type PhasesFormat (line 241) | pub struct PhasesFormat;
method map_types (line 244) | fn map_types(&'_ self, types: &Types) -> Result<Cow<'_, Types>, Format...
method map_type (line 507) | fn map_type(&'_ self, types: &Types, dt: &DataType) -> Result<Cow<'_, ...
function datatype_is_registered_definition (line 533) | fn datatype_is_registered_definition(types: &Types, dt: &DataType) -> bo...
function select_phase_datatype (line 593) | pub fn select_phase_datatype(dt: &DataType, types: &Types, phase: Phase)...
type PhaseRewrite (line 600) | enum PhaseRewrite {
function select_phase_datatype_inner (line 606) | fn select_phase_datatype_inner(ty: &mut DataType, types: &Types, phase: ...
function select_phase_fields (line 680) | fn select_phase_fields(fields: &mut Fields, types: &Types, phase: Phase) {
function select_explicit_phased_type (line 700) | fn select_explicit_phased_type(ty: &DataType, phase: Phase) -> Option<Da...
function select_split_wrapper_variant (line 712) | fn select_split_wrapper_variant(ty: &DataType, phase: Phase) -> Option<D...
function select_split_type_variant (line 741) | fn select_split_type_variant<'a>(
function named_reference_generics (line 776) | fn named_reference_generics(
function named_reference_generics_mut (line 785) | fn named_reference_generics_mut(
type SplitGeneratedTypes (line 795) | struct SplitGeneratedTypes {
type TypeIdentity (line 801) | struct TypeIdentity {
method from_ndt (line 810) | fn from_ndt(ty: &specta::datatype::NamedDataType) -> Self {
function rewrite_datatype_for_phase (line 822) | fn rewrite_datatype_for_phase(
function lower_flattened_struct (line 983) | fn lower_flattened_struct(strct: &mut Struct) -> Result<Option<DataType>...
function field_is_flattened (line 1022) | fn field_is_flattened(field: &Field) -> bool {
function rewrite_fields_for_phase (line 1029) | fn rewrite_fields_for_phase(
function rewrite_field_for_phase (line 1103) | fn rewrite_field_for_phase(
function rewrite_struct_repr_for_phase (line 1139) | fn rewrite_struct_repr_for_phase(
function should_skip_field_for_mode (line 1203) | fn should_skip_field_for_mode(field: &Field, mode: PhaseRewrite) -> Resu...
function skipped_field_marker (line 1215) | fn skipped_field_marker(field: &Field) -> Field {
function unnamed_live_fields (line 1224) | fn unnamed_live_fields(unnamed: &UnnamedFields) -> impl Iterator<Item = ...
function unnamed_live_field_count (line 1228) | fn unnamed_live_field_count(unnamed: &UnnamedFields) -> usize {
function unnamed_has_effective_payload (line 1232) | fn unnamed_has_effective_payload(unnamed: &UnnamedFields) -> bool {
function unnamed_fields_all_skipped (line 1236) | fn unnamed_fields_all_skipped(unnamed: &UnnamedFields) -> bool {
function rewrite_enum_repr_for_phase (line 1240) | fn rewrite_enum_repr_for_phase(
function enum_repr_already_rewritten (line 1319) | fn enum_repr_already_rewritten(e: &Enum) -> bool {
function variant_repr_already_rewritten (line 1327) | fn variant_repr_already_rewritten(name: &str, variant: &Variant) -> bool {
function rewrite_identifier_enum_for_phase (line 1347) | fn rewrite_identifier_enum_for_phase(
function container_rename_all_rule (line 1425) | fn container_rename_all_rule(
function enum_variant_field_rename_rule (line 1444) | fn enum_variant_field_rename_rule(
function identifier_union_variant (line 1481) | fn identifier_union_variant(ty: DataType) -> Variant {
function transform_untagged_variant (line 1489) | fn transform_untagged_variant(variant: &Variant) -> Result<Variant, Erro...
function filter_enum_variants_for_phase (line 1495) | fn filter_enum_variants_for_phase(e: &mut Enum, mode: PhaseRewrite) -> R...
function variant_is_skipped_for_mode (line 1519) | fn variant_is_skipped_for_mode(attrs: &SerdeVariantAttrs, mode: PhaseRew...
function serialized_variant_name (line 1527) | fn serialized_variant_name(
function select_phase_string (line 1566) | fn select_phase_string<'a>(
function select_phase_rule (line 1590) | fn select_phase_rule(
function resolve_phased_type (line 1614) | fn resolve_phased_type(
function conversion_datatype_for_mode (line 1639) | fn conversion_datatype_for_mode(
function select_conversion_target (line 1652) | fn select_conversion_target(
function transform_external_variant (line 1704) | fn transform_external_variant(
function transform_adjacent_variant (line 1731) | fn transform_adjacent_variant(
function transform_internal_variant (line 1756) | fn transform_internal_variant(
function named_fields_datatype (line 1826) | fn named_fields_datatype(fields: Vec<(Cow<'static, str>, Field)>) -> Dat...
function string_literal_datatype (line 1835) | fn string_literal_datatype(value: String) -> DataType {
function is_generated_string_literal_datatype (line 1843) | fn is_generated_string_literal_datatype(ty: &DataType) -> bool {
function variant_has_effective_payload (line 1867) | fn variant_has_effective_payload(variant: &Variant) -> bool {
function variant_payload_field (line 1875) | fn variant_payload_field(variant: &Variant) -> Option<Field> {
function clone_variant_with_named_fields (line 1904) | fn clone_variant_with_named_fields(
function clone_variant_with_unnamed_fields (line 1921) | fn clone_variant_with_unnamed_fields(original: &Variant, fields: Vec<Fie...
function internal_tag_payload_compatibility (line 1935) | fn internal_tag_payload_compatibility(
function internal_tag_variant_payload_compatibility (line 2047) | fn internal_tag_variant_payload_compatibility(
function has_local_phase_difference (line 2076) | fn has_local_phase_difference(dt: &DataType) -> Result<bool, Error> {
function container_has_local_difference (line 2118) | fn container_has_local_difference(attrs: &specta::datatype::Attributes) ...
function fields_have_local_difference (line 2135) | fn fields_have_local_difference(fields: &Fields) -> Result<bool, Error> {
function field_has_local_difference (line 2172) | fn field_has_local_difference(field: &Field) -> Result<bool, Error> {
function variant_has_local_difference (line 2185) | fn variant_has_local_difference(variant: &Variant) -> Result<bool, Error> {
function collect_dependencies (line 2199) | fn collect_dependencies(
function collect_conversion_dependencies (line 2258) | fn collect_conversion_dependencies(
function collect_fields_dependencies (line 2281) | fn collect_fields_dependencies(
function build_from_original (line 2307) | fn build_from_original(
function register_generated_type (line 2317) | fn register_generated_type(types: &mut Types, generated: NamedDataType) ...
function rewrite_named_type_for_phase (line 2328) | fn rewrite_named_type_for_phase(ndt: &mut NamedDataType, mode: PhaseRewr...
function split_type_name (line 2338) | fn split_type_name(original: &NamedDataType, mode: PhaseRewrite) -> Resu...
function renamed_type_name_for_phase (line 2356) | fn renamed_type_name_for_phase(
function apply_field_attrs (line 2378) | fn apply_field_attrs(
function field_is_optional_for_mode (line 2396) | fn field_is_optional_for_mode(
type OneOrManyString (line 2422) | enum OneOrManyString {
type Filters (line 2428) | struct Filters {
type FilterList (line 2434) | struct FilterList {
type Plain (line 2439) | struct Plain {
type WithSkipIf (line 2444) | struct WithSkipIf {
function selects_split_named_reference_for_each_phase (line 2450) | fn selects_split_named_reference_for_each_phase() {
function rewrites_nested_generics_for_each_phase (line 2463) | fn rewrites_nested_generics_for_each_phase() {
function preserves_unsplit_types (line 2490) | fn preserves_unsplit_types() {
function clears_skip_serializing_if_attribute_after_phase_split (line 2503) | fn clears_skip_serializing_if_attribute_after_phase_split() {
function phase_split_field_passes_unified_mode_validation (line 2522) | fn phase_split_field_passes_unified_mode_validation() {
function resolves_explicit_phased_datatypes_without_named_types (line 2543) | fn resolves_explicit_phased_datatypes_without_named_types() {
function assert_named_reference (line 2555) | fn assert_named_reference(dt: &DataType, types: &Types, expected_name: &...
function named_field_type (line 2569) | fn named_field_type<'a>(dt: &'a DataType, types: &'a Types, field_name: ...
function field_has_skip_serializing_if (line 2589) | fn field_has_skip_serializing_if(dt: &DataType, types: &Types, field_nam...
function first_generic_type (line 2612) | fn first_generic_type(dt: &DataType) -> &DataType {
function list_item_type (line 2628) | fn list_item_type(dt: &DataType) -> &DataType {
function formatted_phases (line 2644) | fn formatted_phases(types: Types) -> Types {
FILE: specta-serde/src/parser.rs
constant CONTAINER_RENAME_SERIALIZE (line 6) | const CONTAINER_RENAME_SERIALIZE: &str = "serde:container:rename_seriali...
constant CONTAINER_RENAME_DESERIALIZE (line 7) | const CONTAINER_RENAME_DESERIALIZE: &str = "serde:container:rename_deser...
constant CONTAINER_RENAME_ALL_SERIALIZE (line 8) | const CONTAINER_RENAME_ALL_SERIALIZE: &str = "serde:container:rename_all...
constant CONTAINER_RENAME_ALL_DESERIALIZE (line 9) | const CONTAINER_RENAME_ALL_DESERIALIZE: &str = "serde:container:rename_a...
constant CONTAINER_RENAME_ALL_FIELDS_SERIALIZE (line 10) | const CONTAINER_RENAME_ALL_FIELDS_SERIALIZE: &str = "serde:container:ren...
constant CONTAINER_RENAME_ALL_FIELDS_DESERIALIZE (line 11) | const CONTAINER_RENAME_ALL_FIELDS_DESERIALIZE: &str =
constant CONTAINER_TAG (line 13) | const CONTAINER_TAG: &str = "serde:container:tag";
constant CONTAINER_CONTENT (line 14) | const CONTAINER_CONTENT: &str = "serde:container:content";
constant CONTAINER_UNTAGGED (line 15) | const CONTAINER_UNTAGGED: &str = "serde:container:untagged";
constant CONTAINER_DEFAULT (line 16) | const CONTAINER_DEFAULT: &str = "serde:container:default";
constant CONTAINER_TRANSPARENT (line 17) | const CONTAINER_TRANSPARENT: &str = "serde:container:transparent";
constant CONTAINER_FROM_TYPE_SRC (line 18) | const CONTAINER_FROM_TYPE_SRC: &str = "serde:container:from_type_src";
constant CONTAINER_FROM_RESOLVED (line 19) | const CONTAINER_FROM_RESOLVED: &str = "serde:container:from_resolved";
constant CONTAINER_TRY_FROM_TYPE_SRC (line 20) | const CONTAINER_TRY_FROM_TYPE_SRC: &str = "serde:container:try_from_type...
constant CONTAINER_TRY_FROM_RESOLVED (line 21) | const CONTAINER_TRY_FROM_RESOLVED: &str = "serde:container:try_from_reso...
constant CONTAINER_INTO_TYPE_SRC (line 22) | const CONTAINER_INTO_TYPE_SRC: &str = "serde:container:into_type_src";
constant CONTAINER_INTO_RESOLVED (line 23) | const CONTAINER_INTO_RESOLVED: &str = "serde:container:into_resolved";
constant CONTAINER_VARIANT_IDENTIFIER (line 24) | const CONTAINER_VARIANT_IDENTIFIER: &str = "serde:container:variant_iden...
constant CONTAINER_FIELD_IDENTIFIER (line 25) | const CONTAINER_FIELD_IDENTIFIER: &str = "serde:container:field_identifi...
constant VARIANT_RENAME_SERIALIZE (line 27) | const VARIANT_RENAME_SERIALIZE: &str = "serde:variant:rename_serialize";
constant VARIANT_RENAME_DESERIALIZE (line 28) | const VARIANT_RENAME_DESERIALIZE: &str = "serde:variant:rename_deseriali...
constant VARIANT_ALIASES (line 29) | const VARIANT_ALIASES: &str = "serde:variant:aliases";
constant VARIANT_RENAME_ALL_SERIALIZE (line 30) | const VARIANT_RENAME_ALL_SERIALIZE: &str = "serde:variant:rename_all_ser...
constant VARIANT_RENAME_ALL_DESERIALIZE (line 31) | const VARIANT_RENAME_ALL_DESERIALIZE: &str = "serde:variant:rename_all_d...
constant VARIANT_SKIP_SERIALIZING (line 32) | const VARIANT_SKIP_SERIALIZING: &str = "serde:variant:skip_serializing";
constant VARIANT_SKIP_DESERIALIZING (line 33) | const VARIANT_SKIP_DESERIALIZING: &str = "serde:variant:skip_deserializi...
constant VARIANT_HAS_SERIALIZE_WITH (line 34) | const VARIANT_HAS_SERIALIZE_WITH: &str = "serde:variant:has_serialize_wi...
constant VARIANT_HAS_DESERIALIZE_WITH (line 35) | const VARIANT_HAS_DESERIALIZE_WITH: &str = "serde:variant:has_deserializ...
constant VARIANT_HAS_WITH (line 36) | const VARIANT_HAS_WITH: &str = "serde:variant:has_with";
constant VARIANT_OTHER (line 37) | const VARIANT_OTHER: &str = "serde:variant:other";
constant VARIANT_UNTAGGED (line 38) | const VARIANT_UNTAGGED: &str = "serde:variant:untagged";
constant FIELD_RENAME_SERIALIZE (line 40) | const FIELD_RENAME_SERIALIZE: &str = "serde:field:rename_serialize";
constant FIELD_RENAME_DESERIALIZE (line 41) | const FIELD_RENAME_DESERIALIZE: &str = "serde:field:rename_deserialize";
constant FIELD_ALIASES (line 42) | const FIELD_ALIASES: &str = "serde:field:aliases";
constant FIELD_DEFAULT (line 43) | const FIELD_DEFAULT: &str = "serde:field:default";
constant FIELD_FLATTEN (line 44) | const FIELD_FLATTEN: &str = "serde:field:flatten";
constant FIELD_SKIP_SERIALIZING (line 45) | const FIELD_SKIP_SERIALIZING: &str = "serde:field:skip_serializing";
constant FIELD_SKIP_DESERIALIZING (line 46) | const FIELD_SKIP_DESERIALIZING: &str = "serde:field:skip_deserializing";
constant FIELD_SKIP_SERIALIZING_IF (line 47) | pub(crate) const FIELD_SKIP_SERIALIZING_IF: &str = "serde:field:skip_ser...
constant FIELD_HAS_SERIALIZE_WITH (line 48) | const FIELD_HAS_SERIALIZE_WITH: &str = "serde:field:has_serialize_with";
constant FIELD_HAS_DESERIALIZE_WITH (line 49) | const FIELD_HAS_DESERIALIZE_WITH: &str = "serde:field:has_deserialize_wi...
constant FIELD_HAS_WITH (line 50) | const FIELD_HAS_WITH: &str = "serde:field:has_with";
constant CONTAINER_ATTR_KEYS (line 52) | const CONTAINER_ATTR_KEYS: &[&str] = &[
constant VARIANT_ATTR_KEYS (line 74) | const VARIANT_ATTR_KEYS: &[&str] = &[
constant FIELD_ATTR_KEYS (line 89) | const FIELD_ATTR_KEYS: &[&str] = &[
type ConversionType (line 104) | pub struct ConversionType {
type SerdeContainerAttrs (line 109) | pub struct SerdeContainerAttrs {
method from_attributes (line 132) | pub fn from_attributes(attributes: &Attributes) -> Result<Option<Self>...
type SerdeVariantAttrs (line 177) | pub struct SerdeVariantAttrs {
method from_attributes (line 193) | pub fn from_attributes(attributes: &Attributes) -> Result<Option<Self>...
type SerdeFieldAttrs (line 222) | pub struct SerdeFieldAttrs {
method from_attributes (line 237) | pub fn from_attributes(attributes: &Attributes) -> Result<Option<Self>...
function get_string (line 258) | fn get_string(attributes: &Attributes, key: &str) -> Option<String> {
function get_strings (line 262) | fn get_strings(attributes: &Attributes, key: &str) -> Vec<String> {
function has_attr (line 269) | fn has_attr(attributes: &Attributes, key: &str) -> bool {
function get_datatype (line 273) | fn get_datatype(attributes: &Attributes, key: &str) -> Option<DataType> {
function get_rename_rule (line 277) | fn get_rename_rule(attributes: &Attributes, key: &str) -> Result<Option<...
function has_any_attr (line 286) | fn has_any_attr(attributes: &Attributes, keys: &[&str]) -> bool {
FILE: specta-serde/src/phased.rs
type Phased (line 28) | pub struct Phased<Serialize, Deserialize>(PhantomData<(Serialize, Deseri...
type PhasedTy (line 31) | pub(crate) struct PhasedTy {
function phased (line 37) | pub fn phased(serialize: DataType, deserialize: DataType) -> DataType {
method definition (line 49) | fn definition(types: &mut Types) -> DataType {
FILE: specta-serde/src/repr.rs
type EnumRepr (line 10) | pub enum EnumRepr {
method from_attrs (line 30) | pub(crate) fn from_attrs(attrs: &Attributes) -> Result<Self, Error> {
FILE: specta-serde/src/validate.rs
type ApplyMode (line 16) | pub enum ApplyMode {
function validate_for_mode (line 21) | pub fn validate_for_mode(types: &Types, mode: ApplyMode) -> Result<(), E...
function validate_datatype_for_mode (line 40) | pub(crate) fn validate_datatype_for_mode(
function validate_datatype_for_mode_shallow (line 55) | pub(crate) fn validate_datatype_for_mode_shallow(
function inner (line 70) | fn inner(
function validate_identifier_enum (line 367) | fn validate_identifier_enum(enm: &Enum, path: &str, mode: ApplyMode) -> ...
function validate_container_attributes (line 426) | fn validate_container_attributes(
function validate_variant_attributes (line 465) | fn validate_variant_attributes(
function validate_field_attributes (line 499) | fn validate_field_attributes(field: &Field, path: String, mode: ApplyMod...
function ensure_codec_override (line 541) | fn ensure_codec_override(
function has_type_override (line 556) | fn has_type_override(attributes: &specta::datatype::Attributes) -> bool {
function validate_enum (line 563) | fn validate_enum(enm: &Enum, types: &Types, path: String, mode: ApplyMod...
function validate_untagged_variants (line 588) | fn validate_untagged_variants(enm: &Enum, path: &str) -> Result<(), Erro...
function validate_other_variant (line 613) | fn validate_other_variant(
function validate_internally_tag_enum (line 663) | fn validate_internally_tag_enum(enm: &Enum, types: &Types, path: String)...
function validate_internally_tag_variant (line 671) | fn validate_internally_tag_variant(
function validate_internally_tag_enum_datatype (line 708) | fn validate_internally_tag_enum_datatype(
function named_reference_ty (line 752) | fn named_reference_ty<'a>(
FILE: specta-swift/examples/advanced_unions.rs
type ApiResult (line 13) | enum ApiResult<T, E> {
type Shape (line 37) | enum Shape {
type Point (line 64) | struct Point {
type Rectangle (line 70) | struct Rectangle {
type LineStyle (line 76) | struct LineStyle {
type Color (line 83) | struct Color {
type Container (line 92) | enum Container<T> {
type Tree (line 101) | enum Tree<T> {
type JobStatus (line 112) | enum JobStatus {
type MixedEnum (line 129) | enum MixedEnum {
type Event (line 144) | enum Event {
function main (line 165) | fn main() {
FILE: specta-swift/examples/basic_types.rs
type Primitives (line 13) | struct Primitives {
type Status (line 48) | enum Status {
type ApiResponse (line 64) | struct ApiResponse<T, E> {
type User (line 73) | struct User {
type UserProfile (line 84) | struct UserProfile {
type UserPreferences (line 93) | struct UserPreferences {
type UserMetadata (line 101) | struct UserMetadata {
function main (line 108) | fn main() {
FILE: specta-swift/examples/comments_example.rs
type ApiResponse (line 17) | enum ApiResponse<T> {
type User (line 69) | struct User {
function main (line 107) | fn main() {
FILE: specta-swift/examples/comprehensive_demo.rs
type Task (line 15) | struct Task {
type TaskStatus (line 33) | enum TaskStatus {
type Priority (line 69) | enum Priority {
type User (line 79) | struct User {
type UserProfile (line 93) | struct UserProfile {
type UserPreferences (line 104) | struct UserPreferences {
type Theme (line 113) | enum Theme {
type NotificationSettings (line 122) | struct NotificationSettings {
type NotificationFrequency (line 132) | enum NotificationFrequency {
type PrivacySettings (line 142) | struct PrivacySettings {
type Visibility (line 150) | enum Visibility {
type DataSharing (line 159) | struct DataSharing {
type DisplaySettings (line 168) | struct DisplaySettings {
type UserRole (line 178) | enum UserRole {
type AdminLevel (line 201) | enum AdminLevel {
type TaskMetadata (line 210) | struct TaskMetadata {
type Attachment (line 222) | struct Attachment {
type SubTask (line 233) | struct SubTask {
type SubTaskStatus (line 247) | enum SubTaskStatus {
type ReviewComment (line 256) | struct ReviewComment {
type ApiResponse (line 269) | struct ApiResponse<T, E> {
type ResponseStatus (line 278) | enum ResponseStatus {
type ResponseMetadata (line 291) | struct ResponseMetadata {
type PaginationInfo (line 301) | struct PaginationInfo {
type SystemHealth (line 312) | struct SystemHealth {
type HealthStatus (line 322) | enum HealthStatus {
type ServiceStatus (line 331) | struct ServiceStatus {
type SystemMetrics (line 341) | struct SystemMetrics {
function main (line 351) | fn main() {
FILE: specta-swift/examples/configuration_options.rs
type User (line 13) | struct User {
type ApiResponse (line 21) | enum ApiResponse<T> {
type GenericContainer (line 28) | struct GenericContainer<T, U> {
function main (line 34) | fn main() {
FILE: specta-swift/examples/simple_usage.rs
type User (line 8) | struct User {
type UserRole (line 16) | enum UserRole {
type ApiResult (line 24) | enum ApiResult<T> {
function main (line 30) | fn main() {
FILE: specta-swift/examples/special_types.rs
type IndexerMetrics (line 15) | struct IndexerMetrics {
type EventLog (line 32) | struct EventLog {
type TaskConfig (line 45) | struct TaskConfig {
type PerformanceMetrics (line 60) | struct PerformanceMetrics {
type ApiResponse (line 75) | struct ApiResponse {
type JobStatus (line 90) | enum JobStatus {
type SystemHealth (line 117) | struct SystemHealth {
function main (line 132) | fn main() {
FILE: specta-swift/examples/string_enums.rs
type HttpStatus (line 13) | enum HttpStatus {
type Environment (line 34) | enum Environment {
type ApiResult (line 47) | enum ApiResult {
type UserAction (line 60) | enum UserAction {
type JobState (line 82) | enum JobState {
type NotificationType (line 99) | enum NotificationType {
type Result (line 122) | enum Result<T, E> {
type EventType (line 131) | enum EventType {
type FileType (line 151) | enum FileType {
function main (line 166) | fn main() {
FILE: specta-swift/src/error.rs
type Error (line 7) | pub enum Error {
method format (line 43) | pub(crate) fn format(message: &'static str, source: specta::FormatErro...
FILE: specta-swift/src/primitives.rs
function string_literal_raw_value (line 13) | fn string_literal_raw_value(dt: &DataType) -> Option<&str> {
function enum_string_raw_value (line 41) | fn enum_string_raw_value(variant: &Variant) -> Option<&str> {
function resolved_string_enum (line 63) | fn resolved_string_enum(e: &Enum) -> Option<Vec<(&str, &str)>> {
function serde_variant_payload (line 72) | fn serde_variant_payload<'a>(variant_name: &str, variant: &'a Variant) -...
function self_named_struct_payload (line 88) | fn self_named_struct_payload<'a>(variant_name: &str, dt: &'a DataType) -...
function normalized_payload (line 108) | fn normalized_payload<'a>(variant_name: &str, payload: &'a DataType) -> ...
function is_unit_payload (line 118) | fn is_unit_payload(variant_name: &str, dt: &DataType) -> bool {
function enum_payload_to_swift_type (line 140) | fn enum_payload_to_swift_type(
function should_emit_variant_wrapper (line 161) | fn should_emit_variant_wrapper(variant_name: &str, variant: &Variant) ->...
function wrapper_variant_fields (line 186) | fn wrapper_variant_fields<'a>(variant_name: &str, variant: &'a Variant) ...
function is_unit_like_variant (line 198) | fn is_unit_like_variant(variant_name: &str, variant: &Variant) -> bool {
function export_type (line 218) | pub fn export_type(
function datatype_to_swift (line 383) | pub fn datatype_to_swift(
function apply_datatype_format (line 421) | fn apply_datatype_format(
function apply_datatype_format_children (line 465) | fn apply_datatype_format_children(
function map_fields (line 515) | fn map_fields(
function contains_generic_reference (line 541) | fn contains_generic_reference(dt: &DataType) -> bool {
function fields_contain_generic_reference (line 567) | fn fields_contain_generic_reference(fields: &Fields) -> bool {
function contains_recursive_reference (line 581) | fn contains_recursive_reference(dt: &DataType) -> bool {
function fields_contain_recursive_reference (line 609) | fn fields_contain_recursive_reference(fields: &Fields) -> bool {
function is_duration_struct (line 624) | pub fn is_duration_struct(s: &specta::datatype::Struct) -> bool {
function primitive_to_swift (line 642) | fn primitive_to_swift(primitive: &Primitive) -> Result<String, Error> {
function list_to_swift (line 701) | fn list_to_swift(
function map_to_swift (line 713) | fn map_to_swift(
function struct_to_swift (line 726) | fn struct_to_swift(
function enum_to_swift (line 810) | fn enum_to_swift(
function generate_enum_structs (line 915) | fn generate_enum_structs(
function to_pascal_case (line 979) | fn to_pascal_case(s: &str) -> String {
function tuple_to_swift (line 1004) | fn tuple_to_swift(
function reference_to_swift (line 1027) | fn reference_to_swift(
function generic_to_swift (line 1088) | fn generic_to_swift(
function generate_enum_codable_impl (line 1099) | fn generate_enum_codable_impl(
FILE: specta-swift/src/swift.rs
type Swift (line 15) | pub struct Swift {
method fmt (line 31) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method new (line 105) | pub fn new() -> Self {
method header (line 110) | pub fn header(mut self, header: impl Into<Cow<'static, str>>) -> Self {
method indent (line 116) | pub fn indent(mut self, style: IndentStyle) -> Self {
method naming (line 122) | pub fn naming(mut self, convention: NamingConvention) -> Self {
method generics (line 128) | pub fn generics(mut self, style: GenericStyle) -> Self {
method optionals (line 134) | pub fn optionals(mut self, style: OptionalStyle) -> Self {
method add_protocol (line 140) | pub fn add_protocol(mut self, protocol: impl Into<Cow<'static, str>>) ...
method export (line 146) | pub fn export(&self, types: &Types, format: impl Format) -> Result<Str...
method export_to (line 184) | pub fn export_to(
type IndentStyle (line 45) | pub enum IndentStyle {
method default (line 53) | fn default() -> Self {
type NamingConvention (line 60) | pub enum NamingConvention {
method convert (line 204) | pub fn convert(&self, name: &str) -> String {
method convert_to_camel_case (line 213) | pub fn convert_to_camel_case(&self, name: &str) -> String {
method convert_field (line 218) | pub fn convert_field(&self, name: &str) -> String {
method convert_enum_case (line 227) | pub fn convert_enum_case(&self, name: &str) -> String {
method to_camel_case (line 236) | fn to_camel_case(&self, name: &str) -> String {
method to_pascal_case (line 289) | fn to_pascal_case(&self, name: &str) -> String {
method to_snake_case (line 303) | fn to_snake_case(&self, name: &str) -> String {
type GenericStyle (line 72) | pub enum GenericStyle {
type OptionalStyle (line 82) | pub enum OptionalStyle {
method default (line 91) | fn default() -> Self {
function format_types (line 196) | fn format_types<'a>(types: &'a Types, format: &'a dyn Format) -> Result<...
function needs_duration_helper (line 320) | fn needs_duration_helper(types: &Types) -> bool {
function generate_duration_helper (line 351) | fn generate_duration_helper() -> String {
FILE: specta-swift/tests/advanced_unions.rs
type Point (line 7) | struct Point {
type Circle (line 13) | struct Circle {
type Rectangle (line 19) | struct Rectangle {
type Line (line 25) | struct Line {
type Shape (line 31) | enum Shape {
type ApiResponse (line 61) | enum ApiResponse<T> {
type DatabaseResult (line 90) | enum DatabaseResult<T, E> {
function test_complex_unions (line 120) | fn test_complex_unions() {
function test_union_with_generics (line 173) | fn test_union_with_generics() {
function test_union_naming_conventions (line 197) | fn test_union_naming_conventions() {
FILE: specta-swift/tests/basic.rs
type User (line 7) | struct User {
type Status (line 14) | enum Status {
function test_basic_export (line 22) | fn test_basic_export() {
FILE: specta-swift/tests/common_types.rs
type TestStruct (line 8) | struct TestStruct {
type TestEnum (line 19) | enum TestEnum {
function test_common_types (line 26) | fn test_common_types() {
function test_unsupported_types (line 45) | fn test_unsupported_types() {
FILE: specta-swift/tests/comprehensive.rs
type User (line 7) | struct User {
type UserMetadata (line 19) | struct UserMetadata {
type UserPreferences (line 26) | struct UserPreferences {
type UserRole (line 33) | enum UserRole {
type ApiResponse (line 42) | enum ApiResponse<T> {
type ApiResult (line 49) | struct ApiResult<T, E> {
function test_comprehensive_export (line 56) | fn test_comprehensive_export() {
function test_naming_conventions (line 113) | fn test_naming_conventions() {
function test_swift_configuration (line 127) | fn test_swift_configuration() {
FILE: specta-swift/tests/multiline_comments.rs
type SdPath (line 16) | enum SdPath {
type SimpleStruct (line 35) | struct SimpleStruct {
function test_multiline_comments (line 41) | fn test_multiline_comments() {
FILE: specta-swift/tests/string_enum_implementation.rs
type JobStatus (line 9) | pub enum JobStatus {
type Priority (line 20) | pub enum Priority {
type LogLevel (line 28) | pub enum LogLevel {
type UserRole (line 37) | pub enum UserRole {
type ApiStatus (line 46) | pub enum ApiStatus {
type DatabaseStatus (line 54) | pub enum DatabaseStatus {
type MixedEnum (line 63) | pub enum MixedEnum {
type RegularEnum (line 71) | pub enum RegularEnum {
function test_string_enum_snake_case (line 78) | fn test_string_enum_snake_case() {
function test_string_enum_uppercase (line 96) | fn test_string_enum_uppercase() {
function test_string_enum_camel_case (line 112) | fn test_string_enum_camel_case() {
function test_string_enum_pascal_case (line 129) | fn test_string_enum_pascal_case() {
function test_string_enum_kebab_case (line 146) | fn test_string_enum_kebab_case() {
function test_string_enum_screaming_kebab_case (line 162) | fn test_string_enum_screaming_kebab_case() {
function test_mixed_enum_not_string (line 178) | fn test_mixed_enum_not_string() {
function test_regular_enum_not_string (line 205) | fn test_regular_enum_not_string() {
function test_all_string_enums_together (line 220) | fn test_all_string_enums_together() {
FILE: specta-swift/tests/string_enum_test.rs
type JobStatus (line 10) | enum JobStatus {
type RegularEnum (line 19) | enum RegularEnum {
function test_string_enum_generation (line 26) | fn test_string_enum_generation() {
FILE: specta-swift/tests/struct_reuse_test.rs
type UserData (line 7) | struct UserData {
type ApiResponse (line 14) | enum ApiResponse {
type ApiRequest (line 21) | struct ApiRequest {
function test_struct_reuse_between_standalone_and_enum (line 27) | fn test_struct_reuse_between_standalone_and_enum() {
function test_struct_reuse_with_different_ordering (line 64) | fn test_struct_reuse_with_different_ordering() {
FILE: specta-swift/tests/struct_variants.rs
type Event (line 8) | pub enum Event {
type ApiResponse (line 25) | pub enum ApiResponse {
function test_struct_variants_generation (line 41) | fn test_struct_variants_generation() {
FILE: specta-swift/tests/unions.rs
type User (line 7) | struct User {
type Admin (line 14) | struct Admin {
type Guest (line 22) | struct Guest {
type UserType (line 28) | enum UserType {
type ApiResult (line 56) | enum ApiResult<T, E> {
type ComplexUnion (line 72) | enum ComplexUnion {
function test_enum_with_nested_structs (line 101) | fn test_enum_with_nested_structs() {
function test_swift_union_syntax (line 149) | fn test_swift_union_syntax() {
FILE: specta-swift/tests/uuid_simple.rs
type WithUuid (line 8) | struct WithUuid {
type WithChrono (line 14) | struct WithChrono {
function test_uuid_support (line 21) | fn test_uuid_support() {
function test_chrono_support (line 34) | fn test_chrono_support() {
FILE: specta-swift/tests/uuid_test.rs
type WithUuid (line 9) | struct WithUuid {
function test_uuid_support (line 15) | fn test_uuid_support() {
type WithChrono (line 28) | struct WithChrono {
function test_chrono_support (line 35) | fn test_chrono_support() {
FILE: specta-tags/src/lib.rs
type Tag (line 53) | pub enum Tag {
method fmt (line 67) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
type TransformPlan (line 82) | pub struct TransformPlan {
method analyze (line 88) | pub fn analyze(dt: &DataType, types: &Types) -> Self {
method map (line 103) | pub fn map<'a>(&self, t: &'a str) -> Cow<'a, str> {
type PlanNode (line 123) | enum PlanNode {
method is_identity (line 135) | fn is_identity(&self) -> bool {
type ObjectFieldPlan (line 148) | enum ObjectFieldPlan {
method is_identity (line 153) | fn is_identity(&self) -> bool {
type EnumVariantPlan (line 161) | struct EnumVariantPlan {
type EnumVariantMatcher (line 167) | enum EnumVariantMatcher {
type KnownNamedTag (line 174) | enum KnownNamedTag {
constant BUILTIN_MATCHERS (line 180) | const BUILTIN_MATCHERS: &[(&str, &str, KnownNamedTag)] = &[
type Analyzer (line 204) | struct Analyzer;
method analyze (line 207) | fn analyze(
method analyze_fields (line 334) | fn analyze_fields(
method resolve_named_tag (line 381) | fn resolve_named_tag(&self, module_path: &str, name: &str) -> Option<K...
method analyze_enum_variant (line 388) | fn analyze_enum_variant(
type Renderer (line 430) | struct Renderer {
method render (line 435) | fn render(&mut self, plan: &PlanNode, input: &str) -> String {
method render_object (line 475) | fn render_object(&mut self, fields: &[ObjectFieldPlan], input: &str) -...
method render_leaf (line 496) | fn render_leaf(&mut self, tag: &Tag, input: &str) -> String {
method render_enum (line 505) | fn render_enum(&mut self, variants: &[EnumVariantPlan], input: &str) -...
method next_ident (line 547) | fn next_ident(&mut self, prefix: &str) -> String {
function js_string (line 553) | fn js_string(value: &str) -> String {
function string_literal (line 557) | fn string_literal(ty: &DataType) -> Option<String> {
type Inner (line 578) | struct Inner {
type Root (line 586) | struct Root {
function map_renders_trusting_transforms (line 595) | fn map_renders_trusting_transforms() {
type TaggedEnum (line 623) | enum TaggedEnum {
type AdjacentEnum (line 629) | enum AdjacentEnum {
function map_renders_from_serde_applied_internal_enum_shape (line 634) | fn map_renders_from_serde_applied_internal_enum_shape() {
function map_renders_from_serde_applied_adjacent_enum_shape (line 655) | fn map_renders_from_serde_applied_adjacent_enum_shape() {
FILE: specta-typescript/bindings.ts
type MyOtherType (line 2) | type MyOtherType = {
type MyType (line 6) | type MyType = {
FILE: specta-typescript/src/branded.rs
type Branded (line 99) | pub struct Branded {
method new (line 106) | pub fn new(brand: impl Into<Cow<'static, str>>, ty: DataType) -> Self {
method brand (line 114) | pub fn brand(&self) -> &Cow<'static, str> {
method ty (line 119) | pub fn ty(&self) -> &DataType {
FILE: specta-typescript/src/error.rs
type Error (line 44) | pub struct Error {
method invalid_map_key (line 139) | pub(crate) fn invalid_map_key(
method framework (line 152) | pub fn framework(
method format (line 165) | pub(crate) fn format(
method bigint_forbidden (line 177) | pub(crate) fn bigint_forbidden(path: String) -> Self {
method invalid_name (line 183) | pub(crate) fn invalid_name(path: String, name: impl Into<Cow<'static, ...
method duplicate_type_name (line 192) | pub(crate) fn duplicate_type_name(
method read_dir (line 206) | pub(crate) fn read_dir(path: PathBuf, source: io::Error) -> Self {
method metadata (line 212) | pub(crate) fn metadata(path: PathBuf, source: io::Error) -> Self {
method remove_file (line 218) | pub(crate) fn remove_file(path: PathBuf, source: io::Error) -> Self {
method remove_dir (line 224) | pub(crate) fn remove_dir(path: PathBuf, source: io::Error) -> Self {
method unsupported_opaque_reference (line 230) | pub(crate) fn unsupported_opaque_reference(reference: OpaqueReference)...
method dangling_named_reference (line 236) | pub(crate) fn dangling_named_reference(reference: String) -> Self {
method infinite_recursive_inline_type (line 242) | pub(crate) fn infinite_recursive_inline_type(reference: String) -> Self {
method forbidden_name_legacy (line 248) | pub(crate) fn forbidden_name_legacy(path: ExportPath, name: &'static s...
method invalid_name_legacy (line 254) | pub(crate) fn invalid_name_legacy(path: ExportPath, name: String) -> S...
method unable_to_export (line 260) | pub(crate) fn unable_to_export(layout: Layout) -> Self {
method from (line 268) | fn from(error: io::Error) -> Self {
method from (line 276) | fn from(error: std::fmt::Error) -> Self {
method fmt (line 284) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 385) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method source (line 391) | fn source(&self) -> Option<&(dyn error::Error + 'static)> {
type FrameworkSource (line 48) | type FrameworkSource = Box<dyn error::Error + Send + Sync + 'static>;
constant BIGINT_DOCS_URL (line 49) | const BIGINT_DOCS_URL: &str =
type ErrorKind (line 53) | enum ErrorKind {
function format_location (line 407) | fn format_location(location: Location<'static>) -> String {
FILE: specta-typescript/src/exporter.rs
type Layout (line 20) | pub enum Layout {
method fmt (line 34) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type RuntimeFn (line 41) | struct RuntimeFn(Arc<dyn Fn(FrameworkExporter) -> Result<Cow<'static, st...
method fmt (line 44) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type BrandedTypeImpl (line 51) | pub struct BrandedTypeImpl(
method fmt (line 60) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Exporter (line 68) | pub struct Exporter {
method default (line 81) | pub(crate) fn default() -> Exporter {
method framework_prelude (line 95) | pub fn framework_prelude(mut self, prelude: impl Into<Cow<'static, str...
method framework_runtime (line 105) | pub fn framework_runtime(
method branded_type_impl (line 152) | pub fn branded_type_impl(
method header (line 166) | pub fn header(mut self, header: impl Into<Cow<'static, str>>) -> Self {
method layout (line 172) | pub fn layout(mut self, layout: Layout) -> Self {
method export (line 180) | pub fn export(&self, types: &Types, format: impl Format) -> Result<Str...
method export_to (line 234) | pub fn export_to(
method as_ref (line 720) | fn as_ref(&self) -> &Exporter {
method as_mut (line 726) | fn as_mut(&mut self) -> &mut Exporter {
function reference_module_path (line 480) | fn reference_module_path(types: &Types, r: &NamedReference) -> Result<Op...
function format_types (line 492) | fn format_types<'a>(types: &'a Types, format: &dyn Format) -> Result<Cow...
function map_datatype_format (line 504) | fn map_datatype_format(
function map_datatype_format_children (line 611) | fn map_datatype_format_children(
function named_reference_generics_mut (line 670) | fn named_reference_generics_mut(
function map_datatype_fields (line 679) | fn map_datatype_fields(
function map_named_datatype_format (line 705) | fn map_named_datatype_format(
type BrandedTypeExporter (line 732) | pub struct BrandedTypeExporter<'a> {
function fmt (line 740) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
function as_ref (line 746) | fn as_ref(&self) -> &Exporter {
type Target (line 752) | type Target = Exporter;
method deref (line 754) | fn deref(&self) -> &Self::Target {
function inline (line 761) | pub fn inline(&self, dt: &DataType) -> Result<String, Error> {
function reference (line 767) | pub fn reference(&self, r: &Reference) -> Result<String, Error> {
type FrameworkExporter (line 777) | pub struct FrameworkExporter<'a> {
function fmt (line 788) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
function as_ref (line 794) | fn as_ref(&self) -> &Exporter {
type Target (line 800) | type Target = Exporter;
method deref (line 802) | fn deref(&self) -> &Self::Target {
function render_types (line 812) | pub fn render_types(&mut self) -> Result<Cow<'static, str>, Error> {
function inline (line 826) | pub fn inline(&self, dt: &DataType) -> Result<String, Error> {
function reference (line 832) | pub fn reference(&self, r: &Reference) -> Result<String, Error> {
function export (line 841) | pub fn export<'a>(
type Module (line 853) | struct Module<'a> {
function build_module_graph (line 859) | fn build_module_graph(types: &Types) -> Module<'_> {
function render_file_header (line 895) | fn render_file_header(exporter: &Exporter) -> Result<String, Error> {
function render_types (line 909) | fn render_types(
function render_flat_types (line 1033) | fn render_flat_types<'a>(
function collect_existing_files (line 1061) | fn collect_existing_files(root: &Path) -> Result<HashSet<PathBuf>, Error> {
function is_generated_specta_file (line 1090) | fn is_generated_specta_file(path: &Path, exporter: &Exporter) -> Result<...
function remove_empty_dirs (line 1101) | fn remove_empty_dirs(path: &Path, root: &Path) -> Result<(), Error> {
function cleanup_stale_files (line 1137) | fn cleanup_stale_files(
function exported_type_name (line 1161) | fn exported_type_name(exporter: &Exporter, ndt: &NamedDataType) -> Cow<'...
function module_alias (line 1173) | pub(crate) fn module_alias(module_path: &str) -> String {
function module_import_statement (line 1181) | fn module_import_statement(
function module_import_block (line 1200) | fn module_import_block(
function module_import_path (line 1227) | fn module_import_path(from_module_path: &str, to_module_path: &str) -> S...
FILE: specta-typescript/src/jsdoc.rs
type JSDoc (line 10) | pub struct JSDoc(Exporter);
method from (line 27) | fn from(mut value: Exporter) -> Self {
method new (line 35) | pub fn new() -> Self {
method header (line 42) | pub fn header(self, header: impl Into<Cow<'static, str>>) -> Self {
method layout (line 47) | pub fn layout(self, layout: Layout) -> Self {
method branded_type_impl (line 54) | pub fn branded_type_impl(
method export (line 67) | pub fn export(&self, types: &Types, format: impl Format) -> Result<Str...
method export_to (line 76) | pub fn export_to(
method as_ref (line 87) | fn as_ref(&self) -> &Exporter {
method as_mut (line 93) | fn as_mut(&mut self) -> &mut Exporter {
method default (line 13) | fn default() -> Self {
method from (line 21) | fn from(value: JSDoc) -> Self {
FILE: specta-typescript/src/legacy.rs
type PathItem (line 20) | pub(crate) enum PathItem {
type ExportContext (line 28) | pub(crate) struct ExportContext<'a> {
function with (line 34) | pub(crate) fn with(&self, item: PathItem) -> Self {
function export_path (line 41) | pub(crate) fn export_path(&self) -> ExportPath {
type ExportPath (line 48) | pub struct ExportPath(String);
method new (line 51) | pub(crate) fn new(path: &[PathItem]) -> Self {
method fmt (line 85) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 91) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method eq (line 79) | fn eq(&self, other: &Self) -> bool {
type Result (line 97) | pub(crate) type Result<T> = std::result::Result<T, Error>;
type Output (line 99) | pub(crate) type Output = Result<String>;
function inner_comments (line 102) | fn inner_comments(
function datatype_inner (line 130) | pub(crate) fn datatype_inner(
function unnamed_fields_datatype (line 141) | fn unnamed_fields_datatype(
function tuple_datatype (line 210) | pub(crate) fn tuple_datatype(
function struct_datatype (line 231) | pub(crate) fn struct_datatype(
function enum_variant_datatype (line 369) | fn enum_variant_datatype(
type EnumVariantOutput (line 528) | struct EnumVariantOutput {
type DiscriminatorAnalysis (line 534) | struct DiscriminatorAnalysis {
type VariantTypeOverride (line 541) | struct VariantTypeOverride<'a> {
type DiscriminatorValue (line 547) | enum DiscriminatorValue {
function analyze_discriminator (line 552) | fn analyze_discriminator(
function variant_discriminator (line 597) | fn variant_discriminator(variant: &Variant) -> Option<(String, Discrimin...
function string_literal_datatype_value (line 613) | fn string_literal_datatype_value(ty: &DataType) -> Option<String> {
function exclude_known_literals_type (line 632) | fn exclude_known_literals_type(literals: &[String]) -> Option<String> {
function untagged_strict_keys (line 646) | fn untagged_strict_keys(variant: &Variant) -> Option<BTreeSet<String>> {
function has_anonymous_variant (line 665) | fn has_anonymous_variant(variants: &[&(Cow<'static, str>, Variant)]) -> ...
function strictify_enum_variants (line 669) | fn strictify_enum_variants(variants: &mut [EnumVariantOutput]) {
function enum_datatype (line 699) | pub(crate) fn enum_datatype(
function object_field_to_ts (line 788) | fn object_field_to_ts(
function inline_reference_docs (line 831) | fn inline_reference_docs<'a>(
function sanitise_key (line 854) | fn sanitise_key<'a>(field_name: Cow<'static, str>, force_string: bool) -...
function is_identifier (line 864) | pub(crate) fn is_identifier(name: &str) -> bool {
function escape_typescript_string_literal (line 874) | pub(crate) fn escape_typescript_string_literal(value: &str) -> Cow<'_, s...
function sanitise_type_name (line 901) | pub(crate) fn sanitise_type_name(ctx: ExportContext, ident: &str) -> Out...
constant STRING (line 929) | const STRING: &str = "string";
constant NULL (line 930) | const NULL: &str = "null";
constant NEVER (line 931) | const NEVER: &str = "never";
function js_doc (line 934) | pub(crate) fn js_doc(s: &mut String, docs: &str, deprecated: Option<&Dep...
function escape_jsdoc_text (line 978) | pub(crate) fn escape_jsdoc_text(text: &str) -> Cow<'_, str> {
function deprecated_details (line 986) | pub(crate) fn deprecated_details(typ: &Deprecated) -> Option<String> {
FILE: specta-typescript/src/map_keys.rs
function validate_map_key (line 10) | pub(crate) fn validate_map_key(
function validate_map_key_inner (line 18) | fn validate_map_key_inner(
function substitute_generics (line 178) | fn substitute_generics(dt: &mut DataType, generics: &[(Generic, DataType...
function substitute_field_generics (line 222) | fn substitute_field_generics(fields: &mut Fields, generics: &[(Generic, ...
function primitive_is_valid_key (line 242) | fn primitive_is_valid_key(primitive: Primitive) -> bool {
function invalid_primitive_reason (line 265) | fn invalid_primitive_reason(primitive: Primitive) -> &'static str {
FILE: specta-typescript/src/opaque.rs
type Define (line 6) | pub(crate) struct Define(pub(crate) Cow<'static, str>);
type Any (line 9) | pub(crate) struct Any;
type Unknown (line 12) | pub(crate) struct Unknown;
type Never (line 15) | pub(crate) struct Never;
type Number (line 18) | pub(crate) struct Number;
function define (line 23) | pub fn define(raw: impl Into<Cow<'static, str>>) -> Reference {
FILE: specta-typescript/src/primitives.rs
function export (line 40) | pub fn export<'a>(
function export_internal (line 51) | pub(crate) fn export_internal<'a>(
function export_single_internal (line 95) | fn export_single_internal(
function inline (line 173) | pub fn inline(
function typedef_internal (line 196) | pub(crate) fn typedef_internal(
function append_jsdoc_properties (line 211) | fn append_jsdoc_properties(
function push_jsdoc_property (line 328) | fn push_jsdoc_property(
function push_jsdoc_type (line 351) | fn push_jsdoc_type(s: &mut String, ty: &str, indent: &str) {
function jsdoc_property_name (line 373) | fn jsdoc_property_name(name: &str, optional: bool) -> String {
function append_typedef_body (line 383) | fn append_typedef_body(
function write_generic_parameters (line 444) | fn write_generic_parameters(
function jsdoc_description (line 484) | fn jsdoc_description(docs: &str, deprecated: Option<&Deprecated>) -> Opt...
function reference (line 515) | pub fn reference(
function datatype_with_inline_attr (line 535) | pub(crate) fn datatype_with_inline_attr(
function write_generic_reference (line 574) | fn write_generic_reference(s: &mut String, generic: &GenericReference) {
function scoped_reference_generics (line 578) | fn scoped_reference_generics(
function named_reference_generics (line 593) | fn named_reference_generics(r: &NamedReference) -> Result<&[(GenericRefe...
function named_reference_ty (line 601) | fn named_reference_ty<'a>(types: &'a Types, r: &'a NamedReference) -> Re...
function resolve_scoped_generic_default (line 615) | fn resolve_scoped_generic_default(
function resolved_reference_generics (line 628) | fn resolved_reference_generics(
function shallow_inline_datatype (line 666) | fn shallow_inline_datatype(
type DatatypeRenderer (line 874) | type DatatypeRenderer = fn(
function shallow_intersection_part_datatype (line 886) | fn shallow_intersection_part_datatype(
function intersection_dt (line 915) | fn intersection_dt(
function inline_datatype (line 949) | fn inline_datatype(
function datatype (line 1141) | pub(crate) fn datatype(
function primitive_dt (line 1228) | fn primitive_dt(p: &Primitive, location: Vec<Cow<'static, str>>) -> Resu...
function list_dt (line 1243) | fn list_dt(
function map_key_datatype (line 1328) | fn map_key_datatype(
function map_dt (line 1357) | fn map_dt(
function map_key_path (line 1430) | fn map_key_path(location: &[Cow<'static, str>]) -> String {
function map_key_render_type (line 1438) | fn map_key_render_type(dt: DataType) -> DataType {
function bool_key_literal_datatype (line 1446) | fn bool_key_literal_datatype() -> DataType {
function enum_dt (line 1457) | fn enum_dt(
function tuple_dt (line 1880) | fn tuple_dt(
function reference_dt (line 1920) | fn reference_dt(
function reference_opaque_dt (line 1944) | fn reference_opaque_dt(
function reference_named_dt (line 2000) | fn reference_named_dt(
FILE: specta-typescript/src/references.rs
function with_module_path (line 10) | pub(crate) fn with_module_path<R>(module_path: &str, func: impl FnOnce()...
function current_module_path (line 34) | pub(crate) fn current_module_path() -> Option<String> {
function collect_references (line 41) | pub fn collect_references<R>(func: impl FnOnce() -> R) -> (R, HashSet<Na...
function track_nr (line 87) | pub(crate) fn track_nr(r: &NamedReference) {
FILE: specta-typescript/src/reserved_names.rs
constant RESERVED_TYPE_NAMES (line 2) | pub(crate) const RESERVED_TYPE_NAMES: &[&str] = &[
FILE: specta-typescript/src/types.rs
type Any (line 46) | pub struct Any<T = ()>(T);
method definition (line 49) | fn definition(_: &mut Types) -> DataType {
method fmt (line 55) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
method clone (line 61) | fn clone(&self) -> Self {
method default (line 67) | fn default() -> Self {
function serialize (line 75) | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
function deserialize (line 86) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
type Unknown (line 124) | pub struct Unknown<T = ()>(T);
method definition (line 127) | fn definition(_: &mut Types) -> DataType {
method fmt (line 133) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
method clone (line 139) | fn clone(&self) -> Self {
method default (line 145) | fn default() -> Self {
function serialize (line 153) | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
function deserialize (line 164) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
type Never (line 202) | pub struct Never<T = ()>(T);
method definition (line 205) | fn definition(_: &mut Types) -> DataType {
method fmt (line 211) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
method clone (line 217) | fn clone(&self) -> Self {
method default (line 223) | fn default() -> Self {
function serialize (line 231) | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
function deserialize (line 242) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
type Number (line 283) | pub struct Number<T = ()>(T);
method definition (line 286) | fn definition(_: &mut Types) -> DataType {
method fmt (line 292) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
method clone (line 298) | fn clone(&self) -> Self {
method default (line 304) | fn default() -> Self {
function serialize (line 312) | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
function deserialize (line 323) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
FILE: specta-typescript/src/typescript.rs
type Typescript (line 10) | pub struct Typescript(Exporter);
method from (line 25) | fn from(mut value: Exporter) -> Self {
method new (line 33) | pub fn new() -> Self {
method header (line 40) | pub fn header(self, header: impl Into<Cow<'static, str>>) -> Self {
method layout (line 45) | pub fn layout(self, layout: Layout) -> Self {
method branded_type_impl (line 52) | pub fn branded_type_impl(
method export (line 65) | pub fn export(&self, types: &Types, format: impl Format) -> Result<Str...
method export_to (line 74) | pub fn export_to(
method as_ref (line 85) | fn as_ref(&self) -> &Exporter {
method as_mut (line 91) | fn as_mut(&mut self) -> &mut Exporter {
method default (line 13) | fn default() -> Self {
method from (line 19) | fn from(value: Typescript) -> Self {
FILE: specta-util/src/array.rs
type FixedArray (line 41) | pub struct FixedArray<const N: usize, T: Type>(PhantomData<[T; N]>);
method definition (line 44) | fn definition(types: &mut Types) -> DataType {
FILE: specta-util/src/remapper.rs
type Remapper (line 49) | pub struct Remapper {
method new (line 55) | pub fn new() -> Self {
method rule (line 62) | pub fn rule(mut self, from: DataType, to: DataType) -> Self {
method remap_dt (line 68) | pub fn remap_dt(&self, mut dt: DataType) -> DataType {
method remap_types (line 74) | pub fn remap_types(&self, types: Types) -> Types {
method remap_internal (line 88) | fn remap_internal(&self, dt: &mut DataType) {
method remap_rules (line 119) | fn remap_rules(&self, dt: &mut DataType) {
method remap_fields (line 127) | fn remap_fields(&self, fields: &mut Fields) {
method remap_reference (line 147) | fn remap_reference(&self, reference: &mut Reference) {
function remaps_multiple_rules_in_one_crawl (line 174) | fn remaps_multiple_rules_in_one_crawl() {
function rules_are_piped_in_registration_order (line 195) | fn rules_are_piped_in_registration_order() {
function replacement_is_recrawled (line 205) | fn replacement_is_recrawled() {
function remaps_named_type_bodies (line 218) | fn remaps_named_type_bodies() {
FILE: specta-zod/src/error.rs
type Error (line 9) | pub struct Error {
method framework (line 63) | pub fn framework(
method bigint_forbidden (line 75) | pub(crate) fn bigint_forbidden(path: String) -> Self {
method invalid_name (line 81) | pub(crate) fn invalid_name(path: String, name: impl Into<Cow<'static, ...
method forbidden_name (line 90) | pub(crate) fn forbidden_name(path: String, name: impl Into<Cow<'static...
method duplicate_type_name (line 99) | pub(crate) fn duplicate_type_name(
method read_dir (line 113) | pub(crate) fn read_dir(path: PathBuf, source: io::Error) -> Self {
method metadata (line 119) | pub(crate) fn metadata(path: PathBuf, source: io::Error) -> Self {
method remove_file (line 125) | pub(crate) fn remove_file(path: PathBuf, source: io::Error) -> Self {
method remove_dir (line 131) | pub(crate) fn remove_dir(path: PathBuf, source: io::Error) -> Self {
method unsupported_opaque_reference (line 137) | pub(crate) fn unsupported_opaque_reference(reference: OpaqueReference)...
method dangling_named_reference (line 143) | pub(crate) fn dangling_named_reference(reference: String) -> Self {
method unable_to_export (line 149) | pub(crate) fn unable_to_export(layout: Layout) -> Self {
method format (line 155) | pub(crate) fn format(
method from (line 169) | fn from(error: io::Error) -> Self {
method from (line 177) | fn from(source: std::fmt::Error) -> Self {
method fmt (line 188) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 261) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method source (line 267) | fn source(&self) -> Option<&(dyn error::Error + 'static)> {
type FrameworkSource (line 13) | type FrameworkSource = Box<dyn error::Error + Send + Sync + 'static>;
type ErrorKind (line 16) | enum ErrorKind {
function format_location (line 280) | fn format_location(location: Location<'static>) -> String {
FILE: specta-zod/src/opaque.rs
type Define (line 6) | pub(crate) struct Define(pub(crate) Cow<'static, str>);
type Any (line 9) | pub(crate) struct Any;
type Unknown (line 12) | pub(crate) struct Unknown;
type Never (line 15) | pub(crate) struct Never;
function define (line 20) | pub fn define(raw: impl Into<Cow<'static, str>>) -> Reference {
FILE: specta-zod/src/primitives.rs
type TypeRenderStack (line 17) | pub(crate) type TypeRenderStack = Vec<(Cow<'static, str>, Cow<'static, s...
function named_reference_generics (line 19) | fn named_reference_generics(r: &NamedReference) -> Result<&[(GenericRefe...
function named_reference_ty (line 29) | fn named_reference_ty<'a>(types: &'a Types, r: &'a NamedReference) -> Re...
function export (line 43) | pub fn export<'a>(
function export_internal (line 62) | pub(crate) fn export_internal<'a>(
function export_single_internal (line 80) | fn export_single_internal(
function inline (line 180) | pub fn inline(exporter: &dyn AsRef<Zod>, types: &Types, dt: &DataType) -...
function reference (line 200) | pub fn reference(exporter: &dyn AsRef<Zod>, types: &Types, r: &Reference...
function datatype_with_inline_attr (line 215) | pub(crate) fn datatype_with_inline_attr(
function datatype (line 237) | fn datatype(
function primitive_dt (line 344) | fn primitive_dt(
function list_dt (line 364) | fn list_dt(
function map_dt (line 401) | fn map_dt(
function tuple_dt (line 437) | fn tuple_dt(
function struct_dt (line 472) | fn struct_dt(
function enum_dt (line 572) | fn enum_dt(
function enum_variant_dt (line 617) | fn enum_variant_dt(
function reference_dt (line 753) | fn reference_dt(
function generic_dt (line 770) | fn generic_dt(s: &mut String, g: &GenericReference) {
function reference_opaque_dt (line 774) | fn reference_opaque_dt(s: &mut String, r: &OpaqueReference) -> Result<()...
function reference_named_dt (line 795) | fn reference_named_dt(
function exported_type_name (line 897) | fn exported_type_name(exporter: &Zod, ndt: &NamedDataType) -> Cow<'stati...
function validate_type_name (line 911) | fn validate_type_name(name: &str, path: String) -> Result<(), Error> {
function sanitise_key (line 931) | fn sanitise_key(field_name: &str) -> String {
function is_identifier (line 939) | fn is_identifier(name: &str) -> bool {
function escape_string (line 949) | fn escape_string(value: &str) -> Cow<'_, str> {
FILE: specta-zod/src/references.rs
function with_module_path (line 10) | pub(crate) fn with_module_path<R>(module_path: &str, func: impl FnOnce()...
function current_module_path (line 34) | pub(crate) fn current_module_path() -> Option<String> {
function collect_references (line 39) | pub fn collect_references<R>(func: impl FnOnce() -> R) -> (R, HashSet<Na...
function track_nr (line 79) | pub(crate) fn track_nr(r: &NamedReference) {
FILE: specta-zod/src/reserved_names.rs
constant RESERVED_TYPE_NAMES (line 1) | pub(crate) const RESERVED_TYPE_NAMES: &[&str] = &[
FILE: specta-zod/src/types.rs
type Any (line 11) | pub struct Any<T = ()>(T);
method definition (line 14) | fn definition(_: &mut Types) -> DataType {
method fmt (line 20) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
method clone (line 26) | fn clone(&self) -> Self {
method default (line 32) | fn default() -> Self {
function serialize (line 40) | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
type Unknown (line 49) | pub struct Unknown<T = ()>(T);
method definition (line 52) | fn definition(_: &mut Types) -> DataType {
method fmt (line 58) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
method clone (line 64) | fn clone(&self) -> Self {
method default (line 70) | fn default() -> Self {
function serialize (line 78) | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
type Never (line 87) | pub struct Never<T = ()>(T);
method definition (line 90) | fn definition(_: &mut Types) -> DataType {
method fmt (line 96) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
method clone (line 102) | fn clone(&self) -> Self {
method default (line 108) | fn default() -> Self {
function serialize (line 116) | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
FILE: specta-zod/src/zod.rs
type BigIntExportBehavior (line 19) | pub enum BigIntExportBehavior {
type Layout (line 33) | pub enum Layout {
method fmt (line 44) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type RuntimeFn (line 51) | struct RuntimeFn(
method fmt (line 56) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Zod (line 64) | pub struct Zod {
method new (line 83) | pub fn new() -> Self {
method framework_prelude (line 96) | pub fn framework_prelude(mut self, prelude: impl Into<Cow<'static, str...
method framework_runtime (line 102) | pub fn framework_runtime(
method header (line 114) | pub fn header(mut self, header: impl Into<Cow<'static, str>>) -> Self {
method bigint (line 120) | pub fn bigint(mut self, bigint: BigIntExportBehavior) -> Self {
method layout (line 126) | pub fn layout(mut self, layout: Layout) -> Self {
method export (line 132) | pub fn export(&self, types: &Types, format: impl Format) -> Result<Str...
method export_to (line 170) | pub fn export_to(
method as_ref (line 516) | fn as_ref(&self) -> &Zod {
method as_mut (line 522) | fn as_mut(&mut self) -> &mut Zod {
method default (line 76) | fn default() -> Self {
function format_types (line 394) | fn format_types<'a>(types: &'a Types, format: &dyn Format) -> Result<Cow...
function map_datatype_format (line 406) | fn map_datatype_format(
function map_datatype_format_children (line 425) | fn map_datatype_format_children(
function map_datatype_fields (line 475) | fn map_datatype_fields(
function map_named_datatype_format (line 501) | fn map_named_datatype_format(
type FrameworkExporter (line 528) | pub struct FrameworkExporter<'a> {
function fmt (line 538) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
function as_ref (line 544) | fn as_ref(&self) -> &Zod {
type Target (line 550) | type Target = Zod;
method deref (line 552) | fn deref(&self) -> &Self::Target {
function render_types (line 559) | pub fn render_types(&mut self) -> Result<Cow<'static, str>, Error> {
function inline (line 567) | pub fn inline(&self, dt: &DataType) -> Result<String, Error> {
function reference (line 573) | pub fn reference(&self, r: &Reference) -> Result<String, Error> {
function export (line 582) | pub fn export<'a>(
type Module (line 594) | struct Module<'a> {
function build_module_graph (line 600) | fn build_module_graph(types: &Types) -> Module<'_> {
function render_file_header (line 636) | fn render_file_header(exporter: &Zod) -> String {
function render_types (line 650) | fn render_types(
function render_flat_types (line 670) | fn render_flat_types<'a>(
function collect_existing_files (line 703) | fn collect_existing_files(root: &Path) -> Result<HashSet<PathBuf>, Error> {
function is_generated_specta_file (line 732) | fn is_generated_specta_file(path: &Path, exporter: &Zod) -> Result<bool,...
function remove_empty_dirs (line 742) | fn remove_empty_dirs(path: &Path, root: &Path) -> Result<(), Error> {
function cleanup_stale_files (line 777) | fn cleanup_stale_files(
function exported_type_name (line 801) | fn exported_type_name(exporter: &Zod, ndt: &NamedDataType) -> Cow<'stati...
function module_alias (line 815) | pub(crate) fn module_alias(module_path: &str) -> String {
function module_import_statement (line 823) | fn module_import_statement(from_module_path: &str, to_module_path: &str)...
function module_import_block (line 831) | fn module_import_block(from_module_path: &str, import_paths: &BTreeSet<S...
function module_import_path (line 839) | fn module_import_path(from_module_path: &str, to_module_path: &str) -> S...
FILE: specta/build.rs
function main (line 9) | fn main() {
FILE: specta/src/collect.rs
function collect (line 56) | pub fn collect() -> Types {
function register (line 74) | pub fn register<T: Type>() {
FILE: specta/src/datatype.rs
type DataType (line 36) | pub enum DataType {
FILE: specta/src/datatype/attributes.rs
type DynAttributeValue (line 10) | trait DynAttributeValue: Send + Sync {
method value_any (line 11) | fn value_any(&self) -> &dyn Any;
method eq_dyn (line 12) | fn eq_dyn(&self, other: &dyn DynAttributeValue) -> bool;
method hash_dyn (line 13) | fn hash_dyn(&self, state: &mut dyn Hasher);
method fmt_dyn (line 14) | fn fmt_dyn(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
method value_any (line 23) | fn value_any(&self) -> &dyn Any {
method eq_dyn (line 27) | fn eq_dyn(&self, other: &dyn DynAttributeValue) -> bool {
method hash_dyn (line 34) | fn hash_dyn(&self, state: &mut dyn Hasher) {
method fmt_dyn (line 40) | fn fmt_dyn(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type NamedAttributeValue (line 17) | struct NamedAttributeValue<T>(T);
type Attributes (line 57) | pub struct Attributes(HashMap<Cow<'static, str>, Arc<dyn DynAttributeVal...
method len (line 72) | pub fn len(&self) -> usize {
method is_empty (line 77) | pub fn is_empty(&self) -> bool {
method insert (line 87) | pub fn insert<T>(&mut self, key: impl Into<Cow<'static, str>>, value: T)
method extend (line 100) | pub fn extend(&mut self, other: Self) {
method remove (line 107) | pub fn remove(&mut self, key: &str) -> bool {
method contains_key (line 112) | pub fn contains_key(&self, key: &str) -> bool {
method get_named (line 121) | pub fn get_named(&self, key: &str) -> Option<&dyn Any> {
method get_named_as (line 130) | pub fn get_named_as<T: Any + 'static>(&self, key: &str) -> Option<&T> {
method fmt (line 172) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method clone (line 60) | fn clone(&self) -> Self {
method eq (line 138) | fn eq(&self, other: &Self) -> bool {
method hash (line 152) | fn hash<H: Hasher>(&self, state: &mut H) {
FILE: specta/src/datatype/enum.rs
type Enum (line 17) | pub struct Enum {
method from (line 25) | fn from(t: Enum) -> Self {
type Variant (line 33) | pub struct Variant {
method unit (line 52) | pub fn unit() -> Self {
method named (line 63) | pub fn named() -> VariantBuilder<NamedFields> {
method unnamed (line 79) | pub fn unnamed() -> VariantBuilder<UnnamedFields> {
method from (line 176) | fn from(val: VariantBuilder<NamedFields>) -> Self {
type VariantBuilder (line 99) | pub struct VariantBuilder<V = ()> {
function skip (line 106) | pub fn skip(mut self) -> Self {
function docs (line 112) | pub fn docs(mut self, docs: Cow<'static, str>) -> Self {
function deprecated (line 118) | pub fn deprecated(mut self, reason: Deprecated) -> Self {
function attributes (line 124) | pub fn attributes(mut self, attributes: Attributes) -> Self {
function attributes_mut (line 130) | pub fn attributes_mut(&mut self, attributes: Attributes) {
function field (line 137) | pub fn field(mut self, field: Field) -> Self {
function field_mut (line 143) | pub fn field_mut(mut self, field: Field) -> Self {
function build (line 149) | pub fn build(mut self) -> Variant {
function field (line 157) | pub fn field(mut self, name: impl Into<Cow<'static, str>>, field: Field)...
function field_mut (line 163) | pub fn field_mut(mut self, name: impl Into<Cow<'static, str>>, field: Fi...
function build (line 169) | pub fn build(mut self) -> Variant {
FILE: specta/src/datatype/fields.rs
type Fields (line 10) | pub enum Fields {
type Field (line 28) | pub struct Field {
method new (line 55) | pub fn new(ty: DataType) -> Self {
type UnnamedFields (line 69) | pub struct UnnamedFields {
type NamedFields (line 77) | pub struct NamedFields {
type StructBuilder (line 87) | pub struct StructBuilder<F = ()> {
function field (line 93) | pub fn field(mut self, name: impl Into<Cow<'static, str>>, field: Field)...
function field_mut (line 99) | pub fn field_mut(&mut self, name: impl Into<Cow<'static, str>>, field: F...
function build (line 104) | pub fn build(self) -> DataType {
function field (line 114) | pub fn field(mut self, field: Field) -> Self {
function field_mut (line 120) | pub fn field_mut(&mut self, field: Field) {
function build (line 125) | pub fn build(self) -> DataType {
FILE: specta/src/datatype/function.rs
type Function (line 14) | pub struct Function {
method asyncness (line 31) | pub fn asyncness(&self) -> bool {
method name (line 36) | pub fn name(&self) -> &str {
method args (line 41) | pub fn args(&self) -> &[(Cow<'static, str>, DataType)] {
method result (line 46) | pub fn result(&self) -> Option<&DataType> {
FILE: specta/src/datatype/generic.rs
type Generic (line 16) | pub struct Generic(Cow<'static, str>);
method new (line 22) | pub const fn new(name: Cow<'static, str>) -> Self {
method name (line 27) | pub fn name(&self) -> &Cow<'static, str> {
method reference (line 32) | pub fn reference(&self) -> Self {
method from (line 38) | fn from(v: Generic) -> Self {
type GenericDefinition (line 47) | pub struct GenericDefinition {
method new (line 56) | pub const fn new(name: Cow<'static, str>, default: Option<DataType>) -...
method reference (line 61) | pub fn reference(&self) -> Generic {
FILE: specta/src/datatype/list.rs
type List (line 7) | pub struct List {
method new (line 20) | pub fn new(ty: DataType) -> Self {
method from (line 30) | fn from(t: List) -> Self {
FILE: specta/src/datatype/literal.rs
type Literal (line 22) | pub struct Literal(Arc<dyn LiteralType>);
method new (line 30) | pub fn new<T: LiteralType>(value: T) -> DataType {
method definition (line 35) | pub fn definition(&self, types: &mut Types) -> DataType {
method downcast_ref (line 40) | pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
method from (line 62) | fn from(value: T) -> Self {
method fmt (line 68) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method hash (line 82) | fn hash<H: hash::Hasher>(&self, state: &mut H) {
type LiteralType (line 48) | pub trait LiteralType: Any + Send + Sync + 'static {
method definition (line 50) | fn definition(&self, types: &mut Types) -> DataType;
method eq_dyn (line 52) | fn eq_dyn(&self, other: &dyn LiteralType) -> bool;
method hash_dyn (line 54) | fn hash_dyn(&self, state: &mut dyn hash::Hasher);
method fmt_dyn (line 56) | fn fmt_dyn(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
method as_any (line 58) | fn as_any(&self) -> &dyn Any;
method eq (line 74) | fn eq(&self, other: &Self) -> bool {
type FloatKey (line 136) | enum FloatKey<Bits> {
type FloatLiteral (line 144) | trait FloatLiteral: Copy + PartialEq + Type + fmt::Debug + Send + Sync +...
constant INFINITY (line 147) | const INFINITY: Self;
constant NEG_INFINITY (line 148) | const NEG_INFINITY: Self;
constant NEG_ZERO_BITS (line 149) | const NEG_ZERO_BITS: Self::Bits;
method is_nan (line 151) | fn is_nan(self) -> bool;
method is_negative_zero (line 152) | fn is_negative_zero(self) -> bool;
method to_bits (line 153) | fn to_bits(self) -> Self::Bits;
function from (line 157) | fn from(value: T) -> Self {
FILE: specta/src/datatype/map.rs
type Map (line 8) | pub struct Map(Box<(DataType, DataType)>);
method new (line 12) | pub fn new(key_ty: DataType, value_ty: DataType) -> Self {
method key_ty (line 17) | pub fn key_ty(&self) -> &DataType {
method key_ty_mut (line 22) | pub fn key_ty_mut(&mut self) -> &mut DataType {
method set_key_ty (line 27) | pub fn set_key_ty(&mut self, key_ty: DataType) {
method value_ty (line 32) | pub fn value_ty(&self) -> &DataType {
method value_ty_mut (line 37) | pub fn value_ty_mut(&mut self) -> &mut DataType {
method set_value_ty (line 42) | pub fn set_value_ty(&mut self, value_ty: DataType) {
method from (line 48) | fn from(t: Map) -> Self {
FILE: specta/src/datatype/named.rs
function inline (line 20) | pub fn inline<R>(types: &mut Types, func: impl FnOnce(&mut Types) -> R) ...
type NamedDataType (line 42) | pub struct NamedDataType {
method new (line 67) | pub fn new(
method init_with_sentinel (line 130) | pub fn init_with_sentinel(
method reference (line 267) | pub fn reference(&self, generics: Vec<(Generic, DataType)>) -> Referen...
type Deprecated (line 278) | pub struct Deprecated {
method new (line 289) | pub const fn new() -> Self {
method with_note (line 299) | pub fn with_note(note: Cow<'static, str>) -> Self {
method with_since_note (line 309) | pub fn with_since_note(since: Option<Cow<'static, str>>, note: Cow<'st...
function file_path_to_module_path (line 317) | fn file_path_to_module_path(file_path: &str) -> Option<String> {
function file_path_to_module_path_supports_unix_and_windows_separators (line 345) | fn file_path_to_module_path_supports_unix_and_windows_separators() {
FILE: specta/src/datatype/primitive.rs
type Primitive (line 6) | pub enum Primitive {
method from (line 48) | fn from(t: Primitive) -> Self {
FILE: specta/src/datatype/reference.rs
type Reference (line 13) | pub enum Reference {
method opaque (line 147) | pub fn opaque<T: hash::Hash + Eq + Send + Sync + 'static>(state: T) ->...
method ty_eq (line 155) | pub fn ty_eq(&self, other: &Reference) -> bool {
type NamedReference (line 26) | pub struct NamedReference {
type NamedReferenceType (line 34) | pub enum NamedReferenceType {
type OpaqueReference (line 70) | pub struct OpaqueReference(Arc<dyn DynOpaqueReference>);
method fmt (line 100) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method hash (line 116) | fn hash<H: hash::Hasher>(&self, state: &mut H) {
method type_name (line 123) | pub fn type_name(&self) -> &'static str {
method type_id (line 128) | pub fn type_id(&self) -> TypeId {
method downcast_ref (line 133) | pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
type DynOpaqueReference (line 72) | trait DynOpaqueReference: Any + Send + Sync {
method type_name (line 73) | fn type_name(&self) -> &'static str;
method hash (line 74) | fn hash(&self, hasher: &mut dyn hash::Hasher);
method eq (line 75) | fn eq(&self, other: &dyn Any) -> bool;
method as_any (line 76) | fn as_any(&self) -> &dyn Any;
method type_name (line 82) | fn type_name(&self) -> &'static str {
method hash (line 85) | fn hash(&self, mut hasher: &mut dyn hash::Hasher) {
method eq (line 88) | fn eq(&self, other: &dyn Any) -> bool {
method as_any (line 94) | fn as_any(&self) -> &dyn Any {
type OpaqueReferenceInner (line 80) | struct OpaqueReferenceInner<T>(T);
method eq (line 108) | fn eq(&self, other: &Self) -> bool {
method from (line 165) | fn from(r: Reference) -> Self {
type NamedId (line 175) | pub(crate) enum NamedId {
method hash (line 193) | fn hash<H: hash::Hasher>(&self, state: &mut H) {
method fmt (line 202) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method eq (line 182) | fn eq(&self, other: &Self) -> bool {
FILE: specta/src/datatype/struct.rs
type Struct (line 10) | pub struct Struct {
method unit (line 21) | pub fn unit() -> Self {
method named (line 29) | pub fn named() -> StructBuilder<NamedFields> {
method unnamed (line 38) | pub fn unnamed() -> StructBuilder<UnnamedFields> {
method from (line 48) | fn from(t: Struct) -> Self {
FILE: specta/src/datatype/tuple.rs
type Tuple (line 9) | pub struct Tuple {
method new (line 16) | pub fn new(elements: Vec<DataType>) -> Self {
method from (line 22) | fn from(t: Tuple) -> Self {
FILE: specta/src/format.rs
type FormatError (line 6) | pub type FormatError = Box<dyn error::Error + Send + Sync + 'static>;
type Format (line 15) | pub trait Format {
method map_types (line 20) | fn map_types(&'_ self, types: &Types) -> std::result::Result<Cow<'_, T...
method map_type (line 26) | fn map_type(
method map_types (line 34) | fn map_types(&'_ self, types: &Types) -> std::result::Result<Cow<'_, T...
method map_type (line 38) | fn map_type(
method map_types (line 48) | fn map_types(&'_ self, types: &Types) -> std::result::Result<Cow<'_, T...
method map_type (line 52) | fn map_type(
constant _ (line 62) | const _: Option<&dyn Format> = None;
FILE: specta/src/function/arg.rs
type FunctionArg (line 5) | pub trait FunctionArg {
method to_datatype (line 10) | fn to_datatype(types: &mut Types) -> Option<DataType>;
method to_datatype (line 14) | fn to_datatype(types: &mut Types) -> Option<DataType> {
FILE: specta/src/function/result.rs
type FunctionResult (line 7) | pub trait FunctionResult<TMarker> {
method to_datatype (line 9) | fn to_datatype(types: &mut Types) -> DataType;
type FunctionValueMarker (line 13) | pub enum FunctionValueMarker {}
method to_datatype (line 15) | fn to_datatype(types: &mut Types) -> DataType {
type FunctionFutureMarker (line 21) | pub enum FunctionFutureMarker {}
method to_datatype (line 27) | fn to_datatype(types: &mut Types) -> DataType {
FILE: specta/src/function/specta_fn.rs
type SpectaFn (line 13) | pub trait SpectaFn<TMarker> {
method to_datatype (line 15) | fn to_datatype(
function to_datatype (line 30) | fn to_datatype(
FILE: specta/src/internal.rs
function get_fn_datatype (line 19) | pub fn get_fn_datatype<TMarker, T: SpectaFn<TMarker>>(
FILE: specta/src/lib.rs
type TypeMap (line 54) | pub type TypeMap = Types;
FILE: specta/src/type.rs
type Type (line 30) | pub trait Type {
method definition (line 35) | fn definition(types: &mut Types) -> DataType;
FILE: specta/src/type/impls.rs
method definition (line 20) | fn definition(_: &mut Types) -> DataType {
method definition (line 28) | fn definition(_: &mut Types) -> DataType {
type PrimitiveSet (line 37) | pub(crate) struct PrimitiveSet<T>(PhantomData<T>);
method definition (line 39) | fn definition(types: &mut Types) -> DataType {
type PrimitiveMap (line 47) | pub(crate) struct PrimitiveMap<K, V>(PhantomData<K>, PhantomData<V>);
method definition (line 49) | fn definition(types: &mut Types) -> DataType {
constant _ (line 59) | const _: () = {
method definition (line 208) | fn definition(types: &mut Types) -> DataType {
method definition (line 214) | fn definition(types: &mut Types) -> DataType {
method definition (line 222) | fn definition(types: &mut Types) -> DataType {
method definition (line 236) | fn definition(types: &mut Types) -> DataType {
FILE: specta/src/type/legacy_impls.rs
type String (line 8) | pub struct String;
method definition (line 10) | fn definition(types: &mut Types) -> DataType {
constant _ (line 17) | const _: () = {
constant _ (line 33) | const _: () = {
constant _ (line 85) | const _: () = {
constant _ (line 168) | const _: () = {
constant _ (line 267) | const _: () = {
constant _ (line 358) | const _: () = {
constant _ (line 424) | const _: () = {
constant _ (line 705) | const _: () = {
constant _ (line 841) | const _: () = {
constant _ (line 879) | const _: () = {
constant _ (line 908) | const _: () = {
constant _ (line 958) | const _: () = {
constant _ (line 1498) | const _: () = {
FILE: specta/src/types.rs
type Types (line 23) | pub struct Types {
method fmt (line 114) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method register (line 124) | pub fn register<T: Type>(mut self) -> Self {
method register_mut (line 130) | pub fn register_mut<T: Type>(&mut self) -> &mut Self {
method get (line 139) | pub fn get(&self, r: &NamedReference) -> Option<&NamedDataType> {
method len (line 144) | pub fn len(&self) -> usize {
method is_empty (line 158) | pub fn is_empty(&self) -> bool {
method extend (line 175) | pub fn extend(&mut self, other: &Self) {
method into_sorted_iter (line 205) | pub fn into_sorted_iter(&self) -> impl ExactSizeIterator<Item = &'_ Na...
method into_unsorted_iter (line 222) | pub fn into_unsorted_iter(&self) -> impl ExactSizeIterator<Item = &Nam...
method iter_mut (line 230) | pub fn iter_mut<F>(&mut self, mut f: F)
method map (line 242) | pub fn map<F>(mut self, mut f: F) -> Self
type UnsortedIter (line 255) | struct UnsortedIter<'a> {
type Item (line 261) | type Item = &'a NamedDataType;
method next (line 263) | fn next(&mut self) -> Option<Self::Item> {
method size_hint (line 267) | fn size_hint(&self) -> (usize, Option<usize>) {
FILE: tests/tests/bound.rs
type CustomBound (line 6) | struct CustomBound<T> {
type MultiBound (line 12) | struct MultiBound<T, U> {
type ComplexBound (line 19) | struct ComplexBound<T> {
type ExistingWhere (line 25) | struct ExistingWhere<T>
type EnumWithBound (line 34) | enum EnumWithBound<T> {
type LifetimeBound (line 41) | struct LifetimeBound<T> {
type RequiresClone (line 47) | struct RequiresClone<T> {
function custom_bound (line 52) | fn custom_bound() {
function multi_bound (line 63) | fn multi_bound() {
function complex_bound (line 75) | fn complex_bound() {
function existing_where (line 84) | fn existing_where() {
function enum_bound (line 93) | fn enum_bound() {
function lifetime_bound (line 102) | fn lifetime_bound() {
function requires_clone_bound (line 111) | fn requires_clone_bound() {
function associated_type_bound_issue_138 (line 122) | fn associated_type_bound_issue_138() {
FILE: tests/tests/errors.rs
type MyError (line 10) | pub enum MyError {
FILE: tests/tests/functions.rs
function render_datatype (line 11) | fn render_datatype(ts: &Typescript, types: &Types, dt: &DataType) -> Str...
function a (line 25) | fn a() {}
function b (line 28) | fn b(demo: String) {}
function c (line 31) | fn c(a: String, b: i32, c: bool) {}
function d (line 34) | fn d(demo: String) -> i32 {
function e (line 39) | fn e<T: fmt::Debug>(window: T) {}
function f (line 43) | fn f(mut demo: String) -> i32 {
function g (line 48) | fn g(x: std::string::String) {}
function h (line 57) | fn h(demo: special_string!()) {}
function i (line 60) | fn i() -> Result<i32, f32> {
function k (line 65) | fn k() -> Result<String, f32> {
type Demo (line 71) | pub struct Demo {
function l (line 76) | fn l(Demo { demo }: Demo, (a, b): (String, u32)) {}
function m (line 85) | fn m(special_destructure!(): Demo) {}
function async_fn (line 88) | async fn async_fn() {}
function with_docs (line 92) | fn with_docs() {}
function public_function (line 95) | pub fn public_function() {}
function nested (line 101) | pub fn nested() {}
function raw (line 105) | fn raw(r#type: i32) {}
function rename_all_fn (line 110) | fn rename_all_fn(myArg: i32, anotherValue: String) {}
function renamed_fn (line 114) | fn renamed_fn(myArg: i32) {}
function test_trailing_comma (line 119) | fn test_trailing_comma() {
function test_function_exporting (line 129) | fn test_function_exporting() {
FILE: tests/tests/jsdoc.rs
type Three (line 23) | pub struct Three {
type Two (line 33) | pub struct Two {
type One (line 43) | pub struct One {
function export_to (line 51) | fn export_to() {
function primitives_export (line 89) | fn primitives_export() {
function primitives_export_many (line 119) | fn primitives_export_many() {
function primitives_reference (line 148) | fn primitives_reference() {
function primitives_inline (line 176) | fn primitives_inline() {
function jsdoc_export_bigint_errors (line 196) | fn jsdoc_export_bigint_errors() {
function jsdoc_export_to_files_uses_jsdoc_import_typedefs (line 371) | fn jsdoc_export_to_files_uses_jsdoc_import_typedefs() {
FILE: tests/tests/layouts.rs
type Testing (line 11) | struct Testing {
type Another (line 16) | struct Another {
type MoreType (line 21) | struct MoreType {
type Testing (line 29) | pub struct Testing {
type Testing (line 37) | pub struct Testing {
function duplicate_typenames_layouts (line 44) | fn duplicate_typenames_layouts() {
function non_duplicate_typenames_layouts (line 92) | fn non_duplicate_typenames_layouts() {
function empty_module_path_layouts (line 138) | fn empty_module_path_layouts() {
function temp_dir (line 174) | fn temp_dir() -> TempDir {
function assert_error_contains (line 180) | fn assert_error_contains<T>(result: Result<T, specta_typescript::Error>,...
FILE: tests/tests/legacy_impls.rs
type ErrorStackRootError (line 7) | struct ErrorStackRootError;
method fmt (line 10) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
type LegacyImpls (line 18) | struct LegacyImpls {
type LegacyImplWithBigints (line 85) | struct LegacyImplWithBigints {
function legacy_impls (line 111) | fn legacy_impls() {
function legacy_impl_bigint_errors (line 124) | fn legacy_impl_bigint_errors() {
function legacy_impl_individual_bigint_errors (line 143) | fn legacy_impl_individual_bigint_errors() {
FILE: tests/tests/macro/compile_error.rs
type Demo2 (line 9) | pub enum Demo2 {}
type Error (line 14) | pub struct Error {
type UnitExternal (line 23) | enum UnitExternal {
type UnnamedMultiExternal (line 29) | enum UnnamedMultiExternal {
type FlattenExternal (line 35) | struct FlattenExternal {
type UnnamedUntagged (line 45) | enum UnnamedUntagged {
type UnnamedMultiUntagged (line 52) | enum UnnamedMultiUntagged {
type FlattenUntagged (line 58) | struct FlattenUntagged {
type UnnamedInternal (line 70) | enum UnnamedInternal {
type FlattenInternal (line 78) | struct FlattenInternal {
type InvalidAttrs1 (line 87) | struct InvalidAttrs1;
type InvalidAttrs2 (line 92) | struct InvalidAttrs2;
type InvalidAttrs3 (line 96) | struct InvalidAttrs3 {
type InvalidAttrs4 (line 103) | struct InvalidAttrs4 {
type LegacyContainerRename (line 112) | struct LegacyContainerRename;
type LegacyFieldRename (line 116) | struct LegacyFieldRename {
type LegacyVariantRename (line 123) | enum LegacyVariantRename {
constant INTERNAL_RENAME_KEY (line 128) | const INTERNAL_RENAME_KEY: &str = "renamed";
type InternalRenameFromPath (line 132) | struct InternalRenameFromPath {
type TransparentEnum (line 140) | pub enum TransparentEnum {}
type TransparentTypeOverrideConflict (line 144) | pub struct TransparentTypeOverrideConflict(String);
type InvalidSpectaAttribute1 (line 149) | pub struct InvalidSpectaAttribute1;
type InvalidSpectaAttribute2 (line 154) | pub struct InvalidSpectaAttribute2;
function testing (line 160) | pub fn testing() {}
function invalid_function_rename_all (line 163) | pub fn invalid_function_rename_all() {}
FILE: tests/tests/mod.rs
function compile_errors (line 35) | fn compile_errors() {
FILE: tests/tests/references.rs
type GenericType (line 10) | struct GenericType<T>(T);
type AnotherOne (line 14) | struct AnotherOne;
function references (line 17) | fn references() {
FILE: tests/tests/serde_conversions.rs
type Wire (line 7) | struct Wire {
method from (line 169) | fn from(value: IntoOnly) -> Self {
method from (line 175) | fn from(value: Symmetric) -> Self {
type IntoOnly (line 14) | struct IntoOnly {
type Symmetric (line 21) | struct Symmetric {
method from (line 181) | fn from(value: Wire) -> Self {
type GenericWire (line 27) | struct GenericWire<T> {
type GenericTryFrom (line 34) | struct GenericTryFrom<T> {
type GenericParent (line 40) | struct GenericParent<T> {
type Parent (line 46) | struct Parent {
type CustomCodecNoOverride (line 52) | struct CustomCodecNoOverride {
type CustomCodecWithOverride (line 59) | struct CustomCodecWithOverride {
type CustomCodecWithPhasedOverride (line 67) | struct CustomCodecWithPhasedOverride {
type FieldOnlyPhasedOverride (line 75) | struct FieldOnlyPhasedOverride {
type SkipSerializingIfOnly (line 82) | struct SkipSerializingIfOnly {
type FieldPhaseSpecificRename (line 89) | struct FieldPhaseSpecificRename {
type VariantCodecNoOverride (line 96) | enum VariantCodecNoOverride {
type VariantCodecWithOverride (line 106) | enum VariantCodecWithOverride {
type VariantIdentifierValid (line 118) | enum VariantIdentifierValid {
type FieldIdentifierValid (line 126) | enum FieldIdentifierValid {
function serialize (line 135) | pub fn serialize<S>(_value: &str, serializer: S) -> Result<S::Ok, S::Error>
function deserialize (line 142) | pub fn deserialize<'de, D>(deserializer: D) -> Result<String, D::Error>
function serialize (line 153) | pub fn serialize<S>(value: &str, serializer: S) -> Result<S::Ok, S::Error>
function deserialize (line 160) | pub fn deserialize<'de, D>(deserializer: D) -> Result<String, D::Error>
type Error (line 187) | type Error = std::convert::Infallible;
function try_from (line 189) | fn try_from(value: GenericWire<T>) -> Result<Self, Self::Error> {
function apply_rejects_asymmetric_container_conversion (line 197) | fn apply_rejects_asymmetric_container_conversion() {
function phases_format_splits_container_and_dependents_for_conversions (line 213) | fn phases_format_splits_container_and_dependents_for_conversions() {
function apply_accepts_symmetric_container_conversion (line 228) | fn apply_accepts_symmetric_container_conversion() {
function phases_format_accepts_generic_try_from_container_conversion (line 238) | fn phases_format_accepts_generic_try_from_container_conversion() {
function custom_codec_requires_explicit_override (line 259) | fn custom_codec_requires_explicit_override() {
function custom_codec_variant_requires_explicit_override (line 278) | fn custom_codec_variant_requires_explicit_override() {
function phased_override_requires_phases_format (line 296) | fn phased_override_requires_phases_format() {
function field_only_phased_override_requires_phases_format (line 314) | fn field_only_phased_override_requires_phases_format() {
function phases_format_exports_field_only_phased_override (line 332) | fn phases_format_exports_field_only_phased_override() {
function skip_serializing_if_requires_phases (line 347) | fn skip_serializing_if_requires_phases() {
function field_phase_specific_rename_requires_phases (line 365) | fn field_phase_specific_rename_requires_phases() {
function identifier_enums_require_phases (line 383) | fn identifier_enums_require_phases() {
FILE: tests/tests/serde_identifiers.rs
type VariantIdentifier (line 8) | enum VariantIdentifier {
type FieldIdentifier (line 17) | enum FieldIdentifier {
function identifier_apply_requires_phases (line 24) | fn identifier_apply_requires_phases() {
function identifier_phases_format_exports_deserialize_union (line 49) | fn identifier_phases_format_exports_deserialize_union() {
FILE: tests/tests/serde_other.rs
type InternalOther (line 10) | enum InternalOther {
type AdjacentOther (line 20) | enum AdjacentOther {
function serde_other_requires_phases_format (line 28) | fn serde_other_requires_phases_format() {
function serde_other_internal_tag_widens_deserialize_tag_to_string (line 43) | fn serde_other_internal_tag_widens_deserialize_tag_to_string() {
function serde_other_adjacent_tag_widens_deserialize_tag_to_string (line 55) | fn serde_other_adjacent_tag_widens_deserialize_tag_to_string() {
FILE: tests/tests/swift.rs
type IdentityFormat (line 7) | struct IdentityFormat;
method map_types (line 10) | fn map_types(&'_ self, types: &Types) -> Result<Cow<'_, Types>, specta::...
method map_type (line 14) | fn map_type(
function phase_collections (line 23) | fn phase_collections(types: Types) -> Vec<(&'static str, Box<dyn Format>...
function phase_output (line 31) | fn phase_output(types: &Types, format: impl Format + 'static) -> String {
type JobStatus (line 38) | enum JobStatus {
type RegularEnum (line 45) | enum RegularEnum {
type MixedEnum (line 53) | enum MixedEnum {
function swift_export (line 59) | fn swift_export() {
FILE: tests/tests/types.rs
function types (line 86) | pub fn types() -> (Types, Vec<(&'static str, DataType)>) {
function types_phased (line 431) | pub fn types_phased() -> (Types, Vec<(&'static str, DataType)>) {
type TestCollectionRegister (line 447) | pub enum TestCollectionRegister {}
type Unit1 (line 451) | struct Unit1;
type Unit2 (line 455) | struct Unit2 {}
type Unit3 (line 459) | struct Unit3();
type Unit4 (line 463) | struct Unit4(());
type Unit5 (line 467) | enum Unit5 {
type Unit6 (line 473) | enum Unit6 {
type Unit7 (line 479) | enum Unit7 {
type SimpleStruct (line 485) | struct SimpleStruct {
type TupleStruct1 (line 495) | struct TupleStruct1(i32);
type TupleStruct3 (line 499) | struct TupleStruct3(i32, bool, String);
type RenamedStruct (line 504) | struct RenamedStruct;
type TestEnum (line 508) | enum TestEnum {
type RefStruct (line 517) | struct RefStruct(TestEnum);
type InlineStruct (line 521) | struct InlineStruct {
type InlinerStruct (line 528) | struct InlinerStruct {
type GenericStruct (line 536) | struct GenericStruct<T> {
type FlattenEnumStruct (line 542) | struct FlattenEnumStruct {
type FlattenEnum (line 551) | enum FlattenEnum {
type OverridenStruct (line 559) | struct OverridenStruct {
type HasGenericAlias (line 566) | struct HasGenericAlias(GenericAlias<i32>);
type GenericAlias (line 568) | type GenericAlias<T> = std::collections::HashMap<T, String>;
type SkipVariant (line 572) | enum SkipVariant {
type SkipVariant2 (line 583) | enum SkipVariant2 {
type SkipVariant3 (line 593) | enum SkipVariant3 {
type SkipStructFields (line 609) | struct SkipStructFields {
type SpectaSkipNonTypeField (line 619) | struct SpectaSkipNonTypeField {
type EnumMacroAttributes (line 627) | enum EnumMacroAttributes {
type PlaceholderInnerField (line 643) | struct PlaceholderInnerField {
type InlineEnumField (line 649) | enum InlineEnumField {
type InlineOptionalType (line 656) | struct InlineOptionalType {
type Rename (line 664) | enum Rename {
type TransparentTypeInner (line 672) | struct TransparentTypeInner {
type TransparentType (line 679) | struct TransparentType(TransparentTypeInner);
type TransparentType2 (line 684) | struct TransparentType2(());
type NonTypeType (line 687) | struct NonTypeType;
type TransparentTypeWithOverride (line 692) | struct TransparentTypeWithOverride(#[specta(type = String)] NonTypeType);
type BasicEnum (line 696) | enum BasicEnum {
type NestedEnum (line 704) | enum NestedEnum {
type FlattenOnNestedEnum (line 712) | struct FlattenOnNestedEnum {
type EnumReferenceRecordKey (line 720) | struct EnumReferenceRecordKey {
type MyEmptyInput (line 729) | struct MyEmptyInput {}
type EmptyStruct (line 733) | struct EmptyStruct {}
type EmptyStructWithTag (line 738) | struct EmptyStructWithTag {}
type ExtraBracketsInTupleVariant (line 743) | enum ExtraBracketsInTupleVariant {
type ExtraBracketsInUnnamedStruct (line 749) | struct ExtraBracketsInUnnamedStruct((String));
type RenameWithWeirdCharsField (line 754) | struct RenameWithWeirdCharsField {
type RenamedFieldKeys (line 761) | struct RenamedFieldKeys {
type RenamedVariantWithSkippedPayload (line 778) | enum RenamedVariantWithSkippedPayload {
type RenameWithWeirdCharsVariant (line 786) | enum RenameWithWeirdCharsVariant {
type RenameWithWeirdCharsStruct (line 794) | struct RenameWithWeirdCharsStruct(String);
type RenameWithWeirdCharsEnum (line 799) | enum RenameWithWeirdCharsEnum {}
type MyEnum (line 803) | enum MyEnum {
type InlineTuple (line 810) | struct InlineTuple {
type InlineTuple2 (line 817) | struct InlineTuple2 {
type SkippedFieldWithinVariant (line 825) | enum SkippedFieldWithinVariant {
type KebabCase (line 833) | struct KebabCase {
type Issue281 (line 840) | struct Issue281<'a> {
type LifetimeGenericStruct (line 847) | struct LifetimeGenericStruct<'a, T> {
type LifetimeGenericEnum (line 854) | enum LifetimeGenericEnum<'a, T> {
type Issue374 (line 862) | struct Issue374 {
type Type (line 875) | pub(super) enum Type {}
type GenericType (line 881) | enum GenericType<T> {
type ActualType (line 888) | struct ActualType {
type SpectaTypeOverride (line 894) | struct SpectaTypeOverride {
type ContainerTypeOverrideStruct (line 907) | struct ContainerTypeOverrideStruct {
type ContainerTypeOverrideEnum (line 913) | enum ContainerTypeOverrideEnum {
type ContainerTypeOverrideGeneric (line 919) | struct ContainerTypeOverrideGeneric<T>(std::marker::PhantomData<T>);
type ContainerTypeOverrideToGeneric (line 923) | struct ContainerTypeOverrideToGeneric<T>(std::marker::PhantomData<T>);
type ContainerTypeOverrideTuple (line 927) | struct ContainerTypeOverrideTuple {
type ContainerTypeOverrideTupleGeneric (line 933) | struct ContainerTypeOverrideTupleGeneric<T>(std::marker::PhantomData<T>);
type InvalidToValidType (line 938) | struct InvalidToValidType {
type TupleStruct (line 945) | struct TupleStruct(String);
type TupleStructWithRep (line 950) | struct TupleStructWithRep(String);
type GenericTupleStruct (line 954) | struct GenericTupleStruct<T>(T);
type BracedStruct (line 958) | struct BracedStruct {
type Struct (line 965) | struct Struct {
type Struct2 (line 971) | struct Struct2 {
type Enum (line 979) | enum Enum {
type Enum2 (line 987) | enum Enum2 {
type StructRenameAllUppercase (line 1000) | struct StructRenameAllUppercase {
type EnumRenameAllUppercase (line 1008) | enum EnumRenameAllUppercase {
type StructPhaseSpecificRename (line 1021) | struct StructPhaseSpecificRename {
type RenameSerdeSpecialChar (line 1028) | struct RenameSerdeSpecialChar {
type Enum3 (line 1036) | enum Enum3 {
type Recursive (line 1045) | struct Recursive {
type RecursiveMapValue (line 1051) | struct RecursiveMapValue {
type RecursiveInline (line 1057) | struct RecursiveInline {
type RecursiveTransparent (line 1064) | struct RecursiveTransparent(Box<RecursiveInline>);
type RecursiveInEnum (line 1068) | enum RecursiveInEnum {
type NonOptional (line 1077) | struct NonOptional(Option<String>);
type OptionalOnNamedField (line 1081) | struct OptionalOnNamedField(#[specta(optional)] Option<String>);
type OptionalOnTransparentNamedFieldInner (line 1085) | struct OptionalOnTransparentNamedFieldInner(#[specta(optional)] Option<S...
type OptionalOnTransparentNamedField (line 1089) | struct OptionalOnTransparentNamedField {
type OptionalInEnum (line 1096) | enum OptionalInEnum {
type Regular (line 1113) | struct Regular(HashMap<String, ()>);
type RegularStruct (line 1117) | struct RegularStruct {
type TransparentStruct (line 1124) | struct TransparentStruct(String);
type UnitVariants (line 1128) | enum UnitVariants {
type UntaggedVariantsKey (line 1137) | enum UntaggedVariantsKey {
type UntaggedVariants (line 1146) | enum UntaggedVariants {
type UntaggedVariantsWithoutValue (line 1157) | enum UntaggedVariantsWithoutValue {
type UntaggedVariantsWithDuplicateBranches (line 1166) | enum UntaggedVariantsWithDuplicateBranches {
type InvalidUntaggedVariants (line 1175) | enum InvalidUntaggedVariants {
type Variants (line 1183) | enum Variants {
type MaybeValidKey (line 1192) | struct MaybeValidKey<T>(T);
type ValidMaybeValidKey (line 1197) | struct ValidMaybeValidKey(HashMap<MaybeValidKey<String>, ()>);
type ValidMaybeValidKeyNested (line 1202) | struct ValidMaybeValidKeyNested(HashMap<MaybeValidKey<MaybeValidKey<Stri...
type MacroStruct (line 1212) | struct MacroStruct(field_ty_macro!());
type MacroStruct2 (line 1216) | struct MacroStruct2 {
type MacroEnum (line 1222) | enum MacroEnum {
type DeprecatedType (line 1230) | struct DeprecatedType {
type DeprecatedTypeWithMsg (line 1237) | struct DeprecatedTypeWithMsg {
type DeprecatedTypeWithMsg2 (line 1244) | struct DeprecatedTypeWithMsg2 {
type DeprecatedFields (line 1250) | struct DeprecatedFields {
type DeprecatedTupleVariant (line 1262) | struct DeprecatedTupleVariant(
type DeprecatedEnumVariants (line 1270) | enum DeprecatedEnumVariants {
type CommentedStruct (line 1284) | struct CommentedStruct {
type CommentedEnum (line 1296) | enum CommentedEnum {
type SingleLineComment (line 1315) | enum SingleLineComment {
type Demo (line 1327) | struct Demo<A, B> {
type NonGeneric (line 1332) | type NonGeneric = Demo<u8, bool>;
type HalfGenericA (line 1333) | type HalfGenericA<T> = Demo<T, bool>;
type HalfGenericB (line 1334) | type HalfGenericB<T> = Demo<u8, T>;
type FullGeneric (line 1335) | type FullGeneric<T, U> = Demo<T, U>;
type Another (line 1337) | type Another<T> = FullGeneric<u8, T>;
type MapA (line 1339) | type MapA<A> = HashMap<String, A>;
type MapB (line 1340) | type MapB<B> = HashMap<B, String>;
type MapC (line 1341) | type MapC<B> = HashMap<String, AGenericStruct<B>>;
type AGenericStruct (line 1345) | struct AGenericStruct<T> {
type D (line 1351) | struct D {
type GenericFlattened (line 1357) | struct GenericFlattened<T> {
type C (line 1363) | struct C {
type B (line 1371) | struct B {
type A (line 1377) | struct A {
type ToBeFlattened (line 1390) | struct ToBeFlattened {
type DoubleFlattened (line 1396) | struct DoubleFlattened {
type Inner (line 1403) | struct Inner {
type FlattenedInner (line 1411) | struct FlattenedInner {
type BoxedInner (line 1418) | struct BoxedInner {
type BoxFlattened (line 1424) | struct BoxFlattened {
type BoxInline (line 1431) | struct BoxInline {
type First (line 1438) | struct First {
type Second (line 1444) | struct Second {
type Third (line 1450) | struct Third {
type Fourth (line 1459) | struct Fourth {
type TagOnStructWithInline (line 1468) | struct TagOnStructWithInline {
type Sixth (line 1477) | struct Sixth {
type Seventh (line 1485) | struct Seventh {
type Eight (line 1493) | enum Eight {
type MyEnumTagged (line 1502) | enum MyEnumTagged {
type MyEnumExternal (line 1512) | enum MyEnumExternal {
type MyEnumAdjacent (line 1523) | enum MyEnumAdjacent {
type MyEnumUntagged (line 1534) | enum MyEnumUntagged {
type Ninth (line 1544) | enum Ninth {
type Tenth (line 1555) | enum Tenth {
type Optional (line 1565) | struct Optional {
type ContainerDefault (line 1578) | struct ContainerDefault {
type FieldDefault (line 1585) | struct FieldDefault {
type MixedTaggedAndUntagged (line 1594) | enum MixedTaggedAndUntagged {
type MixedTaggedAndUntaggedStruct (line 1607) | enum MixedTaggedAndUntaggedStruct {
type MixedTaggedAndUntaggedPhased (line 1620) | enum MixedTaggedAndUntaggedPhased {
type TypeWithComplexAttributes (line 1636) | enum TypeWithComplexAttributes {
type AdjacentlyTagged (line 1648) | enum AdjacentlyTagged {
type LoadProjectEvent (line 1664) | enum LoadProjectEvent {
type ExternallyTagged (line 1680) | enum ExternallyTagged {
type Issue221External (line 1689) | enum Issue221External {
type StructWithAlias (line 1697) | struct StructWithAlias {
type StructWithMultipleAliases (line 1705) | struct StructWithMultipleAliases {
type StructWithAliasAndRename (line 1713) | struct StructWithAliasAndRename {
type EnumWithVariantAlias (line 1721) | enum EnumWithVariantAlias {
type EnumWithMultipleVariantAliases (line 1730) | enum EnumWithMultipleVariantAliases {
type EnumWithVariantAliasAndRename (line 1739) | enum EnumWithVariantAliasAndRename {
type InternallyTaggedWithAlias (line 1749) | enum InternallyTaggedWithAlias {
type AdjacentlyTaggedWithAlias (line 1763) | enum AdjacentlyTaggedWithAlias {
type UntaggedWithAlias (line 1777) | enum UntaggedWithAlias {
type Issue221UntaggedSafe (line 1791) | enum Issue221UntaggedSafe {
type Issue221UntaggedMixed (line 1800) | enum Issue221UntaggedMixed {
type EmptyEnum (line 1815) | enum EmptyEnum {}
type EmptyEnumTagged (line 1820) | enum EmptyEnumTagged {}
type EmptyEnumTaggedWContent (line 1825) | enum EmptyEnumTaggedWContent {}
type EmptyEnumUntagged (line 1830) | enum EmptyEnumUntagged {}
type UnitStruct (line 1834) | struct UnitStruct;
type EmptyBracedStruct (line 1838) | struct EmptyBracedStruct {}
type EmptyTupleStruct (line 1842) | struct EmptyTupleStruct();
type TaggedEnumOfUnitStruct (line 1847) | enum TaggedEnumOfUnitStruct {
type TaggedEnumOfEmptyBracedStruct (line 1855) | enum TaggedEnumOfEmptyBracedStruct {
type TaggedEnumOfEmptyTupleStruct (line 1863) | enum TaggedEnumOfEmptyTupleStruct {
type TaggedEnumOfEmptyTupleBracedStructs (line 1871) | enum TaggedEnumOfEmptyTupleBracedStructs {
type TupleStructWithTuple (line 1879) | struct TupleStructWithTuple(());
type TaggedStructOfStructWithTuple (line 1884) | enum TaggedStructOfStructWithTuple {
type InternallyTaggedB (line 1892) | enum InternallyTaggedB {
type InternallyTaggedC (line 1900) | enum InternallyTaggedC {
type InternallyTaggedD (line 1908) | enum InternallyTaggedD {
type InternallyTaggedE (line 1916) | enum InternallyTaggedE {
type InternallyTaggedF (line 1924) | enum InternallyTaggedF {
type InternallyTaggedFInner (line 1932) | enum InternallyTaggedFInner {
type InternallyTaggedG (line 1939) | enum InternallyTaggedG {
type InternallyTaggedGInner (line 1947) | enum InternallyTaggedGInner {
type InternallyTaggedH (line 1954) | enum InternallyTaggedH {
type InternallyTaggedHInner (line 1962) | struct InternallyTaggedHInner(());
type InternallyTaggedI (line 1967) | enum InternallyTaggedI {
type InternallyTaggedIInner (line 1975) | struct InternallyTaggedIInner(String);
type InternallyTaggedL (line 1980) | enum InternallyTaggedL {
type InternallyTaggedLInner (line 1989) | enum InternallyTaggedLInner {
type InternallyTaggedM (line 1997) | enum InternallyTaggedM {
type InternallyTaggedMInner (line 2007) | enum InternallyTaggedMInner {
type SkipOnlyField (line 2014) | struct SkipOnlyField {
type SkipField (line 2021) | struct SkipField {
type SkipOnlyVariantExternallyTagged (line 2029) | enum SkipOnlyVariantExternallyTagged {
type SkipOnlyVariantInternallyTagged (line 2037) | enum SkipOnlyVariantInternallyTagged {
type SkipOnlyVariantAdjacentlyTagged (line 2045) | enum SkipOnlyVariantAdjacentlyTagged {
type SkipOnlyVariantUntagged (line 2053) | enum SkipOnlyVariantUntagged {
type SkipUnnamedFieldInVariant (line 2060) | enum SkipUnnamedFieldInVariant {
type SkipNamedFieldInVariant (line 2071) | enum SkipNamedFieldInVariant {
type TransparentWithSkip (line 2088) | struct TransparentWithSkip((), #[specta(skip)] String);
type TransparentWithSkip2 (line 2093) | struct TransparentWithSkip2(#[specta(skip)] (), String);
type TransparentWithSkip3 (line 2098) | struct TransparentWithSkip3(#[specta(type = String)] Box<dyn Any>);
type LazilySkip (line 2104) | enum LazilySkip {
type FlattenA (line 2116) | struct FlattenA {
type FlattenB (line 2123) | struct FlattenB {
type FlattenC (line 2131) | struct FlattenC {
type FlattenD (line 2139) | struct FlattenD {
type FlattenE (line 2146) | struct FlattenE {
type FlattenF (line 2154) | struct FlattenF {
type FlattenG (line 2162) | struct FlattenG {
type TupleNested (line 2170) | struct TupleNested(Vec<i32>, (Vec<i32>, Vec<i32>), [Vec<i32>; 3]);
type Generic1 (line 2174) | struct Generic1<T: Type> {
type GenericAutoBound (line 2181) | struct GenericAutoBound<T> {
type GenericAutoBound2 (line 2188) | struct GenericAutoBound2<T: PartialEq> {
type Container1 (line 2195) | struct Container1 {
type Generic2 (line 2203) | enum Generic2<A, B, C> {
type GenericStruct2 (line 2216) | struct GenericStruct2<T> {
type GenericNewType1 (line 2229) | struct GenericNewType1<T>(Vec<Vec<T>>);
type GenericTuple (line 2233) | struct GenericTuple<T>(T, Vec<T>, Vec<Vec<T>>);
type InlineGenericNewtype (line 2237) | struct InlineGenericNewtype<T>(T);
type InlineGenericEnum (line 2241) | enum InlineGenericEnum<T> {
type InlineGenericNested (line 2249) | struct InlineGenericNested<T>(
type InlineFlattenGenericsG (line 2260) | struct InlineFlattenGenericsG<T> {
type InlineFlattenGenerics (line 2267) | struct InlineFlattenGenerics {
type GenericDefault (line 2277) | struct GenericDefault<T = String> {
type ChainedGenericDefault (line 2283) | struct ChainedGenericDefault<T = String, U = T> {
type GenericDefaultSkipped (line 2290) | struct GenericDefaultSkipped<#[specta(skip_default_generic)] T = String> {
type GenericDefaultSkippedNonTypeDefault (line 2294) | struct GenericDefaultSkippedNonTypeDefault;
type GenericDefaultSkippedNonType (line 2298) | struct GenericDefaultSkippedNonType<
type Pair (line 2383) | struct Pair<Z, A> {
type GenericParameterOrderPreserved (line 2390) | struct GenericParameterOrderPreserved {
constant CONST_LEN (line 2394) | const CONST_LEN: usize = 1;
type ConstGenericInNonConstContainer (line 2397) | struct ConstGenericInNonConstContainer {
type ConstGenericInConstContainer (line 2408) | struct ConstGenericInConstContainer<const N: usize = 1> {
type NamedConstGeneric (line 2417) | struct NamedConstGeneric<const N: usize = 1> {
type NamedConstGenericContainer (line 2426) | struct NamedConstGenericContainer {
type InlineConstGeneric (line 2434) | struct InlineConstGeneric<const N: usize = 1> {
type InlineConstGenericContainer (line 2444) | struct InlineConstGenericContainer {
type InlineRecursiveConstGeneric (line 2454) | struct InlineRecursiveConstGeneric<const N: usize = 1> {
type InlineRecursiveConstGenericContainer (line 2465) | struct InlineRecursiveConstGenericContainer {
type TransparentA (line 2635) | struct TransparentA(String);
type TransparentB (line 2640) | struct TransparentB(String);
type UsesTransparent (line 2644) | struct UsesTransparent {
function transparent_wrappers_have_distinct_ids (line 2650) | fn transparent_wrappers_have_distinct_ids() {
function struct_collects_all_transparent_field_types (line 2665) | fn struct_collects_all_transparent_field_types() {
function container_default_marks_all_fields_optional_in_unified_mode (line 2679) | fn container_default_marks_all_fields_optional_in_unified_mode() {
function field_default_still_marks_only_that_field_optional (line 2691) | fn field_default_still_marks_only_that_field_optional() {
function mixed_tagged_and_untagged_variants_export_in_unified_mode (line 2703) | fn mixed_tagged_and_untagged_variants_export_in_unified_mode() {
function mixed_tagged_and_untagged_struct_variants_export_in_unified_mode (line 2715) | fn mixed_tagged_and_untagged_struct_variants_export_in_unified_mode() {
function phased_mixed_untagged_variants_split_per_phase (line 2727) | fn phased_mixed_untagged_variants_split_per_phase() {
FILE: tests/tests/typescript.rs
function typescript_types (line 18) | fn typescript_types() -> (Types, Vec<(&'static str, DataType)>) {
type PhaseCollection (line 35) | pub type PhaseCollection = (
type IdentityFormat (line 42) | struct IdentityFormat;
method map_types (line 45) | fn map_types(&'_ self, types: &Types) -> Result<Cow<'_, Types>, specta::...
method map_type (line 49) | fn map_type(
function phase_collections (line 58) | pub fn phase_collections() -> Vec<PhaseCollection> {
function typescript_export (line 86) | fn typescript_export() {
function typescript_export_serde_errors (line 96) | fn typescript_export_serde_errors() {
function typescript_export_bigint_errors (line 407) | fn typescript_export_bigint_errors() {
function typescript_export_to (line 582) | fn typescript_export_to() {
function primitives_export (line 620) | fn primitives_export() {
function primitives_export_many (line 650) | fn primitives_export_many() {
function primitives_reference (line 679) | fn primitives_reference() {
function primitives_inline (line 707) | fn primitives_inline() {
function reserved_names (line 728) | fn reserved_names() {
FILE: tests/tests/utils.rs
function fs_to_string (line 9) | pub fn fs_to_string(path: &Path) -> Result<String, std::io::Error> {
function fs_to_string_impl (line 42) | fn fs_to_string_impl(
function normalize_newlines (line 118) | fn normalize_newlines(text: &str) -> Cow<'_, str> {
FILE: tests/tests/zod.rs
type StructWithBigInt (line 26) | struct StructWithBigInt {
type StructWithStructWithBigInt (line 32) | struct StructWithStructWithBigInt {
type StructWithOptionWithStructWithBigInt (line 39) | struct StructWithOptionWithStructWithBigInt {
type EnumWithInlineStructWithBigInt (line 46) | enum EnumWithInlineStructWithBigInt {
type Recursive (line 52) | struct Recursive {
type Testing (line 57) | struct Testing {
type Another (line 62) | struct Another {
type EmptyStruct (line 68) | struct EmptyStruct {}
type EmptyNamedVariant (line 72) | enum EmptyNamedVariant {
type SerdeTaggedEnum (line 79) | enum SerdeTaggedEnum {
type InvalidInternallyTaggedEnum (line 87) | enum InvalidInternallyTaggedEnum {
type Testing (line 95) | pub struct Testing {
type Testing (line 103) | pub struct Testing {
function inline_for (line 109) | fn inline_for<T: Type>(zod: &Zod) -> Result<String, specta_zod::Error> {
function temp_root (line 115) | fn temp_root() -> std::path::PathBuf {
function zod_export_smoke (line 122) | fn zod_export_smoke() {
function zod_primitives_smoke (line 147) | fn zod_primitives_smoke() {
function zod_bigint_export_behaviors (line 169) | fn zod_bigint_export_behaviors() {
function zod_bigint_errors_propagate_from_nested_types (line 190) | fn zod_bigint_errors_propagate_from_nested_types() {
function zod_layout_duplicate_typenames (line 206) | fn zod_layout_duplicate_typenames() {
function zod_layout_files_export_to (line 222) | fn zod_layout_files_export_to() {
function zod_uses_serde_transformed_resolved_types (line 238) | fn zod_uses_serde_transformed_resolved_types() {
function zod_empty_named_shapes_are_strict (line 248) | fn zod_empty_named_shapes_are_strict() {
function zod_layout_files_preserves_unrelated_typescript_files (line 257) | fn zod_layout_files_preserves_unrelated_typescript_files() {
function typescript_layout_files_preserves_unrelated_typescript_files (line 280) | fn typescript_layout_files_preserves_unrelated_typescript_files() {
function zod_recursive_types_use_lazy (line 303) | fn zod_recursive_types_use_lazy() {
function zod_reserved_type_name_errors (line 312) | fn zod_reserved_type_name_errors() {
function zod_layout_files_errors_on_export (line 324) | fn zod_layout_files_errors_on_export() {
function temp_dir (line 333) | fn temp_dir() -> TempDir {
function export_for (line 337) | fn export_for<T: Type>() -> Result<String, specta_zod::Error> {
Condensed preview — 279 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,286K chars).
[
{
"path": ".github/FUNDING.yml",
"chars": 69,
"preview": "github: [oscartbeaumont]\ncustom: [\"https://paypal.me/oscartbeaumont\"]"
},
{
"path": ".github/dependabot.yml",
"chars": 332,
"preview": "version: 2\n\nmulti-ecosystem-groups:\n specta-deps:\n schedule:\n interval: \"weekly\"\n\nupdates:\n - package-ecosyste"
},
{
"path": ".github/features.js",
"chars": 2414,
"preview": "// This script generates the documentation for the Cargo features from the comments in the `Cargo.toml` file.\n// It dump"
},
{
"path": ".github/workflows/ci.yml",
"chars": 1372,
"preview": "name: CI\n\non:\n workflow_dispatch:\n push:\n branches:\n - main\n pull_request:\n\nenv:\n CARGO_TERM_COLOR: always\n\n"
},
{
"path": ".gitignore",
"chars": 351,
"preview": "# Generated by Cargo\n# will have compiled files and executables\ntarget/\ntest-target/\n\n# These are backup files generated"
},
{
"path": ".rustfmt.toml",
"chars": 47,
"preview": "# https://github.com/specta-rs/specta/pull/222\n"
},
{
"path": ".taplo.toml",
"chars": 32,
"preview": "[formatting]\ncolumn_width = 150\n"
},
{
"path": "AGENTS.md",
"chars": 1527,
"preview": "Specta is a Rust library for easily exporting Rust types to other languages (TypeScript, Swift, Rust, OpenAPI, etc.). It"
},
{
"path": "Cargo.toml",
"chars": 900,
"preview": "[workspace]\nmembers = [\"specta\", \"specta-*\", \"tests\", \"examples/*\"]\nresolver = \"2\"\n\n[workspace.lints.rust]\nunsafe_code ="
},
{
"path": "LICENSE",
"chars": 1070,
"preview": "MIT License\n\nCopyright (c) 2022 Oscar Beaumont\n\nPermission is hereby granted, free of charge, to any person obtaining a "
},
{
"path": "README.md",
"chars": 7913,
"preview": "<div align=\"center\">\n <img height=\"150\" src=\".github/logo.png\" alt=\"Specta Logo\"></img>\n <h1>Specta</h1>\n <p><b"
},
{
"path": "examples/basic-ts/Cargo.toml",
"chars": 390,
"preview": "[package]\nname = \"example-basic-ts\"\nversion = \"0.0.0\"\nedition = \"2024\"\npublish = false\n\n[dependencies]\nspecta = { path ="
},
{
"path": "examples/basic-ts/src/main.rs",
"chars": 1993,
"preview": "use serde::{Deserialize, Serialize};\nuse specta::{Type, Types};\nuse specta_typescript::Typescript;\n\n// Specta works by d"
},
{
"path": "examples/collect/Cargo.toml",
"chars": 275,
"preview": "[package]\nname = \"example-collect\"\nversion = \"0.0.0\"\nedition = \"2024\"\npublish = false\n\n[dependencies]\nspecta = { path = "
},
{
"path": "examples/collect/src/main.rs",
"chars": 663,
"preview": "#![allow(unused)]\n\nuse specta::Type;\nuse specta_typescript::Typescript;\n\n#[derive(Type)]\npub struct User {\n id: Strin"
},
{
"path": "examples/scratchpad/Cargo.toml",
"chars": 316,
"preview": "[package]\nname = \"example-scratchpad\"\nversion = \"0.0.0\"\nedition = \"2024\"\npublish = false\n\n[dependencies]\nspecta = { path"
},
{
"path": "examples/scratchpad/src/main.rs",
"chars": 290,
"preview": "//! A playground for quickly reproducing issue.\n#![allow(warnings)]\n\nuse specta::Types;\n\nfn main() {\n let mut types ="
},
{
"path": "specta/Cargo.toml",
"chars": 7038,
"preview": "[package]\nname = \"specta\"\ndescription = \"Easily export your Rust types to other languages\"\nversion = \"2.0.0-rc.24\"\nautho"
},
{
"path": "specta/build.rs",
"chars": 604,
"preview": "//! Build script for configuring nightly-only cfg flags.\n//!\n//! This build script enables the `is_nightly` cfg when run"
},
{
"path": "specta/src/collect.rs",
"chars": 2390,
"preview": "use std::sync::{Mutex, OnceLock, PoisonError};\n\nuse crate::{Type, Types};\n\n// Global type store for collecting custom ty"
},
{
"path": "specta/src/datatype/attributes.rs",
"chars": 5442,
"preview": "use std::{\n any::Any,\n borrow::Cow,\n collections::{HashMap, hash_map::DefaultHasher},\n fmt,\n hash::{Hash,"
},
{
"path": "specta/src/datatype/enum.rs",
"chars": 5593,
"preview": "use std::borrow::Cow;\n\nuse crate::datatype::Field;\n\nuse super::{Attributes, DataType, Deprecated, Fields, NamedFields, U"
},
{
"path": "specta/src/datatype/fields.rs",
"chars": 4273,
"preview": "//! Field types are used by both enums and structs.\n\nuse crate::datatype::Struct;\n\nuse super::{Attributes, DataType, Dep"
},
{
"path": "specta/src/datatype/function.rs",
"chars": 1568,
"preview": "use std::borrow::Cow;\n\nuse super::{DataType, Deprecated};\n\n/// Runtime type information for a function annotated with `#"
},
{
"path": "specta/src/datatype/generic.rs",
"chars": 1957,
"preview": "use std::borrow::Cow;\n\nuse crate::datatype::DataType;\n\n/// Reference to a named generic parameter.\n///\n/// Exporters usu"
},
{
"path": "specta/src/datatype/list.rs",
"chars": 825,
"preview": "use super::DataType;\n\n/// Sequential collection type, such as [`Vec`](std::vec::Vec), arrays, slices,\n/// or set-like co"
},
{
"path": "specta/src/datatype/literal.rs",
"chars": 6126,
"preview": "//! This works but isn't being shipped for now as we don't need it for const generics anymore.\n//! Also it suffers from "
},
{
"path": "specta/src/datatype/map.rs",
"chars": 1334,
"preview": "use super::DataType;\n\n/// Key-value collection type, such as [`HashMap`](std::collections::HashMap) or\n/// another map-l"
},
{
"path": "specta/src/datatype/named.rs",
"chars": 14048,
"preview": "use std::{\n borrow::Cow,\n hash::{DefaultHasher, Hash, Hasher},\n mem,\n panic::{self, AssertUnwindSafe, Locati"
},
{
"path": "specta/src/datatype/primitive.rs",
"chars": 991,
"preview": "use super::DataType;\n\n/// Rust built-in primitive type.\n#[allow(non_camel_case_types)]\n#[derive(Debug, Clone, PartialEq,"
},
{
"path": "specta/src/datatype/reference.rs",
"chars": 6679,
"preview": "use std::{\n any::{Any, TypeId},\n fmt, hash,\n sync::Arc,\n};\n\nuse crate::datatype::Generic;\n\nuse super::DataType;"
},
{
"path": "specta/src/datatype/struct.rs",
"chars": 1343,
"preview": "use crate::datatype::{Attributes, DataType, Fields};\n\nuse super::StructBuilder;\n\nuse super::{NamedFields, UnnamedFields}"
},
{
"path": "specta/src/datatype/tuple.rs",
"chars": 689,
"preview": "use super::DataType;\n\n/// Represents a Rust [tuple](https://doc.rust-lang.org/std/primitive.tuple.html) type.\n///\n/// Th"
},
{
"path": "specta/src/datatype.rs",
"chars": 1926,
"preview": "//! Types related to working with [`DataType`]. Exposed for advanced users.\n\nmod attributes;\nmod r#enum;\nmod fields;\nmod"
},
{
"path": "specta/src/docs.md",
"chars": 5368,
"preview": "Easily export your Rust types to other languages.\n\nSpecta provides a system for type introspection and a set of language"
},
{
"path": "specta/src/format.rs",
"chars": 2060,
"preview": "use std::{borrow::Cow, error};\n\nuse crate::{Types, datatype::DataType};\n\n/// Error type returned by [`Format`] callbacks"
},
{
"path": "specta/src/function/arg.rs",
"chars": 570,
"preview": "use crate::{Type, Types, datatype::DataType};\n\n/// Implemented by types that can be used as an argument in a function an"
},
{
"path": "specta/src/function/result.rs",
"chars": 763,
"preview": "use std::future::Future;\n\nuse crate::{Type, Types, datatype::DataType};\n\n/// Implemented by types that can be returned f"
},
{
"path": "specta/src/function/specta_fn.rs",
"chars": 3095,
"preview": "use std::borrow::Cow;\n\nuse crate::{\n Types,\n datatype::{Deprecated, Function},\n};\n\nuse super::{FunctionArg, Functi"
},
{
"path": "specta/src/function.rs",
"chars": 4107,
"preview": "//! Support for collecting Rust function signatures.\n//!\n//! Specta does not export callable functions by itself. Instea"
},
{
"path": "specta/src/internal.rs",
"chars": 1196,
"preview": "//! This module contains functions that are public for the sole reason of the macros.\n//!\n//! They will not be documente"
},
{
"path": "specta/src/lib.rs",
"chars": 1514,
"preview": "#![doc = include_str!(\"./docs.md\")]\n#![cfg_attr(docsrs, feature(doc_cfg))]\n#![doc(\n html_logo_url = \"https://github.c"
},
{
"path": "specta/src/type/impls.rs",
"chars": 8074,
"preview": "use std::marker::PhantomData;\n\nuse crate::{\n Type, Types,\n datatype::{self, DataType, List},\n r#type::macros::*"
},
{
"path": "specta/src/type/legacy_impls.rs",
"chars": 63595,
"preview": "use crate::{Type, Types};\n#[allow(unused_imports)]\nuse crate::{datatype::*, r#type::impls::*, r#type::macros::impl_ndt};"
},
{
"path": "specta/src/type/macros.rs",
"chars": 25086,
"preview": "macro_rules! _impl_primitives {\n ($($i:ident)+) => {$(\n impl Type for $i {\n fn definition(_: &mut T"
},
{
"path": "specta/src/type.rs",
"chars": 1584,
"preview": "use crate::{Types, datatype::DataType};\n\nmod impls;\nmod legacy_impls;\nmod macros;\n\n/// Provides runtime type information"
},
{
"path": "specta/src/types.rs",
"chars": 9658,
"preview": "use std::{\n collections::{HashMap, hash_map},\n fmt,\n};\n\nuse crate::{\n Type,\n datatype::{NamedDataType, Named"
},
{
"path": "specta-go/Cargo.toml",
"chars": 786,
"preview": "[package]\nname = \"specta-go\"\ndescription = \"Export your Rust types to Go\"\nversion = \"0.0.2\"\nauthors = [\"Oscar Beaumont <"
},
{
"path": "specta-go/bindings.go",
"chars": 72,
"preview": "package bindings\n\ntype MyType struct {\n\tField String `json:\"field\"`\n}\n\n\n"
},
{
"path": "specta-go/src/error.rs",
"chars": 2108,
"preview": "use std::{error, fmt, io};\n\nuse crate::Layout;\n\n#[derive(Debug)]\n/// Errors that can occur during Go code generation.\npu"
},
{
"path": "specta-go/src/go.rs",
"chars": 7644,
"preview": "use std::{borrow::Cow, path::Path};\n\nuse specta::{\n Format, Types,\n datatype::{DataType, Fields, Reference},\n};\n\nu"
},
{
"path": "specta-go/src/lib.rs",
"chars": 875,
"preview": "//! [Go](https://go.dev) language exporter for [Specta](specta).\n//!\n//! <div class=\"warning\">\n//! This crate is still i"
},
{
"path": "specta-go/src/primitives.rs",
"chars": 12462,
"preview": "use std::collections::HashSet;\n\nuse specta::{\n Types,\n datatype::{\n DataType, Enum, Fields, Generic, NamedD"
},
{
"path": "specta-go/src/reserved_names.rs",
"chars": 1084,
"preview": "/// Reserved keywords and common types in the Go programming language.\npub(crate) const RESERVED_GO_NAMES: &[&str] = &[\n"
},
{
"path": "specta-jsonschema/Cargo.toml",
"chars": 1149,
"preview": "[package]\nname = \"specta-jsonschema\"\ndescription = \"Export your Rust types to a JSON Schema\"\nversion = \"0.0.2\"\nauthors ="
},
{
"path": "specta-jsonschema/examples/jsonschema.rs",
"chars": 1136,
"preview": "#![allow(missing_docs)]\n\nuse serde::{Deserialize, Serialize};\nuse specta::{Type, Types};\nuse specta_jsonschema::{JsonSch"
},
{
"path": "specta-jsonschema/src/error.rs",
"chars": 1089,
"preview": "use std::io;\n\n#[derive(Debug, thiserror::Error)]\npub enum Error {\n #[error(\"IO error: {0}\")]\n Io(#[from] io::Error"
},
{
"path": "specta-jsonschema/src/import.rs",
"chars": 9101,
"preview": "use crate::Error;\nuse schemars::Schema;\nuse serde_json::{Map as JsonMap, Value};\nuse specta::datatype::*;\nuse std::borro"
},
{
"path": "specta-jsonschema/src/json_schema.rs",
"chars": 6341,
"preview": "use crate::{Error, Layout, SchemaVersion, primitives};\nuse serde_json::Value;\nuse specta::{Format, Types, datatype::Name"
},
{
"path": "specta-jsonschema/src/layout.rs",
"chars": 535,
"preview": "/// Controls how JSON schemas are organized in output\n#[derive(Debug, Clone, Copy, PartialEq, Eq)]\npub enum Layout {\n "
},
{
"path": "specta-jsonschema/src/lib.rs",
"chars": 3884,
"preview": "//! [JSON Schema](https://json-schema.org) exporter and importer for [Specta](specta).\n//!\n//! This crate provides bidir"
},
{
"path": "specta-jsonschema/src/primitives.rs",
"chars": 11812,
"preview": "use crate::{Error, JsonSchema};\nuse serde_json::{Map, Value, json};\nuse specta::{\n Types,\n datatype::{NamedDataTyp"
},
{
"path": "specta-jsonschema/src/schema_version.rs",
"chars": 1152,
"preview": "use serde::{Deserialize, Serialize};\n\n/// JSON Schema version specification\n#[derive(Debug, Clone, Copy, PartialEq, Eq, "
},
{
"path": "specta-jsonschema/tests/basic.rs",
"chars": 3427,
"preview": "#![allow(missing_docs)]\n\nuse std::fs;\n\nuse serde::{Deserialize, Serialize};\nuse specta::{Type, Types};\nuse specta_jsonsc"
},
{
"path": "specta-kotlin/Cargo.toml",
"chars": 695,
"preview": "[package]\nname = \"specta-kotlin\"\ndescription = \"Export your Rust types to Kotlin\"\nversion = \"0.0.2\"\nauthors = [\"Oscar Be"
},
{
"path": "specta-kotlin/src/lib.rs",
"chars": 4466,
"preview": "//! [Kotlin](https://kotlinlang.org) language exporter for [Specta](specta).\n//!\n//! <div class=\"warning\">\n//! This crat"
},
{
"path": "specta-macros/Cargo.toml",
"chars": 989,
"preview": "[package]\nname = \"specta-macros\"\ndescription = \"Macros for specta. Don't use directly!\"\nversion = \"2.0.0-rc.24\"\nauthors "
},
{
"path": "specta-macros/README.md",
"chars": 144,
"preview": "# Specta Macros\n\nThe macros for [Specta](https://crates.io/crates/specta). Do not use this crate directly! It is reexpor"
},
{
"path": "specta-macros/src/lib.rs",
"chars": 9063,
"preview": "//! Easily export your Rust types to other languages\n//!\n//! This crate contains the macro which are reexported by the `"
},
{
"path": "specta-macros/src/specta.rs",
"chars": 7530,
"preview": "// inspired by https://github.com/tauri-apps/tauri/blob/2901145c497299f033ba7120af5f2e7ead16c75a/core/tauri-macros/src/c"
},
{
"path": "specta-macros/src/type/attr/container.rs",
"chars": 3528,
"preview": "use proc_macro2::TokenStream;\nuse quote::ToTokens;\nuse syn::Result;\nuse syn::Type;\n\nuse crate::utils::{AttrExtract, Attr"
},
{
"path": "specta-macros/src/type/attr/field.rs",
"chars": 1639,
"preview": "use syn::{Result, Type};\n\nuse crate::utils::{AttrExtract, Attribute};\n\nuse super::RustCAttr;\n\n#[derive(Default)]\npub str"
},
{
"path": "specta-macros/src/type/attr/legacy.rs",
"chars": 1568,
"preview": "#[derive(Clone, Copy)]\npub enum Scope {\n Container,\n Field,\n Variant,\n}\n\nimpl Scope {\n fn as_str(self) -> &'"
},
{
"path": "specta-macros/src/type/attr/mod.rs",
"chars": 160,
"preview": "pub use container::*;\npub use field::*;\npub use legacy::*;\npub use rustc::*;\npub use variant::*;\n\nmod container;\nmod fie"
},
{
"path": "specta-macros/src/type/attr/rustc.rs",
"chars": 4254,
"preview": "use std::borrow::Cow;\n\nuse proc_macro2::TokenStream;\nuse quote::quote;\nuse syn::{Lit, Result};\n\nuse crate::utils::{Attri"
},
{
"path": "specta-macros/src/type/attr/variant.rs",
"chars": 1416,
"preview": "use syn::{Result, Type};\n\nuse crate::utils::{AttrExtract, Attribute};\n\nuse super::RustCAttr;\n\n#[derive(Default)]\npub str"
},
{
"path": "specta-macros/src/type/enum.rs",
"chars": 8872,
"preview": "use super::{\n AttributeScope, attr::*, build_runtime_attributes, generics::type_with_inferred_lifetimes,\n r#struct"
},
{
"path": "specta-macros/src/type/field.rs",
"chars": 2307,
"preview": "use proc_macro2::TokenStream;\nuse quote::quote;\nuse syn::Type;\n\nuse crate::r#type::attr::deprecated_as_tokens;\n\nuse supe"
},
{
"path": "specta-macros/src/type/generics.rs",
"chars": 10996,
"preview": "use proc_macro2::TokenStream;\nuse quote::quote;\nuse std::collections::{HashSet, hash_map::Entry};\nuse syn::{\n ConstPa"
},
{
"path": "specta-macros/src/type/mod.rs",
"chars": 15284,
"preview": "use attr::*;\nuse r#enum::parse_enum;\nuse proc_macro2::TokenStream;\nuse quote::{ToTokens, format_ident, quote};\nuse r#str"
},
{
"path": "specta-macros/src/type/serde.rs",
"chars": 17884,
"preview": "use proc_macro2::TokenStream;\nuse quote::quote;\nuse syn::{Attribute, LitStr, Meta, Result, Type, meta::ParseNestedMeta};"
},
{
"path": "specta-macros/src/type/struct.rs",
"chars": 6239,
"preview": "use crate::{\n r#type::field::construct_field,\n utils::{parse_attrs_with_filter, unraw_raw_ident},\n};\nuse proc_macr"
},
{
"path": "specta-macros/src/utils.rs",
"chars": 11338,
"preview": "use proc_macro2::Span;\nuse quote::ToTokens;\nuse syn::{\n Expr, Ident, Lit, Meta, Path, Result, Token, Type, TypePath,\n"
},
{
"path": "specta-openapi/Cargo.toml",
"chars": 771,
"preview": "[package]\nname = \"specta-openapi\"\ndescription = \"Export your Rust types to OpenAPI\"\nversion = \"0.0.2\"\nauthors = [\"Oscar "
},
{
"path": "specta-openapi/src/lib.rs",
"chars": 12346,
"preview": "//! [OpenAPI](https://www.openapis.org) language exporter for [Specta](specta).\n//!\n//! <div class=\"warning\">\n//! This c"
},
{
"path": "specta-serde/Cargo.toml",
"chars": 905,
"preview": "[package]\nname = \"specta-serde\"\ndescription = \"Serde support for Specta\"\nversion = \"0.0.11\"\nauthors = [\"Oscar Beaumont <"
},
{
"path": "specta-serde/README.md",
"chars": 2667,
"preview": "# Specta Serde\n\n[Serde](https://serde.rs) support for [Specta](https://github.com/specta-rs/specta).\n\nThis allows for ap"
},
{
"path": "specta-serde/src/error.rs",
"chars": 8467,
"preview": "use std::{borrow::Cow, error, fmt};\n\n/// Error type for serde transformation and validation failures.\n#[non_exhaustive]\n"
},
{
"path": "specta-serde/src/inflection.rs",
"chars": 5145,
"preview": "//! This file has been directed copied from Serde (<https://github.com/serde-rs/serde/blob/master/serde_derive/src/inter"
},
{
"path": "specta-serde/src/lib.rs",
"chars": 86970,
"preview": "//! [Serde](https://serde.rs) support for Specta.\n//!\n//! # Choosing a mode\n//!\n//! - Use [`Format`] when serde behavior"
},
{
"path": "specta-serde/src/parser.rs",
"chars": 12420,
"preview": "#![allow(missing_docs)]\n\nuse crate::{Error, inflection::RenameRule};\nuse specta::datatype::{Attributes, DataType};\n\ncons"
},
{
"path": "specta-serde/src/phased.rs",
"chars": 1729,
"preview": "use std::marker::PhantomData;\n\nuse specta::{\n Type, Types,\n datatype::{DataType, Reference},\n};\n\n/// Declares an e"
},
{
"path": "specta-serde/src/repr.rs",
"chars": 1779,
"preview": "use std::borrow::Cow;\n\nuse specta::datatype::Attributes;\n\nuse crate::{Error, parser::SerdeContainerAttrs};\n\n/// Serde re"
},
{
"path": "specta-serde/src/validate.rs",
"chars": 24717,
"preview": "use std::collections::HashSet;\n\nuse specta::{\n Types,\n datatype::{DataType, Enum, Field, Fields, NamedReferenceTyp"
},
{
"path": "specta-swift/Cargo.toml",
"chars": 1449,
"preview": "[package]\nname = \"specta-swift\"\ndescription = \"Export your Rust types to Swift\"\nversion = \"0.0.2\"\nauthors = [\"Jamie Pine"
},
{
"path": "specta-swift/README.md",
"chars": 10618,
"preview": "# Specta Swift\n\n[](https://crates.io/crates/specta-swift)\n"
},
{
"path": "specta-swift/Types.swift",
"chars": 314,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\npublic struct MyOtherType: Codable {\n publ"
},
{
"path": "specta-swift/examples/README.md",
"chars": 7206,
"preview": "# specta-swift Examples\n\nThis directory contains comprehensive examples demonstrating ALL the functionality of the `spec"
},
{
"path": "specta-swift/examples/advanced_unions.rs",
"chars": 4981,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::Swift;\n\n/// Advanced example showcasing"
},
{
"path": "specta-swift/examples/basic_types.rs",
"chars": 3704,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::Swift;\n\n/// Comprehensive example showc"
},
{
"path": "specta-swift/examples/comments_example.rs",
"chars": 4159,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::Swift;\n\n/// A comprehensive example dem"
},
{
"path": "specta-swift/examples/comprehensive_demo.rs",
"chars": 10556,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::Swift;\nuse std::time::Duration;\n\n/// Co"
},
{
"path": "specta-swift/examples/configuration_options.rs",
"chars": 9952,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::{GenericStyle, IndentStyle, NamingConve"
},
{
"path": "specta-swift/examples/generated/AdvancedUnions.swift",
"chars": 13031,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\n/// Advanced example showcasing complex enum "
},
{
"path": "specta-swift/examples/generated/BasicTypes.swift",
"chars": 5878,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\n/// Generic struct demonstrating type paramet"
},
{
"path": "specta-swift/examples/generated/CamelCase.swift",
"chars": 3141,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\npublic enum apiResponse<T> {\n case success"
},
{
"path": "specta-swift/examples/generated/CombinedConfig.swift",
"chars": 3200,
"preview": "// My Custom App Types\n// Generated with love ❤️\nimport Foundation\nimport Codable\nimport Equatable\nimport Hashable\n\npubl"
},
{
"path": "specta-swift/examples/generated/CommentsExample.swift",
"chars": 3578,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\n/// A comprehensive example demonstrating mul"
},
{
"path": "specta-swift/examples/generated/ComprehensiveDemo.swift",
"chars": 18480,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\n// MARK: - Duration Helper\n/// Helper struct "
},
{
"path": "specta-swift/examples/generated/CustomHeader.swift",
"chars": 3174,
"preview": "// Generated by MyAwesomeApp v2.0\n// Custom header with app info\n// DO NOT EDIT MANUALLY\nimport Foundation\n\npublic enum "
},
{
"path": "specta-swift/examples/generated/CustomTypes.swift",
"chars": 4352,
"preview": "// Generated by MyApp - Custom Header\nimport Foundation\n\npublic enum api_result<T> {\n case success(api_resultSuccessD"
},
{
"path": "specta-swift/examples/generated/DefaultConfig.swift",
"chars": 3141,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\npublic enum ApiResponse<T> {\n case success"
},
{
"path": "specta-swift/examples/generated/OptionalType.swift",
"chars": 3159,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\npublic enum ApiResponse<T> {\n case success"
},
{
"path": "specta-swift/examples/generated/PascalCase.swift",
"chars": 3141,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\npublic enum ApiResponse<T> {\n case success"
},
{
"path": "specta-swift/examples/generated/ProtocolGenerics.swift",
"chars": 3141,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\npublic enum ApiResponse<T> {\n case success"
},
{
"path": "specta-swift/examples/generated/QuestionMark.swift",
"chars": 3141,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\npublic enum ApiResponse<T> {\n case success"
},
{
"path": "specta-swift/examples/generated/SimpleTypes.swift",
"chars": 4426,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\npublic enum ApiResult<T> {\n case success(A"
},
{
"path": "specta-swift/examples/generated/SnakeCase.swift",
"chars": 2702,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\npublic enum api_response<T> {\n case succes"
},
{
"path": "specta-swift/examples/generated/Spaces2.swift",
"chars": 3141,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\npublic enum ApiResponse<T> {\n case success"
},
{
"path": "specta-swift/examples/generated/Spaces4.swift",
"chars": 3141,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\npublic enum ApiResponse<T> {\n case success"
},
{
"path": "specta-swift/examples/generated/SpecialTypes.swift",
"chars": 7158,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\n// MARK: - Duration Helper\n/// Helper struct "
},
{
"path": "specta-swift/examples/generated/StringEnums.swift",
"chars": 11207,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\n/// Mixed enum with both string-like and data"
},
{
"path": "specta-swift/examples/generated/Tabs.swift",
"chars": 3141,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\npublic enum ApiResponse<T> {\n case success"
},
{
"path": "specta-swift/examples/generated/TypealiasGenerics.swift",
"chars": 3141,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\n\npublic enum ApiResponse<T> {\n case success"
},
{
"path": "specta-swift/examples/generated/WithProtocols.swift",
"chars": 3205,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\nimport Equatable\nimport Hashable\nimport Custom"
},
{
"path": "specta-swift/examples/generated/WithSerde.swift",
"chars": 3156,
"preview": "// This file has been generated by Specta. DO NOT EDIT.\nimport Foundation\nimport Codable\n\npublic enum ApiResponse<T> {\n "
},
{
"path": "specta-swift/examples/simple_usage.rs",
"chars": 1522,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::Swift;\n\n// Simple user management types"
},
{
"path": "specta-swift/examples/special_types.rs",
"chars": 5457,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::Swift;\nuse std::time::Duration;\n\n/// Ex"
},
{
"path": "specta-swift/examples/string_enums.rs",
"chars": 5802,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::Swift;\n\n/// Comprehensive example showc"
},
{
"path": "specta-swift/src/error.rs",
"chars": 1262,
"preview": "//! Error types for the Swift language exporter.\n\nuse thiserror::Error;\n\n/// Errors that can occur during Swift code gen"
},
{
"path": "specta-swift/src/lib.rs",
"chars": 1491,
"preview": "//! [Swift](https://www.swift.org) language exporter for [Specta](specta).\n//!\n//! This crate provides functionality to "
},
{
"path": "specta-swift/src/primitives.rs",
"chars": 49343,
"preview": "//! Primitive type conversion from Rust to Swift.\n\nuse specta::{\n Format, Types,\n datatype::{\n DataType, En"
},
{
"path": "specta-swift/src/swift.rs",
"chars": 11411,
"preview": "//! Swift language exporter configuration and main export functionality.\n\nuse std::{borrow::Cow, fmt, path::Path};\n\nuse "
},
{
"path": "specta-swift/tests/Cargo.toml",
"chars": 326,
"preview": "[package]\nname = \"specta-swift-tests\"\nversion = \"0.0.0\"\nedition = \"2021\"\npublish = false\n\n[[test]]\nname = \"basic\"\npath ="
},
{
"path": "specta-swift/tests/advanced_unions.rs",
"chars": 5653,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::Swift;\n\n#[derive(Type)]\nstruct Point {\n"
},
{
"path": "specta-swift/tests/basic.rs",
"chars": 852,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::Swift;\n\n#[derive(Type)]\nstruct User {\n "
},
{
"path": "specta-swift/tests/common_types.rs",
"chars": 1647,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::Swift;\n\n// Test with common types that "
},
{
"path": "specta-swift/tests/comprehensive.rs",
"chars": 4224,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::Swift;\n\n#[derive(Type)]\nstruct User {\n "
},
{
"path": "specta-swift/tests/multiline_comments.rs",
"chars": 2469,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::Swift;\n\n/// A path within the Spacedriv"
},
{
"path": "specta-swift/tests/string_enum_implementation.rs",
"chars": 7836,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse serde::{Deserialize, Serialize};\nuse specta::{Type, Types};\nuse specta_swift::Sw"
},
{
"path": "specta-swift/tests/string_enum_test.rs",
"chars": 1561,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse serde::{Deserialize, Serialize};\nuse specta::{Type, Types};\nuse specta_swift::Sw"
},
{
"path": "specta-swift/tests/struct_reuse_test.rs",
"chars": 3061,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::Swift;\n\n#[derive(Type)]\nstruct UserData"
},
{
"path": "specta-swift/tests/struct_variants.rs",
"chars": 2831,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::Swift;\n\n/// Test enum with struct-like "
},
{
"path": "specta-swift/tests/unions.rs",
"chars": 4237,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::Swift;\n\n#[derive(Type)]\nstruct User {\n "
},
{
"path": "specta-swift/tests/uuid_simple.rs",
"chars": 1253,
"preview": "#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};\nuse specta_swift::Swift;\n\n// Test with UUID - this should"
},
{
"path": "specta-swift/tests/uuid_test.rs",
"chars": 1232,
"preview": "//! Integration tests for Swift UUID and chrono support.\n\n#![allow(dead_code, missing_docs)]\n\nuse specta::{Type, Types};"
},
{
"path": "specta-tags/Cargo.toml",
"chars": 1024,
"preview": "[package]\nname = \"specta-tags\"\ndescription = \"Analyze Specta datatypes and generate inline JavaScript transforms\"\nversio"
},
{
"path": "specta-tags/src/lib.rs",
"chars": 23665,
"preview": "//! Analyze Specta datatypes and generate inline JavaScript transforms.\n//!\n//! `TransformPlan` walks a resolved `specta"
},
{
"path": "specta-typescript/Cargo.toml",
"chars": 1210,
"preview": "[package]\nname = \"specta-typescript\"\ndescription = \"Export your Rust types to TypeScript\"\nversion = \"0.0.11\"\nauthors = ["
},
{
"path": "specta-typescript/bindings.ts",
"chars": 176,
"preview": "// This file has been generated by Specta. Do not edit this file manually.\nexport type MyOtherType = {\n\tother_field: str"
},
{
"path": "specta-typescript/src/branded.rs",
"chars": 3511,
"preview": "use std::borrow::Cow;\n\nuse specta::datatype::DataType;\n\n/// Create a branded tuple struct type that exports to TypeScrip"
},
{
"path": "specta-typescript/src/error.rs",
"chars": 15728,
"preview": "use std::{borrow::Cow, error, fmt, io, panic::Location, path::PathBuf};\n\nuse specta::datatype::OpaqueReference;\n\nuse cra"
},
{
"path": "specta-typescript/src/exporter.rs",
"chars": 42934,
"preview": "use std::{\n borrow::Cow,\n collections::{BTreeMap, BTreeSet, HashMap, HashSet},\n fmt,\n ops::Deref,\n panic:"
},
{
"path": "specta-typescript/src/jsdoc.rs",
"chars": 2461,
"preview": "use std::{borrow::Cow, path::Path};\n\nuse specta::{Format, Types};\n\nuse crate::{Branded, BrandedTypeExporter, Error, Expo"
},
{
"path": "specta-typescript/src/legacy.rs",
"chars": 30639,
"preview": "// TODO: Drop this stuff\n\nuse std::{\n borrow::Cow,\n collections::BTreeSet,\n fmt::{self, Write},\n};\n\nuse specta:"
},
{
"path": "specta-typescript/src/lib.rs",
"chars": 1822,
"preview": "//! [TypeScript](https://www.typescriptlang.org) language exporter.\n//!\n//! # Usage\n//!\n//! Add `specta`, `specta-serde`"
},
{
"path": "specta-typescript/src/map_keys.rs",
"chars": 9745,
"preview": "use std::collections::HashSet;\n\nuse specta::{\n Types,\n datatype::{DataType, Fields, Generic, NamedReferenceType, P"
},
{
"path": "specta-typescript/src/opaque.rs",
"chars": 637,
"preview": "use std::borrow::Cow;\n\nuse specta::datatype::Reference;\n\n#[derive(PartialEq, Eq, Hash)]\npub(crate) struct Define(pub(cra"
},
{
"path": "specta-typescript/src/primitives.rs",
"chars": 68031,
"preview": "//! Primitives provide building blocks for Specta-based libraries.\n//!\n//! These are for advanced usecases, you should g"
},
{
"path": "specta-typescript/src/references.rs",
"chars": 2770,
"preview": "use std::{cell::RefCell, collections::HashSet};\n\nuse specta::datatype::NamedReference;\n\nthread_local! {\n static REFER"
},
{
"path": "specta-typescript/src/reserved_names.rs",
"chars": 983,
"preview": "/// Taken from: https://github.com/microsoft/TypeScript/blob/fad889283e710ee947e8412e173d2c050107a3c1/src/compiler/types"
},
{
"path": "specta-typescript/src/types.rs",
"chars": 7690,
"preview": "use std::fmt::Debug;\n\nuse specta::{\n Type, Types,\n datatype::{DataType, Reference},\n};\n\nuse crate::opaque;\n\n/// Ca"
},
{
"path": "specta-typescript/src/typescript.rs",
"chars": 2434,
"preview": "use std::{borrow::Cow, path::Path};\n\nuse specta::{Format, Types};\n\nuse crate::{Branded, BrandedTypeExporter, Error, Expo"
},
{
"path": "specta-util/Cargo.toml",
"chars": 958,
"preview": "[package]\nname = \"specta-util\"\ndescription = \"High-level utilities for working with Specta\"\nversion = \"0.0.11\"\nauthors ="
},
{
"path": "specta-util/src/array.rs",
"chars": 1933,
"preview": "use std::marker::PhantomData;\n\nuse specta::{\n Type, Types,\n datatype::{DataType, List},\n};\n\n/// Declares a fixed-l"
},
{
"path": "specta-util/src/lib.rs",
"chars": 453,
"preview": "//! Extended functionality for [Specta](specta).\n\n#![cfg_attr(docsrs, feature(doc_cfg))]\n#![doc(\n html_logo_url = \"ht"
},
{
"path": "specta-util/src/remapper.rs",
"chars": 7578,
"preview": "use specta::{\n Types,\n datatype::{DataType, Fields, NamedReferenceType, Reference},\n};\n\n/// Recursively replaces ["
},
{
"path": "specta-util/src/selection.rs",
"chars": 2187,
"preview": "// TODO: Should `specta-util` rexport `specta` for these macros???\n\n/// Specta compatible selection of struct fields.\n//"
},
{
"path": "specta-zod/Cargo.toml",
"chars": 1179,
"preview": "[package]\nname = \"specta-zod\"\ndescription = \"Export your Rust types to Zod schemas for TypeScript\"\nversion = \"0.0.2\"\naut"
},
{
"path": "specta-zod/src/error.rs",
"chars": 8544,
"preview": "use std::{borrow::Cow, error, fmt, io, panic::Location, path::PathBuf};\n\nuse specta::datatype::OpaqueReference;\n\nuse cra"
},
{
"path": "specta-zod/src/lib.rs",
"chars": 688,
"preview": "//! [Zod](https://zod.dev) language exporter for [Specta](specta).\n//!\n//! <div class=\"warning\">\n//! This crate is still"
},
{
"path": "specta-zod/src/opaque.rs",
"chars": 576,
"preview": "use std::borrow::Cow;\n\nuse specta::datatype::Reference;\n\n#[derive(PartialEq, Eq, Hash)]\npub(crate) struct Define(pub(cra"
},
{
"path": "specta-zod/src/primitives.rs",
"chars": 28164,
"preview": "//! Primitives provide building blocks for Specta-based libraries.\n\nuse std::{borrow::Cow, fmt::Write as _};\n\nuse specta"
},
{
"path": "specta-zod/src/references.rs",
"chars": 2321,
"preview": "use std::{cell::RefCell, collections::HashSet};\n\nuse specta::datatype::NamedReference;\n\nthread_local! {\n static REFER"
},
{
"path": "specta-zod/src/reserved_names.rs",
"chars": 701,
"preview": "pub(crate) const RESERVED_TYPE_NAMES: &[&str] = &[\n \"break\",\n \"case\",\n \"catch\",\n \"class\",\n \"const\",\n \""
},
{
"path": "specta-zod/src/types.rs",
"chars": 2789,
"preview": "use std::fmt::Debug;\n\nuse specta::{\n Type, Types,\n datatype::{DataType, Reference},\n};\n\nuse crate::opaque;\n\n/// Ca"
},
{
"path": "specta-zod/src/zod.rs",
"chars": 26987,
"preview": "use std::{\n borrow::Cow,\n collections::{BTreeMap, BTreeSet, HashMap, HashSet},\n fmt,\n ops::Deref,\n path::"
},
{
"path": "tests/Cargo.toml",
"chars": 1785,
"preview": "[package]\nname = \"specta-tests\"\nversion = \"0.0.0\"\nedition = \"2024\"\npublish = false\nautotests = false\n\n[[test]]\nname = \"t"
},
{
"path": "tests/tests/bound.rs",
"chars": 2927,
"preview": "use specta::{Type, Types};\nuse specta_typescript::Typescript;\n\n#[derive(Type)]\n#[specta(bound = \"T: Clone + Type\", colle"
},
{
"path": "tests/tests/errors.rs",
"chars": 582,
"preview": "// TODO: Maybe should this be merged into other tests???\n\nuse std::io;\n\nuse specta::Type;\nuse thiserror::Error;\n\n#[deriv"
},
{
"path": "tests/tests/functions.rs",
"chars": 10685,
"preview": "use std::fmt;\n\nuse specta::{\n Format as _, Type, Types,\n datatype::{DataType, Function},\n function::{self, fn_d"
},
{
"path": "tests/tests/jsdoc.rs",
"chars": 11764,
"preview": "use std::{\n path::Path,\n time::{Duration, SystemTime},\n};\n\nuse specta::datatype::{DataType, Reference};\nuse specta"
},
{
"path": "tests/tests/layouts.rs",
"chars": 5449,
"preview": "use std::path::Path;\n\nuse specta::{\n Type, Types,\n datatype::{DataType, NamedDataType, Primitive},\n};\nuse specta_t"
},
{
"path": "tests/tests/legacy_impls.rs",
"chars": 10385,
"preview": "#![allow(deprecated)]\n\nuse specta::{Type, Types};\nuse specta_typescript::Typescript;\n\n#[derive(Debug)]\nstruct ErrorStack"
},
{
"path": "tests/tests/macro/compile_error.rs",
"chars": 3232,
"preview": "//! This file is run with the `trybuild` crate to assert compilation errors in the Specta macros.\n\nuse specta::{Type, sp"
},
{
"path": "tests/tests/macro/compile_error.stderr",
"chars": 8604,
"preview": "error: unsupported serde casing: `camelCase123`\n --> tests/macro/compile_error.rs:8:22\n |\n8 | #[serde(rename_all = \"cam"
},
{
"path": "tests/tests/mod.rs",
"chars": 823,
"preview": "//! We register a single entrypoint so all tests are compiled into a single binary.\n#![allow(unused_parens, unused_varia"
},
{
"path": "tests/tests/references.rs",
"chars": 2427,
"preview": "use std::any::TypeId;\n\nuse specta::{\n Type, Types,\n datatype::{DataType, Reference},\n};\n\n#[derive(Type)]\n#[specta("
},
{
"path": "tests/tests/serde_conversions.rs",
"chars": 11116,
"preview": "use serde::{Deserialize, Serialize};\nuse specta::{Type, Types};\nuse specta_typescript::Typescript;\n\n#[derive(Type, Seria"
},
{
"path": "tests/tests/serde_identifiers.rs",
"chars": 1877,
"preview": "use serde::Deserialize;\nuse specta::{Type, Types};\nuse specta_typescript::Typescript;\n\n#[derive(Type, Deserialize)]\n#[sp"
},
{
"path": "tests/tests/serde_other.rs",
"chars": 1650,
"preview": "// Regression test for https://github.com/specta-rs/specta/issues/131\n\nuse serde::Deserialize;\nuse specta::{Type, Types}"
},
{
"path": "tests/tests/snapshots/test__bound__bound-associated-type-issue-138.snap",
"chars": 171,
"preview": "---\nsource: tests/tests/bound.rs\nexpression: output\n---\n// This file has been generated by Specta. Do not edit this file"
},
{
"path": "tests/tests/snapshots/test__jsdoc__export-many-raw.snap",
"chars": 25465,
"preview": "---\nsource: tests/tests/jsdoc.rs\nexpression: output\n---\n/**\n\t* @typedef {{\n\t*\t\tstart: T,\n\t*\t\tend: T,\n\t*\t}} Range<T>\n\t* @"
},
{
"path": "tests/tests/snapshots/test__jsdoc__export-many-serde.snap",
"chars": 28618,
"preview": "---\nsource: tests/tests/jsdoc.rs\nexpression: output\n---\n/**\n\t* @typedef {{\n\t*\t\tstart: T,\n\t*\t\tend: T,\n\t*\t}} Range<T>\n\t* @"
},
{
"path": "tests/tests/snapshots/test__jsdoc__export-many-serde_phases.snap",
"chars": 29233,
"preview": "---\nsource: tests/tests/jsdoc.rs\nexpression: output\n---\n/**\n\t* https://github.com/specta-rs/specta/issues/374\n\t*\n\t* @ty"
},
{
"path": "tests/tests/snapshots/test__jsdoc__export-raw.snap",
"chars": 30791,
"preview": "---\nsource: tests/tests/jsdoc.rs\nexpression: output\n---\nRange<i32>: /**\n\t* @typedef {{\n\t*\t\tstart: T,\n\t*\t\tend: T,\n\t*\t}} R"
},
{
"path": "tests/tests/snapshots/test__jsdoc__export-serde.snap",
"chars": 33944,
"preview": "---\nsource: tests/tests/jsdoc.rs\nexpression: output\n---\nRange<i32>: /**\n\t* @typedef {{\n\t*\t\tstart: T,\n\t*\t\tend: T,\n\t*\t}} R"
},
{
"path": "tests/tests/snapshots/test__jsdoc__export-serde_phases.snap",
"chars": 34624,
"preview": "---\nsource: tests/tests/jsdoc.rs\nexpression: output\n---\nIssue374: /**\n\t* https://github.com/specta-rs/specta/issues/374"
},
{
"path": "tests/tests/snapshots/test__jsdoc__inline-raw.snap",
"chars": 13074,
"preview": "---\nsource: tests/tests/jsdoc.rs\nexpression: output\n---\ni8: number\ni16: number\ni32: number\nu8: number\nu16: number\nu32: n"
},
{
"path": "tests/tests/snapshots/test__jsdoc__inline-serde.snap",
"chars": 15257,
"preview": "---\nsource: tests/tests/jsdoc.rs\nexpression: output\n---\ni8: number\ni16: number\ni32: number\nu8: number\nu16: number\nu32: n"
}
]
// ... and 79 more files (download for full content)
About this extraction
This page contains the full source code of the specta-rs/specta GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 279 files (2.9 MB), approximately 772.6k tokens, and a symbol index with 1691 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.