1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//! Plugin contract trait definition
//!
//! This module defines the `CompressionAlgorithm` trait that all plugins must implement.
//! Plugins register themselves at compile-time using the `linkme` distributed slice pattern.
use crateResult;
use cratePluginMetadata;
use AtomicBool;
use Arc;
/// Trait that all compression plugins must implement
///
/// Plugins provide compress/decompress operations with cooperative cancellation support.
/// The `cancel_flag` parameter allows the library to signal timeout or user cancellation,
/// and plugins SHOULD check this flag periodically (e.g., every block) and return early if set.
///
/// # Safety and Error Handling
///
/// - All methods return `Result<T>` to enable proper error propagation
/// - Plugins MUST NOT panic - all errors should be returned via `Result`
/// - Plugins MUST validate input data before processing
/// - If `cancel_flag` is set to `true`, plugins SHOULD return `Err(PluginError::Cancelled)`
///
/// # Example Implementation
///
/// ```no_run
/// use crush_core::plugin::{CompressionAlgorithm, PluginMetadata, COMPRESSION_ALGORITHMS};
/// use crush_core::error::Result;
/// use std::sync::Arc;
/// use std::sync::atomic::{AtomicBool, Ordering};
/// use linkme::distributed_slice;
///
/// struct MyPlugin;
///
/// impl CompressionAlgorithm for MyPlugin {
/// fn name(&self) -> &'static str { "my_plugin" }
///
/// fn metadata(&self) -> PluginMetadata {
/// PluginMetadata {
/// name: "my_plugin",
/// version: "1.0.0",
/// magic_number: [0x43, 0x52, 0x01, 0x10],
/// throughput: 500.0,
/// compression_ratio: 0.65,
/// description: "My compression algorithm",
/// }
/// }
///
/// fn compress(&self, input: &[u8], cancel_flag: Arc<AtomicBool>) -> Result<Vec<u8>> {
/// let mut output = Vec::new();
/// for chunk in input.chunks(4096) {
/// // Check cancellation flag periodically
/// if cancel_flag.load(Ordering::Acquire) {
/// return Err(crush_core::error::PluginError::Cancelled.into());
/// }
/// // Compress chunk...
/// }
/// Ok(output)
/// }
///
/// fn decompress(&self, input: &[u8], cancel_flag: Arc<AtomicBool>) -> Result<Vec<u8>> {
/// // Similar implementation with cancellation checking
/// Ok(vec![])
/// }
///
/// fn detect(&self, file_header: &[u8]) -> bool {
/// file_header.len() >= 4 && file_header[0..4] == self.metadata().magic_number
/// }
/// }
///
/// // Register plugin at compile-time
/// #[distributed_slice(COMPRESSION_ALGORITHMS)]
/// static MY_PLUGIN: &dyn CompressionAlgorithm = &MyPlugin;
/// ```