fastly/dictionary/
handle.rs

1#![deprecated(since = "0.8.6", note = "renamed to `handle::config_store`")]
2//! Low-level Compute Dictionary interfaces.
3
4use crate::abi;
5use bytes::BytesMut;
6use fastly_shared::FastlyStatus;
7
8/// A low-level interface to Edge Dictionaries.
9///
10/// Unlike the high-level [`Dictionary`][`crate::dictionary::Dictionary`], this type has methods
11/// that return `Result` values upon failure, rather than panicking. Additionally, the
12/// [`get()`][`Self::get()`] method allows the caller to configure the size of the buffer used to
13/// received lookup results from the host.
14#[derive(Debug, Eq, Hash, PartialEq)]
15#[repr(transparent)]
16#[deprecated(since = "0.8.6", note = "renamed to `ConfigStoreHandle`")]
17pub struct DictionaryHandle {
18    handle: u32,
19}
20
21impl DictionaryHandle {
22    /// An invalid handle.
23    #[deprecated(
24        since = "0.8.6",
25        note = "use the constant in `ConfigStoreHandle` instead"
26    )]
27    pub const INVALID: Self = DictionaryHandle {
28        handle: fastly_shared::INVALID_DICTIONARY_HANDLE,
29    };
30
31    /// Acquire a handle to an Edge Dictionary.
32    ///
33    /// If a handle could not be acquired, an [`OpenError`] will be returned.
34    #[deprecated(
35        since = "0.8.6",
36        note = "use the method on `ConfigStoreHandle` instead"
37    )]
38    pub fn open(name: &str) -> Result<Self, OpenError> {
39        use OpenError::*;
40        let mut handle = Self::INVALID;
41        unsafe { abi::fastly_dictionary::open(name.as_ptr(), name.len(), handle.as_u32_mut()) }
42            .result()
43            .map(|_| handle)
44            .map_err(|status| match status {
45                FastlyStatus::NONE => NameEmpty,
46                FastlyStatus::UNSUPPORTED => NameTooLong,
47                FastlyStatus::INVAL => NameInvalid,
48                FastlyStatus::BADF => DictionaryDoesNotExist,
49                _ => panic!("fastly_dictionary::open returned an unrecognized result"),
50            })
51    }
52
53    /// Lookup a value in this dictionary.
54    ///
55    /// If successful, this function returns `Ok(Some(_))` if an entry was found, or `Ok(None)` if
56    /// no entry with the given key was found. If the lookup failed, a [`LookupError`] will be
57    /// returned.
58    #[deprecated(
59        since = "0.8.6",
60        note = "use the method on `ConfigStoreHandle` instead"
61    )]
62    pub fn get(&self, key: &str, max_len: usize) -> Result<Option<String>, LookupError> {
63        if self.is_invalid() {
64            panic!("cannot lookup value with invalid dictionary handle");
65        }
66        let mut buf = BytesMut::with_capacity(max_len);
67        let mut nwritten = 0;
68        let status = unsafe {
69            abi::fastly_dictionary::get(
70                self.as_u32(),
71                key.as_ptr(),
72                key.len(),
73                buf.as_mut_ptr(),
74                buf.capacity(),
75                &mut nwritten,
76            )
77        };
78        match status.result().map(|_| nwritten) {
79            Ok(nwritten) => {
80                assert!(
81                    nwritten <= buf.capacity(),
82                    "fastly_dictionary::get wrote too many bytes"
83                );
84                unsafe {
85                    buf.set_len(nwritten);
86                }
87                Ok(Some(
88                    String::from_utf8(buf.to_vec()).expect("host returns valid UTF-8"),
89                ))
90            }
91            Err(FastlyStatus::NONE) => Ok(None),
92            Err(FastlyStatus::ERROR) => Err(LookupError::Other),
93            Err(FastlyStatus::BADF) => Err(LookupError::DictionaryInvalid),
94            Err(FastlyStatus::INVAL) => Err(LookupError::KeyInvalid),
95            Err(FastlyStatus::UNSUPPORTED) => Err(LookupError::KeyTooLong),
96            Err(FastlyStatus::BUFLEN) => Err(LookupError::ValueTooLong),
97            Err(FastlyStatus::LIMITEXCEEDED) => Err(LookupError::TooManyLookups),
98            Err(_) => panic!("fastly_dictionary::get returned an unrecognized result"),
99        }
100    }
101
102    /// Return true if the dictionary contains an entry with the given key.
103    #[deprecated(
104        since = "0.8.6",
105        note = "use the method on `ConfigStoreHandle` instead"
106    )]
107    pub fn contains(&self, key: &str) -> Result<bool, LookupError> {
108        use LookupError::*;
109        match self.get(key, 0) {
110            Ok(Some(_)) | Err(ValueTooLong) => Ok(true),
111            Ok(None) => Ok(false),
112            Err(e) => Err(e),
113        }
114    }
115
116    /// Return true if the request handle is valid.
117    #[deprecated(
118        since = "0.8.6",
119        note = "use the method on `ConfigStoreHandle` instead"
120    )]
121    pub fn is_valid(&self) -> bool {
122        !self.is_invalid()
123    }
124
125    /// Return true if the request handle is invalid.
126    #[deprecated(
127        since = "0.8.6",
128        note = "use the method on `ConfigStoreHandle` instead"
129    )]
130    pub fn is_invalid(&self) -> bool {
131        self.handle == Self::INVALID.handle
132    }
133
134    /// Get the underlying representation of the handle.
135    ///
136    /// This should only be used when calling the raw ABI directly, and care should be taken not to
137    /// reuse or alias handle values.
138    #[deprecated(
139        since = "0.8.6",
140        note = "use the method on `ConfigStoreHandle` instead"
141    )]
142    pub(crate) fn as_u32(&self) -> u32 {
143        self.handle
144    }
145
146    /// Get a mutable reference to the underlying `u32` representation of the handle.
147    ///
148    /// This should only be used when calling the raw ABI directly, and care should be taken not to
149    /// reuse or alias handle values.
150    #[deprecated(
151        since = "0.8.6",
152        note = "use the method on `ConfigStoreHandle` instead"
153    )]
154    pub(crate) fn as_u32_mut(&mut self) -> &mut u32 {
155        &mut self.handle
156    }
157}
158
159/// Errors thrown when a dictionary could not be opened.
160#[derive(Debug, thiserror::Error)]
161#[deprecated(since = "0.8.6", note = "use `config_store::OpenError` instead")]
162#[non_exhaustive]
163pub enum OpenError {
164    /// No dictionary with this name was found.
165    #[error("dictionary could not be found")]
166    DictionaryDoesNotExist,
167    /// A dictionary name was empty.
168    #[error("dictionary names cannot be empty")]
169    NameEmpty,
170    /// A dictionary name was too long.
171    #[error("dictionary name too long")]
172    NameTooLong,
173    /// A dictionary name was invalid.
174    #[error("invalid dictionary name")]
175    NameInvalid,
176}
177
178/// Errors thrown when a dictionary lookup failed.
179#[derive(Debug, thiserror::Error)]
180#[deprecated(since = "0.8.6", note = "use `config_store::LookupError` instead")]
181#[non_exhaustive]
182pub enum LookupError {
183    /// The dictionary handle used for a lookup was invalid.
184    #[error("invalid dictionary")]
185    DictionaryInvalid,
186    /// The dictionary key provided was invalid.
187    #[error("invalid dictionary key")]
188    KeyInvalid,
189    /// The dictionary key provided was too long.
190    #[error("dictionary keys must be shorter than 256 characters")]
191    KeyTooLong,
192    /// The dictionary value was too long for the provided buffer length.
193    #[error("dictionary value was longer than the given buffer")]
194    ValueTooLong,
195    /// Too many lookups have been performed
196    #[error("Too many lookups have been performed")]
197    TooManyLookups,
198    /// A dictionary lookup failed for some other reason.
199    #[error("dictionary lookup failed")]
200    Other,
201}