2020-11-20 09:52:28 +01:00
|
|
|
//! Helper module which defines the [`Any`] trait to to allow dynamic value handling.
|
2020-03-08 12:54:02 +01:00
|
|
|
|
2020-11-16 16:10:14 +01:00
|
|
|
use crate::fn_native::SendSync;
|
2020-05-14 12:27:22 +02:00
|
|
|
use crate::r#unsafe::{unsafe_cast_box, unsafe_try_cast};
|
2021-05-08 16:59:33 +02:00
|
|
|
use crate::{FnPtr, ImmutableString, INT};
|
2021-04-17 09:15:54 +02:00
|
|
|
#[cfg(feature = "no_std")]
|
|
|
|
use std::prelude::v1::*;
|
|
|
|
use std::{
|
2020-04-12 17:00:06 +02:00
|
|
|
any::{type_name, Any, TypeId},
|
2020-05-15 15:40:54 +02:00
|
|
|
fmt,
|
2020-11-12 14:53:26 +01:00
|
|
|
hash::{Hash, Hasher},
|
2020-07-31 10:03:08 +02:00
|
|
|
ops::{Deref, DerefMut},
|
2020-03-10 03:07:44 +01:00
|
|
|
};
|
2020-11-16 16:10:14 +01:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-01-04 04:58:24 +01:00
|
|
|
use crate::{ast::FloatWrapper, FLOAT};
|
2020-11-16 16:10:14 +01:00
|
|
|
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
use rust_decimal::Decimal;
|
|
|
|
|
2020-11-16 16:10:14 +01:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
use crate::Array;
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
use crate::Map;
|
2017-12-20 12:16:14 +01:00
|
|
|
|
2020-04-15 16:21:23 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
2021-02-19 08:50:48 +01:00
|
|
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
2021-04-17 09:15:54 +02:00
|
|
|
use std::time::Instant;
|
2020-04-15 16:21:23 +02:00
|
|
|
|
2021-02-13 13:57:56 +01:00
|
|
|
use fmt::Debug;
|
2020-06-17 10:50:57 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
2021-02-19 08:50:48 +01:00
|
|
|
#[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))]
|
2020-06-17 10:50:57 +02:00
|
|
|
use instant::Instant;
|
|
|
|
|
2021-06-28 12:06:05 +02:00
|
|
|
/// The message: never fails because the type was checked
|
2021-06-06 08:47:32 +02:00
|
|
|
const CHECKED: &str = "never fails because the type was checked";
|
|
|
|
|
2020-07-25 09:14:29 +02:00
|
|
|
mod private {
|
|
|
|
use crate::fn_native::SendSync;
|
2021-04-17 09:15:54 +02:00
|
|
|
use std::any::Any;
|
2020-07-25 09:14:29 +02:00
|
|
|
|
2020-07-25 10:09:13 +02:00
|
|
|
/// A sealed trait that prevents other crates from implementing [`Variant`].
|
2020-07-25 09:14:29 +02:00
|
|
|
pub trait Sealed {}
|
|
|
|
|
|
|
|
impl<T: Any + Clone + SendSync> Sealed for T {}
|
|
|
|
}
|
|
|
|
|
2021-03-05 07:18:36 +01:00
|
|
|
/// _(INTERNALS)_ Trait to represent any type.
|
|
|
|
/// Exported under the `internals` feature only.
|
|
|
|
///
|
|
|
|
/// This trait is sealed and cannot be implemented.
|
2020-04-03 13:42:01 +02:00
|
|
|
///
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Currently, [`Variant`] is not [`Send`] nor [`Sync`], so it can practically be any type.
|
2020-11-25 02:36:06 +01:00
|
|
|
/// Turn on the `sync` feature to restrict it to only types that implement [`Send`] `+` [`Sync`].
|
2020-04-12 17:00:06 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2020-07-25 09:14:29 +02:00
|
|
|
pub trait Variant: Any + private::Sealed {
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Convert this [`Variant`] trait object to [`&dyn Any`][Any].
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-04-12 17:00:06 +02:00
|
|
|
fn as_any(&self) -> &dyn Any;
|
2020-02-25 08:02:27 +01:00
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Convert this [`Variant`] trait object to [`&mut dyn Any`][Any].
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-04-12 17:00:06 +02:00
|
|
|
fn as_mut_any(&mut self) -> &mut dyn Any;
|
2017-12-20 12:16:14 +01:00
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Convert this [`Variant`] trait object to an [`Any`] trait object.
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-05-07 13:16:50 +02:00
|
|
|
fn as_box_any(self: Box<Self>) -> Box<dyn Any>;
|
|
|
|
|
2020-03-04 15:00:01 +01:00
|
|
|
/// Get the name of this type.
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-03-03 09:24:03 +01:00
|
|
|
fn type_name(&self) -> &'static str;
|
2019-09-30 19:57:21 +02:00
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Convert into [`Dynamic`].
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-04-12 17:00:06 +02:00
|
|
|
fn into_dynamic(self) -> Dynamic;
|
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Clone into [`Dynamic`].
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-04-12 17:00:06 +02:00
|
|
|
fn clone_into_dynamic(&self) -> Dynamic;
|
2017-12-20 12:16:14 +01:00
|
|
|
}
|
|
|
|
|
2021-03-05 07:18:36 +01:00
|
|
|
/// _(INTERNALS)_ Trait to represent any type.
|
|
|
|
/// Exported under the `internals` feature only.
|
|
|
|
///
|
|
|
|
/// This trait is sealed and cannot be implemented.
|
2020-04-12 17:00:06 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2020-07-25 09:14:29 +02:00
|
|
|
pub trait Variant: Any + Send + Sync + private::Sealed {
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Convert this [`Variant`] trait object to [`&dyn Any`][Any].
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-04-12 17:00:06 +02:00
|
|
|
fn as_any(&self) -> &dyn Any;
|
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Convert this [`Variant`] trait object to [`&mut dyn Any`][Any].
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-04-12 17:00:06 +02:00
|
|
|
fn as_mut_any(&mut self) -> &mut dyn Any;
|
2020-04-02 13:40:02 +02:00
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Convert this [`Variant`] trait object to an [`Any`] trait object.
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-05-12 10:32:22 +02:00
|
|
|
fn as_box_any(self: Box<Self>) -> Box<dyn Any>;
|
2020-05-07 13:16:50 +02:00
|
|
|
|
2020-04-02 13:40:02 +02:00
|
|
|
/// Get the name of this type.
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-04-02 13:40:02 +02:00
|
|
|
fn type_name(&self) -> &'static str;
|
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Convert into [`Dynamic`].
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-04-12 17:00:06 +02:00
|
|
|
fn into_dynamic(self) -> Dynamic;
|
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Clone into [`Dynamic`].
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-04-12 17:00:06 +02:00
|
|
|
fn clone_into_dynamic(&self) -> Dynamic;
|
2020-04-02 13:40:02 +02:00
|
|
|
}
|
|
|
|
|
2020-06-08 08:10:16 +02:00
|
|
|
impl<T: Any + Clone + SendSync> Variant for T {
|
2020-12-29 03:41:20 +01:00
|
|
|
#[inline(always)]
|
2020-04-12 17:00:06 +02:00
|
|
|
fn as_any(&self) -> &dyn Any {
|
2020-06-23 13:24:26 +02:00
|
|
|
self
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
2020-12-29 03:41:20 +01:00
|
|
|
#[inline(always)]
|
2020-04-12 17:00:06 +02:00
|
|
|
fn as_mut_any(&mut self) -> &mut dyn Any {
|
2020-06-23 13:24:26 +02:00
|
|
|
self
|
2017-12-20 12:16:14 +01:00
|
|
|
}
|
2020-12-29 03:41:20 +01:00
|
|
|
#[inline(always)]
|
2020-05-07 13:16:50 +02:00
|
|
|
fn as_box_any(self: Box<Self>) -> Box<dyn Any> {
|
2020-06-23 13:24:26 +02:00
|
|
|
self
|
2020-05-07 13:16:50 +02:00
|
|
|
}
|
2020-12-29 03:41:20 +01:00
|
|
|
#[inline(always)]
|
2020-03-03 09:24:03 +01:00
|
|
|
fn type_name(&self) -> &'static str {
|
|
|
|
type_name::<T>()
|
2019-09-30 19:57:21 +02:00
|
|
|
}
|
2020-12-29 03:41:20 +01:00
|
|
|
#[inline(always)]
|
2020-04-12 17:00:06 +02:00
|
|
|
fn into_dynamic(self) -> Dynamic {
|
|
|
|
Dynamic::from(self)
|
|
|
|
}
|
2020-12-29 03:41:20 +01:00
|
|
|
#[inline(always)]
|
2020-04-12 17:00:06 +02:00
|
|
|
fn clone_into_dynamic(&self) -> Dynamic {
|
|
|
|
Dynamic::from(self.clone())
|
2017-12-20 12:16:14 +01:00
|
|
|
}
|
2019-09-18 12:21:07 +02:00
|
|
|
}
|
2017-12-20 12:16:14 +01:00
|
|
|
|
2020-04-12 17:00:06 +02:00
|
|
|
impl dyn Variant {
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Is this [`Variant`] a specific type?
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-04-05 03:56:52 +02:00
|
|
|
pub fn is<T: Any>(&self) -> bool {
|
2020-04-12 17:00:06 +02:00
|
|
|
TypeId::of::<T>() == self.type_id()
|
2017-12-20 12:16:14 +01:00
|
|
|
}
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
|
|
|
|
2020-12-09 11:37:52 +01:00
|
|
|
/// Modes of access.
|
2020-12-08 15:47:38 +01:00
|
|
|
#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
|
2020-12-09 11:37:52 +01:00
|
|
|
pub enum AccessMode {
|
|
|
|
/// Mutable.
|
|
|
|
ReadWrite,
|
|
|
|
/// Immutable.
|
|
|
|
ReadOnly,
|
2020-12-08 15:47:38 +01:00
|
|
|
}
|
|
|
|
|
2021-05-02 17:57:35 +02:00
|
|
|
/// Arbitrary data attached to a [`Dynamic`] value.
|
2021-05-18 06:24:23 +02:00
|
|
|
#[cfg(target_pointer_width = "64")]
|
|
|
|
pub type Tag = i32;
|
|
|
|
|
|
|
|
/// Arbitrary data attached to a [`Dynamic`] value.
|
|
|
|
#[cfg(target_pointer_width = "32")]
|
2021-05-02 17:57:35 +02:00
|
|
|
pub type Tag = i16;
|
|
|
|
|
|
|
|
/// Default tag value for [`Dynamic`].
|
2021-06-28 12:06:05 +02:00
|
|
|
const DEFAULT_TAG_VALUE: Tag = 0;
|
2021-05-02 17:57:35 +02:00
|
|
|
|
2020-05-15 15:40:54 +02:00
|
|
|
/// Dynamic type containing any value.
|
2020-04-12 17:00:06 +02:00
|
|
|
pub struct Dynamic(pub(crate) Union);
|
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Internal [`Dynamic`] representation.
|
2020-05-09 18:19:13 +02:00
|
|
|
///
|
|
|
|
/// Most variants are boxed to reduce the size.
|
2020-04-12 17:00:06 +02:00
|
|
|
pub enum Union {
|
2021-02-13 16:01:26 +01:00
|
|
|
/// The Unit value - ().
|
2021-05-02 17:57:35 +02:00
|
|
|
Unit((), Tag, AccessMode),
|
2021-02-13 16:01:26 +01:00
|
|
|
/// A boolean value.
|
2021-05-02 17:57:35 +02:00
|
|
|
Bool(bool, Tag, AccessMode),
|
2021-02-13 16:01:26 +01:00
|
|
|
/// An [`ImmutableString`] value.
|
2021-05-02 17:57:35 +02:00
|
|
|
Str(ImmutableString, Tag, AccessMode),
|
2021-02-13 16:01:26 +01:00
|
|
|
/// A character value.
|
2021-05-02 17:57:35 +02:00
|
|
|
Char(char, Tag, AccessMode),
|
2021-02-13 16:01:26 +01:00
|
|
|
/// An integer value.
|
2021-05-02 17:57:35 +02:00
|
|
|
Int(INT, Tag, AccessMode),
|
2021-02-13 16:01:26 +01:00
|
|
|
/// A floating-point value.
|
2021-05-10 05:07:19 +02:00
|
|
|
///
|
|
|
|
/// Not available under `no_float`.
|
2020-04-12 17:00:06 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Float(FloatWrapper<FLOAT>, Tag, AccessMode),
|
2021-05-10 05:07:19 +02:00
|
|
|
/// _(DECIMAL)_ A fixed-precision decimal value.
|
|
|
|
/// Exported under the `decimal` feature only.
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
2021-05-02 17:57:35 +02:00
|
|
|
Decimal(Box<Decimal>, Tag, AccessMode),
|
2021-02-13 16:01:26 +01:00
|
|
|
/// An array value.
|
2021-05-10 05:07:19 +02:00
|
|
|
///
|
|
|
|
/// Not available under `no_index`.
|
2020-05-06 13:45:17 +02:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Array(Box<Array>, Tag, AccessMode),
|
2021-02-13 16:01:26 +01:00
|
|
|
/// An object map value.
|
2021-05-10 05:07:19 +02:00
|
|
|
///
|
|
|
|
/// Not available under `no_object`.
|
2020-05-06 13:45:17 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Map(Box<Map>, Tag, AccessMode),
|
2021-02-13 16:01:26 +01:00
|
|
|
/// A function pointer.
|
2021-05-02 17:57:35 +02:00
|
|
|
FnPtr(Box<FnPtr>, Tag, AccessMode),
|
2021-02-13 16:01:26 +01:00
|
|
|
/// A timestamp value.
|
2021-05-10 05:07:19 +02:00
|
|
|
///
|
|
|
|
/// Not available under `no-std`.
|
2020-09-27 16:15:35 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
TimeStamp(Box<Instant>, Tag, AccessMode),
|
2020-08-08 10:24:10 +02:00
|
|
|
|
2021-02-13 16:01:26 +01:00
|
|
|
/// Any type as a trait object.
|
2021-05-02 17:57:35 +02:00
|
|
|
Variant(Box<Box<dyn Variant>>, Tag, AccessMode),
|
2020-08-08 10:24:10 +02:00
|
|
|
|
2021-02-13 16:01:26 +01:00
|
|
|
/// A _shared_ value of any type.
|
2021-05-10 05:07:19 +02:00
|
|
|
///
|
|
|
|
/// Not available under `no_closure`.
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Shared(crate::Shared<crate::Locked<Dynamic>>, Tag, AccessMode),
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
|
|
|
|
2021-05-10 05:07:19 +02:00
|
|
|
/// _(INTERNALS)_ Lock guard for reading a [`Dynamic`].
|
|
|
|
/// Exported under the `internals` feature only.
|
|
|
|
///
|
|
|
|
/// This type provides transparent interoperability between normal [`Dynamic`] and shared
|
|
|
|
/// [`Dynamic`] values.
|
2020-07-27 06:30:09 +02:00
|
|
|
///
|
2021-05-10 05:07:19 +02:00
|
|
|
/// # Volatile Data Structure
|
|
|
|
///
|
|
|
|
/// This type is volatile and may change.
|
2020-07-27 06:30:09 +02:00
|
|
|
#[derive(Debug)]
|
2021-04-19 12:08:29 +02:00
|
|
|
pub struct DynamicReadLock<'d, T: Clone>(DynamicReadLockInner<'d, T>);
|
2020-07-27 06:30:09 +02:00
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Different types of read guards for [`DynamicReadLock`].
|
2020-07-27 06:30:09 +02:00
|
|
|
#[derive(Debug)]
|
2021-04-19 12:08:29 +02:00
|
|
|
enum DynamicReadLockInner<'d, T: Clone> {
|
2020-07-31 10:03:08 +02:00
|
|
|
/// A simple reference to a non-shared value.
|
2020-07-27 06:30:09 +02:00
|
|
|
Reference(&'d T),
|
2020-08-08 10:24:10 +02:00
|
|
|
|
2021-01-02 16:30:10 +01:00
|
|
|
/// A read guard to a shared [`RefCell`][std::cell::RefCell].
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-07-27 06:30:09 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2021-04-17 09:15:54 +02:00
|
|
|
Guard(std::cell::Ref<'d, Dynamic>),
|
2020-11-20 09:52:28 +01:00
|
|
|
/// A read guard to a shared [`RwLock`][std::sync::RwLock].
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-07-27 06:30:09 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2021-04-17 09:15:54 +02:00
|
|
|
Guard(std::sync::RwLockReadGuard<'d, Dynamic>),
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:08:29 +02:00
|
|
|
impl<'d, T: Any + Clone> Deref for DynamicReadLock<'d, T> {
|
2020-07-27 06:30:09 +02:00
|
|
|
type Target = T;
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
fn deref(&self) -> &Self::Target {
|
2021-06-13 11:41:34 +02:00
|
|
|
match self.0 {
|
|
|
|
DynamicReadLockInner::Reference(ref reference) => *reference,
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
DynamicReadLockInner::Guard(ref guard) => guard.downcast_ref().expect(
|
2021-05-22 13:14:24 +02:00
|
|
|
"never fails because the read guard was created after checking the data type",
|
|
|
|
),
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-10 05:07:19 +02:00
|
|
|
/// _(INTERNALS)_ Lock guard for writing a [`Dynamic`].
|
|
|
|
/// Exported under the `internals` feature only.
|
|
|
|
///
|
|
|
|
/// This type provides transparent interoperability between normal [`Dynamic`] and shared
|
|
|
|
/// [`Dynamic`] values.
|
2020-07-27 06:30:09 +02:00
|
|
|
///
|
2021-05-10 05:07:19 +02:00
|
|
|
/// # Volatile Data Structure
|
|
|
|
///
|
|
|
|
/// This type is volatile and may change.
|
2020-07-27 06:30:09 +02:00
|
|
|
#[derive(Debug)]
|
2021-04-19 12:08:29 +02:00
|
|
|
pub struct DynamicWriteLock<'d, T: Clone>(DynamicWriteLockInner<'d, T>);
|
2020-07-27 06:30:09 +02:00
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Different types of write guards for [`DynamicReadLock`].
|
2020-07-27 06:30:09 +02:00
|
|
|
#[derive(Debug)]
|
2021-04-19 12:08:29 +02:00
|
|
|
enum DynamicWriteLockInner<'d, T: Clone> {
|
2020-07-31 10:03:08 +02:00
|
|
|
/// A simple mutable reference to a non-shared value.
|
2020-07-27 06:30:09 +02:00
|
|
|
Reference(&'d mut T),
|
2020-08-08 10:24:10 +02:00
|
|
|
|
2021-01-02 16:30:10 +01:00
|
|
|
/// A write guard to a shared [`RefCell`][std::cell::RefCell].
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-07-27 06:30:09 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2021-04-17 09:15:54 +02:00
|
|
|
Guard(std::cell::RefMut<'d, Dynamic>),
|
2020-11-20 09:52:28 +01:00
|
|
|
/// A write guard to a shared [`RwLock`][std::sync::RwLock].
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-07-27 06:30:09 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2021-04-17 09:15:54 +02:00
|
|
|
Guard(std::sync::RwLockWriteGuard<'d, Dynamic>),
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
|
|
|
|
2021-04-19 12:08:29 +02:00
|
|
|
impl<'d, T: Any + Clone> Deref for DynamicWriteLock<'d, T> {
|
2020-07-27 06:30:09 +02:00
|
|
|
type Target = T;
|
|
|
|
|
|
|
|
#[inline(always)]
|
|
|
|
fn deref(&self) -> &Self::Target {
|
2021-06-13 11:41:34 +02:00
|
|
|
match self.0 {
|
|
|
|
DynamicWriteLockInner::Reference(ref reference) => *reference,
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
DynamicWriteLockInner::Guard(ref guard) => guard.downcast_ref().expect(
|
2021-05-25 04:54:48 +02:00
|
|
|
"never fails because the write guard was created after checking the data type",
|
2021-05-22 13:14:24 +02:00
|
|
|
),
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-19 12:08:29 +02:00
|
|
|
impl<'d, T: Any + Clone> DerefMut for DynamicWriteLock<'d, T> {
|
2020-07-27 06:30:09 +02:00
|
|
|
#[inline(always)]
|
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
2021-06-13 11:41:34 +02:00
|
|
|
match self.0 {
|
|
|
|
DynamicWriteLockInner::Reference(ref mut reference) => *reference,
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
DynamicWriteLockInner::Guard(ref mut guard) => guard.downcast_mut().expect(
|
2021-05-22 13:14:24 +02:00
|
|
|
"never fails because the write guard was created after checking the data type",
|
|
|
|
),
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
|
|
|
}
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Dynamic {
|
2021-05-02 17:57:35 +02:00
|
|
|
/// Get the arbitrary data attached to this [`Dynamic`].
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-05-25 04:54:48 +02:00
|
|
|
pub const fn tag(&self) -> Tag {
|
2021-05-02 17:57:35 +02:00
|
|
|
match self.0 {
|
|
|
|
Union::Unit(_, tag, _)
|
|
|
|
| Union::Bool(_, tag, _)
|
|
|
|
| Union::Str(_, tag, _)
|
|
|
|
| Union::Char(_, tag, _)
|
|
|
|
| Union::Int(_, tag, _)
|
|
|
|
| Union::FnPtr(_, tag, _)
|
|
|
|
| Union::Variant(_, tag, _) => tag,
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
Union::Float(_, tag, _) => tag,
|
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
Union::Decimal(_, tag, _) => tag,
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
Union::Array(_, tag, _) => tag,
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
Union::Map(_, tag, _) => tag,
|
|
|
|
#[cfg(not(feature = "no_std"))]
|
|
|
|
Union::TimeStamp(_, tag, _) => tag,
|
|
|
|
#[cfg(not(feature = "no_closure"))]
|
|
|
|
Union::Shared(_, tag, _) => tag,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// Attach arbitrary data to this [`Dynamic`].
|
2021-06-12 16:47:43 +02:00
|
|
|
pub fn set_tag(&mut self, value: Tag) -> &mut Self {
|
2021-06-13 11:41:34 +02:00
|
|
|
match self.0 {
|
|
|
|
Union::Unit(_, ref mut tag, _)
|
|
|
|
| Union::Bool(_, ref mut tag, _)
|
|
|
|
| Union::Str(_, ref mut tag, _)
|
|
|
|
| Union::Char(_, ref mut tag, _)
|
|
|
|
| Union::Int(_, ref mut tag, _)
|
|
|
|
| Union::FnPtr(_, ref mut tag, _)
|
|
|
|
| Union::Variant(_, ref mut tag, _) => *tag = value,
|
2021-05-02 17:57:35 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Float(_, ref mut tag, _) => *tag = value,
|
2021-05-02 17:57:35 +02:00
|
|
|
#[cfg(feature = "decimal")]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Decimal(_, ref mut tag, _) => *tag = value,
|
2021-05-02 17:57:35 +02:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Array(_, ref mut tag, _) => *tag = value,
|
2021-05-02 17:57:35 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Map(_, ref mut tag, _) => *tag = value,
|
2021-05-02 17:57:35 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::TimeStamp(_, ref mut tag, _) => *tag = value,
|
2021-05-02 17:57:35 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Shared(_, ref mut tag, _) => *tag = value,
|
2021-05-02 17:57:35 +02:00
|
|
|
}
|
2021-06-12 16:47:43 +02:00
|
|
|
self
|
2021-05-02 17:57:35 +02:00
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Does this [`Dynamic`] hold a variant data type
|
2021-01-02 16:30:10 +01:00
|
|
|
/// instead of one of the supported system primitive types?
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-05-25 04:54:48 +02:00
|
|
|
pub const fn is_variant(&self) -> bool {
|
2020-04-13 04:27:08 +02:00
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Variant(_, _, _) => true,
|
2020-04-13 04:27:08 +02:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
2021-01-02 16:30:10 +01:00
|
|
|
/// Is the value held by this [`Dynamic`] shared?
|
2021-01-11 16:09:33 +01:00
|
|
|
///
|
2021-04-17 06:03:29 +02:00
|
|
|
/// Not available under `no_closure`.
|
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-05-25 04:54:48 +02:00
|
|
|
pub const fn is_shared(&self) -> bool {
|
2021-03-06 03:44:55 +01:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-07-27 06:30:09 +02:00
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(_, _, _) => return true,
|
2021-03-06 14:25:49 +01:00
|
|
|
_ => (),
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
2021-03-06 14:25:49 +01:00
|
|
|
|
2021-03-06 03:44:55 +01:00
|
|
|
false
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Is the value held by this [`Dynamic`] a particular type?
|
2020-07-27 06:30:09 +02:00
|
|
|
///
|
2020-11-20 09:52:28 +01:00
|
|
|
/// If the [`Dynamic`] is a shared variant checking is performed on
|
2021-01-02 16:30:10 +01:00
|
|
|
/// top of its internal value.
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-04-19 12:08:29 +02:00
|
|
|
pub fn is<T: Any + Clone>(&self) -> bool {
|
2020-07-31 00:34:20 +02:00
|
|
|
let mut target_type_id = TypeId::of::<T>();
|
|
|
|
|
|
|
|
if target_type_id == TypeId::of::<String>() {
|
|
|
|
target_type_id = TypeId::of::<ImmutableString>();
|
|
|
|
}
|
|
|
|
|
|
|
|
self.type_id() == target_type_id
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Get the [`TypeId`] of the value held by this [`Dynamic`].
|
2020-08-02 07:33:51 +02:00
|
|
|
///
|
2020-08-04 10:27:55 +02:00
|
|
|
/// # Panics or Deadlocks When Value is Shared
|
2020-08-02 07:33:51 +02:00
|
|
|
///
|
2020-11-25 02:36:06 +01:00
|
|
|
/// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1).
|
2020-08-02 07:33:51 +02:00
|
|
|
/// Otherwise, this call panics if the data is currently borrowed for write.
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-04-12 17:00:06 +02:00
|
|
|
pub fn type_id(&self) -> TypeId {
|
2021-06-13 11:41:34 +02:00
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Unit(_, _, _) => TypeId::of::<()>(),
|
|
|
|
Union::Bool(_, _, _) => TypeId::of::<bool>(),
|
|
|
|
Union::Str(_, _, _) => TypeId::of::<ImmutableString>(),
|
|
|
|
Union::Char(_, _, _) => TypeId::of::<char>(),
|
|
|
|
Union::Int(_, _, _) => TypeId::of::<INT>(),
|
2020-04-12 17:00:06 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Float(_, _, _) => TypeId::of::<FLOAT>(),
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Decimal(_, _, _) => TypeId::of::<Decimal>(),
|
2020-05-06 13:45:17 +02:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Array(_, _, _) => TypeId::of::<Array>(),
|
2020-05-06 13:45:17 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Map(_, _, _) => TypeId::of::<Map>(),
|
|
|
|
Union::FnPtr(_, _, _) => TypeId::of::<FnPtr>(),
|
2020-09-27 16:15:35 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::TimeStamp(_, _, _) => TypeId::of::<Instant>(),
|
2020-08-08 05:46:30 +02:00
|
|
|
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Variant(ref value, _, _) => (***value).type_id(),
|
2020-08-08 05:46:30 +02:00
|
|
|
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
|
|
|
Union::Shared(ref cell, _, _) => (*cell.borrow()).type_id(),
|
2021-03-05 07:18:36 +01:00
|
|
|
|
2021-06-13 11:41:34 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
Union::Shared(ref cell, _, _) => (*cell.read().unwrap()).type_id(),
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Get the name of the type of the value held by this [`Dynamic`].
|
2020-08-02 07:33:51 +02:00
|
|
|
///
|
2020-08-04 10:27:55 +02:00
|
|
|
/// # Panics or Deadlocks When Value is Shared
|
2020-08-02 07:33:51 +02:00
|
|
|
///
|
2020-11-25 02:36:06 +01:00
|
|
|
/// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1).
|
2020-08-02 07:33:51 +02:00
|
|
|
/// Otherwise, this call panics if the data is currently borrowed for write.
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-04-12 17:00:06 +02:00
|
|
|
pub fn type_name(&self) -> &'static str {
|
2021-06-13 11:41:34 +02:00
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Unit(_, _, _) => "()",
|
|
|
|
Union::Bool(_, _, _) => "bool",
|
|
|
|
Union::Str(_, _, _) => "string",
|
|
|
|
Union::Char(_, _, _) => "char",
|
|
|
|
Union::Int(_, _, _) => type_name::<INT>(),
|
2020-04-12 17:00:06 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Float(_, _, _) => type_name::<FLOAT>(),
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Decimal(_, _, _) => "decimal",
|
2020-05-06 13:45:17 +02:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Array(_, _, _) => "array",
|
2020-05-06 13:45:17 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Map(_, _, _) => "map",
|
|
|
|
Union::FnPtr(_, _, _) => "Fn",
|
2020-04-15 16:21:23 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::TimeStamp(_, _, _) => "timestamp",
|
2020-09-27 16:15:35 +02:00
|
|
|
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Variant(ref value, _, _) => (***value).type_name(),
|
2020-08-08 05:46:30 +02:00
|
|
|
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-08-01 16:28:13 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Shared(ref cell, _, _) => cell
|
2020-08-04 03:47:48 +02:00
|
|
|
.try_borrow()
|
|
|
|
.map(|v| (*v).type_name())
|
|
|
|
.unwrap_or("<shared>"),
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-08-01 16:28:13 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Shared(ref cell, _, _) => (*cell.read().unwrap()).type_name(),
|
2017-12-20 12:16:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-12 14:53:26 +01:00
|
|
|
impl Hash for Dynamic {
|
2021-06-06 08:47:32 +02:00
|
|
|
/// Hash the [`Dynamic`] value.
|
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
///
|
|
|
|
/// Panics if the [`Dynamic`] value contains an unrecognized trait object.
|
2020-11-12 14:53:26 +01:00
|
|
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
2021-06-06 08:47:32 +02:00
|
|
|
std::mem::discriminant(&self.0).hash(state);
|
|
|
|
|
2021-06-13 11:41:34 +02:00
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Unit(_, _, _) => ().hash(state),
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Bool(ref b, _, _) => b.hash(state),
|
|
|
|
Union::Str(ref s, _, _) => s.hash(state),
|
|
|
|
Union::Char(ref c, _, _) => c.hash(state),
|
|
|
|
Union::Int(ref i, _, _) => i.hash(state),
|
2020-11-12 14:53:26 +01:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Float(ref f, _, _) => f.hash(state),
|
2020-11-12 14:53:26 +01:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Array(ref a, _, _) => a.as_ref().hash(state),
|
2020-11-12 14:53:26 +01:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Map(ref m, _, _) => m.as_ref().hash(state),
|
|
|
|
Union::FnPtr(ref f, _, _) => f.hash(state),
|
2020-11-12 14:53:26 +01:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
|
|
|
Union::Shared(ref cell, _, _) => (*cell.borrow()).hash(state),
|
2021-03-05 07:18:36 +01:00
|
|
|
|
2021-06-13 11:41:34 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
Union::Shared(ref cell, _, _) => (*cell.read().unwrap()).hash(state),
|
2020-11-12 14:53:26 +01:00
|
|
|
|
2021-06-06 08:47:32 +02:00
|
|
|
#[cfg(not(feature = "only_i32"))]
|
|
|
|
#[cfg(not(feature = "only_i64"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Variant(ref value, _, _) => {
|
|
|
|
let value_any = (***value).as_any();
|
|
|
|
let type_id = value_any.type_id();
|
2021-06-06 08:47:32 +02:00
|
|
|
|
2021-06-13 11:41:34 +02:00
|
|
|
if type_id == TypeId::of::<u8>() {
|
2021-06-06 08:47:32 +02:00
|
|
|
TypeId::of::<u8>().hash(state);
|
2021-06-13 11:41:34 +02:00
|
|
|
value_any.downcast_ref::<u8>().expect(CHECKED).hash(state);
|
|
|
|
} else if type_id == TypeId::of::<u16>() {
|
2021-06-06 08:47:32 +02:00
|
|
|
TypeId::of::<u16>().hash(state);
|
2021-06-13 11:41:34 +02:00
|
|
|
value_any.downcast_ref::<u16>().expect(CHECKED).hash(state);
|
|
|
|
} else if type_id == TypeId::of::<u32>() {
|
2021-06-06 08:47:32 +02:00
|
|
|
TypeId::of::<u32>().hash(state);
|
2021-06-13 11:41:34 +02:00
|
|
|
value_any.downcast_ref::<u32>().expect(CHECKED).hash(state);
|
|
|
|
} else if type_id == TypeId::of::<u64>() {
|
2021-06-06 08:47:32 +02:00
|
|
|
TypeId::of::<u64>().hash(state);
|
2021-06-13 11:41:34 +02:00
|
|
|
value_any.downcast_ref::<u64>().expect(CHECKED).hash(state);
|
|
|
|
} else if type_id == TypeId::of::<i8>() {
|
2021-06-06 08:47:32 +02:00
|
|
|
TypeId::of::<i8>().hash(state);
|
2021-06-13 11:41:34 +02:00
|
|
|
value_any.downcast_ref::<i8>().expect(CHECKED).hash(state);
|
|
|
|
} else if type_id == TypeId::of::<i16>() {
|
2021-06-06 08:47:32 +02:00
|
|
|
TypeId::of::<i16>().hash(state);
|
2021-06-13 11:41:34 +02:00
|
|
|
value_any.downcast_ref::<i16>().expect(CHECKED).hash(state);
|
|
|
|
} else if type_id == TypeId::of::<i32>() {
|
2021-06-06 08:47:32 +02:00
|
|
|
TypeId::of::<i32>().hash(state);
|
2021-06-13 11:41:34 +02:00
|
|
|
value_any.downcast_ref::<i32>().expect(CHECKED).hash(state);
|
|
|
|
} else if type_id == TypeId::of::<i64>() {
|
2021-06-06 08:47:32 +02:00
|
|
|
TypeId::of::<i64>().hash(state);
|
2021-06-13 11:41:34 +02:00
|
|
|
value_any.downcast_ref::<i64>().expect(CHECKED).hash(state);
|
2021-06-06 08:47:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
2021-06-13 11:41:34 +02:00
|
|
|
if type_id == TypeId::of::<u128>() {
|
2021-06-06 08:47:32 +02:00
|
|
|
TypeId::of::<u128>().hash(state);
|
2021-06-13 11:41:34 +02:00
|
|
|
value_any.downcast_ref::<u128>().expect(CHECKED).hash(state);
|
|
|
|
} else if type_id == TypeId::of::<i128>() {
|
2021-06-06 08:47:32 +02:00
|
|
|
TypeId::of::<i128>().hash(state);
|
2021-06-13 11:41:34 +02:00
|
|
|
value_any.downcast_ref::<i128>().expect(CHECKED).hash(state);
|
2021-06-06 08:47:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-04 10:40:15 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
|
|
|
Union::TimeStamp(_, _, _) => unimplemented!("{} cannot be hashed", self.type_name()),
|
2020-11-12 14:53:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-03 04:45:01 +02:00
|
|
|
/// Map the name of a standard type into a friendly form.
|
2021-03-04 11:13:47 +01:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-07-03 04:45:01 +02:00
|
|
|
pub(crate) fn map_std_type_name(name: &str) -> &str {
|
|
|
|
if name == type_name::<String>() {
|
2021-03-26 09:57:28 +01:00
|
|
|
return "string";
|
|
|
|
}
|
|
|
|
if name == type_name::<ImmutableString>() {
|
|
|
|
return "string";
|
2020-07-03 04:45:01 +02:00
|
|
|
}
|
2021-03-26 09:57:28 +01:00
|
|
|
if name == type_name::<&str>() {
|
|
|
|
return "string";
|
|
|
|
}
|
|
|
|
if name == type_name::<FnPtr>() {
|
|
|
|
return "Fn";
|
|
|
|
}
|
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
if name == type_name::<Decimal>() {
|
|
|
|
return "decimal";
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
if name == type_name::<Array>() {
|
|
|
|
return "array";
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
if name == type_name::<Map>() {
|
|
|
|
return "map";
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_std"))]
|
|
|
|
if name == type_name::<Instant>() {
|
|
|
|
return "timestamp";
|
|
|
|
}
|
|
|
|
|
|
|
|
name
|
2020-07-03 04:45:01 +02:00
|
|
|
}
|
|
|
|
|
2020-04-12 17:00:06 +02:00
|
|
|
impl fmt::Display for Dynamic {
|
2019-09-18 12:21:07 +02:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2021-06-13 11:41:34 +02:00
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Unit(_, _, _) => write!(f, ""),
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Bool(ref value, _, _) => fmt::Display::fmt(value, f),
|
|
|
|
Union::Str(ref value, _, _) => fmt::Display::fmt(value, f),
|
|
|
|
Union::Char(ref value, _, _) => fmt::Display::fmt(value, f),
|
|
|
|
Union::Int(ref value, _, _) => fmt::Display::fmt(value, f),
|
2020-04-12 17:00:06 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Float(ref value, _, _) => fmt::Display::fmt(value, f),
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Decimal(ref value, _, _) => fmt::Display::fmt(value, f),
|
2020-05-06 13:45:17 +02:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Array(ref value, _, _) => fmt::Debug::fmt(value, f),
|
2020-05-06 13:45:17 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Map(ref value, _, _) => {
|
2020-07-21 14:58:53 +02:00
|
|
|
f.write_str("#")?;
|
|
|
|
fmt::Debug::fmt(value, f)
|
|
|
|
}
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::FnPtr(ref value, _, _) => fmt::Display::fmt(value, f),
|
2020-05-05 14:54:56 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::TimeStamp(_, _, _) => f.write_str("<timestamp>"),
|
2020-09-27 16:15:35 +02:00
|
|
|
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Variant(ref value, _, _) => {
|
|
|
|
let _value_any = (***value).as_any();
|
|
|
|
let _type_id = _value_any.type_id();
|
2021-02-23 12:08:05 +01:00
|
|
|
|
|
|
|
#[cfg(not(feature = "only_i32"))]
|
|
|
|
#[cfg(not(feature = "only_i64"))]
|
|
|
|
if _type_id == TypeId::of::<u8>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Display::fmt(_value_any.downcast_ref::<u8>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<u16>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Display::fmt(_value_any.downcast_ref::<u16>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<u32>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Display::fmt(_value_any.downcast_ref::<u32>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<u64>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Display::fmt(_value_any.downcast_ref::<u64>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<i8>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Display::fmt(_value_any.downcast_ref::<i8>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<i16>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Display::fmt(_value_any.downcast_ref::<i16>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<i32>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Display::fmt(_value_any.downcast_ref::<i32>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<i64>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Display::fmt(_value_any.downcast_ref::<i64>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
if _type_id == TypeId::of::<f32>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Display::fmt(_value_any.downcast_ref::<f32>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<f64>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Display::fmt(_value_any.downcast_ref::<f64>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
|
|
|
if _type_id == TypeId::of::<u128>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Display::fmt(_value_any.downcast_ref::<u128>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<i128>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Display::fmt(_value_any.downcast_ref::<i128>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
}
|
|
|
|
|
2021-06-13 11:41:34 +02:00
|
|
|
f.write_str((***value).type_name())
|
2021-02-23 12:08:05 +01:00
|
|
|
}
|
2020-08-08 10:24:10 +02:00
|
|
|
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-08-04 03:47:48 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Shared(ref cell, _, _) => {
|
2020-08-04 03:47:48 +02:00
|
|
|
if let Ok(v) = cell.try_borrow() {
|
|
|
|
fmt::Display::fmt(&*v, f)
|
|
|
|
} else {
|
|
|
|
f.write_str("<shared>")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_closure"))]
|
|
|
|
#[cfg(feature = "sync")]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Shared(ref cell, _, _) => fmt::Display::fmt(&*cell.read().unwrap(), f),
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for Dynamic {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2021-06-13 11:41:34 +02:00
|
|
|
match self.0 {
|
|
|
|
Union::Unit(ref value, _, _) => fmt::Debug::fmt(value, f),
|
|
|
|
Union::Bool(ref value, _, _) => fmt::Debug::fmt(value, f),
|
|
|
|
Union::Str(ref value, _, _) => fmt::Debug::fmt(value, f),
|
|
|
|
Union::Char(ref value, _, _) => fmt::Debug::fmt(value, f),
|
|
|
|
Union::Int(ref value, _, _) => fmt::Debug::fmt(value, f),
|
2020-04-12 17:00:06 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Float(ref value, _, _) => fmt::Debug::fmt(value, f),
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Decimal(ref value, _, _) => fmt::Debug::fmt(value, f),
|
2020-05-06 13:45:17 +02:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Array(ref value, _, _) => fmt::Debug::fmt(value, f),
|
2020-05-06 13:45:17 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Map(ref value, _, _) => {
|
2020-07-21 14:58:53 +02:00
|
|
|
f.write_str("#")?;
|
|
|
|
fmt::Debug::fmt(value, f)
|
|
|
|
}
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::FnPtr(ref value, _, _) => fmt::Debug::fmt(value, f),
|
2020-05-05 14:54:56 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::TimeStamp(_, _, _) => write!(f, "<timestamp>"),
|
2020-09-27 16:15:35 +02:00
|
|
|
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Variant(ref value, _, _) => {
|
|
|
|
let _value_any = (***value).as_any();
|
|
|
|
let _type_id = _value_any.type_id();
|
2021-02-23 12:08:05 +01:00
|
|
|
|
|
|
|
#[cfg(not(feature = "only_i32"))]
|
|
|
|
#[cfg(not(feature = "only_i64"))]
|
|
|
|
if _type_id == TypeId::of::<u8>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Debug::fmt(_value_any.downcast_ref::<u8>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<u16>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Debug::fmt(_value_any.downcast_ref::<u16>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<u32>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Debug::fmt(_value_any.downcast_ref::<u32>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<u64>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Debug::fmt(_value_any.downcast_ref::<u64>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<i8>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Debug::fmt(_value_any.downcast_ref::<i8>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<i16>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Debug::fmt(_value_any.downcast_ref::<i16>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<i32>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Debug::fmt(_value_any.downcast_ref::<i32>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<i64>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Debug::fmt(_value_any.downcast_ref::<i64>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
if _type_id == TypeId::of::<f32>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Debug::fmt(_value_any.downcast_ref::<f32>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<f64>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Debug::fmt(_value_any.downcast_ref::<f64>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
|
|
|
if _type_id == TypeId::of::<u128>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Debug::fmt(_value_any.downcast_ref::<u128>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
} else if _type_id == TypeId::of::<i128>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return fmt::Debug::fmt(_value_any.downcast_ref::<i128>().expect(CHECKED), f);
|
2021-02-23 12:08:05 +01:00
|
|
|
}
|
|
|
|
|
2021-06-13 11:41:34 +02:00
|
|
|
f.write_str((***value).type_name())
|
2021-02-23 12:08:05 +01:00
|
|
|
}
|
2020-08-08 10:24:10 +02:00
|
|
|
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-08-04 03:47:48 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Shared(ref cell, _, _) => {
|
2020-08-04 03:47:48 +02:00
|
|
|
if let Ok(v) = cell.try_borrow() {
|
|
|
|
write!(f, "{:?} (shared)", *v)
|
|
|
|
} else {
|
|
|
|
f.write_str("<shared>")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_closure"))]
|
|
|
|
#[cfg(feature = "sync")]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Shared(ref cell, _, _) => fmt::Debug::fmt(&*cell.read().unwrap(), f),
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
2017-12-20 12:16:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-29 12:33:29 +02:00
|
|
|
use AccessMode::*;
|
|
|
|
|
2020-03-04 15:00:01 +01:00
|
|
|
impl Clone for Dynamic {
|
2020-12-08 15:47:38 +01:00
|
|
|
/// Clone the [`Dynamic`] value.
|
|
|
|
///
|
2021-01-02 16:30:10 +01:00
|
|
|
/// # WARNING
|
2020-12-08 15:47:38 +01:00
|
|
|
///
|
2020-12-18 09:31:44 +01:00
|
|
|
/// The cloned copy is marked read-write even if the original is read-only.
|
2020-03-04 15:00:01 +01:00
|
|
|
fn clone(&self) -> Self {
|
2020-05-03 16:17:28 +02:00
|
|
|
match self.0 {
|
2021-05-29 12:33:29 +02:00
|
|
|
Union::Unit(value, tag, _) => Self(Union::Unit(value, tag, ReadWrite)),
|
|
|
|
Union::Bool(value, tag, _) => Self(Union::Bool(value, tag, ReadWrite)),
|
|
|
|
Union::Str(ref value, tag, _) => Self(Union::Str(value.clone(), tag, ReadWrite)),
|
|
|
|
Union::Char(value, tag, _) => Self(Union::Char(value, tag, ReadWrite)),
|
|
|
|
Union::Int(value, tag, _) => Self(Union::Int(value, tag, ReadWrite)),
|
2020-04-12 17:00:06 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-05-29 12:33:29 +02:00
|
|
|
Union::Float(value, tag, _) => Self(Union::Float(value, tag, ReadWrite)),
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
2021-05-03 07:57:47 +02:00
|
|
|
Union::Decimal(ref value, tag, _) => {
|
2021-05-29 12:33:29 +02:00
|
|
|
Self(Union::Decimal(value.clone(), tag, ReadWrite))
|
2021-02-13 13:57:56 +01:00
|
|
|
}
|
2020-05-06 13:45:17 +02:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
2021-05-29 12:33:29 +02:00
|
|
|
Union::Array(ref value, tag, _) => Self(Union::Array(value.clone(), tag, ReadWrite)),
|
2020-05-06 13:45:17 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-05-29 12:33:29 +02:00
|
|
|
Union::Map(ref value, tag, _) => Self(Union::Map(value.clone(), tag, ReadWrite)),
|
|
|
|
Union::FnPtr(ref value, tag, _) => Self(Union::FnPtr(value.clone(), tag, ReadWrite)),
|
2020-09-27 16:15:35 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::TimeStamp(ref value, tag, _) => {
|
2021-05-29 12:33:29 +02:00
|
|
|
Self(Union::TimeStamp(value.clone(), tag, ReadWrite))
|
2020-12-08 15:47:38 +01:00
|
|
|
}
|
2020-08-08 05:46:30 +02:00
|
|
|
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Variant(ref value, tag, _) => {
|
2021-05-25 04:54:48 +02:00
|
|
|
let mut x = value.as_ref().as_ref().clone_into_dynamic();
|
2021-05-02 17:57:35 +02:00
|
|
|
x.set_tag(tag);
|
|
|
|
x
|
|
|
|
}
|
2020-08-08 05:46:30 +02:00
|
|
|
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-29 12:33:29 +02:00
|
|
|
Union::Shared(ref cell, tag, _) => Self(Union::Shared(cell.clone(), tag, ReadWrite)),
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
2020-03-04 15:00:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-30 16:52:36 +02:00
|
|
|
impl Default for Dynamic {
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-04-30 16:52:36 +02:00
|
|
|
fn default() -> Self {
|
2020-11-15 16:14:29 +01:00
|
|
|
Self::UNIT
|
2020-04-30 16:52:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-12 17:00:06 +02:00
|
|
|
impl Dynamic {
|
2020-11-20 09:52:28 +01:00
|
|
|
/// A [`Dynamic`] containing a `()`.
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const UNIT: Dynamic = Self(Union::Unit((), DEFAULT_TAG_VALUE, ReadWrite));
|
2020-11-20 09:52:28 +01:00
|
|
|
/// A [`Dynamic`] containing a `true`.
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const TRUE: Dynamic = Self(Union::Bool(true, DEFAULT_TAG_VALUE, ReadWrite));
|
2020-11-20 09:52:28 +01:00
|
|
|
/// A [`Dynamic`] containing a [`false`].
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const FALSE: Dynamic = Self(Union::Bool(false, DEFAULT_TAG_VALUE, ReadWrite));
|
2020-11-20 09:52:28 +01:00
|
|
|
/// A [`Dynamic`] containing the integer zero.
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const ZERO: Dynamic = Self(Union::Int(0, DEFAULT_TAG_VALUE, ReadWrite));
|
2020-11-20 09:52:28 +01:00
|
|
|
/// A [`Dynamic`] containing the integer one.
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const ONE: Dynamic = Self(Union::Int(1, DEFAULT_TAG_VALUE, ReadWrite));
|
2021-05-11 14:31:31 +02:00
|
|
|
/// A [`Dynamic`] containing the integer two.
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const TWO: Dynamic = Self(Union::Int(2, DEFAULT_TAG_VALUE, ReadWrite));
|
2021-05-11 14:31:31 +02:00
|
|
|
/// A [`Dynamic`] containing the integer ten.
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const TEN: Dynamic = Self(Union::Int(10, DEFAULT_TAG_VALUE, ReadWrite));
|
2020-11-20 09:52:28 +01:00
|
|
|
/// A [`Dynamic`] containing the integer negative one.
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const NEGATIVE_ONE: Dynamic = Self(Union::Int(-1, DEFAULT_TAG_VALUE, ReadWrite));
|
2021-05-10 05:07:19 +02:00
|
|
|
/// A [`Dynamic`] containing `0.0`.
|
|
|
|
///
|
|
|
|
/// Not available under `no_float`.
|
2020-11-16 06:56:07 +01:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-04-06 17:18:41 +02:00
|
|
|
pub const FLOAT_ZERO: Dynamic = Self(Union::Float(
|
|
|
|
FloatWrapper::const_new(0.0),
|
2021-06-28 12:06:05 +02:00
|
|
|
DEFAULT_TAG_VALUE,
|
2021-05-29 12:33:29 +02:00
|
|
|
ReadWrite,
|
2021-04-06 17:18:41 +02:00
|
|
|
));
|
2021-05-10 05:07:19 +02:00
|
|
|
/// A [`Dynamic`] containing `1.0`.
|
|
|
|
///
|
|
|
|
/// Not available under `no_float`.
|
2020-11-16 06:56:07 +01:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-04-06 17:18:41 +02:00
|
|
|
pub const FLOAT_ONE: Dynamic = Self(Union::Float(
|
|
|
|
FloatWrapper::const_new(1.0),
|
2021-06-28 12:06:05 +02:00
|
|
|
DEFAULT_TAG_VALUE,
|
2021-05-29 12:33:29 +02:00
|
|
|
ReadWrite,
|
2021-05-11 14:31:31 +02:00
|
|
|
));
|
|
|
|
/// A [`Dynamic`] containing `2.0`.
|
|
|
|
///
|
|
|
|
/// Not available under `no_float`.
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
pub const FLOAT_TWO: Dynamic = Self(Union::Float(
|
|
|
|
FloatWrapper::const_new(2.0),
|
2021-06-28 12:06:05 +02:00
|
|
|
DEFAULT_TAG_VALUE,
|
2021-05-29 12:33:29 +02:00
|
|
|
ReadWrite,
|
2021-05-11 14:31:31 +02:00
|
|
|
));
|
|
|
|
/// A [`Dynamic`] containing `10.0`.
|
|
|
|
///
|
|
|
|
/// Not available under `no_float`.
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
pub const FLOAT_TEN: Dynamic = Self(Union::Float(
|
|
|
|
FloatWrapper::const_new(10.0),
|
2021-06-28 12:06:05 +02:00
|
|
|
DEFAULT_TAG_VALUE,
|
2021-05-29 12:33:29 +02:00
|
|
|
ReadWrite,
|
2021-04-06 17:18:41 +02:00
|
|
|
));
|
2021-05-10 05:07:19 +02:00
|
|
|
/// A [`Dynamic`] containing the `-1.0`.
|
|
|
|
///
|
|
|
|
/// Not available under `no_float`.
|
2020-11-16 06:56:07 +01:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-04-06 17:18:41 +02:00
|
|
|
pub const FLOAT_NEGATIVE_ONE: Dynamic = Self(Union::Float(
|
|
|
|
FloatWrapper::const_new(-1.0),
|
2021-06-28 12:06:05 +02:00
|
|
|
DEFAULT_TAG_VALUE,
|
2021-05-29 12:33:29 +02:00
|
|
|
ReadWrite,
|
2021-04-06 17:18:41 +02:00
|
|
|
));
|
2020-11-15 16:14:29 +01:00
|
|
|
|
2020-12-09 11:37:52 +01:00
|
|
|
/// Get the [`AccessMode`] for this [`Dynamic`].
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-05-25 04:54:48 +02:00
|
|
|
pub(crate) const fn access_mode(&self) -> AccessMode {
|
2020-12-08 15:47:38 +01:00
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Unit(_, _, access)
|
|
|
|
| Union::Bool(_, _, access)
|
|
|
|
| Union::Str(_, _, access)
|
|
|
|
| Union::Char(_, _, access)
|
|
|
|
| Union::Int(_, _, access)
|
|
|
|
| Union::FnPtr(_, _, access)
|
|
|
|
| Union::Variant(_, _, access) => access,
|
2020-12-08 16:09:12 +01:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Float(_, _, access) => access,
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Decimal(_, _, access) => access,
|
2020-12-08 16:09:12 +01:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Array(_, _, access) => access,
|
2020-12-08 16:09:12 +01:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Map(_, _, access) => access,
|
2020-12-08 16:09:12 +01:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::TimeStamp(_, _, access) => access,
|
2020-12-08 16:09:12 +01:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(_, _, access) => access,
|
2020-12-08 15:47:38 +01:00
|
|
|
}
|
|
|
|
}
|
2020-12-09 11:37:52 +01:00
|
|
|
/// Set the [`AccessMode`] for this [`Dynamic`].
|
2021-06-12 16:47:43 +02:00
|
|
|
pub(crate) fn set_access_mode(&mut self, typ: AccessMode) -> &mut Self {
|
2021-06-13 11:41:34 +02:00
|
|
|
match self.0 {
|
|
|
|
Union::Unit(_, _, ref mut access)
|
|
|
|
| Union::Bool(_, _, ref mut access)
|
|
|
|
| Union::Str(_, _, ref mut access)
|
|
|
|
| Union::Char(_, _, ref mut access)
|
|
|
|
| Union::Int(_, _, ref mut access)
|
|
|
|
| Union::FnPtr(_, _, ref mut access)
|
|
|
|
| Union::Variant(_, _, ref mut access) => *access = typ,
|
2020-12-08 16:09:12 +01:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Float(_, _, ref mut access) => *access = typ,
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Decimal(_, _, ref mut access) => *access = typ,
|
2020-12-08 16:09:12 +01:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Array(ref mut a, _, ref mut access) => {
|
2021-05-15 05:41:42 +02:00
|
|
|
*access = typ;
|
2021-06-12 16:47:43 +02:00
|
|
|
a.iter_mut().for_each(|v| {
|
|
|
|
v.set_access_mode(typ);
|
|
|
|
});
|
2021-05-15 05:41:42 +02:00
|
|
|
}
|
2020-12-08 16:09:12 +01:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Map(ref mut m, _, ref mut access) => {
|
2021-05-15 05:41:42 +02:00
|
|
|
*access = typ;
|
2021-06-12 16:47:43 +02:00
|
|
|
m.values_mut().for_each(|v| {
|
|
|
|
v.set_access_mode(typ);
|
|
|
|
});
|
2021-05-15 05:41:42 +02:00
|
|
|
}
|
2020-12-08 16:09:12 +01:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::TimeStamp(_, _, ref mut access) => *access = typ,
|
2020-12-08 16:09:12 +01:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
Union::Shared(_, _, ref mut access) => *access = typ,
|
2020-12-08 15:47:38 +01:00
|
|
|
}
|
2021-06-12 16:47:43 +02:00
|
|
|
self
|
2020-12-08 15:47:38 +01:00
|
|
|
}
|
2020-12-08 16:09:12 +01:00
|
|
|
/// Is this [`Dynamic`] read-only?
|
|
|
|
///
|
|
|
|
/// Constant [`Dynamic`] values are read-only. If a [`&mut Dynamic`][Dynamic] to such a constant
|
|
|
|
/// is passed to a Rust function, the function can use this information to return an error of
|
2021-01-02 16:30:10 +01:00
|
|
|
/// [`ErrorAssignmentToConstant`][crate::EvalAltResult::ErrorAssignmentToConstant]
|
2020-12-08 16:09:12 +01:00
|
|
|
/// if its value is going to be modified. This safe-guards constant values from being modified
|
|
|
|
/// from within Rust functions.
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-12-08 16:09:12 +01:00
|
|
|
pub fn is_read_only(&self) -> bool {
|
2021-03-06 14:25:49 +01:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-12-09 14:06:36 +01:00
|
|
|
match self.0 {
|
2021-05-29 12:33:29 +02:00
|
|
|
Union::Shared(_, _, ReadOnly) => return true,
|
2020-12-09 14:06:36 +01:00
|
|
|
|
2021-06-13 11:41:34 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
|
|
|
Union::Shared(ref cell, _, _) => {
|
|
|
|
return match cell.borrow().access_mode() {
|
|
|
|
ReadWrite => false,
|
|
|
|
ReadOnly => true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
Union::Shared(ref cell, _, _) => {
|
|
|
|
return match cell.read().unwrap().access_mode() {
|
2021-05-29 12:33:29 +02:00
|
|
|
ReadWrite => false,
|
|
|
|
ReadOnly => true,
|
2021-06-13 11:41:34 +02:00
|
|
|
}
|
2021-03-05 06:34:58 +01:00
|
|
|
}
|
2021-06-13 11:41:34 +02:00
|
|
|
|
2021-03-06 14:25:49 +01:00
|
|
|
_ => (),
|
|
|
|
}
|
2020-12-09 14:06:36 +01:00
|
|
|
|
2021-03-06 14:25:49 +01:00
|
|
|
match self.access_mode() {
|
2021-05-29 12:33:29 +02:00
|
|
|
ReadWrite => false,
|
|
|
|
ReadOnly => true,
|
2020-12-09 14:06:36 +01:00
|
|
|
}
|
2020-12-08 15:47:38 +01:00
|
|
|
}
|
2021-03-05 03:33:48 +01:00
|
|
|
/// Can this [`Dynamic`] be hashed?
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-03-05 03:33:48 +01:00
|
|
|
pub(crate) fn is_hashable(&self) -> bool {
|
2021-06-13 11:41:34 +02:00
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Unit(_, _, _)
|
|
|
|
| Union::Bool(_, _, _)
|
|
|
|
| Union::Str(_, _, _)
|
|
|
|
| Union::Char(_, _, _)
|
|
|
|
| Union::Int(_, _, _) => true,
|
2021-03-05 03:33:48 +01:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Float(_, _, _) => true,
|
2021-03-05 03:33:48 +01:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Array(_, _, _) => true,
|
2021-03-05 03:33:48 +01:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Map(_, _, _) => true,
|
2021-03-05 03:33:48 +01:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-06-13 11:41:34 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
|
|
|
Union::Shared(ref cell, _, _) => cell.borrow().is_hashable(),
|
2021-03-05 07:18:36 +01:00
|
|
|
|
2021-06-13 11:41:34 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
Union::Shared(ref cell, _, _) => cell.read().unwrap().is_hashable(),
|
2021-03-05 03:33:48 +01:00
|
|
|
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Create a [`Dynamic`] from any type. A [`Dynamic`] value is simply returned as is.
|
2020-04-02 06:35:44 +02:00
|
|
|
///
|
2020-05-10 15:25:47 +02:00
|
|
|
/// # Safety
|
|
|
|
///
|
|
|
|
/// This type uses some unsafe code, mainly for type casting.
|
|
|
|
///
|
|
|
|
/// # Notes
|
|
|
|
///
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Beware that you need to pass in an [`Array`] type for it to be recognized as an [`Array`].
|
|
|
|
/// A [`Vec<T>`][Vec] does not get automatically converted to an [`Array`], but will be a generic
|
|
|
|
/// restricted trait object instead, because [`Vec<T>`][Vec] is not a supported standard type.
|
2020-04-16 04:24:30 +02:00
|
|
|
///
|
2021-03-23 05:13:53 +01:00
|
|
|
/// Similarly, passing in a [`HashMap<String, T>`][std::collections::HashMap] or
|
|
|
|
/// [`BTreeMap<String, T>`][std::collections::BTreeMap] will not get a [`Map`] but a trait object.
|
2020-04-16 04:24:30 +02:00
|
|
|
///
|
2020-04-12 17:00:06 +02:00
|
|
|
/// # Examples
|
2020-04-02 06:35:44 +02:00
|
|
|
///
|
2020-04-12 17:00:06 +02:00
|
|
|
/// ```
|
|
|
|
/// use rhai::Dynamic;
|
|
|
|
///
|
|
|
|
/// let result = Dynamic::from(42_i64);
|
|
|
|
/// assert_eq!(result.type_name(), "i64");
|
|
|
|
/// assert_eq!(result.to_string(), "42");
|
|
|
|
///
|
2020-10-07 05:44:06 +02:00
|
|
|
/// let result = Dynamic::from("hello");
|
2020-04-12 17:00:06 +02:00
|
|
|
/// assert_eq!(result.type_name(), "string");
|
|
|
|
/// assert_eq!(result.to_string(), "hello");
|
2020-04-13 04:27:08 +02:00
|
|
|
///
|
|
|
|
/// let new_result = Dynamic::from(result);
|
|
|
|
/// assert_eq!(new_result.type_name(), "string");
|
|
|
|
/// assert_eq!(new_result.to_string(), "hello");
|
2020-04-12 17:00:06 +02:00
|
|
|
/// ```
|
2020-07-22 07:05:24 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-03-22 04:18:09 +01:00
|
|
|
pub fn from<T: Variant + Clone>(mut value: T) -> Self {
|
2020-10-08 16:25:50 +02:00
|
|
|
// Coded this way in order to maximally leverage potentials for dead-code removal.
|
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<Dynamic>() {
|
2021-05-22 13:14:24 +02:00
|
|
|
return unsafe_try_cast::<_, Dynamic>(value).ok().expect(CHECKED);
|
2021-03-22 04:18:09 +01:00
|
|
|
}
|
|
|
|
|
2021-05-25 04:54:48 +02:00
|
|
|
let val = value.as_any();
|
|
|
|
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<INT>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return val.downcast_ref::<INT>().expect(CHECKED).clone().into();
|
2020-07-22 07:05:24 +02:00
|
|
|
}
|
2020-04-12 17:00:06 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<FLOAT>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return val.downcast_ref::<FLOAT>().expect(CHECKED).clone().into();
|
2020-07-22 07:05:24 +02:00
|
|
|
}
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
if TypeId::of::<T>() == TypeId::of::<Decimal>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return val.downcast_ref::<Decimal>().expect(CHECKED).clone().into();
|
2021-02-13 13:57:56 +01:00
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<bool>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return val.downcast_ref::<bool>().expect(CHECKED).clone().into();
|
2020-07-22 07:05:24 +02:00
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<char>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return val.downcast_ref::<char>().expect(CHECKED).clone().into();
|
2020-07-22 07:05:24 +02:00
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return val
|
|
|
|
.downcast_ref::<ImmutableString>()
|
2021-05-22 13:14:24 +02:00
|
|
|
.expect(CHECKED)
|
2020-07-22 07:05:24 +02:00
|
|
|
.clone()
|
|
|
|
.into();
|
|
|
|
}
|
2020-10-06 15:25:05 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<&str>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return val.downcast_ref::<&str>().expect(CHECKED).deref().into();
|
2020-10-06 15:25:05 +02:00
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<()>() {
|
2020-07-22 07:05:24 +02:00
|
|
|
return ().into();
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
value = match unsafe_try_cast::<_, String>(value) {
|
2021-05-11 15:38:07 +02:00
|
|
|
Ok(s) => return s.into(),
|
|
|
|
Err(value) => value,
|
2020-05-06 13:45:17 +02:00
|
|
|
};
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
{
|
2021-03-22 04:18:09 +01:00
|
|
|
value = match unsafe_try_cast::<_, Array>(value) {
|
2021-05-11 15:38:07 +02:00
|
|
|
Ok(array) => return array.into(),
|
|
|
|
Err(value) => value,
|
2020-05-06 13:45:17 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
{
|
2021-03-22 04:18:09 +01:00
|
|
|
value = match unsafe_try_cast::<_, Map>(value) {
|
2021-05-11 15:38:07 +02:00
|
|
|
Ok(map) => return map.into(),
|
|
|
|
Err(value) => value,
|
2021-03-26 09:57:28 +01:00
|
|
|
};
|
2020-05-06 13:45:17 +02:00
|
|
|
}
|
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
value = match unsafe_try_cast::<_, FnPtr>(value) {
|
2021-05-11 15:38:07 +02:00
|
|
|
Ok(fn_ptr) => return fn_ptr.into(),
|
|
|
|
Err(value) => value,
|
2020-08-03 17:11:24 +02:00
|
|
|
};
|
|
|
|
|
2020-09-27 16:15:35 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
|
|
|
{
|
2021-03-22 04:18:09 +01:00
|
|
|
value = match unsafe_try_cast::<_, Instant>(value) {
|
2021-05-11 15:38:07 +02:00
|
|
|
Ok(timestamp) => return timestamp.into(),
|
|
|
|
Err(value) => value,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_closure"))]
|
|
|
|
{
|
|
|
|
value = match unsafe_try_cast::<_, crate::Shared<crate::Locked<Dynamic>>>(value) {
|
|
|
|
Ok(value) => return value.into(),
|
|
|
|
Err(value) => value,
|
2021-03-26 09:57:28 +01:00
|
|
|
};
|
2020-09-27 16:15:35 +02:00
|
|
|
}
|
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
Self(Union::Variant(
|
|
|
|
Box::new(Box::new(value)),
|
2021-06-28 12:06:05 +02:00
|
|
|
DEFAULT_TAG_VALUE,
|
2021-05-29 12:33:29 +02:00
|
|
|
ReadWrite,
|
2021-03-22 04:18:09 +01:00
|
|
|
))
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
2020-12-26 06:05:57 +01:00
|
|
|
/// Turn the [`Dynamic`] value into a shared [`Dynamic`] value backed by an
|
|
|
|
/// [`Rc`][std::rc::Rc]`<`[`RefCell`][std::cell::RefCell]`<`[`Dynamic`]`>>` or
|
|
|
|
/// [`Arc`][std::sync::Arc]`<`[`RwLock`][std::sync::RwLock]`<`[`Dynamic`]`>>`
|
|
|
|
/// depending on the `sync` feature.
|
2020-03-04 15:00:01 +01:00
|
|
|
///
|
2021-02-19 08:50:48 +01:00
|
|
|
/// Not available under `no_closure`.
|
2021-02-06 15:16:44 +01:00
|
|
|
///
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Shared [`Dynamic`] values are relatively cheap to clone as they simply increment the
|
2020-07-31 10:03:08 +02:00
|
|
|
/// reference counts.
|
2020-07-27 06:30:09 +02:00
|
|
|
///
|
2020-12-26 06:05:57 +01:00
|
|
|
/// Shared [`Dynamic`] values can be converted seamlessly to and from ordinary [`Dynamic`]
|
|
|
|
/// values.
|
2020-07-27 06:30:09 +02:00
|
|
|
///
|
2020-11-20 09:52:28 +01:00
|
|
|
/// If the [`Dynamic`] value is already shared, this method returns itself.
|
2021-02-06 15:16:44 +01:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-08-04 12:39:24 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-07-27 06:30:09 +02:00
|
|
|
pub fn into_shared(self) -> Self {
|
2020-12-09 11:37:52 +01:00
|
|
|
let _access = self.access_mode();
|
2020-12-08 15:47:38 +01:00
|
|
|
|
2021-03-06 14:25:49 +01:00
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(_, _, _) => self,
|
|
|
|
_ => Self(Union::Shared(
|
|
|
|
crate::Locked::new(self).into(),
|
2021-06-28 12:06:05 +02:00
|
|
|
DEFAULT_TAG_VALUE,
|
2021-05-02 17:57:35 +02:00
|
|
|
_access,
|
|
|
|
)),
|
2021-03-06 14:25:49 +01:00
|
|
|
}
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Convert the [`Dynamic`] value into specific type.
|
2020-07-31 10:39:38 +02:00
|
|
|
///
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Casting to a [`Dynamic`] just returns as is, but if it contains a shared value,
|
|
|
|
/// it is cloned into a [`Dynamic`] with a normal value.
|
2020-03-04 15:00:01 +01:00
|
|
|
///
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Returns [`None`] if types mismatched.
|
2020-07-27 06:30:09 +02:00
|
|
|
///
|
2020-08-04 10:27:55 +02:00
|
|
|
/// # Panics or Deadlocks
|
2020-07-27 06:30:09 +02:00
|
|
|
///
|
2020-11-25 02:36:06 +01:00
|
|
|
/// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1).
|
2020-07-31 10:03:08 +02:00
|
|
|
/// Otherwise, this call panics if the data is currently borrowed for write.
|
2020-07-27 06:30:09 +02:00
|
|
|
///
|
2020-07-31 10:03:08 +02:00
|
|
|
/// These normally shouldn't occur since most operations in Rhai is single-threaded.
|
2020-04-12 17:00:06 +02:00
|
|
|
///
|
2020-03-04 15:00:01 +01:00
|
|
|
/// # Example
|
|
|
|
///
|
2020-03-19 06:52:10 +01:00
|
|
|
/// ```
|
2020-04-12 17:00:06 +02:00
|
|
|
/// use rhai::Dynamic;
|
2020-03-04 15:00:01 +01:00
|
|
|
///
|
2020-04-12 17:00:06 +02:00
|
|
|
/// let x = Dynamic::from(42_u32);
|
2020-03-04 15:00:01 +01:00
|
|
|
///
|
2020-04-02 06:35:44 +02:00
|
|
|
/// assert_eq!(x.try_cast::<u32>().unwrap(), 42);
|
2020-03-04 15:00:01 +01:00
|
|
|
/// ```
|
2020-07-22 07:05:24 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-04-19 12:08:29 +02:00
|
|
|
pub fn try_cast<T: Any>(self) -> Option<T> {
|
2020-10-08 16:25:50 +02:00
|
|
|
// Coded this way in order to maximally leverage potentials for dead-code removal.
|
|
|
|
|
2021-03-04 03:50:45 +01:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
if let Union::Shared(_, _, _) = self.0 {
|
2021-03-04 03:24:14 +01:00
|
|
|
return self.flatten().try_cast::<T>();
|
2020-07-31 10:39:38 +02:00
|
|
|
}
|
|
|
|
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<Dynamic>() {
|
2021-03-22 04:18:09 +01:00
|
|
|
return unsafe_try_cast::<_, T>(self).ok();
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
|
|
|
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<INT>() {
|
2020-07-22 07:05:24 +02:00
|
|
|
return match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Int(value, _, _) => unsafe_try_cast(value).ok(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-07-31 00:34:20 +02:00
|
|
|
|
2020-07-22 07:05:24 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<FLOAT>() {
|
2020-07-22 07:05:24 +02:00
|
|
|
return match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Float(value, _, _) => unsafe_try_cast(*value).ok(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-07-31 00:34:20 +02:00
|
|
|
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
if TypeId::of::<T>() == TypeId::of::<Decimal>() {
|
|
|
|
return match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Decimal(value, _, _) => unsafe_try_cast(*value).ok(),
|
2021-02-13 13:57:56 +01:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<bool>() {
|
2020-07-22 07:05:24 +02:00
|
|
|
return match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Bool(value, _, _) => unsafe_try_cast(value).ok(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-07-31 00:34:20 +02:00
|
|
|
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
|
2020-07-22 07:05:24 +02:00
|
|
|
return match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Str(value, _, _) => unsafe_try_cast(value).ok(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-07-31 00:34:20 +02:00
|
|
|
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<String>() {
|
2020-07-22 07:05:24 +02:00
|
|
|
return match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Str(value, _, _) => unsafe_try_cast(value.into_owned()).ok(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-07-31 00:34:20 +02:00
|
|
|
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<char>() {
|
2020-07-22 07:05:24 +02:00
|
|
|
return match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Char(value, _, _) => unsafe_try_cast(value).ok(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-07-31 00:34:20 +02:00
|
|
|
|
2020-07-22 07:05:24 +02:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<Array>() {
|
2020-07-22 07:05:24 +02:00
|
|
|
return match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Array(value, _, _) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-07-31 00:34:20 +02:00
|
|
|
|
2020-07-22 07:05:24 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<Map>() {
|
2020-07-22 07:05:24 +02:00
|
|
|
return match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Map(value, _, _) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-07-31 00:34:20 +02:00
|
|
|
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
|
2020-07-22 07:05:24 +02:00
|
|
|
return match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::FnPtr(value, _, _) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-07-31 00:34:20 +02:00
|
|
|
|
2020-09-27 16:15:35 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
|
|
|
if TypeId::of::<T>() == TypeId::of::<Instant>() {
|
|
|
|
return match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::TimeStamp(value, _, _) => unsafe_cast_box::<_, T>(value).ok().map(|v| *v),
|
2020-09-27 16:15:35 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<()>() {
|
2020-07-22 07:05:24 +02:00
|
|
|
return match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Unit(value, _, _) => unsafe_try_cast(value).ok(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-04-13 04:27:08 +02:00
|
|
|
|
2020-04-30 16:52:36 +02:00
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Variant(value, _, _) => (*value).as_box_any().downcast().map(|x| *x).ok(),
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(_, _, _) => unreachable!("Union::Shared case should be already handled"),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
2017-12-20 12:16:14 +01:00
|
|
|
}
|
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Convert the [`Dynamic`] value into a specific type.
|
2020-04-02 06:35:44 +02:00
|
|
|
///
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Casting to a [`Dynamic`] just returns as is, but if it contains a shared value,
|
|
|
|
/// it is cloned into a [`Dynamic`] with a normal value.
|
2020-04-02 06:35:44 +02:00
|
|
|
///
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Returns [`None`] if types mismatched.
|
2020-07-31 10:03:08 +02:00
|
|
|
///
|
2020-08-04 10:27:55 +02:00
|
|
|
/// # Panics or Deadlocks
|
2020-04-02 06:35:44 +02:00
|
|
|
///
|
2020-07-27 06:30:09 +02:00
|
|
|
/// Panics if the cast fails (e.g. the type of the actual value is not the
|
2020-07-31 10:03:08 +02:00
|
|
|
/// same as the specified type).
|
2020-07-27 06:30:09 +02:00
|
|
|
///
|
2020-11-25 02:36:06 +01:00
|
|
|
/// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1).
|
2020-07-31 10:03:08 +02:00
|
|
|
/// Otherwise, this call panics if the data is currently borrowed for write.
|
2020-07-27 06:30:09 +02:00
|
|
|
///
|
2020-07-31 10:03:08 +02:00
|
|
|
/// These normally shouldn't occur since most operations in Rhai is single-threaded.
|
2020-04-02 06:35:44 +02:00
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```
|
2020-04-12 17:00:06 +02:00
|
|
|
/// use rhai::Dynamic;
|
2020-04-02 06:35:44 +02:00
|
|
|
///
|
2020-04-12 17:00:06 +02:00
|
|
|
/// let x = Dynamic::from(42_u32);
|
2020-04-02 06:35:44 +02:00
|
|
|
///
|
|
|
|
/// assert_eq!(x.cast::<u32>(), 42);
|
|
|
|
/// ```
|
2020-07-22 07:05:24 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-04-19 12:08:29 +02:00
|
|
|
pub fn cast<T: Any + Clone>(self) -> T {
|
2021-04-17 06:03:29 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-09-27 05:14:50 +02:00
|
|
|
let self_type_name = if self.is_shared() {
|
|
|
|
// Avoid panics/deadlocks with shared values
|
|
|
|
"<shared>"
|
|
|
|
} else {
|
|
|
|
self.type_name()
|
|
|
|
};
|
2021-04-17 06:03:29 +02:00
|
|
|
#[cfg(feature = "no_closure")]
|
|
|
|
let self_type_name = self.type_name();
|
2020-09-27 05:14:50 +02:00
|
|
|
|
|
|
|
self.try_cast::<T>().unwrap_or_else(|| {
|
|
|
|
panic!(
|
2020-09-28 05:19:49 +02:00
|
|
|
"cannot cast {} value and to {}",
|
2020-09-27 05:14:50 +02:00
|
|
|
self_type_name,
|
|
|
|
type_name::<T>()
|
|
|
|
)
|
|
|
|
})
|
2020-04-02 06:35:44 +02:00
|
|
|
}
|
2021-03-30 12:57:16 +02:00
|
|
|
/// Clone the [`Dynamic`] value and convert it into a specific type.
|
|
|
|
///
|
|
|
|
/// Casting to a [`Dynamic`] just returns as is, but if it contains a shared value,
|
|
|
|
/// it is cloned into a [`Dynamic`] with a normal value.
|
|
|
|
///
|
|
|
|
/// Returns [`None`] if types mismatched.
|
|
|
|
///
|
|
|
|
/// # Panics or Deadlocks
|
|
|
|
///
|
|
|
|
/// Panics if the cast fails (e.g. the type of the actual value is not the
|
|
|
|
/// same as the specified type).
|
|
|
|
///
|
|
|
|
/// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1).
|
|
|
|
/// Otherwise, this call panics if the data is currently borrowed for write.
|
|
|
|
///
|
|
|
|
/// These normally shouldn't occur since most operations in Rhai is single-threaded.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use rhai::Dynamic;
|
|
|
|
///
|
|
|
|
/// let x = Dynamic::from(42_u32);
|
|
|
|
/// let y = &x;
|
|
|
|
///
|
|
|
|
/// assert_eq!(y.clone_cast::<u32>(), 42);
|
|
|
|
/// ```
|
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-04-19 12:08:29 +02:00
|
|
|
pub fn clone_cast<T: Any + Clone>(&self) -> T {
|
2021-04-23 13:10:10 +02:00
|
|
|
self.flatten_clone().cast::<T>()
|
2021-03-30 12:57:16 +02:00
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Flatten the [`Dynamic`] and clone it.
|
2020-07-31 10:03:08 +02:00
|
|
|
///
|
2020-11-20 09:52:28 +01:00
|
|
|
/// If the [`Dynamic`] is not a shared value, it returns a cloned copy.
|
2020-07-31 10:03:08 +02:00
|
|
|
///
|
2021-04-23 13:10:10 +02:00
|
|
|
/// If the [`Dynamic`] is a shared value, it returns a cloned copy of the shared value.
|
2020-08-08 10:24:10 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-08-08 11:04:21 +02:00
|
|
|
pub fn flatten_clone(&self) -> Self {
|
2021-06-13 11:41:34 +02:00
|
|
|
match self.0 {
|
|
|
|
#[cfg(not(feature = "no_closure"))]
|
|
|
|
#[cfg(not(feature = "sync"))]
|
|
|
|
Union::Shared(ref cell, _, _) => cell.borrow().clone(),
|
|
|
|
#[cfg(not(feature = "no_closure"))]
|
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
Union::Shared(ref cell, _, _) => cell.read().unwrap().clone(),
|
|
|
|
_ => self.clone(),
|
2020-08-08 10:24:10 +02:00
|
|
|
}
|
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Flatten the [`Dynamic`].
|
2020-07-31 10:03:08 +02:00
|
|
|
///
|
2020-11-20 09:52:28 +01:00
|
|
|
/// If the [`Dynamic`] is not a shared value, it returns itself.
|
2020-07-31 10:03:08 +02:00
|
|
|
///
|
2020-12-26 06:05:57 +01:00
|
|
|
/// If the [`Dynamic`] is a shared value, it returns the shared value if there are no
|
|
|
|
/// outstanding references, or a cloned copy.
|
2020-07-22 07:05:24 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-08-08 10:24:10 +02:00
|
|
|
pub fn flatten(self) -> Self {
|
2020-07-27 06:30:09 +02:00
|
|
|
match self.0 {
|
2021-06-13 11:41:34 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
|
|
|
Union::Shared(cell, _, _) => crate::fn_native::shared_try_take(cell).map_or_else(
|
|
|
|
#[cfg(not(feature = "sync"))]
|
|
|
|
|cell| cell.borrow().clone(),
|
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
|cell| cell.read().unwrap().clone(),
|
|
|
|
#[cfg(not(feature = "sync"))]
|
|
|
|
|value| value.into_inner(),
|
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
|value| value.into_inner().unwrap(),
|
|
|
|
),
|
|
|
|
_ => self,
|
2021-03-06 14:25:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/// Flatten the [`Dynamic`] in place.
|
|
|
|
///
|
|
|
|
/// If the [`Dynamic`] is not a shared value, it does nothing.
|
|
|
|
///
|
|
|
|
/// If the [`Dynamic`] is a shared value, it is set to the shared value if there are no
|
|
|
|
/// outstanding references, or a cloned copy otherwise.
|
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
pub(crate) fn flatten_in_place(&mut self) -> &mut Self {
|
2021-03-06 14:25:49 +01:00
|
|
|
match self.0 {
|
2021-06-13 11:41:34 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(_, _, _) => match std::mem::take(self).0 {
|
|
|
|
Union::Shared(cell, _, _) => {
|
2021-03-06 15:07:20 +01:00
|
|
|
*self = crate::fn_native::shared_try_take(cell).map_or_else(
|
2021-06-13 11:41:34 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
|
|
|
|cell| cell.borrow().clone(),
|
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
|cell| cell.read().unwrap().clone(),
|
|
|
|
#[cfg(not(feature = "sync"))]
|
|
|
|
|value| value.into_inner(),
|
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
|value| value.into_inner().unwrap(),
|
|
|
|
);
|
2021-03-06 14:25:49 +01:00
|
|
|
}
|
2021-03-07 15:10:54 +01:00
|
|
|
_ => unreachable!(),
|
2021-03-06 14:25:49 +01:00
|
|
|
},
|
|
|
|
_ => (),
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
2021-06-12 16:47:43 +02:00
|
|
|
self
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Is the [`Dynamic`] a shared value that is locked?
|
2020-08-02 07:33:51 +02:00
|
|
|
///
|
2021-04-17 06:03:29 +02:00
|
|
|
/// Not available under `no_closure`.
|
|
|
|
///
|
2020-08-02 07:33:51 +02:00
|
|
|
/// ## Note
|
|
|
|
///
|
2020-11-25 02:36:06 +01:00
|
|
|
/// Under the `sync` feature, shared values use [`RwLock`][std::sync::RwLock] and they are never locked.
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Access just waits until the [`RwLock`][std::sync::RwLock] is released.
|
|
|
|
/// So this method always returns [`false`] under [`Sync`].
|
2021-04-17 06:03:29 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-08-02 07:33:51 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-08-02 07:33:51 +02:00
|
|
|
pub fn is_locked(&self) -> bool {
|
2021-03-06 14:25:49 +01:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-08-02 07:33:51 +02:00
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(ref _cell, _, _) => {
|
2020-08-02 07:33:51 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
|
|
|
return _cell.try_borrow().is_err();
|
|
|
|
|
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
return false;
|
|
|
|
}
|
2021-03-06 14:25:49 +01:00
|
|
|
_ => (),
|
2020-08-02 07:33:51 +02:00
|
|
|
}
|
2021-03-06 14:25:49 +01:00
|
|
|
|
|
|
|
false
|
2020-08-02 07:33:51 +02:00
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Get a reference of a specific type to the [`Dynamic`].
|
|
|
|
/// Casting to [`Dynamic`] just returns a reference to it.
|
2020-07-31 10:03:08 +02:00
|
|
|
///
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Returns [`None`] if the cast fails.
|
2020-08-03 06:10:20 +02:00
|
|
|
///
|
2020-08-04 10:27:55 +02:00
|
|
|
/// # Panics or Deadlocks When Value is Shared
|
2020-08-03 06:10:20 +02:00
|
|
|
///
|
2020-11-25 02:36:06 +01:00
|
|
|
/// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1).
|
2020-08-03 06:10:20 +02:00
|
|
|
/// Otherwise, this call panics if the data is currently borrowed for write.
|
2020-07-27 06:30:09 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-04-19 12:08:29 +02:00
|
|
|
pub fn read_lock<T: Any + Clone>(&self) -> Option<DynamicReadLock<T>> {
|
2020-07-27 06:30:09 +02:00
|
|
|
match self.0 {
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(ref cell, _, _) => {
|
2020-07-27 06:30:09 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2021-03-05 07:18:36 +01:00
|
|
|
let value = cell.borrow();
|
2020-07-27 06:30:09 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2021-03-05 07:18:36 +01:00
|
|
|
let value = cell.read().unwrap();
|
2020-08-03 06:10:20 +02:00
|
|
|
|
2021-05-22 13:14:24 +02:00
|
|
|
if (*value).type_id() != TypeId::of::<T>()
|
|
|
|
&& TypeId::of::<Dynamic>() != TypeId::of::<T>()
|
|
|
|
{
|
2021-03-06 14:25:49 +01:00
|
|
|
return None;
|
2020-08-03 06:10:20 +02:00
|
|
|
} else {
|
2021-03-06 14:25:49 +01:00
|
|
|
return Some(DynamicReadLock(DynamicReadLockInner::Guard(value)));
|
2020-08-03 06:10:20 +02:00
|
|
|
}
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
2021-03-06 14:25:49 +01:00
|
|
|
_ => (),
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
2021-03-06 14:25:49 +01:00
|
|
|
|
|
|
|
self.downcast_ref()
|
|
|
|
.map(|r| DynamicReadLock(DynamicReadLockInner::Reference(r)))
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Get a mutable reference of a specific type to the [`Dynamic`].
|
|
|
|
/// Casting to [`Dynamic`] just returns a mutable reference to it.
|
2020-07-31 10:03:08 +02:00
|
|
|
///
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Returns [`None`] if the cast fails.
|
2020-08-03 06:10:20 +02:00
|
|
|
///
|
2020-08-04 10:27:55 +02:00
|
|
|
/// # Panics or Deadlocks When Value is Shared
|
2020-08-03 06:10:20 +02:00
|
|
|
///
|
2020-11-25 02:36:06 +01:00
|
|
|
/// Under the `sync` feature, this call may deadlock, or [panic](https://doc.rust-lang.org/std/sync/struct.RwLock.html#panics-1).
|
2020-08-03 06:10:20 +02:00
|
|
|
/// Otherwise, this call panics if the data is currently borrowed for write.
|
2020-07-27 06:30:09 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-04-19 12:08:29 +02:00
|
|
|
pub fn write_lock<T: Any + Clone>(&mut self) -> Option<DynamicWriteLock<T>> {
|
2020-07-27 06:30:09 +02:00
|
|
|
match self.0 {
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(ref cell, _, _) => {
|
2020-07-27 06:30:09 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2021-03-05 07:18:36 +01:00
|
|
|
let value = cell.borrow_mut();
|
2020-07-27 06:30:09 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2021-03-05 07:18:36 +01:00
|
|
|
let value = cell.write().unwrap();
|
2020-08-03 06:10:20 +02:00
|
|
|
|
2021-05-22 13:14:24 +02:00
|
|
|
if (*value).type_id() != TypeId::of::<T>()
|
|
|
|
&& TypeId::of::<Dynamic>() != TypeId::of::<T>()
|
|
|
|
{
|
2021-03-06 14:25:49 +01:00
|
|
|
return None;
|
2020-08-03 06:10:20 +02:00
|
|
|
} else {
|
2021-03-06 14:25:49 +01:00
|
|
|
return Some(DynamicWriteLock(DynamicWriteLockInner::Guard(value)));
|
2020-08-03 06:10:20 +02:00
|
|
|
}
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
2021-03-06 14:25:49 +01:00
|
|
|
_ => (),
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
2021-03-06 14:25:49 +01:00
|
|
|
|
|
|
|
self.downcast_mut()
|
|
|
|
.map(|r| DynamicWriteLock(DynamicWriteLockInner::Reference(r)))
|
2020-07-27 06:30:09 +02:00
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Get a reference of a specific type to the [`Dynamic`].
|
|
|
|
/// Casting to [`Dynamic`] just returns a reference to it.
|
2020-07-31 10:03:08 +02:00
|
|
|
///
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Returns [`None`] if the cast fails, or if the value is shared.
|
2020-07-22 07:05:24 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-04-23 13:10:10 +02:00
|
|
|
pub(crate) fn downcast_ref<T: Any + Clone + ?Sized>(&self) -> Option<&T> {
|
2020-10-08 16:25:50 +02:00
|
|
|
// Coded this way in order to maximally leverage potentials for dead-code removal.
|
|
|
|
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<INT>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Int(ref value, _, _) => value.as_any().downcast_ref::<T>(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<FLOAT>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Float(ref value, _, _) => value.as_ref().as_any().downcast_ref::<T>(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
if TypeId::of::<T>() == TypeId::of::<Decimal>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Decimal(ref value, _, _) => value.as_ref().as_any().downcast_ref::<T>(),
|
2021-02-13 13:57:56 +01:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<bool>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Bool(ref value, _, _) => value.as_any().downcast_ref::<T>(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Str(ref value, _, _) => value.as_any().downcast_ref::<T>(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<char>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Char(ref value, _, _) => value.as_any().downcast_ref::<T>(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<Array>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Array(ref value, _, _) => value.as_ref().as_any().downcast_ref::<T>(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<Map>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Map(ref value, _, _) => value.as_ref().as_any().downcast_ref::<T>(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::FnPtr(ref value, _, _) => value.as_ref().as_any().downcast_ref::<T>(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-09-27 16:15:35 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
|
|
|
if TypeId::of::<T>() == TypeId::of::<Instant>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::TimeStamp(ref value, _, _) => value.as_ref().as_any().downcast_ref::<T>(),
|
2020-09-27 16:15:35 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<()>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Unit(ref value, _, _) => value.as_any().downcast_ref::<T>(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<Dynamic>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return self.as_any().downcast_ref::<T>();
|
2020-04-13 17:31:05 +02:00
|
|
|
}
|
|
|
|
|
2021-06-13 11:41:34 +02:00
|
|
|
match self.0 {
|
|
|
|
Union::Variant(ref value, _, _) => (***value).as_any().downcast_ref::<T>(),
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(_, _, _) => None,
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Get a mutable reference of a specific type to the [`Dynamic`].
|
|
|
|
/// Casting to [`Dynamic`] just returns a mutable reference to it.
|
2020-07-31 10:03:08 +02:00
|
|
|
///
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Returns [`None`] if the cast fails, or if the value is shared.
|
2020-07-22 07:05:24 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-04-19 12:08:29 +02:00
|
|
|
pub(crate) fn downcast_mut<T: Any + Clone>(&mut self) -> Option<&mut T> {
|
2020-10-08 16:25:50 +02:00
|
|
|
// Coded this way in order to maximally leverage potentials for dead-code removal.
|
|
|
|
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<INT>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Int(ref mut value, _, _) => value.as_mut_any().downcast_mut::<T>(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<FLOAT>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Float(ref mut value, _, _) => {
|
|
|
|
value.as_mut().as_mut_any().downcast_mut::<T>()
|
|
|
|
}
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
if TypeId::of::<T>() == TypeId::of::<Decimal>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Decimal(ref mut value, _, _) => {
|
|
|
|
value.as_mut().as_mut_any().downcast_mut::<T>()
|
|
|
|
}
|
2021-02-13 13:57:56 +01:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<bool>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Bool(ref mut value, _, _) => value.as_mut_any().downcast_mut::<T>(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<ImmutableString>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Str(ref mut value, _, _) => value.as_mut_any().downcast_mut::<T>(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<char>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Char(ref mut value, _, _) => value.as_mut_any().downcast_mut::<T>(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<Array>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Array(ref mut value, _, _) => {
|
|
|
|
value.as_mut().as_mut_any().downcast_mut::<T>()
|
|
|
|
}
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<Map>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Map(ref mut value, _, _) => value.as_mut().as_mut_any().downcast_mut::<T>(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<FnPtr>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::FnPtr(ref mut value, _, _) => {
|
|
|
|
value.as_mut().as_mut_any().downcast_mut::<T>()
|
|
|
|
}
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-09-27 16:15:35 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
|
|
|
if TypeId::of::<T>() == TypeId::of::<Instant>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::TimeStamp(ref mut value, _, _) => {
|
|
|
|
value.as_mut().as_mut_any().downcast_mut::<T>()
|
|
|
|
}
|
2020-09-27 16:15:35 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<()>() {
|
2021-06-13 11:41:34 +02:00
|
|
|
return match self.0 {
|
|
|
|
Union::Unit(ref mut value, _, _) => value.as_mut_any().downcast_mut::<T>(),
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
if TypeId::of::<T>() == TypeId::of::<Dynamic>() {
|
2021-05-25 04:54:48 +02:00
|
|
|
return self.as_mut_any().downcast_mut::<T>();
|
2020-04-13 17:31:05 +02:00
|
|
|
}
|
|
|
|
|
2021-06-13 11:41:34 +02:00
|
|
|
match self.0 {
|
|
|
|
Union::Variant(ref mut value, _, _) => (***value).as_mut_any().downcast_mut::<T>(),
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(_, _, _) => None,
|
2020-07-22 07:05:24 +02:00
|
|
|
_ => None,
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
|
|
|
}
|
2021-03-05 06:34:58 +01:00
|
|
|
/// Cast the [`Dynamic`] as a unit `()` and return it.
|
|
|
|
/// Returns the name of the actual type if the cast fails.
|
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-03-05 06:34:58 +01:00
|
|
|
pub fn as_unit(&self) -> Result<(), &'static str> {
|
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Unit(value, _, _) => Ok(value),
|
2021-03-05 06:34:58 +01:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(_, _, _) => self.read_lock().map(|v| *v).ok_or_else(|| self.type_name()),
|
2021-03-05 06:34:58 +01:00
|
|
|
_ => Err(self.type_name()),
|
|
|
|
}
|
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Cast the [`Dynamic`] as the system integer type [`INT`] and return it.
|
2020-04-12 17:00:06 +02:00
|
|
|
/// Returns the name of the actual type if the cast fails.
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-04-21 17:25:12 +02:00
|
|
|
pub fn as_int(&self) -> Result<INT, &'static str> {
|
2020-04-12 17:00:06 +02:00
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Int(n, _, _) => Ok(n),
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(_, _, _) => self.read_lock().map(|v| *v).ok_or_else(|| self.type_name()),
|
2020-04-12 17:00:06 +02:00
|
|
|
_ => Err(self.type_name()),
|
|
|
|
}
|
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Cast the [`Dynamic`] as the system floating-point type [`FLOAT`] and return it.
|
2020-05-22 15:49:53 +02:00
|
|
|
/// Returns the name of the actual type if the cast fails.
|
2021-02-13 13:57:56 +01:00
|
|
|
///
|
|
|
|
/// Not available under `no_float`.
|
2020-05-22 15:49:53 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-05-22 15:49:53 +02:00
|
|
|
pub fn as_float(&self) -> Result<FLOAT, &'static str> {
|
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Float(n, _, _) => Ok(*n),
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(_, _, _) => self.read_lock().map(|v| *v).ok_or_else(|| self.type_name()),
|
2020-05-22 15:49:53 +02:00
|
|
|
_ => Err(self.type_name()),
|
|
|
|
}
|
|
|
|
}
|
2021-02-21 07:26:31 +01:00
|
|
|
/// _(DECIMAL)_ Cast the [`Dynamic`] as a [`Decimal`] and return it.
|
2021-02-13 13:57:56 +01:00
|
|
|
/// Returns the name of the actual type if the cast fails.
|
|
|
|
///
|
2021-02-21 07:26:31 +01:00
|
|
|
/// Exported under the `decimal` feature only.
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-03-03 06:34:29 +01:00
|
|
|
pub fn as_decimal(&self) -> Result<Decimal, &'static str> {
|
2021-05-25 04:54:48 +02:00
|
|
|
match self.0 {
|
|
|
|
Union::Decimal(ref n, _, _) => Ok(**n),
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(_, _, _) => self.read_lock().map(|v| *v).ok_or_else(|| self.type_name()),
|
2021-02-13 13:57:56 +01:00
|
|
|
_ => Err(self.type_name()),
|
|
|
|
}
|
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Cast the [`Dynamic`] as a [`bool`] and return it.
|
2020-04-12 17:00:06 +02:00
|
|
|
/// Returns the name of the actual type if the cast fails.
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-04-21 17:25:12 +02:00
|
|
|
pub fn as_bool(&self) -> Result<bool, &'static str> {
|
2020-04-12 17:00:06 +02:00
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Bool(b, _, _) => Ok(b),
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(_, _, _) => self.read_lock().map(|v| *v).ok_or_else(|| self.type_name()),
|
2020-04-12 17:00:06 +02:00
|
|
|
_ => Err(self.type_name()),
|
|
|
|
}
|
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Cast the [`Dynamic`] as a [`char`] and return it.
|
2020-04-12 17:00:06 +02:00
|
|
|
/// Returns the name of the actual type if the cast fails.
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-04-21 17:25:12 +02:00
|
|
|
pub fn as_char(&self) -> Result<char, &'static str> {
|
2020-04-12 17:00:06 +02:00
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Char(n, _, _) => Ok(n),
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(_, _, _) => self.read_lock().map(|v| *v).ok_or_else(|| self.type_name()),
|
2020-04-12 17:00:06 +02:00
|
|
|
_ => Err(self.type_name()),
|
|
|
|
}
|
|
|
|
}
|
2021-03-05 16:00:27 +01:00
|
|
|
/// Cast the [`Dynamic`] as an [`ImmutableString`] and return it.
|
2020-04-12 17:00:06 +02:00
|
|
|
/// Returns the name of the actual type if the cast fails.
|
2020-07-31 00:34:20 +02:00
|
|
|
///
|
2021-03-05 16:00:27 +01:00
|
|
|
/// # Panics
|
|
|
|
///
|
|
|
|
/// Panics if the value is shared.
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-03-06 03:44:55 +01:00
|
|
|
pub(crate) fn as_str_ref(&self) -> Result<&str, &'static str> {
|
2021-05-25 04:54:48 +02:00
|
|
|
match self.0 {
|
|
|
|
Union::Str(ref s, _, _) => Ok(s),
|
2021-03-05 16:00:27 +01:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(_, _, _) => panic!("as_str() cannot be called on shared values"),
|
2020-04-12 17:00:06 +02:00
|
|
|
_ => Err(self.type_name()),
|
|
|
|
}
|
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Convert the [`Dynamic`] into a [`String`] and return it.
|
2020-09-20 08:23:14 +02:00
|
|
|
/// If there are other references to the same string, a cloned copy is returned.
|
2020-04-12 17:00:06 +02:00
|
|
|
/// Returns the name of the actual type if the cast fails.
|
2021-06-10 04:45:44 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-06-10 04:45:44 +02:00
|
|
|
pub fn as_string(self) -> Result<String, &'static str> {
|
|
|
|
self.as_immutable_string().map(ImmutableString::into_owned)
|
2020-06-21 10:37:05 +02:00
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Convert the [`Dynamic`] into an [`ImmutableString`] and return it.
|
2020-06-21 10:37:05 +02:00
|
|
|
/// Returns the name of the actual type if the cast fails.
|
2021-06-10 04:45:44 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-06-10 04:45:44 +02:00
|
|
|
pub fn as_immutable_string(self) -> Result<ImmutableString, &'static str> {
|
2020-04-12 17:00:06 +02:00
|
|
|
match self.0 {
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Str(s, _, _) => Ok(s),
|
2020-08-03 06:10:20 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2021-05-02 17:57:35 +02:00
|
|
|
Union::Shared(cell, _, _) => {
|
2020-07-31 00:34:20 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2021-03-05 07:18:36 +01:00
|
|
|
let value = cell.borrow();
|
2020-07-31 00:34:20 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2021-03-05 07:18:36 +01:00
|
|
|
let value = cell.read().unwrap();
|
2021-01-27 11:34:32 +01:00
|
|
|
|
2021-06-13 11:41:34 +02:00
|
|
|
match value.0 {
|
|
|
|
Union::Str(ref s, _, _) => Ok(s.clone()),
|
2021-03-05 07:18:36 +01:00
|
|
|
_ => Err((*value).type_name()),
|
2020-07-31 00:34:20 +02:00
|
|
|
}
|
|
|
|
}
|
2020-06-25 12:07:57 +02:00
|
|
|
_ => Err(self.type_name()),
|
|
|
|
}
|
|
|
|
}
|
2020-04-22 06:12:13 +02:00
|
|
|
}
|
2020-04-12 17:00:06 +02:00
|
|
|
|
2020-04-22 06:12:13 +02:00
|
|
|
impl From<()> for Dynamic {
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2020-04-22 06:12:13 +02:00
|
|
|
fn from(value: ()) -> Self {
|
2021-06-28 12:06:05 +02:00
|
|
|
Self(Union::Unit(value, DEFAULT_TAG_VALUE, ReadWrite))
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
2020-04-22 06:12:13 +02:00
|
|
|
}
|
|
|
|
impl From<bool> for Dynamic {
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2020-04-22 06:12:13 +02:00
|
|
|
fn from(value: bool) -> Self {
|
2021-06-28 12:06:05 +02:00
|
|
|
Self(Union::Bool(value, DEFAULT_TAG_VALUE, ReadWrite))
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
2020-04-22 06:12:13 +02:00
|
|
|
}
|
|
|
|
impl From<INT> for Dynamic {
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2020-04-22 06:12:13 +02:00
|
|
|
fn from(value: INT) -> Self {
|
2021-06-28 12:06:05 +02:00
|
|
|
Self(Union::Int(value, DEFAULT_TAG_VALUE, ReadWrite))
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
2020-04-22 06:12:13 +02:00
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
impl From<FLOAT> for Dynamic {
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2020-04-22 06:12:13 +02:00
|
|
|
fn from(value: FLOAT) -> Self {
|
2021-06-28 12:06:05 +02:00
|
|
|
Self(Union::Float(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
|
2021-01-04 04:58:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-04-06 17:18:41 +02:00
|
|
|
impl From<FloatWrapper<FLOAT>> for Dynamic {
|
2021-01-04 04:58:24 +01:00
|
|
|
#[inline(always)]
|
2021-04-06 17:18:41 +02:00
|
|
|
fn from(value: FloatWrapper<FLOAT>) -> Self {
|
2021-06-28 12:06:05 +02:00
|
|
|
Self(Union::Float(value, DEFAULT_TAG_VALUE, ReadWrite))
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
2020-04-22 06:12:13 +02:00
|
|
|
}
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
impl From<Decimal> for Dynamic {
|
|
|
|
#[inline(always)]
|
|
|
|
fn from(value: Decimal) -> Self {
|
2021-06-29 12:25:20 +02:00
|
|
|
Self(Union::Decimal(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
|
2021-02-13 13:57:56 +01:00
|
|
|
}
|
|
|
|
}
|
2020-04-22 06:12:13 +02:00
|
|
|
impl From<char> for Dynamic {
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2020-04-22 06:12:13 +02:00
|
|
|
fn from(value: char) -> Self {
|
2021-06-28 12:06:05 +02:00
|
|
|
Self(Union::Char(value, DEFAULT_TAG_VALUE, ReadWrite))
|
2020-04-12 17:00:06 +02:00
|
|
|
}
|
2020-04-22 06:12:13 +02:00
|
|
|
}
|
2020-06-23 13:24:26 +02:00
|
|
|
impl<S: Into<ImmutableString>> From<S> for Dynamic {
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2020-06-23 13:24:26 +02:00
|
|
|
fn from(value: S) -> Self {
|
2021-06-28 12:06:05 +02:00
|
|
|
Self(Union::Str(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
|
2020-05-25 07:44:28 +02:00
|
|
|
}
|
|
|
|
}
|
2021-03-29 05:36:02 +02:00
|
|
|
impl From<&ImmutableString> for Dynamic {
|
|
|
|
#[inline(always)]
|
|
|
|
fn from(value: &ImmutableString) -> Self {
|
|
|
|
value.clone().into()
|
|
|
|
}
|
|
|
|
}
|
2020-05-06 13:45:17 +02:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
2021-04-20 16:21:51 +02:00
|
|
|
impl Dynamic {
|
2021-05-10 05:07:19 +02:00
|
|
|
/// Create a [`Dynamic`] from an [`Array`].
|
2021-04-20 16:21:51 +02:00
|
|
|
#[inline(always)]
|
|
|
|
pub(crate) fn from_array(array: Array) -> Self {
|
2021-06-29 12:25:20 +02:00
|
|
|
Self(Union::Array(array.into(), DEFAULT_TAG_VALUE, ReadWrite))
|
2021-04-20 16:21:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_index"))]
|
2021-04-20 13:19:35 +02:00
|
|
|
impl<T: Variant + Clone> From<Vec<T>> for Dynamic {
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2021-04-20 13:19:35 +02:00
|
|
|
fn from(value: Vec<T>) -> Self {
|
2020-12-08 15:47:38 +01:00
|
|
|
Self(Union::Array(
|
|
|
|
Box::new(value.into_iter().map(Dynamic::from).collect()),
|
2021-06-28 12:06:05 +02:00
|
|
|
DEFAULT_TAG_VALUE,
|
2021-05-29 12:33:29 +02:00
|
|
|
ReadWrite,
|
2020-12-08 15:47:38 +01:00
|
|
|
))
|
2020-04-22 08:07:34 +02:00
|
|
|
}
|
|
|
|
}
|
2020-05-28 17:57:09 +02:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
|
|
|
impl<T: Variant + Clone> From<&[T]> for Dynamic {
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2020-05-28 17:57:09 +02:00
|
|
|
fn from(value: &[T]) -> Self {
|
2020-12-08 15:47:38 +01:00
|
|
|
Self(Union::Array(
|
|
|
|
Box::new(value.iter().cloned().map(Dynamic::from).collect()),
|
2021-06-28 12:06:05 +02:00
|
|
|
DEFAULT_TAG_VALUE,
|
2021-05-29 12:33:29 +02:00
|
|
|
ReadWrite,
|
2020-12-08 15:47:38 +01:00
|
|
|
))
|
2020-05-28 17:57:09 +02:00
|
|
|
}
|
|
|
|
}
|
2021-03-07 15:10:54 +01:00
|
|
|
#[cfg(not(feature = "no_index"))]
|
2021-04-17 09:15:54 +02:00
|
|
|
impl<T: Variant + Clone> std::iter::FromIterator<T> for Dynamic {
|
2021-03-07 15:10:54 +01:00
|
|
|
#[inline(always)]
|
|
|
|
fn from_iter<X: IntoIterator<Item = T>>(iter: X) -> Self {
|
|
|
|
Self(Union::Array(
|
|
|
|
Box::new(iter.into_iter().map(Dynamic::from).collect()),
|
2021-06-28 12:06:05 +02:00
|
|
|
DEFAULT_TAG_VALUE,
|
2021-05-29 12:33:29 +02:00
|
|
|
ReadWrite,
|
2021-03-07 15:10:54 +01:00
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
2020-05-06 13:45:17 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-04-20 16:21:51 +02:00
|
|
|
impl Dynamic {
|
2021-05-10 05:07:19 +02:00
|
|
|
/// Create a [`Dynamic`] from a [`Map`].
|
2021-04-20 16:21:51 +02:00
|
|
|
#[inline(always)]
|
|
|
|
pub(crate) fn from_map(map: Map) -> Self {
|
2021-06-29 12:25:20 +02:00
|
|
|
Self(Union::Map(map.into(), DEFAULT_TAG_VALUE, ReadWrite))
|
2021-04-20 16:21:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-03-23 05:13:53 +01:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
2021-04-17 09:15:54 +02:00
|
|
|
impl<K: Into<crate::Identifier>, T: Variant + Clone> From<std::collections::HashMap<K, T>>
|
2020-11-16 09:28:04 +01:00
|
|
|
for Dynamic
|
|
|
|
{
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2021-04-17 09:15:54 +02:00
|
|
|
fn from(value: std::collections::HashMap<K, T>) -> Self {
|
2020-12-08 15:47:38 +01:00
|
|
|
Self(Union::Map(
|
|
|
|
Box::new(
|
|
|
|
value
|
|
|
|
.into_iter()
|
|
|
|
.map(|(k, v)| (k.into(), Dynamic::from(v)))
|
|
|
|
.collect(),
|
|
|
|
),
|
2021-06-28 12:06:05 +02:00
|
|
|
DEFAULT_TAG_VALUE,
|
2021-05-29 12:33:29 +02:00
|
|
|
ReadWrite,
|
2020-12-08 15:47:38 +01:00
|
|
|
))
|
2020-04-22 08:07:34 +02:00
|
|
|
}
|
|
|
|
}
|
2021-03-23 05:13:53 +01:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-06-30 05:08:29 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
|
|
|
impl<K: Into<crate::Identifier>> From<std::collections::HashSet<K>> for Dynamic {
|
|
|
|
#[inline(always)]
|
|
|
|
fn from(value: std::collections::HashSet<K>) -> Self {
|
|
|
|
Self(Union::Map(
|
|
|
|
Box::new(
|
|
|
|
value
|
|
|
|
.into_iter()
|
|
|
|
.map(|k| (k.into(), Dynamic::UNIT))
|
|
|
|
.collect(),
|
|
|
|
),
|
|
|
|
DEFAULT_TAG_VALUE,
|
|
|
|
ReadWrite,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
2021-04-17 09:15:54 +02:00
|
|
|
impl<K: Into<crate::Identifier>, T: Variant + Clone> From<std::collections::BTreeMap<K, T>>
|
|
|
|
for Dynamic
|
2021-03-23 05:13:53 +01:00
|
|
|
{
|
|
|
|
#[inline(always)]
|
2021-04-17 09:15:54 +02:00
|
|
|
fn from(value: std::collections::BTreeMap<K, T>) -> Self {
|
2021-03-23 05:13:53 +01:00
|
|
|
Self(Union::Map(
|
|
|
|
Box::new(
|
|
|
|
value
|
|
|
|
.into_iter()
|
|
|
|
.map(|(k, v)| (k.into(), Dynamic::from(v)))
|
|
|
|
.collect(),
|
|
|
|
),
|
2021-06-28 12:06:05 +02:00
|
|
|
DEFAULT_TAG_VALUE,
|
2021-05-29 12:33:29 +02:00
|
|
|
ReadWrite,
|
2021-03-23 05:13:53 +01:00
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
2021-06-30 05:08:29 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
impl<K: Into<crate::Identifier>> From<std::collections::BTreeSet<K>> for Dynamic {
|
|
|
|
#[inline(always)]
|
|
|
|
fn from(value: std::collections::BTreeSet<K>) -> Self {
|
|
|
|
Self(Union::Map(
|
|
|
|
Box::new(
|
|
|
|
value
|
|
|
|
.into_iter()
|
|
|
|
.map(|k| (k.into(), Dynamic::UNIT))
|
|
|
|
.collect(),
|
|
|
|
),
|
|
|
|
DEFAULT_TAG_VALUE,
|
|
|
|
ReadWrite,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
2020-06-25 12:07:57 +02:00
|
|
|
impl From<FnPtr> for Dynamic {
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2020-06-25 12:07:57 +02:00
|
|
|
fn from(value: FnPtr) -> Self {
|
2021-06-29 12:25:20 +02:00
|
|
|
Self(Union::FnPtr(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
|
2020-07-22 17:12:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
impl From<Box<FnPtr>> for Dynamic {
|
2020-08-08 05:46:30 +02:00
|
|
|
#[inline(always)]
|
2020-07-22 17:12:09 +02:00
|
|
|
fn from(value: Box<FnPtr>) -> Self {
|
2021-06-28 12:06:05 +02:00
|
|
|
Self(Union::FnPtr(value, DEFAULT_TAG_VALUE, ReadWrite))
|
2020-06-25 12:07:57 +02:00
|
|
|
}
|
|
|
|
}
|
2020-09-27 12:47:20 +02:00
|
|
|
#[cfg(not(feature = "no_std"))]
|
2020-09-26 13:41:04 +02:00
|
|
|
impl From<Instant> for Dynamic {
|
|
|
|
#[inline(always)]
|
|
|
|
fn from(value: Instant) -> Self {
|
2021-06-29 12:25:20 +02:00
|
|
|
Self(Union::TimeStamp(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
|
2020-09-26 13:41:04 +02:00
|
|
|
}
|
|
|
|
}
|
2021-05-11 15:38:07 +02:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
|
|
|
impl From<crate::Shared<crate::Locked<Dynamic>>> for Dynamic {
|
|
|
|
#[inline(always)]
|
|
|
|
fn from(value: crate::Shared<crate::Locked<Self>>) -> Self {
|
2021-06-28 12:06:05 +02:00
|
|
|
Self(Union::Shared(value.into(), DEFAULT_TAG_VALUE, ReadWrite))
|
2021-05-11 15:38:07 +02:00
|
|
|
}
|
|
|
|
}
|