lindera/
dictionary.rs

1use std::path::Path;
2
3use pyo3::{exceptions::PyValueError, prelude::*};
4
5use lindera::dictionary::{
6    Dictionary, DictionaryBuilder, Metadata, UserDictionary,
7    load_dictionary as lindera_load_dictionary,
8    load_user_dictionary as lindera_load_user_dictionary,
9};
10
11use crate::metadata::PyMetadata;
12
13#[pyclass(name = "Dictionary")]
14#[derive(Clone)]
15pub struct PyDictionary {
16    pub inner: Dictionary,
17}
18
19#[pymethods]
20impl PyDictionary {
21    pub fn metadata_name(&self) -> String {
22        self.inner.metadata.name.clone()
23    }
24
25    pub fn metadata_encoding(&self) -> String {
26        self.inner.metadata.encoding.clone()
27    }
28
29    pub fn metadata(&self) -> PyMetadata {
30        PyMetadata::from(self.inner.metadata.clone())
31    }
32
33    fn __str__(&self) -> String {
34        "Dictionary".to_string()
35    }
36
37    fn __repr__(&self) -> String {
38        "Dictionary()".to_string()
39    }
40}
41
42impl PyDictionary {
43    // Internal helper function to create PyDictionary from Lindera Dictionary
44    pub fn new(dictionary: Dictionary) -> Self {
45        Self { inner: dictionary }
46    }
47}
48
49#[pyclass(name = "UserDictionary")]
50#[derive(Clone)]
51pub struct PyUserDictionary {
52    pub inner: UserDictionary,
53}
54
55#[pymethods]
56impl PyUserDictionary {
57    fn __str__(&self) -> String {
58        "UserDictionary".to_string()
59    }
60
61    fn __repr__(&self) -> String {
62        "UserDictionary()".to_string()
63    }
64}
65
66impl PyUserDictionary {
67    // Internal helper function to create PyUserDictionary from Lindera UserDictionary
68    pub fn new(user_dictionary: UserDictionary) -> Self {
69        Self {
70            inner: user_dictionary,
71        }
72    }
73}
74
75#[pyfunction]
76#[pyo3(signature = (input_dir, output_dir, metadata))]
77pub fn build_dictionary(input_dir: &str, output_dir: &str, metadata: PyMetadata) -> PyResult<()> {
78    let input_path = Path::new(input_dir);
79    let output_path = Path::new(output_dir);
80
81    if !input_path.exists() {
82        return Err(PyValueError::new_err(format!(
83            "Input directory does not exist: {input_dir}"
84        )));
85    }
86
87    let builder = DictionaryBuilder::new(metadata.into());
88
89    builder
90        .build_dictionary(input_path, output_path)
91        .map_err(|e| PyValueError::new_err(format!("Failed to build dictionary: {e}")))?;
92
93    Ok(())
94}
95
96#[pyfunction]
97#[pyo3(signature = (_kind, input_file, output_dir, metadata=None))]
98pub fn build_user_dictionary(
99    _kind: &str,
100    input_file: &str,
101    output_dir: &str,
102    metadata: Option<crate::metadata::PyMetadata>,
103) -> PyResult<()> {
104    let input_path = Path::new(input_file);
105    let output_path = Path::new(output_dir);
106
107    if !input_path.exists() {
108        return Err(PyValueError::new_err(format!(
109            "Input file does not exist: {input_file}"
110        )));
111    }
112
113    // Use provided metadata or create default
114    let meta = match metadata {
115        Some(py_metadata) => {
116            let lindera_meta: Metadata = py_metadata.into();
117            lindera_meta
118        }
119        None => Metadata::default(),
120    };
121
122    let builder = DictionaryBuilder::new(meta);
123
124    // Build user dictionary from CSV
125    builder
126        .build_user_dictionary(input_path, output_path)
127        .map_err(|e| PyValueError::new_err(format!("Failed to build user dictionary: {e}")))?;
128
129    Ok(())
130}
131
132#[pyfunction]
133#[pyo3(signature = (uri))]
134pub fn load_dictionary(uri: &str) -> PyResult<PyDictionary> {
135    lindera_load_dictionary(uri)
136        .map_err(|e| PyValueError::new_err(format!("Failed to load dictionary from '{uri}': {e}")))
137        .map(PyDictionary::new)
138}
139
140#[pyfunction]
141#[pyo3(signature = (uri, metadata))]
142pub fn load_user_dictionary(uri: &str, metadata: PyMetadata) -> PyResult<PyUserDictionary> {
143    let meta: Metadata = metadata.into();
144    lindera_load_user_dictionary(uri, &meta)
145        .map_err(|e| {
146            PyValueError::new_err(format!("Failed to load user dictionary from '{uri}': {e}"))
147        })
148        .map(PyUserDictionary::new)
149}