1use std::borrow::Cow;
2use std::fmt::Display;
3use std::hash::Hash;
4use std::str::{self, FromStr};
5use std::mem;
6
7
8use crate::{ParamValue, ParamValueParseError, Value};
9
10#[derive(Debug, Clone, PartialEq, PartialOrd, Default)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize))]
16pub enum ValueRef<'a> {
17 String(Cow<'a, str>),
19 Float(f64),
21 Int(i64),
23 Buffer(Cow<'a, [u8]>),
25 #[default]
27 Empty,
28 Boolean(bool),
30 List(Cow<'a, [Value]>),
32}
33
34impl Eq for ValueRef<'_> {}
35
36impl From<String> for ValueRef<'_> {
37 fn from(value: String) -> Self {
38 value.parse().unwrap()
39 }
40}
41
42impl<'a> From<&'a str> for ValueRef<'a> {
43 fn from(value: &'a str) -> Self {
44 ValueRef::new(value)
45 }
46}
47
48impl<'a> From<Cow<'a, str>> for ValueRef<'a> {
49 fn from(value: Cow<'a, str>) -> Self {
50 match value {
51 Cow::Borrowed(s) => Self::new(s),
52 Cow::Owned(s) => s.parse().unwrap(),
53 }
54 }
55}
56
57impl PartialEq<String> for ValueRef<'_> {
58 fn eq(&self, other: &String) -> bool {
59 self.as_str() == other.as_str()
60 }
61}
62
63impl PartialEq<str> for ValueRef<'_> {
64 fn eq(&self, other: &str) -> bool {
65 self.as_str() == other
66 }
67}
68
69impl PartialEq<&str> for ValueRef<'_> {
70 fn eq(&self, other: &&str) -> bool {
71 self.as_str() == *other
72 }
73}
74
75impl PartialEq<i64> for ValueRef<'_> {
76 fn eq(&self, other: &i64) -> bool {
77 if let Self::Int(val) = self {
78 val == other
79 } else {
80 false
81 }
82 }
83}
84
85impl PartialEq<f64> for ValueRef<'_> {
86 fn eq(&self, other: &f64) -> bool {
87 if let Self::Float(val) = self {
88 val == other
89 } else {
90 false
91 }
92 }
93}
94
95impl PartialEq<bool> for ValueRef<'_> {
96 fn eq(&self, other: &bool) -> bool {
97 if let Self::Boolean(val) = self {
98 val == other
99 } else {
100 false
101 }
102 }
103}
104
105impl FromStr for ValueRef<'_> {
106 type Err = ParamValueParseError;
107
108 fn from_str(s: &str) -> Result<Self, Self::Err> {
109 if s.is_empty() {
110 return Ok(Self::Empty);
111 }
112 if let Ok(value) = s.parse() {
113 Ok(Self::Int(value))
114 } else if let Ok(value) = s.parse() {
115 Ok(Self::Float(value))
116 } else if let Ok(value) = s.parse() {
117 Ok(Self::Boolean(value))
118 } else {
119 Ok(Self::String(Cow::Owned(s.to_string())))
120 }
121 }
122}
123
124impl Display for ValueRef<'_> {
125 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126 match self {
127 Self::String(v) => f.write_str(v),
128 Self::Float(v) => v.fmt(f),
129 Self::Int(v) => v.fmt(f),
130 Self::Buffer(v) => f.write_str(&String::from_utf8_lossy(v)),
131 Self::Empty => f.write_str(""),
132 Self::Boolean(v) => v.fmt(f),
133 Self::List(v) => {
134 f.write_str("[ ")?;
135 if let Some(vi) = v.first() {
136 vi.fmt(f)?;
137 }
138 for vi in v.iter().skip(1) {
139 f.write_str(", ")?;
140 vi.fmt(f)?;
141 }
142 f.write_str(" ]")
143 }
144 }
145 }
146}
147
148impl<'a> ValueRef<'a> {
149 pub fn new(s: &'a str) -> Self {
153 if s.is_empty() {
154 return Self::Empty;
155 }
156 if let Ok(value) = s.parse::<i64>() {
157 Self::Int(value)
158 } else if let Ok(value) = s.parse::<f64>() {
159 Self::Float(value)
160 } else if let Ok(value) = s.parse() {
161 Self::Boolean(value)
162 } else {
163 Self::String(Cow::Borrowed(s))
164 }
165 }
166
167 pub const fn wrap(s: &'a str) -> Self {
169 Self::String(Cow::Borrowed(s))
170 }
171
172 fn is_empty(&self) -> bool {
173 matches!(self, Self::Empty)
174 }
175
176 fn is_i64(&self) -> bool {
177 matches!(self, Self::Int(_))
178 }
179
180 fn is_f64(&self) -> bool {
181 matches!(self, Self::Float(_))
182 }
183
184 fn is_buffer(&self) -> bool {
185 matches!(self, Self::Buffer(_))
186 }
187
188 fn is_str(&self) -> bool {
189 matches!(self, Self::String(_))
190 }
191
192 fn is_list(&self) -> bool {
193 matches!(self, Self::List(_))
194 }
195
196 fn to_bool(&self) -> Result<bool, ParamValueParseError> {
197 if let Self::Boolean(val) = self {
198 Ok(*val)
199 } else if self.is_numeric() {
200 Ok(self.to_i64()? != 0)
201 } else if let Self::Empty = self {
202 Ok(false)
203 } else if let Ok(v) = self.parse() {
204 Ok(v)
205 } else {
206 Err(ParamValueParseError::FailedToExtractInt(Some(
207 self.to_string(),
208 )))
209 }
210 }
211
212 pub fn coerce_bool(&mut self) -> Result<(), ParamValueParseError> {
214 let value = self.to_bool()?;
215 *self = Self::Boolean(value);
216 Ok(())
217 }
218
219 pub fn coerce_f64(&mut self) -> Result<(), ParamValueParseError> {
221 let value = self.to_f64()?;
222 *self = Self::Float(value);
223 Ok(())
224 }
225
226 pub fn coerce_i64(&mut self) -> Result<(), ParamValueParseError> {
228 let value = self.to_i64()?;
229 *self = Self::Int(value);
230 Ok(())
231 }
232
233 pub fn coerce_str(&mut self) -> Result<(), ParamValueParseError> {
235 if self.is_str() {
236 } else {
237 let value = self.to_string();
238 *self = Self::String(Cow::Owned(value));
239 }
240 Ok(())
241 }
242
243 pub fn coerce_empty(&mut self) {
245 *self = Self::Empty;
246 }
247
248 pub fn coerce_buffer(&mut self) -> Result<(), ParamValueParseError> {
250 if self.is_buffer() {
251 Ok(())
252 } else {
253 let buffer = Cow::Owned(self.to_buffer()?.to_vec());
254 *self = Self::Buffer(buffer);
255 Ok(())
256 }
257 }
258
259 pub fn coerce_list(&mut self) -> Result<(), ParamValueParseError> {
261 if !self.is_list() {
262 let dup = match self {
263 Self::Boolean(v) => Value::Boolean(*v),
264 Self::Empty => Value::Empty,
265 Self::Float(v) => Value::Float(*v),
266 Self::Int(v) => Value::Int(*v),
267 Self::Buffer(v) => Value::Buffer(v.to_vec().into()),
268 Self::String(v) => Value::String(v.to_string()),
269 Self::List(_) => unimplemented!(),
270 };
271 *self = Self::List(Cow::Owned([dup].into()));
272 }
273 Ok(())
274 }
275
276 fn parse<T: FromStr>(&self) -> Result<T, T::Err> {
277 match self {
278 Self::String(s) => s.parse(),
279 Self::Float(v) => v.to_string().parse(),
280 Self::Int(i) => i.to_string().parse(),
281 Self::Buffer(b) => String::from_utf8_lossy(b).parse(),
282 Self::Empty => "".parse(),
283 Self::Boolean(v) => v.to_string().parse(),
284 Self::List(_) => self.to_string().parse(),
285 }
286 }
287
288 fn to_f64(&self) -> Result<f64, ParamValueParseError> {
289 if let Self::Float(val) = self {
290 return Ok(*val);
291 } else if let Self::Int(val) = self {
292 return Ok(*val as f64);
293 } else if let Self::String(val) = self {
294 if let Ok(v) = val.parse() {
295 return Ok(v);
296 }
297 }
298 Err(ParamValueParseError::FailedToExtractFloat(Some(
299 self.to_string(),
300 )))
301 }
302
303 fn to_i64(&self) -> Result<i64, ParamValueParseError> {
304 if let Self::Int(val) = self {
305 return Ok(*val);
306 } else if let Self::Float(val) = self {
307 return Ok(*val as i64);
308 } else if let Self::String(val) = self {
309 if let Ok(v) = val.parse() {
310 return Ok(v);
311 }
312 }
313 Err(ParamValueParseError::FailedToExtractInt(Some(
314 self.to_string(),
315 )))
316 }
317
318 fn to_str(&self) -> Cow<'_, str> {
319 if let Self::String(val) = self {
320 Cow::Borrowed(val)
321 } else {
322 Cow::Owned(self.to_string())
323 }
324 }
325
326 fn to_buffer(&self) -> Result<Cow<'_, [u8]>, ParamValueParseError> {
327 if let Self::Buffer(val) = self {
328 match val {
329 Cow::Borrowed(v) => Ok(Cow::Borrowed(*v)),
330 Cow::Owned(v) => Ok(Cow::Borrowed(v)),
331 }
332 } else if let Self::String(val) = self {
333 Ok(Cow::Borrowed(val.as_bytes()))
334 } else {
335 Err(ParamValueParseError::FailedToExtractBuffer)
336 }
337 }
338}
339
340impl ParamValue for ValueRef<'_> {
341 fn is_empty(&self) -> bool {
342 self.is_empty()
343 }
344
345 fn is_i64(&self) -> bool {
346 self.is_i64()
347 }
348
349 fn is_f64(&self) -> bool {
350 self.is_f64()
351 }
352
353 fn is_buffer(&self) -> bool {
354 self.is_buffer()
355 }
356
357 fn is_str(&self) -> bool {
358 self.is_str()
359 }
360
361 fn is_boolean(&self) -> bool {
362 matches!(self, Self::Boolean(_))
363 }
364
365 fn to_bool(&self) -> Result<bool, ParamValueParseError> {
366 self.to_bool()
367 }
368
369 fn to_f64(&self) -> Result<f64, ParamValueParseError> {
370 self.to_f64()
371 }
372
373 fn to_i64(&self) -> Result<i64, ParamValueParseError> {
374 self.to_i64()
375 }
376
377 fn to_str(&self) -> Cow<'_, str> {
378 self.to_str()
379 }
380
381 fn to_buffer(&self) -> Result<Cow<'_, [u8]>, ParamValueParseError> {
382 self.to_buffer()
383 }
384
385 fn parse<T: FromStr>(&self) -> Result<T, T::Err> {
386 self.parse()
387 }
388
389 fn as_bytes(&self) -> Cow<'_, [u8]> {
390 match self {
391 Self::String(v) => Cow::Borrowed(v.as_bytes()),
392 Self::Buffer(v) => Cow::Borrowed(v.as_ref()),
393 Self::Float(v) => Cow::Owned(v.to_string().into_bytes()),
394 Self::Int(v) => Cow::Owned(v.to_string().into_bytes()),
395 Self::Empty => Cow::Borrowed(b""),
396 Self::Boolean(v) => Cow::Owned(v.to_string().into_bytes()),
397 Self::List(_) => Cow::Owned(self.to_string().into_bytes()),
398 }
399 }
400
401 fn as_ref(&self) -> ValueRef<'_> {
402 self.clone()
403 }
404
405 fn data_len(&self) -> usize {
406 match self {
407 Self::String(v) => v.len(),
408 Self::Buffer(v) => v.len(),
409 Self::Float(_) => 8,
410 Self::Int(_) => 8,
411 Self::Empty => 0,
412 Self::Boolean(_) => mem::size_of::<bool>(),
413 Self::List(v) => v.iter().map(|vi| vi.data_len()).sum(),
414 }
415 }
416
417 fn is_list(&self) -> bool {
418 self.is_list()
419 }
420
421 fn as_slice(&self) -> Cow<'_, [Value]> {
422 match self {
423 Self::List(v) => Cow::Borrowed(v),
424 _ => {
425 let dup = match self {
426 Self::Boolean(v) => Value::Boolean(*v),
427 Self::Empty => Value::Empty,
428 Self::Float(v) => Value::Float(*v),
429 Self::Int(v) => Value::Int(*v),
430 Self::Buffer(v) => Value::Buffer(v.to_vec().into()),
431 Self::String(v) => Value::String(v.to_string()),
432 Self::List(_) => unimplemented!(),
433 };
434 Cow::Owned([dup].into())
435 }
436 }
437 }
438}
439
440impl<'a> From<&'a Value> for ValueRef<'a> {
441 fn from(value: &'a Value) -> Self {
442 match value {
443 Value::String(s) => Self::String(Cow::Borrowed(s)),
444 Value::Float(v) => Self::Float(*v),
445 Value::Int(v) => Self::Int(*v),
446 Value::Buffer(v) => Self::Buffer(Cow::Borrowed(v)),
447 Value::Empty => Self::Empty,
448 Value::Boolean(v) => Self::Boolean(*v),
449 Value::List(v) => Self::List(Cow::Borrowed(v)),
450 }
451 }
452}
453
454impl PartialEq<Value> for ValueRef<'_> {
455 fn eq(&self, other: &Value) -> bool {
456 *self == other.as_ref()
457 }
458}
459
460impl<'a> PartialEq<ValueRef<'a>> for Value {
461 fn eq(&self, other: &ValueRef<'a>) -> bool {
462 self.as_ref() == *other
463 }
464}
465
466impl<'a> From<ValueRef<'a>> for Value {
467 fn from(value: ValueRef<'a>) -> Self {
468 match value {
469 ValueRef::String(s) => match s {
470 Cow::Borrowed(s) => Self::String(s.to_string()),
471 Cow::Owned(s) => Self::String(s),
472 },
473 ValueRef::Float(v) => Self::Float(v),
474 ValueRef::Int(v) => Self::Int(v),
475 ValueRef::Buffer(v) => Self::Buffer(v.to_vec().into_boxed_slice()),
476 ValueRef::Empty => Self::Empty,
477 ValueRef::Boolean(v) => Self::Boolean(v),
478 ValueRef::List(v) => {
479 let mut ve = Vec::with_capacity(v.len());
480 for vi in v.iter() {
481 ve.push(vi.clone())
482 }
483 Self::List(ve.into_boxed_slice())
484 }
485 }
486 }
487}
488
489impl Hash for ValueRef<'_> {
490 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
491 core::mem::discriminant(self).hash(state);
492 match self {
493 Self::String(s) => s.hash(state),
494 Self::Float(v) => v.to_bits().hash(state),
495 Self::Int(v) => (*v).hash(state),
496 Self::Buffer(v) => v.hash(state),
497 Self::Empty => 0u8.hash(state),
498 Self::Boolean(v) => (*v).hash(state),
499 Self::List(v) => v.iter().for_each(|vi| vi.hash(state)),
500 }
501 }
502}
503
504macro_rules! param_value_ref_int {
505 ($val:ty) => {
506 impl<'a> From<$val> for ValueRef<'a> {
507 fn from(value: $val) -> Self {
508 Self::Int(value as i64)
509 }
510 }
511
512 impl<'a> From<&$val> for ValueRef<'a> {
513 fn from(value: &$val) -> Self {
514 Self::Int(*value as i64)
515 }
516 }
517
518 impl<'a> From<Option<$val>> for ValueRef<'a> {
519 fn from(value: Option<$val>) -> Self {
520 if let Some(v) = value {
521 Self::Int(v as i64)
522 } else {
523 Self::Empty
524 }
525 }
526 }
527 };
528}
529
530macro_rules! param_value_ref_float {
531 ($val:ty) => {
532 impl<'a> From<$val> for ValueRef<'a> {
533 fn from(value: $val) -> Self {
534 Self::Float(value as f64)
535 }
536 }
537
538 impl<'a> From<&$val> for ValueRef<'a> {
539 fn from(value: &$val) -> Self {
540 Self::Float(*value as f64)
541 }
542 }
543
544 impl<'a> From<Option<$val>> for ValueRef<'a> {
545 fn from(value: Option<$val>) -> Self {
546 if let Some(v) = value {
547 Self::Float(v as f64)
548 } else {
549 Self::Empty
550 }
551 }
552 }
553 };
554}
555
556impl From<ValueRef<'_>> for f32 {
557 fn from(value: ValueRef<'_>) -> Self {
558 value.to_f32().unwrap()
559 }
560}
561
562impl From<ValueRef<'_>> for f64 {
563 fn from(value: ValueRef<'_>) -> Self {
564 value.to_f64().unwrap()
565 }
566}
567
568impl From<ValueRef<'_>> for i32 {
569 fn from(value: ValueRef<'_>) -> Self {
570 value.to_i32().unwrap()
571 }
572}
573
574impl From<ValueRef<'_>> for i64 {
575 fn from(value: ValueRef<'_>) -> Self {
576 value.to_i64().unwrap()
577 }
578}
579
580impl From<bool> for Value {
581 fn from(value: bool) -> Self {
582 Self::Boolean(value)
583 }
584}
585
586impl From<bool> for ValueRef<'_> {
587 fn from(value: bool) -> Self {
588 Self::Boolean(value)
589 }
590}
591
592param_value_ref_int!(i8);
593param_value_ref_int!(i16);
594param_value_ref_int!(i32);
595param_value_ref_int!(i64);
596
597param_value_ref_int!(u8);
598param_value_ref_int!(u16);
599param_value_ref_int!(u32);
600param_value_ref_int!(u64);
601param_value_ref_int!(usize);
602
603param_value_ref_float!(f32);
604param_value_ref_float!(f64);