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
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
use std::marker::{PhantomData};

pub trait Toggle<T> {
  fn as_ref(&self) -> Option<&T>;
  fn as_mut(&mut self) -> Option<&mut T>;
}

pub type Disabled<T> = Disable<T>;
pub type Enabled<T> = Enable<T>;

pub struct Disable<T> {
  _marker:  PhantomData<T>,
}

impl<T> Disable<T> {
  #[inline]
  pub fn new() -> Disable<T> {
    Disable{_marker: PhantomData}
  }
}

impl<T> Toggle<T> for Disable<T> {
  #[inline]
  fn as_ref(&self) -> Option<&T> {
    None
  }

  #[inline]
  fn as_mut(&mut self) -> Option<&mut T> {
    None
  }
}

impl<T> Clone for Disable<T> where T: Clone {
  fn clone(&self) -> Disable<T> {
    Disable{_marker: PhantomData}
  }
}

impl<T> Copy for Disable<T> where T: Copy {
}

pub struct Enable<T> {
  value:    T,
}

impl<T> Enable<T> {
  #[inline]
  pub fn new(value: T) -> Enable<T> {
    Enable{value: value}
  }
}

impl<T> Toggle<T> for Enable<T> {
  #[inline]
  fn as_ref(&self) -> Option<&T> {
    Some(&self.value)
  }

  #[inline]
  fn as_mut(&mut self) -> Option<&mut T> {
    Some(&mut self.value)
  }
}

impl<T> Clone for Enable<T> where T: Clone {
  fn clone(&self) -> Enable<T> {
    Enable{value: self.value.clone()}
  }
}

impl<T> Copy for Enable<T> where T: Copy {
}

#[cfg(test)]
mod tests {

  use super::{Toggle, Disable, Enable};

  struct Hello<Tg> where Tg: Toggle<String> {
    t: Tg,
  }

  #[test]
  fn test_disable() {
    let hello = Hello{t: Disable::new()};
    assert!(hello.t.as_ref().is_none());
  }

  #[test]
  fn test_disable_mut() {
    let mut hello = Hello{t: Disable::new()};
    assert!(hello.t.as_mut().is_none());
  }

  #[test]
  fn test_enable() {
    let hello = Hello{t: Enable::new(format!("Hello, world!"))};
    assert!(hello.t.as_ref().is_some());
  }

  #[test]
  fn test_enable_mut() {
    let mut hello = Hello{t: Enable::new(format!("Hello, world!"))};
    *hello.t.as_mut().unwrap() = format!("Goodbye, cruel world!");
    assert_eq!("Goodbye, cruel world!", hello.t.as_ref().unwrap());
  }

}