1
// Copyright 2020, Collabora Ltd.
2
// SPDX-License-Identifier: MIT OR Apache-2.0
3

            
4
// Structures used to send config data
5

            
6
use reqwest::Client;
7
use serde::Serialize;
8

            
9
use crate::ddi::{Error, Execution, Finished};
10

            
11
/// A request from the server asking to upload the device configuration.
12
#[derive(Debug)]
13
pub struct ConfigRequest {
14
    client: Client,
15
    url: String,
16
}
17

            
18
impl ConfigRequest {
19
12
    pub(crate) fn new(client: Client, url: String) -> Self {
20
12
        Self { client, url }
21
12
    }
22

            
23
    /// Send the requested device configuration to the server.
24
    ///
25
    /// The configuration is represented as the `data` argument which
26
    /// need to be serializable.
27
2
    pub async fn upload<T: Serialize>(
28
2
        &self,
29
2
        execution: Execution,
30
2
        finished: Finished,
31
2
        mode: Option<Mode>,
32
2
        data: T,
33
2
        details: Vec<&str>,
34
2
    ) -> Result<(), Error> {
35
2
        let details = details.iter().map(|m| m.to_string()).collect();
36
2
        let data = ConfigData::new(execution, finished, mode, data, details);
37
2
        let reply = self.client.put(&self.url).json(&data).send().await?;
38

            
39
2
        reply.error_for_status()?;
40
2
        Ok(())
41
2
    }
42
}
43

            
44
#[derive(Debug, Serialize)]
45
pub(crate) struct ConfigData<T: Serialize> {
46
    status: Status,
47
    mode: Option<Mode>,
48
    data: T,
49
    // skip 'id' as its semantic is unclear and it's left empty in the doc
50
}
51
#[derive(Debug, Serialize)]
52
struct Status {
53
    execution: Execution,
54
    result: ResultT,
55
    details: Vec<String>,
56
}
57

            
58
#[derive(Debug, Serialize)]
59
pub(crate) struct ResultT {
60
    finished: Finished,
61
}
62

            
63
/// Update mode that should be applied when updating target
64
// FIXME: would be good to have better documentation of the fields but the spec does not say much
65
#[derive(Debug, Serialize)]
66
#[serde(rename_all = "lowercase")]
67
pub enum Mode {
68
    /// Merge
69
    Merge,
70
    /// Replace
71
    Replace,
72
    /// Remove
73
    Remove,
74
}
75

            
76
impl<T: Serialize> ConfigData<T> {
77
2
    pub(crate) fn new(
78
2
        execution: Execution,
79
2
        finished: Finished,
80
2
        mode: Option<Mode>,
81
2
        data: T,
82
2
        details: Vec<String>,
83
2
    ) -> Self {
84
2
        Self {
85
2
            data,
86
2
            status: Status {
87
2
                execution,
88
2
                result: ResultT { finished },
89
2
                details,
90
2
            },
91
2
            mode,
92
2
        }
93
2
    }
94
}