haproxy_config/config/
backend.rs1use std::collections::{HashMap, HashSet};
2
3use super::Address;
4use super::{Acl, error::Error, Name, Server};
5use crate::section::borrowed::Section;
6use crate::line::borrowed::Line;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct Backend {
12 pub name: String,
13 pub config: HashMap<String, Option<String>>,
14 pub options: HashMap<String, Option<String>>,
15 pub acls: HashSet<Acl>,
16 pub servers: Vec<Server>,
17}
18
19type Pair = (Name, Backend);
20impl<'a> TryFrom<&'a Section<'a>> for Pair {
21 type Error = Error;
22
23 fn try_from(entry: &'a Section<'a>) -> Result<(Name, Backend), Self::Error> {
24 let Section::Backend{ proxy, lines, ..} = entry else {
25 unreachable!()
26 };
27
28 let mut config = HashMap::new();
29 let mut options = HashMap::new();
30 let mut acls = HashSet::new();
31 let mut servers = Vec::new();
32 let mut other = Vec::new();
33
34 for line in lines
35 .iter()
36 .filter(|l| !matches!(l, Line::Blank | Line::Comment(_)))
37 {
38 match line {
39 Line::Config { key, value, .. } => {
40 let key = (*key).to_string();
41 let value = value.map(ToOwned::to_owned);
42 config.insert(key, value);
43 }
44 Line::Option {
45 keyword: key,
46 value,
47 ..
48 } => {
49 let key = (*key).to_string();
50 let value = value.map(ToOwned::to_owned);
51 options.insert(key, value);
52 }
53 Line::Acl { name, rule, .. } => {
54 acls.insert(Acl {
55 name: (*name).to_string(),
56 rule: rule.ok_or(Error::acl_without_rule(name))?.to_string(),
57 });
58 }
59 Line::Server {
60 name, addr, option, ..
61 } => servers.push(Server {
62 name: (*name).to_string(),
63 addr: Address::from(addr),
64 option: option.map(ToOwned::to_owned),
65 }),
66 wrong => other.push(wrong),
67 }
68 }
69
70 if !other.is_empty() {
71 return Err(Error::wrong_backend_lines(other));
72 }
73
74 Ok((
75 (*proxy).to_string(),
76 Backend {
77 name: (*proxy).to_string(),
78 config,
79 options,
80 acls,
81 servers,
82 },
83 ))
84 }
85}
86
87impl<'a> Backend {
88 pub(crate) fn parse_multiple(entries: &'a [Section<'a>]) -> Result<HashMap<Name, Self>, Error> {
89 entries
90 .iter()
91 .filter(|e| matches!(e, Section::Backend { .. }))
92 .map(Pair::try_from)
93 .collect()
94 }
95}