use sim_kernel::{Error, Result, Symbol};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum HttpWriteMethod {
#[default]
Put,
Post,
}
impl HttpWriteMethod {
pub fn as_str(self) -> &'static str {
match self {
Self::Put => "PUT",
Self::Post => "POST",
}
}
fn from_str(value: &str) -> Result<Self> {
match value {
"PUT" => Ok(Self::Put),
"POST" => Ok(Self::Post),
other => Err(Error::Eval(format!(
"table/http: unsupported write method {other}"
))),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct HttpDirOptions {
pub base_url: String,
pub codec: Symbol,
pub write_method: HttpWriteMethod,
pub timeout_ms: u64,
pub max_body_bytes: usize,
}
impl HttpDirOptions {
pub fn new(base_url: impl Into<String>) -> Self {
Self {
base_url: base_url.into(),
codec: Symbol::qualified("codec", "lisp"),
write_method: HttpWriteMethod::Put,
timeout_ms: 5_000,
max_body_bytes: 1024 * 1024,
}
}
pub fn with_codec(mut self, codec: Symbol) -> Self {
self.codec = codec;
self
}
pub fn with_write_method(mut self, write_method: HttpWriteMethod) -> Self {
self.write_method = write_method;
self
}
pub fn with_timeout_ms(mut self, timeout_ms: u64) -> Self {
self.timeout_ms = timeout_ms;
self
}
pub fn with_max_body_bytes(mut self, max_body_bytes: usize) -> Self {
self.max_body_bytes = max_body_bytes;
self
}
}
pub(crate) fn validate_options(options: &HttpDirOptions) -> Result<()> {
if options.timeout_ms == 0 {
return Err(Error::Eval(
"table/http: timeout_ms must be non-zero".to_owned(),
));
}
if options.base_url.trim().is_empty() {
return Err(Error::Eval("table/http: base_url is empty".to_owned()));
}
let _ = sim_lib_net_core::parse_url(options.base_url.trim())
.map_err(|err| Error::Eval(format!("table/http: {err}")))?;
Ok(())
}
pub(crate) fn normalize_options(mut options: HttpDirOptions) -> HttpDirOptions {
options.base_url = options.base_url.trim().trim_end_matches('/').to_owned();
options
}
impl TryFrom<crate::HttpDirDescriptor> for HttpDirOptions {
type Error = Error;
fn try_from(value: crate::HttpDirDescriptor) -> Result<Self> {
Ok(Self {
base_url: value.base_url,
codec: value.codec,
write_method: HttpWriteMethod::from_str(&value.write_method)?,
timeout_ms: value.timeout_ms,
max_body_bytes: value.max_body_bytes,
})
}
}