gq_core/
data.rs

1use crate::format::Indentation;
2use derive_getters::Getters;
3use derive_more::Display;
4use serde_json::Value;
5use std::borrow::Cow;
6use thiserror::Error;
7
8pub mod format;
9
10#[derive(Debug, Error)]
11pub enum Error {
12    #[error("json parsing error: {0}")]
13    Json(#[from] serde_json::Error),
14    #[error("yaml parsing error: {0}")]
15    Yaml(#[from] serde_yaml::Error),
16    #[error("format error: {0}")]
17    Format(#[from] format::Error),
18}
19
20#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Display)]
21pub enum DataType {
22    Json,
23    Yaml,
24}
25
26// TODO: implement Hash, partialEq and Eq with an id field, so string comparition is cheap
27#[derive(Debug, Getters, Clone, Hash, PartialEq, Eq)]
28pub struct Data<'a> {
29    payload: Cow<'a, str>,
30    data_type: DataType,
31}
32
33impl<'a> Data<'a> {
34    pub fn json(data: Cow<'a, str>) -> Self {
35        Self {
36            payload: data,
37            data_type: DataType::Json,
38        }
39    }
40
41    pub fn yaml(data: Cow<'a, str>) -> Self {
42        Self {
43            payload: data,
44            data_type: DataType::Yaml,
45        }
46    }
47
48    pub fn pretty_from_value(
49        value: &Value,
50        data_type: DataType,
51        indentation: Indentation,
52    ) -> Result<Self, Error> {
53        let payload = data_type.pretty_format(value, indentation)?;
54        Ok(Self {
55            payload: Cow::Owned(payload),
56            data_type,
57        })
58    }
59    pub fn pretty_convert_to(
60        &self,
61        target_type: DataType,
62        indentation: Indentation,
63    ) -> Result<Data, Error> {
64        let value = Value::try_from(self)?;
65        let payload = target_type.pretty_format(&value, indentation)?;
66        let data = Self {
67            payload: Cow::Owned(payload),
68            data_type: target_type,
69        };
70        Ok(data)
71    }
72
73    pub fn pretty_format(&'a self, indentation: Indentation) -> Result<Self, Error> {
74        let value = Value::try_from(self)?;
75        let payload = self.data_type.pretty_format(&value, indentation)?;
76        Ok(Self {
77            payload: Cow::Owned(payload),
78            data_type: self.data_type,
79        })
80    }
81
82    pub fn into_inner(self) -> Cow<'a, str> {
83        self.payload
84    }
85
86    pub fn into_owned(self) -> Data<'static> {
87        Data {
88            payload: Cow::Owned(self.payload.into_owned()),
89            data_type: self.data_type,
90        }
91    }
92}
93
94impl DataType {
95    pub fn value_from_str(&self, data: &str) -> Result<Value, Error> {
96        let result = match self {
97            DataType::Json => serde_json::from_str(data)?,
98            DataType::Yaml => serde_yaml::from_str(data)?,
99        };
100        Ok(result)
101    }
102}
103
104impl TryFrom<&Data<'_>> for Value {
105    type Error = Error;
106
107    fn try_from(data: &Data) -> Result<Self, Self::Error> {
108        data.data_type.value_from_str(&data.payload)
109    }
110}