1use std::{
4 cell::RefCell,
5 cmp::{Eq, PartialEq},
6 collections::HashSet,
7 fmt::{self, Debug, Display, Formatter},
8 mem::{self, ManuallyDrop},
9};
10
11use core_extensions::{matches, StringExt};
12
13use crate::{
14 abi_stability::{
15 extra_checks::{ExtraChecksStaticRef, StoredExtraChecks},
16 stable_abi_trait::AbiConsts,
17 },
18 const_utils::log2_usize,
19 prefix_type::{FieldAccessibility, FieldConditionality},
20 reflection::ModReflMode,
21 sabi_types::{CmpIgnored, NulStr, VersionStrings},
22 std_types::{RSlice, RStr, UTypeId},
23};
24
25mod construction;
26pub mod data_structures;
27mod iterators;
28mod printing;
29mod shared_vars;
30mod small_types;
31pub mod tagging;
32mod tl_data;
33mod tl_enums;
34mod tl_field;
35mod tl_fields;
36mod tl_functions;
37mod tl_lifetimes;
38mod tl_multi_tl;
39mod tl_other;
40mod tl_prefix;
41mod tl_reflection;
42
43pub(crate) use self::iterators::ChainOnce;
44
45pub use self::{
46 construction::{ItemInfo, _private_MonoTypeLayoutDerive, _private_TypeLayoutDerive},
47 shared_vars::{MonoSharedVars, SharedVars},
48 small_types::{OptionU16, OptionU8, StartLen, StartLenConverter, StartLenRepr},
49 tagging::Tag,
50 tl_data::{GenericTLData, MismatchedTLDataVariant, MonoTLData, TLData, TLDataDiscriminant},
51 tl_enums::{
52 DiscriminantRepr, GenericTLEnum, IncompatibleWithNonExhaustive, IsExhaustive,
53 MakeTLNonExhaustive, MonoTLEnum, TLDiscriminant, TLDiscriminants, TLEnum, TLNonExhaustive,
54 },
55 tl_field::{CompTLField, CompTLFieldRepr, TLField},
56 tl_fields::{CompTLFields, TLFields, TLFieldsIterator},
57 tl_functions::{
58 CompTLFunction, TLFunction, TLFunctionIter, TLFunctionQualifiers, TLFunctionSlice,
59 TLFunctions,
60 },
61 tl_lifetimes::{
62 LifetimeArrayOrSlice, LifetimeIndex, LifetimeIndexArray, LifetimeIndexPair,
63 LifetimeIndexPairRepr, LifetimeRange,
64 },
65 tl_multi_tl::{MTLIterator, MultipleTypeLayouts, TypeLayoutIndex, TypeLayoutRange},
66 tl_other::{
67 CompGenericParams, FmtFullType, GenericParams, ModPath, ReprAttr, TLFieldOrFunction,
68 TLPrimitive,
69 },
70 tl_prefix::{GenericTLPrefixType, MonoTLPrefixType, TLPrefixType},
71 tl_reflection::{CompFieldAccessor, FieldAccessor},
72};
73
74#[repr(C)]
79#[derive(Copy, Clone, StableAbi)]
80#[sabi(unsafe_sabi_opaque_fields)]
87pub struct TypeLayout {
88 shared_vars: &'static SharedVars,
89
90 mono: &'static MonoTypeLayout,
92
93 is_nonzero: bool,
96
97 alignment_power_of_two: u8,
99
100 size: usize,
102
103 tag: Option<&'static Tag>,
104
105 data: GenericTLData,
106
107 extra_checks: CmpIgnored<Option<&'static ManuallyDrop<StoredExtraChecks>>>,
109
110 type_id: extern "C" fn() -> UTypeId,
112}
113
114unsafe impl Send for TypeLayout {}
115unsafe impl Sync for TypeLayout {}
116
117unsafe impl Send for MonoTypeLayout {}
118unsafe impl Sync for MonoTypeLayout {}
119
120impl TypeLayout {
123 pub(crate) const fn from_std<T>(
124 shared_vars: &'static SharedVars,
125 mono: &'static MonoTypeLayout,
126 abi_consts: AbiConsts,
127 data: GenericTLData,
128 ) -> Self {
129 Self {
130 shared_vars,
131 mono,
132 is_nonzero: abi_consts.is_nonzero,
133 type_id: abi_consts.type_id.0,
134 alignment_power_of_two: log2_usize(mem::align_of::<T>()),
135 size: mem::size_of::<T>(),
136 data,
137 extra_checks: CmpIgnored::new(None),
138 tag: None,
139 }
140 }
141
142 #[doc(hidden)]
143 pub const fn from_derive<T>(p: _private_TypeLayoutDerive) -> Self {
144 Self {
145 shared_vars: p.shared_vars,
146 mono: p.mono,
147 is_nonzero: p.abi_consts.is_nonzero,
148 type_id: p.abi_consts.type_id.0,
149 alignment_power_of_two: log2_usize(mem::align_of::<T>()),
150 size: mem::size_of::<T>(),
151 data: p.data,
152 extra_checks: CmpIgnored::new(p.extra_checks),
153 tag: p.tag,
154 }
155 }
156
157 pub const fn shared_vars(&self) -> &'static SharedVars {
160 self.shared_vars
161 }
162
163 #[doc(hidden)]
165 pub fn full_type(&self) -> FmtFullType {
166 FmtFullType {
167 name: self.mono.name(),
168 generics: self.generics(),
169 primitive: self.mono.data.to_primitive(),
170 utypeid: self.get_utypeid(),
171 }
172 }
173
174 pub fn package_and_version(&self) -> (RStr<'static>, VersionStrings) {
176 let (package, version) = self.item_info().package_and_version();
177
178 (RStr::from_str(package), VersionStrings::new(version))
179 }
180
181 pub fn package(&self) -> RStr<'static> {
183 let (package, _) = self.item_info().package_and_version();
184 RStr::from_str(package)
185 }
186
187 pub fn package_version(&self) -> VersionStrings {
189 let (_, version) = self.item_info().package_and_version();
190 VersionStrings::new(version)
191 }
192
193 pub const fn line(&self) -> u32 {
195 self.item_info().line
196 }
197
198 pub const fn mod_path(&self) -> ModPath {
200 self.item_info().mod_path
201 }
202
203 #[inline]
205 pub fn extra_checks(&self) -> Option<ExtraChecksStaticRef> {
206 self.extra_checks.value.map(|x| x.sabi_reborrow())
207 }
208
209 pub const fn get_fields(&self) -> Option<TLFields> {
226 match self.mono.get_fields() {
227 Some(fields) => Some(fields.expand(self.shared_vars)),
228 None => None,
229 }
230 }
231
232 pub const fn is_prefix_kind(&self) -> bool {
234 matches!(self.data, GenericTLData::PrefixType { .. })
235 }
236
237 #[inline]
239 pub fn name(&self) -> &'static str {
240 self.mono.name()
241 }
242
243 #[inline]
246 pub const fn is_nonzero(&self) -> bool {
247 self.is_nonzero
248 }
249
250 #[doc(hidden)]
251 #[cfg(feature = "testing")]
252 pub const fn _set_is_nonzero(mut self, is_nonzero: bool) -> Self {
253 self.is_nonzero = is_nonzero;
254 self
255 }
256
257 #[doc(hidden)]
258 #[cfg(feature = "testing")]
259 pub const fn _set_extra_checks(
260 mut self,
261 extra_checks: CmpIgnored<Option<&'static ManuallyDrop<StoredExtraChecks>>>,
262 ) -> Self {
263 self.extra_checks = extra_checks;
264 self
265 }
266
267 #[doc(hidden)]
268 #[cfg(feature = "testing")]
269 pub const fn _set_type_id(mut self, type_id: extern "C" fn() -> UTypeId) -> Self {
270 self.type_id = type_id;
271 self
272 }
273
274 #[inline]
277 pub fn get_utypeid(&self) -> UTypeId {
278 (self.type_id)()
279 }
280
281 #[inline]
283 pub const fn item_info(&self) -> &ItemInfo {
284 self.mono.item_info()
285 }
286
287 #[inline]
289 pub const fn alignment(&self) -> usize {
290 1_usize << (self.alignment_power_of_two as u32)
291 }
292
293 #[inline]
295 pub const fn size(&self) -> usize {
296 self.size
297 }
298
299 pub const fn tag(&self) -> &'static Tag {
303 match self.tag {
304 Some(x) => x,
305 None => Tag::NULL,
306 }
307 }
308
309 pub const fn repr_attr(&self) -> ReprAttr {
311 self.mono.repr_attr()
312 }
313
314 pub const fn mod_refl_mode(&self) -> ModReflMode {
317 self.mono.mod_refl_mode()
318 }
319
320 pub fn data(&self) -> TLData {
323 self.mono
324 .data
325 .expand(self.data, self.shared_vars)
326 .unwrap_or_else(|e| {
327 panic!("\nError inside of '{}' type \n{}", self.full_type(), e);
328 })
329 }
330
331 pub const fn data_discriminant(&self) -> TLDataDiscriminant {
334 self.mono.data.as_discriminant()
335 }
336
337 #[inline]
340 pub fn phantom_fields(&self) -> TLFields {
341 unsafe {
342 let slice = std::slice::from_raw_parts(
343 self.mono.phantom_fields,
344 self.mono.phantom_fields_len as usize,
345 );
346 TLFields::from_fields(slice, self.shared_vars)
347 }
348 }
349
350 pub fn generics(&self) -> GenericParams {
352 self.mono.generics.expand(self.shared_vars)
353 }
354
355 pub const fn mono_type_layout(&self) -> &MonoTypeLayout {
357 self.mono
358 }
359}
360
361impl PartialEq for TypeLayout {
362 fn eq(&self, other: &TypeLayout) -> bool {
363 self.get_utypeid() == other.get_utypeid()
364 }
365}
366
367impl Eq for TypeLayout {}
368
369#[repr(C)]
373#[derive(Copy, Clone, StableAbi)]
374#[sabi(unsafe_sabi_opaque_fields)]
375pub struct MonoTypeLayout {
376 shared_vars: MonoSharedVars,
377
378 name: *const u8,
380
381 item_info: CmpIgnored<ItemInfo>,
384
385 data: MonoTLData,
387 generics: CompGenericParams,
389
390 phantom_fields: *const CompTLField,
393 phantom_fields_len: u8,
394
395 repr_attr: ReprAttr,
397
398 mod_refl_mode: ModReflMode,
400
401 name_len: u16,
402}
403
404#[allow(clippy::too_many_arguments)]
405impl MonoTypeLayout {
406 pub(crate) const fn new(
407 shared_vars: MonoSharedVars,
408 name: RStr<'static>,
409 item_info: ItemInfo,
410 data: MonoTLData,
411 generics: CompGenericParams,
412 repr_attr: ReprAttr,
413 mod_refl_mode: ModReflMode,
414 phantom_fields: RSlice<'static, CompTLField>,
415 ) -> Self {
416 Self {
417 shared_vars,
418 name: name.as_ptr(),
419 name_len: name.len() as u16,
420 item_info: CmpIgnored::new(item_info),
421 data,
422 generics,
423 repr_attr,
424 mod_refl_mode,
425 phantom_fields: phantom_fields.as_ptr(),
426 phantom_fields_len: phantom_fields.len() as u8,
427 }
428 }
429
430 #[doc(hidden)]
431 pub const fn from_derive(p: _private_MonoTypeLayoutDerive) -> Self {
432 Self {
433 name: p.name.as_ptr(),
434 name_len: p.name.len() as u16,
435 phantom_fields: p.phantom_fields.as_ptr() as *const CompTLFieldRepr
436 as *const CompTLField,
437 phantom_fields_len: p.phantom_fields.len() as u8,
438 item_info: CmpIgnored::new(p.item_info),
439 data: p.data,
440 generics: p.generics,
441 repr_attr: p.repr_attr,
442 mod_refl_mode: p.mod_refl_mode,
443 shared_vars: p.shared_vars,
444 }
445 }
446
447 pub fn name(&self) -> &'static str {
449 unsafe {
450 let slic = std::slice::from_raw_parts(self.name, self.name_len as usize);
451 std::str::from_utf8_unchecked(slic)
452 }
453 }
454
455 pub const fn repr_attr(&self) -> ReprAttr {
457 self.repr_attr
458 }
459
460 pub const fn mod_refl_mode(&self) -> ModReflMode {
463 self.mod_refl_mode
464 }
465
466 pub const fn item_info(&self) -> &ItemInfo {
468 &self.item_info.value
469 }
470
471 pub const fn shared_vars(&self) -> &MonoSharedVars {
474 &self.shared_vars
475 }
476
477 pub const fn shared_vars_static(&'static self) -> &'static MonoSharedVars {
482 &self.shared_vars
483 }
484
485 pub const fn get_fields(&self) -> Option<CompTLFields> {
502 match self.data {
503 MonoTLData::Primitive { .. } => None,
504 MonoTLData::Opaque => None,
505 MonoTLData::Struct { fields } => Some(fields),
506 MonoTLData::Union { fields } => Some(fields),
507 MonoTLData::Enum(tlenum) => Some(tlenum.fields),
508 MonoTLData::PrefixType(prefix) => Some(prefix.fields),
509 }
510 }
511
512 pub fn field_names(&self) -> impl ExactSizeIterator<Item = &'static str> + Clone + 'static {
514 self.get_fields()
515 .unwrap_or(CompTLFields::EMPTY)
516 .field_names(&self.shared_vars)
517 }
518
519 pub fn get_field_name(&self, nth: usize) -> Option<&'static str> {
522 self.get_fields()
523 .unwrap_or(CompTLFields::EMPTY)
524 .get_field_name(nth, &self.shared_vars)
525 }
526}
527
528impl Debug for MonoTypeLayout {
529 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
530 f.debug_struct("MonoTypeLayout")
531 .field("name", &self.name())
532 .field("item_info", self.item_info())
533 .field("repr_attr", &self.repr_attr())
534 .field("mod_refl_mode", &self.mod_refl_mode())
535 .finish()
536 }
537}