badge_maker/badge/
badge.rs

1use crate::badge::color::util::u64_to_hex;
2use crate::badge::style::Style;
3use crate::badge::{Links, Logo};
4use crate::render::renderers::styles::*;
5use crate::render::BadgeRenderer;
6use std::hash::{Hash, Hasher};
7
8/// The purpose of a unique id is to make the svg compatible with direct website embedding.
9///
10/// Hashing is done as a escaping mechanism.
11fn gen_id(
12    label: &Option<String>,
13    message: &str,
14    label_color: &str,
15    color: &str,
16    style: &Style,
17    links: &Links,
18    logo: &Option<Logo>,
19) -> String {
20    let mut hasher = seahash::SeaHasher::new();
21    logo.hash(&mut hasher);
22    label.hash(&mut hasher);
23    label_color.hash(&mut hasher);
24    color.hash(&mut hasher);
25    style.hash(&mut hasher);
26    message.hash(&mut hasher);
27    links.left.hash(&mut hasher);
28    links.right.hash(&mut hasher);
29    u64_to_hex(hasher.finish())
30}
31
32/// Badges are valid and have all the necessary
33/// fields to construct an SVG without error.
34/// Use the [BadgeBuilder](crate::badge::BadgeBuilder) to construct.
35///
36/// # Example
37///
38/// ```rust
39/// use badge_maker::BadgeBuilder;
40/// # use badge_maker::error::Error;
41///
42/// let badge = BadgeBuilder::new()
43///   .message("Example")
44///   .build()?;
45///
46/// # Ok::<(), Error>(())
47/// ```
48///
49#[derive(Debug, Eq, PartialEq)]
50pub struct Badge {
51    label: Option<String>,
52    message: String,
53    label_color: String,
54    color: String,
55    style: Style,
56    links: Links,
57    logo: Option<Logo>,
58    id: String,
59    ids: String,
60    idr: String,
61}
62
63impl Badge {
64    pub(crate) fn new(
65        label: Option<String>,
66        message: String,
67        label_color: String,
68        color: String,
69        style: Style,
70        links: Links,
71        logo: Option<Logo>,
72    ) -> Self {
73        let id = gen_id(
74            &label,
75            &message,
76            &label_color,
77            &color,
78            &style,
79            &links,
80            &logo,
81        );
82        let ids = format!("bms-{}", id);
83        let idr = format!("bmr-{}", id);
84
85        Self {
86            label,
87            message,
88            label_color,
89            color,
90            style,
91            links,
92            logo,
93            id,
94            ids,
95            idr,
96        }
97    }
98
99    pub fn svg(&self) -> String {
100        match self.style {
101            Style::Flat => Flat::render(self),
102            Style::Plastic => Plastic::render(self),
103            Style::FlatSquare => FlatSquare::render(self),
104        }
105    }
106
107    pub fn label(&self) -> &Option<String> {
108        &self.label
109    }
110
111    pub fn message(&self) -> &str {
112        &self.message
113    }
114
115    pub fn label_color(&self) -> &str {
116        &self.label_color
117    }
118
119    pub fn color(&self) -> &str {
120        &self.color
121    }
122
123    pub fn style(&self) -> Style {
124        self.style
125    }
126
127    pub fn links(&self) -> &Links {
128        &self.links
129    }
130
131    pub fn logo(&self) -> &Option<Logo> {
132        &self.logo
133    }
134
135    pub fn ids(&self) -> &str {
136        &self.ids
137    }
138
139    pub fn idr(&self) -> &str {
140        &self.idr
141    }
142    pub fn id(&self) -> &str {
143        &self.id
144    }
145}
146
147#[cfg(test)]
148mod tests {
149    use super::*;
150    use crate::badge::style::Style::Flat;
151
152    #[test]
153    fn gen_id_test() {
154        assert_eq!(
155            gen_id(
156                &Some("hello".to_string()),
157                "e",
158                "e",
159                "3",
160                &Flat,
161                &Links {
162                    left: Option::from("hello".to_string()),
163                    right: None,
164                },
165                &None,
166            ),
167            "95efd3465e2fbf49"
168        );
169        assert_eq!(
170            gen_id(
171                &Some("hello".to_string()),
172                "message",
173                "label_color",
174                "#ec3d",
175                &Flat,
176                &Links {
177                    left: None,
178                    right: None,
179                },
180                &None,
181            ),
182            "81df87a2241d1ad9"
183        );
184    }
185}