shared_mime/
query.rs

1use std::{
2    ffi::OsStr,
3    fs::{self, Metadata},
4    io::ErrorKind,
5    path::Path,
6};
7
8use log::trace;
9
10use crate::QueryError;
11
12/// Information avaialble for a query to the database.
13pub struct FileQuery<'a> {
14    /// The file's name.
15    pub(crate) filename: Option<&'a OsStr>,
16    /// The file metadata.
17    pub(crate) metadata: Option<Metadata>,
18}
19
20/// Builder for [FileQuery].
21pub struct FileQueryBuilder<'name> {
22    /// The file's name.
23    filename: Option<&'name OsStr>,
24    /// The file metadata.
25    metadata: Option<Metadata>,
26}
27
28impl FileQuery<'_> {
29    pub fn builder() -> FileQueryBuilder<'static> {
30        FileQueryBuilder::new()
31    }
32}
33
34impl<'name> FileQuery<'name> {
35    pub fn for_filename(name: &'name OsStr) -> FileQuery<'name> {
36        FileQuery::builder().filename(name).build()
37    }
38
39    pub fn for_path(path: &'name Path) -> Result<FileQuery, QueryError> {
40        let mut fqb = Self::builder();
41
42        if let Some(name) = path.file_name() {
43            trace!("{}: using filename {:?}", path.display(), name);
44            fqb = fqb.filename(name);
45        }
46
47        trace!("{}: looking up metadata", path.display());
48        match fs::metadata(&path) {
49            Ok(meta) => fqb = fqb.metadata(meta),
50            Err(e) if e.kind() == ErrorKind::NotFound => {
51                trace!("{}: file not found", path.display());
52            }
53            Err(e) => return Err(e.into()),
54        };
55
56        Ok(fqb.build())
57    }
58}
59
60impl FileQueryBuilder<'static> {
61    pub fn new() -> FileQueryBuilder<'static> {
62        FileQueryBuilder {
63            filename: None,
64            metadata: None,
65        }
66    }
67}
68
69impl<'name> FileQueryBuilder<'name> {
70    /// Build the file query.
71    pub fn build(self) -> FileQuery<'name> {
72        FileQuery {
73            filename: self.filename,
74            metadata: self.metadata,
75        }
76    }
77
78    /// Set the filename for this builder.
79    pub fn filename<'new>(self, name: &'new OsStr) -> FileQueryBuilder<'new> {
80        FileQueryBuilder {
81            filename: Some(name),
82            ..self
83        }
84    }
85
86    /// Set the metadata for this builder.
87    pub fn metadata(self, meta: fs::Metadata) -> FileQueryBuilder<'name> {
88        FileQueryBuilder {
89            metadata: Some(meta),
90            ..self
91        }
92    }
93}