viceroy-lib 0.17.0

Viceroy implementation details.
Documentation
//! fastly_log` hostcall implementations.

use {
    crate::{
        error::Error,
        session::Session,
        wiggle_abi::{fastly_log::FastlyLog, types::EndpointHandle},
    },
    lazy_static::lazy_static,
    wiggle::{GuestMemory, GuestPtr},
};

fn is_reserved_endpoint(name: &[u8]) -> bool {
    use regex::bytes::{RegexSet, RegexSetBuilder};
    const RESERVED_ENDPOINTS: &[&str] = &["^stdout$", "^stderr$", "^fst_managed_"];
    lazy_static! {
        static ref RESERVED_ENDPOINT_RE: RegexSet = RegexSetBuilder::new(RESERVED_ENDPOINTS)
            .case_insensitive(true)
            .build()
            .unwrap();
    }
    RESERVED_ENDPOINT_RE.is_match(name)
}

impl FastlyLog for Session {
    fn endpoint_get(
        &mut self,
        memory: &mut GuestMemory<'_>,
        name: GuestPtr<[u8]>,
    ) -> Result<EndpointHandle, Error> {
        let name = memory.as_slice(name)?.ok_or(Error::SharedMemory)?;

        if is_reserved_endpoint(name) {
            return Err(Error::InvalidArgument);
        }

        Ok(self.log_endpoint_handle(name))
    }

    fn write(
        &mut self,
        memory: &mut GuestMemory<'_>,
        endpoint_handle: EndpointHandle,
        msg: GuestPtr<[u8]>,
    ) -> Result<u32, Error> {
        let endpoint = self.log_endpoint(endpoint_handle)?;
        let msg = memory.as_slice(msg)?.ok_or(Error::SharedMemory)?;

        // The log API is infallible, so if we get an error, warn about it
        // rather than bubbling it up through the log API.
        match endpoint.write_entry(msg) {
            Ok(()) => {}
            Err(err) => tracing::error!("Error writing log message: {:?}", err),
        }

        Ok(msg.len().try_into().unwrap())
    }
}