use std::{fmt::Display, path::PathBuf};
use serde::{Deserialize, Serialize};
use crate::paths::data_dir;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Config {
#[serde(alias = "backend")]
pub backends: Vec<BackendInfo>,
pub default_backend: Option<String>,
#[serde(default = "default_manifest_url")]
pub manifest_url: String,
}
impl Default for Config {
fn default() -> Self {
Self {
backends: vec![BackendInfo {
name: "local-store".to_owned(),
info: Default::default(),
}],
manifest_url: default_manifest_url(),
default_backend: None,
}
}
}
pub fn default_manifest_url() -> String {
"https://raw.githubusercontent.com/mtkennerly/ludusavi-manifest/master/data/manifest.yaml"
.to_owned()
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum BackendTy {
Filesystem { root: PathBuf },
WebDav(WebDavInfo),
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct BackendInfo {
pub name: String,
#[serde(flatten)]
pub info: BackendTy,
}
impl BackendInfo {
pub fn pretty_print(&self) -> String {
match &self.info {
BackendTy::Filesystem { root } => format!("filesystem at '{root:?}'"),
BackendTy::WebDav(web_dav_info) => format!(
"webdav at '{url}/{root:?}' with username {username}",
root = web_dav_info.root,
username = web_dav_info.username,
url = web_dav_info.url
),
}
}
}
impl Default for BackendTy {
fn default() -> Self {
Self::Filesystem {
root: data_dir().join("local-store"),
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct WebDavInfo {
pub url: String,
pub username: String,
pub psk: Option<String>,
pub root: PathBuf,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct GameInfoConfig {
pub steam_id: Option<SteamId>,
pub save_dirs: Vec<String>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SteamId(u32);
impl SteamId {
pub fn new(id: u32) -> Self {
Self(id)
}
pub fn id(self) -> u32 {
self.0
}
}
impl Display for SteamId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}", self.0))
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SteamId64(u64);
impl SteamId64 {
pub fn new(id: u64) -> Self {
Self(id)
}
pub fn to_id3(self) -> u32 {
const ID64_BASE: i64 = 76561197960265728;
let with_off = self.0 as i64 - ID64_BASE;
let acc_type = with_off % 2;
let acc_id = ((with_off - acc_type) / 2) + acc_type;
(acc_id * 2 - acc_type) as u32
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
pub enum BackendType {
Filesystem,
WebDav,
}