@@ -15,6 +15,7 @@ use std::path::PathBuf;
15
15
use std:: rc:: Rc ;
16
16
use std:: { cmp, fmt, iter, str} ;
17
17
18
+ use serde:: ser:: { self , Serialize , Serializer } ;
18
19
use serde:: de:: { Deserialize , Deserializer } ;
19
20
use serde_json as json;
20
21
@@ -53,6 +54,35 @@ impl fmt::Display for FileName {
53
54
}
54
55
}
55
56
57
+ impl < ' de > Deserialize < ' de > for FileName {
58
+ fn deserialize < D > ( deserializer : D ) -> Result < FileName , D :: Error >
59
+ where
60
+ D : Deserializer < ' de > ,
61
+ {
62
+ let s = String :: deserialize ( deserializer) ?;
63
+ if s == "stdin" {
64
+ Ok ( FileName :: Stdin )
65
+ } else {
66
+ Ok ( FileName :: Real ( s. into ( ) ) )
67
+ }
68
+ }
69
+ }
70
+
71
+ impl Serialize for FileName {
72
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
73
+ where
74
+ S : Serializer ,
75
+ {
76
+ let s = match self {
77
+ FileName :: Stdin => Ok ( "stdin" ) ,
78
+ FileName :: Real ( path) => path. to_str ( ) . ok_or_else ( ||
79
+ ser:: Error :: custom ( "path can't be serialized as UTF-8 string" ) )
80
+ } ;
81
+
82
+ s. and_then ( |s| serializer. serialize_str ( s) )
83
+ }
84
+ }
85
+
56
86
impl LineRange {
57
87
pub fn file_name ( & self ) -> FileName {
58
88
self . file . name . clone ( ) . into ( )
@@ -175,6 +205,20 @@ impl FileLines {
175
205
Files ( self . 0 . as_ref ( ) . map ( |m| m. keys ( ) ) )
176
206
}
177
207
208
+ /// Returns JSON representation as accepted by the `--file-lines JSON` arg.
209
+ pub fn to_json_spans ( & self ) -> Vec < JsonSpan > {
210
+ match & self . 0 {
211
+ None => vec ! [ ] ,
212
+ Some ( file_ranges) => file_ranges
213
+ . iter ( )
214
+ . flat_map ( |( file, ranges) | ranges. iter ( ) . map ( move |r| ( file, r) ) )
215
+ . map ( |( file, range) | JsonSpan {
216
+ file : file. to_owned ( ) ,
217
+ range : ( range. lo , range. hi ) ,
218
+ } ) . collect ( ) ,
219
+ }
220
+ }
221
+
178
222
/// Returns true if `self` includes all lines in all files. Otherwise runs `f` on all ranges in
179
223
/// the designated file (if any) and returns true if `f` ever does.
180
224
fn file_range_matches < F > ( & self , file_name : & FileName , f : F ) -> bool
@@ -249,22 +293,12 @@ impl str::FromStr for FileLines {
249
293
}
250
294
251
295
// For JSON decoding.
252
- #[ derive( Clone , Debug , Deserialize ) ]
253
- struct JsonSpan {
254
- #[ serde( deserialize_with = "deserialize_filename" ) ]
296
+ #[ derive( Clone , Debug , Deserialize , Serialize ) ]
297
+ pub struct JsonSpan {
255
298
file : FileName ,
256
299
range : ( usize , usize ) ,
257
300
}
258
301
259
- fn deserialize_filename < ' de , D : Deserializer < ' de > > ( d : D ) -> Result < FileName , D :: Error > {
260
- let s = String :: deserialize ( d) ?;
261
- if s == "stdin" {
262
- Ok ( FileName :: Stdin )
263
- } else {
264
- Ok ( FileName :: Real ( s. into ( ) ) )
265
- }
266
- }
267
-
268
302
impl JsonSpan {
269
303
fn into_tuple ( self ) -> Result < ( FileName , Range ) , String > {
270
304
let ( lo, hi) = self . range ;
@@ -350,4 +384,28 @@ mod test {
350
384
Range :: new( 3 , 7 ) . merge( Range :: new( 4 , 5 ) )
351
385
) ;
352
386
}
387
+
388
+ use std:: { collections:: HashMap , path:: PathBuf } ;
389
+ use super :: { FileName , FileLines } ;
390
+ use super :: json:: { self , json, json_internal} ;
391
+
392
+ #[ test]
393
+ fn file_lines_to_json ( ) {
394
+ let ranges: HashMap < FileName , Vec < Range > > = [
395
+ ( FileName :: Real ( PathBuf :: from ( "src/main.rs" ) ) , vec ! [
396
+ Range :: new( 1 , 3 ) ,
397
+ Range :: new( 5 , 7 )
398
+ ] ) ,
399
+ ( FileName :: Real ( PathBuf :: from ( "src/lib.rs" ) ) , vec ! [
400
+ Range :: new( 1 , 7 )
401
+ ] ) ] . iter ( ) . cloned ( ) . collect ( ) ;
402
+
403
+ let file_lines = FileLines :: from_ranges ( ranges) ;
404
+ let json = json:: to_value ( & file_lines. to_json_spans ( ) ) . unwrap ( ) ;
405
+ assert_eq ! ( json, json! { [
406
+ { "file" : "src/main.rs" , "range" : [ 1 , 3 ] } ,
407
+ { "file" : "src/main.rs" , "range" : [ 5 , 7 ] } ,
408
+ { "file" : "src/lib.rs" , "range" : [ 1 , 7 ] } ,
409
+ ] } ) ;
410
+ }
353
411
}
0 commit comments