1use bytemuck::{AnyBitPattern, NoUninit, cast_slice, cast_slice_mut};
2use half::f16;
3use indexmap::IndexMap;
4use smol_str::SmolStr;
5use std::any::Any;
6use std::collections::BTreeMap;
7use std::mem;
8use tinyvec::TinyVec;
9const TINY_SIZE: usize = 28;
10pub mod json;
11
12#[inline]
15pub fn f16_to_f64(bits: u16) -> f64 {
16 f16::from_bits(bits).to_f64()
17}
18
19#[inline]
21pub fn f64_to_f16(value: f64) -> u16 {
22 f16::from_f64(value).to_bits()
23}
24#[derive(Debug, Default, Clone, PartialEq)]
25pub struct MyVec<T> {
26 pub(crate) data: TinyVec<[u8; TINY_SIZE]>,
27 phantom: std::marker::PhantomData<T>,
28}
29
30impl<T> MyVec<T> {
31 pub fn len(&self) -> usize {
32 let size = mem::size_of::<T>().max(1);
34 self.data.len() / size
35 }
36
37 pub fn is_empty(&self) -> bool {
38 self.data.is_empty()
39 }
40
41 pub fn as_slice(&self) -> &[u8] {
42 self.data.as_slice()
43 }
44}
45
46impl<T: NoUninit + AnyBitPattern> MyVec<T> {
47 pub fn push(&mut self, value: T) {
48 let binding = [value];
49 let bytes = cast_slice(&binding);
50 self.data.extend_from_slice(bytes);
51 }
52
53 pub fn pop(&mut self) -> Option<T>
54 where
55 T: AnyBitPattern,
56 {
57 if self.data.len() < mem::size_of::<T>() {
58 return None;
59 }
60 let start = self.data.len() - mem::size_of::<T>();
61 let slice = &self.data[start..];
62 let value = cast_slice::<u8, T>(slice)[0];
63 self.data.truncate(start);
64 Some(value)
65 }
66
67 pub fn get(&self, idx: usize) -> Option<T> {
68 if idx >= self.len() {
69 return None;
70 }
71 let start = idx * mem::size_of::<T>();
72 let slice = &self.data[start..start + mem::size_of::<T>()];
73 Some(cast_slice::<u8, T>(slice)[0])
74 }
75
76 pub fn set(&mut self, idx: usize, value: T) {
77 if idx < self.len() {
78 let start = idx * mem::size_of::<T>();
79 let slice = &mut self.data[start..start + mem::size_of::<T>()];
80 cast_slice_mut::<u8, T>(slice)[0] = value;
81 }
82 }
83
84 pub fn iter(&self) -> Iter<'_, T> {
85 Iter { data: self.data.as_slice(), index: 0, phantom: std::marker::PhantomData }
86 }
87 pub fn extend_from_slice(&mut self, slice: &[T]) {
88 self.data.extend_from_slice(cast_slice(slice));
89 }
90}
91
92impl<T: NoUninit> From<&[T]> for MyVec<T> {
93 fn from(vec: &[T]) -> Self {
94 let mut data: TinyVec<[u8; TINY_SIZE]> = TinyVec::new();
95 data.extend_from_slice(cast_slice(vec));
96 Self { data, phantom: std::marker::PhantomData }
97 }
98}
99
100impl<T: NoUninit, const N: usize> From<[T; N]> for MyVec<T> {
101 fn from(arr: [T; N]) -> Self {
102 Self::from(&arr[..])
103 }
104}
105
106impl<T: AnyBitPattern> From<MyVec<T>> for Vec<T> {
107 fn from(my_vec: MyVec<T>) -> Self {
108 cast_slice(my_vec.data.as_slice()).to_vec()
109 }
110}
111
112pub struct Iter<'a, T> {
113 data: &'a [u8],
114 index: usize,
115 phantom: std::marker::PhantomData<T>,
116}
117
118impl<'a, T: AnyBitPattern> Iterator for Iter<'a, T> {
119 type Item = &'a T;
120 fn next(&mut self) -> Option<Self::Item> {
121 let size = std::mem::size_of::<T>();
122 let start = self.index * size;
123
124 if start + size > self.data.len() {
125 return None;
126 }
127
128 let slice = &self.data[start..start + size];
129 let value = &cast_slice::<u8, T>(slice)[0];
130 self.index += 1;
131 Some(value)
132 }
133
134 fn size_hint(&self) -> (usize, Option<usize>) {
135 let size = std::mem::size_of::<T>().max(1);
136 let remaining = self.data.len() / size - self.index;
137 (remaining, Some(remaining))
138 }
139}
140
141impl<'a, T: AnyBitPattern> ExactSizeIterator for Iter<'a, T> {
142 fn len(&self) -> usize {
143 self.data.len() / std::mem::size_of::<T>() - self.index
144 }
145}
146
147#[derive(Debug, thiserror::Error)]
148pub enum DynamicErr {
149 #[error("type mismatch")]
150 TypeMismatch,
151 #[error("range error: {0}")]
152 Range(i64),
153 #[error("没有成员: {0}")]
154 NoField(SmolStr),
155 #[error("out of range")]
156 OutOfRange,
157}
158
159pub use parking_lot::RwLock;
160use std::sync::Arc;
161
162pub trait CustomProperty: Any + Send + Sync {
163 fn get_key(&self, key: &str) -> Option<Dynamic>;
164
165 fn set_key(&self, key: &str, value: Dynamic) -> bool;
166
167 fn contains_key(&self, key: &str) -> bool {
168 self.get_key(key).is_some()
169 }
170}
171
172#[derive(Clone)]
173pub struct CustomValue {
174 type_name: &'static str,
175 value: Arc<dyn Any + Send + Sync>,
176 get_key: Option<fn(&(dyn Any + Send + Sync), &str) -> Option<Dynamic>>,
177 set_key: Option<fn(&(dyn Any + Send + Sync), &str, Dynamic) -> bool>,
178 contains_key: Option<fn(&(dyn Any + Send + Sync), &str) -> bool>,
179}
180
181impl CustomValue {
182 pub fn new<T>(value: T) -> Self
183 where
184 T: Any + Send + Sync + 'static,
185 {
186 Self { type_name: std::any::type_name::<T>(), value: Arc::new(value), get_key: None, set_key: None, contains_key: None }
187 }
188
189 pub fn from_arc<T>(value: Arc<T>) -> Self
190 where
191 T: Any + Send + Sync + 'static,
192 {
193 Self { type_name: std::any::type_name::<T>(), value, get_key: None, set_key: None, contains_key: None }
194 }
195
196 pub fn new_with_properties<T>(value: T) -> Self
197 where
198 T: CustomProperty + 'static,
199 {
200 Self::from_property_arc(Arc::new(value))
201 }
202
203 pub fn from_property_arc<T>(value: Arc<T>) -> Self
204 where
205 T: CustomProperty + 'static,
206 {
207 fn get_key<T: CustomProperty + 'static>(value: &(dyn Any + Send + Sync), key: &str) -> Option<Dynamic> {
208 value.downcast_ref::<T>()?.get_key(key)
209 }
210
211 fn set_key<T: CustomProperty + 'static>(value: &(dyn Any + Send + Sync), key: &str, next: Dynamic) -> bool {
212 value.downcast_ref::<T>().is_some_and(|value| value.set_key(key, next))
213 }
214
215 fn contains_key<T: CustomProperty + 'static>(value: &(dyn Any + Send + Sync), key: &str) -> bool {
216 value.downcast_ref::<T>().is_some_and(|value| value.contains_key(key))
217 }
218
219 Self { type_name: std::any::type_name::<T>(), value, get_key: Some(get_key::<T>), set_key: Some(set_key::<T>), contains_key: Some(contains_key::<T>) }
220 }
221
222 pub fn as_any(&self) -> &(dyn Any + Send + Sync) {
223 self.value.as_ref()
224 }
225
226 pub fn custom_type_name(&self) -> &'static str {
227 self.type_name
228 }
229
230 fn ptr_eq(&self, other: &Self) -> bool {
231 Arc::ptr_eq(&self.value, &other.value)
232 }
233
234 fn get_key(&self, key: &str) -> Option<Dynamic> {
235 self.get_key.and_then(|get_key| get_key(self.as_any(), key))
236 }
237
238 fn set_key(&self, key: &str, value: Dynamic) -> bool {
239 self.set_key.is_some_and(|set_key| set_key(self.as_any(), key, value))
240 }
241
242 fn contains_key(&self, key: &str) -> bool {
243 self.contains_key.is_some_and(|contains_key| contains_key(self.as_any(), key))
244 }
245}
246
247impl std::fmt::Debug for CustomValue {
248 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
249 f.debug_struct("CustomValue").field("type_name", &self.type_name).finish()
250 }
251}
252
253#[derive(Debug)]
254pub struct StructBytes {
255 bytes: RwLock<Vec<u8>>,
256 dynamic_fields: RwLock<BTreeMap<usize, Box<Dynamic>>>,
257}
258
259impl StructBytes {
260 fn new(size: usize) -> Arc<Self> {
261 Arc::new(Self { bytes: RwLock::new(vec![0; size]), dynamic_fields: RwLock::new(BTreeMap::new()) })
262 }
263
264 fn addr(&self) -> usize {
265 self.bytes.read().as_ptr() as usize
266 }
267
268 fn copy_from_ptr(addr: usize, ty: &Type) -> Arc<Self> {
269 let size = ty.storage_width() as usize;
270 let storage = Self::new(size);
271 if addr != 0 && size > 0 {
272 unsafe {
273 std::ptr::copy_nonoverlapping(addr as *const u8, storage.addr() as *mut u8, size);
274 }
275 storage.clone_dynamic_fields_from(addr, ty, 0);
276 }
277 storage
278 }
279
280 fn clone_dynamic_fields_from(&self, src_addr: usize, ty: &Type, dst_offset: usize) {
281 match ty {
282 Type::Bool | Type::I8 | Type::U8 | Type::I16 | Type::U16 | Type::I32 | Type::U32 | Type::I64 | Type::U64 | Type::F16 | Type::F32 | Type::F64 | Type::Void => {}
283 Type::Struct { fields, .. } => {
284 let (_, offsets) = Type::struct_layout(fields);
285 for ((_, field_ty), offset) in fields.iter().zip(offsets) {
286 self.clone_dynamic_fields_from(src_addr + offset as usize, field_ty, dst_offset + offset as usize);
287 }
288 }
289 Type::Array(elem_ty, len) | Type::Vec(elem_ty, len) => {
290 let width = elem_ty.storage_width() as usize;
291 for idx in 0..*len as usize {
292 self.clone_dynamic_fields_from(src_addr + idx * width, elem_ty, dst_offset + idx * width);
293 }
294 }
295 _ => {
296 let ptr = unsafe { std::ptr::read_unaligned(src_addr as *const usize) };
297 if ptr != 0 {
298 let value = unsafe { (&*(ptr as *const Dynamic)).deep_clone() };
299 self.write_dynamic_ptr_at(dst_offset, value);
300 }
301 }
302 }
303 }
304
305 fn clear_dynamic_fields_in(&self, start: usize, width: usize) {
306 let end = start.saturating_add(width);
307 self.dynamic_fields.write().retain(|offset, _| *offset < start || *offset >= end);
308 }
309
310 fn read_dynamic_ptr_at(&self, offset: usize) -> Option<Dynamic> {
311 if let Some(value) = self.dynamic_fields.read().get(&offset) {
312 return Some(value.as_ref().clone());
313 }
314 let ptr = unsafe { std::ptr::read_unaligned((self.addr() + offset) as *const usize) };
315 if ptr == 0 { None } else { Some(unsafe { (&*(ptr as *const Dynamic)).clone() }) }
316 }
317
318 fn write_dynamic_ptr_at(&self, offset: usize, value: Dynamic) {
319 let mut boxed = Box::new(value);
320 let ptr = boxed.as_mut() as *mut Dynamic as usize;
321 self.dynamic_fields.write().insert(offset, boxed);
322 unsafe {
323 std::ptr::write_unaligned((self.addr() + offset) as *mut usize, ptr);
324 }
325 }
326}
327
328#[derive(Debug, Default, Clone)]
329pub enum Dynamic {
330 #[default]
331 Null,
332 Bool(bool),
333 U8(u8),
334 I8(i8),
335 U16(u16),
336 I16(i16),
337 U32(u32),
338 I32(i32), U64(u64),
340 I64(i64),
341 F16(u16), F32(f32), F64(f64),
344 String(SmolStr),
345 StringBuf(String),
346 Bytes(Vec<u8>),
347 VecI8(MyVec<i8>),
348 VecU16(MyVec<u16>),
349 VecI16(MyVec<i16>),
350 VecU32(MyVec<u32>),
351 VecI32(MyVec<i32>),
352 VecF32(MyVec<f32>),
353 VecU64(Vec<u64>),
354 VecI64(Vec<i64>),
355 VecF64(Vec<f64>),
356 List(Arc<RwLock<Vec<Dynamic>>>),
357 Map(Arc<RwLock<IndexMap<SmolStr, Dynamic>>>),
358 StructView {
359 addr: usize,
360 ty: Arc<Type>,
361 },
362 StructOwned {
363 storage: Arc<StructBytes>,
364 ty: Arc<Type>,
365 },
366 Custom(Box<CustomValue>),
367 Iter {
368 idx: usize,
369 keys: Vec<SmolStr>,
370 value: Box<Dynamic>,
371 },
372}
373
374unsafe impl Send for Dynamic {}
375unsafe impl Sync for Dynamic {}
376
377impl PartialEq for Dynamic {
378 fn eq(&self, other: &Self) -> bool {
379 match (self, other) {
380 (Self::Null, Self::Null) => true,
381 (Self::Bool(a), Self::Bool(b)) => a == b,
382 (a, b) if a.is_str() && b.is_str() => a.as_str() == b.as_str(),
383 (Self::Bytes(a), Self::Bytes(b)) => a == b,
384 (Self::U8(a), Self::U8(b)) => a == b,
386 (Self::I8(a), Self::I8(b)) => a == b,
387 (Self::U16(a), Self::U16(b)) => a == b,
388 (Self::I16(a), Self::I16(b)) => a == b,
389 (Self::U32(a), Self::U32(b)) => a == b,
390 (Self::I32(a), Self::I32(b)) => a == b,
391 (Self::U64(a), Self::U64(b)) => a == b,
392 (Self::I64(a), Self::I64(b)) => a == b,
393 (a, b) if (a.is_int() || a.is_uint()) && (b.is_int() || b.is_uint()) => a.as_int().or_else(|| a.as_uint().and_then(|v| i64::try_from(v).ok())) == b.as_int().or_else(|| b.as_uint().and_then(|v| i64::try_from(v).ok())),
396 (Self::F16(a), Self::F16(b)) => a == b,
398 (Self::F32(a), Self::F32(b)) => a.to_bits() == b.to_bits(),
399 (Self::F64(a), Self::F64(b)) => a.to_bits() == b.to_bits(),
400 (a, b) if (a.is_f16() || a.is_f32() || a.is_f64()) && (b.is_f16() || b.is_f32() || b.is_f64()) => a.as_float() == b.as_float(),
401 (Self::VecI8(a), Self::VecI8(b)) => a.data == b.data,
403 (Self::VecU16(a), Self::VecU16(b)) => a.data == b.data,
404 (Self::VecI16(a), Self::VecI16(b)) => a.data == b.data,
405 (Self::VecU32(a), Self::VecU32(b)) => a.data == b.data,
406 (Self::VecI32(a), Self::VecI32(b)) => a.data == b.data,
407 (Self::VecF32(a), Self::VecF32(b)) => a.data == b.data,
408 (Self::VecU64(a), Self::VecU64(b)) => a == b,
409 (Self::VecI64(a), Self::VecI64(b)) => a == b,
410 (Self::VecF64(a), Self::VecF64(b)) => a == b,
411 (Self::List(a), Self::List(b)) => {
413 let a_guard = a.read();
414 let b_guard = b.read();
415 if a_guard.len() != b_guard.len() {
416 return false;
417 }
418 a_guard.iter().zip(b_guard.iter()).all(|(x, y)| x == y)
419 }
420 (Self::Map(a), Self::Map(b)) => {
422 let a_guard = a.read();
423 let b_guard = b.read();
424 if a_guard.len() != b_guard.len() {
425 return false;
426 }
427 for (k, v) in a_guard.iter() {
428 if let Some(other_v) = b_guard.get(k) {
429 if v != other_v {
430 return false;
431 }
432 } else {
433 return false;
434 }
435 }
436 true
437 }
438 (Self::StructView { addr: a_addr, ty: a_ty }, Self::StructView { addr: b_addr, ty: b_ty }) => a_addr == b_addr && a_ty == b_ty,
440 (Self::StructOwned { storage: a, ty: a_ty }, Self::StructOwned { storage: b, ty: b_ty }) => a_ty == b_ty && *a.bytes.read() == *b.bytes.read(),
441 (Self::Custom(a), Self::Custom(b)) => a.ptr_eq(b),
442 _ => false,
443 }
444 }
445}
446
447impl Eq for Dynamic {}
448
449use std::cmp::Ordering;
450
451impl PartialOrd for Dynamic {
452 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
453 Some(self.cmp(other))
454 }
455}
456
457impl Ord for Dynamic {
458 fn cmp(&self, other: &Self) -> Ordering {
459 if self.is_float() || other.is_float() {
461 return self.as_float().unwrap_or(0.0).total_cmp(&other.as_float().unwrap_or(0.0));
462 }
463 if self.is_int() || self.is_uint() || other.is_int() || other.is_uint() {
466 let left = self.as_uint().map(|v| v as i128).or_else(|| self.as_int().map(|v| v as i128)).unwrap_or(0);
467 let right = other.as_uint().map(|v| v as i128).or_else(|| other.as_int().map(|v| v as i128)).unwrap_or(0);
468 return left.cmp(&right);
469 }
470 if self.is_false() && other.is_true() {
471 Ordering::Less } else if self.is_true() && other.is_false() {
473 Ordering::Greater } else if self.is_null() && other.is_null() {
475 Ordering::Equal
476 } else if self.is_str() && other.is_str() {
477 self.as_str().cmp(other.as_str())
478 } else {
479 Ordering::Equal
480 }
481 }
482}
483
484macro_rules! impl_dynamic_scalar {
485 ($variant:ident, $ty:ty) => {
486 impl From<$ty> for Dynamic {
487 fn from(value: $ty) -> Self {
488 Dynamic::$variant(value)
489 }
490 }
491 };
492}
493
494impl_dynamic_scalar!(Bool, bool);
495
496impl_dynamic_scalar!(I8, i8);
497impl_dynamic_scalar!(U16, u16);
498impl_dynamic_scalar!(I16, i16);
499impl_dynamic_scalar!(U32, u32);
500impl_dynamic_scalar!(I32, i32);
501impl_dynamic_scalar!(F32, f32);
502impl_dynamic_scalar!(I64, i64);
503impl_dynamic_scalar!(U64, u64);
504impl_dynamic_scalar!(F64, f64);
505impl_dynamic_scalar!(String, SmolStr);
506impl From<&str> for Dynamic {
507 fn from(s: &str) -> Self {
508 Dynamic::String(s.into())
509 }
510}
511
512macro_rules! impl_try_from_dynamic_int {
513 ($($target:ty),+ $(,)?) => {
514 $(
515 impl TryFrom<Dynamic> for $target {
516 type Error = DynamicErr;
517 fn try_from(value: Dynamic) -> Result<Self, Self::Error> {
518 match value {
519 Dynamic::F32(v) => Ok(v as $target),
520 Dynamic::F64(v) => Ok(v as $target),
521 Dynamic::String(v) => v.trim().parse::<$target>().or_else(|_| v.trim().parse::<f64>().map(|value| value as $target)).map_err(|_| DynamicErr::TypeMismatch),
522 Dynamic::StringBuf(v) => v.trim().parse::<$target>().or_else(|_| v.trim().parse::<f64>().map(|value| value as $target)).map_err(|_| DynamicErr::TypeMismatch),
523 Dynamic::U8(v) => v.try_into().map_err(|_| DynamicErr::OutOfRange),
524 Dynamic::U16(v) => v.try_into().map_err(|_| DynamicErr::OutOfRange),
525 Dynamic::U32(v) => v.try_into().map_err(|_| DynamicErr::OutOfRange),
526 Dynamic::U64(v) => v.try_into().map_err(|_| DynamicErr::OutOfRange),
527 Dynamic::I8(v) => v.try_into().map_err(|_| DynamicErr::OutOfRange),
528 Dynamic::I16(v) => v.try_into().map_err(|_| DynamicErr::OutOfRange),
529 Dynamic::I32(v) => v.try_into().map_err(|_| DynamicErr::OutOfRange),
530 Dynamic::I64(v) => v.try_into().map_err(|_| DynamicErr::OutOfRange),
531 _ => Err(DynamicErr::TypeMismatch),
532 }
533 }
534 }
535 )+
536 };
537}
538impl_try_from_dynamic_int!(u8, u16, u32, u64, i8, i16, i32, i64);
539
540impl TryFrom<Dynamic> for f64 {
541 type Error = DynamicErr;
542 fn try_from(value: Dynamic) -> Result<Self, Self::Error> {
543 match value {
544 Dynamic::F32(v) => Ok(v as f64),
545 Dynamic::F64(v) => Ok(v),
546 Dynamic::U8(v) => Ok(v as f64),
547 Dynamic::U16(v) => Ok(v as f64),
548 Dynamic::U32(v) => Ok(v as f64),
549 Dynamic::U64(v) => Ok(v as f64),
550 Dynamic::I8(v) => Ok(v as f64),
551 Dynamic::I16(v) => Ok(v as f64),
552 Dynamic::I32(v) => Ok(v as f64),
553 Dynamic::I64(v) => Ok(v as f64),
554 Dynamic::String(v) => v.trim().parse::<f64>().map_err(|_| DynamicErr::TypeMismatch),
555 Dynamic::StringBuf(v) => v.trim().parse::<f64>().map_err(|_| DynamicErr::TypeMismatch),
556 _ => Err(DynamicErr::TypeMismatch),
557 }
558 }
559}
560
561impl TryFrom<Dynamic> for f32 {
562 type Error = DynamicErr;
563 fn try_from(value: Dynamic) -> Result<Self, Self::Error> {
564 match value {
565 Dynamic::F32(v) => Ok(v),
566 Dynamic::F64(v) => Ok(v as f32),
567 Dynamic::U8(v) => Ok(v as f32),
568 Dynamic::U16(v) => Ok(v as f32),
569 Dynamic::U32(v) => Ok(v as f32),
570 Dynamic::U64(v) => Ok(v as f32),
571 Dynamic::I8(v) => Ok(v as f32),
572 Dynamic::I16(v) => Ok(v as f32),
573 Dynamic::I32(v) => Ok(v as f32),
574 Dynamic::I64(v) => Ok(v as f32),
575 Dynamic::String(v) => v.trim().parse::<f32>().map_err(|_| DynamicErr::TypeMismatch),
576 Dynamic::StringBuf(v) => v.trim().parse::<f32>().map_err(|_| DynamicErr::TypeMismatch),
577 _ => Err(DynamicErr::TypeMismatch),
578 }
579 }
580}
581
582impl TryFrom<Dynamic> for bool {
583 type Error = DynamicErr;
584 fn try_from(value: Dynamic) -> Result<Self, Self::Error> {
585 match value {
586 Dynamic::Bool(v) => Ok(v),
587 Dynamic::U8(v) => Ok(v != 0),
588 Dynamic::U16(v) => Ok(v != 0),
589 Dynamic::U32(v) => Ok(v != 0),
590 Dynamic::U64(v) => Ok(v != 0),
591 Dynamic::I8(v) => Ok(v != 0),
592 Dynamic::I16(v) => Ok(v != 0),
593 Dynamic::I32(v) => Ok(v != 0),
594 Dynamic::I64(v) => Ok(v != 0),
595 _ => Err(DynamicErr::TypeMismatch),
596 }
597 }
598}
599
600impl TryFrom<Dynamic> for SmolStr {
601 type Error = DynamicErr;
602 fn try_from(value: Dynamic) -> Result<Self, Self::Error> {
603 match value {
604 Dynamic::String(s) => Ok(s),
605 Dynamic::StringBuf(s) => Ok(s.into()),
606 _ => Err(DynamicErr::TypeMismatch),
607 }
608 }
609}
610
611macro_rules! impl_dynamic_vec_from_slice {
612 ($variant:ident, $ty:ty) => {
613 impl From<&[$ty]> for Dynamic {
614 fn from(vec: &[$ty]) -> Self {
615 Dynamic::$variant(MyVec::from(vec))
616 }
617 }
618
619 impl<const N: usize> From<[$ty; N]> for Dynamic {
620 fn from(vec: [$ty; N]) -> Self {
621 Dynamic::$variant(MyVec::from(vec))
622 }
623 }
624 };
625}
626
627impl_dynamic_vec_from_slice!(VecI8, i8);
628impl_dynamic_vec_from_slice!(VecU16, u16);
629impl_dynamic_vec_from_slice!(VecI16, i16);
630impl_dynamic_vec_from_slice!(VecU32, u32);
631impl_dynamic_vec_from_slice!(VecI32, i32);
632impl_dynamic_vec_from_slice!(VecF32, f32);
633
634impl From<&[u8]> for Dynamic {
635 fn from(vec: &[u8]) -> Self {
636 Dynamic::Bytes(vec.to_vec())
637 }
638}
639
640impl From<Vec<u8>> for Dynamic {
641 fn from(vec: Vec<u8>) -> Self {
642 Dynamic::Bytes(vec)
643 }
644}
645
646impl From<&[u64]> for Dynamic {
647 fn from(vec: &[u64]) -> Self {
648 Dynamic::VecU64(vec.to_vec())
649 }
650}
651
652impl<const N: usize> From<[u64; N]> for Dynamic {
653 fn from(vec: [u64; N]) -> Self {
654 Dynamic::VecU64(vec.to_vec())
655 }
656}
657
658impl From<&[i64]> for Dynamic {
659 fn from(vec: &[i64]) -> Self {
660 Dynamic::VecI64(vec.to_vec())
661 }
662}
663impl<const N: usize> From<[i64; N]> for Dynamic {
664 fn from(vec: [i64; N]) -> Self {
665 Dynamic::VecI64(vec.to_vec())
666 }
667}
668
669impl From<&[f64]> for Dynamic {
670 fn from(vec: &[f64]) -> Self {
671 Dynamic::VecF64(vec.to_vec())
672 }
673}
674impl<const N: usize> From<[f64; N]> for Dynamic {
675 fn from(vec: [f64; N]) -> Self {
676 Dynamic::VecF64(vec.to_vec())
677 }
678}
679
680impl<T: Into<Dynamic>> From<Vec<T>> for Dynamic {
681 fn from(vec: Vec<T>) -> Self {
682 let vec = vec.into_iter().map(|v| v.into()).collect();
683 Dynamic::List(Arc::new(RwLock::new(vec)))
684 }
685}
686
687impl From<String> for Dynamic {
688 fn from(s: String) -> Self {
689 Dynamic::String(s.into())
690 }
691}
692
693impl ToString for Dynamic {
694 fn to_string(&self) -> String {
695 match self {
696 Self::Null => "()".into(),
697 Self::Bool(b) => {
698 if *b {
699 "true".into()
700 } else {
701 "false".into()
702 }
703 }
704 Self::U8(u) => u.to_string(),
705 Self::U16(u) => u.to_string(),
706 Self::U32(u) => u.to_string(),
707 Self::U64(u) => u.to_string(),
708 Self::I8(u) => u.to_string(),
709 Self::I16(u) => u.to_string(),
710 Self::I32(u) => u.to_string(),
711 Self::I64(u) => u.to_string(),
712 Self::F32(u) => u.to_string(),
713 Self::F64(u) => u.to_string(),
714 Self::String(s) => s.to_string(),
715 Self::StringBuf(s) => s.clone(),
716 _ => {
717 let mut buf = String::new();
718 self.to_json(&mut buf);
719 if buf.is_empty() { format!("{:?}", self) } else { buf }
720 }
721 }
722 }
723}
724
725use anyhow::Result;
726impl Dynamic {
727 pub fn custom<T>(value: T) -> Self
728 where
729 T: Any + Send + Sync + 'static,
730 {
731 Self::Custom(Box::new(CustomValue::new(value)))
732 }
733
734 pub fn custom_arc<T>(value: Arc<T>) -> Self
735 where
736 T: Any + Send + Sync + 'static,
737 {
738 Self::Custom(Box::new(CustomValue::from_arc(value)))
739 }
740
741 pub fn custom_with_properties<T>(value: T) -> Self
742 where
743 T: CustomProperty + 'static,
744 {
745 Self::Custom(Box::new(CustomValue::new_with_properties(value)))
746 }
747
748 pub fn custom_property_arc<T>(value: Arc<T>) -> Self
749 where
750 T: CustomProperty + 'static,
751 {
752 Self::Custom(Box::new(CustomValue::from_property_arc(value)))
753 }
754
755 pub fn is_custom(&self) -> bool {
756 matches!(self, Self::Custom(_))
757 }
758
759 pub fn custom_type_name(&self) -> Option<&'static str> {
760 if let Self::Custom(value) = self { Some(value.custom_type_name()) } else { None }
761 }
762
763 pub fn as_custom<T>(&self) -> Option<&T>
764 where
765 T: Any + Send + Sync,
766 {
767 if let Self::Custom(value) = self { value.as_any().downcast_ref::<T>() } else { None }
768 }
769
770 pub fn deep_clone(&self) -> Self {
771 match self {
772 Self::Map(m) => {
773 let m = m.read().iter().map(|(k, v)| (k.clone(), v.deep_clone())).collect();
774 Self::map(m)
775 }
776 Self::List(l) => {
777 let l = l.read().iter().map(|item| item.deep_clone()).collect();
778 Self::list(l)
779 }
780 Self::StructView { addr, ty } => Self::owned_struct_from_ptr(*addr, ty.as_ref().clone()),
781 Self::StructOwned { storage, ty } => Self::owned_struct_from_ptr(storage.addr(), ty.as_ref().clone()),
782 _ => self.clone(),
783 }
784 }
785
786 pub fn struct_view(addr: usize, ty: Type) -> Self {
787 Self::StructView { addr, ty: Arc::new(ty) }
788 }
789
790 pub fn owned_struct_from_ptr(addr: usize, ty: Type) -> Self {
791 Self::StructOwned { storage: StructBytes::copy_from_ptr(addr, &ty), ty: Arc::new(ty) }
792 }
793
794 fn struct_addr_ty(&self) -> Option<(usize, &Type)> {
795 match self {
796 Self::StructView { addr, ty } => Some((*addr, ty.as_ref())),
797 Self::StructOwned { storage, ty } => Some((storage.addr(), ty.as_ref())),
798 _ => None,
799 }
800 }
801
802 fn struct_storage(&self) -> Option<&StructBytes> {
803 match self {
804 Self::StructOwned { storage, .. } => Some(storage),
805 _ => None,
806 }
807 }
808
809 pub fn add(&mut self, val: i64) -> Option<i64> {
810 match self {
815 Self::U8(u) => u.checked_add_signed(val as i8).map(|v| {
816 *u = v;
817 v as i64
818 }),
819 Self::U16(u) => u.checked_add_signed(val as i16).map(|v| {
820 *u = v;
821 v as i64
822 }),
823 Self::U32(u) => u.checked_add_signed(val as i32).map(|v| {
824 *u = v;
825 v as i64
826 }),
827 Self::U64(u) => u.checked_add_signed(val).map(|v| {
828 *u = v;
829 v as i64
830 }),
831 Self::I8(i) => i.checked_add(val as i8).map(|v| {
832 *i = v;
833 v as i64
834 }),
835 Self::I16(i) => i.checked_add(val as i16).map(|v| {
836 *i = v;
837 v as i64
838 }),
839 Self::I32(i) => i.checked_add(val as i32).map(|v| {
840 *i = v;
841 v as i64
842 }),
843 Self::I64(i) => i.checked_add(val).map(|v| {
844 *i = v;
845 v
846 }),
847 _ => None,
848 }
849 }
850
851 pub fn is_vec(&self) -> bool {
852 use Dynamic::*;
853 match self {
854 VecI8(_) | VecU16(_) | Self::VecI16(_) | VecU32(_) | VecI32(_) | VecF32(_) | VecU64(_) | VecI64(_) | VecF64(_) => true,
855 _ => false,
856 }
857 }
858
859 pub fn as_bytes(&self) -> Option<&[u8]> {
860 match self {
861 Self::Bytes(b) => Some(b.as_slice()),
862 _ => None,
863 }
864 }
865
866 pub fn as_str(&self) -> &str {
867 match self {
868 Dynamic::String(s) => s.as_str(),
869 Dynamic::StringBuf(s) => s.as_str(),
870 _ => "",
871 }
872 }
873
874 pub fn is_native(&self) -> bool {
875 if self.is_f64() || self.is_f32() || self.is_int() || self.is_uint() || self.is_true() || self.is_false() { true } else { false }
878 }
879
880 pub fn from_utf8(buf: &[u8]) -> Result<Self> {
881 Ok(Dynamic::from(SmolStr::new(std::str::from_utf8(buf)?)))
882 }
883
884 pub fn append(&self, other: Self) {
885 match (self, other) {
886 (Self::List(left), rhs) => {
887 if let Self::List(right) = rhs {
888 if Arc::ptr_eq(left, &right) {
891 let mut right_clone = right.write().clone();
892 left.write().append(&mut right_clone);
893 } else {
894 left.write().append(&mut right.write());
895 }
896 } else {
897 left.write().push(rhs);
898 }
899 }
900 (Self::Map(left), Self::Map(right)) => {
901 if Arc::ptr_eq(left, &right) {
902 let mut right_clone = right.write().clone();
903 left.write().append(&mut right_clone);
904 } else {
905 left.write().append(&mut right.write());
906 }
907 }
908 (_, _) => {}
909 }
910 }
911
912 pub fn into_vec<T: TryFrom<Self> + 'static>(self) -> Option<Vec<T>> {
913 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<Dynamic>() {
914 match self {
915 Dynamic::List(list) => match Arc::try_unwrap(list) {
916 Ok(vec) => Some(unsafe { mem::transmute::<Vec<Dynamic>, Vec<T>>(vec.into_inner()) }),
917 Err(_) => None,
918 },
919 _ => {
920 let mut vec = Vec::with_capacity(self.len());
921 for idx in 0..self.len() {
922 if let Some(item) = self.get_idx(idx) {
923 vec.push(item);
924 }
925 }
926 Some(unsafe { mem::transmute(vec) })
927 }
928 }
929 } else {
930 match self {
931 Dynamic::List(list) => Arc::try_unwrap(list).ok().map(|l| l.into_inner().into_iter().filter_map(|l| T::try_from(l).ok()).collect()),
932 Dynamic::Bytes(vec) => {
933 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<u8>() {
934 let bytes_vec: Vec<u8> = Vec::from(vec);
935 Some(unsafe { mem::transmute(bytes_vec) })
936 } else {
937 None
938 }
939 }
940 Dynamic::VecI8(vec) => {
941 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<i8>() {
942 let vec_i8: Vec<i8> = Vec::from(vec);
943 Some(unsafe { mem::transmute(vec_i8) })
944 } else {
945 None
946 }
947 }
948 Dynamic::VecU16(vec) => {
949 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<u16>() {
950 let vec_u16: Vec<u16> = Vec::from(vec);
951 Some(unsafe { mem::transmute(vec_u16) })
952 } else {
953 None
954 }
955 }
956 Dynamic::VecI16(vec) => {
957 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<i16>() {
958 let vec_i16: Vec<i16> = Vec::from(vec);
959 Some(unsafe { mem::transmute(vec_i16) })
960 } else {
961 None
962 }
963 }
964 Dynamic::VecU32(vec) => {
965 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<u32>() {
966 let vec_u32: Vec<u32> = Vec::from(vec);
967 Some(unsafe { mem::transmute(vec_u32) })
968 } else {
969 None
970 }
971 }
972 Dynamic::VecI32(vec) => {
973 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<i32>() {
974 let vec_i32: Vec<i32> = Vec::from(vec);
975 Some(unsafe { mem::transmute(vec_i32) })
976 } else {
977 None
978 }
979 }
980 Dynamic::VecF32(vec) => {
981 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<f32>() {
982 let vec_f32: Vec<f32> = Vec::from(vec);
983 Some(unsafe { mem::transmute(vec_f32) })
984 } else {
985 None
986 }
987 }
988 Dynamic::VecU64(vec) => {
989 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<u64>() {
990 Some(unsafe { mem::transmute(vec) })
991 } else {
992 None
993 }
994 }
995 Dynamic::VecI64(vec) => {
996 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<i64>() {
997 Some(unsafe { mem::transmute(vec) })
998 } else {
999 None
1000 }
1001 }
1002 Dynamic::VecF64(vec) => {
1003 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<f64>() {
1004 Some(unsafe { mem::transmute(vec) })
1005 } else {
1006 None
1007 }
1008 }
1009 _ => None,
1010 }
1011 }
1012 }
1013
1014 pub fn push<T: Into<Dynamic> + 'static>(&mut self, value: T) -> bool {
1015 match self {
1016 Self::List(list) => {
1017 list.write().push(value.into());
1018 true
1019 }
1020 Self::Bytes(vec) => {
1021 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<u8>() {
1022 vec.push(unsafe { mem::transmute_copy(&value) });
1023 true
1024 } else {
1025 false
1026 }
1027 }
1028 Self::VecI8(vec) => {
1029 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<i8>() {
1030 vec.push(unsafe { mem::transmute_copy(&value) });
1031 true
1032 } else {
1033 false
1034 }
1035 }
1036 Self::VecU16(vec) => {
1037 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<u16>() {
1038 vec.push(unsafe { mem::transmute_copy(&value) });
1039 true
1040 } else {
1041 false
1042 }
1043 }
1044 Self::VecI16(vec) => {
1045 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<i16>() {
1046 vec.push(unsafe { mem::transmute_copy(&value) });
1047 true
1048 } else {
1049 false
1050 }
1051 }
1052 Self::VecU32(vec) => {
1053 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<u32>() {
1054 vec.push(unsafe { mem::transmute_copy(&value) });
1055 true
1056 } else {
1057 false
1058 }
1059 }
1060 Self::VecI32(vec) => {
1061 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<i32>() {
1062 vec.push(unsafe { mem::transmute_copy(&value) });
1063 true
1064 } else {
1065 false
1066 }
1067 }
1068 Self::VecF32(vec) => {
1069 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<f32>() {
1070 vec.push(unsafe { mem::transmute_copy(&value) });
1071 true
1072 } else {
1073 false
1074 }
1075 }
1076 Self::VecU64(vec) => {
1077 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<u64>() {
1078 vec.push(unsafe { mem::transmute_copy(&value) });
1079 true
1080 } else {
1081 false
1082 }
1083 }
1084 Self::VecI64(vec) => {
1085 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<i64>() {
1086 vec.push(unsafe { mem::transmute_copy(&value) });
1087 true
1088 } else {
1089 false
1090 }
1091 }
1092 Self::VecF64(vec) => {
1093 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<f64>() {
1094 vec.push(unsafe { mem::transmute_copy(&value) });
1095 true
1096 } else {
1097 false
1098 }
1099 }
1100 _ => false,
1101 }
1102 }
1103
1104 pub fn push_dynamic(&mut self, value: Dynamic) -> bool {
1105 match self {
1106 Self::List(list) => {
1107 list.write().push(value);
1108 true
1109 }
1110 Self::Bytes(vec) => value.try_into().map(|value| vec.push(value)).is_ok(),
1111 Self::VecI8(vec) => value.try_into().map(|value| vec.push(value)).is_ok(),
1112 Self::VecU16(vec) => value.try_into().map(|value| vec.push(value)).is_ok(),
1113 Self::VecI16(vec) => value.try_into().map(|value| vec.push(value)).is_ok(),
1114 Self::VecU32(vec) => value.try_into().map(|value| vec.push(value)).is_ok(),
1115 Self::VecI32(vec) => value.try_into().map(|value| vec.push(value)).is_ok(),
1116 Self::VecF32(vec) => value.try_into().map(|value| vec.push(value)).is_ok(),
1117 Self::VecU64(vec) => value.try_into().map(|value| vec.push(value)).is_ok(),
1118 Self::VecI64(vec) => value.try_into().map(|value| vec.push(value)).is_ok(),
1119 Self::VecF64(vec) => value.try_into().map(|value| vec.push(value)).is_ok(),
1120 _ => false,
1121 }
1122 }
1123
1124 pub fn pop(&mut self) -> Option<Dynamic> {
1125 match self {
1126 Self::List(list) => list.write().pop(),
1127 Self::Bytes(vec) => vec.pop().map(Dynamic::U8),
1128 Self::VecI8(vec) => vec.pop().map(Dynamic::I8),
1129 Self::VecU16(vec) => vec.pop().map(Dynamic::U16),
1130 Self::VecI16(vec) => vec.pop().map(Dynamic::I16),
1131 Self::VecU32(vec) => vec.pop().map(Dynamic::U32),
1132 Self::VecI32(vec) => vec.pop().map(Dynamic::I32),
1133 Self::VecF32(vec) => vec.pop().map(Dynamic::F32),
1134 Self::VecU64(vec) => vec.pop().map(Dynamic::U64),
1135 Self::VecI64(vec) => vec.pop().map(Dynamic::I64),
1136 Self::VecF64(vec) => vec.pop().map(Dynamic::F64),
1137 _ => None,
1138 }
1139 }
1140
1141 pub fn is_null(&self) -> bool {
1142 match self {
1143 Self::Null => true,
1144 _ => false,
1145 }
1146 }
1147
1148 pub fn as_bool(&self) -> Option<bool> {
1149 if let Self::Bool(b) = self { Some(*b) } else { None }
1150 }
1151
1152 pub fn is_true(&self) -> bool {
1153 match self {
1154 Self::Bool(b) => *b,
1155 _ => false,
1156 }
1157 }
1158
1159 pub fn is_false(&self) -> bool {
1160 match self {
1161 Self::Bool(b) => !*b,
1162 _ => false,
1163 }
1164 }
1165
1166 pub fn is_int(&self) -> bool {
1167 match self {
1168 Self::I8(_) | Self::I16(_) | Self::I32(_) | Self::I64(_) => true,
1169 _ => false,
1170 }
1171 }
1172
1173 pub fn as_int(&self) -> Option<i64> {
1174 match self {
1175 Self::U8(u) => Some(*u as i64),
1176 Self::U16(u) => Some(*u as i64),
1177 Self::U32(u) => Some(*u as i64),
1178 Self::U64(u) => i64::try_from(*u).ok(),
1179 Self::I8(i) => Some(*i as i64),
1180 Self::I16(i) => Some(*i as i64),
1181 Self::I32(i) => Some(*i as i64),
1182 Self::I64(i) => Some(*i as i64),
1183 _ => None,
1184 }
1185 }
1186
1187 pub fn is_uint(&self) -> bool {
1188 match self {
1189 Self::U8(_) | Self::U16(_) | Self::U32(_) | Self::U64(_) => true,
1190 _ => false,
1191 }
1192 }
1193
1194 pub fn as_uint(&self) -> Option<u64> {
1195 match self {
1196 Self::U8(i) => Some(*i as u64),
1197 Self::U16(i) => Some(*i as u64),
1198 Self::U32(i) => Some(*i as u64),
1199 Self::U64(i) => Some(*i as u64),
1200 _ => None,
1201 }
1202 }
1203
1204 pub fn is_f32(&self) -> bool {
1205 if let Self::F32(_) = self { true } else { false }
1206 }
1207
1208 pub fn is_float(&self) -> bool {
1209 match self {
1210 Self::F16(_) | Self::F32(_) | Self::F64(_) => true,
1211 _ => false,
1212 }
1213 }
1214
1215 pub fn is_f16(&self) -> bool {
1216 if let Self::F16(_) = self { true } else { false }
1217 }
1218
1219 pub fn is_str(&self) -> bool {
1220 if let Self::String(_) | Self::StringBuf(_) = self { true } else { false }
1221 }
1222
1223 pub fn is_f64(&self) -> bool {
1224 if let Self::F64(_) = self { true } else { false }
1225 }
1226
1227 pub fn as_float(&self) -> Option<f64> {
1228 match self {
1229 Self::U8(u) => Some(*u as f64),
1230 Self::U16(u) => Some(*u as f64),
1231 Self::U32(u) => Some(*u as f64),
1232 Self::U64(u) => Some(*u as f64),
1233 Self::I8(i) => Some(*i as f64),
1234 Self::I16(i) => Some(*i as f64),
1235 Self::I32(i) => Some(*i as f64),
1236 Self::I64(i) => Some(*i as f64),
1237 Self::F16(bits) => Some(f16_to_f64(*bits)),
1238 Self::F32(f) => Some(*f as f64),
1239 Self::F64(f) => Some(*f),
1240 _ => None,
1241 }
1242 }
1243
1244 pub fn is_signed(&self) -> bool {
1245 match self {
1246 Self::I8(_) | Self::I16(_) | Self::I32(_) | Self::I64(_) | Self::F16(_) | Self::F32(_) | Self::F64(_) => true,
1247 _ => false,
1248 }
1249 }
1250
1251 pub fn size_of(&self) -> usize {
1252 match self {
1253 Self::I8(_) | Self::U8(_) => 1,
1254 Self::I16(_) | Self::U16(_) => 2,
1255 Self::I32(_) | Self::U32(_) | Self::F32(_) => 4,
1256 Self::I64(_) | Self::U64(_) | Self::F64(_) => 8,
1257 Self::F16(_) => 2,
1258 Self::String(s) => s.len(),
1259 Self::StringBuf(s) => s.len(),
1260 Self::Bytes(bytes) => bytes.len(),
1261 Self::VecI8(vec) => vec.len(),
1262 Self::VecU16(vec) => vec.len(),
1263 Self::VecI16(vec) => vec.len(),
1264 Self::VecU32(vec) => vec.len(),
1265 Self::VecI32(vec) => vec.len(),
1266 Self::VecF32(vec) => vec.len(),
1267 Self::VecI64(vec) => vec.len(),
1268 Self::VecU64(vec) => vec.len(),
1269 Self::VecF64(vec) => vec.len(),
1270 Self::List(list) => list.read().len(),
1271 Self::Map(obj) => obj.read().len(),
1272 Self::StructView { ty, .. } | Self::StructOwned { ty, .. } => ty.len(),
1273 Self::Custom(_) => 0,
1274 _ => 1,
1275 }
1276 }
1277
1278 pub fn list(v: Vec<Dynamic>) -> Self {
1279 Dynamic::List(Arc::new(RwLock::new(v)))
1280 }
1281
1282 pub fn is_list(&self) -> bool {
1283 match self {
1284 Self::List(_) | Self::VecF32(_) | Self::VecF64(_) | Self::VecI16(_) | Self::VecI32(_) | Self::VecI64(_) | Self::VecU16(_) | Self::VecU32(_) | Self::VecU64(_) => true,
1285 Self::StructView { ty, .. } | Self::StructOwned { ty, .. } => ty.is_array() || ty.is_vec(),
1286 _ => false,
1287 }
1288 }
1289
1290 pub fn split(self, tag: &str) -> Self {
1291 match self {
1292 Self::String(s) => Self::list(s.split(tag).map(|p| Dynamic::from(p)).collect()),
1293 Self::StringBuf(s) => Self::list(s.split(tag).map(|p| Dynamic::from(p)).collect()),
1294 _ => self,
1295 }
1296 }
1297
1298 pub fn map(m: BTreeMap<SmolStr, Dynamic>) -> Self {
1299 Dynamic::Map(Arc::new(RwLock::new(m.into_iter().collect())))
1302 }
1303
1304 pub fn into_map(self) -> Option<IndexMap<SmolStr, Dynamic>> {
1305 if let Self::Map(map) = self { Arc::try_unwrap(map).ok().map(|m| m.into_inner()) } else { None }
1306 }
1307
1308 pub fn is_map(&self) -> bool {
1309 if let Self::Map(_) | Self::StructView { .. } | Self::StructOwned { .. } = self { true } else { false }
1310 }
1311
1312 pub fn insert<K: Into<SmolStr>, T: Into<Self>>(&self, key: K, value: T) {
1313 match self {
1314 Self::Map(obj) => {
1315 obj.write().insert(key.into(), value.into());
1316 }
1317 _ => {}
1318 }
1319 }
1320
1321 pub fn len(&self) -> usize {
1322 match self {
1323 Self::String(value) => value.len(),
1324 Self::StringBuf(value) => value.len(),
1325 Self::List(list) => list.read().len(),
1326 Self::Bytes(bytes) => bytes.len(),
1327 Self::VecI8(vec) => vec.len(),
1328 Self::VecU16(vec) => vec.len(),
1329 Self::VecI16(vec) => vec.len(),
1330 Self::VecU32(vec) => vec.len(),
1331 Self::VecI32(vec) => vec.len(),
1332 Self::VecF32(vec) => vec.len(),
1333 Self::VecI64(vec) => vec.len(),
1334 Self::VecU64(vec) => vec.len(),
1335 Self::VecF64(vec) => vec.len(),
1336 Self::Map(obj) => obj.read().len(),
1337 Self::Custom(_) => 0,
1338 _ => 0,
1339 }
1340 }
1341
1342 pub fn keys(&self) -> Vec<SmolStr> {
1343 if let Self::Map(map) = self {
1344 map.read().keys().cloned().collect()
1345 } else if let Some((_, Type::Struct { params: _, fields })) = self.struct_addr_ty() {
1346 fields.iter().map(|(name, _)| name.clone()).collect()
1347 } else {
1348 Vec::new()
1349 }
1350 }
1351
1352 pub fn contains(&self, key: &str) -> bool {
1353 if let Self::Map(map) = self {
1354 map.read().get(key).is_some_and(|value| !value.is_null())
1355 } else if let Self::StructView { ty, .. } | Self::StructOwned { ty, .. } = self {
1356 ty.get_field(key).is_ok()
1357 } else if let Self::List(list) = self {
1358 list.read().iter().find(|l| l.as_str() == key).is_some()
1359 } else if let Self::String(s) = self {
1360 s.contains(key)
1361 } else if let Self::StringBuf(s) = self {
1362 s.contains(key)
1363 } else if let Self::Custom(value) = self {
1364 value.contains_key(key)
1365 } else {
1366 false
1367 }
1368 }
1369
1370 pub fn starts_with(&self, prefix: &str) -> bool {
1371 if let Self::String(s) = self {
1372 s.starts_with(prefix)
1373 } else if let Self::StringBuf(s) = self {
1374 s.starts_with(prefix)
1375 } else {
1376 false
1377 }
1378 }
1379
1380 pub fn ends_with(&self, suffix: &str) -> bool {
1381 if let Self::String(s) = self {
1382 s.ends_with(suffix)
1383 } else if let Self::StringBuf(s) = self {
1384 s.ends_with(suffix)
1385 } else {
1386 false
1387 }
1388 }
1389
1390 pub fn get_dynamic(&self, key: &str) -> Option<Dynamic> {
1391 if let Self::Map(map) = self {
1392 map.read().get(key).cloned()
1393 } else if let Some((addr, ty)) = self.struct_addr_ty() {
1394 let (idx, field_ty) = ty.get_field(key).ok()?;
1395 Self::read_struct_field(addr, idx, field_ty, ty, self.struct_storage())
1396 } else if let Self::Custom(value) = self {
1397 value.get_key(key)
1398 } else {
1399 None
1400 }
1401 }
1402
1403 pub fn set_dynamic(&self, key: SmolStr, value: impl Into<Dynamic>) {
1404 if let Self::Map(map) = self {
1405 map.write().insert(key, value.into());
1406 } else if let Some((addr, ty)) = self.struct_addr_ty()
1407 && let Ok((idx, field_ty)) = ty.get_field(key.as_str())
1408 {
1409 Self::write_struct_field(addr, idx, field_ty, ty, value.into(), self.struct_storage());
1410 } else if let Self::Custom(custom) = self {
1411 custom.set_key(key.as_str(), value.into());
1412 }
1413 }
1414
1415 fn field_addr(addr: usize, idx: usize, struct_ty: &Type) -> Option<usize> {
1416 struct_ty.field_offset(idx).map(|offset| addr + offset as usize)
1417 }
1418
1419 fn read_dynamic_ptr(addr: usize, storage: Option<&StructBytes>, offset: usize) -> Option<Dynamic> {
1420 if let Some(storage) = storage {
1421 return storage.read_dynamic_ptr_at(offset);
1422 }
1423 let ptr = unsafe { std::ptr::read_unaligned(addr as *const usize) };
1424 if ptr == 0 { None } else { Some(unsafe { (&*(ptr as *const Dynamic)).clone() }) }
1425 }
1426
1427 fn write_dynamic_ptr(addr: usize, value: Dynamic, storage: Option<&StructBytes>, offset: usize) {
1428 if let Some(storage) = storage {
1429 storage.write_dynamic_ptr_at(offset, value);
1430 } else {
1431 let ptr = Box::into_raw(Box::new(value)) as usize;
1432 unsafe {
1433 std::ptr::write_unaligned(addr as *mut usize, ptr);
1434 }
1435 }
1436 }
1437
1438 fn read_struct_field(addr: usize, idx: usize, field_ty: &Type, struct_ty: &Type, storage: Option<&StructBytes>) -> Option<Dynamic> {
1439 let field_addr = Self::field_addr(addr, idx, struct_ty)?;
1440 let offset = field_addr.saturating_sub(addr);
1441 match field_ty {
1442 Type::Bool => Some(Dynamic::Bool(unsafe { std::ptr::read_unaligned(field_addr as *const u8) } != 0)),
1443 Type::I8 => Some(Dynamic::I8(unsafe { std::ptr::read_unaligned(field_addr as *const i8) })),
1444 Type::U8 => Some(Dynamic::U8(unsafe { std::ptr::read_unaligned(field_addr as *const u8) })),
1445 Type::I16 => Some(Dynamic::I16(unsafe { std::ptr::read_unaligned(field_addr as *const i16) })),
1446 Type::U16 => Some(Dynamic::U16(unsafe { std::ptr::read_unaligned(field_addr as *const u16) })),
1447 Type::I32 => Some(Dynamic::I32(unsafe { std::ptr::read_unaligned(field_addr as *const i32) })),
1448 Type::U32 => Some(Dynamic::U32(unsafe { std::ptr::read_unaligned(field_addr as *const u32) })),
1449 Type::I64 => Some(Dynamic::I64(unsafe { std::ptr::read_unaligned(field_addr as *const i64) })),
1450 Type::U64 => Some(Dynamic::U64(unsafe { std::ptr::read_unaligned(field_addr as *const u64) })),
1451 Type::F32 => Some(Dynamic::F32(unsafe { std::ptr::read_unaligned(field_addr as *const f32) })),
1452 Type::F64 => Some(Dynamic::F64(unsafe { std::ptr::read_unaligned(field_addr as *const f64) })),
1453 ty if ty.is_struct() || ty.is_array() || ty.is_vec() => {
1454 if storage.is_some() {
1455 Some(Dynamic::owned_struct_from_ptr(field_addr, field_ty.clone()))
1456 } else {
1457 Some(Dynamic::struct_view(field_addr, field_ty.clone()))
1458 }
1459 }
1460 _ => Self::read_dynamic_ptr(field_addr, storage, offset),
1461 }
1462 }
1463
1464 fn write_struct_field(addr: usize, idx: usize, field_ty: &Type, struct_ty: &Type, value: Dynamic, storage: Option<&StructBytes>) {
1465 let Some(field_addr) = Self::field_addr(addr, idx, struct_ty) else {
1466 return;
1467 };
1468 let offset = field_addr.saturating_sub(addr);
1469 if let Some(storage) = storage {
1470 storage.clear_dynamic_fields_in(offset, field_ty.storage_width() as usize);
1471 }
1472 match field_ty {
1473 Type::Bool => unsafe {
1474 std::ptr::write_unaligned(field_addr as *mut u8, if value.is_true() { 1 } else { 0 });
1475 },
1476 Type::I8 => unsafe {
1477 std::ptr::write_unaligned(field_addr as *mut i8, value.try_into().unwrap_or_default());
1478 },
1479 Type::U8 => unsafe {
1480 std::ptr::write_unaligned(field_addr as *mut u8, value.try_into().unwrap_or_default());
1481 },
1482 Type::I16 => unsafe {
1483 std::ptr::write_unaligned(field_addr as *mut i16, value.try_into().unwrap_or_default());
1484 },
1485 Type::U16 => unsafe {
1486 std::ptr::write_unaligned(field_addr as *mut u16, value.try_into().unwrap_or_default());
1487 },
1488 Type::I32 => unsafe {
1489 std::ptr::write_unaligned(field_addr as *mut i32, value.try_into().unwrap_or_default());
1490 },
1491 Type::U32 => unsafe {
1492 std::ptr::write_unaligned(field_addr as *mut u32, value.try_into().unwrap_or_default());
1493 },
1494 Type::I64 => unsafe {
1495 std::ptr::write_unaligned(field_addr as *mut i64, value.try_into().unwrap_or_default());
1496 },
1497 Type::U64 => unsafe {
1498 std::ptr::write_unaligned(field_addr as *mut u64, value.try_into().unwrap_or_default());
1499 },
1500 Type::F32 => unsafe {
1501 std::ptr::write_unaligned(field_addr as *mut f32, f32::try_from(value).unwrap_or_default());
1502 },
1503 Type::F64 => unsafe {
1504 std::ptr::write_unaligned(field_addr as *mut f64, f64::try_from(value).unwrap_or_default());
1505 },
1506 ty if ty.is_struct() || ty.is_array() || ty.is_vec() => {
1507 if let Some((src_addr, _)) = value.struct_addr_ty() {
1508 if let Some(storage) = storage {
1509 unsafe {
1510 std::ptr::copy_nonoverlapping(src_addr as *const u8, field_addr as *mut u8, field_ty.storage_width() as usize);
1511 }
1512 storage.clone_dynamic_fields_from(src_addr, field_ty, offset);
1513 } else {
1514 unsafe {
1515 std::ptr::copy_nonoverlapping(src_addr as *const u8, field_addr as *mut u8, field_ty.storage_width() as usize);
1516 }
1517 }
1518 }
1519 }
1520 _ => Self::write_dynamic_ptr(field_addr, value, storage, offset),
1521 }
1522 }
1523
1524 pub fn remove_dynamic(&self, key: &str) -> Option<Dynamic> {
1525 if let Self::Map(map) = self { map.write().shift_remove(key) } else { None }
1527 }
1528
1529 pub fn get_idx(&self, idx: usize) -> Option<Self> {
1530 match self {
1531 Self::List(list) => list.read().get(idx).cloned(),
1532 Self::VecI8(vec) => vec.get(idx).map(Self::I8),
1533 Self::VecU16(vec) => vec.get(idx).map(Self::U16),
1534 Self::VecI16(vec) => vec.get(idx).map(Self::I16),
1535 Self::VecU32(vec) => vec.get(idx).map(Self::U32),
1536 Self::VecI32(vec) => vec.get(idx).map(Self::I32),
1537 Self::VecF32(vec) => vec.get(idx).map(Self::F32),
1538 Self::VecI64(vec) => vec.get(idx).cloned().map(Self::I64),
1539 Self::VecU64(vec) => vec.get(idx).cloned().map(Self::U64),
1540 Self::VecF64(vec) => vec.get(idx).cloned().map(Self::F64),
1541 Self::StructView { addr, ty } => {
1542 if let Type::Struct { params: _, fields } = ty.as_ref() {
1543 fields.get(idx).and_then(|(_, field_ty)| Self::read_struct_field(*addr, idx, field_ty, ty.as_ref(), None))
1544 } else {
1545 Self::read_aggregate_index(*addr, idx, ty.as_ref(), None)
1546 }
1547 }
1548 Self::StructOwned { storage, ty } => Self::read_aggregate_index(storage.addr(), idx, ty.as_ref(), Some(storage)),
1549 _ => None,
1550 }
1551 }
1552
1553 fn read_aggregate_index(addr: usize, idx: usize, ty: &Type, storage: Option<&StructBytes>) -> Option<Self> {
1554 match ty {
1555 Type::Struct { fields, .. } => fields.get(idx).and_then(|(_, field_ty)| Self::read_struct_field(addr, idx, field_ty, ty, storage)),
1556 Type::Array(elem_ty, len) | Type::Vec(elem_ty, len) => {
1557 if idx >= *len as usize {
1558 return None;
1559 }
1560 let elem_addr = addr + idx * elem_ty.storage_width() as usize;
1561 Some(Self::read_aggregate_value(elem_addr, elem_ty, storage, elem_addr.saturating_sub(addr)))
1562 }
1563 _ => None,
1564 }
1565 }
1566
1567 fn read_aggregate_value(addr: usize, ty: &Type, storage: Option<&StructBytes>, offset: usize) -> Self {
1568 match ty {
1569 Type::Bool => Dynamic::Bool(unsafe { std::ptr::read_unaligned(addr as *const u8) } != 0),
1570 Type::I8 => Dynamic::I8(unsafe { std::ptr::read_unaligned(addr as *const i8) }),
1571 Type::U8 => Dynamic::U8(unsafe { std::ptr::read_unaligned(addr as *const u8) }),
1572 Type::I16 => Dynamic::I16(unsafe { std::ptr::read_unaligned(addr as *const i16) }),
1573 Type::U16 => Dynamic::U16(unsafe { std::ptr::read_unaligned(addr as *const u16) }),
1574 Type::I32 => Dynamic::I32(unsafe { std::ptr::read_unaligned(addr as *const i32) }),
1575 Type::U32 => Dynamic::U32(unsafe { std::ptr::read_unaligned(addr as *const u32) }),
1576 Type::I64 => Dynamic::I64(unsafe { std::ptr::read_unaligned(addr as *const i64) }),
1577 Type::U64 => Dynamic::U64(unsafe { std::ptr::read_unaligned(addr as *const u64) }),
1578 Type::F32 => Dynamic::F32(unsafe { std::ptr::read_unaligned(addr as *const f32) }),
1579 Type::F64 => Dynamic::F64(unsafe { std::ptr::read_unaligned(addr as *const f64) }),
1580 ty if ty.is_struct() || ty.is_array() || ty.is_vec() => {
1581 if storage.is_some() {
1582 Dynamic::owned_struct_from_ptr(addr, ty.clone())
1583 } else {
1584 Dynamic::struct_view(addr, ty.clone())
1585 }
1586 }
1587 _ => Self::read_dynamic_ptr(addr, storage, offset).unwrap_or(Dynamic::Null),
1588 }
1589 }
1590
1591 pub fn into_iter(self) -> Self {
1592 if self.is_map() {
1593 let keys = self.keys();
1594 Self::Iter { idx: 0, keys, value: Box::new(self) }
1595 } else {
1596 Self::Iter { idx: 0, keys: Vec::new(), value: Box::new(self) }
1597 }
1598 }
1599
1600 pub fn next(&mut self) -> Option<Self> {
1601 if let Self::Iter { idx, keys, value } = self {
1602 if !keys.is_empty() {
1603 if *idx < keys.len() {
1604 let k = keys[*idx].clone();
1605 let v = value.get_dynamic(k.as_str()).unwrap_or(Dynamic::Null);
1607 *idx += 1;
1608 return Some(v);
1609 }
1610 } else {
1611 if let Some(v) = value.get_idx(*idx) {
1612 *idx += 1;
1613 return Some(v);
1614 }
1615 }
1616 }
1617 None
1618 }
1619
1620 pub fn next_pair(&mut self) -> Option<Self> {
1621 if let Self::Iter { idx, keys, value } = self {
1622 if !keys.is_empty() {
1623 if *idx < keys.len() {
1624 let k = keys[*idx].clone();
1625 let v = value.get_dynamic(k.as_str()).unwrap_or(Dynamic::Null);
1626 *idx += 1;
1627 return Some(list!(k, v));
1628 }
1629 } else {
1630 if let Some(v) = value.get_idx(*idx) {
1631 *idx += 1;
1632 return Some(v);
1633 }
1634 }
1635 }
1636 None
1637 }
1638
1639 pub fn set_idx(&mut self, idx: usize, val: Dynamic) {
1640 match self {
1641 Self::List(list) => {
1642 list.write().get_mut(idx).map(|l| *l = val);
1643 }
1644 Self::VecI8(vec) => {
1645 if let Ok(value) = val.try_into() {
1646 vec.set(idx, value);
1647 }
1648 }
1649 Self::VecU16(vec) => {
1650 if let Ok(value) = val.try_into() {
1651 vec.set(idx, value);
1652 }
1653 }
1654 Self::VecI16(vec) => {
1655 if let Ok(value) = val.try_into() {
1656 vec.set(idx, value);
1657 }
1658 }
1659 Self::VecU32(vec) => {
1660 if let Ok(value) = val.try_into() {
1661 vec.set(idx, value);
1662 }
1663 }
1664 Self::VecI32(vec) => {
1665 if let Ok(value) = val.try_into() {
1666 vec.set(idx, value);
1667 }
1668 }
1669 Self::VecF32(vec) => {
1670 if let Ok(value) = val.try_into() {
1671 vec.set(idx, value);
1672 }
1673 }
1674 Self::VecI64(vec) => {
1675 if let Some(slot) = vec.get_mut(idx)
1676 && let Ok(value) = val.try_into()
1677 {
1678 *slot = value;
1679 }
1680 }
1681 Self::VecU64(vec) => {
1682 if let Some(slot) = vec.get_mut(idx)
1683 && let Ok(value) = val.try_into()
1684 {
1685 *slot = value;
1686 }
1687 }
1688 Self::VecF64(vec) => {
1689 if let Some(slot) = vec.get_mut(idx)
1690 && let Ok(value) = val.try_into()
1691 {
1692 *slot = value;
1693 }
1694 }
1695 Self::StructView { addr, ty } => {
1696 if let Type::Struct { params: _, fields } = ty.as_ref()
1697 && let Some((_, field_ty)) = fields.get(idx)
1698 {
1699 Self::write_struct_field(*addr, idx, field_ty, ty.as_ref(), val, None);
1700 } else {
1701 Self::write_aggregate_index(*addr, idx, ty.as_ref(), val, None);
1702 }
1703 }
1704 Self::StructOwned { storage, ty } => {
1705 if let Type::Struct { params: _, fields } = ty.as_ref()
1706 && let Some((_, field_ty)) = fields.get(idx)
1707 {
1708 Self::write_struct_field(storage.addr(), idx, field_ty, ty.as_ref(), val, Some(storage));
1709 } else {
1710 Self::write_aggregate_index(storage.addr(), idx, ty.as_ref(), val, Some(storage));
1711 }
1712 }
1713 _ => {}
1714 }
1715 }
1716
1717 fn write_aggregate_index(addr: usize, idx: usize, ty: &Type, val: Dynamic, storage: Option<&StructBytes>) {
1718 let (elem_ty, len) = match ty {
1719 Type::Array(elem_ty, len) | Type::Vec(elem_ty, len) => (elem_ty.as_ref(), *len as usize),
1720 _ => return,
1721 };
1722 if idx >= len {
1723 return;
1724 }
1725 let offset = idx * elem_ty.storage_width() as usize;
1726 let elem_addr = addr + offset;
1727 if let Some(storage) = storage {
1728 storage.clear_dynamic_fields_in(offset, elem_ty.storage_width() as usize);
1729 }
1730 match elem_ty {
1731 Type::Bool => unsafe { std::ptr::write_unaligned(elem_addr as *mut u8, if val.is_true() { 1 } else { 0 }) },
1732 Type::I8 => unsafe { std::ptr::write_unaligned(elem_addr as *mut i8, val.try_into().unwrap_or_default()) },
1733 Type::U8 => unsafe { std::ptr::write_unaligned(elem_addr as *mut u8, val.try_into().unwrap_or_default()) },
1734 Type::I16 => unsafe { std::ptr::write_unaligned(elem_addr as *mut i16, val.try_into().unwrap_or_default()) },
1735 Type::U16 => unsafe { std::ptr::write_unaligned(elem_addr as *mut u16, val.try_into().unwrap_or_default()) },
1736 Type::I32 => unsafe { std::ptr::write_unaligned(elem_addr as *mut i32, val.try_into().unwrap_or_default()) },
1737 Type::U32 => unsafe { std::ptr::write_unaligned(elem_addr as *mut u32, val.try_into().unwrap_or_default()) },
1738 Type::I64 => unsafe { std::ptr::write_unaligned(elem_addr as *mut i64, val.try_into().unwrap_or_default()) },
1739 Type::U64 => unsafe { std::ptr::write_unaligned(elem_addr as *mut u64, val.try_into().unwrap_or_default()) },
1740 Type::F32 => unsafe { std::ptr::write_unaligned(elem_addr as *mut f32, f32::try_from(val).unwrap_or_default()) },
1741 Type::F64 => unsafe { std::ptr::write_unaligned(elem_addr as *mut f64, f64::try_from(val).unwrap_or_default()) },
1742 ty if ty.is_struct() || ty.is_array() || ty.is_vec() => {
1743 if let Some((src_addr, _)) = val.struct_addr_ty() {
1744 unsafe {
1745 std::ptr::copy_nonoverlapping(src_addr as *const u8, elem_addr as *mut u8, elem_ty.storage_width() as usize);
1746 }
1747 if let Some(storage) = storage {
1748 storage.clone_dynamic_fields_from(src_addr, elem_ty, offset);
1749 }
1750 }
1751 }
1752 _ => Self::write_dynamic_ptr(elem_addr, val, storage, offset),
1753 }
1754 }
1755
1756 pub fn to_markdown(&self) -> String {
1757 let mut s = String::new();
1758 if let Self::Map(m) = self {
1759 for (key, v) in m.read().iter() {
1760 s.push_str(&format!("#### ```{}```\n", key));
1761 s.push_str(&v.to_markdown());
1762 s.push('\n');
1763 }
1764 } else if let Self::Bytes(bytes) = self {
1765 let head = bytes.get(..8).unwrap_or(bytes);
1766 s = format!("[{}{}]", hex::encode(head), if bytes.len() > 8 { "..." } else { "" });
1767 } else {
1768 let len = self.len();
1769 if len > 0 {
1770 for idx in 0..len {
1771 s.push_str(&format!("- {}\n", self.get_idx(idx).unwrap().to_markdown()));
1772 }
1773 } else {
1774 s = self.to_string();
1775 }
1776 }
1777 s
1778 }
1779}
1780
1781#[cfg(test)]
1782mod tests {
1783 use super::*;
1784 use parking_lot::RwLock;
1785
1786 #[derive(Debug, PartialEq)]
1787 struct CustomCounter {
1788 value: i64,
1789 }
1790
1791 #[test]
1792 fn type_add_promotion_rules() {
1793 use crate::Type;
1794 assert_eq!(Type::I32 + Type::I32, Type::I32);
1796 assert_eq!(Type::I32 + Type::Str, Type::Str);
1798 assert_eq!(Type::I32 + Type::Any, Type::Any);
1800 assert_eq!(Type::I64 + Type::F32, Type::F32);
1802 assert_eq!(Type::F32 + Type::F64, Type::F64);
1803 assert_eq!(Type::I8 + Type::I32, Type::I32);
1805 assert_eq!(Type::I32 + Type::I64, Type::I64);
1806 assert_eq!(Type::I32 + Type::U32, Type::I32);
1808 assert_eq!(Type::U8 + Type::U32, Type::U32);
1810 }
1811
1812 #[test]
1813 fn dynamic_enum_stays_compact() {
1814 assert_eq!(std::mem::size_of::<Dynamic>(), 40);
1815 }
1816
1817 #[test]
1818 fn custom_values_can_be_downcast_and_shared_by_clone() {
1819 let value = Dynamic::custom(RwLock::new(CustomCounter { value: 7 }));
1820 assert!(value.is_custom());
1821 assert!(value.custom_type_name().is_some());
1822
1823 let cloned = value.clone();
1824 assert_eq!(cloned.as_custom::<RwLock<CustomCounter>>().unwrap().read().value, 7);
1825
1826 cloned.as_custom::<RwLock<CustomCounter>>().unwrap().write().value = 9;
1827 assert_eq!(value.as_custom::<RwLock<CustomCounter>>().unwrap().read().value, 9);
1828 assert_eq!(value, cloned);
1829 }
1830
1831 #[derive(Debug, Default)]
1832 struct CustomPropertyBag {
1833 values: RwLock<BTreeMap<SmolStr, Dynamic>>,
1834 }
1835
1836 impl CustomProperty for CustomPropertyBag {
1837 fn get_key(&self, key: &str) -> Option<Dynamic> {
1838 self.values.read().get(key).cloned()
1839 }
1840
1841 fn set_key(&self, key: &str, value: Dynamic) -> bool {
1842 self.values.write().insert(key.into(), value);
1843 true
1844 }
1845 }
1846
1847 #[test]
1848 fn custom_values_can_forward_dynamic_properties() {
1849 let value = Dynamic::custom_with_properties(CustomPropertyBag::default());
1850
1851 value.set_dynamic("file_mode".into(), 2i64);
1852
1853 assert!(value.contains("file_mode"));
1854 assert_eq!(value.get_dynamic("file_mode").and_then(|value| value.as_int()), Some(2));
1855 }
1856
1857 #[test]
1858 fn deep_clone_recursively_copies_maps_and_lists() {
1859 let nested = Dynamic::map(Default::default());
1860 nested.insert("score", 1);
1861
1862 let value = Dynamic::map(Default::default());
1863 value.insert("nested", nested.clone());
1864 value.insert("items", Dynamic::list(vec![nested.clone()]));
1865
1866 let cloned = value.deep_clone();
1867 cloned.get_dynamic("nested").unwrap().insert("score", 2);
1868 cloned.get_dynamic("items").unwrap().get_idx(0).unwrap().insert("score", 3);
1869
1870 assert_eq!(value.get_dynamic("nested").unwrap().get_dynamic("score").and_then(|v| v.as_int()), Some(1));
1871 assert_eq!(value.get_dynamic("items").unwrap().get_idx(0).unwrap().get_dynamic("score").and_then(|v| v.as_int()), Some(1));
1872 }
1873
1874 #[test]
1875 fn string_add_keeps_concat_semantics() {
1876 let left = Dynamic::from("hello");
1877 let right = Dynamic::from(" world");
1878 let joined = left + right;
1879 assert!(matches!(joined, Dynamic::StringBuf(_)));
1880 assert_eq!(joined.as_str(), "hello world");
1881
1882 assert_eq!((Dynamic::from("level ") + Dynamic::I64(7)).as_str(), "level 7");
1883 assert_eq!((Dynamic::I64(7) + Dynamic::from(" days")).as_str(), "7 days");
1884 }
1885
1886 #[test]
1887 fn string_add_reuses_string_buf_after_first_concat() {
1888 let mut value = Dynamic::from("a") + Dynamic::from("b");
1889 assert!(matches!(value, Dynamic::StringBuf(_)));
1890
1891 value = value + Dynamic::from("c");
1892 assert!(matches!(value, Dynamic::StringBuf(_)));
1893 assert_eq!(value.as_str(), "abc");
1894 }
1895
1896 #[test]
1897 fn u64_as_int_does_not_wrap() {
1898 assert_eq!(Dynamic::U64(i64::MAX as u64).as_int(), Some(i64::MAX));
1899 assert_eq!(Dynamic::U64(i64::MAX as u64 + 1).as_int(), None);
1900 }
1901
1902 #[test]
1903 fn dynamic_integer_ops_report_fault_instead_of_panicking() {
1904 let _ = take_fault();
1905 assert_eq!(Dynamic::U64(u64::MAX) + Dynamic::U64(1), Dynamic::Null);
1906 assert!(take_fault().is_some());
1907
1908 assert_eq!(Dynamic::I64(i64::MAX) + Dynamic::I64(1), Dynamic::Null);
1909 assert!(take_fault().is_some());
1910
1911 assert_eq!(Dynamic::I32(1) << Dynamic::I32(64), Dynamic::Null);
1912 assert!(take_fault().is_some());
1913 }
1914
1915 #[test]
1916 fn typed_vec_set_idx_ignores_bad_index_or_value_without_panicking() {
1917 let mut values = Dynamic::VecI64(vec![1, 2, 3]);
1918 values.set_idx(10, Dynamic::I64(99));
1919 assert_eq!(values.get_idx(2).and_then(|value| value.as_int()), Some(3));
1920
1921 values.set_idx(1, Dynamic::from("bad"));
1922 assert_eq!(values.get_idx(1).and_then(|value| value.as_int()), Some(2));
1923
1924 values.set_idx(1, Dynamic::I64(7));
1925 assert_eq!(values.get_idx(1).and_then(|value| value.as_int()), Some(7));
1926 }
1927
1928 #[test]
1929 fn nested_struct_fields_use_inline_storage() {
1930 let inner_ty = Type::Struct { params: vec![], fields: vec![("value".into(), Type::I64)] };
1931 let outer_ty = Type::Struct { params: vec![], fields: vec![("inner".into(), inner_ty.clone()), ("tag".into(), Type::I64)] };
1932
1933 let mut inner_bytes = vec![0u8; inner_ty.storage_width() as usize];
1934 let mut outer_bytes = vec![0u8; outer_ty.storage_width() as usize];
1935 let inner = Dynamic::struct_view(inner_bytes.as_mut_ptr() as usize, inner_ty);
1936 let outer = Dynamic::struct_view(outer_bytes.as_mut_ptr() as usize, outer_ty);
1937
1938 inner.set_dynamic("value".into(), Dynamic::I64(17));
1939 outer.set_dynamic("inner".into(), inner);
1940 outer.set_dynamic("tag".into(), Dynamic::I64(3));
1941
1942 let read_inner = outer.get_dynamic("inner").expect("inner field");
1943 assert_eq!(read_inner.get_dynamic("value").and_then(|value| value.as_int()), Some(17));
1944 assert_eq!(outer.get_dynamic("tag").and_then(|value| value.as_int()), Some(3));
1945 }
1946
1947 #[test]
1948 fn owned_struct_clones_dynamic_pointer_fields() {
1949 let ty = Type::Struct { params: vec![], fields: vec![("name".into(), Type::Str)] };
1950 let mut bytes = vec![0u8; ty.storage_width() as usize];
1951 let original = Box::into_raw(Box::new(Dynamic::from("alpha"))) as usize;
1952 unsafe {
1953 std::ptr::write_unaligned(bytes.as_mut_ptr() as *mut usize, original);
1954 }
1955
1956 let owned = Dynamic::owned_struct_from_ptr(bytes.as_ptr() as usize, ty);
1957 unsafe {
1958 drop(Box::from_raw(original as *mut Dynamic));
1959 }
1960
1961 assert_eq!(owned.get_dynamic("name").map(|value| value.as_str().to_string()), Some("alpha".to_string()));
1962 owned.set_dynamic("name".into(), Dynamic::from("beta"));
1963 assert_eq!(owned.get_dynamic("name").map(|value| value.as_str().to_string()), Some("beta".to_string()));
1964 }
1965
1966 #[test]
1967 fn aggregate_array_fields_support_dynamic_index_access() {
1968 let ty = Type::Array(std::rc::Rc::new(Type::I64), 3);
1969 let mut bytes = vec![0u8; ty.storage_width() as usize];
1970 for (idx, value) in [3i64, 5, 7].into_iter().enumerate() {
1971 unsafe {
1972 std::ptr::write_unaligned(bytes.as_mut_ptr().add(idx * 8) as *mut i64, value);
1973 }
1974 }
1975
1976 let mut array = Dynamic::owned_struct_from_ptr(bytes.as_ptr() as usize, ty);
1977 assert_eq!(array.get_idx(1).and_then(|value| value.as_int()), Some(5));
1978 array.set_idx(1, Dynamic::I64(11));
1979 assert_eq!(array.get_idx(1).and_then(|value| value.as_int()), Some(11));
1980 }
1981
1982 #[test]
1983 fn f16_roundtrip_via_helpers() {
1984 let bits = f64_to_f16(1.0);
1985 assert_eq!(bits, 0x3C00);
1986 assert_eq!(f16_to_f64(bits), 1.0);
1987 let bits = f64_to_f16(0.5);
1988 assert_eq!(bits, 0x3800);
1989 assert_eq!(f16_to_f64(bits), 0.5);
1990 }
1991
1992 #[test]
1993 fn f16_dynamic_get_type_and_is_float() {
1994 let v = Dynamic::F16(0x3C00);
1995 assert_eq!(v.get_type(), Type::F16);
1996 assert!(v.is_f16());
1997 assert!(v.is_signed());
1998 assert_eq!(v.size_of(), 2);
1999 assert_eq!(v.as_float(), Some(1.0));
2000 }
2001
2002 #[test]
2003 fn f16_force_from_f64_preserves_value() {
2004 let d = Type::F16.force(Dynamic::F64(2.0)).unwrap();
2005 let Dynamic::F16(bits) = d else {
2006 panic!("expected F16");
2007 };
2008 assert_eq!(bits, 0x4000);
2009 assert_eq!(f16_to_f64(bits), 2.0);
2010 }
2011
2012 #[test]
2013 fn f16_compare_equal_by_bits() {
2014 assert_eq!(Dynamic::F16(0x3C00), Dynamic::F16(0x3C00));
2015 assert_ne!(Dynamic::F16(0x3C00), Dynamic::F16(0x4000));
2016 }
2017
2018 #[test]
2019 fn f16_subnormal_roundtrip() {
2020 let bits = f64_to_f16(5.96e-8);
2022 assert_eq!(bits, 0x0001);
2023 let back = f16_to_f64(bits);
2024 let expected = half::f16::from_bits(0x0001).to_f64();
2025 assert_eq!(back, expected, "got {back}");
2026 }
2027
2028 #[test]
2029 fn f16_infinity_roundtrip() {
2030 let bits = f64_to_f16(f64::INFINITY);
2031 assert_eq!(bits, 0x7C00);
2032 assert!(f16_to_f64(bits).is_infinite());
2033
2034 let bits = f64_to_f16(f64::NEG_INFINITY);
2035 assert_eq!(bits, 0xFC00);
2036 assert!(f16_to_f64(bits).is_sign_negative());
2037 }
2038
2039 #[test]
2040 fn fn_type_partial_eq_with_diff_ret_returns_false_not_panic() {
2041 use std::rc::Rc;
2042 let a = Type::Fn { tys: vec![Type::I32], ret: Rc::new(Type::I32) };
2043 let b = Type::Fn { tys: vec![Type::I32], ret: Rc::new(Type::F32) };
2044 assert!(a != b);
2045 assert!(!(a == b));
2046 }
2047
2048 #[test]
2049 fn fn_type_partial_eq_same_args_same_ret_is_true() {
2050 use std::rc::Rc;
2051 let a = Type::Fn { tys: vec![Type::I32], ret: Rc::new(Type::I32) };
2052 let b = Type::Fn { tys: vec![Type::I32], ret: Rc::new(Type::I32) };
2053 assert!(a == b);
2054 }
2055
2056 #[test]
2057 fn fn_type_partial_eq_diff_args_returns_false() {
2058 use std::rc::Rc;
2059 let a = Type::Fn { tys: vec![Type::I32], ret: Rc::new(Type::Void) };
2060 let b = Type::Fn { tys: vec![Type::I64], ret: Rc::new(Type::Void) };
2061 assert!(a != b);
2062 }
2063
2064 #[test]
2065 fn fn_type_partial_eq_with_any_ret_is_false() {
2066 use std::rc::Rc;
2067 let a = Type::Fn { tys: vec![Type::I32], ret: Rc::new(Type::Any) };
2068 let b = Type::Fn { tys: vec![Type::I32], ret: Rc::new(Type::I32) };
2069 assert!(a != b);
2070 }
2071}
2072
2073#[macro_export]
2074macro_rules! assert_ok {
2075 ( $x: expr, $ok: expr) => {
2076 if $x {
2077 return Ok($ok);
2078 }
2079 };
2080}
2081
2082#[macro_export]
2083macro_rules! assert_err {
2084 ( $x: expr, $err: expr) => {
2085 if $x {
2086 return Err($err);
2087 }
2088 };
2089}
2090
2091pub struct ZOnce {
2092 first: Option<&'static str>,
2093 other: &'static str,
2094}
2095
2096impl ZOnce {
2097 pub fn new(first: &'static str, other: &'static str) -> Self {
2098 Self { first: Some(first), other }
2099 }
2100 pub fn take(&mut self) -> &'static str {
2101 self.first.take().unwrap_or(self.other)
2102 }
2103}
2104
2105mod fixvec;
2106pub use fixvec::FixVec;
2107mod msgpack;
2108pub use msgpack::{MsgPack, MsgUnpack};
2109
2110pub use json::{FromJson, ToJson};
2111
2112mod yaml;
2113pub use yaml::{FromYaml, ToYaml};
2114
2115mod fault;
2116pub use fault::{has_fault, set_fault, take_fault};
2117mod ops;
2118mod types;
2119pub use types::{ConstIntOp, Type, call_fn, set_dynamic_return_handler};
2120
2121#[macro_export]
2122macro_rules! list {
2123 ($($v:expr),+ $(,)?) => {{
2124 let mut list = Vec::new();
2125 $( let _ = list.push(Dynamic::from($v)); )*
2126 Dynamic::List(::std::sync::Arc::new($crate::RwLock::new(list)))
2127 }};
2128}
2129
2130#[macro_export]
2131macro_rules! map {
2132 ($($k:expr => $v:expr), *) => {{
2133 let mut obj = std::collections::BTreeMap::new();
2134 $( let _ = obj.insert(smol_str::SmolStr::from($k), Dynamic::from($v)); )*
2135 Dynamic::map(obj)
2136 }};
2137}