[][src]Module core_extensions::maybe_unsafe

Allows defining traits whose functions/methods can be safe/unsafe to call depending on the implementor.

Example

An alternative implementation of Default whose safety is determined by the implementor.

use core_extensions::maybe_unsafe::{IsSafe,IsUnsafe,MaybeUnsafe};
use std::{fmt,mem};


/// Alternative definition of Default.
trait AlternativeDefault{
    /// Whether AlternativeDefault::default is safe to call.
    ///
    /// If Safety=IsUnsafe one must consult the documentation of the implementor
    /// to check what must be done to maintain safety.
    type Safety:MaybeUnsafe;

    fn default(safety:&Self::Safety)->Self;
}

#[derive(Debug,PartialEq)]
pub struct ZeroInit<T>(pub T);

#[derive(Debug,PartialEq)]
pub struct WithDefault<T>(pub T);

/// # Safety
///
/// Make sure to use this only on types on which 0 is a valid bit pattern.
impl<T> AlternativeDefault for ZeroInit<T> {
    type Safety=IsUnsafe;
    fn default(safety:&IsUnsafe)->Self{
        unsafe_!{safety=>
            ZeroInit(mem::zeroed())
        }
    }
}

impl<T> AlternativeDefault for WithDefault<T>
where T:Default
{
    type Safety=IsSafe;
    fn default(_:&IsSafe)->Self{
        WithDefault(Default::default())
    }
}

fn no_unsafe<T,U,F>(v:&Option<T>,f:F)->U
where T:fmt::Debug+AlternativeDefault<Safety=IsSafe>,
      F:FnOnce(&T)->U,
{
    match v.as_ref() {
        Some(v)=>f(v),
        None=>f(&AlternativeDefault::default(&())),
    }
}

fn uses_unsafe(v:Option<ZeroInit<usize>>)->usize{
    v.unwrap_or_else(||unsafe{
        //zeroing a usize is fine.
        IsUnsafe::with(AlternativeDefault::default)
    }).0
}

no_unsafe(&None::<WithDefault<bool>> ,|v| assert_eq!(v.0,false) );
no_unsafe(&Some(WithDefault(true))   ,|v| assert_eq!(v.0,true) );
no_unsafe(&None::<WithDefault<usize>>,|v| assert_eq!(v.0,0)  );
no_unsafe(&Some(WithDefault(10))     ,|v| assert_eq!(v.0,10) );

assert_eq!(uses_unsafe(Some(ZeroInit(10))),10);
assert_eq!(uses_unsafe(None              ),0);


Structs

IsUnsafe

Represents the unsafe effect.

Traits

MaybeUnsafe

The trait used to choose whether traits' function/method is safe(using IsSafe) or unsafe(using IsUnsafe) to call.

Type Definitions

IsSafe

Represents the safe effect.