1mod check;
12mod data;
13mod error;
14mod media;
15
16pub(crate) use error::ServiceError;
17
18pub fn source_problems(path: &str, text: &str) -> Vec<yog_data::Diagnostic> {
21 check::check(path, text).problems
22}
23
24use yog_data::Schema;
25
26#[derive(Debug, Clone, Schema)]
28pub(crate) struct Request {
29 pub(crate) method: String,
30 #[data(default)]
31 pub(crate) params: yog_data::Value,
32}
33
34pub(crate) type Reply = Result<yog_data::Value, ServiceError>;
36
37pub fn run() -> Result<(), String> {
39 let mut input = std::io::stdin().lock();
40 let mut out = std::io::stdout().lock();
41 loop {
42 let reply = match yog_data::io::read_frame_bytes(&mut input) {
43 Ok(None) => return Ok(()),
44 Ok(Some(bytes)) => match yog_data::read_bytes::<Request>(&bytes) {
45 Ok(request) => answer(&request),
46 Err(e) => Err(format!("not a request: {e:?}").into()),
47 },
48 Err(e) => return Err(e.to_string()),
49 };
50 yog_data::io::write_frame(&mut out, &reply).map_err(|e| e.to_string())?;
51 }
52}
53
54pub(crate) fn answer(request: &Request) -> Reply {
56 let (method, params) = (request.method.as_str(), &request.params);
57 let reply = data::method(method, params)
58 .or_else(|| media::method(method, params))
59 .or_else(|| crate::design::service::dispatch(method, params))
61 .unwrap_or_else(|| Err(format!("no method `{method}`").into()));
62 reply
63 .map(|v| yog_data::typed::flatten(&v))
64 .map_err(|mut e| {
65 e.file = e.file.take().or_else(|| file_of(params));
66 e
67 })
68}
69
70fn file_of(params: &yog_data::Value) -> Option<String> {
72 let path = |v: &yog_data::Value| {
73 v.get(yog_ids::serve_param::PATH)
74 .and_then(yog_data::Value::as_str)
75 .map(str::to_string)
76 };
77 path(params).or_else(|| params.get(yog_ids::serve_param::ARGS).and_then(path))
78}
79
80#[cfg(test)]
81mod tests;