use crate::notification::spatial::SpatialMetadata;
use aviso_validators::{EnumConstraint, NumericConstraint};
use serde::Serialize;
use std::collections::HashMap;
use std::str::FromStr;
#[derive(Debug, Clone, Copy, Serialize, PartialEq)]
pub enum OperationType {
Notify,
Watch,
Replay,
}
impl FromStr for OperationType {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"notify" => Ok(OperationType::Notify),
"watch" => Ok(OperationType::Watch),
"replay" => Ok(OperationType::Replay),
_ => anyhow::bail!("Invalid operation type: {}", s),
}
}
}
impl OperationType {
pub fn as_str(&self) -> &'static str {
match self {
OperationType::Notify => "notify",
OperationType::Watch => "watch",
OperationType::Replay => "replay",
}
}
pub fn all_operations() -> Vec<Self> {
vec![
OperationType::Notify,
OperationType::Watch,
OperationType::Replay,
]
}
pub fn all_operation_strings() -> Vec<&'static str> {
Self::all_operations()
.iter()
.map(|op| op.as_str())
.collect()
}
}
pub struct AvisoCloudEventTypes;
impl AvisoCloudEventTypes {
pub const AVISO_TYPE_PREFIX: &'static str = "int.ecmwf.aviso";
pub fn get_supported_types() -> Vec<String> {
OperationType::all_operations()
.iter()
.map(|op| format!("{}.{}", Self::AVISO_TYPE_PREFIX, op.as_str()))
.collect()
}
pub fn get_unsupported_type_error(actual_type: &str) -> String {
let supported_types = Self::get_supported_types();
format!(
"Only Aviso CloudEvent types are supported. Got: '{}'. Expected one of: [{}]",
actual_type,
supported_types.join(", ")
)
}
pub fn is_aviso_type(cloudevent_type: &str) -> bool {
cloudevent_type.starts_with(Self::AVISO_TYPE_PREFIX)
}
pub fn validate_and_extract_operation(
cloudevent_type: &str,
) -> Result<OperationType, anyhow::Error> {
if !cloudevent_type.starts_with(Self::AVISO_TYPE_PREFIX) {
anyhow::bail!(
"Invalid Aviso CloudEvent type '{}'. Must start with '{}'",
cloudevent_type,
Self::AVISO_TYPE_PREFIX
);
}
let operation_part = cloudevent_type
.strip_prefix(Self::AVISO_TYPE_PREFIX)
.and_then(|s| s.strip_prefix('.'))
.unwrap_or("");
match OperationType::from_str(operation_part) {
Ok(operation) => {
tracing::debug!(
cloudevent_type = cloudevent_type,
operation = operation_part,
"Valid Aviso CloudEvent type with operation"
);
Ok(operation)
}
Err(_) => {
anyhow::bail!(
"Invalid Aviso CloudEvent operation '{}' in type '{}'. \
Supported operations: [{}]",
operation_part,
cloudevent_type,
OperationType::all_operation_strings().join(", ")
);
}
}
}
}
#[derive(Debug, Clone)]
pub struct ProcessingResult {
pub event_type: String,
pub topic: String,
pub canonicalized_params: HashMap<String, String>,
pub identifier_constraints: HashMap<String, IdentifierConstraint>,
pub spatial_metadata: Option<SpatialMetadata>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum IdentifierConstraint {
Int(NumericConstraint<i64>),
Enum(EnumConstraint),
Float(NumericConstraint<f64>),
}