swamp_types/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/types
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5mod cache;
6mod calc_compat;
7mod flags;
8pub mod prelude;
9mod pretty_print;
10mod supporting_types;
11mod type_kind;
12
13use crate::flags::TypeFlags;
14pub use crate::type_kind::TypeKind;
15use std::fmt::{Display, Formatter};
16use std::rc::Rc;
17
18#[derive(PartialEq, Clone, Eq, Hash, Copy, Debug)]
19pub struct TypeId(u32);
20
21impl TypeId {
22    pub const EMPTY: u32 = 0xffffffff;
23
24    #[must_use]
25    pub const fn new(id: u32) -> Self {
26        Self(id)
27    }
28
29    #[must_use]
30    pub const fn inner(&self) -> u32 {
31        self.0
32    }
33}
34
35impl Display for TypeId {
36    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
37        write!(f, "{}", self.0)
38    }
39}
40
41#[derive(Debug, Clone, PartialEq, Eq, Hash)]
42pub struct Type {
43    pub id: TypeId,
44    pub flags: TypeFlags,
45    pub kind: Rc<TypeKind>,
46}
47
48pub type TypeRef = Rc<Type>;
49
50impl Display for Type {
51    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
52        write!(f, "{}", self.kind)
53    }
54}
55
56impl Type {
57    #[inline]
58    #[must_use]
59    pub const fn is_scalar(&self) -> bool {
60        self.flags.contains(TypeFlags::IS_SCALAR)
61    }
62
63    #[inline]
64    #[must_use]
65    pub const fn can_be_stored_in_field(&self) -> bool {
66        self.flags.contains(TypeFlags::IS_STORAGE)
67    }
68
69    #[inline]
70    #[must_use]
71    pub const fn can_be_stored_in_transient_field(&self) -> bool {
72        self.flags.contains(TypeFlags::ALLOWED_FOR_SCOPED_BORROW)
73    }
74
75    #[inline]
76    #[must_use]
77    pub const fn can_be_stored_in_variable(&self) -> bool {
78        self.flags.contains(TypeFlags::ALLOWED_FOR_VARIABLE)
79    }
80
81    #[must_use]
82    pub fn is_option(&self) -> bool {
83        matches!(&*self.kind, TypeKind::Optional(_))
84    }
85
86    #[inline]
87    #[must_use]
88    pub const fn is_storage(&self) -> bool {
89        self.flags.contains(TypeFlags::IS_STORAGE)
90    }
91
92    #[inline]
93    #[must_use]
94    pub const fn allowed_as_return_type(&self) -> bool {
95        self.flags.contains(TypeFlags::IS_ALLOWED_RETURN)
96    }
97
98    #[inline]
99    #[must_use]
100    pub const fn allowed_as_parameter_type(&self) -> bool {
101        self.flags.contains(TypeFlags::IS_ALLOWED_RETURN)
102    }
103
104    #[inline]
105    #[must_use]
106    pub const fn allowed_for_scoped_borrow(&self) -> bool {
107        self.flags.contains(TypeFlags::ALLOWED_FOR_SCOPED_BORROW)
108    }
109
110    #[inline]
111    #[must_use]
112    pub const fn can_be_materialized(&self) -> bool {
113        self.flags.contains(TypeFlags::ALLOWED_FOR_SCOPED_BORROW)
114            | self.flags.contains(TypeFlags::IS_STORAGE)
115    }
116
117    /// Check if this type requires explicit collection storage allocation from caller
118    /// This includes all aggregate types including optionals that need memory
119    /// allocation and proper setup of the r0 register by the caller
120    #[must_use]
121    pub fn collection_view_that_needs_explicit_storage(&self) -> bool {
122        match &*self.kind {
123            // Dynamic collections that need explicit storage
124            TypeKind::DynamicLengthVecView(_)
125            | TypeKind::DynamicLengthMapView(_, _)
126            | TypeKind::StackView(_)
127            | TypeKind::QueueView(_)
128            | TypeKind::SparseView(_)
129            | TypeKind::GridView(_)
130            | TypeKind::SliceView(_) => true,
131
132            // Optional types that contain types needing storage
133            TypeKind::Optional(inner_type) => {
134                inner_type.collection_view_that_needs_explicit_storage()
135            }
136
137            _ => false,
138        }
139    }
140}