2020-03-05 13:09:32 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2020-04-02 20:50:59 +00:00
|
|
|
|
|
|
|
use std::path::{Path, PathBuf};
|
2020-03-05 13:09:32 +00:00
|
|
|
|
2020-03-28 18:21:46 +00:00
|
|
|
pub use f64 as Rank;
|
|
|
|
pub use i64 as Epoch; // use a signed integer so subtraction can be performed on it
|
|
|
|
|
2020-04-10 21:30:50 +00:00
|
|
|
#[derive(Debug, Deserialize, Serialize)]
|
2020-03-05 13:09:32 +00:00
|
|
|
pub struct Dir {
|
2020-03-27 11:41:26 +00:00
|
|
|
pub path: PathBuf,
|
2020-03-05 13:09:32 +00:00
|
|
|
pub rank: Rank,
|
2020-03-13 00:49:37 +00:00
|
|
|
pub last_accessed: Epoch,
|
2020-03-05 13:09:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Dir {
|
|
|
|
pub fn is_dir(&self) -> bool {
|
2020-03-27 11:41:26 +00:00
|
|
|
self.path.is_dir()
|
2020-03-05 13:09:32 +00:00
|
|
|
}
|
|
|
|
|
2020-03-27 11:41:26 +00:00
|
|
|
#[cfg(unix)]
|
2020-03-05 13:09:32 +00:00
|
|
|
pub fn is_match(&self, query: &[String]) -> bool {
|
2020-03-27 11:41:26 +00:00
|
|
|
use bstr::ByteSlice;
|
2020-04-02 20:50:59 +00:00
|
|
|
|
|
|
|
use std::ffi::OsStr;
|
2020-03-27 11:41:26 +00:00
|
|
|
use std::os::unix::ffi::OsStrExt;
|
2020-03-05 13:09:32 +00:00
|
|
|
|
2020-04-02 20:50:59 +00:00
|
|
|
let path_lower = self.path.as_os_str().as_bytes().to_lowercase();
|
|
|
|
|
|
|
|
if let Some(query_name) = query
|
|
|
|
.last()
|
|
|
|
.and_then(|query_last| Path::new(query_last).file_name())
|
|
|
|
{
|
|
|
|
if let Some(dir_name) = Path::new(OsStr::from_bytes(&path_lower)).file_name() {
|
|
|
|
let dir_name_bytes = dir_name.as_bytes();
|
|
|
|
let query_name_bytes = query_name.as_bytes();
|
|
|
|
|
|
|
|
if !dir_name_bytes.contains_str(query_name_bytes) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut subpath = path_lower.as_slice();
|
2020-03-05 13:09:32 +00:00
|
|
|
|
2020-03-27 11:41:26 +00:00
|
|
|
for subquery in query.iter() {
|
|
|
|
let subquery_bytes = subquery.as_bytes();
|
|
|
|
match subpath.find(subquery_bytes) {
|
|
|
|
Some(idx) => subpath = &subpath[idx + subquery_bytes.len()..],
|
|
|
|
None => return false,
|
2020-03-05 13:09:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-27 11:41:26 +00:00
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(unix))]
|
|
|
|
pub fn is_match(&self, query: &[String]) -> bool {
|
2020-04-02 20:50:59 +00:00
|
|
|
let path_lower = match self.path.to_str() {
|
2020-03-27 11:41:26 +00:00
|
|
|
Some(path_str) => path_str.to_lowercase(),
|
|
|
|
None => return false, // silently ignore invalid UTF-8
|
|
|
|
};
|
|
|
|
|
2020-04-02 20:50:59 +00:00
|
|
|
let mut subpath = path_lower.as_str();
|
|
|
|
|
|
|
|
if let Some(query_name) = query
|
|
|
|
.last()
|
|
|
|
.and_then(|query_last| Path::new(query_last).file_name())
|
|
|
|
{
|
|
|
|
if let Some(dir_name) = Path::new(&path_lower).file_name() {
|
|
|
|
// unwrap is safe here because we've already handled invalid UTF-8
|
|
|
|
let dir_name_str = dir_name.to_str().unwrap();
|
|
|
|
let query_name_str = query_name.to_str().unwrap();
|
|
|
|
|
|
|
|
if !dir_name_str.contains(query_name_str) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-27 11:41:26 +00:00
|
|
|
|
|
|
|
for subquery in query.iter() {
|
2020-03-05 13:09:32 +00:00
|
|
|
match subpath.find(subquery) {
|
|
|
|
Some(idx) => subpath = &subpath[idx + subquery.len()..],
|
|
|
|
None => return false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
2020-03-13 00:49:37 +00:00
|
|
|
pub fn get_frecency(&self, now: Epoch) -> Rank {
|
|
|
|
const HOUR: Epoch = 60 * 60;
|
|
|
|
const DAY: Epoch = 24 * HOUR;
|
|
|
|
const WEEK: Epoch = 7 * DAY;
|
2020-03-05 13:09:32 +00:00
|
|
|
|
|
|
|
let duration = now - self.last_accessed;
|
|
|
|
if duration < HOUR {
|
2020-03-06 17:43:32 +00:00
|
|
|
self.rank * 4.0
|
2020-03-05 13:09:32 +00:00
|
|
|
} else if duration < DAY {
|
2020-03-06 17:43:32 +00:00
|
|
|
self.rank * 2.0
|
2020-03-05 13:09:32 +00:00
|
|
|
} else if duration < WEEK {
|
2020-03-06 17:43:32 +00:00
|
|
|
self.rank / 2.0
|
2020-03-05 13:09:32 +00:00
|
|
|
} else {
|
2020-03-06 17:43:32 +00:00
|
|
|
self.rank / 4.0
|
2020-03-05 13:09:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|