rincon_core/api/
method.rs

1//! Method Calls as Data
2//!
3//! The REST API of ArangoDB defines operations to be invoked by a client
4//! application. In this driver we speak of a method call for the invocation
5//! of a REST operation. Each operation or method is defined by its input
6//! parameters and its return type. The input parameters may be mandatory or
7//! optional.
8//!
9//! In rincon method calls are represented as structs that implement the
10//! `Method` and the `Prepare` traits. Hence method calls are in fact structs
11//! that hold the data necessary to invoke an operation.
12//!
13//! The big advantage of defining method calls as data types is that instances
14//! of concrete method calls can be easily queued, distributed, repeated, cached
15//! or processed in batches. Further it is very easy to extend the driver with
16//! new operations by simple defining a new struct for each new operation, done.
17
18use std;
19use std::fmt::{self, Debug, Display};
20use std::iter::{ExactSizeIterator, FromIterator, Iterator};
21use std::slice::Iter;
22use std::vec::IntoIter;
23
24use serde::de::DeserializeOwned;
25use serde::ser::Serialize;
26
27use api::types::Value;
28use arango::ErrorCode;
29
30/// A `Method` type can be used to represent method calls.
31///
32/// This trait defines the result type of a method. As the rincon driver uses
33/// the `serde` crate as its serialization framework the return type must
34/// implement the `DeserializeOwned` trait of `serde`.
35pub trait Method {
36    /// The type of the result of a method call.
37    type Result: DeserializeOwned;
38
39    /// Specification of the fields of RPC-like return type.
40    ///
41    /// The design of the ArangoDB REST API is not very type safe friendly as
42    /// different operations use different fields in the top level result type.
43    /// Mainly it does not stick to one RPC-like style of fields returned as
44    /// operation results. Hence this hack is used to overcome this issue and
45    /// allows the driver to always return specific types for each operation.
46    const RETURN_TYPE: RpcReturnType;
47
48    /// Returns the specification of the RPC-like return type.
49    fn return_type(&self) -> RpcReturnType {
50        Self::RETURN_TYPE
51    }
52}
53
54/// A `Prepare` type of a method call is used to convert the method call into
55/// a concrete request that is specific to the protocol used by a `Connector`.
56///
57/// For example the `JsonHttpConnector` converts the `Prepare` type into a
58/// HTTP-request and serializes the content as JSON into the body of the
59/// request.
60///
61/// As the rincon driver uses the `serde` crate as its serialization framework
62/// the content type must implement the `Serialize` trait of `serde`.
63pub trait Prepare {
64    /// The type of the content of a method call.
65    ///
66    /// The content is the part of a request that is sent within the body of a
67    /// REST call.
68    type Content: Serialize;
69
70    /// Returns the type of operation this method is executing.
71    fn operation(&self) -> Operation;
72
73    /// Returns the resource path of a REST operation.
74    fn path(&self) -> String;
75
76    /// Returns the query parameters of this method.
77    ///
78    /// The query parameters are usually part of the URL of a REST call.
79    fn parameters(&self) -> Parameters;
80
81    /// Returns the header parameters of this method.
82    ///
83    /// The header parameters are usually sent with the HTTP header of a REST
84    /// call.
85    fn header(&self) -> Parameters;
86
87    /// Returns the content of this method if any.
88    ///
89    /// The content of a method is usually sent within the body of a REST call.
90    fn content(&self) -> Option<&Self::Content>;
91}
92
93/// Enumeration of the used operation of a REST API.
94///
95/// The operations are defined in a logical sense thus being abstract over the
96/// HTTP operations like POST, GET, PUT, PATCH, etc.
97#[derive(Clone, Copy, Debug)]
98pub enum Operation {
99    /// Create a new entity
100    Create,
101    /// Get an entity or resource
102    Read,
103    /// Modify an existing entity
104    Modify,
105    /// Replace an existing entity
106    Replace,
107    /// Delete an entity
108    Delete,
109    /// Get the header data or short info about an entity
110    ReadHeader,
111}
112
113/// A new type for a set of parameters or name/value pairs.
114///
115/// Each parameter consists of the name of the parameter and its value.
116#[derive(Clone, PartialEq)]
117pub struct Parameters {
118    list: Vec<(String, Value)>,
119}
120
121impl Parameters {
122    /// Creates and empty set of parameters.
123    pub fn empty() -> Self {
124        Parameters {
125            list: Vec::new(),
126        }
127    }
128
129    /// Creates a new set of parameters, which is empty.
130    pub fn new() -> Self {
131        Parameters {
132            list: Vec::new(),
133        }
134    }
135
136    /// Creates a new set of parameters with the given capacity.
137    ///
138    /// When the number of parameters to be inserted in the new parameter set
139    /// is known beforehand using this function can speed up memory allocation.
140    pub fn with_capacity(capacity: usize) -> Self {
141        Parameters {
142            list: Vec::with_capacity(capacity),
143        }
144    }
145
146    /// Returns whether this parameter set is empty.
147    pub fn is_empty(&self) -> bool {
148        self.list.is_empty()
149    }
150
151    /// Returns an `Iterator` over the parameters in this set.
152    pub fn iter(&self) -> ParameterIter {
153        ParameterIter {
154            inner: self.list.iter(),
155        }
156    }
157
158    /// Inserts a name/value pair as a new parameter into this set.
159    pub fn insert<K, V>(&mut self, name: K, value: V)
160        where K: Into<String>, V: Into<Value>
161    {
162        self.list.push((name.into(), value.into()));
163    }
164}
165
166impl Default for Parameters {
167    fn default() -> Self {
168        Parameters {
169            list: Vec::default(),
170        }
171    }
172}
173
174impl Debug for Parameters {
175    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
176        f.write_str("Parameters")
177            .and_then(|_| f.debug_list().entries(self.iter()).finish())
178    }
179}
180
181impl Display for Parameters {
182    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
183        let mut display = String::new();
184        display.push_str("Parameters[");
185        if !self.list.is_empty() {
186            for &(ref key, ref value) in &self.list {
187                display.push_str(key);
188                display.push('=');
189                display.push_str(&value.to_string());
190                display.push(',');
191                display.push(' ');
192            }
193            display.pop();
194            display.pop();
195        }
196        display.push(']');
197        f.write_str(&display)
198    }
199}
200
201impl<K, V> From<Vec<(K, V)>> for Parameters
202    where K: Into<String>, V: Into<Value>
203{
204    fn from(list: Vec<(K, V)>) -> Self {
205        Parameters::from_iter(list)
206    }
207}
208
209impl<K, V> FromIterator<(K, V)> for Parameters
210    where K: Into<String>, V: Into<Value>
211{
212    fn from_iter<T: IntoIterator<Item=(K, V)>>(iter: T) -> Parameters {
213        Parameters {
214            list: Vec::from_iter(iter.into_iter().map(|(k, v)| (k.into(), v.into()))),
215        }
216    }
217}
218
219impl<'i, K, V> FromIterator<&'i (K, V)> for Parameters
220    where K: Into<String> + Clone, V: Into<Value> + Clone
221{
222    fn from_iter<T: IntoIterator<Item=&'i (K, V)>>(iter: T) -> Parameters {
223        Parameters {
224            list: Vec::from_iter(iter.into_iter().map(|&(ref k, ref v)|
225                (k.clone().into(), v.clone().into()))),
226        }
227    }
228}
229
230impl<K, V> Extend<(K, V)> for Parameters
231    where K: Into<String>, V: Into<Value>
232{
233    fn extend<T: IntoIterator<Item=(K, V)>>(&mut self, iter: T) {
234        self.list.extend(iter.into_iter().map(|(k, v)| (k.into(), v.into())));
235    }
236}
237
238/// An `Iterator` over the references to name/value pairs of a parameter set.
239///
240/// This iterator is created by calling the `Parameters.iter()` function.
241#[derive(Debug)]
242pub struct ParameterIter<'i> {
243    inner: Iter<'i, (String, Value)>,
244}
245
246impl<'i> Iterator for ParameterIter<'i> {
247    type Item = &'i (String, Value);
248
249    fn next(&mut self) -> Option<Self::Item> {
250        self.inner.next()
251    }
252
253    fn size_hint(&self) -> (usize, Option<usize>) {
254        self.inner.size_hint()
255    }
256}
257
258impl<'i> ExactSizeIterator for ParameterIter<'i> {
259    fn len(&self) -> usize {
260        self.inner.len()
261    }
262}
263
264/// Specification of the fields of RPC-like return type.
265///
266/// The design of the ArangoDB REST API is not very type safe friendly as
267/// different operations use different fields in the top level result type.
268/// Mainly it does not stick to one RPC-like style of fields returned as
269/// operation results. Hence this hack is used to overcome this issue and
270/// allows the driver to always return specific types for each operation.
271#[allow(missing_copy_implementations)]
272#[derive(Debug, Clone, PartialEq)]
273pub struct RpcReturnType {
274    /// The name of the result field if any or none if the fields of the result
275    /// type are at the top level returned object.
276    pub result_field: Option<&'static str>,
277
278    /// The name of the code field that contains the error code if there is any
279    /// or none if the result will never contain an error code.
280    pub code_field: Option<&'static str>,
281}
282
283/// A container for entities in the result of a method call, where the result
284/// contains a list of entities and there might be error information for single
285/// results only, not the whole operation.
286#[derive(Debug, Clone, PartialEq)]
287pub enum Result<T> {
288    /// The successful result for one single entity of an operation that has
289    /// been executed for multiple entities.
290    Success(T),
291    /// The error for one single result that occurred during execution of an
292    /// operation for multiple entities.
293    Failed(Error),
294}
295
296impl<T> Result<T> {
297    /// Converts this `Result` into a `::std::result::Result`.
298    pub fn into_std_result(self) -> std::result::Result<T, Error> {
299        use self::Result::*;
300        match self {
301            Success(value) => Ok(value),
302            Failed(error) => Err(error),
303        }
304    }
305
306    /// Returns this `Result` as a `::std::result::Result` to the references
307    /// of the success or error value.
308    pub fn as_std_result(&self) -> std::result::Result<&T, &Error> {
309        use self::Result::*;
310        match *self {
311            Success(ref value) => Ok(value),
312            Failed(ref error) => Err(error),
313        }
314    }
315}
316
317impl<T> From<std::result::Result<T, Error>> for Result<T> {
318    fn from(value: std::result::Result<T, Error>) -> Self {
319        use self::Result::*;
320        match value {
321            Ok(value) => Success(value),
322            Err(error) => Failed(error),
323        }
324    }
325}
326
327/// A container for a list of `Result`s. This type is used as return type for
328/// methods that operate on a list of entities where the result can contain
329/// error information for single entities only, not the whole operation.
330#[derive(Debug, Clone, PartialEq, Deserialize)]
331pub struct ResultList<T>(#[serde(bound(deserialize = "T: DeserializeOwned"))] Vec<Result<T>>);
332
333impl<T> ResultList<T> {
334    /// Returns the result at the given index if available.
335    pub fn get(&self, index: usize) -> Option<std::result::Result<&T, &Error>> {
336        self.0.get(index).map(|x| x.as_std_result())
337    }
338
339    /// Returns an `Iterator` over the result items in this result list.
340    pub fn iter(&self) -> ResultListIter<T> {
341        ResultListIter(self.0.iter())
342    }
343}
344
345impl<T> FromIterator<std::result::Result<T, Error>> for ResultList<T> {
346    fn from_iter<I>(iter: I) -> Self
347        where I: IntoIterator<Item=std::result::Result<T, Error>>
348    {
349        ResultList(Vec::from_iter(iter.into_iter().map(From::from)))
350    }
351}
352
353impl<T> FromIterator<Result<T>> for ResultList<T> {
354    fn from_iter<I>(iter: I) -> Self
355        where I: IntoIterator<Item=Result<T>>
356    {
357        ResultList(Vec::from_iter(iter.into_iter()))
358    }
359}
360
361impl<T> IntoIterator for ResultList<T>
362    where T: DeserializeOwned
363{
364    type Item = std::result::Result<T, Error>;
365    type IntoIter = ResultListIntoIter<T>;
366
367    fn into_iter(self) -> Self::IntoIter {
368        ResultListIntoIter(self.0.into_iter())
369    }
370}
371
372/// An `Iterator` over the result items of a `ResultList`.
373///
374/// This iterator is returned by the `ResultList.into_iter()` function.
375#[derive(Debug)]
376pub struct ResultListIntoIter<T>(IntoIter<Result<T>>);
377
378impl<T> Iterator for ResultListIntoIter<T> {
379    type Item = std::result::Result<T, Error>;
380
381    fn next(&mut self) -> Option<Self::Item> {
382        self.0.next().map(|x| x.into_std_result())
383    }
384}
385
386impl<T> ExactSizeIterator for ResultListIntoIter<T> {}
387
388/// An `Iterator` over references to the result items of a `ResultList`.
389///
390/// This iterator is returned by the `ResulList.iter()` function.
391#[derive(Debug)]
392pub struct ResultListIter<'a, T: 'a>(Iter<'a, Result<T>>);
393
394impl<'a, T> Iterator for ResultListIter<'a, T> {
395    type Item = std::result::Result<&'a T, &'a Error>;
396
397    fn next(&mut self) -> Option<Self::Item> {
398        self.0.next().map(|x| x.as_std_result())
399    }
400}
401
402impl<'a, T> ExactSizeIterator for ResultListIter<'a, T> {}
403
404/// Represents an error that occurs during method execution.
405///
406/// A method `Error` is returned by the ArangoDB server when the execution of
407/// an operation fails.
408#[derive(Clone, PartialEq, Deserialize)]
409pub struct Error {
410    #[serde(rename = "errorNum")]
411    code: ErrorCode,
412    #[serde(rename = "errorMessage")]
413    message: String,
414}
415
416impl Error {
417    /// Contructs a new method `Error` with given code and message.
418    pub fn new<M>(code: ErrorCode, message: M) -> Self
419        where M: Into<String>
420    {
421        Error {
422            code,
423            message: message.into(),
424        }
425    }
426
427    /// Returns the code of this error.
428    ///
429    /// The possible error codes are defined by ArangoDB.
430    pub fn code(&self) -> ErrorCode {
431        self.code
432    }
433
434    /// Returns the message of this error.
435    ///
436    /// The message coming with an error is received from the ArangoDB server.
437    /// The driver transparently copies the error message into this property of
438    /// the `Error` struct.
439    pub fn message(&self) -> &str {
440        &self.message
441    }
442}
443
444impl Debug for Error {
445    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
446        f.write_str(&format!("Error {}: {}",
447            &self.code.as_u16(), &self.message))
448    }
449}
450
451impl Display for Error {
452    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
453        f.write_str(&format!("Error {}: {}",
454            &self.code.as_u16(), &self.message))
455    }
456}