1use lindera::dictionary::Metadata;
10
11use crate::schema::CoreSchema;
12
13const DEFAULT_NAME: &str = "default";
15const DEFAULT_ENCODING: &str = "UTF-8";
17const DEFAULT_WORD_COST: i16 = -10000;
19const DEFAULT_LEFT_CONTEXT_ID: u16 = 1288;
21const DEFAULT_RIGHT_CONTEXT_ID: u16 = 1288;
23const DEFAULT_FIELD_VALUE: &str = "*";
25
26fn default_user_dictionary_schema() -> CoreSchema {
28 CoreSchema::new(vec![
29 "surface".to_string(),
30 "reading".to_string(),
31 "pronunciation".to_string(),
32 ])
33}
34
35#[derive(Debug, Clone)]
44pub struct CoreMetadata {
45 pub name: String,
47 pub encoding: String,
49 pub default_word_cost: i16,
51 pub default_left_context_id: u16,
53 pub default_right_context_id: u16,
55 pub default_field_value: String,
57 pub flexible_csv: bool,
59 pub skip_invalid_cost_or_id: bool,
61 pub normalize_details: bool,
63 pub dictionary_schema: CoreSchema,
65 pub user_dictionary_schema: CoreSchema,
67}
68
69impl CoreMetadata {
70 #[allow(clippy::too_many_arguments)]
72 pub fn new(
73 name: Option<String>,
74 encoding: Option<String>,
75 default_word_cost: Option<i16>,
76 default_left_context_id: Option<u16>,
77 default_right_context_id: Option<u16>,
78 default_field_value: Option<String>,
79 flexible_csv: Option<bool>,
80 skip_invalid_cost_or_id: Option<bool>,
81 normalize_details: Option<bool>,
82 dictionary_schema: Option<CoreSchema>,
83 user_dictionary_schema: Option<CoreSchema>,
84 ) -> Self {
85 Self {
86 name: name.unwrap_or_else(|| DEFAULT_NAME.to_string()),
87 encoding: encoding.unwrap_or_else(|| DEFAULT_ENCODING.to_string()),
88 default_word_cost: default_word_cost.unwrap_or(DEFAULT_WORD_COST),
89 default_left_context_id: default_left_context_id.unwrap_or(DEFAULT_LEFT_CONTEXT_ID),
90 default_right_context_id: default_right_context_id.unwrap_or(DEFAULT_RIGHT_CONTEXT_ID),
91 default_field_value: default_field_value
92 .unwrap_or_else(|| DEFAULT_FIELD_VALUE.to_string()),
93 flexible_csv: flexible_csv.unwrap_or(false),
94 skip_invalid_cost_or_id: skip_invalid_cost_or_id.unwrap_or(false),
95 normalize_details: normalize_details.unwrap_or(false),
96 dictionary_schema: dictionary_schema.unwrap_or_else(CoreSchema::create_default),
97 user_dictionary_schema: user_dictionary_schema
98 .unwrap_or_else(default_user_dictionary_schema),
99 }
100 }
101
102 pub fn create_default() -> Self {
104 Self::new(
105 None, None, None, None, None, None, None, None, None, None, None,
106 )
107 }
108}
109
110impl Default for CoreMetadata {
111 fn default() -> Self {
113 Self::create_default()
114 }
115}
116
117impl From<Metadata> for CoreMetadata {
118 fn from(metadata: Metadata) -> Self {
120 Self {
121 name: metadata.name,
122 encoding: metadata.encoding,
123 default_word_cost: metadata.default_word_cost,
124 default_left_context_id: metadata.default_left_context_id,
125 default_right_context_id: metadata.default_right_context_id,
126 default_field_value: metadata.default_field_value,
127 flexible_csv: metadata.flexible_csv,
128 skip_invalid_cost_or_id: metadata.skip_invalid_cost_or_id,
129 normalize_details: metadata.normalize_details,
130 dictionary_schema: metadata.dictionary_schema.into(),
131 user_dictionary_schema: metadata.user_dictionary_schema.into(),
132 }
133 }
134}
135
136impl From<CoreMetadata> for Metadata {
137 fn from(metadata: CoreMetadata) -> Self {
139 Metadata::new(
140 metadata.name,
141 metadata.encoding,
142 metadata.default_word_cost,
143 metadata.default_left_context_id,
144 metadata.default_right_context_id,
145 metadata.default_field_value,
146 metadata.flexible_csv,
147 metadata.skip_invalid_cost_or_id,
148 metadata.normalize_details,
149 metadata.dictionary_schema.into(),
150 metadata.user_dictionary_schema.into(),
151 )
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158
159 #[test]
160 fn create_default_uses_binding_defaults() {
161 let m = CoreMetadata::create_default();
162 assert_eq!(m.name, "default");
163 assert_eq!(m.encoding, "UTF-8");
164 assert_eq!(m.default_word_cost, -10000);
165 assert_eq!(m.default_left_context_id, 1288);
166 assert_eq!(m.default_right_context_id, 1288);
167 assert_eq!(m.default_field_value, "*");
168 assert!(!m.flexible_csv);
169 assert!(!m.skip_invalid_cost_or_id);
170 assert!(!m.normalize_details);
171 assert_eq!(m.dictionary_schema.field_count(), 13);
173 assert_eq!(m.dictionary_schema.fields()[5], "pos_detail_1");
174 assert_eq!(m.user_dictionary_schema.fields().len(), 3);
175 assert_eq!(m.user_dictionary_schema.fields()[1], "reading");
176 }
177
178 #[test]
179 fn new_applies_overrides() {
180 let m = CoreMetadata::new(
181 Some("custom".to_string()),
182 Some("EUC-JP".to_string()),
183 Some(-5000),
184 Some(100),
185 Some(200),
186 Some("N/A".to_string()),
187 Some(true),
188 Some(true),
189 Some(true),
190 None,
191 None,
192 );
193 assert_eq!(m.name, "custom");
194 assert_eq!(m.encoding, "EUC-JP");
195 assert_eq!(m.default_word_cost, -5000);
196 assert_eq!(m.default_left_context_id, 100);
197 assert_eq!(m.default_right_context_id, 200);
198 assert_eq!(m.default_field_value, "N/A");
199 assert!(m.flexible_csv && m.skip_invalid_cost_or_id && m.normalize_details);
200 }
201
202 #[test]
203 fn converts_to_and_from_lindera() {
204 let m = CoreMetadata::create_default();
205 let lindera: Metadata = m.into();
206 assert_eq!(lindera.name, "default");
207 assert_eq!(lindera.default_left_context_id, 1288);
208 assert_eq!(lindera.user_dictionary_schema.field_count(), 3);
209
210 let back: CoreMetadata = lindera.into();
211 assert_eq!(back.name, "default");
212 assert_eq!(back.dictionary_schema.fields()[5], "pos_detail_1");
213 }
214}