Skip to main content

diffr_plugin_sdk/
native.rs

1//! Native registrations contributed by linked plugin crates.
2use crate::types::SourceSides;
3use crate::{tree, FileEntry, Move, Plugin, QuerySource};
4
5/// The object-safe form of a plugin, after its options have been deserialized.
6pub trait Instance: Send + Sync {
7    fn queries(&self) -> anyhow::Result<Vec<QuerySource>>;
8    fn enrich(
9        &self,
10        file: &FileEntry,
11        sides: &SourceSides,
12    ) -> anyhow::Result<Vec<crate::Annotation>>;
13    fn classify(&self, file: &FileEntry) -> anyhow::Result<Vec<String>>;
14    fn mutate(&self, file: &FileEntry, sides: &SourceSides) -> anyhow::Result<Vec<Move>>;
15}
16
17/// A name and constructor, registered without instantiating the plugin.
18pub struct Registration {
19    pub name: &'static str,
20    pub create: fn(&str) -> anyhow::Result<Box<dyn Instance>>,
21}
22
23#[doc(hidden)]
24pub fn create<P: Plugin + Send + Sync + 'static>(
25    options: &str,
26) -> anyhow::Result<Box<dyn Instance>> {
27    let options = serde_json::from_str(options)
28        .map_err(|error| anyhow::anyhow!("invalid options: {error}"))?;
29    Ok(Box::new(Adapter(P::new(options)?)))
30}
31
32struct Adapter<P>(P);
33
34impl<P: Plugin + Send + Sync> Instance for Adapter<P> {
35    fn enrich(
36        &self,
37        file: &FileEntry,
38        sides: &SourceSides,
39    ) -> anyhow::Result<Vec<crate::Annotation>> {
40        self.0.enrich(file, &tree::sides(sides)?)
41    }
42    fn queries(&self) -> anyhow::Result<Vec<QuerySource>> {
43        self.0.queries()
44    }
45    fn classify(&self, file: &FileEntry) -> anyhow::Result<Vec<String>> {
46        self.0.classify(file)
47    }
48    fn mutate(&self, file: &FileEntry, sides: &SourceSides) -> anyhow::Result<Vec<Move>> {
49        self.0.mutate(file, &tree::sides(sides)?)
50    }
51}