sudachi/plugin/connect_cost/
inhibit_connection.rs

1/*
2 * Copyright (c) 2021-2024 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::prelude::*;
24
25/// A edit connection cost plugin for inhibiting the connections.
26///
27/// Example setting file
28/// ``
29/// {
30///     {
31///         "class": "relative-path/to/so-file/from/resource-path",
32///         "inhibitPair": [[0, 233], [435, 332]]
33///     }
34/// }
35/// ``
36#[derive(Default)]
37pub struct InhibitConnectionPlugin {
38    /// At each pair, the first one is right_id of the left node
39    /// and the second one is left_id of right node in a connection
40    inhibit_pairs: Vec<(i16, i16)>,
41}
42
43/// Struct corresponds with raw config json file.
44#[allow(non_snake_case)]
45#[derive(Deserialize)]
46struct PluginSettings {
47    inhibitPair: Vec<(i16, i16)>,
48}
49
50impl InhibitConnectionPlugin {
51    fn inhibit_connection(grammar: &mut Grammar, left: i16, right: i16) {
52        grammar.set_connect_cost(left, right, Grammar::INHIBITED_CONNECTION);
53    }
54}
55
56impl EditConnectionCostPlugin for InhibitConnectionPlugin {
57    fn set_up(
58        &mut self,
59        settings: &Value,
60        _config: &Config,
61        _grammar: &Grammar,
62    ) -> SudachiResult<()> {
63        let settings: PluginSettings = serde_json::from_value(settings.clone())?;
64        let inhibit_pairs = settings.inhibitPair;
65        self.inhibit_pairs = inhibit_pairs;
66        Ok(())
67    }
68
69    fn edit(&self, grammar: &mut Grammar) {
70        for (left, right) in &self.inhibit_pairs {
71            InhibitConnectionPlugin::inhibit_connection(grammar, *left, *right);
72        }
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79
80    #[test]
81    fn edit() {
82        let left = 0;
83        let right = 0;
84        let bytes = build_mock_bytes();
85        let mut grammar = build_mock_grammar(&bytes);
86        let plugin = InhibitConnectionPlugin {
87            inhibit_pairs: vec![(left, right)],
88        };
89
90        plugin.edit(&mut grammar);
91        assert_eq!(
92            Grammar::INHIBITED_CONNECTION,
93            grammar.connect_cost(left, right)
94        );
95    }
96
97    fn build_mock_bytes() -> Vec<u8> {
98        let mut buf = Vec::new();
99        // 0 - pos size, 1x1 connection with 0 element
100        buf.extend(&0_i16.to_le_bytes());
101        buf.extend(&1_i16.to_le_bytes());
102        buf.extend(&1_i16.to_le_bytes());
103        buf.extend(&0_i16.to_le_bytes());
104        buf
105    }
106
107    fn build_mock_grammar(bytes: &[u8]) -> Grammar {
108        Grammar::parse(bytes, 0).expect("Failed to create grammar")
109    }
110}