lindera/
mode.rs

1use pyo3::prelude::*;
2
3use lindera::mode::{Mode as LinderaMode, Penalty as LinderaPenalty};
4
5#[pyclass(name = "Mode")]
6#[derive(Debug, Clone, Copy)]
7pub enum PyMode {
8    Normal,
9    Decompose,
10}
11
12#[pymethods]
13impl PyMode {
14    #[new]
15    #[pyo3(signature = (mode_str=None))]
16    pub fn new(mode_str: Option<&str>) -> PyResult<Self> {
17        match mode_str {
18            Some("decompose") | Some("Decompose") => Ok(PyMode::Decompose),
19            Some("normal") | Some("Normal") | None => Ok(PyMode::Normal),
20            Some(s) => Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(format!(
21                "Invalid mode: {s}. Must be 'normal' or 'decompose'"
22            ))),
23        }
24    }
25
26    fn __str__(&self) -> &str {
27        match self {
28            PyMode::Normal => "normal",
29            PyMode::Decompose => "decompose",
30        }
31    }
32
33    fn __repr__(&self) -> String {
34        format!("Mode.{self:?}")
35    }
36
37    #[getter]
38    pub fn name(&self) -> &str {
39        self.__str__()
40    }
41
42    pub fn is_normal(&self) -> bool {
43        matches!(self, PyMode::Normal)
44    }
45
46    pub fn is_decompose(&self) -> bool {
47        matches!(self, PyMode::Decompose)
48    }
49}
50
51impl From<PyMode> for LinderaMode {
52    fn from(mode: PyMode) -> Self {
53        match mode {
54            PyMode::Normal => LinderaMode::Normal,
55            PyMode::Decompose => LinderaMode::Decompose(LinderaPenalty::default()),
56        }
57    }
58}
59
60impl From<LinderaMode> for PyMode {
61    fn from(mode: LinderaMode) -> Self {
62        match mode {
63            LinderaMode::Normal => PyMode::Normal,
64            LinderaMode::Decompose(_) => PyMode::Decompose,
65        }
66    }
67}
68
69#[pyclass(name = "Penalty")]
70#[derive(Debug, Clone, Copy)]
71pub struct PyPenalty {
72    kanji_penalty_length_threshold: usize,
73    kanji_penalty_length_penalty: i32,
74    other_penalty_length_threshold: usize,
75    other_penalty_length_penalty: i32,
76}
77
78#[pymethods]
79impl PyPenalty {
80    #[new]
81    #[pyo3(signature = (kanji_penalty_length_threshold=None, kanji_penalty_length_penalty=None, other_penalty_length_threshold=None, other_penalty_length_penalty=None))]
82    pub fn new(
83        kanji_penalty_length_threshold: Option<usize>,
84        kanji_penalty_length_penalty: Option<i32>,
85        other_penalty_length_threshold: Option<usize>,
86        other_penalty_length_penalty: Option<i32>,
87    ) -> Self {
88        PyPenalty {
89            kanji_penalty_length_threshold: kanji_penalty_length_threshold.unwrap_or(2),
90            kanji_penalty_length_penalty: kanji_penalty_length_penalty.unwrap_or(3000),
91            other_penalty_length_threshold: other_penalty_length_threshold.unwrap_or(7),
92            other_penalty_length_penalty: other_penalty_length_penalty.unwrap_or(1700),
93        }
94    }
95
96    #[getter]
97    pub fn get_kanji_penalty_length_threshold(&self) -> usize {
98        self.kanji_penalty_length_threshold
99    }
100
101    #[setter]
102    pub fn set_kanji_penalty_length_threshold(&mut self, value: usize) {
103        self.kanji_penalty_length_threshold = value;
104    }
105
106    #[getter]
107    pub fn get_kanji_penalty_length_penalty(&self) -> i32 {
108        self.kanji_penalty_length_penalty
109    }
110
111    #[setter]
112    pub fn set_kanji_penalty_length_penalty(&mut self, value: i32) {
113        self.kanji_penalty_length_penalty = value;
114    }
115
116    #[getter]
117    pub fn get_other_penalty_length_threshold(&self) -> usize {
118        self.other_penalty_length_threshold
119    }
120
121    #[setter]
122    pub fn set_other_penalty_length_threshold(&mut self, value: usize) {
123        self.other_penalty_length_threshold = value;
124    }
125
126    #[getter]
127    pub fn get_other_penalty_length_penalty(&self) -> i32 {
128        self.other_penalty_length_penalty
129    }
130
131    #[setter]
132    pub fn set_other_penalty_length_penalty(&mut self, value: i32) {
133        self.other_penalty_length_penalty = value;
134    }
135
136    fn __str__(&self) -> String {
137        format!(
138            "Penalty(kanji_threshold={}, kanji_penalty={}, other_threshold={}, other_penalty={})",
139            self.kanji_penalty_length_threshold,
140            self.kanji_penalty_length_penalty,
141            self.other_penalty_length_threshold,
142            self.other_penalty_length_penalty
143        )
144    }
145
146    fn __repr__(&self) -> String {
147        self.__str__()
148    }
149}
150
151impl From<PyPenalty> for LinderaPenalty {
152    fn from(penalty: PyPenalty) -> Self {
153        LinderaPenalty {
154            kanji_penalty_length_threshold: penalty.kanji_penalty_length_threshold,
155            kanji_penalty_length_penalty: penalty.kanji_penalty_length_penalty,
156            other_penalty_length_threshold: penalty.other_penalty_length_threshold,
157            other_penalty_length_penalty: penalty.other_penalty_length_penalty,
158        }
159    }
160}
161
162impl From<LinderaPenalty> for PyPenalty {
163    fn from(penalty: LinderaPenalty) -> Self {
164        PyPenalty {
165            kanji_penalty_length_threshold: penalty.kanji_penalty_length_threshold,
166            kanji_penalty_length_penalty: penalty.kanji_penalty_length_penalty,
167            other_penalty_length_threshold: penalty.other_penalty_length_threshold,
168            other_penalty_length_penalty: penalty.other_penalty_length_penalty,
169        }
170    }
171}