133 lines
3.1 KiB
Rust

use serde::{Deserialize, Serialize};
use std::fs;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum StationStatus {
Online,
Offline,
Receive,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StationId(pub String);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Station {
pub id: StationId,
pub name: String,
pub host: String,
pub port: i32,
pub url: Option<String>,
pub status: StationStatus,
pub location: Option<String>,
pub genre: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Server {
pub address: String,
pub port: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Base {
pub title: String,
pub meta: Option<Vec<(String, String)>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
pub base: Base,
pub server: Server,
pub stations: Option<Vec<Station>>,
}
impl Config {
pub fn new() -> Self {
Config::default()
}
pub fn open(path: &std::path::Path) -> Result<Config, ConfigError> {
fs::read_to_string(path)?.parse()
}
pub fn data_dir() -> Result<std::path::PathBuf, ConfigError> {
let cwd = std::env::current_dir()?;
if cfg!(debug_assertions) {
Ok(cwd.join("temp"))
} else {
Ok(cwd)
}
}
pub fn to_string(&self) -> Result<String, ConfigError> {
Ok(toml::to_string(self)?)
}
pub fn write(&self, path: &std::path::Path) -> Result<(), ConfigError> {
Ok(fs::write(path, self.to_string()?)?)
}
}
impl Default for Config {
fn default() -> Self {
Config {
base: Base {
title: String::from("Elnafo Radio"),
meta: None,
},
server: Server {
address: String::from("127.0.0.1"),
port: 54605,
},
stations: None,
}
}
}
impl std::str::FromStr for Config {
type Err = ConfigError;
fn from_str(s: &str) -> Result<Self, ConfigError> {
toml::from_str(s).map_err(|_| ConfigError::Parse)
}
}
#[derive(Debug)]
pub enum ConfigError {
Parse,
StringParse,
Serialize,
IO,
}
impl std::error::Error for ConfigError {}
impl std::fmt::Display for ConfigError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::Parse => write!(f, "Failed to parse Config from string"),
Self::StringParse => write!(f, "Failed to parse environment variable"),
Self::Serialize => write!(f, "Failed to serialize Config to TOML"),
Self::IO => write!(f, "Failed to write a configuration file"),
}
}
}
impl From<toml::ser::Error> for ConfigError {
fn from(_: toml::ser::Error) -> Self {
ConfigError::Serialize
}
}
impl From<std::io::Error> for ConfigError {
fn from(_: std::io::Error) -> Self {
ConfigError::IO
}
}
impl From<std::num::ParseIntError> for ConfigError {
fn from(_: std::num::ParseIntError) -> Self {
ConfigError::StringParse
}
}