1#![cfg_attr( feature="unstable", feature(
9 fn_traits,
10 generator_trait,
11 generators,
12 trusted_len,
13 unboxed_closures
14))]
15
16#[macro_use]
17pub mod macros;
18
19pub mod export {
31 pub mod exchange {
32 pub use crate::{
33 EnumToEnum,
34 ExchangeFrom,
35 ExchangeInto,
36 FromVariant,
37 IntoEnum,
38 TyPat,
39 };
40 pub use enumx_derive::{
41 Enum,
42 Exchange,
43 FromVariant as _,
44 Proto,
45 def_impls,
46 enumx,
47 };
48 }
49 pub mod impls {
50 pub mod derives {
51 pub use enumx_derive::{
52 def_impls,
53 sum,
54 sum_err,
55 };
56 }
57 pub use derives::*;
58 pub use crate::{
59 impl_trait,
60 impl_super_traits,
61 impl_all_traits,
62 };
63 }
64
65 pub use exchange::*;
66 pub use impls::*;
67}
68
69pub use enumx_derive::{
70 Enum,
71 Exchange,
72 FromVariant,
73 Proto,
74 def_impls,
75 enumx,
76 sum,
77 sum_err,
78};
79
80pub trait FromVariant<Variant, Index> {
82 fn from_variant( variant: Variant ) -> Self;
83}
84
85pub trait IntoEnum<Enum, Index> {
87 fn into_enum( self ) -> Enum;
88}
89
90impl<Enum,Variant,Index> IntoEnum<Enum, Index> for Variant
91 where Enum: FromVariant<Variant, Index>
92{
93 fn into_enum( self ) -> Enum {
94 <Enum as FromVariant::<Variant, Index>>::from_variant( self )
95 }
96}
97
98pub trait ExchangeFrom<Src, Index> {
100 fn exchange_from( src: Src ) -> Self;
101}
102
103pub trait ExchangeInto<Dest, Index> {
105 fn exchange_into( self ) -> Dest;
106}
107
108impl<Src, Dest, Index> ExchangeInto<Dest, Index> for Src
109 where Dest: ExchangeFrom<Src, Index>,
110{
111 fn exchange_into( self ) -> Dest {
112 Dest::exchange_from( self )
113 }
114}
115
116pub struct EnumToEnum<Index>( Index );
118
119pub trait Proto {
121 type Type;
122 fn from_proto( src: Self::Type ) -> Self;
123 fn into_proto( self ) -> Self::Type;
124}
125
126#[cfg( any( feature="enum16", feature="enum32" ))]
152pub mod predefined {
153 use crate as enumx;
154 use crate::{Exchange, def_impls, impl_trait};
155
156 #[cfg( feature="enum16" )]
157 def_impls! {
158 #[derive( Exchange, Clone, Debug, PartialEq, Eq, PartialOrd, Ord )]
159 pub enum Enum![ 0..=16 ];
160 }
161
162 #[cfg( feature="enum32" )]
163 def_impls! {
164 #[derive( Exchange, Clone, Debug, PartialEq, Eq, PartialOrd, Ord )]
165 pub enum Enum![ 17..=32 ];
166 }
167
168 #[cfg( feature="enum16" )]
169 pub mod enum1_16 {
170 use super::*;
171
172 impl_trait!{ _impl!(T) AsRef<T> _for!( Enum![1..=16] )}
173 impl_trait!{ _impl!(T) AsMut<T> _for!( Enum![1..=16] )}
174 impl_trait!{ DoubleEndedIterator _for!( Enum![1..=16] )}
175 impl_trait!{ ExactSizeIterator _for!( Enum![1..=16] )}
176 impl_trait!{ _impl!(A) Extend<A> _for!( Enum![1..=16] )}
177 impl_trait!{ Iterator _for!( Enum![1..=16] )}
178 impl_trait!{ std::error::Error _for!( Enum![1..=16] )}
179 impl_trait!{ std::fmt::Display _for!( Enum![1..=16] )}
180 impl_trait!{ std::iter::FusedIterator _for!( Enum![1..=16] )}
181 impl_trait!{ std::ops::Deref _for!( Enum![1..=16] )}
182 impl_trait!{ std::ops::DerefMut _for!( Enum![1..=16] )}
183
184 #[cfg( feature="unstable" )]
185 crate::impl_all_traits!{ _impl!(Args) Fn<Args> _for!( Enum![1..=16] )}
186
187 #[cfg( feature="unstable" )]
188 impl_trait!{ std::iter::TrustedLen _for!( Enum![1..=16] )}
189
190 #[cfg( feature="unstable" )]
191 impl_trait!{ _impl!(R) std::ops::Generator<R> _for!( Enum![1..=16] )}
192 }
193
194 #[cfg( feature="enum32" )]
195 pub mod enum17_32 {
196 use super::*;
197
198 impl_trait!{ _impl!(T) AsRef<T> _for!( Enum![17..=32] )}
199 impl_trait!{ _impl!(T) AsMut<T> _for!( Enum![17..=32] )}
200 impl_trait!{ DoubleEndedIterator _for!( Enum![17..=32] )}
201 impl_trait!{ ExactSizeIterator _for!( Enum![17..=32] )}
202 impl_trait!{ _impl!(A) Extend<A> _for!( Enum![17..=32] )}
203 impl_trait!{ Iterator _for!( Enum![17..=32] )}
204 impl_trait!{ std::error::Error _for!( Enum![17..=32] )}
205 impl_trait!{ std::fmt::Display _for!( Enum![17..=32] )}
206 impl_trait!{ std::iter::FusedIterator _for!( Enum![17..=32] )}
207 impl_trait!{ std::ops::Deref _for!( Enum![17..=32] )}
208 impl_trait!{ std::ops::DerefMut _for!( Enum![17..=32] )}
209
210 #[cfg( feature="unstable" )]
211 crate::impl_all_traits!{ _impl!(Args) Fn<Args> _for!( Enum![17..=32] )}
212
213 #[cfg( feature="unstable" )]
214 impl_trait!{ std::iter::TrustedLen _for!( Enum![17..=32] )}
215
216 #[cfg( feature="unstable" )]
217 impl_trait!{ _impl!(R) std::ops::Generator<R> _for!( Enum![17..=32] )}
218 }
219}
220
221pub mod proto {
223 use crate as enumx;
224 use crate::def_impls;
225
226 def_impls! {
227 pub enum __![ 0..=16 ];
228 }
229
230 #[cfg( feature="enum32" )]
231 def_impls! {
232 pub enum __![ 17..=32 ];
233 }
234}
235
236macro_rules! impl_exchange_from {
237 ( $($index:tt)+ ) => {
238 $(
239 impl<Enum,Variant> ExchangeFrom<Variant,[(); $index]> for Enum
240 where Enum: FromVariant<Variant,[(); $index]>
241 {
242 fn exchange_from( variant: Variant ) -> Self {
243 Enum::from_variant( variant )
244 }
245 }
246 )+
247 };
248}
249
250impl_exchange_from!( 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 );
251
252pub type TyPat<T> = T;
265
266#[cfg( test )]
267mod tests {
268 mod test_unnamed {
269 use crate::*;
270 use crate::predefined::*;
271
272 #[test]
273 fn test_from_variant() {
274 let enum1 = Enum1::<i32>::from_variant( 2018 );
275 assert_eq!( enum1, Enum1::_0( 2018 ));
276
277 let enum2 = Enum2::<i32, String>::from_variant( "rust".to_string() );
278 assert_eq!( enum2, Enum2::_1( "rust".to_string() ));
279
280 let enum3 = Enum3::<i32, String, bool>::from_variant( true );
281 assert_eq!( enum3, Enum3::_2( true ));
282 }
283
284 #[test]
285 fn test_into_enum() {
286 let enum1: Enum1<i32> = 2018.exchange_into();
287 assert_eq!( enum1, Enum1::_0( 2018 ));
288
289 let enum2: Enum2<i32, String> = "rust".to_string().exchange_into();
290 assert_eq!( enum2, Enum2::_1( "rust".to_string() ));
291
292 let enum3: Enum3<i32, String, bool> = true.exchange_into();
293 assert_eq!( enum3, Enum3::_2( true ));
294 }
295
296 #[test]
297 fn test_exchange_from() {
298 let enum1 = Enum1::<String>::exchange_from( "rust".to_string() );
299
300 let enum1 = Enum1::<String>::exchange_from( enum1 );
301 assert_eq!( enum1, Enum1::_0( "rust".to_string() ));
302
303 let enum2 = Enum2::<i32, String>::exchange_from( enum1 );
304 assert_eq!( enum2, Enum2::_1( "rust".to_string() ));
305
306 let enum2 = Enum2::<String, i32>::exchange_from( enum2 );
307 assert_eq!( enum2, Enum2::_0("rust".to_string() ));
308
309 let enum3 = Enum3::<bool, i32, String>::exchange_from( enum2 );
310 assert_eq!( enum3, Enum3::_2( "rust".to_string() ));
311
312 let enum3 = Enum3::<String, i32, bool>::exchange_from( enum3 );
313 assert_eq!( enum3, Enum3::_0( "rust".to_string() ));
314 }
315
316 #[test]
317 fn test_exchange_into() {
318 let enum1 = Enum1::<i32>::exchange_from( 2018 );
319
320 let enum1: Enum1<i32> = enum1.exchange_into();
321 assert_eq!( enum1, Enum1::_0( 2018 ));
322
323 let enum2: Enum2<String, i32> = enum1.exchange_into();
324 assert_eq!( enum2, Enum2::_1( 2018 ));
325
326 let enum2: Enum2<i32, String> = enum2.exchange_into();
327 assert_eq!( enum2, Enum2::_0( 2018 ));
328
329 let enum3: Enum3<bool, String, i32> = enum2.exchange_into();
330 assert_eq!( enum3, Enum3::_2( 2018 ));
331
332 let enum3: Enum3<i32, String, bool> = enum3.exchange_into();
333 assert_eq!( enum3, Enum3::_0( 2018 ));
334 }
335 }
336
337 mod test_named {
338 use crate::*;
339 use crate::predefined::*;
340 use crate as enumx;
341
342 #[derive( Exchange, Clone, Debug, PartialEq, Eq, PartialOrd, Ord )]
343 enum One<T> {
344 The(T),
345 }
346
347 #[derive( Exchange, Clone, Debug, PartialEq, Eq, PartialOrd, Ord )]
348 enum Two<A, B> {
349 Former(A),
350 Latter(B),
351 }
352
353 #[derive( Exchange, Clone, Debug, PartialEq, Eq, PartialOrd, Ord )]
354 enum Three<A, B, C> {
355 First(A),
356 Second(B),
357 Third(C),
358 }
359
360 #[test]
361 fn test_from_variant() {
362 let one = One::<i32>::from_variant( 2018 );
363 assert_eq!( one, One::The( 2018 ));
364
365 let two = Two::<i32, String>::from_variant( "rust".to_string() );
366 assert_eq!( two, Two::Latter( "rust".to_string() ));
367
368 let three = Three::<i32, String, bool>::from_variant( true );
369 assert_eq!( three, Three::Third( true ));
370 }
371
372 #[test]
373 fn test_into_enum() {
374 let one: One<i32> = 2018.into_enum();
375 assert_eq!( one, One::The( 2018 ));
376
377 let two: Two<i32, String> = "rust".to_string().into_enum();
378 assert_eq!( two, Two::Latter( "rust".to_string() ));
379
380 let three: Three<i32, String, bool> = true.into_enum();
381 assert_eq!( three, Three::Third( true ));
382 }
383
384 #[test]
385 fn test_exchange_from() {
386 let one = One::<i32>::exchange_from( 2018 );
387 let enum1 = Enum1::<i32>::exchange_from( one );
388 let one = One::<i32>::exchange_from( enum1 );
389
390 let one = One::<i32>::exchange_from( one );
391 assert_eq!( one, One::The( 2018 ));
392
393 let two = Two::<String, i32>::exchange_from( one );
394 assert_eq!( two, Two::Latter( 2018 ));
395
396 let two = Two::<i32, String>::exchange_from( two );
397 assert_eq!( two, Two::Former( 2018 ));
398
399 let three = Three::<bool, String, i32>::exchange_from( two );
400 assert_eq!( three, Three::Third( 2018 ));
401
402 let three = Three::<i32, String, bool>::exchange_from( three );
403 assert_eq!( three, Three::First( 2018 ));
404 }
405
406 #[test]
407 fn test_exchange_into() {
408 let one = One::<String>::exchange_from( "rust".to_string() );
409
410 let one: One<String> = one.exchange_into();
411 assert_eq!( one, One::The( "rust".to_string() ));
412
413 let two: Two<i32, String> = one.exchange_into();
414 assert_eq!( two, Two::Latter( "rust".to_string() ));
415
416 let two: Two<String, i32> = two.exchange_into();
417 assert_eq!( two, Two::Former( "rust".to_string() ));
418
419 let three: Three<bool, i32, String> = two.exchange_into();
420 assert_eq!( three, Three::Third( "rust".to_string() ));
421
422 let three: Three<String, i32, bool> = three.exchange_into();
423 assert_eq!( three, Three::First( "rust".to_string() ));
424 }
425
426 #[test]
427 fn test_adhoc_from_named() {
428 let three = Three::<bool, String, i32>::exchange_from( 2018 );
429 let enum3 = Enum3::<String, i32, bool>::exchange_from( three );
430 assert_eq!( enum3, Enum3::_1( 2018 ));
431 }
432
433 #[test]
434 fn test_adhoc_into_named() {
435 let enum3 = Enum3::<String, i32, bool>::exchange_from( 2018 );
436 let three: Three<bool, String, i32> = enum3.exchange_into();
437 assert_eq!( three, Three::Third( 2018 ));
438 }
439
440 #[test]
441 fn test_named_into_adhoc() {
442 let three = Three::<bool, String, i32>::exchange_from( 2018 );
443 let enum3: Enum3<String, i32, bool> = three.exchange_into();
444 assert_eq!( enum3, Enum3::_1( 2018 ));
445 }
446
447 #[test]
448 fn test_named_from_adhoc() {
449 let enum3 = Enum3::<String, i32, bool>::exchange_from( 2018 );
450 let three = Three::<bool, String, i32>::exchange_from( enum3 );
451 assert_eq!( three, Three::Third( 2018 ));
452 }
453 }
454}