use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct PinocConfig {
pub provider: ProviderConfig,
#[serde(default)]
pub idl: IdlConfig,
#[serde(default)]
pub client: ClientConfig,
#[serde(default)]
pub check: CheckConfig,
#[serde(default)]
pub build: BuildConfig,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, clap::ValueEnum)]
#[serde(rename_all = "lowercase")]
pub enum Arch {
V0,
V1,
V2,
V3,
V4,
}
impl Arch {
pub fn as_str(self) -> &'static str {
match self {
Arch::V0 => "v0",
Arch::V1 => "v1",
Arch::V2 => "v2",
Arch::V3 => "v3",
Arch::V4 => "v4",
}
}
}
#[derive(Debug, Default, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct BuildConfig {
#[serde(default)]
pub arch: Option<Arch>,
}
#[derive(Debug, Deserialize)]
pub struct ProviderConfig {
pub cluster: String,
pub wallet: String,
}
#[derive(Debug, Default, Deserialize)]
pub struct IdlConfig {
#[serde(default)]
pub generator: Option<String>,
}
#[derive(Debug, Default, Deserialize)]
pub struct ClientConfig {
#[serde(default)]
pub out_dir: Option<String>,
#[serde(default)]
pub shank_out_dir: Option<String>,
#[serde(default)]
pub codama_out_dir: Option<String>,
}
#[derive(Debug, Default, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct CheckConfig {
#[serde(default)]
pub deny: Vec<String>,
#[serde(default)]
pub warn: Vec<String>,
#[serde(default)]
pub allow: Vec<String>,
#[serde(default)]
pub confidence_threshold: Option<String>,
#[serde(default)]
pub authority_names: Vec<String>,
}
pub fn read_pinoc_config_optional() -> Result<Option<PinocConfig>> {
let config_path = Path::new("Pinoc.toml");
if !config_path.exists() {
eprintln!(
"💡 No Pinoc.toml found. Run `pinoc config init` to create one for this project."
);
return Ok(None);
}
Ok(Some(parse_pinoc_config(config_path)?))
}
pub fn build_arch() -> Result<Option<Arch>> {
let config_path = Path::new("Pinoc.toml");
if !config_path.exists() {
return Ok(None);
}
Ok(parse_pinoc_config(config_path)?.build.arch)
}
fn parse_pinoc_config(config_path: &Path) -> Result<PinocConfig> {
let config_content =
fs::read_to_string(config_path).with_context(|| "Failed to read Pinoc.toml")?;
toml::from_str(&config_content).with_context(|| "Failed to parse Pinoc.toml")
}