doc_code_snippets! { mod "guide_03", type_ident=Guide03, template=r##" Here's an example of using a type-level-Range as a ConstValue-parameter to a struct. Trait/Type glossary: - ConstRange: the ConstValue equivalent of ::std::ops::Range. - RangeTrait: a trait that allows using a ConstRange in generic contexts. Automatically generated by the TypeLevel derive macro. //@use_codeblock:struct_decl,ignore Here we declare the ranged usize type,which uses a ConstValue parameter to store the range of valid integers. //@use_codeblock:rangeusize-impl,ignore Here the ConstValue range parameter limits which RangedUsize is constructible. Note the requirement of the IntoRuntime trait in the methods that need to convert the ConstRange to a runtime value. //@use_codeblock:assert_zst,ignore This demonstrates that this is trully zero memory overhead. //@use_codeblock:main,ignore Here are a many examples of ranged integers,with different ranges and different integer values.




















# The entire thing //@use_codeblock:all,rust "##, code=r##" //@codeblock-start:all #[macro_use] extern crate derive_type_level; #[macro_use] extern crate type_level_values; use type_level_values::prelude::*; //@codeblock-start:struct_decl use std::ops::Range; #[derive(MutConstValue)] #[mcv( doc=" Type that wraps and limits the range of a usize, using a ConstRange to determine the range it is limited to. ", derive(Debug,Copy,Clone,PartialEq,PartialOrd,Eq,Ord), Type="RangedUsize",ConstValue="R", )] pub struct __RangedUsize{ range:ConstWrapper, n:usize, } //@codeblock-end:struct_decl //@codeblock-start:rangeusize-impl impl RangedUsize{ fn new(n:usize)->Option where R:IntoRuntime>, { let range_=R::to_runtime(); if range_.start <= n && n < range_.end { Some(Self{ n, range:ConstWrapper::NEW }) }else{ None } } fn with_range(n:usize,_range:R)->Option where R:IntoRuntime>, { Self::new(n) } fn value(self)->usize{ self.n } fn range(self)->Range where R:IntoRuntime> { R::to_runtime() } } //@codeblock-end:rangeusize-impl fn main(){ //@codeblock-start:assert_zst assert_eq!( ::std::mem::size_of::(), ::std::mem::size_of::>>() ); //@codeblock-end:assert_zst //@codeblock-start:main { type UsedRange=ConstRange; let range:UsedRange=ConstRange{ start:U0::CW, end:U10::CW, }; let ranged_int=|n| RangedUsize::with_range( n , range ).unwrap().value() ; assert_eq!( ranged_int( 0 ) , 0 ); assert_eq!( ranged_int( 5 ) , 5 ); assert_eq!( ranged_int( 9 ) , 9 ); assert_eq!( RangedUsize::new( 10 ) , None::> ); } { type UsedRange=ConstRange; let range:UsedRange=ConstRange{ start:U0::CW, end:U100::CW, }; let ranged_int=|n| RangedUsize::with_range( n , range ).unwrap().value() ; assert_eq!( ranged_int( 0 ) , 0 ); assert_eq!( ranged_int( 5 ) , 5 ); assert_eq!( ranged_int( 9 ) , 9 ); assert_eq!( ranged_int( 50 ) , 50 ); assert_eq!( ranged_int( 99 ) , 99 ); assert_eq!( RangedUsize::new( 100 ) , None::> ); } { type UsedRange=ConstRange; let range=UsedRange::MTVAL; let ranged_int=|n| RangedUsize::with_range( n , range ).unwrap().value() ; assert_eq!( RangedUsize::new( 0 ) , None::> ); assert_eq!( RangedUsize::new( 5 ) , None::> ); assert_eq!( RangedUsize::new( 9 ) , None::> ); assert_eq!( ranged_int( 10 ) , 10 ); assert_eq!( ranged_int( 50 ) , 50 ); assert_eq!( ranged_int( 99 ) , 99 ); assert_eq!( RangedUsize::new( 100 ) , None::> ); } //@codeblock-end:main } "##, }