#[cfg(feature = "config_parsing")]
use serde::{self, de};
#[cfg(feature = "config_parsing")]
use serde_value::Value;
#[cfg(feature = "config_parsing")]
use std::collections::BTreeMap;
use crate::append::rolling_file::{
policy::{compound::roll::Roll, Policy},
LogFile,
};
#[cfg(feature = "config_parsing")]
use crate::config::{Deserialize, Deserializers};
pub mod roll;
pub mod trigger;
#[cfg(feature = "config_parsing")]
#[derive(Clone, Eq, PartialEq, Hash, Debug, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub struct CompoundPolicyConfig {
trigger: Trigger,
roller: Roller,
}
#[cfg(feature = "config_parsing")]
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
struct Trigger {
kind: String,
config: Value,
}
#[cfg(feature = "config_parsing")]
impl<'de> serde::Deserialize<'de> for Trigger {
fn deserialize<D>(d: D) -> Result<Trigger, D::Error>
where
D: serde::Deserializer<'de>,
{
let mut map = BTreeMap::<Value, Value>::deserialize(d)?;
let kind = match map.remove(&Value::String("kind".to_owned())) {
Some(kind) => kind.deserialize_into().map_err(|e| e.to_error())?,
None => return Err(de::Error::missing_field("kind")),
};
Ok(Trigger {
kind,
config: Value::Map(map),
})
}
}
#[cfg(feature = "config_parsing")]
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
struct Roller {
kind: String,
config: Value,
}
#[cfg(feature = "config_parsing")]
impl<'de> serde::Deserialize<'de> for Roller {
fn deserialize<D>(d: D) -> Result<Roller, D::Error>
where
D: serde::Deserializer<'de>,
{
let mut map = BTreeMap::<Value, Value>::deserialize(d)?;
let kind = match map.remove(&Value::String("kind".to_owned())) {
Some(kind) => kind.deserialize_into().map_err(|e| e.to_error())?,
None => return Err(de::Error::missing_field("kind")),
};
Ok(Roller {
kind,
config: Value::Map(map),
})
}
}
#[derive(Debug)]
pub struct CompoundPolicy {
trigger: Box<dyn trigger::Trigger>,
roller: Box<dyn Roll>,
}
impl CompoundPolicy {
pub fn new(trigger: Box<dyn trigger::Trigger>, roller: Box<dyn Roll>) -> CompoundPolicy {
CompoundPolicy { trigger, roller }
}
}
impl Policy for CompoundPolicy {
fn process(&self, log: &mut LogFile) -> anyhow::Result<()> {
if self.trigger.trigger(log)? {
log.roll();
self.roller.roll(log.path())?;
}
Ok(())
}
fn is_pre_process(&self) -> bool {
self.trigger.is_pre_process()
}
}
#[cfg(feature = "config_parsing")]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
pub struct CompoundPolicyDeserializer;
#[cfg(feature = "config_parsing")]
impl Deserialize for CompoundPolicyDeserializer {
type Trait = dyn Policy;
type Config = CompoundPolicyConfig;
fn deserialize(
&self,
config: CompoundPolicyConfig,
deserializers: &Deserializers,
) -> anyhow::Result<Box<dyn Policy>> {
let trigger = deserializers.deserialize(&config.trigger.kind, config.trigger.config)?;
let roller = deserializers.deserialize(&config.roller.kind, config.roller.config)?;
Ok(Box::new(CompoundPolicy::new(trigger, roller)))
}
}