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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use super::HttpRequestError;
#[cfg(feature = "fp-bindgen")]
use fp_bindgen::prelude::Serializable;
use serde::{Deserialize, Serialize};
use std::num::ParseFloatError;
use typed_builder::TypedBuilder;

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, thiserror::Error)]
#[cfg_attr(
    feature = "fp-bindgen",
    derive(Serializable),
    fp(rust_module = "fiberplane_models::providers")
)]
#[non_exhaustive]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum Error {
    #[error("unsupported request")]
    UnsupportedRequest,
    #[error("validation error: {errors:?}")]
    ValidationError {
        /// List of errors, so all fields that failed validation can
        /// be highlighted at once.
        errors: Vec<ValidationError>,
    },
    #[error("http error: {error:?}")]
    #[cfg_attr(feature = "fp-bindgen", fp(rename_all = "camelCase"))]
    Http { error: HttpRequestError },
    #[error("data error: {message}")]
    #[cfg_attr(feature = "fp-bindgen", fp(rename_all = "camelCase"))]
    Data { message: String },
    #[error("deserialization error: {message}")]
    #[cfg_attr(feature = "fp-bindgen", fp(rename_all = "camelCase"))]
    Deserialization { message: String },
    #[error("config error: {message}")]
    #[cfg_attr(feature = "fp-bindgen", fp(rename_all = "camelCase"))]
    Config { message: String },
    #[error("provider cannot be found")]
    NotFound,
    #[error("proxy is disconnected")]
    ProxyDisconnected,
    #[error("error invoking provider: {message}")]
    Invocation { message: String },
    #[error("error: {message}")]
    #[cfg_attr(feature = "fp-bindgen", fp(rename_all = "camelCase"))]
    Other { message: String },
}

impl From<base64::DecodeError> for Error {
    fn from(error: base64::DecodeError) -> Self {
        Self::Deserialization {
            message: format!("Invalid base64 string: {error}"),
        }
    }
}

impl From<HttpRequestError> for Error {
    fn from(error: HttpRequestError) -> Self {
        Self::Http { error }
    }
}

impl From<ParseFloatError> for Error {
    fn from(error: ParseFloatError) -> Self {
        Self::Deserialization {
            message: format!("Invalid floating point number: {error}"),
        }
    }
}

impl From<rmpv::decode::Error> for Error {
    fn from(error: rmpv::decode::Error) -> Self {
        Self::Deserialization {
            message: format!("Invalid MessagePack payload: {error}"),
        }
    }
}

impl From<rmp_serde::decode::Error> for Error {
    fn from(error: rmp_serde::decode::Error) -> Self {
        Self::Deserialization {
            message: format!("Invalid MessagePack payload: {error}"),
        }
    }
}
impl From<rmp_serde::encode::Error> for Error {
    fn from(error: rmp_serde::encode::Error) -> Self {
        Self::Data {
            message: format!("Cannot serialize to MessagePack: {error}"),
        }
    }
}

impl From<serde_json::Error> for Error {
    fn from(error: serde_json::Error) -> Self {
        Self::Deserialization {
            message: format!("Invalid JSON payload: {error}"),
        }
    }
}

impl From<time::error::Parse> for Error {
    fn from(error: time::error::Parse) -> Self {
        Self::Deserialization {
            message: format!("Invalid date time: {error}"),
        }
    }
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, TypedBuilder)]
#[cfg_attr(
    feature = "fp-bindgen",
    derive(Serializable),
    fp(rust_module = "fiberplane_models::providers")
)]
#[non_exhaustive]
#[serde(rename_all = "camelCase")]
pub struct ValidationError {
    /// Refers to a field from the query schema.
    pub field_name: String,
    /// Description of why the validation failed.
    pub message: String,
}