Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/duskmoon314/utility-rs
Try impl TypeScript's utility types in rust via proc_macro
https://github.com/duskmoon314/utility-rs
proc-macro rust
Last synced: 12 days ago
JSON representation
Try impl TypeScript's utility types in rust via proc_macro
- Host: GitHub
- URL: https://github.com/duskmoon314/utility-rs
- Owner: duskmoon314
- License: mit
- Created: 2021-11-25T09:06:00.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2024-07-30T10:28:27.000Z (3 months ago)
- Last Synced: 2024-10-10T20:49:43.931Z (28 days ago)
- Topics: proc-macro, rust
- Language: Rust
- Homepage: https://crates.io/crates/utility-types
- Size: 32.2 KB
- Stars: 21
- Watchers: 2
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# utility types
This crate use proc-macro to realize several utility types of Typescript in Rust.
| macro | Typescript Utility Type |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| [Partial] | [Partial\](https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype) |
| [Pick] | [Pick\](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys) |
| [Omit] | [Omit\](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys) |
| [Extract] | [Extract\](https://www.typescriptlang.org/docs/handbook/utility-types.html#extracttype-union) |
| [Exclude] | [Exclude\](https://www.typescriptlang.org/docs/handbook/utility-types.html#excludeuniontype-excludedmembers) |## Example
Here is an example of how to use this crate.
```rust
use utility_types::{Omit, Partial, Pick, Required};
#[derive(Clone, Partial, Required, Pick, Omit)]
#[partial(ident = PartialFoo, derive(Debug, PartialEq), forward_attrs())]
#[required(ident = RequiredFoo, derive(Debug, PartialEq), forward_attrs())]
#[pick(arg(ident = PickAB, fields(a, b), derive(Debug, PartialEq)), forward_attrs())]
#[omit(arg(ident = OmitCD, fields(c, d), derive(Debug, PartialEq)), forward_attrs())]
pub struct Foo {
a: u8,
b: Option,
c: Option>,
}
```The above code will generate the following code.
```rust
#[derive(Debug, PartialEq)]
pub struct PartialFoo {
a: Option,
b: Option>,
c: Option>>,
}
#[derive(Debug, PartialEq)]
pub struct RequiredFoo {
a: u8,
b: u8,
c: Vec,
}
#[derive(Debug, PartialEq)]
pub struct PickAB {
a: u8,
b: Option,
}
#[derive(Debug, PartialEq)]
pub struct OmitCD {
a: u8,
b: Option,
}
```Some useful traits are also generated:
- `From` for `PartialFoo`, `PickAB`, `OmitCD`
- `From` for `Foo`### Forwarding Attributes
To use this crate with other crates that need attributes, you can use the `forward_attrs` attribute to control which attributes are forwarded to the generated struct or enum.
```rust
use serde::{Deserialize, Serialize};
use utility_types::Omit;#[derive(Debug, PartialEq, Serialize, Deserialize, Omit)]
#[omit(
arg(
ident = OmitCD,
fields(c, d),
derive(Debug, PartialEq, Serialize, Deserialize),
forward_attrs(serde)
)
)]
#[serde(rename_all = "UPPERCASE")]
pub struct Foo {
a: u8,
b: Option,
c: Option>,
}let omit_cd: OmitCD = serde_json::from_str(r#"{"A": 1, "B": 2}"#).unwrap();
assert_eq!(omit_cd, OmitCD { a: 1, b: Some(2) });
```The behavior of the `forward_attrs` attribute is as follows:
- If **not provided**, all attributes are forwarded by default.
- If provided with a list of attributes, only the specified attributes are forwarded.
- For example, `forward_attrs(doc, serde)` will forward only `doc` and `serde`.
- If provided with **only `*`** (`forward_attrs(*)`), all attributes are forwarded.
- If provided with **an empty list** (`forward_attrs()`), no attributes are forwarded.
- If provided with a list inside `not()`, all attributes except the specified attributes are forwarded.
- For example, `forward_attrs(not(serde))` will forward all attributes except `serde`.## Known Issue
Currently I don't analyze which generic is used in the generated struct or enum. So rustc will complain if the field with generic is not included in the generated struct or enum.