use std::fmt::{Display, Formatter}; use rust_lisp::model::Value as RValue; use serde::{Deserialize, Deserializer}; #[derive(Clone, Debug)] pub struct Value(Vec); unsafe impl Send for Value {} unsafe impl Sync for Value {} impl Into for RValue { fn into(self) -> Value { Value(vec![self]) } } impl Into> for Value { fn into(self) -> Vec { self.0 } } impl Display for Value { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { let mut s = String::new(); s.push_str("(begin\n"); for i in &self.0 { s.push_str(&format!("{}\n", i)); } s.push_str(")"); write!(f, "{}", &s) } } impl<'de> Deserialize<'de> for Value { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let s: String = Deserialize::deserialize(deserializer)?; let r: Vec = rust_lisp::parser::parse(&s) .filter_map(|x| x.ok()) .collect(); Ok(Value(r)) } } #[derive(Clone, Debug, Deserialize)] pub struct Program { #[serde(rename = "match")] pub match_: Value, pub cmd: String, #[serde(default)] pub run: Option, } #[derive(Clone, Debug, Deserialize)] pub struct Signal { #[serde(default)] pub run: Option, #[serde(default = "Signal::default_timeout")] pub timeout: u64, } impl Signal { fn default_timeout() -> u64 { 500 } } #[derive(Clone, Debug, Deserialize)] #[serde(untagged)] pub enum ProgramEntry { Program(Program), Signal(Signal), } // Program is only unsafe because Value has dyn Any in it (via Foreign). // if we don't use !Send in Foreign everything is fine. unsafe impl Send for Program {} #[derive(Clone, Debug, Deserialize)] pub struct Config { #[serde(default = "Config::default_timeout")] pub timeout: u64, #[serde(default = "Config::default_init")] pub init: Value, #[serde(default)] pub cmd: Option, #[serde(default = "Config::default_programs")] pub programs: Vec, } // Config is only unsafe because Value has dyn Any in it (via Foreign). // if we don't use !Send in Foreign everything is fine. unsafe impl Send for Config {} impl Config { fn default_timeout() -> u64 { 3000 } fn default_init() -> Value { Value(vec![]) } fn default_programs() -> Vec { vec![] } }