use serde::{Deserialize, Serialize};
use std::hash::Hash;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum ResourceUnit {
CPU,
MemoryMB,
StorageMB,
NetworkEgressMB,
NetworkIngressMB,
GPU,
Request,
Invocation,
ExecutionTimeMS,
StorageIOPS,
Custom(String),
}
impl core::fmt::Display for ResourceUnit {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
ResourceUnit::CPU => write!(f, "CPU"),
ResourceUnit::MemoryMB => write!(f, "MemoryMB"),
ResourceUnit::StorageMB => write!(f, "StorageMB"),
ResourceUnit::NetworkEgressMB => write!(f, "NetworkEgressMB"),
ResourceUnit::NetworkIngressMB => write!(f, "NetworkIngressMB"),
ResourceUnit::GPU => write!(f, "GPU"),
ResourceUnit::Request => write!(f, "Request"),
ResourceUnit::Invocation => write!(f, "Invocation"),
ResourceUnit::ExecutionTimeMS => write!(f, "ExecutionTimeMS"),
ResourceUnit::StorageIOPS => write!(f, "StorageIOPS"),
ResourceUnit::Custom(name) => write!(f, "{name}"),
}
}
}
#[derive(Debug, thiserror::Error)]
#[error("Failed to parse resource unit")]
pub struct ParseResourceUnitError;
impl core::str::FromStr for ResourceUnit {
type Err = ParseResourceUnitError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_uppercase().as_str() {
"CPU" => Ok(ResourceUnit::CPU),
"MEMORYMB" => Ok(ResourceUnit::MemoryMB),
"STORAGEMB" => Ok(ResourceUnit::StorageMB),
"NETWORKEGRESSMB" => Ok(ResourceUnit::NetworkEgressMB),
"NETWORKINGRESSMB" => Ok(ResourceUnit::NetworkIngressMB),
"GPU" => Ok(ResourceUnit::GPU),
"REQUEST" => Ok(ResourceUnit::Request),
"INVOCATION" => Ok(ResourceUnit::Invocation),
"EXECUTIONTIMEMS" => Ok(ResourceUnit::ExecutionTimeMS),
"STORAGEIOPS" => Ok(ResourceUnit::StorageIOPS),
_ => Ok(ResourceUnit::Custom(s.to_string())),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Price {
pub value: u128,
pub token: String,
}
impl Price {
pub fn new(value: u128, token: impl Into<String>) -> Self {
Self {
value,
token: token.into(),
}
}
pub fn add(&self, other: &Price) -> Result<Price, &'static str> {
if self.token != other.token {
return Err("Cannot add prices with different tokens");
}
Ok(Price {
value: self.value.saturating_add(other.value),
token: self.token.clone(),
})
}
pub fn scale(&self, factor: u128) -> Price {
Price {
value: self.value.saturating_mul(factor),
token: self.token.clone(),
}
}
}
impl core::fmt::Display for Price {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let whole = self.value / 1_000_000;
let fractional = self.value % 1_000_000;
write!(f, "{}.{:06} {}", whole, fractional, self.token)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResourceRequirement {
pub unit: ResourceUnit,
pub quantity: u128,
}
impl ResourceRequirement {
pub fn new(unit: ResourceUnit, quantity: u128) -> Self {
Self { unit, quantity }
}
}