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