Skip to main content

lsp_max/closure_channel/
decoder.rs

1use super::diagnostics::LSPMAX_PROSE_CLOSURE_TOKEN_REFUSED;
2use super::grammar::PROSE_CLOSURE_TOKENS;
3use super::packet::ClosurePacket;
4
5pub struct DecoderResult {
6    pub q: u8,
7    pub diagnostics: Vec<String>,
8}
9
10pub fn decode(text: &str, packet: &ClosurePacket) -> DecoderResult {
11    let mut diagnostics = Vec::new();
12
13    // Extract text outside of string boundaries
14    let mut in_string = false;
15    let mut escaped = false;
16    let mut outside_text = String::new();
17
18    for c in text.chars() {
19        if escaped {
20            escaped = false;
21            if !in_string {
22                outside_text.push(c);
23            }
24            continue;
25        }
26        if c == '\\' {
27            escaped = true;
28            if !in_string {
29                outside_text.push(c);
30            }
31            continue;
32        }
33        if c == '"' {
34            in_string = !in_string;
35            outside_text.push(' ');
36            continue;
37        }
38        if !in_string {
39            outside_text.push(c);
40        }
41    }
42
43    let lower_outside = outside_text.to_lowercase();
44    let mut refused = false;
45    for token in PROSE_CLOSURE_TOKENS {
46        if lower_outside.contains(&token.to_lowercase()) {
47            refused = true;
48            break;
49        }
50    }
51
52    if refused {
53        diagnostics.push(LSPMAX_PROSE_CLOSURE_TOKEN_REFUSED.to_string());
54        return DecoderResult { q: 0, diagnostics };
55    }
56
57    let valid_q = packet.f_t == 0 && packet.w_t == 1 && packet.c_t == 1 && !packet.r_b.is_empty();
58
59    DecoderResult {
60        q: if valid_q { 1 } else { 0 },
61        diagnostics,
62    }
63}