Skip to main content

sudachi/plugin/connect_cost/
inhibit_connection.rs

1/*
2 * Copyright (c) 2021-2026 Works Applications Co., Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use serde::Deserialize;
18use serde_json::Value;
19
20use crate::config::Config;
21use crate::dic::grammar::Grammar;
22use crate::plugin::connect_cost::EditConnectionCostPlugin;
23use crate::plugin::PluginError;
24use crate::prelude::*;
25
26/// A edit connection cost plugin for inhibiting the connections.
27///
28/// Example setting file
29/// ``
30/// {
31///     {
32///         "class": "relative-path/to/so-file/from/resource-path",
33///         "inhibitPair": [[0, 233], [435, 332]]
34///     }
35/// }
36/// ``
37#[derive(Default)]
38pub struct InhibitConnectionPlugin {
39    /// At each pair, the first one is right_id of the left node
40    /// and the second one is left_id of right node in a connection
41    inhibit_pairs: Vec<(i16, i16)>,
42}
43
44/// Struct corresponds with raw config json file.
45#[allow(non_snake_case)]
46#[derive(Deserialize)]
47struct PluginSettings {
48    inhibitPair: Vec<(i16, i16)>,
49}
50
51impl InhibitConnectionPlugin {
52    fn inhibit_connection(grammar: &mut Grammar, left: i16, right: i16) {
53        grammar.set_connect_cost(left, right, Grammar::INHIBITED_CONNECTION);
54    }
55}
56
57impl EditConnectionCostPlugin for InhibitConnectionPlugin {
58    fn set_up(
59        &mut self,
60        settings: &Value,
61        _config: &Config,
62        _grammar: &Grammar,
63    ) -> SudachiResult<()> {
64        let settings: PluginSettings =
65            serde_json::from_value(settings.clone()).map_err(PluginError::from)?;
66        let inhibit_pairs = settings.inhibitPair;
67        self.inhibit_pairs = inhibit_pairs;
68        Ok(())
69    }
70
71    fn edit(&self, grammar: &mut Grammar) {
72        for (left, right) in &self.inhibit_pairs {
73            InhibitConnectionPlugin::inhibit_connection(grammar, *left, *right);
74        }
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81    use crate::dic::connect::ConnectionMatrix;
82    use crate::dic::pos::PosList;
83
84    #[test]
85    fn edit() {
86        let left = 0;
87        let right = 0;
88        let bytes = build_mock_connection_bytes();
89        let mut grammar = build_mock_grammar(&bytes);
90        let plugin = InhibitConnectionPlugin {
91            inhibit_pairs: vec![(left, right)],
92        };
93
94        plugin.edit(&mut grammar);
95        assert_eq!(
96            Grammar::INHIBITED_CONNECTION,
97            grammar.connect_cost(left, right)
98        );
99    }
100
101    fn build_mock_connection_bytes() -> Vec<u8> {
102        let mut buf = Vec::new();
103        // 1x1 connection with 0 element
104        buf.extend(&1_i16.to_le_bytes());
105        buf.extend(&1_i16.to_le_bytes());
106        buf.extend(&0_i16.to_le_bytes());
107        buf
108    }
109
110    fn build_mock_grammar(connection_bytes: &[u8]) -> Grammar<'_> {
111        let pos_list = PosList::default();
112        let connection = ConnectionMatrix::from_bytes(connection_bytes)
113            .expect("Failed to parse connection matrix");
114        Grammar::from_parts(pos_list, connection)
115    }
116}