fn correct_file(
        &self,
        path: PathBuf,
        bandaids: impl IntoIterator<Item = BandAid>,
    ) -> Result<()> {
        let path = fs::canonicalize(path.as_path())?;
        let path = path.as_path();
        log::trace!("Attempting to open {} as read", path.display());
        let ro = fs::OpenOptions::new().read(true).open(path)?;

        let mut reader = std::io::BufReader::new(ro);

        const TEMPORARY: &str = ".spellcheck.tmp";

        // Avoid issues when processing multiple files in parallel
        let tmp_name = TEMPORARY.to_owned() + uuid::Uuid::new_v4().to_string().as_str();

        let tmp = std::env::current_dir()
            .expect("Must have cwd")
            .join(tmp_name);
        let wr = fs::OpenOptions::new()
            .write(true)
            .truncate(true)
            .create(true)
            .open(&tmp)?;

        let mut writer = std::io::BufWriter::with_capacity(1024, wr);

        let mut content = String::with_capacity(2e6 as usize);
        reader.get_mut().read_to_string(&mut content)?;

        {
            let th = crate::TinHat::on();

            apply_patches(
                bandaids.into_iter().map(Patch::from),
                content.as_str(), // FIXME for efficiency, correct_lines should integrate with `BufRead` instead of a `String` buffer
                &mut writer,
            )?;

            writer.flush()?;
            // Required for windows support, which does not allow
            // to move a file while it is opened, see
            // <https://github.com/drahnr/cargo-spellcheck/issues/251>
            drop(writer);
            drop(reader);
            fs::rename(tmp, path)?;

            // Writing for this file is done, unblock the signal handler.
            drop(th);
        }

        Ok(())
    }
assumes suggestions are sorted by line number and column number and must
be non overlapping
src/action/mod.rs