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
}
"##,
}