1use core::borrow::Borrow;
2use core::hash::Hash;
3use core::ops::Deref;
4
5use crate::alloc::{Box, Vec};
6use crate::sync::Arc;
7
8use super::{FromValue, Repr, Rtti, RttiKind, RuntimeError, Tuple, TypeInfo, Value};
9
10pub struct DynamicEmpty {
12 rtti: Arc<Rtti>,
13}
14
15impl FromValue for DynamicEmpty {
16 #[inline]
17 fn from_value(value: Value) -> Result<Self, RuntimeError> {
18 match value.take_repr() {
19 Repr::Dynamic(value) if matches!(value.rtti().kind, RttiKind::Empty) => Ok(Self {
20 rtti: value.rtti().clone(),
21 }),
22 value => Err(RuntimeError::expected_empty(value.type_info())),
23 }
24 }
25}
26
27impl DynamicEmpty {
28 #[inline]
30 pub fn type_info(&self) -> TypeInfo {
31 Rtti::type_info(self.rtti.clone())
32 }
33}
34
35pub struct DynamicTuple {
40 rtti: Arc<Rtti>,
41 values: Vec<Value>,
42}
43
44impl FromValue for DynamicTuple {
45 #[inline]
46 fn from_value(value: Value) -> Result<Self, RuntimeError> {
47 match value.take_repr() {
48 Repr::Dynamic(value) if matches!(value.rtti().kind, RttiKind::Tuple) => {
49 let mut values = Vec::try_with_capacity(value.len())?;
50
51 for value in value.borrow_ref()?.iter() {
52 values.try_push(value.clone())?;
53 }
54
55 Ok(Self {
56 rtti: value.rtti().clone(),
57 values,
58 })
59 }
60 value => Err(RuntimeError::expected_tuple(value.type_info())),
61 }
62 }
63}
64
65impl DynamicTuple {
66 #[inline]
68 pub fn type_info(&self) -> TypeInfo {
69 Rtti::type_info(self.rtti.clone())
70 }
71}
72
73impl Deref for DynamicTuple {
74 type Target = Tuple;
75
76 #[inline]
77 fn deref(&self) -> &Self::Target {
78 Tuple::new(&self.values)
79 }
80}
81
82pub struct DynamicStruct {
84 rtti: Arc<Rtti>,
85 values: Vec<Value>,
86}
87
88impl FromValue for DynamicStruct {
89 #[inline]
90 fn from_value(value: Value) -> Result<Self, RuntimeError> {
91 match value.take_repr() {
92 Repr::Dynamic(value) if matches!(value.rtti().kind, RttiKind::Struct) => {
93 let mut values = Vec::try_with_capacity(value.len())?;
94
95 for value in value.borrow_ref()?.iter() {
96 values.try_push(value.clone())?;
97 }
98
99 Ok(Self {
100 rtti: value.rtti().clone(),
101 values,
102 })
103 }
104 value => Err(RuntimeError::expected_struct(value.type_info())),
105 }
106 }
107}
108
109impl DynamicStruct {
110 #[inline]
112 pub fn get<Q>(&self, key: &Q) -> Option<&Value>
113 where
114 Box<str>: Borrow<Q>,
115 Q: Hash + Eq + ?Sized,
116 {
117 let index = *self.rtti.fields.get(key)?;
118 self.values.get(index)
119 }
120
121 #[inline]
123 pub fn type_info(&self) -> TypeInfo {
124 Rtti::type_info(self.rtti.clone())
125 }
126}