use {
crate::{
error::Error,
session::Session,
wiggle_abi::{
fastly_dictionary::FastlyDictionary,
types::{DictionaryHandle, FastlyStatus},
},
},
wiggle::{GuestMemory, GuestPtr},
};
#[derive(Debug, thiserror::Error)]
pub enum DictionaryError {
#[error("Unknown dictionary item: {0}")]
UnknownDictionaryItem(String),
#[error("Unknown dictionary: {0}")]
UnknownDictionary(String),
}
impl DictionaryError {
pub fn to_fastly_status(&self) -> FastlyStatus {
use DictionaryError::*;
match self {
UnknownDictionaryItem(_) => FastlyStatus::None,
UnknownDictionary(_) => FastlyStatus::Badf,
}
}
}
impl FastlyDictionary for Session {
fn open(
&mut self,
memory: &mut GuestMemory<'_>,
name: GuestPtr<str>,
) -> Result<DictionaryHandle, Error> {
self.dictionary_handle(memory.as_str(name)?.ok_or(Error::SharedMemory)?)
}
fn get(
&mut self,
memory: &mut GuestMemory<'_>,
dictionary: DictionaryHandle,
key: GuestPtr<str>,
buf: GuestPtr<u8>,
buf_len: u32,
nwritten_out: GuestPtr<u32>,
) -> Result<(), Error> {
let dict = &self.dictionary(dictionary)?.contents;
let item_bytes = {
let key = memory.as_str(key)?.ok_or(Error::SharedMemory)?;
dict.get(key)
.ok_or_else(|| DictionaryError::UnknownDictionaryItem(key.to_owned()))?
.as_bytes()
};
if item_bytes.len() > usize::try_from(buf_len).expect("buf_len must fit in usize") {
memory.write(nwritten_out, u32::try_from(item_bytes.len()).unwrap_or(0))?;
return Err(Error::BufferLengthError {
buf: "dictionary_item",
len: "dictionary_item_max_len",
});
}
let item_len = u32::try_from(item_bytes.len()).unwrap();
memory.write(nwritten_out, item_len)?;
memory.copy_from_slice(item_bytes, buf.as_array(item_len))?;
Ok(())
}
}