viceroy_lib/wiggle_abi/
geo_impl.rs

1//! fastly_geo` hostcall implementations.
2
3use std::{
4    convert::TryInto,
5    net::{IpAddr, Ipv4Addr, Ipv6Addr},
6};
7
8use {
9    crate::{error::Error, session::Session, wiggle_abi::fastly_geo::FastlyGeo},
10    std::convert::TryFrom,
11    wiggle::{GuestMemory, GuestPtr},
12};
13
14impl FastlyGeo for Session {
15    fn lookup(
16        &mut self,
17        memory: &mut GuestMemory<'_>,
18        addr_octets: GuestPtr<u8>,
19        addr_len: u32,
20        buf: GuestPtr<u8>,
21        buf_len: u32,
22        nwritten_out: GuestPtr<u32>,
23    ) -> Result<(), Error> {
24        let octets = memory.to_vec(addr_octets.as_array(addr_len))?;
25
26        let ip_addr: IpAddr = match addr_len {
27            4 => IpAddr::V4(Ipv4Addr::from(
28                TryInto::<[u8; 4]>::try_into(octets).unwrap(),
29            )),
30            16 => IpAddr::V6(Ipv6Addr::from(
31                TryInto::<[u8; 16]>::try_into(octets).unwrap(),
32            )),
33            _ => return Err(Error::InvalidArgument),
34        };
35
36        let result = self.geolocation_lookup(&ip_addr).unwrap_or_default();
37
38        if result.len() > buf_len as usize {
39            memory.write(nwritten_out, u32::try_from(result.len()).unwrap_or(0))?;
40            return Err(Error::BufferLengthError {
41                buf: "geolocation_lookup",
42                len: "geolocation_lookup_max_len",
43            });
44        }
45
46        let result_len =
47            u32::try_from(result.len()).expect("smaller than value_max_len means it must fit");
48
49        memory.copy_from_slice(result.as_bytes(), buf.as_array(result_len))?;
50        memory.write(nwritten_out, result_len)?;
51        Ok(())
52    }
53}