apollo_federation/connectors/
variable.rs1use std::fmt::Display;
4use std::fmt::Formatter;
5use std::ops::Range;
6use std::str::FromStr;
7
8use itertools::Itertools;
9
10use super::id::ConnectedElement;
11use super::json_selection::SelectionTrie;
12use crate::connectors::validation::Code;
13
14#[derive(Clone, PartialEq)]
17pub(crate) struct VariableContext<'schema> {
18 pub(crate) element: &'schema ConnectedElement<'schema>,
20
21 pub(super) phase: Phase,
22 pub(super) target: Target,
23}
24
25impl<'schema> VariableContext<'schema> {
26 pub(crate) const fn new(
27 element: &'schema ConnectedElement<'schema>,
28 phase: Phase,
29 target: Target,
30 ) -> Self {
31 Self {
32 element,
33 phase,
34 target,
35 }
36 }
37
38 pub(crate) fn available_namespaces(&self) -> impl Iterator<Item = Namespace> {
40 match &self.phase {
41 Phase::Response => {
42 vec![
43 Namespace::Args,
44 Namespace::Config,
45 Namespace::Context,
46 Namespace::Status,
47 Namespace::This,
48 Namespace::Request,
49 Namespace::Response,
50 Namespace::Env,
51 ]
52 }
53 }
54 .into_iter()
55 }
56
57 pub(crate) fn namespaces_joined(&self) -> String {
59 self.available_namespaces()
60 .map(|s| s.to_string())
61 .sorted()
62 .join(", ")
63 }
64
65 pub(crate) const fn error_code(&self) -> Code {
67 match self.target {
68 Target::Body => Code::InvalidSelection,
69 }
70 }
71}
72
73#[derive(Clone, Copy, PartialEq)]
75pub(crate) enum Phase {
76 Response,
78}
79
80#[allow(unused)]
82#[derive(Clone, Copy, PartialEq)]
83pub(crate) enum Target {
84 Body,
86}
87
88#[derive(PartialEq, Eq, Clone, Copy, Hash)]
90pub enum Namespace {
91 Args,
92 Config,
93 Context,
94 Status,
95 This,
96 Batch,
97 Request,
98 Response,
99 Env,
100}
101
102impl Namespace {
103 pub const fn as_str(&self) -> &'static str {
104 match self {
105 Self::Args => "$args",
106 Self::Config => "$config",
107 Self::Context => "$context",
108 Self::Status => "$status",
109 Self::This => "$this",
110 Self::Batch => "$batch",
111 Self::Request => "$request",
112 Self::Response => "$response",
113 Self::Env => "$env",
114 }
115 }
116}
117
118impl FromStr for Namespace {
119 type Err = ();
120
121 fn from_str(s: &str) -> Result<Self, Self::Err> {
122 match s {
123 "$args" => Ok(Self::Args),
124 "$config" => Ok(Self::Config),
125 "$context" => Ok(Self::Context),
126 "$status" => Ok(Self::Status),
127 "$this" => Ok(Self::This),
128 "$batch" => Ok(Self::Batch),
129 "$request" => Ok(Self::Request),
130 "$response" => Ok(Self::Response),
131 "$env" => Ok(Self::Env),
132 _ => Err(()),
133 }
134 }
135}
136
137impl std::fmt::Debug for Namespace {
138 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
139 write!(f, "{}", self.as_str())
140 }
141}
142
143impl Display for Namespace {
144 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
145 write!(f, "{}", self.as_str())
146 }
147}
148
149#[derive(Debug, Eq, PartialEq, Clone, Hash)]
152pub struct VariableReference<N: FromStr + ToString> {
153 pub namespace: VariableNamespace<N>,
155
156 pub(crate) selection: SelectionTrie,
159
160 pub(crate) location: Option<Range<usize>>,
162}
163
164impl<N: FromStr + ToString> Display for VariableReference<N> {
165 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
166 f.write_str(self.namespace.namespace.to_string().as_str())?;
167 if !self.selection.is_empty() {
168 write!(f, " {{ {} }}", self.selection)?;
169 }
170 Ok(())
171 }
172}
173
174#[derive(Debug, Eq, PartialEq, Clone, Hash)]
176pub struct VariableNamespace<N: FromStr + ToString> {
177 pub namespace: N,
178 pub(crate) location: Option<Range<usize>>,
179}