mutant_lib/
events.rs

1use crate::error::Error;
2use futures::future::BoxFuture;
3use serde::{Deserialize, Serialize};
4
5/// Events emitted during the 'put' (store) operation.
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub enum PutEvent {
8    /// Indicates that the allocator needs to reserve new scratchpads.
9    ReservingScratchpads { needed: u64 },
10    /// Indicates the start of the reservation process for a batch of pads.
11    ReservingPads { count: u64 },
12    /// Reports the result of reserving a single pad within a batch.
13    PadReserved {
14        index: u64,
15        total: u64,
16        result: Result<(), String>, // Ok(()) on success, Err(error_string) on failure
17    },
18    /// Prompts the caller (e.g., the binary) to confirm the reservation.
19    /// The callback should return `Ok(true)` to proceed, `Ok(false)` to cancel.
20    ConfirmReservation {
21        needed: u64,
22        data_size: u64,
23        total_space: u64,
24        free_space: u64,
25        current_scratchpads: usize,
26        estimated_cost: Option<String>,
27    },
28    /// Reports progress during scratchpad reservation.
29    ReservationProgress { current: u64, total: u64 },
30    /// Indicates that the data upload process is starting.
31    StartingUpload { total_bytes: u64 },
32    /// Reports progress during data upload.
33    UploadProgress {
34        bytes_written: u64,
35        total_bytes: u64,
36    },
37    /// Indicates that the data upload process has finished.
38    UploadFinished,
39    /// Indicates the entire store operation (allocation, write, metadata update) is complete.
40    StoreComplete,
41    /// Indicates that a single scratchpad's worth of data has been successfully uploaded.
42    ScratchpadUploadComplete { index: u64, total: u64 },
43    /// Indicates that a single scratchpad has been fully committed/finalized after upload.
44    ScratchpadCommitComplete { index: u64, total: u64 },
45}
46
47/// Type alias for the callback function used during the 'put' operation.
48/// Uses `async FnMut` which requires the `async_fn_in_trait` feature.
49/// It returns a `BoxFuture` to handle the async nature in a trait object.
50pub type PutCallback =
51    Box<dyn FnMut(PutEvent) -> BoxFuture<'static, Result<bool, Error>> + Send + Sync>;
52
53#[inline]
54pub async fn invoke_callback(
55    callback: &mut Option<PutCallback>,
56    event: PutEvent,
57) -> Result<(), Error> {
58    if let Some(cb) = callback {
59        let fut = cb(event);
60        match fut.await {
61            Ok(true) => Ok(()),
62            Ok(false) => Err(Error::OperationCancelled),
63            Err(e) => Err(e),
64        }
65    } else {
66        Ok(())
67    }
68}
69
70/// Events emitted during the library initialization, primarily for first-run setup.
71#[derive(Debug, Clone)]
72pub enum InitProgressEvent {
73    /// Starting the initialization process.
74    Starting { total_steps: u64 },
75    /// Progress update for a specific step.
76    Step { step: u64, message: String },
77    /// Initialization completed successfully.
78    Complete { message: String },
79    /// Initialization failed.
80    Failed { error_msg: String },
81    /// An existing configuration was found and loaded (skipping first-run).
82    ExistingLoaded { message: String },
83}
84
85/// Type alias for the callback function used during library initialization.
86/// The callback returns a simple Result to indicate success or failure, but
87/// doesn't need to return a boolean like PutCallback.
88pub type InitCallback =
89    Box<dyn FnMut(InitProgressEvent) -> BoxFuture<'static, Result<(), Error>> + Send + Sync>;
90
91#[inline]
92pub(crate) async fn invoke_init_callback(
93    callback: &mut Option<InitCallback>,
94    event: InitProgressEvent,
95) -> Result<(), Error> {
96    if let Some(cb) = callback {
97        let fut = cb(event);
98        fut.await
99    } else {
100        Ok(())
101    }
102}
103
104/// Events emitted during the `MutAnt::fetch` process.
105#[derive(Debug, Clone)]
106pub enum GetEvent {
107    /// Indicates the start of the download process, providing the total size.
108    StartingDownload { total_bytes: u64 },
109    /// Reports the progress of the download.
110    DownloadProgress { bytes_read: u64, total_bytes: u64 },
111    /// Indicates that the download has finished successfully.
112    DownloadFinished,
113}
114
115/// Callback type for Get/Fetch progress updates.
116/// The callback returns a simple Result to indicate success or failure.
117pub type GetCallback =
118    Box<dyn FnMut(GetEvent) -> BoxFuture<'static, Result<(), Error>> + Send + Sync>;
119
120// Helper function for invoking the Get callback if it exists.
121// Note: We might need a distinct invoke function if the return type differs significantly,
122// but since both InitCallback and GetCallback return Result<(), Error>, we might be able to reuse or generalize.
123// For now, let's assume invoke_init_callback logic works (simple propagation).
124#[inline]
125pub(crate) async fn invoke_get_callback(
126    callback: &mut Option<GetCallback>,
127    event: GetEvent,
128) -> Result<(), Error> {
129    if let Some(cb) = callback {
130        let fut = cb(event);
131        fut.await
132    } else {
133        Ok(())
134    }
135}