1use crate::gc::GcContainer;
6use crate::value::*;
7use std::hash::{Hash, Hasher};
8
9pub(crate) trait Dispatcher {
11 fn typ(&self) -> ValueType;
12
13 fn array_with_size(
14 &self,
15 size: usize,
16 cap: usize,
17 val: &GosValue,
18 gcos: &GcContainer,
19 ) -> GosValue;
20
21 fn array_with_data(&self, data: Vec<GosValue>, gcc: &GcContainer) -> GosValue;
22
23 fn array_copy_semantic(&self, vdata: &ValueData, gcc: &GcContainer) -> ValueData;
24
25 fn slice_copy_semantic(&self, vdata: &ValueData) -> ValueData;
26
27 fn array_hash(&self, val: &GosValue, state: &mut dyn Hasher);
29
30 fn array_eq(&self, a: &ValueData, b: &ValueData) -> bool;
31
32 fn array_cmp(&self, a: &ValueData, b: &ValueData) -> std::cmp::Ordering;
33
34 fn array_get_vec(&self, val: &GosValue) -> Vec<GosValue>;
35
36 fn slice_get_vec(&self, val: &GosValue) -> Option<Vec<GosValue>>;
37
38 fn array_len(&self, val: &GosValue) -> usize;
39
40 fn slice_slice(
41 &self,
42 slice: &GosValue,
43 begin: isize,
44 end: isize,
45 max: isize,
46 ) -> RuntimeResult<GosValue>;
47
48 fn slice_array(&self, arr: GosValue, begin: isize, end: isize) -> RuntimeResult<GosValue>;
49
50 fn slice_append(
51 &self,
52 this: GosValue,
53 other: GosValue,
54 gcc: &GcContainer,
55 ) -> RuntimeResult<GosValue>;
56
57 fn slice_copy_from(&self, this: GosValue, other: GosValue) -> usize;
58
59 fn array_get(&self, from: &GosValue, i: usize) -> RuntimeResult<GosValue>;
60
61 fn array_set(&self, to: &GosValue, val: &GosValue, i: usize) -> RuntimeResult<()>;
62
63 fn slice_get(&self, from: &GosValue, i: usize) -> RuntimeResult<GosValue>;
64
65 fn slice_set(&self, to: &GosValue, val: &GosValue, i: usize) -> RuntimeResult<()>;
66
67 fn array_slice_iter(&self, val: &GosValue) -> RuntimeResult<SliceEnumIter<'static, AnyElem>>;
68
69 fn array_slice_next(
70 &self,
71 iter: &mut SliceEnumIter<'static, AnyElem>,
72 ) -> Option<(usize, GosValue)>;
73
74 fn slice_swap(&self, slice: &GosValue, i: usize, j: usize) -> RuntimeResult<()>;
75}
76
77pub(crate) trait DynHash {
79 fn dyn_hash(&self, state: &mut dyn Hasher);
80}
81
82impl<H: Hash + ?Sized> DynHash for H {
83 fn dyn_hash(&self, mut state: &mut dyn Hasher) {
84 self.hash(&mut state);
85 }
86}
87
88macro_rules! define_dispatcher {
89 ($dispatcher:tt, $elem:ty) => {
90 pub(crate) struct $dispatcher {
91 typ: ValueType,
92 }
93
94 impl $dispatcher {
95 pub(crate) fn new(t: ValueType) -> $dispatcher {
96 $dispatcher { typ: t }
97 }
98 }
99
100 impl Dispatcher for $dispatcher {
101 fn typ(&self) -> ValueType {
102 self.typ
103 }
104
105 fn array_with_size(
106 &self,
107 size: usize,
108 cap: usize,
109 val: &GosValue,
110 gcc: &GcContainer,
111 ) -> GosValue {
112 GosValue::new_array(
113 ArrayObj::<$elem>::with_size(size, cap, val, gcc),
114 self.typ,
115 gcc,
116 )
117 }
118
119 #[inline]
120 fn array_with_data(&self, data: Vec<GosValue>, gcc: &GcContainer) -> GosValue {
121 GosValue::new_array(ArrayObj::<$elem>::with_data(data), self.typ, gcc)
122 }
123
124 #[inline]
125 fn array_copy_semantic(&self, vdata: &ValueData, gcc: &GcContainer) -> ValueData {
126 ValueData::new_array::<$elem>(vdata.as_array::<$elem>().0.clone(), gcc)
127 }
128
129 #[inline]
130 fn slice_copy_semantic(&self, vdata: &ValueData) -> ValueData {
131 match vdata.as_slice::<$elem>() {
132 Some(s) => ValueData::new_slice(s.0.clone()),
133 None => ValueData::new_nil(ValueType::Slice),
134 }
135 }
136
137 #[inline]
138 fn array_hash(&self, val: &GosValue, state: &mut dyn Hasher) {
139 val.as_array::<$elem>().0.dyn_hash(state);
140 }
141
142 #[inline]
143 fn array_eq(&self, a: &ValueData, b: &ValueData) -> bool {
144 a.as_array::<$elem>().0 == b.as_array::<$elem>().0
145 }
146
147 #[inline]
148 fn array_cmp(&self, a: &ValueData, b: &ValueData) -> std::cmp::Ordering {
149 a.as_array::<$elem>().0.cmp(&b.as_array::<$elem>().0)
150 }
151
152 fn array_get_vec(&self, val: &GosValue) -> Vec<GosValue> {
153 val.as_array::<$elem>()
154 .0
155 .as_rust_slice()
156 .iter()
157 .map(|x| x.clone().into_value(val.t_elem()))
158 .collect()
159 }
160
161 fn slice_get_vec(&self, val: &GosValue) -> Option<Vec<GosValue>> {
162 val.as_slice::<$elem>().map(|x| {
163 x.0.as_rust_slice()
164 .iter()
165 .map(|y| y.clone().into_value(val.t_elem()))
166 .collect()
167 })
168 }
169
170 #[inline]
171 fn array_len(&self, val: &GosValue) -> usize {
172 val.as_array::<$elem>().0.len()
173 }
174
175 #[inline]
176 fn slice_slice(
177 &self,
178 slice: &GosValue,
179 begin: isize,
180 end: isize,
181 max: isize,
182 ) -> RuntimeResult<GosValue> {
183 Ok(GosValue::new_slice(
184 slice
185 .as_non_nil_slice::<$elem>()?
186 .0
187 .slice(begin, end, max)?,
188 slice.t_elem,
189 ))
190 }
191
192 #[inline]
193 fn slice_array(
194 &self,
195 arr: GosValue,
196 begin: isize,
197 end: isize,
198 ) -> RuntimeResult<GosValue> {
199 Ok(GosValue::new_slice::<$elem>(
200 SliceObj::with_array(arr, begin, end)?,
201 self.typ,
202 ))
203 }
204
205 #[inline]
206 fn slice_append(
207 &self,
208 this: GosValue,
209 other: GosValue,
210 gcc: &GcContainer,
211 ) -> RuntimeResult<GosValue> {
212 let a = this.as_slice::<$elem>();
213 let b = other.as_slice::<$elem>();
214 match b {
215 Some(y) => match a {
216 Some(x) => {
217 let mut to = x.0.clone();
218 to.append(&y.0);
219 Ok(GosValue::new_slice(to, other.t_elem()))
220 }
221 None => {
222 let data = y.0.as_rust_slice().to_vec();
223 let arr = ArrayObj::<$elem>::with_raw_data(data);
224 let slice = SliceObj::<$elem>::with_array(
225 GosValue::new_array(arr, other.t_elem(), gcc),
226 0,
227 -1,
228 )?;
229 Ok(GosValue::new_slice(slice, other.t_elem()))
230 }
231 },
232 None => Ok(this),
233 }
234 }
235
236 #[inline]
237 fn slice_copy_from(&self, this: GosValue, other: GosValue) -> usize {
238 let a = this.as_slice::<$elem>();
239 let b = other.as_slice::<$elem>();
240 match (a, b) {
241 (Some(x), Some(y)) => x.0.copy_from(&y.0),
242 _ => 0,
243 }
244 }
245
246 #[inline]
247 fn array_get(&self, from: &GosValue, i: usize) -> RuntimeResult<GosValue> {
248 from.as_array::<$elem>().0.get(i, self.typ)
249 }
250
251 #[inline]
252 fn array_set(&self, to: &GosValue, val: &GosValue, i: usize) -> RuntimeResult<()> {
253 to.as_array::<$elem>().0.set(i, val)
254 }
255
256 #[inline]
257 fn slice_get(&self, from: &GosValue, i: usize) -> RuntimeResult<GosValue> {
258 from.as_non_nil_slice::<$elem>()?.0.get(i, self.typ)
259 }
260
261 #[inline]
262 fn slice_set(&self, to: &GosValue, val: &GosValue, i: usize) -> RuntimeResult<()> {
263 to.as_non_nil_slice::<$elem>()?.0.set(i, val)
264 }
265
266 #[inline]
267 fn array_slice_iter(
268 &self,
269 val: &GosValue,
270 ) -> RuntimeResult<SliceEnumIter<'static, AnyElem>> {
271 let rust_slice = match val.typ() {
272 ValueType::Slice => val.as_non_nil_slice::<$elem>()?.0.as_rust_slice(),
273 ValueType::Array => val.as_array::<$elem>().0.as_rust_slice(),
274 _ => unreachable!(),
275 };
276 Ok(unsafe { std::mem::transmute(rust_slice.iter().enumerate()) })
277 }
278
279 #[inline]
280 fn array_slice_next(
281 &self,
282 iter: &mut SliceEnumIter<'static, AnyElem>,
283 ) -> Option<(usize, GosValue)> {
284 let iter: &mut SliceEnumIter<'static, $elem> = unsafe { std::mem::transmute(iter) };
285 match iter.next() {
286 Some((i, v)) => Some((i, v.clone().into_value(self.typ))),
287 None => None,
288 }
289 }
290
291 #[inline]
292 fn slice_swap(&self, slice: &GosValue, i: usize, j: usize) -> RuntimeResult<()> {
293 slice.as_non_nil_slice::<$elem>()?.0.swap(i, j)
294 }
295 }
296 };
297}
298
299#[derive(Clone, Copy)]
300pub(crate) enum ElemType {
301 ElemType8,
302 ElemType16,
303 ElemType32,
304 ElemType64,
305 ElemTypeWord,
306 ElemTypeGos,
307}
308
309pub(crate) struct ArrCaller {
310 disp_array: [Box<dyn Dispatcher>; ValueType::Channel as usize + 1],
311}
312
313impl ArrCaller {
314 pub fn new() -> ArrCaller {
315 ArrCaller {
316 disp_array: [
317 Box::new(DispatcherGos::new(ValueType::Void)),
318 Box::new(Dispatcher8::new(ValueType::Bool)),
319 Box::new(DispatcherWord::new(ValueType::Int)),
320 Box::new(Dispatcher8::new(ValueType::Int8)),
321 Box::new(Dispatcher16::new(ValueType::Int16)),
322 Box::new(Dispatcher32::new(ValueType::Int32)),
323 Box::new(Dispatcher64::new(ValueType::Int64)),
324 Box::new(DispatcherWord::new(ValueType::Uint)),
325 Box::new(DispatcherWord::new(ValueType::UintPtr)),
326 Box::new(Dispatcher8::new(ValueType::Uint8)),
327 Box::new(Dispatcher16::new(ValueType::Uint16)),
328 Box::new(Dispatcher32::new(ValueType::Uint32)),
329 Box::new(Dispatcher64::new(ValueType::Uint64)),
330 Box::new(Dispatcher32::new(ValueType::Float32)),
331 Box::new(Dispatcher64::new(ValueType::Float64)),
332 Box::new(Dispatcher64::new(ValueType::Complex64)),
333 Box::new(DispatcherWord::new(ValueType::Function)),
334 Box::new(DispatcherWord::new(ValueType::Package)),
335 Box::new(DispatcherGos::new(ValueType::Metadata)),
336 Box::new(DispatcherGos::new(ValueType::Complex128)),
337 Box::new(DispatcherGos::new(ValueType::String)),
338 Box::new(DispatcherGos::new(ValueType::Array)),
339 Box::new(DispatcherGos::new(ValueType::Struct)),
340 Box::new(DispatcherGos::new(ValueType::Pointer)),
341 Box::new(DispatcherGos::new(ValueType::UnsafePtr)),
342 Box::new(DispatcherGos::new(ValueType::Closure)),
343 Box::new(DispatcherGos::new(ValueType::Slice)),
344 Box::new(DispatcherGos::new(ValueType::Map)),
345 Box::new(DispatcherGos::new(ValueType::Interface)),
346 Box::new(DispatcherGos::new(ValueType::Channel)),
347 ],
348 }
349 }
350
351 #[inline]
352 pub fn get(&self, t: ValueType) -> &Box<dyn Dispatcher> {
353 &self.disp_array[t as usize]
354 }
355
356 #[inline]
357 pub fn get_slow(t: ValueType) -> Box<dyn Dispatcher> {
358 match t {
359 ValueType::Int8 | ValueType::Uint8 => Box::new(Dispatcher8::new(t)),
360 ValueType::Int16 | ValueType::Uint16 => Box::new(Dispatcher16::new(t)),
361 ValueType::Int32 | ValueType::Uint32 | ValueType::Float32 => {
362 Box::new(Dispatcher32::new(t))
363 }
364 ValueType::Int64 | ValueType::Uint64 | ValueType::Float64 | ValueType::Complex64 => {
365 Box::new(Dispatcher64::new(t))
366 }
367 ValueType::Int
368 | ValueType::Uint
369 | ValueType::UintPtr
370 | ValueType::Function
371 | ValueType::Package => Box::new(Dispatcher64::new(t)),
372 _ => Box::new(DispatcherGos::new(t)),
373 }
374 }
375
376 #[inline]
377 pub fn get_elem_type(t: ValueType) -> ElemType {
378 const ELEM_TYPES: [ElemType; ValueType::Channel as usize + 1] = [
379 ElemType::ElemTypeGos,
380 ElemType::ElemType8,
381 ElemType::ElemTypeWord,
382 ElemType::ElemType8,
383 ElemType::ElemType16,
384 ElemType::ElemType32,
385 ElemType::ElemType64,
386 ElemType::ElemTypeWord,
387 ElemType::ElemTypeWord,
388 ElemType::ElemType8,
389 ElemType::ElemType16,
390 ElemType::ElemType32,
391 ElemType::ElemType64,
392 ElemType::ElemType32,
393 ElemType::ElemType64,
394 ElemType::ElemType64,
395 ElemType::ElemTypeWord,
396 ElemType::ElemTypeWord,
397 ElemType::ElemTypeGos,
398 ElemType::ElemTypeGos,
399 ElemType::ElemTypeGos,
400 ElemType::ElemTypeGos,
401 ElemType::ElemTypeGos,
402 ElemType::ElemTypeGos,
403 ElemType::ElemTypeGos,
404 ElemType::ElemTypeGos,
405 ElemType::ElemTypeGos,
406 ElemType::ElemTypeGos,
407 ElemType::ElemTypeGos,
408 ElemType::ElemTypeGos,
409 ];
410 ELEM_TYPES[t as usize]
411 }
412
413 }