use crate::error::{ChunkingError, Result};
use crate::*;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
pub enum SeqOpMode {
#[default]
Increasing,
Decreasing,
}
#[derive(Debug, Clone)]
pub struct ChunkingConfig {
pub seq_threshold: u64,
pub jump_trigger: u64,
pub jump_size: u64,
pub op_mode: SeqOpMode,
pub min_block_size: u64,
pub avg_block_size: u64,
pub max_block_size: u64,
}
impl ChunkingConfig {
pub fn new() -> Self {
Self::default()
}
pub fn builder() -> ChunkingConfigBuilder {
ChunkingConfigBuilder::new()
}
pub fn validate(&self) -> Result<()> {
if self.seq_threshold == 0 {
return Err(ChunkingError::InvalidConfig("seq_threshold must be greater than 0".into()));
}
if self.min_block_size == 0 {
return Err(ChunkingError::InvalidConfig("min_block_size must be greater than 0".into()));
}
if self.max_block_size < self.min_block_size {
return Err(ChunkingError::InvalidConfig("max_block_size must be >= min_block_size".into()));
}
if self.jump_size == 0 {
return Err(ChunkingError::InvalidConfig("jump_size must be greater than 0".into()));
}
Ok(())
}
pub fn seq_threshold(&self) -> u64 { self.seq_threshold }
pub fn jump_trigger(&self) -> u64 { self.jump_trigger }
pub fn jump_size(&self) -> u64 { self.jump_size }
pub fn op_mode(&self) -> SeqOpMode { self.op_mode }
pub fn min_block_size(&self) -> u64 { self.min_block_size }
pub fn avg_block_size(&self) -> u64 { self.avg_block_size }
pub fn max_block_size(&self) -> u64 { self.max_block_size }
}
impl Default for ChunkingConfig {
fn default() -> Self {
Self {
seq_threshold: DEFAULT_SEQ_THRESHOLD,
jump_trigger: DEFAULT_JUMP_TRIGGER,
jump_size: DEFAULT_JUMP_SIZE,
op_mode: SeqOpMode::default(),
min_block_size: DEFAULT_MIN_BLOCK_SIZE,
avg_block_size: DEFAULT_AVG_BLOCK_SIZE,
max_block_size: DEFAULT_MAX_BLOCK_SIZE,
}
}
}
#[derive(Debug)]
pub struct ChunkingConfigBuilder {
config: ChunkingConfig,
}
impl ChunkingConfigBuilder {
pub fn new() -> Self {
Self {
config: ChunkingConfig::default(),
}
}
pub fn seq_threshold(mut self, threshold: u64) -> Self {
self.config.seq_threshold = threshold;
self
}
pub fn jump_trigger(mut self, trigger: u64) -> Self {
self.config.jump_trigger = trigger;
self
}
pub fn jump_size(mut self, size: u64) -> Self {
self.config.jump_size = size;
self
}
pub fn op_mode(mut self, mode: SeqOpMode) -> Self {
self.config.op_mode = mode;
self
}
pub fn min_block_size(mut self, size: u64) -> Self {
self.config.min_block_size = size;
self
}
pub fn avg_block_size(mut self, size: u64) -> Self {
self.config.avg_block_size = size;
self
}
pub fn max_block_size(mut self, size: u64) -> Self {
self.config.max_block_size = size;
self
}
pub fn build(self) -> Result<ChunkingConfig> {
self.config.validate()?;
Ok(self.config)
}
pub fn build_unchecked(self) -> ChunkingConfig {
self.config
}
}
impl Default for ChunkingConfigBuilder {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = ChunkingConfig::new();
assert_eq!(config.seq_threshold(), DEFAULT_SEQ_THRESHOLD);
assert_eq!(config.op_mode(), SeqOpMode::Increasing);
assert!(config.validate().is_ok());
}
#[test]
fn test_builder_pattern() {
let config = ChunkingConfig::builder()
.seq_threshold(10)
.min_block_size(2048)
.max_block_size(32768)
.op_mode(SeqOpMode::Decreasing)
.build()
.unwrap();
assert_eq!(config.seq_threshold(), 10);
assert_eq!(config.min_block_size(), 2048);
assert_eq!(config.max_block_size(), 32768);
assert_eq!(config.op_mode(), SeqOpMode::Decreasing);
}
#[test]
fn test_invalid_config() {
let result = ChunkingConfig::builder()
.seq_threshold(0)
.build();
assert!(result.is_err());
}
#[test]
fn test_invalid_block_sizes() {
let result = ChunkingConfig::builder()
.min_block_size(8192)
.max_block_size(4096) .build();
assert!(result.is_err());
}
}