From 970b7f6f64b941280361cfb196e6e56f0c023b20 Mon Sep 17 00:00:00 2001 From: Guilhem Date: Wed, 3 Aug 2022 15:54:52 +0200 Subject: [PATCH 01/12] feat: Separate convert into from and to --- src/cli.rs | 17 +++++++++++++++-- src/lib.rs | 25 +++++++++++++++++-------- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index 0b2ea81..c2ba11f 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,3 +1,4 @@ +use crate::display::format_dentition; use crate::lib::NotationKind; use crate::lib::Tooth; use clap::{Parser, Subcommand, ValueEnum}; @@ -20,6 +21,12 @@ enum Action { #[clap(value_parser)] value: String, }, + Display { + #[clap(value_enum, short = 'n', long)] + notation: NotationKindArg, + #[clap(takes_value = false, short = 'p', long)] + primary: bool, + }, } #[derive(Parser, Debug)] struct Args { @@ -34,17 +41,23 @@ fn convert_kind(kind_arg: &NotationKindArg) -> NotationKind { NotationKindArg::Alphanumeric => NotationKind::Alphanumeric, } } + pub fn run_cli() { let args = Args::parse(); match &args.action { Action::Convert { from, to, value } => { - let tooth_result = Tooth::convert(&convert_kind(from), &convert_kind(&to), value); + let tooth_result = Tooth::from(value, &convert_kind(from)); + let output_string = match tooth_result { + Ok(tooth) => tooth.to(&convert_kind(to)), Err(err) => err, - Ok(ok) => ok, }; + println!("{}", output_string); } + Action::Display { notation, primary } => { + println!("{}", format_dentition(!primary, &convert_kind(notation))) + } }; } diff --git a/src/lib.rs b/src/lib.rs index 330fce4..801d45b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -230,18 +230,27 @@ impl Tooth { quadrant.to_owned() + &number } - pub fn convert(from: &NotationKind, to: &NotationKind, value: &str) -> Result { - let tooth_result = match from { + pub fn from(value: &str, from: &NotationKind) -> Result { + match from { NotationKind::Iso => Tooth::from_iso(value), NotationKind::Uns => Tooth::from_uns(value), NotationKind::Alphanumeric => Tooth::from_alphanumeric(value), - }; + } + } + pub fn to(&self, to: &NotationKind) -> String { + match to { + NotationKind::Iso => self.to_iso(), + NotationKind::Uns => self.to_uns(), + NotationKind::Alphanumeric => self.to_alphanumeric(), + } + } + + #[deprecated(since = "1.0.0", note = "Use 'to' and 'from' directly")] + pub fn convert(from: &NotationKind, to: &NotationKind, value: &str) -> Result { + let tooth_result = Tooth::from(value, from); + match tooth_result { - Ok(tooth) => match to { - NotationKind::Iso => Ok(tooth.to_iso()), - NotationKind::Uns => Ok(tooth.to_uns()), - NotationKind::Alphanumeric => Ok(tooth.to_alphanumeric()), - }, + Ok(tooth) => Ok(tooth.to(to)), Err(err) => Err(err), } } From 962c9db6f9d4960c686b3e077a6bf4860ff56104 Mon Sep 17 00:00:00 2001 From: Guilhem Date: Wed, 3 Aug 2022 15:57:29 +0200 Subject: [PATCH 02/12] feat: Add tooth display --- Cargo.lock | 7 ++++++ Cargo.toml | 3 ++- src/display.rs | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 22 ++++++++++++++--- src/main.rs | 1 + 5 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 src/display.rs diff --git a/Cargo.lock b/Cargo.lock index d9dc346..35f8c5c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -69,6 +69,7 @@ name = "dental-notation" version = "0.1.0" dependencies = [ "clap", + "owo-colors", ] [[package]] @@ -120,6 +121,12 @@ version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" +[[package]] +name = "owo-colors" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "decf7381921fea4dcb2549c5667eda59b3ec297ab7e2b5fc33eac69d2e7da87b" + [[package]] name = "proc-macro-error" version = "1.0.4" diff --git a/Cargo.toml b/Cargo.toml index 4c51d97..b40ffe2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -clap = {version = "3.2.5", features = [ "derive" ] } \ No newline at end of file +clap = {version = "3.2.5", features = [ "derive" ] } +owo-colors = "3" \ No newline at end of file diff --git a/src/display.rs b/src/display.rs new file mode 100644 index 0000000..9ade6bd --- /dev/null +++ b/src/display.rs @@ -0,0 +1,67 @@ +use crate::lib::NotationKind; +use crate::lib::{QuadrantKind, Tooth, ToothType}; +use owo_colors::{OwoColorize, Style}; + +enum JawKind { + Top, + Bottom, +} + +fn format_tooth(tooth: &Tooth, notation: &NotationKind) -> String { + let tooth_label = tooth.to(notation); + + let mut style = Style::new(); + style = match &tooth.get_type() { + ToothType::Canine => style.yellow(), + ToothType::Incisor => style.green(), + ToothType::Premolar => style.cyan(), + ToothType::Molar => style.blue(), + }; + format!(" {}", tooth_label.style(style)) +} + +fn format_quadrant(quadrant: QuadrantKind, permanent: bool, notation: &NotationKind) -> String { + let max = Tooth::quadrant_max(permanent); + let format_tooth = |i| { + let tooth = Tooth::new(i, quadrant, permanent).unwrap(); + format_tooth(&tooth, notation) + }; + if quadrant == QuadrantKind::TopLeft || quadrant == QuadrantKind::BottomLeft { + (1..=max).rev().map(format_tooth).collect() + } else { + (1..=max).map(format_tooth).collect() + } +} + +fn format_jaw(jaw: JawKind, permanent: bool, notation: &NotationKind) -> String { + let (quadrant_1, quadrant_2) = match jaw { + JawKind::Top => (QuadrantKind::TopLeft, QuadrantKind::TopRight), + JawKind::Bottom => (QuadrantKind::BottomLeft, QuadrantKind::BottomRight), + }; + format!( + " {} |{}", + format_quadrant(quadrant_1, permanent, notation), + format_quadrant(quadrant_2, permanent, notation) + ) +} + +pub fn format_dentition(permanent: bool, notation: &NotationKind) -> String { + let item_count = Tooth::quadrant_max(permanent); + let item_width = match (notation, permanent) { + (NotationKind::Iso, _) => 2, + (NotationKind::Uns, true) => 2, + (NotationKind::Uns, false) => 1, + (NotationKind::Alphanumeric, _) => 3, + }; + let jaw_len = (item_width + 1) * (item_count * 2 + 1); + let mut result = String::with_capacity((jaw_len * 4).into()); + result.push_str(&format_jaw(JawKind::Top, permanent, notation)); + result.push_str("\nR "); + for _ in 1..=jaw_len { + result.push_str("-"); + } + result.push_str(" L\n"); + result.push_str(&format_jaw(JawKind::Bottom, permanent, notation)); + + result +} diff --git a/src/lib.rs b/src/lib.rs index 801d45b..2dab6a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,13 @@ pub enum QuadrantKind { BottomRight, } +pub enum ToothType { + Incisor, + Canine, + Premolar, + Molar, +} + pub struct Tooth { quadrant: QuadrantKind, number: u8, @@ -20,7 +27,7 @@ pub struct Tooth { } impl Tooth { - fn _new(number: u8, quadrant: QuadrantKind, permanent: bool) -> Result { + pub fn new(number: u8, quadrant: QuadrantKind, permanent: bool) -> Result { if let Err(err) = Tooth::check_tooth_number(number, permanent) { return Err(err); } @@ -48,7 +55,7 @@ impl Tooth { } } - fn quadrant_max(permanent: bool) -> u8 { + pub fn quadrant_max(permanent: bool) -> u8 { if permanent { 8 } else { @@ -155,7 +162,7 @@ impl Tooth { }; if self.permanent { - value.to_string() + format!("{:2}", value) } else { ((value + 64) as char).to_string() } @@ -254,6 +261,15 @@ impl Tooth { Err(err) => Err(err), } } + + pub fn get_type(&self) -> ToothType { + match (&self.number, &self.permanent) { + (1..=2, _) => ToothType::Incisor, + (3, _) => ToothType::Canine, + (4..=5, true) => ToothType::Premolar, + _ => ToothType::Molar, + } + } } #[cfg(test)] diff --git a/src/main.rs b/src/main.rs index 79286f4..5f12f15 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ mod cli; +mod display; mod lib; fn main() { From 519ae2a261ac283df13ff9859ea97e39de3d3c74 Mon Sep 17 00:00:00 2001 From: Guilhem Date: Wed, 3 Aug 2022 16:29:59 +0200 Subject: [PATCH 03/12] refactor: Replace convert_kind to into --- src/cli.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index c2ba11f..3782ab2 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -34,11 +34,19 @@ struct Args { action: Action, } -fn convert_kind(kind_arg: &NotationKindArg) -> NotationKind { - match kind_arg { +impl Into for NotationKindArg { + fn into(self) -> NotationKind { + (&self).into() + } +} + +impl Into for &NotationKindArg { + fn into(self) -> NotationKind { + match self { NotationKindArg::Iso => NotationKind::Iso, NotationKindArg::Uns => NotationKind::Uns, NotationKindArg::Alphanumeric => NotationKind::Alphanumeric, + } } } @@ -47,10 +55,10 @@ pub fn run_cli() { match &args.action { Action::Convert { from, to, value } => { - let tooth_result = Tooth::from(value, &convert_kind(from)); + let tooth_result = Tooth::from(value, &from.into()); let output_string = match tooth_result { - Ok(tooth) => tooth.to(&convert_kind(to)), + Ok(tooth) => tooth.to(&to.into()), Err(err) => err, }; From 1bae864faa5afebd955b9ea03e711f7f1d2659bc Mon Sep 17 00:00:00 2001 From: Guilhem Date: Thu, 4 Aug 2022 16:45:53 +0200 Subject: [PATCH 04/12] refactor: Create ToothDisplay trait --- src/cli.rs | 34 +++++++++++--- src/display.rs | 67 --------------------------- src/display/cli.rs | 110 +++++++++++++++++++++++++++++++++++++++++++++ src/display/mod.rs | 13 ++++++ src/lib.rs | 1 + 5 files changed, 152 insertions(+), 73 deletions(-) delete mode 100644 src/display.rs create mode 100644 src/display/cli.rs create mode 100644 src/display/mod.rs diff --git a/src/cli.rs b/src/cli.rs index 3782ab2..85a99b2 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,4 +1,4 @@ -use crate::display::format_dentition; +use crate::display::{ToothCliFormatter, ToothDisplay}; use crate::lib::NotationKind; use crate::lib::Tooth; use clap::{Parser, Subcommand, ValueEnum}; @@ -26,6 +26,8 @@ enum Action { notation: NotationKindArg, #[clap(takes_value = false, short = 'p', long)] primary: bool, + #[clap(value_parser)] + value: Option, }, } #[derive(Parser, Debug)] @@ -43,9 +45,9 @@ impl Into for NotationKindArg { impl Into for &NotationKindArg { fn into(self) -> NotationKind { match self { - NotationKindArg::Iso => NotationKind::Iso, - NotationKindArg::Uns => NotationKind::Uns, - NotationKindArg::Alphanumeric => NotationKind::Alphanumeric, + NotationKindArg::Iso => NotationKind::Iso, + NotationKindArg::Uns => NotationKind::Uns, + NotationKindArg::Alphanumeric => NotationKind::Alphanumeric, } } } @@ -64,8 +66,28 @@ pub fn run_cli() { println!("{}", output_string); } - Action::Display { notation, primary } => { - println!("{}", format_dentition(!primary, &convert_kind(notation))) + Action::Display { + notation, + primary, + value, + } => { + let converted_value = match value { + Some(t) => { + let tooth_result = Tooth::from(t, ¬ation.into()); + match tooth_result { + Ok(tr) => Some(tr), + Err(err) => { + eprintln!("{}", err); + return; + } + } + } + None => None, + }; + println!( + "{}", + ToothCliFormatter::format(¬ation.into(), !primary, &converted_value) + ); } }; } diff --git a/src/display.rs b/src/display.rs deleted file mode 100644 index 9ade6bd..0000000 --- a/src/display.rs +++ /dev/null @@ -1,67 +0,0 @@ -use crate::lib::NotationKind; -use crate::lib::{QuadrantKind, Tooth, ToothType}; -use owo_colors::{OwoColorize, Style}; - -enum JawKind { - Top, - Bottom, -} - -fn format_tooth(tooth: &Tooth, notation: &NotationKind) -> String { - let tooth_label = tooth.to(notation); - - let mut style = Style::new(); - style = match &tooth.get_type() { - ToothType::Canine => style.yellow(), - ToothType::Incisor => style.green(), - ToothType::Premolar => style.cyan(), - ToothType::Molar => style.blue(), - }; - format!(" {}", tooth_label.style(style)) -} - -fn format_quadrant(quadrant: QuadrantKind, permanent: bool, notation: &NotationKind) -> String { - let max = Tooth::quadrant_max(permanent); - let format_tooth = |i| { - let tooth = Tooth::new(i, quadrant, permanent).unwrap(); - format_tooth(&tooth, notation) - }; - if quadrant == QuadrantKind::TopLeft || quadrant == QuadrantKind::BottomLeft { - (1..=max).rev().map(format_tooth).collect() - } else { - (1..=max).map(format_tooth).collect() - } -} - -fn format_jaw(jaw: JawKind, permanent: bool, notation: &NotationKind) -> String { - let (quadrant_1, quadrant_2) = match jaw { - JawKind::Top => (QuadrantKind::TopLeft, QuadrantKind::TopRight), - JawKind::Bottom => (QuadrantKind::BottomLeft, QuadrantKind::BottomRight), - }; - format!( - " {} |{}", - format_quadrant(quadrant_1, permanent, notation), - format_quadrant(quadrant_2, permanent, notation) - ) -} - -pub fn format_dentition(permanent: bool, notation: &NotationKind) -> String { - let item_count = Tooth::quadrant_max(permanent); - let item_width = match (notation, permanent) { - (NotationKind::Iso, _) => 2, - (NotationKind::Uns, true) => 2, - (NotationKind::Uns, false) => 1, - (NotationKind::Alphanumeric, _) => 3, - }; - let jaw_len = (item_width + 1) * (item_count * 2 + 1); - let mut result = String::with_capacity((jaw_len * 4).into()); - result.push_str(&format_jaw(JawKind::Top, permanent, notation)); - result.push_str("\nR "); - for _ in 1..=jaw_len { - result.push_str("-"); - } - result.push_str(" L\n"); - result.push_str(&format_jaw(JawKind::Bottom, permanent, notation)); - - result -} diff --git a/src/display/cli.rs b/src/display/cli.rs new file mode 100644 index 0000000..a153aa5 --- /dev/null +++ b/src/display/cli.rs @@ -0,0 +1,110 @@ +use super::JawKind; +use crate::display::ToothDisplay; +use crate::lib::{NotationKind, QuadrantKind, Tooth, ToothType}; +use owo_colors::{OwoColorize, Style}; + +pub struct ToothCliFormatter; + +impl ToothCliFormatter { + fn format_tooth( + tooth: &Tooth, + notation: &NotationKind, + selected_value: &Option, + ) -> String { + let tooth_label = tooth.to(notation); + + let mut style = Style::new(); + style = match &tooth.get_type() { + ToothType::Canine => style.yellow(), + ToothType::Incisor => style.green(), + ToothType::Premolar => style.cyan(), + ToothType::Molar => style.blue(), + }; + + if let Some(t) = selected_value { + if t == tooth { + style = style.reversed(); + } + } + format!(" {}", tooth_label.style(style)) + } + + fn format_quadrant( + notation: &NotationKind, + + permanent: bool, + quadrant: QuadrantKind, + selected_value: &Option, + ) -> String { + let max = Tooth::quadrant_max(permanent); + let format_tooth = |i| { + let tooth = Tooth::new(i, quadrant, permanent).unwrap(); + ToothCliFormatter::format_tooth(&tooth, notation, selected_value) + }; + if quadrant == QuadrantKind::TopLeft || quadrant == QuadrantKind::BottomLeft { + (1..=max).rev().map(format_tooth).collect() + } else { + (1..=max).map(format_tooth).collect() + } + } + + fn format_jaw( + notation: &NotationKind, + permanent: bool, + jaw: JawKind, + selected_value: &Option, + ) -> String { + let (quadrant_1, quadrant_2) = match jaw { + JawKind::Top => (QuadrantKind::TopLeft, QuadrantKind::TopRight), + JawKind::Bottom => (QuadrantKind::BottomLeft, QuadrantKind::BottomRight), + }; + format!( + " {} |{}", + ToothCliFormatter::format_quadrant(notation, permanent, quadrant_1, selected_value), + ToothCliFormatter::format_quadrant(notation, permanent, quadrant_2, selected_value) + ) + } + + fn calculate_separator_len(notation: &NotationKind, permanent: bool) -> u8 { + let item_count = Tooth::quadrant_max(permanent); + let item_width = match (notation, permanent) { + (NotationKind::Iso, _) => 2, + (NotationKind::Uns, true) => 2, + (NotationKind::Uns, false) => 1, + (NotationKind::Alphanumeric, _) => 3, + }; + (item_width + 1) * (item_count * 2 + 1) + } + + pub fn format_dentition( + notation: &NotationKind, + permanent: bool, + selected_value: &Option, + ) -> String { + let jaw_len = ToothCliFormatter::calculate_separator_len(notation, permanent); + let mut result = String::with_capacity((jaw_len * 4).into()); + result.push_str(&ToothCliFormatter::format_jaw( + notation, + permanent, + JawKind::Top, + selected_value, + )); + result.push_str("\nR "); + result.push_str(&"-".repeat(jaw_len.into())); + result.push_str(" L\n"); + result.push_str(&ToothCliFormatter::format_jaw( + notation, + permanent, + JawKind::Bottom, + selected_value, + )); + + result + } +} + +impl ToothDisplay for ToothCliFormatter { + fn format(notation: &NotationKind, permanent: bool, selected_value: &Option) -> String { + ToothCliFormatter::format_dentition(notation, permanent, selected_value) + } +} diff --git a/src/display/mod.rs b/src/display/mod.rs new file mode 100644 index 0000000..6977820 --- /dev/null +++ b/src/display/mod.rs @@ -0,0 +1,13 @@ +pub use crate::display::cli::*; +use crate::lib::NotationKind; +use crate::lib::Tooth; +mod cli; + +pub enum JawKind { + Top, + Bottom, +} + +pub trait ToothDisplay { + fn format(notation: &NotationKind, permanent: bool, selected_value: &Option) -> String; +} diff --git a/src/lib.rs b/src/lib.rs index 2dab6a9..8a8e48d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ pub enum ToothType { Molar, } +#[derive(PartialEq)] pub struct Tooth { quadrant: QuadrantKind, number: u8, From ab29780e1484fb3ab3df08789f808a2f3b75aa39 Mon Sep 17 00:00:00 2001 From: Guilhem Date: Thu, 4 Aug 2022 17:07:14 +0200 Subject: [PATCH 05/12] refactor: Separate dental-notation from dental-notation-cli --- Cargo.lock | 229 -------------------- Cargo.toml | 1 - dental-notation-cli/.gitignore | 1 + dental-notation-cli/Cargo.lock | 252 +++++++++++++++++++++++ dental-notation-cli/Cargo.toml | 10 + {src => dental-notation-cli/src}/cli.rs | 6 +- {src => dental-notation-cli/src}/main.rs | 2 - src/display/cli.rs | 2 +- src/display/mod.rs | 4 +- src/lib.rs | 2 + 10 files changed, 271 insertions(+), 238 deletions(-) create mode 100644 dental-notation-cli/.gitignore create mode 100644 dental-notation-cli/Cargo.lock create mode 100644 dental-notation-cli/Cargo.toml rename {src => dental-notation-cli/src}/cli.rs (94%) rename {src => dental-notation-cli/src}/main.rs (66%) diff --git a/Cargo.lock b/Cargo.lock index 35f8c5c..fb84c2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,244 +2,15 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "clap" -version = "3.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53da17d37dba964b9b3ecb5c5a1f193a2762c700e6829201e645b9381c99dc7" -dependencies = [ - "atty", - "bitflags", - "clap_derive", - "clap_lex", - "indexmap", - "once_cell", - "strsim", - "termcolor", - "textwrap", -] - -[[package]] -name = "clap_derive" -version = "3.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c11d40217d16aee8508cc8e5fde8b4ff24639758608e5374e731b53f85749fb9" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5538cd660450ebeb4234cfecf8f2284b844ffc4c50531e66d584ad5b91293613" -dependencies = [ - "os_str_bytes", -] - [[package]] name = "dental-notation" version = "0.1.0" dependencies = [ - "clap", "owo-colors", ] -[[package]] -name = "hashbrown" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" - -[[package]] -name = "heck" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "indexmap" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c6392766afd7964e2531940894cffe4bd8d7d17dbc3c1c4857040fd4b33bdb3" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "libc" -version = "0.2.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" - -[[package]] -name = "once_cell" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" - -[[package]] -name = "os_str_bytes" -version = "6.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" - [[package]] name = "owo-colors" version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "decf7381921fea4dcb2549c5667eda59b3ec297ab7e2b5fc33eac69d2e7da87b" - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.96" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "termcolor" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" - -[[package]] -name = "unicode-ident" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index b40ffe2..d129dc2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,5 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies] -clap = {version = "3.2.5", features = [ "derive" ] } owo-colors = "3" \ No newline at end of file diff --git a/dental-notation-cli/.gitignore b/dental-notation-cli/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/dental-notation-cli/.gitignore @@ -0,0 +1 @@ +/target diff --git a/dental-notation-cli/Cargo.lock b/dental-notation-cli/Cargo.lock new file mode 100644 index 0000000..b73cfd4 --- /dev/null +++ b/dental-notation-cli/Cargo.lock @@ -0,0 +1,252 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "clap" +version = "3.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3dbbb6653e7c55cc8595ad3e1f7be8f32aba4eb7ff7f0fd1163d4f3d137c0a9" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "once_cell", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba52acd3b0a5c33aeada5cdaa3267cdc7c594a98731d4268cdc1532f4264cb4" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "dental-notation" +version = "0.1.0" +dependencies = [ + "owo-colors", +] + +[[package]] +name = "dental-notation-cli" +version = "0.1.0" +dependencies = [ + "clap", + "dental-notation", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "indexmap" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "libc" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" + +[[package]] +name = "once_cell" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" + +[[package]] +name = "os_str_bytes" +version = "6.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4" + +[[package]] +name = "owo-colors" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "decf7381921fea4dcb2549c5667eda59b3ec297ab7e2b5fc33eac69d2e7da87b" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + +[[package]] +name = "unicode-ident" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/dental-notation-cli/Cargo.toml b/dental-notation-cli/Cargo.toml new file mode 100644 index 0000000..30a88a9 --- /dev/null +++ b/dental-notation-cli/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "dental-notation-cli" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = {version = "3.2.5", features = [ "derive" ] } +dental-notation = { path = ".." } \ No newline at end of file diff --git a/src/cli.rs b/dental-notation-cli/src/cli.rs similarity index 94% rename from src/cli.rs rename to dental-notation-cli/src/cli.rs index 85a99b2..407d8ec 100644 --- a/src/cli.rs +++ b/dental-notation-cli/src/cli.rs @@ -1,7 +1,7 @@ -use crate::display::{ToothCliFormatter, ToothDisplay}; -use crate::lib::NotationKind; -use crate::lib::Tooth; use clap::{Parser, Subcommand, ValueEnum}; +use dental_notation::display::{ToothCliFormatter, ToothDisplay}; +use dental_notation::NotationKind; +use dental_notation::Tooth; #[derive(Copy, Clone, Debug, ValueEnum)] enum NotationKindArg { diff --git a/src/main.rs b/dental-notation-cli/src/main.rs similarity index 66% rename from src/main.rs rename to dental-notation-cli/src/main.rs index 5f12f15..0b87e87 100644 --- a/src/main.rs +++ b/dental-notation-cli/src/main.rs @@ -1,6 +1,4 @@ mod cli; -mod display; -mod lib; fn main() { cli::run_cli() diff --git a/src/display/cli.rs b/src/display/cli.rs index a153aa5..ffc8154 100644 --- a/src/display/cli.rs +++ b/src/display/cli.rs @@ -1,6 +1,6 @@ use super::JawKind; use crate::display::ToothDisplay; -use crate::lib::{NotationKind, QuadrantKind, Tooth, ToothType}; +use crate::{NotationKind, QuadrantKind, Tooth, ToothType}; use owo_colors::{OwoColorize, Style}; pub struct ToothCliFormatter; diff --git a/src/display/mod.rs b/src/display/mod.rs index 6977820..08590f5 100644 --- a/src/display/mod.rs +++ b/src/display/mod.rs @@ -1,6 +1,6 @@ pub use crate::display::cli::*; -use crate::lib::NotationKind; -use crate::lib::Tooth; +use crate::NotationKind; +use crate::Tooth; mod cli; pub enum JawKind { diff --git a/src/lib.rs b/src/lib.rs index 8a8e48d..d52b5b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +pub mod display; + #[derive(Copy, Clone)] pub enum NotationKind { Iso, From 86c5892f002336d06bdd8be7064c625be0d816b4 Mon Sep 17 00:00:00 2001 From: Guilhem Date: Fri, 5 Aug 2022 14:11:44 +0200 Subject: [PATCH 06/12] refactor: Remove std but add alloc --- src/display/cli.rs | 2 ++ src/display/mod.rs | 1 + src/lib.rs | 6 ++++++ 3 files changed, 9 insertions(+) diff --git a/src/display/cli.rs b/src/display/cli.rs index ffc8154..3c90567 100644 --- a/src/display/cli.rs +++ b/src/display/cli.rs @@ -1,6 +1,8 @@ use super::JawKind; use crate::display::ToothDisplay; use crate::{NotationKind, QuadrantKind, Tooth, ToothType}; +use alloc::format; +use alloc::string::String; use owo_colors::{OwoColorize, Style}; pub struct ToothCliFormatter; diff --git a/src/display/mod.rs b/src/display/mod.rs index 08590f5..b248f58 100644 --- a/src/display/mod.rs +++ b/src/display/mod.rs @@ -1,6 +1,7 @@ pub use crate::display::cli::*; use crate::NotationKind; use crate::Tooth; +use alloc::string::String; mod cli; pub enum JawKind { diff --git a/src/lib.rs b/src/lib.rs index d52b5b2..8901bb3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,9 @@ +#![no_std] +extern crate alloc; +use crate::alloc::borrow::ToOwned; +use alloc::format; +use alloc::string::{String, ToString}; + pub mod display; #[derive(Copy, Clone)] From ea7a032c9566957735b2624171528cc1e74f4354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Barth=C3=A9s?= Date: Fri, 2 Sep 2022 18:36:06 +0200 Subject: [PATCH 07/12] refactor: Change visibility and extract Tooth struct --- src/display/cli.rs | 15 +- src/display/mod.rs | 5 +- src/lib.rs | 833 ++------------------------------------------- src/tooth.rs | 815 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 848 insertions(+), 820 deletions(-) create mode 100644 src/tooth.rs diff --git a/src/display/cli.rs b/src/display/cli.rs index 3c90567..eaf762f 100644 --- a/src/display/cli.rs +++ b/src/display/cli.rs @@ -5,6 +5,7 @@ use alloc::format; use alloc::string::String; use owo_colors::{OwoColorize, Style}; +/// Formatter used to display a complete jaw in a CLI. pub struct ToothCliFormatter; impl ToothCliFormatter { @@ -77,12 +78,10 @@ impl ToothCliFormatter { }; (item_width + 1) * (item_count * 2 + 1) } +} - pub fn format_dentition( - notation: &NotationKind, - permanent: bool, - selected_value: &Option, - ) -> String { +impl ToothDisplay for ToothCliFormatter { + fn format(notation: &NotationKind, permanent: bool, selected_value: &Option) -> String { let jaw_len = ToothCliFormatter::calculate_separator_len(notation, permanent); let mut result = String::with_capacity((jaw_len * 4).into()); result.push_str(&ToothCliFormatter::format_jaw( @@ -104,9 +103,3 @@ impl ToothCliFormatter { result } } - -impl ToothDisplay for ToothCliFormatter { - fn format(notation: &NotationKind, permanent: bool, selected_value: &Option) -> String { - ToothCliFormatter::format_dentition(notation, permanent, selected_value) - } -} diff --git a/src/display/mod.rs b/src/display/mod.rs index b248f58..f88217d 100644 --- a/src/display/mod.rs +++ b/src/display/mod.rs @@ -1,14 +1,17 @@ +//! Formatters to display a complete jaw. + pub use crate::display::cli::*; use crate::NotationKind; use crate::Tooth; use alloc::string::String; mod cli; -pub enum JawKind { +enum JawKind { Top, Bottom, } +/// Trait needed to format a complete jaw pub trait ToothDisplay { fn format(notation: &NotationKind, permanent: bool, selected_value: &Option) -> String; } diff --git a/src/lib.rs b/src/lib.rs index 8901bb3..66cacab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,812 +1,29 @@ +/*! +This crate provides seralizing and deserializing from different text representation of dental notations. You can find the different available notation in the enum [NotationKind]. + +It primarily exposes one struct, [Tooth], which operates the different conversions. It also contains another module, [`display`], used to format tooth for different +# Usage + +This crate is [on crates.io](https://crates.io/crates/dental_notation) and can be +used by adding `dental_notation` to your dependencies in your project's `Cargo.toml`. + +```toml +[dependencies] +dental_notation = "1" +``` + +If you're using Rust 2015, then you'll also need to add it to your crate root: + +```rust +extern crate dental_notation; +``` + +*/ + #![no_std] extern crate alloc; -use crate::alloc::borrow::ToOwned; -use alloc::format; -use alloc::string::{String, ToString}; pub mod display; - -#[derive(Copy, Clone)] -pub enum NotationKind { - Iso, - Uns, - Alphanumeric, -} - -#[derive(PartialEq, Clone, Copy, Debug)] -pub enum QuadrantKind { - TopLeft, - TopRight, - BottomLeft, - BottomRight, -} - -pub enum ToothType { - Incisor, - Canine, - Premolar, - Molar, -} - -#[derive(PartialEq)] -pub struct Tooth { - quadrant: QuadrantKind, - number: u8, - permanent: bool, -} - -impl Tooth { - pub fn new(number: u8, quadrant: QuadrantKind, permanent: bool) -> Result { - if let Err(err) = Tooth::check_tooth_number(number, permanent) { - return Err(err); - } - - Ok(Tooth { - number, - quadrant, - permanent, - }) - } - - fn check_tooth_number(number: u8, permanent: bool) -> Result<(), String> { - if permanent && (number < 1 || number > 8) { - Err(format!( - "Permanent tooth {} should be in range [1; 8]", - number - )) - } else if !permanent && (number < 1 || number > 5) { - Err(format!( - "Primary tooth {} should be in range [1; 5]", - number - )) - } else { - Ok(()) - } - } - - pub fn quadrant_max(permanent: bool) -> u8 { - if permanent { - 8 - } else { - 5 - } - } - - pub fn from_iso(value: &str) -> Result { - if value.len() != 2 { - return Err(format!("{} is not a valid ISO dental notation", value)); - } - let mut char_iter = value.chars(); - let (quadrant, permanent) = match char_iter.next().unwrap() { - '1' => (QuadrantKind::TopLeft, true), - '2' => (QuadrantKind::TopRight, true), - '3' => (QuadrantKind::BottomRight, true), - '4' => (QuadrantKind::BottomLeft, true), - '5' => (QuadrantKind::TopLeft, false), - '6' => (QuadrantKind::TopRight, false), - '7' => (QuadrantKind::BottomRight, false), - '8' => (QuadrantKind::BottomLeft, false), - x => return Err(format!("Quadrant value {} not included in range [1; 8]", x)), - }; - - let tooth_string = char_iter.next().unwrap(); - let tooth_number_option = tooth_string.to_digit(10); - - if tooth_number_option.is_none() { - return Err(format!("{} is not a number", tooth_string)); - } - let number = tooth_number_option.unwrap() as u8; - if let Err(err) = Tooth::check_tooth_number(number, permanent) { - return Err(err); - } - Ok(Tooth { - quadrant, - permanent, - number, - }) - } - - pub fn to_iso(&self) -> String { - let quadrant_number: u8 = match (&self.quadrant, self.permanent) { - (QuadrantKind::TopLeft, true) => 1, - (QuadrantKind::TopRight, true) => 2, - (QuadrantKind::BottomLeft, true) => 4, - (QuadrantKind::BottomRight, true) => 3, - (QuadrantKind::TopLeft, false) => 5, - (QuadrantKind::TopRight, false) => 6, - (QuadrantKind::BottomLeft, false) => 8, - (QuadrantKind::BottomRight, false) => 7, - }; - quadrant_number.to_string() + &self.number.to_string() - } - - pub fn from_uns(value: &str) -> Result { - let number_value_option = value.parse::(); - let mut permanent = false; - let uns = if number_value_option.is_ok() { - permanent = true; - number_value_option.unwrap() - } else { - (value.chars().next().expect("No value available") as i32 - 64) as u8 - }; - - if permanent && (uns < 1 || uns > 32) { - return Err(format!( - "UNS permanent tooth has to be in range [1; 32] (currently {})", - uns - )); - } else if !permanent && (uns < 1 || uns > 20) { - return Err(format!("UNS primary tooth has to be in range [A; T]")); - } - let max = Tooth::quadrant_max(permanent); - let quadrant = match ((uns - 1) / max) + 1 { - 1 => QuadrantKind::TopLeft, - 2 => QuadrantKind::TopRight, - 3 => QuadrantKind::BottomRight, - 4 => QuadrantKind::BottomLeft, - _ => return Err(format!("UNS tooth value not in range")), - }; - let number = if quadrant == QuadrantKind::TopRight || quadrant == QuadrantKind::BottomLeft { - ((uns - 1) % max) + 1 - } else { - max - ((uns - 1) % max) - }; - if let Err(err) = Tooth::check_tooth_number(number, permanent) { - return Err(err); - } - Ok(Tooth { - quadrant, - number, - permanent, - }) - } - - pub fn to_uns(&self) -> String { - let max = Tooth::quadrant_max(self.permanent); - let value: u8 = match (&self.quadrant, self.number) { - (QuadrantKind::TopLeft, x) => max - x + 1, - (QuadrantKind::TopRight, x) => x + max, - (QuadrantKind::BottomRight, x) => (max - x + 1) + max * 2, - (QuadrantKind::BottomLeft, x) => x + max * 3, - }; - - if self.permanent { - format!("{:2}", value) - } else { - ((value + 64) as char).to_string() - } - } - - pub fn from_alphanumeric(value: &str) -> Result { - if value.len() != 3 { - return Err(format!( - "{} is not a valid alphanumeric dental notation", - value - )); - } - let quadrant = match &value[0..2] { - "UL" => QuadrantKind::TopLeft, - "UR" => QuadrantKind::TopRight, - "LR" => QuadrantKind::BottomRight, - "LL" => QuadrantKind::BottomLeft, - x => { - return Err(format!( - "Quadrant value {} not a valid value (accepted: ['UL', 'UR', 'LR', 'LL'])", - x - )) - } - }; - - let tooth_string = &value[2..3]; - - let (number, permanent) = match tooth_string { - "1" => (1, true), - "2" => (2, true), - "3" => (3, true), - "4" => (4, true), - "5" => (5, true), - "6" => (6, true), - "7" => (7, true), - "8" => (8, true), - "A" => (1, false), - "B" => (2, false), - "C" => (3, false), - "D" => (4, false), - "E" => (5, false), - x => { - return Err(format!( - "Number value {} not a valid value (accepted: [1; 8] and ['A'; 'E'])", - x - )) - } - }; - if let Err(err) = Tooth::check_tooth_number(number, permanent) { - return Err(err); - } - Ok(Tooth { - quadrant, - permanent, - number, - }) - } - - pub fn to_alphanumeric(&self) -> String { - let quadrant = match &self.quadrant { - QuadrantKind::TopLeft => "UL", - QuadrantKind::TopRight => "UR", - QuadrantKind::BottomRight => "LR", - QuadrantKind::BottomLeft => "LL", - }; - - let number = if self.permanent { - self.number.to_string() - } else { - ((self.number + 64) as char).to_string() - }; - quadrant.to_owned() + &number - } - - pub fn from(value: &str, from: &NotationKind) -> Result { - match from { - NotationKind::Iso => Tooth::from_iso(value), - NotationKind::Uns => Tooth::from_uns(value), - NotationKind::Alphanumeric => Tooth::from_alphanumeric(value), - } - } - pub fn to(&self, to: &NotationKind) -> String { - match to { - NotationKind::Iso => self.to_iso(), - NotationKind::Uns => self.to_uns(), - NotationKind::Alphanumeric => self.to_alphanumeric(), - } - } - - #[deprecated(since = "1.0.0", note = "Use 'to' and 'from' directly")] - pub fn convert(from: &NotationKind, to: &NotationKind, value: &str) -> Result { - let tooth_result = Tooth::from(value, from); - - match tooth_result { - Ok(tooth) => Ok(tooth.to(to)), - Err(err) => Err(err), - } - } - - pub fn get_type(&self) -> ToothType { - match (&self.number, &self.permanent) { - (1..=2, _) => ToothType::Incisor, - (3, _) => ToothType::Canine, - (4..=5, true) => ToothType::Premolar, - _ => ToothType::Molar, - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - macro_rules! to { - ($name:ident, $func:ident, $quadrant:expr,$number:expr, $permanent:expr, $value:expr) => { - #[test] - fn $name() { - let tooth = Tooth { - quadrant: $quadrant, - number: $number, - permanent: $permanent, - }; - assert_eq!(tooth.$func(), $value); - } - }; - } - - macro_rules! from { - ($name:ident, $func:ident, $value:expr, $quadrant:expr,$number:expr, $permanent:expr) => { - #[test] - fn $name() { - let tooth = Tooth::$func($value).unwrap(); - - assert_eq!(tooth.quadrant, $quadrant); - assert_eq!(tooth.number, $number); - assert_eq!(tooth.permanent, $permanent); - } - }; - } - - macro_rules! from_fail { - ($name:ident, $func:ident, $value:expr) => { - #[test] - fn $name() { - assert!(Tooth::$func($value).is_err()); - } - }; - } - - to!(to_iso_11, to_iso, QuadrantKind::TopLeft, 1, true, "11"); - to!(to_iso_18, to_iso, QuadrantKind::TopLeft, 8, true, "18"); - to!(to_iso_21, to_iso, QuadrantKind::TopRight, 1, true, "21"); - to!(to_iso_28, to_iso, QuadrantKind::TopRight, 8, true, "28"); - to!(to_iso_31, to_iso, QuadrantKind::BottomRight, 1, true, "31"); - to!(to_iso_38, to_iso, QuadrantKind::BottomRight, 8, true, "38"); - to!(to_iso_41, to_iso, QuadrantKind::BottomLeft, 1, true, "41"); - to!(to_iso_48, to_iso, QuadrantKind::BottomLeft, 8, true, "48"); - to!(to_iso_51, to_iso, QuadrantKind::TopLeft, 1, false, "51"); - to!(to_iso_55, to_iso, QuadrantKind::TopLeft, 5, false, "55"); - to!(to_iso_61, to_iso, QuadrantKind::TopRight, 1, false, "61"); - to!(to_iso_65, to_iso, QuadrantKind::TopRight, 5, false, "65"); - to!(to_iso_71, to_iso, QuadrantKind::BottomRight, 1, false, "71"); - to!(to_iso_75, to_iso, QuadrantKind::BottomRight, 5, false, "75"); - to!(to_iso_81, to_iso, QuadrantKind::BottomLeft, 1, false, "81"); - to!(to_iso_85, to_iso, QuadrantKind::BottomLeft, 5, false, "85"); - - from!(from_iso_11, from_iso, "11", QuadrantKind::TopLeft, 1, true); - from!(from_iso_18, from_iso, "18", QuadrantKind::TopLeft, 8, true); - from!(from_iso_21, from_iso, "21", QuadrantKind::TopRight, 1, true); - from!(from_iso_28, from_iso, "28", QuadrantKind::TopRight, 8, true); - from!( - from_iso_31, - from_iso, - "31", - QuadrantKind::BottomRight, - 1, - true - ); - from!( - from_iso_38, - from_iso, - "38", - QuadrantKind::BottomRight, - 8, - true - ); - from!( - from_iso_41, - from_iso, - "41", - QuadrantKind::BottomLeft, - 1, - true - ); - from!( - from_iso_48, - from_iso, - "48", - QuadrantKind::BottomLeft, - 8, - true - ); - from!(from_iso_51, from_iso, "51", QuadrantKind::TopLeft, 1, false); - from!(from_iso_55, from_iso, "55", QuadrantKind::TopLeft, 5, false); - from!( - from_iso_61, - from_iso, - "61", - QuadrantKind::TopRight, - 1, - false - ); - from!( - from_iso_65, - from_iso, - "65", - QuadrantKind::TopRight, - 5, - false - ); - from!( - from_iso_71, - from_iso, - "71", - QuadrantKind::BottomRight, - 1, - false - ); - from!( - from_iso_75, - from_iso, - "75", - QuadrantKind::BottomRight, - 5, - false - ); - from!( - from_iso_81, - from_iso, - "81", - QuadrantKind::BottomLeft, - 1, - false - ); - from!( - from_iso_85, - from_iso, - "85", - QuadrantKind::BottomLeft, - 5, - false - ); - - from_fail!(from_iso_fail_10, from_iso, "10"); - from_fail!(from_iso_fail_19, from_iso, "19"); - from_fail!(from_iso_fail_20, from_iso, "20"); - from_fail!(from_iso_fail_29, from_iso, "29"); - from_fail!(from_iso_fail_30, from_iso, "30"); - from_fail!(from_iso_fail_39, from_iso, "39"); - from_fail!(from_iso_fail_40, from_iso, "40"); - from_fail!(from_iso_fail_49, from_iso, "49"); - from_fail!(from_iso_fail_50, from_iso, "50"); - from_fail!(from_iso_fail_56, from_iso, "56"); - from_fail!(from_iso_fail_60, from_iso, "60"); - from_fail!(from_iso_fail_66, from_iso, "66"); - from_fail!(from_iso_fail_70, from_iso, "70"); - from_fail!(from_iso_fail_76, from_iso, "76"); - from_fail!(from_iso_fail_80, from_iso, "80"); - from_fail!(from_iso_fail_86, from_iso, "86"); - - to!(to_uns_1, to_uns, QuadrantKind::TopLeft, 1, true, "8"); - to!(to_uns_8, to_uns, QuadrantKind::TopLeft, 8, true, "1"); - to!(to_uns_9, to_uns, QuadrantKind::TopRight, 1, true, "9"); - to!(to_uns_16, to_uns, QuadrantKind::TopRight, 8, true, "16"); - to!(to_uns_17, to_uns, QuadrantKind::BottomRight, 1, true, "24"); - to!(to_uns_24, to_uns, QuadrantKind::BottomRight, 8, true, "17"); - to!(to_uns_25, to_uns, QuadrantKind::BottomLeft, 1, true, "25"); - to!(to_uns_32, to_uns, QuadrantKind::BottomLeft, 8, true, "32"); - to!(to_uns_a, to_uns, QuadrantKind::TopLeft, 1, false, "E"); - to!(to_uns_e, to_uns, QuadrantKind::TopLeft, 5, false, "A"); - to!(to_uns_f, to_uns, QuadrantKind::TopRight, 1, false, "F"); - to!(to_uns_j, to_uns, QuadrantKind::TopRight, 5, false, "J"); - to!(to_uns_k, to_uns, QuadrantKind::BottomRight, 1, false, "O"); - to!(to_uns_o, to_uns, QuadrantKind::BottomRight, 5, false, "K"); - to!(to_uns_p, to_uns, QuadrantKind::BottomLeft, 1, false, "P"); - to!(to_uns_t, to_uns, QuadrantKind::BottomLeft, 5, false, "T"); - - from!(from_uns_8, from_uns, "8", QuadrantKind::TopLeft, 1, true); - from!(from_uns_1, from_uns, "1", QuadrantKind::TopLeft, 8, true); - from!(from_uns_9, from_uns, "9", QuadrantKind::TopRight, 1, true); - from!(from_uns_16, from_uns, "16", QuadrantKind::TopRight, 8, true); - from!( - from_uns_24, - from_uns, - "24", - QuadrantKind::BottomRight, - 1, - true - ); - from!( - from_uns_17, - from_uns, - "17", - QuadrantKind::BottomRight, - 8, - true - ); - from!( - from_uns_25, - from_uns, - "25", - QuadrantKind::BottomLeft, - 1, - true - ); - from!( - from_uns_32, - from_uns, - "32", - QuadrantKind::BottomLeft, - 8, - true - ); - from!(from_uns_e, from_uns, "E", QuadrantKind::TopLeft, 1, false); - from!(from_uns_a, from_uns, "A", QuadrantKind::TopLeft, 5, false); - from!(from_uns_f, from_uns, "F", QuadrantKind::TopRight, 1, false); - from!(from_uns_j, from_uns, "J", QuadrantKind::TopRight, 5, false); - from!( - from_uns_o, - from_uns, - "O", - QuadrantKind::BottomRight, - 1, - false - ); - from!( - from_uns_k, - from_uns, - "K", - QuadrantKind::BottomRight, - 5, - false - ); - from!( - from_uns_p, - from_uns, - "P", - QuadrantKind::BottomLeft, - 1, - false - ); - from!( - from_uns_t, - from_uns, - "T", - QuadrantKind::BottomLeft, - 5, - false - ); - - from_fail!(from_uns_fail_0, from_uns, "0"); - from_fail!(from_uns_fail_33, from_uns, "33"); - from_fail!(from_uns_fail_at, from_uns, "@"); - from_fail!(from_uns_fail_u, from_uns, "U"); - - to!( - to_alphanumeric_ul1, - to_alphanumeric, - QuadrantKind::TopLeft, - 1, - true, - "UL1" - ); - to!( - to_alphanumeric_ul8, - to_alphanumeric, - QuadrantKind::TopLeft, - 8, - true, - "UL8" - ); - to!( - to_alphanumeric_ur1, - to_alphanumeric, - QuadrantKind::TopRight, - 1, - true, - "UR1" - ); - to!( - to_alphanumeric_ur8, - to_alphanumeric, - QuadrantKind::TopRight, - 8, - true, - "UR8" - ); - to!( - to_alphanumeric_lr1, - to_alphanumeric, - QuadrantKind::BottomRight, - 1, - true, - "LR1" - ); - to!( - to_alphanumeric_lr8, - to_alphanumeric, - QuadrantKind::BottomRight, - 8, - true, - "LR8" - ); - to!( - to_alphanumeric_ll1, - to_alphanumeric, - QuadrantKind::BottomLeft, - 1, - true, - "LL1" - ); - to!( - to_alphanumeric_ll8, - to_alphanumeric, - QuadrantKind::BottomLeft, - 8, - true, - "LL8" - ); - to!( - to_alphanumeric_ula, - to_alphanumeric, - QuadrantKind::TopLeft, - 1, - false, - "ULA" - ); - to!( - to_alphanumeric_ule, - to_alphanumeric, - QuadrantKind::TopLeft, - 5, - false, - "ULE" - ); - to!( - to_alphanumeric_ura, - to_alphanumeric, - QuadrantKind::TopRight, - 1, - false, - "URA" - ); - to!( - to_alphanumeric_ure, - to_alphanumeric, - QuadrantKind::TopRight, - 5, - false, - "URE" - ); - to!( - to_alphanumeric_lra, - to_alphanumeric, - QuadrantKind::BottomRight, - 1, - false, - "LRA" - ); - to!( - to_alphanumeric_lre, - to_alphanumeric, - QuadrantKind::BottomRight, - 5, - false, - "LRE" - ); - to!( - to_alphanumeric_lla, - to_alphanumeric, - QuadrantKind::BottomLeft, - 1, - false, - "LLA" - ); - to!( - to_alphanumeric_lle, - to_alphanumeric, - QuadrantKind::BottomLeft, - 5, - false, - "LLE" - ); - from!( - from_alphanumeric_ul1, - from_alphanumeric, - "UL1", - QuadrantKind::TopLeft, - 1, - true - ); - from!( - from_alphanumeric_ul8, - from_alphanumeric, - "UL8", - QuadrantKind::TopLeft, - 8, - true - ); - from!( - from_alphanumeric_ur1, - from_alphanumeric, - "UR1", - QuadrantKind::TopRight, - 1, - true - ); - from!( - from_alphanumeric_ur8, - from_alphanumeric, - "UR8", - QuadrantKind::TopRight, - 8, - true - ); - from!( - from_alphanumeric_lr1, - from_alphanumeric, - "LR1", - QuadrantKind::BottomRight, - 1, - true - ); - from!( - from_alphanumeric_lr8, - from_alphanumeric, - "LR8", - QuadrantKind::BottomRight, - 8, - true - ); - from!( - from_alphanumeric_ll1, - from_alphanumeric, - "LL1", - QuadrantKind::BottomLeft, - 1, - true - ); - from!( - from_alphanumeric_ll8, - from_alphanumeric, - "LL8", - QuadrantKind::BottomLeft, - 8, - true - ); - from!( - from_alphanumeric_ula, - from_alphanumeric, - "ULA", - QuadrantKind::TopLeft, - 1, - false - ); - from!( - from_alphanumeric_ule, - from_alphanumeric, - "ULE", - QuadrantKind::TopLeft, - 5, - false - ); - from!( - from_alphanumeric_ura, - from_alphanumeric, - "URA", - QuadrantKind::TopRight, - 1, - false - ); - from!( - from_alphanumeric_ure, - from_alphanumeric, - "URE", - QuadrantKind::TopRight, - 5, - false - ); - from!( - from_alphanumeric_lra, - from_alphanumeric, - "LRA", - QuadrantKind::BottomRight, - 1, - false - ); - from!( - from_alphanumeric_lre, - from_alphanumeric, - "LRE", - QuadrantKind::BottomRight, - 5, - false - ); - from!( - from_alphanumeric_lla, - from_alphanumeric, - "LLA", - QuadrantKind::BottomLeft, - 1, - false - ); - from!( - from_alphanumeric_lle, - from_alphanumeric, - "LLE", - QuadrantKind::BottomLeft, - 5, - false - ); - from_fail!(from_alphanumeric_fail_ul0, from_alphanumeric, "UL0"); - from_fail!(from_alphanumeric_fail_ul9, from_alphanumeric, "UL9"); - from_fail!(from_alphanumeric_fail_ur0, from_alphanumeric, "UR0"); - from_fail!(from_alphanumeric_fail_ur9, from_alphanumeric, "UR9"); - from_fail!(from_alphanumeric_fail_lr0, from_alphanumeric, "LR0"); - from_fail!(from_alphanumeric_fail_lr9, from_alphanumeric, "LR9"); - from_fail!(from_alphanumeric_fail_ll0, from_alphanumeric, "LL0"); - from_fail!(from_alphanumeric_fail_ll9, from_alphanumeric, "LL9"); - from_fail!(from_alphanumeric_fail_ulat, from_alphanumeric, "UL@"); - from_fail!(from_alphanumeric_fail_ulf, from_alphanumeric, "ULF"); - from_fail!(from_alphanumeric_fail_urat, from_alphanumeric, "UR@"); - from_fail!(from_alphanumeric_fail_urf, from_alphanumeric, "URF"); - from_fail!(from_alphanumeric_fail_lrat, from_alphanumeric, "LR@"); - from_fail!(from_alphanumeric_fail_lrf, from_alphanumeric, "LRF"); - from_fail!(from_alphanumeric_fail_llat, from_alphanumeric, "LL@"); - from_fail!(from_alphanumeric_fail_llf, from_alphanumeric, "LLF"); -} +pub mod tooth; +#[doc(inline)] +pub use tooth::*; diff --git a/src/tooth.rs b/src/tooth.rs new file mode 100644 index 0000000..d4968c0 --- /dev/null +++ b/src/tooth.rs @@ -0,0 +1,815 @@ +use crate::alloc::borrow::ToOwned; +use alloc::format; +use alloc::string::{String, ToString}; + +#[derive(Copy, Clone)] +pub enum NotationKind { + /// [FDI / ISO 3950 notation](https://en.wikipedia.org/wiki/FDI_World_Dental_Federation_notation) + Iso, + /// [UNS (Universal Numbering System) notation](https://en.wikipedia.org/wiki/Universal_Numbering_System) + Uns, + /// [Alphanumeric notation](https://en.wikipedia.org/wiki/Dental_notation#Alphanumeric_notation) + Alphanumeric, +} + +#[derive(PartialEq, Clone, Copy, Debug)] +pub enum QuadrantKind { + TopLeft, + TopRight, + BottomLeft, + BottomRight, +} + +pub enum ToothType { + Incisor, + Canine, + Premolar, + Molar, +} + +/// Represent a tooth notation. It provides the different methods to convert from and to different notations in two different ways: +/// - [`from`](Tooth::from) and [`to`](Tooth::to), and providing the [NotationKind] as parameter, +/// - `from_xx` and `to_xx`, `xx` being one of the following: `iso`, `uns` and `alphanumeric. +#[derive(PartialEq)] +pub struct Tooth { + quadrant: QuadrantKind, + number: u8, + permanent: bool, +} + +impl Tooth { + pub fn new(number: u8, quadrant: QuadrantKind, permanent: bool) -> Result { + if let Err(err) = Tooth::check_tooth_number(number, permanent) { + return Err(err); + } + + Ok(Tooth { + number, + quadrant, + permanent, + }) + } + + fn check_tooth_number(number: u8, permanent: bool) -> Result<(), String> { + if permanent && (number < 1 || number > 8) { + Err(format!( + "Permanent tooth {} should be in range [1; 8]", + number + )) + } else if !permanent && (number < 1 || number > 5) { + Err(format!( + "Primary tooth {} should be in range [1; 5]", + number + )) + } else { + Ok(()) + } + } + + /// Get the maximum value for a tooth number (depending if it is a primary dentition or not) + pub fn quadrant_max(permanent: bool) -> u8 { + if permanent { + 8 + } else { + 5 + } + } + + pub fn from_iso(value: &str) -> Result { + if value.len() != 2 { + return Err(format!("{} is not a valid ISO dental notation", value)); + } + let mut char_iter = value.chars(); + let (quadrant, permanent) = match char_iter.next().unwrap() { + '1' => (QuadrantKind::TopLeft, true), + '2' => (QuadrantKind::TopRight, true), + '3' => (QuadrantKind::BottomRight, true), + '4' => (QuadrantKind::BottomLeft, true), + '5' => (QuadrantKind::TopLeft, false), + '6' => (QuadrantKind::TopRight, false), + '7' => (QuadrantKind::BottomRight, false), + '8' => (QuadrantKind::BottomLeft, false), + x => return Err(format!("Quadrant value {} not included in range [1; 8]", x)), + }; + + let tooth_string = char_iter.next().unwrap(); + let tooth_number_option = tooth_string.to_digit(10); + + if tooth_number_option.is_none() { + return Err(format!("{} is not a number", tooth_string)); + } + let number = tooth_number_option.unwrap() as u8; + if let Err(err) = Tooth::check_tooth_number(number, permanent) { + return Err(err); + } + Ok(Tooth { + quadrant, + permanent, + number, + }) + } + + pub fn to_iso(&self) -> String { + let quadrant_number: u8 = match (&self.quadrant, self.permanent) { + (QuadrantKind::TopLeft, true) => 1, + (QuadrantKind::TopRight, true) => 2, + (QuadrantKind::BottomLeft, true) => 4, + (QuadrantKind::BottomRight, true) => 3, + (QuadrantKind::TopLeft, false) => 5, + (QuadrantKind::TopRight, false) => 6, + (QuadrantKind::BottomLeft, false) => 8, + (QuadrantKind::BottomRight, false) => 7, + }; + quadrant_number.to_string() + &self.number.to_string() + } + + pub fn from_uns(value: &str) -> Result { + let number_value_option = value.parse::(); + let mut permanent = false; + let uns = if number_value_option.is_ok() { + permanent = true; + number_value_option.unwrap() + } else { + (value.chars().next().expect("No value available") as i32 - 64) as u8 + }; + + if permanent && (uns < 1 || uns > 32) { + return Err(format!( + "UNS permanent tooth has to be in range [1; 32] (currently {})", + uns + )); + } else if !permanent && (uns < 1 || uns > 20) { + return Err(format!("UNS primary tooth has to be in range [A; T]")); + } + let max = Tooth::quadrant_max(permanent); + let quadrant = match ((uns - 1) / max) + 1 { + 1 => QuadrantKind::TopLeft, + 2 => QuadrantKind::TopRight, + 3 => QuadrantKind::BottomRight, + 4 => QuadrantKind::BottomLeft, + _ => return Err(format!("UNS tooth value not in range")), + }; + let number = if quadrant == QuadrantKind::TopRight || quadrant == QuadrantKind::BottomLeft { + ((uns - 1) % max) + 1 + } else { + max - ((uns - 1) % max) + }; + if let Err(err) = Tooth::check_tooth_number(number, permanent) { + return Err(err); + } + Ok(Tooth { + quadrant, + number, + permanent, + }) + } + + pub fn to_uns(&self) -> String { + let max = Tooth::quadrant_max(self.permanent); + let value: u8 = match (&self.quadrant, self.number) { + (QuadrantKind::TopLeft, x) => max - x + 1, + (QuadrantKind::TopRight, x) => x + max, + (QuadrantKind::BottomRight, x) => (max - x + 1) + max * 2, + (QuadrantKind::BottomLeft, x) => x + max * 3, + }; + + if self.permanent { + format!("{:2}", value) + } else { + ((value + 64) as char).to_string() + } + } + + pub fn from_alphanumeric(value: &str) -> Result { + if value.len() != 3 { + return Err(format!( + "{} is not a valid alphanumeric dental notation", + value + )); + } + let quadrant = match &value[0..2] { + "UL" => QuadrantKind::TopLeft, + "UR" => QuadrantKind::TopRight, + "LR" => QuadrantKind::BottomRight, + "LL" => QuadrantKind::BottomLeft, + x => { + return Err(format!( + "Quadrant value {} not a valid value (accepted: ['UL', 'UR', 'LR', 'LL'])", + x + )) + } + }; + + let tooth_string = &value[2..3]; + + let (number, permanent) = match tooth_string { + "1" => (1, true), + "2" => (2, true), + "3" => (3, true), + "4" => (4, true), + "5" => (5, true), + "6" => (6, true), + "7" => (7, true), + "8" => (8, true), + "A" => (1, false), + "B" => (2, false), + "C" => (3, false), + "D" => (4, false), + "E" => (5, false), + x => { + return Err(format!( + "Number value {} not a valid value (accepted: [1; 8] and ['A'; 'E'])", + x + )) + } + }; + if let Err(err) = Tooth::check_tooth_number(number, permanent) { + return Err(err); + } + Ok(Tooth { + quadrant, + permanent, + number, + }) + } + + pub fn to_alphanumeric(&self) -> String { + let quadrant = match &self.quadrant { + QuadrantKind::TopLeft => "UL", + QuadrantKind::TopRight => "UR", + QuadrantKind::BottomRight => "LR", + QuadrantKind::BottomLeft => "LL", + }; + + let number = if self.permanent { + self.number.to_string() + } else { + ((self.number + 64) as char).to_string() + }; + quadrant.to_owned() + &number + } + + pub fn from(value: &str, from: &NotationKind) -> Result { + match from { + NotationKind::Iso => Tooth::from_iso(value), + NotationKind::Uns => Tooth::from_uns(value), + NotationKind::Alphanumeric => Tooth::from_alphanumeric(value), + } + } + pub fn to(&self, to: &NotationKind) -> String { + match to { + NotationKind::Iso => self.to_iso(), + NotationKind::Uns => self.to_uns(), + NotationKind::Alphanumeric => self.to_alphanumeric(), + } + } + + #[deprecated(since = "1.0.0", note = "Use 'to' and 'from' directly")] + pub fn convert(from: &NotationKind, to: &NotationKind, value: &str) -> Result { + let tooth_result = Tooth::from(value, from); + + match tooth_result { + Ok(tooth) => Ok(tooth.to(to)), + Err(err) => Err(err), + } + } + + pub fn get_type(&self) -> ToothType { + match (&self.number, &self.permanent) { + (1..=2, _) => ToothType::Incisor, + (3, _) => ToothType::Canine, + (4..=5, true) => ToothType::Premolar, + _ => ToothType::Molar, + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + macro_rules! to { + ($name:ident, $func:ident, $quadrant:expr,$number:expr, $permanent:expr, $value:expr) => { + #[test] + fn $name() { + let tooth = Tooth { + quadrant: $quadrant, + number: $number, + permanent: $permanent, + }; + assert_eq!(tooth.$func(), $value); + } + }; + } + + macro_rules! from { + ($name:ident, $func:ident, $value:expr, $quadrant:expr,$number:expr, $permanent:expr) => { + #[test] + fn $name() { + let tooth = Tooth::$func($value).unwrap(); + + assert_eq!(tooth.quadrant, $quadrant); + assert_eq!(tooth.number, $number); + assert_eq!(tooth.permanent, $permanent); + } + }; + } + + macro_rules! from_fail { + ($name:ident, $func:ident, $value:expr) => { + #[test] + fn $name() { + assert!(Tooth::$func($value).is_err()); + } + }; + } + + to!(to_iso_11, to_iso, QuadrantKind::TopLeft, 1, true, "11"); + to!(to_iso_18, to_iso, QuadrantKind::TopLeft, 8, true, "18"); + to!(to_iso_21, to_iso, QuadrantKind::TopRight, 1, true, "21"); + to!(to_iso_28, to_iso, QuadrantKind::TopRight, 8, true, "28"); + to!(to_iso_31, to_iso, QuadrantKind::BottomRight, 1, true, "31"); + to!(to_iso_38, to_iso, QuadrantKind::BottomRight, 8, true, "38"); + to!(to_iso_41, to_iso, QuadrantKind::BottomLeft, 1, true, "41"); + to!(to_iso_48, to_iso, QuadrantKind::BottomLeft, 8, true, "48"); + to!(to_iso_51, to_iso, QuadrantKind::TopLeft, 1, false, "51"); + to!(to_iso_55, to_iso, QuadrantKind::TopLeft, 5, false, "55"); + to!(to_iso_61, to_iso, QuadrantKind::TopRight, 1, false, "61"); + to!(to_iso_65, to_iso, QuadrantKind::TopRight, 5, false, "65"); + to!(to_iso_71, to_iso, QuadrantKind::BottomRight, 1, false, "71"); + to!(to_iso_75, to_iso, QuadrantKind::BottomRight, 5, false, "75"); + to!(to_iso_81, to_iso, QuadrantKind::BottomLeft, 1, false, "81"); + to!(to_iso_85, to_iso, QuadrantKind::BottomLeft, 5, false, "85"); + + from!(from_iso_11, from_iso, "11", QuadrantKind::TopLeft, 1, true); + from!(from_iso_18, from_iso, "18", QuadrantKind::TopLeft, 8, true); + from!(from_iso_21, from_iso, "21", QuadrantKind::TopRight, 1, true); + from!(from_iso_28, from_iso, "28", QuadrantKind::TopRight, 8, true); + from!( + from_iso_31, + from_iso, + "31", + QuadrantKind::BottomRight, + 1, + true + ); + from!( + from_iso_38, + from_iso, + "38", + QuadrantKind::BottomRight, + 8, + true + ); + from!( + from_iso_41, + from_iso, + "41", + QuadrantKind::BottomLeft, + 1, + true + ); + from!( + from_iso_48, + from_iso, + "48", + QuadrantKind::BottomLeft, + 8, + true + ); + from!(from_iso_51, from_iso, "51", QuadrantKind::TopLeft, 1, false); + from!(from_iso_55, from_iso, "55", QuadrantKind::TopLeft, 5, false); + from!( + from_iso_61, + from_iso, + "61", + QuadrantKind::TopRight, + 1, + false + ); + from!( + from_iso_65, + from_iso, + "65", + QuadrantKind::TopRight, + 5, + false + ); + from!( + from_iso_71, + from_iso, + "71", + QuadrantKind::BottomRight, + 1, + false + ); + from!( + from_iso_75, + from_iso, + "75", + QuadrantKind::BottomRight, + 5, + false + ); + from!( + from_iso_81, + from_iso, + "81", + QuadrantKind::BottomLeft, + 1, + false + ); + from!( + from_iso_85, + from_iso, + "85", + QuadrantKind::BottomLeft, + 5, + false + ); + + from_fail!(from_iso_fail_10, from_iso, "10"); + from_fail!(from_iso_fail_19, from_iso, "19"); + from_fail!(from_iso_fail_20, from_iso, "20"); + from_fail!(from_iso_fail_29, from_iso, "29"); + from_fail!(from_iso_fail_30, from_iso, "30"); + from_fail!(from_iso_fail_39, from_iso, "39"); + from_fail!(from_iso_fail_40, from_iso, "40"); + from_fail!(from_iso_fail_49, from_iso, "49"); + from_fail!(from_iso_fail_50, from_iso, "50"); + from_fail!(from_iso_fail_56, from_iso, "56"); + from_fail!(from_iso_fail_60, from_iso, "60"); + from_fail!(from_iso_fail_66, from_iso, "66"); + from_fail!(from_iso_fail_70, from_iso, "70"); + from_fail!(from_iso_fail_76, from_iso, "76"); + from_fail!(from_iso_fail_80, from_iso, "80"); + from_fail!(from_iso_fail_86, from_iso, "86"); + + to!(to_uns_1, to_uns, QuadrantKind::TopLeft, 1, true, "8"); + to!(to_uns_8, to_uns, QuadrantKind::TopLeft, 8, true, "1"); + to!(to_uns_9, to_uns, QuadrantKind::TopRight, 1, true, "9"); + to!(to_uns_16, to_uns, QuadrantKind::TopRight, 8, true, "16"); + to!(to_uns_17, to_uns, QuadrantKind::BottomRight, 1, true, "24"); + to!(to_uns_24, to_uns, QuadrantKind::BottomRight, 8, true, "17"); + to!(to_uns_25, to_uns, QuadrantKind::BottomLeft, 1, true, "25"); + to!(to_uns_32, to_uns, QuadrantKind::BottomLeft, 8, true, "32"); + to!(to_uns_a, to_uns, QuadrantKind::TopLeft, 1, false, "E"); + to!(to_uns_e, to_uns, QuadrantKind::TopLeft, 5, false, "A"); + to!(to_uns_f, to_uns, QuadrantKind::TopRight, 1, false, "F"); + to!(to_uns_j, to_uns, QuadrantKind::TopRight, 5, false, "J"); + to!(to_uns_k, to_uns, QuadrantKind::BottomRight, 1, false, "O"); + to!(to_uns_o, to_uns, QuadrantKind::BottomRight, 5, false, "K"); + to!(to_uns_p, to_uns, QuadrantKind::BottomLeft, 1, false, "P"); + to!(to_uns_t, to_uns, QuadrantKind::BottomLeft, 5, false, "T"); + + from!(from_uns_8, from_uns, "8", QuadrantKind::TopLeft, 1, true); + from!(from_uns_1, from_uns, "1", QuadrantKind::TopLeft, 8, true); + from!(from_uns_9, from_uns, "9", QuadrantKind::TopRight, 1, true); + from!(from_uns_16, from_uns, "16", QuadrantKind::TopRight, 8, true); + from!( + from_uns_24, + from_uns, + "24", + QuadrantKind::BottomRight, + 1, + true + ); + from!( + from_uns_17, + from_uns, + "17", + QuadrantKind::BottomRight, + 8, + true + ); + from!( + from_uns_25, + from_uns, + "25", + QuadrantKind::BottomLeft, + 1, + true + ); + from!( + from_uns_32, + from_uns, + "32", + QuadrantKind::BottomLeft, + 8, + true + ); + from!(from_uns_e, from_uns, "E", QuadrantKind::TopLeft, 1, false); + from!(from_uns_a, from_uns, "A", QuadrantKind::TopLeft, 5, false); + from!(from_uns_f, from_uns, "F", QuadrantKind::TopRight, 1, false); + from!(from_uns_j, from_uns, "J", QuadrantKind::TopRight, 5, false); + from!( + from_uns_o, + from_uns, + "O", + QuadrantKind::BottomRight, + 1, + false + ); + from!( + from_uns_k, + from_uns, + "K", + QuadrantKind::BottomRight, + 5, + false + ); + from!( + from_uns_p, + from_uns, + "P", + QuadrantKind::BottomLeft, + 1, + false + ); + from!( + from_uns_t, + from_uns, + "T", + QuadrantKind::BottomLeft, + 5, + false + ); + + from_fail!(from_uns_fail_0, from_uns, "0"); + from_fail!(from_uns_fail_33, from_uns, "33"); + from_fail!(from_uns_fail_at, from_uns, "@"); + from_fail!(from_uns_fail_u, from_uns, "U"); + + to!( + to_alphanumeric_ul1, + to_alphanumeric, + QuadrantKind::TopLeft, + 1, + true, + "UL1" + ); + to!( + to_alphanumeric_ul8, + to_alphanumeric, + QuadrantKind::TopLeft, + 8, + true, + "UL8" + ); + to!( + to_alphanumeric_ur1, + to_alphanumeric, + QuadrantKind::TopRight, + 1, + true, + "UR1" + ); + to!( + to_alphanumeric_ur8, + to_alphanumeric, + QuadrantKind::TopRight, + 8, + true, + "UR8" + ); + to!( + to_alphanumeric_lr1, + to_alphanumeric, + QuadrantKind::BottomRight, + 1, + true, + "LR1" + ); + to!( + to_alphanumeric_lr8, + to_alphanumeric, + QuadrantKind::BottomRight, + 8, + true, + "LR8" + ); + to!( + to_alphanumeric_ll1, + to_alphanumeric, + QuadrantKind::BottomLeft, + 1, + true, + "LL1" + ); + to!( + to_alphanumeric_ll8, + to_alphanumeric, + QuadrantKind::BottomLeft, + 8, + true, + "LL8" + ); + to!( + to_alphanumeric_ula, + to_alphanumeric, + QuadrantKind::TopLeft, + 1, + false, + "ULA" + ); + to!( + to_alphanumeric_ule, + to_alphanumeric, + QuadrantKind::TopLeft, + 5, + false, + "ULE" + ); + to!( + to_alphanumeric_ura, + to_alphanumeric, + QuadrantKind::TopRight, + 1, + false, + "URA" + ); + to!( + to_alphanumeric_ure, + to_alphanumeric, + QuadrantKind::TopRight, + 5, + false, + "URE" + ); + to!( + to_alphanumeric_lra, + to_alphanumeric, + QuadrantKind::BottomRight, + 1, + false, + "LRA" + ); + to!( + to_alphanumeric_lre, + to_alphanumeric, + QuadrantKind::BottomRight, + 5, + false, + "LRE" + ); + to!( + to_alphanumeric_lla, + to_alphanumeric, + QuadrantKind::BottomLeft, + 1, + false, + "LLA" + ); + to!( + to_alphanumeric_lle, + to_alphanumeric, + QuadrantKind::BottomLeft, + 5, + false, + "LLE" + ); + from!( + from_alphanumeric_ul1, + from_alphanumeric, + "UL1", + QuadrantKind::TopLeft, + 1, + true + ); + from!( + from_alphanumeric_ul8, + from_alphanumeric, + "UL8", + QuadrantKind::TopLeft, + 8, + true + ); + from!( + from_alphanumeric_ur1, + from_alphanumeric, + "UR1", + QuadrantKind::TopRight, + 1, + true + ); + from!( + from_alphanumeric_ur8, + from_alphanumeric, + "UR8", + QuadrantKind::TopRight, + 8, + true + ); + from!( + from_alphanumeric_lr1, + from_alphanumeric, + "LR1", + QuadrantKind::BottomRight, + 1, + true + ); + from!( + from_alphanumeric_lr8, + from_alphanumeric, + "LR8", + QuadrantKind::BottomRight, + 8, + true + ); + from!( + from_alphanumeric_ll1, + from_alphanumeric, + "LL1", + QuadrantKind::BottomLeft, + 1, + true + ); + from!( + from_alphanumeric_ll8, + from_alphanumeric, + "LL8", + QuadrantKind::BottomLeft, + 8, + true + ); + from!( + from_alphanumeric_ula, + from_alphanumeric, + "ULA", + QuadrantKind::TopLeft, + 1, + false + ); + from!( + from_alphanumeric_ule, + from_alphanumeric, + "ULE", + QuadrantKind::TopLeft, + 5, + false + ); + from!( + from_alphanumeric_ura, + from_alphanumeric, + "URA", + QuadrantKind::TopRight, + 1, + false + ); + from!( + from_alphanumeric_ure, + from_alphanumeric, + "URE", + QuadrantKind::TopRight, + 5, + false + ); + from!( + from_alphanumeric_lra, + from_alphanumeric, + "LRA", + QuadrantKind::BottomRight, + 1, + false + ); + from!( + from_alphanumeric_lre, + from_alphanumeric, + "LRE", + QuadrantKind::BottomRight, + 5, + false + ); + from!( + from_alphanumeric_lla, + from_alphanumeric, + "LLA", + QuadrantKind::BottomLeft, + 1, + false + ); + from!( + from_alphanumeric_lle, + from_alphanumeric, + "LLE", + QuadrantKind::BottomLeft, + 5, + false + ); + from_fail!(from_alphanumeric_fail_ul0, from_alphanumeric, "UL0"); + from_fail!(from_alphanumeric_fail_ul9, from_alphanumeric, "UL9"); + from_fail!(from_alphanumeric_fail_ur0, from_alphanumeric, "UR0"); + from_fail!(from_alphanumeric_fail_ur9, from_alphanumeric, "UR9"); + from_fail!(from_alphanumeric_fail_lr0, from_alphanumeric, "LR0"); + from_fail!(from_alphanumeric_fail_lr9, from_alphanumeric, "LR9"); + from_fail!(from_alphanumeric_fail_ll0, from_alphanumeric, "LL0"); + from_fail!(from_alphanumeric_fail_ll9, from_alphanumeric, "LL9"); + from_fail!(from_alphanumeric_fail_ulat, from_alphanumeric, "UL@"); + from_fail!(from_alphanumeric_fail_ulf, from_alphanumeric, "ULF"); + from_fail!(from_alphanumeric_fail_urat, from_alphanumeric, "UR@"); + from_fail!(from_alphanumeric_fail_urf, from_alphanumeric, "URF"); + from_fail!(from_alphanumeric_fail_lrat, from_alphanumeric, "LR@"); + from_fail!(from_alphanumeric_fail_lrf, from_alphanumeric, "LRF"); + from_fail!(from_alphanumeric_fail_llat, from_alphanumeric, "LL@"); + from_fail!(from_alphanumeric_fail_llf, from_alphanumeric, "LLF"); +} From 845ba2fd3317d2e1b6e8addd52e39048f549301d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Barth=C3=A9s?= Date: Fri, 2 Sep 2022 18:37:21 +0200 Subject: [PATCH 08/12] docs: Add information to cargo.toml --- Cargo.toml | 3 +++ dental-notation-cli/Cargo.toml | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d129dc2..c80abf6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,9 @@ name = "dental-notation" version = "0.1.0" edition = "2021" +repository = "https://git.barthes.xyz/guilhem/dental-notation" +license = "GPL-3.0-or-later" +categories = ["parsing"] [dependencies] owo-colors = "3" \ No newline at end of file diff --git a/dental-notation-cli/Cargo.toml b/dental-notation-cli/Cargo.toml index 30a88a9..200a314 100644 --- a/dental-notation-cli/Cargo.toml +++ b/dental-notation-cli/Cargo.toml @@ -2,8 +2,9 @@ name = "dental-notation-cli" version = "0.1.0" edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +repository = "https://git.barthes.xyz/guilhem/dental-notation-cli" +license = "GPL-3.0-or-later" +categories = ["parsing", "command-line-utilities"] [dependencies] clap = {version = "3.2.5", features = [ "derive" ] } From f604d70aa1e5fc0b5e1689f8ee6e691d5805f639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Barth=C3=A9s?= Date: Fri, 2 Sep 2022 18:41:21 +0200 Subject: [PATCH 09/12] docs: Add description in manifest --- Cargo.toml | 1 + dental-notation-cli/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index c80abf6..dd9314a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ name = "dental-notation" version = "0.1.0" edition = "2021" +description = "Library converting between different tooth numbering systems" repository = "https://git.barthes.xyz/guilhem/dental-notation" license = "GPL-3.0-or-later" categories = ["parsing"] diff --git a/dental-notation-cli/Cargo.toml b/dental-notation-cli/Cargo.toml index 200a314..9887ebd 100644 --- a/dental-notation-cli/Cargo.toml +++ b/dental-notation-cli/Cargo.toml @@ -2,6 +2,7 @@ name = "dental-notation-cli" version = "0.1.0" edition = "2021" +description = "CLI used to represent mouth in different tooth numbering systems and converting between these systems" repository = "https://git.barthes.xyz/guilhem/dental-notation-cli" license = "GPL-3.0-or-later" categories = ["parsing", "command-line-utilities"] From 6287fc88279b6158be29f7c69c250caf1f28a278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Barth=C3=A9s?= Date: Fri, 2 Sep 2022 20:53:41 +0200 Subject: [PATCH 10/12] refactor: split cli --- dental-notation-cli/.gitignore | 1 - dental-notation-cli/Cargo.lock | 252 -------------------------------- dental-notation-cli/Cargo.toml | 12 -- dental-notation-cli/src/cli.rs | 93 ------------ dental-notation-cli/src/main.rs | 5 - 5 files changed, 363 deletions(-) delete mode 100644 dental-notation-cli/.gitignore delete mode 100644 dental-notation-cli/Cargo.lock delete mode 100644 dental-notation-cli/Cargo.toml delete mode 100644 dental-notation-cli/src/cli.rs delete mode 100644 dental-notation-cli/src/main.rs diff --git a/dental-notation-cli/.gitignore b/dental-notation-cli/.gitignore deleted file mode 100644 index ea8c4bf..0000000 --- a/dental-notation-cli/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/dental-notation-cli/Cargo.lock b/dental-notation-cli/Cargo.lock deleted file mode 100644 index b73cfd4..0000000 --- a/dental-notation-cli/Cargo.lock +++ /dev/null @@ -1,252 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "clap" -version = "3.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3dbbb6653e7c55cc8595ad3e1f7be8f32aba4eb7ff7f0fd1163d4f3d137c0a9" -dependencies = [ - "atty", - "bitflags", - "clap_derive", - "clap_lex", - "indexmap", - "once_cell", - "strsim", - "termcolor", - "textwrap", -] - -[[package]] -name = "clap_derive" -version = "3.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba52acd3b0a5c33aeada5cdaa3267cdc7c594a98731d4268cdc1532f4264cb4" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - -[[package]] -name = "dental-notation" -version = "0.1.0" -dependencies = [ - "owo-colors", -] - -[[package]] -name = "dental-notation-cli" -version = "0.1.0" -dependencies = [ - "clap", - "dental-notation", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "heck" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "indexmap" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "libc" -version = "0.2.127" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" - -[[package]] -name = "once_cell" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" - -[[package]] -name = "os_str_bytes" -version = "6.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4" - -[[package]] -name = "owo-colors" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "decf7381921fea4dcb2549c5667eda59b3ec297ab7e2b5fc33eac69d2e7da87b" - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "termcolor" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" - -[[package]] -name = "unicode-ident" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/dental-notation-cli/Cargo.toml b/dental-notation-cli/Cargo.toml deleted file mode 100644 index 9887ebd..0000000 --- a/dental-notation-cli/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "dental-notation-cli" -version = "0.1.0" -edition = "2021" -description = "CLI used to represent mouth in different tooth numbering systems and converting between these systems" -repository = "https://git.barthes.xyz/guilhem/dental-notation-cli" -license = "GPL-3.0-or-later" -categories = ["parsing", "command-line-utilities"] - -[dependencies] -clap = {version = "3.2.5", features = [ "derive" ] } -dental-notation = { path = ".." } \ No newline at end of file diff --git a/dental-notation-cli/src/cli.rs b/dental-notation-cli/src/cli.rs deleted file mode 100644 index 407d8ec..0000000 --- a/dental-notation-cli/src/cli.rs +++ /dev/null @@ -1,93 +0,0 @@ -use clap::{Parser, Subcommand, ValueEnum}; -use dental_notation::display::{ToothCliFormatter, ToothDisplay}; -use dental_notation::NotationKind; -use dental_notation::Tooth; - -#[derive(Copy, Clone, Debug, ValueEnum)] -enum NotationKindArg { - Iso, - Uns, - Alphanumeric, -} -#[derive(Debug, Subcommand)] -enum Action { - Convert { - #[clap(value_enum, short = 'f', long)] - from: NotationKindArg, - - #[clap(value_enum, short = 't', long)] - to: NotationKindArg, - - #[clap(value_parser)] - value: String, - }, - Display { - #[clap(value_enum, short = 'n', long)] - notation: NotationKindArg, - #[clap(takes_value = false, short = 'p', long)] - primary: bool, - #[clap(value_parser)] - value: Option, - }, -} -#[derive(Parser, Debug)] -struct Args { - #[clap(subcommand)] - action: Action, -} - -impl Into for NotationKindArg { - fn into(self) -> NotationKind { - (&self).into() - } -} - -impl Into for &NotationKindArg { - fn into(self) -> NotationKind { - match self { - NotationKindArg::Iso => NotationKind::Iso, - NotationKindArg::Uns => NotationKind::Uns, - NotationKindArg::Alphanumeric => NotationKind::Alphanumeric, - } - } -} - -pub fn run_cli() { - let args = Args::parse(); - - match &args.action { - Action::Convert { from, to, value } => { - let tooth_result = Tooth::from(value, &from.into()); - - let output_string = match tooth_result { - Ok(tooth) => tooth.to(&to.into()), - Err(err) => err, - }; - - println!("{}", output_string); - } - Action::Display { - notation, - primary, - value, - } => { - let converted_value = match value { - Some(t) => { - let tooth_result = Tooth::from(t, ¬ation.into()); - match tooth_result { - Ok(tr) => Some(tr), - Err(err) => { - eprintln!("{}", err); - return; - } - } - } - None => None, - }; - println!( - "{}", - ToothCliFormatter::format(¬ation.into(), !primary, &converted_value) - ); - } - }; -} diff --git a/dental-notation-cli/src/main.rs b/dental-notation-cli/src/main.rs deleted file mode 100644 index 0b87e87..0000000 --- a/dental-notation-cli/src/main.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod cli; - -fn main() { - cli::run_cli() -} From 56a50ab6f4247b259794bea1cdcb31434b349808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Barth=C3=A9s?= Date: Fri, 2 Sep 2022 20:53:57 +0200 Subject: [PATCH 11/12] ci: bump version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fb84c2c..6c5a3a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "dental-notation" -version = "0.1.0" +version = "1.0.0" dependencies = [ "owo-colors", ] diff --git a/Cargo.toml b/Cargo.toml index dd9314a..0107796 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dental-notation" -version = "0.1.0" +version = "1.0.0" edition = "2021" description = "Library converting between different tooth numbering systems" repository = "https://git.barthes.xyz/guilhem/dental-notation" From d59d253ee9c6a01057643c7fa0966e63d0531a7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guilhem=20Barth=C3=A9s?= Date: Fri, 2 Sep 2022 23:03:40 +0200 Subject: [PATCH 12/12] ci: Add CI pipeline file --- .drone.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .drone.yml diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..175bbc7 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,15 @@ +kind: pipeline +type: docker +name: default + +steps: + - name: publish + image: rust:slim + commands: + - /usr/bin/env cargo publish + environment: + CARGO_REGISTRY_TOKEN: + from_secret: cargo_token +trigger: + event: + - tag