summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/config.rs111
-rw-r--r--src/expr.rs42
-rw-r--r--src/field.rs190
-rw-r--r--src/fileinfo.rs2
-rw-r--r--src/function.rs642
-rw-r--r--src/ignore/docker.rs94
-rw-r--r--src/ignore/git.rs139
-rw-r--r--src/ignore/hg.rs161
-rw-r--r--src/ignore/mod.rs2
-rw-r--r--src/lexer.rs864
-rw-r--r--src/main.rs146
-rw-r--r--src/mode.rs58
-rw-r--r--src/operators.rs16
-rw-r--r--src/output/csv.rs2
-rw-r--r--src/output/flat.rs11
-rw-r--r--src/output/html.rs3
-rw-r--r--src/output/json.rs12
-rw-r--r--src/output/mod.rs94
-rw-r--r--src/parser.rs839
-rw-r--r--src/query.rs76
-rw-r--r--src/searcher.rs1416
-rw-r--r--src/util/capabilities.rs134
-rw-r--r--src/util/datetime.rs83
-rw-r--r--src/util/dimensions/image.rs77
-rw-r--r--src/util/dimensions/mkv.rs37
-rw-r--r--src/util/dimensions/mod.rs33
-rw-r--r--src/util/dimensions/mp4.rs26
-rw-r--r--src/util/dimensions/svg.rs37
-rw-r--r--src/util/duration/mod.rs22
-rw-r--r--src/util/duration/mp3.rs18
-rw-r--r--src/util/duration/mp4.rs22
-rw-r--r--src/util/duration/wav.rs7
-rw-r--r--src/util/glob.rs12
-rw-r--r--src/util/japanese.rs12
-rw-r--r--src/util/mod.rs345
-rw-r--r--src/util/top_n.rs29
-rw-r--r--src/util/wbuf.rs1
37 files changed, 3639 insertions, 2176 deletions
diff --git a/src/config.rs b/src/config.rs
index be3b774..a92d868 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,3 +1,5 @@
+//! Handles configuration loading and saving
+
use std::fs;
use std::io::{Read, Write};
use std::path::PathBuf;
@@ -18,25 +20,25 @@ macro_rules! vec_of_strings {
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct Config {
- pub no_color : Option<bool>,
+ pub no_color: Option<bool>,
pub gitignore: Option<bool>,
pub hgignore: Option<bool>,
pub dockerignore: Option<bool>,
- pub is_zip_archive : Option<Vec<String>>,
- pub is_archive : Option<Vec<String>>,
- pub is_audio : Option<Vec<String>>,
- pub is_book : Option<Vec<String>>,
- pub is_doc : Option<Vec<String>>,
- pub is_font : Option<Vec<String>>,
- pub is_image : Option<Vec<String>>,
- pub is_source : Option<Vec<String>>,
- pub is_video : Option<Vec<String>>,
- pub default_file_size_format : Option<String>,
+ pub is_zip_archive: Option<Vec<String>>,
+ pub is_archive: Option<Vec<String>>,
+ pub is_audio: Option<Vec<String>>,
+ pub is_book: Option<Vec<String>>,
+ pub is_doc: Option<Vec<String>>,
+ pub is_font: Option<Vec<String>>,
+ pub is_image: Option<Vec<String>>,
+ pub is_source: Option<Vec<String>>,
+ pub is_video: Option<Vec<String>>,
+ pub default_file_size_format: Option<String>,
pub check_for_updates: Option<bool>,
#[serde(skip_serializing, default = "get_false")]
- pub debug : bool,
+ pub debug: bool,
#[serde(skip)]
- save : bool,
+ save: bool,
}
fn get_false() -> bool {
@@ -68,13 +70,10 @@ impl Config {
}
pub fn from(config_file: PathBuf) -> Result<Config, String> {
- if let Ok(mut file) = fs::File::open(&config_file) {
+ if let Ok(mut file) = fs::File::open(config_file) {
let mut contents = String::new();
- if let Ok(_) = file.read_to_string(&mut contents) {
- match toml::from_str(&contents) {
- Ok(config) => Ok(config),
- Err(err) => Err(err.to_string())
- }
+ if file.read_to_string(&mut contents).is_ok() {
+ toml::from_str(&contents).map_err(|err| err.to_string())
} else {
Err("Could not read config file. Using default settings.".to_string())
}
@@ -97,18 +96,13 @@ impl Config {
#[cfg(not(windows))]
fn get_project_dir() -> Option<PathBuf> {
- match ProjectDirs::from("", ORGANIZATION, APPLICATION) {
- Some(pd) => Some(pd.config_dir().to_path_buf()),
- _ => None
- }
+ ProjectDirs::from("", ORGANIZATION, APPLICATION).map(|pd| pd.config_dir().to_path_buf())
}
#[cfg(windows)]
fn get_project_dir() -> Option<PathBuf> {
- match ProjectDirs::from("", ORGANIZATION, APPLICATION) {
- Some(pd) => Some(pd.config_dir().parent().unwrap().to_path_buf()),
- _ => None
- }
+ ProjectDirs::from("", ORGANIZATION, APPLICATION)
+ .map(|pd| pd.config_dir().parent().unwrap().to_path_buf())
}
pub fn save(&self) {
@@ -133,29 +127,54 @@ impl Config {
let toml = toml::to_string_pretty(&self).unwrap();
if let Ok(mut file) = fs::File::create(&config_file) {
- let _ = file.write_all(&toml.as_bytes());
+ let _ = file.write_all(toml.as_bytes());
}
}
pub fn default() -> Config {
Config {
- no_color : Some(false),
- gitignore : Some(false),
- hgignore : Some(false),
- dockerignore : Some(false),
- is_zip_archive : vec_of_strings![".zip", ".jar", ".war", ".ear"],
- is_archive : vec_of_strings![".7z", ".bz2", ".bzip2", ".gz", ".gzip", ".lz", ".rar", ".tar", ".xz", ".zip"],
- is_audio : vec_of_strings![".aac", ".aiff", ".amr", ".flac", ".gsm", ".m4a", ".m4b", ".m4p", ".mp3", ".ogg", ".wav", ".wma"],
- is_book : vec_of_strings![".azw3", ".chm", ".djv", ".djvu", ".epub", ".fb2", ".mobi", ".pdf"],
- is_doc : vec_of_strings![".accdb", ".doc", ".docm", ".docx", ".dot", ".dotm", ".dotx", ".mdb", ".odp", ".ods", ".odt", ".pdf", ".potm", ".potx", ".ppt", ".pptm", ".pptx", ".rtf", ".xlm", ".xls", ".xlsm", ".xlsx", ".xlt", ".xltm", ".xltx", ".xps"],
- is_font : vec_of_strings![".eot", ".fon", ".otc", ".otf", ".ttc", ".ttf", ".woff", ".woff2"],
- is_image : vec_of_strings![".bmp", ".exr", ".gif", ".heic", ".jpeg", ".jpg", ".jxl", ".png", ".psb", ".psd", ".svg", ".tga", ".tiff", ".webp"],
- is_source : vec_of_strings![".asm", ".bas", ".c", ".cc", ".ceylon", ".clj", ".coffee", ".cpp", ".cs", ".d", ".dart", ".elm", ".erl", ".go", ".gradle", ".groovy", ".h", ".hh", ".hpp", ".java", ".jl", ".js", ".jsp", ".jsx", ".kt", ".kts", ".lua", ".nim", ".pas", ".php", ".pl", ".pm", ".py", ".rb", ".rs", ".scala", ".sol", ".swift", ".tcl", ".ts", ".tsx", ".vala", ".vb", ".zig"],
- is_video : vec_of_strings![".3gp", ".avi", ".flv", ".m4p", ".m4v", ".mkv", ".mov", ".mp4", ".mpeg", ".mpg", ".webm", ".wmv"],
- default_file_size_format : Some(String::new()),
- check_for_updates : Some(false),
- debug : false,
- save : true,
+ no_color: Some(false),
+ gitignore: Some(false),
+ hgignore: Some(false),
+ dockerignore: Some(false),
+ is_zip_archive: vec_of_strings![".zip", ".jar", ".war", ".ear"],
+ is_archive: vec_of_strings![
+ ".7z", ".bz2", ".bzip2", ".gz", ".gzip", ".lz", ".rar", ".tar", ".xz", ".zip"
+ ],
+ is_audio: vec_of_strings![
+ ".aac", ".aiff", ".amr", ".flac", ".gsm", ".m4a", ".m4b", ".m4p", ".mp3", ".ogg",
+ ".wav", ".wma"
+ ],
+ is_book: vec_of_strings![
+ ".azw3", ".chm", ".djv", ".djvu", ".epub", ".fb2", ".mobi", ".pdf"
+ ],
+ is_doc: vec_of_strings![
+ ".accdb", ".doc", ".docm", ".docx", ".dot", ".dotm", ".dotx", ".mdb", ".odp",
+ ".ods", ".odt", ".pdf", ".potm", ".potx", ".ppt", ".pptm", ".pptx", ".rtf", ".xlm",
+ ".xls", ".xlsm", ".xlsx", ".xlt", ".xltm", ".xltx", ".xps"
+ ],
+ is_font: vec_of_strings![
+ ".eot", ".fon", ".otc", ".otf", ".ttc", ".ttf", ".woff", ".woff2"
+ ],
+ is_image: vec_of_strings![
+ ".bmp", ".exr", ".gif", ".heic", ".jpeg", ".jpg", ".jxl", ".png", ".psb", ".psd",
+ ".svg", ".tga", ".tiff", ".webp"
+ ],
+ is_source: vec_of_strings![
+ ".asm", ".bas", ".c", ".cc", ".ceylon", ".clj", ".coffee", ".cpp", ".cs", ".d",
+ ".dart", ".elm", ".erl", ".go", ".gradle", ".groovy", ".h", ".hh", ".hpp", ".java",
+ ".jl", ".js", ".jsp", ".jsx", ".kt", ".kts", ".lua", ".nim", ".pas", ".php", ".pl",
+ ".pm", ".py", ".rb", ".rs", ".scala", ".sol", ".swift", ".tcl", ".ts", ".tsx",
+ ".vala", ".vb", ".zig"
+ ],
+ is_video: vec_of_strings![
+ ".3gp", ".avi", ".flv", ".m4p", ".m4v", ".mkv", ".mov", ".mp4", ".mpeg", ".mpg",
+ ".webm", ".wmv"
+ ],
+ default_file_size_format: Some(String::new()),
+ check_for_updates: Some(false),
+ debug: false,
+ save: true,
}
}
}
@@ -170,4 +189,4 @@ mod tests {
assert!(config.is_source.unwrap().contains(&String::from(".rs")));
}
-} \ No newline at end of file
+}
diff --git a/src/expr.rs b/src/expr.rs
index e66fcf3..2d5f5db 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -170,7 +170,7 @@ impl Expr {
result.extend(right.get_required_fields());
}
- if let Some( field) = self.field {
+ if let Some(field) = self.field {
result.insert(field);
}
@@ -190,7 +190,7 @@ impl Expr {
fn contains_numeric_field(expr: &Expr) -> bool {
let field = match expr.field {
Some(ref field) => field.is_numeric_field(),
- None => false
+ None => false,
};
if field {
@@ -199,19 +199,17 @@ impl Expr {
let function = match expr.function {
Some(ref function) => function.is_numeric_function(),
- None => false
+ None => false,
};
if function {
return true;
}
- let left = match expr.left {
- Some(ref left) => Self::contains_numeric_field(&left),
- None => false
- };
-
- left
+ match expr.left {
+ Some(ref left) => Self::contains_numeric_field(left),
+ None => false,
+ }
}
pub fn contains_datetime(&self) -> bool {
@@ -221,19 +219,17 @@ impl Expr {
fn contains_datetime_field(expr: &Expr) -> bool {
let field = match expr.field {
Some(ref field) => field.is_datetime_field(),
- None => false
+ None => false,
};
if field {
return true;
}
- let left = match expr.left {
- Some(ref left) => Self::contains_datetime_field(&left),
- None => false
- };
-
- left
+ match expr.left {
+ Some(ref left) => Self::contains_datetime_field(left),
+ None => false,
+ }
}
pub fn contains_colorized(&self) -> bool {
@@ -247,19 +243,17 @@ impl Expr {
let field = match expr.field {
Some(ref field) => field.is_colorized_field(),
- None => false
+ None => false,
};
if field {
return true;
}
- let left = match expr.left {
- Some(ref left) => Self::contains_colorized_field(&left),
- None => false
- };
-
- left
+ match expr.left {
+ Some(ref left) => Self::contains_colorized_field(left),
+ None => false,
+ }
}
}
@@ -287,7 +281,7 @@ impl Display for Expr {
}
if let Some(ref val) = self.val {
- fmt.write_str(&val)?;
+ fmt.write_str(val)?;
}
if let Some(ref right) = self.right {
diff --git a/src/field.rs b/src/field.rs
index 4edd6ec..ee71784 100644
--- a/src/field.rs
+++ b/src/field.rs
@@ -1,3 +1,5 @@
+//! Defines the various fields available in the query language
+
use std::fmt::Display;
use std::fmt::Error;
use std::fmt::Formatter;
@@ -189,134 +191,128 @@ impl FromStr for Field {
}
impl Display for Field {
- fn fmt(&self, f: &mut Formatter) -> Result<(), Error>{
+ fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "{:?}", self)
}
}
impl Serialize for Field {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
- where S: Serializer
+ where
+ S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl Field {
+ #[rustfmt::skip]
pub fn is_numeric_field(&self) -> bool {
- match self {
- Field::Size | Field::FormattedSize
+ matches!(self, Field::Size | Field::FormattedSize
| Field::Uid | Field::Gid
| Field::Width | Field::Height
| Field::LineCount
| Field::Duration
| Field::Bitrate | Field::Freq | Field::Year
- | Field::ExifGpsLatitude | Field::ExifGpsLongitude | Field::ExifGpsAltitude => true,
- _ => false
- }
+ | Field::ExifGpsLatitude | Field::ExifGpsLongitude | Field::ExifGpsAltitude)
}
pub fn is_datetime_field(&self) -> bool {
- match self {
- Field::Created | Field::Accessed | Field::Modified
- | Field::ExifDateTime => true,
- _ => false
- }
+ matches!(
+ self,
+ Field::Created | Field::Accessed | Field::Modified | Field::ExifDateTime
+ )
}
pub fn is_boolean_field(&self) -> bool {
- match self {
+ matches!(
+ self,
Field::IsDir
- | Field::IsFile
- | Field::UserRead
- | Field::UserWrite
- | Field::UserExec
- | Field::UserAll
- | Field::GroupRead
- | Field::GroupWrite
- | Field::GroupExec
- | Field::GroupAll
- | Field::OtherRead
- | Field::OtherWrite
- | Field::OtherExec
- | Field::OtherAll
- | Field::Suid
- | Field::Sgid
- | Field::IsSymlink
- | Field::IsPipe
- | Field::IsCharacterDevice
- | Field::IsBlockDevice
- | Field::IsSocket
- | Field::IsHidden
- | Field::HasXattrs
- | Field::IsEmpty
- | Field::IsShebang
- | Field::IsBinary
- | Field::IsText
- | Field::IsArchive
- | Field::IsAudio
- | Field::IsBook
- | Field::IsDoc
- | Field::IsFont
- | Field::IsImage
- | Field::IsSource
- | Field::IsVideo => true,
- _ => false
- }
+ | Field::IsFile
+ | Field::UserRead
+ | Field::UserWrite
+ | Field::UserExec
+ | Field::UserAll
+ | Field::GroupRead
+ | Field::GroupWrite
+ | Field::GroupExec
+ | Field::GroupAll
+ | Field::OtherRead
+ | Field::OtherWrite
+ | Field::OtherExec
+ | Field::OtherAll
+ | Field::Suid
+ | Field::Sgid
+ | Field::IsSymlink
+ | Field::IsPipe
+ | Field::IsCharacterDevice
+ | Field::IsBlockDevice
+ | Field::IsSocket
+ | Field::IsHidden
+ | Field::HasXattrs
+ | Field::IsEmpty
+ | Field::IsShebang
+ | Field::IsBinary
+ | Field::IsText
+ | Field::IsArchive
+ | Field::IsAudio
+ | Field::IsBook
+ | Field::IsDoc
+ | Field::IsFont
+ | Field::IsImage
+ | Field::IsSource
+ | Field::IsVideo
+ )
}
pub fn is_available_for_archived_files(&self) -> bool {
- match self {
+ matches!(
+ self,
Field::Name
- | Field::Extension
- | Field::Path
- | Field::AbsPath
- | Field::Directory
- | Field::AbsDir
- | Field::Size
- | Field::FormattedSize
- | Field::IsDir
- | Field::IsFile
- | Field::IsSymlink
- | Field::IsPipe
- | Field::IsCharacterDevice
- | Field::IsBlockDevice
- | Field::IsSocket
- | Field::Mode
- | Field::UserRead
- | Field::UserWrite
- | Field::UserExec
- | Field::UserAll
- | Field::GroupRead
- | Field::GroupWrite
- | Field::GroupExec
- | Field::GroupAll
- | Field::OtherRead
- | Field::OtherWrite
- | Field::OtherExec
- | Field::OtherAll
- | Field::Suid
- | Field::Sgid
- | Field::IsHidden
- | Field::IsEmpty
- | Field::Modified
- | Field::IsArchive
- | Field::IsAudio
- | Field::IsBook
- | Field::IsDoc
- | Field::IsFont
- | Field::IsImage
- | Field::IsSource
- | Field::IsVideo
- => true,
- _ => false
- }
+ | Field::Extension
+ | Field::Path
+ | Field::AbsPath
+ | Field::Directory
+ | Field::AbsDir
+ | Field::Size
+ | Field::FormattedSize
+ | Field::IsDir
+ | Field::IsFile
+ | Field::IsSymlink
+ | Field::IsPipe
+ | Field::IsCharacterDevice
+ | Field::IsBlockDevice
+ | Field::IsSocket
+ | Field::Mode
+ | Field::UserRead
+ | Field::UserWrite
+ | Field::UserExec
+ | Field::UserAll
+ | Field::GroupRead
+ | Field::GroupWrite
+ | Field::GroupExec
+ | Field::GroupAll
+ | Field::OtherRead
+ | Field::OtherWrite
+ | Field::OtherExec
+ | Field::OtherAll
+ | Field::Suid
+ | Field::Sgid
+ | Field::IsHidden
+ | Field::IsEmpty
+ | Field::Modified
+ | Field::IsArchive
+ | Field::IsAudio
+ | Field::IsBook
+ | Field::IsDoc
+ | Field::IsFont
+ | Field::IsImage
+ | Field::IsSource
+ | Field::IsVideo
+ )
}
pub fn is_colorized_field(&self) -> bool {
- match self {
- Field::Name => true,
- _ => false
- }
+ matches!(self, Field::Name)
}
}
diff --git a/src/fileinfo.rs b/src/fileinfo.rs
index c7d8d1b..96f3b63 100644
--- a/src/fileinfo.rs
+++ b/src/fileinfo.rs
@@ -12,6 +12,6 @@ pub fn to_file_info(zipped_file: &zip::read::ZipFile) -> FileInfo {
name: zipped_file.name().to_string(),
size: zipped_file.size(),
mode: zipped_file.unix_mode(),
- modified: zipped_file.last_modified()
+ modified: zipped_file.last_modified(),
}
}
diff --git a/src/function.rs b/src/function.rs
index 0a10650..074416c 100644
--- a/src/function.rs
+++ b/src/function.rs
@@ -1,3 +1,6 @@
+//! Functions for processing values in the query language.
+//! This module contains both the regular and aggregate functions used in the query language.
+
use std::collections::HashMap;
use std::fmt::Display;
use std::fmt::Error;
@@ -19,11 +22,11 @@ use xattr::FileExt;
use human_time::ToHumanTimeString;
use crate::fileinfo::FileInfo;
-use crate::util::{capitalize, error_exit, format_date};
use crate::util::format_datetime;
use crate::util::parse_datetime;
use crate::util::parse_filesize;
use crate::util::str_to_bool;
+use crate::util::{capitalize, error_exit, format_date};
#[derive(Clone, Debug)]
pub enum VariantType {
@@ -105,8 +108,8 @@ impl Variant {
result += &value.to_owned();
result
- },
- false => value.to_owned()
+ }
+ false => value.to_owned(),
};
Variant {
@@ -123,8 +126,14 @@ impl Variant {
pub fn from_bool(value: bool) -> Variant {
Variant {
value_type: VariantType::Bool,
- string_value: match value { true => String::from("true"), _ => String::from("false") },
- int_value: match value { true => Some(1), _ => Some(0) },
+ string_value: match value {
+ true => String::from("true"),
+ _ => String::from("false"),
+ },
+ int_value: match value {
+ true => Some(1),
+ _ => Some(0),
+ },
float_value: None,
bool_value: Some(value),
dt_from: None,
@@ -161,8 +170,8 @@ impl Variant {
Ok(i) => i as i64,
_ => match parse_filesize(&self.string_value) {
Some(size) => size as i64,
- _ => 0
- }
+ _ => 0,
+ },
}
}
}
@@ -181,8 +190,8 @@ impl Variant {
Ok(f) => f,
_ => match parse_filesize(&self.string_value) {
Some(size) => size as f64,
- _ => 0.0
- }
+ _ => 0.0,
+ },
}
}
}
@@ -207,8 +216,8 @@ impl Variant {
match parse_datetime(&self.string_value) {
Ok((dt_from, dt_to)) => {
return (dt_from, dt_to);
- },
- _ => error_exit("Can't parse datetime", &self.string_value)
+ }
+ _ => error_exit("Can't parse datetime", &self.string_value),
}
}
@@ -217,80 +226,142 @@ impl Variant {
}
impl Display for Variant {
- fn fmt(&self, f: &mut Formatter) -> Result<(), Error>{
+ fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "{}", self.to_string())
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
pub enum Function {
+ // ===== Regular functions =====
+ // String conversion functions
+ /// Convert the value to lowercase
Lower,
+ /// Convert the value to UPPERCASE
Upper,
+ /// Capitalize the first letter of each word (Title Case)
InitCap,
+ /// Get the length of the string
Length,
+ /// Convert the value to base64
ToBase64,
+ /// Read the value as base64
FromBase64,
+
+ // String manipulation functions
+ /// Concatenate the value with the arguments
+ Concat,
+ /// Concatenate the arguments, separated by the value
+ ConcatWs,
+ /// Get a substring of the value, from a position and length
+ Substring,
+ /// Replace a substring in the value with another string
+ Replace,
+ /// Trim whitespace from the value
+ Trim,
+ /// Trim whitespace from the start of the value
+ LTrim,
+ /// Trim whitespace from the end of the value
+ RTrim,
+
+ // Numeric functions
+ /// Get the binary representation of the value
Bin,
+ /// Get the hexadecimal representation of the value
Hex,
+ /// Get the octal representation of the value
Oct,
+ /// Raise the value to the power of another value
Power,
+ /// Get the square root of the value
Sqrt,
+ // Japanese string functions
+ /// Check if the string contains Japanese characters
ContainsJapanese,
+ /// Check if the string contains Hiragana characters
ContainsHiragana,
+ /// Check if the string contains Katakana characters
ContainsKatakana,
+ /// Check if the string contains Kana characters
ContainsKana,
+ /// Check if the string contains Kanji characters
ContainsKanji,
- Concat,
- ConcatWs,
- Substring,
- Replace,
- Trim,
- LTrim,
- RTrim,
- Coalesce,
+ // Formatting functions
+ /// Format a file size in human-readable format
FormatSize,
+ /// Format a time duration in human-readable format
FormatTime,
- Min,
- Max,
- Avg,
- Sum,
- Count,
-
- StdDevPop,
- StdDevSamp,
- VarPop,
- VarSamp,
-
+ // Date and time functions
+ /// Get the current date
CurrentDate,
+ /// Get the day from a date
Day,
+ /// Get the month from a date
Month,
+ /// Get the year from a date
Year,
+ /// Get the day of the week from a date
DayOfWeek,
+ // File functions
#[cfg(all(unix, feature = "users"))]
+ /// Get the current user ID
CurrentUid,
#[cfg(all(unix, feature = "users"))]
+ /// Get the current username
CurrentUser,
#[cfg(all(unix, feature = "users"))]
+ /// Get the current group ID
CurrentGid,
#[cfg(all(unix, feature = "users"))]
+ /// Get the current group name
CurrentGroup,
+ /// Checks if a file contains a substring
Contains,
#[cfg(unix)]
+ /// Check if the file has a specific extended attribute
HasXattr,
#[cfg(unix)]
+ /// Get the value of an extended attribute
Xattr,
#[cfg(target_os = "linux")]
+ /// Check if the file has capabilities (security.capability xattr)
HasCapabilities,
#[cfg(target_os = "linux")]
+ /// Check if the file has a specific capability (security.capability xattr)
HasCapability,
+ // Miscellaneous functions
+ /// Return the first non-empty value
+ Coalesce,
+ /// Gets a random number from 0 to the value, or between two values
Random,
+
+ // ===== Aggregate functions =====
+ /// Get the minimum value
+ Min,
+ /// Get the maximum value
+ Max,
+ /// Get the average value
+ Avg,
+ /// Get the sum of all values
+ Sum,
+ /// Get the number of values
+ Count,
+
+ /// Get the population standard deviation
+ StdDevPop,
+ /// Get the sample standard deviation
+ StdDevSamp,
+ /// Get the population variance
+ VarPop,
+ /// Get the sample variance
+ VarSamp,
}
impl FromStr for Function {
@@ -377,52 +448,56 @@ impl FromStr for Function {
}
impl Display for Function {
- fn fmt(&self, f: &mut Formatter) -> Result<(), Error>{
+ fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "{:?}", self)
}
}
impl Serialize for Function {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
- where S: Serializer
+ where
+ S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl Function {
+ /// Check if the function is an aggregate function
pub fn is_aggregate_function(&self) -> bool {
- match self {
+ matches!(
+ self,
Function::Min
- | Function::Max
- | Function::Avg
- | Function::Sum
- | Function::Count
- | Function::StdDevPop
- | Function::StdDevSamp
- | Function::VarPop
- | Function::VarSamp => true,
- _ => false
- }
+ | Function::Max
+ | Function::Avg
+ | Function::Sum
+ | Function::Count
+ | Function::StdDevPop
+ | Function::StdDevSamp
+ | Function::VarPop
+ | Function::VarSamp
+ )
}
+ /// Check if the function is a numeric function, i.e. it returns a numeric value.
pub fn is_numeric_function(&self) -> bool {
if self.is_aggregate_function() {
return true;
}
- match self {
+ matches!(
+ self,
Function::Length
- | Function::Random
- | Function::Day
- | Function::Month
- | Function::Year
- | Function::Power
- | Function::Sqrt => true,
- _ => false
- }
+ | Function::Random
+ | Function::Day
+ | Function::Month
+ | Function::Year
+ | Function::Power
+ | Function::Sqrt
+ )
}
+ /// Check if the function is a boolean function, i.e. it returns a boolean value.
pub fn is_boolean_function(&self) -> bool {
#[cfg(unix)]
if self == &Function::HasXattr {
@@ -434,119 +509,77 @@ impl Function {
return true;
}
- match self {
+ matches!(
+ self,
Function::Contains
- | Function::ContainsHiragana
- | Function::ContainsKatakana
- | Function::ContainsKana
- | Function::ContainsKanji
- | Function::ContainsJapanese => true,
- _ => false
- }
+ | Function::ContainsHiragana
+ | Function::ContainsKatakana
+ | Function::ContainsKana
+ | Function::ContainsKanji
+ | Function::ContainsJapanese
+