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
//! The provider abstraction.
//!
//! Every autostart backend (XDG `.desktop`, systemd user units, and future ones
//! such as OpenRC or DE session restore) implements [`AutostartProvider`]. The
//! [`crate::registry::Registry`] aggregates providers behind this single trait.
//!
//! ## Why async
//!
//! The I/O methods are `async` on purpose: probing and querying some backends
//! (notably systemd over D-Bus) can block for a noticeable time. Keeping the core
//! `async` and runtime-agnostic means it only ever `await`s — it never spins up a
//! runtime or `block_on`s — so a GUI front-end can drive it without pinning its
//! render thread on a slow bus call. Binaries bring their own runtime.
use Result;
use async_trait;
use crate;
/// A backend that can enumerate and manage autostart entries.
///
/// Implementors must be `Send + Sync` so the registry can hold them as
/// `Box<dyn AutostartProvider>` and share them across tasks.
///
/// ```
/// use anyhow::Result;
/// use async_trait::async_trait;
/// use runlatch_core::{AutostartEntry, AutostartProvider, Scope};
///
/// struct MyProvider;
///
/// #[async_trait]
/// impl AutostartProvider for MyProvider {
/// fn id(&self) -> &'static str { "my-provider" }
/// fn scope(&self) -> Scope { Scope::User }
/// // Return `false` (never panic) when the backend isn't present;
/// // the registry then silently skips this provider.
/// async fn is_available(&self) -> bool { true }
/// async fn entries(&self) -> Result<Vec<AutostartEntry>> { Ok(vec![]) }
/// async fn enable(&self, _id: &str) -> Result<()> { Ok(()) }
/// async fn disable(&self, _id: &str) -> Result<()> { Ok(()) }
/// async fn add(&self, _entry: &AutostartEntry) -> Result<()> { Ok(()) }
/// async fn remove(&self, _id: &str) -> Result<()> { Ok(()) }
/// }
/// ```