| Crates.io | seoul |
| lib.rs | seoul |
| version | 1.0.0 |
| created_at | 2024-02-17 02:28:03.692632+00 |
| updated_at | 2025-10-18 05:26:51.243677+00 |
| description | trait Isomorphism |
| homepage | |
| repository | https://github.com/acheul/seoul-rs |
| max_upload_size | |
| id | 1142960 |
| size | 12,453 |
✈️ V1.0.0 has major updates from former versions. See Version Log for changes.
Implement bunch of Into and From traits for isomorphic transformation.
StructInto<Field> for SelfInto<&Field> for &SelfInto<&mut Field> for &mut SelfFrom<(Field1, Field2, ..)> for SelfInto<(Field1, Field2, ..)> for SelfInto<(&Field1, &Field2, ..)> for &SelfInto<(&mut Field1, &mut Field2, ..)> for &mut Self#[isomorphism(into_field)]
#[into_field(skip)] attribute or redundant types already captured in preceding fields will not be invoked.#[isomorphism(intofrom_tuple)]
#[into_field] / #[into_field(skip)]
#[into_field] attribute still invoke into_field regardless of the container attribute.#[into_field(skip)] do not invoke into_field implements for themselves even though the container attribute has into_field.use seoul::Isomorphism;
#[derive(Debug, Clone, PartialEq, Isomorphism)]
#[isomorphism(into_field, intofrom_tuple)]
struct ABC<T> {
a: i32,
b: String,
c: Vec<T>,
}
let mut abc: ABC<String> = ABC {
a: 10i32,
b: "ABC".to_string(),
c: vec!["A".to_string()],
};
assert_eq!(Into::<&i32>::into(&abc), &10i32);
let x: (&mut i32, &mut String, &mut Vec<String>) = (&mut abc).into();
x.2.push("B".to_string());
let x: (&i32, &String, &Vec<String>) = (&abc).into();
assert_eq!(x.2, &["A".to_string(), "B".to_string()]);
let (a, b, mut c): (i32, String, Vec<String>) = abc.into();
c.push("C".to_string());
let abc: ABC<String> = (a, b, c).into();
assert!(abc.c.len() == 3);
EnumFrom<Varaint> for Selfpub fn name(&self) -> &str to the type's implement scope.name.Into<OtherType> for SelfInto<&OtherType> for SelfFrom<OtherType> for SelfFrom<&OtherType> for SelfContainer Attributes
#[isomorphism(from_variant)]
impl From<Field> for Selfimpl From<(Field1, Field2, ..)> for Selfimpl From<()> for Self#[from_variant(skip)] attribute or redundant types already captured in preceding variants will not be invoked.#[isomorphism(name_variant)] / #[isomorphism(name_variant = "specific_method_name")]
name, it can be changed by passing a specific name in the attribute.For convert:
#[isomorphism(into = u8)]
#[isomorphism(default_into = 10u8)]
#[isomorphism(skip_restore)]
From<(&)OtherType> for Self#[isomorphism(skip_ref_restore)]
From<&OtherType> for Self#[isomorphism(restore_panic = "panic..!")]
From<(&)OtherType> for Self's match syntax, the rest cases will invoke panic with the given panic literal: _ => panic!("panic..!").#[isomorphism(default_restore = SelfValue)]
In the From<(&)OtherType> for Self's match syntax, if the restore_panic is not given, this value will be used for rest cases's match: _ => SelfValue.
If default_restore is not given either, the default value of Self type will be used: _ => Self::default(). (Then it must impl Default)
Variant Attributes
#[from_variant] / #[from_variant(skip)]
#[from_variant] attribute still invoke from_variant regardless of the container attribute.#[from_variant(skip)] do not invoke from_variant implements for themselves even though the container attribute has from_variant.#[name("specific_var_name")]
#[into(10u8)]
default_into value - 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> for Self).
If it's not given, the default value for the variant will be used.
use seoul::Isomorphism;
#[derive(Debug, Clone, PartialEq, Isomorphism)]
#[isomorphism(from_variant, name_variant)]
enum ABC {
A(u32),
B { _a: String, _b: Vec<i32> },
C,
D(u32, i32),
}
let x: ABC = 10u32.into();
assert_eq!(x, ABC::A(10u32));
assert_eq!(x.name(), "A");
let x: ABC = ("string".to_string(), vec![10i32]).into();
assert_eq!(x, ABC::B { _a: "string".to_string(), _b: vec![10i32] });
assert_eq!(x.name(), "B");
let x: ABC = ().into();
assert_eq!(x, ABC::C);
let x: ABC = (10u32, 11i32).into();
assert_eq!(x, ABC::D(10u32, 11i32));
use seoul::Isomorphism;
#[derive(Debug, Clone, PartialEq, Isomorphism)]
#[isomorphism(into = u8, default_into = 5u8, default_restore = ABC::A)]
enum ABC {
#[into(10)]
A,
#[into(20)]
B,
#[into(30)]
C,
D,
}
assert_eq!(Into::<u8>::into(ABC::A), 10u8);
assert_eq!(Into::<u8>::into(ABC::D), 5u8);
assert_eq!(Into::<ABC>::into(&20), ABC::B);
assert_eq!(Into::<ABC>::into(0), ABC::A);
Declare a borrowed fields' data type ("reflica") from an original struct/enum data type, and implement Into trait to the reflica.
struct AB { a: u8, b: String } ->
struct RefAB<'a> { a: &'a u8, b: &'a String }Into<RefAB<'a>> for &'a ABenum AB { A, B { a: u8, b: String } } ->
enum RefAB<'a> { A, B { a: &'a u8, b: &'a String } }Into<RefAB<'a>> for &'a AB#[reflica(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[derive(...)] attribute of the new Reflica data type.reflica attribute, any path with name other than prefix will be counted as a trait.#[reflica(prefix="SpecificPrefix")]
Ref + Original type's name. However other prefix name can be passed with the prefix path.use seoul::Reflica;
// struct
#[derive(Reflica)]
// attribute for derive implementation for the reflica
#[reflica(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
struct AB<I> {
a: u8,
b: I
}
// RefAB delcared
let _: RefAB<String> = RefAB { a: &8, b: &String::from("ab") };
// check Into<RefAB> for &AB
let x = AB { a: 0, b: String::from("x")};
let _: RefAB<String> = (&x).into();
// check derive `Ord`
let a: RefAB<u8> = RefAB { a: &2, b: &10 };
let b: RefAB<u8> = RefAB { a: &2, b: &11 };
let c: RefAB<u8> = RefAB { a: &3, b: &10 };
let x = vec![a, b, c];
let mut y = x.clone();
y.sort();
assert_eq!(x, y);
// enum, use prefix other than basic `Ref`
#[derive(Reflica)]
#[reflica(Clone, Copy, Debug, prefix="Ref2")]
enum ABC<I> where I: Clone {
A,
B { a: u8, b: I },
C(u8)
}
// Ref2AB delcared
let _: Ref2ABC<u8> = Ref2ABC::A;
let _: Ref2ABC<String> = Ref2ABC::B { a: &8, b: &String::from("ab") };
// check Into<Ref2AB>
let x = ABC::B { a: 0, b: String::from("x")};
let _: Ref2ABC<String> = (&x).into();
let x = ABC::<u8>::C(0);
let _: Ref2ABC<u8> = (&x).into();