1use std::collections::HashMap;
2use std::fs;
3
4#[derive(Debug, Clone)]
6pub enum PklValue {
7 String(String),
8 Integer(i64),
9 Float(f64),
10 Boolean(bool),
11 Object(HashMap<String, PklValue>),
12 Array(Vec<PklValue>),
13}
14
15pub fn parse_pkl(filename: &str) -> Result<PklValue, String> {
18 let content = fs::read_to_string(filename)
19 .map_err(|err| format!("Error reading file: {}", err))?;
20 let mut lines = content.lines();
21
22 let root_object = parse_object(&mut lines)?;
23
24 Ok(root_object)
25}
26
27pub fn parse_object<'a, I>(lines: &mut I) -> Result<PklValue, String>
29where
30 I: Iterator<Item = &'a str>,
31{
32 let mut object = HashMap::new();
33
34 while let Some(line) = lines.next() {
35 let line = line.trim();
36
37 if line.is_empty() || line.starts_with("#") {
39 continue;
40 }
41
42 if line.ends_with('{') {
44 let key = line.trim_end_matches('{').trim();
45 let nested_object = parse_object(lines)?;
46 object.insert(key.to_string(), nested_object);
47 } else if line.ends_with('}') {
48 break;
50 } else {
51 let parts: Vec<&str> = line.splitn(2, '=').collect();
53 if parts.len() != 2 {
54 return Err("Invalid syntax".to_string());
55 }
56
57 let key = parts[0].trim();
58 let value = parts[1].trim();
59 let parsed_value = parse_value(value)?;
60
61 object.insert(key.to_string(), parsed_value);
62 }
63 }
64
65 Ok(PklValue::Object(object))
66}
67
68
69
70pub fn parse_value(value: &str) -> Result<PklValue, String> {
72 if value.starts_with('"') && value.ends_with('"') {
73 Ok(PklValue::String(value[1..value.len() - 1].to_string()))
74 } else if let Ok(integer) = value.parse::<i64>() {
75 Ok(PklValue::Integer(integer))
76 } else if let Ok(float) = value.parse::<f64>() {
77 Ok(PklValue::Float(float))
78 } else if value == "true" {
79 Ok(PklValue::Boolean(true))
80 } else if value == "false" {
81 Ok(PklValue::Boolean(false))
82 } else if value.starts_with('{') && value.ends_with('}') {
83 let inner_object_content = &value[1..value.len() - 1];
85 let inner_object = parse_pkl_inner_object(inner_object_content)?;
86 Ok(inner_object)
87 } else {
88 Err("Unsupported value type".to_string())
89 }
90}
91
92pub fn parse_pkl_inner_object(content: &str) -> Result<PklValue, String> {
94 let mut lines = content.lines();
95 let mut object = HashMap::new();
96
97 while let Some(line) = lines.next() {
98 let line = line.trim();
99
100 if line.is_empty() || line.starts_with("#") {
102 continue;
103 }
104
105 let parts: Vec<&str> = line.splitn(2, '=').collect();
106 if parts.len() != 2 {
107 return Err("Invalid syntax".to_string());
108 }
109
110 let key = parts[0].trim();
111 let value = parts[1].trim();
112 let parsed_value = parse_value(value)?;
113
114 object.insert(key.to_string(), parsed_value);
115 }
116
117 Ok(PklValue::Object(object))
118}
119
120pub fn print_parameter(pkl_value: &PklValue, parameter: &str) {
122 match pkl_value {
123 PklValue::Object(object) => {
124 if let Some(value) = object.get(parameter) {
126 println!("{}: {:?}", parameter, value);
127 } else {
128 for (_, nested_value) in object {
130 print_parameter(nested_value, parameter);
131 }
132 }
133 }
134 _ => {
135 println!("Parameter '{}' not found.", parameter);
136 }
137 }
138}
139
140pub fn find_parameter(pkl_value: &PklValue, parameter: &str) -> Option<PklValue> {
142 match pkl_value {
143 PklValue::Object(object) => {
144 if let Some(value) = object.get(parameter) {
146 Some(value.clone())
147 } else {
148 for (_, nested_value) in object {
150 if let Some(found_value) = find_parameter(nested_value, parameter) {
151 return Some(found_value);
152 }
153 }
154 None
155 }
156 }
157 _ => None,
158 }
159}