1use std::{borrow::Cow, fmt, num::NonZeroUsize, string::String, sync::Arc};
4use thiserror::Error;
5
6#[derive(Clone, Debug, Default)]
11pub struct CompilationProgress {
12 phase_name: Option<Cow<'static, str>>,
13 phase_step_count: Option<u64>,
14 phase_step: Option<u64>,
15}
16
17impl CompilationProgress {
18 pub fn new(
20 phase_name: Option<Cow<'static, str>>,
21 phase_step_count: Option<u64>,
22 phase_step: Option<u64>,
23 ) -> Self {
24 Self {
25 phase_name,
26 phase_step_count,
27 phase_step,
28 }
29 }
30
31 pub fn phase_name(&self) -> Option<&str> {
33 self.phase_name.as_deref()
34 }
35
36 pub fn phase_step_count(&self) -> Option<u64> {
38 self.phase_step_count
39 }
40
41 pub fn phase_step(&self) -> Option<u64> {
43 self.phase_step
44 }
45}
46
47#[derive(Clone, Debug, Error)]
49#[error("{reason}")]
50pub struct UserAbort {
51 reason: String,
52}
53
54impl UserAbort {
55 pub fn new(reason: impl Into<String>) -> Self {
57 Self {
58 reason: reason.into(),
59 }
60 }
61
62 pub fn reason(&self) -> &str {
64 &self.reason
65 }
66}
67
68type ProgressCallback =
69 dyn Fn(CompilationProgress) -> Result<(), UserAbort> + Send + Sync + 'static;
70type ReserveSizeCallbackFn = dyn Fn(usize) -> Result<(), UserAbort> + Send + Sync + 'static;
71
72#[derive(Clone)]
73struct ReserveSizeCallback {
74 callback: Arc<ReserveSizeCallbackFn>,
75 chunk_size: NonZeroUsize,
76}
77
78#[derive(Clone)]
80pub struct CompilationProgressCallback {
81 callback: Arc<ProgressCallback>,
82 reserve_size_callback: Option<ReserveSizeCallback>,
83}
84
85impl CompilationProgressCallback {
86 pub fn new<F>(callback: F) -> Self
93 where
94 F: Fn(CompilationProgress) -> Result<(), UserAbort> + Send + Sync + 'static,
95 {
96 Self {
97 callback: Arc::new(callback),
98 reserve_size_callback: None,
99 }
100 }
101
102 pub fn with_reserve_size_callback<F>(mut self, callback: F, chunk_size: NonZeroUsize) -> Self
107 where
108 F: Fn(usize) -> Result<(), UserAbort> + Send + Sync + 'static,
109 {
110 self.reserve_size_callback = Some(ReserveSizeCallback {
111 callback: Arc::new(callback),
112 chunk_size,
113 });
114 self
115 }
116
117 pub fn reserve_size_chunk_size(&self) -> Option<NonZeroUsize> {
119 self.reserve_size_callback
120 .as_ref()
121 .map(|callback| callback.chunk_size)
122 }
123
124 pub fn reserve_size(&self, size_increase: usize) -> Result<(), UserAbort> {
128 match &self.reserve_size_callback {
129 Some(callback) => (callback.callback)(size_increase),
130 None => Ok(()),
131 }
132 }
133
134 pub fn notify(&self, progress: CompilationProgress) -> Result<(), UserAbort> {
136 (self.callback)(progress)
137 }
138}
139
140impl fmt::Debug for CompilationProgressCallback {
141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142 f.debug_struct("CompilationProgressCallback").finish()
143 }
144}