use anyhow::Result;
use navm::{cmd::Cmd, output::Output};
use std::error::Error;
use thiserror::Error;
pub type InputTranslator = dyn Fn(Cmd) -> Result<String> + Send + Sync;
pub type OutputTranslator = dyn Fn(String) -> Result<Output> + Send + Sync;
pub fn default_input_translate(cmd: Cmd) -> Result<String> {
Ok(cmd.to_string())
}
pub fn default_output_translate(content: String) -> Result<Output> {
Ok(Output::OTHER { content })
}
pub fn default_input_translator() -> Box<InputTranslator> {
Box::new(default_input_translate)
}
pub fn default_output_translator() -> Box<OutputTranslator> {
Box::new(default_output_translate)
}
pub struct IoTranslators {
pub input_translator: Box<InputTranslator>,
pub output_translator: Box<OutputTranslator>,
}
impl IoTranslators {
pub fn new<I, O>(i: I, o: O) -> Self
where
I: Fn(Cmd) -> Result<String> + Send + Sync + 'static,
O: Fn(String) -> Result<Output> + Send + Sync + 'static,
{
Self {
input_translator: Box::new(i),
output_translator: Box::new(o),
}
}
}
impl Default for IoTranslators {
fn default() -> IoTranslators {
IoTranslators {
input_translator: Box::new(|cmd| Ok(cmd.to_string())),
output_translator: Box::new(|content| Ok(Output::OTHER { content })),
}
}
}
impl<I, O> From<(I, O)> for IoTranslators
where
I: Fn(Cmd) -> Result<String> + Send + Sync + 'static,
O: Fn(String) -> Result<Output> + Send + Sync + 'static,
{
fn from(value: (I, O)) -> Self {
Self::new(value.0, value.1)
}
}
mod translate_error {
use super::*;
use anyhow::anyhow;
#[derive(Debug, Error)]
pub enum TranslateError {
#[error("不支持的NAVM指令:\"{0}\"")]
UnsupportedInput(Cmd),
#[error("NAVM转译错误:「{0}」")]
ParseError(#[from] anyhow::Error),
}
impl From<&'_ str> for TranslateError {
fn from(value: &'_ str) -> Self {
Self::ParseError(anyhow!("{value}"))
}
}
impl From<&'_ String> for TranslateError {
fn from(value: &'_ String) -> Self {
Self::ParseError(anyhow!("{value}"))
}
}
impl TranslateError {
pub fn from_error(value: impl Error) -> Self {
Self::from(&value.to_string())
}
pub fn error_anyhow(value: impl Error + Send + Sync + 'static) -> anyhow::Error {
Self::ParseError(value.into()).into()
}
pub fn err_anyhow<T, S>(from: S) -> anyhow::Result<T>
where
Self: From<S>,
{
Err(Self::from(from).into())
}
pub fn anyhow(value: impl Into<Self>) -> anyhow::Error {
anyhow::Error::from(value.into())
}
}
}
pub use translate_error::*;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
let _t1 = IoTranslators::default();
}
}