use super::*;
impl GGLineStyle {
pub const BLANK: Self = Self([0, 0, 0, 0, 0, 0, 0, 0]);
pub const SOLID: Self = Self([16, 16, 16, 16, 16, 16, 16, 16]);
pub const DASHED: Self = Self([4, 4, 4, 4, 4, 4, 4, 4]);
pub const DOTTED: Self = Self([1, 3, 1, 3, 1, 3, 1, 3]);
pub const DOT_DASH: Self = Self([1, 3, 4, 3, 1, 3, 4, 3]);
pub const LONG_DASH: Self = Self([7, 3, 7, 3, 7, 3, 7, 3]);
pub const TWO_DASH: Self = Self([2, 2, 6, 2, 2, 2, 6, 2]);
pub fn is_blank(&self) -> bool {
self.eq(&Self::BLANK)
}
pub fn is_solid(&self) -> bool {
self.eq(&Self::SOLID)
}
pub fn new(raw: [u8; 8]) -> Self {
Self(raw)
}
pub fn iter(&self) -> GGLineDrawOrBlank {
if self.is_blank() {
GGLineDrawOrBlank::Blank
}
else if self.is_solid() {
GGLineDrawOrBlank::Solid
}
else {
GGLineDrawOrBlank::Cycle { state: self.0.iter().cycle(), should_draw: true, rest_count: self.0[0] }
}
}
}
impl Default for GGLineStyle {
fn default() -> Self {
Self::SOLID
}
}
impl Default for GGLineJoint {
fn default() -> Self {
Self::Round
}
}
impl FromStr for GGLineStyle {
type Err = GGError;
fn from_str(hex: &str) -> Result<Self> {
let style: Result<Vec<_>> = hex.chars().map(|c| hex_to_u8(hex)).collect();
let out = match style?[..] {
[] => Self::BLANK,
[w4] => Self([w4, w4, w4, w4, w4, w4, w4, w4]),
[b4, w4] => Self([b4, w4, b4, w4, b4, w4, b4, w4]),
[b3, w3, b4, w4] => Self([b3, w3, b4, w4, b3, w3, b4, w4]),
[b1, w1, b2, w2, b3, w3, b4, w4] => Self([b1, w1, b2, w2, b3, w3, b4, w4]),
_ => return Err(GGError::SyntaxError("Unknown Hex Line Style".to_string())),
};
Ok(out)
}
}
fn hex_to_u8(hex: &str) -> Result<u8> {
Ok(u8::from_str_radix(hex, 16)?)
}
impl<'a> IntoIterator for &'a GGLineStyle {
type Item = bool;
type IntoIter = GGLineDrawOrBlank<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> Iterator for GGLineDrawOrBlank<'a> {
type Item = bool;
fn next(&mut self) -> Option<Self::Item> {
match self {
Self::Blank => Some(false),
Self::Solid => Some(true),
Self::Cycle { state, should_draw, rest_count } => unsafe {
if *rest_count == 0 {
*rest_count = *state.next().unwrap_unchecked();
*should_draw = !*should_draw;
Some(*should_draw)
}
else {
*rest_count -= 1;
Some(*should_draw)
}
},
}
}
}
pub enum GGLineDrawOrBlank<'a> {
Blank,
Solid,
Cycle { state: Cycle<std::slice::Iter<'a, u8>>, should_draw: bool, rest_count: u8 },
}