1use std::collections::BTreeMap;
9use std::fmt::Debug;
10
11use serde::{Deserialize, Serialize};
12
13#[derive(Debug, PartialEq, Serialize, Deserialize, Copy, Clone, PartialOrd)]
15#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
16#[serde(untagged)]
17pub enum Number {
18 Int(i64),
20
21 Float(f64),
23}
24
25impl From<i64> for Number {
26 #[inline(always)]
27 fn from(value: i64) -> Self {
28 Self::Int(value)
29 }
30}
31
32impl From<f64> for Number {
33 #[inline(always)]
34 fn from(value: f64) -> Self {
35 Self::Float(value)
36 }
37}
38
39#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, PartialOrd)]
41#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
42#[serde(untagged)]
43pub enum Value {
44 Null,
46
47 Bool(bool),
49
50 Number(Number),
52
53 String(String),
55
56 List(Vec<Value>),
58
59 Map(BTreeMap<String, Value>),
61}
62
63impl From<Value> for serde_json::Value {
64 fn from(value: Value) -> Self {
65 match value {
66 Value::Null => serde_json::Value::Null,
67 Value::Bool(b) => serde_json::Value::Bool(b),
68 Value::Number(Number::Float(f)) => {
69 serde_json::Value::Number(serde_json::Number::from_f64(f).unwrap())
70 }
71 Value::Number(Number::Int(i)) => serde_json::Value::Number(i.into()),
72 Value::String(s) => serde_json::Value::String(s),
73 Value::List(list) => serde_json::Value::Array(list.into_iter().map(Into::into).collect()),
74 Value::Map(map) => serde_json::Value::Object(
75 map
76 .into_iter()
77 .map(|(key, value)| (key, value.into()))
78 .collect(),
79 ),
80 }
81 }
82}
83
84impl From<serde_json::Value> for Value {
85 fn from(value: serde_json::Value) -> Self {
86 match value {
87 serde_json::Value::Null => Value::Null,
88 serde_json::Value::Bool(b) => Value::Bool(b),
89 serde_json::Value::Number(n) => Value::Number(if let Some(f) = n.as_f64() {
90 Number::Float(f)
91 } else if let Some(n) = n.as_u64() {
92 Number::Int(n as i64)
93 } else if let Some(n) = n.as_i64() {
94 Number::Int(n)
95 } else {
96 Number::Int(0)
97 }),
98 serde_json::Value::String(s) => Value::String(s),
99 serde_json::Value::Array(list) => Value::List(list.into_iter().map(Into::into).collect()),
100 serde_json::Value::Object(map) => Value::Map(
101 map
102 .into_iter()
103 .map(|(key, value)| (key, value.into()))
104 .collect(),
105 ),
106 }
107 }
108}
109
110impl From<bool> for Value {
111 #[inline(always)]
112 fn from(value: bool) -> Self {
113 Self::Bool(value)
114 }
115}
116
117impl<T: Into<Number>> From<T> for Value {
118 #[inline(always)]
119 fn from(value: T) -> Self {
120 Self::Number(value.into())
121 }
122}
123
124impl From<String> for Value {
125 #[inline(always)]
126 fn from(value: String) -> Self {
127 Value::String(value)
128 }
129}
130
131impl From<toml::Value> for Value {
132 #[inline(always)]
133 fn from(value: toml::Value) -> Self {
134 use toml::Value as Toml;
135
136 match value {
137 Toml::String(s) => s.into(),
138 Toml::Integer(i) => i.into(),
139 Toml::Float(f) => f.into(),
140 Toml::Boolean(b) => b.into(),
141 Toml::Datetime(d) => d.to_string().into(),
142 Toml::Array(a) => Value::List(a.into_iter().map(Value::from).collect()),
143 Toml::Table(t) => Value::Map(t.into_iter().map(|(k, v)| (k, v.into())).collect()),
144 }
145 }
146}
147
148#[cfg(feature = "build")]
149mod build {
150 use std::convert::identity;
151
152 use crate::tokens::*;
153
154 use super::*;
155 use proc_macro2::TokenStream;
156 use quote::{quote, ToTokens, TokenStreamExt};
157
158 impl ToTokens for Number {
159 fn to_tokens(&self, tokens: &mut TokenStream) {
160 let prefix = quote! { ::tauri::utils::acl::Number };
161
162 tokens.append_all(match self {
163 Self::Int(i) => {
164 quote! { #prefix::Int(#i) }
165 }
166 Self::Float(f) => {
167 quote! { #prefix::Float (#f) }
168 }
169 });
170 }
171 }
172
173 impl ToTokens for Value {
174 fn to_tokens(&self, tokens: &mut TokenStream) {
175 let prefix = quote! { ::tauri::utils::acl::Value };
176
177 tokens.append_all(match self {
178 Value::Null => quote! { #prefix::Null },
179 Value::Bool(bool) => quote! { #prefix::Bool(#bool) },
180 Value::Number(number) => quote! { #prefix::Number(#number) },
181 Value::String(str) => {
182 let s = str_lit(str);
183 quote! { #prefix::String(#s) }
184 }
185 Value::List(vec) => {
186 let items = vec_lit(vec, identity);
187 quote! { #prefix::List(#items) }
188 }
189 Value::Map(map) => {
190 let map = map_lit(
191 quote! { ::std::collections::BTreeMap },
192 map,
193 str_lit,
194 identity,
195 );
196 quote! { #prefix::Map(#map) }
197 }
198 });
199 }
200 }
201}