feat: add abi stable crates
This commit is contained in:
154
__ffi/abi_stable_crates/interface/src/commands.rs
Normal file
154
__ffi/abi_stable_crates/interface/src/commands.rs
Normal file
@@ -0,0 +1,154 @@
|
||||
use crate::{PluginId,WhichPlugin};
|
||||
|
||||
use std::fmt;
|
||||
use serde::{
|
||||
Serialize,Deserialize,
|
||||
de::{self,Deserializer, DeserializeOwned, IgnoredAny, Visitor, MapAccess, Error as _},
|
||||
};
|
||||
use abi_stable::{StableAbi, std_types::*};
|
||||
|
||||
/// The commands that map to methods in the Plugin trait.
|
||||
// This is intentionally not `#[derive(StableAbi)]`,
|
||||
// since it can be extended in minor versions of the interface.
|
||||
// I has to be serialized to pass it through ffi.
|
||||
#[derive(Debug,Clone,PartialEq,Eq,Serialize,Deserialize)]
|
||||
pub enum BasicCommand{
|
||||
GetCommands,
|
||||
}
|
||||
|
||||
|
||||
/// These is the (serialized) return value of calling `PluginExt::send_basic_command`.
|
||||
// This is intentionally not `#[derive(StableAbi)]`,
|
||||
// since it can be extended in minor versions of the interface.
|
||||
// I has to be serialized to pass it through ffi.
|
||||
#[derive(Debug,Clone,PartialEq,Eq,Serialize,Deserialize)]
|
||||
pub enum BasicRetVal{
|
||||
GetCommands(RVec<CommandDescription>),
|
||||
}
|
||||
|
||||
|
||||
// This is intentionally not `#[derive(StableAbi)]`,
|
||||
// since it can be extended in minor versions of the interface.
|
||||
// I has to be serialized to pass it through ffi.
|
||||
#[derive(Debug,Clone,PartialEq,Eq,Serialize,Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum CommandUnion<T>{
|
||||
ForPlugin(T),
|
||||
Basic(BasicCommand),
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug,Clone,PartialEq,Eq,Serialize,Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum ReturnValUnion<T>{
|
||||
ForPlugin(T),
|
||||
Basic(BasicRetVal),
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/// A partially deserialize command,that only deserialized its variant.
|
||||
#[derive(Debug,Clone)]
|
||||
pub struct WhichVariant{
|
||||
pub variant:RString,
|
||||
}
|
||||
|
||||
|
||||
struct WhichVariantVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for WhichVariantVisitor{
|
||||
type Value = WhichVariant;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a map with a single entry,or a string")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<WhichVariant, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(WhichVariant{variant:value.to_string().into()})
|
||||
}
|
||||
|
||||
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
|
||||
where
|
||||
M: MapAccess<'de>,
|
||||
{
|
||||
let (variant,_)=access.next_entry::<RString,IgnoredAny>()?
|
||||
.ok_or_else(||M::Error::custom("Expected a map with a single entry"))?;
|
||||
if let Some((second,_))=access.next_entry::<RString,IgnoredAny>()? {
|
||||
let s=format!(
|
||||
"Expected a map with a single field,\n\
|
||||
instead found both {{ \"{}\":... , \"{}\": ... }}",
|
||||
variant,
|
||||
second,
|
||||
);
|
||||
return Err(M::Error::custom(s));
|
||||
}
|
||||
Ok(WhichVariant{variant})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for WhichVariant{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_map(WhichVariantVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/// Denotes this as a command type.
|
||||
pub trait CommandTrait:Serialize{
|
||||
type Returns:DeserializeOwned;
|
||||
}
|
||||
|
||||
impl CommandTrait for BasicCommand{
|
||||
type Returns=BasicRetVal;
|
||||
}
|
||||
|
||||
|
||||
/// Describes a command.
|
||||
#[repr(C)]
|
||||
#[derive(Debug,Clone,PartialEq,Eq,Serialize,Deserialize,StableAbi)]
|
||||
pub struct CommandDescription{
|
||||
/// A description of what this command does.
|
||||
pub name:RCow<'static,str>,
|
||||
/// A description of what this command does,
|
||||
/// optionally with a description of the command format.
|
||||
pub description:RCow<'static,str>,
|
||||
}
|
||||
|
||||
|
||||
impl CommandDescription{
|
||||
pub fn from_literals(
|
||||
name:&'static str,
|
||||
description:&'static str,
|
||||
)->Self{
|
||||
CommandDescription{
|
||||
name:name.into(),
|
||||
description:description.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug,Clone,PartialEq,Eq,StableAbi)]
|
||||
pub struct AsyncCommand{
|
||||
pub from:PluginId,
|
||||
pub which_plugin:WhichPlugin,
|
||||
pub command:RString,
|
||||
}
|
||||
Reference in New Issue
Block a user