Skip to main content

rmux_sdk/snapshot/
color.rs

1use serde::{Deserialize, Serialize};
2
3/// Color encoding carried by a captured pane cell.
4#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
5#[non_exhaustive]
6pub enum PaneColor {
7    /// Terminal default color sentinel.
8    #[default]
9    Default,
10    /// Explicit no-color sentinel.
11    None,
12    /// Terminal color sentinel.
13    Terminal,
14    /// Standard ANSI color value `0..=7`.
15    Ansi {
16        /// Standard ANSI palette index.
17        index: u8,
18    },
19    /// Bright ANSI color value `90..=97`.
20    BrightAnsi {
21        /// Bright ANSI palette index.
22        index: u8,
23    },
24    /// 256-color palette value encoded with the RMUX/tmux 256-color flag.
25    Indexed {
26        /// 256-color palette index.
27        index: u8,
28    },
29    /// True-color RGB value encoded with the RMUX/tmux RGB flag.
30    Rgb {
31        /// Red component.
32        red: u8,
33        /// Green component.
34        green: u8,
35        /// Blue component.
36        blue: u8,
37    },
38    /// Unknown or future raw color encoding.
39    Encoded {
40        /// Raw encoded color value.
41        value: i32,
42    },
43}
44
45impl PaneColor {
46    /// Raw encoding for the terminal default color.
47    pub const DEFAULT_ENCODING: i32 = 8;
48    /// Raw encoding for the explicit no-color sentinel.
49    pub const NONE_ENCODING: i32 = -1;
50    /// Raw encoding for the terminal color sentinel.
51    pub const TERMINAL_ENCODING: i32 = 9;
52    /// Raw flag for 256-color palette values.
53    pub const INDEXED_FLAG: i32 = 0x0100_0000;
54    /// Raw flag for true-color RGB values.
55    pub const RGB_FLAG: i32 = 0x0200_0000;
56
57    /// Creates a standard ANSI color value.
58    #[must_use]
59    pub const fn ansi(index: u8) -> Self {
60        Self::Ansi { index }
61    }
62
63    /// Creates a bright ANSI color value.
64    #[must_use]
65    pub const fn bright_ansi(index: u8) -> Self {
66        Self::BrightAnsi { index }
67    }
68
69    /// Creates a 256-color palette value.
70    #[must_use]
71    pub const fn indexed(index: u8) -> Self {
72        Self::Indexed { index }
73    }
74
75    /// Creates an RGB true-color value.
76    #[must_use]
77    pub const fn rgb(red: u8, green: u8, blue: u8) -> Self {
78        Self::Rgb { red, green, blue }
79    }
80
81    /// Creates a color DTO from a raw RMUX/tmux-compatible encoding.
82    #[must_use]
83    pub fn from_encoded(value: i32) -> Self {
84        match value {
85            Self::NONE_ENCODING => Self::None,
86            Self::DEFAULT_ENCODING => Self::Default,
87            Self::TERMINAL_ENCODING => Self::Terminal,
88            0..=7 => Self::Ansi { index: value as u8 },
89            90..=97 => Self::BrightAnsi {
90                index: (value - 90) as u8,
91            },
92            _ if value & !(Self::INDEXED_FLAG | 0xff) == 0 && value & Self::INDEXED_FLAG != 0 => {
93                Self::Indexed {
94                    index: (value & 0xff) as u8,
95                }
96            }
97            _ if value & !(Self::RGB_FLAG | 0x00ff_ffff) == 0 && value & Self::RGB_FLAG != 0 => {
98                Self::Rgb {
99                    red: ((value >> 16) & 0xff) as u8,
100                    green: ((value >> 8) & 0xff) as u8,
101                    blue: (value & 0xff) as u8,
102                }
103            }
104            _ => Self::Encoded { value },
105        }
106    }
107
108    /// Returns the raw RMUX/tmux-compatible color encoding.
109    #[must_use]
110    pub const fn encoded(self) -> i32 {
111        match self {
112            Self::Default => Self::DEFAULT_ENCODING,
113            Self::None => Self::NONE_ENCODING,
114            Self::Terminal => Self::TERMINAL_ENCODING,
115            Self::Ansi { index } => index as i32,
116            Self::BrightAnsi { index } => 90 + index as i32,
117            Self::Indexed { index } => Self::INDEXED_FLAG | index as i32,
118            Self::Rgb { red, green, blue } => {
119                Self::RGB_FLAG | ((red as i32) << 16) | ((green as i32) << 8) | blue as i32
120            }
121            Self::Encoded { value } => value,
122        }
123    }
124}