1use std::{fmt, marker::PhantomData};
16
17use super::{
18 is_bits::IsBits,
19 valid_layout::{ValidField, ValidLayout},
20};
21use crate::{
22 convert::{
23 ccall_types::{CCallArg, CCallReturn},
24 unbox::Unbox,
25 },
26 data::types::{construct_type::ConstructType, typecheck::Typecheck},
27 prelude::{DataType, LocalScope, Managed, Target, Value},
28};
29
30pub unsafe trait HasLayout<'scope, 'data>: ConstructType {
36 type Layout: ValidLayout;
38}
39
40unsafe impl<'scope, 'data, T: ConstructType + ValidLayout> HasLayout<'scope, 'data> for T {
41 type Layout = T;
42}
43
44#[repr(transparent)]
46pub struct TypedLayout<L, T> {
47 data: L,
48 _ty: PhantomData<T>,
49}
50
51impl<L, T> TypedLayout<L, T>
52where
53 L: ValidField,
54 T: ConstructType,
55{
56 #[inline]
60 pub const unsafe fn new_relaxed(data: L) -> Self {
61 TypedLayout {
62 data,
63 _ty: PhantomData,
64 }
65 }
66
67 #[inline]
69 pub fn into_layout(self) -> L {
70 self.data
71 }
72}
73
74impl<'scope, 'data, T> TypedLayout<T::Layout, T>
75where
76 T: HasLayout<'scope, 'data>,
77{
78 #[inline]
80 pub const fn new(data: T::Layout) -> Self {
81 TypedLayout {
82 data,
83 _ty: PhantomData,
84 }
85 }
86}
87
88unsafe impl<L, T> IsBits for TypedLayout<L, T>
89where
90 L: IsBits + ValidLayout,
91 T: 'static + HasLayout<'static, 'static, Layout = L>,
92{
93}
94
95impl<L, T> Clone for TypedLayout<L, T>
96where
97 L: Clone,
98{
99 fn clone(&self) -> Self {
100 Self {
101 data: self.data.clone(),
102 _ty: PhantomData,
103 }
104 }
105}
106
107impl<L, T> fmt::Debug for TypedLayout<L, T>
108where
109 L: fmt::Debug,
110{
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 f.debug_struct("TypedLayout")
113 .field("data", &self.data)
114 .finish()
115 }
116}
117
118unsafe impl<L, T> Typecheck for TypedLayout<L, T>
119where
120 L: Typecheck,
121 T: ConstructType,
122{
123 fn typecheck(t: DataType) -> bool {
124 t.unrooted_target().local_scope::<_, 1>(|mut frame| {
125 let ty = T::construct_type(&mut frame);
126 if ty != t {
127 return false;
128 }
129
130 L::typecheck(t)
131 })
132 }
133}
134
135unsafe impl<L, T> ValidLayout for TypedLayout<L, T>
136where
137 L: ValidLayout,
138 T: ConstructType,
139{
140 fn valid_layout(t: Value) -> bool {
141 t.unrooted_target().local_scope::<_, 1>(|mut frame| {
142 let ty = T::construct_type(&mut frame);
143 if ty != t {
144 return false;
145 }
146
147 L::valid_layout(t)
148 })
149 }
150
151 fn type_object<'target, Tgt: Target<'target>>(target: &Tgt) -> Value<'target, 'static> {
152 L::type_object(target)
153 }
154}
155
156unsafe impl<L, T> ValidField for TypedLayout<L, T>
157where
158 L: ValidField,
159 T: ConstructType,
160{
161 fn valid_field(t: Value) -> bool {
162 t.unrooted_target().local_scope::<_, 1>(|mut frame| {
163 let ty = T::construct_type(&mut frame);
164 if ty != t {
165 return false;
166 }
167
168 L::valid_field(t)
169 })
170 }
171}
172
173unsafe impl<L, T> Unbox for TypedLayout<L, T>
174where
175 L: Clone,
176 T: ConstructType,
177{
178 type Output = Self;
179}
180
181unsafe impl<L, T> ConstructType for TypedLayout<L, T>
182where
183 T: ConstructType,
184{
185 type Static = T::Static;
186
187 #[inline]
188 fn construct_type_uncached<'target, Tgt>(
189 target: Tgt,
190 ) -> crate::prelude::ValueData<'target, 'static, Tgt>
191 where
192 Tgt: Target<'target>,
193 {
194 T::construct_type_uncached(target)
195 }
196
197 #[inline]
198 fn construct_type_with_env_uncached<'target, Tgt>(
199 target: Tgt,
200 env: &crate::data::types::construct_type::TypeVarEnv,
201 ) -> crate::prelude::ValueData<'target, 'static, Tgt>
202 where
203 Tgt: Target<'target>,
204 {
205 T::construct_type_with_env_uncached(target, env)
206 }
207
208 #[inline]
209 fn base_type<'target, Tgt>(target: &Tgt) -> Option<Value<'target, 'static>>
210 where
211 Tgt: Target<'target>,
212 {
213 T::base_type(target)
214 }
215}
216
217unsafe impl<L, T> CCallArg for TypedLayout<L, T>
218where
219 L: IsBits,
220 T: ConstructType,
221{
222 type CCallArgType = Self;
223 type FunctionArgType = Self;
224}
225
226unsafe impl<L, T> CCallReturn for TypedLayout<L, T>
227where
228 L: IsBits,
229 T: ConstructType,
230{
231 type FunctionReturnType = Self;
232 type CCallReturnType = Self;
233 type ReturnAs = Self;
234
235 #[inline]
236 unsafe fn return_or_throw(self) -> Self::ReturnAs {
237 self
238 }
239}