1
+ use std:: io:: { Read , Write } ;
2
+ use super :: language:: * ;
3
+
4
+ pub struct CodeFile {
5
+ pub language : Language ,
6
+ pub path : std:: path:: PathBuf ,
7
+ pub question_title : String ,
8
+ pub code : String ,
9
+ }
10
+
11
+ impl CodeFile {
12
+ pub fn from_dir ( ) -> Self {
13
+ let mut code_file: Option < CodeFile > = None ;
14
+ let files = std:: fs:: read_dir ( "./" ) . unwrap ( ) ;
15
+ for file in files {
16
+ let Ok ( file) = file else {
17
+ // Bad path
18
+ continue
19
+ } ;
20
+ let path = file. path ( ) ;
21
+ let Some ( file_name) = path. file_name ( ) . and_then ( |filename| filename. to_str ( ) ) else {
22
+ // Non-UTF-8 name
23
+ continue
24
+ } ;
25
+ let Some ( extension) = path. extension ( ) . and_then ( |ext| ext. to_str ( ) ) else {
26
+ // A hidden file (like .gitignore), or a file with no '.', or a file with weird non-UTF-8 extension.
27
+ continue
28
+ } ;
29
+ let Some ( language) = Language :: from_str ( extension) else {
30
+ // Unsupported language
31
+ continue ;
32
+ } ;
33
+
34
+ code_file = Some (
35
+ CodeFile {
36
+ language, path : path. clone ( ) , question_title : String :: new ( ) , code : String :: new ( )
37
+ }
38
+ ) ;
39
+
40
+ if file_name. starts_with ( "main" ) {
41
+ break ;
42
+ }
43
+ }
44
+ let mut code_file = code_file. unwrap_or_else ( || {
45
+ let default_code_file = CodeFile {
46
+ language : Language :: Rust ,
47
+ path : std:: path:: PathBuf :: from ( "main.rs" ) ,
48
+ question_title : String :: new ( ) ,
49
+ code : String :: new ( ) ,
50
+ } ;
51
+ println ! (
52
+ "No code file found. Creating a new file named {}" ,
53
+ default_code_file. path. display( )
54
+ ) ;
55
+ let mut file =
56
+ std:: fs:: File :: create ( & default_code_file. path ) . expect ( "Error during file creation" ) ;
57
+ let two_sum_problem = b"struct Solution;\n \n // https://leetcode.com/problems/two-sum/ #LCSTART\n \n impl Solution {\n \t pub fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {\n \n \t }\n } // #LCEND\n fn main() {}" ;
58
+ file. write_all ( two_sum_problem) . expect ( "File write failed" ) ;
59
+
60
+ default_code_file
61
+ } ) ;
62
+ let mut file = std:: fs:: File :: open ( & code_file. path ) . unwrap ( ) ;
63
+ let mut code = String :: new ( ) ;
64
+ file. read_to_string ( & mut code) . expect ( & format ! (
65
+ "Failed to read file {}" ,
66
+ code_file. path. display( )
67
+ ) ) ;
68
+ let start = code
69
+ . find ( "#LCSTART" )
70
+ . map ( |idx| idx +
71
+ // This returning None the user
72
+ // wants to submit a practically empty file,
73
+ // but hey we don't judge!
74
+ code[ idx..] . find ( '\n' ) . unwrap_or ( 0 ) )
75
+ . unwrap_or ( 0 ) ;
76
+
77
+ let end = code. find ( "#LCEND" ) . unwrap_or ( code. len ( ) ) ;
78
+ if let Some ( problem) = code. find ( "leetcode.com/problems/" ) {
79
+ let problem = ( & code[ problem..] ) . split_whitespace ( ) . next ( ) . unwrap ( ) ;
80
+ let problem = problem. split ( '/' ) . skip ( 2 ) . next ( ) . unwrap ( ) ;
81
+ code_file. question_title = problem. to_string ( ) ;
82
+ } else {
83
+ println ! ( "No leetcode problem found in the code file. Please add the problem link in the code file using comments." ) ;
84
+ // terminate with error
85
+ std:: process:: exit ( 1 ) ;
86
+ }
87
+ code_file. code = code[ start..end] . to_string ( ) ;
88
+ code_file
89
+ }
90
+
91
+ pub fn from_file ( path : String ) -> Self {
92
+ let extension = path. split ( '.' ) . last ( ) . unwrap ( ) ;
93
+ let language = Language :: from_str ( extension) . expect ( "File extension not supported" ) ;
94
+ let file = std:: fs:: File :: open ( & path) ;
95
+ let Ok ( mut file) = file else {
96
+ println ! ( "Error while opening file {}" , & path ) ;
97
+ std:: process:: exit ( 1 ) ;
98
+ } ;
99
+ let mut code = String :: new ( ) ;
100
+ file. read_to_string ( & mut code)
101
+ . expect ( & format ! ( "Failed to read file {}" , & path) ) ;
102
+ let start = code
103
+ . find ( "#LCSTART" )
104
+ . map ( |idx| idx +
105
+ // This returning None the user
106
+ // wants to submit a practically empty file,
107
+ // but hey we don't judge!
108
+ code[ idx..] . find ( '\n' ) . unwrap_or ( 0 ) )
109
+ . unwrap_or ( 0 ) ;
110
+
111
+ let end = code. find ( "#LCEND" ) . unwrap_or ( code. len ( ) ) ;
112
+ if let Some ( problem) = code. find ( "leetcode.com/problems/" ) {
113
+ let problem = ( & code[ problem..] ) . split_whitespace ( ) . next ( ) . unwrap ( ) ;
114
+ let problem = problem. split ( '/' ) . into_iter ( ) . rev ( ) . skip ( 1 ) . next ( ) . unwrap ( ) ;
115
+ let question_title = problem. to_string ( ) ;
116
+ Self {
117
+ language,
118
+ path : std:: path:: PathBuf :: from ( path) ,
119
+ question_title,
120
+ code : code[ start..end] . to_string ( ) ,
121
+ }
122
+ } else {
123
+ println ! ( "No leetcode problem found in the code file. Please add the problem link in the code file using comments." ) ;
124
+ // terminate with error
125
+ std:: process:: exit ( 1 ) ;
126
+ }
127
+ }
128
+ }
129
+
130
+
131
+ #[ derive( Default ) ]
132
+ struct CodeFileBuilder {
133
+ language : Option < Language > ,
134
+ path : Option < std:: path:: PathBuf > ,
135
+ question_title : Option < String > ,
136
+ code : Option < String > ,
137
+ }
138
+
139
+ impl CodeFileBuilder {
140
+ pub fn new ( ) -> Self {
141
+ Default :: default ( )
142
+ }
143
+
144
+ pub fn build ( self ) -> CodeFile {
145
+ CodeFile {
146
+ language : self . language . unwrap_or ( Language :: Rust ) ,
147
+ path : self . path . unwrap_or_else ( || std:: path:: PathBuf :: from ( "main.rs" ) ) ,
148
+ question_title : self . question_title . unwrap_or_else ( || String :: new ( ) ) ,
149
+ code : self . code . unwrap_or_else ( || String :: new ( ) ) ,
150
+ }
151
+ }
152
+
153
+ pub fn set_language ( mut self , language : Language ) -> Self {
154
+ self . language = Some ( language) ;
155
+ self
156
+ }
157
+
158
+ pub fn set_path ( mut self , path : std:: path:: PathBuf ) -> Self {
159
+ self . path = Some ( path) ;
160
+ self
161
+ }
162
+
163
+ pub fn set_question_title ( mut self , question_title : String ) -> Self {
164
+ self . question_title = Some ( question_title) ;
165
+ self
166
+ }
167
+
168
+ pub fn set_code ( mut self , code : String ) -> Self {
169
+ self . code = Some ( code) ;
170
+ self
171
+ }
172
+ }
0 commit comments