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#[cfg(not(feature = "no_index"))]
26use crate::{Array, Blob};
27
28#[cfg(not(feature = "no_object"))]
29use crate::Map;
30
31#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
34#[non_exhaustive]
35pub enum AccessMode {
36 ReadWrite,
38 ReadOnly,
40}
41
42#[cfg(target_pointer_width = "64")]
44pub type Tag = i32;
45
46#[cfg(target_pointer_width = "32")]
48pub type Tag = i16;
49
50const DEFAULT_TAG_VALUE: Tag = 0;
52
53#[must_use]
55pub struct Dynamic(pub(crate) Union);
56
57#[must_use]
61pub enum Union {
62 Unit((), Tag, AccessMode),
64 Bool(bool, Tag, AccessMode),
66 Str(ImmutableString, Tag, AccessMode),
68 Char(char, Tag, AccessMode),
70 Int(INT, Tag, AccessMode),
72 #[cfg(not(feature = "no_float"))]
74 Float(super::FloatWrapper<crate::FLOAT>, Tag, AccessMode),
75 #[cfg(feature = "decimal")]
78 Decimal(Box<rust_decimal::Decimal>, Tag, AccessMode),
79 #[cfg(not(feature = "no_index"))]
81 Array(Box<Array>, Tag, AccessMode),
82 #[cfg(not(feature = "no_index"))]
84 Blob(Box<Blob>, Tag, AccessMode),
85 #[cfg(not(feature = "no_object"))]
87 Map(Box<Map>, Tag, AccessMode),
88 FnPtr(Box<FnPtr>, Tag, AccessMode),
90 #[cfg(not(feature = "no_time"))]
92 TimeStamp(Box<Instant>, Tag, AccessMode),
93
94 Variant(Box<Box<dyn Variant>>, Tag, AccessMode),
99
100 #[cfg(not(feature = "no_closure"))]
102 Shared(crate::Shared<crate::Locked<Dynamic>>, Tag, AccessMode),
103}
104
105#[derive(Debug)]
111#[must_use]
112pub struct DynamicReadLock<'d, T: Clone>(DynamicReadLockInner<'d, T>);
113
114#[derive(Debug)]
116#[must_use]
117enum DynamicReadLockInner<'d, T: Clone> {
118 Reference(&'d T),
120
121 #[cfg(not(feature = "no_closure"))]
123 Guard(crate::func::native::LockGuard<'d, Dynamic>),
124}
125
126impl<'d, T: Any + Clone> Deref for DynamicReadLock<'d, T> {
127 type Target = T;
128
129 #[inline]
130 fn deref(&self) -> &Self::Target {
131 match self.0 {
132 DynamicReadLockInner::Reference(reference) => reference,
133 #[cfg(not(feature = "no_closure"))]
134 DynamicReadLockInner::Guard(ref guard) => guard.downcast_ref().unwrap(),
135 }
136 }
137}
138
139#[derive(Debug)]
145#[must_use]
146pub struct DynamicWriteLock<'d, T: Clone>(DynamicWriteLockInner<'d, T>);
147
148#[derive(Debug)]
150#[must_use]
151enum DynamicWriteLockInner<'d, T: Clone> {
152 Reference(&'d mut T),
154
155 #[cfg(not(feature = "no_closure"))]
157 Guard(crate::func::native::LockGuardMut<'d, Dynamic>),
158}
159
160impl<'d, T: Any + Clone> Deref for DynamicWriteLock<'d, T> {
161 type Target = T;
162
163 #[inline]
164 fn deref(&self) -> &Self::Target {
165 match self.0 {
166 DynamicWriteLockInner::Reference(ref reference) => reference,
167 #[cfg(not(feature = "no_closure"))]
168 DynamicWriteLockInner::Guard(ref guard) => guard.downcast_ref().unwrap(),
169 }
170 }
171}
172
173impl<'d, T: Any + Clone> DerefMut for DynamicWriteLock<'d, T> {
174 #[inline]
175 fn deref_mut(&mut self) -> &mut Self::Target {
176 match self.0 {
177 DynamicWriteLockInner::Reference(ref mut reference) => reference,
178 #[cfg(not(feature = "no_closure"))]
179 DynamicWriteLockInner::Guard(ref mut guard) => guard.downcast_mut().unwrap(),
180 }
181 }
182}
183
184impl Dynamic {
185 #[must_use]
187 pub const fn tag(&self) -> Tag {
188 match self.0 {
189 Union::Unit((), tag, _)
190 | Union::Bool(_, tag, _)
191 | Union::Str(_, tag, _)
192 | Union::Char(_, tag, _)
193 | Union::Int(_, tag, _)
194 | Union::FnPtr(_, tag, _)
195 | Union::Variant(_, tag, _) => tag,
196
197 #[cfg(not(feature = "no_float"))]
198 Union::Float(_, tag, _) => tag,
199 #[cfg(feature = "decimal")]
200 Union::Decimal(_, tag, _) => tag,
201 #[cfg(not(feature = "no_index"))]
202 Union::Array(_, tag, _) | Union::Blob(_, tag, _) => tag,
203 #[cfg(not(feature = "no_object"))]
204 Union::Map(_, tag, _) => tag,
205 #[cfg(not(feature = "no_time"))]
206 Union::TimeStamp(_, tag, _) => tag,
207 #[cfg(not(feature = "no_closure"))]
208 Union::Shared(_, tag, _) => tag,
209 }
210 }
211 pub fn set_tag(&mut self, value: Tag) -> &mut Self {
213 match self.0 {
214 Union::Unit((), ref mut tag, _)
215 | Union::Bool(_, ref mut tag, _)
216 | Union::Str(_, ref mut tag, _)
217 | Union::Char(_, ref mut tag, _)
218 | Union::Int(_, ref mut tag, _)
219 | Union::FnPtr(_, ref mut tag, _)
220 | Union::Variant(_, ref mut tag, _) => *tag = value,
221
222 #[cfg(not(feature = "no_float"))]
223 Union::Float(_, ref mut tag, _) => *tag = value,
224 #[cfg(feature = "decimal")]
225 Union::Decimal(_, ref mut tag, _) => *tag = value,
226 #[cfg(not(feature = "no_index"))]
227 Union::Array(_, ref mut tag, _) | Union::Blob(_, ref mut tag, _) => *tag = value,
228 #[cfg(not(feature = "no_object"))]
229 Union::Map(_, ref mut tag, _) => *tag = value,
230 #[cfg(not(feature = "no_time"))]
231 Union::TimeStamp(_, ref mut tag, _) => *tag = value,
232 #[cfg(not(feature = "no_closure"))]
233 Union::Shared(_, ref mut tag, _) => *tag = value,
234 }
235 self
236 }
237 #[inline(always)]
240 #[must_use]
241 pub const fn is_variant(&self) -> bool {
242 matches!(self.0, Union::Variant(..))
243 }
244 #[cfg(not(feature = "no_closure"))]
248 #[inline(always)]
249 #[must_use]
250 pub const fn is_shared(&self) -> bool {
251 matches!(self.0, Union::Shared(..))
252 }
253 #[inline]
260 #[must_use]
261 pub fn is<T: Any + Clone>(&self) -> bool {
262 #[cfg(not(feature = "no_closure"))]
263 if self.is_shared() {
264 return TypeId::of::<T>() == self.type_id();
265 }
266
267 if TypeId::of::<T>() == TypeId::of::<()>() {
268 return matches!(self.0, Union::Unit(..));
269 }
270 if TypeId::of::<T>() == TypeId::of::<bool>() {
271 return matches!(self.0, Union::Bool(..));
272 }
273 if TypeId::of::<T>() == TypeId::of::<char>() {
274 return matches!(self.0, Union::Char(..));
275 }
276 if TypeId::of::<T>() == TypeId::of::<INT>() {
277 return matches!(self.0, Union::Int(..));
278 }
279 #[cfg(not(feature = "no_float"))]
280 if TypeId::of::<T>() == TypeId::of::<crate::FLOAT>() {
281 return matches!(self.0, Union::Float(..));
282 }
283 if TypeId::of::<T>() == TypeId::of::<ImmutableString>()
284 || TypeId::of::<T>() == TypeId::of::<String>()
285 {
286 return matches!(self.0, Union::Str(..));
287 }
288 #[cfg(not(feature = "no_index"))]
289 if TypeId::of::<T>() == TypeId::of::<Array>() {
290 return matches!(self.0, Union::Array(..));
291 }
292 #[cfg(not(feature = "no_index"))]
293 if TypeId::of::<T>() == TypeId::of::<Blob>() {
294 return matches!(self.0, Union::Blob(..));
295 }
296 #[cfg(not(feature = "no_object"))]
297 if TypeId::of::<T>() == TypeId::of::<Map>() {
298 return matches!(self.0, Union::Map(..));
299 }
300 #[cfg(feature = "decimal")]
301 if TypeId::of::<T>() == TypeId::of::<rust_decimal::Decimal>() {
302 return matches!(self.0, Union::Decimal(..));
303 }
304 if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
305 return matches!(self.0, Union::FnPtr(..));
306 }
307 #[cfg(not(feature = "no_time"))]
308 if TypeId::of::<T>() == TypeId::of::<crate::Instant>() {
309 return matches!(self.0, Union::TimeStamp(..));
310 }
311
312 TypeId::of::<T>() == self.type_id()
313 }
314 #[must_use]
321 pub fn type_id(&self) -> TypeId {
322 match self.0 {
323 Union::Unit(..) => TypeId::of::<()>(),
324 Union::Bool(..) => TypeId::of::<bool>(),
325 Union::Str(..) => TypeId::of::<ImmutableString>(),
326 Union::Char(..) => TypeId::of::<char>(),
327 Union::Int(..) => TypeId::of::<INT>(),
328 #[cfg(not(feature = "no_float"))]
329 Union::Float(..) => TypeId::of::<crate::FLOAT>(),
330 #[cfg(feature = "decimal")]
331 Union::Decimal(..) => TypeId::of::<rust_decimal::Decimal>(),
332 #[cfg(not(feature = "no_index"))]
333 Union::Array(..) => TypeId::of::<Array>(),
334 #[cfg(not(feature = "no_index"))]
335 Union::Blob(..) => TypeId::of::<Blob>(),
336 #[cfg(not(feature = "no_object"))]
337 Union::Map(..) => TypeId::of::<Map>(),
338 Union::FnPtr(..) => TypeId::of::<FnPtr>(),
339 #[cfg(not(feature = "no_time"))]
340 Union::TimeStamp(..) => TypeId::of::<Instant>(),
341
342 Union::Variant(ref v, ..) => (***v).type_id(),
343
344 #[cfg(not(feature = "no_closure"))]
345 Union::Shared(ref cell, ..) => (*crate::func::locked_read(cell).unwrap()).type_id(),
346 }
347 }
348 #[must_use]
355 pub fn type_name(&self) -> &'static str {
356 match self.0 {
357 Union::Unit(..) => "()",
358 Union::Bool(..) => "bool",
359 Union::Str(..) => "string",
360 Union::Char(..) => "char",
361 Union::Int(..) => type_name::<INT>(),
362 #[cfg(not(feature = "no_float"))]
363 Union::Float(..) => type_name::<crate::FLOAT>(),
364 #[cfg(feature = "decimal")]
365 Union::Decimal(..) => "decimal",
366 #[cfg(not(feature = "no_index"))]
367 Union::Array(..) => "array",
368 #[cfg(not(feature = "no_index"))]
369 Union::Blob(..) => "blob",
370 #[cfg(not(feature = "no_object"))]
371 Union::Map(..) => "map",
372 Union::FnPtr(..) => "Fn",
373 #[cfg(not(feature = "no_time"))]
374 Union::TimeStamp(..) => "timestamp",
375
376 Union::Variant(ref v, ..) => (***v).type_name(),
377
378 #[cfg(not(feature = "no_closure"))]
379 Union::Shared(ref cell, ..) => (*crate::func::locked_read(cell).unwrap()).type_name(),
380 }
381 }
382}
383
384impl Hash for Dynamic {
385 fn hash<H: Hasher>(&self, state: &mut H) {
391 mem::discriminant(&self.0).hash(state);
392
393 match self.0 {
394 Union::Unit(..) => (),
395 Union::Bool(ref b, ..) => b.hash(state),
396 Union::Str(ref s, ..) => s.hash(state),
397 Union::Char(ref c, ..) => c.hash(state),
398 Union::Int(ref i, ..) => i.hash(state),
399 #[cfg(not(feature = "no_float"))]
400 Union::Float(ref f, ..) => f.hash(state),
401 #[cfg(feature = "decimal")]
402 Union::Decimal(ref d, ..) => d.hash(state),
403 #[cfg(not(feature = "no_index"))]
404 Union::Array(ref a, ..) => a.hash(state),
405 #[cfg(not(feature = "no_index"))]
406 Union::Blob(ref a, ..) => a.hash(state),
407 #[cfg(not(feature = "no_object"))]
408 Union::Map(ref m, ..) => m.hash(state),
409 #[cfg(not(feature = "no_function"))]
410 Union::FnPtr(ref f, ..) if f.env.is_some() => {
411 unimplemented!("FnPtr with embedded environment cannot be hashed")
412 }
413 Union::FnPtr(ref f, ..) => {
414 f.fn_name().hash(state);
415 f.curry().hash(state);
416 }
417
418 #[cfg(not(feature = "no_closure"))]
419 Union::Shared(ref cell, ..) => (*crate::func::locked_read(cell).unwrap()).hash(state),
420
421 Union::Variant(ref v, ..) => {
422 let _value_any = (***v).as_any();
423
424 #[cfg(not(feature = "only_i32"))]
425 #[cfg(not(feature = "only_i64"))]
426 if let Some(value) = _value_any.downcast_ref::<u8>() {
427 return value.hash(state);
428 } else if let Some(value) = _value_any.downcast_ref::<u16>() {
429 return value.hash(state);
430 } else if let Some(value) = _value_any.downcast_ref::<u32>() {
431 return value.hash(state);
432 } else if let Some(value) = _value_any.downcast_ref::<u64>() {
433 return value.hash(state);
434 } else if let Some(value) = _value_any.downcast_ref::<i8>() {
435 return value.hash(state);
436 } else if let Some(value) = _value_any.downcast_ref::<i16>() {
437 return value.hash(state);
438 } else if let Some(value) = _value_any.downcast_ref::<i32>() {
439 return value.hash(state);
440 } else if let Some(value) = _value_any.downcast_ref::<i64>() {
441 return value.hash(state);
442 }
443
444 #[cfg(not(feature = "no_float"))]
445 #[cfg(not(feature = "f32_float"))]
446 if let Some(value) = _value_any.downcast_ref::<f32>() {
447 return value.to_ne_bytes().hash(state);
448 }
449 #[cfg(not(feature = "no_float"))]
450 #[cfg(feature = "f32_float")]
451 if let Some(value) = _value_any.downcast_ref::<f64>() {
452 return value.to_ne_bytes().hash(state);
453 }
454
455 #[cfg(not(feature = "only_i32"))]
456 #[cfg(not(feature = "only_i64"))]
457 #[cfg(not(target_family = "wasm"))]
458 if let Some(value) = _value_any.downcast_ref::<u128>() {
459 return value.hash(state);
460 } else if let Some(value) = _value_any.downcast_ref::<i128>() {
461 return value.hash(state);
462 }
463
464 if let Some(range) = _value_any.downcast_ref::<ExclusiveRange>() {
465 return range.hash(state);
466 } else if let Some(range) = _value_any.downcast_ref::<InclusiveRange>() {
467 return range.hash(state);
468 }
469
470 unimplemented!("Custom type {} cannot be hashed", self.type_name())
471 }
472
473 #[cfg(not(feature = "no_time"))]
474 Union::TimeStamp(..) => unimplemented!("Timestamp cannot be hashed"),
475 }
476 }
477}
478
479impl fmt::Display for Dynamic {
480 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
481 match self.0 {
482 Union::Unit(..) => Ok(()),
483 Union::Bool(ref v, ..) => fmt::Display::fmt(v, f),
484 Union::Str(ref v, ..) => fmt::Display::fmt(v, f),
485 Union::Char(ref v, ..) => fmt::Display::fmt(v, f),
486 Union::Int(ref v, ..) => fmt::Display::fmt(v, f),
487 #[cfg(not(feature = "no_float"))]
488 Union::Float(ref v, ..) => fmt::Display::fmt(v, f),
489 #[cfg(feature = "decimal")]
490 Union::Decimal(ref v, ..) => fmt::Display::fmt(v, f),
491 #[cfg(not(feature = "no_index"))]
492 Union::Array(..) => fmt::Debug::fmt(self, f),
493 #[cfg(not(feature = "no_index"))]
494 Union::Blob(..) => fmt::Debug::fmt(self, f),
495 #[cfg(not(feature = "no_object"))]
496 Union::Map(..) => fmt::Debug::fmt(self, f),
497 Union::FnPtr(ref v, ..) => fmt::Display::fmt(v, f),
498 #[cfg(not(feature = "no_time"))]
499 Union::TimeStamp(..) => f.write_str("<timestamp>"),
500
501 Union::Variant(ref v, ..) => {
502 let _value_any = (***v).as_any();
503 let _type_id = _value_any.type_id();
504
505 #[cfg(not(feature = "only_i32"))]
506 #[cfg(not(feature = "only_i64"))]
507 if let Some(value) = _value_any.downcast_ref::<u8>() {
508 return fmt::Display::fmt(value, f);
509 } else if let Some(value) = _value_any.downcast_ref::<u16>() {
510 return fmt::Display::fmt(value, f);
511 } else if let Some(value) = _value_any.downcast_ref::<u32>() {
512 return fmt::Display::fmt(value, f);
513 } else if let Some(value) = _value_any.downcast_ref::<u64>() {
514 return fmt::Display::fmt(value, f);
515 } else if let Some(value) = _value_any.downcast_ref::<i8>() {
516 return fmt::Display::fmt(value, f);
517 } else if let Some(value) = _value_any.downcast_ref::<i16>() {
518 return fmt::Display::fmt(value, f);
519 } else if let Some(value) = _value_any.downcast_ref::<i32>() {
520 return fmt::Display::fmt(value, f);
521 } else if let Some(value) = _value_any.downcast_ref::<i64>() {
522 return fmt::Display::fmt(value, f);
523 }
524
525 #[cfg(not(feature = "no_float"))]
526 #[cfg(not(feature = "f32_float"))]
527 if let Some(value) = _value_any.downcast_ref::<f32>() {
528 return fmt::Display::fmt(value, f);
529 }
530 #[cfg(not(feature = "no_float"))]
531 #[cfg(feature = "f32_float")]
532 if let Some(value) = _value_any.downcast_ref::<f64>() {
533 return fmt::Display::fmt(value, f);
534 }
535
536 #[cfg(not(feature = "only_i32"))]
537 #[cfg(not(feature = "only_i64"))]
538 #[cfg(not(target_family = "wasm"))]
539 if let Some(value) = _value_any.downcast_ref::<u128>() {
540 return fmt::Display::fmt(value, f);
541 } else if let Some(value) = _value_any.downcast_ref::<i128>() {
542 return fmt::Display::fmt(value, f);
543 }
544
545 if let Some(range) = _value_any.downcast_ref::<ExclusiveRange>() {
546 return if range.end == INT::MAX {
547 write!(f, "{}..", range.start)
548 } else {
549 write!(f, "{}..{}", range.start, range.end)
550 };
551 } else if let Some(range) = _value_any.downcast_ref::<InclusiveRange>() {
552 return if *range.end() == INT::MAX {
553 write!(f, "{}..=", range.start())
554 } else {
555 write!(f, "{}..={}", range.start(), range.end())
556 };
557 }
558
559 f.write_str((***v).type_name())
560 }
561
562 #[cfg(not(feature = "no_closure"))]
563 Union::Shared(ref cell, ..) if cfg!(feature = "unchecked") => {
564 match crate::func::locked_read(cell) {
565 Some(v) => write!(f, "{} (shared)", *v),
566 _ => f.write_str("<shared>"),
567 }
568 }
569 #[cfg(not(feature = "no_closure"))]
570 Union::Shared(..) => {
571 #[cfg(feature = "no_std")]
572 use hashbrown::HashSet;
573 #[cfg(not(feature = "no_std"))]
574 use std::collections::HashSet;
575
576 fn display_fmt_print(
578 f: &mut fmt::Formatter<'_>,
579 value: &Dynamic,
580 dict: &mut HashSet<*const Dynamic>,
581 ) -> fmt::Result {
582 match value.0 {
583 #[cfg(not(feature = "no_closure"))]
584 Union::Shared(ref cell, ..) => match crate::func::locked_read(cell) {
585 Some(v) => {
586 if dict.insert(value) {
587 display_fmt_print(f, &v, dict)?;
588 f.write_str(" (shared)")
589 } else {
590 f.write_str("<shared>")
591 }
592 }
593 _ => f.write_str("<shared>"),
594 },
595 #[cfg(not(feature = "no_index"))]
596 Union::Array(ref arr, ..) => {
597 dict.insert(value);
598
599 f.write_str("[")?;
600 for (i, v) in arr.iter().enumerate() {
601 if i > 0 {
602 f.write_str(", ")?;
603 }
604 display_fmt_print(f, v, dict)?;
605 }
606 f.write_str("]")
607 }
608 #[cfg(not(feature = "no_object"))]
609 Union::Map(ref map, ..) => {
610 dict.insert(value);
611
612 f.write_str("#{")?;
613 for (i, (k, v)) in map.iter().enumerate() {
614 if i > 0 {
615 f.write_str(", ")?;
616 }
617 fmt::Display::fmt(k, f)?;
618 f.write_str(": ")?;
619 display_fmt_print(f, v, dict)?;
620 }
621 f.write_str("}")
622 }
623 _ => fmt::Display::fmt(value, f),
624 }
625 }
626
627 display_fmt_print(f, self, &mut <_>::default())
628 }
629 }
630 }
631}
632
633impl fmt::Debug for Dynamic {
634 #[cold]
635 #[inline(never)]
636 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
637 match self.0 {
638 Union::Unit(ref v, ..) => fmt::Debug::fmt(v, f),
639 Union::Bool(ref v, ..) => fmt::Debug::fmt(v, f),
640 Union::Str(ref v, ..) => fmt::Debug::fmt(v, f),
641 Union::Char(ref v, ..) => fmt::Debug::fmt(v, f),
642 Union::Int(ref v, ..) => fmt::Debug::fmt(v, f),
643 #[cfg(not(feature = "no_float"))]
644 Union::Float(ref v, ..) => fmt::Debug::fmt(v, f),
645 #[cfg(feature = "decimal")]
646 Union::Decimal(ref v, ..) => fmt::Debug::fmt(v, f),
647 #[cfg(not(feature = "no_index"))]
648 Union::Array(ref v, ..) => fmt::Debug::fmt(v, f),
649 #[cfg(not(feature = "no_index"))]
650 Union::Blob(ref v, ..) => {
651 f.write_str("[")?;
652 v.iter().enumerate().try_for_each(|(i, v)| {
653 if i > 0 && i % 8 == 0 {
654 f.write_str(" ")?;
655 }
656 write!(f, "{v:02x}")
657 })?;
658 f.write_str("]")
659 }
660 #[cfg(not(feature = "no_object"))]
661 Union::Map(ref v, ..) => {
662 f.write_str("#")?;
663 fmt::Debug::fmt(v, f)
664 }
665 Union::FnPtr(ref v, ..) => fmt::Debug::fmt(v, f),
666 #[cfg(not(feature = "no_time"))]
667 Union::TimeStamp(..) => write!(f, "<timestamp>"),
668
669 Union::Variant(ref v, ..) => {
670 let _value_any = (***v).as_any();
671 let _type_id = _value_any.type_id();
672
673 #[cfg(not(feature = "only_i32"))]
674 #[cfg(not(feature = "only_i64"))]
675 if let Some(value) = _value_any.downcast_ref::<u8>() {
676 return fmt::Debug::fmt(value, f);
677 } else if let Some(value) = _value_any.downcast_ref::<u16>() {
678 return fmt::Debug::fmt(value, f);
679 } else if let Some(value) = _value_any.downcast_ref::<u32>() {
680 return fmt::Debug::fmt(value, f);
681 } else if let Some(value) = _value_any.downcast_ref::<u64>() {
682 return fmt::Debug::fmt(value, f);
683 } else if let Some(value) = _value_any.downcast_ref::<i8>() {
684 return fmt::Debug::fmt(value, f);
685 } else if let Some(value) = _value_any.downcast_ref::<i16>() {
686 return fmt::Debug::fmt(value, f);
687 } else if let Some(value) = _value_any.downcast_ref::<i32>() {
688 return fmt::Debug::fmt(value, f);
689 } else if let Some(value) = _value_any.downcast_ref::<i64>() {
690 return fmt::Debug::fmt(value, f);
691 }
692
693 #[cfg(not(feature = "no_float"))]
694 #[cfg(not(feature = "f32_float"))]
695 if let Some(value) = _value_any.downcast_ref::<f32>() {
696 return fmt::Debug::fmt(value, f);
697 }
698 #[cfg(not(feature = "no_float"))]
699 #[cfg(feature = "f32_float")]
700 if let Some(value) = _value_any.downcast_ref::<f64>() {
701 return fmt::Debug::fmt(value, f);
702 }
703
704 #[cfg(not(feature = "only_i32"))]
705 #[cfg(not(feature = "only_i64"))]
706 #[cfg(not(target_family = "wasm"))]
707 if let Some(value) = _value_any.downcast_ref::<u128>() {
708 return fmt::Debug::fmt(value, f);
709 } else if let Some(value) = _value_any.downcast_ref::<i128>() {
710 return fmt::Debug::fmt(value, f);
711 }
712
713 if let Some(range) = _value_any.downcast_ref::<ExclusiveRange>() {
714 return if range.end == INT::MAX {
715 write!(f, "{}..", range.start)
716 } else {
717 write!(f, "{}..{}", range.start, range.end)
718 };
719 } else if let Some(range) = _value_any.downcast_ref::<InclusiveRange>() {
720 return if *range.end() == INT::MAX {
721 write!(f, "{}..=", range.start())
722 } else {
723 write!(f, "{}..={}", range.start(), range.end())
724 };
725 }
726
727 f.write_str((***v).type_name())
728 }
729
730 #[cfg(not(feature = "no_closure"))]
731 Union::Shared(ref cell, ..) if cfg!(feature = "unchecked") => {
732 match crate::func::locked_read(cell) {
733 Some(v) => write!(f, "{:?} (shared)", *v),
734 _ => f.write_str("<shared>"),
735 }
736 }
737 #[cfg(not(feature = "no_closure"))]
738 Union::Shared(..) => {
739 #[cfg(feature = "no_std")]
740 use hashbrown::HashSet;
741 #[cfg(not(feature = "no_std"))]
742 use std::collections::HashSet;
743
744 fn checked_debug_fmt(
746 f: &mut fmt::Formatter<'_>,
747 value: &Dynamic,
748 dict: &mut HashSet<*const Dynamic>,
749 ) -> fmt::Result {
750 match value.0 {
751 Union::Shared(ref cell, ..) => match crate::func::locked_read(cell) {
752 Some(v) => {
753 if dict.insert(value) {
754 checked_debug_fmt(f, &v, dict)?;
755 f.write_str(" (shared)")
756 } else {
757 f.write_str("<shared>")
758 }
759 }
760 _ => f.write_str("<shared>"),
761 },
762 #[cfg(not(feature = "no_index"))]
763 Union::Array(ref arr, ..) => {
764 dict.insert(value);
765
766 f.write_str("[")?;
767 for (i, v) in arr.iter().enumerate() {
768 if i > 0 {
769 f.write_str(", ")?;
770 }
771 checked_debug_fmt(f, v, dict)?;
772 }
773 f.write_str("]")
774 }
775 #[cfg(not(feature = "no_object"))]
776 Union::Map(ref map, ..) => {
777 dict.insert(value);
778
779 f.write_str("#{")?;
780 for (i, (k, v)) in map.iter().enumerate() {
781 if i > 0 {
782 f.write_str(", ")?;
783 }
784 fmt::Debug::fmt(k, f)?;
785 f.write_str(": ")?;
786 checked_debug_fmt(f, v, dict)?;
787 }
788 f.write_str("}")
789 }
790 Union::FnPtr(ref fnptr, ..) => {
791 dict.insert(value);
792
793 fmt::Display::fmt(&fnptr.typ, f)?;
794 f.write_str("(")?;
795 fmt::Debug::fmt(fnptr.fn_name(), f)?;
796 for curry in &fnptr.curry {
797 f.write_str(", ")?;
798 checked_debug_fmt(f, curry, dict)?;
799 }
800 f.write_str(")")
801 }
802 _ => fmt::Debug::fmt(value, f),
803 }
804 }
805
806 checked_debug_fmt(f, self, &mut <_>::default())
807 }
808 }
809 }
810}
811
812#[allow(clippy::enum_glob_use)]
813use AccessMode::*;
814
815impl Clone for Dynamic {
816 fn clone(&self) -> Self {
822 match self.0 {
823 Union::Unit(v, tag, ..) => Self(Union::Unit(v, tag, ReadWrite)),
824 Union::Bool(v, tag, ..) => Self(Union::Bool(v, tag, ReadWrite)),
825 Union::Str(ref v, tag, ..) => Self(Union::Str(v.clone(), tag, ReadWrite)),
826 Union::Char(v, tag, ..) => Self(Union::Char(v, tag, ReadWrite)),
827 Union::Int(v, tag, ..) => Self(Union::Int(v, tag, ReadWrite)),
828 #[cfg(not(feature = "no_float"))]
829 Union::Float(v, tag, ..) => Self(Union::Float(v, tag, ReadWrite)),
830 #[cfg(feature = "decimal")]
831 Union::Decimal(ref v, tag, ..) => Self(Union::Decimal(v.clone(), tag, ReadWrite)),
832 #[cfg(not(feature = "no_index"))]
833 Union::Array(ref v, tag, ..) => Self(Union::Array(v.clone(), tag, ReadWrite)),
834 #[cfg(not(feature = "no_index"))]
835 Union::Blob(ref v, tag, ..) => Self(Union::Blob(v.clone(), tag, ReadWrite)),
836 #[cfg(not(feature = "no_object"))]
837 Union::Map(ref v, tag, ..) => Self(Union::Map(v.clone(), tag, ReadWrite)),
838 Union::FnPtr(ref v, tag, ..) => Self(Union::FnPtr(v.clone(), tag, ReadWrite)),
839 #[cfg(not(feature = "no_time"))]
840 Union::TimeStamp(ref v, tag, ..) => Self(Union::TimeStamp(v.clone(), tag, ReadWrite)),
841
842 Union::Variant(ref v, tag, ..) => Self(Union::Variant(
843 v.as_ref().as_ref().clone_object().into(),
844 tag,
845 ReadWrite,
846 )),
847
848 #[cfg(not(feature = "no_closure"))]
849 Union::Shared(ref cell, tag, ..) => Self(Union::Shared(cell.clone(), tag, ReadWrite)),
850 }
851 }
852}
853
854impl Default for Dynamic {
855 #[inline(always)]
856 fn default() -> Self {
857 Self::UNIT
858 }
859}
860
861#[cfg(not(feature = "no_float"))]
862#[cfg(feature = "f32_float")]
863use std::f32::consts as FloatConstants;
864#[cfg(not(feature = "no_float"))]
865#[cfg(not(feature = "f32_float"))]
866use std::f64::consts as FloatConstants;
867
868impl Dynamic {
869 pub const UNIT: Self = Self(Union::Unit((), DEFAULT_TAG_VALUE, ReadWrite));
871 pub const TRUE: Self = Self::from_bool(true);
873 pub const FALSE: Self = Self::from_bool(false);
875 pub const ZERO: Self = Self::from_int(0);
877 pub const ONE: Self = Self::from_int(1);
879 pub const TWO: Self = Self::from_int(2);
881 pub const THREE: Self = Self::from_int(3);
883 pub const TEN: Self = Self::from_int(10);
885 pub const HUNDRED: Self = Self::from_int(100);
887 pub const THOUSAND: Self = Self::from_int(1000);
889 pub const MILLION: Self = Self::from_int(1_000_000);
891 pub const NEGATIVE_ONE: Self = Self::from_int(-1);
893 pub const NEGATIVE_TWO: Self = Self::from_int(-2);
895 #[cfg(not(feature = "no_float"))]
899 pub const FLOAT_ZERO: Self = Self::from_float(0.0);
900 #[cfg(not(feature = "no_float"))]
904 pub const FLOAT_ONE: Self = Self::from_float(1.0);
905 #[cfg(not(feature = "no_float"))]
909 pub const FLOAT_TWO: Self = Self::from_float(2.0);
910 #[cfg(not(feature = "no_float"))]
914 pub const FLOAT_TEN: Self = Self::from_float(10.0);
915 #[cfg(not(feature = "no_float"))]
919 pub const FLOAT_HUNDRED: Self = Self::from_float(100.0);
920 #[cfg(not(feature = "no_float"))]
924 pub const FLOAT_THOUSAND: Self = Self::from_float(1000.0);
925 #[cfg(not(feature = "no_float"))]
929 pub const FLOAT_MILLION: Self = Self::from_float(1_000_000.0);
930 #[cfg(not(feature = "no_float"))]
934 pub const FLOAT_NEGATIVE_ONE: Self = Self::from_float(-1.0);
935 #[cfg(not(feature = "no_float"))]
939 pub const FLOAT_NEGATIVE_TWO: Self = Self::from_float(-2.0);
940 #[cfg(not(feature = "no_float"))]
944 pub const FLOAT_HALF: Self = Self::from_float(0.5);
945 #[cfg(not(feature = "no_float"))]
949 pub const FLOAT_QUARTER: Self = Self::from_float(0.25);
950 #[cfg(not(feature = "no_float"))]
954 pub const FLOAT_FIFTH: Self = Self::from_float(0.2);
955 #[cfg(not(feature = "no_float"))]
959 pub const FLOAT_TENTH: Self = Self::from_float(0.1);
960 #[cfg(not(feature = "no_float"))]
964 pub const FLOAT_HUNDREDTH: Self = Self::from_float(0.01);
965 #[cfg(not(feature = "no_float"))]
969 pub const FLOAT_THOUSANDTH: Self = Self::from_float(0.001);
970 #[cfg(not(feature = "no_float"))]
974 pub const FLOAT_MILLIONTH: Self = Self::from_float(0.000_001);
975 #[cfg(not(feature = "no_float"))]
979 pub const FLOAT_PI: Self = Self::from_float(FloatConstants::PI);
980 #[cfg(not(feature = "no_float"))]
984 pub const FLOAT_HALF_PI: Self = Self::from_float(FloatConstants::FRAC_PI_2);
985 #[cfg(not(feature = "no_float"))]
989 pub const FLOAT_QUARTER_PI: Self = Self::from_float(FloatConstants::FRAC_PI_4);
990 #[cfg(not(feature = "no_float"))]
994 pub const FLOAT_TWO_PI: Self = Self::from_float(FloatConstants::TAU);
995 #[cfg(not(feature = "no_float"))]
999 pub const FLOAT_INVERSE_PI: Self = Self::from_float(FloatConstants::FRAC_1_PI);
1000 #[cfg(not(feature = "no_float"))]
1004 pub const FLOAT_E: Self = Self::from_float(FloatConstants::E);
1005 #[cfg(not(feature = "no_float"))]
1009 pub const FLOAT_LOG_E: Self = Self::from_float(FloatConstants::LOG10_E);
1010 #[cfg(not(feature = "no_float"))]
1014 pub const FLOAT_LN_10: Self = Self::from_float(FloatConstants::LN_10);
1015
1016 #[inline(always)]
1018 pub const fn from_bool(value: bool) -> Self {
1019 Self(Union::Bool(value, DEFAULT_TAG_VALUE, ReadWrite))
1020 }
1021 #[inline(always)]
1023 pub const fn from_int(value: INT) -> Self {
1024 Self(Union::Int(value, DEFAULT_TAG_VALUE, ReadWrite))
1025 }
1026 #[inline(always)]
1028 pub const fn from_char(value: char) -> Self {
1029 Self(Union::Char(value, DEFAULT_TAG_VALUE, ReadWrite))
1030 }
1031 #[cfg(not(feature = "no_float"))]
1035 #[inline(always)]
1036 pub const fn from_float(value: crate::FLOAT) -> Self {
1037 Self(Union::Float(
1038 super::FloatWrapper::new(value),
1039 DEFAULT_TAG_VALUE,
1040 ReadWrite,
1041 ))
1042 }
1043 #[cfg(feature = "decimal")]
1047 #[inline(always)]
1048 pub fn from_decimal(value: rust_decimal::Decimal) -> Self {
1049 Self(Union::Decimal(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
1050 }
1051 #[cfg(not(feature = "no_index"))]
1053 #[inline(always)]
1054 pub fn from_array(array: Array) -> Self {
1055 Self(Union::Array(array.into(), DEFAULT_TAG_VALUE, ReadWrite))
1056 }
1057 #[cfg(not(feature = "no_index"))]
1059 #[inline(always)]
1060 pub fn from_blob(blob: Blob) -> Self {
1061 Self(Union::Blob(blob.into(), DEFAULT_TAG_VALUE, ReadWrite))
1062 }
1063 #[cfg(not(feature = "no_object"))]
1065 #[inline(always)]
1066 pub fn from_map(map: Map) -> Self {
1067 Self(Union::Map(map.into(), DEFAULT_TAG_VALUE, ReadWrite))
1068 }
1069 #[cfg(not(feature = "no_time"))]
1073 #[inline(always)]
1074 pub fn from_timestamp(value: Instant) -> Self {
1075 Self(Union::TimeStamp(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
1076 }
1077
1078 #[must_use]
1080 pub(crate) const fn access_mode(&self) -> AccessMode {
1081 match self.0 {
1082 Union::Unit(.., access)
1083 | Union::Bool(.., access)
1084 | Union::Str(.., access)
1085 | Union::Char(.., access)
1086 | Union::Int(.., access)
1087 | Union::FnPtr(.., access)
1088 | Union::Variant(.., access) => access,
1089
1090 #[cfg(not(feature = "no_float"))]
1091 Union::Float(.., access) => access,
1092 #[cfg(feature = "decimal")]
1093 Union::Decimal(.., access) => access,
1094 #[cfg(not(feature = "no_index"))]
1095 Union::Array(.., access) | Union::Blob(.., access) => access,
1096 #[cfg(not(feature = "no_object"))]
1097 Union::Map(.., access) => access,
1098 #[cfg(not(feature = "no_time"))]
1099 Union::TimeStamp(.., access) => access,
1100 #[cfg(not(feature = "no_closure"))]
1101 Union::Shared(.., access) => access,
1102 }
1103 }
1104 pub(crate) fn set_access_mode(&mut self, typ: AccessMode) -> &mut Self {
1106 match self.0 {
1107 Union::Unit(.., ref mut access)
1108 | Union::Bool(.., ref mut access)
1109 | Union::Str(.., ref mut access)
1110 | Union::Char(.., ref mut access)
1111 | Union::Int(.., ref mut access)
1112 | Union::FnPtr(.., ref mut access)
1113 | Union::Variant(.., ref mut access) => *access = typ,
1114
1115 #[cfg(not(feature = "no_float"))]
1116 Union::Float(.., ref mut access) => *access = typ,
1117 #[cfg(feature = "decimal")]
1118 Union::Decimal(.., ref mut access) => *access = typ,
1119 #[cfg(not(feature = "no_index"))]
1120 Union::Array(ref mut a, _, ref mut access) => {
1121 *access = typ;
1122 for v in a.as_mut() {
1123 v.set_access_mode(typ);
1124 }
1125 }
1126 #[cfg(not(feature = "no_index"))]
1127 Union::Blob(.., ref mut access) => *access = typ,
1128 #[cfg(not(feature = "no_object"))]
1129 Union::Map(ref mut m, _, ref mut access) => {
1130 *access = typ;
1131 for v in m.values_mut() {
1132 v.set_access_mode(typ);
1133 }
1134 }
1135 #[cfg(not(feature = "no_time"))]
1136 Union::TimeStamp(.., ref mut access) => *access = typ,
1137 #[cfg(not(feature = "no_closure"))]
1138 Union::Shared(.., ref mut access) => *access = typ,
1139 }
1140 self
1141 }
1142 #[inline(always)]
1144 pub fn into_read_only(self) -> Self {
1145 let mut value = self;
1146 value.set_access_mode(AccessMode::ReadOnly);
1147 value
1148 }
1149 #[must_use]
1174 pub fn is_read_only(&self) -> bool {
1175 #[cfg(not(feature = "no_closure"))]
1176 if let Union::Shared(ref cell, ..) = self.0 {
1177 return match crate::func::locked_read(cell).map_or(ReadWrite, |v| v.access_mode()) {
1178 ReadWrite => false,
1179 ReadOnly => true,
1180 };
1181 }
1182
1183 match self.access_mode() {
1184 ReadWrite => false,
1185 ReadOnly => true,
1186 }
1187 }
1188 #[must_use]
1202 pub(crate) fn is_hashable(&self) -> bool {
1203 match self.0 {
1204 Union::Unit(..)
1205 | Union::Bool(..)
1206 | Union::Str(..)
1207 | Union::Char(..)
1208 | Union::Int(..) => true,
1209
1210 #[cfg(not(feature = "no_float"))]
1211 Union::Float(..) => true,
1212 #[cfg(feature = "decimal")]
1213 Union::Decimal(..) => true,
1214 #[cfg(not(feature = "no_index"))]
1215 Union::Array(ref a, ..) => a.iter().all(Self::is_hashable),
1216 #[cfg(not(feature = "no_index"))]
1217 Union::Blob(..) => true,
1218 #[cfg(not(feature = "no_object"))]
1219 Union::Map(ref m, ..) => m.values().all(Self::is_hashable),
1220 #[cfg(not(feature = "no_function"))]
1221 Union::FnPtr(ref f, ..) if f.env.is_some() => false,
1222 Union::FnPtr(ref f, ..) => f.curry().iter().all(Self::is_hashable),
1223 #[cfg(not(feature = "no_time"))]
1224 Union::TimeStamp(..) => false,
1225
1226 Union::Variant(ref v, ..) => {
1227 let _value_any = (***v).as_any();
1228 let _type_id = _value_any.type_id();
1229
1230 #[cfg(not(feature = "only_i32"))]
1231 #[cfg(not(feature = "only_i64"))]
1232 if _type_id == TypeId::of::<u8>()
1233 || _type_id == TypeId::of::<u16>()
1234 || _type_id == TypeId::of::<u32>()
1235 || _type_id == TypeId::of::<u64>()
1236 || _type_id == TypeId::of::<i8>()
1237 || _type_id == TypeId::of::<i16>()
1238 || _type_id == TypeId::of::<i32>()
1239 || _type_id == TypeId::of::<i64>()
1240 {
1241 return true;
1242 }
1243
1244 #[cfg(not(feature = "no_float"))]
1245 #[cfg(not(feature = "f32_float"))]
1246 if _type_id == TypeId::of::<f32>() {
1247 return true;
1248 }
1249 #[cfg(not(feature = "no_float"))]
1250 #[cfg(feature = "f32_float")]
1251 if _type_id == TypeId::of::<f64>() {
1252 return true;
1253 }
1254
1255 #[cfg(not(feature = "only_i32"))]
1256 #[cfg(not(feature = "only_i64"))]
1257 #[cfg(not(target_family = "wasm"))]
1258 if _type_id == TypeId::of::<u128>() || _type_id == TypeId::of::<i128>() {
1259 return true;
1260 }
1261
1262 if _type_id == TypeId::of::<ExclusiveRange>()
1263 || _type_id == TypeId::of::<InclusiveRange>()
1264 {
1265 return true;
1266 }
1267
1268 false
1269 }
1270
1271 #[cfg(not(feature = "no_closure"))]
1272 Union::Shared(ref cell, ..) if cfg!(feature = "unchecked") => {
1273 crate::func::locked_read(cell).map_or(false, |v| v.is_hashable())
1274 }
1275 #[cfg(not(feature = "no_closure"))]
1276 Union::Shared(..) => {
1277 #[cfg(feature = "no_std")]
1278 use hashbrown::HashSet;
1279 #[cfg(not(feature = "no_std"))]
1280 use std::collections::HashSet;
1281
1282 fn checked_is_hashable(
1284 value: &Dynamic,
1285 dict: &mut HashSet<*const Dynamic>,
1286 ) -> bool {
1287 match value.0 {
1288 Union::Shared(ref cell, ..) => crate::func::locked_read(cell)
1289 .map_or(false, |v| {
1290 dict.insert(value) && checked_is_hashable(&v, dict)
1291 }),
1292 #[cfg(not(feature = "no_index"))]
1293 Union::Array(ref a, ..) => a.iter().all(|v| checked_is_hashable(v, dict)),
1294 #[cfg(not(feature = "no_object"))]
1295 Union::Map(ref m, ..) => m.values().all(|v| checked_is_hashable(v, dict)),
1296 Union::FnPtr(ref f, ..) => {
1297 f.env.is_none()
1298 && f.curry().iter().all(|v| checked_is_hashable(v, dict))
1299 }
1300 _ => value.is_hashable(),
1301 }
1302 }
1303
1304 checked_is_hashable(self, &mut <_>::default())
1305 }
1306 }
1307 }
1308 #[inline]
1373 pub fn from<T: Variant + Clone>(value: T) -> Self {
1374 reify! { value => |v: Self| return v }
1377 reify! { value => |v: INT| return v.into() }
1378
1379 #[cfg(not(feature = "no_float"))]
1380 reify! { value => |v: crate::FLOAT| return v.into() }
1381
1382 #[cfg(feature = "decimal")]
1383 reify! { value => |v: rust_decimal::Decimal| return v.into() }
1384
1385 reify! { value => |v: bool| return v.into() }
1386 reify! { value => |v: char| return v.into() }
1387 reify! { value => |v: ImmutableString| return v.into() }
1388 reify! { value => |v: String| return v.into() }
1389 reify! { value => |v: &str| return v.into() }
1390 reify! { value => |v: ()| return v.into() }
1391
1392 #[cfg(not(feature = "no_index"))]
1393 reify! { value => |v: Array| return v.into() }
1394 #[cfg(not(feature = "no_index"))]
1395 reify! { value => |v: Blob| return Self::from_blob(v) }
1397 #[cfg(not(feature = "no_object"))]
1398 reify! { value => |v: Map| return v.into() }
1399 reify! { value => |v: FnPtr| return v.into() }
1400
1401 #[cfg(not(feature = "no_time"))]
1402 reify! { value => |v: Instant| return v.into() }
1403 #[cfg(not(feature = "no_closure"))]
1404 reify! { value => |v: crate::Shared<crate::Locked<Self>>| return v.into() }
1405
1406 Self(Union::Variant(
1407 Box::new(Box::new(value)),
1408 DEFAULT_TAG_VALUE,
1409 ReadWrite,
1410 ))
1411 }
1412 #[cfg(not(feature = "no_closure"))]
1426 #[inline]
1427 pub fn into_shared(self) -> Self {
1428 let _access = self.access_mode();
1429
1430 match self.0 {
1431 Union::Shared(..) => self,
1432 _ => Self(Union::Shared(
1433 crate::Locked::new(self).into(),
1434 DEFAULT_TAG_VALUE,
1435 _access,
1436 )),
1437 }
1438 }
1439 #[inline(always)]
1441 pub fn take(&mut self) -> Self {
1442 mem::take(self)
1443 }
1444 #[inline(always)]
1474 #[must_use]
1475 #[allow(unused_mut)]
1476 pub fn try_cast<T: Any>(mut self) -> Option<T> {
1477 self.try_cast_result().ok()
1478 }
1479 #[allow(unused_mut)]
1499 pub fn try_cast_result<T: Any>(mut self) -> Result<T, Self> {
1500 #[cfg(not(feature = "no_closure"))]
1503 {
1504 self = self.flatten();
1505 }
1506
1507 if TypeId::of::<T>() == TypeId::of::<Self>() {
1508 return Ok(reify! { self => !!! T });
1509 }
1510 if TypeId::of::<T>() == TypeId::of::<()>() {
1511 return match self.0 {
1512 Union::Unit(..) => Ok(reify! { () => !!! T }),
1513 _ => Err(self),
1514 };
1515 }
1516 if TypeId::of::<T>() == TypeId::of::<INT>() {
1517 return match self.0 {
1518 Union::Int(n, ..) => Ok(reify! { n => !!! T }),
1519 _ => Err(self),
1520 };
1521 }
1522 #[cfg(not(feature = "no_float"))]
1523 if TypeId::of::<T>() == TypeId::of::<crate::FLOAT>() {
1524 return match self.0 {
1525 Union::Float(v, ..) => Ok(reify! { *v => !!! T }),
1526 _ => Err(self),
1527 };
1528 }
1529 #[cfg(feature = "decimal")]
1530 if TypeId::of::<T>() == TypeId::of::<rust_decimal::Decimal>() {
1531 return match self.0 {
1532 Union::Decimal(v, ..) => Ok(reify! { *v => !!! T }),
1533 _ => Err(self),
1534 };
1535 }
1536 if TypeId::of::<T>() == TypeId::of::<bool>() {
1537 return match self.0 {
1538 Union::Bool(b, ..) => Ok(reify! { b => !!! T }),
1539 _ => Err(self),
1540 };
1541 }
1542 if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
1543 return match self.0 {
1544 Union::Str(s, ..) => Ok(reify! { s => !!! T }),
1545 _ => Err(self),
1546 };
1547 }
1548 if TypeId::of::<T>() == TypeId::of::<String>() {
1549 return match self.0 {
1550 Union::Str(s, ..) => Ok(reify! { s.to_string() => !!! T }),
1551 _ => Err(self),
1552 };
1553 }
1554 if TypeId::of::<T>() == TypeId::of::<char>() {
1555 return match self.0 {
1556 Union::Char(c, ..) => Ok(reify! { c => !!! T }),
1557 _ => Err(self),
1558 };
1559 }
1560 #[cfg(not(feature = "no_index"))]
1561 if TypeId::of::<T>() == TypeId::of::<Array>() {
1562 return match self.0 {
1563 Union::Array(a, ..) => Ok(reify! { *a => !!! T }),
1564 _ => Err(self),
1565 };
1566 }
1567 #[cfg(not(feature = "no_index"))]
1568 if TypeId::of::<T>() == TypeId::of::<Blob>() {
1569 return match self.0 {
1570 Union::Blob(b, ..) => Ok(reify! { *b => !!! T }),
1571 _ => Err(self),
1572 };
1573 }
1574 #[cfg(not(feature = "no_object"))]
1575 if TypeId::of::<T>() == TypeId::of::<Map>() {
1576 return match self.0 {
1577 Union::Map(m, ..) => Ok(reify! { *m => !!! T }),
1578 _ => Err(self),
1579 };
1580 }
1581 if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
1582 return match self.0 {
1583 Union::FnPtr(f, ..) => Ok(reify! { *f => !!! T }),
1584 _ => Err(self),
1585 };
1586 }
1587 #[cfg(not(feature = "no_time"))]
1588 if TypeId::of::<T>() == TypeId::of::<Instant>() {
1589 return match self.0 {
1590 Union::TimeStamp(t, ..) => Ok(reify! { *t => !!! T }),
1591 _ => Err(self),
1592 };
1593 }
1594
1595 match self.0 {
1596 Union::Variant(v, ..) if TypeId::of::<T>() == (**v).type_id() => {
1597 Ok((*v).as_boxed_any().downcast().map(|x| *x).unwrap())
1598 }
1599 _ => Err(self),
1600 }
1601 }
1602 #[inline]
1633 #[must_use]
1634 pub fn cast<T: Any + Clone>(self) -> T {
1635 if TypeId::of::<T>() == TypeId::of::<Self>() {
1637 return reify! { self => !!! T };
1638 }
1639
1640 #[cfg(not(feature = "no_closure"))]
1641 let self_type_name = if self.is_shared() {
1642 "<shared>"
1644 } else {
1645 self.type_name()
1646 };
1647 #[cfg(feature = "no_closure")]
1648 let self_type_name = self.type_name();
1649
1650 self.try_cast::<T>()
1651 .unwrap_or_else(|| panic!("cannot cast {} to {}", self_type_name, type_name::<T>()))
1652 }
1653 #[inline(always)]
1684 #[must_use]
1685 pub fn clone_cast<T: Any + Clone>(&self) -> T {
1686 self.flatten_clone().cast::<T>()
1687 }
1688 #[inline]
1703 pub fn flatten_clone(&self) -> Self {
1704 match self.0 {
1705 #[cfg(not(feature = "no_closure"))]
1706 Union::Shared(ref cell, ..) => {
1707 crate::func::locked_read(cell).map_or_else(|| self.clone(), |v| v.flatten_clone())
1708 }
1709 _ => self.clone(),
1710 }
1711 }
1712 #[inline]
1729 pub fn flatten(self) -> Self {
1730 match self.0 {
1731 #[cfg(not(feature = "no_closure"))]
1732 Union::Shared(cell, tag, access) => match crate::func::native::shared_try_take(cell) {
1733 #[cfg(not(feature = "sync"))]
1735 Ok(value) => value.into_inner().flatten(),
1736 #[cfg(feature = "sync")]
1737 #[cfg(not(feature = "no_std"))]
1738 Ok(value) => value.into_inner().unwrap().flatten(),
1739 #[cfg(feature = "sync")]
1740 #[cfg(feature = "no_std")]
1741 Ok(value) => value.into_inner().flatten(),
1742 Err(cell) => {
1744 if let Some(guard) = crate::func::locked_read(&cell) {
1745 return guard.flatten_clone();
1746 }
1747 Self(Union::Shared(cell, tag, access))
1748 }
1749 },
1750 _ => self,
1751 }
1752 }
1753 #[cfg(not(feature = "no_closure"))]
1763 #[inline]
1764 #[must_use]
1765 pub fn is_locked(&self) -> bool {
1766 #[cfg(not(feature = "no_closure"))]
1767 if let Union::Shared(ref _cell, ..) = self.0 {
1768 #[cfg(not(feature = "sync"))]
1769 return _cell.try_borrow().is_err();
1770 #[cfg(feature = "sync")]
1771 return false;
1772 }
1773
1774 false
1775 }
1776 #[inline]
1791 pub fn read_lock<T: Any + Clone>(&self) -> Option<DynamicReadLock<T>> {
1792 match self.0 {
1793 #[cfg(not(feature = "no_closure"))]
1794 Union::Shared(ref cell, ..) => {
1795 return match crate::func::locked_read(cell) {
1796 Some(guard)
1797 if TypeId::of::<Self>() == TypeId::of::<T>()
1798 || (*guard).type_id() == TypeId::of::<T>() =>
1799 {
1800 Some(DynamicReadLock(DynamicReadLockInner::Guard(guard)))
1801 }
1802 _ => None,
1803 };
1804 }
1805 _ => (),
1806 }
1807
1808 self.downcast_ref()
1809 .map(DynamicReadLockInner::Reference)
1810 .map(DynamicReadLock)
1811 }
1812 #[inline]
1827 pub fn write_lock<T: Any + Clone>(&mut self) -> Option<DynamicWriteLock<T>> {
1828 match self.0 {
1829 #[cfg(not(feature = "no_closure"))]
1830 Union::Shared(ref cell, ..) => {
1831 return match crate::func::locked_write(cell) {
1832 Some(guard)
1833 if TypeId::of::<Self>() == TypeId::of::<T>()
1834 || (*guard).type_id() == TypeId::of::<T>() =>
1835 {
1836 Some(DynamicWriteLock(DynamicWriteLockInner::Guard(guard)))
1837 }
1838 _ => None,
1839 };
1840 }
1841 _ => (),
1842 }
1843
1844 self.downcast_mut()
1845 .map(DynamicWriteLockInner::Reference)
1846 .map(DynamicWriteLock)
1847 }
1848 #[inline]
1858 #[must_use]
1859 pub(crate) fn downcast_ref<T: Any + Clone + ?Sized>(&self) -> Option<&T> {
1860 if TypeId::of::<T>() == TypeId::of::<INT>() {
1863 return match self.0 {
1864 Union::Int(ref v, ..) => v.as_any().downcast_ref::<T>(),
1865 _ => None,
1866 };
1867 }
1868 #[cfg(not(feature = "no_float"))]
1869 if TypeId::of::<T>() == TypeId::of::<crate::FLOAT>() {
1870 return match self.0 {
1871 Union::Float(ref v, ..) => v.as_ref().as_any().downcast_ref::<T>(),
1872 _ => None,
1873 };
1874 }
1875 #[cfg(feature = "decimal")]
1876 if TypeId::of::<T>() == TypeId::of::<rust_decimal::Decimal>() {
1877 return match self.0 {
1878 Union::Decimal(ref v, ..) => v.as_ref().as_any().downcast_ref::<T>(),
1879 _ => None,
1880 };
1881 }
1882 if TypeId::of::<T>() == TypeId::of::<bool>() {
1883 return match self.0 {
1884 Union::Bool(ref v, ..) => v.as_any().downcast_ref::<T>(),
1885 _ => None,
1886 };
1887 }
1888 if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
1889 return match self.0 {
1890 Union::Str(ref v, ..) => v.as_any().downcast_ref::<T>(),
1891 _ => None,
1892 };
1893 }
1894 if TypeId::of::<T>() == TypeId::of::<char>() {
1895 return match self.0 {
1896 Union::Char(ref v, ..) => v.as_any().downcast_ref::<T>(),
1897 _ => None,
1898 };
1899 }
1900 #[cfg(not(feature = "no_index"))]
1901 if TypeId::of::<T>() == TypeId::of::<Array>() {
1902 return match self.0 {
1903 Union::Array(ref v, ..) => v.as_ref().as_any().downcast_ref::<T>(),
1904 _ => None,
1905 };
1906 }
1907 #[cfg(not(feature = "no_index"))]
1908 if TypeId::of::<T>() == TypeId::of::<Blob>() {
1909 return match self.0 {
1910 Union::Blob(ref v, ..) => v.as_ref().as_any().downcast_ref::<T>(),
1911 _ => None,
1912 };
1913 }
1914 #[cfg(not(feature = "no_object"))]
1915 if TypeId::of::<T>() == TypeId::of::<Map>() {
1916 return match self.0 {
1917 Union::Map(ref v, ..) => v.as_ref().as_any().downcast_ref::<T>(),
1918 _ => None,
1919 };
1920 }
1921 if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
1922 return match self.0 {
1923 Union::FnPtr(ref v, ..) => v.as_ref().as_any().downcast_ref::<T>(),
1924 _ => None,
1925 };
1926 }
1927 #[cfg(not(feature = "no_time"))]
1928 if TypeId::of::<T>() == TypeId::of::<Instant>() {
1929 return match self.0 {
1930 Union::TimeStamp(ref v, ..) => v.as_ref().as_any().downcast_ref::<T>(),
1931 _ => None,
1932 };
1933 }
1934 if TypeId::of::<T>() == TypeId::of::<()>() {
1935 return match self.0 {
1936 Union::Unit(ref v, ..) => v.as_any().downcast_ref::<T>(),
1937 _ => None,
1938 };
1939 }
1940 if TypeId::of::<T>() == TypeId::of::<Self>() {
1941 return self.as_any().downcast_ref::<T>();
1942 }
1943
1944 match self.0 {
1945 Union::Variant(ref v, ..) => (***v).as_any().downcast_ref::<T>(),
1946 #[cfg(not(feature = "no_closure"))]
1947 Union::Shared(..) => None,
1948 _ => None,
1949 }
1950 }
1951 #[inline]
1961 #[must_use]
1962 pub(crate) fn downcast_mut<T: Any + Clone + ?Sized>(&mut self) -> Option<&mut T> {
1963 if TypeId::of::<T>() == TypeId::of::<INT>() {
1966 return match self.0 {
1967 Union::Int(ref mut v, ..) => v.as_any_mut().downcast_mut::<T>(),
1968 _ => None,
1969 };
1970 }
1971 #[cfg(not(feature = "no_float"))]
1972 if TypeId::of::<T>() == TypeId::of::<crate::FLOAT>() {
1973 return match self.0 {
1974 Union::Float(ref mut v, ..) => v.as_mut().as_any_mut().downcast_mut::<T>(),
1975 _ => None,
1976 };
1977 }
1978 #[cfg(feature = "decimal")]
1979 if TypeId::of::<T>() == TypeId::of::<rust_decimal::Decimal>() {
1980 return match self.0 {
1981 Union::Decimal(ref mut v, ..) => v.as_mut().as_any_mut().downcast_mut::<T>(),
1982 _ => None,
1983 };
1984 }
1985 if TypeId::of::<T>() == TypeId::of::<bool>() {
1986 return match self.0 {
1987 Union::Bool(ref mut v, ..) => v.as_any_mut().downcast_mut::<T>(),
1988 _ => None,
1989 };
1990 }
1991 if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
1992 return match self.0 {
1993 Union::Str(ref mut v, ..) => v.as_any_mut().downcast_mut::<T>(),
1994 _ => None,
1995 };
1996 }
1997 if TypeId::of::<T>() == TypeId::of::<char>() {
1998 return match self.0 {
1999 Union::Char(ref mut v, ..) => v.as_any_mut().downcast_mut::<T>(),
2000 _ => None,
2001 };
2002 }
2003 #[cfg(not(feature = "no_index"))]
2004 if TypeId::of::<T>() == TypeId::of::<Array>() {
2005 return match self.0 {
2006 Union::Array(ref mut v, ..) => v.as_mut().as_any_mut().downcast_mut::<T>(),
2007 _ => None,
2008 };
2009 }
2010 #[cfg(not(feature = "no_index"))]
2011 if TypeId::of::<T>() == TypeId::of::<Blob>() {
2012 return match self.0 {
2013 Union::Blob(ref mut v, ..) => v.as_mut().as_any_mut().downcast_mut::<T>(),
2014 _ => None,
2015 };
2016 }
2017 #[cfg(not(feature = "no_object"))]
2018 if TypeId::of::<T>() == TypeId::of::<Map>() {
2019 return match self.0 {
2020 Union::Map(ref mut v, ..) => v.as_mut().as_any_mut().downcast_mut::<T>(),
2021 _ => None,
2022 };
2023 }
2024 if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
2025 return match self.0 {
2026 Union::FnPtr(ref mut v, ..) => v.as_mut().as_any_mut().downcast_mut::<T>(),
2027 _ => None,
2028 };
2029 }
2030 #[cfg(not(feature = "no_time"))]
2031 if TypeId::of::<T>() == TypeId::of::<Instant>() {
2032 return match self.0 {
2033 Union::TimeStamp(ref mut v, ..) => v.as_mut().as_any_mut().downcast_mut::<T>(),
2034 _ => None,
2035 };
2036 }
2037 if TypeId::of::<T>() == TypeId::of::<()>() {
2038 return match self.0 {
2039 Union::Unit(ref mut v, ..) => v.as_any_mut().downcast_mut::<T>(),
2040 _ => None,
2041 };
2042 }
2043 if TypeId::of::<T>() == TypeId::of::<Self>() {
2044 return self.as_any_mut().downcast_mut::<T>();
2045 }
2046
2047 match self.0 {
2048 Union::Variant(ref mut v, ..) => (***v).as_any_mut().downcast_mut::<T>(),
2049 #[cfg(not(feature = "no_closure"))]
2050 Union::Shared(..) => None,
2051 _ => None,
2052 }
2053 }
2054
2055 #[inline]
2066 #[must_use]
2067 pub fn is_unit(&self) -> bool {
2068 match self.0 {
2069 Union::Unit(..) => true,
2070 #[cfg(not(feature = "no_closure"))]
2071 Union::Shared(ref cell, ..) => {
2072 crate::func::locked_read(cell).map_or(false, |v| matches!(v.0, Union::Unit(..)))
2073 }
2074 _ => false,
2075 }
2076 }
2077 #[inline]
2088 #[must_use]
2089 pub fn is_int(&self) -> bool {
2090 match self.0 {
2091 Union::Int(..) => true,
2092 #[cfg(not(feature = "no_closure"))]
2093 Union::Shared(ref cell, ..) => {
2094 crate::func::locked_read(cell).map_or(false, |v| matches!(v.0, Union::Int(..)))
2095 }
2096 _ => false,
2097 }
2098 }
2099 #[cfg(not(feature = "no_float"))]
2112 #[inline]
2113 #[must_use]
2114 pub fn is_float(&self) -> bool {
2115 match self.0 {
2116 Union::Float(..) => true,
2117 #[cfg(not(feature = "no_closure"))]
2118 Union::Shared(ref cell, ..) => {
2119 crate::func::locked_read(cell).map_or(false, |v| matches!(v.0, Union::Float(..)))
2120 }
2121 _ => false,
2122 }
2123 }
2124 #[cfg(feature = "decimal")]
2136 #[inline]
2137 #[must_use]
2138 pub fn is_decimal(&self) -> bool {
2139 match self.0 {
2140 Union::Decimal(..) => true,
2141 #[cfg(not(feature = "no_closure"))]
2142 Union::Shared(ref cell, ..) => {
2143 crate::func::locked_read(cell).map_or(false, |v| matches!(v.0, Union::Decimal(..)))
2144 }
2145 _ => false,
2146 }
2147 }
2148 #[inline]
2159 #[must_use]
2160 pub fn is_bool(&self) -> bool {
2161 match self.0 {
2162 Union::Bool(..) => true,
2163 #[cfg(not(feature = "no_closure"))]
2164 Union::Shared(ref cell, ..) => {
2165 crate::func::locked_read(cell).map_or(false, |v| matches!(v.0, Union::Bool(..)))
2166 }
2167 _ => false,
2168 }
2169 }
2170 #[inline]
2181 #[must_use]
2182 pub fn is_char(&self) -> bool {
2183 match self.0 {
2184 Union::Char(..) => true,
2185 #[cfg(not(feature = "no_closure"))]
2186 Union::Shared(ref cell, ..) => {
2187 crate::func::locked_read(cell).map_or(false, |v| matches!(v.0, Union::Char(..)))
2188 }
2189 _ => false,
2190 }
2191 }
2192 #[inline]
2203 #[must_use]
2204 pub fn is_string(&self) -> bool {
2205 match self.0 {
2206 Union::Str(..) => true,
2207 #[cfg(not(feature = "no_closure"))]
2208 Union::Shared(ref cell, ..) => {
2209 crate::func::locked_read(cell).map_or(false, |v| matches!(v.0, Union::Str(..)))
2210 }
2211 _ => false,
2212 }
2213 }
2214 #[cfg(not(feature = "no_index"))]
2227 #[inline]
2228 #[must_use]
2229 pub fn is_array(&self) -> bool {
2230 match self.0 {
2231 Union::Array(..) => true,
2232 #[cfg(not(feature = "no_closure"))]
2233 Union::Shared(ref cell, ..) => {
2234 crate::func::locked_read(cell).map_or(false, |v| matches!(v.0, Union::Array(..)))
2235 }
2236 _ => false,
2237 }
2238 }
2239 #[cfg(not(feature = "no_index"))]
2252 #[inline]
2253 #[must_use]
2254 pub fn is_blob(&self) -> bool {
2255 match self.0 {
2256 Union::Blob(..) => true,
2257 #[cfg(not(feature = "no_closure"))]
2258 Union::Shared(ref cell, ..) => {
2259 crate::func::locked_read(cell).map_or(false, |v| matches!(v.0, Union::Blob(..)))
2260 }
2261 _ => false,
2262 }
2263 }
2264 #[cfg(not(feature = "no_object"))]
2277 #[inline]
2278 #[must_use]
2279 pub fn is_map(&self) -> bool {
2280 match self.0 {
2281 Union::Map(..) => true,
2282 #[cfg(not(feature = "no_closure"))]
2283 Union::Shared(ref cell, ..) => {
2284 crate::func::locked_read(cell).map_or(false, |v| matches!(v.0, Union::Map(..)))
2285 }
2286 _ => false,
2287 }
2288 }
2289 #[inline]
2300 #[must_use]
2301 pub fn is_fnptr(&self) -> bool {
2302 match self.0 {
2303 Union::FnPtr(..) => true,
2304 #[cfg(not(feature = "no_closure"))]
2305 Union::Shared(ref cell, ..) => {
2306 crate::func::locked_read(cell).map_or(false, |v| matches!(v.0, Union::FnPtr(..)))
2307 }
2308 _ => false,
2309 }
2310 }
2311 #[cfg(not(feature = "no_time"))]
2324 #[inline]
2325 #[must_use]
2326 pub fn is_timestamp(&self) -> bool {
2327 match self.0 {
2328 Union::TimeStamp(..) => true,
2329 #[cfg(not(feature = "no_closure"))]
2330 Union::Shared(ref cell, ..) => crate::func::locked_read(cell)
2331 .map_or(false, |v| matches!(v.0, Union::TimeStamp(..))),
2332 _ => false,
2333 }
2334 }
2335
2336 #[inline]
2351 pub fn as_unit(&self) -> Result<(), &'static str> {
2352 match self.0 {
2353 Union::Unit(..) => Ok(()),
2354 #[cfg(not(feature = "no_closure"))]
2355 Union::Shared(ref cell, ..) => crate::func::locked_read(cell)
2356 .and_then(|guard| match guard.0 {
2357 Union::Unit(..) => Some(()),
2358 _ => None,
2359 })
2360 .ok_or_else(|| cell.type_name()),
2361 _ => Err(self.type_name()),
2362 }
2363 }
2364 #[inline]
2379 pub fn as_int(&self) -> Result<INT, &'static str> {
2380 match self.0 {
2381 Union::Int(n, ..) => Ok(n),
2382 #[cfg(not(feature = "no_closure"))]
2383 Union::Shared(ref cell, ..) => crate::func::locked_read(cell)
2384 .and_then(|guard| match guard.0 {
2385 Union::Int(n, ..) => Some(n),
2386 _ => None,
2387 })
2388 .ok_or_else(|| cell.type_name()),
2389 _ => Err(self.type_name()),
2390 }
2391 }
2392 #[cfg(not(feature = "no_float"))]
2409 #[inline]
2410 pub fn as_float(&self) -> Result<crate::FLOAT, &'static str> {
2411 match self.0 {
2412 Union::Float(n, ..) => Ok(*n),
2413 #[cfg(not(feature = "no_closure"))]
2414 Union::Shared(ref cell, ..) => crate::func::locked_read(cell)
2415 .and_then(|guard| match guard.0 {
2416 Union::Float(n, ..) => Some(*n),
2417 _ => None,
2418 })
2419 .ok_or_else(|| cell.type_name()),
2420 _ => Err(self.type_name()),
2421 }
2422 }
2423 #[cfg(feature = "decimal")]
2439 #[inline]
2440 pub fn as_decimal(&self) -> Result<rust_decimal::Decimal, &'static str> {
2441 match self.0 {
2442 Union::Decimal(ref n, ..) => Ok(**n),
2443 #[cfg(not(feature = "no_closure"))]
2444 Union::Shared(ref cell, ..) => crate::func::locked_read(cell)
2445 .and_then(|guard| match guard.0 {
2446 Union::Decimal(ref n, ..) => Some(**n),
2447 _ => None,
2448 })
2449 .ok_or_else(|| cell.type_name()),
2450 _ => Err(self.type_name()),
2451 }
2452 }
2453 #[inline]
2468 pub fn as_bool(&self) -> Result<bool, &'static str> {
2469 match self.0 {
2470 Union::Bool(b, ..) => Ok(b),
2471 #[cfg(not(feature = "no_closure"))]
2472 Union::Shared(ref cell, ..) => crate::func::locked_read(cell)
2473 .and_then(|guard| match guard.0 {
2474 Union::Bool(b, ..) => Some(b),
2475 _ => None,
2476 })
2477 .ok_or_else(|| cell.type_name()),
2478 _ => Err(self.type_name()),
2479 }
2480 }
2481 #[inline]
2496 pub fn as_char(&self) -> Result<char, &'static str> {
2497 match self.0 {
2498 Union::Char(c, ..) => Ok(c),
2499 #[cfg(not(feature = "no_closure"))]
2500 Union::Shared(ref cell, ..) => crate::func::locked_read(cell)
2501 .and_then(|guard| match guard.0 {
2502 Union::Char(c, ..) => Some(c),
2503 _ => None,
2504 })
2505 .ok_or_else(|| cell.type_name()),
2506 _ => Err(self.type_name()),
2507 }
2508 }
2509 #[inline]
2524 pub fn as_immutable_string_ref(
2525 &self,
2526 ) -> Result<impl Deref<Target = ImmutableString> + '_, &'static str> {
2527 self.read_lock::<ImmutableString>()
2528 .ok_or_else(|| self.type_name())
2529 }
2530 #[inline]
2545 pub fn as_immutable_string_mut(
2546 &mut self,
2547 ) -> Result<impl DerefMut<Target = ImmutableString> + '_, &'static str> {
2548 let type_name = self.type_name();
2549 self.write_lock::<ImmutableString>().ok_or(type_name)
2550 }
2551 #[cfg(not(feature = "no_index"))]
2568 #[inline(always)]
2569 pub fn as_array_ref(&self) -> Result<impl Deref<Target = Array> + '_, &'static str> {
2570 self.read_lock::<Array>().ok_or_else(|| self.type_name())
2571 }
2572 #[cfg(not(feature = "no_index"))]
2589 #[inline(always)]
2590 pub fn as_array_mut(&mut self) -> Result<impl DerefMut<Target = Array> + '_, &'static str> {
2591 let type_name = self.type_name();
2592 self.write_lock::<Array>().ok_or(type_name)
2593 }
2594 #[cfg(not(feature = "no_index"))]
2611 #[inline(always)]
2612 pub fn as_blob_ref(&self) -> Result<impl Deref<Target = Blob> + '_, &'static str> {
2613 self.read_lock::<Blob>().ok_or_else(|| self.type_name())
2614 }
2615 #[cfg(not(feature = "no_index"))]
2632 #[inline(always)]
2633 pub fn as_blob_mut(&mut self) -> Result<impl DerefMut<Target = Blob> + '_, &'static str> {
2634 let type_name = self.type_name();
2635 self.write_lock::<Blob>().ok_or(type_name)
2636 }
2637 #[cfg(not(feature = "no_object"))]
2654 #[inline(always)]
2655 pub fn as_map_ref(&self) -> Result<impl Deref<Target = Map> + '_, &'static str> {
2656 self.read_lock::<Map>().ok_or_else(|| self.type_name())
2657 }
2658 #[cfg(not(feature = "no_object"))]
2675 #[inline(always)]
2676 pub fn as_map_mut(&mut self) -> Result<impl DerefMut<Target = Map> + '_, &'static str> {
2677 let type_name = self.type_name();
2678 self.write_lock::<Map>().ok_or(type_name)
2679 }
2680 #[inline]
2697 pub fn into_string(self) -> Result<String, &'static str> {
2698 self.into_immutable_string()
2699 .map(ImmutableString::into_owned)
2700 }
2701 #[inline]
2716 pub fn into_immutable_string(self) -> Result<ImmutableString, &'static str> {
2717 match self.0 {
2718 Union::Str(s, ..) => Ok(s),
2719 #[cfg(not(feature = "no_closure"))]
2720 Union::Shared(ref cell, ..) => crate::func::locked_read(cell)
2721 .and_then(|guard| match guard.0 {
2722 Union::Str(ref s, ..) => Some(s.clone()),
2723 _ => None,
2724 })
2725 .ok_or_else(|| cell.type_name()),
2726 _ => Err(self.type_name()),
2727 }
2728 }
2729 #[cfg(not(feature = "no_index"))]
2746 #[inline(always)]
2747 pub fn into_array(self) -> Result<Array, &'static str> {
2748 match self.0 {
2749 Union::Array(a, ..) => Ok(*a),
2750 #[cfg(not(feature = "no_closure"))]
2751 Union::Shared(ref cell, ..) => crate::func::locked_read(cell)
2752 .and_then(|guard| match guard.0 {
2753 Union::Array(ref a, ..) => Some(a.as_ref().clone()),
2754 _ => None,
2755 })
2756 .ok_or_else(|| cell.type_name()),
2757 _ => Err(self.type_name()),
2758 }
2759 }
2760 #[cfg(not(feature = "no_index"))]
2777 #[inline(always)]
2778 pub fn into_typed_array<T: Variant + Clone>(self) -> Result<Vec<T>, &'static str> {
2779 match self.0 {
2780 Union::Array(a, ..) => a
2781 .into_iter()
2782 .map(|v| {
2783 #[cfg(not(feature = "no_closure"))]
2784 let typ = if v.is_shared() {
2785 "<shared>"
2787 } else {
2788 v.type_name()
2789 };
2790 #[cfg(feature = "no_closure")]
2791 let typ = v.type_name();
2792
2793 v.try_cast::<T>().ok_or(typ)
2794 })
2795 .collect(),
2796 Union::Blob(b, ..) if TypeId::of::<T>() == TypeId::of::<u8>() => {
2797 Ok(reify! { *b => !!! Vec<T> })
2798 }
2799 #[cfg(not(feature = "no_closure"))]
2800 Union::Shared(ref cell, ..) => crate::func::locked_read(cell)
2801 .and_then(|guard| match guard.0 {
2802 Union::Array(ref a, ..) => a
2803 .iter()
2804 .map(|v| v.read_lock::<T>().map(|v| v.clone()))
2805 .collect(),
2806 Union::Blob(ref b, ..) if TypeId::of::<T>() == TypeId::of::<u8>() => {
2807 Some(reify! { b.clone() => !!! Vec<T> })
2808 }
2809 _ => None,
2810 })
2811 .ok_or_else(|| cell.type_name()),
2812 _ => Err(self.type_name()),
2813 }
2814 }
2815 #[cfg(not(feature = "no_index"))]
2832 #[inline(always)]
2833 pub fn into_blob(self) -> Result<Blob, &'static str> {
2834 match self.0 {
2835 Union::Blob(b, ..) => Ok(*b),
2836 #[cfg(not(feature = "no_closure"))]
2837 Union::Shared(ref cell, ..) => crate::func::locked_read(cell)
2838 .and_then(|guard| match guard.0 {
2839 Union::Blob(ref b, ..) => Some(b.as_ref().clone()),
2840 _ => None,
2841 })
2842 .ok_or_else(|| cell.type_name()),
2843 _ => Err(self.type_name()),
2844 }
2845 }
2846
2847 #[inline]
2854 #[allow(clippy::only_used_in_recursion)]
2855 pub fn deep_scan(&mut self, mut filter: impl FnMut(&mut Self)) {
2856 fn scan_inner(value: &mut Dynamic, filter: &mut (impl FnMut(&mut Dynamic) + ?Sized)) {
2857 filter(value);
2858
2859 match &mut value.0 {
2860 #[cfg(not(feature = "no_index"))]
2861 Union::Array(a, ..) => a.iter_mut().for_each(|v| scan_inner(v, filter)),
2862 #[cfg(not(feature = "no_object"))]
2863 Union::Map(m, ..) => m.values_mut().for_each(|v| scan_inner(v, filter)),
2864 Union::FnPtr(f, ..) => f.iter_curry_mut().for_each(|v| scan_inner(v, filter)),
2865 _ => (),
2866 }
2867 }
2868
2869 scan_inner(self, &mut filter);
2870 }
2871}
2872
2873impl From<()> for Dynamic {
2874 #[inline(always)]
2875 fn from(value: ()) -> Self {
2876 Self(Union::Unit(value, DEFAULT_TAG_VALUE, ReadWrite))
2877 }
2878}
2879impl From<bool> for Dynamic {
2880 #[inline(always)]
2881 fn from(value: bool) -> Self {
2882 Self(Union::Bool(value, DEFAULT_TAG_VALUE, ReadWrite))
2883 }
2884}
2885impl From<INT> for Dynamic {
2886 #[inline(always)]
2887 fn from(value: INT) -> Self {
2888 Self(Union::Int(value, DEFAULT_TAG_VALUE, ReadWrite))
2889 }
2890}
2891#[cfg(not(feature = "no_float"))]
2892impl From<crate::FLOAT> for Dynamic {
2893 #[inline(always)]
2894 fn from(value: crate::FLOAT) -> Self {
2895 Self(Union::Float(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
2896 }
2897}
2898#[cfg(not(feature = "no_float"))]
2899impl From<super::FloatWrapper<crate::FLOAT>> for Dynamic {
2900 #[inline(always)]
2901 fn from(value: super::FloatWrapper<crate::FLOAT>) -> Self {
2902 Self(Union::Float(value, DEFAULT_TAG_VALUE, ReadWrite))
2903 }
2904}
2905#[cfg(feature = "decimal")]
2906impl From<rust_decimal::Decimal> for Dynamic {
2907 #[inline(always)]
2908 fn from(value: rust_decimal::Decimal) -> Self {
2909 Self(Union::Decimal(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
2910 }
2911}
2912impl From<char> for Dynamic {
2913 #[inline(always)]
2914 fn from(value: char) -> Self {
2915 Self(Union::Char(value, DEFAULT_TAG_VALUE, ReadWrite))
2916 }
2917}
2918impl<S: Into<ImmutableString>> From<S> for Dynamic {
2919 #[inline(always)]
2920 fn from(value: S) -> Self {
2921 Self(Union::Str(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
2922 }
2923}
2924impl FromStr for Dynamic {
2925 type Err = ();
2926
2927 fn from_str(value: &str) -> Result<Self, Self::Err> {
2928 Ok(Self(Union::Str(value.into(), DEFAULT_TAG_VALUE, ReadWrite)))
2929 }
2930}
2931#[cfg(not(feature = "no_index"))]
2932impl<T: Variant + Clone> From<Vec<T>> for Dynamic {
2933 #[inline]
2934 fn from(value: Vec<T>) -> Self {
2935 Self(Union::Array(
2936 Box::new(value.into_iter().map(Self::from).collect()),
2937 DEFAULT_TAG_VALUE,
2938 ReadWrite,
2939 ))
2940 }
2941}
2942#[cfg(not(feature = "no_index"))]
2943impl<T: Variant + Clone> From<&[T]> for Dynamic {
2944 #[inline]
2945 fn from(value: &[T]) -> Self {
2946 Self(Union::Array(
2947 Box::new(value.iter().cloned().map(Self::from).collect()),
2948 DEFAULT_TAG_VALUE,
2949 ReadWrite,
2950 ))
2951 }
2952}
2953#[cfg(not(feature = "no_index"))]
2954impl<T: Variant + Clone> std::iter::FromIterator<T> for Dynamic {
2955 #[inline]
2956 fn from_iter<X: IntoIterator<Item = T>>(iter: X) -> Self {
2957 Self(Union::Array(
2958 Box::new(iter.into_iter().map(Self::from).collect()),
2959 DEFAULT_TAG_VALUE,
2960 ReadWrite,
2961 ))
2962 }
2963}
2964#[cfg(not(feature = "no_object"))]
2965#[cfg(not(feature = "no_std"))]
2966impl<K: Into<crate::Identifier>, T: Variant + Clone> From<std::collections::HashMap<K, T>>
2967 for Dynamic
2968{
2969 #[inline]
2970 fn from(value: std::collections::HashMap<K, T>) -> Self {
2971 Self(Union::Map(
2972 Box::new(
2973 value
2974 .into_iter()
2975 .map(|(k, v)| (k.into(), Self::from(v)))
2976 .collect(),
2977 ),
2978 DEFAULT_TAG_VALUE,
2979 ReadWrite,
2980 ))
2981 }
2982}
2983#[cfg(not(feature = "no_object"))]
2984#[cfg(not(feature = "no_std"))]
2985impl<K: Into<crate::Identifier>> From<std::collections::HashSet<K>> for Dynamic {
2986 #[inline]
2987 fn from(value: std::collections::HashSet<K>) -> Self {
2988 Self(Union::Map(
2989 Box::new(value.into_iter().map(|k| (k.into(), Self::UNIT)).collect()),
2990 DEFAULT_TAG_VALUE,
2991 ReadWrite,
2992 ))
2993 }
2994}
2995#[cfg(not(feature = "no_object"))]
2996impl<K: Into<crate::Identifier>, T: Variant + Clone> From<std::collections::BTreeMap<K, T>>
2997 for Dynamic
2998{
2999 #[inline]
3000 fn from(value: std::collections::BTreeMap<K, T>) -> Self {
3001 Self(Union::Map(
3002 Box::new(
3003 value
3004 .into_iter()
3005 .map(|(k, v)| (k.into(), Self::from(v)))
3006 .collect(),
3007 ),
3008 DEFAULT_TAG_VALUE,
3009 ReadWrite,
3010 ))
3011 }
3012}
3013#[cfg(not(feature = "no_object"))]
3014impl<K: Into<crate::Identifier>> From<std::collections::BTreeSet<K>> for Dynamic {
3015 #[inline]
3016 fn from(value: std::collections::BTreeSet<K>) -> Self {
3017 Self(Union::Map(
3018 Box::new(value.into_iter().map(|k| (k.into(), Self::UNIT)).collect()),
3019 DEFAULT_TAG_VALUE,
3020 ReadWrite,
3021 ))
3022 }
3023}
3024impl From<FnPtr> for Dynamic {
3025 #[inline(always)]
3026 fn from(value: FnPtr) -> Self {
3027 Self(Union::FnPtr(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
3028 }
3029}
3030#[cfg(not(feature = "no_time"))]
3031impl From<Instant> for Dynamic {
3032 #[inline(always)]
3033 fn from(value: Instant) -> Self {
3034 Self(Union::TimeStamp(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
3035 }
3036}
3037#[cfg(not(feature = "no_closure"))]
3038impl From<crate::Shared<crate::Locked<Self>>> for Dynamic {
3039 #[inline(always)]
3040 fn from(value: crate::Shared<crate::Locked<Self>>) -> Self {
3041 Self(Union::Shared(value, DEFAULT_TAG_VALUE, ReadWrite))
3042 }
3043}
3044
3045impl From<ExclusiveRange> for Dynamic {
3046 #[inline(always)]
3047 fn from(value: ExclusiveRange) -> Self {
3048 Self::from(value)
3049 }
3050}
3051impl From<InclusiveRange> for Dynamic {
3052 #[inline(always)]
3053 fn from(value: InclusiveRange) -> Self {
3054 Self::from(value)
3055 }
3056}