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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use std::net::Ipv4Addr;

/// Zero copy representations of the lines in a config section, fast to create however hard to
/// pass around as it has a lifetime. This is the default returned by
/// [`parse_sections`][crate::parse_sections].
pub mod borrowed;
/// Owned representations of a config section, far easier to work with. Can be created
/// from a [`borrowed::Section`] using [`From`].
pub mod owned;

use crate::line::owned::Line;

use crate::config::Address;

impl<'a> From<&'a borrowed::Section<'a>> for owned::Section {
    fn from(section: &'a borrowed::Section<'a>) -> Self {
        match section {
            borrowed::Section::BlankLine => owned::Section::BlankLine,
            borrowed::Section::Comment(comment) => owned::Section::Comment((*comment).to_string()),
            borrowed::Section::Global { comment, lines } => owned::Section::Global {
                comment: comment.map(ToOwned::to_owned),
                lines: lines.iter().map(Line::from).collect(),
            },
            borrowed::Section::Default {
                comment,
                proxy,
                lines,
            } => owned::Section::Default {
                comment: comment.map(ToOwned::to_owned),
                proxy: proxy.map(ToOwned::to_owned),
                lines: lines.iter().map(Line::from).collect(),
            },
            borrowed::Section::Frontend {
                comment,
                proxy,
                lines,
                header_addr,
            } => owned::Section::Frontend {
                comment: comment.map(ToOwned::to_owned),
                proxy: (*proxy).to_string(),
                lines: lines.iter().map(Line::from).collect(),
                header_addr: header_addr.as_ref().map(|(address_ref, config)| {
                    (Address::from(address_ref), config.map(ToOwned::to_owned))
                }),
            },
            borrowed::Section::Listen {
                comment,
                proxy,
                lines,
                header_addr,
            } => owned::Section::Listen {
                comment: comment.map(ToOwned::to_owned),
                proxy: (*proxy).to_string(),
                lines: lines.iter().map(Line::from).collect(),
                header_addr: header_addr.as_ref().map(|(address_ref, config)| {
                    (Address::from(address_ref), config.map(ToOwned::to_owned))
                }),
            },
            borrowed::Section::Backend {
                comment,
                proxy,
                lines,
            } => owned::Section::Backend {
                comment: comment.map(ToOwned::to_owned),
                proxy: (*proxy).to_string(),
                lines: lines.iter().map(Line::from).collect(),
            },
            borrowed::Section::Userlist {
                comment,
                name,
                lines,
            } => owned::Section::Userlist {
                comment: comment.map(ToOwned::to_owned),
                name: (*name).to_string(),
                lines: lines.iter().map(Line::from).collect(),
            },
            borrowed::Section::UnknownLine { line } => owned::Section::UnknownLine {
                line: (*line).to_string(),
            },
        }
    }
}

/// See [`Host`](super::config::Host) for an owned variant.
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum HostRef<'input> {
    Ipv4(Ipv4Addr),
    Dns(&'input str),
    Wildcard,
}

/// See [`Address`](super::config::Address) for an owned variant.
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct AddressRef<'input> {
    pub host: HostRef<'input>,
    pub port: Option<u16>,
}

/// In combination with an [`Acl`](Line::Acl) forms the condition for picking a backend
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum BackendModifier {
    If,
    Unless,
}

/// See [`Password`](super::config::Password) for an owned variant.
#[derive(Debug)]
pub enum PasswordRef<'input> {
    Secure(&'input str),
    Insecure(&'input str),
}