19 个版本
0.3.0 | 2024 年 3 月 16 日 |
---|---|
0.2.0 | 2024 年 3 月 1 日 |
0.1.19 | 2022 年 7 月 2 日 |
0.1.18 | 2022 年 6 月 11 日 |
0.1.16 | 2022 年 5 月 31 日 |
在 开发工具 中排名第 914
每月下载量 1,252
在 42 个 Crates 中使用(通过 proc_macro_tools)
140KB
2K SLoC
模块 :: 基本数据类型
基本数据类型和类型构造函数,如 Single、Pair、Homopair、Many。
在 Rust 中,你通常需要将给定类型包裹成一个新的类型。特别是孤儿规则的作用基本上是防止你为外部类型实现外部特质。为了克服这个限制,开发者通常会通过引入新类型将外部类型包裹在元组中。类型构造函数正是这样做的,并为构造的类型自动实现 From、Into、Deref 等特质。
除了单元素类型构造函数之外,还有 pair
、homopair
和 many
等类型构造函数。
Single
用于包裹单个元素。Pair
用于包裹不同元素的元组。HomoPair
用于包裹相同类型的元素对。Many
用于包裹元素向量Vec
。
类型构造的宏 types
宏 types
负责生成 Single、Pair、Homopair、Many 的代码。每个类型构造函数都有自己的关键字,但 Pair 和 Homopair 在构成类型数量上的区别使用相同的关键字。可以一次性定义所有类型。
{
use type_constructor::prelude::*;
types!
{
pub single MySingle : f32;
pub single SingleWithParametrized : std::sync::Arc< T : Copy >;
pub single SingleWithParameter : < T >;
pub pair MyPair : f32;
pub pair PairWithParametrized : std::sync::Arc< T1 : Copy >, std::sync::Arc< T2 : Copy >;
pub pair PairWithParameter : < T1, T2 >;
pub pair MyHomoPair : f32;
pub pair HomoPairWithParametrized : std::sync::Arc< T : Copy >;
pub pair HomoPairWithParameter : < T >;
pub many MyMany : f32;
pub many ManyWithParametrized : std::sync::Arc< T : Copy >;
pub many ManyWithParameter : < T >;
}
}
它生成了超过 1000 行代码,否则你需要手动编写。
没有宏
宏 types
用于生成新类型,但在某些情况下,重用已经生成的此类类型就足够了。该库提供了这样的类型:Single、Pair、Homopair、Many。注意:如果你避免生成新类型,可能会因为孤儿规则而无法定义自己的外部特质实现。
let i32_in_tuple = type_constructor::Single::< i32 >::from( 13 );
dbg!( i32_in_tuple );
// i32_in_tuple = Single( 13 )
let i32_and_f32_in_tuple = type_constructor::Pair::< i32, f32 >::from( ( 13, 13.0 ) );
dbg!( i32_and_f32_in_tuple );
// vec_of_i32_in_tuple = Pair( 13, 13.0 )
let two_i32_in_tuple = type_constructor::HomoPair::< i32 >::from( ( 13, 31 ) );
dbg!( two_i32_in_tuple );
// vec_of_i32_in_tuple = HomoPair( 13, 31 )
let vec_of_i32_in_tuple = type_constructor::Many::< i32 >::from( [ 1, 2, 3 ] );
dbg!( vec_of_i32_in_tuple );
// vec_of_i32_in_tuple = Many([ 1, 2, 3 ])
创建
创建是一个可变参数构造函数。它是任意长度构造函数的统一接口。在实现了多个特质 From_0
、From_1 一直到
MakeN
后,可以使用 from!
来构造实例。
#[ cfg( feature = "make" ) ]
{
use type_constructor::prelude::*;
let instance1 : Struct1 = from!();
let instance2 : Struct1 = from!( 13 );
let instance3 : Struct1 = from!( 1, 3 );
}
VectorizedFrom
标准 From
对元组和数组来说无法自动实现,也无法因为孤儿规则而实现。这就是为什么一对特质 VectorizedFrom
/VectorizedInto
可能很有用。它们是为元组和数组实现的。它们的实现基于标准 From
,如果 From
为元组的元素实现了,则 VectorizedFrom
/VectorizedInto
也会为包含这些元素的集合实现。
#[ cfg( feature = "vectorized_from" ) ]
{
use type_constructor::prelude::*;
types!( single Single1 : i32 );
let src = ( 1, 3 );
let got = <( Single1, Single1 )>::vectorized_from( src );
}
基本用例 :: 单行单元素
要定义自己的单用宏 types!
。单行定义如下。
use type_constructor::prelude::*;
types!( pub single MySingle : i32 );
let x = MySingle( 13 );
println!( "x : {}", x.0 );
它生成代码
use type_constructor::prelude::*;
pub struct MySingle( pub i32 );
impl core::ops::Deref for MySingle
{
type Target = i32;
fn deref( &self ) -> &Self::Target
{
&self.0
}
}
impl From< i32 > for MySingle
{
fn from( src : i32 ) -> Self
{
Self( src )
}
}
impl From< MySingle > for i32
{
fn from( src : MySingle ) -> Self
{
src.0
}
}
/* ... */
let x = MySingle( 13 );
println!( "x : {}", x.0 );
基本用例 :: 带有 derives 和属性的单一
可以定义属性以及 derives。
use type_constructor::prelude::*;
types!
{
/// This is also attribute and macro understands it.
#[ derive( Debug ) ]
pub single MySingle : i32;
}
let x = MySingle( 13 );
dbg!( x );
它生成代码
use type_constructor::prelude::*;
/// This is also an attribute and macro understands it.
#[ derive( Debug ) ]
pub struct MySingle( pub i32 );
impl core::ops::Deref for MySingle
{
type Target = i32;
fn deref( &self ) -> &Self::Target
{
&self.0
}
}
impl From< i32 > for MySingle
{
fn from( src : i32 ) -> Self
{
Self( src )
}
}
impl From< MySingle > for i32
{
fn from( src : MySingle ) -> Self
{
src.0
}
}
/* ... */
let x = MySingle( 13 );
dbg!( x );
基本用例 :: 用 struct 代替宏
有时使用通用类型而不是定义全新类型就足够了。在这种情况下,可以使用参数化 struct Single< T >
而不是宏 types!
。
use type_constructor::prelude::*;
let x = Single::< i32 >( 13 );
dbg!( x );
基本用例 :: 单元素带参数
元组的元素可以是参数化的。
use type_constructor::prelude::*;
types!
{
#[ derive( Debug ) ]
pub single MySingle : std::sync::Arc< T : Copy >;
}
let x = MySingle( std::sync::Arc::new( 13 ) );
dbg!( x );
它生成代码
use type_constructor::*;
#[ derive( Debug ) ]
pub struct MySingle< T : Copy >( pub std::sync::Arc< T > );
impl<T: Copy> core::ops::Deref for MySingle< T >
{
type Target = std::sync::Arc< T >;
fn deref( &self ) -> &Self::Target
{
&self.0
}
}
impl< T : Copy > From< std::sync::Arc< T > > for MySingle< T >
{
fn from( src : std::sync::Arc< T >) -> Self {
Self( src )
}
}
impl< T : Copy > From< MySingle< T > > for std::sync::Arc< T >
{
fn from(src: MySingle< T >) -> Self
{
src.0
}
}
/* ... */
let x = MySingle( std::sync::Arc::new( 13 ) );
基本用例 :: 参数化元组
除了参数化元素外,还可以定义参数化元组。
use type_constructor::prelude::*;
types!
{
#[ derive( Debug ) ]
pub single MySingle : < T : Copy >;
}
let x = MySingle( 13 );
dbg!( x );
它生成代码
#[ derive( Debug ) ]
pub struct MySingle< T : Copy >( pub T );
impl< T : Copy > core::ops::Deref
for MySingle< T >
{
type Target = T;
fn deref( &self ) -> &Self::Target
{
&self.0
}
}
impl< T : Copy > From< T >
for MySingle< T >
{
fn from( src : T ) -> Self
{
Self( src )
}
}
let x = MySingle( 13 );
dbg!( 13 );
基本用例 :: 单行对
有时需要将多个元素包裹在一个元组中。如果元素的类型不同,使用 pair
。同一个宏 types
负责生成 single
、pair
和 many
的代码。
use type_constructor::prelude::*;
types!( pub pair MyPair : i32, i64 );
let x = MyPair( 13, 31 );
println!( "x : ( {}, {} )", x.0, x.1 );
// prints : x : ( 13, 31 )
它生成代码
use type_constructor::prelude::*;
pub struct MyPair( pub i32, pub i64 );
impl From< ( i32, i64 ) > for MyPair
{
fn from( src : ( i32, i64 ) ) -> Self { Self( src.0, src.1 ) }
}
impl From< MyPair > for ( i32, i64 )
{
fn from( src : MyPair ) -> Self { ( src.0, src.1 ) }
}
#[cfg( feature = "make" ) ]
impl From_2< i32, i64 > for MyPair
{
fn from_2( _0 : i32, _1 : i64 ) -> Self { Self( _0, _1 ) }
}
/* ... */
let x = MyPair( 13, 31 );
println!( "x : ( {}, {} )", x.0, x.1 );
基本用例 :: 带参数的对
和 single
一样,pair
也可以有参数。
use type_constructor::prelude::*;
use core::fmt;
types!
{
#[ derive( Debug ) ]
pub pair MyPair : < T1 : fmt::Debug, T2 : fmt::Debug >;
}
let x = MyPair( 13, 13.0 );
dbg!( x );
// prints : x = MyPair( 13, 13.0 )
它生成代码
use type_constructor::prelude::*;
use core::fmt;
#[ derive( Debug ) ]
pub struct MyPair< T1, T2 >( pub T1, pub T2 );
impl< T1, T2 > From<( T1, T2 )> for MyPair< T1, T2 >
{
fn from( src : ( T1, T2 ) ) -> Self { Self( src.0, src.1 ) }
}
impl< T1, T2 > From< MyPair< T1, T2 > > for ( T1, T2 )
{
fn from( src : MyPair< T1, T2 > ) -> Self { ( src.0, src.1 ) }
}
#[ cfg( feature = "make" ) ]
impl< T1, T2 > From_0 for MyPair< T1, T2 >
where
T1 : Default,
T2 : Default,
{
fn from_0() -> Self { Self( Default::default(), Default::default() ) }
}
#[ cfg( feature = "make" ) ]
impl< T1, T2 > From_2< T1, T2 > for MyPair< T1, T2 >
{
fn from_2( _0 : T1, _1 : T2 ) -> Self { Self( _0, _1 ) }
}
/* ... */
let x = MyPair( 13, 13.0 );
dbg!( x );
// prints : x = MyPair( 13, 13.0 )
基本用例 :: 单行同构对
如果您需要将一对具有相同类型的元素包裹起来,请使用类型构造函数 pair
。对于 pair
和 homopair
,同一个类型构造函数 pair
,定义中类型的数量不同,homopair
只有一个,因为它的两个元素都具有相同的类型。同一个宏 types
负责生成 single
、pair
和 many
的代码。
use type_constructor::prelude::*;
types!( pub pair MyPair : i32, i64 );
let x = MyPair( 13, 31 );
println!( "x : ( {}, {} )", x.0, x.1 );
// prints : x : ( 13, 31 )
它生成代码
use type_constructor::prelude::*;
pub struct MyPair( pub i32, pub i64 );
impl From< ( i32, i64 ) > for MyPair
{
fn from( src : ( i32, i64 ) ) -> Self { Self( src.0, src.1 ) }
}
impl From< MyPair > for ( i32, i64 )
{
fn from( src : MyPair ) -> Self { ( src.0, src.1 ) }
}
#[ cfg( feature = "make" ) ]
impl From_2< i32, i64 > for MyPair
{
fn from_2( _0 : i32, _1 : i64 ) -> Self { Self( _0, _1 ) }
}
/* ... */
let x = MyPair( 13, 31 );
println!( "x : ( {}, {} )", x.0, x.1 );
基本用例 :: 同构对带参数
与 heteropair
不同,homopair
有许多特质被实现。其中一些包括:将 clone_as_tuple
和 clone_as_array 实现为克隆为元组或数组,将
as_tuple
、as_array
、as_slice
实现为将其重新解释为元组或数组或切片,实现了 From
/Into
特质以将其转换为元组、数组、切片或标量。
use type_constructor::prelude::*;
use core::fmt;
types!
{
#[ derive( Debug ) ]
pub pair MyHomoPair : < T : fmt::Debug >;
}
let x = MyHomoPair( 13, 31 );
dbg!( &x );
// prints : &x = MyHomoPair( 13, 31 )
let clone_as_array : [ i32 ; 2 ] = x.clone_as_array();
dbg!( &clone_as_array );
// prints : &clone_as_array = [ 13, 31 ]
let clone_as_tuple : ( i32 , i32 ) = x.clone_as_tuple();
dbg!( &clone_as_tuple );
// prints : &clone_as_tuple = ( 13, 31 )
它生成代码
use type_constructor::prelude::*;
use core::fmt;
#[ derive( Debug ) ]
pub struct MyHomoPair< T >( pub T, pub T );
impl< T > core::ops::Deref for MyHomoPair< T >
{
type Target = ( T, T );
fn deref( &self ) -> &Self::Target
{
#[ cfg( debug_assertions ) ]
{
let layout1 = std::alloc::Layout::new::< Self >();
let layout2 = std::alloc::Layout::new::< Self::Target >();
debug_assert_eq!( layout1, layout2 );
}
unsafe { std::mem::transmute::< _, _ >( self ) }
}
}
impl< T > core::ops::DerefMut for MyHomoPair< T >
{
fn deref_mut( &mut self ) -> &mut Self::Target
{
#[ cfg( debug_assertions ) ]
{
let layout1 = std::alloc::Layout::new::< Self >();
let layout2 = std::alloc::Layout::new::< Self::Target >();
debug_assert_eq!( layout1, layout2 );
}
unsafe { std::mem::transmute::< _, _ >( self ) }
}
}
impl< T > From< ( T, T ) > for MyHomoPair< T >
{
fn from( src : ( T, T ) ) -> Self { Self( src.0, src.1 ) }
}
impl< T > From< MyHomoPair< T >> for ( T, T )
{
fn from( src : MyHomoPair< T > ) -> Self { ( src.0, src.1 ) }
}
impl< T > From< [ T; 2 ] > for MyHomoPair< T >
where
T : Clone,
{
fn from( src : [ T; 2 ] ) -> Self { Self( src[ 0 ].clone(), src[ 1 ].clone() ) }
}
impl< T > From< MyHomoPair< T >> for [ T; 2 ]
{
fn from( src : MyHomoPair< T > ) -> Self { [ src.0, src.1 ] }
}
impl< T > From< &[ T ] > for MyHomoPair< T >
where
T : Clone,
{
fn from( src : &[ T ] ) -> Self
{
debug_assert_eq!( src.len(), 2 );
Self( src[ 0 ].clone(), src[ 1 ].clone() )
}
}
impl< T > From< T > for MyHomoPair< T >
where
T : Clone,
{
fn from( src : T ) -> Self { Self( src.clone(), src.clone() ) }
}
impl< T > CloneAsTuple< ( T, T ) > for MyHomoPair< T >
where
T : Clone,
{
fn clone_as_tuple( &self ) -> ( T, T ) { ( self.0.clone(), self.1.clone() ) }
}
impl< T > CloneAsArray< T, 2 > for MyHomoPair< T >
where
T : Clone,
{
fn clone_as_array( &self ) -> [ T; 2 ] { [ self.0.clone(), self.1.clone() ] }
}
impl< T > AsTuple< ( T, T ) > for MyHomoPair< T >
{
fn as_tuple( &self ) -> &( T, T ) { unsafe { std::mem::transmute::< &_, &( T, T ) >( self ) } }
}
impl< T > AsArray< T, 2 > for MyHomoPair< T >
{
fn as_array( &self ) -> &[ T; 2 ] { unsafe { std::mem::transmute::< &_, &[ T; 2 ] >( self ) } }
}
impl< T > AsSlice< T > for MyHomoPair< T >
{
fn as_slice( &self ) -> &[ T ] { &self.as_array()[ .. ] }
}
#[ cfg( feature = "make" ) ]
impl< T > From_0 for MyHomoPair< T >
where
T : Default,
{
fn from_0() -> Self { Self( Default::default(), Default::default() ) }
}
#[ cfg( feature = "make" ) ]
impl< T > From_1< T > for MyHomoPair< T >
where
T : Clone,
{
fn from_1( _0 : T ) -> Self { Self( _0.clone(), _0.clone() ) }
}
#[ cfg( feature = "make" ) ]
impl< T > From_2< T, T > for MyHomoPair< T >
{
fn from_2( _0 : T, _1 : T ) -> Self { Self( _0, _1 ) }
}
/* ... */
let x = MyHomoPair( 13, 31 );
dbg!( &x );
// prints : &x = MyHomoPair( 13, 31 )
let clone_as_array : [ i32 ; 2 ] = x.clone_as_array();
dbg!( &clone_as_array );
// prints : &clone_as_array = [ 13, 31 ]
let clone_as_tuple : ( i32 , i32 ) = x.clone_as_tuple();
dbg!( &clone_as_tuple );
// prints : &clone_as_tuple = ( 13, 31 )
基本用例 :: 单行多个元素
使用类型构造函数 many
将 Vec
包裹在元组中。类似于 single
,它为其实现了必要的特质。
// #[ cfg
// (
// all
// (
// feature = "many",
// any( not( feature = "no_std" ), feature = "use_alloc" ),
// )
// ) ]
// {
// use type_constructor::prelude::*;
//
// types!( pub many MyMany : i32 );
// let x = MyMany::from( [ 1, 2, 3 ] );
// println!( "x : {:?}", x.0 );
// }
它生成代码
use type_constructor::prelude::*;
pub struct MyMany( pub std::vec::Vec< i32 > );
impl core::ops::Deref for MyMany
{
type Target = std::vec::Vec< i32 >;
fn deref( &self ) -> &Self::Target { &self.0 }
}
impl core::ops::DerefMut for MyMany
{
fn deref_mut( &mut self ) -> &mut Self::Target { &mut self.0 }
}
impl From< i32 > for MyMany
{
fn from( src : i32 ) -> Self { Self( vec![ src ] ) }
}
impl From< ( i32, ) > for MyMany
{
fn from( src : ( i32, ) ) -> Self { Self( vec![ src.0 ] ) }
}
impl< const N: usize > From< [ i32; N ] > for MyMany
where
i32 : Clone,
{
fn from( src : [ i32; N ] ) -> Self { Self( std::vec::Vec::from( src ) ) }
}
impl From< &[ i32 ] > for MyMany
where
i32 : Clone,
{
fn from( src : &[ i32 ] ) -> Self
{
debug_assert_eq!( src.len(), 1 );
Self( std::vec::Vec::from( src ) )
}
}
impl AsSlice< i32 > for MyMany
where
i32 : Clone,
{
fn as_slice( &self ) -> &[ i32 ] { &self[ .. ] }
}
#[ cfg( feature = "make" ) ]
impl From_0 for MyMany
{
fn from_0() -> Self { Self( std::vec::Vec::< i32 >::new() ) }
}
#[ cfg( feature = "make" ) ]
impl From_1< i32 > for MyMany
{
fn from_1( _0 : i32 ) -> Self { Self( vec![ _0 ] ) }
}
#[ cfg( feature = "make" ) ]
impl From_2< i32, i32 > for MyMany
{
fn from_2( _0 : i32, _1 : i32 ) -> Self { Self( vec![ _0, _1 ] ) }
}
#[ cfg( feature = "make" ) ]
impl From_3< i32, i32, i32 > for MyMany
{
fn from_3( _0 : i32, _1 : i32, _2 : i32 ) -> Self { Self( vec![ _0, _1, _2 ] ) }
}
/* ... */
let x = MyMany::from( [ 1, 2, 3 ] );
println!( "x : {:?}", x.0 );
基本用例 :: make - 可变参数构造函数
实现特性 [From_0]、[From_1] 直至 MakeN,以提供接口,使用不同的参数集来构造你的结构。在这个示例结构中,Struct1 可以不带参数、带单个参数或带两个参数来构造。
- 不带参数的构造函数将字段填充为零。
- 带单个参数的构造函数将两个字段都设置为参数的值。
- 带两个参数的构造函数设置每个字段的单独值。
#[ cfg( feature = "make" ) ]
{
use type_constructor::prelude::*;
#[ derive( Debug, PartialEq ) ]
struct Struct1
{
a : i32,
b : i32,
}
impl From_0 for Struct1
{
fn from_0() -> Self
{
Self { a : 0, b : 0 }
}
}
impl From_1< i32 > for Struct1
{
fn from_1( val : i32 ) -> Self
{
Self { a : val, b : val }
}
}
impl From_2< i32, i32 > for Struct1
{
fn from_2( val1 : i32, val2 : i32 ) -> Self
{
Self { a : val1, b : val2 }
}
}
let got : Struct1 = from!();
let exp = Struct1{ a : 0, b : 0 };
assert_eq!( got, exp );
let got : Struct1 = from!( 13 );
let exp = Struct1{ a : 13, b : 13 };
assert_eq!( got, exp );
let got : Struct1 = from!( 1, 3 );
let exp = Struct1{ a : 1, b : 3 };
assert_eq!( got, exp );
}
将它们添加到你的项目中
cargo add type_constructor
从仓库中尝试使用
git clone https://github.com/Wandalen/wTools
cd wTools
cd examples/type_constructor_trivial_sample
cargo run
依赖项
~1–1.4MB
~31K SLoC