Avoid hard-coding variable type for shared.
This commit is contained in:
parent
af2f8acb5d
commit
cc53b21731
111
src/any.rs
111
src/any.rs
@ -160,18 +160,7 @@ pub enum Union {
|
|||||||
FnPtr(Box<FnPtr>),
|
FnPtr(Box<FnPtr>),
|
||||||
Variant(Box<Box<dyn Variant>>),
|
Variant(Box<Box<dyn Variant>>),
|
||||||
#[cfg(not(feature = "no_shared"))]
|
#[cfg(not(feature = "no_shared"))]
|
||||||
Shared(Box<SharedCell>),
|
Shared(SharedMut<Dynamic>),
|
||||||
}
|
|
||||||
|
|
||||||
/// Internal Shared Dynamic representation.
|
|
||||||
///
|
|
||||||
/// Created with `Dynamic::into_shared()`.
|
|
||||||
#[cfg(not(feature = "no_shared"))]
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct SharedCell {
|
|
||||||
value_type_id: TypeId,
|
|
||||||
value_type_name: &'static str,
|
|
||||||
container: SharedMut<Dynamic>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Underlying `Variant` read guard for `Dynamic`.
|
/// Underlying `Variant` read guard for `Dynamic`.
|
||||||
@ -202,7 +191,7 @@ impl<'d, T: Variant + Clone> Deref for DynamicReadLock<'d, T> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
match &self.0 {
|
match &self.0 {
|
||||||
DynamicReadLockInner::Reference(reference) => reference.deref(),
|
DynamicReadLockInner::Reference(reference) => *reference,
|
||||||
// Unwrapping is safe because all checking is already done in its constructor
|
// Unwrapping is safe because all checking is already done in its constructor
|
||||||
#[cfg(not(feature = "no_shared"))]
|
#[cfg(not(feature = "no_shared"))]
|
||||||
DynamicReadLockInner::Guard(guard) => guard.downcast_ref().unwrap(),
|
DynamicReadLockInner::Guard(guard) => guard.downcast_ref().unwrap(),
|
||||||
@ -238,7 +227,7 @@ impl<'d, T: Variant + Clone> Deref for DynamicWriteLock<'d, T> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
match &self.0 {
|
match &self.0 {
|
||||||
DynamicWriteLockInner::Reference(reference) => reference.deref(),
|
DynamicWriteLockInner::Reference(reference) => *reference,
|
||||||
// Unwrapping is safe because all checking is already done in its constructor
|
// Unwrapping is safe because all checking is already done in its constructor
|
||||||
#[cfg(not(feature = "no_shared"))]
|
#[cfg(not(feature = "no_shared"))]
|
||||||
DynamicWriteLockInner::Guard(guard) => guard.downcast_ref().unwrap(),
|
DynamicWriteLockInner::Guard(guard) => guard.downcast_ref().unwrap(),
|
||||||
@ -250,7 +239,7 @@ impl<'d, T: Variant + Clone> DerefMut for DynamicWriteLock<'d, T> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
match &mut self.0 {
|
match &mut self.0 {
|
||||||
DynamicWriteLockInner::Reference(reference) => reference.deref_mut(),
|
DynamicWriteLockInner::Reference(reference) => *reference,
|
||||||
// Unwrapping is safe because all checking is already done in its constructor
|
// Unwrapping is safe because all checking is already done in its constructor
|
||||||
#[cfg(not(feature = "no_shared"))]
|
#[cfg(not(feature = "no_shared"))]
|
||||||
DynamicWriteLockInner::Guard(guard) => guard.downcast_mut().unwrap(),
|
DynamicWriteLockInner::Guard(guard) => guard.downcast_mut().unwrap(),
|
||||||
@ -309,7 +298,11 @@ impl Dynamic {
|
|||||||
Union::FnPtr(_) => TypeId::of::<FnPtr>(),
|
Union::FnPtr(_) => TypeId::of::<FnPtr>(),
|
||||||
Union::Variant(value) => (***value).type_id(),
|
Union::Variant(value) => (***value).type_id(),
|
||||||
#[cfg(not(feature = "no_shared"))]
|
#[cfg(not(feature = "no_shared"))]
|
||||||
Union::Shared(cell) => (**cell).value_type_id,
|
#[cfg(not(feature = "sync"))]
|
||||||
|
Union::Shared(cell) => (*cell.borrow()).type_id(),
|
||||||
|
#[cfg(not(feature = "no_shared"))]
|
||||||
|
#[cfg(feature = "sync")]
|
||||||
|
Union::Shared(cell) => (*cell.read().unwrap()).type_id(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,7 +326,11 @@ impl Dynamic {
|
|||||||
Union::Variant(value) if value.is::<Instant>() => "timestamp",
|
Union::Variant(value) if value.is::<Instant>() => "timestamp",
|
||||||
Union::Variant(value) => (***value).type_name(),
|
Union::Variant(value) => (***value).type_name(),
|
||||||
#[cfg(not(feature = "no_shared"))]
|
#[cfg(not(feature = "no_shared"))]
|
||||||
Union::Shared(cell) => (**cell).value_type_name,
|
#[cfg(not(feature = "sync"))]
|
||||||
|
Union::Shared(cell) => (*cell.borrow()).type_name(),
|
||||||
|
#[cfg(not(feature = "no_shared"))]
|
||||||
|
#[cfg(feature = "sync")]
|
||||||
|
Union::Shared(cell) => (*cell.read().unwrap()).type_name(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -390,7 +387,7 @@ impl fmt::Display for Dynamic {
|
|||||||
Union::Variant(value) if value.is::<Instant>() => write!(f, "<timestamp>"),
|
Union::Variant(value) if value.is::<Instant>() => write!(f, "<timestamp>"),
|
||||||
Union::Variant(value) => write!(f, "{}", (*value).type_name()),
|
Union::Variant(value) => write!(f, "{}", (*value).type_name()),
|
||||||
#[cfg(not(feature = "no_shared"))]
|
#[cfg(not(feature = "no_shared"))]
|
||||||
Union::Shared(cell) => write!(f, "<shared {}>", (**cell).value_type_name),
|
Union::Shared(_) => f.write_str("<shared>"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -418,7 +415,7 @@ impl fmt::Debug for Dynamic {
|
|||||||
Union::Variant(value) if value.is::<Instant>() => write!(f, "<timestamp>"),
|
Union::Variant(value) if value.is::<Instant>() => write!(f, "<timestamp>"),
|
||||||
Union::Variant(value) => write!(f, "{}", (*value).type_name()),
|
Union::Variant(value) => write!(f, "{}", (*value).type_name()),
|
||||||
#[cfg(not(feature = "no_shared"))]
|
#[cfg(not(feature = "no_shared"))]
|
||||||
Union::Shared(cell) => write!(f, "<shared {}>", (**cell).value_type_name),
|
Union::Shared(_) => f.write_str("<shared>"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -569,15 +566,10 @@ impl Dynamic {
|
|||||||
#[cfg(not(feature = "no_shared"))]
|
#[cfg(not(feature = "no_shared"))]
|
||||||
return match self.0 {
|
return match self.0 {
|
||||||
Union::Shared(..) => self,
|
Union::Shared(..) => self,
|
||||||
_ => Self(Union::Shared(Box::new(SharedCell {
|
|
||||||
value_type_id: self.type_id(),
|
|
||||||
value_type_name: self.type_name(),
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
container: Rc::new(RefCell::new(self)),
|
_ => Self(Union::Shared(Rc::new(RefCell::new(self)))),
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
container: Arc::new(RwLock::new(self)),
|
_ => Self(Union::Shared(Arc::new(RwLock::new(self)))),
|
||||||
}))),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "no_shared")]
|
#[cfg(feature = "no_shared")]
|
||||||
@ -614,13 +606,11 @@ impl Dynamic {
|
|||||||
match self.0 {
|
match self.0 {
|
||||||
#[cfg(not(feature = "no_shared"))]
|
#[cfg(not(feature = "no_shared"))]
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
Union::Shared(cell) => return cell.container.borrow().deref().clone().try_cast(),
|
Union::Shared(cell) => return cell.borrow().clone().try_cast(),
|
||||||
|
|
||||||
#[cfg(not(feature = "no_shared"))]
|
#[cfg(not(feature = "no_shared"))]
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
Union::Shared(cell) => {
|
Union::Shared(cell) => return cell.read().unwrap().clone().try_cast(),
|
||||||
return cell.container.read().unwrap().deref().clone().try_cast()
|
|
||||||
}
|
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -752,32 +742,11 @@ impl Dynamic {
|
|||||||
match self.0 {
|
match self.0 {
|
||||||
#[cfg(not(feature = "no_shared"))]
|
#[cfg(not(feature = "no_shared"))]
|
||||||
Union::Shared(ref cell) => {
|
Union::Shared(ref cell) => {
|
||||||
let type_id = TypeId::of::<T>();
|
|
||||||
|
|
||||||
if type_id != TypeId::of::<Dynamic>() && type_id != cell.value_type_id {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
return Some(
|
return Some(cell.borrow().downcast_ref::<T>().unwrap().clone());
|
||||||
cell.container
|
|
||||||
.borrow()
|
|
||||||
.deref()
|
|
||||||
.downcast_ref::<T>()
|
|
||||||
.unwrap()
|
|
||||||
.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
return Some(
|
return Some(cell.read().unwrap().downcast_ref::<T>().unwrap().clone());
|
||||||
cell.container
|
|
||||||
.read()
|
|
||||||
.unwrap()
|
|
||||||
.deref()
|
|
||||||
.downcast_ref::<T>()
|
|
||||||
.unwrap()
|
|
||||||
.clone(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
_ => self.downcast_ref().cloned(),
|
_ => self.downcast_ref().cloned(),
|
||||||
}
|
}
|
||||||
@ -792,20 +761,12 @@ impl Dynamic {
|
|||||||
match self.0 {
|
match self.0 {
|
||||||
#[cfg(not(feature = "no_shared"))]
|
#[cfg(not(feature = "no_shared"))]
|
||||||
Union::Shared(ref cell) => {
|
Union::Shared(ref cell) => {
|
||||||
let type_id = TypeId::of::<T>();
|
|
||||||
|
|
||||||
if type_id != TypeId::of::<Dynamic>() && type_id != cell.value_type_id {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
return Some(DynamicReadLock(DynamicReadLockInner::Guard(
|
return Some(DynamicReadLock(DynamicReadLockInner::Guard(cell.borrow())));
|
||||||
cell.container.borrow(),
|
|
||||||
)));
|
|
||||||
|
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
return Some(DynamicReadLock(DynamicReadLockInner::Guard(
|
return Some(DynamicReadLock(DynamicReadLockInner::Guard(
|
||||||
cell.container.read().unwrap(),
|
cell.read().unwrap(),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
_ => self
|
_ => self
|
||||||
@ -823,20 +784,14 @@ impl Dynamic {
|
|||||||
match self.0 {
|
match self.0 {
|
||||||
#[cfg(not(feature = "no_shared"))]
|
#[cfg(not(feature = "no_shared"))]
|
||||||
Union::Shared(ref cell) => {
|
Union::Shared(ref cell) => {
|
||||||
let type_id = TypeId::of::<T>();
|
|
||||||
|
|
||||||
if type_id != TypeId::of::<Dynamic>() && cell.value_type_id != type_id {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
return Some(DynamicWriteLock(DynamicWriteLockInner::Guard(
|
return Some(DynamicWriteLock(DynamicWriteLockInner::Guard(
|
||||||
cell.container.borrow_mut(),
|
cell.borrow_mut(),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
return Some(DynamicWriteLock(DynamicWriteLockInner::Guard(
|
return Some(DynamicWriteLock(DynamicWriteLockInner::Guard(
|
||||||
cell.container.write().unwrap(),
|
cell.write().unwrap(),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
_ => self
|
_ => self
|
||||||
@ -1086,16 +1041,22 @@ impl Dynamic {
|
|||||||
#[cfg(not(feature = "no_shared"))]
|
#[cfg(not(feature = "no_shared"))]
|
||||||
Union::Shared(cell) => {
|
Union::Shared(cell) => {
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
match &cell.container.borrow().deref().0 {
|
{
|
||||||
|
let inner = cell.borrow();
|
||||||
|
match &inner.0 {
|
||||||
Union::Str(s) => Ok(s.clone()),
|
Union::Str(s) => Ok(s.clone()),
|
||||||
Union::FnPtr(f) => Ok(f.clone().take_data().0),
|
Union::FnPtr(f) => Ok(f.clone().take_data().0),
|
||||||
_ => Err(cell.value_type_name),
|
_ => Err((*inner).type_name()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
match &cell.container.read().unwrap().deref().0 {
|
{
|
||||||
|
let inner = cell.read().unwrap();
|
||||||
|
match &inner.0 {
|
||||||
Union::Str(s) => Ok(s.clone()),
|
Union::Str(s) => Ok(s.clone()),
|
||||||
Union::FnPtr(f) => Ok(f.clone().take_data().0),
|
Union::FnPtr(f) => Ok(f.clone().take_data().0),
|
||||||
_ => Err(cell.value_type_name),
|
_ => Err((*inner).type_name()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(self.type_name()),
|
_ => Err(self.type_name()),
|
||||||
|
@ -1185,8 +1185,8 @@ pub fn run_builtin_op_assignment(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if args_type == TypeId::of::<INT>() {
|
if args_type == TypeId::of::<INT>() {
|
||||||
let mut x = x.write_lock::<INT>().unwrap();
|
|
||||||
let y = y.clone().cast::<INT>();
|
let y = y.clone().cast::<INT>();
|
||||||
|
let mut x = x.write_lock::<INT>().unwrap();
|
||||||
|
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
match op {
|
match op {
|
||||||
@ -1221,8 +1221,8 @@ pub fn run_builtin_op_assignment(
|
|||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
} else if args_type == TypeId::of::<bool>() {
|
} else if args_type == TypeId::of::<bool>() {
|
||||||
let mut x = x.write_lock::<bool>().unwrap();
|
|
||||||
let y = y.clone().cast::<bool>();
|
let y = y.clone().cast::<bool>();
|
||||||
|
let mut x = x.write_lock::<bool>().unwrap();
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
"&=" => return Ok(Some(*x = *x && y)),
|
"&=" => return Ok(Some(*x = *x && y)),
|
||||||
@ -1230,19 +1230,19 @@ pub fn run_builtin_op_assignment(
|
|||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
} else if args_type == TypeId::of::<ImmutableString>() {
|
} else if args_type == TypeId::of::<ImmutableString>() {
|
||||||
|
let y = y.read_lock::<ImmutableString>().unwrap().deref().clone();
|
||||||
let mut x = x.write_lock::<ImmutableString>().unwrap();
|
let mut x = x.write_lock::<ImmutableString>().unwrap();
|
||||||
let y = y.read_lock::<ImmutableString>().unwrap();
|
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
"+=" => return Ok(Some(*x += y.deref())),
|
"+=" => return Ok(Some(*x += y)),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
if args_type == TypeId::of::<FLOAT>() {
|
if args_type == TypeId::of::<FLOAT>() {
|
||||||
let mut x = x.write_lock::<FLOAT>().unwrap();
|
|
||||||
let y = y.clone().cast::<FLOAT>();
|
let y = y.clone().cast::<FLOAT>();
|
||||||
|
let mut x = x.write_lock::<FLOAT>().unwrap();
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
"+=" => return Ok(Some(*x += y)),
|
"+=" => return Ok(Some(*x += y)),
|
||||||
|
12
src/utils.rs
12
src/utils.rs
@ -264,6 +264,18 @@ impl AddAssign<&ImmutableString> for ImmutableString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AddAssign<ImmutableString> for ImmutableString {
|
||||||
|
fn add_assign(&mut self, rhs: ImmutableString) {
|
||||||
|
if !rhs.is_empty() {
|
||||||
|
if self.is_empty() {
|
||||||
|
self.0 = rhs.0;
|
||||||
|
} else {
|
||||||
|
self.make_mut().push_str(rhs.0.as_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Add<&str> for ImmutableString {
|
impl Add<&str> for ImmutableString {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
|
@ -11,11 +11,23 @@ fn test_shared() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
assert_eq!(engine.eval::<bool>("shared(true)")?, true);
|
assert_eq!(engine.eval::<bool>("shared(true)")?, true);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<String>("let x = shared(true); type_of(x)")?,
|
||||||
|
"bool"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<String>("let x = shared(true); x = (); type_of(x)")?,
|
||||||
|
"()"
|
||||||
|
);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
assert_eq!(engine.eval::<f64>("shared(4.2)")?, 4.2);
|
assert_eq!(engine.eval::<f64>("shared(4.2)")?, 4.2);
|
||||||
|
|
||||||
assert_eq!(engine.eval::<String>(r#"shared("test")"#)?, "test");
|
assert_eq!(engine.eval::<String>(r#"shared("test")"#)?, "test");
|
||||||
|
|
||||||
|
assert_eq!(engine.eval::<String>(r#"shared("test")"#)?, "test");
|
||||||
|
|
||||||
assert_eq!(engine.eval::<char>("shared('x')")?, 'x');
|
assert_eq!(engine.eval::<char>("shared('x')")?, 'x');
|
||||||
|
|
||||||
assert!(engine.eval::<bool>("is_shared(shared(42))")?);
|
assert!(engine.eval::<bool>("is_shared(shared(42))")?);
|
||||||
|
Loading…
Reference in New Issue
Block a user