use crate::error::Error;
use crate::wiggle_abi::{FastlyStatus, Session, fastly_device_detection::FastlyDeviceDetection};
use std::convert::TryFrom;
use wiggle::{GuestMemory, GuestPtr};
#[derive(Debug, thiserror::Error)]
pub enum DeviceDetectionError {
#[error("No device detection data: {0}")]
NoDeviceDetectionData(String),
}
impl DeviceDetectionError {
pub fn to_fastly_status(&self) -> FastlyStatus {
use DeviceDetectionError::*;
match self {
NoDeviceDetectionData(_) => FastlyStatus::None,
}
}
}
impl FastlyDeviceDetection for Session {
fn lookup(
&mut self,
memory: &mut GuestMemory<'_>,
user_agent: GuestPtr<str>,
buf: GuestPtr<u8>,
buf_len: u32,
nwritten_out: GuestPtr<u32>,
) -> Result<(), Error> {
let result = {
let user_agent_slice = memory
.as_slice(user_agent.as_bytes())?
.ok_or(Error::SharedMemory)?;
let user_agent_str = std::str::from_utf8(user_agent_slice)?;
self.device_detection_lookup(user_agent_str)
.ok_or_else(|| {
DeviceDetectionError::NoDeviceDetectionData(user_agent_str.to_string())
})?
};
if result.len() > buf_len as usize {
memory.write(nwritten_out, u32::try_from(result.len()).unwrap_or(0))?;
return Err(Error::BufferLengthError {
buf: "device_detection_lookup",
len: "device_detection_lookup_max_len",
});
}
let result_len =
u32::try_from(result.len()).expect("smaller than buf_len means it must fit");
memory.copy_from_slice(result.as_bytes(), buf.as_array(result_len))?;
memory.write(nwritten_out, result_len)?;
Ok(())
}
}