safer_ffi/layout/
_mod.rs

1//! Trait abstractions describing the semantics of "being `#[repr(C)]`"
2
3use_prelude!();
4
5pub(crate) mod macros;
6
7#[doc(inline)]
8pub use crate::CType;
9#[doc(inline)]
10pub use crate::ReprC;
11pub use crate::derive_ReprC;
12#[doc(inline)]
13pub use crate::from_CType_impl_ReprC;
14
15type_level_enum! {
16    pub
17    enum OpaqueKind {
18        Concrete,
19        Opaque,
20    }
21}
22
23/// One of the two core traits of this crate (with [`ReprC`][`trait@ReprC`]).
24///
25/// `CType` is an `unsafe` trait that binds a Rust type to a C typedef.
26///
27/// To optimise compile-times, the C typedef part is gated behind the `headers`
28/// cargo feature, so when that feature is not enabled, the trait may "look"
29/// like a marker trait, but it isn't.
30///
31/// That's why **manually implementing this trait is strongly discouraged**,
32/// although not forbidden:
33///
34///   - If you trully want a manual implementation of `CType` (_e.g._, for an "opaque type" pattern,
35///     _i.e._, a forward declaration), then, to implement the trait so that it works no matter the
36///     status of the `safer_ffi/headers` feature, one must define the methods as if feature was
37///     present, but with a `#[::safer_ffi::cfg_headers]` gate slapped on _each_ method.
38///
39/// # Safety
40///
41/// The Rust type in an `extern "C"` function must have the same layout and ABI
42/// as the defined C type, and all the bit-patterns representing any instance
43/// of such C type must be valid and safe bit-patterns for the Rust type.
44///
45/// For the most common types, there are only two reasons to correctly be a
46/// `CType`:
47///
48///   - being a primitive type, such as an integer type or a (slim) pointer.
49///
50///       - This crates provides as many of these implementations as possible.
51///
52///   - and recursively, a non-zero-sized `#[repr(C)]` struct of `CType` fields.
53///
54///       - the [`CType!`] macro can be used to wrap a `#[repr(C)]` struct definition to _safely_
55///         and automagically implement the trait when it is sound to do so.
56///
57/// Note that types such as Rust's [`bool`] are ruled out by this definition,
58/// since it has the ABI of a `u8 <-> uint8_t`, and yet there are many
59/// bit-patterns for the `uint8_t` type that do not make _valid_ `bool`s.
60///
61/// For such types, see the [`ReprC`][`trait@ReprC`] trait.
62///
63/// Safety (non-exhaustive list at the moment):
64///   - `::core::mem::zeroed::<Self>()` must be sound to use.
65pub unsafe trait CType: Sized + Copy {
66    type OPAQUE_KIND: OpaqueKind::T;
67
68    fn zeroed() -> Self {
69        unsafe { ::core::mem::zeroed() }
70    }
71
72    #[apply(__cfg_headers__!)]
73    /// Necessary one-time code for [`CType::name()`] to make sense.
74    ///
75    /// Some types, such as `char`, are part of the language, and can be
76    /// used directly by [`CType::name()`].
77    /// In that case, there is nothing else to _define_, and all is fine.
78    ///
79    ///   - That is the default implementation of this method: doing nothing.
80    ///
81    /// But most often than not, a `typedef` or an `#include` is required.
82    ///
83    /// In that case, here is the place to put it, with the help of the
84    /// provided `Definer`.
85    ///
86    /// # Idempotency?
87    ///
88    /// Given some `definer: &mut dyn Definer`, **the `define_self__impl(definer)`
89    /// call is not to be called more than once, thanks to the convenience
90    /// method [`Self::define_self()`], which is the one to guarantee idempotency**
91    /// (thanks to the [`Definer`]'s [`.define_once()`][`Definer::define_once()`] helper).
92    ///
93    /// # Safety
94    ///
95    /// Given that the defined types may be used by [`CType::name_wrapping_var()`],
96    /// and [`CType::name()`], the same safety disclaimers apply.
97    ///
98    /// ## Examples
99    ///
100    /// ### `#[repr(C)] struct Foo { x: i32 }`
101    ///
102    /// ```rust
103    /// use ::safer_ffi::headers::Definer;
104    /// use ::safer_ffi::headers::languages::HeaderLanguage;
105    /// use ::safer_ffi::layout::CType;
106    /// use ::safer_ffi::layout::OpaqueKind;
107    /// use ::std::io;
108    /// use ::std::marker::PhantomData;
109    ///
110    /// #[derive(Clone, Copy)]
111    /// #[repr(C)]
112    /// struct Foo {
113    ///     x: i32,
114    /// }
115    ///
116    /// unsafe impl CType for Foo {
117    ///     #[::safer_ffi::cfg_headers]
118    ///     fn define_self__impl(
119    ///         language: &'_ dyn HeaderLanguage,
120    ///         definer: &'_ mut dyn Definer,
121    ///     ) -> io::Result<()> {
122    ///         // ensure int32_t makes sense
123    ///         <i32 as CType>::define_self(language, definer)?;
124    ///         language.declare_struct(
125    ///             language,
126    ///             definer,
127    ///             // no docs.
128    ///             &[],
129    ///             &PhantomData::<Self>,
130    ///             &[::safer_ffi::headers::languages::StructField {
131    ///                 docs: &[],
132    ///                 name: "x",
133    ///                 ty: &PhantomData::<i32>,
134    ///             }],
135    ///         )?;
136    ///         Ok(())
137    ///     }
138    ///
139    ///     #[::safer_ffi::cfg_headers]
140    ///     fn short_name() -> String {
141    ///         "Foo".into()
142    ///     }
143    ///
144    ///     type OPAQUE_KIND = OpaqueKind::Concrete;
145    ///
146    ///     // ...
147    /// }
148    /// ```
149    #[allow(nonstandard_style)]
150    fn define_self__impl(
151        language: &'_ dyn HeaderLanguage,
152        definer: &'_ mut dyn Definer,
153    ) -> io::Result<()>;
154
155    #[apply(__cfg_headers__!)]
156    fn define_self(
157        language: &'_ dyn HeaderLanguage,
158        definer: &'_ mut dyn Definer,
159    ) -> io::Result<()> {
160        definer.define_once(
161            &F(|out| Self::render(out, language)).to_string(),
162            &mut |definer| Self::define_self__impl(language, definer),
163        )
164    }
165
166    #[apply(__cfg_headers__!)]
167    /// A short-name description of the type, mainly used to fill
168    /// "placeholders" such as when monomorphising generics structs or
169    /// arrays.
170    ///
171    /// This provides the implementation used by [`CType::short_name`]`()`.
172    ///
173    /// There are no bad implementations of this method, except,
174    /// of course, for the obligation to provide a valid identifier chunk,
175    /// _i.e._, the output must only contain alphanumeric digits and
176    /// underscores.
177    ///
178    /// For instance, given `T : CType` and `const N: usize > 0`, the type
179    /// `[T; N]` (inline fixed-size array of `N` consecutive elements of
180    /// type `T`) will be typedef-named as:
181    ///
182    /// ```rust,ignore
183    /// write!(fmt, "{}_{}_array", <T as CType>::short_name(), N)
184    /// ```
185    ///
186    /// Generally, typedefs with a trailing `_t` will see that `_t` trimmed
187    /// when used as a `short_name`.
188    ///
189    /// ## Implementation by [`CType!`]:
190    ///
191    /// A non generic struct such as:
192    ///
193    /// ```rust,ignore
194    /// CType! {
195    ///     #[repr(C)]
196    ///     struct Foo { /* fields */ }
197    /// }
198    /// ```
199    ///
200    /// will have `Foo` as its `short_name`.
201    ///
202    /// A generic struct such as:
203    ///
204    /// ```rust,ignore
205    /// CType! {
206    ///     #[repr(C)]
207    ///     struct Foo[T] where { T : CType } { /* fields */ }
208    /// }
209    /// ```
210    ///
211    /// will have `Foo_xxx` as its `short_name`, with `xxx` being `T`'s
212    /// `short_name`.
213    fn short_name() -> String;
214
215    /// Display itself as header code which refers to this C type.
216    ///
217    /// This can be:
218    ///
219    ///   - either through some direct syntactical construct derived off some other stuff, e.g., in
220    ///     C, `{} const*` for the `*const T` case,
221    ///
222    ///   - or simply by given a simple/single identifier name from a helper type alias or type
223    ///     definition having occurred in `define_self` (common case).
224    ///
225    ///     In this case, the name is probably going to be equal to `Self::short_name() + "_t"`.
226    ///
227    ///     **The default implementation does this.**
228    #[apply(__cfg_headers__!)]
229    fn render(
230        out: &'_ mut dyn io::Write,
231        _language: &'_ dyn HeaderLanguage,
232    ) -> io::Result<()> {
233        write!(out, "{}_t", Self::short_name())
234    }
235
236    /// Convenience directly-`String`-outputting version of [`Self::render()`].
237    #[apply(__cfg_headers__!)]
238    fn name(language: &dyn HeaderLanguage) -> String {
239        F(|out| Self::render(out, language)).to_string()
240    }
241
242    /// Same as [`Self::render()`], but for "appending the varname/fn-name after it, with
243    /// whitespace.
244    ///
245    /// This, on its own would be a silly thing for which to dedicate a whole function.
246    ///
247    /// However, C being how it is, in the non-simple/single-typename ident cases for
248    /// `Self::render()`, mainly and most notably, in the array and `fn` pointer cases, the
249    /// varname/fn-name does not just go after the whole type.
250    ///
251    /// Instead, **it has to be interspersed in the middle of the type**.
252    ///
253    /// For instance, in the `fn(c_int) -> u8` case, it would have to be:
254    ///
255    /// > `uint8_t (*{var_name})(int)`.
256    ///
257    /// So such cases need to override the default implementation here, do the right thing, and then
258    /// override the other simpler non-`wrapping_var` versions thereof, to delegate to this function
259    /// with `var_name = ""`.
260    ///
261    /// > ⚠️ **NOTE**: when overriding this default impl, remember to `Self::render()` as
262    /// `Self::render_wrapping_var(…, "")`.
263    ///
264    /// ---
265    ///
266    /// Default implementation is to simply emit `{self.render()}{sep}{var_name}`, in pseudo-code
267    /// parlance.
268    #[apply(__cfg_headers__!)]
269    fn render_wrapping_var(
270        out: &'_ mut dyn io::Write,
271        language: &'_ dyn HeaderLanguage,
272        // Either a `&&str`, or a `&fmt::Arguments<'_>`, for instance.
273        var_name: Option<&dyn ::core::fmt::Display>,
274    ) -> io::Result<()> {
275        write!(
276            out,
277            "{}{sep}{var_name}",
278            F(|out| Self::render(out, language)),
279            sep = var_name.sep(),
280            var_name = var_name.or_empty(),
281        )?;
282        Ok(())
283    }
284
285    #[apply(__cfg_headers__!)]
286    /// The core method of the trait: it provides the code to emit in the target
287    /// [`HeaderLanguage`] in order to refer to the corresponding C type.
288    ///
289    /// The implementations are thus much like any classic `.to_string()` impl,
290    /// except that:
291    ///
292    ///   - it must output valid C code representing the type corresponding to the Rust type.
293    ///
294    ///   - a `var_name` may be supplied, in which case the type must use that as its "variable
295    ///     name" (C being how it is, the var name may need to be inserted in the middle of the
296    ///     types, such as with arrays and function pointers).
297    ///
298    /// # Safety
299    ///
300    /// Here is where the meat of the safety happens: associating a Rust
301    /// type to a non-corresponding C definition will cause Undefined
302    /// Behavior when a function using such type in its ABI is called.
303    ///
304    /// ## Examples
305    ///
306    /// #### `i32`
307    ///
308    /// ```rust ,ignore
309    /// # #[repr(transparent)] struct i32(::core::primitive::i32);
310    ///
311    /// use ::safer_ffi::{headers::languages::HeaderLanguage, layout::CType};
312    ///
313    /// unsafe impl CType for i32 {
314    ///     #[::safer_ffi::cfg_headers]
315    ///     fn name_wrapping_var (
316    ///         header_language: &dyn HeaderLanguage,
317    ///         var_name: Option<&dyn ::core::fmt::Display>,
318    ///     ) -> String
319    ///     {
320    ///         // Usually this kind of logic for primitive types is
321    ///         // provided by the `HeaderLanguage` itself, rather than hard-coded by the type…
322    ///         assert_eq!(header_language.language_name(), "C");
323    ///
324    ///         let sep = if var_name { " " } else { "" };
325    ///         format!("int32_t{sep}{var_name}")
326    ///     }
327    ///
328    ///     // ...
329    /// }
330    /// ```
331    fn name_wrapping_var(
332        language: &'_ dyn HeaderLanguage,
333        var_name: Option<&dyn ::core::fmt::Display>,
334    ) -> String {
335        F(|out| Self::render_wrapping_var(out, language, var_name)).to_string()
336    }
337
338    #[apply(__cfg_headers__!)]
339    /// Optional language-specific metadata attached to the type (_e.g._,
340    /// some `[MarshalAs(UnmanagedType.FunctionPtr)]` annotation for C#).
341    ///
342    /// To be done using:
343    ///
344    /// <code>\&[provide_with]\(|req| req.give_if_requested::\<[CSharpMarshaler]\>(…))</code>
345    ///
346    /// [CSharpMarshaler]: `crate::headers::languages::CSharpMarshaler`
347    fn metadata() -> &'static dyn Provider {
348        &None
349    }
350}
351
352/// The meat of the crate. _The_ trait.
353///
354/// This trait describes that **a type has a defined / fixed `#[repr(C)]`
355/// layout**.
356///
357/// This is expressed at the type level by the `unsafe` (trait) type
358/// association of `ReprC::CLayout`, which must be a [`CType`][`trait@CType`].
359///
360/// Because of that property, the type may be used in the API of an
361/// `#[ffi_export]`-ed function, where ABI-wise it will be replaced by its
362/// equivalent [C layout][`ReprC::CLayout`].
363///
364/// Then, `#[ffi_export]` will transmute the `CType` parameters back to the
365/// provided `ReprC` types, using [`from_raw_unchecked`].
366///
367/// Although, from a pure point of view, no checks are performed at this step
368/// whatsoever, in practice, when `debug_assertions` are enabled, some "sanity
369/// checks" are performed on the input parameters: [`ReprC::is_valid`] is
370/// called in that case (as part of the implementation of [`from_raw`]).
371///
372///   - Although that may look innocent, it is actually pretty powerful tool:
373///
374///     **For instance, a non-null pointer coming from C can, this way, be
375///     automatically checked and unwrapped, and the same applies for
376///     enumerations having a finite number of valid bit-patterns.**
377///
378/// # Safety
379///
380/// It must be sound to transmute from a `ReprC::CLayout` instance when the
381/// bit pattern represents a _safe_ instance of `Self`.
382///
383/// # Implementing `ReprC`
384///
385/// It is generally recommended to avoid manually (and `unsafe`-ly)
386/// implementing the [`ReprC`] trait. Instead, the recommended and blessed way
387/// is to use the [`#[derive_ReprC]`](/safer_ffi/layout/attr.derive_ReprC.html)
388/// attribute on your `#[repr(C)] struct` (or your field-less
389/// `#[repr(<integer>)] enum`).
390///
391/// [`ReprC`]: `trait@ReprC`
392///
393/// ## Examples
394///
395/// #### Simple `struct`
396///
397/// ```rust,no_run
398/// # fn main () {}
399/// use ::safer_ffi::prelude::*;
400///
401/// #[derive_ReprC]
402/// #[repr(C)]
403/// struct Instant {
404///     seconds: u64,
405///     nanos: u32,
406/// }
407/// ```
408///
409///   - corresponding to the following C definition:
410///
411///     ```C
412///     typedef struct {
413///         uint64_t seconds;
414///         uint32_t nanos;
415///     } Instant_t;
416///     ```
417///
418/// #### Field-less `enum`
419///
420/// ```rust,no_run
421/// # fn main () {}
422/// use ::safer_ffi::prelude::*;
423///
424/// #[derive_ReprC]
425/// #[repr(u8)]
426/// enum Status {
427///     Ok = 0,
428///     Busy,
429///     NotInTheMood,
430///     OnStrike,
431///     OhNo,
432/// }
433/// ```
434///
435///   - corresponding to the following C definition:
436///
437///     ```C
438///     typedef uint8_t Status_t; enum {
439///         STATUS_OK = 0,
440///         STATUS_BUSY,
441///         STATUS_NOT_IN_THE_MOOD,
442///         STATUS_ON_STRIKE,
443///         STATUS_OH_NO,
444///     }
445///     ```
446///
447/// #### Generic `struct`
448///
449/// ```rust,no_run
450/// # fn main () {}
451/// use ::safer_ffi::prelude::*;
452///
453/// #[derive_ReprC]
454/// #[repr(C)]
455/// struct Point<Coordinate: ReprC> {
456///     x: Coordinate,
457///     y: Coordinate,
458/// }
459/// ```
460///
461/// Each monomorphization leads to its own C definition:
462///
463///   - **`Point<i32>`**
464///
465///     ```C
466///     typedef struct {
467///         int32_t x;
468///         int32_t y;
469///     } Point_int32_t;
470///     ```
471///
472///   - **`Point<f64>`**
473///
474///     ```C
475///     typedef struct {
476///         double x;
477///         double y;
478///     } Point_double_t;
479///     ```
480pub unsafe trait ReprC: Sized {
481    /// The `CType` having the same layout as `Self`.
482    type CLayout: CType;
483
484    /// Sanity checks that can be performed on an instance of the `CType`
485    /// layout.
486    ///
487    /// Such checks are performed when calling [`from_raw`], or equivalently
488    /// (⚠️ only with `debug_assertions` enabled ⚠️), [`from_raw_unchecked`].
489    ///
490    /// Implementation-wise, this function is only a "sanity check" step:
491    ///
492    ///   - It is valid (although rather pointless) for this function to always return `true`, even
493    ///     if the input may be `unsafe` to transmute to `Self`, or even be an _invalid_ value of
494    ///     type `Self`.
495    ///
496    ///   - In the other direction, it is not unsound, although it would be a logic error, to always
497    ///     return `false`.
498    ///
499    ///   - This is because it is impossible to have a function that for any type is able to tell if
500    ///     a given bit pattern is a safe value of that type.
501    ///
502    /// In practice, if this function returns `false`, then such result must be
503    /// trusted, _i.e._, transmuting such instance to the `Self` type will,
504    /// at the very least, break a _safety_ invariant, and it will even most
505    /// probably break a _validity_ invariant.
506    ///
507    /// On the other hand, if the function returns `true`, then the result is
508    /// inconclusive; there is no explicit reason to stop going on, but that
509    /// doesn't necessarily make it sound.
510    ///
511    /// # TL,DR
512    ///
513    /// > This function **may yield false positives** but no false negatives.
514    ///
515    /// ## Example: `Self = &'borrow i32`
516    ///
517    /// When `Self = &'borrow i32`, we know that the backing pointer is
518    /// necessarily non-null and well-aligned.
519    ///
520    /// This means that bit-patterns such as `0 as *const i32` or
521    /// `37 as *const i32` are "blatantly unsound" to transmute to a
522    /// `&'borrow i32`, and thus `<&'borrow i32 as ReprC>::is_valid` will
523    /// return `false` in such cases.
524    ///
525    /// But if given `4 as *const i32`, or if given `{ let p = &*Box::new(42)
526    /// as *const i32; p }`, then `is_valid` will return `true` in both cases,
527    /// since it doesn't know better.
528    ///
529    /// ## Example: `bool` or `#[repr(u8)] enum Foo { A, B }`
530    ///
531    /// In the case of `bool`, or in the case of a `#[repr(<integer>)]`
532    /// field-less enum, then the valid bit-patterns and the invalid
533    /// bit-patterns are all known and finite.
534    ///
535    /// In that case, `ReprC::is_valid` will return a `bool` that truly
536    /// represents the validity of the bit-pattern, in both directions
537    ///
538    ///   - _i.e._, no false positives (_validity_-wise);
539    ///
540    /// Still, there may be _safety_ invariants involved with custom types,
541    /// so even then it is unclear.
542    fn is_valid(it: &'_ Self::CLayout) -> bool;
543}
544
545pub type CLayoutOf<ImplReprC> = <ImplReprC as ReprC>::CLayout;
546
547#[doc(hidden)] /** For clarity;
548                   this macro may be stabilized
549                   if downstream users find it useful
550                **/
551#[macro_export]
552#[cfg_attr(rustfmt, rustfmt::skip)]
553macro_rules! from_CType_impl_ReprC {(
554    $(@for[$($generics:tt)*])? $T:ty $(where $($bounds:tt)*)?
555) => (
556    unsafe
557    impl$(<$($generics)*>)? $crate::layout::ReprC
558        for $T
559    where
560        $($($bounds)*)?
561    {
562        type CLayout = Self;
563
564        #[inline]
565        fn is_valid (_: &'_ Self::CLayout)
566          -> bool
567        {
568            true
569        }
570    }
571)}
572
573#[inline]
574pub unsafe fn from_raw_unchecked<T: ReprC>(c_layout: T::CLayout) -> T {
575    if let Some(it) = unsafe { from_raw::<T>(c_layout) } {
576        it
577    } else {
578        if cfg!(debug_assertions) || cfg!(test) {
579            panic!(
580                "Error: not a valid bit-pattern for the type `{}`",
581                // c_layout,
582                ::core::any::type_name::<T>(),
583            );
584        } else {
585            unsafe { ::core::hint::unreachable_unchecked() }
586        }
587    }
588}
589
590#[deny(unsafe_op_in_unsafe_fn)]
591#[inline]
592pub unsafe fn from_raw<T: ReprC>(c_layout: T::CLayout) -> Option<T> {
593    if <T as ReprC>::is_valid(&c_layout).not() {
594        None
595    } else {
596        Some(unsafe {
597            const_assert! {
598                for [T]
599                    [T : ReprC] => [T::CLayout : Copy]
600            }
601            crate::utils::transmute_unchecked(c_layout)
602        })
603    }
604}
605
606#[deny(unsafe_op_in_unsafe_fn)]
607#[inline]
608pub unsafe fn into_raw<T: ReprC>(it: T) -> T::CLayout {
609    unsafe { crate::utils::transmute_unchecked(::core::mem::ManuallyDrop::new(it)) }
610}
611
612pub use impls::Opaque;
613pub(crate) mod impls;
614
615mod niche;
616
617#[apply(hidden_export)]
618use niche::HasNiche as __HasNiche__;
619
620#[apply(hidden_export)]
621trait Is {
622    type EqTo: ?Sized;
623}
624impl<T: ?Sized> Is for T {
625    type EqTo = Self;
626}
627
628/// Alias for `ReprC where Self::CLayout::OPAQUE_KIND = OpaqueKind::Concrete`
629pub trait ConcreteReprC
630where
631    Self: ReprC,
632{
633    type ConcreteCLayout: Is<EqTo = CLayoutOf<Self>> + CType<OPAQUE_KIND = OpaqueKind::Concrete>;
634}
635impl<T: ?Sized> ConcreteReprC for T
636where
637    Self: ReprC,
638    CLayoutOf<Self>: CType<OPAQUE_KIND = OpaqueKind::Concrete>,
639{
640    type ConcreteCLayout = CLayoutOf<Self>;
641}
642
643#[apply(hidden_export)]
644fn __assert_concrete__<T>()
645where
646    T: ConcreteReprC,
647{
648}