summaryrefslogtreecommitdiffhomepage
path: root/mullvad-cli/src/cmds/mod.rs
blob: 88e4184f0729ab0d0b1f962d52754b43f3281251 (plain)
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
76
77
78
79
80
81
82
use clap::builder::{PossibleValuesParser, TypedValueParser, ValueParser};
use std::ops::Deref;

pub mod account;
pub mod api_access;
pub mod auto_connect;
pub mod beta_program;
pub mod bridge;
pub mod custom_list;
pub mod dns;
pub mod lan;
pub mod lockdown;
pub mod obfuscation;
pub mod relay;
pub mod relay_constraints;
pub mod reset;
pub mod split_tunnel;
pub mod status;
pub mod tunnel;
pub mod tunnel_state;
pub mod version;

/// A value parser that parses "on" or "off" into a boolean
#[derive(Debug, Clone, Copy)]
pub struct BooleanOption {
    state: bool,
    on_label: &'static str,
    off_label: &'static str,
}

impl Deref for BooleanOption {
    type Target = bool;

    fn deref(&self) -> &Self::Target {
        &self.state
    }
}

impl clap::builder::ValueParserFactory for BooleanOption {
    type Parser = ValueParser;

    /// A value parser that parses "on" or "off" into a `BooleanOption`
    fn value_parser() -> Self::Parser {
        Self::custom_parser("on", "off")
    }
}

impl BooleanOption {
    /// A value parser that parses `on_label` and `off_label` into a `BooleanOption`
    fn custom_parser(on_label: &'static str, off_label: &'static str) -> ValueParser {
        assert!(on_label != off_label);

        ValueParser::new(
            PossibleValuesParser::new([on_label, off_label])
                .map(move |val| Self::with_labels(val == on_label, on_label, off_label)),
        )
    }

    fn with_labels(state: bool, on_label: &'static str, off_label: &'static str) -> Self {
        Self {
            state,
            on_label,
            off_label,
        }
    }
}

impl From<bool> for BooleanOption {
    fn from(state: bool) -> Self {
        Self::with_labels(state, "on", "off")
    }
}

impl std::fmt::Display for BooleanOption {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if self.state {
            self.on_label.fmt(f)
        } else {
            self.off_label.fmt(f)
        }
    }
}