1use crate::{ExclusiveRange, FnPtr, ImmutableString, InclusiveRange, INT};
4#[cfg(feature = "no_std")]
5use std::prelude::v1::*;
6use std::{
7 any::{type_name, Any, TypeId},
8 fmt,
9 hash::{Hash, Hasher},
10 mem,
11 ops::{Deref, DerefMut},
12 str::FromStr,
13};
14
15pub use super::Variant;
16
17#[cfg(not(feature = "no_time"))]
18#[cfg(any(not(target_family = "wasm"), not(target_os = "unknown")))]
19pub use std::time::Instant;
20
21#[cfg(not(feature = "no_time"))]
22#[cfg(all(target_family = "wasm", target_os = "unknown"))]
23pub use instant::Instant;
24
25#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
28#[non_exhaustive]
29pub enum AccessMode {
30 ReadWrite,
32 ReadOnly,
34}
35
36#[cfg(target_pointer_width = "64")]
38pub type Tag = i32;
39
40#[cfg(target_pointer_width = "32")]
42pub type Tag = i16;
43
44const DEFAULT_TAG_VALUE: Tag = 0;
46
47#[must_use]
49pub struct Dynamic(pub(crate) Union);
50
51#[must_use]
55pub enum Union {
56 Unit((), Tag, AccessMode),
58 Bool(bool, Tag, AccessMode),
60 Str(ImmutableString, Tag, AccessMode),
62 Char(char, Tag, AccessMode),
64 Int(INT, Tag, AccessMode),
66 #[cfg(not(feature = "no_float"))]
68 Float(super::FloatWrapper<crate::FLOAT>, Tag, AccessMode),
69 #[cfg(feature = "decimal")]
72 Decimal(Box<rust_decimal::Decimal>, Tag, AccessMode),
73 #[cfg(not(feature = "no_index"))]
75 Array(Box<crate::Array>, Tag, AccessMode),
76 #[cfg(not(feature = "no_index"))]
78 Blob(Box<crate::Blob>, Tag, AccessMode),
79 #[cfg(not(feature = "no_object"))]
81 Map(Box<crate::Map>, Tag, AccessMode),
82 FnPtr(Box<FnPtr>, Tag, AccessMode),
84 #[cfg(not(feature = "no_time"))]
86 TimeStamp(Box<Instant>, Tag, AccessMode),
87
88 Variant(Box<Box<dyn Variant>>, Tag, AccessMode),
93
94 #[cfg(not(feature = "no_closure"))]
96 Shared(crate::Shared<crate::Locked<Dynamic>>, Tag, AccessMode),
97}
98
99#[derive(Debug)]
105#[must_use]
106pub struct DynamicReadLock<'d, T: Clone>(DynamicReadLockInner<'d, T>);
107
108#[derive(Debug)]
110#[must_use]
111enum DynamicReadLockInner<'d, T: Clone> {
112 Reference(&'d T),
114
115 #[cfg(not(feature = "no_closure"))]
117 Guard(crate::func::native::LockGuard<'d, Dynamic>),
118}
119
120impl<'d, T: Any + Clone> Deref for DynamicReadLock<'d, T> {
121 type Target = T;
122
123 #[inline]
124 fn deref(&self) -> &Self::Target {
125 match self.0 {
126 DynamicReadLockInner::Reference(reference) => reference,
127 #[cfg(not(feature = "no_closure"))]
128 DynamicReadLockInner::Guard(ref guard) => guard.downcast_ref().unwrap(),
129 }
130 }
131}
132
133#[derive(Debug)]
139#[must_use]
140pub struct DynamicWriteLock<'d, T: Clone>(DynamicWriteLockInner<'d, T>);
141
142#[derive(Debug)]
144#[must_use]
145enum DynamicWriteLockInner<'d, T: Clone> {
146 Reference(&'d mut T),
148
149 #[cfg(not(feature = "no_closure"))]
151 Guard(crate::func::native::LockGuardMut<'d, Dynamic>),
152}
153
154impl<'d, T: Any + Clone> Deref for DynamicWriteLock<'d, T> {
155 type Target = T;
156
157 #[inline]
158 fn deref(&self) -> &Self::Target {
159 match self.0 {
160 DynamicWriteLockInner::Reference(ref reference) => reference,
161 #[cfg(not(feature = "no_closure"))]
162 DynamicWriteLockInner::Guard(ref guard) => guard.downcast_ref().unwrap(),
163 }
164 }
165}
166
167impl<'d, T: Any + Clone> DerefMut for DynamicWriteLock<'d, T> {
168 #[inline]
169 fn deref_mut(&mut self) -> &mut Self::Target {
170 match self.0 {
171 DynamicWriteLockInner::Reference(ref mut reference) => reference,
172 #[cfg(not(feature = "no_closure"))]
173 DynamicWriteLockInner::Guard(ref mut guard) => guard.downcast_mut().unwrap(),
174 }
175 }
176}
177
178impl Dynamic {
179 #[must_use]
181 pub const fn tag(&self) -> Tag {
182 match self.0 {
183 Union::Unit((), tag, _)
184 | Union::Bool(_, tag, _)
185 | Union::Str(_, tag, _)
186 | Union::Char(_, tag, _)
187 | Union::Int(_, tag, _)
188 | Union::FnPtr(_, tag, _)
189 | Union::Variant(_, tag, _) => tag,
190
191 #[cfg(not(feature = "no_float"))]
192 Union::Float(_, tag, _) => tag,
193 #[cfg(feature = "decimal")]
194 Union::Decimal(_, tag, _) => tag,
195 #[cfg(not(feature = "no_index"))]
196 Union::Array(_, tag, _) | Union::Blob(_, tag, _) => tag,
197 #[cfg(not(feature = "no_object"))]
198 Union::Map(_, tag, _) => tag,
199 #[cfg(not(feature = "no_time"))]
200 Union::TimeStamp(_, tag, _) => tag,
201 #[cfg(not(feature = "no_closure"))]
202 Union::Shared(_, tag, _) => tag,
203 }
204 }
205 pub fn set_tag(&mut self, value: Tag) -> &mut Self {
207 match self.0 {
208 Union::Unit((), ref mut tag, _)
209 | Union::Bool(_, ref mut tag, _)
210 | Union::Str(_, ref mut tag, _)
211 | Union::Char(_, ref mut tag, _)
212 | Union::Int(_, ref mut tag, _)
213 | Union::FnPtr(_, ref mut tag, _)
214 | Union::Variant(_, ref mut tag, _) => *tag = value,
215
216 #[cfg(not(feature = "no_float"))]
217 Union::Float(_, ref mut tag, _) => *tag = value,
218 #[cfg(feature = "decimal")]
219 Union::Decimal(_, ref mut tag, _) => *tag = value,
220 #[cfg(not(feature = "no_index"))]
221 Union::Array(_, ref mut tag, _) | Union::Blob(_, ref mut tag, _) => *tag = value,
222 #[cfg(not(feature = "no_object"))]
223 Union::Map(_, ref mut tag, _) => *tag = value,
224 #[cfg(not(feature = "no_time"))]
225 Union::TimeStamp(_, ref mut tag, _) => *tag = value,
226 #[cfg(not(feature = "no_closure"))]
227 Union::Shared(_, ref mut tag, _) => *tag = value,
228 }
229 self
230 }
231 #[inline(always)]
234 #[must_use]
235 pub const fn is_variant(&self) -> bool {
236 matches!(self.0, Union::Variant(..))
237 }
238 #[cfg(not(feature = "no_closure"))]
242 #[inline(always)]
243 #[must_use]
244 pub const fn is_shared(&self) -> bool {
245 matches!(self.0, Union::Shared(..))
246 }
247 #[inline]
254 #[must_use]
255 pub fn is<T: Any + Clone>(&self) -> bool {
256 #[cfg(not(feature = "no_closure"))]
257 if self.is_shared() {
258 return TypeId::of::<T>() == self.type_id();
259 }
260
261 if TypeId::of::<T>() == TypeId::of::<()>() {
262 return matches!(self.0, Union::Unit(..));
263 }
264 if TypeId::of::<T>() == TypeId::of::<bool>() {
265 return matches!(self.0, Union::Bool(..));
266 }
267 if TypeId::of::<T>() == TypeId::of::<char>() {
268 return matches!(self.0, Union::Char(..));
269 }
270 if TypeId::of::<T>() == TypeId::of::<INT>() {
271 return matches!(self.0, Union::Int(..));
272 }
273 #[cfg(not(feature = "no_float"))]
274 if TypeId::of::<T>() == TypeId::of::<crate::FLOAT>() {
275 return matches!(self.0, Union::Float(..));
276 }
277 if TypeId::of::<T>() == TypeId::of::<ImmutableString>()
278 || TypeId::of::<T>() == TypeId::of::<String>()
279 {
280 return matches!(self.0, Union::Str(..));
281 }
282 #[cfg(not(feature = "no_index"))]
283 if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
284 return matches!(self.0, Union::Array(..));
285 }
286 #[cfg(not(feature = "no_index"))]
287 if TypeId::of::<T>() == TypeId::of::<crate::Blob>() {
288 return matches!(self.0, Union::Blob(..));
289 }
290 #[cfg(not(feature = "no_object"))]
291 if TypeId::of::<T>() == TypeId::of::<crate::Map>() {
292 return matches!(self.0, Union::Map(..));
293 }
294 #[cfg(feature = "decimal")]
295 if TypeId::of::<T>() == TypeId::of::<rust_decimal::Decimal>() {
296 return matches!(self.0, Union::Decimal(..));
297 }
298 if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
299 return matches!(self.0, Union::FnPtr(..));
300 }
301 #[cfg(not(feature = "no_time"))]
302 if TypeId::of::<T>() == TypeId::of::<crate::Instant>() {
303 return matches!(self.0, Union::TimeStamp(..));
304 }
305
306 TypeId::of::<T>() == self.type_id()
307 }
308 #[must_use]
315 pub fn type_id(&self) -> TypeId {
316 match self.0 {
317 Union::Unit(..) => TypeId::of::<()>(),
318 Union::Bool(..) => TypeId::of::<bool>(),
319 Union::Str(..) => TypeId::of::<ImmutableString>(),
320 Union::Char(..) => TypeId::of::<char>(),
321 Union::Int(..) => TypeId::of::<INT>(),
322 #[cfg(not(feature = "no_float"))]
323 Union::Float(..) => TypeId::of::<crate::FLOAT>(),
324 #[cfg(feature = "decimal")]
325 Union::Decimal(..) => TypeId::of::<rust_decimal::Decimal>(),
326 #[cfg(not(feature = "no_index"))]
327 Union::Array(..) => TypeId::of::<crate::Array>(),
328 #[cfg(not(feature = "no_index"))]
329 Union::Blob(..) => TypeId::of::<crate::Blob>(),
330 #[cfg(not(feature = "no_object"))]
331 Union::Map(..) => TypeId::of::<crate::Map>(),
332 Union::FnPtr(..) => TypeId::of::<FnPtr>(),
333 #[cfg(not(feature = "no_time"))]
334 Union::TimeStamp(..) => TypeId::of::<Instant>(),
335
336 Union::Variant(ref v, ..) => (***v).type_id(),
337
338 #[cfg(not(feature = "no_closure"))]
339 Union::Shared(ref cell, ..) => (*crate::func::locked_read(cell)).type_id(),
340 }
341 }
342 #[must_use]
349 pub fn type_name(&self) -> &'static str {
350 match self.0 {
351 Union::Unit(..) => "()",
352 Union::Bool(..) => "bool",
353 Union::Str(..) => "string",
354 Union::Char(..) => "char",
355 Union::Int(..) => type_name::<INT>(),
356 #[cfg(not(feature = "no_float"))]
357 Union::Float(..) => type_name::<crate::FLOAT>(),
358 #[cfg(feature = "decimal")]
359 Union::Decimal(..) => "decimal",
360 #[cfg(not(feature = "no_index"))]
361 Union::Array(..) => "array",
362 #[cfg(not(feature = "no_index"))]
363 Union::Blob(..) => "blob",
364 #[cfg(not(feature = "no_object"))]
365 Union::Map(..) => "map",
366 Union::FnPtr(..) => "Fn",
367 #[cfg(not(feature = "no_time"))]
368 Union::TimeStamp(..) => "timestamp",
369
370 Union::Variant(ref v, ..) => (***v).type_name(),
371
372 #[cfg(not(feature = "no_closure"))]
373 Union::Shared(ref cell, ..) => (*crate::func::locked_read(cell)).type_name(),
374 }
375 }
376}
377
378#[cfg(feature = "indexmap")]
379fn hash_indexmap<H: Hasher>(m: &Box<crate::Map>, state: &mut H) {
380 let mut m = m.iter().collect::<Vec<_>>();
381 m.sort_unstable_by_key(|x| x.0);
382 for kv in m.into_iter() {
383 kv.hash(state);
384 }
385}
386
387impl Hash for Dynamic {
388 fn hash<H: Hasher>(&self, state: &mut H) {
394 mem::discriminant(&self.0).hash(state);
395
396 match self.0 {
397 Union::Unit(..) => (),
398 Union::Bool(ref b, ..) => b.hash(state),
399 Union::Str(ref s, ..) => s.hash(state),
400 Union::Char(ref c, ..) => c.hash(state),
401 Union::Int(ref i, ..) => i.hash(state),
402 #[cfg(not(feature = "no_float"))]
403 Union::Float(ref f, ..) => f.hash(state),
404 #[cfg(feature = "decimal")]
405 Union::Decimal(ref d, ..) => d.hash(state),
406 #[cfg(not(feature = "no_index"))]
407 Union::Array(ref a, ..) => a.hash(state),
408 #[cfg(not(feature = "no_index"))]
409 Union::Blob(ref a, ..) => a.hash(state),
410
411 #[cfg(not(feature = "no_object"))]
412 #[cfg(not(feature = "indexmap"))]
413 Union::Map(ref m, ..) => m.hash(state),
414 #[cfg(not(feature = "no_object"))]
415 #[cfg(feature = "indexmap")]
416 Union::Map(ref m, ..) => hash_indexmap(m, state),
417
418 Union::FnPtr(ref f, ..) if f.environ.is_some() => {
419 unimplemented!("FnPtr with embedded environment cannot be hashed")
420 }
421 Union::FnPtr(ref f, ..) => {
422 f.fn_name().hash(state);
423 f.curry().hash(state);
424 }
425 #[cfg(not(feature = "no_closure"))]
426 Union::Shared(ref cell, ..) => (*crate::func::locked_read(cell)).hash(state),
427
428 Union::Variant(ref v, ..) => {
429 let _value_any = (***v).as_any();
430
431 #[cfg(not(feature = "only_i32"))]
432 #[cfg(not(feature = "only_i64"))]
433 if let Some(value) = _value_any.downcast_ref::<u8>() {
434 return value.hash(state);
435 } else if let Some(value) = _value_any.downcast_ref::<u16>() {
436 return value.hash(state);
437 } else if let Some(value) = _value_any.downcast_ref::<u32>() {
438 return value.hash(state);
439 } else if let Some(value) = _value_any.downcast_ref::<u64>() {
440 return value.hash(state);
441 } else if let Some(value) = _value_any.downcast_ref::<i8>() {
442 return value.hash(state);
443 } else if let Some(value) = _value_any.downcast_ref::<i16>() {
444 return value.hash(state);
445 } else if let Some(value) = _value_any.downcast_ref::<i32>() {
446 return value.hash(state);
447 } else if let Some(value) = _value_any.downcast_ref::<i64>() {
448 return value.hash(state);
449 }
450
451 #[cfg(not(feature = "no_float"))]
452 #[cfg(not(feature = "f32_float"))]
453 if let Some(value) = _value_any.downcast_ref::<f32>() {
454 return value.to_ne_bytes().hash(state);
455 }
456 #[cfg(not(feature = "no_float"))]
457 #[cfg(feature = "f32_float")]
458 if let Some(value) = _value_any.downcast_ref::<f64>() {
459 return value.to_ne_bytes().hash(state);
460 }
461
462 #[cfg(not(feature = "only_i32"))]
463 #[cfg(not(feature = "only_i64"))]
464 #[cfg(not(target_family = "wasm"))]
465 if let Some(value) = _value_any.downcast_ref::<u128>() {
466 return value.hash(state);
467 } else if let Some(value) = _value_any.downcast_ref::<i128>() {
468 return value.hash(state);
469 }
470
471 if let Some(range) = _value_any.downcast_ref::<ExclusiveRange>() {
472 return range.hash(state);
473 } else if let Some(range) = _value_any.downcast_ref::<InclusiveRange>() {
474 return range.hash(state);
475 }
476
477 unimplemented!("Custom type {} cannot be hashed", self.type_name())
478 }
479
480 #[cfg(not(feature = "no_time"))]
481 Union::TimeStamp(..) => unimplemented!("Timestamp cannot be hashed"),
482 }
483 }
484}
485
486impl fmt::Display for Dynamic {
487 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
488 match self.0 {
489 Union::Unit(..) => Ok(()),
490 Union::Bool(ref v, ..) => fmt::Display::fmt(v, f),
491 Union::Str(ref v, ..) => fmt::Display::fmt(v, f),
492 Union::Char(ref v, ..) => fmt::Display::fmt(v, f),
493 Union::Int(ref v, ..) => fmt::Display::fmt(v, f),
494 #[cfg(not(feature = "no_float"))]
495 Union::Float(ref v, ..) => fmt::Display::fmt(v, f),
496 #[cfg(feature = "decimal")]
497 Union::Decimal(ref v, ..) => fmt::Display::fmt(v, f),
498 #[cfg(not(feature = "no_index"))]
499 Union::Array(..) => fmt::Debug::fmt(self, f),
500 #[cfg(not(feature = "no_index"))]
501 Union::Blob(..) => fmt::Debug::fmt(self, f),
502 #[cfg(not(feature = "no_object"))]
503 Union::Map(..) => fmt::Debug::fmt(self, f),
504 Union::FnPtr(ref v, ..) => fmt::Display::fmt(v, f),
505 #[cfg(not(feature = "no_time"))]
506 Union::TimeStamp(..) => f.write_str("<timestamp>"),
507
508 Union::Variant(ref v, ..) => {
509 let _value_any = (***v).as_any();
510 let _type_id = _value_any.type_id();
511
512 #[cfg(not(feature = "only_i32"))]
513 #[cfg(not(feature = "only_i64"))]
514 if let Some(value) = _value_any.downcast_ref::<u8>() {
515 return fmt::Display::fmt(value, f);
516 } else if let Some(value) = _value_any.downcast_ref::<u16>() {
517 return fmt::Display::fmt(value, f);
518 } else if let Some(value) = _value_any.downcast_ref::<u32>() {
519 return fmt::Display::fmt(value, f);
520 } else if let Some(value) = _value_any.downcast_ref::<u64>() {
521 return fmt::Display::fmt(value, f);
522 } else if let Some(value) = _value_any.downcast_ref::<i8>() {
523 return fmt::Display::fmt(value, f);
524 } else if let Some(value) = _value_any.downcast_ref::<i16>() {
525 return fmt::Display::fmt(value, f);
526 } else if let Some(value) = _value_any.downcast_ref::<i32>() {
527 return fmt::Display::fmt(value, f);
528 } else if let Some(value) = _value_any.downcast_ref::<i64>() {
529 return fmt::Display::fmt(value, f);
530 }
531
532 #[cfg(not(feature = "no_float"))]
533 #[cfg(not(feature = "f32_float"))]
534 if let Some(value) = _value_any.downcast_ref::<f32>() {
535 return fmt::Display::fmt(value, f);
536 }
537 #[cfg(not(feature = "no_float"))]
538 #[cfg(feature = "f32_float")]
539 if let Some(value) = _value_any.downcast_ref::<f64>() {
540 return fmt::Display::fmt(value, f);
541 }
542
543 #[cfg(not(feature = "only_i32"))]
544 #[cfg(not(feature = "only_i64"))]
545 #[cfg(not(target_family = "wasm"))]
546 if let Some(value) = _value_any.downcast_ref::<u128>() {
547 return fmt::Display::fmt(value, f);
548 } else if let Some(value) = _value_any.downcast_ref::<i128>() {
549 return fmt::Display::fmt(value, f);
550 }
551
552 if let Some(range) = _value_any.downcast_ref::<ExclusiveRange>() {
553 return write!(f, "{}..{}", range.start, range.end);
554 } else if let Some(range) = _value_any.downcast_ref::<InclusiveRange>() {
555 return write!(f, "{}..={}", range.start(), range.end());
556 }
557
558 f.write_str((***v).type_name())
559 }
560
561 #[cfg(not(feature = "no_closure"))]
562 Union::Shared(ref cell, ..) if cfg!(feature = "unchecked") => {
563 #[cfg(not(feature = "sync"))]
564 match cell.try_borrow() {
565 Ok(v) => {
566 fmt::Display::fmt(&*v, f)?;
567 f.write_str(" (shared)")
568 }
569 Err(_) => f.write_str("<shared>"),
570 }
571 #[cfg(feature = "sync")]
572 fmt::Display::fmt(&*cell.read().unwrap(), f)
573 }
574 #[cfg(not(feature = "no_closure"))]
575 Union::Shared(..) => {
576 #[cfg(feature = "no_std")]
577 use hashbrown::HashSet;
578 #[cfg(not(feature = "no_std"))]
579 use std::collections::HashSet;
580
581 fn display_fmt(
583 value: &Dynamic,
584 f: &mut fmt::Formatter<'_>,
585 dict: &mut HashSet<*const Dynamic>,
586 ) -> fmt::Result {
587 match value.0 {
588 #[cfg(not(feature = "no_closure"))]
589 #[cfg(not(feature = "sync"))]
590 Union::Shared(ref cell, ..) => match cell.try_borrow() {
591 Ok(v) => {
592 if dict.insert(value) {
593 display_fmt(&*v, f, dict)?;
594 f.write_str(" (shared)")
595 } else {
596 f.write_str("<shared>")
597 }
598 }
599 Err(_) => f.write_str("<shared>"),
600 },
601 #[cfg(not(feature = "no_closure"))]
602 #[cfg(feature = "sync")]
603 Union::Shared(ref cell, ..) => {
604 let v = cell.read().unwrap();
605
606 if dict.insert(value) {
607 display_fmt(&*v, f, dict)
608 } else {
609 f.write_str("<shared>")
610 }
611 }
612 #[cfg(not(feature = "no_index"))]
613 Union::Array(ref arr, ..) => {
614 dict.insert(value);
615
616 f.write_str("[")?;
617 for (i, v) in arr.iter().enumerate() {
618 if i > 0 {
619 f.write_str(", ")?;
620 }
621 display_fmt(v, f, dict)?;
622 }
623 f.write_str("]")
624 }
625 #[cfg(not(feature = "no_object"))]
626 Union::Map(ref map, ..) => {
627 dict.insert(value);
628
629 f.write_str("#{")?;
630 for (i, (k, v)) in map.iter().enumerate() {
631 if i > 0 {
632 f.write_str(", ")?;
633 }
634 fmt::Display::fmt(k, f)?;
635 f.write_str(": ")?;
636 display_fmt(v, f, dict)?;
637 }
638 f.write_str("}")
639 }
640 _ => fmt::Display::fmt(value, f),
641 }
642 }
643
644 display_fmt(self, f, &mut <_>::default())
645 }
646 }
647 }
648}
649
650impl fmt::Debug for Dynamic {
651 #[cold]
652 #[inline(never)]
653 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
654 match self.0 {
655 Union::Unit(ref v, ..) => fmt::Debug::fmt(v, f),
656 Union::Bool(ref v, ..) => fmt::Debug::fmt(v, f),
657 Union::Str(ref v, ..) => fmt::Debug::fmt(v, f),
658 Union::Char(ref v, ..) => fmt::Debug::fmt(v, f),
659 Union::Int(ref v, ..) => fmt::Debug::fmt(v, f),
660 #[cfg(not(feature = "no_float"))]
661 Union::Float(ref v, ..) => fmt::Debug::fmt(v, f),
662 #[cfg(feature = "decimal")]
663 Union::Decimal(ref v, ..) => fmt::Debug::fmt(v, f),
664 #[cfg(not(feature = "no_index"))]
665 Union::Array(ref v, ..) => fmt::Debug::fmt(v, f),
666 #[cfg(not(feature = "no_index"))]
667 Union::Blob(ref v, ..) => {
668 f.write_str("[")?;
669 v.iter().enumerate().try_for_each(|(i, v)| {
670 if i > 0 && i % 8 == 0 {
671 f.write_str(" ")?;
672 }
673 write!(f, "{v:02x}")
674 })?;
675 f.write_str("]")
676 }
677 #[cfg(not(feature = "no_object"))]
678 Union::Map(ref v, ..) => {
679 f.write_str("#")?;
680 fmt::Debug::fmt(v, f)
681 }
682 Union::FnPtr(ref v, ..) => fmt::Debug::fmt(v, f),
683 #[cfg(not(feature = "no_time"))]
684 Union::TimeStamp(..) => write!(f, "<timestamp>"),
685
686 Union::Variant(ref v, ..) => {
687 let _value_any = (***v).as_any();
688 let _type_id = _value_any.type_id();
689
690 #[cfg(not(feature = "only_i32"))]
691 #[cfg(not(feature = "only_i64"))]
692 if let Some(value) = _value_any.downcast_ref::<u8>() {
693 return fmt::Debug::fmt(value, f);
694 } else if let Some(value) = _value_any.downcast_ref::<u16>() {
695 return fmt::Debug::fmt(value, f);
696 } else if let Some(value) = _value_any.downcast_ref::<u32>() {
697 return fmt::Debug::fmt(value, f);
698 } else if let Some(value) = _value_any.downcast_ref::<u64>() {
699 return fmt::Debug::fmt(value, f);
700 } else if let Some(value) = _value_any.downcast_ref::<i8>() {
701 return fmt::Debug::fmt(value, f);
702 } else if let Some(value) = _value_any.downcast_ref::<i16>() {
703 return fmt::Debug::fmt(value, f);
704 } else if let Some(value) = _value_any.downcast_ref::<i32>() {
705 return fmt::Debug::fmt(value, f);
706 } else if let Some(value) = _value_any.downcast_ref::<i64>() {
707 return fmt::Debug::fmt(value, f);
708 }
709
710 #[cfg(not(feature = "no_float"))]
711 #[cfg(not(feature = "f32_float"))]
712 if let Some(value) = _value_any.downcast_ref::<f32>() {
713 return fmt::Debug::fmt(value, f);
714 }
715 #[cfg(not(feature = "no_float"))]
716 #[cfg(feature = "f32_float")]
717 if let Some(value) = _value_any.downcast_ref::<f64>() {
718 return fmt::Debug::fmt(value, f);
719 }
720
721 #[cfg(not(feature = "only_i32"))]
722 #[cfg(not(feature = "only_i64"))]
723 #[cfg(not(target_family = "wasm"))]
724 if let Some(value) = _value_any.downcast_ref::<u128>() {
725 return fmt::Debug::fmt(value, f);
726 } else if let Some(value) = _value_any.downcast_ref::<i128>() {
727 return fmt::Debug::fmt(value, f);
728 }
729
730 if let Some(range) = _value_any.downcast_ref::<ExclusiveRange>() {
731 return write!(f, "{}..{}", range.start, range.end);
732 } else if let Some(range) = _value_any.downcast_ref::<InclusiveRange>() {
733 return write!(f, "{}..={}", range.start(), range.end());
734 }
735
736 f.write_str((***v).type_name())
737 }
738
739 #[cfg(not(feature = "no_closure"))]
740 Union::Shared(ref cell, ..) if cfg!(feature = "unchecked") => {
741 #[cfg(not(feature = "sync"))]
742 match cell.try_borrow() {
743 Ok(v) => {
744 fmt::Debug::fmt(&*v, f)?;
745 f.write_str(" (shared)")
746 }
747 Err(_) => f.write_str("<shared>"),
748 }
749 #[cfg(feature = "sync")]
750 fmt::Debug::fmt(&*cell.read().unwrap(), f)
751 }
752 #[cfg(not(feature = "no_closure"))]
753 Union::Shared(..) => {
754 #[cfg(feature = "no_std")]
755 use hashbrown::HashSet;
756 #[cfg(not(feature = "no_std"))]
757 use std::collections::HashSet;
758
759 fn debug_fmt(
761 value: &Dynamic,
762 f: &mut fmt::Formatter<'_>,
763 dict: &mut HashSet<*const Dynamic>,
764 ) -> fmt::Result {
765 match value.0 {
766 #[cfg(not(feature = "no_closure"))]
767 #[cfg(not(feature = "sync"))]
768 Union::Shared(ref cell, ..) => match cell.try_borrow() {
769 Ok(v) => {
770 if dict.insert(value) {
771 debug_fmt(&*v, f, dict)?;
772 f.write_str(" (shared)")
773 } else {
774 f.write_str("<shared>")
775 }
776 }
777 Err(_) => f.write_str("<shared>"),
778 },
779 #[cfg(not(feature = "no_closure"))]
780 #[cfg(feature = "sync")]
781 Union::Shared(ref cell, ..) => {
782 let v = cell.read().unwrap();
783
784 if dict.insert(value) {
785 debug_fmt(&*v, f, dict)?;
786 f.write_str(" (shared)")
787 } else {
788 f.write_str("<shared>")
789 }
790 }
791 #[cfg(not(feature = "no_index"))]
792 Union::Array(ref arr, ..) => {
793 dict.insert(value);
794
795 f.write_str("[")?;
796 for (i, v) in arr.iter().enumerate() {
797 if i > 0 {
798 f.write_str(", ")?;
799 }
800 debug_fmt(v, f, dict)?;
801 }
802 f.write_str("]")
803 }
804 #[cfg(not(feature = "no_object"))]
805 Union::Map(ref map, ..) => {
806 dict.insert(value);
807
808 f.write_str("#{")?;
809 for (i, (k, v)) in map.iter().enumerate() {
810 if i > 0 {
811 f.write_str(", ")?;
812 }
813 fmt::Debug::fmt(k, f)?;
814 f.write_str(": ")?;
815 debug_fmt(v, f, dict)?;
816 }
817 f.write_str("}")
818 }
819 Union::FnPtr(ref fnptr, ..) => {
820 dict.insert(value);
821
822 f.write_str("Fn")?;
823 #[cfg(not(feature = "no_function"))]
824 if fnptr.fn_def.is_some() {
825 f.write_str("*")?;
826 }
827 f.write_str("(")?;
828 fmt::Debug::fmt(fnptr.fn_name(), f)?;
829 for curry in fnptr.curry.iter() {
830 f.write_str(", ")?;
831 debug_fmt(curry, f, dict)?;
832 }
833 f.write_str(")")
834 }
835 _ => fmt::Debug::fmt(value, f),
836 }
837 }
838
839 debug_fmt(self, f, &mut <_>::default())
840 }
841 }
842 }
843}
844
845#[allow(clippy::enum_glob_use)]
846use AccessMode::*;
847
848impl Clone for Dynamic {
849 fn clone(&self) -> Self {
855 match self.0 {
856 Union::Unit(v, tag, ..) => Self(Union::Unit(v, tag, ReadWrite)),
857 Union::Bool(v, tag, ..) => Self(Union::Bool(v, tag, ReadWrite)),
858 Union::Str(ref v, tag, ..) => Self(Union::Str(v.clone(), tag, ReadWrite)),
859 Union::Char(v, tag, ..) => Self(Union::Char(v, tag, ReadWrite)),
860 Union::Int(v, tag, ..) => Self(Union::Int(v, tag, ReadWrite)),
861 #[cfg(not(feature = "no_float"))]
862 Union::Float(v, tag, ..) => Self(Union::Float(v, tag, ReadWrite)),
863 #[cfg(feature = "decimal")]
864 Union::Decimal(ref v, tag, ..) => Self(Union::Decimal(v.clone(), tag, ReadWrite)),
865 #[cfg(not(feature = "no_index"))]
866 Union::Array(ref v, tag, ..) => Self(Union::Array(v.clone(), tag, ReadWrite)),
867 #[cfg(not(feature = "no_index"))]
868 Union::Blob(ref v, tag, ..) => Self(Union::Blob(v.clone(), tag, ReadWrite)),
869 #[cfg(not(feature = "no_object"))]
870 Union::Map(ref v, tag, ..) => Self(Union::Map(v.clone(), tag, ReadWrite)),
871 Union::FnPtr(ref v, tag, ..) => Self(Union::FnPtr(v.clone(), tag, ReadWrite)),
872 #[cfg(not(feature = "no_time"))]
873 Union::TimeStamp(ref v, tag, ..) => Self(Union::TimeStamp(v.clone(), tag, ReadWrite)),
874
875 Union::Variant(ref v, tag, ..) => Self(Union::Variant(
876 v.as_ref().as_ref().clone_object().into(),
877 tag,
878 ReadWrite,
879 )),
880
881 #[cfg(not(feature = "no_closure"))]
882 Union::Shared(ref cell, tag, ..) => Self(Union::Shared(cell.clone(), tag, ReadWrite)),
883 }
884 }
885}
886
887impl Default for Dynamic {
888 #[inline(always)]
889 fn default() -> Self {
890 Self::UNIT
891 }
892}
893
894#[cfg(not(feature = "no_float"))]
895#[cfg(feature = "f32_float")]
896use std::f32::consts as FloatConstants;
897#[cfg(not(feature = "no_float"))]
898#[cfg(not(feature = "f32_float"))]
899use std::f64::consts as FloatConstants;
900
901impl Dynamic {
902 pub const UNIT: Self = Self(Union::Unit((), DEFAULT_TAG_VALUE, ReadWrite));
904 pub const TRUE: Self = Self::from_bool(true);
906 pub const FALSE: Self = Self::from_bool(false);
908 pub const ZERO: Self = Self::from_int(0);
910 pub const ONE: Self = Self::from_int(1);
912 pub const TWO: Self = Self::from_int(2);
914 pub const THREE: Self = Self::from_int(3);
916 pub const TEN: Self = Self::from_int(10);
918 pub const HUNDRED: Self = Self::from_int(100);
920 pub const THOUSAND: Self = Self::from_int(1000);
922 pub const MILLION: Self = Self::from_int(1_000_000);
924 pub const NEGATIVE_ONE: Self = Self::from_int(-1);
926 pub const NEGATIVE_TWO: Self = Self::from_int(-2);
928 #[cfg(not(feature = "no_float"))]
932 pub const FLOAT_ZERO: Self = Self::from_float(0.0);
933 #[cfg(not(feature = "no_float"))]
937 pub const FLOAT_ONE: Self = Self::from_float(1.0);
938 #[cfg(not(feature = "no_float"))]
942 pub const FLOAT_TWO: Self = Self::from_float(2.0);
943 #[cfg(not(feature = "no_float"))]
947 pub const FLOAT_TEN: Self = Self::from_float(10.0);
948 #[cfg(not(feature = "no_float"))]
952 pub const FLOAT_HUNDRED: Self = Self::from_float(100.0);
953 #[cfg(not(feature = "no_float"))]
957 pub const FLOAT_THOUSAND: Self = Self::from_float(1000.0);
958 #[cfg(not(feature = "no_float"))]
962 pub const FLOAT_MILLION: Self = Self::from_float(1_000_000.0);
963 #[cfg(not(feature = "no_float"))]
967 pub const FLOAT_NEGATIVE_ONE: Self = Self::from_float(-1.0);
968 #[cfg(not(feature = "no_float"))]
972 pub const FLOAT_NEGATIVE_TWO: Self = Self::from_float(-2.0);
973 #[cfg(not(feature = "no_float"))]
977 pub const FLOAT_HALF: Self = Self::from_float(0.5);
978 #[cfg(not(feature = "no_float"))]
982 pub const FLOAT_QUARTER: Self = Self::from_float(0.25);
983 #[cfg(not(feature = "no_float"))]
987 pub const FLOAT_FIFTH: Self = Self::from_float(0.2);
988 #[cfg(not(feature = "no_float"))]
992 pub const FLOAT_TENTH: Self = Self::from_float(0.1);
993 #[cfg(not(feature = "no_float"))]
997 pub const FLOAT_HUNDREDTH: Self = Self::from_float(0.01);
998 #[cfg(not(feature = "no_float"))]
1002 pub const FLOAT_THOUSANDTH: Self = Self::from_float(0.001);
1003 #[cfg(not(feature = "no_float"))]
1007 pub const FLOAT_MILLIONTH: Self = Self::from_float(0.000_001);
1008 #[cfg(not(feature = "no_float"))]
1012 pub const FLOAT_PI: Self = Self::from_float(FloatConstants::PI);
1013 #[cfg(not(feature = "no_float"))]
1017 pub const FLOAT_HALF_PI: Self = Self::from_float(FloatConstants::FRAC_PI_2);
1018 #[cfg(not(feature = "no_float"))]
1022 pub const FLOAT_QUARTER_PI: Self = Self::from_float(FloatConstants::FRAC_PI_4);
1023 #[cfg(not(feature = "no_float"))]
1027 pub const FLOAT_TWO_PI: Self = Self::from_float(FloatConstants::TAU);
1028 #[cfg(not(feature = "no_float"))]
1032 pub const FLOAT_INVERSE_PI: Self = Self::from_float(FloatConstants::FRAC_1_PI);
1033 #[cfg(not(feature = "no_float"))]
1037 pub const FLOAT_E: Self = Self::from_float(FloatConstants::E);
1038 #[cfg(not(feature = "no_float"))]
1042 pub const FLOAT_LOG_E: Self = Self::from_float(FloatConstants::LOG10_E);
1043 #[cfg(not(feature = "no_float"))]
1047 pub const FLOAT_LN_10: Self = Self::from_float(FloatConstants::LN_10);
1048
1049 #[inline(always)]
1051 pub const fn from_bool(value: bool) -> Self {
1052 Self(Union::Bool(value, DEFAULT_TAG_VALUE, ReadWrite))
1053 }
1054 #[inline(always)]
1056 pub const fn from_int(value: INT) -> Self {
1057 Self(Union::Int(value, DEFAULT_TAG_VALUE, ReadWrite))
1058 }
1059 #[inline(always)]
1061 pub const fn from_char(value: char) -> Self {
1062 Self(Union::Char(value, DEFAULT_TAG_VALUE, ReadWrite))
1063 }
1064 #[cfg(not(feature = "no_float"))]
1068 #[inline(always)]
1069 pub const fn from_float(value: crate::FLOAT) -> Self {
1070 Self(Union::Float(
1071 super::FloatWrapper::new(value),
1072 DEFAULT_TAG_VALUE,
1073 ReadWrite,
1074 ))
1075 }
1076 #[cfg(feature = "decimal")]
1080 #[inline(always)]
1081 pub fn from_decimal(value: rust_decimal::Decimal) -> Self {
1082 Self(Union::Decimal(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
1083 }
1084 #[cfg(not(feature = "no_index"))]
1086 #[inline(always)]
1087 pub fn from_array(array: crate::Array) -> Self {
1088 Self(Union::Array(array.into(), DEFAULT_TAG_VALUE, ReadWrite))
1089 }
1090 #[cfg(not(feature = "no_index"))]
1092 #[inline(always)]
1093 pub fn from_blob(blob: crate::Blob) -> Self {
1094 Self(Union::Blob(blob.into(), DEFAULT_TAG_VALUE, ReadWrite))
1095 }
1096 #[cfg(not(feature = "no_object"))]
1098 #[inline(always)]
1099 pub fn from_map(map: crate::Map) -> Self {
1100 Self(Union::Map(map.into(), DEFAULT_TAG_VALUE, ReadWrite))
1101 }
1102 #[cfg(not(feature = "no_time"))]
1106 #[inline(always)]
1107 pub fn from_timestamp(value: Instant) -> Self {
1108 Self(Union::TimeStamp(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
1109 }
1110
1111 #[must_use]
1113 pub(crate) const fn access_mode(&self) -> AccessMode {
1114 match self.0 {
1115 Union::Unit(.., access)
1116 | Union::Bool(.., access)
1117 | Union::Str(.., access)
1118 | Union::Char(.., access)
1119 | Union::Int(.., access)
1120 | Union::FnPtr(.., access)
1121 | Union::Variant(.., access) => access,
1122
1123 #[cfg(not(feature = "no_float"))]
1124 Union::Float(.., access) => access,
1125 #[cfg(feature = "decimal")]
1126 Union::Decimal(.., access) => access,
1127 #[cfg(not(feature = "no_index"))]
1128 Union::Array(.., access) | Union::Blob(.., access) => access,
1129 #[cfg(not(feature = "no_object"))]
1130 Union::Map(.., access) => access,
1131 #[cfg(not(feature = "no_time"))]
1132 Union::TimeStamp(.., access) => access,
1133 #[cfg(not(feature = "no_closure"))]
1134 Union::Shared(.., access) => access,
1135 }
1136 }
1137 pub(crate) fn set_access_mode(&mut self, typ: AccessMode) -> &mut Self {
1139 match self.0 {
1140 Union::Unit(.., ref mut access)
1141 | Union::Bool(.., ref mut access)
1142 | Union::Str(.., ref mut access)
1143 | Union::Char(.., ref mut access)
1144 | Union::Int(.., ref mut access)
1145 | Union::FnPtr(.., ref mut access)
1146 | Union::Variant(.., ref mut access) => *access = typ,
1147
1148 #[cfg(not(feature = "no_float"))]
1149 Union::Float(.., ref mut access) => *access = typ,
1150 #[cfg(feature = "decimal")]
1151 Union::Decimal(.., ref mut access) => *access = typ,
1152 #[cfg(not(feature = "no_index"))]
1153 Union::Array(ref mut a, _, ref mut access) => {
1154 *access = typ;
1155 for v in a.as_mut() {
1156 v.set_access_mode(typ);
1157 }
1158 }
1159 #[cfg(not(feature = "no_index"))]
1160 Union::Blob(.., ref mut access) => *access = typ,
1161 #[cfg(not(feature = "no_object"))]
1162 Union::Map(ref mut m, _, ref mut access) => {
1163 *access = typ;
1164 for v in m.values_mut() {
1165 v.set_access_mode(typ);
1166 }
1167 }
1168 #[cfg(not(feature = "no_time"))]
1169 Union::TimeStamp(.., ref mut access) => *access = typ,
1170 #[cfg(not(feature = "no_closure"))]
1171 Union::Shared(.., ref mut access) => *access = typ,
1172 }
1173 self
1174 }
1175 #[inline(always)]
1177 pub fn into_read_only(self) -> Self {
1178 let mut value = self;
1179 value.set_access_mode(AccessMode::ReadOnly);
1180 value
1181 }
1182 #[must_use]
1200 pub fn is_read_only(&self) -> bool {
1201 #[cfg(not(feature = "no_closure"))]
1202 if let Union::Shared(ref cell, ..) = self.0 {
1203 return match crate::func::locked_read(cell).access_mode() {
1204 ReadWrite => false,
1205 ReadOnly => true,
1206 };
1207 }
1208
1209 match self.access_mode() {
1210 ReadWrite => false,
1211 ReadOnly => true,
1212 }
1213 }
1214 #[must_use]
1216 pub(crate) fn is_hashable(&self) -> bool {
1217 match self.0 {
1218 Union::Unit(..)
1219 | Union::Bool(..)
1220 | Union::Str(..)
1221 | Union::Char(..)
1222 | Union::Int(..) => true,
1223
1224 #[cfg(not(feature = "no_float"))]
1225 Union::Float(..) => true,
1226 #[cfg(feature = "decimal")]
1227 Union::Decimal(..) => true,
1228 #[cfg(not(feature = "no_index"))]
1229 Union::Array(ref a, ..) => a.iter().all(Self::is_hashable),
1230 #[cfg(not(feature = "no_index"))]
1231 Union::Blob(..) => true,
1232 #[cfg(not(feature = "no_object"))]
1233 Union::Map(ref m, ..) => m.values().all(Self::is_hashable),
1234 Union::FnPtr(ref f, ..) => {
1235 f.environ.is_none() && f.curry().iter().all(Self::is_hashable)
1236 }
1237 #[cfg(not(feature = "no_time"))]
1238 Union::TimeStamp(..) => false,
1239
1240 Union::Variant(ref v, ..) => {
1241 let _value_any = (***v).as_any();
1242 let _type_id = _value_any.type_id();
1243
1244 #[cfg(not(feature = "only_i32"))]
1245 #[cfg(not(feature = "only_i64"))]
1246 if _type_id == TypeId::of::<u8>()
1247 || _type_id == TypeId::of::<u16>()
1248 || _type_id == TypeId::of::<u32>()
1249 || _type_id == TypeId::of::<u64>()
1250 || _type_id == TypeId::of::<i8>()
1251 || _type_id == TypeId::of::<i16>()
1252 || _type_id == TypeId::of::<i32>()
1253 || _type_id == TypeId::of::<i64>()
1254 {
1255 return true;
1256 }
1257
1258 #[cfg(not(feature = "no_float"))]
1259 #[cfg(not(feature = "f32_float"))]
1260 if _type_id == TypeId::of::<f32>() {
1261 return true;
1262 }
1263 #[cfg(not(feature = "no_float"))]
1264 #[cfg(feature = "f32_float")]
1265 if _type_id == TypeId::of::<f64>() {
1266 return true;
1267 }
1268
1269 #[cfg(not(feature = "only_i32"))]
1270 #[cfg(not(feature = "only_i64"))]
1271 #[cfg(not(target_family = "wasm"))]
1272 if _type_id == TypeId::of::<u128>() || _type_id == TypeId::of::<i128>() {
1273 return true;
1274 }
1275
1276 if _type_id == TypeId::of::<ExclusiveRange>()
1277 || _type_id == TypeId::of::<InclusiveRange>()
1278 {
1279 return true;
1280 }
1281
1282 false
1283 }
1284
1285 #[cfg(not(feature = "no_closure"))]
1286 Union::Shared(ref cell, ..) => crate::func::locked_read(cell).is_hashable(),
1287 }
1288 }
1289 #[inline]
1354 pub fn from<T: Variant + Clone>(value: T) -> Self {
1355 reify! { value => |v: Self| return v }
1358 reify! { value => |v: INT| return v.into() }
1359
1360 #[cfg(not(feature = "no_float"))]
1361 reify! { value => |v: crate::FLOAT| return v.into() }
1362
1363 #[cfg(feature = "decimal")]
1364 reify! { value => |v: rust_decimal::Decimal| return v.into() }
1365
1366 reify! { value => |v: bool| return v.into() }
1367 reify! { value => |v: char| return v.into() }
1368 reify! { value => |v: ImmutableString| return v.into() }
1369 reify! { value => |v: String| return v.into() }
1370 reify! { value => |v: &str| return v.into() }
1371 reify! { value => |v: ()| return v.into() }
1372
1373 #[cfg(not(feature = "no_index"))]
1374 reify! { value => |v: crate::Array| return v.into() }
1375 #[cfg(not(feature = "no_index"))]
1376 reify! { value => |v: crate::Blob| return Self::from_blob(v) }
1378 #[cfg(not(feature = "no_object"))]
1379 reify! { value => |v: crate::Map| return v.into() }
1380 reify! { value => |v: FnPtr| return v.into() }
1381
1382 #[cfg(not(feature = "no_time"))]
1383 reify! { value => |v: Instant| return v.into() }
1384 #[cfg(not(feature = "no_closure"))]
1385 reify! { value => |v: crate::Shared<crate::Locked<Self>>| return v.into() }
1386
1387 Self(Union::Variant(
1388 Box::new(Box::new(value)),
1389 DEFAULT_TAG_VALUE,
1390 ReadWrite,
1391 ))
1392 }
1393 #[cfg(not(feature = "no_closure"))]
1407 #[inline]
1408 pub fn into_shared(self) -> Self {
1409 let _access = self.access_mode();
1410
1411 match self.0 {
1412 Union::Shared(..) => self,
1413 _ => Self(Union::Shared(
1414 crate::Locked::new(self).into(),
1415 DEFAULT_TAG_VALUE,
1416 _access,
1417 )),
1418 }
1419 }
1420 #[inline(always)]
1422 pub fn take(&mut self) -> Self {
1423 mem::take(self)
1424 }
1425 #[inline(always)]
1449 #[must_use]
1450 #[allow(unused_mut)]
1451 pub fn try_cast<T: Any>(mut self) -> Option<T> {
1452 self.try_cast_raw().ok()
1453 }
1454 #[allow(unused_mut)]
1461 pub(crate) fn try_cast_raw<T: Any>(mut self) -> Result<T, Self> {
1462 #[cfg(not(feature = "no_closure"))]
1465 {
1466 self = self.flatten();
1467 }
1468
1469 if TypeId::of::<T>() == TypeId::of::<Self>() {
1470 return Ok(reify! { self => !!! T });
1471 }
1472 if TypeId::of::<T>() == TypeId::of::<()>() {
1473 return match self.0 {
1474 Union::Unit(..) => Ok(reify! { () => !!! T }),
1475 _ => Err(self),
1476 };
1477 }
1478 if TypeId::of::<T>() == TypeId::of::<INT>() {
1479 return match self.0 {
1480 Union::Int(n, ..) => Ok(reify! { n => !!! T }),
1481 _ => Err(self),
1482 };
1483 }
1484 #[cfg(not(feature = "no_float"))]
1485 if TypeId::of::<T>() == TypeId::of::<crate::FLOAT>() {
1486 return match self.0 {
1487 Union::Float(v, ..) => Ok(reify! { *v => !!! T }),
1488 _ => Err(self),
1489 };
1490 }
1491 #[cfg(feature = "decimal")]
1492 if TypeId::of::<T>() == TypeId::of::<rust_decimal::Decimal>() {
1493 return match self.0 {
1494 Union::Decimal(v, ..) => Ok(reify! { *v => !!! T }),
1495 _ => Err(self),
1496 };
1497 }
1498 if TypeId::of::<T>() == TypeId::of::<bool>() {
1499 return match self.0 {
1500 Union::Bool(b, ..) => Ok(reify! { b => !!! T }),
1501 _ => Err(self),
1502 };
1503 }
1504 if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
1505 return match self.0 {
1506 Union::Str(s, ..) => Ok(reify! { s => !!! T }),
1507 _ => Err(self),
1508 };
1509 }
1510 if TypeId::of::<T>() == TypeId::of::<String>() {
1511 return match self.0 {
1512 Union::Str(s, ..) => Ok(reify! { s.to_string() => !!! T }),
1513 _ => Err(self),
1514 };
1515 }
1516 if TypeId::of::<T>() == TypeId::of::<char>() {
1517 return match self.0 {
1518 Union::Char(c, ..) => Ok(reify! { c => !!! T }),
1519 _ => Err(self),
1520 };
1521 }
1522 #[cfg(not(feature = "no_index"))]
1523 if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
1524 return match self.0 {
1525 Union::Array(a, ..) => Ok(reify! { *a => !!! T }),
1526 _ => Err(self),
1527 };
1528 }
1529 #[cfg(not(feature = "no_index"))]
1530 if TypeId::of::<T>() == TypeId::of::<crate::Blob>() {
1531 return match self.0 {
1532 Union::Blob(b, ..) => Ok(reify! { *b => !!! T }),
1533 _ => Err(self),
1534 };
1535 }
1536 #[cfg(not(feature = "no_object"))]
1537 if TypeId::of::<T>() == TypeId::of::<crate::Map>() {
1538 return match self.0 {
1539 Union::Map(m, ..) => Ok(reify! { *m => !!! T }),
1540 _ => Err(self),
1541 };
1542 }
1543 if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
1544 return match self.0 {
1545 Union::FnPtr(f, ..) => Ok(reify! { *f => !!! T }),
1546 _ => Err(self),
1547 };
1548 }
1549 #[cfg(not(feature = "no_time"))]
1550 if TypeId::of::<T>() == TypeId::of::<Instant>() {
1551 return match self.0 {
1552 Union::TimeStamp(t, ..) => Ok(reify! { *t => !!! T }),
1553 _ => Err(self),
1554 };
1555 }
1556
1557 match self.0 {
1558 Union::Variant(v, ..) if TypeId::of::<T>() == (**v).type_id() => {
1559 Ok((*v).as_boxed_any().downcast().map(|x| *x).unwrap())
1560 }
1561 #[cfg(not(feature = "no_closure"))]
1562 Union::Shared(..) => unreachable!("Union::Shared case should be already handled"),
1563 _ => Err(self),
1564 }
1565 }
1566 #[inline]
1590 #[must_use]
1591 pub fn cast<T: Any + Clone>(self) -> T {
1592 if TypeId::of::<T>() == TypeId::of::<Self>() {
1594 return reify! { self => !!! T };
1595 }
1596
1597 #[cfg(not(feature = "no_closure"))]
1598 let self_type_name = if self.is_shared() {
1599 "<shared>"
1601 } else {
1602 self.type_name()
1603 };
1604 #[cfg(feature = "no_closure")]
1605 let self_type_name = self.type_name();
1606
1607 self.try_cast::<T>()
1608 .unwrap_or_else(|| panic!("cannot cast {} to {}", self_type_name, type_name::<T>()))
1609 }
1610 #[inline(always)]
1638 #[must_use]
1639 pub fn clone_cast<T: Any + Clone>(&self) -> T {
1640 self.flatten_clone().cast::<T>()
1641 }
1642 #[inline]
1648 pub fn flatten_clone(&self) -> Self {
1649 match self.0 {
1650 #[cfg(not(feature = "no_closure"))]
1651 Union::Shared(ref cell, ..) => crate::func::locked_read(cell).clone(),
1652 _ => self.clone(),
1653 }
1654 }
1655 #[inline]
1662 pub fn flatten(self) -> Self {
1663 match self.0 {
1664 #[cfg(not(feature = "no_closure"))]
1665 Union::Shared(cell, ..) => crate::func::native::shared_try_take(cell).map_or_else(
1666 |ref cell| crate::func::locked_read(cell).clone(),
1667 #[cfg(not(feature = "sync"))]
1668 crate::Locked::into_inner,
1669 #[cfg(feature = "sync")]
1670 |value| value.into_inner().unwrap(),
1671 ),
1672 _ => self,
1673 }
1674 }
1675 #[cfg(not(feature = "no_closure"))]
1685 #[inline]
1686 #[must_use]
1687 pub fn is_locked(&self) -> bool {
1688 #[cfg(not(feature = "no_closure"))]
1689 if let Union::Shared(ref _cell, ..) = self.0 {
1690 #[cfg(not(feature = "sync"))]
1691 return _cell.try_borrow().is_err();
1692 #[cfg(feature = "sync")]
1693 return false;
1694 }
1695
1696 false
1697 }
1698 #[inline]
1708 pub fn read_lock<T: Any + Clone>(&self) -> Option<DynamicReadLock<T>> {
1709 match self.0 {
1710 #[cfg(not(feature = "no_closure"))]
1711 Union::Shared(ref cell, ..) => {
1712 let value = crate::func::locked_read(cell);
1713
1714 return if (*value).type_id() != TypeId::of::<T>()
1715 && TypeId::of::<Self>() != TypeId::of::<T>()
1716 {
1717 None
1718 } else {
1719 Some(DynamicReadLock(DynamicReadLockInner::Guard(value)))
1720 };
1721 }
1722 _ => (),
1723 }
1724
1725 self.downcast_ref()
1726 .map(DynamicReadLockInner::Reference)
1727 .map(DynamicReadLock)
1728 }
1729 #[inline]
1739 pub fn write_lock<T: Any + Clone>(&mut self) -> Option<DynamicWriteLock<T>> {
1740 match self.0 {
1741 #[cfg(not(feature = "no_closure"))]
1742 Union::Shared(ref cell, ..) => {
1743 let guard = crate::func::locked_write(cell);
1744
1745 return if (*guard).type_id() != TypeId::of::<T>()
1746 && TypeId::of::<Self>() != TypeId::of::<T>()
1747 {
1748 None
1749 } else {
1750 Some(DynamicWriteLock(DynamicWriteLockInner::Guard(guard)))
1751 };
1752 }
1753 _ => (),
1754 }
1755
1756 self.downcast_mut()
1757 .map(DynamicWriteLockInner::Reference)
1758 .map(DynamicWriteLock)
1759 }
1760 #[inline]
1765 #[must_use]
1766 pub(crate) fn downcast_ref<T: Any + Clone + ?Sized>(&self) -> Option<&T> {
1767 if TypeId::of::<T>() == TypeId::of::<INT>() {
1770 return match self.0 {
1771 Union::Int(ref v, ..) => v.as_any().downcast_ref::<T>(),
1772 _ => None,
1773 };
1774 }
1775 #[cfg(not(feature = "no_float"))]
1776 if TypeId::of::<T>() == TypeId::of::<crate::FLOAT>() {
1777 return match self.0 {
1778 Union::Float(ref v, ..) => v.as_ref().as_any().downcast_ref::<T>(),
1779 _ => None,
1780 };
1781 }
1782 #[cfg(feature = "decimal")]
1783 if TypeId::of::<T>() == TypeId::of::<rust_decimal::Decimal>() {
1784 return match self.0 {
1785 Union::Decimal(ref v, ..) => v.as_ref().as_any().downcast_ref::<T>(),
1786 _ => None,
1787 };
1788 }
1789 if TypeId::of::<T>() == TypeId::of::<bool>() {
1790 return match self.0 {
1791 Union::Bool(ref v, ..) => v.as_any().downcast_ref::<T>(),
1792 _ => None,
1793 };
1794 }
1795 if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
1796 return match self.0 {
1797 Union::Str(ref v, ..) => v.as_any().downcast_ref::<T>(),
1798 _ => None,
1799 };
1800 }
1801 if TypeId::of::<T>() == TypeId::of::<char>() {
1802 return match self.0 {
1803 Union::Char(ref v, ..) => v.as_any().downcast_ref::<T>(),
1804 _ => None,
1805 };
1806 }
1807 #[cfg(not(feature = "no_index"))]
1808 if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
1809 return match self.0 {
1810 Union::Array(ref v, ..) => v.as_ref().as_any().downcast_ref::<T>(),
1811 _ => None,
1812 };
1813 }
1814 #[cfg(not(feature = "no_index"))]
1815 if TypeId::of::<T>() == TypeId::of::<crate::Blob>() {
1816 return match self.0 {
1817 Union::Blob(ref v, ..) => v.as_ref().as_any().downcast_ref::<T>(),
1818 _ => None,
1819 };
1820 }
1821 #[cfg(not(feature = "no_object"))]
1822 if TypeId::of::<T>() == TypeId::of::<crate::Map>() {
1823 return match self.0 {
1824 Union::Map(ref v, ..) => v.as_ref().as_any().downcast_ref::<T>(),
1825 _ => None,
1826 };
1827 }
1828 if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
1829 return match self.0 {
1830 Union::FnPtr(ref v, ..) => v.as_ref().as_any().downcast_ref::<T>(),
1831 _ => None,
1832 };
1833 }
1834 #[cfg(not(feature = "no_time"))]
1835 if TypeId::of::<T>() == TypeId::of::<Instant>() {
1836 return match self.0 {
1837 Union::TimeStamp(ref v, ..) => v.as_ref().as_any().downcast_ref::<T>(),
1838 _ => None,
1839 };
1840 }
1841 if TypeId::of::<T>() == TypeId::of::<()>() {
1842 return match self.0 {
1843 Union::Unit(ref v, ..) => v.as_any().downcast_ref::<T>(),
1844 _ => None,
1845 };
1846 }
1847 if TypeId::of::<T>() == TypeId::of::<Self>() {
1848 return self.as_any().downcast_ref::<T>();
1849 }
1850
1851 match self.0 {
1852 Union::Variant(ref v, ..) => (***v).as_any().downcast_ref::<T>(),
1853 #[cfg(not(feature = "no_closure"))]
1854 Union::Shared(..) => None,
1855 _ => None,
1856 }
1857 }
1858 #[inline]
1863 #[must_use]
1864 pub(crate) fn downcast_mut<T: Any + Clone + ?Sized>(&mut self) -> Option<&mut T> {
1865 if TypeId::of::<T>() == TypeId::of::<INT>() {
1868 return match self.0 {
1869 Union::Int(ref mut v, ..) => v.as_any_mut().downcast_mut::<T>(),
1870 _ => None,
1871 };
1872 }
1873 #[cfg(not(feature = "no_float"))]
1874 if TypeId::of::<T>() == TypeId::of::<crate::FLOAT>() {
1875 return match self.0 {
1876 Union::Float(ref mut v, ..) => v.as_mut().as_any_mut().downcast_mut::<T>(),
1877 _ => None,
1878 };
1879 }
1880 #[cfg(feature = "decimal")]
1881 if TypeId::of::<T>() == TypeId::of::<rust_decimal::Decimal>() {
1882 return match self.0 {
1883 Union::Decimal(ref mut v, ..) => v.as_mut().as_any_mut().downcast_mut::<T>(),
1884 _ => None,
1885 };
1886 }
1887 if TypeId::of::<T>() == TypeId::of::<bool>() {
1888 return match self.0 {
1889 Union::Bool(ref mut v, ..) => v.as_any_mut().downcast_mut::<T>(),
1890 _ => None,
1891 };
1892 }
1893 if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
1894 return match self.0 {
1895 Union::Str(ref mut v, ..) => v.as_any_mut().downcast_mut::<T>(),
1896 _ => None,
1897 };
1898 }
1899 if TypeId::of::<T>() == TypeId::of::<char>() {
1900 return match self.0 {
1901 Union::Char(ref mut v, ..) => v.as_any_mut().downcast_mut::<T>(),
1902 _ => None,
1903 };
1904 }
1905 #[cfg(not(feature = "no_index"))]
1906 if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
1907 return match self.0 {
1908 Union::Array(ref mut v, ..) => v.as_mut().as_any_mut().downcast_mut::<T>(),
1909 _ => None,
1910 };
1911 }
1912 #[cfg(not(feature = "no_index"))]
1913 if TypeId::of::<T>() == TypeId::of::<crate::Blob>() {
1914 return match self.0 {
1915 Union::Blob(ref mut v, ..) => v.as_mut().as_any_mut().downcast_mut::<T>(),
1916 _ => None,
1917 };
1918 }
1919 #[cfg(not(feature = "no_object"))]
1920 if TypeId::of::<T>() == TypeId::of::<crate::Map>() {
1921 return match self.0 {
1922 Union::Map(ref mut v, ..) => v.as_mut().as_any_mut().downcast_mut::<T>(),
1923 _ => None,
1924 };
1925 }
1926 if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
1927 return match self.0 {
1928 Union::FnPtr(ref mut v, ..) => v.as_mut().as_any_mut().downcast_mut::<T>(),
1929 _ => None,
1930 };
1931 }
1932 #[cfg(not(feature = "no_time"))]
1933 if TypeId::of::<T>() == TypeId::of::<Instant>() {
1934 return match self.0 {
1935 Union::TimeStamp(ref mut v, ..) => v.as_mut().as_any_mut().downcast_mut::<T>(),
1936 _ => None,
1937 };
1938 }
1939 if TypeId::of::<T>() == TypeId::of::<()>() {
1940 return match self.0 {
1941 Union::Unit(ref mut v, ..) => v.as_any_mut().downcast_mut::<T>(),
1942 _ => None,
1943 };
1944 }
1945 if TypeId::of::<T>() == TypeId::of::<Self>() {
1946 return self.as_any_mut().downcast_mut::<T>();
1947 }
1948
1949 match self.0 {
1950 Union::Variant(ref mut v, ..) => (***v).as_any_mut().downcast_mut::<T>(),
1951 #[cfg(not(feature = "no_closure"))]
1952 Union::Shared(..) => None,
1953 _ => None,
1954 }
1955 }
1956
1957 #[inline]
1959 #[must_use]
1960 pub fn is_unit(&self) -> bool {
1961 match self.0 {
1962 Union::Unit(..) => true,
1963 #[cfg(not(feature = "no_closure"))]
1964 Union::Shared(ref cell, ..) => {
1965 matches!(crate::func::locked_read(cell).0, Union::Unit(..))
1966 }
1967 _ => false,
1968 }
1969 }
1970 #[inline]
1972 #[must_use]
1973 pub fn is_int(&self) -> bool {
1974 match self.0 {
1975 Union::Int(..) => true,
1976 #[cfg(not(feature = "no_closure"))]
1977 Union::Shared(ref cell, ..) => {
1978 matches!(crate::func::locked_read(cell).0, Union::Int(..))
1979 }
1980 _ => false,
1981 }
1982 }
1983 #[cfg(not(feature = "no_float"))]
1987 #[inline]
1988 #[must_use]
1989 pub fn is_float(&self) -> bool {
1990 match self.0 {
1991 Union::Float(..) => true,
1992 #[cfg(not(feature = "no_closure"))]
1993 Union::Shared(ref cell, ..) => {
1994 matches!(crate::func::locked_read(cell).0, Union::Float(..))
1995 }
1996 _ => false,
1997 }
1998 }
1999 #[cfg(feature = "decimal")]
2003 #[inline]
2004 #[must_use]
2005 pub fn is_decimal(&self) -> bool {
2006 match self.0 {
2007 Union::Decimal(..) => true,
2008 #[cfg(not(feature = "no_closure"))]
2009 Union::Shared(ref cell, ..) => {
2010 matches!(crate::func::locked_read(cell).0, Union::Decimal(..))
2011 }
2012 _ => false,
2013 }
2014 }
2015 #[inline]
2017 #[must_use]
2018 pub fn is_bool(&self) -> bool {
2019 match self.0 {
2020 Union::Bool(..) => true,
2021 #[cfg(not(feature = "no_closure"))]
2022 Union::Shared(ref cell, ..) => {
2023 matches!(crate::func::locked_read(cell).0, Union::Bool(..))
2024 }
2025 _ => false,
2026 }
2027 }
2028 #[inline]
2030 #[must_use]
2031 pub fn is_char(&self) -> bool {
2032 match self.0 {
2033 Union::Char(..) => true,
2034 #[cfg(not(feature = "no_closure"))]
2035 Union::Shared(ref cell, ..) => {
2036 matches!(crate::func::locked_read(cell).0, Union::Char(..))
2037 }
2038 _ => false,
2039 }
2040 }
2041 #[inline]
2043 #[must_use]
2044 pub fn is_string(&self) -> bool {
2045 match self.0 {
2046 Union::Str(..) => true,
2047 #[cfg(not(feature = "no_closure"))]
2048 Union::Shared(ref cell, ..) => {
2049 matches!(crate::func::locked_read(cell).0, Union::Str(..))
2050 }
2051 _ => false,
2052 }
2053 }
2054 #[cfg(not(feature = "no_index"))]
2058 #[inline]
2059 #[must_use]
2060 pub fn is_array(&self) -> bool {
2061 match self.0 {
2062 Union::Array(..) => true,
2063 #[cfg(not(feature = "no_closure"))]
2064 Union::Shared(ref cell, ..) => {
2065 matches!(crate::func::locked_read(cell).0, Union::Array(..))
2066 }
2067 _ => false,
2068 }
2069 }
2070 #[cfg(not(feature = "no_index"))]
2074 #[inline]
2075 #[must_use]
2076 pub fn is_blob(&self) -> bool {
2077 match self.0 {
2078 Union::Blob(..) => true,
2079 #[cfg(not(feature = "no_closure"))]
2080 Union::Shared(ref cell, ..) => {
2081 matches!(crate::func::locked_read(cell).0, Union::Blob(..))
2082 }
2083 _ => false,
2084 }
2085 }
2086 #[cfg(not(feature = "no_object"))]
2090 #[inline]
2091 #[must_use]
2092 pub fn is_map(&self) -> bool {
2093 match self.0 {
2094 Union::Map(..) => true,
2095 #[cfg(not(feature = "no_closure"))]
2096 Union::Shared(ref cell, ..) => {
2097 matches!(crate::func::locked_read(cell).0, Union::Map(..))
2098 }
2099 _ => false,
2100 }
2101 }
2102 #[inline]
2104 #[must_use]
2105 pub fn is_fnptr(&self) -> bool {
2106 match self.0 {
2107 Union::FnPtr(..) => true,
2108 #[cfg(not(feature = "no_closure"))]
2109 Union::Shared(ref cell, ..) => {
2110 matches!(crate::func::locked_read(cell).0, Union::FnPtr(..))
2111 }
2112 _ => false,
2113 }
2114 }
2115 #[cfg(not(feature = "no_time"))]
2119 #[inline]
2120 #[must_use]
2121 pub fn is_timestamp(&self) -> bool {
2122 match self.0 {
2123 Union::TimeStamp(..) => true,
2124 #[cfg(not(feature = "no_closure"))]
2125 Union::Shared(ref cell, ..) => {
2126 matches!(crate::func::locked_read(cell).0, Union::TimeStamp(..))
2127 }
2128 _ => false,
2129 }
2130 }
2131
2132 #[inline]
2135 pub fn as_unit(&self) -> Result<(), &'static str> {
2136 match self.0 {
2137 Union::Unit(..) => Ok(()),
2138 #[cfg(not(feature = "no_closure"))]
2139 Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
2140 Union::Unit(..) => Ok(()),
2141 _ => Err(cell.type_name()),
2142 },
2143 _ => Err(self.type_name()),
2144 }
2145 }
2146 #[inline]
2149 pub fn as_int(&self) -> Result<INT, &'static str> {
2150 match self.0 {
2151 Union::Int(n, ..) => Ok(n),
2152 #[cfg(not(feature = "no_closure"))]
2153 Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
2154 Union::Int(n, ..) => Ok(n),
2155 _ => Err(cell.type_name()),
2156 },
2157 _ => Err(self.type_name()),
2158 }
2159 }
2160 #[cfg(not(feature = "no_float"))]
2165 #[inline]
2166 pub fn as_float(&self) -> Result<crate::FLOAT, &'static str> {
2167 match self.0 {
2168 Union::Float(n, ..) => Ok(*n),
2169 #[cfg(not(feature = "no_closure"))]
2170 Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
2171 Union::Float(n, ..) => Ok(*n),
2172 _ => Err(cell.type_name()),
2173 },
2174 _ => Err(self.type_name()),
2175 }
2176 }
2177 #[cfg(feature = "decimal")]
2182 #[inline]
2183 pub fn as_decimal(&self) -> Result<rust_decimal::Decimal, &'static str> {
2184 match self.0 {
2185 Union::Decimal(ref n, ..) => Ok(**n),
2186 #[cfg(not(feature = "no_closure"))]
2187 Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
2188 Union::Decimal(ref n, ..) => Ok(**n),
2189 _ => Err(cell.type_name()),
2190 },
2191 _ => Err(self.type_name()),
2192 }
2193 }
2194 #[inline]
2197 pub fn as_bool(&self) -> Result<bool, &'static str> {
2198 match self.0 {
2199 Union::Bool(b, ..) => Ok(b),
2200 #[cfg(not(feature = "no_closure"))]
2201 Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
2202 Union::Bool(b, ..) => Ok(b),
2203 _ => Err(cell.type_name()),
2204 },
2205 _ => Err(self.type_name()),
2206 }
2207 }
2208 #[inline]
2211 pub fn as_char(&self) -> Result<char, &'static str> {
2212 match self.0 {
2213 Union::Char(c, ..) => Ok(c),
2214 #[cfg(not(feature = "no_closure"))]
2215 Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
2216 Union::Char(c, ..) => Ok(c),
2217 _ => Err(cell.type_name()),
2218 },
2219 _ => Err(self.type_name()),
2220 }
2221 }
2222 #[inline]
2226 pub fn into_string(self) -> Result<String, &'static str> {
2227 self.into_immutable_string()
2228 .map(ImmutableString::into_owned)
2229 }
2230 #[inline]
2233 pub fn into_immutable_string(self) -> Result<ImmutableString, &'static str> {
2234 match self.0 {
2235 Union::Str(s, ..) => Ok(s),
2236 #[cfg(not(feature = "no_closure"))]
2237 Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
2238 Union::Str(ref s, ..) => Ok(s.clone()),
2239 _ => Err(cell.type_name()),
2240 },
2241 _ => Err(self.type_name()),
2242 }
2243 }
2244 #[cfg(not(feature = "no_index"))]
2249 #[inline(always)]
2250 pub fn into_array(self) -> Result<crate::Array, &'static str> {
2251 match self.0 {
2252 Union::Array(a, ..) => Ok(*a),
2253 #[cfg(not(feature = "no_closure"))]
2254 Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
2255 Union::Array(ref a, ..) => Ok(a.as_ref().clone()),
2256 _ => Err(cell.type_name()),
2257 },
2258 _ => Err(self.type_name()),
2259 }
2260 }
2261 #[cfg(not(feature = "no_index"))]
2266 #[inline(always)]
2267 pub fn into_typed_array<T: Variant + Clone>(self) -> Result<Vec<T>, &'static str> {
2268 match self.0 {
2269 Union::Array(a, ..) => a
2270 .into_iter()
2271 .map(|v| {
2272 #[cfg(not(feature = "no_closure"))]
2273 let typ = if v.is_shared() {
2274 "<shared>"
2276 } else {
2277 v.type_name()
2278 };
2279 #[cfg(feature = "no_closure")]
2280 let typ = v.type_name();
2281
2282 v.try_cast::<T>().ok_or(typ)
2283 })
2284 .collect(),
2285 Union::Blob(b, ..) if TypeId::of::<T>() == TypeId::of::<u8>() => {
2286 Ok(reify! { *b => !!! Vec<T> })
2287 }
2288 #[cfg(not(feature = "no_closure"))]
2289 Union::Shared(ref cell, ..) => {
2290 match crate::func::locked_read(cell).0 {
2291 Union::Array(ref a, ..) => {
2292 a.iter()
2293 .map(|v| {
2294 #[cfg(not(feature = "no_closure"))]
2295 let typ = if v.is_shared() {
2296 "<shared>"
2298 } else {
2299 v.type_name()
2300 };
2301 #[cfg(feature = "no_closure")]
2302 let typ = v.type_name();
2303
2304 v.read_lock::<T>().ok_or(typ).map(|v| v.clone())
2305 })
2306 .collect()
2307 }
2308 Union::Blob(ref b, ..) if TypeId::of::<T>() == TypeId::of::<u8>() => {
2309 Ok(reify! { b.clone() => !!! Vec<T> })
2310 }
2311 _ => Err(cell.type_name()),
2312 }
2313 }
2314 _ => Err(self.type_name()),
2315 }
2316 }
2317 #[cfg(not(feature = "no_index"))]
2322 #[inline(always)]
2323 pub fn into_blob(self) -> Result<crate::Blob, &'static str> {
2324 match self.0 {
2325 Union::Blob(b, ..) => Ok(*b),
2326 #[cfg(not(feature = "no_closure"))]
2327 Union::Shared(ref cell, ..) => match crate::func::locked_read(cell).0 {
2328 Union::Blob(ref b, ..) => Ok(b.as_ref().clone()),
2329 _ => Err(cell.type_name()),
2330 },
2331 _ => Err(self.type_name()),
2332 }
2333 }
2334
2335 #[inline]
2340 #[allow(clippy::only_used_in_recursion)]
2341 pub fn deep_scan(&mut self, mut filter: impl FnMut(&mut Self)) {
2342 fn scan_inner(value: &mut Dynamic, filter: &mut (impl FnMut(&mut Dynamic) + ?Sized)) {
2343 filter(value);
2344
2345 match &mut value.0 {
2346 #[cfg(not(feature = "no_index"))]
2347 Union::Array(a, ..) => a.iter_mut().for_each(|v| scan_inner(v, filter)),
2348 #[cfg(not(feature = "no_object"))]
2349 Union::Map(m, ..) => m.values_mut().for_each(|v| scan_inner(v, filter)),
2350 Union::FnPtr(f, ..) => f.iter_curry_mut().for_each(|v| scan_inner(v, filter)),
2351 _ => (),
2352 }
2353 }
2354
2355 scan_inner(self, &mut filter);
2356 }
2357}
2358
2359impl From<()> for Dynamic {
2360 #[inline(always)]
2361 fn from(value: ()) -> Self {
2362 Self(Union::Unit(value, DEFAULT_TAG_VALUE, ReadWrite))
2363 }
2364}
2365impl From<bool> for Dynamic {
2366 #[inline(always)]
2367 fn from(value: bool) -> Self {
2368 Self(Union::Bool(value, DEFAULT_TAG_VALUE, ReadWrite))
2369 }
2370}
2371impl From<INT> for Dynamic {
2372 #[inline(always)]
2373 fn from(value: INT) -> Self {
2374 Self(Union::Int(value, DEFAULT_TAG_VALUE, ReadWrite))
2375 }
2376}
2377#[cfg(not(feature = "no_float"))]
2378impl From<crate::FLOAT> for Dynamic {
2379 #[inline(always)]
2380 fn from(value: crate::FLOAT) -> Self {
2381 Self(Union::Float(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
2382 }
2383}
2384#[cfg(not(feature = "no_float"))]
2385impl From<super::FloatWrapper<crate::FLOAT>> for Dynamic {
2386 #[inline(always)]
2387 fn from(value: super::FloatWrapper<crate::FLOAT>) -> Self {
2388 Self(Union::Float(value, DEFAULT_TAG_VALUE, ReadWrite))
2389 }
2390}
2391#[cfg(feature = "decimal")]
2392impl From<rust_decimal::Decimal> for Dynamic {
2393 #[inline(always)]
2394 fn from(value: rust_decimal::Decimal) -> Self {
2395 Self(Union::Decimal(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
2396 }
2397}
2398impl From<char> for Dynamic {
2399 #[inline(always)]
2400 fn from(value: char) -> Self {
2401 Self(Union::Char(value, DEFAULT_TAG_VALUE, ReadWrite))
2402 }
2403}
2404impl<S: Into<ImmutableString>> From<S> for Dynamic {
2405 #[inline(always)]
2406 fn from(value: S) -> Self {
2407 Self(Union::Str(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
2408 }
2409}
2410impl FromStr for Dynamic {
2411 type Err = ();
2412
2413 fn from_str(value: &str) -> Result<Self, Self::Err> {
2414 Ok(Self(Union::Str(value.into(), DEFAULT_TAG_VALUE, ReadWrite)))
2415 }
2416}
2417#[cfg(not(feature = "no_index"))]
2418impl<T: Variant + Clone> From<Vec<T>> for Dynamic {
2419 #[inline]
2420 fn from(value: Vec<T>) -> Self {
2421 Self(Union::Array(
2422 Box::new(value.into_iter().map(Self::from).collect()),
2423 DEFAULT_TAG_VALUE,
2424 ReadWrite,
2425 ))
2426 }
2427}
2428#[cfg(not(feature = "no_index"))]
2429impl<T: Variant + Clone> From<&[T]> for Dynamic {
2430 #[inline]
2431 fn from(value: &[T]) -> Self {
2432 Self(Union::Array(
2433 Box::new(value.iter().cloned().map(Self::from).collect()),
2434 DEFAULT_TAG_VALUE,
2435 ReadWrite,
2436 ))
2437 }
2438}
2439#[cfg(not(feature = "no_index"))]
2440impl<T: Variant + Clone> std::iter::FromIterator<T> for Dynamic {
2441 #[inline]
2442 fn from_iter<X: IntoIterator<Item = T>>(iter: X) -> Self {
2443 Self(Union::Array(
2444 Box::new(iter.into_iter().map(Self::from).collect()),
2445 DEFAULT_TAG_VALUE,
2446 ReadWrite,
2447 ))
2448 }
2449}
2450#[cfg(not(feature = "no_object"))]
2451#[cfg(not(feature = "no_std"))]
2452impl<K: Into<crate::Identifier>, T: Variant + Clone> From<std::collections::HashMap<K, T>>
2453 for Dynamic
2454{
2455 #[inline]
2456 fn from(value: std::collections::HashMap<K, T>) -> Self {
2457 Self(Union::Map(
2458 Box::new(
2459 value
2460 .into_iter()
2461 .map(|(k, v)| (k.into(), Self::from(v)))
2462 .collect(),
2463 ),
2464 DEFAULT_TAG_VALUE,
2465 ReadWrite,
2466 ))
2467 }
2468}
2469#[cfg(not(feature = "no_object"))]
2470#[cfg(not(feature = "no_std"))]
2471impl<K: Into<crate::Identifier>> From<std::collections::HashSet<K>> for Dynamic {
2472 #[inline]
2473 fn from(value: std::collections::HashSet<K>) -> Self {
2474 Self(Union::Map(
2475 Box::new(value.into_iter().map(|k| (k.into(), Self::UNIT)).collect()),
2476 DEFAULT_TAG_VALUE,
2477 ReadWrite,
2478 ))
2479 }
2480}
2481#[cfg(not(feature = "no_object"))]
2482impl<K: Into<crate::Identifier>, T: Variant + Clone> From<std::collections::BTreeMap<K, T>>
2483 for Dynamic
2484{
2485 #[inline]
2486 fn from(value: std::collections::BTreeMap<K, T>) -> Self {
2487 Self(Union::Map(
2488 Box::new(
2489 value
2490 .into_iter()
2491 .map(|(k, v)| (k.into(), Self::from(v)))
2492 .collect(),
2493 ),
2494 DEFAULT_TAG_VALUE,
2495 ReadWrite,
2496 ))
2497 }
2498}
2499#[cfg(not(feature = "no_object"))]
2500#[cfg(feature = "indexmap")]
2501impl<K: Into<crate::Identifier>, T: Variant + Clone> From<indexmap::IndexMap<K, T>> for Dynamic {
2502 #[inline]
2503 fn from(value: indexmap::IndexMap<K, T>) -> Self {
2504 Self(Union::Map(
2505 Box::new(
2506 value
2507 .into_iter()
2508 .map(|(k, v)| (k.into(), Self::from(v)))
2509 .collect(),
2510 ),
2511 DEFAULT_TAG_VALUE,
2512 ReadWrite,
2513 ))
2514 }
2515}
2516#[cfg(not(feature = "no_object"))]
2517impl<K: Into<crate::Identifier>> From<std::collections::BTreeSet<K>> for Dynamic {
2518 #[inline]
2519 fn from(value: std::collections::BTreeSet<K>) -> Self {
2520 Self(Union::Map(
2521 Box::new(value.into_iter().map(|k| (k.into(), Self::UNIT)).collect()),
2522 DEFAULT_TAG_VALUE,
2523 ReadWrite,
2524 ))
2525 }
2526}
2527impl From<FnPtr> for Dynamic {
2528 #[inline(always)]
2529 fn from(value: FnPtr) -> Self {
2530 Self(Union::FnPtr(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
2531 }
2532}
2533#[cfg(not(feature = "no_time"))]
2534impl From<Instant> for Dynamic {
2535 #[inline(always)]
2536 fn from(value: Instant) -> Self {
2537 Self(Union::TimeStamp(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
2538 }
2539}
2540#[cfg(not(feature = "no_closure"))]
2541impl From<crate::Shared<crate::Locked<Self>>> for Dynamic {
2542 #[inline(always)]
2543 fn from(value: crate::Shared<crate::Locked<Self>>) -> Self {
2544 Self(Union::Shared(value, DEFAULT_TAG_VALUE, ReadWrite))
2545 }
2546}
2547
2548impl From<ExclusiveRange> for Dynamic {
2549 #[inline(always)]
2550 fn from(value: ExclusiveRange) -> Self {
2551 Self::from(value)
2552 }
2553}
2554impl From<InclusiveRange> for Dynamic {
2555 #[inline(always)]
2556 fn from(value: InclusiveRange) -> Self {
2557 Self::from(value)
2558 }
2559}