1use lcax_core::value::AnyValue;
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use std::fmt;
6
7#[cfg(feature = "jsbindings")]
8use wasm_bindgen::prelude::*;
9
10#[cfg(feature = "jsbindings")]
11use tsify_next::{declare, Tsify};
12
13#[cfg(feature = "pybindings")]
14use pyo3::prelude::*;
15
16#[cfg(feature = "jsbindings")]
17use strum::IntoEnumIterator;
18
19#[cfg(feature = "jsbindings")]
20use strum_macros::EnumIter;
21
22#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone, PartialEq)]
23#[serde(rename_all = "lowercase")]
24#[cfg_attr(
25 feature = "jsbindings",
26 derive(Tsify, EnumIter),
27 tsify(into_wasm_abi, from_wasm_abi)
28)]
29#[cfg_attr(feature = "pybindings", pyclass(eq, eq_int))]
30pub enum Unit {
31 M,
32 M2,
33 M3,
34 KG,
35 TONES,
36 PCS,
37 KWH,
38 L,
39 M2R1,
40 KM,
41 #[allow(non_camel_case_types)]
42 TONES_KM,
43 KGM3,
44 UNKNOWN,
45}
46
47#[cfg(feature = "jsbindings")]
48#[wasm_bindgen]
49pub fn units() -> Vec<Unit> {
50 Unit::iter().collect()
51}
52
53impl From<&String> for Unit {
54 fn from(unit: &String) -> Self {
55 match unit.to_ascii_lowercase().as_str() {
56 "m" => Unit::M,
57 "m2" | "m^2" | "qm" => Unit::M2,
58 "m3" | "m^3" => Unit::M3,
59 "km" => Unit::KM,
60 "kg" => Unit::KG,
61 "tones" | "tonnes" => Unit::TONES,
62 "pcs" | "stk" | "pcs." => Unit::PCS,
63 "l" => Unit::L,
64 "kwh" => Unit::KWH,
65 "m2r1" => Unit::M2R1,
66 "tones*km" => Unit::TONES_KM,
67 "kgm3" => Unit::KGM3,
68 _ => Unit::UNKNOWN,
69 }
70 }
71}
72impl fmt::Display for Unit {
73 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74 write!(f, "{:?}", self)
75 }
76}
77
78impl Default for Unit {
79 fn default() -> Unit {
80 Unit::UNKNOWN
81 }
82}
83
84#[derive(Deserialize, Serialize, JsonSchema, Clone, PartialEq)]
85#[serde(rename_all = "camelCase")]
86#[cfg_attr(feature = "jsbindings", derive(Tsify))]
87#[cfg_attr(feature = "pybindings", pyclass(get_all, set_all))]
88pub struct Conversion {
89 pub value: f64,
90 pub to: Unit,
91 pub meta_data: Option<MetaData>,
92}
93
94#[cfg_attr(feature = "pybindings", pymethods)]
95impl Conversion {
96 #[cfg(feature = "pybindings")]
97 #[new]
98 #[pyo3(signature = (to, value, meta_data=None))]
99 pub fn new_py(to: Unit, value: f64, meta_data: Option<MetaData>) -> Self {
100 Self {
101 to,
102 value,
103 meta_data,
104 }
105 }
106
107 #[cfg(feature = "pybindings")]
108 fn __repr__(&self) -> String {
109 format!("Conversion: {}", self.to)
110 }
111
112 #[cfg(feature = "pybindings")]
113 fn __str__(&self) -> String {
114 format!("Conversion: {}", self.to)
115 }
116}
117
118#[derive(Deserialize, Serialize, JsonSchema, Clone, PartialEq)]
119#[serde(rename_all = "camelCase")]
120#[cfg_attr(feature = "jsbindings", derive(Tsify))]
121#[cfg_attr(feature = "pybindings", pyclass(get_all, set_all))]
122pub struct Source {
123 pub name: String,
124 pub url: Option<String>,
125}
126
127#[cfg_attr(feature = "pybindings", pymethods)]
128impl Source {
129 #[cfg(feature = "pybindings")]
130 #[new]
131 #[pyo3(signature = (name, url=None))]
132 pub fn new_py(name: String, url: Option<String>) -> Self {
133 Self { name, url }
134 }
135 #[cfg(feature = "pybindings")]
136 fn __repr__(&self) -> String {
137 format!("Source: {}", self.name)
138 }
139
140 #[cfg(feature = "pybindings")]
141 fn __str__(&self) -> String {
142 format!("Source: {}", self.name)
143 }
144}
145
146#[derive(Deserialize, Serialize, JsonSchema, Clone, PartialEq)]
147#[cfg_attr(feature = "jsbindings", derive(Tsify))]
148#[cfg_attr(feature = "pybindings", pyclass(get_all, set_all))]
149pub struct Reference {
150 pub uri: String,
151 pub format: Option<String>,
152 pub version: Option<String>,
153 pub overrides: Option<HashMap<String, Option<AnyValue>>>,
154}
155
156#[cfg_attr(feature = "jsbindings", declare)]
157pub type MetaData = HashMap<String, Option<AnyValue>>;