fn read_record_dfa()

in rust-csv/csv-core/src/reader.rs [626:703]


    fn read_record_dfa(
        &mut self,
        input: &[u8],
        output: &mut [u8],
        ends: &mut [usize],
    ) -> (ReadRecordResult, usize, usize, usize) {
        if input.is_empty() {
            let s = self.transition_final_dfa(self.dfa_state);
            let res =
                self.dfa.new_read_record_result(s, true, false, false, false);
            // This part is a little tricky. When reading the final record,
            // the last result the caller will get is an InputEmpty, and while
            // they'll have everything they need in `output`, they'll be
            // missing the final end position of the final field in `ends`.
            // We insert that here, but we must take care to handle the case
            // where `ends` doesn't have enough space. If it doesn't have
            // enough space, then we also can't transition to the next state.
            return match res {
                ReadRecordResult::Record => {
                    if ends.is_empty() {
                        return (ReadRecordResult::OutputEndsFull, 0, 0, 0);
                    }
                    self.dfa_state = s;
                    ends[0] = self.output_pos;
                    self.output_pos = 0;
                    (res, 0, 0, 1)
                }
                _ => {
                    self.dfa_state = s;
                    (res, 0, 0, 0)
                }
            };
        }
        if output.is_empty() {
            return (ReadRecordResult::OutputFull, 0, 0, 0);
        }
        if ends.is_empty() {
            return (ReadRecordResult::OutputEndsFull, 0, 0, 0);
        }
        let (mut nin, mut nout, mut nend) = (0, 0, 0);
        let mut state = self.dfa_state;
        while nin < input.len() && nout < output.len() && nend < ends.len() {
            let (s, has_out) = self.dfa.get_output(state, input[nin]);
            self.line += (input[nin] == b'\n') as u64;
            state = s;
            if has_out {
                output[nout] = input[nin];
                nout += 1;
            }
            nin += 1;
            if state >= self.dfa.final_field {
                ends[nend] = self.output_pos + nout;
                nend += 1;
                if state > self.dfa.final_field {
                    break;
                }
            }
            if state == self.dfa.in_field || state == self.dfa.in_quoted {
                self.dfa
                    .classes
                    .scan_and_copy(input, &mut nin, output, &mut nout);
            }
        }
        let res = self.dfa.new_read_record_result(
            state,
            false,
            nin >= input.len(),
            nout >= output.len(),
            nend >= ends.len(),
        );
        self.dfa_state = state;
        if res.is_record() {
            self.output_pos = 0;
        } else {
            self.output_pos += nout;
        }
        (res, nin, nout, nend)
    }