go_vm/
metadata.rs

1// Copyright 2022 The Goscript Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5use crate::bytecode::{FunctionKey, MetadataKey, MetadataObjs, VMObjects};
6use crate::gc::GcContainer;
7use crate::instruction::{OpIndex, ValueType};
8use crate::objects::{IfaceBinding, StructObj};
9use crate::value::ArrCaller;
10use crate::value::GosValue;
11#[cfg(feature = "serde_borsh")]
12use borsh::{
13    maybestd::io::Result as BorshResult, maybestd::io::Write as BorshWrite, BorshDeserialize,
14    BorshSerialize,
15};
16use go_parser::Map;
17use std::cell::RefCell;
18use std::rc::Rc;
19
20#[cfg_attr(feature = "serde_borsh", derive(BorshDeserialize, BorshSerialize))]
21#[derive(PartialEq, Eq, Clone, Debug)]
22pub enum ChannelType {
23    Send,
24    Recv,
25    SendRecv,
26}
27
28#[derive(Debug)]
29pub struct PrimitiveMeta {
30    pub mbool: Meta,
31    pub mint: Meta,
32    pub mint8: Meta,
33    pub mint16: Meta,
34    pub mint32: Meta,
35    pub mint64: Meta,
36    pub muint: Meta,
37    pub muint_ptr: Meta,
38    pub muint8: Meta,
39    pub muint16: Meta,
40    pub muint32: Meta,
41    pub muint64: Meta,
42    pub mfloat32: Meta,
43    pub mfloat64: Meta,
44    pub mcomplex64: Meta,
45    pub mcomplex128: Meta,
46    pub mstr: Meta,
47    pub unsafe_ptr: Meta,
48    pub default_sig: Meta,
49    pub empty_iface: Meta,
50    pub none: Meta,
51}
52
53impl PrimitiveMeta {
54    pub fn new(objs: &mut MetadataObjs) -> PrimitiveMeta {
55        PrimitiveMeta {
56            mbool: Meta::with_type(MetadataType::Bool, objs),
57            mint: Meta::with_type(MetadataType::Int, objs),
58            mint8: Meta::with_type(MetadataType::Int8, objs),
59            mint16: Meta::with_type(MetadataType::Int16, objs),
60            mint32: Meta::with_type(MetadataType::Int32, objs),
61            mint64: Meta::with_type(MetadataType::Int64, objs),
62            muint: Meta::with_type(MetadataType::Uint, objs),
63            muint_ptr: Meta::with_type(MetadataType::UintPtr, objs),
64            muint8: Meta::with_type(MetadataType::Uint8, objs),
65            muint16: Meta::with_type(MetadataType::Uint16, objs),
66            muint32: Meta::with_type(MetadataType::Uint32, objs),
67            muint64: Meta::with_type(MetadataType::Uint64, objs),
68            mfloat32: Meta::with_type(MetadataType::Float32, objs),
69            mfloat64: Meta::with_type(MetadataType::Float64, objs),
70            mcomplex64: Meta::with_type(MetadataType::Complex64, objs),
71            mcomplex128: Meta::with_type(MetadataType::Complex128, objs),
72            mstr: Meta::with_type(MetadataType::Str, objs),
73            unsafe_ptr: Meta::with_type(MetadataType::UnsafePtr, objs),
74            default_sig: Meta::with_type(MetadataType::Signature(SigMetadata::default()), objs),
75            empty_iface: Meta::with_type(MetadataType::Interface(Fields::new(vec![])), objs),
76            none: Meta::with_type(MetadataType::None, objs),
77        }
78    }
79}
80
81#[cfg_attr(feature = "serde_borsh", derive(BorshDeserialize, BorshSerialize))]
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
83pub struct Meta {
84    pub key: MetadataKey,
85    pub ptr_depth: u8,
86    pub is_type: bool,
87}
88
89impl Meta {
90    #[inline]
91    pub fn new(key: MetadataKey, pdepth: u8, is_type: bool) -> Meta {
92        Meta {
93            key: key,
94            ptr_depth: pdepth,
95            is_type: is_type,
96        }
97    }
98
99    #[inline]
100    pub fn with_type(v: MetadataType, metas: &mut MetadataObjs) -> Meta {
101        Meta::new(metas.insert(v), 0, false)
102    }
103
104    #[inline]
105    pub fn new_array(elem_meta: Meta, size: usize, metas: &mut MetadataObjs) -> Meta {
106        let t = MetadataType::Array(elem_meta, size);
107        Meta {
108            key: metas.insert(t),
109            ptr_depth: 0,
110            is_type: false,
111        }
112    }
113
114    #[inline]
115    pub fn new_slice(val_meta: Meta, metas: &mut MetadataObjs) -> Meta {
116        Meta::with_type(MetadataType::Slice(val_meta), metas)
117    }
118
119    #[inline]
120    pub fn new_map(kmeta: Meta, vmeta: Meta, metas: &mut MetadataObjs) -> Meta {
121        Meta::with_type(MetadataType::Map(kmeta, vmeta), metas)
122    }
123
124    #[inline]
125    pub fn new_interface(fields: Fields, metas: &mut MetadataObjs) -> Meta {
126        Meta::with_type(MetadataType::Interface(fields), metas)
127    }
128
129    #[inline]
130    pub fn new_channel(typ: ChannelType, val_meta: Meta, metas: &mut MetadataObjs) -> Meta {
131        Meta::with_type(MetadataType::Channel(typ, val_meta), metas)
132    }
133
134    #[inline]
135    pub(crate) fn new_struct(f: Fields, objs: &mut VMObjects) -> Meta {
136        let key = objs.metas.insert(MetadataType::Struct(f));
137        Meta::new(key, 0, false)
138    }
139
140    pub fn new_sig(
141        recv: Option<Meta>,
142        params: Vec<Meta>,
143        results: Vec<Meta>,
144        variadic: Option<(Meta, Meta)>,
145        metas: &mut MetadataObjs,
146    ) -> Meta {
147        let params_type = params.iter().map(|x| x.value_type(metas)).collect();
148        let t = MetadataType::Signature(SigMetadata {
149            recv,
150            params,
151            results,
152            variadic,
153            params_type,
154        });
155        Meta::with_type(t, metas)
156    }
157
158    pub fn new_named(underlying: Meta, metas: &mut MetadataObjs) -> Meta {
159        //debug_assert!(underlying.value_type(metas) != ValueType::Named);
160        Meta::with_type(MetadataType::Named(Methods::new(), underlying), metas)
161    }
162
163    #[inline]
164    pub fn mtype_unwraped<'a>(&self, metas: &'a MetadataObjs) -> &'a MetadataType {
165        metas[self.key].unwrap_named(metas)
166    }
167
168    #[inline]
169    pub fn ptr_to(&self) -> Meta {
170        let mut m = *self;
171        m.ptr_depth += 1;
172        m
173    }
174
175    #[inline]
176    pub fn unptr_to(&self) -> Meta {
177        assert!(self.ptr_depth > 0);
178        let mut m = *self;
179        m.ptr_depth -= 1;
180        m
181    }
182
183    #[inline]
184    pub fn into_type_category(mut self) -> Meta {
185        self.is_type = true;
186        self
187    }
188
189    #[inline]
190    pub fn into_value_category(mut self) -> Meta {
191        self.is_type = false;
192        self
193    }
194
195    #[inline]
196    pub fn value_type(&self, metas: &MetadataObjs) -> ValueType {
197        match self.is_type {
198            false => match self.ptr_depth {
199                0 => match &metas[self.key] {
200                    MetadataType::Bool => ValueType::Bool,
201                    MetadataType::Int => ValueType::Int,
202                    MetadataType::Int8 => ValueType::Int8,
203                    MetadataType::Int16 => ValueType::Int16,
204                    MetadataType::Int32 => ValueType::Int32,
205                    MetadataType::Int64 => ValueType::Int64,
206                    MetadataType::Uint => ValueType::Uint,
207                    MetadataType::UintPtr => ValueType::UintPtr,
208                    MetadataType::Uint8 => ValueType::Uint8,
209                    MetadataType::Uint16 => ValueType::Uint16,
210                    MetadataType::Uint32 => ValueType::Uint32,
211                    MetadataType::Uint64 => ValueType::Uint64,
212                    MetadataType::Float32 => ValueType::Float32,
213                    MetadataType::Float64 => ValueType::Float64,
214                    MetadataType::Complex64 => ValueType::Complex64,
215                    MetadataType::Complex128 => ValueType::Complex128,
216                    MetadataType::UnsafePtr => ValueType::UnsafePtr,
217                    MetadataType::Str => ValueType::String,
218                    MetadataType::Struct(_) => ValueType::Struct,
219                    MetadataType::Signature(_) => ValueType::Closure,
220                    MetadataType::Array(_, _) => ValueType::Array,
221                    MetadataType::Slice(_) => ValueType::Slice,
222                    MetadataType::Map(_, _) => ValueType::Map,
223                    MetadataType::Interface(_) => ValueType::Interface,
224                    MetadataType::Channel(_, _) => ValueType::Channel,
225                    MetadataType::Named(_, m) => m.value_type(metas),
226                    MetadataType::None => ValueType::Void,
227                },
228                _ => ValueType::Pointer,
229            },
230            true => ValueType::Metadata,
231        }
232    }
233
234    #[inline]
235    pub(crate) fn zero(&self, mobjs: &MetadataObjs, gcc: &GcContainer) -> GosValue {
236        match self.ptr_depth {
237            0 => match &mobjs[self.key] {
238                MetadataType::Bool => false.into(),
239                MetadataType::Int => 0isize.into(),
240                MetadataType::Int8 => 0i8.into(),
241                MetadataType::Int16 => 0i16.into(),
242                MetadataType::Int32 => 0i32.into(),
243                MetadataType::Int64 => 0i64.into(),
244                MetadataType::Uint => 0isize.into(),
245                MetadataType::UintPtr => GosValue::new_uint_ptr(0),
246                MetadataType::Uint8 => 0u8.into(),
247                MetadataType::Uint16 => 0u16.into(),
248                MetadataType::Uint32 => 0u32.into(),
249                MetadataType::Uint64 => 0u64.into(),
250                MetadataType::Float32 => GosValue::new_float32(0.0.into()),
251                MetadataType::Float64 => GosValue::new_float64(0.0.into()),
252                MetadataType::Complex64 => GosValue::new_complex64(0.0.into(), 0.0.into()),
253                MetadataType::Complex128 => GosValue::new_complex128(0.0.into(), 0.0.into()),
254                MetadataType::UnsafePtr => GosValue::new_nil(ValueType::UnsafePtr),
255                MetadataType::Str => GosValue::with_str(""),
256                MetadataType::Array(m, size) => {
257                    let val = m.zero(mobjs, gcc);
258                    let t = m.value_type(mobjs);
259                    let caller = ArrCaller::get_slow(t);
260                    GosValue::array_with_size(*size, *size, &val, &caller, gcc)
261                }
262                MetadataType::Slice(m) => GosValue::new_nil_slice(m.value_type(mobjs)),
263                MetadataType::Struct(f) => {
264                    let field_zeros: Vec<GosValue> =
265                        f.fields.iter().map(|x| x.meta.zero(mobjs, gcc)).collect();
266                    let struct_val = StructObj::new(field_zeros);
267                    GosValue::new_struct(struct_val, gcc)
268                }
269                MetadataType::Signature(_) => GosValue::new_nil(ValueType::Closure),
270                MetadataType::Map(_, _) => GosValue::new_nil(ValueType::Map),
271                MetadataType::Interface(_) => GosValue::new_nil(ValueType::Interface),
272                MetadataType::Channel(_, _) => GosValue::new_nil(ValueType::Channel),
273                MetadataType::Named(_, gm) => gm.zero(mobjs, gcc),
274                MetadataType::None => unreachable!(),
275            },
276            _ => GosValue::new_nil(ValueType::Pointer),
277        }
278    }
279
280    #[inline]
281    pub fn field_indices(&self, name: &str, metas: &MetadataObjs) -> Vec<usize> {
282        let key = self.recv_meta_key();
283        match &metas[Meta::new(key, 0, false).underlying(metas).key] {
284            MetadataType::Struct(m) => m.indices_by_name(name),
285            _ => unreachable!(),
286        }
287    }
288
289    #[inline]
290    pub fn underlying(&self, metas: &MetadataObjs) -> Meta {
291        match &metas[self.key] {
292            MetadataType::Named(_, u) => *u,
293            _ => *self,
294        }
295    }
296
297    #[inline]
298    pub fn recv_meta_key(&self) -> MetadataKey {
299        assert!(self.ptr_depth <= 1);
300        self.key
301    }
302
303    pub fn add_method(&self, name: String, pointer_recv: bool, metas: &mut MetadataObjs) {
304        let k = self.recv_meta_key();
305        match &mut metas[k] {
306            MetadataType::Named(m, _) => {
307                m.members.push(Rc::new(RefCell::new(MethodDesc {
308                    pointer_recv: pointer_recv,
309                    func: None,
310                })));
311                m.mapping.insert(name, m.members.len() as OpIndex - 1);
312            }
313            _ => unreachable!(),
314        }
315    }
316
317    pub fn set_method_code(&self, name: &String, func: FunctionKey, metas: &mut MetadataObjs) {
318        let k = self.recv_meta_key();
319        match &mut metas[k] {
320            MetadataType::Named(m, _) => {
321                let index = m.mapping[name] as usize;
322                m.members[index].borrow_mut().func = Some(func);
323            }
324            _ => unreachable!(),
325        }
326    }
327
328    /// Depth-first search for method by name
329    fn get_iface_binding(&self, name: &String, metas: &MetadataObjs) -> Option<IfaceBinding> {
330        match &metas[self.key] {
331            MetadataType::Named(m, underlying) => match m.mapping.get(name) {
332                Some(&i) => Some(IfaceBinding::Struct(m.members[i as usize].clone(), None)),
333                None => underlying.get_iface_binding(name, metas),
334            },
335            MetadataType::Interface(fields) => fields
336                .try_index_by_name(name)
337                .map(|x| IfaceBinding::Iface(x, None)),
338            MetadataType::Struct(fields) => {
339                for (i, f) in fields.fields.iter().enumerate() {
340                    if let Some(mut re) = f.meta.get_iface_binding(name, metas) {
341                        let indices = match &mut re {
342                            IfaceBinding::Struct(_, indices) | IfaceBinding::Iface(_, indices) => {
343                                indices
344                            }
345                        };
346                        if let Some(x) = indices {
347                            x.push(i as OpIndex)
348                        } else {
349                            *indices = Some(vec![i as OpIndex]);
350                        }
351                        return Some(re);
352                    }
353                }
354                None
355            }
356            _ => None,
357        }
358    }
359
360    #[inline]
361    pub fn get_method(&self, index: OpIndex, metas: &MetadataObjs) -> Rc<RefCell<MethodDesc>> {
362        let k = self.recv_meta_key();
363        let m = match &metas[k] {
364            MetadataType::Named(methods, _) => methods,
365            _ => unreachable!(),
366        };
367        m.members[index as usize].clone()
368    }
369
370    pub fn identical(&self, other: &Self, metas: &MetadataObjs) -> bool {
371        (self.key == other.key) || metas[self.key].identical(&metas[other.key], metas)
372    }
373
374    pub fn bind_with_iface(
375        &self,
376        value_meta: Self,
377        metas: &MetadataObjs,
378    ) -> (Meta, Vec<IfaceBinding>) {
379        let fields: Vec<&String> = match &metas[self.underlying(metas).key] {
380            MetadataType::Interface(m) => m.infos().iter().map(|x| &x.name).collect(),
381            _ => unreachable!(),
382        };
383        (
384            value_meta,
385            fields
386                .iter()
387                .map(|x| value_meta.get_iface_binding(x, metas).unwrap())
388                .collect(),
389        )
390    }
391}
392
393#[cfg_attr(feature = "serde_borsh", derive(BorshDeserialize, BorshSerialize))]
394#[derive(Debug, Clone)]
395pub struct FieldInfo {
396    pub meta: Meta,
397    pub name: String,
398    pub tag: Option<String>,
399    //pub exported: bool,
400    pub embedded_indices: Option<Vec<usize>>,
401}
402
403impl FieldInfo {
404    pub fn exported(&self) -> bool {
405        self.name.chars().next().unwrap().is_uppercase()
406    }
407
408    pub fn lookup_tag(&self, key: &str) -> Option<String> {
409        if self.tag.is_none() {
410            return None;
411        }
412
413        let mut tag: &str = self.tag.as_ref().unwrap();
414        while !tag.is_empty() {
415            // Skip leading space.
416            let i = tag.find(|c: char| c != ' ').unwrap_or(tag.len());
417            tag = &tag[i..];
418            if tag.is_empty() {
419                break;
420            }
421
422            // Scan to colon. A space, a quote or a control character is a syntax error.
423            let i = tag
424                .find(|c: char| c <= ' ' || c == ':' || c == '"' || c as u32 == 0x7f)
425                .unwrap_or(tag.len());
426
427            if i == 0 || i + 1 >= tag.len() || &tag[i..i + 1] != ":" || &tag[i + 1..i + 2] != "\"" {
428                break;
429            }
430
431            let name = &tag[..i];
432            tag = &tag[i + 1..];
433
434            // Scan quoted string to find value.
435            let mut i = 1;
436            while i < tag.len() && &tag[i..i + 1] != "\"" {
437                if &tag[i..i + 1] == "\\" {
438                    i += 1;
439                }
440                i += 1;
441            }
442
443            if i >= tag.len() {
444                break;
445            }
446
447            let qvalue = &tag[..i + 1];
448            tag = &tag[i + 1..];
449
450            if key == name {
451                let value = str::replace(qvalue, "\\\"", "\"")
452                    .trim_matches('"')
453                    .to_string();
454                return Some(value);
455            }
456        }
457        None
458    }
459}
460
461#[cfg_attr(feature = "serde_borsh", derive(BorshDeserialize, BorshSerialize))]
462#[derive(Debug, Clone)]
463pub struct Fields {
464    fields: Vec<FieldInfo>,
465}
466
467impl Fields {
468    #[inline]
469    pub fn new(fields: Vec<FieldInfo>) -> Fields {
470        Fields { fields }
471    }
472
473    #[inline]
474    pub fn infos(&self) -> &[FieldInfo] {
475        self.fields.as_ref()
476    }
477
478    #[inline]
479    pub fn get<'a, 'b: 'a>(&'a self, indices: &[usize], metas: &'b MetadataObjs) -> &'a FieldInfo {
480        debug_assert!(indices.len() > 0);
481        if indices.len() == 1 {
482            self.get_non_embedded(indices[0])
483        } else {
484            metas[self.fields[indices[0] as usize].meta.key]
485                .unwrap_named(metas)
486                .as_struct()
487                .get(&indices[1..], metas)
488        }
489    }
490
491    #[inline]
492    pub fn get_non_embedded(&self, index: usize) -> &FieldInfo {
493        &self.fields[index]
494    }
495
496    #[inline]
497    pub fn try_index_by_name(&self, name: &str) -> Option<usize> {
498        for (i, f) in self.fields.iter().enumerate() {
499            if f.name == name {
500                return Some(i);
501            }
502        }
503        None
504    }
505
506    #[inline]
507    pub fn index_by_name(&self, name: &str) -> usize {
508        self.try_index_by_name(name).unwrap()
509    }
510
511    #[inline]
512    pub fn indices_by_name(&self, name: &str) -> Vec<usize> {
513        let index = self.index_by_name(name);
514        match &self.fields[index].embedded_indices {
515            Some(indices) => indices.clone(),
516            None => vec![index],
517        }
518    }
519
520    #[inline]
521    pub fn identical(&self, other: &Self, metas: &MetadataObjs) -> bool {
522        if self.fields.len() != other.fields.len() {
523            return false;
524        }
525        for (i, f) in self.fields.iter().enumerate() {
526            let other_f = &other.fields[i];
527            let ok = f.name == other_f.name
528                && f.embedded_indices == other_f.embedded_indices
529                && f.meta.identical(&other_f.meta, metas);
530            if !ok {
531                return false;
532            }
533        }
534        true
535    }
536}
537
538#[cfg_attr(feature = "serde_borsh", derive(BorshDeserialize, BorshSerialize))]
539#[derive(Debug, Clone, Copy)]
540pub struct MethodDesc {
541    pub pointer_recv: bool,
542    pub func: Option<FunctionKey>,
543}
544
545#[derive(Debug, Clone)]
546pub struct Methods {
547    pub members: Vec<Rc<RefCell<MethodDesc>>>,
548    pub mapping: Map<String, OpIndex>,
549}
550
551impl Methods {
552    pub fn new() -> Methods {
553        Methods {
554            members: vec![],
555            mapping: Map::new(),
556        }
557    }
558}
559
560#[cfg(feature = "serde_borsh")]
561impl BorshSerialize for Methods {
562    fn serialize<W: BorshWrite>(&self, writer: &mut W) -> BorshResult<()> {
563        let methods: Vec<MethodDesc> = self.members.iter().map(|x| *x.borrow()).collect();
564        methods.serialize(writer)?;
565        self.mapping.serialize(writer)
566    }
567}
568
569#[cfg(feature = "serde_borsh")]
570impl BorshDeserialize for Methods {
571    fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> BorshResult<Self> {
572        let methods = Vec::<MethodDesc>::deserialize_reader(reader)?;
573        let members = methods
574            .into_iter()
575            .map(|x| Rc::new(RefCell::new(x)))
576            .collect();
577        let mapping = Map::<String, OpIndex>::deserialize_reader(reader)?;
578        Ok(Methods { members, mapping })
579    }
580}
581
582#[cfg_attr(feature = "serde_borsh", derive(BorshDeserialize, BorshSerialize))]
583#[derive(Debug, Clone)]
584pub struct SigMetadata {
585    pub recv: Option<Meta>,
586    pub params: Vec<Meta>,
587    pub results: Vec<Meta>,
588    pub variadic: Option<(Meta, Meta)>,
589    pub params_type: Vec<ValueType>, // for calling FFI
590}
591
592impl Default for SigMetadata {
593    fn default() -> SigMetadata {
594        Self {
595            recv: None,
596            params: vec![],
597            results: vec![],
598            variadic: None,
599            params_type: vec![],
600        }
601    }
602}
603
604impl SigMetadata {
605    pub fn pointer_recv(&self) -> bool {
606        match &self.recv {
607            Some(r) => r.ptr_depth > 0,
608            None => false,
609        }
610    }
611
612    pub fn identical(&self, other: &Self, metas: &MetadataObjs) -> bool {
613        if !match (&self.recv, &other.recv) {
614            (None, None) => true,
615            (Some(a), Some(b)) => a.identical(b, metas),
616            _ => false,
617        } {
618            return false;
619        }
620        if self.params.len() != other.params.len() {
621            return false;
622        }
623        for (i, p) in self.params.iter().enumerate() {
624            if !p.identical(&other.params[i], metas) {
625                return false;
626            }
627        }
628        if self.results.len() != other.results.len() {
629            return false;
630        }
631        for (i, r) in self.results.iter().enumerate() {
632            if !r.identical(&other.results[i], metas) {
633                return false;
634            }
635        }
636        if !match (&self.variadic, &other.variadic) {
637            (None, None) => true,
638            (Some((a, _)), Some((b, _))) => a.identical(b, metas),
639            _ => false,
640        } {
641            return false;
642        }
643        true
644    }
645}
646
647#[cfg_attr(feature = "serde_borsh", derive(BorshDeserialize, BorshSerialize))]
648#[derive(Debug, Clone)]
649pub enum MetadataType {
650    Bool,
651    Int,
652    Int8,
653    Int16,
654    Int32,
655    Int64,
656    Uint,
657    UintPtr,
658    Uint8,
659    Uint16,
660    Uint32,
661    Uint64,
662    Float32,
663    Float64,
664    Complex64,
665    Complex128,
666    UnsafePtr,
667    Str,
668    Array(Meta, usize),
669    Slice(Meta),
670    Struct(Fields),
671    Signature(SigMetadata),
672    Map(Meta, Meta),
673    Interface(Fields),
674    Channel(ChannelType, Meta),
675    Named(Methods, Meta),
676    None,
677}
678
679impl MetadataType {
680    #[inline]
681    pub fn as_signature(&self) -> &SigMetadata {
682        match self {
683            Self::Signature(s) => s,
684            _ => unreachable!(),
685        }
686    }
687
688    #[inline]
689    pub fn as_interface(&self) -> &Fields {
690        match self {
691            Self::Interface(fields) => fields,
692            _ => unreachable!(),
693        }
694    }
695
696    #[inline]
697    pub fn as_channel(&self) -> (&ChannelType, &Meta) {
698        match self {
699            Self::Channel(t, m) => (t, m),
700            _ => unreachable!(),
701        }
702    }
703
704    #[inline]
705    pub fn as_array(&self) -> (&Meta, &usize) {
706        match self {
707            Self::Array(m, s) => (m, s),
708            _ => unreachable!(),
709        }
710    }
711
712    #[inline]
713    pub fn as_slice(&self) -> &Meta {
714        match self {
715            Self::Slice(m) => m,
716            _ => unreachable!(),
717        }
718    }
719
720    #[inline]
721    pub fn as_map(&self) -> (&Meta, &Meta) {
722        match self {
723            Self::Map(k, v) => (k, v),
724            _ => unreachable!(),
725        }
726    }
727
728    #[inline]
729    pub fn as_struct(&self) -> &Fields {
730        match self {
731            Self::Struct(f) => f,
732            _ => unreachable!(),
733        }
734    }
735
736    #[inline]
737    pub fn as_named(&self) -> (&Methods, &Meta) {
738        match self {
739            Self::Named(meth, meta) => (meth, meta),
740            _ => unreachable!(),
741        }
742    }
743
744    #[inline]
745    pub fn as_named_mut(&mut self) -> (&mut Methods, &mut Meta) {
746        match self {
747            Self::Named(meth, meta) => (meth, meta),
748            _ => unreachable!(),
749        }
750    }
751
752    #[inline]
753    pub fn unwrap_named<'a, 'b: 'a>(&'a self, metas: &'b MetadataObjs) -> &'a Self {
754        match self {
755            Self::Named(_, meta) => &metas[meta.key],
756            _ => self,
757        }
758    }
759
760    pub fn identical(&self, other: &Self, metas: &MetadataObjs) -> bool {
761        match (self, other) {
762            (Self::Bool, Self::Bool) => true,
763            (Self::Int, Self::Int) => true,
764            (Self::Int8, Self::Int8) => true,
765            (Self::Int16, Self::Int16) => true,
766            (Self::Int32, Self::Int32) => true,
767            (Self::Int64, Self::Int64) => true,
768            (Self::Uint8, Self::Uint8) => true,
769            (Self::Uint16, Self::Uint16) => true,
770            (Self::Uint32, Self::Uint32) => true,
771            (Self::Uint64, Self::Uint64) => true,
772            (Self::Float32, Self::Float32) => true,
773            (Self::Float64, Self::Float64) => true,
774            (Self::Complex64, Self::Complex64) => true,
775            (Self::Complex128, Self::Complex128) => true,
776            (Self::Str, Self::Str) => true,
777            (Self::Struct(a), Self::Struct(b)) => a.identical(b, metas),
778            (Self::Signature(a), Self::Signature(b)) => a.identical(b, metas),
779            (Self::Array(a, size_a), Self::Array(b, size_b)) => {
780                size_a == size_b && a.identical(b, metas)
781            }
782            (Self::Slice(a), Self::Slice(b)) => a.identical(b, metas),
783            (Self::Map(ak, av), Self::Map(bk, bv)) => {
784                ak.identical(bk, metas) && av.identical(bv, metas)
785            }
786            (Self::Interface(a), Self::Interface(b)) => a.identical(b, metas),
787            (Self::Channel(at, avt), Self::Channel(bt, bvt)) => {
788                at == bt && avt.identical(bvt, metas)
789            }
790            (Self::Named(_, a), Self::Named(_, b)) => a.identical(b, metas),
791            _ => false,
792        }
793    }
794}