lindera_dictionary/dictionary/
metadata.rs1use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
2use serde::{Deserialize, Serialize};
3
4use crate::dictionary::context_id_map::ContextIdMap;
5use crate::dictionary::schema::Schema;
6
7const DEFAULT_WORD_COST: i16 = -10000;
8const DEFAULT_LEFT_CONTEXT_ID: u16 = 1288;
9const DEFAULT_RIGHT_CONTEXT_ID: u16 = 1288;
10const DEFAULT_FIELD_VALUE: &str = "*";
11
12#[derive(Clone, Serialize, Deserialize, Archive, RkyvSerialize, RkyvDeserialize)]
13
14pub struct ModelInfo {
15 pub feature_count: usize,
16 pub label_count: usize,
17 pub max_left_context_id: usize,
18 pub max_right_context_id: usize,
19 pub connection_matrix_size: String,
20 pub version: String,
21 pub training_iterations: u64,
22 pub regularization: f64,
23 pub updated_at: u64,
24}
25
26#[derive(Clone, Serialize, Deserialize, Archive, RkyvSerialize, RkyvDeserialize)]
27
28pub struct Metadata {
29 pub name: String, pub encoding: String, pub default_word_cost: i16, pub default_left_context_id: u16, pub default_right_context_id: u16, pub default_field_value: String, pub flexible_csv: bool, pub skip_invalid_cost_or_id: bool, pub normalize_details: bool, #[serde(default, skip_serializing_if = "std::ops::Not::not")]
43 pub connection_id_mapping: bool,
44 #[serde(default, skip_serializing_if = "Option::is_none")]
52 pub context_id_map: Option<ContextIdMap>,
53 pub dictionary_schema: Schema, pub user_dictionary_schema: Schema, #[serde(skip_serializing_if = "Option::is_none")]
56 pub model_info: Option<ModelInfo>, }
58
59impl Default for Metadata {
60 fn default() -> Self {
61 Metadata::new(
63 "default".to_string(),
64 "UTF-8".to_string(),
65 DEFAULT_WORD_COST,
66 DEFAULT_LEFT_CONTEXT_ID,
67 DEFAULT_RIGHT_CONTEXT_ID,
68 DEFAULT_FIELD_VALUE.to_string(),
69 false,
70 false,
71 false,
72 Schema::default(),
73 Schema::new(vec![
74 "surface".to_string(),
75 "reading".to_string(),
76 "pronunciation".to_string(),
77 ]),
78 )
79 }
80}
81
82impl Metadata {
83 #[allow(clippy::too_many_arguments)]
84 pub fn new(
85 name: String,
86 encoding: String,
87 simple_word_cost: i16,
88 default_left_context_id: u16,
89 default_right_context_id: u16,
90 default_field_value: String,
91 flexible_csv: bool,
92 skip_invalid_cost_or_id: bool,
93 normalize_details: bool,
94 schema: Schema,
95 userdic_schema: Schema,
96 ) -> Self {
97 Self {
98 encoding,
99 default_word_cost: simple_word_cost,
100 default_left_context_id,
101 default_right_context_id,
102 default_field_value,
103 dictionary_schema: schema,
104 name,
105 flexible_csv,
106 skip_invalid_cost_or_id,
107 normalize_details,
108 connection_id_mapping: false,
109 context_id_map: None,
110 user_dictionary_schema: userdic_schema,
111 model_info: None,
112 }
113 }
114
115 pub fn load(data: &[u8]) -> crate::LinderaResult<Self> {
118 if data.is_empty() {
120 return Err(crate::error::LinderaErrorKind::Io
121 .with_error(anyhow::anyhow!("Empty metadata data")));
122 }
123
124 serde_json::from_slice(data).map_err(|err| {
126 crate::error::LinderaErrorKind::Deserialize
127 .with_error(anyhow::anyhow!(err))
128 .add_context("Failed to deserialize metadata from JSON")
129 })
130 }
131
132 pub fn load_or_default(data: &[u8], default_fn: fn() -> Self) -> Self {
135 if data.is_empty() {
136 default_fn()
137 } else {
138 match Self::load(data) {
139 Ok(metadata) => metadata,
140 Err(_) => default_fn(),
141 }
142 }
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149
150 #[test]
151 fn test_metadata_default() {
152 let metadata = Metadata::default();
153 assert_eq!(metadata.name, "default");
154 }
156
157 #[test]
158 fn test_metadata_new() {
159 let schema = Schema::default();
160 let metadata = Metadata::new(
161 "TestDict".to_string(),
162 "UTF-8".to_string(),
163 -10000,
164 0,
165 0,
166 "*".to_string(),
167 false,
168 false,
169 false,
170 schema.clone(),
171 Schema::new(vec!["surface".to_string(), "reading".to_string()]),
172 );
173 assert_eq!(metadata.name, "TestDict");
174 }
176
177 #[test]
178 fn test_metadata_serialization() {
179 let metadata = Metadata::default();
180
181 let serialized = serde_json::to_string(&metadata).unwrap();
183 assert!(serialized.contains("default"));
184 assert!(serialized.contains("schema"));
185 assert!(serialized.contains("name"));
186
187 let deserialized: Metadata = serde_json::from_str(&serialized).unwrap();
189 assert_eq!(deserialized.name, "default");
190 }
192}