1use std::fmt::Debug;
2use std::fmt::Display;
3
4use jpreprocess_core::word_entry::WordEntry;
5use jpreprocess_core::{
6 cform::CForm, ctype::CType, pos::*, pronunciation::Pronunciation, word_details::WordDetails,
7};
8
9use jpreprocess_core::accent_rule::ChainRules;
10
11#[derive(Clone, PartialEq, Debug)]
12pub struct NJDNode {
13 string: String, details: WordDetails,
15}
16
17impl Display for NJDNode {
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 write!(
20 f,
21 "{},{}",
22 self.string,
23 self.details.to_str_vec(self.string.to_owned()).join(",")
24 )
25 }
26}
27
28impl NJDNode {
29 pub fn new_single(s: &str) -> Self {
30 let nodes = Self::load_csv(s);
31 if nodes.len() == 1 {
32 nodes.into_iter().next().unwrap()
33 } else {
34 panic!("input string must contain exactly one node.");
35 }
36 }
37 pub fn load_csv(s: &str) -> Vec<Self> {
38 let splited = {
39 let mut splited: Vec<&str> = s.split(',').collect();
40 splited.resize(13, "");
41 splited
42 };
43 Self::load_str(splited[0], &splited[1..splited.len()])
44 }
45 pub fn load_str(string: &str, details: &[&str]) -> Vec<Self> {
46 let entry = WordEntry::load(details).unwrap();
47 Self::load(string, &entry)
48 }
49 pub fn load(string: &str, entry: &WordEntry) -> Vec<Self> {
50 entry
51 .get_with_string(string)
52 .into_iter()
53 .map(|(string, details)| Self { string, details })
54 .collect()
55 }
56
57 pub fn transfer_from(&mut self, node: &mut Self) {
58 self.string.push_str(&node.string);
59 if let Some(add) = &node.details.read {
60 if let Some(read) = &mut self.details.read {
61 read.push_str(add);
62 } else {
63 self.details.read = Some(add.to_string());
64 }
65 }
66 self.get_pron_mut().transfer_from(&node.details.pron);
67 node.reset();
68 }
69 pub fn reset(&mut self) {
70 self.string.clear();
71 self.details = WordDetails::default();
72 }
73}
74
75impl NJDNode {
77 pub fn get_chain_flag(&self) -> Option<bool> {
78 self.details.chain_flag
79 }
80 pub fn set_chain_flag(&mut self, chain_flag: bool) {
81 self.details.chain_flag = Some(chain_flag);
82 }
83
84 pub fn get_chain_rule(&self) -> &ChainRules {
85 &self.details.chain_rule
86 }
87 pub fn unset_chain_rule(&mut self) {
88 self.details.chain_rule.unset();
89 }
90
91 pub fn get_pos(&self) -> &POS {
92 &self.details.pos
93 }
94 pub fn get_pos_mut(&mut self) -> &mut POS {
95 &mut self.details.pos
96 }
97
98 pub fn is_renyou(&self) -> bool {
99 self.details.cform.is_renyou()
100 }
101 pub fn get_ctype(&self) -> &CType {
102 &self.details.ctype
103 }
104 pub fn get_cform(&self) -> &CForm {
105 &self.details.cform
106 }
107
108 pub fn get_string(&self) -> &str {
109 self.string.as_str()
110 }
111 pub fn replace_string(&mut self, new_string: &str) {
112 self.string = new_string.to_string();
113 }
114
115 pub fn get_read(&self) -> Option<&str> {
116 self.details.read.as_deref()
117 }
118 pub fn set_read(&mut self, read: &str) {
119 self.details.read = Some(read.to_string());
120 }
121
122 pub fn get_pron(&self) -> &Pronunciation {
123 &self.details.pron
124 }
125 pub fn get_pron_mut(&mut self) -> &mut Pronunciation {
126 &mut self.details.pron
127 }
128 pub fn set_pron(&mut self, pron: Pronunciation) {
129 self.details.pron = pron;
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::NJDNode;
136
137 #[test]
138 fn single_node() {
139 let node = NJDNode::new_single(".,名詞,接尾,助数詞,*,*,*,.,テン,テン,0/2,*,-1");
140 assert_eq!(node.string, ".");
141 assert!(!node.is_renyou());
142
143 assert_eq!(
144 node.to_string(),
145 ".,名詞,接尾,助数詞,*,*,*,.,テン,テン,0/2,*,-1"
146 )
147 }
148
149 #[test]
150 fn multiple_nodes() {
151 let nodes = NJDNode::load_csv("あーあ,感動詞,*,*,*,*,*,あー:あ,アー:ア,アー:ア,1/2:1/1,C1");
152 assert_eq!(nodes.len(), 2);
153
154 assert_eq!(
155 nodes[0].to_string(),
156 "あー,感動詞,*,*,*,*,*,あー,アー,アー,1/2,C1,-1"
157 );
158 assert_eq!(
159 nodes[1].to_string(),
160 "あ,感動詞,*,*,*,*,*,あ,ア,ア,1/1,C1,0"
161 );
162 }
163
164 #[test]
165 fn test_send() {
166 fn assert_send<T: Send>() {}
167 assert_send::<NJDNode>();
168 }
169
170 #[test]
171 fn test_sync() {
172 fn assert_sync<T: Sync>() {}
173 assert_sync::<NJDNode>();
174 }
175}