@@ -66,6 +66,9 @@ impl GraffitiFile {
66
66
67
67
for line in lines {
68
68
let line = line. map_err ( |e| Error :: InvalidLine ( e. to_string ( ) ) ) ?;
69
+ if line. trim ( ) . is_empty ( ) {
70
+ continue ;
71
+ }
69
72
let ( pk_opt, graffiti) = read_line ( & line) ?;
70
73
match pk_opt {
71
74
Some ( pk) => {
@@ -133,16 +136,25 @@ mod tests {
133
136
const CUSTOM_GRAFFITI1 : & str = "custom-graffiti1" ;
134
137
const CUSTOM_GRAFFITI2 : & str = "graffitiwall:720:641:#ffff00" ;
135
138
const EMPTY_GRAFFITI : & str = "" ;
139
+ // Newline test cases
140
+ const CUSTOM_GRAFFITI4 : & str = "newlines-tests" ;
141
+
136
142
const PK1 : & str = "0x800012708dc03f611751aad7a43a082142832b5c1aceed07ff9b543cf836381861352aa923c70eeb02018b638aa306aa" ;
137
143
const PK2 : & str = "0x80001866ce324de7d80ec73be15e2d064dcf121adf1b34a0d679f2b9ecbab40ce021e03bb877e1a2fe72eaaf475e6e21" ;
138
144
const PK3 : & str = "0x9035d41a8bc11b08c17d0d93d876087958c9d055afe86fce558e3b988d92434769c8d50b0b463708db80c6aae1160c02" ;
145
+ const PK4 : & str = "0x8c0fca2cc70f44188a4b79e5623ac85898f1df479e14a1f4ebb615907810b6fb939c3fb4ba2081b7a5b6e33dc73621d2" ;
146
+ const PK5 : & str = "0x87998b0ea4a8826f03d1985e5a5ce7235bd3a56fb7559b02a55b737f4ebc69b0bf35444de5cf2680cb7eb2283eb62050" ;
147
+ const PK6 : & str = "0xa2af9b128255568e2ee5c42af118cc4301198123d210dbdbf2ca7ec0222f8d491f308e85076b09a2f44a75875cd6fa0f" ;
139
148
140
149
// Create a graffiti file in the required format and return a path to the file.
141
150
fn create_graffiti_file ( ) -> PathBuf {
142
151
let temp = TempDir :: new ( ) . unwrap ( ) ;
143
152
let pk1 = PublicKeyBytes :: deserialize ( & hex:: decode ( & PK1 [ 2 ..] ) . unwrap ( ) ) . unwrap ( ) ;
144
153
let pk2 = PublicKeyBytes :: deserialize ( & hex:: decode ( & PK2 [ 2 ..] ) . unwrap ( ) ) . unwrap ( ) ;
145
154
let pk3 = PublicKeyBytes :: deserialize ( & hex:: decode ( & PK3 [ 2 ..] ) . unwrap ( ) ) . unwrap ( ) ;
155
+ let pk4 = PublicKeyBytes :: deserialize ( & hex:: decode ( & PK4 [ 2 ..] ) . unwrap ( ) ) . unwrap ( ) ;
156
+ let pk5 = PublicKeyBytes :: deserialize ( & hex:: decode ( & PK5 [ 2 ..] ) . unwrap ( ) ) . unwrap ( ) ;
157
+ let pk6 = PublicKeyBytes :: deserialize ( & hex:: decode ( & PK6 [ 2 ..] ) . unwrap ( ) ) . unwrap ( ) ;
146
158
147
159
let file_name = temp. into_path ( ) . join ( "graffiti.txt" ) ;
148
160
@@ -160,6 +172,29 @@ mod tests {
160
172
graffiti_file
161
173
. write_all ( format ! ( "{}:{}\n " , pk3. as_hex_string( ) , EMPTY_GRAFFITI ) . as_bytes ( ) )
162
174
. unwrap ( ) ;
175
+
176
+ // Test Lines with leading newlines - these empty lines will be skipped
177
+ graffiti_file. write_all ( b"\n " ) . unwrap ( ) ;
178
+ graffiti_file. write_all ( b" \n " ) . unwrap ( ) ;
179
+ graffiti_file
180
+ . write_all ( format ! ( "{}: {}\n " , pk4. as_hex_string( ) , CUSTOM_GRAFFITI4 ) . as_bytes ( ) )
181
+ . unwrap ( ) ;
182
+
183
+ // Test Empty lines between entries - these will be skipped
184
+ graffiti_file. write_all ( b"\n " ) . unwrap ( ) ;
185
+ graffiti_file. write_all ( b" \n " ) . unwrap ( ) ;
186
+ graffiti_file. write_all ( b"\t \n " ) . unwrap ( ) ;
187
+ graffiti_file
188
+ . write_all ( format ! ( "{}: {}\n " , pk5. as_hex_string( ) , CUSTOM_GRAFFITI4 ) . as_bytes ( ) )
189
+ . unwrap ( ) ;
190
+
191
+ // Test Trailing empty lines - these will be skipped
192
+ graffiti_file
193
+ . write_all ( format ! ( "{}: {}\n " , pk6. as_hex_string( ) , CUSTOM_GRAFFITI4 ) . as_bytes ( ) )
194
+ . unwrap ( ) ;
195
+ graffiti_file. write_all ( b"\n " ) . unwrap ( ) ;
196
+ graffiti_file. write_all ( b" \n " ) . unwrap ( ) ;
197
+
163
198
graffiti_file. flush ( ) . unwrap ( ) ;
164
199
file_name
165
200
}
@@ -172,6 +207,9 @@ mod tests {
172
207
let pk1 = PublicKeyBytes :: deserialize ( & hex:: decode ( & PK1 [ 2 ..] ) . unwrap ( ) ) . unwrap ( ) ;
173
208
let pk2 = PublicKeyBytes :: deserialize ( & hex:: decode ( & PK2 [ 2 ..] ) . unwrap ( ) ) . unwrap ( ) ;
174
209
let pk3 = PublicKeyBytes :: deserialize ( & hex:: decode ( & PK3 [ 2 ..] ) . unwrap ( ) ) . unwrap ( ) ;
210
+ let pk4 = PublicKeyBytes :: deserialize ( & hex:: decode ( & PK4 [ 2 ..] ) . unwrap ( ) ) . unwrap ( ) ;
211
+ let pk5 = PublicKeyBytes :: deserialize ( & hex:: decode ( & PK5 [ 2 ..] ) . unwrap ( ) ) . unwrap ( ) ;
212
+ let pk6 = PublicKeyBytes :: deserialize ( & hex:: decode ( & PK6 [ 2 ..] ) . unwrap ( ) ) . unwrap ( ) ;
175
213
176
214
// Read once
177
215
gf. read_graffiti_file ( ) . unwrap ( ) ;
@@ -190,6 +228,20 @@ mod tests {
190
228
GraffitiString :: from_str( EMPTY_GRAFFITI ) . unwrap( ) . into( )
191
229
) ;
192
230
231
+ // Test newline cases - all empty lines should be skipped
232
+ assert_eq ! (
233
+ gf. load_graffiti( & pk4) . unwrap( ) . unwrap( ) ,
234
+ GraffitiString :: from_str( CUSTOM_GRAFFITI4 ) . unwrap( ) . into( )
235
+ ) ;
236
+ assert_eq ! (
237
+ gf. load_graffiti( & pk5) . unwrap( ) . unwrap( ) ,
238
+ GraffitiString :: from_str( CUSTOM_GRAFFITI4 ) . unwrap( ) . into( )
239
+ ) ;
240
+ assert_eq ! (
241
+ gf. load_graffiti( & pk6) . unwrap( ) . unwrap( ) ,
242
+ GraffitiString :: from_str( CUSTOM_GRAFFITI4 ) . unwrap( ) . into( )
243
+ ) ;
244
+
193
245
// Random pk should return the default graffiti
194
246
let random_pk = Keypair :: random ( ) . pk . compress ( ) ;
195
247
assert_eq ! (
0 commit comments