viceroy_lib/wiggle_abi/
device_detection_impl.rs

1//! fastly_device_detection` hostcall implementations.
2
3use crate::error::Error;
4use crate::wiggle_abi::{fastly_device_detection::FastlyDeviceDetection, FastlyStatus, Session};
5use std::convert::TryFrom;
6use wiggle::{GuestMemory, GuestPtr};
7
8#[derive(Debug, thiserror::Error)]
9pub enum DeviceDetectionError {
10    /// Device detection data for given user_agent not found.
11    #[error("No device detection data: {0}")]
12    NoDeviceDetectionData(String),
13}
14
15impl DeviceDetectionError {
16    /// Convert to an error code representation suitable for passing across the ABI boundary.
17    pub fn to_fastly_status(&self) -> FastlyStatus {
18        use DeviceDetectionError::*;
19        match self {
20            NoDeviceDetectionData(_) => FastlyStatus::None,
21        }
22    }
23}
24
25impl FastlyDeviceDetection for Session {
26    fn lookup(
27        &mut self,
28        memory: &mut GuestMemory<'_>,
29        user_agent: GuestPtr<str>,
30        buf: GuestPtr<u8>,
31        buf_len: u32,
32        nwritten_out: GuestPtr<u32>,
33    ) -> Result<(), Error> {
34        let result = {
35            let user_agent_slice = memory
36                .as_slice(user_agent.as_bytes())?
37                .ok_or(Error::SharedMemory)?;
38            let user_agent_str = std::str::from_utf8(&user_agent_slice)?;
39
40            self.device_detection_lookup(user_agent_str)
41                .ok_or_else(|| {
42                    DeviceDetectionError::NoDeviceDetectionData(user_agent_str.to_string())
43                })?
44        };
45
46        if result.len() > buf_len as usize {
47            memory.write(nwritten_out, u32::try_from(result.len()).unwrap_or(0))?;
48            return Err(Error::BufferLengthError {
49                buf: "device_detection_lookup",
50                len: "device_detection_lookup_max_len",
51            });
52        }
53
54        let result_len =
55            u32::try_from(result.len()).expect("smaller than buf_len means it must fit");
56
57        memory.copy_from_slice(result.as_bytes(), buf.as_array(result_len))?;
58
59        memory.write(nwritten_out, result_len)?;
60        Ok(())
61    }
62}