dittolive_ditto/disk_usage/
mod.rs1use_prelude!();
18use core::ffi::c_void;
19use std::sync::{Arc, Mutex, Weak};
20
21use ffi_sdk::{ffi_utils::Blocking, BoxedDitto, FsComponent};
22use serde::Deserialize;
23
24#[repr(C)]
25#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)]
26pub enum FileSystemType {
28 Directory = 0,
30
31 File,
33
34 SymLink,
36}
37
38#[derive(Deserialize, Debug, Clone, Eq, PartialEq)]
39pub struct DiskUsageChild {
41 pub fs_type: FileSystemType,
43 pub path: String,
45 pub size_in_bytes: usize,
47 pub children: Option<Vec<DiskUsageChild>>,
49}
50
51pub struct DiskUsageObserverCtx<F: ?Sized + DiskUsageCallback> {
54 handle: Option<repr_c::Box<ffi_sdk::DiskUsageObserver>>,
57 on_update: F,
59}
60
61#[doc(hidden)]
62#[deprecated(note = "This is now named `DiskUsageObserverCtx`")]
63pub type DiskUsageObserver = DiskUsageObserverCtx<dyn DiskUsageCallback>;
64
65trait_alias! {
66 pub trait DiskUsageCallback = 'static + Send + FnMut(DiskUsageChild)
70}
71
72#[allow(type_alias_bounds)]
76pub type DiskUsageObserverHandle<F: ?Sized + DiskUsageCallback = dyn DiskUsageCallback> =
77 Mutex<DiskUsageObserverCtx<F>>;
78
79const _ASSERT_IMPLS: &(dyn Send + Sync) = &::core::marker::PhantomData::<DiskUsageObserverHandle>;
80
81impl<F: DiskUsageCallback> DiskUsageObserverCtx<F> {
82 fn set_handle(&mut self, handle: repr_c::Box<ffi_sdk::DiskUsageObserver>) {
83 self.handle = Some(handle);
84 }
85
86 #[track_caller]
90 unsafe fn borrowing_from_ctx(
91 ctx: *const c_void,
92 yielding: impl FnOnce(&Weak<DiskUsageObserverHandle<F>>),
93 ) {
94 let weak_ctx = ::core::mem::ManuallyDrop::new(Weak::from_raw(
95 ctx.cast::<DiskUsageObserverHandle<F>>(),
96 ));
97 yielding(&weak_ctx)
98 }
99
100 unsafe extern "C" fn on_event(ctx: *mut c_void, cbor: c_slice::Ref<'_, u8>, _: Blocking) {
101 Self::borrowing_from_ctx(ctx, |weak_ctx| {
102 if let Some(strong_ctx) = weak_ctx.upgrade() {
103 let tree = ::serde_cbor::from_slice(cbor.as_slice()).unwrap();
104 (strong_ctx.lock().unwrap().on_update)(tree);
105 }
106 })
107 }
108
109 unsafe extern "C" fn retain(ctx: *mut c_void, _: Blocking) {
110 Self::borrowing_from_ctx(ctx, |weak_ctx| {
112 _ = Weak::into_raw(weak_ctx.clone());
113 });
114 }
115
116 unsafe extern "C" fn release(ctx: *mut c_void, _: Blocking) {
117 drop(Weak::from_raw(ctx.cast::<DiskUsageObserverHandle<F>>()));
119 }
120}
121
122pub struct DiskUsage {
124 ditto: Arc<BoxedDitto>,
125 component: FsComponent,
126}
127
128impl DiskUsage {
129 pub(crate) fn new(ditto: Arc<BoxedDitto>, component: FsComponent) -> Self {
131 Self { ditto, component }
132 }
133
134 pub fn exec(&self) -> DiskUsageChild {
136 let cval = ffi_sdk::ditto_disk_usage(&self.ditto, self.component);
137 ::serde_cbor::from_slice(cval.as_slice()).unwrap()
138 }
139
140 pub fn observe<F: DiskUsageCallback>(&self, callback: F) -> Arc<DiskUsageObserverHandle> {
142 let observer: DiskUsageObserverHandle<F> = Mutex::new(DiskUsageObserverCtx::<F> {
143 on_update: callback,
144 handle: None,
145 });
146 let observer: Arc<DiskUsageObserverHandle<F>> = Arc::new(observer);
147
148 let weak_observer = Arc::downgrade(&observer);
159
160 let handle = unsafe {
161 ffi_sdk::ditto_register_disk_usage_callback(
162 &self.ditto,
163 self.component,
164 weak_observer.as_ptr() as *mut _,
165 Some(DiskUsageObserverCtx::<F>::retain),
166 Some(DiskUsageObserverCtx::<F>::release),
167 Some(<unsafe extern "C" fn(_, c_slice::Ref<'_, _>, _)>::into(
168 DiskUsageObserverCtx::<F>::on_event,
169 )),
170 )
171 };
172 drop(weak_observer);
175
176 observer.lock().unwrap().set_handle(handle.unwrap());
177 observer
178 }
179}