=head1 NAME

nbdkit-rust-plugin - writing nbdkit plugins in Rust

=head1 SYNOPSIS

 nbdkit /path/to/libplugin.so [arguments...]

=head1 DESCRIPTION

This manual page describes how to write nbdkit plugins in compiled
Rust code.  Rust plugins are compiled to F<*.so> files (the same as
plugins written in C) and are used in the same way.

=head1 WRITING A RUST NBDKIT PLUGIN

Broadly speaking, Rust nbdkit plugins work like C ones, so you should
read L<nbdkit-plugin(3)> first.

You should also look at
L<https://github.com/libguestfs/nbdkit/blob/master/plugins/rust/src/lib.rs>
and
L<https://github.com/libguestfs/nbdkit/blob/master/plugins/rust/examples/ramdisk.rs>
in the nbdkit source tree.  The first describes the plugin interface
for Rust plugins and the second provides a simple example.

We may change how Rust plugins are written in future to make them more
idiomatic.  At the moment each callback corresponds directly to a C
callback - in fact each is called directly from the server.

Your Rust code should define a public C<plugin_init> function which
returns a pointer to a C<Plugin> struct.  This struct is exactly
compatible with the C struct used by C plugins.

 extern crate nbdkit;
 use nbdkit::*;
 use nbdkit::ThreadModel::*;
 
 #[no_mangle]
 extern fn myplugin_thread_model () -> ThreadModel {
    SerializeAllRequests
 }
 
 //... more functions
 
 pub extern fn plugin_init () -> *const Plugin {
    // Plugin name.
    let name = "myplugin\0"
      as *const str as *const [c_char] as *const c_char;

    // Create a mutable plugin, setting the 4 required fields.
    let mut plugin = Plugin::new (
        name,
        myplugin_open,
        myplugin_get_size,
        myplugin_pread
    );
    // Update any other fields as required.
    plugin.close = Some (myplugin_close);
    plugin.pwrite = Some (myplugin_pwrite);
    plugin.thread_model = Some (myplugin_thread_model);

    // Return the pointer.
    let plugin = Box::new(plugin);
    return Box::into_raw(plugin);
}

=head2 Compiling a Rust nbdkit plugin

Because you are building a C-compatible shared library, the crate type
must be set to:

 crate-type = ["cdylib"]

After compiling using C<cargo build> you can then use
C<libmyplugin.so> as an nbdkit plugin (see L<nbdkit(1)>,
L<nbdkit-plugin(3)>):

 nbdkit ./libmyplugin.so [args ...]

=head2 Threads

One of the members in C<Plugin> returned by C<plugin_init> is
C<thread_model>, which must return one of the values in the table
below. For more information on thread models, see
L<nbdkit-plugin(3)/THREADS>.  If this optional function is not
provided, the thread model defaults to
C<nbdkit::ThreadModel::Parallel>.

=over 4

=item C<nbdkit::ThreadModel::SerializeConnections>

=item C<nbdkit::ThreadModel::SerializeAllRequests>

=item C<nbdkit::ThreadModel::SerializeRequests>

=item C<nbdkit::ThreadModel::Parallel>

=back

=head2 Missing callbacks

=over 4

=item Missing: C<can_extents> and C<extents>

These are not yet supported.

=back

=head1 VERSION

Rust plugins first appeared in nbdkit 1.12.

=head1 SEE ALSO

L<nbdkit(1)>,
L<nbdkit-plugin(3)>,
L<cargo(1)>.

=head1 AUTHORS

Richard W.M. Jones

=head1 COPYRIGHT

Copyright (C) 2019 Red Hat Inc.
