1use std::collections::BTreeMap;
9
10use ahk::runtime::{Property, Report, Step, Value};
11use ahk::warnings::Warning;
12
13use crate::json::Object;
14
15pub fn the_report(report: &Report, notes: &[String]) -> String {
17 let mut object = Object::new(1024);
18 object.boolean("ok", report.ok);
19 object.field("steps", |out| the_steps(out, &report.steps));
20 object.texts("output", &report.output);
21 object.field("warnings", |out| the_warnings(out, &report.warnings));
22 object.texts("notes", notes);
23 match &report.error {
24 Some(error) => object.text("error", error),
25 None => object.nothing("error"),
26 };
27 object.optional_number("error_line", report.error_line.map(i64::from));
28 object.optional_number("exit_code", report.exit_code.map(i64::from));
29 object.number("elapsed_ms", report.elapsed_ms as i64);
30 object.field("variables", |out| the_variables(out, &report.variables));
31 object.finish()
32}
33
34pub fn the_failure_of_the_load(error: &str, line: u32, column: u32) -> String {
39 let mut object = Object::new(256);
40 object.boolean("ok", false);
41 object.text("error", error);
42 object.number("error_line", i64::from(line));
43 object.number("column", i64::from(column));
44 object.field("steps", |out| out.push_str("[]"));
47 object.field("output", |out| out.push_str("[]"));
48 object.field("notes", |out| out.push_str("[]"));
49 object.finish()
50}
51
52fn the_steps(out: &mut String, steps: &[Step]) {
54 out.push('[');
55 for (index, step) in steps.iter().enumerate() {
56 if index > 0 {
57 out.push(',');
58 }
59 let mut object = Object::new(128);
60 object.number("line", i64::from(step.line));
61 object.text("op", &step.op);
62 object.text("detail", &step.detail);
63 object.boolean("ok", step.ok);
64 object.number("elapsed_ms", step.elapsed_ms as i64);
65 out.push_str(&object.finish());
66 }
67 out.push(']');
68}
69
70fn the_warnings(out: &mut String, warnings: &[Warning]) {
72 out.push('[');
73 for (index, warning) in warnings.iter().enumerate() {
74 if index > 0 {
75 out.push(',');
76 }
77 let mut object = Object::new(128);
78 object.number("line", i64::from(warning.line));
79 object.text("message", &warning.message);
80 out.push_str(&object.finish());
81 }
82 out.push(']');
83}
84
85fn the_variables(out: &mut String, variables: &BTreeMap<String, Value>) {
87 out.push('{');
88 for (index, (name, value)) in variables.iter().enumerate() {
89 if index > 0 {
90 out.push(',');
91 }
92 crate::json::write_text(out, name);
93 out.push(':');
94 the_value(out, value);
95 }
96 out.push('}');
97}
98
99fn the_value(out: &mut String, value: &Value) {
101 match value {
102 Value::Int(number) => out.push_str(&number.to_string()),
103 Value::Float(number) => {
104 if number.is_finite() {
105 out.push_str(&number.to_string());
106 } else {
107 out.push_str("null");
109 }
110 }
111 Value::Text(text) => crate::json::write_text(out, text),
112 Value::Unset | Value::Skipped => crate::json::write_text(out, ""),
117 Value::List(values) => {
118 out.push('[');
119 for (index, value) in values.iter().enumerate() {
120 if index > 0 {
121 out.push(',');
122 }
123 the_value(out, value);
124 }
125 out.push(']');
126 }
127 Value::Object(object) => {
128 let object = object.borrow();
129 let mut written = Object::new(256);
130 written.text("class", &object.class);
131 written.field("properties", |out| {
132 the_properties(out, &object.properties)
133 });
134 out.push_str(&written.finish());
135 }
136 Value::Reference(reference) => {
137 let mut written = Object::new(128);
138 written.text("name", &reference.name);
139 written.text("scope", &format!("{:?}", reference.scope));
140 written.boolean("alias", reference.alias);
141 out.push_str(&written.finish());
142 }
143 }
144}
145
146fn the_properties(out: &mut String, properties: &BTreeMap<String, Property>) {
148 out.push('{');
149 for (index, (name, property)) in properties.iter().enumerate() {
150 if index > 0 {
151 out.push(',');
152 }
153 crate::json::write_text(out, name);
154 out.push(':');
155 let mut written = Object::new(128);
156 written.text("name", &property.name);
157 written.field("value", |out| the_value(out, &property.value));
158 out.push_str(&written.finish());
159 }
160 out.push('}');
161}