@@ -23,7 +23,18 @@ struct DistToNextType {
23
23
alpha_numeric : Option < usize > ,
24
24
kanji : Option < usize > ,
25
25
byte : Option < usize > ,
26
- end : usize
26
+ end : usize ,
27
+ }
28
+ impl DistToNextType {
29
+ fn run_length ( & self ) -> usize {
30
+ [ self . numeric , self . alpha_numeric , self . kanji , self . byte , Some ( self . end ) ] . iter ( ) . filter_map ( |d| {
31
+ if let Some ( num) = d {
32
+ if * num == 0 { None } else { * d }
33
+ } else {
34
+ None
35
+ }
36
+ } ) . min ( ) . unwrap ( )
37
+ }
27
38
}
28
39
29
40
pub struct Encoder < ' a > {
@@ -73,9 +84,9 @@ impl<'a> Encoder<'a> {
73
84
. peekable ( ) ;
74
85
while input_iter. peek ( ) . is_some ( ) {
75
86
let ( next_encoding, mut bit_run, char_count) = match current_encoding {
76
- EncodingModes :: Numeric => Self :: encode_numeric_run ( & mut input_iter) ,
77
- EncodingModes :: AlphaNumeric => self . encode_alphanumeric_run ( & mut input_iter) ,
78
- EncodingModes :: Byte => self . encode_byte_run ( & mut input_iter) ,
87
+ EncodingModes :: Numeric => Self :: encode_numeric_run ( & mut input_iter, dynamic_mode ) ? ,
88
+ EncodingModes :: AlphaNumeric => self . encode_alphanumeric_run ( & mut input_iter, dynamic_mode ) ? ,
89
+ EncodingModes :: Byte => self . encode_byte_run ( & mut input_iter, dynamic_mode ) ? ,
79
90
_ => unreachable ! ( ) ,
80
91
} ;
81
92
self . output_data
@@ -210,7 +221,8 @@ impl<'a> Encoder<'a> {
210
221
211
222
fn encode_numeric_run < ' b , Input > (
212
223
input : & mut Peekable < Input > ,
213
- ) -> ( EncodingModes , BitVec < u8 , Msb0 > , usize )
224
+ dynamic : bool
225
+ ) -> Result < ( EncodingModes , BitVec < u8 , Msb0 > , usize ) , EncodingError >
214
226
where
215
227
Input : Iterator < Item = ( char , & ' b DistToNextType ) > ,
216
228
{
@@ -238,18 +250,22 @@ impl<'a> Encoder<'a> {
238
250
}
239
251
240
252
let next_mode = if let Some ( & ( c, _) ) = input. peek ( ) {
253
+ if !dynamic {
254
+ return Err ( EncodingError :: new ( "Need to change mode, but not dynamic" ) ) ;
255
+ }
241
256
Self :: char_type ( c)
242
257
} else {
243
258
// Doesn't matter
244
259
EncodingModes :: Numeric
245
260
} ;
246
- ( next_mode, encoded_numbers, char_count)
261
+ Ok ( ( next_mode, encoded_numbers, char_count) )
247
262
}
248
263
249
264
fn encode_alphanumeric_run < ' b , Input > (
250
265
& self ,
251
266
input : & mut Peekable < Input > ,
252
- ) -> ( EncodingModes , BitVec < u8 , Msb0 > , usize )
267
+ dynamic : bool
268
+ ) -> Result < ( EncodingModes , BitVec < u8 , Msb0 > , usize ) , EncodingError >
253
269
where
254
270
Input : Iterator < Item = ( char , & ' b DistToNextType ) > ,
255
271
{
@@ -259,11 +275,12 @@ impl<'a> Encoder<'a> {
259
275
( 10 ..=26 ) => 15 ,
260
276
( 27 ..) => 17 ,
261
277
} ;
278
+ let should_switch_down = c. is_ascii_digit ( )
279
+ && distances. alpha_numeric . unwrap_or ( usize:: MAX )
280
+ . min ( distances. byte . unwrap_or ( usize:: MAX ) )
281
+ . min ( distances. end ) >= min_dist_to_non_num;
262
282
Self :: is_qr_alphanumeric ( c)
263
- && ( !c. is_ascii_digit ( )
264
- || distances. alpha_numeric . unwrap_or ( usize:: MAX )
265
- . min ( distances. byte . unwrap_or ( usize:: MAX )
266
- . min ( distances. end ) ) < min_dist_to_non_num)
283
+ && ( !should_switch_down || !dynamic)
267
284
} ) ;
268
285
let mut char_count = 0usize ;
269
286
let mut encoded_alphanums = bitvec ! [ u8 , Msb0 ; ] ;
@@ -287,44 +304,55 @@ impl<'a> Encoder<'a> {
287
304
}
288
305
289
306
let next_mode = if let Some ( & ( c, _) ) = input. peek ( ) {
307
+ if !dynamic {
308
+ return Err ( EncodingError :: new ( "Need to change mode, but not dynamic" ) )
309
+ }
290
310
Self :: char_type ( c)
291
311
} else {
292
312
// Doesn't matter
293
313
EncodingModes :: Numeric
294
314
} ;
295
- ( next_mode, encoded_alphanums, char_count)
315
+ Ok ( ( next_mode, encoded_alphanums, char_count) )
296
316
}
297
317
298
318
fn encode_byte_run < ' b , Input > (
299
319
& self ,
300
320
input : & mut Peekable < Input > ,
301
- ) -> ( EncodingModes , BitVec < u8 , Msb0 > , usize )
321
+ dynamic : bool
322
+ ) -> Result < ( EncodingModes , BitVec < u8 , Msb0 > , usize ) , EncodingError >
302
323
where
303
324
Input : Iterator < Item = ( char , & ' b DistToNextType ) > ,
304
325
{
305
- let bytes = input. peeking_take_while ( |& ( c, distances) | {
306
- let min_dist_alphanum_to_byte = match self . size_estimate {
307
- ( 0 ..=9 ) => 11 ,
308
- ( 10 ..=26 ) => 15 ,
309
- ( 27 ..) => 16 ,
310
- } ;
311
- let min_dist_num_to_byte = match self . size_estimate {
312
- ( 0 ..=9 ) => 6 ,
313
- ( 10 ..=26 ) => 8 ,
314
- ( 27 ..) => 9 ,
315
- } ;
316
- let min_dist_num_to_alphanum = match self . size_estimate {
317
- ( 0 ..=9 ) => 6 ,
318
- ( 10 ..=26 ) => 7 ,
319
- ( 27 ..) => 8 ,
320
- } ;
321
-
322
- let change_to_alphanum = Self :: is_qr_alphanumeric ( c)
323
- && distances. byte . unwrap_or ( usize:: MAX ) . min ( distances. end ) >= min_dist_alphanum_to_byte;
324
- let change_to_numeric = c. is_ascii_digit ( )
326
+ let min_dist_alphanum_to_byte = match self . size_estimate {
327
+ ( 0 ..=9 ) => 11 ,
328
+ ( 10 ..=26 ) => 15 ,
329
+ ( 27 ..) => 16 ,
330
+ } ;
331
+ let min_dist_num_to_byte = match self . size_estimate {
332
+ ( 0 ..=9 ) => 6 ,
333
+ ( 10 ..=26 ) => 8 ,
334
+ ( 27 ..) => 9 ,
335
+ } ;
336
+ let min_dist_num_to_alphanum = match self . size_estimate {
337
+ ( 0 ..=9 ) => 6 ,
338
+ ( 10 ..=26 ) => 7 ,
339
+ ( 27 ..) => 8 ,
340
+ } ;
341
+ let change_to_alphanum = |c, distances : & DistToNextType | -> bool {
342
+ Self :: is_qr_alphanumeric ( c)
343
+ && distances. byte . unwrap_or ( usize:: MAX ) . min ( distances. end ) >= min_dist_alphanum_to_byte
344
+ } ;
345
+ let change_to_numeric = |c : char , distances : & DistToNextType | -> bool {
346
+ // TODO: needs to depend on run length as well!
347
+ c. is_ascii_digit ( )
325
348
&& ( distances. byte . unwrap_or ( usize:: MAX ) . min ( distances. end ) >= min_dist_num_to_byte
326
- || distances. alpha_numeric . unwrap_or ( usize:: MAX ) . min ( distances. end ) >= min_dist_num_to_alphanum) ;
327
- !( change_to_alphanum || change_to_numeric)
349
+ || distances. alpha_numeric . unwrap_or ( usize:: MAX ) . min ( distances. run_length ( ) ) . min ( distances. end ) >= min_dist_num_to_alphanum)
350
+ } ;
351
+
352
+ let bytes = input. peeking_take_while ( |& ( c, distances) | {
353
+ let should_change_to_alphanum = change_to_alphanum ( c, distances) ;
354
+ let should_change_to_numeric = change_to_numeric ( c, distances) ;
355
+ !( should_change_to_alphanum || should_change_to_numeric) || !dynamic
328
356
} ) ;
329
357
330
358
let mut byte_count = 0usize ;
@@ -342,13 +370,22 @@ impl<'a> Encoder<'a> {
342
370
}
343
371
}
344
372
345
- let next_mode = if let Some ( & ( c, _) ) = input. peek ( ) {
346
- Self :: char_type ( c)
373
+ let next_mode = if let Some ( & ( c, distances) ) = input. peek ( ) {
374
+ if !dynamic {
375
+ return Err ( EncodingError :: new ( "Need to change mode, but not dynamic" ) )
376
+ }
377
+ if change_to_alphanum ( c, distances) {
378
+ EncodingModes :: AlphaNumeric
379
+ } else if change_to_numeric ( c, distances) {
380
+ EncodingModes :: Numeric
381
+ } else {
382
+ unreachable ! ( )
383
+ }
347
384
} else {
348
385
// Doesn't matter
349
386
EncodingModes :: Byte
350
387
} ;
351
- ( next_mode, encoded_bytes, byte_count)
388
+ Ok ( ( next_mode, encoded_bytes, byte_count) )
352
389
}
353
390
354
391
fn sequence_preamble ( & self , encoding : EncodingModes , char_count : usize ) -> BitVec < u8 , Msb0 > {
0 commit comments