frinZ 4.4.0

fringe search for Yamaguchi Interferometer and Japanese VLBI Network
Documentation
use memmap2::Mmap;
use std::error::Error;
use std::fs::{self, File};
use std::io::{copy, Read, Write};
use std::path::{Path, PathBuf};
use tempfile::NamedTempFile;
use zstd::stream::read::Decoder;

fn is_zstd_input(path: &Path) -> bool {
    path.extension()
        .and_then(|ext| ext.to_str())
        .map(|ext| ext.eq_ignore_ascii_case("zst"))
        .unwrap_or(false)
}

pub fn read_input_prefix(path: &Path, len: usize) -> Result<Vec<u8>, Box<dyn Error>> {
    let mut buf = vec![0u8; len];
    if is_zstd_input(path) {
        let file = File::open(path)?;
        let mut decoder = Decoder::new(file)?;
        decoder.read_exact(&mut buf)?;
    } else {
        let mut file = File::open(path)?;
        file.read_exact(&mut buf)?;
    }
    Ok(buf)
}

pub fn read_input_bytes(path: &Path) -> Result<Vec<u8>, Box<dyn Error>> {
    if is_zstd_input(path) {
        let file = File::open(path)?;
        let mut decoder = Decoder::new(file)?;
        let mut buffer = Vec::new();
        decoder.read_to_end(&mut buffer)?;
        Ok(buffer)
    } else {
        Ok(fs::read(path)?)
    }
}

pub fn open_input_mmap(path: &Path) -> Result<(Mmap, Option<NamedTempFile>), Box<dyn Error>> {
    if !is_zstd_input(path) {
        let file = File::open(path)?;
        let mmap = unsafe { Mmap::map(&file)? };
        return Ok((mmap, None));
    }

    let mut decoder = Decoder::new(File::open(path)?)?;
    let mut temp = tempfile::Builder::new()
        .prefix("frinz_input_")
        .suffix(".cor")
        .tempfile_in(std::env::temp_dir())?;
    copy(&mut decoder, &mut temp)?;
    temp.as_file_mut().flush()?;

    let map_file = temp.reopen()?;
    let mmap = unsafe { Mmap::map(&map_file)? };
    Ok((mmap, Some(temp)))
}

pub fn output_stem_from_path(path: &Path) -> Result<String, Box<dyn Error>> {
    let stem = if is_zstd_input(path) {
        PathBuf::from(path.file_stem().ok_or("Invalid input filename")?)
            .file_stem()
            .ok_or("Invalid compressed input filename")?
            .to_string_lossy()
            .to_string()
    } else {
        path.file_stem()
            .ok_or("Invalid input filename")?
            .to_string_lossy()
            .to_string()
    };
    Ok(stem)
}