#tuple #enums #struct #from #into

intuple

将结构和枚举转换为元组和反向转换 - 递归,忽略字段

2个不稳定版本

0.2.0 2023年11月14日
0.1.0 2022年9月25日

#1657 in Rust模式

Download history

54 每月下载量
用于 2 个crate(通过 querio

MIT/Apache

15KB
77

功能

🐍 将 struct 转换为元组并反向转换
🦎 将 enum 转换为元组并反向转换
🦢 获取 struct 字段的(mut)引用元组
🐓 获取 enum 字段的(mut)引用元组
🦥 忽略特定字段
🦆 递归地完成所有操作

用法

🐠 在 Cargo.toml 中添加 intuple 依赖

[dependencies]
intuple = "0.2"

🦀 在 rust 中使用/导入所有内容

use intuple::*;

🦚 多种转换方式

#[derive(Intuple)]
struct Struct {a:u32, b:u32, c:u32}

fn main(){
    // use std traits
    let strct: Struct = (3,2,1).into();
    let tuple = <(u32, u32, u32)>::from(strct);
    let strct = Struct::from((3,2,1));
    let tuple: (u32, u32, u32) = strct.into();
    // OR intuple trait
    let strct = Struct::from_tuple((3,2,1));
    let tuple = strct.into_tuple(); // or strct.intuple()
    // references
    let strct = Struct::from_tuple((3,2,1));    
    let tupref = strct.as_tuple_ref(); // (&u32,&u32,&u32)
    let tupref = strct.as_tuple_ref_mut(); // (&mut u32,&mut u32,&mut u32)
    *tupref.1 = 3;
}

元组类型

🦊 通过限定路径访问生成的元组类型

#[derive(Intuple)]
struct Nice {a:u32, b:u32, c:u32}
fn main(){
    let tup: <Nice as Intuple>::Tuple = (3,2,1);
    let tup: (u32, u32, u32) = (3,2,1); // <- same as above
    // reference tuple types
    let tup: <Nice as IntupleRef>::Tuple = (&3,&2,&1);
    let tup: (&u32, &u32, &u32) = (&3,&2,&1); // <- same as above
    // mut reference tuple types
    let tup: <Nice as IntupleRef>::TupleMut = (&mut 3,&mut 2,&mut 1);
    let tup: (&mut u32, &mut u32, &mut u32) = (&mut 3,&mut 2,&mut 1); // <- same as above
}

忽略

🦥 使用 #[igno]/#[ignore] 忽略特定字段
🐻 或者 #[intuple(igno)]/#[intuple(ignore)]
🐼 在转换为结构时,被忽略的字段需要实现 Default 特性

#[derive(Intuple)]
struct Struct {a:u32, #[igno] b:u32, c:u32}
fn main(){
    let strct = Struct::from((2,1));     
    // => {a:2, b:0, c:1}  
    let tuple: (u32, u32) = strct.into();
    // => (2, 1)
}

递归

🦊 使用 #[recursive]/#[rcsv] 递归转换
🦐 或 #[intuple(rcsv)]/#[intuple(recursive)]
🐼 递归字段需要派生 Intuple

#[derive(Intuple)]
struct Struct {a:u32, b:u32, c:u32}
#[derive(Intuple)]
struct Recursive {a:u32, #[recursive] b:Struct, c:u32}
fn main(){
    let rcsv: Recursive = (9,(3,2,1),8).into(); 
    // => Recursive{a:9, b:Struct{a:3,b:2,c:1}, c:8}
    let tuple: RecursiveIntuple = rcsv.into(); 
    // => (9,(3,2,1),8)
}

🦆 递归也可以与 .as_tuple_ref()as_tuple_ref_mut() 一起使用

#[derive(Intuple)]
struct Struct {a:u32, b:u32, c:u32}
#[derive(Intuple)]
struct Recursive {a:u32, #[recursive] b:Struct, c:u32}
fn main(){
    let rcsv = Recursive::from((9,(3,2,1),8)); 
    let tuple = rcsv.as_tuple_ref(); 
    // => (&9,(&3,&2,&1),&8)
}

枚举

🙉 将枚举转换为元组不如结构体直接,因此实现了两种方法!

🐍 1. 位置法

🐆 使用 Intuple - 不生成额外的枚举或结构体
🐢 字段元组被包裹在 Option<> 中,这些又位于另一个元组内部
🦎 外部元组字段的数量与枚举变体的数量相同
🐊 所需的 None 变体将转换为 (None,None,None,...)
🐉 任何其他变体将占据一个槽位,具体取决于其位置 (None,Some(tuple),None,...)

// Positional
#[derive( Intuple, Debug )]
// enums require a 'None' variant
enum Enum { None, Unit, Unnamed(u32,u32), Another(u8,u8) }
fn main(){
    let enum = Enum::Unnamed(1,2); 
    let tuple = enum.as_tuple_ref(); 
    // => (None, Some((&1,&2)), None)
    let tuple = enum.into_tuple(); 
    // => (None, Some((1,2)), None)
    let enum = Enum::None; 
    let tuple = rcsv.into_tuple(); 
    // => (None,None,None)
}

🦊 2. 生成元组枚举

🐈 使用 IntupleEnum - 将生成 三个 额外的枚举
🐕 {EnumName}Intuple{EnumName}IntupleRef{EnumName}IntupleRefMut
🦄 这些枚举将使用原始变体名称并包含一个元组
🐔 要为它们设置派生,请使用 #[intuple(derive(...))]
⚠ 要在 任何地方 递归使用它们,请使用 #[recursive_enum]#[rcsve]
🦢 .into()/.from(..) 已实现,但自定义方法改为
🐓 .from_tuple_enum(..).into_tuple_enum().as_tuple_enum_ref().as_tuple_enum_ref_mut()

// Generated
#[derive( IntupleEnum, Debug )]
#[intuple(derive( Debug ))]
enum Enum { Unit, Unnamed(u32,u32), Another(u8,u8) }
fn main(){
    let enum = Enum::Unnamed(1,2); 
    let tuple = enum.as_tuple_enum_ref(); 
    // => EnumIntupleRef::Unnamed((&1,&2))
    let tuple = enum.into_tuple_enum(); 
    // => EnumIntupleRef::Unnamed((1,2))
}

示例:Serde - 突破思维定势

🦄 可以使用 serde 而不实现 Serialize/Deserialize
🐔 这仅适用于 位置枚举元组

use intuple::*;

#[derive(Intuple)]
struct Named{a:u32, b:u32, c:u32, d:u32, e:u32, f:u32}

fn main(){
    let named = Named::from((1,2,3,4,5,6));
    let json = serde_json::to_string(&named.as_tuple_ref()).unwrap();
    println!("{}",json); //=> "[1,2,3,4,5,6]"

    let tuple = serde_json::from_str::<<Named as Intuple>::Tuple>(&json).unwrap();
    let named_again = Named::from(tuple);
    // named == named_again
}

更多信息

🦎 更新日志
🐱 GitHub
👾 Discord 服务器


许可证

许可协议为 Apache License, Version 2.0 或 MIT 许可证,您可选择其一。
除非您明确声明,否则您有意提交以包含在本软件包中的任何贡献,根据 Apache-2.0 许可协议定义,将双重许可如上所述,不附加任何额外条款或条件。

依赖项

~295–750KB
~18K SLoC