use serde::{Deserialize, Serialize};
use crate::*;
#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum EntryType {
File {
#[serde(rename = "mimeType")]
mime_type: String,
},
Dir,
}
impl EntryType {
pub fn is_file(&self) -> bool {
matches!(self, Self::File { .. })
}
pub fn is_dir(&self) -> bool {
matches!(self, Self::Dir)
}
pub fn file_mime_type(&self) -> Option<&str> {
match self {
EntryType::File { mime_type } => Some(&mime_type),
EntryType::Dir => None,
}
}
pub fn into_file_mime_type(self) -> Option<String> {
match self {
EntryType::File { mime_type } => Some(mime_type),
EntryType::Dir => None,
}
}
pub fn file_mime_type_or_err(&self) -> Result<&str> {
self.file_mime_type().ok_or_else(|| Error::with("not a file"))
}
pub fn into_file_mime_type_or_err(self) -> Result<String> {
self.into_file_mime_type().ok_or_else(|| Error::with("not a file"))
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum Entry {
#[non_exhaustive]
File {
uri: FileUri,
name: String,
last_modified: std::time::SystemTime,
len: u64,
mime_type: String,
},
#[non_exhaustive]
Dir {
uri: FileUri,
name: String,
last_modified: std::time::SystemTime,
}
}
impl Entry {
pub fn is_file(&self) -> bool {
matches!(self, Self::File { .. })
}
pub fn is_dir(&self) -> bool {
matches!(self, Self::Dir { .. })
}
pub fn uri(&self) -> &FileUri {
match self {
Entry::File { uri, .. } => uri,
Entry::Dir { uri, .. } => uri,
}
}
pub fn name(&self) -> &str {
match self {
Entry::File { name, .. } => name,
Entry::Dir { name, .. } => name,
}
}
pub fn last_modified(&self) -> std::time::SystemTime {
match self {
Entry::File { last_modified, .. } => *last_modified,
Entry::Dir { last_modified, .. } => *last_modified,
}
}
pub fn file_mime_type(&self) -> Option<&str> {
match self {
Entry::File { mime_type, .. } => Some(mime_type),
Entry::Dir { .. } => None,
}
}
pub fn file_len(&self) -> Option<u64> {
match self {
Entry::File { len, .. } => Some(*len),
Entry::Dir { .. } => None,
}
}
pub fn file_mime_type_or_err(&self) -> Result<&str> {
self.file_mime_type().ok_or_else(|| Error::with("not a file"))
}
pub fn file_len_or_err(&self) -> Result<u64> {
self.file_len().ok_or_else(|| Error::with("not a file"))
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum OptionalEntry {
#[non_exhaustive]
File {
uri: Option<FileUri>,
name: Option<String>,
last_modified: Option<std::time::SystemTime>,
len: Option<u64>,
mime_type: Option<String>,
},
#[non_exhaustive]
Dir {
uri: Option<FileUri>,
name: Option<String>,
last_modified: Option<std::time::SystemTime>,
}
}
impl OptionalEntry {
pub fn is_file(&self) -> bool {
matches!(self, Self::File { .. })
}
pub fn is_dir(&self) -> bool {
matches!(self, Self::Dir { .. })
}
pub fn into_uri(self) -> Option<FileUri> {
match self {
Self::File { uri, .. } => uri,
Self::Dir { uri, .. } => uri,
}
}
pub fn into_uri_or_err(self) -> Result<FileUri> {
self.into_uri().ok_or_else(|| Error::missing_value("uri"))
}
pub fn uri_or_err(&self) -> Result<&FileUri> {
self.uri().ok_or_else(|| Error::missing_value("uri"))
}
pub fn name_or_err(&self) -> Result<&str> {
self.name().ok_or_else(|| Error::missing_value("name"))
}
pub fn last_modified_or_err(&self) -> Result<std::time::SystemTime> {
self.last_modified().ok_or_else(|| Error::missing_value("last_modified"))
}
pub fn file_mime_type_or_err(&self) -> Result<&str> {
self.file_mime_type().ok_or_else(|| Error::with("not a file or missing value: mime_type"))
}
pub fn file_len_or_err(&self) -> Result<u64> {
self.file_len().ok_or_else(|| Error::with("not a file or missing value: len"))
}
pub fn uri(&self) -> Option<&FileUri> {
match self {
Self::File { uri, .. } => uri.as_ref(),
Self::Dir { uri, .. } => uri.as_ref(),
}
}
pub fn name(&self) -> Option<&str> {
match self {
Self::File { name, .. } => name.as_deref(),
Self::Dir { name, .. } => name.as_deref(),
}
}
pub fn last_modified(&self) -> Option<std::time::SystemTime> {
match self {
Self::File { last_modified, .. } => *last_modified,
Self::Dir { last_modified, .. } => *last_modified,
}
}
pub fn file_mime_type(&self) -> Option<&str> {
match self {
Self::File { mime_type, .. } => mime_type.as_deref(),
Self::Dir { .. } => None,
}
}
pub fn file_len(&self) -> Option<u64> {
match self {
Self::File { len, .. } => *len,
Self::Dir { .. } => None,
}
}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct EntryOptions {
pub uri: bool,
pub name: bool,
pub last_modified: bool,
pub len: bool,
pub mime_type: bool,
}
impl EntryOptions {
pub const ALL: EntryOptions = EntryOptions {
uri: true,
name: true,
last_modified: true,
len: true,
mime_type: true
};
pub const NONE: EntryOptions = EntryOptions {
uri: false,
name: false,
last_modified: false,
len: false,
mime_type: false
};
pub const URI_ONLY: EntryOptions = EntryOptions {
uri: true,
..Self::NONE
};
pub const URI_AND_NAME: EntryOptions = EntryOptions {
uri: true,
name: true,
..Self::NONE
};
}
impl TryFrom<OptionalEntry> for Entry {
type Error = crate::Error;
fn try_from(value: OptionalEntry) -> std::result::Result<Self, Self::Error> {
Ok(match value {
OptionalEntry::File { uri, name, last_modified, len, mime_type } => Entry::File {
uri: uri.ok_or_else(|| Error::missing_value("uri"))?,
name: name.ok_or_else(|| Error::missing_value("name"))?,
last_modified: last_modified.ok_or_else(|| Error::missing_value("last_modified"))?,
len: len.ok_or_else(|| Error::missing_value("len"))?,
mime_type: mime_type.ok_or_else(|| Error::missing_value("mime_type"))?,
},
OptionalEntry::Dir { uri, name, last_modified } => Entry::Dir {
uri: uri.ok_or_else(|| Error::missing_value("uri"))?,
name: name.ok_or_else(|| Error::missing_value("name"))?,
last_modified: last_modified.ok_or_else(|| Error::missing_value("last_modified"))?,
},
})
}
}