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 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
use std::ops::Not;
use self::Stroke::{Back, Hand};
#[cfg(feature = "serde")]
use serde_crate::{Deserialize, Serialize};
/// Stroke of a row, i.e. handstroke (`Stroke::Hand`) or backstroke (`Stroke::Back`).
#[repr(u8)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
#[cfg_attr(
feature = "serde",
derive(Deserialize, Serialize),
serde(crate = "serde_crate", rename_all = "snake_case")
)]
pub enum Stroke {
Hand = 0,
Back = 1,
}
impl Stroke {
/// Returns the `Stroke` which happens `offset` [`Row`](crate::Row)s after a given `start`
/// `Stroke`.
///
/// # Example
///
/// ```
/// use bellframe::Stroke;
///
/// assert_eq!(Stroke::Hand.offset(0), Stroke::Hand);
/// // The row after a backstroke is a handstroke
/// assert_eq!(Stroke::Back.offset(1), Stroke::Hand);
/// assert_eq!(Stroke::Hand.offset(1235124), Stroke::Hand); // Whoa lots of ringing
/// ```
pub fn offset(self, offset: usize) -> Stroke {
if offset % 2 == 0 {
self
} else {
!self
}
}
/// Returns the `Stroke` which happens `offset` [`Row`](crate::Row)s after (or before) `self`.
///
/// # Example
///
/// ```
/// use bellframe::Stroke;
///
/// assert_eq!(Stroke::Hand.offset_i(0), Stroke::Hand);
/// // The row after a backstroke is a handstroke
/// assert_eq!(Stroke::Back.offset_i(1), Stroke::Hand);
/// // The row before a backstroke is also a handstroke
/// assert_eq!(Stroke::Back.offset_i(-1), Stroke::Hand);
/// assert_eq!(Stroke::Hand.offset_i(1235124), Stroke::Hand); // Whoa lots of ringing
/// ```
pub fn offset_i(self, offset: isize) -> Stroke {
if offset % 2 == 0 {
self
} else {
!self
}
}
}
impl Not for Stroke {
type Output = Self;
/// Returns the opposite `Stroke` to `self`
///
/// # Example
///
/// ```
/// use bellframe::Stroke;
///
/// assert_eq!(!Stroke::Hand, Stroke::Back);
/// assert_eq!(!Stroke::Back, Stroke::Hand);
/// ```
fn not(self) -> Self::Output {
match self {
Hand => Back,
Back => Hand,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn offset() {
#[track_caller]
fn check(start: Stroke, offset: usize, expected: Stroke) {
assert_eq!(start.offset(offset), expected);
}
check(Hand, 0, Hand);
check(Back, 0, Back);
check(Hand, 1, Back);
check(Back, 1, Hand);
check(Hand, 123547, Back);
check(Back, 123547, Hand);
check(Hand, usize::MAX, Back); // usize::MAX is odd
check(Back, usize::MAX, Hand);
}
#[test]
fn offset_i() {
#[track_caller]
fn check(start: Stroke, offset: isize, expected: Stroke) {
assert_eq!(start.offset_i(offset), expected);
}
check(Hand, 0, Hand);
check(Back, 0, Back);
check(Hand, 1, Back);
check(Back, 1, Hand);
check(Hand, 123547, Back);
check(Back, 123547, Hand);
check(Hand, isize::MAX, Back); // isize::MAX is odd
check(Back, isize::MAX, Hand);
check(Hand, isize::MIN, Hand); // isize::MIN is even
check(Back, isize::MIN, Back);
}
#[test]
fn not() {
assert_eq!(!Hand, Back);
assert_eq!(!Back, Hand);
}
}