doc_code_snippets! {
mod "guide_07",
type_ident=Guide07,
template=r##"
This chapter demonstrates a Mutator Function used to mutate the
ConstValue-parameter of a type wrapped in an Arc.
To demonstrate mutation of a ConstValue-parameter
we'll use a type which wraps an RwLock,
restricting when it allows mutable access of its contents.
//@use_codeblock:access_enum,ignore
This declares an enum describing whether one has read or mutable access
to the contents of the RwLock.
//@use_codeblock:rw_locker_struct,ignore
This declares a wrapper around an RwLock which also takes an Access ConstValue-parameter.
//@use_codeblock:rw_locker_new,ignore
This declares the constructor,which always returns the RwLocker with `RwAccess`
because the caller can restrict access to `ReadAccess` with
`.mutparam(RestrictAccess,().ty_())`.
//@use_codeblock:read_method,ignore
This wraps the RwLock::read method,callable with any ConstValue-parameter.
The reason it is a generic parameter instead of `RwLocker<_,ReadAccess >`
is because it would disallow calling the method with `RwLocker<_,RwAccess >`.
//@use_codeblock:write_method,ignore
This wraps the RwLock::write method,accessible only if the ConstValue-parameter is RwAccess.
//@use_codeblock:restrict_access,ignore
This defines a Mutator Function which restricts the RwLocker to have read access
(instead of mutable).
The `pub fn Name=FunctionType` syntax is used to delegate to another TypeFn_.
//@use_codeblock:replace_with,ignore
This is a function which accesses the RwLock's contents mutably,
setting them to the default value of the type.
//@use_codeblock:read_value,ignore
This is a function only has immutable access,
because it uses a generic parameter with no bounds,
and simply prints the contents of the RwLock.
//@use_codeblock:main_0,ignore
This is the start of the main function.
Here we initialize locker in an `Arc` and show that both functions are callable
because RwLocker is created with `RwAccess`.
//@use_codeblock:main_1,ignore
Here we clone the Arc,creating another handle to the value,
changing its ConstValue-parameter from `RwAccess` to `ReadAccess`,
note that `locker` was not affected by `restricted_locker` changing its ConstValue-parameter.
# 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::*;
use type_level_values::field_traits::{SetField,SetField_};
use type_level_values::fn_adaptors::{Const};
use std::sync::Arc;
use std::sync::{RwLock,RwLockReadGuard,RwLockWriteGuard,LockResult,TryLockResult};
use std::fmt;
//@codeblock-start:access_enum
#[derive(TypeLevel)]
#[typelevel(
derive(ConstEq,ConstOrd),
reexport(Variants),
)]
pub enum Access{
ReadAccess,
RwAccess,
}
//@codeblock-end:access_enum
//@codeblock-start:rw_locker_struct
#[derive(MutConstValue)]
#[mcv(
derive(Debug),
Type = "RwLocker",ConstValue = "C",
)]
pub struct __RwLocker{
lock:RwLock,
access:ConstWrapper,
}
//@codeblock-end:rw_locker_struct
//@codeblock-start:rw_locker_new
impl RwLocker{
pub fn new(value:T)->Self{
Self{
lock:RwLock::new(value),
access:ConstWrapper::NEW,
}
}
}
//@codeblock-end:rw_locker_new
//@codeblock-start:read_method
impl RwLocker{
pub fn read(&self) -> LockResult>{
self.lock.read()
}
}
//@codeblock-end:read_method
//@codeblock-start:write_method
impl RwLocker{
pub fn write(&self) -> LockResult>{
self.lock.write()
}
}
//@codeblock-end :write_method
//@codeblock-start:restrict_access
mutator_fn!{
type This[T,A]=(RwLocker)
type AllowedSelf=(allowed_self_constructors::All)
pub fn RestrictAccess=Const;
}
//@codeblock-end:restrict_access
//@codeblock-start:replace_with
fn replace_with_default(locker:&RwLocker)
where
T:Default
{
*locker.write().unwrap()=T::default()
}
//@codeblock-end :replace_with
//@codeblock-start:read_value
fn read_value(locker:&RwLocker)
where
T:fmt::Debug
{
println!("{:?}", locker.read().unwrap() );
}
//@codeblock-end :read_value
fn main(){
//@codeblock-start:main_0
// locker : Arc< RwLocker< String, RwAccess > >
let locker=Arc::new(RwLocker::new("hello".to_string()));
{
read_value(&locker);
replace_with_default(&locker);
}
//@codeblock-end:main_0
//@codeblock-start:main_1
{
// restricted_locker : Arc< RwLocker< String, ReadAccess > >
let restricted_locker=RwLocker::mutparam_arc(
locker.clone(),
RestrictAccess::NEW,
().ty_(),
);
read_value( &restricted_locker );
// can't call this function,because restricted_locker only has read access.
// replace_with_default( &restricted_locker );
// can call it with locker because it still has RwAccess.
replace_with_default( &locker );
}
//@codeblock-end:main_1
}
"##,
}