Skip to main content

lamco_data_control/
options.rs

1//! Connection options and the protocol choice.
2
3use std::fmt;
4
5/// The data-control protocol in use.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7#[non_exhaustive]
8pub enum Protocol {
9    /// `ext-data-control-v1`, the standardized protocol.
10    Ext,
11    /// `wlr-data-control-unstable-v1`, the wlroots protocol.
12    Wlr,
13}
14
15impl fmt::Display for Protocol {
16    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17        match self {
18            Protocol::Ext => f.write_str("ext-data-control-v1"),
19            Protocol::Wlr => f.write_str("wlr-data-control-unstable-v1"),
20        }
21    }
22}
23
24/// Which protocol to prefer when the compositor offers both.
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
26#[non_exhaustive]
27pub enum Preference {
28    /// Prefer `ext-data-control-v1`, then `wlr-data-control-unstable-v1`.
29    #[default]
30    Auto,
31    /// Prefer `ext-data-control-v1`.
32    Ext,
33    /// Prefer `wlr-data-control-unstable-v1`.
34    Wlr,
35}
36
37/// Options for [`DataControl::connect_with`](crate::DataControl::connect_with).
38///
39/// ```
40/// use lamco_data_control::{Options, Preference};
41///
42/// let options = Options::new()
43///     .preference(Preference::Wlr)
44///     .allow_fallback(false);
45/// ```
46#[derive(Debug, Clone)]
47pub struct Options {
48    pub(crate) preference: Preference,
49    pub(crate) allow_fallback: bool,
50    pub(crate) max_read_bytes: usize,
51}
52
53impl Options {
54    /// The default read size limit: 100 MiB.
55    pub const DEFAULT_MAX_READ_BYTES: usize = 100 * 1024 * 1024;
56
57    /// Options with automatic protocol selection and fallback enabled.
58    #[must_use]
59    pub fn new() -> Self {
60        Self {
61            preference: Preference::Auto,
62            allow_fallback: true,
63            max_read_bytes: Self::DEFAULT_MAX_READ_BYTES,
64        }
65    }
66
67    /// Choose which protocol to prefer.
68    #[must_use]
69    pub fn preference(mut self, preference: Preference) -> Self {
70        self.preference = preference;
71        self
72    }
73
74    /// Whether to use the other protocol when the preferred one is missing.
75    #[must_use]
76    pub fn allow_fallback(mut self, allow: bool) -> Self {
77        self.allow_fallback = allow;
78        self
79    }
80
81    /// Limit, in bytes, for one [`read`](crate::DataControl::read).
82    #[must_use]
83    pub fn max_read_bytes(mut self, limit: usize) -> Self {
84        self.max_read_bytes = limit;
85        self
86    }
87}
88
89impl Default for Options {
90    fn default() -> Self {
91        Self::new()
92    }
93}
94
95impl Options {
96    /// The protocols to try, in order.
97    pub(crate) fn candidates(&self) -> Vec<Protocol> {
98        let (first, second) = match self.preference {
99            Preference::Auto | Preference::Ext => (Protocol::Ext, Protocol::Wlr),
100            Preference::Wlr => (Protocol::Wlr, Protocol::Ext),
101        };
102        if self.allow_fallback {
103            vec![first, second]
104        } else {
105            vec![first]
106        }
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use super::{Options, Preference, Protocol};
113
114    #[test]
115    fn auto_tries_ext_then_wlr() {
116        assert_eq!(Options::new().candidates(), [Protocol::Ext, Protocol::Wlr]);
117    }
118
119    #[test]
120    fn a_wlr_preference_tries_wlr_first() {
121        let options = Options::new().preference(Preference::Wlr);
122        assert_eq!(options.candidates(), [Protocol::Wlr, Protocol::Ext]);
123    }
124
125    #[test]
126    fn disabling_fallback_leaves_only_the_preferred_protocol() {
127        let options = Options::new()
128            .preference(Preference::Wlr)
129            .allow_fallback(false);
130        assert_eq!(options.candidates(), [Protocol::Wlr]);
131    }
132}