rosu_map/section/colors/
mod.rs

1use std::{
2    ops::{Index, IndexMut},
3    str::FromStr,
4};
5
6pub use self::decode::{Colors, ColorsKey, ColorsState, ParseColorsError};
7
8pub(crate) mod decode; // pub(crate) for intradoc-links
9
10/// Basic RGBA color.
11#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
12pub struct Color(pub [u8; 4]);
13
14impl Color {
15    /// Initialize a new color.
16    pub const fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
17        Self([r, g, b, a])
18    }
19
20    /// Get the red value.
21    pub fn red(self) -> u8 {
22        self[0]
23    }
24
25    /// Get the green value.
26    pub fn green(self) -> u8 {
27        self[1]
28    }
29
30    /// Get the blue value.
31    pub fn blue(self) -> u8 {
32        self[2]
33    }
34
35    /// Get the alpha value.
36    pub fn alpha(self) -> u8 {
37        self[3]
38    }
39}
40
41impl Index<usize> for Color {
42    type Output = u8;
43
44    fn index(&self, index: usize) -> &Self::Output {
45        &self.0[index]
46    }
47}
48
49impl IndexMut<usize> for Color {
50    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
51        &mut self.0[index]
52    }
53}
54
55impl From<[u8; 4]> for Color {
56    fn from(color: [u8; 4]) -> Self {
57        Self(color)
58    }
59}
60
61impl FromStr for Color {
62    type Err = ParseColorsError;
63
64    #[allow(clippy::many_single_char_names)]
65    fn from_str(s: &str) -> Result<Self, Self::Err> {
66        let mut split = s.split(',').map(str::trim);
67
68        let r = split.next();
69        let g = split.next();
70        let b = split.next();
71        let none = split.nth(1);
72
73        let (Some(r), Some(g), Some(b), None) = (r, g, b, none) else {
74            return Err(ParseColorsError::IncorrectColor);
75        };
76
77        Ok(Self::new(r.parse()?, g.parse()?, b.parse()?, 255))
78    }
79}
80
81/// A combination of a [`Color`] and a name.
82#[derive(Clone, Debug, Default, PartialEq, Eq)]
83pub struct CustomColor {
84    pub name: String,
85    pub color: Color,
86}