fn next()

in src/aes128gcm.rs [450:516]


    fn next(&mut self) -> Option<Self::Item> {
        let records_remaining = self.num_records - self.sequence_number;
        // We stop iterating when we've produced all records.
        if records_remaining == 0 {
            assert!(
                self.plaintext.is_empty(),
                "record chunking error: the plaintext was not fully consumed"
            );
            assert!(
                self.extra_plaintext == 0,
                "record chunking error: the extra plaintext was not fully consumed"
            );
            assert!(
                self.pad_length == 0,
                "record chunking error: the padding was not fully consumed"
            );
            return None;
        }
        // Allocate a chunk of plaintext to this record.
        // We target `plaintext_per_record` bytes per record, but it's a little
        // more complicated than that...
        let mut plaintext_share = self.plaintext_per_record;
        if plaintext_share > self.plaintext.len() {
            // ...because the final record is allowed to be smaller.
            assert!(
                records_remaining == 1,
                "record chunking error: the plaintext was consumed too early"
            );
            plaintext_share = self.plaintext.len();
        } else {
            // ...because non-final records need to consume any extra plaintext.
            if self.extra_plaintext > 0 {
                // The extra plaintext must be distributed as evenly as possible
                // amongst all but the final record.
                let mut extra_share = self.extra_plaintext / (records_remaining - 1);
                if self.extra_plaintext % (records_remaining - 1) != 0 {
                    extra_share += 1;
                }
                plaintext_share += extra_share;
                self.extra_plaintext -= extra_share;
            }
        }
        let plaintext = &self.plaintext[0..plaintext_share];
        self.plaintext = &self.plaintext[plaintext_share..];
        // Fill the rest of the record with padding.
        let padding_share = std::cmp::min(self.pad_length, self.rs - plaintext_share);
        self.pad_length -= padding_share;
        assert!(
            padding_share > 0,
            "record chunking error: the padding was consumed too early"
        );
        // Check where we are in the iteration.
        let sequence_number = self.sequence_number;
        self.sequence_number += 1;
        let is_final = self.sequence_number == self.num_records;
        assert!(
            is_final || plaintext.len() + padding_share == self.rs,
            "record chunking error: non-final record is too short"
        );
        // That's a record!
        Some(PlaintextRecord {
            plaintext,
            padding: padding_share,
            sequence_number,
            is_final,
        })
    }