use crate::abi;
use crate::handle::BodyHandle;
use fastly_shared::FastlyStatus;
use std::net::IpAddr;
pub(crate) struct AclHandle {
handle: u32,
}
impl AclHandle {
#[cfg_attr(
not(target_env = "p1"),
deprecated(
since = "0.11.6",
note = "This code will need to be updated for wasip2."
)
)]
const INVALID: Self = Self {
handle: fastly_shared::INVALID_ACL_HANDLE,
};
pub fn open(acl_name: &str) -> Result<Self, OpenError> {
let mut handle = Self::INVALID;
unsafe { abi::fastly_acl::open(acl_name.as_ptr(), acl_name.len(), handle.as_u32_mut()) }
.result()
.map(|_| handle)
.map_err(|fastly_status| fastly_status.into())
}
pub fn lookup(&self, ip: IpAddr) -> Result<Option<BodyHandle>, LookupError> {
if self.is_invalid() {
return Err(LookupError::InvalidHandle);
}
let ipv4_bytes;
let ipv6_bytes;
let ip_bytes = match ip {
IpAddr::V4(v4) => {
ipv4_bytes = v4.octets();
&ipv4_bytes[..]
}
IpAddr::V6(v6) => {
ipv6_bytes = v6.octets();
&ipv6_bytes[..]
}
};
let mut body_handle_out = fastly_shared::INVALID_BODY_HANDLE;
let mut acl_error_out = abi::fastly_acl::AclError::Uninitialized;
unsafe {
abi::fastly_acl::lookup(
self.as_u32(),
ip_bytes.as_ptr(),
ip_bytes.len(),
&mut body_handle_out,
&mut acl_error_out,
)
}
.result()
.map_err(|fastly_status| -> LookupError { fastly_status.into() })?;
match acl_error_out {
abi::fastly_acl::AclError::Ok => {
if body_handle_out == fastly_shared::INVALID_BODY_HANDLE {
return Err(LookupError::InvalidResponseBody);
}
let body_handle = unsafe { BodyHandle::from_u32(body_handle_out) };
Ok(Some(body_handle))
}
abi::fastly_acl::AclError::NoContent => Ok(None),
other => Err(other.into()),
}
}
fn as_u32(&self) -> u32 {
return self.handle;
}
fn as_u32_mut(&mut self) -> &mut u32 {
&mut self.handle
}
#[cfg_attr(
not(target_env = "p1"),
deprecated(
since = "0.11.6",
note = "This code will need to be updated for wasip2."
)
)]
pub fn is_invalid(&self) -> bool {
self.handle == Self::INVALID.handle
}
}
#[derive(Debug, thiserror::Error)]
pub enum OpenError {
#[error("acl not found")]
AclNotFound,
#[error("unexpected error: {0:?}")]
Unexpected(FastlyStatus),
}
impl From<FastlyStatus> for OpenError {
fn from(fastly_status: FastlyStatus) -> Self {
match fastly_status {
FastlyStatus::NONE => Self::AclNotFound,
unexpected => Self::Unexpected(unexpected),
}
}
}
#[derive(Debug, thiserror::Error)]
pub enum LookupError {
#[error("invalid acl handle")]
InvalidHandle,
#[error("response body is invalid")]
InvalidResponseBody,
#[error("a provided argument was invalid")]
InvalidArgument,
#[error("too many requests")]
TooManyRequests,
#[error("unexpected error: {0:?}")]
FastlyStatus(FastlyStatus),
#[error("unexpected error: {0:?}")]
AclError(abi::fastly_acl::AclError),
}
impl From<FastlyStatus> for LookupError {
fn from(fastly_status: FastlyStatus) -> Self {
match fastly_status {
FastlyStatus::BADF => Self::InvalidHandle,
FastlyStatus::INVAL => Self::InvalidArgument,
unexpected => Self::FastlyStatus(unexpected),
}
}
}
impl From<fastly_sys::fastly_acl::AclError> for LookupError {
fn from(acl_error: fastly_sys::fastly_acl::AclError) -> Self {
match acl_error {
fastly_sys::fastly_acl::AclError::TooManyRequests => Self::TooManyRequests,
other => Self::AclError(other),
}
}
}