Skip to main content

qrcode_core/
bits.rs

1#![allow(clippy::unreadable_literal, clippy::unusual_byte_groupings)]
2//! Bit-level data encoding for QR codes.
3//!
4//! This module handles the conversion of raw input data into the bit stream
5//! that gets placed onto the QR code canvas. It supports all four data modes:
6//!
7//! - **Numeric** — digits 0-9 (most efficient)
8//! - **Alphanumeric** — uppercase letters, digits, and a few symbols
9//! - **Byte** — arbitrary 8-bit data (including UTF-8)
10//! - **Kanji** — Shift JIS encoded double-byte characters
11//!
12//! The [`Bits`] struct is the main entry point. Use [`encode_auto`] or
13//! [`encode_auto_micro`] for automatic version and mode selection, or
14//! construct a [`Bits`] manually for advanced use cases like ECI designators
15//! or FNC1 patterns.
16
17#[cfg(not(feature = "std"))]
18#[allow(unused_imports)]
19use alloc::{
20    borrow::ToOwned,
21    format,
22    string::{String, ToString},
23    vec,
24    vec::Vec,
25};
26
27use core::cmp::min;
28
29use crate::cast::{As, Truncate};
30use crate::mode::EncodingMode;
31use crate::optimize::{Optimizer, Parser, Segment, total_encoded_len};
32use crate::types::{EcLevel, Mode, QrError, QrResult, Version};
33
34//------------------------------------------------------------------------------
35//{{{ Bits
36
37/// Set of QR data modes used by an encoded bit stream.
38///
39/// This records which payload modes were emitted, without retaining input bytes
40/// or every segment boundary. Use [`iter`](Self::iter) when call sites need the
41/// modes in a stable QR mode order.
42#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
43#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
44pub struct EncodingModes {
45    bits: u8,
46}
47
48impl EncodingModes {
49    /// Creates an empty mode set.
50    #[must_use]
51    pub const fn empty() -> Self {
52        Self { bits: 0 }
53    }
54
55    /// Creates a mode set containing one mode.
56    #[must_use]
57    pub const fn from_mode(mode: Mode) -> Self {
58        Self { bits: mode_bit(mode) }
59    }
60
61    /// Returns `true` when `mode` was used by the encoded bit stream.
62    #[must_use]
63    pub const fn contains(self, mode: Mode) -> bool {
64        self.bits & mode_bit(mode) != 0
65    }
66
67    /// Returns `true` when no data modes have been recorded.
68    #[must_use]
69    pub const fn is_empty(self) -> bool {
70        self.bits == 0
71    }
72
73    /// Number of distinct data modes recorded.
74    #[must_use]
75    pub const fn len(self) -> usize {
76        (self.contains(Mode::Numeric) as usize)
77            + (self.contains(Mode::Alphanumeric) as usize)
78            + (self.contains(Mode::Byte) as usize)
79            + (self.contains(Mode::Kanji) as usize)
80    }
81
82    /// Returns an iterator over the recorded modes in stable QR mode order:
83    /// Numeric, Alphanumeric, Byte, Kanji.
84    pub const fn iter(self) -> EncodingModesIter {
85        EncodingModesIter { modes: self, index: 0 }
86    }
87
88    fn insert(&mut self, mode: Mode) {
89        self.bits |= mode_bit(mode);
90    }
91}
92
93/// Iterator returned by [`EncodingModes::iter`].
94#[derive(Clone, Debug)]
95pub struct EncodingModesIter {
96    modes: EncodingModes,
97    index: u8,
98}
99
100impl Iterator for EncodingModesIter {
101    type Item = Mode;
102
103    fn next(&mut self) -> Option<Self::Item> {
104        while self.index < 4 {
105            let mode = match self.index {
106                0 => Mode::Numeric,
107                1 => Mode::Alphanumeric,
108                2 => Mode::Byte,
109                _ => Mode::Kanji,
110            };
111            self.index += 1;
112            if self.modes.contains(mode) {
113                return Some(mode);
114            }
115        }
116        None
117    }
118
119    fn size_hint(&self) -> (usize, Option<usize>) {
120        let remaining = self.modes.iter().skip(self.index as usize).count();
121        (remaining, Some(remaining))
122    }
123}
124
125impl ExactSizeIterator for EncodingModesIter {}
126impl core::iter::FusedIterator for EncodingModesIter {}
127
128const fn mode_bit(mode: Mode) -> u8 {
129    match mode {
130        Mode::Numeric => 1 << 0,
131        Mode::Alphanumeric => 1 << 1,
132        Mode::Byte => 1 << 2,
133        Mode::Kanji => 1 << 3,
134    }
135}
136
137/// The `Bits` structure stores the encoded data for a QR code.
138pub struct Bits {
139    data: Vec<u8>,
140    bit_offset: usize,
141    version: Version,
142    encoding_modes: EncodingModes,
143    payload_bits_len: Option<usize>,
144}
145
146impl Bits {
147    /// Constructs a new, empty bits structure.
148    pub const fn new(version: Version) -> Self {
149        Self {
150            data: Vec::new(),
151            bit_offset: 0,
152            version,
153            encoding_modes: EncodingModes::empty(),
154            payload_bits_len: None,
155        }
156    }
157
158    /// Pushes an N-bit big-endian integer to the end of the bits.
159    ///
160    /// Note: It is up to the developer to ensure that `number` really only is
161    /// `n` bit in size. Otherwise, the excess bits may stomp on the existing
162    /// ones.
163    fn push_number(&mut self, n: usize, number: u16) {
164        debug_assert!(n == 16 || n < 16 && number < (1 << n), "{number} is too big as a {n}-bit number");
165
166        let b = self.bit_offset + n;
167        let last_index = self.data.len().wrapping_sub(1);
168        match (self.bit_offset, b) {
169            (0, 0..=8) => {
170                self.data.push((number << (8 - b)).truncate_as_u8());
171            }
172            (0, _) => {
173                self.data.push((number >> (b - 8)).truncate_as_u8());
174                self.data.push((number << (16 - b)).truncate_as_u8());
175            }
176            (_, 0..=8) => {
177                self.data[last_index] |= (number << (8 - b)).truncate_as_u8();
178            }
179            (_, 9..=16) => {
180                self.data[last_index] |= (number >> (b - 8)).truncate_as_u8();
181                self.data.push((number << (16 - b)).truncate_as_u8());
182            }
183            _ => {
184                self.data[last_index] |= (number >> (b - 8)).truncate_as_u8();
185                self.data.push((number >> (b - 16)).truncate_as_u8());
186                self.data.push((number << (24 - b)).truncate_as_u8());
187            }
188        }
189        self.bit_offset = b & 7;
190    }
191
192    /// Pushes an N-bit big-endian integer to the end of the bits, and check
193    /// that the number does not overflow the bits.
194    ///
195    /// Returns `Err(QrError::DataTooLong)` on overflow.
196    pub fn push_number_checked(&mut self, n: usize, number: usize) -> QrResult<()> {
197        if n > 16 || number >= (1 << n) {
198            Err(QrError::DataTooLong)
199        } else {
200            self.push_number(n, number.as_u16());
201            Ok(())
202        }
203    }
204
205    /// Reserves `n` extra bits of space for pushing.
206    pub fn reserve(&mut self, n: usize) {
207        let extra_bytes = (n + (8 - self.bit_offset) % 8) / 8;
208        self.data.reserve(extra_bytes);
209    }
210
211    /// Convert the bits into a byte vector.
212    pub fn into_bytes(self) -> Vec<u8> {
213        self.data
214    }
215
216    /// Total number of bits currently pushed.
217    pub fn len(&self) -> usize {
218        if self.bit_offset == 0 { self.data.len() * 8 } else { (self.data.len() - 1) * 8 + self.bit_offset }
219    }
220
221    /// Whether there are any bits pushed.
222    pub fn is_empty(&self) -> bool {
223        self.data.is_empty()
224    }
225
226    /// The maximum number of bits allowed by the provided QR code version and
227    /// error correction level.
228    ///
229    /// # Errors
230    ///
231    /// Returns `Err(QrError::InvalidVersion)` if it is not valid to use the
232    /// `ec_level` for the given version (e.g. `Version::Micro(1)` with
233    /// `EcLevel::H`).
234    pub fn max_len(&self, ec_level: EcLevel) -> QrResult<usize> {
235        self.version.fetch(ec_level, &DATA_LENGTHS)
236    }
237
238    /// Version of the QR code.
239    pub fn version(&self) -> Version {
240        self.version
241    }
242
243    /// Data modes recorded while payload segments were pushed.
244    #[must_use]
245    pub const fn encoding_modes(&self) -> EncodingModes {
246        self.encoding_modes
247    }
248
249    /// Number of payload bits before terminator and padding bits were added.
250    ///
251    /// If [`push_terminator`](Self::push_terminator) has not been called, this
252    /// returns the current bit length.
253    #[must_use]
254    pub fn payload_bits_len(&self) -> usize {
255        match self.payload_bits_len {
256            Some(len) => len,
257            None => self.len(),
258        }
259    }
260
261    /// Remaining data capacity, in bits, before terminator and padding bits.
262    ///
263    /// # Errors
264    ///
265    /// Returns [`QrError::InvalidVersion`] when the stored version is
266    /// incompatible with `ec_level`.
267    pub fn remaining_capacity_bits(&self, ec_level: EcLevel) -> QrResult<usize> {
268        Ok(self.max_len(ec_level)?.saturating_sub(self.payload_bits_len()))
269    }
270}
271
272#[test]
273fn test_push_number() {
274    let mut bits = Bits::new(Version::Normal(1));
275
276    bits.push_number(3, 0b010); // 0:0 .. 0:3
277    bits.push_number(3, 0b110); // 0:3 .. 0:6
278    bits.push_number(3, 0b101); // 0:6 .. 1:1
279    bits.push_number(7, 0b001_1010); // 1:1 .. 2:0
280    bits.push_number(4, 0b1100); // 2:0 .. 2:4
281    bits.push_number(12, 0b1011_0110_1101); // 2:4 .. 4:0
282    bits.push_number(10, 0b01_1001_0001); // 4:0 .. 5:2
283    bits.push_number(15, 0b111_0010_1110_0011); // 5:2 .. 7:1
284
285    let bytes = bits.into_bytes();
286
287    assert_eq!(
288        bytes,
289        vec![
290            0b010_110_10, // 90
291            0b1_001_1010, // 154
292            0b1100_1011,  // 203
293            0b0110_1101,  // 109
294            0b01_1001_00, // 100
295            0b01_111_001, // 121
296            0b0_1110_001, // 113
297            0b1_0000000,  // 128
298        ]
299    );
300}
301
302#[cfg(test)]
303mod metadata_tests {
304    use crate::bits::{Bits, EncodingModes};
305    use crate::types::{EcLevel, Mode, Version};
306
307    #[test]
308    fn encoding_modes_iterates_in_stable_mode_order() {
309        let modes = EncodingModes::from_mode(Mode::Byte);
310        let mut modes_with_numeric = modes;
311        modes_with_numeric.insert(Mode::Numeric);
312
313        assert_eq!(modes_with_numeric.iter().collect::<Vec<_>>(), vec![Mode::Numeric, Mode::Byte]);
314    }
315
316    #[test]
317    fn bits_records_successful_payload_modes() {
318        let mut bits = Bits::new(Version::Normal(1));
319
320        bits.push_numeric_data(b"012").unwrap();
321        bits.push_byte_data(b"abc").unwrap();
322
323        assert!(bits.encoding_modes().contains(Mode::Numeric));
324        assert!(bits.encoding_modes().contains(Mode::Byte));
325        assert!(!bits.encoding_modes().contains(Mode::Kanji));
326    }
327
328    #[test]
329    fn remaining_capacity_uses_payload_len_before_padding() {
330        let mut bits = Bits::new(Version::Normal(1));
331
332        bits.push_numeric_data(b"01234567").unwrap();
333        bits.push_terminator(EcLevel::M).unwrap();
334
335        assert_eq!(bits.len(), 128);
336        assert_eq!(bits.payload_bits_len(), 41);
337        assert_eq!(bits.remaining_capacity_bits(EcLevel::M), Ok(87));
338    }
339}
340
341//}}}
342//------------------------------------------------------------------------------
343//{{{ Mode indicator
344
345/// An "extended" mode indicator, includes all indicators supported by QR code
346/// beyond those bearing data.
347#[derive(Copy, Clone)]
348pub enum ExtendedMode {
349    /// ECI mode indicator, to introduce an ECI designator.
350    Eci,
351
352    /// The normal mode to introduce data.
353    Data(Mode),
354
355    /// FNC-1 mode in the first position.
356    Fnc1First,
357
358    /// FNC-1 mode in the second position.
359    Fnc1Second,
360
361    /// Structured append.
362    StructuredAppend,
363}
364
365impl Bits {
366    /// Push the mode indicator to the end of the bits.
367    ///
368    /// # Errors
369    ///
370    /// If the mode is not supported in the provided version, this method
371    /// returns `Err(QrError::UnsupportedCharacterSet)`.
372    pub fn push_mode_indicator(&mut self, mode: ExtendedMode) -> QrResult<()> {
373        #[allow(clippy::match_same_arms)]
374        let number = match (self.version, mode) {
375            (Version::Micro(1), ExtendedMode::Data(Mode::Numeric)) => return Ok(()),
376            (Version::Micro(_), ExtendedMode::Data(Mode::Numeric)) => 0,
377            (Version::Micro(_), ExtendedMode::Data(Mode::Alphanumeric)) => 1,
378            (Version::Micro(_), ExtendedMode::Data(Mode::Byte)) => 0b10,
379            (Version::Micro(_), ExtendedMode::Data(Mode::Kanji)) => 0b11,
380            (Version::Micro(_), _) => return Err(QrError::UnsupportedCharacterSet),
381            (_, ExtendedMode::Data(Mode::Numeric)) => 0b0001,
382            (_, ExtendedMode::Data(Mode::Alphanumeric)) => 0b0010,
383            (_, ExtendedMode::Data(Mode::Byte)) => 0b0100,
384            (_, ExtendedMode::Data(Mode::Kanji)) => 0b1000,
385            (_, ExtendedMode::Eci) => 0b0111,
386            (_, ExtendedMode::Fnc1First) => 0b0101,
387            (_, ExtendedMode::Fnc1Second) => 0b1001,
388            (_, ExtendedMode::StructuredAppend) => 0b0011,
389        };
390        let bits = self.version.mode_bits_count();
391        self.push_number_checked(bits, number).or(Err(QrError::UnsupportedCharacterSet))
392    }
393}
394
395//}}}
396//------------------------------------------------------------------------------
397//{{{ ECI
398
399impl Bits {
400    /// Push an ECI (Extended Channel Interpretation) designator to the bits.
401    ///
402    /// An ECI designator is a 6-digit number to specify the character set of
403    /// the following binary data. After calling this method, one could call
404    /// `.push_byte_data()` or similar methods to insert the actual data, e.g.
405    ///
406    ///     #![allow(unused_must_use)]
407    ///
408    ///     use qrcode_core::bits::Bits;
409    ///     use qrcode_core::types::Version;
410    ///
411    ///     let mut bits = Bits::new(Version::Normal(1));
412    ///     bits.push_eci_designator(9); // 9 = ISO-8859-7 (Greek).
413    ///     bits.push_byte_data(b"\xa1\xa2\xa3\xa4\xa5"); // ΑΒΓΔΕ
414    ///
415    ///
416    /// The full list of ECI designator values can be found from
417    /// <http://strokescribe.com/en/ECI.html>. Some example values are:
418    ///
419    /// ECI # | Character set
420    /// ------|-------------------------------------
421    /// 3     | ISO-8859-1 (Western European)
422    /// 20    | Shift JIS (Japanese)
423    /// 23    | Windows 1252 (Latin 1) (Western European)
424    /// 25    | UTF-16 Big Endian
425    /// 26    | UTF-8
426    /// 28    | Big 5 (Traditional Chinese)
427    /// 29    | GB-18030 (Simplified Chinese)
428    /// 30    | EUC-KR (Korean)
429    ///
430    /// # Errors
431    ///
432    /// If the QR code version does not support ECI, this method will return
433    /// `Err(QrError::UnsupportedCharacterSet)`.
434    ///
435    /// If the designator is outside the expected range, this method will
436    /// return `Err(QrError::InvalidECIDesignator)`.
437    pub fn push_eci_designator(&mut self, eci_designator: u32) -> QrResult<()> {
438        self.reserve(12); // assume the common case that eci_designator <= 127.
439        self.push_mode_indicator(ExtendedMode::Eci)?;
440        match eci_designator {
441            0..=127 => {
442                self.push_number(8, eci_designator.as_u16());
443            }
444            128..=16383 => {
445                self.push_number(2, 0b10);
446                self.push_number(14, eci_designator.as_u16());
447            }
448            16384..=999_999 => {
449                self.push_number(3, 0b110);
450                self.push_number(5, (eci_designator >> 16).as_u16());
451                self.push_number(16, (eci_designator & 0xffff).as_u16());
452            }
453            _ => return Err(QrError::InvalidEciDesignator { value: eci_designator }),
454        }
455        Ok(())
456    }
457}
458
459#[cfg(test)]
460mod eci_tests {
461    use crate::bits::Bits;
462    use crate::types::{QrError, Version};
463
464    #[test]
465    fn test_9() {
466        let mut bits = Bits::new(Version::Normal(1));
467        assert_eq!(bits.push_eci_designator(9), Ok(()));
468        assert_eq!(bits.into_bytes(), vec![0b0111_0000, 0b1001_0000]);
469    }
470
471    #[test]
472    fn test_899() {
473        let mut bits = Bits::new(Version::Normal(1));
474        assert_eq!(bits.push_eci_designator(899), Ok(()));
475        assert_eq!(bits.into_bytes(), vec![0b0111_10_00, 0b00111000, 0b0011_0000]);
476    }
477
478    #[test]
479    fn test_999999() {
480        let mut bits = Bits::new(Version::Normal(1));
481        assert_eq!(bits.push_eci_designator(999999), Ok(()));
482        assert_eq!(bits.into_bytes(), vec![0b0111_110_0, 0b11110100, 0b00100011, 0b1111_0000]);
483    }
484
485    #[test]
486    fn test_invalid_designator() {
487        let mut bits = Bits::new(Version::Normal(1));
488        assert_eq!(bits.push_eci_designator(1000000), Err(QrError::InvalidEciDesignator { value: 1000000 }));
489    }
490
491    #[test]
492    fn test_unsupported_character_set() {
493        let mut bits = Bits::new(Version::Micro(4));
494        assert_eq!(bits.push_eci_designator(9), Err(QrError::UnsupportedCharacterSet));
495    }
496}
497
498//}}}
499//------------------------------------------------------------------------------
500//{{{ Mode::Numeric mode
501
502impl Bits {
503    fn push_header(&mut self, mode: Mode, raw_data_len: usize) -> QrResult<()> {
504        let length_bits = mode.length_bits_count(self.version);
505        self.reserve(length_bits + 4 + mode.data_bits_count(raw_data_len));
506        self.push_mode_indicator(ExtendedMode::Data(mode))?;
507        self.push_number_checked(length_bits, raw_data_len)?;
508        Ok(())
509    }
510
511    /// Encodes a numeric string to the bits.
512    ///
513    /// The data should only contain the characters 0 to 9.
514    ///
515    /// # Errors
516    ///
517    /// Returns `Err(QrError::DataTooLong)` on overflow.
518    pub fn push_numeric_data(&mut self, data: &[u8]) -> QrResult<()> {
519        self.push_header(Mode::Numeric, data.len())?;
520        for chunk in data.chunks(3) {
521            let number = chunk.iter().map(|b| u16::from(*b - b'0')).fold(0, |a, b| a * 10 + b);
522            let length = chunk.len() * 3 + 1;
523            self.push_number(length, number);
524        }
525        self.encoding_modes.insert(Mode::Numeric);
526        self.payload_bits_len = None;
527        Ok(())
528    }
529}
530
531#[cfg(test)]
532mod numeric_tests {
533    use crate::bits::Bits;
534    use crate::types::{QrError, Version};
535
536    #[test]
537    fn test_iso_18004_2006_example_1() {
538        let mut bits = Bits::new(Version::Normal(1));
539        assert_eq!(bits.push_numeric_data(b"01234567"), Ok(()));
540        assert_eq!(bits.into_bytes(), vec![0b0001_0000, 0b001000_00, 0b00001100, 0b01010110, 0b01_100001, 0b1_0000000]);
541    }
542
543    #[test]
544    fn test_iso_18004_2000_example_2() {
545        let mut bits = Bits::new(Version::Normal(1));
546        assert_eq!(bits.push_numeric_data(b"0123456789012345"), Ok(()));
547        assert_eq!(
548            bits.into_bytes(),
549            vec![
550                0b0001_0000,
551                0b010000_00,
552                0b00001100,
553                0b01010110,
554                0b01_101010,
555                0b0110_1110,
556                0b000101_00,
557                0b11101010,
558                0b0101_0000,
559            ]
560        );
561    }
562
563    #[test]
564    fn test_iso_18004_2006_example_2() {
565        let mut bits = Bits::new(Version::Micro(3));
566        assert_eq!(bits.push_numeric_data(b"0123456789012345"), Ok(()));
567        assert_eq!(
568            bits.into_bytes(),
569            vec![0b00_10000_0, 0b00000110, 0b0_0101011, 0b001_10101, 0b00110_111, 0b0000101_0, 0b01110101, 0b00101_000,]
570        );
571    }
572
573    #[test]
574    fn test_data_too_long_error() {
575        let mut bits = Bits::new(Version::Micro(1));
576        assert_eq!(bits.push_numeric_data(b"12345678"), Err(QrError::DataTooLong));
577    }
578}
579
580//}}}
581//------------------------------------------------------------------------------
582//{{{ Mode::Alphanumeric mode
583
584/// In QR code `Mode::Alphanumeric` mode, a pair of alphanumeric characters will
585/// be encoded as a base-45 integer. `alphanumeric_digit` converts each
586/// character into its corresponding base-45 digit.
587///
588/// The conversion is specified in ISO/IEC 18004:2006, §8.4.3, Table 5.
589#[inline]
590fn alphanumeric_digit(character: u8) -> u16 {
591    match character {
592        b'0'..=b'9' => u16::from(character - b'0'),
593        b'A'..=b'Z' => u16::from(character - b'A') + 10,
594        b' ' => 36,
595        b'$' => 37,
596        b'%' => 38,
597        b'*' => 39,
598        b'+' => 40,
599        b'-' => 41,
600        b'.' => 42,
601        b'/' => 43,
602        b':' => 44,
603        _ => 0,
604    }
605}
606
607impl Bits {
608    /// Encodes an alphanumeric string to the bits.
609    ///
610    /// The data should only contain the characters A to Z (excluding lowercase),
611    /// 0 to 9, space, `$`, `%`, `*`, `+`, `-`, `.`, `/` or `:`.
612    ///
613    /// # Errors
614    ///
615    /// Returns `Err(QrError::DataTooLong)` on overflow.
616    pub fn push_alphanumeric_data(&mut self, data: &[u8]) -> QrResult<()> {
617        self.push_header(Mode::Alphanumeric, data.len())?;
618        for chunk in data.chunks(2) {
619            let number = chunk.iter().map(|b| alphanumeric_digit(*b)).fold(0, |a, b| a * 45 + b);
620            let length = chunk.len() * 5 + 1;
621            self.push_number(length, number);
622        }
623        self.encoding_modes.insert(Mode::Alphanumeric);
624        self.payload_bits_len = None;
625        Ok(())
626    }
627}
628
629#[cfg(test)]
630mod alphanumeric_tests {
631    use crate::bits::Bits;
632    use crate::types::{QrError, Version};
633
634    #[test]
635    fn test_iso_18004_2006_example() {
636        let mut bits = Bits::new(Version::Normal(1));
637        assert_eq!(bits.push_alphanumeric_data(b"AC-42"), Ok(()));
638        assert_eq!(bits.into_bytes(), vec![0b0010_0000, 0b00101_001, 0b11001110, 0b11100111, 0b001_00001, 0b0_0000000]);
639    }
640
641    #[test]
642    fn test_micro_qr_unsupported() {
643        let mut bits = Bits::new(Version::Micro(1));
644        assert_eq!(bits.push_alphanumeric_data(b"A"), Err(QrError::UnsupportedCharacterSet));
645    }
646
647    #[test]
648    fn test_data_too_long() {
649        let mut bits = Bits::new(Version::Micro(2));
650        assert_eq!(bits.push_alphanumeric_data(b"ABCDEFGH"), Err(QrError::DataTooLong));
651    }
652}
653
654//}}}
655//------------------------------------------------------------------------------
656//{{{ Mode::Byte mode
657
658impl Bits {
659    /// Encodes 8-bit byte data to the bits.
660    ///
661    /// # Errors
662    ///
663    /// Returns `Err(QrError::DataTooLong)` on overflow.
664    pub fn push_byte_data(&mut self, data: &[u8]) -> QrResult<()> {
665        self.push_header(Mode::Byte, data.len())?;
666        for b in data {
667            self.push_number(8, u16::from(*b));
668        }
669        self.encoding_modes.insert(Mode::Byte);
670        self.payload_bits_len = None;
671        Ok(())
672    }
673}
674
675#[cfg(test)]
676mod byte_tests {
677    use crate::bits::Bits;
678    use crate::types::{QrError, Version};
679
680    #[test]
681    fn test() {
682        let mut bits = Bits::new(Version::Normal(1));
683        assert_eq!(bits.push_byte_data(b"\x12\x34\x56\x78\x9a\xbc\xde\xf0"), Ok(()));
684        assert_eq!(
685            bits.into_bytes(),
686            vec![
687                0b0100_0000,
688                0b1000_0001,
689                0b0010_0011,
690                0b0100_0101,
691                0b0110_0111,
692                0b1000_1001,
693                0b1010_1011,
694                0b1100_1101,
695                0b1110_1111,
696                0b0000_0000,
697            ]
698        );
699    }
700
701    #[test]
702    fn test_micro_qr_unsupported() {
703        let mut bits = Bits::new(Version::Micro(2));
704        assert_eq!(bits.push_byte_data(b"?"), Err(QrError::UnsupportedCharacterSet));
705    }
706
707    #[test]
708    fn test_data_too_long() {
709        let mut bits = Bits::new(Version::Micro(3));
710        assert_eq!(bits.push_byte_data(b"0123456701234567"), Err(QrError::DataTooLong));
711    }
712}
713
714//}}}
715//------------------------------------------------------------------------------
716//{{{ Mode::Kanji mode
717
718impl Bits {
719    /// Encodes Shift JIS double-byte data to the bits.
720    ///
721    /// # Errors
722    ///
723    /// Returns `Err(QrError::DataTooLong)` on overflow.
724    ///
725    /// Returns `Err(QrError::InvalidCharacter)` if the data is not Shift JIS
726    /// double-byte data (e.g. if the length of data is not an even number).
727    pub fn push_kanji_data(&mut self, data: &[u8]) -> QrResult<()> {
728        self.push_header(Mode::Kanji, data.len() / 2)?;
729        for (i, kanji) in data.chunks(2).enumerate() {
730            if kanji.len() != 2 {
731                return Err(QrError::InvalidCharacter { position: i * 2, byte: kanji[0] });
732            }
733            let cp = u16::from(kanji[0]) * 256 + u16::from(kanji[1]);
734            let bytes = if cp < 0xe040 { cp - 0x8140 } else { cp - 0xc140 };
735            let number = (bytes >> 8) * 0xc0 + (bytes & 0xff);
736            self.push_number(13, number);
737        }
738        self.encoding_modes.insert(Mode::Kanji);
739        self.payload_bits_len = None;
740        Ok(())
741    }
742}
743
744impl Bits {
745    /// Encodes data with a type-level QR encoding mode.
746    ///
747    /// This is the type-safe counterpart to calling one of
748    /// [`push_numeric_data`](Self::push_numeric_data),
749    /// [`push_alphanumeric_data`](Self::push_alphanumeric_data),
750    /// [`push_byte_data`](Self::push_byte_data), or
751    /// [`push_kanji_data`](Self::push_kanji_data) directly.
752    ///
753    /// # Errors
754    ///
755    /// Returns [`QrError::InvalidCharacter`] when `data` is not valid for `M`.
756    /// Returns the same length or version errors as the mode-specific push
757    /// method after validation succeeds.
758    pub fn push_mode_data<M: EncodingMode>(&mut self, data: &[u8]) -> QrResult<()> {
759        if let Some((position, byte)) = M::invalid_character(data) {
760            return Err(QrError::InvalidCharacter { position, byte });
761        }
762
763        match M::MODE {
764            Mode::Numeric => self.push_numeric_data(data),
765            Mode::Alphanumeric => self.push_alphanumeric_data(data),
766            Mode::Byte => self.push_byte_data(data),
767            Mode::Kanji => self.push_kanji_data(data),
768        }
769    }
770}
771
772#[cfg(test)]
773mod typed_mode_tests {
774    use crate::bits::Bits;
775    use crate::mode::{AlphanumericMode, ByteMode, KanjiMode, NumericMode};
776    use crate::types::{QrError, Version};
777
778    #[test]
779    fn push_mode_data_matches_numeric_specific_encoder() {
780        let mut typed = Bits::new(Version::Normal(1));
781        let mut direct = Bits::new(Version::Normal(1));
782
783        assert_eq!(typed.push_mode_data::<NumericMode>(b"01234567"), Ok(()));
784        assert_eq!(direct.push_numeric_data(b"01234567"), Ok(()));
785        assert_eq!(typed.into_bytes(), direct.into_bytes());
786    }
787
788    #[test]
789    fn push_mode_data_matches_other_specific_encoders() {
790        let mut alphanumeric = Bits::new(Version::Normal(1));
791        let mut byte = Bits::new(Version::Normal(1));
792        let mut kanji = Bits::new(Version::Normal(1));
793
794        assert_eq!(alphanumeric.push_mode_data::<AlphanumericMode>(b"AC-42"), Ok(()));
795        assert_eq!(byte.push_mode_data::<ByteMode>(b"\x12\x34"), Ok(()));
796        assert_eq!(kanji.push_mode_data::<KanjiMode>(b"\x93\x5f\xe4\xaa"), Ok(()));
797    }
798
799    #[test]
800    fn push_mode_data_rejects_invalid_mode_input_before_writing() {
801        let mut bits = Bits::new(Version::Normal(1));
802
803        assert_eq!(
804            bits.push_mode_data::<NumericMode>(b"12a"),
805            Err(QrError::InvalidCharacter { position: 2, byte: b'a' })
806        );
807        assert!(bits.into_bytes().is_empty());
808    }
809}
810
811#[cfg(test)]
812mod kanji_tests {
813    use crate::bits::Bits;
814    use crate::types::{QrError, Version};
815
816    #[test]
817    fn test_iso_18004_example() {
818        let mut bits = Bits::new(Version::Normal(1));
819        assert_eq!(bits.push_kanji_data(b"\x93\x5f\xe4\xaa"), Ok(()));
820        assert_eq!(bits.into_bytes(), vec![0b1000_0000, 0b0010_0110, 0b11001111, 0b1_1101010, 0b101010_00]);
821    }
822
823    #[test]
824    fn test_micro_qr_unsupported() {
825        let mut bits = Bits::new(Version::Micro(2));
826        assert_eq!(bits.push_kanji_data(b"?"), Err(QrError::UnsupportedCharacterSet));
827    }
828
829    #[test]
830    fn test_data_too_long() {
831        let mut bits = Bits::new(Version::Micro(3));
832        assert_eq!(bits.push_kanji_data(b"\x93_\x93_\x93_\x93_\x93_\x93_\x93_\x93_"), Err(QrError::DataTooLong));
833    }
834}
835
836//}}}
837//------------------------------------------------------------------------------
838//{{{ FNC1 mode
839
840impl Bits {
841    /// Encodes an indicator that the following data are formatted according to
842    /// the UCC/EAN Application Identifiers standard.
843    ///
844    ///     #![allow(unused_must_use)]
845    ///
846    ///     use qrcode_core::bits::Bits;
847    ///     use qrcode_core::types::Version;
848    ///
849    ///     let mut bits = Bits::new(Version::Normal(1));
850    ///     bits.push_fnc1_first_position();
851    ///     bits.push_numeric_data(b"01049123451234591597033130128");
852    ///     bits.push_alphanumeric_data(b"%10ABC123");
853    ///
854    /// In QR code, the character `%` is used as the data field separator (0x1D).
855    ///
856    /// # Errors
857    ///
858    /// If the mode is not supported in the provided version, this method
859    /// returns `Err(QrError::UnsupportedCharacterSet)`.
860    pub fn push_fnc1_first_position(&mut self) -> QrResult<()> {
861        self.push_mode_indicator(ExtendedMode::Fnc1First)
862    }
863
864    /// Encodes an indicator that the following data are formatted in accordance
865    /// with specific industry or application specifications previously agreed
866    /// with AIM International.
867    ///
868    ///     #![allow(unused_must_use)]
869    ///
870    ///     use qrcode_core::bits::Bits;
871    ///     use qrcode_core::types::Version;
872    ///
873    ///     let mut bits = Bits::new(Version::Normal(1));
874    ///     bits.push_fnc1_second_position(37);
875    ///     bits.push_alphanumeric_data(b"AA1234BBB112");
876    ///     bits.push_byte_data(b"text text text text\r");
877    ///
878    /// If the application indicator is a single Latin alphabet (a–z / A–Z),
879    /// please pass in its ASCII value + 100:
880    ///
881    /// ```ignore
882    /// bits.push_fnc1_second_position(b'A' + 100);
883    /// ```
884    ///
885    /// # Errors
886    ///
887    /// If the mode is not supported in the provided version, this method
888    /// returns `Err(QrError::UnsupportedCharacterSet)`.
889    pub fn push_fnc1_second_position(&mut self, application_indicator: u8) -> QrResult<()> {
890        self.push_mode_indicator(ExtendedMode::Fnc1Second)?;
891        self.push_number(8, u16::from(application_indicator));
892        Ok(())
893    }
894}
895
896//}}}
897//------------------------------------------------------------------------------
898//{{{ Structured Append
899
900impl Bits {
901    /// Pushes a Structured Append header (ISO/IEC 18004 §7.4) to the front of
902    /// the bit stream.
903    ///
904    /// Structured Append splits one logical message across 2..=16 QR symbols.
905    /// Every symbol in the sequence carries this 20-bit header as the very
906    /// first thing in its bit stream, *before* the data mode indicator:
907    ///
908    /// - 4-bit mode indicator `0011`,
909    /// - an 8-bit symbol-sequence indicator whose **high nibble** is this
910    ///   symbol's zero-based index (`position - 1`) and whose **low nibble** is
911    ///   `total - 1`,
912    /// - an 8-bit `parity` byte (the XOR of every byte of the original,
913    ///   un-split message — identical in every symbol).
914    ///
915    /// Structured Append is **not** valid for Micro QR; this method returns
916    /// `Err(QrError::UnsupportedCharacterSet)` for a Micro QR version.
917    ///
918    /// # Errors
919    ///
920    /// Returns [`QrError::UnsupportedCharacterSet`] on a Micro QR version, and
921    /// [`QrError::InvalidStructuredAppend`] if `total` is not `2..=16` or
922    /// `position` is not `1..=total`.
923    ///
924    /// ```
925    /// use qrcode_core::bits::Bits;
926    /// use qrcode_core::types::Version;
927    ///
928    /// let mut bits = Bits::new(Version::Normal(1));
929    /// bits.push_structured_append_header(1, 3, 0x5a);
930    /// // First symbol of a 3-symbol sequence; parity 0x5a.
931    /// ```
932    pub fn push_structured_append_header(&mut self, position: u8, total: u8, parity: u8) -> QrResult<()> {
933        if self.version.is_micro() {
934            return Err(QrError::UnsupportedCharacterSet);
935        }
936        if !(2..=16).contains(&total) || !(1..=total).contains(&position) {
937            return Err(QrError::InvalidStructuredAppend {
938                value: if !(2..=16).contains(&total) { total } else { position },
939            });
940        }
941        // ISO/IEC 18004 stores both fields with zero-based nibbles:
942        // high = position - 1, low = total - 1.
943        let sequence = (u16::from(position - 1) << 4) | u16::from(total - 1);
944        self.reserve(20);
945        self.push_mode_indicator(ExtendedMode::StructuredAppend)?;
946        self.push_number(8, sequence);
947        self.push_number(8, u16::from(parity));
948        Ok(())
949    }
950}
951
952#[cfg(test)]
953mod structured_append_tests {
954    use crate::bits::Bits;
955    use crate::types::{EcLevel, QrError, Version};
956
957    #[test]
958    fn test_header_bit_layout() {
959        // First symbol of a 3-symbol sequence, parity 0x5a.
960        // Bits: 0011 | 0000 0010 (pos 0 | total 2) | 0101 1010 (parity) = 20 bits.
961        let mut bits = Bits::new(Version::Normal(1));
962        assert_eq!(bits.push_structured_append_header(1, 3, 0x5a), Ok(()));
963        assert_eq!(bits.into_bytes(), vec![0x30, 0x25, 0xA0]);
964    }
965
966    #[test]
967    fn test_header_bit_layout_second_of_two() {
968        // Second symbol of a 2-symbol sequence, parity 0xff.
969        // sequence indicator = (1 << 4) | 1 = 0x11.
970        // Bits: 0011 | 0001 0001 | 1111 1111 → 0x31 0x1f 0xf0.
971        let mut bits = Bits::new(Version::Normal(1));
972        assert_eq!(bits.push_structured_append_header(2, 2, 0xff), Ok(()));
973        assert_eq!(bits.into_bytes(), vec![0x31, 0x1F, 0xF0]);
974    }
975
976    #[test]
977    fn test_header_value_16_uses_max_nibble() {
978        // 16th symbol of a 16-symbol sequence, parity 0 → both nibbles are 15.
979        // Bits: 0011 | 1111 1111 | 0000 0000 → 0x3f 0xf0 0x00.
980        let mut bits = Bits::new(Version::Normal(1));
981        assert_eq!(bits.push_structured_append_header(16, 16, 0x00), Ok(()));
982        assert_eq!(bits.into_bytes(), vec![0x3F, 0xF0, 0x00]);
983    }
984
985    #[test]
986    fn test_micro_rejected() {
987        let mut bits = Bits::new(Version::Micro(2));
988        assert_eq!(bits.push_structured_append_header(1, 2, 0), Err(QrError::UnsupportedCharacterSet));
989    }
990
991    #[test]
992    fn test_invalid_total() {
993        let mut bits = Bits::new(Version::Normal(1));
994        assert_eq!(bits.push_structured_append_header(1, 1, 0), Err(QrError::InvalidStructuredAppend { value: 1 }));
995        assert_eq!(bits.push_structured_append_header(1, 17, 0), Err(QrError::InvalidStructuredAppend { value: 17 }));
996    }
997
998    #[test]
999    fn test_invalid_position() {
1000        let mut bits = Bits::new(Version::Normal(1));
1001        assert_eq!(bits.push_structured_append_header(0, 3, 0), Err(QrError::InvalidStructuredAppend { value: 0 }));
1002        assert_eq!(bits.push_structured_append_header(4, 3, 0), Err(QrError::InvalidStructuredAppend { value: 4 }));
1003    }
1004
1005    #[test]
1006    fn test_header_then_data_round_trips() {
1007        // Header + a byte-mode segment + terminator must yield a valid symbol.
1008        let mut bits = Bits::new(Version::Normal(1));
1009        bits.push_structured_append_header(1, 2, 0).unwrap();
1010        bits.push_byte_data(b"ab").unwrap();
1011        assert!(bits.push_terminator(EcLevel::M).is_ok());
1012    }
1013}
1014
1015//}}}
1016//------------------------------------------------------------------------------
1017//{{{ Finish
1018
1019// This table is copied from ISO/IEC 18004:2006 §6.4.10, Table 7.
1020static DATA_LENGTHS: [[usize; 4]; 44] = [
1021    // Normal versions
1022    [152, 128, 104, 72],
1023    [272, 224, 176, 128],
1024    [440, 352, 272, 208],
1025    [640, 512, 384, 288],
1026    [864, 688, 496, 368],
1027    [1088, 864, 608, 480],
1028    [1248, 992, 704, 528],
1029    [1552, 1232, 880, 688],
1030    [1856, 1456, 1056, 800],
1031    [2192, 1728, 1232, 976],
1032    [2592, 2032, 1440, 1120],
1033    [2960, 2320, 1648, 1264],
1034    [3424, 2672, 1952, 1440],
1035    [3688, 2920, 2088, 1576],
1036    [4184, 3320, 2360, 1784],
1037    [4712, 3624, 2600, 2024],
1038    [5176, 4056, 2936, 2264],
1039    [5768, 4504, 3176, 2504],
1040    [6360, 5016, 3560, 2728],
1041    [6888, 5352, 3880, 3080],
1042    [7456, 5712, 4096, 3248],
1043    [8048, 6256, 4544, 3536],
1044    [8752, 6880, 4912, 3712],
1045    [9392, 7312, 5312, 4112],
1046    [10208, 8000, 5744, 4304],
1047    [10960, 8496, 6032, 4768],
1048    [11744, 9024, 6464, 5024],
1049    [12248, 9544, 6968, 5288],
1050    [13048, 10136, 7288, 5608],
1051    [13880, 10984, 7880, 5960],
1052    [14744, 11640, 8264, 6344],
1053    [15640, 12328, 8920, 6760],
1054    [16568, 13048, 9368, 7208],
1055    [17528, 13800, 9848, 7688],
1056    [18448, 14496, 10288, 7888],
1057    [19472, 15312, 10832, 8432],
1058    [20528, 15936, 11408, 8768],
1059    [21616, 16816, 12016, 9136],
1060    [22496, 17728, 12656, 9776],
1061    [23648, 18672, 13328, 10208],
1062    // Micro versions
1063    [20, 0, 0, 0],
1064    [40, 32, 0, 0],
1065    [84, 68, 0, 0],
1066    [128, 112, 80, 0],
1067];
1068
1069impl Bits {
1070    /// Pushes the ending bits to indicate no more data.
1071    ///
1072    /// # Errors
1073    ///
1074    /// Returns `Err(QrError::DataTooLong)` on overflow.
1075    ///
1076    /// Returns `Err(QrError::InvalidVersion)` if it is not valid to use the
1077    /// `ec_level` for the given version (e.g. `Version::Micro(1)` with
1078    /// `EcLevel::H`).
1079    pub fn push_terminator(&mut self, ec_level: EcLevel) -> QrResult<()> {
1080        let terminator_size = match self.version {
1081            Version::Micro(a) => a.as_usize() * 2 + 1,
1082            Version::Normal(_) => 4,
1083        };
1084
1085        let cur_length = self.len();
1086        let data_length = self.max_len(ec_level)?;
1087        if cur_length > data_length {
1088            return Err(QrError::DataTooLong);
1089        }
1090        self.payload_bits_len = Some(cur_length);
1091
1092        let terminator_size = min(terminator_size, data_length - cur_length);
1093        if terminator_size > 0 {
1094            self.push_number(terminator_size, 0);
1095        }
1096
1097        if self.len() < data_length {
1098            const PADDING_BYTES: &[u8] = &[0b1110_1100, 0b0001_0001];
1099
1100            self.bit_offset = 0;
1101            let data_bytes_length = data_length / 8;
1102            let padding_bytes_count = data_bytes_length.saturating_sub(self.data.len());
1103            let padding = PADDING_BYTES.iter().copied().cycle().take(padding_bytes_count);
1104            self.data.extend(padding);
1105        }
1106
1107        if self.len() < data_length {
1108            self.data.push(0);
1109        }
1110
1111        Ok(())
1112    }
1113}
1114
1115#[cfg(test)]
1116mod finish_tests {
1117    use crate::bits::Bits;
1118    use crate::types::{EcLevel, QrError, Version};
1119
1120    #[test]
1121    fn test_hello_world() {
1122        let mut bits = Bits::new(Version::Normal(1));
1123        assert_eq!(bits.push_alphanumeric_data(b"HELLO WORLD"), Ok(()));
1124        assert_eq!(bits.push_terminator(EcLevel::Q), Ok(()));
1125        assert_eq!(
1126            bits.into_bytes(),
1127            vec![
1128                0b00100000, 0b01011011, 0b00001011, 0b01111000, 0b11010001, 0b01110010, 0b11011100, 0b01001101,
1129                0b01000011, 0b01000000, 0b11101100, 0b00010001, 0b11101100,
1130            ]
1131        );
1132    }
1133
1134    #[test]
1135    fn test_too_long() {
1136        let mut bits = Bits::new(Version::Micro(1));
1137        assert_eq!(bits.push_numeric_data(b"9999999"), Ok(()));
1138        assert_eq!(bits.push_terminator(EcLevel::L), Err(QrError::DataTooLong));
1139    }
1140
1141    #[test]
1142    fn test_no_terminator() {
1143        let mut bits = Bits::new(Version::Micro(1));
1144        assert_eq!(bits.push_numeric_data(b"99999"), Ok(()));
1145        assert_eq!(bits.push_terminator(EcLevel::L), Ok(()));
1146        assert_eq!(bits.into_bytes(), vec![0b101_11111, 0b00111_110, 0b0011_0000]);
1147    }
1148
1149    #[test]
1150    fn test_no_padding() {
1151        let mut bits = Bits::new(Version::Micro(1));
1152        assert_eq!(bits.push_numeric_data(b"9999"), Ok(()));
1153        assert_eq!(bits.push_terminator(EcLevel::L), Ok(()));
1154        assert_eq!(bits.into_bytes(), vec![0b100_11111, 0b00111_100, 0b1_000_0000]);
1155    }
1156
1157    #[test]
1158    fn test_micro_version_1_half_byte_padding() {
1159        let mut bits = Bits::new(Version::Micro(1));
1160        assert_eq!(bits.push_numeric_data(b"999"), Ok(()));
1161        assert_eq!(bits.push_terminator(EcLevel::L), Ok(()));
1162        assert_eq!(bits.into_bytes(), vec![0b011_11111, 0b00111_000, 0b0000_0000]);
1163    }
1164
1165    #[test]
1166    fn test_micro_version_1_full_byte_padding() {
1167        let mut bits = Bits::new(Version::Micro(1));
1168        assert_eq!(bits.push_numeric_data(b""), Ok(()));
1169        assert_eq!(bits.push_terminator(EcLevel::L), Ok(()));
1170        assert_eq!(bits.into_bytes(), vec![0b000_000_00, 0b11101100, 0]);
1171    }
1172}
1173
1174//}}}
1175//------------------------------------------------------------------------------
1176//{{{ Front end.
1177
1178impl Bits {
1179    /// Push a segmented data to the bits, and then terminate it.
1180    ///
1181    /// # Errors
1182    ///
1183    /// Returns `Err(QrError::DataTooLong)` on overflow.
1184    ///
1185    /// Returns `Err(QrError::InvalidData)` if the segment refers to incorrectly
1186    /// encoded byte sequences.
1187    pub fn push_segments<I>(&mut self, data: &[u8], segments_iter: I) -> QrResult<()>
1188    where
1189        I: Iterator<Item = Segment>,
1190    {
1191        for segment in segments_iter {
1192            let slice = &data[segment.begin..segment.end];
1193            match segment.mode {
1194                Mode::Numeric => self.push_numeric_data(slice),
1195                Mode::Alphanumeric => self.push_alphanumeric_data(slice),
1196                Mode::Byte => self.push_byte_data(slice),
1197                Mode::Kanji => self.push_kanji_data(slice),
1198            }?;
1199        }
1200        Ok(())
1201    }
1202
1203    /// Pushes the data the bits, using the optimal encoding.
1204    ///
1205    /// # Errors
1206    ///
1207    /// Returns `Err(QrError::DataTooLong)` on overflow.
1208    pub fn push_optimal_data(&mut self, data: &[u8]) -> QrResult<()> {
1209        let segments = Parser::new(data).optimize(self.version);
1210        self.push_segments(data, segments)
1211    }
1212}
1213
1214#[cfg(test)]
1215mod encode_tests {
1216    use crate::bits::Bits;
1217    use crate::types::{EcLevel, QrError, QrResult, Version};
1218
1219    fn encode(data: &[u8], version: Version, ec_level: EcLevel) -> QrResult<Vec<u8>> {
1220        let mut bits = Bits::new(version);
1221        bits.push_optimal_data(data)?;
1222        bits.push_terminator(ec_level)?;
1223        Ok(bits.into_bytes())
1224    }
1225
1226    #[test]
1227    fn test_alphanumeric() {
1228        let res = encode(b"HELLO WORLD", Version::Normal(1), EcLevel::Q);
1229        assert_eq!(
1230            res,
1231            Ok(vec![
1232                0b00100000, 0b01011011, 0b00001011, 0b01111000, 0b11010001, 0b01110010, 0b11011100, 0b01001101,
1233                0b01000011, 0b01000000, 0b11101100, 0b00010001, 0b11101100,
1234            ])
1235        );
1236    }
1237
1238    #[test]
1239    fn test_auto_mode_switch() {
1240        let res = encode(b"123A", Version::Micro(2), EcLevel::L);
1241        assert_eq!(res, Ok(vec![0b0_0011_000, 0b1111011_1, 0b001_00101, 0b0_00000_00, 0b11101100]));
1242    }
1243
1244    #[test]
1245    fn test_too_long() {
1246        let res = encode(b">>>>>>>>", Version::Normal(1), EcLevel::H);
1247        assert_eq!(res, Err(QrError::DataTooLong));
1248    }
1249}
1250
1251//}}}
1252//------------------------------------------------------------------------------
1253//{{{ Auto version minimization
1254
1255/// Returns the data capacity (in bits) for the given version and error
1256/// correction level — the maximum number of data bits a symbol of that version
1257/// can hold.
1258///
1259/// # Errors
1260///
1261/// Returns [`QrError::InvalidVersion`] for an incompatible version / ec-level
1262/// combination (e.g. a Micro QR version with [`EcLevel::H`]).
1263pub fn data_capacity_bits(version: Version, ec_level: EcLevel) -> QrResult<usize> {
1264    version.fetch(ec_level, &DATA_LENGTHS)
1265}
1266
1267/// Automatically determines the minimum version to store the data, and encode
1268/// the result.
1269///
1270/// This method will not consider any Micro QR code versions.
1271///
1272/// # Errors
1273///
1274/// Returns `Err(QrError::DataTooLong)` if the data is too long to fit even the
1275/// highest QR code version.
1276pub fn encode_auto(data: &[u8], ec_level: EcLevel) -> QrResult<Bits> {
1277    if data.len() > crate::limits::DEFAULT_MAX_DATA_LENGTH {
1278        return Err(QrError::DataTooLong);
1279    }
1280    encode_auto_with_max_version(data, ec_level, 40)
1281}
1282
1283/// Automatically encodes data while capping normal QR version selection.
1284///
1285/// This is the bounded counterpart to [`encode_auto`]. The maximum version is
1286/// validated by the caller (`ResourceLimits`) and is kept as a small integer
1287/// here so this low-level helper remains useful to the facade without adding
1288/// a dependency cycle.
1289pub fn encode_auto_with_max_version(data: &[u8], ec_level: EcLevel, max_version: i16) -> QrResult<Bits> {
1290    if !(1..=40).contains(&max_version) {
1291        return Err(QrError::InvalidResourceLimits);
1292    }
1293    let segments = Parser::new(data).collect::<Vec<Segment>>();
1294    let mut checkpoints = [0_i16; 4];
1295    let mut checkpoint_count = 0;
1296    for candidate in [9_i16, 26, 40, max_version] {
1297        if candidate <= max_version && !checkpoints[..checkpoint_count].contains(&candidate) {
1298            checkpoints[checkpoint_count] = candidate;
1299            checkpoint_count += 1;
1300        }
1301    }
1302    for candidate in checkpoints[..checkpoint_count].iter() {
1303        let version = Version::Normal(*candidate);
1304        let opt_segments = Optimizer::new(segments.iter().copied(), version).collect::<Vec<_>>();
1305        let total_len = total_encoded_len(&opt_segments, version);
1306        let data_capacity = version.fetch(ec_level, &DATA_LENGTHS)?;
1307        if total_len <= data_capacity {
1308            let min_version = find_min_version_up_to(total_len, ec_level, *candidate);
1309            let mut bits = Bits::new(min_version);
1310            bits.reserve(total_len);
1311            bits.push_segments(data, opt_segments.into_iter())?;
1312            bits.push_terminator(ec_level)?;
1313            return Ok(bits);
1314        }
1315    }
1316    Err(QrError::DataTooLong)
1317}
1318
1319fn find_min_version_up_to(length: usize, ec_level: EcLevel, max_version: i16) -> Version {
1320    for version in 1..=max_version {
1321        if DATA_LENGTHS[(version - 1) as usize][ec_level as usize] >= length {
1322            return Version::Normal(version);
1323        }
1324    }
1325    Version::Normal(max_version)
1326}
1327
1328/// Automatically determines the minimum Micro QR version to store the data,
1329/// and encode the result.
1330///
1331/// This method only considers Micro QR code versions (1–4).
1332///
1333/// # Errors
1334///
1335/// Returns `Err(QrError::DataTooLong)` if the data is too long to fit even the
1336/// highest Micro QR version.
1337///
1338/// Returns `Err(QrError::InvalidVersion)` if the `ec_level` is not supported
1339/// by any Micro QR version (e.g. `EcLevel::H`).
1340pub fn encode_auto_micro(data: &[u8], ec_level: EcLevel) -> QrResult<Bits> {
1341    if data.len() > crate::limits::DEFAULT_MAX_DATA_LENGTH {
1342        return Err(QrError::DataTooLong);
1343    }
1344    let segments = Parser::new(data).collect::<Vec<Segment>>();
1345    for micro_version in 1..=4 {
1346        let version = Version::Micro(micro_version);
1347        let data_capacity = match version.fetch(ec_level, &DATA_LENGTHS) {
1348            Ok(cap) if cap > 0 => cap,
1349            _ => continue,
1350        };
1351        let opt_segments = Optimizer::new(segments.iter().copied(), version).collect::<Vec<_>>();
1352        let total_len = total_encoded_len(&opt_segments, version);
1353        if total_len <= data_capacity {
1354            let mut bits = Bits::new(version);
1355            bits.reserve(total_len);
1356            bits.push_segments(data, opt_segments.into_iter())?;
1357            bits.push_terminator(ec_level)?;
1358            return Ok(bits);
1359        }
1360    }
1361    Err(QrError::DataTooLong)
1362}
1363
1364/// Finds the smallest version (QR code only) that can store N bits of data
1365/// in the given error correction level.
1366pub fn find_min_version(length: usize, ec_level: EcLevel) -> Version {
1367    let mut base = 0_usize;
1368    let mut size = 39;
1369    while size > 1 {
1370        let half = size / 2;
1371        let mid = base + half;
1372        // mid is always in [0, size).
1373        // mid >= 0: by definition
1374        // mid < size: mid = size / 2 + size / 4 + size / 8 ...
1375        base = if DATA_LENGTHS[mid][ec_level as usize] > length { base } else { mid };
1376        size -= half;
1377    }
1378    // base is always in [0, mid) because base <= mid.
1379    base = if DATA_LENGTHS[base][ec_level as usize] >= length { base } else { base + 1 };
1380    Version::Normal((base + 1).as_i16())
1381}
1382
1383#[cfg(test)]
1384mod encode_auto_tests {
1385    use crate::bits::{encode_auto, encode_auto_with_max_version, find_min_version};
1386    use crate::types::{EcLevel, QrError, Version};
1387
1388    #[test]
1389    fn test_find_min_version() {
1390        assert_eq!(find_min_version(60, EcLevel::L), Version::Normal(1));
1391        assert_eq!(find_min_version(200, EcLevel::L), Version::Normal(2));
1392        assert_eq!(find_min_version(200, EcLevel::H), Version::Normal(3));
1393        assert_eq!(find_min_version(20000, EcLevel::L), Version::Normal(37));
1394        assert_eq!(find_min_version(640, EcLevel::L), Version::Normal(4));
1395        assert_eq!(find_min_version(641, EcLevel::L), Version::Normal(5));
1396        assert_eq!(find_min_version(999999, EcLevel::H), Version::Normal(40));
1397    }
1398
1399    #[test]
1400    fn test_alpha_q() {
1401        let bits = encode_auto(b"HELLO WORLD", EcLevel::Q).unwrap();
1402        assert_eq!(bits.version(), Version::Normal(1));
1403    }
1404
1405    #[test]
1406    fn test_alpha_h() {
1407        let bits = encode_auto(b"HELLO WORLD", EcLevel::H).unwrap();
1408        assert_eq!(bits.version(), Version::Normal(2));
1409    }
1410
1411    #[test]
1412    fn test_mixed() {
1413        let bits = encode_auto(b"This is a mixed data test. 1234567890", EcLevel::H).unwrap();
1414        assert_eq!(bits.version(), Version::Normal(4));
1415    }
1416
1417    #[test]
1418    fn bounded_auto_encoding_rejects_version_overflow_and_caps_search() {
1419        assert!(matches!(encode_auto_with_max_version(b"x", EcLevel::M, 0), Err(QrError::InvalidResourceLimits)));
1420        assert!(matches!(encode_auto_with_max_version(&[0_u8; 128], EcLevel::M, 1), Err(QrError::DataTooLong)));
1421    }
1422}
1423
1424//}}}
1425//------------------------------------------------------------------------------