Skip to main content

ogcapi_processes/
greeter.rs

1use std::collections::HashMap;
2
3use anyhow::Result;
4use schemars::{JsonSchema, schema_for};
5use serde::Deserialize;
6
7use ogcapi_types::{
8    common::Exception,
9    processes::{
10        Execute, Format, InlineOrRefData, Input, InputValueNoObject, Output, Process,
11        TransmissionMode,
12    },
13};
14
15use crate::{ProcessResponseBody, Processor};
16
17/// Greeter `Processor`
18///
19/// Example processor that takes a name as input and returns a greeting.
20///
21/// # Usage
22///
23/// ```bash
24/// curl http://localhost:8484/processes/greet/execution \
25///         -H 'Content-Type: application/json' \
26///         -d '{ "inputs": { "name": "World" } }'
27/// ```
28#[derive(Clone)]
29pub struct Greeter;
30
31/// Inputs for the `greet` process
32#[derive(Deserialize, Debug, JsonSchema)]
33pub struct GreeterInputs {
34    /// Name to be greeted
35    pub name: String,
36}
37
38impl GreeterInputs {
39    pub fn execute_input(&self) -> HashMap<String, Input> {
40        HashMap::from([(
41            "name".to_string(),
42            Input::InlineOrRefData(InlineOrRefData::InputValueNoObject(
43                InputValueNoObject::String(self.name.to_owned()),
44            )),
45        )])
46    }
47}
48
49/// Outputs for the `greet` process
50#[derive(Clone, Debug, JsonSchema)]
51pub struct GreeterOutputs {
52    pub greeting: String,
53}
54
55impl GreeterOutputs {
56    pub fn execute_output() -> HashMap<String, Output> {
57        HashMap::from([(
58            "greeting".to_string(),
59            Output {
60                format: Some(Format {
61                    media_type: Some("text/plain".to_string()),
62                    encoding: Some("utf8".to_string()),
63                    schema: None,
64                }),
65                transmission_mode: TransmissionMode::Value,
66            },
67        )])
68    }
69}
70
71impl TryFrom<ProcessResponseBody> for GreeterOutputs {
72    type Error = Exception;
73
74    fn try_from(value: ProcessResponseBody) -> Result<Self, Self::Error> {
75        if let ProcessResponseBody::Requested(buf) = value {
76            Ok(GreeterOutputs {
77                greeting: String::from_utf8(buf).unwrap(),
78            })
79        } else {
80            Err(Exception::new("500"))
81        }
82    }
83}
84
85#[async_trait::async_trait]
86impl Processor for Greeter {
87    fn id(&self) -> &'static str {
88        "greet"
89    }
90
91    fn version(&self) -> &'static str {
92        "0.1.0"
93    }
94
95    fn process(&self) -> Result<Process> {
96        Process::try_new(
97            self.id(),
98            self.version(),
99            &schema_for!(GreeterInputs).schema,
100            &schema_for!(GreeterOutputs).schema,
101        )
102        .map_err(Into::into)
103    }
104
105    async fn execute(&self, execute: Execute) -> Result<ProcessResponseBody> {
106        let value = serde_json::to_value(execute.inputs).unwrap();
107        let inputs: GreeterInputs = serde_json::from_value(value).unwrap();
108        Ok(ProcessResponseBody::Requested(
109            format!("Hello, {}!\n", inputs.name).as_bytes().to_owned(),
110        ))
111    }
112}
113
114#[cfg(test)]
115mod tests {
116    use ogcapi_types::processes::Execute;
117
118    use crate::{
119        Processor,
120        greeter::{Greeter, GreeterInputs, GreeterOutputs},
121    };
122
123    #[tokio::test]
124    async fn test_greeter() {
125        let greeter = Greeter;
126        assert_eq!(greeter.id(), "greet");
127
128        println!(
129            "Process:\n{}",
130            serde_json::to_string_pretty(&greeter.process().unwrap()).unwrap()
131        );
132
133        let input = GreeterInputs {
134            name: "Greeter".to_string(),
135        };
136
137        let execute = Execute {
138            inputs: input.execute_input(),
139            outputs: GreeterOutputs::execute_output(),
140            ..Default::default()
141        };
142
143        let output: GreeterOutputs = greeter.execute(execute).await.unwrap().try_into().unwrap();
144        assert_eq!(output.greeting, "Hello, Greeter!\n");
145    }
146}