harper_core/
irregular_verbs.rs1use lazy_static::lazy_static;
2use serde::Deserialize;
3use std::sync::Arc;
4
5type Verb = (String, String, String);
6
7#[derive(Debug, Deserialize)]
8pub struct IrregularVerbs {
9 verbs: Vec<Verb>,
10}
11
12fn uncached_inner_new() -> Arc<IrregularVerbs> {
15 IrregularVerbs::from_json_file(include_str!("../irregular_verbs.json"))
16 .map(Arc::new)
17 .unwrap_or_else(|e| panic!("Failed to load irregular verb table: {}", e))
18}
19
20lazy_static! {
21 static ref VERBS: Arc<IrregularVerbs> = uncached_inner_new();
22}
23
24impl IrregularVerbs {
25 pub fn new() -> Self {
26 Self { verbs: 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 verbs JSON");
33
34 let mut verbs = Vec::new();
35
36 for value in values {
37 match value {
38 serde_json::Value::Array(arr) if arr.len() == 3 => {
39 if let (Some(lemma), Some(preterite), Some(past_participle)) =
41 (arr[0].as_str(), arr[1].as_str(), arr[2].as_str())
42 {
43 verbs.push((
44 lemma.to_string(),
45 preterite.to_string(),
46 past_participle.to_string(),
47 ));
48 }
49 }
50 serde_json::Value::String(_) => {}
52 _ => {}
53 }
54 }
55
56 Ok(Self { verbs })
57 }
58
59 pub fn curated() -> Arc<Self> {
60 (*VERBS).clone()
61 }
62
63 pub fn get_past_participle_for_preterite(&self, preterite: &str) -> Option<&str> {
64 self.verbs
65 .iter()
66 .find(|(_, pt, _)| pt.eq_ignore_ascii_case(preterite))
67 .map(|(_, _, pp)| pp.as_str())
68 }
69}
70
71impl Default for IrregularVerbs {
72 fn default() -> Self {
73 Self::new()
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn can_find_irregular_past_participle_for_preterite_lowercase() {
83 assert_eq!(
84 IrregularVerbs::curated().get_past_participle_for_preterite("arose"),
85 Some("arisen")
86 );
87 }
88
89 #[test]
90 fn can_find_irregular_past_participle_for_preterite_uppercase() {
91 assert_eq!(
92 IrregularVerbs::curated().get_past_participle_for_preterite("WENT"),
93 Some("gone")
94 );
95 }
96
97 #[test]
98 fn can_find_irregular_past_participle_same_as_past_tense() {
99 assert_eq!(
100 IrregularVerbs::curated().get_past_participle_for_preterite("taught"),
101 Some("taught")
102 );
103 }
104
105 #[test]
106 fn cant_find_regular_past_participle() {
107 assert_eq!(
108 IrregularVerbs::curated().get_past_participle_for_preterite("walked"),
109 None
110 );
111 }
112
113 #[test]
114 fn cant_find_non_verb() {
115 assert_eq!(
116 IrregularVerbs::curated().get_past_participle_for_preterite("the"),
117 None
118 );
119 }
120}