gravel_ffi/
provider.rs

1use crate::config::PluginConfigAdapter;
2use crate::hit::{ArcDynHit, clone_hit_arc};
3use abi_stable::StableAbi;
4use abi_stable::sabi_trait;
5use abi_stable::std_types::{RBox, RStr, RVec};
6
7/// FFI-safe [`ProviderInner`] trait object.
8pub type BoxDynProvider = ProviderInner_TO<'static, RBox<()>>;
9
10/// This trait is auto-implemented with the [`crate::gravel_provider`] macro.
11///
12/// It does some boilerplate conversions to reduce complexity in the real [`Provider`].
13#[sabi_trait]
14pub trait ProviderInner: Send {
15	fn query(&self, query: RStr<'_>) -> ProviderResult;
16	fn clear_caches(&self) {
17		// do nothing
18	}
19}
20
21/// Abstracts functionality required for a provider.
22///
23/// Implement this and add the [`crate::gravel_provider`] macro to write a provider plugin:
24/// ```
25/// use gravel_ffi::prelude::*;
26///
27/// pub struct MyProvider {
28///     // put state here
29/// }
30///
31/// // give the plugin a memorable name
32/// #[gravel_provider("my_provider")]
33/// impl Provider for MyProvider {
34///     fn new(config: &PluginConfigAdapter<'_>) -> Self {
35///         Self { }
36///     }
37///
38///     fn query(&self, query: &str) -> ProviderResult {
39///         ProviderResult::empty()
40///     }
41/// }
42/// ```
43pub trait Provider {
44	/// Constructs a new provider.
45	fn new(config: &PluginConfigAdapter<'_>) -> Self;
46
47	/// Queries the provider and returns hits.
48	fn query(&self, query: &str) -> ProviderResult;
49
50	/// Clears all caches the provider may keep.
51	fn clear_caches(&self) {
52		// do nothing
53	}
54}
55
56/// A collection of hits returned by a provider.
57#[repr(C)]
58#[derive(StableAbi, Debug)]
59pub struct ProviderResult {
60	pub hits: RVec<ArcDynHit>,
61}
62
63impl ProviderResult {
64	/// Constructs a new [`ProviderResult`] from some hits.
65	#[must_use]
66	pub fn new(hits: impl IntoIterator<Item = impl Into<ArcDynHit>>) -> Self {
67		let hits = hits.into_iter().map(Into::into).collect();
68		Self { hits }
69	}
70
71	/// Constructs a new [`ProviderResult`] from some borrowed hits, cloning them (incrementing the Rc).
72	#[must_use]
73	pub fn from_cached<'a>(hits: impl IntoIterator<Item = &'a ArcDynHit>) -> Self {
74		let hits = hits.into_iter().map(clone_hit_arc).collect();
75		Self { hits }
76	}
77
78	/// Constructs a new [`ProviderResult`] with one or no hits.
79	#[must_use]
80	pub fn from_option(hit: Option<impl Into<ArcDynHit>>) -> Self {
81		hit.map_or_else(Self::empty, Self::single)
82	}
83
84	/// Constructs an empty [`ProviderResult`].
85	#[must_use]
86	pub fn empty() -> Self {
87		Self { hits: RVec::new() }
88	}
89
90	/// Constructs a new [`ProviderResult`] from a single hit.
91	#[must_use]
92	pub fn single(hit: impl Into<ArcDynHit>) -> Self {
93		let hits = vec![hit.into()].into();
94		Self { hits }
95	}
96}