1#![allow(clippy::unreadable_literal, clippy::unusual_byte_groupings)]
2use std::cmp::min;
5
6#[cfg(feature = "bench")]
7extern crate test;
8
9use crate::cast::{As, Truncate};
10use crate::optimize::{total_encoded_len, Optimizer, Parser, Segment};
11use crate::types::{EcLevel, Mode, QrError, QrResult, Version};
12
13pub struct Bits {
18 data: Vec<u8>,
19 bit_offset: usize,
20 version: Version,
21}
22
23impl Bits {
24 pub fn new(version: Version) -> Self {
26 Self { data: Vec::new(), bit_offset: 0, version }
27 }
28
29 fn push_number(&mut self, n: usize, number: u16) {
35 debug_assert!(n == 16 || n < 16 && number < (1 << n), "{number} is too big as a {n}-bit number");
36
37 let b = self.bit_offset + n;
38 let last_index = self.data.len().wrapping_sub(1);
39 match (self.bit_offset, b) {
40 (0, 0..=8) => {
41 self.data.push((number << (8 - b)).truncate_as_u8());
42 }
43 (0, _) => {
44 self.data.push((number >> (b - 8)).truncate_as_u8());
45 self.data.push((number << (16 - b)).truncate_as_u8());
46 }
47 (_, 0..=8) => {
48 self.data[last_index] |= (number << (8 - b)).truncate_as_u8();
49 }
50 (_, 9..=16) => {
51 self.data[last_index] |= (number >> (b - 8)).truncate_as_u8();
52 self.data.push((number << (16 - b)).truncate_as_u8());
53 }
54 _ => {
55 self.data[last_index] |= (number >> (b - 8)).truncate_as_u8();
56 self.data.push((number >> (b - 16)).truncate_as_u8());
57 self.data.push((number << (24 - b)).truncate_as_u8());
58 }
59 }
60 self.bit_offset = b & 7;
61 }
62
63 pub fn push_number_checked(&mut self, n: usize, number: usize) -> QrResult<()> {
68 if n > 16 || number >= (1 << n) {
69 Err(QrError::DataTooLong)
70 } else {
71 self.push_number(n, number.as_u16());
72 Ok(())
73 }
74 }
75
76 fn reserve(&mut self, n: usize) {
78 let extra_bytes = (n + (8 - self.bit_offset) % 8) / 8;
79 self.data.reserve(extra_bytes);
80 }
81
82 pub fn into_bytes(self) -> Vec<u8> {
84 self.data
85 }
86
87 pub fn len(&self) -> usize {
89 if self.bit_offset == 0 {
90 self.data.len() * 8
91 } else {
92 (self.data.len() - 1) * 8 + self.bit_offset
93 }
94 }
95
96 pub fn is_empty(&self) -> bool {
98 self.data.is_empty()
99 }
100
101 pub fn max_len(&self, ec_level: EcLevel) -> QrResult<usize> {
110 self.version.fetch(ec_level, &DATA_LENGTHS)
111 }
112
113 pub fn version(&self) -> Version {
115 self.version
116 }
117}
118
119#[test]
120fn test_push_number() {
121 let mut bits = Bits::new(Version::Normal(1));
122
123 bits.push_number(3, 0b010); bits.push_number(3, 0b110); bits.push_number(3, 0b101); bits.push_number(7, 0b001_1010); bits.push_number(4, 0b1100); bits.push_number(12, 0b1011_0110_1101); bits.push_number(10, 0b01_1001_0001); bits.push_number(15, 0b111_0010_1110_0011); let bytes = bits.into_bytes();
133
134 assert_eq!(
135 bytes,
136 vec![
137 0b010_110_10, 0b1_001_1010, 0b1100_1011, 0b0110_1101, 0b01_1001_00, 0b01_111_001, 0b0_1110_001, 0b1_0000000, ]
146 );
147}
148
149#[cfg(feature = "bench")]
150#[bench]
151fn bench_push_splitted_bytes(bencher: &mut test::Bencher) {
152 bencher.iter(|| {
153 let mut bits = Bits::new(Version::Normal(40));
154 bits.push_number(4, 0b0101);
155 for _ in 0..1024 {
156 bits.push_number(8, 0b10101010);
157 }
158 bits.into_bytes()
159 });
160}
161
162#[derive(Copy, Clone)]
169pub enum ExtendedMode {
170 Eci,
172
173 Data(Mode),
175
176 Fnc1First,
178
179 Fnc1Second,
181
182 StructuredAppend,
184}
185
186impl Bits {
187 pub fn push_mode_indicator(&mut self, mode: ExtendedMode) -> QrResult<()> {
194 #[allow(clippy::match_same_arms)]
195 let number = match (self.version, mode) {
196 (Version::Micro(1), ExtendedMode::Data(Mode::Numeric)) => return Ok(()),
197 (Version::Micro(_), ExtendedMode::Data(Mode::Numeric)) => 0,
198 (Version::Micro(_), ExtendedMode::Data(Mode::Alphanumeric)) => 1,
199 (Version::Micro(_), ExtendedMode::Data(Mode::Byte)) => 0b10,
200 (Version::Micro(_), ExtendedMode::Data(Mode::Kanji)) => 0b11,
201 (Version::Micro(_), _) => return Err(QrError::UnsupportedCharacterSet),
202 (_, ExtendedMode::Data(Mode::Numeric)) => 0b0001,
203 (_, ExtendedMode::Data(Mode::Alphanumeric)) => 0b0010,
204 (_, ExtendedMode::Data(Mode::Byte)) => 0b0100,
205 (_, ExtendedMode::Data(Mode::Kanji)) => 0b1000,
206 (_, ExtendedMode::Eci) => 0b0111,
207 (_, ExtendedMode::Fnc1First) => 0b0101,
208 (_, ExtendedMode::Fnc1Second) => 0b1001,
209 (_, ExtendedMode::StructuredAppend) => 0b0011,
210 };
211 let bits = self.version.mode_bits_count();
212 self.push_number_checked(bits, number).or(Err(QrError::UnsupportedCharacterSet))
213 }
214}
215
216impl Bits {
221 pub fn push_eci_designator(&mut self, eci_designator: u32) -> QrResult<()> {
259 self.reserve(12); self.push_mode_indicator(ExtendedMode::Eci)?;
261 match eci_designator {
262 0..=127 => {
263 self.push_number(8, eci_designator.as_u16());
264 }
265 128..=16383 => {
266 self.push_number(2, 0b10);
267 self.push_number(14, eci_designator.as_u16());
268 }
269 16384..=999_999 => {
270 self.push_number(3, 0b110);
271 self.push_number(5, (eci_designator >> 16).as_u16());
272 self.push_number(16, (eci_designator & 0xffff).as_u16());
273 }
274 _ => return Err(QrError::InvalidEciDesignator),
275 }
276 Ok(())
277 }
278}
279
280#[cfg(test)]
281mod eci_tests {
282 use crate::bits::Bits;
283 use crate::types::{QrError, Version};
284
285 #[test]
286 fn test_9() {
287 let mut bits = Bits::new(Version::Normal(1));
288 assert_eq!(bits.push_eci_designator(9), Ok(()));
289 assert_eq!(bits.into_bytes(), vec![0b0111_0000, 0b1001_0000]);
290 }
291
292 #[test]
293 fn test_899() {
294 let mut bits = Bits::new(Version::Normal(1));
295 assert_eq!(bits.push_eci_designator(899), Ok(()));
296 assert_eq!(bits.into_bytes(), vec![0b0111_10_00, 0b00111000, 0b0011_0000]);
297 }
298
299 #[test]
300 fn test_999999() {
301 let mut bits = Bits::new(Version::Normal(1));
302 assert_eq!(bits.push_eci_designator(999999), Ok(()));
303 assert_eq!(bits.into_bytes(), vec![0b0111_110_0, 0b11110100, 0b00100011, 0b1111_0000]);
304 }
305
306 #[test]
307 fn test_invalid_designator() {
308 let mut bits = Bits::new(Version::Normal(1));
309 assert_eq!(bits.push_eci_designator(1000000), Err(QrError::InvalidEciDesignator));
310 }
311
312 #[test]
313 fn test_unsupported_character_set() {
314 let mut bits = Bits::new(Version::Micro(4));
315 assert_eq!(bits.push_eci_designator(9), Err(QrError::UnsupportedCharacterSet));
316 }
317}
318
319impl Bits {
324 fn push_header(&mut self, mode: Mode, raw_data_len: usize) -> QrResult<()> {
325 let length_bits = mode.length_bits_count(self.version);
326 self.reserve(length_bits + 4 + mode.data_bits_count(raw_data_len));
327 self.push_mode_indicator(ExtendedMode::Data(mode))?;
328 self.push_number_checked(length_bits, raw_data_len)?;
329 Ok(())
330 }
331
332 pub fn push_numeric_data(&mut self, data: &[u8]) -> QrResult<()> {
340 self.push_header(Mode::Numeric, data.len())?;
341 for chunk in data.chunks(3) {
342 let number = chunk.iter().map(|b| u16::from(*b - b'0')).fold(0, |a, b| a * 10 + b);
343 let length = chunk.len() * 3 + 1;
344 self.push_number(length, number);
345 }
346 Ok(())
347 }
348}
349
350#[cfg(test)]
351mod numeric_tests {
352 use crate::bits::Bits;
353 use crate::types::{QrError, Version};
354
355 #[test]
356 fn test_iso_18004_2006_example_1() {
357 let mut bits = Bits::new(Version::Normal(1));
358 assert_eq!(bits.push_numeric_data(b"01234567"), Ok(()));
359 assert_eq!(bits.into_bytes(), vec![0b0001_0000, 0b001000_00, 0b00001100, 0b01010110, 0b01_100001, 0b1_0000000]);
360 }
361
362 #[test]
363 fn test_iso_18004_2000_example_2() {
364 let mut bits = Bits::new(Version::Normal(1));
365 assert_eq!(bits.push_numeric_data(b"0123456789012345"), Ok(()));
366 assert_eq!(
367 bits.into_bytes(),
368 vec![
369 0b0001_0000,
370 0b010000_00,
371 0b00001100,
372 0b01010110,
373 0b01_101010,
374 0b0110_1110,
375 0b000101_00,
376 0b11101010,
377 0b0101_0000,
378 ]
379 );
380 }
381
382 #[test]
383 fn test_iso_18004_2006_example_2() {
384 let mut bits = Bits::new(Version::Micro(3));
385 assert_eq!(bits.push_numeric_data(b"0123456789012345"), Ok(()));
386 assert_eq!(
387 bits.into_bytes(),
388 vec![0b00_10000_0, 0b00000110, 0b0_0101011, 0b001_10101, 0b00110_111, 0b0000101_0, 0b01110101, 0b00101_000,]
389 );
390 }
391
392 #[test]
393 fn test_data_too_long_error() {
394 let mut bits = Bits::new(Version::Micro(1));
395 assert_eq!(bits.push_numeric_data(b"12345678"), Err(QrError::DataTooLong));
396 }
397}
398
399#[inline]
409fn alphanumeric_digit(character: u8) -> u16 {
410 match character {
411 b'0'..=b'9' => u16::from(character - b'0'),
412 b'A'..=b'Z' => u16::from(character - b'A') + 10,
413 b' ' => 36,
414 b'$' => 37,
415 b'%' => 38,
416 b'*' => 39,
417 b'+' => 40,
418 b'-' => 41,
419 b'.' => 42,
420 b'/' => 43,
421 b':' => 44,
422 _ => 0,
423 }
424}
425
426impl Bits {
427 pub fn push_alphanumeric_data(&mut self, data: &[u8]) -> QrResult<()> {
436 self.push_header(Mode::Alphanumeric, data.len())?;
437 for chunk in data.chunks(2) {
438 let number = chunk.iter().map(|b| alphanumeric_digit(*b)).fold(0, |a, b| a * 45 + b);
439 let length = chunk.len() * 5 + 1;
440 self.push_number(length, number);
441 }
442 Ok(())
443 }
444}
445
446#[cfg(test)]
447mod alphanumeric_tests {
448 use crate::bits::Bits;
449 use crate::types::{QrError, Version};
450
451 #[test]
452 fn test_iso_18004_2006_example() {
453 let mut bits = Bits::new(Version::Normal(1));
454 assert_eq!(bits.push_alphanumeric_data(b"AC-42"), Ok(()));
455 assert_eq!(bits.into_bytes(), vec![0b0010_0000, 0b00101_001, 0b11001110, 0b11100111, 0b001_00001, 0b0_0000000]);
456 }
457
458 #[test]
459 fn test_micro_qr_unsupported() {
460 let mut bits = Bits::new(Version::Micro(1));
461 assert_eq!(bits.push_alphanumeric_data(b"A"), Err(QrError::UnsupportedCharacterSet));
462 }
463
464 #[test]
465 fn test_data_too_long() {
466 let mut bits = Bits::new(Version::Micro(2));
467 assert_eq!(bits.push_alphanumeric_data(b"ABCDEFGH"), Err(QrError::DataTooLong));
468 }
469}
470
471impl Bits {
476 pub fn push_byte_data(&mut self, data: &[u8]) -> QrResult<()> {
482 self.push_header(Mode::Byte, data.len())?;
483 for b in data {
484 self.push_number(8, u16::from(*b));
485 }
486 Ok(())
487 }
488}
489
490#[cfg(test)]
491mod byte_tests {
492 use crate::bits::Bits;
493 use crate::types::{QrError, Version};
494
495 #[test]
496 fn test() {
497 let mut bits = Bits::new(Version::Normal(1));
498 assert_eq!(bits.push_byte_data(b"\x12\x34\x56\x78\x9a\xbc\xde\xf0"), Ok(()));
499 assert_eq!(
500 bits.into_bytes(),
501 vec![
502 0b0100_0000,
503 0b1000_0001,
504 0b0010_0011,
505 0b0100_0101,
506 0b0110_0111,
507 0b1000_1001,
508 0b1010_1011,
509 0b1100_1101,
510 0b1110_1111,
511 0b0000_0000,
512 ]
513 );
514 }
515
516 #[test]
517 fn test_micro_qr_unsupported() {
518 let mut bits = Bits::new(Version::Micro(2));
519 assert_eq!(bits.push_byte_data(b"?"), Err(QrError::UnsupportedCharacterSet));
520 }
521
522 #[test]
523 fn test_data_too_long() {
524 let mut bits = Bits::new(Version::Micro(3));
525 assert_eq!(bits.push_byte_data(b"0123456701234567"), Err(QrError::DataTooLong));
526 }
527}
528
529impl Bits {
534 pub fn push_kanji_data(&mut self, data: &[u8]) -> QrResult<()> {
543 self.push_header(Mode::Kanji, data.len() / 2)?;
544 for kanji in data.chunks(2) {
545 if kanji.len() != 2 {
546 return Err(QrError::InvalidCharacter);
547 }
548 let cp = u16::from(kanji[0]) * 256 + u16::from(kanji[1]);
549 let bytes = if cp < 0xe040 { cp - 0x8140 } else { cp - 0xc140 };
550 let number = (bytes >> 8) * 0xc0 + (bytes & 0xff);
551 self.push_number(13, number);
552 }
553 Ok(())
554 }
555}
556
557#[cfg(test)]
558mod kanji_tests {
559 use crate::bits::Bits;
560 use crate::types::{QrError, Version};
561
562 #[test]
563 fn test_iso_18004_example() {
564 let mut bits = Bits::new(Version::Normal(1));
565 assert_eq!(bits.push_kanji_data(b"\x93\x5f\xe4\xaa"), Ok(()));
566 assert_eq!(bits.into_bytes(), vec![0b1000_0000, 0b0010_0110, 0b11001111, 0b1_1101010, 0b101010_00]);
567 }
568
569 #[test]
570 fn test_micro_qr_unsupported() {
571 let mut bits = Bits::new(Version::Micro(2));
572 assert_eq!(bits.push_kanji_data(b"?"), Err(QrError::UnsupportedCharacterSet));
573 }
574
575 #[test]
576 fn test_data_too_long() {
577 let mut bits = Bits::new(Version::Micro(3));
578 assert_eq!(bits.push_kanji_data(b"\x93_\x93_\x93_\x93_\x93_\x93_\x93_\x93_"), Err(QrError::DataTooLong));
579 }
580}
581
582impl Bits {
587 pub fn push_fnc1_first_position(&mut self) -> QrResult<()> {
607 self.push_mode_indicator(ExtendedMode::Fnc1First)
608 }
609
610 pub fn push_fnc1_second_position(&mut self, application_indicator: u8) -> QrResult<()> {
636 self.push_mode_indicator(ExtendedMode::Fnc1Second)?;
637 self.push_number(8, u16::from(application_indicator));
638 Ok(())
639 }
640}
641
642static DATA_LENGTHS: [[usize; 4]; 44] = [
648 [152, 128, 104, 72],
650 [272, 224, 176, 128],
651 [440, 352, 272, 208],
652 [640, 512, 384, 288],
653 [864, 688, 496, 368],
654 [1088, 864, 608, 480],
655 [1248, 992, 704, 528],
656 [1552, 1232, 880, 688],
657 [1856, 1456, 1056, 800],
658 [2192, 1728, 1232, 976],
659 [2592, 2032, 1440, 1120],
660 [2960, 2320, 1648, 1264],
661 [3424, 2672, 1952, 1440],
662 [3688, 2920, 2088, 1576],
663 [4184, 3320, 2360, 1784],
664 [4712, 3624, 2600, 2024],
665 [5176, 4056, 2936, 2264],
666 [5768, 4504, 3176, 2504],
667 [6360, 5016, 3560, 2728],
668 [6888, 5352, 3880, 3080],
669 [7456, 5712, 4096, 3248],
670 [8048, 6256, 4544, 3536],
671 [8752, 6880, 4912, 3712],
672 [9392, 7312, 5312, 4112],
673 [10208, 8000, 5744, 4304],
674 [10960, 8496, 6032, 4768],
675 [11744, 9024, 6464, 5024],
676 [12248, 9544, 6968, 5288],
677 [13048, 10136, 7288, 5608],
678 [13880, 10984, 7880, 5960],
679 [14744, 11640, 8264, 6344],
680 [15640, 12328, 8920, 6760],
681 [16568, 13048, 9368, 7208],
682 [17528, 13800, 9848, 7688],
683 [18448, 14496, 10288, 7888],
684 [19472, 15312, 10832, 8432],
685 [20528, 15936, 11408, 8768],
686 [21616, 16816, 12016, 9136],
687 [22496, 17728, 12656, 9776],
688 [23648, 18672, 13328, 10208],
689 [20, 0, 0, 0],
691 [40, 32, 0, 0],
692 [84, 68, 0, 0],
693 [128, 112, 80, 0],
694];
695
696impl Bits {
697 pub fn push_terminator(&mut self, ec_level: EcLevel) -> QrResult<()> {
707 let terminator_size = match self.version {
708 Version::Micro(a) => a.as_usize() * 2 + 1,
709 Version::Normal(_) => 4,
710 };
711
712 let cur_length = self.len();
713 let data_length = self.max_len(ec_level)?;
714 if cur_length > data_length {
715 return Err(QrError::DataTooLong);
716 }
717
718 let terminator_size = min(terminator_size, data_length - cur_length);
719 if terminator_size > 0 {
720 self.push_number(terminator_size, 0);
721 }
722
723 if self.len() < data_length {
724 const PADDING_BYTES: &[u8] = &[0b1110_1100, 0b0001_0001];
725
726 self.bit_offset = 0;
727 let data_bytes_length = data_length / 8;
728 let padding_bytes_count = data_bytes_length - self.data.len();
729 let padding = PADDING_BYTES.iter().copied().cycle().take(padding_bytes_count);
730 self.data.extend(padding);
731 }
732
733 if self.len() < data_length {
734 self.data.push(0);
735 }
736
737 Ok(())
738 }
739}
740
741#[cfg(test)]
742mod finish_tests {
743 use crate::bits::Bits;
744 use crate::types::{EcLevel, QrError, Version};
745
746 #[test]
747 fn test_hello_world() {
748 let mut bits = Bits::new(Version::Normal(1));
749 assert_eq!(bits.push_alphanumeric_data(b"HELLO WORLD"), Ok(()));
750 assert_eq!(bits.push_terminator(EcLevel::Q), Ok(()));
751 assert_eq!(
752 bits.into_bytes(),
753 vec![
754 0b00100000, 0b01011011, 0b00001011, 0b01111000, 0b11010001, 0b01110010, 0b11011100, 0b01001101,
755 0b01000011, 0b01000000, 0b11101100, 0b00010001, 0b11101100,
756 ]
757 );
758 }
759
760 #[test]
761 fn test_too_long() {
762 let mut bits = Bits::new(Version::Micro(1));
763 assert_eq!(bits.push_numeric_data(b"9999999"), Ok(()));
764 assert_eq!(bits.push_terminator(EcLevel::L), Err(QrError::DataTooLong));
765 }
766
767 #[test]
768 fn test_no_terminator() {
769 let mut bits = Bits::new(Version::Micro(1));
770 assert_eq!(bits.push_numeric_data(b"99999"), Ok(()));
771 assert_eq!(bits.push_terminator(EcLevel::L), Ok(()));
772 assert_eq!(bits.into_bytes(), vec![0b101_11111, 0b00111_110, 0b0011_0000]);
773 }
774
775 #[test]
776 fn test_no_padding() {
777 let mut bits = Bits::new(Version::Micro(1));
778 assert_eq!(bits.push_numeric_data(b"9999"), Ok(()));
779 assert_eq!(bits.push_terminator(EcLevel::L), Ok(()));
780 assert_eq!(bits.into_bytes(), vec![0b100_11111, 0b00111_100, 0b1_000_0000]);
781 }
782
783 #[test]
784 fn test_micro_version_1_half_byte_padding() {
785 let mut bits = Bits::new(Version::Micro(1));
786 assert_eq!(bits.push_numeric_data(b"999"), Ok(()));
787 assert_eq!(bits.push_terminator(EcLevel::L), Ok(()));
788 assert_eq!(bits.into_bytes(), vec![0b011_11111, 0b00111_000, 0b0000_0000]);
789 }
790
791 #[test]
792 fn test_micro_version_1_full_byte_padding() {
793 let mut bits = Bits::new(Version::Micro(1));
794 assert_eq!(bits.push_numeric_data(b""), Ok(()));
795 assert_eq!(bits.push_terminator(EcLevel::L), Ok(()));
796 assert_eq!(bits.into_bytes(), vec![0b000_000_00, 0b11101100, 0]);
797 }
798}
799
800impl Bits {
805 pub fn push_segments<I>(&mut self, data: &[u8], segments_iter: I) -> QrResult<()>
814 where
815 I: Iterator<Item = Segment>,
816 {
817 for segment in segments_iter {
818 let slice = &data[segment.begin..segment.end];
819 match segment.mode {
820 Mode::Numeric => self.push_numeric_data(slice),
821 Mode::Alphanumeric => self.push_alphanumeric_data(slice),
822 Mode::Byte => self.push_byte_data(slice),
823 Mode::Kanji => self.push_kanji_data(slice),
824 }?;
825 }
826 Ok(())
827 }
828
829 pub fn push_optimal_data(&mut self, data: &[u8]) -> QrResult<()> {
835 let segments = Parser::new(data).optimize(self.version);
836 self.push_segments(data, segments)
837 }
838}
839
840#[cfg(test)]
841mod encode_tests {
842 use crate::bits::Bits;
843 use crate::types::{EcLevel, QrError, QrResult, Version};
844
845 fn encode(data: &[u8], version: Version, ec_level: EcLevel) -> QrResult<Vec<u8>> {
846 let mut bits = Bits::new(version);
847 bits.push_optimal_data(data)?;
848 bits.push_terminator(ec_level)?;
849 Ok(bits.into_bytes())
850 }
851
852 #[test]
853 fn test_alphanumeric() {
854 let res = encode(b"HELLO WORLD", Version::Normal(1), EcLevel::Q);
855 assert_eq!(
856 res,
857 Ok(vec![
858 0b00100000, 0b01011011, 0b00001011, 0b01111000, 0b11010001, 0b01110010, 0b11011100, 0b01001101,
859 0b01000011, 0b01000000, 0b11101100, 0b00010001, 0b11101100,
860 ])
861 );
862 }
863
864 #[test]
865 fn test_auto_mode_switch() {
866 let res = encode(b"123A", Version::Micro(2), EcLevel::L);
867 assert_eq!(res, Ok(vec![0b0_0011_000, 0b1111011_1, 0b001_00101, 0b0_00000_00, 0b11101100]));
868 }
869
870 #[test]
871 fn test_too_long() {
872 let res = encode(b">>>>>>>>", Version::Normal(1), EcLevel::H);
873 assert_eq!(res, Err(QrError::DataTooLong));
874 }
875}
876
877pub fn encode_auto(data: &[u8], ec_level: EcLevel) -> QrResult<Bits> {
891 let segments = Parser::new(data).collect::<Vec<Segment>>();
892 for version in &[Version::Normal(9), Version::Normal(26), Version::Normal(40)] {
893 let opt_segments = Optimizer::new(segments.iter().copied(), *version).collect::<Vec<_>>();
894 let total_len = total_encoded_len(&opt_segments, *version);
895 let data_capacity = version.fetch(ec_level, &DATA_LENGTHS).expect("invalid DATA_LENGTHS");
896 if total_len <= data_capacity {
897 let min_version = find_min_version(total_len, ec_level);
898 let mut bits = Bits::new(min_version);
899 bits.reserve(total_len);
900 bits.push_segments(data, opt_segments.into_iter())?;
901 bits.push_terminator(ec_level)?;
902 return Ok(bits);
903 }
904 }
905 Err(QrError::DataTooLong)
906}
907
908fn find_min_version(length: usize, ec_level: EcLevel) -> Version {
911 let mut base = 0_usize;
912 let mut size = 39;
913 while size > 1 {
914 let half = size / 2;
915 let mid = base + half;
916 base = if DATA_LENGTHS[mid][ec_level as usize] > length { base } else { mid };
920 size -= half;
921 }
922 base = if DATA_LENGTHS[base][ec_level as usize] >= length { base } else { base + 1 };
924 Version::Normal((base + 1).as_i16())
925}
926
927#[cfg(test)]
928mod encode_auto_tests {
929 use crate::bits::{encode_auto, find_min_version};
930 use crate::types::{EcLevel, Version};
931
932 #[test]
933 fn test_find_min_version() {
934 assert_eq!(find_min_version(60, EcLevel::L), Version::Normal(1));
935 assert_eq!(find_min_version(200, EcLevel::L), Version::Normal(2));
936 assert_eq!(find_min_version(200, EcLevel::H), Version::Normal(3));
937 assert_eq!(find_min_version(20000, EcLevel::L), Version::Normal(37));
938 assert_eq!(find_min_version(640, EcLevel::L), Version::Normal(4));
939 assert_eq!(find_min_version(641, EcLevel::L), Version::Normal(5));
940 assert_eq!(find_min_version(999999, EcLevel::H), Version::Normal(40));
941 }
942
943 #[test]
944 fn test_alpha_q() {
945 let bits = encode_auto(b"HELLO WORLD", EcLevel::Q).unwrap();
946 assert_eq!(bits.version(), Version::Normal(1));
947 }
948
949 #[test]
950 fn test_alpha_h() {
951 let bits = encode_auto(b"HELLO WORLD", EcLevel::H).unwrap();
952 assert_eq!(bits.version(), Version::Normal(2));
953 }
954
955 #[test]
956 fn test_mixed() {
957 let bits = encode_auto(b"This is a mixed data test. 1234567890", EcLevel::H).unwrap();
958 assert_eq!(bits.version(), Version::Normal(4));
959 }
960}
961
962#[cfg(feature = "bench")]
963#[bench]
964fn bench_find_min_version(bencher: &mut test::Bencher) {
965 use test::black_box;
966
967 bencher.iter(|| {
968 black_box(find_min_version(60, EcLevel::L));
969 black_box(find_min_version(200, EcLevel::L));
970 black_box(find_min_version(200, EcLevel::H));
971 black_box(find_min_version(20000, EcLevel::L));
972 black_box(find_min_version(640, EcLevel::L));
973 black_box(find_min_version(641, EcLevel::L));
974 black_box(find_min_version(999999, EcLevel::H));
975 })
976}
977
978