use http::StatusCode;
use ocm_types::error::Error;
use serde::Serialize;
pub trait ResourceRepo: Clone + std::fmt::Debug + Send + Sync {
type Item: Resource + Send;
fn get_resource(
&self,
resource_id: &str,
) -> impl Future<Output = Result<Self::Item, ResourceError>> + Send;
fn resource_types(&self) -> &'static [&'static str] {
&[Self::Item::RESOURCE_TYPE]
}
}
pub trait Resource: Clone + std::fmt::Debug + Send + Sync + Serialize {
const RESOURCE_TYPE: &str;
fn uri(&self) -> &str;
fn name(&self) -> &str;
fn resource_type(&self) -> &str {
Self::RESOURCE_TYPE
}
}
#[derive(Debug)]
pub enum ResourceError {
InvalidResourceId(String),
InvalidResource(String),
NotFound,
Io(std::io::Error),
}
impl From<ResourceError> for Error {
fn from(value: ResourceError) -> Self {
match value {
ResourceError::InvalidResourceId(id_error) => Error {
message: format!("Id is invalid: {id_error}"),
validation_errors: vec![],
},
ResourceError::InvalidResource(resource_error) => Error {
message: format!("Resource was found but is invalid: {resource_error}"),
validation_errors: vec![],
},
ResourceError::NotFound => Error {
message: "Resource was not found".to_string(),
validation_errors: vec![],
},
ResourceError::Io(error) => Error {
message: format!("Resource could not be accessed: {error}"),
validation_errors: vec![],
},
}
}
}
impl ResourceError {
pub fn status_code(&self) -> StatusCode {
match self {
ResourceError::InvalidResourceId(_) => StatusCode::NOT_ACCEPTABLE,
ResourceError::InvalidResource(_) => StatusCode::BAD_GATEWAY,
ResourceError::NotFound => StatusCode::NOT_FOUND,
ResourceError::Io(_) => StatusCode::BAD_GATEWAY,
}
}
}
impl From<std::io::Error> for ResourceError {
fn from(value: std::io::Error) -> Self {
Self::Io(value)
}
}