1use crate::{AngularMomentum, Charge, Isospin, Parity, ParticleClass, ParticleType};
2
3#[derive(Clone, Debug, Default)]
25pub struct ParticleSearchQuery {
26 pub(crate) name_contains: Option<String>,
27 pub(crate) particle_class: Option<ParticleClass>,
28 pub(crate) particle_type: Option<ParticleType>,
29 pub(crate) charge: Option<Charge>,
30 pub(crate) isospin: QuantumFilter<Isospin>,
31 pub(crate) g_parity: QuantumFilter<Parity>,
32 pub(crate) angular_momentum: QuantumFilter<AngularMomentum>,
33 pub(crate) parity: QuantumFilter<Parity>,
34 pub(crate) charge_conjugation: QuantumFilter<Parity>,
35 pub(crate) mass_range_mev: Option<(f64, f64)>,
36 pub(crate) width_range_mev: Option<(f64, f64)>,
37 pub(crate) lifetime_range_seconds: Option<(f64, f64)>,
38 pub(crate) decays_to: DecayFilter,
39 pub(crate) decays_from: Vec<String>,
40 pub(crate) decay_state_expansion: DecayStateExpansion,
41}
42
43#[derive(Clone, Debug, Default)]
44pub struct DecayFilter {
45 pub(crate) states: Vec<String>,
46 pub(crate) mode: DecayMatchMode,
47}
48
49#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
51pub enum DecayMatchMode {
52 #[default]
54 Exact,
55 Contains,
57}
58
59#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
61pub enum DecayStateExpansion {
62 #[default]
64 Inclusive,
65 Literal,
67}
68
69#[derive(Clone, Debug, Default)]
71pub enum QuantumFilter<T> {
72 #[default]
74 Any,
75 Missing,
77 Value(T),
79}
80
81impl ParticleSearchQuery {
82 #[must_use]
84 pub fn new() -> Self {
85 Self::default()
86 }
87
88 #[must_use]
90 pub fn name_contains(mut self, value: impl Into<String>) -> Self {
91 self.name_contains = Some(value.into());
92 self
93 }
94
95 #[must_use]
97 pub const fn class(mut self, particle_class: ParticleClass) -> Self {
98 self.particle_class = Some(particle_class);
99 self
100 }
101
102 #[must_use]
104 pub const fn particle_type(mut self, particle_type: ParticleType) -> Self {
105 self.particle_type = Some(particle_type);
106 self
107 }
108
109 #[must_use]
111 pub const fn charge(mut self, charge: Charge) -> Self {
112 self.charge = Some(charge);
113 self
114 }
115
116 #[must_use]
120 pub fn isospin(mut self, isospin: impl Into<Option<Isospin>>) -> Self {
121 self.isospin = quantum_filter(isospin);
122 self
123 }
124
125 #[must_use]
129 pub fn g_parity(mut self, g_parity: impl Into<Option<Parity>>) -> Self {
130 self.g_parity = quantum_filter(g_parity);
131 self
132 }
133
134 #[must_use]
138 pub fn angular_momentum(
139 mut self,
140 angular_momentum: impl Into<Option<AngularMomentum>>,
141 ) -> Self {
142 self.angular_momentum = quantum_filter(angular_momentum);
143 self
144 }
145
146 #[must_use]
150 pub fn parity(mut self, parity: impl Into<Option<Parity>>) -> Self {
151 self.parity = quantum_filter(parity);
152 self
153 }
154
155 #[must_use]
159 pub fn charge_conjugation(mut self, charge_conjugation: impl Into<Option<Parity>>) -> Self {
160 self.charge_conjugation = quantum_filter(charge_conjugation);
161 self
162 }
163
164 #[must_use]
166 pub const fn mass_range_mev(mut self, min: f64, max: f64) -> Self {
167 self.mass_range_mev = Some((min, max));
168 self
169 }
170
171 #[must_use]
173 pub const fn width_range_mev(mut self, min: f64, max: f64) -> Self {
174 self.width_range_mev = Some((min, max));
175 self
176 }
177
178 #[must_use]
180 pub const fn lifetime_range_seconds(mut self, min: f64, max: f64) -> Self {
181 self.lifetime_range_seconds = Some((min, max));
182 self
183 }
184
185 #[must_use]
190 pub fn decays_to<I, S>(mut self, states: I) -> Self
191 where
192 I: IntoIterator<Item = S>,
193 S: Into<String>,
194 {
195 self.decays_to = DecayFilter {
196 states: states.into_iter().map(Into::into).collect(),
197 mode: DecayMatchMode::Exact,
198 };
199 self
200 }
201
202 #[must_use]
204 pub fn decay_contains<I, S>(mut self, states: I) -> Self
205 where
206 I: IntoIterator<Item = S>,
207 S: Into<String>,
208 {
209 self.decays_to = DecayFilter {
210 states: states.into_iter().map(Into::into).collect(),
211 mode: DecayMatchMode::Contains,
212 };
213 self
214 }
215
216 #[must_use]
218 pub fn decays_from<I, S>(mut self, states: I) -> Self
219 where
220 I: IntoIterator<Item = S>,
221 S: Into<String>,
222 {
223 self.decays_from = states.into_iter().map(Into::into).collect();
224 self
225 }
226
227 #[must_use]
229 pub const fn decay_state_expansion(mut self, expansion: DecayStateExpansion) -> Self {
230 self.decay_state_expansion = expansion;
231 self
232 }
233}
234
235fn quantum_filter<T>(filter: impl Into<Option<T>>) -> QuantumFilter<T> {
236 filter.into().map_or_else(
237 || QuantumFilter::Missing,
238 |value| QuantumFilter::Value(value),
239 )
240}