verty

Crates.ioverty
lib.rsverty
version0.1.1
sourcesrc
created_at2024-11-27 22:12:21.873975
updated_at2024-11-27 22:25:45.716715
descriptionprocedural macro to generate different versions of a type
homepage
repositoryhttps://codeberg.org/T0mstone/verty
max_upload_size
id1463692
size75,463
T0mstone (T0mstone)

documentation

README

Versioned types for Rust

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 usizes.

Example

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
}

Features

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.

  • The number of versions the type has will be determined by the highest version explicitly mentioned in any of these helper attributes.
  • The range must be a range literal of usize literals or a single usize literal (e.g. 2 is equivalent to 2..=2)
  • The version types are called <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>.

  • The input of 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>.

Similar crates

  • 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.
Commit count: 0

cargo fmt