10 个版本

0.3.5 2024 年 8 月 13 日
0.3.4 2024 年 8 月 8 日
0.2.2 2024 年 8 月 4 日
0.2.0 2024 年 7 月 23 日
0.1.0 2024 年 2 月 17 日

#389数据结构

Download history 2/week @ 2024-05-27 133/week @ 2024-07-22 267/week @ 2024-07-29 471/week @ 2024-08-05 134/week @ 2024-08-12

1,005 每月下载量
用于 fracter

MIT 许可证

21KB
75

Seoul-Rs

Crates.io docs.rs

  • Enum 数据类型派生特质 Isomorphism
  • StructEnum 数据类型派生特质 Tuplike
  • StructEnum 数据类型派生特质 Reflica
  • Enum 数据类型派生特质 IntoWrap

特质 Isomorphism

  • 针对 enum 数据类型。使用 derive 宏方便地进行枚举值转换。

  • 基本方法

    • fn title(&self) ->String;
    • fn list() -> Vec<Self>;
  • derive 宏还实现了

    • Into<T>Self&Self
    • From<T>From<&T>Self (当 Default 实现,并给出 "has_default" 语法时)

derive 语法和后备

  • 当在变体级别未给出 title 时,将使用变体的名称(Ident)作为标题。
  • 当在顶级属性级别未给出 list 时,将返回每个变体的默认格式列表。
  • 当在变体级别未给出 into 值时,将使用 <Into<T>> 特质中的类型(T)的默认值。
  • 当类型实现了 Default 且在顶级属性级别给出了 has_default 时,将为每个给定的 into 类型(T)实现 From<T>From<&T>

示例

use seoul::Isomorphism;

#[derive(PartialEq, Debug, Isomorphism)]
#[isomorphism(u8, list=[A, B(10)])]
enum ABC {
  #[into(0)] #[title("A")] A,
  #[into(1)] B(i32),
  C,
}

// `list()`
let list = ABC::list();
assert_eq!(list, vec![ABC::A, ABC::B(10)]);

let a: ABC = ABC::A;
let b = ABC::B(10);
let c = ABC::C;

// `title()`
assert_eq!(a.title(), "A");
assert_eq!(b.title(), "B");
assert_eq!(c.title(), "C");

// `Into<T>` for `&Self` and `Self`
assert_eq!(Into::<u8>::into(&a), 0);
assert_eq!(Into::<u8>::into(a), 0);
assert_eq!(Into::<u8>::into(&b), 1);
assert_eq!(Into::<u8>::into(c), 0);
#[derive(Default, Debug, Isomorphism, PartialEq)]
#[isomorphism(into=[u8, i8], has_default)]
pub enum CD {
  #[default] #[into([0, 1])] C,
  #[into([0, -1])] D,
}

// list
assert_eq!(CD::list(), vec![CD::C, CD::D]);

// Into
assert_eq!(Into::<u8>::into(CD::C), 0);
assert_eq!(Into::<i8>::into(CD::C), 1);
assert_eq!(Into::<u8>::into(CD::D), 0);
assert_eq!(Into::<i8>::into(CD::D), -1);

// From
assert_eq!(Into::<CD>::into(1i8), CD::C);
assert_eq!(Into::<CD>::into(-1i8), CD::D);
// fallback to default value of `CD`
assert_eq!(Into::<CD>::into(-0i8), CD::C);

特质 Tuplike

  • 针对 struct 数据类型。将结构化数据转换为 tuple 格式。

    • AB { a: 0, b: 10 } <=> (0, 10)
  • 使用 derive 宏,您可以实现

    • From<T> trait 实现 Self
    • Into<T> trait 实现 Self
    • Into<R> trait 实现 &Self
    • 因此,T 是结构体字段的元组格式,
    • R 是它们的引用元组格式。
  • 对于枚举数据类型,每个变体将只实现 From<T> trait。

示例

use seoul::Tuplike;

#[derive(Debug, Clone, PartialEq, Tuplike)]
struct AB {
  a: u8, b: String
}

let tuple_: (u8, String) = (0, "string".to_string());
let ab_: AB = AB { a: 0, b: "string".to_string() };

let ab_into: (u8, String) = ab_.clone().into();
let tuple_into: AB = tuple_.clone().into();

assert_eq!(&ab_into, &tuple_);
assert_eq!(&tuple_into, &ab_);

let _ab_ref_into: (&u8, &String) = (&ab_).into();


// for enum, just `From<T>` will be implemented for each variant.
#[derive(Debug, Clone, PartialEq, Tuplike)]
enum ABC {
  A,
  B(String),
  C { a: i32, b: String }
}

let _ = ABC::A;

let b1: (String,) = ("string".to_string(),);
let b2: ABC = ABC::B("string".to_string());

let b1_: ABC = b1.clone().into();

assert_eq!(&b1_, &b2);

let c1: (i32, String) = (10, "string".to_string());
let c2: ABC = ABC::C { a: 10, b: "string".to_string() };
let c1_: ABC = c1.clone().into();

assert_eq!(&c1_, &c2);

Reflica trait

  • 从原始结构体/枚举数据类型声明借用字段的类型("reflica"),并实现 Into trait 到 reflica。

  • reflica 概念

    • 结构体 AB { a: u8, b:String} ->
      • 声明 struct RefAB<'a> { a: &'a u8, b: &'a String }
      • 实现 Into<RefAB<'a>> for &'a AB
    • 枚举 AB {A,B{a: u8,b: String } } ->
      • 声明 enum RefAB<'a> { A, B { a: &'a u8, b: &'a String } }
      • 实现 Into<RefAB<'a>> for &'a AB

示例

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)]
// `prefix` attribute's string value will be used for reflica's prefix, other than the basic prefix `Ref`
#[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();

IntoWrap trait

  • 为枚举类型数据中的每个变体实现 From traits,当变体有一个未命名字段时,将字段数据转换为枚举数据。

  • 因此,每个变体不应有任何冗余类型或泛型,以避免任何冲突实现。

  • IntoWrap 可以被视为为枚举的包装变体而设计的 Tuplike 的非元组单变量版本。

示例

use seoul::IntoWrap;

#[derive(Debug, Clone, PartialEq, IntoWrap)]
enum ABCD {
  A, // skip
  B(i32), // impl From<i32> for ABCD
  C { a: i32 }, // skip
  D(String) // impl From<String> for ABCD
}

let _ = ABCD::A;
let _ = ABCD::C { a: 10 };

let b: i32 = 10;
let b: ABCD = b.into();

let d = "string".to_string();
let d: ABCD = d.into();

assert_eq!(b, ABCD::B(10));
assert_eq!(d, ABCD::D("string".to_string()));


#[derive(Debug, Clone, PartialEq, IntoWrap)]
enum AB<X: Clone, Y> where Y: Clone {
  A((X, X)), // impl<X: Clone, Y> From<X, X> for AB where Y: Clone
  B(Vec<Y>) // impl<X: Clone, Y> From<Vec<X>> for AB where Y: Clone
}

let a: (String, String) = ("x".to_string(), "x".to_string());
let a: AB<String, i32> = a.into();

let b: Vec<i32> = vec![0, 1, 2];
let b: AB<String, i32> = b.into();

assert_eq!(a, AB::<String, i32>::A(("x".to_string(), "x".to_string())));
assert_eq!(b, AB::<String, i32>::B(vec![0, 1, 2]));


// This case won't work due to conflicting implementations.
/*#[derive(Debug, Clone, PartialEq, IntoWrap)]
enum AB<X: Clone, Y> where Y: Clone {
  A(X),
  B(Vec<Y>)
}*/

开发日志

- ver.0.2.0
  - `From<T>` implemented only with `has_default` attribute syntax when `Default` is implemented.
- ver 0.2.1~2
  - correct some typos

- ver 0.3.0
  - Add `Tuplike`.
- ver 0.3.1
  - Add an associated type `Tuple` to the trait `Tuplike`

- ver 0.3.2
  - Add `Reflica`

- ver 0.3.3
  - On `Tuplike`:
    - delete associated type `Tuple` from the trait.
    - derive macro now works on the enum type too: but only `From<T>` trait will be implemented for each variant.
  - Add `IntoWrap`

- ver 0.3.5
  - On `Isomorphism`:
    - Reinforced derive macro's generic parsing ability.
    - For struct type, the derive macro would only implement the Isormophism trait with each methods of it returning default values.

依赖项

约290–750KB
约18K SLoC