jobberdb/
configuration.rs1use crate::prelude::*;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Serialize, Deserialize, Debug, Clone, Default)]
9pub struct Configuration {
10 pub base: Properties,
12 pub tags: HashMap<String, Properties>,
14}
15
16impl Configuration {
17 pub fn set(&mut self, tags: &Option<TagSet>, update: &Properties) -> bool {
19 let mut modified = false;
20 if let Some(tags) = tags {
21 for tag in tags.iter() {
22 if let Some(tag_configuration) = self.tags.get_mut(tag) {
23 if tag_configuration.update(update.clone()) {
24 modified = true;
25 }
26 } else {
27 self.tags.insert(tag.clone(), update.clone());
28 modified = true;
29 }
30 }
31 } else if self.base.update(update.clone()) {
32 modified = true;
33 }
34 modified
35 }
36 pub fn get_and_why(&self, tags: &TagSet) -> (Option<String>, &Properties) {
38 for tag in &tags.0 {
39 if let Some(properties) = self.tags.get(tag) {
40 return (Some(tag.clone()), properties);
41 }
42 }
43 (None, &self.base)
44 }
45 pub fn get(&self, tags: &TagSet) -> &Properties {
47 match &self.get_checked(tags) {
48 Ok(properties) => properties,
49 _ => panic!("unexpected tag collision"),
50 }
51 }
52 pub fn get_checked(&self, tags: &TagSet) -> Result<&Properties, Error> {
54 let mut found = TagSet::new();
55 let mut properties = None;
56 for tag in &tags.0 {
57 if let Some(p) = self.tags.get(tag) {
58 found.insert(tag);
59 properties = Some(p);
60 }
61 }
62 match found.len() {
63 0 => Ok(&self.base),
64 1 => Ok(properties.unwrap()),
65 _ => Err(Error::TagCollision(found)),
66 }
67 }
68}
69
70#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
72pub struct Properties {
73 pub resolution: Option<f64>,
75 pub rate: Option<f64>,
77 pub max_hours: Option<u32>,
79}
80
81impl Properties {
82 pub fn update(&mut self, properties: Properties) -> bool {
88 let mut modified = false;
89 if let Some(resolution) = properties.resolution {
90 self.resolution = Some(resolution);
91 modified = true;
92 }
93 if let Some(rate) = properties.rate {
94 self.rate = Some(rate);
95 modified = true;
96 }
97 if let Some(max_hours) = properties.max_hours {
98 self.max_hours = Some(max_hours);
99 modified = true;
100 }
101 modified
102 }
103}
104
105impl Default for Properties {
106 fn default() -> Self {
107 Self {
108 resolution: Some(0.25),
109 rate: None,
110 max_hours: None,
111 }
112 }
113}
114
115impl std::fmt::Display for Properties {
116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117 if let Some(resolution) = self.resolution {
118 writeln!(f, "Resolution: {} hours", resolution)?;
119 }
120 if let Some(rate) = self.rate {
121 writeln!(f, "Payment per hour: {}", rate)?
122 };
123 if let Some(max_hours) = self.max_hours {
124 writeln!(f, "Maximum work time: {} hours", max_hours)?
125 };
126 Ok(())
127 }
128}