1use super::{DataType, Field};
2use num_traits::NumCast;
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5use std::{collections::HashMap, fmt::Debug, hash::Hash, time::Duration};
6
7#[derive(Clone, Default, Debug)]
8pub enum AnyValue<'a> {
9 #[default]
10 Null,
11
12 Bool(bool),
13
14 UInt8(u8),
15 UInt16(u16),
16 UInt32(u32),
17 UInt64(u64),
18 UInt128(u128),
19
20 Int8(i8),
21 Int16(i16),
22 Int32(i32),
23 Int64(i64),
24 Int128(i128),
25
26 Float32(f32),
27 Float64(f64),
28
29 Duration(Duration),
30
31 Char(char),
32 Str(&'a str),
33 StrOwned(String),
34
35 Slice(&'a [AnyValue<'a>]),
36 Vector(Vec<AnyValue<'a>>),
37
38 Struct(Vec<(Field, AnyValue<'a>)>),
39}
40
41impl<'a> AnyValue<'a> {
42 #[inline]
43 pub fn is_null(&self) -> bool {
44 matches!(self, Self::Null)
45 }
46
47 #[inline]
48 pub fn is_boolean(&self) -> bool {
49 matches!(self, Self::Bool(_))
50 }
51
52 #[inline]
53 pub fn is_float(&self) -> bool {
54 matches!(self, Self::Float32(_) | Self::Float64(_))
55 }
56
57 #[inline]
58 pub fn is_int(&self) -> bool {
59 matches!(
60 self,
61 Self::Int8(_)
62 | Self::Int16(_)
63 | Self::Int32(_)
64 | Self::Int64(_)
65 | Self::Int128(_)
66 | Self::UInt8(_)
67 | Self::UInt16(_)
68 | Self::UInt32(_)
69 | Self::UInt64(_)
70 | Self::UInt128(_)
71 )
72 }
73
74 #[inline]
75 pub fn is_string(&self) -> bool {
76 matches!(self, Self::Str(_) | Self::StrOwned(_))
77 }
78
79 #[inline]
80 pub fn is_nested(&self) -> bool {
81 matches!(self, Self::Struct(_) | Self::Vector(_) | Self::Slice(_))
82 }
83
84 #[inline]
85 pub fn len(&self) -> Option<usize> {
86 match self {
87 Self::Slice(vals) => Some(vals.len()),
88 Self::Vector(vals) => Some(vals.len()),
89 Self::Struct(vals) => Some(vals.len()),
90 _ => None,
91 }
92 }
93
94 #[inline]
95 pub fn is_numeric(&self) -> bool {
96 matches!(
97 self,
98 Self::UInt8(_)
99 | Self::UInt16(_)
100 | Self::UInt32(_)
101 | Self::UInt64(_)
102 | Self::Int8(_)
103 | Self::Int16(_)
104 | Self::Int32(_)
105 | Self::Int64(_)
106 | Self::Int128(_)
107 | Self::Float32(_)
108 | Self::Float64(_)
109 )
110 }
111
112 #[inline]
113 pub fn type_name(&self) -> &'static str {
114 match self {
115 Self::Null => "null",
116 Self::Bool(_) => "bool",
117 Self::UInt8(_) => "u8",
118 Self::UInt16(_) => "u16",
119 Self::UInt32(_) => "u32",
120 Self::UInt64(_) => "u64",
121 Self::UInt128(_) => "u128",
122 Self::Int8(_) => "i8",
123 Self::Int16(_) => "i16",
124 Self::Int32(_) => "i32",
125 Self::Int64(_) => "i64",
126 Self::Int128(_) => "i128",
127 Self::Float32(_) => "f32",
128 Self::Float64(_) => "f64",
129 Self::Char(_) => "char",
130 Self::Str(_) => "string",
131 Self::StrOwned(_) => "string",
132 Self::Slice(_) => "list",
133 Self::Vector(_) => "list",
134 Self::Struct(_) => "struct",
135 Self::Duration(_) => "duration",
136 }
137 }
138
139 #[inline]
140 pub fn dtype(&self) -> DataType {
141 match self {
142 Self::Null => DataType::Null,
143
144 Self::Bool(_) => DataType::Boolean,
145
146 Self::UInt8(_) => DataType::UInt8,
147 Self::UInt16(_) => DataType::UInt16,
148 Self::UInt32(_) => DataType::UInt32,
149 Self::UInt64(_) => DataType::UInt64,
150 Self::UInt128(_) => DataType::UInt128,
151
152 Self::Int8(_) => DataType::Int8,
153 Self::Int16(_) => DataType::Int16,
154 Self::Int32(_) => DataType::Int32,
155 Self::Int64(_) => DataType::Int64,
156 Self::Int128(_) => DataType::Int128,
157
158 Self::Float32(_) => DataType::Float32,
159 Self::Float64(_) => DataType::Float64,
160
161 Self::Duration(_) => DataType::Duration,
162
163 Self::Char(_) => DataType::Char,
164 Self::Str(_) => DataType::String,
165 Self::StrOwned(_) => DataType::String,
166
167 Self::Slice(vals) => DataType::List(
168 vals.iter()
169 .map(|v| v.dtype())
170 .next()
171 .unwrap_or(DataType::Null)
172 .into(),
173 ),
174 Self::Vector(vals) => DataType::List(
175 vals.iter()
176 .map(|v| v.dtype())
177 .next()
178 .unwrap_or(DataType::Null)
179 .into(),
180 ),
181
182 Self::Struct(vals) => DataType::Struct(vals.iter().map(|(f, _)| f.clone()).collect()),
183 }
184 }
185
186 pub fn cast(self, to: &DataType) -> Option<AnyValue<'a>> {
187 use DataType as D;
188
189 if self.dtype() == *to {
190 return Some(self);
191 }
192
193 match (self, to) {
194 (_, D::Null) => Some(AnyValue::Null),
195 (AnyValue::Bool(v), D::Boolean) => Some(AnyValue::Bool(v)),
196 (v, D::UInt8) => v.extract().map(AnyValue::UInt8),
197 (v, D::UInt16) => v.extract().map(AnyValue::UInt16),
198 (v, D::UInt32) => v.extract().map(AnyValue::UInt32),
199 (v, D::UInt64) => v.extract().map(AnyValue::UInt64),
200 (v, D::UInt128) => v.extract().map(AnyValue::UInt128),
201 (v, D::Int8) => v.extract().map(AnyValue::Int8),
202 (v, D::Int16) => v.extract().map(AnyValue::Int16),
203 (v, D::Int32) => v.extract().map(AnyValue::Int32),
204 (v, D::Int64) => v.extract().map(AnyValue::Int64),
205 (v, D::Int128) => v.extract().map(AnyValue::Int128),
206 (v, D::Float32) => v.extract().map(AnyValue::Float32),
207 (v, D::Float64) => v.extract().map(AnyValue::Float64),
208 (v, D::Duration) => v
209 .extract()
210 .map(|ms| AnyValue::Duration(Duration::from_millis(ms))),
211 (v, D::Char) => v.extract::<u8>().map(|b| AnyValue::Char(b as char)),
212 (v @ AnyValue::Str(_), D::String) | (v @ AnyValue::StrOwned(_), D::String) => {
213 Some(v.into_static())
214 }
215 _ => None,
216 }
217 }
218
219 #[inline]
222 pub fn into_static(self) -> AnyValue<'static> {
223 use AnyValue::*;
224 match self {
225 Null => Null,
226 Int8(v) => Int8(v),
227 Int16(v) => Int16(v),
228 Int32(v) => Int32(v),
229 Int64(v) => Int64(v),
230 Int128(v) => Int128(v),
231 UInt8(v) => UInt8(v),
232 UInt16(v) => UInt16(v),
233 UInt32(v) => UInt32(v),
234 UInt64(v) => UInt64(v),
235 UInt128(v) => UInt128(v),
236 Bool(v) => Bool(v),
237 Float32(v) => Float32(v),
238 Float64(v) => Float64(v),
239 Duration(d) => Duration(d),
240 Char(v) => Char(v),
241 Str(v) => StrOwned(v.to_string()),
242 StrOwned(v) => StrOwned(v),
243 Slice(v) => Vector(v.into_iter().map(|v| v.clone().into_static()).collect()),
244 Vector(v) => Vector(v.into_iter().map(AnyValue::into_static).collect()),
245 Struct(v) => Struct(
246 v.into_iter()
247 .map(|(field, val)| (field, val.into_static()))
248 .collect(),
249 ),
250 }
251 }
252
253 pub fn extract<T: NumCast>(&self) -> Option<T> {
254 match self {
255 AnyValue::UInt8(v) => NumCast::from(*v),
256 AnyValue::UInt16(v) => NumCast::from(*v),
257 AnyValue::UInt32(v) => NumCast::from(*v),
258 AnyValue::UInt64(v) => NumCast::from(*v),
259 AnyValue::UInt128(v) => NumCast::from(*v),
260 AnyValue::Int8(v) => NumCast::from(*v),
261 AnyValue::Int16(v) => NumCast::from(*v),
262 AnyValue::Int32(v) => NumCast::from(*v),
263 AnyValue::Int64(v) => NumCast::from(*v),
264 AnyValue::Int128(v) => NumCast::from(*v),
265 AnyValue::Float32(v) => NumCast::from(*v),
266 AnyValue::Float64(v) => NumCast::from(*v),
267 AnyValue::Duration(d) => NumCast::from(d.as_millis()),
268 _ => None,
269 }
270 }
271
272 pub fn into_string(self) -> Option<String> {
273 match self {
274 AnyValue::Str(s) => Some(s.to_string()),
275 AnyValue::StrOwned(s) => Some(s),
276 _ => None,
277 }
278 }
279
280 pub fn as_str(&self) -> Option<&str> {
281 match self {
282 AnyValue::Str(s) => Some(*s),
283 AnyValue::StrOwned(s) => Some(s.as_str()),
284 _ => None,
285 }
286 }
287}
288
289impl<'a> AnyValue<'a> {
290 pub fn get_index(&self, index: usize) -> Option<AnyValue<'a>> {
291 match self {
292 AnyValue::Vector(values) => values.get(index).cloned(),
293 AnyValue::Slice(values) => values.get(index).cloned(),
294 _ => None,
295 }
296 }
297
298 pub fn get_key(&self, key: &AnyValue<'a>) -> Option<AnyValue<'a>> {
299 match self {
300 AnyValue::Struct(fields) => {
301 let key_str = match key {
302 AnyValue::Str(s) => *s,
303 AnyValue::StrOwned(s) => s.as_str(),
304 _ => return None,
305 };
306
307 fields
308 .iter()
309 .find(|(field, _)| field.name() == key_str)
310 .map(|(_, value)| value.clone())
311 }
312 _ => None,
313 }
314 }
315
316 pub fn get_field(&self, field: &Field) -> Option<AnyValue<'a>> {
317 match self {
318 AnyValue::Struct(fields) => fields
319 .iter()
320 .find(|(f, _)| f.name() == field.name())
321 .map(|(_, value)| value.clone()),
322 _ => None,
323 }
324 }
325}
326
327impl<'a> PartialEq for AnyValue<'a> {
328 #[inline]
329 fn eq(&self, other: &Self) -> bool {
330 use AnyValue::*;
331 match (self, other) {
332 (Null, Null) => true,
333 (Bool(a), Bool(b)) => a == b,
334 (UInt8(a), UInt8(b)) => a == b,
335 (UInt16(a), UInt16(b)) => a == b,
336 (UInt32(a), UInt32(b)) => a == b,
337 (UInt64(a), UInt64(b)) => a == b,
338 (Int8(a), Int8(b)) => a == b,
339 (Int16(a), Int16(b)) => a == b,
340 (Int32(a), Int32(b)) => a == b,
341 (Int64(a), Int64(b)) => a == b,
342 (Int128(a), Int128(b)) => a == b,
343 (Float32(a), Float32(b)) => a == b,
344 (Float64(a), Float64(b)) => a == b,
345 (Duration(a), Duration(b)) => a == b,
346 (Char(a), Char(b)) => a == b,
347 (Str(a), Str(b)) => a == b,
348 (Str(a), StrOwned(b)) => *a == b.as_str(),
349 (StrOwned(a), Str(b)) => a.as_str() == *b,
350 (StrOwned(a), StrOwned(b)) => a == b,
351 (Vector(a), Vector(b)) if a.len() == b.len() => {
352 a.iter().zip(b.iter()).all(|(x, y)| x == y)
353 }
354 (Struct(a), Struct(b))
355 if a.len() == b.len()
356 && a.iter()
357 .map(|(f, _)| f.name())
358 .eq(b.iter().map(|(f, _)| f.name())) =>
359 {
360 a.iter()
361 .zip(b.iter())
362 .all(|((f1, v1), (f2, v2))| f1.name() == f2.name() && v1 == v2)
363 }
364 _ => false,
365 }
366 }
367}
368
369impl<'a> Eq for AnyValue<'a> {}
370
371impl<'a> Hash for AnyValue<'a> {
372 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
373 use AnyValue::*;
374 match self {
375 Null => 0.hash(state),
376 Bool(v) => v.hash(state),
377
378 Int8(v) => v.hash(state),
379 Int16(v) => v.hash(state),
380 Int32(v) => v.hash(state),
381 Int64(v) => v.hash(state),
382 Int128(v) => v.hash(state),
383
384 UInt8(v) => v.hash(state),
385 UInt16(v) => v.hash(state),
386 UInt32(v) => v.hash(state),
387 UInt64(v) => v.hash(state),
388 UInt128(v) => v.hash(state),
389
390 Float32(v) => v.to_ne_bytes().hash(state),
391 Float64(v) => v.to_ne_bytes().hash(state),
392
393 Duration(v) => v.hash(state),
394
395 Char(v) => v.hash(state),
396 Str(v) => v.hash(state),
397 StrOwned(v) => v.hash(state),
398
399 Vector(v) => v.hash(state),
400 Slice(v) => v.hash(state),
401
402 Struct(v) => v.iter().for_each(|(k, v)| {
403 k.hash(state);
404 v.hash(state);
405 }),
406 }
407 }
408}
409
410impl<'a> From<&'a str> for AnyValue<'a> {
411 fn from(s: &'a str) -> Self {
412 AnyValue::Str(s)
413 }
414}
415
416impl<'a> From<String> for AnyValue<'a> {
417 fn from(s: String) -> Self {
418 AnyValue::StrOwned(s)
419 }
420}
421
422impl From<f32> for AnyValue<'_> {
423 fn from(f: f32) -> Self {
424 AnyValue::Float32(f)
425 }
426}
427
428impl From<f64> for AnyValue<'_> {
429 fn from(f: f64) -> Self {
430 AnyValue::Float64(f)
431 }
432}
433
434impl From<bool> for AnyValue<'_> {
435 fn from(b: bool) -> Self {
436 AnyValue::Bool(b)
437 }
438}
439
440impl From<char> for AnyValue<'_> {
441 fn from(c: char) -> Self {
442 AnyValue::Char(c)
443 }
444}
445
446impl<'a> From<Duration> for AnyValue<'a> {
447 fn from(d: Duration) -> Self {
448 AnyValue::Duration(d)
449 }
450}
451
452impl<'a> From<Vec<AnyValue<'a>>> for AnyValue<'a> {
453 fn from(v: Vec<AnyValue<'a>>) -> Self {
454 AnyValue::Vector(v)
455 }
456}
457
458impl From<i32> for AnyValue<'_> {
459 fn from(i: i32) -> Self {
460 AnyValue::Int32(i)
461 }
462}
463
464impl<T, K> From<HashMap<T, K>> for AnyValue<'_>
465where
466 T: Into<String> + Clone,
467 K: Into<AnyValue<'static>> + Clone,
468{
469 fn from(map: HashMap<T, K>) -> Self {
470 AnyValue::Struct(
471 map.into_iter()
472 .map(|(k, v)| {
473 let cloned_value = v.clone().into();
474 (
475 Field::new(k.into().into(), cloned_value.dtype()),
476 cloned_value,
477 )
478 })
479 .collect(),
480 )
481 }
482}
483
484#[inline]
485pub(crate) fn apply_zipped_slice(
486 one: &[AnyValue<'_>],
487 two: &[AnyValue<'_>],
488 f: impl Fn(&AnyValue<'_>, &AnyValue<'_>) -> Option<AnyValue<'static>>,
489) -> Option<AnyValue<'static>> {
490 if one.len() != two.len() {
491 return None;
492 }
493
494 Some(AnyValue::Vector(
495 one.iter()
496 .zip(two.iter())
497 .map(|pair| match f(pair.0, pair.1) {
498 Some(v) => v,
499 None => AnyValue::Null,
500 })
501 .collect::<Vec<AnyValue>>(),
502 ))
503}
504
505#[inline]
506pub(crate) fn apply_zipped_struct_slice(
507 one: &[(Field, AnyValue<'_>)],
508 two: &[(Field, AnyValue<'_>)],
509 f: impl Fn(&AnyValue<'_>, &AnyValue<'_>) -> Option<AnyValue<'static>>,
510) -> Option<AnyValue<'static>> {
511 if one.len() != two.len() {
512 return None;
513 }
514
515 if !one
516 .iter()
517 .map(|(f, _)| f.name())
518 .eq(two.iter().map(|(f, _)| f.name()))
519 {
520 return None;
521 }
522
523 let mut out = Vec::with_capacity(one.len());
524 for ((fa, va), (_, vb)) in one.iter().zip(two.iter()) {
525 if va.is_null() || vb.is_null() {
526 out.push((fa.clone(), AnyValue::Null));
527 continue;
528 }
529
530 out.push((fa.clone(), f(va, vb)?));
531 }
532
533 Some(AnyValue::Struct(out))
534}
535
536#[inline]
537pub(crate) fn dedup_slice<'a>(value: &[AnyValue<'a>]) -> AnyValue<'a> {
538 let mut sorted_buff = Vec::with_capacity(value.len());
539 for v in value.iter() {
540 match sorted_buff.binary_search(v) {
541 Ok(_) => {}
542 Err(pos) => sorted_buff.insert(pos, v.clone()),
543 }
544 }
545
546 AnyValue::Vector(sorted_buff)
547}
548
549#[cfg(feature = "serde")]
550impl<'a> Serialize for AnyValue<'a> {
551 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
552 where
553 S: serde::Serializer,
554 {
555 use AnyValue::*;
556 match self {
557 Null => serializer.serialize_unit_variant("AnyValue", 0, "Null"),
558 Bool(v) => serializer.serialize_bool(*v),
559 UInt8(v) => serializer.serialize_u8(*v),
560 UInt16(v) => serializer.serialize_u16(*v),
561 UInt32(v) => serializer.serialize_u32(*v),
562 UInt64(v) => serializer.serialize_u64(*v),
563 UInt128(v) => serializer.serialize_u128(*v),
564 Int8(v) => serializer.serialize_i8(*v),
565 Int16(v) => serializer.serialize_i16(*v),
566 Int32(v) => serializer.serialize_i32(*v),
567 Int64(v) => serializer.serialize_i64(*v),
568 Int128(v) => serializer.serialize_i128(*v),
569 Float32(v) => serializer.serialize_f32(*v),
570 Float64(v) => serializer.serialize_f64(*v),
571 Duration(v) => serializer.serialize_u64(v.as_millis() as u64),
572 Char(v) => serializer.serialize_char(*v),
573 Str(v) => serializer.serialize_str(v),
574 StrOwned(v) => serializer.serialize_str(v),
575 Slice(vals) => vals.serialize(serializer),
576 Vector(vals) => vals.serialize(serializer),
577 Struct(vals) => vals.serialize(serializer),
578 }
579 }
580}
581
582#[cfg(feature = "serde")]
583impl<'a, 'de> Deserialize<'de> for AnyValue<'a> {
584 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
585 where
586 D: serde::Deserializer<'de>,
587 {
588 use AnyValue::*;
589 #[derive(Deserialize)]
590 #[serde(tag = "type", content = "value")]
591 enum AnyValueDef {
592 Null,
593 Bool(bool),
594 UInt8(u8),
595 UInt16(u16),
596 UInt32(u32),
597 UInt64(u64),
598 UInt128(u128),
599 Int8(i8),
600 Int16(i16),
601 Int32(i32),
602 Int64(i64),
603 Int128(i128),
604 Float32(f32),
605 Float64(f64),
606 Duration(u64),
607 Char(char),
608 Str(String),
609 StrOwned(String),
610 Slice(Vec<AnyValueDef>),
611 Vector(Vec<AnyValueDef>),
612 Struct(Vec<(Field, AnyValueDef)>),
613 }
614
615 impl From<AnyValueDef> for AnyValue<'_> {
616 fn from(def: AnyValueDef) -> Self {
617 match def {
618 AnyValueDef::Null => Null,
619 AnyValueDef::Bool(v) => Bool(v),
620 AnyValueDef::UInt8(v) => UInt8(v),
621 AnyValueDef::UInt16(v) => UInt16(v),
622 AnyValueDef::UInt32(v) => UInt32(v),
623 AnyValueDef::UInt64(v) => UInt64(v),
624 AnyValueDef::UInt128(v) => UInt128(v),
625 AnyValueDef::Int8(v) => Int8(v),
626 AnyValueDef::Int16(v) => Int16(v),
627 AnyValueDef::Int32(v) => Int32(v),
628 AnyValueDef::Int64(v) => Int64(v),
629 AnyValueDef::Int128(v) => Int128(v),
630 AnyValueDef::Float32(v) => Float32(v),
631 AnyValueDef::Float64(v) => Float64(v),
632 AnyValueDef::Duration(ms) => Duration(std::time::Duration::from_millis(ms)),
633 AnyValueDef::Char(v) => Char(v),
634 AnyValueDef::Str(s) | AnyValueDef::StrOwned(s) => StrOwned(s),
635 AnyValueDef::Slice(vals) => {
636 Vector(vals.into_iter().map(AnyValue::from).collect())
637 }
638 AnyValueDef::Vector(vals) => {
639 Vector(vals.into_iter().map(AnyValue::from).collect())
640 }
641 AnyValueDef::Struct(vals) => {
642 Struct(vals.into_iter().map(|(f, v)| (f, v.into())).collect())
643 }
644 }
645 }
646 }
647
648 let def = AnyValueDef::deserialize(deserializer)?;
649 Ok(match def {
650 AnyValueDef::Null => Null,
651 AnyValueDef::Bool(v) => Bool(v),
652 AnyValueDef::UInt8(v) => UInt8(v),
653 AnyValueDef::UInt16(v) => UInt16(v),
654 AnyValueDef::UInt32(v) => UInt32(v),
655 AnyValueDef::UInt64(v) => UInt64(v),
656 AnyValueDef::UInt128(v) => UInt128(v),
657 AnyValueDef::Int8(v) => Int8(v),
658 AnyValueDef::Int16(v) => Int16(v),
659 AnyValueDef::Int32(v) => Int32(v),
660 AnyValueDef::Int64(v) => Int64(v),
661 AnyValueDef::Int128(v) => Int128(v),
662 AnyValueDef::Float32(v) => Float32(v),
663 AnyValueDef::Float64(v) => Float64(v),
664 AnyValueDef::Char(v) => Char(v),
665 AnyValueDef::Str(v) => StrOwned(v), AnyValueDef::StrOwned(v) => StrOwned(v), AnyValueDef::Duration(ms) => Duration(std::time::Duration::from_millis(ms)),
668 AnyValueDef::Slice(vals) => Vector(vals.into_iter().map(|v| v.into()).collect()),
669 AnyValueDef::Vector(vals) => Vector(vals.into_iter().map(|v| v.into()).collect()),
670 AnyValueDef::Struct(vals) => {
671 Struct(vals.into_iter().map(|(f, v)| (f, v.into())).collect())
672 }
673 })
674 }
675}
676
677#[cfg(test)]
678mod tests {
679 use super::{DataType, Field};
680
681 use super::AnyValue;
682
683 #[test]
684 fn test_anyvalue_equality() {
685 let v1 = AnyValue::Struct(vec![
686 (
687 Field::from(("field1", DataType::Int32)),
688 AnyValue::Int32(42),
689 ),
690 (
691 Field::from(("field2", DataType::String)),
692 AnyValue::Str("hello"),
693 ),
694 ]);
695
696 let v2 = AnyValue::Struct(vec![
697 (
698 Field::from(("field1", DataType::Int32)),
699 AnyValue::Int32(42),
700 ),
701 (
702 Field::from(("field2", DataType::String)),
703 AnyValue::Str("hello"),
704 ),
705 ]);
706
707 let v3 = AnyValue::Struct(vec![
708 (
709 Field::from(("field1", DataType::Int32)),
710 AnyValue::Int32(43),
711 ),
712 (
713 Field::from(("field2", DataType::String)),
714 AnyValue::Str("hello"),
715 ),
716 ]);
717
718 assert_eq!(v1, v2);
719 assert_ne!(v1, v3);
720 }
721
722 #[test]
723 fn test_anyvalue_type_name() {
724 let v = AnyValue::Float64(3.14);
725 assert_eq!(v.type_name(), "f64");
726 }
727}