rustdoc-prettier 0.1.0

Format `//!` and `///` comments with prettier
use super::Interface;
use crate::span::LineColumn;
use std::str::{Chars, Split};

#[derive(Debug)]
pub struct CachingOffsetCalculator<'original> {
    lines: Split<'original, char>,
    chars: Option<Chars<'original>>,
    line_column: LineColumn,
    offset: usize,
    ascii: bool,
}

#[derive(Debug)]
pub struct StatelessOffsetCalculator<'original> {
    original: &'original str,
}

impl<'original> CachingOffsetCalculator<'original> {
    pub fn new(original: &'original str) -> Self {
        Self {
            lines: original.split('\n'),
            chars: None,
            line_column: LineColumn { line: 1, column: 0 },
            offset: 0,
            ascii: true,
        }
    }
}

impl<'original> StatelessOffsetCalculator<'original> {
    #[allow(dead_code)]
    pub fn new(original: &'original str) -> Self {
        Self { original }
    }
}

impl<'original> Interface for CachingOffsetCalculator<'original> {
    fn offset_from_line_column(&mut self, line_column: LineColumn) -> (usize, bool) {
        assert!(self.line_column <= line_column);

        let mut chars = self
            .chars
            .take()
            .unwrap_or_else(|| self.lines.next().unwrap().chars());

        if self.line_column.line < line_column.line {
            let suffix = chars.collect::<String>();
            self.offset += suffix.as_bytes().len() + 1;
            self.ascii &= suffix.is_ascii();
            self.line_column.line += 1;
            self.line_column.column = 0;

            while self.line_column.line < line_column.line {
                let line = self.lines.next().unwrap();
                self.offset += line.as_bytes().len() + 1;
                self.ascii &= line.is_ascii();
                self.line_column.line += 1;
                self.line_column.column = 0;
            }

            chars = self.lines.next().unwrap().chars();
        }

        let prefix = (&mut chars)
            .take(line_column.column - self.line_column.column)
            .collect::<String>();
        self.offset += prefix.as_bytes().len();
        self.ascii &= prefix.is_ascii();
        self.line_column.column = line_column.column;

        self.chars = Some(chars);

        (self.offset, self.ascii)
    }
}

impl<'original> Interface for StatelessOffsetCalculator<'original> {
    #[cfg_attr(
        dylint_lib = "misleading_variable_name",
        allow(misleading_variable_name)
    )]
    fn offset_from_line_column(&mut self, line_column: LineColumn) -> (usize, bool) {
        let mut lines = self.original.split('\n');
        let mut offset = 0;
        let mut ascii = true;

        for _ in 1..line_column.line {
            let line = lines.next().unwrap();
            offset += line.as_bytes().len() + 1;
            ascii &= line.is_ascii();
        }

        let prefix = lines
            .next()
            .unwrap()
            .chars()
            .take(line_column.column)
            .collect::<String>();
        offset += prefix.as_bytes().len();
        ascii &= prefix.is_ascii();

        (offset, ascii)
    }
}