reproto_core/
rp_path_spec.rs

1//! Path specifications
2
3use errors::Result;
4use std::vec;
5use {Diagnostics, Flavor, RpEndpointArgument, Translate, Translator};
6
7/// A part of a step.
8#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
9#[serde(bound = "F::Type: ::serde::Serialize")]
10#[serde(tag = "type", rename_all = "snake_case")]
11pub enum RpPathPart<F: 'static>
12where
13    F: Flavor,
14{
15    Variable(RpEndpointArgument<F>),
16    Segment(String),
17}
18
19impl<F: 'static, T> Translate<T> for RpPathPart<F>
20where
21    F: Flavor,
22    T: Translator<Source = F>,
23{
24    type Source = F;
25    type Out = RpPathPart<T::Target>;
26
27    /// Translate into different flavor.
28    fn translate(self, diag: &mut Diagnostics, translator: &T) -> Result<RpPathPart<T::Target>> {
29        use self::RpPathPart::*;
30
31        let out = match self {
32            Variable(arg) => Variable(arg.translate(diag, translator)?),
33            Segment(segment) => Segment(segment),
34        };
35
36        Ok(out)
37    }
38}
39
40/// A step in a path specification.
41#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
42#[serde(bound = "F::Type: ::serde::Serialize")]
43pub struct RpPathStep<F: 'static>
44where
45    F: Flavor,
46{
47    pub parts: Vec<RpPathPart<F>>,
48}
49
50impl<F: 'static, T> Translate<T> for RpPathStep<F>
51where
52    F: Flavor,
53    T: Translator<Source = F>,
54{
55    type Source = F;
56    type Out = RpPathStep<T::Target>;
57
58    /// Translate into different flavor.
59    fn translate(self, diag: &mut Diagnostics, translator: &T) -> Result<RpPathStep<T::Target>> {
60        Ok(RpPathStep {
61            parts: self.parts.translate(diag, translator)?,
62        })
63    }
64}
65
66/// A path specification.
67#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
68#[serde(bound = "F::Type: ::serde::Serialize")]
69pub struct RpPathSpec<F: 'static>
70where
71    F: Flavor,
72{
73    pub steps: Vec<RpPathStep<F>>,
74}
75
76#[derive(Debug)]
77pub struct Vars<'a, F: 'static>
78where
79    F: Flavor,
80{
81    iter: vec::IntoIter<&'a RpEndpointArgument<F>>,
82}
83
84impl<'a, F: 'static> Iterator for Vars<'a, F>
85where
86    F: Flavor,
87{
88    type Item = &'a RpEndpointArgument<F>;
89
90    fn next(&mut self) -> Option<Self::Item> {
91        self.iter.next()
92    }
93}
94
95impl<F: 'static> RpPathSpec<F>
96where
97    F: Flavor,
98{
99    /// List all variables in the path spec.
100    pub fn vars(&self) -> Vars<F> {
101        let mut vars = Vec::new();
102
103        for step in &self.steps {
104            for part in &step.parts {
105                if let RpPathPart::Variable(ref var) = *part {
106                    vars.push(var);
107                }
108            }
109        }
110
111        Vars {
112            iter: vars.into_iter(),
113        }
114    }
115}
116
117impl<F: 'static, T> Translate<T> for RpPathSpec<F>
118where
119    F: Flavor,
120    T: Translator<Source = F>,
121{
122    type Source = F;
123    type Out = RpPathSpec<T::Target>;
124
125    /// Translate into different flavor.
126    fn translate(self, diag: &mut Diagnostics, translator: &T) -> Result<RpPathSpec<T::Target>> {
127        Ok(RpPathSpec {
128            steps: self.steps.translate(diag, translator)?,
129        })
130    }
131}