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