lindera_ruby/
dictionary.rs1use std::path::Path;
7
8use magnus::prelude::*;
9use magnus::{Error, Ruby, function, method};
10
11use lindera::dictionary::{
12 Dictionary, DictionaryBuilder, Metadata, UserDictionary,
13 load_dictionary as lindera_load_dictionary,
14 load_user_dictionary as lindera_load_user_dictionary,
15};
16
17use crate::error::to_magnus_error;
18use crate::metadata::RbMetadata;
19
20#[magnus::wrap(class = "Lindera::Dictionary", free_immediately, size)]
24#[derive(Clone)]
25pub struct RbDictionary {
26 pub inner: Dictionary,
28}
29
30impl RbDictionary {
31 fn metadata_name(&self) -> String {
37 self.inner.metadata.name.clone()
38 }
39
40 fn metadata_encoding(&self) -> String {
46 self.inner.metadata.encoding.clone()
47 }
48
49 fn metadata(&self) -> RbMetadata {
55 RbMetadata::from(self.inner.metadata.clone())
56 }
57
58 fn to_s(&self) -> String {
60 "Dictionary".to_string()
61 }
62
63 fn inspect(&self) -> String {
65 format!(
66 "#<Lindera::Dictionary: name='{}'>",
67 self.inner.metadata.name
68 )
69 }
70}
71
72#[magnus::wrap(class = "Lindera::UserDictionary", free_immediately, size)]
77#[derive(Clone)]
78pub struct RbUserDictionary {
79 pub inner: UserDictionary,
81}
82
83impl RbUserDictionary {
84 fn to_s(&self) -> String {
86 "UserDictionary".to_string()
87 }
88
89 fn inspect(&self) -> String {
91 "UserDictionary()".to_string()
92 }
93}
94
95fn load_dictionary(uri: String) -> Result<RbDictionary, Error> {
105 let ruby = Ruby::get().expect("Ruby runtime not initialized");
106 lindera_load_dictionary(&uri)
107 .map_err(|e| {
108 to_magnus_error(
109 &ruby,
110 format!("Failed to load dictionary from '{uri}': {e}"),
111 )
112 })
113 .map(|d| RbDictionary { inner: d })
114}
115
116fn load_user_dictionary(uri: String, metadata: &RbMetadata) -> Result<RbUserDictionary, Error> {
127 let ruby = Ruby::get().expect("Ruby runtime not initialized");
128 let meta: Metadata = metadata.clone().into();
129 lindera_load_user_dictionary(&uri, &meta)
130 .map_err(|e| {
131 to_magnus_error(
132 &ruby,
133 format!("Failed to load user dictionary from '{uri}': {e}"),
134 )
135 })
136 .map(|d| RbUserDictionary { inner: d })
137}
138
139fn build_dictionary(
147 input_dir: String,
148 output_dir: String,
149 metadata: &RbMetadata,
150) -> Result<(), Error> {
151 let ruby = Ruby::get().expect("Ruby runtime not initialized");
152 let input_path = Path::new(&input_dir);
153 let output_path = Path::new(&output_dir);
154
155 if !input_path.exists() {
156 return Err(Error::new(
157 ruby.exception_arg_error(),
158 format!("Input directory does not exist: {input_dir}"),
159 ));
160 }
161
162 let builder = DictionaryBuilder::new(metadata.clone().into());
163 builder
164 .build_dictionary(input_path, output_path)
165 .map_err(|e| to_magnus_error(&ruby, format!("Failed to build dictionary: {e}")))?;
166
167 Ok(())
168}
169
170fn build_user_dictionary(
179 _kind: String,
180 input_file: String,
181 output_dir: String,
182 metadata: Option<&RbMetadata>,
183) -> Result<(), Error> {
184 let ruby = Ruby::get().expect("Ruby runtime not initialized");
185 let input_path = Path::new(&input_file);
186 let output_path = Path::new(&output_dir);
187
188 if !input_path.exists() {
189 return Err(Error::new(
190 ruby.exception_arg_error(),
191 format!("Input file does not exist: {input_file}"),
192 ));
193 }
194
195 let meta = match metadata {
196 Some(m) => m.clone().into(),
197 None => Metadata::default(),
198 };
199
200 let builder = DictionaryBuilder::new(meta);
201 builder
202 .build_user_dictionary(input_path, output_path)
203 .map_err(|e| to_magnus_error(&ruby, format!("Failed to build user dictionary: {e}")))?;
204
205 Ok(())
206}
207
208pub fn define(ruby: &Ruby, module: &magnus::RModule) -> Result<(), Error> {
219 let dict_class = module.define_class("Dictionary", ruby.class_object())?;
220 dict_class.define_method("metadata_name", method!(RbDictionary::metadata_name, 0))?;
221 dict_class.define_method(
222 "metadata_encoding",
223 method!(RbDictionary::metadata_encoding, 0),
224 )?;
225 dict_class.define_method("metadata", method!(RbDictionary::metadata, 0))?;
226 dict_class.define_method("to_s", method!(RbDictionary::to_s, 0))?;
227 dict_class.define_method("inspect", method!(RbDictionary::inspect, 0))?;
228
229 let user_dict_class = module.define_class("UserDictionary", ruby.class_object())?;
230 user_dict_class.define_method("to_s", method!(RbUserDictionary::to_s, 0))?;
231 user_dict_class.define_method("inspect", method!(RbUserDictionary::inspect, 0))?;
232
233 module.define_module_function("load_dictionary", function!(load_dictionary, 1))?;
234 module.define_module_function("load_user_dictionary", function!(load_user_dictionary, 2))?;
235 module.define_module_function("build_dictionary", function!(build_dictionary, 3))?;
236 module.define_module_function("build_user_dictionary", function!(build_user_dictionary, 4))?;
237
238 Ok(())
239}