facet_core/lib.rs
1#![cfg_attr(not(feature = "std"), no_std)]
2// Enable portable_simd when available (detected via autocfg in build.rs)
3#![cfg_attr(has_portable_simd, feature(portable_simd))]
4#![warn(missing_docs)]
5#![warn(clippy::std_instead_of_core)]
6#![warn(clippy::std_instead_of_alloc)]
7// Allow uncommon unicode in the 𝟋 prelude module
8#![allow(uncommon_codepoints)]
9//!
10//! [](https://coveralls.io/github/facet-rs/facet?branch=main)
11//! [](https://crates.io/crates/facet-core)
12//! [](https://docs.rs/facet-core)
13//! [](./LICENSE)
14//! [](https://discord.gg/JhD7CwCJ8F)
15//!
16//! Defines the `Facet` trait and implements it for a lot (a LOT) of builtin types.
17//!
18//! This crate is foundational to facet's reflection capabilities, providing the type system that enables runtime type manipulation.
19//!
20#![doc = include_str!("../readme-footer.md")]
21
22#[cfg(feature = "alloc")]
23extern crate alloc;
24
25// Core type definitions (merged from facet-core-types)
26mod types;
27pub use types::*;
28
29// Write trait for serializers
30mod write;
31pub use write::Write;
32
33// Implementations of the Shape trait
34mod impls;
35#[cfg(feature = "semver")]
36pub use semver;
37
38/// Allows querying the [`Shape`] of a type, which in turn lets us inspect any fields, build a value of
39/// this type progressively, etc.
40///
41/// The `'facet` lifetime allows `Facet` to be derived for types that borrow from something else.
42///
43/// # Safety
44///
45/// If you implement this wrong, all the safe abstractions in `facet-reflect`,
46/// all the serializers, deserializers, the entire ecosystem is unsafe.
47///
48/// You're responsible for describing the type layout properly, and annotating all the invariants.
49pub unsafe trait Facet<'facet>: 'facet {
50 /// The shape of this type, including: whether it's a Struct, an Enum, something else?
51 ///
52 /// All its fields, with their names, types, attributes, doc comments, etc.
53 /// VTables for list operations, set operations, map operations, option operations,
54 /// and implementations for Display, Debug, etc.—marker traits like Send, Sync, Copy, Eq,
55 /// and probably other things I'm forgetting.
56 const SHAPE: &'static Shape;
57}
58
59/// Returns the shape of a type as a function pointer.
60///
61/// This is a helper for lazy shape initialization in field definitions.
62/// Using a function pointer instead of a direct reference moves const
63/// evaluation from compile time to runtime, improving compile times.
64///
65/// # Example
66///
67/// ```ignore
68/// use facet_core::{FieldBuilder, shape_of};
69///
70/// // In field definitions:
71/// FieldBuilder::new("my_field", shape_of::<i32>, 0)
72/// ```
73#[inline]
74pub const fn shape_of<'a, T: Facet<'a>>() -> &'static Shape {
75 T::SHAPE
76}
77
78/// Ultra-compact prelude for derive macro codegen (the "digamma" prelude).
79///
80/// All exports are prefixed with `𝟋` to avoid collisions after `use ::facet::𝟋::*;`
81///
82/// The `𝟋` character (U+1D4CB, Mathematical Script Small F, "digamma") was chosen because:
83/// - It's a valid Rust identifier (XID_Start)
84/// - It's visually distinctive ("this is internal macro stuff")
85/// - It won't collide with any user-defined names
86#[doc(hidden)]
87#[allow(nonstandard_style)]
88pub mod 𝟋 {
89 // === Type aliases ===
90 pub use crate::Attr as 𝟋Attr;
91 pub use crate::Def as 𝟋Def;
92 pub use crate::DefaultSource as 𝟋DS;
93 pub use crate::EnumRepr as 𝟋ERpr;
94 pub use crate::EnumType as 𝟋ETy;
95 pub use crate::EnumTypeBuilder as 𝟋ETyB;
96 pub use crate::Facet as 𝟋Fct;
97 pub use crate::Field as 𝟋Fld;
98 pub use crate::FieldBuilder as 𝟋FldB;
99 pub use crate::FieldFlags as 𝟋FF;
100 pub use crate::HashProxy as 𝟋HP;
101 pub use crate::MarkerTraits as 𝟋Mt;
102 pub use crate::Repr as 𝟋Repr;
103 pub use crate::Shape as 𝟋Shp;
104 pub use crate::ShapeBuilder as 𝟋ShpB;
105 pub use crate::ShapeFlags as 𝟋ShpF;
106 pub use crate::ShapeRef as 𝟋ShpR;
107 pub use crate::StructKind as 𝟋Sk;
108 pub use crate::StructType as 𝟋STy;
109 pub use crate::StructTypeBuilder as 𝟋STyB;
110 pub use crate::Type as 𝟋Ty;
111 pub use crate::UserType as 𝟋UTy;
112 pub use crate::VTableDirect as 𝟋VtD;
113 pub use crate::VTableErased as 𝟋VtE;
114 pub use crate::Variance as 𝟋Vnc;
115 pub use crate::VarianceDesc as 𝟋VncD;
116 pub use crate::Variant as 𝟋Var;
117 pub use crate::VariantBuilder as 𝟋VarB;
118 pub use ::core::option::Option::None as 𝟋None;
119 pub use ::core::option::Option::Some as 𝟋Some;
120 pub use ::core::result::Result::Err as 𝟋Err;
121 pub use ::core::result::Result::Ok as 𝟋Ok;
122
123 // === Core utility re-exports ===
124 pub use ::core::mem::forget as 𝟋forget;
125 pub use ::core::mem::transmute as 𝟋transmute;
126 pub use ::core::ptr::drop_in_place as 𝟋drop_in_place;
127
128 /// Helper to get shape of a type as a function - monomorphized per type
129 pub use crate::shape_of as 𝟋shp;
130
131 // === Declaration ID ===
132 pub use crate::DeclId as 𝟋DId;
133 pub use crate::decl_id_hash as 𝟋dih;
134
135 // === Constants ===
136 /// Empty attributes slice
137 pub const 𝟋NOAT: &[crate::FieldAttribute] = &[];
138 /// Empty doc slice
139 pub const 𝟋NODOC: &[&str] = &[];
140 /// Empty flags
141 pub const 𝟋NOFL: crate::FieldFlags = crate::FieldFlags::empty();
142 /// Computed variance (for non-opaque types) - bivariant base with field walking fallback
143 pub const 𝟋CV: crate::VarianceDesc = crate::VarianceDesc::BIVARIANT;
144
145 // === Type Aliases ===
146 /// PhantomData type for shadow structs, invariant with respect to lifetime `'a`.
147 pub type 𝟋Ph<'a> = ::core::marker::PhantomData<*mut &'a ()>;
148
149 /// String type for proxy conversion errors (requires alloc feature).
150 #[cfg(feature = "alloc")]
151 pub type 𝟋Str = ::alloc::string::String;
152
153 /// Fallback when alloc is not available - proxy requires alloc at runtime,
154 /// but we need a type for compilation in no_std contexts.
155 #[cfg(not(feature = "alloc"))]
156 pub type 𝟋Str = &'static str;
157
158 /// Result type alias for macro-generated code.
159 pub type 𝟋Result<T, E> = ::core::result::Result<T, E>;
160
161 // === Helper functions ===
162 /// Returns `drop_in_place::<T>` as a function pointer for vtable construction.
163 pub const fn 𝟋drop_for<T>() -> unsafe fn(*mut T) {
164 ::core::ptr::drop_in_place::<T>
165 }
166
167 /// Returns a default_in_place function pointer for TypeOpsDirect.
168 /// # Safety
169 /// The pointer must point to uninitialized memory of sufficient size and alignment for T.
170 pub const fn 𝟋default_for<T: Default>() -> unsafe fn(*mut T) {
171 unsafe fn default_in_place<T: Default>(ptr: *mut T) {
172 unsafe { ptr.write(T::default()) };
173 }
174 default_in_place::<T>
175 }
176
177 /// Returns a clone_into function pointer for TypeOpsDirect.
178 /// # Safety
179 /// - `src` must point to a valid, initialized value of type T
180 /// - `dst` must point to uninitialized memory of sufficient size and alignment for T
181 pub const fn 𝟋clone_for<T: Clone>() -> unsafe fn(*const T, *mut T) {
182 unsafe fn clone_into<T: Clone>(src: *const T, dst: *mut T) {
183 unsafe { dst.write((*src).clone()) };
184 }
185 clone_into::<T>
186 }
187
188 // === TypeOpsIndirect helpers ===
189 // These take OxPtrMut/OxPtrConst and work with wide pointers
190
191 /// Returns a drop_in_place function pointer for TypeOpsIndirect.
192 pub const fn 𝟋indirect_drop_for<T>() -> unsafe fn(crate::OxPtrMut) {
193 unsafe fn drop_in_place<T>(ox: crate::OxPtrMut) {
194 unsafe { ::core::ptr::drop_in_place(ox.ptr().as_ptr::<T>() as *mut T) };
195 }
196 drop_in_place::<T>
197 }
198
199 /// Returns a default_in_place function pointer for TypeOpsIndirect.
200 pub const fn 𝟋indirect_default_for<T: Default>() -> unsafe fn(crate::OxPtrUninit) -> bool {
201 unsafe fn default_in_place<T: Default>(ox: crate::OxPtrUninit) -> bool {
202 unsafe { ox.put(T::default()) };
203 true
204 }
205 default_in_place::<T>
206 }
207
208 /// Returns a clone_into function pointer for TypeOpsIndirect.
209 pub const fn 𝟋indirect_clone_for<T: Clone>() -> unsafe fn(crate::OxPtrConst, crate::OxPtrMut) {
210 unsafe fn clone_into<T: Clone>(src: crate::OxPtrConst, dst: crate::OxPtrMut) {
211 let src_val = unsafe { &*(src.ptr().as_byte_ptr() as *const T) };
212 unsafe { dst.ptr().as_uninit().put(src_val.clone()) };
213 }
214 clone_into::<T>
215 }
216
217 // === Specialization ===
218 pub use crate::types::specialization::impls;
219 pub use crate::types::specialization::{
220 Spez, SpezCloneIntoNo, SpezCloneIntoYes, SpezDebugNo, SpezDebugYes, SpezDefaultInPlaceNo,
221 SpezDefaultInPlaceYes, SpezDisplayNo, SpezDisplayYes, SpezEmpty, SpezHashNo, SpezHashYes,
222 SpezOrdNo, SpezOrdYes, SpezParseNo, SpezParseYes, SpezPartialEqNo, SpezPartialEqYes,
223 SpezPartialOrdNo, SpezPartialOrdYes,
224 };
225}