5
5
#![ deny( warnings) ]
6
6
#![ deny( missing_docs) ]
7
7
8
+ extern crate itertools;
8
9
extern crate serde;
9
10
#[ macro_use]
10
11
extern crate serde_derive;
@@ -17,6 +18,9 @@ extern crate serde_json;
17
18
pub use graphql_query_derive:: * ;
18
19
19
20
use std:: collections:: HashMap ;
21
+ use std:: fmt:: { self , Display } ;
22
+
23
+ use itertools:: Itertools ;
20
24
21
25
/// A convenience trait that can be used to build a GraphQL request body.
22
26
///
91
95
}
92
96
93
97
/// Represents a location inside a query string. Used in errors. See [`Error`].
94
- #[ derive( Debug , Serialize , Deserialize , PartialEq ) ]
98
+ #[ derive( Debug , Clone , Copy , Default , Serialize , Deserialize , PartialEq ) ]
95
99
pub struct Location {
96
100
/// The line number in the query string where the error originated (starting from 1).
97
101
pub line : i32 ,
@@ -100,7 +104,7 @@ pub struct Location {
100
104
}
101
105
102
106
/// Part of a path in a query. It can be an object key or an array index. See [`Error`].
103
- #[ derive( Debug , Serialize , Deserialize , PartialEq ) ]
107
+ #[ derive( Debug , Clone , Serialize , Deserialize , PartialEq ) ]
104
108
#[ serde( untagged) ]
105
109
pub enum PathFragment {
106
110
/// A key inside an object
@@ -109,6 +113,15 @@ pub enum PathFragment {
109
113
Index ( i32 ) ,
110
114
}
111
115
116
+ impl Display for PathFragment {
117
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
118
+ match * self {
119
+ PathFragment :: Key ( ref key) => write ! ( f, "{}" , key) ,
120
+ PathFragment :: Index ( ref idx) => write ! ( f, "{}" , idx) ,
121
+ }
122
+ }
123
+ }
124
+
112
125
/// An element in the top-level `errors` array of a response body.
113
126
///
114
127
/// This tries to be as close to the spec as possible.
@@ -177,7 +190,7 @@ pub enum PathFragment {
177
190
/// # Ok(())
178
191
/// # }
179
192
/// ```
180
- #[ derive( Debug , Serialize , Deserialize , PartialEq ) ]
193
+ #[ derive( Debug , Clone , Serialize , Deserialize , PartialEq ) ]
181
194
pub struct Error {
182
195
/// The human-readable error message. This is the only required field.
183
196
pub message : String ,
@@ -189,6 +202,25 @@ pub struct Error {
189
202
pub extensions : Option < HashMap < String , serde_json:: Value > > ,
190
203
}
191
204
205
+ impl Display for Error {
206
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
207
+ // Use `/` as a separator like JSON Pointer.
208
+ let path = self . path
209
+ . as_ref ( )
210
+ . map ( |fragments| format ! ( "{}" , fragments. iter( ) . format( "/" ) ) )
211
+ . unwrap_or_else ( || "<query>" . to_string ( ) ) ;
212
+
213
+ // Get the location of the error. We'll use just the first location for this.
214
+ let loc = self . locations
215
+ . as_ref ( )
216
+ . and_then ( |locations| locations. iter ( ) . next ( ) )
217
+ . cloned ( )
218
+ . unwrap_or_else ( Location :: default) ;
219
+
220
+ write ! ( f, "{}:{}:{}: {}" , path, loc. line, loc. column, self . message)
221
+ }
222
+ }
223
+
192
224
/// The generic shape taken by the responses of GraphQL APIs.
193
225
///
194
226
/// This will generally be used with the `ResponseData` struct from a derived module.
0 commit comments