flutter-engine 0.3.2

Flutter engine embedder in rust
use std::{
    error, fmt,
    sync::mpsc::{RecvError, SendError},
};

use crate::codec::{MethodCallResult, Value};

#[derive(Debug)]
pub enum MethodArgsError {
    WrongType(String, Value),
    MissingField(String),
}

impl fmt::Display for MethodArgsError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            MethodArgsError::MissingField(field) => {
                write!(f, "missing field \"{}\" in map", field.as_str())
            }
            MethodArgsError::WrongType(expected, actual) => write!(
                f,
                "expected value for type \"{}\", but found {:?}",
                expected, actual
            ),
        }
    }
}

impl error::Error for MethodArgsError {}

#[derive(Debug)]
pub enum MethodCallError {
    NotImplemented,
    ArgParseError(MethodArgsError),
    DeserializeError(ValueError),
    ChannelClosed,
    SendError(String),
    RustError(Box<error::Error>),
    CustomError {
        code: String,
        message: String,
        details: Value,
    },
    UnspecifiedError,
}

impl MethodCallError {
    pub fn from_error<T: error::Error + 'static>(error: T) -> Self {
        MethodCallError::RustError(Box::new(error))
    }
}

impl From<MethodArgsError> for MethodCallError {
    fn from(error: MethodArgsError) -> Self {
        MethodCallError::ArgParseError(error)
    }
}

impl From<ValueError> for MethodCallError {
    fn from(error: ValueError) -> Self {
        MethodCallError::DeserializeError(error)
    }
}

impl<T> From<SendError<T>> for MethodCallError {
    fn from(error: SendError<T>) -> Self {
        MethodCallError::SendError(format!("{}", error))
    }
}

impl From<RecvError> for MethodCallError {
    fn from(error: RecvError) -> Self {
        MethodCallError::RustError(Box::new(error))
    }
}

impl fmt::Display for MethodCallError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            MethodCallError::NotImplemented => write!(f, "method not implemented"),
            MethodCallError::ArgParseError(err) => write!(f, "failed to parse arguments: {}", err),
            MethodCallError::DeserializeError(err) => {
                write!(f, "failed to deserialize value: {}", err)
            }
            MethodCallError::ChannelClosed => write!(f, "channel already closed"),
            MethodCallError::SendError(msg) => write!(f, "message send error: {}", msg),
            MethodCallError::RustError(error) => write!(f, "rust error: {}", error),
            MethodCallError::CustomError {
                code,
                message,
                details,
            } => write!(f, "{} ({})\ndetails: {:?}", message, code, details),
            MethodCallError::UnspecifiedError => write!(f, "unspecified error"),
        }
    }
}

impl error::Error for MethodCallError {
    fn cause(&self) -> Option<&error::Error> {
        match self {
            MethodCallError::RustError(err) => Some(&**err),
            _ => None,
        }
    }
}

impl Into<MethodCallResult> for MethodCallError {
    fn into(self) -> MethodCallResult {
        match self {
            MethodCallError::NotImplemented => MethodCallResult::NotImplemented,
            MethodCallError::CustomError {
                code,
                message,
                details,
            } => MethodCallResult::Err {
                code,
                message,
                details,
            },
            error => MethodCallResult::Err {
                code: "".into(),
                message: format!("{}", error),
                details: Value::Null,
            },
        }
    }
}

#[derive(Debug)]
pub enum ValueError {
    Message(String),
    WrongType,
    NoList,
    NoMap,
}

impl fmt::Display for ValueError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ValueError::Message(s) => write!(f, "{}", s),
            ValueError::WrongType => write!(f, "wrong type"),
            ValueError::NoList => write!(f, "value is not a list"),
            ValueError::NoMap => write!(f, "value is not a map"),
        }
    }
}

impl serde::de::Error for ValueError {
    fn custom<T: fmt::Display>(msg: T) -> Self {
        ValueError::Message(msg.to_string())
    }
}

impl error::Error for ValueError {}