#constructor #pair #traits #single #type #wrap #general-purpose

no-std type_constructor

基本数据类型和类型构造函数,如 Single、Pair、Many

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

Download history 451/week @ 2024-04-08 441/week @ 2024-04-15 700/week @ 2024-04-22 572/week @ 2024-04-29 970/week @ 2024-05-06 1346/week @ 2024-05-13 461/week @ 2024-05-20 1246/week @ 2024-05-27 571/week @ 2024-06-03 329/week @ 2024-06-10 322/week @ 2024-06-17 159/week @ 2024-06-24 350/week @ 2024-07-01 143/week @ 2024-07-08 443/week @ 2024-07-15 285/week @ 2024-07-22

每月下载量 1,252
42 个 Crates 中使用(通过 proc_macro_tools

MIT 许可证

140KB
2K SLoC

模块 :: 基本数据类型

deprecated rust-status docs.rs Open in Gitpod discord

基本数据类型和类型构造函数,如 Single、Pair、Homopair、Many。

在 Rust 中,你通常需要将给定类型包裹成一个新的类型。特别是孤儿规则的作用基本上是防止你为外部类型实现外部特质。为了克服这个限制,开发者通常会通过引入新类型将外部类型包裹在元组中。类型构造函数正是这样做的,并为构造的类型自动实现 From、Into、Deref 等特质。

除了单元素类型构造函数之外,还有 pairhomopairmany 等类型构造函数。

  • 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_0From_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 负责生成 singlepairmany 的代码。

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。对于 pairhomopair,同一个类型构造函数 pair,定义中类型的数量不同,homopair 只有一个,因为它的两个元素都具有相同的类型。同一个宏 types 负责生成 singlepairmany 的代码。

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_tupleclone_as_array 实现为克隆为元组或数组,将 as_tupleas_arrayas_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 )

基本用例 :: 单行多个元素

使用类型构造函数 manyVec 包裹在元组中。类似于 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