aimx/inference/
response.rs1use crate::{
9 aim::Typedef,
10 inference::{Item, Suffix, parse_inline_item, parse_item, parse_key},
11 literals::{Literal, parse_date, parse_number},
12 values::Value,
13};
14use anyhow::{Result, anyhow};
15use std::{collections::HashMap, sync::Arc};
16
17#[derive(Debug, PartialEq, Clone)]
21pub enum Response {
22 Single(Item),
24 Multiline(Vec<Item>),
26}
27
28pub fn parse_response(input: &str) -> Option<HashMap<Arc<str>, Response>> {
32 let mut response_map: HashMap<Arc<str>, Response> = HashMap::new();
33 let mut current_list: Vec<Item> = Vec::new();
34 let mut current_key: Option<Arc<str>> = None;
35 let mut first_item: Option<Item> = None;
36
37 for line in input.lines() {
39 if let Ok((input, (key, suffix))) = parse_key(line) {
41 if let (Some(key), Some(item)) = (current_key, first_item) {
43 response_map.insert(key, Response::new(&item, ¤t_list));
44 }
45 match suffix {
46 Suffix::Colon => {
47 if let Ok((_, item)) = parse_inline_item(input) {
49 response_map.insert(key, Response::Single(item));
50 }
51 current_key = None;
52 }
53 Suffix::Eol | Suffix::ColonEol => {
54 current_key = Some(key);
56 }
57 }
58 first_item = None;
59 current_list.clear();
60
61 } else if let Some(key) = ¤t_key {
63 if let Some(item) = &first_item {
65 if let Ok((_, result)) = parse_item(line) {
66 let prefixes_match = match (&item, &result) {
68 (Item::Value(prefix1, _), Item::Value(prefix2, _)) => prefix1 == prefix2,
69 (Item::Task(prefix1, _, _), Item::Task(prefix2, _, _)) => {
70 prefix1 == prefix2
71 }
72 _ => false, };
74 if prefixes_match {
75 current_list.push(result);
76 } else {
77 response_map.insert(key.clone(), Response::new(item, ¤t_list));
78 current_key = None;
79 first_item = None;
80 current_list.clear();
81 }
82 } else {
83 response_map.insert(key.clone(), Response::new(item, ¤t_list));
84 current_key = None;
85 first_item = None;
86 current_list.clear();
87 }
88 }
89 else if let Ok((_, result)) = parse_item(line) {
91 current_list.push(result.clone());
92 first_item = Some(result);
93 }
94 else {
96 current_key = None;
97 }
98 }
99 }
100 if let (Some(key), Some(item)) = (current_key, first_item) {
102 response_map.insert(key, Response::new(&item, ¤t_list));
103 }
104
105 if response_map.is_empty() {
107 None
108 } else {
109 Some(response_map)
110 }
111}
112
113fn from_single(input: &str, typedef: &Typedef) -> Result<Literal> {
118 if input.trim().is_empty() {
119 return Err(anyhow!("Nothing to assign"));
120 }
121 if typedef.is_number() {
122 match parse_number(input) {
123 Ok((_, number)) => return Ok(Literal::from_number(number)),
124 Err(e) => return Err(anyhow!("Parse error: {}", e)),
125 }
126 }
127 if typedef.is_date() {
128 match parse_date(input) {
129 Ok((_, date)) => return Ok(Literal::from_date(date)),
130 Err(e) => return Err(anyhow!("Parse error: {}", e)),
131 }
132 }
133 if typedef.is_text() {
134 return Ok(Literal::from_text(Arc::from(input)));
135 }
136 Err(anyhow!("Type definition mismatch"))
137}
138
139fn from_task(input: &str, typedef: &Typedef, status: &Option<bool>) -> Result<Literal> {
144 if input.trim().is_empty() {
145 return Err(anyhow!("Nothing to assign"));
146 }
147 if typedef.is_task() {
148 return Ok(Literal::from_task(*status, Arc::from(input)));
149 }
150 from_single(input, typedef)
152}
153
154fn from_multiline(multiline: &[Item], typedef: &Typedef) -> Result<Arc<Value>> {
159 if multiline.is_empty() {
160 return Err(anyhow!("Nothing to assign"));
161 }
162 let mut array: Vec<Arc<Value>> = Vec::new();
163 for item in multiline.iter() {
165 let result = match item {
167 Item::Value(_, input) => from_single(input, typedef),
168 Item::Task(_, status, input) => from_task(input, typedef, status),
169 };
170 if let Ok(literal) = result {
172 if typedef.is_array() {
174 array.push(Arc::new(Value::Literal(literal)));
175 } else {
177 return Ok(Arc::new(Value::Literal(literal)));
178 }
179 }
180 }
181 if !array.is_empty() {
182 return Ok(Arc::new(Value::Array(Arc::new(array))));
183 }
184 Err(anyhow!("Type definition mismatch"))
185}
186
187impl Response {
188 pub fn new(item: &Item, list: &[Item]) -> Self {
192 if list.len() > 1 {
193 Response::Multiline(list.to_vec())
194 } else {
195 Response::Single(item.clone())
196 }
197 }
198
199 pub fn to_value(&self, typedef: &Typedef) -> Result<Arc<Value>> {
203 match self {
204 Response::Single(item) => {
205 let literal = match item {
206 Item::Value(_, input) => from_single(input, typedef)?,
207 Item::Task(_, status, input) => from_task(input, typedef, status)?,
208 };
209 if typedef.is_array() {
211 let array: Vec<Arc<Value>> = vec![Arc::new(Value::Literal(literal))];
212 return Ok(Arc::new(Value::Array(Arc::new(array))));
213 }
214 Ok(Arc::new(Value::Literal(literal)))
215 }
216 Response::Multiline(multiline) => from_multiline(multiline, typedef),
217 }
218 }
219}