harper_core/
irregular_nouns.rs1use lazy_static::lazy_static;
2use serde::Deserialize;
3use std::sync::Arc;
4
5type Noun = (String, String);
6
7#[derive(Debug, Deserialize)]
8pub struct IrregularNouns {
9 nouns: Vec<Noun>,
10}
11
12fn uncached_inner_new() -> Arc<IrregularNouns> {
15 IrregularNouns::from_json_file(include_str!("../irregular_nouns.json"))
16 .map(Arc::new)
17 .unwrap_or_else(|e| panic!("Failed to load irregular noun table: {}", e))
18}
19
20lazy_static! {
21 static ref NOUNS: Arc<IrregularNouns> = uncached_inner_new();
22}
23
24impl IrregularNouns {
25 pub fn new() -> Self {
26 Self { nouns: vec![] }
27 }
28
29 pub fn from_json_file(json: &str) -> Result<Self, serde_json::Error> {
30 let values: Vec<serde_json::Value> =
32 serde_json::from_str(json).expect("Failed to parse irregular nouns JSON");
33
34 let mut nouns = Vec::new();
35
36 for value in values {
37 match value {
38 serde_json::Value::Array(arr) if arr.len() == 2 => {
39 if let (Some(singular), Some(plural)) = (arr[0].as_str(), arr[1].as_str()) {
41 nouns.push((singular.to_string(), plural.to_string()));
42 }
43 }
44 serde_json::Value::String(_) => {}
46 _ => {}
47 }
48 }
49
50 Ok(Self { nouns })
51 }
52
53 pub fn curated() -> Arc<Self> {
54 (*NOUNS).clone()
55 }
56
57 pub fn get_plural_for_singular(&self, singular: &str) -> Option<&str> {
58 self.nouns
59 .iter()
60 .find(|(sg, _)| sg.eq_ignore_ascii_case(singular))
61 .map(|(_, pl)| pl.as_str())
62 }
63
64 pub fn get_singular_for_plural(&self, plural: &str) -> Option<&str> {
65 self.nouns
66 .iter()
67 .find(|(_, pl)| pl.eq_ignore_ascii_case(plural))
68 .map(|(sg, _)| sg.as_str())
69 }
70}
71
72impl Default for IrregularNouns {
73 fn default() -> Self {
74 Self::new()
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn can_find_irregular_plural_for_singular_lowercase() {
84 assert_eq!(
85 IrregularNouns::curated().get_plural_for_singular("man"),
86 Some("men")
87 );
88 }
89
90 #[test]
91 fn can_find_irregular_plural_for_singular_uppercase() {
92 assert_eq!(
93 IrregularNouns::curated().get_plural_for_singular("WOMAN"),
94 Some("women")
95 );
96 }
97
98 #[test]
99 fn can_find_singular_for_irregular_plural() {
100 assert_eq!(
101 IrregularNouns::curated().get_singular_for_plural("children"),
102 Some("child")
103 );
104 }
105
106 #[test]
107 fn cant_find_regular_plural() {
108 assert_eq!(
109 IrregularNouns::curated().get_plural_for_singular("car"),
110 None
111 );
112 }
113
114 #[test]
115 fn cant_find_non_noun() {
116 assert_eq!(
117 IrregularNouns::curated().get_plural_for_singular("the"),
118 None
119 );
120 }
121}