Skip to main content

luaur_common/methods/
variant_get_if_variant.rs

1use crate::records::variant::{
2    Variant1, Variant2, Variant3, Variant4, Variant5, Variant6, Variant7,
3};
4
5pub fn variant_get_if() {
6    // This file should not contain shared logic; the real translation is provided
7    // via the per-arity `get_if` methods generated below.
8    // The C++ method:
9    //   template<typename T>
10    //   const T* get_if() const
11    // maps to returning `Option<&T>` / `Option<&mut T>` in the Rust port.
12    // However, per the schedule, this specific one-shot item is the `const T*` version,
13    // so we return `Option<&T>`.
14}
15
16/// Returns `Some(&T)` if the active alternative has type `T`, else `None`.
17impl<T0: 'static> Variant1<T0> {
18    pub fn get_if<T: 'static>(&self) -> Option<&T> {
19        let tid = Self::get_type_id::<T>();
20        if tid < 0 {
21            return None;
22        }
23
24        if self.index() as i32 == tid {
25            // SAFETY:
26            // - In this port, VariantN stores the active alternative as a real value inside the enum.
27            // - `get_type_id::<T>()` guarantees the active variant matches `T`.
28            // - We can safely take a reference to the correct payload.
29            if tid == 0 {
30                self.get_if_0().and_then(|v| {
31                    let r: &T = unsafe { &*(v as *const T0 as *const T) };
32                    Some(r)
33                })
34            } else {
35                None
36            }
37        } else {
38            None
39        }
40    }
41}
42
43/// Returns `Some(&T)` if the active alternative has type `T`, else `None`.
44impl<T0: 'static, T1: 'static> Variant2<T0, T1> {
45    pub fn get_if<T: 'static>(&self) -> Option<&T> {
46        let tid = Self::get_type_id::<T>();
47        if tid < 0 {
48            return None;
49        }
50
51        if self.index() as i32 == tid {
52            match tid {
53                0 => self.get_if_0().and_then(|v0| {
54                    let r: &T = unsafe { &*(v0 as *const T0 as *const T) };
55                    Some(r)
56                }),
57                1 => self.get_if_1().and_then(|v1| {
58                    let r: &T = unsafe { &*(v1 as *const T1 as *const T) };
59                    Some(r)
60                }),
61                _ => None,
62            }
63        } else {
64            None
65        }
66    }
67}
68
69/// Returns `Some(&T)` if the active alternative has type `T`, else `None`.
70impl<T0: 'static, T1: 'static, T2: 'static> Variant3<T0, T1, T2> {
71    pub fn get_if<T: 'static>(&self) -> Option<&T> {
72        let tid = Self::get_type_id::<T>();
73        if tid < 0 {
74            return None;
75        }
76
77        if self.index() as i32 == tid {
78            match tid {
79                0 => self.get_if_0().and_then(|v0| {
80                    let r: &T = unsafe { &*(v0 as *const T0 as *const T) };
81                    Some(r)
82                }),
83                1 => self.get_if_1().and_then(|v1| {
84                    let r: &T = unsafe { &*(v1 as *const T1 as *const T) };
85                    Some(r)
86                }),
87                2 => self.get_if_2().and_then(|v2| {
88                    let r: &T = unsafe { &*(v2 as *const T2 as *const T) };
89                    Some(r)
90                }),
91                _ => None,
92            }
93        } else {
94            None
95        }
96    }
97}
98
99/// Returns `Some(&T)` if the active alternative has type `T`, else `None`.
100impl<T0: 'static, T1: 'static, T2: 'static, T3: 'static> Variant4<T0, T1, T2, T3> {
101    pub fn get_if<T: 'static>(&self) -> Option<&T> {
102        let tid = Self::get_type_id::<T>();
103        if tid < 0 {
104            return None;
105        }
106
107        if self.index() as i32 == tid {
108            match tid {
109                0 => self.get_if_0().and_then(|v0| {
110                    let r: &T = unsafe { &*(v0 as *const T0 as *const T) };
111                    Some(r)
112                }),
113                1 => self.get_if_1().and_then(|v1| {
114                    let r: &T = unsafe { &*(v1 as *const T1 as *const T) };
115                    Some(r)
116                }),
117                2 => self.get_if_2().and_then(|v2| {
118                    let r: &T = unsafe { &*(v2 as *const T2 as *const T) };
119                    Some(r)
120                }),
121                3 => self.get_if_3().and_then(|v3| {
122                    let r: &T = unsafe { &*(v3 as *const T3 as *const T) };
123                    Some(r)
124                }),
125                _ => None,
126            }
127        } else {
128            None
129        }
130    }
131}
132
133/// Returns `Some(&T)` if the active alternative has type `T`, else `None`.
134impl<T0: 'static, T1: 'static, T2: 'static, T3: 'static, T4: 'static> Variant5<T0, T1, T2, T3, T4> {
135    pub fn get_if<T: 'static>(&self) -> Option<&T> {
136        let tid = Self::get_type_id::<T>();
137        if tid < 0 {
138            return None;
139        }
140
141        if self.index() as i32 == tid {
142            match tid {
143                0 => self.get_if_0().and_then(|v0| {
144                    let r: &T = unsafe { &*(v0 as *const T0 as *const T) };
145                    Some(r)
146                }),
147                1 => self.get_if_1().and_then(|v1| {
148                    let r: &T = unsafe { &*(v1 as *const T1 as *const T) };
149                    Some(r)
150                }),
151                2 => self.get_if_2().and_then(|v2| {
152                    let r: &T = unsafe { &*(v2 as *const T2 as *const T) };
153                    Some(r)
154                }),
155                3 => self.get_if_3().and_then(|v3| {
156                    let r: &T = unsafe { &*(v3 as *const T3 as *const T) };
157                    Some(r)
158                }),
159                4 => self.get_if_4().and_then(|v4| {
160                    let r: &T = unsafe { &*(v4 as *const T4 as *const T) };
161                    Some(r)
162                }),
163                _ => None,
164            }
165        } else {
166            None
167        }
168    }
169}
170
171/// Returns `Some(&T)` if the active alternative has type `T`, else `None`.
172impl<T0: 'static, T1: 'static, T2: 'static, T3: 'static, T4: 'static, T5: 'static>
173    Variant6<T0, T1, T2, T3, T4, T5>
174{
175    pub fn get_if<T: 'static>(&self) -> Option<&T> {
176        let tid = Self::get_type_id::<T>();
177        if tid < 0 {
178            return None;
179        }
180
181        if self.index() as i32 == tid {
182            match tid {
183                0 => self.get_if_0().and_then(|v0| {
184                    let r: &T = unsafe { &*(v0 as *const T0 as *const T) };
185                    Some(r)
186                }),
187                1 => self.get_if_1().and_then(|v1| {
188                    let r: &T = unsafe { &*(v1 as *const T1 as *const T) };
189                    Some(r)
190                }),
191                2 => self.get_if_2().and_then(|v2| {
192                    let r: &T = unsafe { &*(v2 as *const T2 as *const T) };
193                    Some(r)
194                }),
195                3 => self.get_if_3().and_then(|v3| {
196                    let r: &T = unsafe { &*(v3 as *const T3 as *const T) };
197                    Some(r)
198                }),
199                4 => self.get_if_4().and_then(|v4| {
200                    let r: &T = unsafe { &*(v4 as *const T4 as *const T) };
201                    Some(r)
202                }),
203                5 => self.get_if_5().and_then(|v5| {
204                    let r: &T = unsafe { &*(v5 as *const T5 as *const T) };
205                    Some(r)
206                }),
207                _ => None,
208            }
209        } else {
210            None
211        }
212    }
213}
214
215/// Returns `Some(&T)` if the active alternative has type `T`, else `None`.
216impl<T0: 'static, T1: 'static, T2: 'static, T3: 'static, T4: 'static, T5: 'static, T6: 'static>
217    Variant7<T0, T1, T2, T3, T4, T5, T6>
218{
219    pub fn get_if<T: 'static>(&self) -> Option<&T> {
220        let tid = Self::get_type_id::<T>();
221        if tid < 0 {
222            return None;
223        }
224
225        if self.index() as i32 == tid {
226            match tid {
227                0 => self.get_if_0().and_then(|v0| {
228                    let r: &T = unsafe { &*(v0 as *const T0 as *const T) };
229                    Some(r)
230                }),
231                1 => self.get_if_1().and_then(|v1| {
232                    let r: &T = unsafe { &*(v1 as *const T1 as *const T) };
233                    Some(r)
234                }),
235                2 => self.get_if_2().and_then(|v2| {
236                    let r: &T = unsafe { &*(v2 as *const T2 as *const T) };
237                    Some(r)
238                }),
239                3 => self.get_if_3().and_then(|v3| {
240                    let r: &T = unsafe { &*(v3 as *const T3 as *const T) };
241                    Some(r)
242                }),
243                4 => self.get_if_4().and_then(|v4| {
244                    let r: &T = unsafe { &*(v4 as *const T4 as *const T) };
245                    Some(r)
246                }),
247                5 => self.get_if_5().and_then(|v5| {
248                    let r: &T = unsafe { &*(v5 as *const T5 as *const T) };
249                    Some(r)
250                }),
251                6 => self.get_if_6().and_then(|v6| {
252                    let r: &T = unsafe { &*(v6 as *const T6 as *const T) };
253                    Some(r)
254                }),
255                _ => None,
256            }
257        } else {
258            None
259        }
260    }
261}