Skip to content

Commit bdfee14

Browse files
committed
add support for json to lisp and vice versa in the web endpoint
1 parent fc34228 commit bdfee14

File tree

4 files changed

+174
-68
lines changed

4 files changed

+174
-68
lines changed

src/evaluator.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ pub fn obj2str(sc: *mut s7_scheme, obj: *mut s7_cell) -> String {
8989
}
9090
}
9191

92-
pub fn scheme2json(expression: &str) -> Result<Value, String> {
92+
pub fn lisp2json(expression: &str) -> Result<Value, String> {
9393
// <TYPE>: <JSON>
9494
// ------------------------------------------------------
9595
// symbol: "string"
@@ -122,7 +122,7 @@ pub fn scheme2json(expression: &str) -> Result<Value, String> {
122122
}
123123
}
124124

125-
pub fn json2scheme(expression: Value) -> Result<String, String> {
125+
pub fn json2lisp(expression: &Value) -> Result<String, String> {
126126
unsafe {
127127
let sc: *mut s7_scheme = s7_init();
128128
match json_to_s7_obj(sc, &expression) {

src/lib.rs

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
22

33
pub use crate::config::Config;
4-
use crate::evaluator::{Evaluator, Primitive, Type, json2scheme, obj2str, scheme2json};
4+
use crate::evaluator::{Evaluator, Primitive, Type, json2lisp, obj2str, lisp2json};
55
use crate::extensions::crypto::{
66
primitive_s7_crypto_generate, primitive_s7_crypto_sign, primitive_s7_crypto_verify,
77
};
@@ -139,20 +139,83 @@ impl Journal {
139139
}
140140

141141
pub fn evaluate_json(&self, query: Value) -> Value {
142-
match json2scheme(query) {
142+
match json2lisp(&query) {
143143
Ok(scheme_query) => {
144144
let result = self.evaluate_record(NULL, scheme_query.as_str());
145-
match scheme2json(result.as_str()) {
145+
match lisp2json(result.as_str()) {
146146
Ok(json_result) => json_result,
147-
Err(_) => scheme2json("(error parse-error \"Failed to parse Scheme to JSON\")")
147+
Err(_) => {
148+
log::warn!(
149+
"Failed to parse Scheme to JSON. Result: {}",
150+
result
151+
);
152+
lisp2json("(error parse-error \"Failed to parse Scheme to JSON\")")
153+
}
148154
.expect("Error parsing the JSON error message"),
149155
}
150156
}
151-
Err(_) => scheme2json("(error parse-error \"Failed to parse JSON to Scheme\")")
157+
Err(_) => {
158+
let query_str = serde_json::to_string(&query)
159+
.unwrap_or_else(|_| "<unprintable json>".to_string());
160+
log::warn!(
161+
"Failed to parse JSON to Scheme. Query: {}",
162+
query_str
163+
);
164+
lisp2json("(error parse-error \"Failed to parse JSON to Scheme\")")
165+
}
152166
.expect("Error parsing the JSON error message"),
153167
}
154168
}
155169

170+
/// Convert a Lisp expression into its JSON representation without evaluation.
171+
///
172+
/// # Examples
173+
/// ```
174+
/// use journal_sdk::JOURNAL;
175+
/// use serde_json::json;
176+
///
177+
/// let output = JOURNAL.lisp_to_json("(+ 1 2)");
178+
/// assert_eq!(output, json!(["+", 1, 2]));
179+
/// ```
180+
pub fn lisp_to_json(&self, query: &str) -> Value {
181+
match lisp2json(query) {
182+
Ok(json_result) => json_result,
183+
Err(_) => {
184+
log::warn!(
185+
"Failed to parse Scheme to JSON. Query: {}",
186+
query
187+
);
188+
lisp2json("(error parse-error \"Failed to parse Scheme to JSON\")")
189+
}
190+
.expect("Error parsing the JSON error message"),
191+
}
192+
}
193+
194+
/// Convert a JSON expression into its Lisp representation without evaluation.
195+
///
196+
/// # Examples
197+
/// ```
198+
/// use journal_sdk::JOURNAL;
199+
/// use serde_json::json;
200+
///
201+
/// let output = JOURNAL.json_to_lisp(json!(["+", 1, 2]));
202+
/// assert_eq!(output, "(+ 1 2)");
203+
/// ```
204+
pub fn json_to_lisp(&self, query: Value) -> String {
205+
match json2lisp(&query) {
206+
Ok(scheme_result) => scheme_result,
207+
Err(_) => {
208+
let query_str = serde_json::to_string(&query)
209+
.unwrap_or_else(|_| "<unprintable json>".to_string());
210+
log::warn!(
211+
"Failed to parse JSON to Scheme. Query: {}",
212+
query_str
213+
);
214+
"(error parse-error \"Failed to parse JSON to Scheme\")".to_string()
215+
}
216+
}
217+
}
218+
156219
fn evaluate_record(&self, record: Word, query: &str) -> String {
157220
let mut runs = 0;
158221
let cache = Arc::new(Mutex::new(HashMap::new()));

src/main.rs

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use journal_sdk::{Config, JOURNAL};
22
use log::info;
33
use rocket::config::Config as RocketConfig;
44
use rocket::data::{Limits, ToByteUnit};
5-
use rocket::response::content::RawHtml;
5+
use rocket::response::content::{RawHtml, RawText};
66
use rocket::serde::json::Json;
77
use rocket::{get, post, routes};
88
use serde_json::Value;
@@ -20,6 +20,8 @@ const INDEX_HTML: &str = r#"<!DOCTYPE html>
2020
<ul>
2121
<li><a href="/interface">LISP Interface</a></li>
2222
<li><a href="/interface/json">JSON Interface</a></li>
23+
<li><a href="/interface/lisp-to-json">LISP to JSON</a></li>
24+
<li><a href="/interface/json-to-lisp">JSON to LISP</a></li>
2325
</ul>
2426
</body>
2527
</html>
@@ -28,7 +30,7 @@ const INDEX_HTML: &str = r#"<!DOCTYPE html>
2830
const INTERFACE_HTML: &str = r#"<!DOCTYPE html>
2931
<html>
3032
<head>
31-
<h2>{}</h2>
33+
<h2>__TITLE__</h2>
3234
</head>
3335
<body style="padding: 0 20px; font-family: 'Consolas'">
3436
<textarea id="query" rows="8" cols="128" spellcheck="false"></textarea>
@@ -43,9 +45,7 @@ const INTERFACE_HTML: &str = r#"<!DOCTYPE html>
4345
let query = document.getElementById('query').value;
4446
fetch('', {
4547
method: 'POST',
46-
headers: {
47-
'Content-Type': 'application/json',
48-
},
48+
__HEADERS__
4949
body: query,
5050
}).then(response => {
5151
return response.text();
@@ -76,17 +76,43 @@ async fn index() -> RawHtml<String> {
7676

7777
#[get("/interface", format = "text/html")]
7878
async fn inform_lisp() -> RawHtml<String> {
79-
RawHtml(INTERFACE_HTML.replace("{}", "LISP Interface"))
79+
RawHtml(
80+
INTERFACE_HTML
81+
.replace("__TITLE__", "LISP Interface")
82+
.replace("__HEADERS__", ""),
83+
)
8084
}
8185

8286
#[post("/interface", data = "<query>", rank = 1)]
8387
async fn evaluate_lisp(query: &str) -> String {
8488
JOURNAL.evaluate(query)
8589
}
8690

91+
#[get("/interface/lisp-to-json", format = "text/html")]
92+
async fn inform_lisp_to_json() -> RawHtml<String> {
93+
RawHtml(
94+
INTERFACE_HTML
95+
.replace("__TITLE__", "LISP to JSON")
96+
.replace("__HEADERS__", ""),
97+
)
98+
}
99+
100+
#[post("/interface/lisp-to-json", data = "<query>", rank = 1)]
101+
async fn lisp_to_json(query: &str) -> Json<Value> {
102+
let result = JOURNAL.lisp_to_json(query);
103+
Json(result)
104+
}
105+
87106
#[get("/interface/json", format = "text/html")]
88107
async fn inform_json() -> RawHtml<String> {
89-
RawHtml(INTERFACE_HTML.replace("{}", "JSON Interface"))
108+
RawHtml(
109+
INTERFACE_HTML
110+
.replace("__TITLE__", "JSON Interface")
111+
.replace(
112+
"__HEADERS__",
113+
"headers: { 'Content-Type': 'application/json' },",
114+
),
115+
)
90116
}
91117

92118
#[post("/interface/json", data = "<query>", format = "json", rank = 1)]
@@ -95,6 +121,19 @@ async fn evaluate_json(query: Json<Value>) -> Json<Value> {
95121
Json(result)
96122
}
97123

124+
#[get("/interface/json-to-lisp", format = "text/html")]
125+
async fn inform_json_to_lisp() -> RawHtml<String> {
126+
RawHtml(INTERFACE_HTML.replace("__TITLE__", "JSON to LISP").replace(
127+
"__HEADERS__",
128+
"headers: { 'Content-Type': 'application/json' },",
129+
))
130+
}
131+
132+
#[post("/interface/json-to-lisp", data = "<query>", format = "json", rank = 1)]
133+
async fn json_to_lisp(query: Json<Value>) -> RawText<String> {
134+
RawText(JOURNAL.json_to_lisp(query.into_inner()))
135+
}
136+
98137
#[rocket::main]
99138
async fn main() {
100139
let config = Config::new();
@@ -156,8 +195,12 @@ async fn main() {
156195
index,
157196
inform_lisp,
158197
evaluate_lisp,
198+
inform_lisp_to_json,
199+
lisp_to_json,
159200
inform_json,
160-
evaluate_json
201+
evaluate_json,
202+
inform_json_to_lisp,
203+
json_to_lisp
161204
],
162205
)
163206
.configure(rocket_config)

0 commit comments

Comments
 (0)