use std::fmt;
use bson::Bson;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Error {
pub code: i64,
pub message: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub data: Option<Box<Bson>>,
}
impl Error {
pub const TIMED_OUT: i64 = -32000;
pub const NOT_EXECUTABLE: i64 = -32001;
pub const BOOT_FAILED: i64 = -32002;
pub const NOT_FOUND: i64 = -32005;
pub const IS_A_DIRECTORY: i64 = -32006;
pub const IO_FAILED: i64 = -32007;
pub const UNSUPPORTED_MOUNT: i64 = -32008;
pub const MOUNT_FAILED: i64 = -32009;
pub const UNSUPPORTED_NETWORK: i64 = -32010;
pub const UNSUPPORTED_IMAGE: i64 = -32011;
pub const UNKNOWN_IMAGE: i64 = -32012;
pub const UNSUPPORTED_MACHINE: i64 = -32013;
pub const INVALID_REQUEST: i64 = -32600;
pub const METHOD_NOT_FOUND: i64 = -32601;
pub const INVALID_PARAMS: i64 = -32602;
pub const INTERNAL_ERROR: i64 = -32603;
pub fn new(code: i64, message: impl Into<String>) -> Self {
Error {
code,
message: message.into(),
data: None,
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} ({})", self.message, self.code)
}
}
impl std::error::Error for Error {}
#[cfg(test)]
mod tests {
use super::Error;
#[test]
fn every_error_code_is_distinct() {
let codes = [
("TIMED_OUT", Error::TIMED_OUT),
("NOT_EXECUTABLE", Error::NOT_EXECUTABLE),
("BOOT_FAILED", Error::BOOT_FAILED),
("NOT_FOUND", Error::NOT_FOUND),
("IS_A_DIRECTORY", Error::IS_A_DIRECTORY),
("IO_FAILED", Error::IO_FAILED),
("UNSUPPORTED_MOUNT", Error::UNSUPPORTED_MOUNT),
("MOUNT_FAILED", Error::MOUNT_FAILED),
("UNSUPPORTED_NETWORK", Error::UNSUPPORTED_NETWORK),
("UNSUPPORTED_IMAGE", Error::UNSUPPORTED_IMAGE),
("UNKNOWN_IMAGE", Error::UNKNOWN_IMAGE),
("INVALID_REQUEST", Error::INVALID_REQUEST),
("METHOD_NOT_FOUND", Error::METHOD_NOT_FOUND),
("INVALID_PARAMS", Error::INVALID_PARAMS),
("INTERNAL_ERROR", Error::INTERNAL_ERROR),
];
let mut seen = std::collections::HashMap::new();
for (name, code) in codes {
if let Some(taken) = seen.insert(code, name) {
panic!("{code} is both {taken} and {name}");
}
}
}
}