#![cfg(any(unix, target_os = "redox"))]
use std::path::{Path, PathBuf};
mod parser;
mod utils;
#[derive(Debug)]
pub enum Error {
Io(std::io::Error),
NoHome,
Parse,
}
impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Self {
Self::Io(e)
}
}
impl From<std::str::Utf8Error> for Error {
fn from(_: std::str::Utf8Error) -> Self {
Self::Parse
}
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::Io(e) => e.fmt(f),
Self::NoHome => write!(f, "unable to find the home directory"),
Self::Parse => write!(f, "error while parsing"),
}
}
}
impl std::error::Error for Error {}
pub struct UserDirs {
desktop: Option<PathBuf>,
documents: Option<PathBuf>,
downloads: Option<PathBuf>,
music: Option<PathBuf>,
pictures: Option<PathBuf>,
public: Option<PathBuf>,
templates: Option<PathBuf>,
videos: Option<PathBuf>,
projects: Option<PathBuf>,
}
impl std::fmt::Debug for UserDirs {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("UserDirs").finish()
}
}
impl UserDirs {
pub fn new() -> Result<Self, Error> {
let mut this = Self {
desktop: None,
documents: None,
downloads: None,
music: None,
pictures: None,
public: None,
templates: None,
videos: None,
projects: None,
};
utils::parse_file(|key, val| {
match key {
utils::DESKTOP => this.desktop = val,
utils::DOCUMENTS => this.documents = val,
utils::DOWNLOADS => this.downloads = val,
utils::MUSIC => this.music = val,
utils::PICTURES => this.pictures = val,
utils::PUBLIC => this.public = val,
utils::TEMPLATES => this.templates = val,
utils::VIDEOS => this.videos = val,
utils::PROJECTS => this.projects = val,
_ => {}
}
true
})?;
Ok(this)
}
pub fn desktop(&self) -> Option<&Path> {
self.desktop.as_deref()
}
pub fn documents(&self) -> Option<&Path> {
self.documents.as_deref()
}
pub fn downloads(&self) -> Option<&Path> {
self.downloads.as_deref()
}
pub fn music(&self) -> Option<&Path> {
self.music.as_deref()
}
pub fn pictures(&self) -> Option<&Path> {
self.pictures.as_deref()
}
pub fn public(&self) -> Option<&Path> {
self.public.as_deref()
}
pub fn templates(&self) -> Option<&Path> {
self.templates.as_deref()
}
pub fn videos(&self) -> Option<&Path> {
self.videos.as_deref()
}
pub fn projects(&self) -> Option<&Path> {
self.projects.as_deref()
}
}
fn read_single(env: &[u8]) -> Result<Option<PathBuf>, Error> {
let mut ret = None;
utils::parse_file(|key, val| {
if key == env {
ret = val;
false
} else {
true
}
})?;
Ok(ret)
}
pub fn desktop() -> Result<Option<PathBuf>, Error> {
read_single(utils::DESKTOP)
}
pub fn documents() -> Result<Option<PathBuf>, Error> {
read_single(utils::DOCUMENTS)
}
pub fn downloads() -> Result<Option<PathBuf>, Error> {
read_single(utils::DOWNLOADS)
}
pub fn music() -> Result<Option<PathBuf>, Error> {
read_single(utils::MUSIC)
}
pub fn pictures() -> Result<Option<PathBuf>, Error> {
read_single(utils::PICTURES)
}
pub fn public() -> Result<Option<PathBuf>, Error> {
read_single(utils::PUBLIC)
}
pub fn templates() -> Result<Option<PathBuf>, Error> {
read_single(utils::TEMPLATES)
}
pub fn videos() -> Result<Option<PathBuf>, Error> {
read_single(utils::VIDEOS)
}
pub fn projects() -> Result<Option<PathBuf>, Error> {
read_single(utils::PROJECTS)
}