zenoh_plugin_trait/
vtable.rs

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
//
// Copyright (c) 2023 ZettaScale Technology
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
//
// Contributors:
//   ZettaScale Zenoh Team, <zenoh@zettascale.tech>
//
use zenoh_result::ZResult;

use crate::{Plugin, StructVersion, FEATURES};

pub type PluginLoaderVersion = u64;
pub const PLUGIN_LOADER_VERSION: PluginLoaderVersion = 1;

type StartFn<StartArgs, Instance> = fn(&str, &StartArgs) -> ZResult<Instance>;

#[repr(C)]
pub struct PluginVTable<StartArgs, Instance> {
    pub plugin_version: &'static str,
    pub plugin_long_version: &'static str,
    pub start: StartFn<StartArgs, Instance>,
}
impl<StartArgs, Instance> StructVersion for PluginVTable<StartArgs, Instance> {
    fn struct_version() -> u64 {
        1
    }
    fn struct_features() -> &'static str {
        FEATURES
    }
}

impl<StartArgs, Instance> PluginVTable<StartArgs, Instance> {
    pub fn new<ConcretePlugin: Plugin<StartArgs = StartArgs, Instance = Instance>>() -> Self {
        Self {
            plugin_version: ConcretePlugin::PLUGIN_VERSION,
            plugin_long_version: ConcretePlugin::PLUGIN_LONG_VERSION,
            start: ConcretePlugin::start,
        }
    }
}

/// This macro adds non-mangled functions which provides plugin version and loads it into the host.
/// If plugin library should work also as static, consider calling this macro under feature condition
///
/// The functions declared by this macro are:
///
/// - `get_plugin_loader_version` - returns `PLUGIN_LOADER_VERSION` const of the crate. The [`PluginsManager`](crate::manager::PluginsManager)
///    will check if this version is compatible with the host.
/// - `get_compatibility` - returns [`Compatibility`](crate::Compatibility) struct which contains all version information (Rust compiler version, features used, version of plugin's structures).
///    The layout  of this structure is guaranteed to be stable until the [`PLUGIN_LOADER_VERSION`](crate::PLUGIN_LOADER_VERSION) is changed,
///    so it's safe to use it in the host after call to `get_plugin_loader_version` returns compatible version.
///    Then the [`PluginsManager`](crate::manager::PluginsManager) compares the returned [`Compatibility`](crate::Compatibility) with it's own and decides if it can continue loading the plugin.
/// - `load_plugin` - returns [`PluginVTable`](crate::PluginVTable) which is able to create plugin's instance.
///
#[macro_export]
macro_rules! declare_plugin {
    ($ty: path) => {
        #[no_mangle]
        fn get_plugin_loader_version() -> $crate::PluginLoaderVersion {
            $crate::PLUGIN_LOADER_VERSION
        }

        #[no_mangle]
        fn get_compatibility() -> $crate::Compatibility {
            $crate::Compatibility::with_plugin_version::<
                <$ty as $crate::Plugin>::StartArgs,
                <$ty as $crate::Plugin>::Instance,
                $ty,
            >()
        }

        #[no_mangle]
        fn load_plugin() -> $crate::PluginVTable<
            <$ty as $crate::Plugin>::StartArgs,
            <$ty as $crate::Plugin>::Instance,
        > {
            $crate::PluginVTable::new::<$ty>()
        }
    };
}