Skip to main content

airup_sdk/files/
mod.rs

1//! Definitions of Airup's file formats.
2
3pub mod milestone;
4pub mod policy;
5pub mod service;
6pub mod system_conf;
7
8pub use milestone::Milestone;
9pub use policy::Policy;
10pub use service::Service;
11pub use system_conf::SystemConf;
12
13use crate::prelude::*;
14use std::{borrow::Cow, sync::Arc};
15
16pub trait Validate {
17    fn validate(&self) -> Result<(), ReadError>;
18}
19
20pub trait Named {
21    fn set_name(&mut self, name: String);
22}
23
24pub fn merge(doc: &mut toml::Value, patch: &toml::Value) {
25    if !patch.is_table() {
26        *doc = patch.clone();
27        return;
28    }
29
30    if !doc.is_table() {
31        *doc = toml::Value::Table(toml::Table::new());
32    }
33    let map = doc.as_table_mut().unwrap();
34    for (key, value) in patch.as_table().unwrap() {
35        if value.is_table() && value.as_table().unwrap().is_empty() {
36            map.remove(key.as_str());
37        } else {
38            merge(
39                map.entry(key.as_str())
40                    .or_insert(toml::Value::Table(toml::Table::new())),
41                value,
42            );
43        }
44    }
45}
46
47#[derive(Debug, Clone, thiserror::Error)]
48pub enum ReadError {
49    #[error("{0}")]
50    Io(Arc<std::io::Error>),
51
52    #[error("{0}")]
53    Parse(String),
54
55    #[error("{0}")]
56    Validation(Cow<'static, str>),
57}
58impl From<std::io::Error> for ReadError {
59    fn from(value: std::io::Error) -> Self {
60        Self::Io(value.into())
61    }
62}
63impl From<toml::de::Error> for ReadError {
64    fn from(value: toml::de::Error) -> Self {
65        Self::Parse(value.message().to_owned())
66    }
67}
68impl From<&'static str> for ReadError {
69    fn from(value: &'static str) -> Self {
70        Self::Validation(value.into())
71    }
72}
73impl From<String> for ReadError {
74    fn from(value: String) -> Self {
75        Self::Validation(value.into())
76    }
77}
78impl From<std::io::ErrorKind> for ReadError {
79    fn from(value: std::io::ErrorKind) -> Self {
80        Self::from(std::io::Error::from(value))
81    }
82}
83impl IntoApiError for ReadError {
84    fn into_api_error(self) -> crate::Error {
85        match self {
86            Self::Io(err) => match err.kind() {
87                std::io::ErrorKind::NotFound => crate::Error::NotFound,
88                _ => crate::Error::Io {
89                    message: err.to_string(),
90                },
91            },
92            Self::Parse(x) => crate::Error::BadObject { message: x.into() },
93            Self::Validation(x) => crate::Error::BadObject { message: x },
94        }
95    }
96}