Seoul-Rs
A Procedural Macros Toolkit for Struct and Enum Types' Transformation
✈️ V1.0.0 has major updates from former versions. See Version Log for changes.
TOC
Trait Isomorphism
Implement bunch of Into and From traits for isomorphic transformation.
Isomorphism for Struct
Abilities
- into_field: Self ➡️ Each Field
- impl
Into<Field>forSelf - impl
Into<&Field>for&Self - impl
Into<&mut Field>for&mut Self
- impl
- intofrom_tuple: Self ↔️ Tuple of Fields
- impl
From<(Field1, Field2, ..)>forSelf - impl
Into<(Field1, Field2, ..)>forSelf - impl
Into<(&Field1, &Field2, ..)>for&Self - impl
Into<(&mut Field1, &mut Field2, ..)>for&mut Self
- impl
Attributes
- Container Attributes
-
#[isomorphism(into_field)]- Invoke into_field's implements for each fields.
- Fields with
#[into_field(skip)]attribute or redundant types already captured in preceding fields will not be invoked.
-
#[isomorphism(intofrom_tuple)]- Invoke intofrom_tuple's implements.
-
- Field Attributes
#[into_field]/#[into_field(skip)]- Fields with
#[into_field]attribute still invoke into_field regardless of the container attribute. - However ones with
#[into_field(skip)]do not invoke into_field implements for themselves even though the container attribute hasinto_field.
- Fields with
Examples
use Isomorphism;
let mut abc: = ABC ;
assert_eq!;
let x: = .into;
x.2.push;
let x: = .into;
assert_eq!;
let : = abc.into;
c.push;
let abc: = .into;
assert!;
Isomorphism for Enum
Abilities
- from_variant: Each Variant ➡️ Self
- impl
From<Varaint>forSelf
- impl
- name_variant
- Add a method with signature
pub fn name(&self) -> &strto the type's implement scope. - The method matches each variant into the variant's own name literal, while it can be specified differently by a variant attribute
name.
- Add a method with signature
- convert: Self ↔️ Other Type
- Convert each variant to other type's matching value, and vice versa.
- impl
Into<OtherType>forSelf - impl
Into<&OtherType>forSelf - impl
From<OtherType>forSelf - impl
From<&OtherType>forSelf
Attributes
-
Container Attributes
-
#[isomorphism(from_variant)]- Invoke from_variant's implements for each variants.
- For a variant with one field:
impl From<Field> for Self - One with multiple fields:
impl From<(Field1, Field2, ..)> for Self - One with no fields:
impl From<()> for Self
- For a variant with one field:
- Fields with
#[from_variant(skip)]attribute or redundant types already captured in preceding variants will not be invoked.
- Invoke from_variant's implements for each variants.
-
#[isomorphism(name_variant)]/#[isomorphism(name_variant = "specific_method_name")]- Invoke name_variant.
- While the default name of the method is
name, it can be changed by passing a specific name in the attribute.
-
For convert:
-
#[isomorphism(into = u8)]- Invoke convert. Specify the type for the convertion.
-
#[isomorphism(default_into = 10u8)]- When convert is invoked but a variant does not have specified convert-into value, this value will be matched. If this one is not given either, a default value of convert-into type will be used (The type must have Default then).
-
#[isomorphism(skip_restore)]- Do not implement neither
From<(&)OtherType>forSelf
- Do not implement neither
-
#[isomorphism(skip_ref_restore)]- Do not implement
From<&OtherType>forSelf
- Do not implement
-
#[isomorphism(restore_panic = "panic..!")]- In the
From<(&)OtherType>forSelf's match syntax, the rest cases will invoke panic with the given panic literal:_ => panic!("panic..!").
- In the
-
#[isomorphism(default_restore = SelfValue)]- In the
From<(&)OtherType>forSelf's match syntax, if therestore_panicis not given, this value will be used for rest cases's match:_ => SelfValue. - If
default_restoreis not given either, the default value of Self type will be used:_ => Self::default(). (Then it must impl Default)
- In the
-
-
-
Variant Attributes
#[from_variant]/#[from_variant(skip)]- Variants with
#[from_variant]attribute still invoke from_variant regardless of the container attribute. - However ones with
#[from_variant(skip)]do not invoke from_variant implements for themselves even though the container attribute hasfrom_variant.
- Variants with
#[name("specific_var_name")]- Specify the variant's matching name literal for name_variant's method.
#[into(10u8)]- Specify the variant's convert-into value for convert.
- If it's not given, container attribute's
default_intovalue - or, without it, the type's default value - will be used.
#[rstore(SelfValue)]- Specify the variant's value that will be converted from its matching convert-into value. (In
From<(&)OtherType>forSelf). - If it's not given, the default value for the variant will be used.
- Specify the variant's value that will be converted from its matching convert-into value. (In
Examples
use Isomorphism;
let x: ABC = 10u32.into;
assert_eq!;
assert_eq!;
let x: ABC = .into;
assert_eq!;
assert_eq!;
let x: ABC = .into;
assert_eq!;
let x: ABC = .into;
assert_eq!;
use Isomorphism;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
Trait Reflica
Declare a borrowed fields' data type ("reflica") from an original struct/enum data type, and implement Into trait to the reflica.
Abilities:
struct AB { a: u8, b: String }->- declare
struct RefAB<'a> { a: &'a u8, b: &'a String } - impl
Into<RefAB<'a>>for&'a AB
- declare
enum AB { A, B { a: u8, b: String } }->- declare
enum RefAB<'a> { A, B { a: &'a u8, b: &'a String } } - impl
Into<RefAB<'a>>for&'a AB
- declare
Attributes
- Container Attributes
-
#[reflica(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]- The traits listed will be passed to the
#[derive(...)]attribute of the new Reflica data type. - In the
reflicaattribute, any path with name other thanprefixwill be counted as a trait.
- The traits listed will be passed to the
-
#[reflica(prefix="SpecificPrefix")]- By default, the new Reflica type's name is determined by
Ref+Original type's name. However other prefix name can be passed with theprefixpath.
- By default, the new Reflica type's name is determined by
-
Example
use Reflica;
// struct
// attribute for derive implementation for the reflica
// RefAB delcared
let _: = RefAB ;
// check Into<RefAB> for &AB
let x = AB ;
let _: = .into;
// check derive `Ord`
let a: = RefAB ;
let b: = RefAB ;
let c: = RefAB ;
let x = vec!;
let mut y = x.clone;
y.sort;
assert_eq!;
// enum, use prefix other than basic `Ref`
// Ref2AB delcared
let _: = A;
let _: = B ;
// check Into<Ref2AB>
let x = ABCB ;
let _: = .into;
let x = ABC::C;
let _: = .into;