1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
 * File: error.rs
 * Project: src
 * Created Date: 30/06/2023
 * Author: Shun Suzuki
 * -----
 * Last Modified: 05/09/2023
 * Modified By: Shun Suzuki (suzuki@hapis.k.u-tokyo.ac.jp)
 * -----
 * Copyright (c) 2023 Shun Suzuki. All rights reserved.
 *
 */

use std::error::Error;

use thiserror::Error;
use tonic::Status;

#[derive(Error, Debug)]
pub enum AUTDProtoBufError {
    #[error("{0}")]
    Status(String),
    #[error("{0}")]
    SendError(String),
    #[error("{0}")]
    TokioSendError(String),
    #[error("{0}")]
    TransportError(String),
    #[error("{0}")]
    TokioJoinError(String),
    #[error("{0}")]
    AUTDError(autd3::prelude::AUTDError),
    #[error("This data is not supported.")]
    NotSupportedData,
}

impl From<autd3::prelude::AUTDError> for AUTDProtoBufError {
    fn from(e: autd3::prelude::AUTDError) -> Self {
        AUTDProtoBufError::AUTDError(e)
    }
}

impl From<autd3::driver::error::AUTDInternalError> for AUTDProtoBufError {
    fn from(e: autd3::driver::error::AUTDInternalError) -> Self {
        AUTDProtoBufError::AUTDError(e.into())
    }
}

impl From<tonic::Status> for AUTDProtoBufError {
    fn from(e: tonic::Status) -> Self {
        AUTDProtoBufError::Status(e.to_string())
    }
}

impl<T> From<std::sync::mpsc::SendError<T>> for AUTDProtoBufError {
    fn from(e: std::sync::mpsc::SendError<T>) -> Self {
        AUTDProtoBufError::SendError(e.to_string())
    }
}

impl<T> From<tokio::sync::mpsc::error::SendError<T>> for AUTDProtoBufError {
    fn from(e: tokio::sync::mpsc::error::SendError<T>) -> Self {
        AUTDProtoBufError::TokioSendError(e.to_string())
    }
}

impl From<tokio::task::JoinError> for AUTDProtoBufError {
    fn from(e: tokio::task::JoinError) -> Self {
        AUTDProtoBufError::TokioJoinError(e.to_string())
    }
}

impl From<tonic::transport::Error> for AUTDProtoBufError {
    fn from(e: tonic::transport::Error) -> Self {
        match e.source() {
            Some(source) => AUTDProtoBufError::TransportError(source.to_string()),
            None => AUTDProtoBufError::TransportError(e.to_string()),
        }
    }
}

impl From<AUTDProtoBufError> for autd3::driver::error::AUTDInternalError {
    fn from(e: AUTDProtoBufError) -> Self {
        autd3::driver::error::AUTDInternalError::LinkError(e.to_string())
    }
}

pub fn match_for_io_error(err_status: &Status) -> Option<&std::io::Error> {
    let mut err: &(dyn Error + 'static) = err_status;
    loop {
        if let Some(io_err) = err.downcast_ref::<std::io::Error>() {
            return Some(io_err);
        }
        if let Some(h2_err) = err.downcast_ref::<h2::Error>() {
            if let Some(io_err) = h2_err.get_io() {
                return Some(io_err);
            }
        }
        err = match err.source() {
            Some(err) => err,
            None => return None,
        };
    }
}