1use anyhow::Result;
2use arcstr::ArcStr;
3use bytes::{Buf, BufMut};
4use chrono::prelude::*;
5use compact_str::{format_compact, CompactString};
6use netidx_core::{
7 pack::{self, Pack, PackError},
8 utils,
9};
10use rust_decimal::Decimal;
11use serde::{Deserialize, Serialize};
12use smallvec::SmallVec;
13use std::{hint::unreachable_unchecked, iter, ptr, result, str::FromStr, time::Duration};
14
15pub mod array;
16mod convert;
17mod op;
18pub mod parser;
19pub mod pbuf;
20mod print;
21#[cfg(test)]
22mod test;
23mod typ;
24
25pub use array::ValArray;
26pub use convert::FromValue;
27pub use pbuf::PBytes;
28pub use print::{printf, NakedValue};
29pub use typ::Typ;
30
31#[macro_export]
32macro_rules! valarray {
33 ($proto:expr; $size:literal) => {{
34 let proto: Value = $proto.into();
35 Value::Array(std::array::from_fn::<_, $size, _>(|_| proto.clone()))
36 }};
37 ($($e:expr),+) => {
38 Value::Array([$($e.into()),+].into())
39 }
40}
41
42fn _test_valarray() {
43 let v: Value = valarray![1, 2, 5.3, 10];
44 let _: Value = valarray![valarray!["elts", v], valarray!["foo", ["bar"]]];
45}
46
47const COPY_MAX: u32 = 0x0000_4000;
48
49#[derive(Debug, Serialize, Deserialize)]
60#[serde(tag = "type", content = "value")]
61#[repr(u32)]
62pub enum Value {
63 U32(u32) = 0x0000_0001,
65 V32(u32) = 0x0000_0002,
67 I32(i32) = 0x0000_0004,
69 Z32(i32) = 0x0000_0008,
71 U64(u64) = 0x0000_0010,
73 V64(u64) = 0x0000_0020,
75 I64(i64) = 0x0000_0040,
77 Z64(i64) = 0x0000_0080,
79 F32(f32) = 0x0000_0100,
81 F64(f64) = 0x0000_0200,
83 Decimal(Decimal) = 0x0000_0400,
85 DateTime(DateTime<Utc>) = 0x0000_0800,
87 Duration(Duration) = 0x0000_1000,
89 Bool(bool) = 0x0000_2000,
91 Null = 0x0000_4000,
93 String(ArcStr) = 0x8000_0000,
95 Bytes(PBytes) = 0x4000_0000,
97 Error(ArcStr) = 0x2000_0000,
99 Array(ValArray) = 0x1000_0000,
101}
102
103fn _assert_variants_are_copy(v: &Value) -> Value {
107 let i = match v {
108 Value::U32(i) | Value::V32(i) => Value::U32(*i),
110 Value::I32(i) | Value::Z32(i) => Value::I32(*i),
111 Value::U64(i) | Value::V64(i) => Value::U64(*i),
112 Value::I64(i) | Value::Z64(i) => Value::I64(*i),
113 Value::F32(i) => Value::F32(*i),
114 Value::F64(i) => Value::F64(*i),
115 Value::Decimal(i) => Value::Decimal(*i),
116 Value::DateTime(i) => Value::DateTime(*i),
117 Value::Duration(i) => Value::Duration(*i),
118 Value::Bool(b) => Value::Bool(*b),
119 Value::Null => Value::Null,
120
121 Value::String(i) => Value::String(i.clone()),
123 Value::Bytes(i) => Value::Bytes(i.clone()),
124 Value::Error(i) => Value::Error(i.clone()),
125 Value::Array(i) => Value::Array(i.clone()),
126 };
127 panic!("{i}")
128}
129
130impl Clone for Value {
131 fn clone(&self) -> Self {
132 if self.is_copy() {
133 unsafe { ptr::read(self) }
134 } else {
135 match self {
136 Self::String(c) => Self::String(c.clone()),
137 Self::Bytes(b) => Self::Bytes(b.clone()),
138 Self::Error(e) => Self::Error(e.clone()),
139 Self::Array(a) => Self::Array(a.clone()),
140 Value::U32(_)
141 | Value::V32(_)
142 | Value::I32(_)
143 | Value::Z32(_)
144 | Value::U64(_)
145 | Value::V64(_)
146 | Value::I64(_)
147 | Value::Z64(_)
148 | Value::F32(_)
149 | Value::F64(_)
150 | Value::Decimal(_)
151 | Value::DateTime(_)
152 | Value::Duration(_)
153 | Value::Bool(_)
154 | Value::Null => unsafe { unreachable_unchecked() },
155 }
156 }
157 }
158
159 fn clone_from(&mut self, source: &Self) {
160 if self.is_copy() {
161 unsafe { ptr::copy_nonoverlapping(source, self, 1) };
162 } else {
163 match source {
164 Self::String(c) => {
165 *self = Self::String(c.clone());
166 }
167 Self::Bytes(b) => {
168 *self = Self::Bytes(b.clone());
169 }
170 Self::Error(e) => {
171 *self = Self::Error(e.clone());
172 }
173 Self::Array(a) => {
174 *self = Self::Array(a.clone());
175 }
176 Value::U32(_)
177 | Value::V32(_)
178 | Value::I32(_)
179 | Value::Z32(_)
180 | Value::U64(_)
181 | Value::V64(_)
182 | Value::I64(_)
183 | Value::Z64(_)
184 | Value::F32(_)
185 | Value::F64(_)
186 | Value::Decimal(_)
187 | Value::DateTime(_)
188 | Value::Duration(_)
189 | Value::Bool(_)
190 | Value::Null => unsafe { unreachable_unchecked() },
191 }
192 }
193 }
194}
195
196impl FromStr for Value {
197 type Err = anyhow::Error;
198
199 fn from_str(s: &str) -> result::Result<Self, Self::Err> {
200 parser::parse_value(s)
201 }
202}
203
204impl Pack for Value {
205 fn encoded_len(&self) -> usize {
206 1 + match self {
207 Value::U32(v) => Pack::encoded_len(v),
208 Value::V32(v) => pack::varint_len(*v as u64),
209 Value::I32(v) => Pack::encoded_len(v),
210 Value::Z32(v) => pack::varint_len(pack::i32_zz(*v) as u64),
211 Value::U64(v) => Pack::encoded_len(v),
212 Value::V64(v) => pack::varint_len(*v),
213 Value::I64(v) => Pack::encoded_len(v),
214 Value::Z64(v) => pack::varint_len(pack::i64_zz(*v) as u64),
215 Value::F32(v) => Pack::encoded_len(v),
216 Value::F64(v) => Pack::encoded_len(v),
217 Value::DateTime(d) => Pack::encoded_len(d),
218 Value::Duration(d) => Pack::encoded_len(d),
219 Value::String(c) => Pack::encoded_len(c),
220 Value::Bytes(b) => Pack::encoded_len(b),
221 Value::Bool(_) | Value::Null => 0,
222 Value::Error(c) => Pack::encoded_len(c),
223 Value::Array(elts) => Pack::encoded_len(elts),
224 Value::Decimal(d) => Pack::encoded_len(d),
225 }
226 }
227
228 fn encode(&self, buf: &mut impl BufMut) -> result::Result<(), PackError> {
231 match self {
232 Value::U32(i) => {
233 buf.put_u8(0);
234 Pack::encode(i, buf)
235 }
236 Value::V32(i) => {
237 buf.put_u8(1);
238 Ok(pack::encode_varint(*i as u64, buf))
239 }
240 Value::I32(i) => {
241 buf.put_u8(2);
242 Pack::encode(i, buf)
243 }
244 Value::Z32(i) => {
245 buf.put_u8(3);
246 Ok(pack::encode_varint(pack::i32_zz(*i) as u64, buf))
247 }
248 Value::U64(i) => {
249 buf.put_u8(4);
250 Pack::encode(i, buf)
251 }
252 Value::V64(i) => {
253 buf.put_u8(5);
254 Ok(pack::encode_varint(*i, buf))
255 }
256 Value::I64(i) => {
257 buf.put_u8(6);
258 Pack::encode(i, buf)
259 }
260 Value::Z64(i) => {
261 buf.put_u8(7);
262 Ok(pack::encode_varint(pack::i64_zz(*i), buf))
263 }
264 Value::F32(i) => {
265 buf.put_u8(8);
266 Pack::encode(i, buf)
267 }
268 Value::F64(i) => {
269 buf.put_u8(9);
270 Pack::encode(i, buf)
271 }
272 Value::DateTime(dt) => {
273 buf.put_u8(10);
274 Pack::encode(dt, buf)
275 }
276 Value::Duration(d) => {
277 buf.put_u8(11);
278 Pack::encode(d, buf)
279 }
280 Value::String(s) => {
281 buf.put_u8(12);
282 Pack::encode(s, buf)
283 }
284 Value::Bytes(b) => {
285 buf.put_u8(13);
286 Pack::encode(b, buf)
287 }
288 Value::Bool(true) => Ok(buf.put_u8(14)),
289 Value::Bool(false) => Ok(buf.put_u8(15)),
290 Value::Null => Ok(buf.put_u8(16)),
291 Value::Error(e) => {
294 buf.put_u8(18);
295 Pack::encode(e, buf)
296 }
297 Value::Array(elts) => {
298 buf.put_u8(19);
299 Pack::encode(elts, buf)
300 }
301 Value::Decimal(d) => {
302 buf.put_u8(20);
303 Pack::encode(d, buf)
304 }
305 }
306 }
307
308 fn decode(buf: &mut impl Buf) -> result::Result<Self, PackError> {
309 match <u8 as Pack>::decode(buf)? {
310 0 => Ok(Value::U32(Pack::decode(buf)?)),
311 1 => Ok(Value::V32(pack::decode_varint(buf)? as u32)),
312 2 => Ok(Value::I32(Pack::decode(buf)?)),
313 3 => Ok(Value::Z32(pack::i32_uzz(pack::decode_varint(buf)? as u32))),
314 4 => Ok(Value::U64(Pack::decode(buf)?)),
315 5 => Ok(Value::V64(pack::decode_varint(buf)?)),
316 6 => Ok(Value::I64(Pack::decode(buf)?)),
317 7 => Ok(Value::Z64(pack::i64_uzz(pack::decode_varint(buf)?))),
318 8 => Ok(Value::F32(Pack::decode(buf)?)),
319 9 => Ok(Value::F64(Pack::decode(buf)?)),
320 10 => Ok(Value::DateTime(Pack::decode(buf)?)),
321 11 => Ok(Value::Duration(Pack::decode(buf)?)),
322 12 => Ok(Value::String(Pack::decode(buf)?)),
323 13 => Ok(Value::Bytes(Pack::decode(buf)?)),
324 14 => Ok(Value::Bool(true)),
325 15 => Ok(Value::Bool(false)),
326 16 => Ok(Value::Null),
327 17 => Ok(Value::Null), 18 => Ok(Value::Error(Pack::decode(buf)?)),
329 19 => Ok(Value::Array(Pack::decode(buf)?)),
330 20 => Ok(Value::Decimal(Pack::decode(buf)?)),
331 _ => Err(PackError::UnknownTag),
332 }
333 }
334}
335
336impl Value {
337 pub fn approx_eq(&self, v: &Self) -> bool {
338 use std::num::FpCategory::*;
339 match (self, v) {
340 (Value::U32(l) | Value::V32(l), Value::U32(r) | Value::V32(r)) => l == r,
341 (Value::I32(l) | Value::Z32(l), Value::I32(r) | Value::Z32(r)) => l == r,
342 (Value::U64(l) | Value::V64(l), Value::U64(r) | Value::V64(r)) => l == r,
343 (Value::I64(l) | Value::Z64(l), Value::I64(r) | Value::Z64(r)) => l == r,
344 (Value::F32(l), Value::F32(r)) => match (l.classify(), r.classify()) {
345 (Nan, Nan) => true,
346 (Zero, Zero) => true,
347 (_, _) => (l - r).abs() <= f32::EPSILON,
348 },
349 (Value::F64(l), Value::F64(r)) => match (l.classify(), r.classify()) {
350 (Nan, Nan) => true,
351 (Zero, Zero) => true,
352 (_, _) => (l - r).abs() <= f64::EPSILON,
353 },
354 (Value::Decimal(l), Value::Decimal(r)) => l == r,
355 (Value::DateTime(l), Value::DateTime(r)) => l == r,
356 (Value::Duration(l), Value::Duration(r)) => {
357 (l.as_secs_f64() - r.as_secs_f64()).abs() <= f64::EPSILON
358 }
359 (Value::String(l), Value::String(r)) => l == r,
360 (Value::Bytes(l), Value::Bytes(r)) => l == r,
361 (Value::Bool(l), Value::Bool(r)) => l == r,
362 (Value::Null, Value::Null) => true,
363 (Value::Error(l), Value::Error(r)) => l == r,
364 (Value::Array(l), Value::Array(r)) => {
365 l.len() == r.len()
366 && l.iter().zip(r.iter()).all(|(v0, v1)| v0.approx_eq(v1))
367 }
368 (Value::Array(_), _) | (_, Value::Array(_)) => false,
369 (l, r) if l.number() || r.number() => {
370 match (l.clone().cast_to::<f64>(), r.clone().cast_to::<f64>()) {
371 (Ok(l), Ok(r)) => match (l.classify(), r.classify()) {
372 (Nan, Nan) => true,
373 (Zero, Zero) => true,
374 (_, _) => (l - r).abs() <= f64::EPSILON,
375 },
376 (_, _) => false,
377 }
378 }
379 (_, _) => false,
380 }
381 }
382
383 pub fn discriminant(&self) -> u32 {
384 unsafe { *<*const _>::from(self).cast::<u32>() }
385 }
386
387 pub fn is_copy(&self) -> bool {
388 self.discriminant() <= COPY_MAX
389 }
390
391 pub fn cast(self, typ: Typ) -> Option<Value> {
393 macro_rules! cast_number {
394 ($v:expr, $typ:expr) => {
395 match typ {
396 Typ::U32 => Some(Value::U32($v as u32)),
397 Typ::V32 => Some(Value::V32($v as u32)),
398 Typ::I32 => Some(Value::I32($v as i32)),
399 Typ::Z32 => Some(Value::Z32($v as i32)),
400 Typ::U64 => Some(Value::U64($v as u64)),
401 Typ::V64 => Some(Value::V64($v as u64)),
402 Typ::I64 => Some(Value::I64($v as i64)),
403 Typ::Z64 => Some(Value::Z64($v as i64)),
404 Typ::F32 => Some(Value::F32($v as f32)),
405 Typ::F64 => Some(Value::F64($v as f64)),
406 Typ::Decimal => match Decimal::try_from($v) {
407 Ok(d) => Some(Value::Decimal(d)),
408 Err(_) => None,
409 },
410 Typ::DateTime => {
411 Some(Value::DateTime(DateTime::from_timestamp($v as i64, 0)?))
412 }
413 Typ::Duration => {
414 Some(Value::Duration(Duration::from_secs($v as u64)))
415 }
416 Typ::Bool => Some(if $v as i64 > 0 {
417 Value::Bool(true)
418 } else {
419 Value::Bool(false)
420 }),
421 Typ::String => {
422 Some(Value::String(format_compact!("{}", self).as_str().into()))
423 }
424 Typ::Bytes => None,
425 Typ::Error => None,
426 Typ::Array => Some(Value::Array([self.clone()].into())),
427 Typ::Null => Some(Value::Null),
428 }
429 };
430 }
431 match self {
432 Value::String(s) => match typ {
433 Typ::String => Some(Value::String(s)),
434 Typ::Error => Some(Value::Error(s)),
435 Typ::Array => Some(Value::Array([Value::String(s)].into())),
436 _ => s.parse::<Value>().ok().and_then(|v| v.cast(typ)),
437 },
438 v if typ == Typ::String => {
439 Some(Value::String(format_compact!("{}", v).as_str().into()))
440 }
441 Value::Array(elts) if typ != Typ::Array => {
442 elts.first().and_then(|v| v.clone().cast(typ))
443 }
444 v @ Value::Array(_) => Some(v),
445 Value::U32(v) | Value::V32(v) => cast_number!(v, typ),
446 Value::I32(v) | Value::Z32(v) => cast_number!(v, typ),
447 Value::U64(v) | Value::V64(v) => cast_number!(v, typ),
448 Value::I64(v) | Value::Z64(v) => cast_number!(v, typ),
449 Value::F32(v) => cast_number!(v, typ),
450 Value::F64(v) => cast_number!(v, typ),
451 Value::Decimal(v) => match typ {
452 Typ::Decimal => Some(Value::Decimal(v)),
453 Typ::U32 => v.try_into().ok().map(Value::U32),
454 Typ::V32 => v.try_into().ok().map(Value::V32),
455 Typ::I32 => v.try_into().ok().map(Value::I32),
456 Typ::Z32 => v.try_into().ok().map(Value::Z32),
457 Typ::U64 => v.try_into().ok().map(Value::U64),
458 Typ::V64 => v.try_into().ok().map(Value::V64),
459 Typ::I64 => v.try_into().ok().map(Value::I64),
460 Typ::Z64 => v.try_into().ok().map(Value::Z64),
461 Typ::F32 => v.try_into().ok().map(Value::F32),
462 Typ::F64 => v.try_into().ok().map(Value::F64),
463 Typ::String => {
464 Some(Value::String(format_compact!("{}", v).as_str().into()))
465 }
466 Typ::Bool
467 | Typ::Array
468 | Typ::Bytes
469 | Typ::DateTime
470 | Typ::Duration
471 | Typ::Null
472 | Typ::Error => None,
473 },
474 Value::DateTime(v) => match typ {
475 Typ::U32 | Typ::V32 => {
476 let ts = v.timestamp();
477 if ts < 0 && ts > u32::MAX as i64 {
478 None
479 } else {
480 if typ == Typ::U32 {
481 Some(Value::U32(ts as u32))
482 } else {
483 Some(Value::V32(ts as u32))
484 }
485 }
486 }
487 Typ::I32 | Typ::Z32 => {
488 let ts = v.timestamp();
489 if ts < i32::MIN as i64 || ts > i32::MAX as i64 {
490 None
491 } else {
492 if typ == Typ::I32 {
493 Some(Value::I32(ts as i32))
494 } else {
495 Some(Value::Z32(ts as i32))
496 }
497 }
498 }
499 Typ::U64 | Typ::V64 => {
500 let ts = v.timestamp();
501 if ts < 0 {
502 None
503 } else {
504 if typ == Typ::U64 {
505 Some(Value::U64(ts as u64))
506 } else {
507 Some(Value::V64(ts as u64))
508 }
509 }
510 }
511 Typ::I64 => Some(Value::I64(v.timestamp())),
512 Typ::Z64 => Some(Value::Z64(v.timestamp())),
513 Typ::F32 | Typ::F64 => {
514 let dur = v.timestamp() as f64;
515 let dur = dur
516 + (v.timestamp_nanos_opt()
517 .expect("cannot represent as timestamp with ns precision")
518 / 1_000_000_000) as f64;
519 if typ == Typ::F32 {
520 Some(Value::F32(dur as f32))
521 } else {
522 Some(Value::F64(dur))
523 }
524 }
525 Typ::DateTime => Some(Value::DateTime(v)),
526 Typ::Decimal => None,
527 Typ::Duration => None,
528 Typ::Bool => None,
529 Typ::Bytes => None,
530 Typ::Error => None,
531 Typ::Array => Some(Value::Array([self].into())),
532 Typ::Null => Some(Value::Null),
533 Typ::String => unreachable!(),
534 },
535 Value::Duration(d) => match typ {
536 Typ::U32 => Some(Value::U32(d.as_secs() as u32)),
537 Typ::V32 => Some(Value::V32(d.as_secs() as u32)),
538 Typ::I32 => Some(Value::I32(d.as_secs() as i32)),
539 Typ::Z32 => Some(Value::Z32(d.as_secs() as i32)),
540 Typ::U64 => Some(Value::U64(d.as_secs() as u64)),
541 Typ::V64 => Some(Value::V64(d.as_secs() as u64)),
542 Typ::I64 => Some(Value::I64(d.as_secs() as i64)),
543 Typ::Z64 => Some(Value::Z64(d.as_secs() as i64)),
544 Typ::F32 => Some(Value::F32(d.as_secs_f32())),
545 Typ::F64 => Some(Value::F64(d.as_secs_f64())),
546 Typ::Decimal => None,
547 Typ::DateTime => None,
548 Typ::Duration => Some(Value::Duration(d)),
549 Typ::Bool => None,
550 Typ::Bytes => None,
551 Typ::Error => None,
552 Typ::Array => Some(Value::Array([self].into())),
553 Typ::Null => Some(Value::Null),
554 Typ::String => unreachable!(),
555 },
556 Value::Bool(b) => match typ {
557 Typ::U32 => Some(Value::U32(b as u32)),
558 Typ::V32 => Some(Value::V32(b as u32)),
559 Typ::I32 => Some(Value::I32(b as i32)),
560 Typ::Z32 => Some(Value::Z32(b as i32)),
561 Typ::U64 => Some(Value::U64(b as u64)),
562 Typ::V64 => Some(Value::V64(b as u64)),
563 Typ::I64 => Some(Value::I64(b as i64)),
564 Typ::Z64 => Some(Value::Z64(b as i64)),
565 Typ::F32 => Some(Value::F32(b as u32 as f32)),
566 Typ::F64 => Some(Value::F64(b as u64 as f64)),
567 Typ::Decimal => None,
568 Typ::DateTime => None,
569 Typ::Duration => None,
570 Typ::Bool => Some(self),
571 Typ::Bytes => None,
572 Typ::Error => None,
573 Typ::Array => Some(Value::Array([self].into())),
574 Typ::Null => Some(Value::Null),
575 Typ::String => unreachable!(),
576 },
577 Value::Bytes(_) if typ == Typ::Bytes => Some(self),
578 Value::Bytes(_) => None,
579 Value::Error(_) => Value::Bool(false).cast(typ),
580 Value::Null if typ == Typ::Null => Some(self),
581 Value::Null => None,
582 }
583 }
584
585 pub fn cast_to<T: FromValue + Sized>(self) -> Result<T> {
587 <T as FromValue>::from_value(self)
588 }
589
590 pub fn get_as<T: FromValue + Sized>(self) -> Option<T> {
591 <T as FromValue>::get(self)
592 }
593
594 pub fn err<T: std::error::Error>(e: T) -> Value {
595 use std::fmt::Write;
596 let mut tmp = CompactString::new("");
597 write!(tmp, "{e}").unwrap();
598 Value::Error(tmp.as_str().into())
599 }
600
601 pub fn number(&self) -> bool {
604 match self {
605 Value::U32(_)
606 | Value::V32(_)
607 | Value::I32(_)
608 | Value::Z32(_)
609 | Value::U64(_)
610 | Value::V64(_)
611 | Value::I64(_)
612 | Value::Z64(_)
613 | Value::F32(_)
614 | Value::F64(_)
615 | Value::Decimal(_) => true,
616 Value::DateTime(_)
617 | Value::Duration(_)
618 | Value::String(_)
619 | Value::Bytes(_)
620 | Value::Bool(_)
621 | Value::Null
622 | Value::Error(_)
623 | Value::Array(_) => false,
624 }
625 }
626
627 pub fn flatten(self) -> impl Iterator<Item = Value> {
631 use utils::Either;
632 match self {
633 Value::Array(elts) => {
634 let mut stack: SmallVec<[(ValArray, usize); 8]> = SmallVec::new();
635 stack.push((elts, 0));
636 Either::Left(iter::from_fn(move || loop {
637 match stack.last_mut() {
638 None => break None,
639 Some((elts, pos)) => {
640 if *pos >= elts.len() {
641 stack.pop();
642 } else {
643 match &elts[*pos] {
644 Value::Array(elts) => {
645 *pos += 1;
646 let elts = elts.clone();
647 stack.push((elts, 0));
648 }
649 val => {
650 *pos += 1;
651 break Some(val.clone());
652 }
653 }
654 }
655 }
656 }
657 }))
658 }
659 val => Either::Right(iter::once(val)),
660 }
661 }
662}