1#![warn(warnings)] #![allow(clippy::all)]
3#![cfg_attr(rustfmt, rustfmt::skip)]
4#![cfg_attr(feature = "nightly",
5 feature(doc_cfg)
6)]
7#![cfg_attr(not(feature = "std"),
8 no_std,
9)]
10
11#![allow(
12 nonstandard_style,
13 trivial_bounds,
14 unused_parens,
15)]
16#![warn(
17 missing_copy_implementations,
18 missing_debug_implementations,
19)]
20#![deny(
21 bare_trait_objects,
22 elided_lifetimes_in_paths,
23 unconditional_recursion,
24 unused_must_use,
25)]
26#![doc = include_str!("../README.md")]
27
28#[macro_use]
29extern crate macro_rules_attribute;
30
31#[macro_use]
32#[path = "utils/_mod.rs"]
33#[doc(hidden)] pub
34mod __utils__;
35use __utils__ as utils;
36
37#[apply(hidden_export)]
38use ::paste;
39
40pub use ::safer_ffi_proc_macros::ffi_export;
88
89pub use ::safer_ffi_proc_macros::cfg_headers;
92
93pub use ::safer_ffi_proc_macros::c_str as c;
129
130pub use ::safer_ffi_proc_macros::derive_ReprC;
223
224#[macro_use]
225#[path = "layout/_mod.rs"]
226pub mod layout;
227
228__cfg_headers__! {
229 #[doc(hidden)] pub
230 use ::inventory;
231
232 #[cfg_attr(feature = "nightly",
233 doc(cfg(feature = "headers")),
234 )]
235 #[path = "headers/_mod.rs"]
236 pub
237 mod headers;
238
239 #[allow(missing_copy_implementations, missing_debug_implementations)]
240 #[doc(hidden)] pub
241 struct FfiExport {
242 pub
243 name: &'static str,
244
245 pub
246 gen_def:
247 fn(&mut dyn headers::Definer, headers::Language)
248 -> std::io::Result<()>
249 ,
250 }
251
252 self::inventory::collect!(FfiExport);
253}
254
255cfg_alloc! {
256 extern crate alloc;
257}
258
259cfg_alloc! {
260 pub
261 mod boxed;
262}
263
264pub
265mod bytes;
266
267#[doc(inline)]
268pub use self::c_char_module::c_char;
269#[path = "c_char.rs"]
270mod c_char_module;
271
272pub
273mod char_p;
274
275pub
276mod closure;
277
278#[cfg(feature = "dyn-traits")]
279#[cfg_attr(feature = "nightly",
280 doc(cfg(feature = "dyn-traits")),
281)]
282#[path = "dyn_traits/_mod.rs"]
283pub
284mod dyn_traits;
285
286#[cfg(feature = "futures")]
287#[cfg_attr(all(docs, feature = "nightly"),
288 doc(cfg(feature = "futures"))
289)]
290#[doc(no_inline)]
291pub use dyn_traits::futures;
292
293pub
294mod libc;
295
296pub
297mod option;
298
299pub
300mod ptr;
301
302pub
303mod slice;
304
305#[cfg(feature = "stabby")]
306#[cfg_attr(all(docs, feature = "nightly"),
307 doc(cfg(feature = "stabby"))
308)]
309#[path = "stabby/_mod.rs"]
310pub
311mod stabby;
312
313#[path = "string/_mod.rs"]
314pub
315mod string;
316
317#[doc(no_inline)]
318pub
319use tuple::*;
320
321pub
322mod tuple;
323
324cfg_alloc! {
325 #[doc(inline)]
326 pub use string::String;
327
328 #[doc(inline)]
329 pub use vec::Vec;
330 pub mod vec;
331}
332
333#[doc(inline)]
334pub use layout::impls::c_int;
335
336pub
337mod prelude {
338 #[doc(no_inline)]
339 pub use crate::{
340 ffi_export,
341 layout::ReprC,
342 };
343 pub
344 mod char_p {
345 #[doc(no_inline)]
346 pub use crate::char_p::{
347 char_p_raw as Raw,
348 char_p_ref as Ref,
349 };
350 cfg_alloc! {
351 #[doc(no_inline)]
352 pub use crate::char_p::{
353 char_p_boxed as Box,
354 new,
355 };
356 }
357 }
358 pub
359 mod c_slice {
360 #[doc(no_inline)]
361 pub use crate::slice::{
362 slice_mut as Mut,
363 slice_raw as Raw,
364 slice_ref as Ref,
365 };
366 cfg_alloc! {
367 #[doc(no_inline)]
368 pub use crate::slice::slice_boxed as Box;
369 }
370 }
371 pub
372 mod repr_c {
373 cfg_alloc! {
374 #[doc(no_inline)]
375 pub use crate::{
376 boxed::Box,
377 string::String,
378 vec::Vec,
379 option::TaggedOption,
380 };
381
382 pub
383 type Arc<T> = <T as crate::boxed::FitForCArc>::CArcWrapped;
384 }
385 }
386 pub
387 mod str {
388 #[doc(no_inline)]
389 pub use crate::string::{
390 str_ref as Ref,
392 };
393 cfg_alloc! {
394 #[doc(no_inline)]
395 pub use crate::string::str_boxed as Box;
396 }
397 }
398
399 #[doc(no_inline)]
400 pub use {
401 crate::layout::derive_ReprC,
402 ::safer_ffi_proc_macros::derive_ReprC2,
403 crate::c,
404 ::core::{
405 convert::{
406 TryFrom as _,
407 TryInto as _,
408 },
409 ops::Not as _,
410 },
411 };
412
413 pub use ::uninit::prelude::{
414 Out,
416 AsOut,
418 ManuallyDropMut,
420 };
421
422 #[cfg(feature = "dyn-traits")]
423 #[cfg_attr(all(docs, feature = "nightly"),
424 doc(cfg(feature = "dyn-traits"))
425 )]
426 pub use crate::dyn_traits::VirtualPtr;
427}
428
429#[macro_export]
430macro_rules! NULL {() => (
431 $crate::ඞ::ptr::null_mut()
432)}
433
434#[cfg(feature = "log")]
435#[apply(hidden_export)]
436use ::log;
437
438#[cfg(feature = "js")]
439#[path = "js/_mod.rs"]
441pub mod js;
442
443#[apply(hidden_export)]
444#[allow(missing_copy_implementations, missing_debug_implementations)]
445struct __PanicOnDrop__ {} impl Drop for __PanicOnDrop__ {
446 fn drop (self: &'_ mut Self)
447 {
448 panic!()
449 }
450}
451
452#[apply(hidden_export)]
453macro_rules! __abort_with_msg__ { ($($tt:tt)*) => (
454 match ($crate::__PanicOnDrop__ {}) { _ => {
455 $crate::ඞ::__error__!($($tt)*);
456 $crate::ඞ::panic!($($tt)*);
457 }}
458)}
459
460extern crate self as safer_ffi;
461
462#[apply(hidden_export)]
463use __ as ඞ;
464
465#[apply(hidden_export)]
466mod __ {
467 #[cfg(feature = "alloc")]
468 pub extern crate alloc;
469
470 pub use {
471 ::core::{
472 self,
473 marker::PhantomData,
474 pin::Pin,
475 primitive::{
476 u8, u16, u32, usize, u64, u128,
477 i8, i16, i32, isize, i64, i128,
478 bool,
479 char,
480 str,
481 },
482 },
483 ::scopeguard::{
484 self,
485 },
486 crate::{
487 ptr,
488 layout::{
489 CLayoutOf,
490 ConcreteReprC,
491 CType,
492 OpaqueKind,
493 ReprC,
494 __HasNiche__,
495 },
496 prelude::*,
497 },
498 };
499
500 #[cfg(feature = "headers")]
501 pub use {
502 crate::{
503 headers::{
504 Definer,
505 Language,
506 languages::{
507 self,
508 EnumVariant,
509 FunctionArg,
510 HeaderLanguage,
511 StructField,
512 },
513 },
514 inventory,
515 FfiExport,
516 },
517 };
518
519 match_cfg! {
520 feature = "std" => {
521 pub use ::std::{*,
522 self,
523 prelude::rust_2021::*,
524 };
525 },
526 feature = "alloc" => {
527 pub use {
528 ::core::{*,
529 prelude::rust_2021::*,
530 },
531 ::alloc::{
532 boxed::Box,
533 string::String,
534 vec::Vec,
535 },
536 };
537 },
538 _ => {
539 pub use ::core::{*,
540 prelude::rust_2021::*,
541 };
542 }
543 }
544
545 pub
550 type Identity<'hrtb, T> =
551 <T as IdentityIgnoring<'hrtb>>::ItSelf
552 ;
553 pub
555 trait IdentityIgnoring<'__> {
556 type ItSelf : ?Sized;
557 }
558 impl<T : ?Sized> IdentityIgnoring<'_> for T {
559 type ItSelf = Self;
560 }
561
562 match_cfg! {
563 feature = "log" => {
564 #[apply(hidden_export)]
565 macro_rules! __error__ {( $($msg:tt)* ) => (
566 $crate::log::error! { $($msg)* }
567 )}
568 },
569 feature = "std" => {
570 #[apply(hidden_export)]
571 macro_rules! __error__ {( $($msg:tt)* ) => (
572 $crate::ඞ::eprintln! { $($msg)* }
573 )}
574 },
575 _ => {
576 #[apply(hidden_export)]
577 macro_rules! __error__ {( $($msg:tt)* ) => (
578 )}
580 },
581 }
582 pub use __error__;
583
584 #[allow(missing_debug_implementations)]
585 pub
586 struct UnwindGuard (
587 pub &'static str,
588 );
589
590 impl Drop for UnwindGuard {
591 fn drop (self: &'_ mut Self)
592 {
593 let &mut Self(fname) = self;
594 __abort_with_msg__!("\
595 Error, attempted to panic across the FFI \
596 boundary of `{fname}()`, \
597 which is Undefined Behavior.\n\
598 Aborting for soundness.\
599 ");
600 }
601 }
602
603 #[cfg(feature = "alloc")]
604 pub
605 fn append_unqualified_name (
606 out: &'_ mut String,
607 ty_name: &'_ str,
608 )
609 {
610 #[inline(never)]
611 fn mb_split_with<'r> (
612 orig: &'r str,
613 splitter: fn(&'r str) -> Option<(&'r str, &'r str)>,
614 ) -> (&'r str, Option<&'r str>)
615 {
616 splitter(orig).map_or((orig, None), |(l, r)| (l, Some(r)))
617 }
618
619 let ty_name = ty_name.trim();
620 if let Some(tuple_innards) = ty_name.strip_prefix('(') {
621 tuple_innards
623 .strip_suffix(')').unwrap()
624 .split(',')
625 .for_each(|generic| {
626 append_unqualified_name(out, generic);
627 })
628 ;
629 } else if let Some(bracketed_innards) = ty_name.strip_prefix('[') {
630 let (elem_ty, mb_len) = mb_split_with(
632 bracketed_innards.strip_suffix(']').unwrap(),
633 |s| s.rsplit_once(';'),
634 );
635 append_unqualified_name(out, elem_ty);
636 if let Some(len) = mb_len {
637 append_unqualified_name(out, len);
638 }
639 } else {
640 out.push('_');
642 let (mut path, mb_generics) = mb_split_with(
643 ty_name,
644 |s| s.split_once('<'),
645 );
646 let is_valid_for_ident = |c: char| {
647 c.is_alphanumeric() || matches!(c, '_')
648 };
649 if let Some(trait_path) = path.strip_prefix("dyn ") {
650 out.push_str("dyn_");
651 path = trait_path;
652 }
653 if path.chars().all(|c| is_valid_for_ident(c) || c == ':') {
654 let unqualified = path.rsplitn(2, ':').next().unwrap().trim();
655 out.push_str(unqualified);
656 } else {
657 path.chars().for_each(|c| {
659 out.push(if is_valid_for_ident(c) { c } else { '_' });
660 });
661 }
662 if let Some(generics) = mb_generics {
663 let generics = generics.strip_suffix('>').unwrap();
664 generics.split(',').for_each(|generic| {
665 append_unqualified_name(out, generic);
666 });
667 }
668 }
669 }
670
671 #[doc(hidden)] #[macro_export]
673 macro_rules! ඞassert_expr {( $e:expr $(,)? ) => ( $e )}
674 #[doc(inline)]
675 pub use ඞassert_expr as assert_expr;
676}