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
/*!

Prefix-types are types that derive StableAbi along with the 
`#[sabi(kind(Prefix(prefix_struct="PrefixEquivalent")))]` attribute.
This is mostly intended for **vtables** and **modules**.

Prefix-types cannot directly be passed through ffi,
instead they must be converted to the type declared with `prefix_struct="PrefixEquivalent"`,
and then pass `&PrefixEquivalent` instead.

To convert `T` to `&PrefixEquivalent` use either:

- `PrefixTypeTrait::leak_into_prefix`:<br>
    Which does the conversion directly,but leaks the value.

- `prefix_type::WithMetadata::new` and then `WithMetadata::as_prefix`:<br>
    Use this if you need a compiletime constant.
    First create a `&'a WithMetadata<Self>` constant,
    then use the `WithMetadata::as_prefix` method at runtime 
    to cast it to `&PrefixEquivalent`.

All fields on `&PrefixEquivalent` are accessed through accessor methods 
with the same name as the fields.

To ensure that libraries stay abi compatible,
the first minor version of the library must apply the `#[sabi(last_prefix_field)]` to some 
field and every minor version after that must add fields at the end (never moving that attribute).
Changing the field that `#[sabi(last_prefix_field)]` is applied to is a breaking change.

Getter methods for fields after the one to which `#[sabi(last_prefix_field)]` was applied to
will return `Option<FieldType>` by default,because those fields might not exist 
(the struct might come from a previous version of the library).
To override how to deal with nonexistent fields,
use the `#[sabi(missing_field())]` attribute,
applied to either the struct or the field.

# Grammar Reference

For the grammar reference,you can look at the documentation for 
[`#[derive(StableAbi)]`](../stable_abi_derive/index.html).

# Examples

### Example 1

Declaring a Prefix-type.

```

use abi_stable::{
    StableAbi,
    std_types::{RDuration,RStr},
};

#[repr(C)]
#[derive(StableAbi)]
#[sabi(kind(Prefix(prefix_struct="Module")))]
#[sabi(missing_field(panic))]
pub struct ModuleVal {
    pub lib_name:RStr<'static>,

    #[sabi(last_prefix_field)]
    pub elapsed:extern fn()->RDuration,

    pub description:RStr<'static>,
}

# fn main(){}

```

### Example 2:Declaring a type with a VTable

Here is the implementation of a Box-like type,which uses a VTable that is itself a Prefix.

```

use std::{
    ops::{Deref,DerefMut},
    marker::PhantomData,
    mem::ManuallyDrop,
};

use abi_stable::{
    StableAbi,
    extern_fn_panic_handling,
    pointer_trait::{CallReferentDrop, StableDeref, TransmuteElement},
    prefix_type::{PrefixTypeTrait,WithMetadata},
};

/// An ffi-safe `Box<T>`
#[repr(C)]
#[derive(StableAbi)]
pub struct BoxLike<T> {
    data: *mut T,
    
    // This can't be a `&'static BoxVtable<T>` because Rust will complain that 
    // `T` does not live for the `'static` lifetime.
    vtable: *const BoxVtable<T>,

    _marker: PhantomData<T>,
}


impl<T> BoxLike<T>{
    pub fn new(value:T)->Self{
        let box_=Box::new(value);
        
        Self{
            data:Box::into_raw(box_),
            vtable:unsafe{ (*BoxVtableVal::VTABLE).as_prefix() },
            _marker:PhantomData,
        }
    }

    // This is to get around a limitation of the type system where
    // vtables of generic types can't just be `&'static VTable<T>`
    // because it complains that T doesn't live forever.
    fn vtable<'a>(&self)->&'a BoxVtable<T>{
        unsafe{ &(*self.vtable) }
    }

    /// Extracts the value this owns.
    pub fn into_inner(self)->T{
        let this=ManuallyDrop::new(self);
        let vtable=this.vtable();
        unsafe{
            // Must copy this before calling `vtable.destructor()`
            // because otherwise it would be reading from a dangling pointer.
            let ret=this.data.read();
            vtable.destructor()(this.data,CallReferentDrop::No);
            ret
        }
    }
}


impl<T> Deref for BoxLike<T> {
    type Target=T;

    fn deref(&self)->&T{
        unsafe{
            &(*self.data)
        }
    }
}

impl<T> DerefMut for BoxLike<T> {
    fn deref_mut(&mut self)->&mut T{
        unsafe{
            &mut (*self.data)
        }
    }
}


impl<T> Drop for BoxLike<T>{
    fn drop(&mut self){
        let vtable=self.vtable();

        unsafe{
            vtable.destructor()(self.data,CallReferentDrop::Yes)
        }
    }
}


#[repr(C)]
#[derive(StableAbi)]
#[sabi(kind(Prefix(prefix_struct="BoxVtable")))]
pub(crate) struct BoxVtableVal<T> {
    #[sabi(last_prefix_field)]
    destructor: unsafe extern "C" fn(*mut T, CallReferentDrop),
}


impl<T> BoxVtableVal<T>{
    const TMP0:Self=Self{
        destructor:destroy_box::<T>,
    };

    // This can't be a `&'static WithMetadata<Self>` because Rust will complain that 
    // `T` does not live for the `'static` lifetime.
    const VTABLE:*const WithMetadata<Self>={
        &WithMetadata::new(PrefixTypeTrait::METADATA,Self::TMP0)
    };
}

unsafe extern "C" fn destroy_box<T>(v: *mut T, call_drop: CallReferentDrop) {
    extern_fn_panic_handling! {
        let mut box_ = Box::from_raw(v as *mut ManuallyDrop<T>);
        if call_drop == CallReferentDrop::Yes {
            ManuallyDrop::drop(&mut *box_);
        }
        drop(box_);
    }
}

# fn main(){}

```


### Example 3:module

This declares,initializes,and uses a module.

```
use abi_stable::{
    StableAbi,
    std_types::RDuration,
    prefix_type::PrefixTypeTrait,
};


#[repr(C)]
#[derive(StableAbi)]
#[sabi(kind(Prefix(prefix_struct="PersonMod")))]
pub struct PersonModVal {

    // The getter for this field is infallible,defined (approximately) like this:
    // ```
    //  extern fn customer_for(&self)->extern fn(Id)->RDuration {
    //      self.customer_for
    //  }
    // ```
    #[sabi(last_prefix_field)]
    pub customer_for: extern fn(Id)->RDuration,

    // The default behavior for the getter is to return an Option<FieldType>,
    // if the field exists it returns Some(_),
    // otherwise it returns None.
    pub bike_count: extern fn(Id)->u32,

    // The getter for this field panics if the field doesn't exist.
    #[sabi(missing_field(panic))]
    pub visits: extern fn(Id)->u32,

    // The getter for this field returns `default_score()` if the field doesn't exist.
    #[sabi(missing_field(with="default_score"))]
    pub score: extern fn(Id)->u32,
    
    // The getter for this field returns `Default::default()` if the field doesn't exist.
    #[sabi(missing_field(default))]
    pub visit_length: Option< extern fn(Id)->RDuration >,

}

fn default_score()-> extern fn(Id)->u32 {
    extern fn default(_:Id)->u32{
        1000
    }

    default
}

type Id=u32;

#
#   static VARS:&[(RDuration,u32)]=&[
#       (RDuration::new(1_000,0),10),
#       (RDuration::new(1_000_000,0),1),
#   ];
#
#   extern fn customer_for(id:Id)->RDuration{
#       VARS[id as usize].0
#   }
# 
#   extern fn bike_count(id:Id)->u32{
#       VARS[id as usize].1
#   }
#   extern fn visits(id:Id)->u32{
#       VARS[id as usize].1
#   }
#   extern fn score(id:Id)->u32{
#       VARS[id as usize].1
#   }
#

/*
    ...
    Elided function definitions
    ...
*/

# fn main(){

let module:&'static PersonMod=
    PersonModVal{
        customer_for,
        bike_count,
        visits,
        score,
        visit_length:None,
    }.leak_into_prefix();


// Getting the value for every field of `module`.

let customer_for: extern fn(Id)->RDuration = 
    module.customer_for();

let bike_count: Option<extern fn(Id)->u32> = 
    module.bike_count();

let visits: extern fn(Id)->u32=
    module.visits();

let score: extern fn(Id)->u32=
    module.score();

let visit_length: Option<extern fn(Id)->RDuration> =
    module.visit_length();

# }


```

*/