use std::{fmt, cell}; use std::any::Any; use crate::arg::ArgBuilder; use crate::{Path as PathName, Interface as IfaceName, Member as MemberName, Signature, Message, arg}; use super::crossroads::{Crossroads, PathData, MLookup}; use super::info::{MethodInfo, PropInfo}; use super::MethodErr; pub struct DebugMethod(pub H::Method); impl fmt::Debug for DebugMethod { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "...") } } pub struct DebugProp(pub Option, pub Option); impl fmt::Debug for DebugProp { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "...") } } pub trait Handlers { type Method; type GetProp; type SetProp; type Iface; } /// Parallel tree - Par #[derive(Debug, Clone, Copy, Default)] pub struct Par; impl Par { pub fn typed_getprop(getf: G) -> ::GetProp where G: Fn(&I, &ParInfo) -> Result + Send + Sync + 'static { Box::new(move |data, ia, info| { let iface: &I = data.downcast_ref().unwrap(); let t = getf(iface, info)?; ia.append(t); Ok(()) }) } pub fn typed_setprop arg::Get<'z>, S>(setf: S) -> ::SetProp where S: Fn(&I, &ParInfo, T) -> Result<(), MethodErr> + Send + Sync + 'static { Box::new(move |data, ii, info| { let iface: &I = data.downcast_ref().unwrap(); let t: T = ii.read()?; setf(iface, info, t) }) } } #[derive(Debug)] pub struct ParInfo<'a> { lookup: MLookup<'a, Par>, message: &'a Message, } impl<'a> ParInfo<'a> { pub fn msg(&self) -> &Message { self.message } pub (super) fn new(msg: &'a Message, lookup: MLookup<'a, Par>) -> Self { ParInfo { lookup, message: msg } } pub fn path_data(&self) -> &PathData { self.lookup.data } pub fn crossroads(&self) -> &Crossroads { self.lookup.cr } } impl Handlers for Par { type Method = Box Option + Send + Sync + 'static>; type GetProp = Box Result<(), MethodErr> + Send + Sync + 'static>; type SetProp = Box Result<(), MethodErr> + Send + Sync + 'static>; type Iface = Box; } impl MethodInfo<'_, Par> { pub fn new_par(name: N, f: F) -> Self where F: Fn(&T, &ParInfo) -> Result, MethodErr> + Send + Sync + 'static, N: Into>, T: Any + Send + Sync + 'static, { Self::new(name.into(), Box::new(move |data, info| { let x = data.downcast_ref().unwrap(); f(x, info).unwrap_or_else(|e| { Some(e.to_message(info.message)) }) })) } } /// Mutable, non-Send tree #[derive(Debug, Clone, Copy, Default)] pub struct Mut; #[derive(Debug)] pub struct MutCtx<'a> { message: &'a Message, send_extra: cell::RefCell>, } impl<'a> MutCtx<'a> { pub fn msg(&self) -> &Message { self.message } pub fn send(&self, msg: Message) { self.send_extra.borrow_mut().push(msg); } pub (super) fn new(msg: &'a Message) -> Self { MutCtx { message: msg, send_extra: Default::default() } } } impl Handlers for Mut { type Method = MutMethod; type GetProp = Box Result<(), MethodErr> + 'static>; type SetProp = Box Result<(), MethodErr> + 'static>; type Iface = Box; } pub struct MutMethod(pub (super) MutMethods); pub (super) enum MutMethods { MutIface(Box Option + 'static>), // Info(Box Option + 'static>), // MutCr(fn(&mut Crossroads, &Message) -> Vec), } impl Mut { pub fn typed_method_iface(mut f: F) -> ::Method where F: FnMut(&mut I, &MutCtx, IA) -> Result + 'static { MutMethod(MutMethods::MutIface(Box::new(move |data, info| { let iface: &mut I = data.downcast_mut().unwrap(); let ia = match IA::read(info.msg()) { Err(e) => return Some(MethodErr::from(e).to_message(info.msg())), Ok(ia) => ia, }; match f(iface, info, ia) { Err(e) => Some(e.to_message(info.msg())), Ok(r) => { let mut m = info.msg().method_return(); OA::append(r, &mut m); Some(m) }, } }))) } }