Crates.io | verty |
lib.rs | verty |
version | 0.1.1 |
source | src |
created_at | 2024-11-27 22:12:21.873975 |
updated_at | 2024-11-27 22:25:45.716715 |
description | procedural macro to generate different versions of a type |
homepage | |
repository | https://codeberg.org/T0mstone/verty |
max_upload_size | |
id | 1463692 |
size | 75,463 |
This is a procedural macro that makes writing types that have multiple versions short and easy!
This is done by just putting #[versioned]
on a single type definition,
which will then be converted into multiple types (one for each version)
and, optionally, an enum of all versions of the type.
The versions have to be usize
s.
use verty::versioned;
# #[versioned(start = 1, end = 3)] struct Schema { /* ... */}
#[versioned(start = 1)]
struct CustomerData {
name: String,
#[ver = 1..=2]
age: u8,
#[ver = 3..]
is_over_18: bool,
last_login_ip: ver_match! {
1 => { std::net::Ipv4Addr };
2.. => { std::net::IpAddr }
},
#[ver = 2]
agreed_to_cookies: bool,
schema: VerType!(Schema),
}
expands to
# #[verty::versioned(start = 1, end = 3)] struct Schema { /* ... */}
struct CustomerDataV1 {
name: String,
age: u8,
last_login_ip: std::net::Ipv4Addr,
schema: SchemaV1
}
struct CustomerDataV2 {
name: String,
age: u8,
last_login_ip: std::net::IpAddr,
agreed_to_cookies: bool,
schema: SchemaV2
}
struct CustomerDataV3 {
name: String,
is_over_18: bool,
last_login_ip: std::net::IpAddr,
schema: SchemaV3
}
All three kinds of types are supported: struct
, enum
, union
.
You can put a #[ver = <range>]
helper attribute on any
fields, variants, variant fields, or generic parameters
to restrict which versions of the type they appear in.
usize
literals or a single usize
literal
(e.g. 2
is equivalent to 2..=2
)<input>V<n>
by default,
where <input>
is the name of the input type and <n>
is the version.You can put a #[ver_attr(<range>, <attr>)]
helper attribute anywhere
to apply #[<attr>]
in its place, but only for versions in <range>
.
This works exactly like #[cfg_attr(...)]
.
You can put a #[ver_where(<range>, <clauses>)]
helper attribute on the type definition
to apply where <clauses>
to it, but only for versions in <range>
.
You can use the ver_match!
pseudo-macro to produce a statement/expression/type/item
depending on the expanded version.
The syntax is ver_match! { $(<range> => { <anything> });+ $(;)? }
.
Note that each version must appear exactly once, no more, no less.
You can use the VerType!
pesudo-macro as a field type to get version-dependent types.
For example, VerType!(Foo)
expands to FooV<n>
in version <n>
.
VerType!
can also contain pseudo-macros, which are expanded accordingly,
for example VerType!(Bar<ver_gen!(1, T)>)
would expand to BarV0<>
for version 0 and BarV1<T>
for version 1.You can use the ver_gen!
pseudo-macro in generic argument lists to only include a generic argument for a given version.
Its syntax is ver_gen!(<range>, <generic argument>)
.
You can give arguments to the macro (#[versioned(<args>)]
instead of #[versioned]
) to influence code generation.
The options are comma-separated, with the following possibilities:
start = <n>
: Let <n>
be the first version instead of 0. This is probably mostly useful with 1 (i.e. start = 1
).
Also makes ..<m>
ranges start with <n>
instead of 0.
Also makes using a version number below it anywhere an error.end = <n>
: Let <n>
be the last version instead of the highest mentioned one.
Also makes using a version number above it anywhere an error.rename(<n> => <ident>)
: Rename the type for version <n>
to <ident>
.duplicate
is very useful to copy-paste items with slight changes between each of them,
but it requires a moderate amount of boilerplate,
especially when you have more complex differences between the different copies.