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}