# typeshift
`typeshift` provides a Zod-like parse workflow with idiomatic Rust types.
The struct or enum is the single source of truth. With one attribute, you get:
- `Serialize`
- `Deserialize`
- `Validate`
- `JsonSchema`
## Install
```toml
[dependencies]
typeshift = "0.5"
```
## Quick start
```rust
use typeshift::typeshift;
#[typeshift]
struct User {
#[validate(length(min = 3))]
name: String,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let user: User = typeshift::parse_str(r#"{"name":"Ada"}"#)?;
let json = typeshift::to_json(&user)?;
let schema = typeshift::schema_json::<User>();
assert_eq!(json, r#"{"name":"Ada"}"#);
assert_eq!(schema["type"], "object");
Ok(())
}
```
## API
- `parse_str<T: TypeShift>(&str) -> Result<T, TypeShiftError>`
- `to_json<T: TypeShift>(&T) -> Result<String, serde_json::Error>`
- `schema_json<T: TypeShift>() -> serde_json::Value`
## Notes
- `#[typeshift]` supports structs and enums, including generics.
- Enum variant fields with `#[validate(...)]` are validated during `parse_str`.
- Unions are intentionally not supported.
- `#[derive(TypeShift)]` is a legacy compatibility marker and does not generate impls.
- Current MSRV is Rust 1.81.
## Validation to schema mapping
`typeshift` uses `schemars` and forwards compatible `#[validate(...)]` attributes
into generated JSON Schema. Common mappings include:
- `#[validate(email)]` -> `format: "email"`
- `#[validate(url)]` -> `format: "uri"`
- `#[validate(length(...))]` -> `minLength` / `maxLength` (or `minItems` / `maxItems`)
- `#[validate(range(...))]` -> `minimum` / `maximum`
- `#[validate(regex(path = ...))]` -> `pattern`
- `#[validate(required)]` on `Option<T>` -> schema treats field as required `T`
Some validators are runtime-only and not directly representable as JSON Schema
(for example `custom`, `must_match`, and `nested` behavior).
## More examples
- `cargo run -p typeshift --example basic`
- `cargo run -p typeshift --example enum_tagged`
- `cargo run -p typeshift --example generic_envelope`
- `cargo run -p typeshift --example full_flow`