abi_stable 0.10.5

For doing Rust-to-Rust ffi,writing libraries loaded at program startup.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
[![Rust](https://github.com/rodrimati1992/abi_stable_crates/workflows/Rust/badge.svg)](https://github.com/rodrimati1992/abi_stable_crates/actions) [![Join the chat at https://gitter.im/abi_stable_crates/community](https://badges.gitter.im/abi_stable_crates/community.svg)](https://gitter.im/abi_stable_crates/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![](https://img.shields.io/crates/v/abi_stable.svg)][crates-io]
[![api-docs](https://docs.rs/abi_stable/badge.svg)][Documentation]

[crates-io]: https://crates.io/crates/abi_stable

[Documentation]: https://docs.rs/abi_stable

For Rust-to-Rust ffi,
with a focus on creating libraries loaded at program startup,
and with load-time type-checking.

This library allows defining Rust libraries that can be loaded at runtime. 
This isn't possible with the default (Rust) ABI and representation, since it's unstable.

These are some usecases for this library:
    
- Converting a Rust dependency tree from compiling statically into a single binary,
    into one binary (and potentially) many dynamic libraries,
    allowing separate re-compilation on changes.

- Creating a plugin system (without support for unloading).
    
# Features

Currently this library has these features:

- Features the [`sabi_trait`] attribute macro, for creating ffi-safe trait objects.

- Ffi-safe equivalent of some trait objects with [`DynTrait`].

- Provides ffi-safe alternatives/wrappers for many standard library types,
    in the [`std_types`] module.

- Provides ffi-safe wrappers for some types defined in external crates,
    in the [`external_types`] module.

- Provides the [`StableAbi`] trait for asserting that types are ffi-safe.

- The [prefix types] feature for building extensible modules and vtables,
without breaking ABI compatibility.

- Supports ffi-safe [nonexhaustive enums], wrapped in [`NonExhaustive`].

- Checking at load-time that the types in the dynamic library have the expected layout,
    allowing for semver compatible changes while checking the layout of types.

- Provides the [`StableAbi` derive] macro
    to both assert that the type is ffi compatible,
    and to get the layout of the type at load-time to check that it is still compatible.

# Changelog

The changelog is in the "Changelog.md" file.

# Example crates

For **example crates** using `abi_stable` you can look at the 
crates in the examples directory, in the repository for this crate.

To run the example crates you'll generally have to build the `*_impl` crate,
then run the `*_user` crate (all `*_user` crates should have a help message).

These are the example crates:

- 0 - modules and interface types:
    Demonstrates abi_stable "modules"(structs of function pointers),
    and interface types through a command line application with a dynamically linked backend.

- 1 - trait objects:
    Demonstrates ffi-safe trait objects (Generated using the [`sabi_trait`] attribute macro)
    by creating a minimal plugin system.

- 2 - nonexhaustive-enums:
    Demonstrates nonexhaustive-enums as parameters and return values,
    for an application that manages the catalogue of a shop.

<span id = "readme_example"></span>
# Example

This is a full example,demonstrating:

- `user crates`(defined in the Architecture section below).

- Ffi-safe trait objects, generated through the [`sabi_trait`] attribute macro.

- [`DynTrait`]:
An ffi-safe multi-trait object for a selection of traits,
which can also be downcast back into the concrete type.

- `interface crates`(defined in the Architecture section below).

- `ìmplementation crates`(defined in the Architecture section below).

Note that each section represents its own crate ,
with comments for how to turn them into 3 separate crates.

```rust


/////////////////////////////////////////////////////////////////////////////////
//
//                        Application (user crate) 
//
////////////////////////////////////////////////////////////////////////////////

use abi_stable::std_types::RVec;

use interface_crate::{
    AppenderBox,Appender_TO,
    ExampleLib_Ref,BoxedInterface,load_root_module_in_directory,
};

fn main(){
    // The type annotation is for the reader
    let library: ExampleLib_Ref =
        load_root_module_in_directory("./target/debug".as_ref())
            .unwrap_or_else(|e| panic!("{}",e) );

    {
        /*/////////////////////////////////////////////////////////////////////////////////
        
        This block demonstrates `#[sabi_trait]` generated trait objects

        */////////////////////////////////////////////////////////////////////////////////

        // The type annotation is for the reader
        let mut appender: AppenderBox<u32> = library.new_appender()();
        appender.push(100);
        appender.push(200);

        // The primary way to use the methods in the trait is through the inherent methods on 
        // the ffi-safe trait object.
        Appender_TO::push(&mut appender,300);
        appender.append(vec![500,600].into());
        assert_eq!(
            appender.into_rvec(),
            RVec::from(vec![100,200,300,500,600]) 
        );
    }
    {
        /*/////////////////////////////////////////////////////////////////////////////////
        
        This block demonstrates the `DynTrait<>` trait object.
        
        `DynTrait` is used here as a safe opaque type which can only be unwrapped back to the 
        original type in the dynamic library that constructed the `DynTrait` itself.

        */////////////////////////////////////////////////////////////////////////////////

        // The type annotation is for the reader
        let mut unwrapped: BoxedInterface = library.new_boxed_interface()();

        library.append_string()(&mut unwrapped, "Hello".into());
        library.append_string()(&mut unwrapped, ", world!".into());

        assert_eq!(&*unwrapped.to_string(), "Hello, world!");
    }

    println!("success");
}


/////////////////////////////////////////////////////////////////////////////////
//
//                      Interface crate
//
//////////////////////////////////////////////////////////////////////////////////

mod interface_crate{

use std::path::Path;

use abi_stable::{
    StableAbi,
    DynTrait,
    sabi_trait,
    library::{LibraryError, RootModule},
    package_version_strings,
    std_types::{RBox, RString, RVec},
    sabi_types::VersionStrings,
};


/// This struct is the root module,
/// which must be converted to `ExampleLib_Ref` to be passed through ffi.
/// 
/// The `#[sabi(kind(Prefix(prefix_ref="ExampleLib_Ref")))]` 
/// attribute tells `StableAbi` to create an ffi-safe static refernce type
/// for `ExampleLib` called `ExampleLib_Ref`.
/// 
/// The `#[sabi(missing_field(panic))]` attribute specifies that trying to 
/// access a field that doesn't exist must panic with a message saying that
/// the field is inaccessible.
#[repr(C)]
#[derive(StableAbi)] 
#[sabi(kind(Prefix(prefix_ref="ExampleLib_Ref")))]
#[sabi(missing_field(panic))]
pub struct ExampleLib {
    pub new_appender: extern "C" fn() -> AppenderBox<u32>,

    pub new_boxed_interface: extern "C" fn() -> BoxedInterface<'static>,

    /// The `#[sabi(last_prefix_field)]` attribute here means that this is the last
    /// field in this struct that was defined in the first compatible version of the library
    /// (0.1.0, 0.2.0, 0.3.0, 1.0.0, 2.0.0 ,etc),
    /// requiring new fields to always be added below preexisting ones.
    /// 
    /// The `#[sabi(last_prefix_field)]` attribute would stay on this field until the
    /// library bumps its "major" version,
    /// at which point it would be moved to the last field at the time.
    /// 
    #[sabi(last_prefix_field)]
    pub append_string: extern "C" fn(&mut BoxedInterface<'_>, RString),
}


/// The RootModule trait defines how to load the root module of a library.
impl RootModule for ExampleLib_Ref {

    abi_stable::declare_root_module_statics!{ExampleLib_Ref}

    const BASE_NAME: &'static str = "example_library";
    const NAME: &'static str = "example_library";
    const VERSION_STRINGS: VersionStrings = package_version_strings!();
}

/// `#[sabi_trait]` is how one creates an ffi-safe trait object from a trait definition.
/// 
/// In this case the trait object is `Appender_TO<'lt, Pointer<()>, Element>`,where:
/// 
/// - `'lt`:
///     Is the lifetime bound of the type that constructed the trait object
///     (`'static` is the lifetime bound of objects that don't borrow anything).
/// 
/// - `Pointer<()>`:
///     Is any pointer that implements some abi_stable specific traits,
///     this pointer owns the value that implements `Appender`.
/// 
/// - `Element`:
///     This is the element type of the collection that we operate on.
/// 
#[sabi_trait]
pub trait Appender{
    /// The element type of the collection.
    type Element;

    /// Appends one element at the end of the collection.    
    fn push(&mut self, value: Self::Element);
    
    /// Appends many elements at the end of the collection.    
    fn append(&mut self, vec: RVec<Self::Element>);

    /// Converts this collection into an `RVec`.
    /// 
    /// As opposed to regular trait objects,
    /// it is possible to call by-value methods on trait objects generated by `#[sabi_trait]`.
    /// 
    /// The `#[sabi(last_prefix_field)]` attribute here means that this is the last method 
    /// that was defined in the first compatible version of the library
    /// (0.1.0, 0.2.0, 0.3.0, 1.0.0, 2.0.0 ,etc),
    /// requiring new methods to always be added below preexisting ones.
    /// 
    /// The `#[sabi(last_prefix_field)]` attribute would stay on this method until the library 
    /// bumps its "major" version,
    /// at which point it would be moved to the last method at the time.
    /// 
    #[sabi(last_prefix_field)]
    fn into_rvec(self) -> RVec<Self::Element>;
}

/// A type alias for the Appender trait object.
///
/// `'static` here means that the trait object cannot contain any borrows.
pub type AppenderBox<T> = Appender_TO<'static, RBox<()>, T>;



/*

/// This loads the root from the library in the `directory` folder.
///
/// This for the case where this example is copied into the 3 crates.
/// 
pub fn load_root_module_in_directory(directory: &Path) -> Result<ExampleLib_Ref, LibraryError> {
    ExampleLib_Ref::load_from_directory(directory)
}
*/

/// This loads the root module
///
/// This is for the case where this example is copied into a single crate
pub fn load_root_module_in_directory(_: &Path) -> Result<ExampleLib_Ref, LibraryError> {
    ExampleLib_Ref::load_module_with(|| Ok(super::implementation::get_library()) )
}

//////////////////////////////////////////////////////////


/// This type implements `ÌnterfaceType`
/// (because of the `#[sabi(impl_InterfaceType())]` helper attribute of `#[derive(StableAbi)]` ),
/// describing the traits required when constructing `DynTrait<_, TheInterface>`,
/// and are then implemented by it.
#[repr(C)]
#[derive(StableAbi)]
#[sabi(impl_InterfaceType(Sync,Send,Debug,Display))]
pub struct TheInterface;


/// An alias for the trait object used in this example
pub type BoxedInterface<'borr> = DynTrait<'borr, RBox<()>, TheInterface>;

}



/////////////////////////////////////////////////////////////////////////////////
//
//                            Implementation crate
//
// This is generally done in a separate crate than the interface.
//
//////////////////////////////////////////////////////////////////////////////////
//
// If you copy paste this into its own crate use this setting in the 
// Cargo.toml file.
//
// ```
// [lib]
// name = "example_library"
// crate-type = ["cdylib",'rlib']
// ```
//
//
//////////////////////////////////////////////////////////////////////////////////

mod implementation {

use std::fmt::{self, Display};


// Comment this out if this is on its own crate
use super::interface_crate;

use interface_crate::{
    Appender,
    AppenderBox,
    Appender_TO,
    BoxedInterface,
    ExampleLib_Ref,
    ExampleLib,
    TheInterface,
};

use abi_stable::{
    ImplType,
    DynTrait,
    erased_types::TypeInfo,
    export_root_module,
    sabi_extern_fn,
    impl_get_type_info,
    prefix_type::PrefixTypeTrait,
    sabi_trait::prelude::TD_Opaque,
    std_types::{RString, RVec},
};


/// The function which exports the root module of the library.
/// 
/// The root module is exported inside a static of `LibHeader` type,
/// which has this extra metadata:
/// 
/// - The abi_stable version number used by the dynamic library.
/// 
/// - A constant describing the layout of the exported root module,and every type it references.
/// 
/// - A lazily initialized reference to the root module.
/// 
/// - The constructor function of the root module.
/// 
#[export_root_module]
pub fn get_library() -> ExampleLib_Ref {
    ExampleLib{
        new_appender,
        new_boxed_interface,
        append_string,
    }.leak_into_prefix()
}

/// This is the `implementation crate` dual of `TheInterface`.
/// 
/// A `DynTrait<_, TheInterface>` is expected to (but not enforced to) only be 
/// constructed from a `StringBuilder`.
#[derive(Debug,Clone)]
pub struct StringBuilder{
    pub text: String,
    pub appended: Vec<RString>,
}

///
/// Defines this as an `implementation type`,
/// this trait is mostly for improving error messages when unerasing the DynTrait.
///
impl ImplType for StringBuilder {
    type Interface = TheInterface;

    const INFO: &'static TypeInfo = impl_get_type_info! { Self };
}

impl Display for StringBuilder{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result{
        fmt::Display::fmt(&self.text, f)
    }
}

impl StringBuilder{
    /// Appends the string at the end.
    pub fn append_string(&mut self, string: RString){
        self.text.push_str(&string);
        self.appended.push(string);
    }
}

#[sabi_extern_fn]
pub fn new_appender() -> AppenderBox<u32>{
    What `TD_Opaque` does here is specify that the trait object cannot be downcasted,
    disallowing the `Appender_TO` from being unwrapped back into an `RVec<u32>`
    using the `trait_object.obj.*_downcast_*()` methods.
    
    To be able to unwrap a `#[sabi_trait]` trait object back into the type it 
    was constructed with,you must:

    - Have a type that implements `std::anu::Any`
    (it requires that the type doesn't borrow anything).

    - Pass `TD_CanDowncast` instead of `TD_Opaque` to Appender_TO::{from_value,from_ptr}.

    - Unerase the trait object back into the original type with
        `trait_object.obj.downcast_into_impltype::<RVec<u32>>().unwrap()` 
        (or the other unerasure methods).

    Unerasing a trait object will fail in any of these conditions:

    - It wasn't constructed in the same dynamic library.
    
    - It's not the same type.

    - It was constructed with `TD_Opaque`.

    */
    Appender_TO::from_value(RVec::new(),TD_Opaque)
}


/// Constructs a BoxedInterface.
#[sabi_extern_fn]
fn new_boxed_interface() -> BoxedInterface<'static>{
    DynTrait::from_value(StringBuilder{
        text:"".into(),
        appended:vec![],
    })
}


/// Appends a string to the erased `StringBuilderType`.
#[sabi_extern_fn]
fn append_string(wrapped: &mut BoxedInterface<'_>, string: RString){
    wrapped
        .downcast_as_mut_impltype::<StringBuilder>() // Returns `Result<&mut StringBuilder, _>`
        .unwrap() // Returns `&mut StringBuilder`
        .append_string(string);
}


impl<T> Appender for RVec<T>{
    type Element=T;
    fn push(&mut self,value:Self::Element){
        self.push(value);
    }
    fn append(&mut self,vec:RVec<Self::Element>){
        self.extend(vec);
    }
    fn into_rvec(self) -> RVec<Self::Element>{
        self
    }
}


}

```



# Safety

This library ensures that the loaded libraries are safe to use through these mechanisms:

- The abi_stable ABI of the library is checked,
    Each `0.y.0` version and `x.0.0` version of abi_stable defines its own ABI 
    which is incompatible with previous versions.

- Types are recursively checked when the dynamic library is loaded,
    before any function can be called.

Note that this library assumes that dynamic libraries come from a benign source,
these checks are done purely to detect programming errors.

# Planned features

None right now.

# Non-features (extremely unlikely to be added)

Supporting library unloading,
since this requires building the entire library with the assumption that anything 
might get unloaded at any time.

# Architecture


This is a way that users can structure their libraries to allow for dynamic linking.

For how to evolve dynamically loaded libraries loaded using the safe API in abi_stable 
[look here](https://docs.rs/abi_stable/*/abi_stable/docs/library_evolution/index.html).

### Interface crate

A crate which declares:

- The root module (a structs of function pointers/other modules),
    which implements the [`RootModule`] trait,
    exported from the dynamic library.

- All the sub-modules of the root module.

- All the public types passed to and returned by the functions.

- Optionally:
    declare the ffi-safe traits with the [`sabi_trait`] attribute,
    used as trait objects in the public interface.

- Optionally:
    declares ìnterface types,types which implement [`InterfaceType`],
    used to specify the traits usable in the [`DynTrait`] ffi-safe trait object .


### Implementation crate

The crate compiled as a dynamic library that:

- Implements all the functions declared in the `interface crate`.

- Declares a function to export the root module,
    using the [`export_root_module`] attribute to export the module.

- Optionally:
    Implement traits that were annotated with the [`sabi_trait`] attribute,
    constructing their trait objects exposed in the public API.

- Optionally:create types which implement `ImplType<Iterface= FooInterface >`,
    where `FooInterface` is a type that implements [`InterfaceType`] declared in
    the interface crate,
    so as to be able to use wrap it in [`DynTrait`]s of that interface.

### User crate

A crate that that declares the `ìnterface crate` as a dependency,
and loads the pre-compiled `implementation crate` dynamic library from some path.

# Minimum Rust version

This crate support Rust back to 1.46.0

You can manually enable support for Rust past 1.46.0 with the `rust_*_*` cargo features.

Had to bump the MSRV from 1.41.0 to 1.46.0 because fixing Rust nightly
compatibility caused Internal Compiler Errors in older Rust versions.

# Crate Features

These are default cargo features that enable optional crates :

- "channels":
    Depends on `crossbeam-channel`,
    wrapping channels from it for ffi in `abi_stable::external_types::crossbeam_channel` .

- "serde_json":
    Depends on `serde_json`,
    providing ffi-safe equivalents of 
    `&serde_json::value::RawValue` and `Box<serde_json::value::RawValue>`,
    in `abi_stable::external_types::serde_json` .


To disable the default features use:
```
[dependencies.abi_stable]
version = "<current_version>"
default-features = false
features = [  ]
```
enabling the features you need in the `features` array.


### Manually enabled

These are crate features to manually enable support for newer language features:

- "rust_1_51_0":
Enables impls which require using const generics,
including implementing StableAbi for arrays of all lengths,
requires Rust Rust 1.51.0 or higher.

- "rust_latest_stable":
Enables the "rust_1_*" features for all the stable releases.

# Tools

Here are some tools,all of which are in the "tools" directory(folder).

### sabi_extract

A program to extract a variety of information from an abi_stable dynamic library.

# License

abi_stable is licensed under either of

    Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
    MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

# Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in abi_stable by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.



[`std_types`]: https://docs.rs/abi_stable/*/abi_stable/std_types/index.html
[`external_types`]: https://docs.rs/abi_stable/*/abi_stable/external_types/index.html
[prefix types]: https://docs.rs/abi_stable/*/abi_stable/docs/prefix_types/index.html
[Prefix types]: https://docs.rs/abi_stable/*/abi_stable/docs/prefix_types/index.html
[nonexhaustive enums]: https://docs.rs/abi_stable/*/abi_stable/docs/sabi_nonexhaustive/index.html
[Nonexhaustive enums]: https://docs.rs/abi_stable/*/abi_stable/docs/sabi_nonexhaustive/index.html
[library_evolution]: https://docs.rs/abi_stable/*/abi_stable/docs/library_evolution/index.html
[`NonExhaustive`]: https://docs.rs/abi_stable/*/abi_stable/nonexhaustive_enum/struct.NonExhaustive.html
[the readme]: https://github.com/rodrimati1992/abi_stable_crates/blob/master/readme.md
[`RootModule`]: https://docs.rs/abi_stable/*/abi_stable/library/trait.RootModule.html
[`StableAbi`]: https://docs.rs/abi_stable/*/abi_stable/abi_stability/stable_abi_trait/trait.StableAbi.html
[`sabi_trait`]: https://docs.rs/abi_stable/*/abi_stable/attr.sabi_trait.html
[Trait objects]: https://docs.rs/abi_stable/*/abi_stable/attr.sabi_trait.html
[`StableAbi` derive]: https://docs.rs/abi_stable/*/abi_stable/derive.StableAbi.html
[`DynTrait`]: https://docs.rs/abi_stable/*/abi_stable/struct.DynTrait.html
[Troubleshooting]: https://docs.rs/abi_stable/*/abi_stable/docs/troubleshooting/index.html
[Unsafe code guidelines]: https://docs.rs/abi_stable/*/abi_stable/docs/unsafe_code_guidelines/index.html

[`InterfaceType`]: https://docs.rs/abi_stable/*/abi_stable/trait.InterfaceType.html
[`export_root_module`]: https://docs.rs/abi_stable/*/abi_stable/attr.export_root_module.html