diff options
author | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2019-12-27 15:20:02 +0200 |
---|---|---|
committer | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2019-12-27 17:57:48 +0200 |
commit | b964a6a033ec9c197ad8cfd2e6bd4b4208cf23c4 (patch) | |
tree | 04a365a74218b1b9a51311a131b4d76d3d16b7a2 /ui/src/plugins/rpc.rs | |
parent | 12509748f6cf7a34e0b15935729c59e31993eb61 (diff) |
Plugins WIP #2
Diffstat (limited to 'ui/src/plugins/rpc.rs')
-rw-r--r-- | ui/src/plugins/rpc.rs | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/ui/src/plugins/rpc.rs b/ui/src/plugins/rpc.rs new file mode 100644 index 00000000..1d3b91a0 --- /dev/null +++ b/ui/src/plugins/rpc.rs @@ -0,0 +1,144 @@ +/* + * meli - plugins + * + * Copyright 2019 Manos Pitsidianakis + * + * This file is part of meli. + * + * meli is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * meli is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with meli. If not, see <http://www.gnu.org/licenses/>. + */ + +use super::*; +use rmp_serde::Deserializer; +use serde::{Deserialize, Serialize}; + +#[derive(Debug)] +pub struct RpcChannel { + stream: UnixStream, + session: Uuid, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub struct PluginGreeting { + version: String, +} + +impl RpcChannel { + pub fn new(mut stream: UnixStream, session: &Uuid) -> Result<RpcChannel> { + let mut ret = RpcChannel { + stream, + session: session.clone(), + }; + let greeting: PluginGreeting = ret.from_read().map_err(|err| { + MeliError::new(format!("Could not get correct plugin greeting: {}", err)) + })?; + debug!(&greeting); + //if greeting.version != "dev" { + // return Err("Plugin is not compatible with our API (dev)".into()); + //} + ret.write_ref(&rmpv::ValueRef::String(session.to_string().as_str().into()))?; + debug!(ret.expect_ack())?; + Ok(ret) + } + + pub fn expect_ack(&mut self) -> Result<()> { + debug!("expect_ack()"); + let ack: u32 = debug!(rmp_serde::decode::from_read(&mut self.stream)) + .map_err(|_| MeliError::new("Plugin did not return ACK."))?; + if 0x6 == ack { + Ok(()) + } else { + Err(MeliError::new("Plugin did not return ACK.")) + } + } + + pub fn ack(&mut self) -> Result<()> { + debug!("ack()"); + debug!(rmpv::encode::write_value_ref( + &mut self.stream, + &rmpv::ValueRef::Integer(0x6.into()) + )) + .map_err(|err| MeliError::new(err.to_string()))?; + let _ = self.stream.flush(); + Ok(()) + } + + pub fn write_ref(&mut self, value_ref: &rmpv::ValueRef) -> Result<()> { + debug!("write_ref() {:?}", value_ref); + debug!(rmpv::encode::write_value_ref(&mut self.stream, value_ref)) + .map_err(|err| MeliError::new(err.to_string()))?; + let _ = self.stream.flush(); + Ok(()) + } + + pub fn read(&mut self) -> Result<rmpv::Value> { + debug!("read()"); + let ret: RpcResult = debug!(rmp_serde::decode::from_read(&mut self.stream)) + .map_err(|err| MeliError::new(err.to_string()))?; + let _ = self.stream.flush(); + self.ack(); + debug!("read() ret={:?}", &ret); + ret.into() + } + + pub fn from_read<T>(&mut self) -> Result<T> + where + T: core::fmt::Debug + serde::de::DeserializeOwned, + { + debug!("from_read()"); + let ret: Result<T> = debug!(rmp_serde::decode::from_read(&mut self.stream)) + .map_err(|err| MeliError::new(err.to_string())); + let _ = self.stream.flush(); + self.ack(); + debug!("read() ret={:?}", &ret); + ret + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +#[serde(tag = "t", content = "c")] +enum RpcResult { + Ok(rmpv::Value), + Err(String), +} + +impl RpcResult { + fn into(self) -> Result<rmpv::Value> { + match self { + RpcResult::Ok(v) => Ok(v), + RpcResult::Err(err) => Err(MeliError::new(err)), + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +#[serde(tag = "t", content = "c")] +pub enum PluginResult<T: core::fmt::Debug + Clone> { + Ok(T), + Err(String), +} + +impl<T: core::fmt::Debug + Clone + serde::Serialize + serde::de::DeserializeOwned> Into<Result<T>> + for PluginResult<T> +{ + fn into(self) -> Result<T> { + match self { + PluginResult::Ok(v) => Ok(v), + PluginResult::Err(err) => Err(MeliError::new(err)), + } + } +} |