1
- use std:: {
2
- fs:: File ,
3
- io:: { self , BufReader , Read } ,
4
- path:: PathBuf ,
5
- time:: SystemTime ,
6
- } ;
1
+ use std:: { fs:: File , io, mem:: take, path:: PathBuf , str:: from_utf8, time:: SystemTime } ;
7
2
8
- use super :: { change :: Change , constants:: COULD_NOT_UNWRAP_FILENAME } ;
3
+ use super :: constants:: COULD_NOT_UNWRAP_FILENAME ;
9
4
10
- pub struct FileData {
5
+ #[ derive( Debug ) ]
6
+ pub struct FileData < ' a > {
11
7
path : PathBuf ,
12
- lines : Vec < String > ,
13
- changes : Vec < Change > ,
8
+ lines : Vec < & ' a str > ,
14
9
modified : SystemTime ,
15
10
ends_with_newline : bool ,
16
11
}
17
12
18
- impl FileData {
13
+ impl < ' a > FileData < ' a > {
19
14
pub fn ends_with_newline ( & self ) -> bool {
20
15
self . ends_with_newline
21
16
}
22
17
23
- pub fn get_file ( path : PathBuf ) -> io:: Result < Self > {
24
- let file = File :: open ( path. clone ( ) ) ?;
18
+ pub fn get_file (
19
+ path : PathBuf ,
20
+ lines : Vec < & ' a str > ,
21
+ ends_with_newline : bool ,
22
+ ) -> io:: Result < Self > {
23
+ let file = File :: open ( & path) ?;
25
24
let modified = file. metadata ( ) ?. modified ( ) ?;
26
- let mut buf_reader = BufReader :: new ( file) ;
27
- let mut content = String :: new ( ) ;
28
- buf_reader. read_to_string ( & mut content) ?;
29
25
30
- let mut lines = content
31
- . lines ( )
32
- . map ( |line| line. to_string ( ) )
33
- . collect :: < Vec < String > > ( ) ;
34
-
35
- let ends_with_newline = content. ends_with ( "\n " ) ;
36
-
37
- if ends_with_newline {
38
- lines. push ( String :: from ( "" ) ) ;
39
- }
40
-
41
- let changes = vec ! [ Change :: None ; lines. len( ) ] ;
42
-
43
- let result = Self {
26
+ Ok ( Self {
44
27
path,
45
28
lines,
46
- changes,
47
29
modified,
48
30
ends_with_newline,
49
- } ;
50
-
51
- Ok ( result)
31
+ } )
52
32
}
53
33
54
- pub fn get_context_identifier ( & self , change_index : usize ) -> & str {
55
- match self . changes [ change_index] {
56
- Change :: None => " " ,
57
- Change :: Unchanged ( _) => " " ,
58
- Change :: Insert ( _) => "+" ,
59
- Change :: Delete ( _) => "-" ,
60
- Change :: Substitute ( _) => "!" ,
61
- }
62
- }
63
-
64
- pub fn lines ( & self ) -> & Vec < String > {
34
+ pub fn lines ( & self ) -> & Vec < & str > {
65
35
& self . lines
66
36
}
67
37
68
- pub fn line ( & self , index : usize ) -> & String {
69
- & self . lines [ index]
38
+ pub fn line ( & self , index : usize ) -> & str {
39
+ self . lines [ index]
70
40
}
71
41
72
42
pub fn modified ( & self ) -> SystemTime {
@@ -80,35 +50,54 @@ impl FileData {
80
50
}
81
51
}
82
52
83
- return COULD_NOT_UNWRAP_FILENAME ;
53
+ COULD_NOT_UNWRAP_FILENAME
84
54
}
85
55
86
- pub fn set_change ( & mut self , change : Change , index : usize ) {
87
- self . changes [ index ] = change ;
56
+ pub fn path ( & self ) -> & str {
57
+ self . path . to_str ( ) . unwrap_or ( COULD_NOT_UNWRAP_FILENAME )
88
58
}
59
+ }
89
60
90
- pub fn expected_changed_in_range (
91
- & self ,
92
- start : usize ,
93
- end : usize ,
94
- expected_changes : & Vec < fn ( & Change ) -> bool > ,
95
- ) -> bool {
96
- for i in start..=end {
97
- for expected_change in expected_changes {
98
- if expected_change ( & self . changes [ i] ) {
99
- return true ;
100
- }
101
- }
102
- }
61
+ pub struct LineReader < ' a > {
62
+ content : & ' a [ u8 ] ,
63
+ ends_with_newline : bool ,
64
+ }
103
65
104
- return false ;
66
+ impl < ' a > LineReader < ' a > {
67
+ pub fn new ( content : & ' a [ u8 ] ) -> Self {
68
+ let ends_with_newline = content. last ( ) == Some ( & b'\n' ) ;
69
+ Self {
70
+ content,
71
+ ends_with_newline,
72
+ }
105
73
}
106
-
107
- pub fn change ( & self , index : usize ) -> & Change {
108
- & self . changes [ index]
74
+ pub fn ends_with_newline ( & self ) -> bool {
75
+ self . ends_with_newline
109
76
}
77
+ }
110
78
111
- pub fn path ( & self ) -> & str {
112
- self . path . to_str ( ) . unwrap_or ( COULD_NOT_UNWRAP_FILENAME )
79
+ impl < ' a > Iterator for LineReader < ' a > {
80
+ type Item = & ' a str ;
81
+
82
+ fn next ( & mut self ) -> Option < Self :: Item > {
83
+ let mut carriage = false ;
84
+ let mut iter = self . content . iter ( ) . enumerate ( ) ;
85
+ let mut line_len = loop {
86
+ match iter. next ( ) {
87
+ Some ( ( i, b'\n' ) ) => break i + 1 ,
88
+ None => {
89
+ return ( !self . content . is_empty ( ) ) . then ( || {
90
+ from_utf8 ( take ( & mut self . content ) ) . expect ( "Failed to convert to str" )
91
+ } ) ;
92
+ }
93
+ Some ( ( _, & it) ) => carriage = it == b'\r' ,
94
+ }
95
+ } ;
96
+ let ( line, rest) = self . content . split_at ( line_len) ;
97
+ if carriage {
98
+ line_len -= 1 ;
99
+ }
100
+ self . content = rest;
101
+ Some ( from_utf8 ( & line[ ..line_len - 1 ] ) . expect ( "Failed to convert to str" ) )
113
102
}
114
103
}
0 commit comments