1use std::{cell::RefCell, error::Error};
2
3mod parser;
4
5#[derive(Debug)]
6pub struct Config<'a> {
7 contents: RefCell<Vec<&'a str>>,
8}
9
10impl<'a> Config<'a> {
11 pub fn load(contents: Vec<&'a str>) -> Config {
12 Config {
13 contents: RefCell::new(contents),
14 }
15 }
16
17 pub fn get_config(&self) -> String {
18 self.contents
19 .borrow()
20 .iter()
21 .map(|c| c.to_string())
22 .collect::<Vec<String>>()
23 .join("\n")
24 }
25
26 pub fn list_contexts(&self) -> Result<String, Box<dyn Error>> {
27 Ok(self
28 .get_contexts()?
29 .iter()
30 .map(|c| c.to_string())
31 .collect::<Vec<String>>()
32 .join("\n"))
33 }
34
35 pub fn check_context(&self, context: &str) -> Result<bool, &'static str> {
36 let contexts = self.get_contexts()?;
37
38 Ok(contexts.iter().any(|c| *c == context))
39 }
40
41 pub fn get_current_context(&self) -> Result<&str, &'static str> {
42 let contents = self.contents.borrow();
43 let iter = contents.iter();
44
45 for line in iter {
46 if let Some(current_context) = parser::match_literal(line, "current-context: ") {
47 return Ok(current_context);
48 }
49 }
50
51 Err("current-context is not set")
52 }
53
54 pub fn set_current_context(&'a self, new_context: &'a str) -> Result<(), &'static str> {
55 let mut contents = self.contents.borrow_mut();
56 let iter = contents.iter();
57
58 for (index, line) in iter.enumerate() {
59 if parser::match_literal(line, "current-context:").is_some() {
60 contents.push(new_context);
61 contents.swap_remove(index);
62 return Ok(());
63 }
64 }
65
66 contents.push(new_context);
67
68 Ok(())
69 }
70
71 pub fn unset_current_context(&'a self) -> Result<(), &'static str> {
72 let mut contents = self.contents.borrow_mut();
73 let iter = contents.iter();
74
75 for (index, line) in iter.enumerate() {
76 if parser::match_literal(line, "current-context:").is_some() {
77 contents.remove(index);
78 return Ok(());
79 }
80 }
81
82 Ok(())
83 }
84
85 fn get_contexts(&self) -> Result<Vec<&str>, &'static str> {
86 let mut contexts = Vec::<&str>::new();
87 let contents = self.contents.borrow();
88 let mut input = contents.iter().peekable();
89
90 while let Some(line) = input.next() {
91 if parser::match_literal(line, "contexts:").is_some() {
92 while parser::is_in_mapping(input.peek().ok_or("Reached the end of contexts.")?)
93 .is_ok()
94 {
95 if let Some(line) = input.next() {
96 if let Some(name) = parser::match_literal(line, " name: ") {
97 contexts.push(name);
98 }
99 }
100 }
101
102 break;
103 }
104 }
105
106 if contexts.is_empty() {
107 return Err("Cannot get contexts!");
108 }
109
110 Ok(contexts)
111 }
112}