identicode/
lib.rs

1// Copyright 2022 gulje
2
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy
5// of the License at
6
7//   http://www.apache.org/licenses/LICENSE-2.0
8
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations
13// under the License.
14
15pub const CURRENT_VERSION: u32 = 3;
16
17#[derive(PartialEq)]
18enum Modes {
19    Version,
20    Language,
21    Branch,
22    OS,
23    Other,
24}
25
26pub enum Tokens {
27    Language,
28    Branch,
29    OS,
30    Other,
31
32    Push,
33    Push5,
34    Push10,
35    Push50,
36    Push100,
37    Sub,
38
39    Print,
40}
41
42pub struct Identicode {
43    lang_list: Vec<String>,
44    branch_list: Vec<String>,
45    os_list: Vec<String>,
46    other_list: Vec<String>,
47
48    mode: Modes,
49
50    stack: u64,
51
52    pub version: u32,
53    pub languages: Vec<String>,
54    pub branches: Vec<String>,
55    pub oses: Vec<String>,
56    pub others: Vec<String>,
57}
58
59impl Tokens {
60    fn val(ch: char) -> Self {
61        use self::Tokens::*;
62
63        match ch {
64            '$' => Language,
65            '@' => Branch,
66            '?' => OS,
67            '&' => Other,
68
69            '+' => Push,
70            '*' => Push5,
71            '/' => Push10,
72            '%' => Push50,
73            '=' => Push100,
74            '-' => Sub,
75
76            ';' => Print,
77            _ => {
78                println!("\x1b[1;31merror:\x1b[0m unknown character '{}'", ch);
79                std::process::exit(1);
80            }
81        }
82    }
83}
84
85impl Default for Identicode {
86    fn default() -> Self {
87        let langs = String::from_utf8_lossy(include_bytes!("data/langs.txt"))
88            .lines()
89            .map(str::to_string)
90            .collect();
91        let branches = String::from_utf8_lossy(include_bytes!("data/branches.txt"))
92            .lines()
93            .map(str::to_string)
94            .collect();
95        let oses = String::from_utf8_lossy(include_bytes!("data/oses.txt"))
96            .lines()
97            .map(str::to_string)
98            .collect();
99        let others = String::from_utf8_lossy(include_bytes!("data/others.txt"))
100            .lines()
101            .map(str::to_string)
102            .collect();
103
104        Identicode {
105        	version: 0,
106            mode: Modes::Version,
107            stack: 0,
108            languages: vec![],
109            branches: vec![],
110            oses: vec![],
111            others: vec![],
112            lang_list: langs,
113            branch_list: branches,
114            other_list: others,
115            os_list: oses,
116        }
117    }
118}
119
120impl Identicode {
121    pub fn init(&mut self, file_data: String) {
122        use Tokens::*;
123
124        for ch in file_data.chars() {
125            match Tokens::val(ch) {
126                Language => {
127                    self.mode = Modes::Language;
128                }
129                Branch => {
130                    self.mode = Modes::Branch;
131                }
132                OS => {
133                    self.mode = Modes::OS;
134                }
135                Other => {
136                    self.mode = Modes::Other;
137                }
138
139                Push => {
140                    self.stack += 1;
141                }
142                Push5 => {
143                    self.stack += 5;
144                }
145                Push10 => {
146                    self.stack += 10;
147                }
148                Push50 => {
149                    self.stack += 50;
150                }
151                Push100 => {
152                    self.stack += 100;
153                }
154                Sub => {
155                    self.stack -= 1;
156                }
157
158                Print => {
159                    fn push_item(vect: &mut Vec<String>, list: &mut Vec<String>, stack: u64) {
160                        if list[stack as usize] != "" {
161                            vect.push(list[stack as usize].clone());
162                            list[stack as usize] = "".to_string();
163                        }
164                    }
165
166                    if self.mode == Modes::Language && self.stack < self.lang_list.len() as u64 {
167                        push_item(&mut self.languages, &mut self.lang_list, self.stack);
168                    } else if self.mode == Modes::Branch
169                        && self.stack < self.branch_list.len() as u64
170                    {
171                        push_item(&mut self.branches, &mut self.branch_list, self.stack);
172                    } else if self.mode == Modes::OS && self.stack < self.os_list.len() as u64 {
173                        push_item(&mut self.oses, &mut self.os_list, self.stack);
174                    } else if self.mode == Modes::Other && self.stack < self.other_list.len() as u64
175                    {
176                        push_item(&mut self.others, &mut self.other_list, self.stack);
177                    } else if self.mode == Modes::Version {
178                    	self.version = self.stack as u32;
179                    	self.stack = 0;
180                    }
181
182                    self.stack = 0;
183                }
184            }
185        }
186    }
187}