1#![warn(missing_docs)]
4#![warn(clippy::pedantic, clippy::nursery, clippy::style)]
5
6#[cfg(test)]
7mod test_utils;
8
9mod file;
10mod ptn;
11mod tps;
12
13pub use file::*;
14pub use ptn::*;
15pub use tps::*;
16
17use std::{
18 error::Error,
19 fmt::{Display, Formatter, Result as FmtResult},
20 str::FromStr,
21};
22
23#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
27pub enum Piece {
28 Flat,
30 Wall,
32 Cap,
34}
35
36impl Default for Piece {
37 fn default() -> Self {
38 Self::Flat
39 }
40}
41
42impl Display for Piece {
43 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
44 match self {
45 Self::Flat => "",
46 Self::Wall => "S",
47 Self::Cap => "C",
48 }
49 .fmt(f)
50 }
51}
52
53#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
55pub enum ParsePieceError {
56 TooLong,
58 BadChar,
60}
61
62impl Error for ParsePieceError {}
63
64impl Display for ParsePieceError {
65 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
66 match self {
67 Self::TooLong => "piece consisted of multiple characters",
68 Self::BadChar => "unknown piece character (not 'F', 'S', 'C')",
69 }
70 .fmt(f)
71 }
72}
73
74impl FromStr for Piece {
75 type Err = ParsePieceError;
76
77 fn from_str(s: &str) -> Result<Self, Self::Err> {
78 let mut chars = s.chars();
79
80 let c = chars.next();
81
82 if chars.next().is_some() {
83 Err(ParsePieceError::TooLong)?;
84 }
85
86 Ok(match c.unwrap_or('F') {
87 'F' => Self::Flat,
88 'S' => Self::Wall,
89 'C' => Self::Cap,
90 _ => Err(ParsePieceError::BadChar)?,
91 })
92 }
93}