use crate::{
Dof, DofErrorInner as DE, Layer, Result,
dofinitions::{Finger, Key},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Pos {
row: usize,
col: usize,
}
impl Pos {
pub const fn new(row: usize, col: usize) -> Self {
Self { row, col }
}
pub const fn row(&self) -> usize {
self.row
}
pub const fn col(&self) -> usize {
self.col
}
}
impl From<(usize, usize)> for Pos {
fn from((row, col): (usize, usize)) -> Self {
Self { row, col }
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct KeyPos {
pub layer: String,
pub pos: Pos,
}
impl KeyPos {
pub fn new(layer: &str, pos: Pos) -> Self {
let layer = layer.into();
Self { layer, pos }
}
pub fn layer_name(&self) -> &str {
&self.layer
}
pub const fn pos(&self) -> &Pos {
&self.pos
}
pub const fn row(&self) -> usize {
self.pos.row
}
pub const fn col(&self) -> usize {
self.pos.col
}
}
impl From<(&str, Pos)> for KeyPos {
fn from((layer, pos): (&str, Pos)) -> Self {
let layer = layer.into();
KeyPos { layer, pos }
}
}
impl From<(&str, (usize, usize))> for KeyPos {
fn from((layer, pos): (&str, (usize, usize))) -> Self {
KeyPos::new(layer, pos.into())
}
}
impl Layer {
pub fn get_key(&self, pos: Pos) -> Result<&Key> {
let key = self
.0
.get(pos.row)
.ok_or(DE::InvalidPosition(pos.row as u8, pos.col as u8))?
.get(pos.col)
.ok_or(DE::InvalidPosition(pos.row as u8, pos.col as u8))?;
Ok(key)
}
pub fn get_key_mut(&mut self, pos: Pos) -> Result<&mut Key> {
let key = self
.0
.get_mut(pos.row)
.ok_or(DE::InvalidPosition(pos.row as u8, pos.col as u8))?
.get_mut(pos.col)
.ok_or(DE::InvalidPosition(pos.row as u8, pos.col as u8))?;
Ok(key)
}
pub fn set_key(&mut self, pos: Pos, key: Key) -> Result<()> {
*self.get_key_mut(pos)? = key;
Ok(())
}
}
impl Dof {
pub fn get(&self, key: impl Into<Key>) -> Vec<KeyPos> {
let key = key.into();
self.keys()
.into_iter()
.filter(|dk| dk.output == &key)
.map(|dk| dk.keypos())
.collect::<Vec<_>>()
}
pub fn tower(&self, pos: impl Into<Pos>) -> Vec<Key> {
let pos = pos.into();
self.keys()
.into_iter()
.filter(|dk| dk.pos() == pos)
.map(|dk| dk.output.clone())
.collect::<Vec<_>>()
}
pub fn finger(&self, pos: impl Into<Pos>) -> Option<Finger> {
let Pos { row, col } = pos.into();
self.fingering().0.get(row)?.get(col).copied()
}
pub fn swap(&mut self, keypos1: impl Into<KeyPos>, keypos2: impl Into<KeyPos>) -> Result<()> {
let KeyPos {
layer: layer_name1,
pos: pos1,
} = keypos1.into();
let KeyPos {
layer: layer_name2,
pos: pos2,
} = keypos2.into();
if layer_name1 == layer_name2 {
if pos1 == pos2 {
return Ok(());
}
let layer = self
.0
.layers
.get_mut(&layer_name1)
.ok_or(DE::LayerDoesntExist(layer_name1.clone()))?;
let key1 = layer.get_key(pos1).cloned()?;
let key2 = layer.get_key(pos2).cloned()?;
layer.set_key(pos1, key2)?;
layer.set_key(pos2, key1)?;
} else {
let mut layer1 = self
.0
.layers
.remove(&layer_name1)
.ok_or(DE::LayerDoesntExist(layer_name1.clone()))?;
let mut layer2 = self
.0
.layers
.remove(&layer_name2)
.ok_or(DE::LayerDoesntExist(layer_name2.clone()))?;
let key1 = layer1.get_key_mut(pos1)?;
let key2 = layer2.get_key_mut(pos2)?;
std::mem::swap(key1, key2);
self.0.layers.insert(layer_name1, layer1);
self.0.layers.insert(layer_name2, layer2);
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
static MINIMAL: &str = include_str!("../example_dofs/minimal_valid.dof");
#[test]
fn get() {
let buggy = include_str!("../example_dofs/buggy.dof");
let buggy_json = serde_json::from_str::<Dof>(buggy).expect("couldn't parse json");
assert_eq!(buggy_json.get(Key::Char('a')), [("main", (1, 5)).into()]);
assert_eq!(
buggy_json.get(Key::Transparent),
[
("l2", (2, 0)).into(),
("l2s", (2, 0)).into(),
("l2s", (2, 2)).into(),
("shift", (2, 2)).into()
]
);
}
#[test]
fn swap_main_layer_same_row() {
let minimal_json = serde_json::from_str::<Dof>(MINIMAL).expect("couldn't parse json");
let mut minimal_clone = minimal_json.clone();
let swap1 = KeyPos::new("main", (0, 0).into());
let swap2 = KeyPos::new("main", (0, 9).into());
minimal_clone
.swap(swap1.clone(), swap2.clone())
.expect("couldn't swap because");
minimal_clone
.swap(swap1, swap2)
.expect("couldn't swap because");
assert_eq!(minimal_json, minimal_clone);
}
#[test]
fn swap_main_layer() {
let minimal_json = serde_json::from_str::<Dof>(MINIMAL).expect("couldn't parse json");
let mut minimal_clone = minimal_json.clone();
let swap1 = KeyPos::new("main", (2, 0).into());
let swap2 = KeyPos::new("main", (1, 10).into());
minimal_clone
.swap(swap1.clone(), swap2.clone())
.expect("couldn't swap because");
assert_ne!(minimal_json, minimal_clone);
minimal_clone
.swap(swap1, swap2)
.expect("couldn't swap because");
assert_eq!(minimal_json, minimal_clone);
}
#[test]
fn swap_different_layers() {
let minimal_json = serde_json::from_str::<Dof>(MINIMAL).expect("couldn't parse json");
let mut minimal_clone = minimal_json.clone();
let swap1 = KeyPos::new("shift", (2, 0).into());
let swap2 = KeyPos::new("main", (1, 10).into());
minimal_clone
.swap(swap1.clone(), swap2.clone())
.expect("couldn't swap because");
minimal_clone
.swap(swap1, swap2)
.expect("couldn't swap because");
assert_eq!(minimal_json, minimal_clone);
}
}