Files
keep/src/meta_plugin.rs
Andrew Phillips 9d60461354 feat: add is_finalized to MetaPluginResponse and remove direct db interaction from meta plugins
Co-authored-by: aider (openai/andrew/openrouter/deepseek/deepseek-chat-v3.1) <aider@aider.chat>
2025-08-26 17:11:27 -03:00

194 lines
7.3 KiB
Rust

use anyhow::Result;
use log::debug;
use serde::{Deserialize, Serialize};
pub mod program;
pub mod digest;
pub mod system;
pub mod magic;
pub mod binary;
use crate::meta_plugin::program::MetaPluginProgram;
use crate::meta_plugin::digest::{DigestSha256MetaPlugin, ReadTimeMetaPlugin, ReadRateMetaPlugin};
use crate::meta_plugin::system::{CwdMetaPlugin, UidMetaPlugin, UserMetaPlugin, GidMetaPlugin, GroupMetaPlugin, ShellMetaPlugin, ShellPidMetaPlugin, KeepPidMetaPlugin, HostnameMetaPlugin, FullHostnameMetaPlugin};
use crate::meta_plugin::magic::MagicFileMetaPlugin;
use crate::meta_plugin::binary::BinaryMetaPlugin;
/// Represents metadata to be stored
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetaData {
pub name: String,
pub value: String,
}
/// Response from meta plugin operations
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct MetaPluginResponse {
pub metadata: Vec<MetaData>,
pub is_finalized: bool,
}
#[derive(Debug, Eq, PartialEq, Clone, strum::EnumIter, strum::Display, strum::EnumString)]
#[strum(ascii_case_insensitive)]
pub enum MetaPluginType {
FileMagic,
FileMime,
FileEncoding,
MagicFile,
LineCount,
WordCount,
Cwd,
Binary,
Uid,
User,
Gid,
Group,
Shell,
ShellPid,
KeepPid,
DigestSha256,
DigestMd5,
ReadTime,
ReadRate,
Hostname,
FullHostname,
}
/// Central function to handle metadata output with name mapping
/// outputs: HashMap where key is internal name, value is either custom name or "false" to disable
pub fn process_metadata_outputs(internal_name: &str, value: String, outputs: &std::collections::HashMap<String, serde_yaml::Value>) -> Option<MetaData> {
// Check if this output is disabled
if let Some(mapping) = outputs.get(internal_name) {
if let Some(false_val) = mapping.as_bool() {
if !false_val {
debug!("META: Skipping disabled output: {}", internal_name);
return None;
}
}
if let Some(custom_name) = mapping.as_str() {
debug!("META: Processing metadata: internal_name={}, custom_name={}, value={}", internal_name, custom_name, value);
return Some(MetaData {
name: custom_name.to_string(),
value,
});
}
}
// Default: use internal name as output name
debug!("META: Processing metadata: name={}, value={}", internal_name, value);
Some(MetaData {
name: internal_name.to_string(),
value,
})
}
pub trait MetaPlugin {
fn is_supported(&self) -> bool {
true
}
fn is_internal(&self) -> bool {
false
}
// Update the meta plugin with new data
fn update(&mut self, data: &[u8]) -> MetaPluginResponse {
// Default implementation does nothing
MetaPluginResponse {
metadata: Vec::new(),
is_finalized: false,
}
}
fn finalize(&mut self) -> MetaPluginResponse {
// Default implementation does nothing
MetaPluginResponse {
metadata: Vec::new(),
is_finalized: true,
}
}
fn meta_name(&self) -> String;
// Get program information for display in status
fn program_info(&self) -> Option<(&str, Vec<&str>)> {
None
}
// Initialize the plugin
fn initialize(&mut self) -> MetaPluginResponse {
// Default implementation does nothing
MetaPluginResponse {
metadata: Vec::new(),
is_finalized: false,
}
}
// Access to outputs mapping
fn outputs(&self) -> &std::collections::HashMap<String, serde_yaml::Value>;
fn outputs_mut(&mut self) -> &mut std::collections::HashMap<String, serde_yaml::Value>;
// Access to options mapping
fn options(&self) -> &std::collections::HashMap<String, serde_yaml::Value>;
fn options_mut(&mut self) -> &mut std::collections::HashMap<String, serde_yaml::Value>;
// Get the default output names this plugin can produce
fn default_outputs(&self) -> Vec<String> {
// Default implementation returns empty - plugins should override this
Vec::new()
}
// Get the default options for this plugin
fn default_options(&self) -> std::collections::HashMap<String, serde_yaml::Value> {
// Default implementation returns empty - plugins should override this
std::collections::HashMap::new()
}
// Configure plugin with options (excluding outputs)
fn configure_options(&mut self, _options: &std::collections::HashMap<String, serde_yaml::Value>) -> Result<()> {
// Default implementation does nothing - plugins can override this
Ok(())
}
// Configure plugin outputs mapping
fn configure_outputs(&mut self, outputs: &std::collections::HashMap<String, serde_yaml::Value>) -> Result<()> {
for (key, value) in outputs {
self.outputs_mut().insert(key.clone(), value.clone());
}
Ok(())
}
// Configure both options and outputs
fn configure(&mut self, options: &std::collections::HashMap<String, serde_yaml::Value>, outputs: &std::collections::HashMap<String, serde_yaml::Value>) -> Result<()> {
self.configure_options(options)?;
self.configure_outputs(outputs)?;
Ok(())
}
}
pub fn get_meta_plugin(meta_plugin_type: MetaPluginType) -> Box<dyn MetaPlugin> {
match meta_plugin_type {
MetaPluginType::FileMagic => Box::new(MetaPluginProgram::new_simple("file", vec!["-bE", "-"], "file_magic".to_string(), true)),
MetaPluginType::FileMime => Box::new(MetaPluginProgram::new_simple("file", vec!["-b", "--mime-type", "-"], "file_mime".to_string(), true)),
MetaPluginType::FileEncoding => Box::new(MetaPluginProgram::new_simple("file", vec!["-b", "--mime-encoding", "-"], "file_encoding".to_string(), true)),
MetaPluginType::MagicFile => Box::new(MagicFileMetaPlugin::new_simple()),
MetaPluginType::LineCount => Box::new(MetaPluginProgram::new_simple("wc", vec!["-l"], "line_count".to_string(), true)),
MetaPluginType::WordCount => Box::new(MetaPluginProgram::new_simple("wc", vec!["-w"], "word_count".to_string(), true)),
MetaPluginType::Cwd => Box::new(CwdMetaPlugin::new_simple()),
MetaPluginType::Binary => Box::new(BinaryMetaPlugin::new_simple()),
MetaPluginType::Uid => Box::new(UidMetaPlugin::new_simple()),
MetaPluginType::User => Box::new(UserMetaPlugin::new_simple()),
MetaPluginType::Gid => Box::new(GidMetaPlugin::new_simple()),
MetaPluginType::Group => Box::new(GroupMetaPlugin::new_simple()),
MetaPluginType::Shell => Box::new(ShellMetaPlugin::new_simple()),
MetaPluginType::ShellPid => Box::new(ShellPidMetaPlugin::new_simple()),
MetaPluginType::KeepPid => Box::new(KeepPidMetaPlugin::new_simple()),
MetaPluginType::DigestSha256 => Box::new(DigestSha256MetaPlugin::new_simple()),
MetaPluginType::DigestMd5 => Box::new(MetaPluginProgram::new_simple("md5sum", vec![], "digest_md5".to_string(), true)),
MetaPluginType::ReadTime => Box::new(ReadTimeMetaPlugin::new_simple()),
MetaPluginType::ReadRate => Box::new(ReadRateMetaPlugin::new_simple()),
MetaPluginType::Hostname => Box::new(HostnameMetaPlugin::new_simple()),
MetaPluginType::FullHostname => Box::new(FullHostnameMetaPlugin::new_simple()),
}
}