1pub mod mapping;
2
3pub use mapping::{apply_after_stat, resolve_mappings};
4
5#[derive(Clone, Debug, PartialEq, Eq, Hash)]
7pub enum Aesthetic {
8 X,
9 Y,
10 Color,
11 Fill,
12 Size,
13 Shape,
14 Alpha,
15 Linetype,
16 Group,
17 Ymin,
18 Ymax,
19 Xmin,
20 Xmax,
21 Label,
22 Weight,
23 Xend,
24 Yend,
25 Angle,
26 Radius,
27}
28
29impl Aesthetic {
30 pub fn col_name(&self) -> &str {
32 match self {
33 Aesthetic::X => "x",
34 Aesthetic::Y => "y",
35 Aesthetic::Color => "color",
36 Aesthetic::Fill => "fill",
37 Aesthetic::Size => "size",
38 Aesthetic::Shape => "shape",
39 Aesthetic::Alpha => "alpha",
40 Aesthetic::Linetype => "linetype",
41 Aesthetic::Group => "group",
42 Aesthetic::Ymin => "ymin",
43 Aesthetic::Ymax => "ymax",
44 Aesthetic::Xmin => "xmin",
45 Aesthetic::Xmax => "xmax",
46 Aesthetic::Label => "label",
47 Aesthetic::Weight => "weight",
48 Aesthetic::Xend => "xend",
49 Aesthetic::Yend => "yend",
50 Aesthetic::Angle => "angle",
51 Aesthetic::Radius => "radius",
52 }
53 }
54}
55
56#[derive(Clone, Debug, PartialEq)]
58pub enum MappingStage {
59 BeforeStat,
61 AfterStat,
63}
64
65#[derive(Clone, Debug)]
67pub struct AesMapping {
68 pub column: String,
69 pub aesthetic: Aesthetic,
70 pub stage: MappingStage,
71}
72
73#[derive(Clone, Debug, Default)]
75pub struct Aes {
76 pub mappings: Vec<AesMapping>,
77}
78
79impl Aes {
80 pub fn new() -> Self {
81 Self::default()
82 }
83
84 fn push(mut self, col: &str, aesthetic: Aesthetic) -> Self {
85 self.mappings.push(AesMapping {
86 column: col.to_string(),
87 aesthetic,
88 stage: MappingStage::BeforeStat,
89 });
90 self
91 }
92
93 fn push_after_stat(mut self, col: &str, aesthetic: Aesthetic) -> Self {
94 self.mappings.push(AesMapping {
95 column: col.to_string(),
96 aesthetic,
97 stage: MappingStage::AfterStat,
98 });
99 self
100 }
101
102 pub fn x(self, col: &str) -> Self {
103 self.push(col, Aesthetic::X)
104 }
105 pub fn y(self, col: &str) -> Self {
106 self.push(col, Aesthetic::Y)
107 }
108 pub fn color(self, col: &str) -> Self {
109 self.push(col, Aesthetic::Color)
110 }
111 pub fn fill(self, col: &str) -> Self {
112 self.push(col, Aesthetic::Fill)
113 }
114 pub fn size(self, col: &str) -> Self {
115 self.push(col, Aesthetic::Size)
116 }
117 pub fn shape(self, col: &str) -> Self {
118 self.push(col, Aesthetic::Shape)
119 }
120 pub fn alpha(self, col: &str) -> Self {
121 self.push(col, Aesthetic::Alpha)
122 }
123 pub fn group(self, col: &str) -> Self {
124 self.push(col, Aesthetic::Group)
125 }
126 pub fn ymin(self, col: &str) -> Self {
127 self.push(col, Aesthetic::Ymin)
128 }
129 pub fn ymax(self, col: &str) -> Self {
130 self.push(col, Aesthetic::Ymax)
131 }
132 pub fn label(self, col: &str) -> Self {
133 self.push(col, Aesthetic::Label)
134 }
135 pub fn weight(self, col: &str) -> Self {
136 self.push(col, Aesthetic::Weight)
137 }
138 pub fn xend(self, col: &str) -> Self {
139 self.push(col, Aesthetic::Xend)
140 }
141 pub fn yend(self, col: &str) -> Self {
142 self.push(col, Aesthetic::Yend)
143 }
144 pub fn xmin(self, col: &str) -> Self {
145 self.push(col, Aesthetic::Xmin)
146 }
147 pub fn xmax(self, col: &str) -> Self {
148 self.push(col, Aesthetic::Xmax)
149 }
150 pub fn angle(self, col: &str) -> Self {
151 self.push(col, Aesthetic::Angle)
152 }
153 pub fn radius(self, col: &str) -> Self {
154 self.push(col, Aesthetic::Radius)
155 }
156 pub fn linetype(self, col: &str) -> Self {
157 self.push(col, Aesthetic::Linetype)
158 }
159
160 pub fn after_stat_y(self, col: &str) -> Self {
166 self.push_after_stat(col, Aesthetic::Y)
167 }
168
169 pub fn after_stat_x(self, col: &str) -> Self {
171 self.push_after_stat(col, Aesthetic::X)
172 }
173
174 pub fn after_stat_fill(self, col: &str) -> Self {
176 self.push_after_stat(col, Aesthetic::Fill)
177 }
178
179 pub fn after_stat_color(self, col: &str) -> Self {
181 self.push_after_stat(col, Aesthetic::Color)
182 }
183
184 pub fn after_stat_size(self, col: &str) -> Self {
186 self.push_after_stat(col, Aesthetic::Size)
187 }
188
189 pub fn after_stat_alpha(self, col: &str) -> Self {
191 self.push_after_stat(col, Aesthetic::Alpha)
192 }
193
194 pub fn get_mapping(&self, aes: &Aesthetic) -> Option<&str> {
196 self.mappings
197 .iter()
198 .find(|m| m.aesthetic == *aes)
199 .map(|m| m.column.as_str())
200 }
201
202 pub fn merge(&self, other: &Aes) -> Aes {
204 let mut result = self.clone();
205 for m in &other.mappings {
206 result
208 .mappings
209 .retain(|existing| existing.aesthetic != m.aesthetic);
210 result.mappings.push(m.clone());
211 }
212 result
213 }
214}