oreq 0.2.6

The tool for interactively creating curl arguments from OpenAPI.
Documentation
use std::{
    env::current_dir,
    fs::File,
    io::{self, Read},
    path::PathBuf,
};

use anyhow::{anyhow, Context as _};
use crossterm::tty::IsTty;
use serde::de::DeserializeOwned;

enum SupportExt {
    Json,
    Yaml,
}

#[derive(Debug, Clone)]
pub struct ReadSchema<T>
where
    T: DeserializeOwned,
{
    pub schema: T,
    pub base_dir: PathBuf,
}

impl<T> ReadSchema<T>
where
    T: DeserializeOwned,
{
    pub fn get_schema(path: PathBuf) -> anyhow::Result<Self> {
        let path = &path.clone();
        let ext = path.extension().ok_or(anyhow!("No extension"))?;
        let ext = match ext.to_str() {
            Some("json") => Ok(SupportExt::Json),
            Some("yaml") => Ok(SupportExt::Yaml),
            Some("yml") => Ok(SupportExt::Yaml),
            _ => Err(anyhow!("Unsupported extension")),
        }?;

        let mut file = File::open(path)?;
        let mut content = Vec::new();
        file.read_to_end(&mut content)?;

        let result =
            match ext {
                SupportExt::Json => serde_json::from_slice::<T>(&content)
                    .with_context(|| "Parse failed".to_string()),
                SupportExt::Yaml => serde_yaml::from_slice::<T>(&content)
                    .with_context(|| "Parse failed".to_string()),
            }?;

        let base_dir = path.parent();
        let base_dir = if let Some(base_dir) = base_dir {
            base_dir.to_owned()
        } else {
            current_dir()?
        };

        Ok(Self {
            schema: result,
            base_dir,
        })
    }

    pub fn get_schema_from_stdin() -> anyhow::Result<Self> {
        let mut content = Vec::new();
        if !io::stdin().is_tty() {
            io::stdin().read_to_end(&mut content)?;
        }

        let yaml_result = serde_yaml::from_slice::<T>(&content);
        let json_result = serde_json::from_slice::<T>(&content);

        let result = yaml_result
            .or(json_result)
            .with_context(|| "Parse failed".to_string())?;

        Ok(Self {
            schema: result,
            base_dir: current_dir()?,
        })
    }
}