1use crate::attrs::{AttrKey, AttrVal};
2
3pub trait MutatorDescriptor {
5 fn get_description_attributes(&self) -> Box<dyn Iterator<Item = (AttrKey, AttrVal)> + '_>;
8}
9
10pub mod owned {
11 use attrs::AttrType;
12
13 use super::*;
14 use crate::params_attributes::{
15 is_valid_param_key, MUTATOR_PARAMS_DEFAULT_VALUE_SUFFIX, MUTATOR_PARAMS_DESCRIPTION_SUFFIX,
16 MUTATOR_PARAMS_LEAST_EFFECT_VALUE_SUFFIX, MUTATOR_PARAMS_NAME_SUFFIX,
17 MUTATOR_PARAMS_PREFIX, MUTATOR_PARAMS_VALUE_DISTRIBUTION_KIND_SUFFIX,
18 MUTATOR_PARAMS_VALUE_DISTRIBUTION_OPTION_SET_INTERFIX,
19 MUTATOR_PARAMS_VALUE_DISTRIBUTION_SCALING_SUFFIX, MUTATOR_PARAMS_VALUE_MAX_SUFFIX,
20 MUTATOR_PARAMS_VALUE_MIN_SUFFIX, MUTATOR_PARAMS_VALUE_TYPE_SUFFIX,
21 };
22 use crate::{attrs, params_attributes::is_valid_single_key_segment_contents};
23 use std::collections::{BTreeMap, HashMap};
24
25 #[derive(Debug, Clone)]
26 pub struct OwnedMutatorDescriptor {
27 pub name: Option<String>,
28 pub description: Option<String>,
29 pub layer: Option<MutatorLayer>,
30 pub group: Option<String>,
31 pub operation: Option<MutatorOperation>,
32 pub statefulness: Option<MutatorStatefulness>,
33 pub organization_custom_metadata: Option<OrganizationCustomMetadata>,
34 pub params: Vec<OwnedMutatorParamDescriptor>,
36 }
37
38 impl OwnedMutatorDescriptor {
39 pub fn into_description_attributes(
40 self,
41 ) -> Box<dyn Iterator<Item = (AttrKey, AttrVal)> + 'static> {
42 let mut all_mutator_attrs: Vec<(AttrKey, AttrVal)> = vec![];
43 if let Some(mutator_name) = self.name.as_ref() {
44 all_mutator_attrs.push((attrs::mutator::NAME, mutator_name.into()))
45 }
46 if let Some(mutator_description) = self.description.as_ref() {
47 all_mutator_attrs.push((attrs::mutator::DESCRIPTION, mutator_description.into()))
48 }
49 if let Some(mutator_layer) = self.layer.as_ref() {
50 all_mutator_attrs.push((attrs::mutator::LAYER, mutator_layer.name().into()))
51 }
52 if let Some(mutator_group) = self.group.as_ref() {
53 all_mutator_attrs.push((attrs::mutator::GROUP, mutator_group.into()))
54 }
55 if let Some(mutator_operation) = self.operation.as_ref() {
56 all_mutator_attrs.push((attrs::mutator::OPERATION, mutator_operation.name().into()))
57 }
58 if let Some(organization_custom_metadata) = self.organization_custom_metadata.as_ref() {
59 let mut mutator_level_custom_metadata_prefix = "mutator.".to_string();
60 mutator_level_custom_metadata_prefix.push_str(
61 organization_custom_metadata
62 .organization_name_segment
63 .as_str(),
64 );
65 mutator_level_custom_metadata_prefix.push('.');
66 for (k, v) in organization_custom_metadata.attributes.iter() {
67 all_mutator_attrs.push((
68 AttrKey::from(format!("{mutator_level_custom_metadata_prefix}{k}")),
69 v.clone(),
70 ));
71 }
72 }
73
74 for param in &self.params {
75 all_mutator_attrs.extend(param.mutator_params_param_key_prefixed_attributes());
76 }
77
78 Box::new(all_mutator_attrs.into_iter())
79 }
80
81 pub fn try_from_description_attributes(
82 i: impl Iterator<Item = (AttrKey, AttrVal)>,
83 ) -> Result<Self, ParamDescriptorFromAttrsError> {
84 let mut attrs_map: BTreeMap<AttrKey, AttrVal> = i.collect();
85 let mut d = OwnedMutatorDescriptor {
86 name: None,
87 description: None,
88 layer: None,
89 group: None,
90 operation: None,
91 statefulness: None,
92 organization_custom_metadata: None,
93 params: vec![],
94 };
95 if let Some(AttrVal::String(s)) = attrs_map.remove(&attrs::mutator::NAME) {
96 d.name = Some(s.to_string());
97 }
98 if let Some(AttrVal::String(s)) = attrs_map.remove(&attrs::mutator::DESCRIPTION) {
99 d.description = Some(s.to_string());
100 }
101 if let Some(AttrVal::String(s)) = attrs_map.remove(&attrs::mutator::GROUP) {
102 d.group = Some(s.to_string());
103 }
104 if let Some(AttrVal::String(s)) = attrs_map.remove(&attrs::mutator::LAYER) {
105 d.layer = match s.as_ref() {
106 "implementational" => Some(MutatorLayer::Implementational),
107 "operational" => Some(MutatorLayer::Operational),
108 "environmental" => Some(MutatorLayer::Environmental),
109 _ => None,
110 };
111 }
112 if let Some(AttrVal::String(s)) = attrs_map.remove(&attrs::mutator::OPERATION) {
113 d.operation = match s.as_ref() {
114 "delay" => Some(MutatorOperation::Delay),
115 "duplicate" => Some(MutatorOperation::Duplicate),
116 "drop_fraction" => Some(MutatorOperation::DropFraction),
117 "drop_positional" => Some(MutatorOperation::DropPositional),
118 "disable" => Some(MutatorOperation::Disable),
119 "enable" => Some(MutatorOperation::Enable),
120 "corrupt" => Some(MutatorOperation::Corrupt),
121 "set_to_value" => Some(MutatorOperation::SetToValue),
122 "substitute_next_value" => Some(MutatorOperation::SubstituteNextValue),
123 "reorder" => Some(MutatorOperation::Reorder),
124 "stimulate" => Some(MutatorOperation::Stimulate),
125 _ => None,
126 };
127 }
128 if let Some(AttrVal::String(s)) = attrs_map.remove(&attrs::mutator::STATEFULNESS) {
129 d.statefulness = match s.as_ref() {
130 "permanent" => Some(MutatorStatefulness::Permanent),
131 "intermittent" => Some(MutatorStatefulness::Intermittent),
132 "transient" => Some(MutatorStatefulness::Transient),
133 _ => None,
134 };
135 }
136 let _ = attrs_map.remove(&attrs::mutator::ID);
137 let _ = attrs_map.remove(&attrs::mutator::SOURCE_FILE);
140 let _ = attrs_map.remove(&attrs::mutator::SOURCE_LINE);
141 let _ = attrs_map.remove(&attrs::mutator::SAFETY);
142
143 let mut custom_bucket: BTreeMap<AttrKey, AttrVal> = Default::default();
144 let mut param_key_to_pairs: BTreeMap<String, BTreeMap<AttrKey, AttrVal>> =
145 Default::default();
146 for (k, v) in attrs_map {
147 if let Some(rest) = k.as_ref().strip_prefix(MUTATOR_PARAMS_PREFIX) {
148 if let Some((key, _post_key)) = rest.split_once('.') {
149 let post_key_pairs = param_key_to_pairs.entry(key.to_string()).or_default();
150 post_key_pairs.insert(k, v);
151 } else {
152 }
154 } else {
155 custom_bucket.insert(k, v);
156 }
157 }
158 for (pk, pairs) in param_key_to_pairs {
159 d.params.push(
160 OwnedMutatorParamDescriptor::try_from_param_key_and_attributes(pk, pairs)?,
161 )
162 }
163
164 Ok(d)
167 }
168 }
169 #[derive(Debug, thiserror::Error, Eq, PartialEq)]
170 pub enum ParamDescriptorFromAttrsError {
171 #[error("Missing the `mutator.params.<param-key>.name` attribute")]
172 MissingParameterNameAttribute,
173 #[error("Missing the `mutator.params.<param-key>.value_type` attribute")]
174 MissingValueTypeAttribute,
175 #[error("Invalid parameter key. Parameter keys must be ASCII with no periods.")]
176 InvalidParameterKey,
177 }
178
179 impl MutatorDescriptor for OwnedMutatorDescriptor {
180 fn get_description_attributes(&self) -> Box<dyn Iterator<Item = (AttrKey, AttrVal)> + '_> {
181 let mut all_mutator_attrs: Vec<(AttrKey, AttrVal)> = vec![];
182 if let Some(mutator_name) = self.name.as_ref() {
183 all_mutator_attrs.push((attrs::mutator::NAME, mutator_name.into()))
184 }
185 if let Some(mutator_description) = self.description.as_ref() {
186 all_mutator_attrs.push((attrs::mutator::DESCRIPTION, mutator_description.into()))
187 }
188 if let Some(mutator_layer) = self.layer.as_ref() {
189 all_mutator_attrs.push((attrs::mutator::LAYER, mutator_layer.name().into()))
190 }
191 if let Some(mutator_group) = self.group.as_ref() {
192 all_mutator_attrs.push((attrs::mutator::GROUP, mutator_group.into()))
193 }
194 if let Some(mutator_operation) = self.operation.as_ref() {
195 all_mutator_attrs.push((attrs::mutator::OPERATION, mutator_operation.name().into()))
196 }
197 if let Some(organization_custom_metadata) = self.organization_custom_metadata.as_ref() {
198 let mut mutator_level_custom_metadata_prefix = "mutator.".to_string();
199 mutator_level_custom_metadata_prefix.push_str(
200 organization_custom_metadata
201 .organization_name_segment
202 .as_str(),
203 );
204 mutator_level_custom_metadata_prefix.push('.');
205 for (k, v) in organization_custom_metadata.attributes.iter() {
206 all_mutator_attrs.push((
207 AttrKey::from(format!("{mutator_level_custom_metadata_prefix}{k}")),
208 v.clone(),
209 ));
210 }
211 }
212
213 for param in &self.params {
214 all_mutator_attrs.extend(param.mutator_params_param_key_prefixed_attributes());
215 }
216
217 Box::new(all_mutator_attrs.into_iter())
218 }
219 }
220
221 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
222 pub enum MutatorLayer {
223 Implementational,
224 Operational,
225 Environmental,
226 }
227 impl MutatorLayer {
228 pub fn name(&self) -> &'static str {
229 match self {
230 MutatorLayer::Implementational => "implementational",
231 MutatorLayer::Operational => "operational",
232 MutatorLayer::Environmental => "environmental",
233 }
234 }
235 }
236 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
237 pub enum MutatorStatefulness {
238 Permanent,
240 Intermittent,
243 Transient,
246 }
247 impl MutatorStatefulness {
248 pub fn name(&self) -> &'static str {
249 match self {
250 MutatorStatefulness::Permanent => "permanent",
251 MutatorStatefulness::Intermittent => "intermittent",
252 MutatorStatefulness::Transient => "transient",
253 }
254 }
255 }
256
257 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
258 pub enum MutatorOperation {
259 Delay,
260 Duplicate,
261 DropFraction,
262 DropPositional,
263 Disable,
264 Enable,
265 Corrupt,
266 SetToValue,
267 SubstituteNextValue,
268 Reorder,
269 Stimulate,
270 }
271 impl MutatorOperation {
272 pub fn name(&self) -> &'static str {
273 match self {
274 MutatorOperation::Delay => "delay",
275 MutatorOperation::Duplicate => "duplicate",
276 MutatorOperation::DropFraction => "drop_fraction",
277 MutatorOperation::DropPositional => "drop_positional",
278 MutatorOperation::Disable => "disable",
279 MutatorOperation::Enable => "enable",
280 MutatorOperation::Corrupt => "corrupt",
281 MutatorOperation::SetToValue => "set_to_value",
282 MutatorOperation::SubstituteNextValue => "substitute_next_value",
283 MutatorOperation::Reorder => "reorder",
284 MutatorOperation::Stimulate => "stimulate",
285 }
286 }
287 }
288
289 #[derive(Debug, Clone)]
290 pub struct OrganizationCustomMetadata {
291 organization_name_segment: String,
293 pub attributes: HashMap<String, AttrVal>,
295 }
296
297 impl OrganizationCustomMetadata {
298 pub fn empty(organization_name_segment: String) -> Option<Self> {
299 if is_valid_single_key_segment_contents(organization_name_segment.as_str()) {
300 Some(OrganizationCustomMetadata {
301 organization_name_segment,
302 attributes: Default::default(),
303 })
304 } else {
305 None
306 }
307 }
308 pub fn new(
309 organization_name_segment: String,
310 attributes: HashMap<String, AttrVal>,
311 ) -> Option<Self> {
312 if is_valid_single_key_segment_contents(organization_name_segment.as_str()) {
313 Some(OrganizationCustomMetadata {
314 organization_name_segment,
315 attributes,
316 })
317 } else {
318 None
319 }
320 }
321
322 pub fn organization_name_segment(&self) -> &str {
323 self.organization_name_segment.as_str()
324 }
325 }
326
327 #[derive(Debug, Clone)]
328 pub struct OwnedMutatorParamDescriptor {
329 pub value_type: AttrType,
330 pub name: String,
333 pub description: Option<String>,
334 pub value_min: Option<AttrVal>,
335 pub value_max: Option<AttrVal>,
336 pub default_value: Option<AttrVal>,
337 pub least_effect_value: Option<AttrVal>,
338 pub value_distribution_kind: Option<ValueDistributionKind>,
339 pub value_distribution_scaling: Option<ValueDistributionScaling>,
340 pub value_distribution_option_set: Option<BTreeMap<String, AttrVal>>,
341 pub organization_custom_metadata: Option<OrganizationCustomMetadata>,
342 }
343
344 impl OwnedMutatorParamDescriptor {
345 pub(crate) fn mutator_params_param_key_prefixed_attributes(
346 &self,
347 ) -> impl Iterator<Item = (AttrKey, AttrVal)> {
348 let mut param_attrs: Vec<(AttrKey, AttrVal)> = vec![];
349 let mut param_prefix = crate::params_attributes::MUTATOR_PARAMS_PREFIX.to_string();
350 param_prefix.push_str(self.name.as_str());
351 param_attrs.push((
353 AttrKey::from(format!(
354 "{param_prefix}{}",
355 crate::params_attributes::MUTATOR_PARAMS_NAME_SUFFIX
356 )),
357 self.name.as_str().into(),
358 ));
359 param_attrs.push((
360 AttrKey::from(format!(
361 "{param_prefix}{}",
362 crate::params_attributes::MUTATOR_PARAMS_VALUE_TYPE_SUFFIX
363 )),
364 self.value_type.to_string().into(),
365 ));
366
367 if let Some(param_description) = self.description.as_ref() {
368 param_attrs.push((
369 AttrKey::from(format!(
370 "{param_prefix}{}",
371 crate::params_attributes::MUTATOR_PARAMS_DESCRIPTION_SUFFIX
372 )),
373 param_description.into(),
374 ));
375 }
376 if let Some(value_min) = self.value_min.as_ref() {
377 param_attrs.push((
378 AttrKey::from(format!(
379 "{param_prefix}{}",
380 crate::params_attributes::MUTATOR_PARAMS_VALUE_MIN_SUFFIX
381 )),
382 value_min.clone(),
383 ));
384 }
385 if let Some(value_max) = self.value_max.as_ref() {
386 param_attrs.push((
387 AttrKey::from(format!(
388 "{param_prefix}{}",
389 crate::params_attributes::MUTATOR_PARAMS_VALUE_MAX_SUFFIX
390 )),
391 value_max.clone(),
392 ));
393 }
394 if let Some(default_value) = self.default_value.as_ref() {
395 param_attrs.push((
396 AttrKey::from(format!(
397 "{param_prefix}{}",
398 crate::params_attributes::MUTATOR_PARAMS_DEFAULT_VALUE_SUFFIX
399 )),
400 default_value.clone(),
401 ));
402 }
403 if let Some(least_effect_value) = self.least_effect_value.as_ref() {
404 param_attrs.push((
405 AttrKey::from(format!(
406 "{param_prefix}{}",
407 crate::params_attributes::MUTATOR_PARAMS_LEAST_EFFECT_VALUE_SUFFIX
408 )),
409 least_effect_value.clone(),
410 ));
411 }
412
413 if let Some(value_distribution_kind) = self.value_distribution_kind.as_ref() {
414 param_attrs.push((
415 AttrKey::from(format!(
416 "{param_prefix}{}",
417 crate::params_attributes::MUTATOR_PARAMS_VALUE_DISTRIBUTION_KIND_SUFFIX
418 )),
419 value_distribution_kind.name().into(),
420 ));
421 }
422 if let Some(value_distribution_scaling) = self.value_distribution_scaling.as_ref() {
423 param_attrs.push((
424 AttrKey::from(format!(
425 "{param_prefix}{}",
426 crate::params_attributes::MUTATOR_PARAMS_VALUE_DISTRIBUTION_SCALING_SUFFIX
427 )),
428 value_distribution_scaling.name().into(),
429 ));
430 }
431 if let Some(option_set) = self.value_distribution_option_set.as_ref() {
432 for (option_key_segment, option_val) in option_set {
435 param_attrs.push((AttrKey::from(format!("{param_prefix}{}{}", crate::params_attributes::MUTATOR_PARAMS_VALUE_DISTRIBUTION_OPTION_SET_INTERFIX, option_key_segment)), option_val.clone()));
436 }
437 }
438
439 if let Some(organization_custom_metadata) = self.organization_custom_metadata.as_ref() {
440 let mut parameter_level_custom_metadata_prefix = param_prefix.clone();
441 parameter_level_custom_metadata_prefix.push_str(
442 organization_custom_metadata
443 .organization_name_segment
444 .as_str(),
445 );
446 parameter_level_custom_metadata_prefix.push('.');
447 for (k, v) in organization_custom_metadata.attributes.iter() {
448 param_attrs.push((
449 AttrKey::from(format!("{parameter_level_custom_metadata_prefix}{k}")),
450 v.clone(),
451 ));
452 }
453 }
454
455 param_attrs.into_iter()
456 }
457
458 pub(crate) fn try_from_param_key_and_attributes(
460 param_key: String,
461 attributes: BTreeMap<AttrKey, AttrVal>,
462 ) -> Result<Self, ParamDescriptorFromAttrsError> {
463 if !is_valid_param_key(¶m_key) {
464 return Err(ParamDescriptorFromAttrsError::InvalidParameterKey);
465 }
466 let mut value_type: Option<AttrType> = None;
467 let mut name: Option<String> = None;
468 let mut description: Option<String> = None;
469 let mut value_min: Option<AttrVal> = None;
470 let mut value_max: Option<AttrVal> = None;
471 let mut default_value: Option<AttrVal> = None;
472 let mut least_effect_value: Option<AttrVal> = None;
473 let mut value_distribution_kind: Option<ValueDistributionKind> = None;
474 let mut value_distribution_scaling: Option<ValueDistributionScaling> = None;
475 let mut value_distribution_option_set: Option<BTreeMap<String, AttrVal>> = None;
476 let organization_custom_metadata: Option<OrganizationCustomMetadata> = None;
478
479 let params_prefix = format!("mutator.params.{param_key}");
480 for (k, v) in attributes {
481 if let Some(post_key_with_period) = k.as_ref().strip_prefix(¶ms_prefix) {
482 if post_key_with_period == MUTATOR_PARAMS_NAME_SUFFIX {
483 if let AttrVal::String(s) = v {
484 name = Some(s.to_string());
485 }
486 } else if post_key_with_period == MUTATOR_PARAMS_VALUE_TYPE_SUFFIX {
487 if let AttrVal::String(s) = v {
488 value_type = match s.as_ref() {
489 "TimelineId" => Some(AttrType::TimelineId),
490 "String" => Some(AttrType::String),
491 "Integer" => Some(AttrType::Integer),
492 "BigInteger" => Some(AttrType::BigInt),
493 "Float" => Some(AttrType::Float),
494 "Bool" => Some(AttrType::Bool),
495 "Nanoseconds" => Some(AttrType::Nanoseconds),
496 "LogicalTime" => Some(AttrType::LogicalTime),
497 "Any" => Some(AttrType::Any),
498 "Coordinate" => Some(AttrType::EventCoordinate),
499 _ => None,
500 }
501 }
502 } else if post_key_with_period == MUTATOR_PARAMS_DESCRIPTION_SUFFIX {
503 if let AttrVal::String(s) = v {
504 description = Some(s.to_string());
505 }
506 } else if post_key_with_period == MUTATOR_PARAMS_VALUE_MIN_SUFFIX {
507 value_min = Some(v);
508 } else if post_key_with_period == MUTATOR_PARAMS_VALUE_MAX_SUFFIX {
509 value_max = Some(v);
510 } else if post_key_with_period == MUTATOR_PARAMS_DEFAULT_VALUE_SUFFIX {
511 default_value = Some(v);
512 } else if post_key_with_period == MUTATOR_PARAMS_LEAST_EFFECT_VALUE_SUFFIX {
513 least_effect_value = Some(v);
514 } else if post_key_with_period == MUTATOR_PARAMS_VALUE_DISTRIBUTION_KIND_SUFFIX
515 {
516 if let AttrVal::String(s) = v {
517 value_distribution_kind = match s.as_ref() {
518 "continuous" => Some(ValueDistributionKind::Continuous),
519 "discrete" => Some(ValueDistributionKind::Discrete),
520 _ => None,
521 };
522 }
523 } else if post_key_with_period
524 == MUTATOR_PARAMS_VALUE_DISTRIBUTION_SCALING_SUFFIX
525 {
526 if let AttrVal::String(s) = v {
527 value_distribution_scaling = match s.as_ref() {
528 "linear" => Some(ValueDistributionScaling::Linear),
529 "complex" => Some(ValueDistributionScaling::Complex),
530 "circular" => Some(ValueDistributionScaling::Circular),
531 _ => None,
532 };
533 }
534 } else if let Some(option_set_member_key) = post_key_with_period
535 .strip_prefix(MUTATOR_PARAMS_VALUE_DISTRIBUTION_OPTION_SET_INTERFIX)
536 {
537 let mut option_set =
538 value_distribution_option_set.take().unwrap_or_default();
539 option_set.insert(option_set_member_key.to_string(), v);
540 value_distribution_option_set = Some(option_set)
541 }
542 }
543 }
544 let d = OwnedMutatorParamDescriptor {
548 value_type: if let Some(vt) = value_type {
549 vt
550 } else {
551 return Err(ParamDescriptorFromAttrsError::MissingValueTypeAttribute);
552 },
553 name: if let Some(n) = name {
554 n
555 } else {
556 return Err(ParamDescriptorFromAttrsError::MissingParameterNameAttribute);
557 },
558 description,
559 value_min,
560 value_max,
561 default_value,
562 least_effect_value,
563 value_distribution_kind,
564 value_distribution_scaling,
565 value_distribution_option_set,
566 organization_custom_metadata,
567 };
568 Ok(d)
569 }
570 }
571
572 impl OwnedMutatorParamDescriptor {
573 pub fn new(value_type: AttrType, name: String) -> Option<Self> {
577 if is_valid_single_key_segment_contents(name.as_str()) {
578 Some(OwnedMutatorParamDescriptor {
579 value_type,
580 name,
581 description: None,
582 value_min: None,
583 value_max: None,
584 default_value: None,
585 least_effect_value: None,
586 value_distribution_kind: None,
587 value_distribution_scaling: None,
588 value_distribution_option_set: None,
589 organization_custom_metadata: None,
590 })
591 } else {
592 None
593 }
594 }
595
596 pub fn with_description(mut self, s: &str) -> Self {
597 self.description = Some(s.to_owned());
598 self
599 }
600
601 pub fn with_value_min(mut self, val: impl Into<AttrVal>) -> Self {
602 self.value_min = Some(val.into());
603 self
604 }
605
606 pub fn with_value_max(mut self, val: impl Into<AttrVal>) -> Self {
607 self.value_max = Some(val.into());
608 self
609 }
610
611 pub fn with_default_value(mut self, val: impl Into<AttrVal>) -> Self {
612 self.default_value = Some(val.into());
613 self
614 }
615
616 pub fn with_least_effect_value(mut self, val: impl Into<AttrVal>) -> Self {
617 self.least_effect_value = Some(val.into());
618 self
619 }
620
621 pub fn with_value_distribution_kind(mut self, kind: ValueDistributionKind) -> Self {
622 self.value_distribution_kind = Some(kind);
623 self
624 }
625
626 pub fn with_value_distribution_scaling(
627 mut self,
628 scaling: ValueDistributionScaling,
629 ) -> Self {
630 self.value_distribution_scaling = Some(scaling);
631 self
632 }
633
634 pub fn with_value_distribution_option(mut self, key: &str, val: AttrVal) -> Self {
635 if self.value_distribution_option_set.is_none() {
636 self.value_distribution_option_set = Some(Default::default());
637 }
638
639 self.value_distribution_option_set
640 .as_mut()
641 .unwrap()
642 .insert(key.to_owned(), val);
643
644 self
645 }
646 }
647
648 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
649 pub enum ValueDistributionKind {
650 Continuous,
651 Discrete,
652 }
653 impl ValueDistributionKind {
654 pub fn name(&self) -> &'static str {
655 match self {
656 ValueDistributionKind::Continuous => "continuous",
657 ValueDistributionKind::Discrete => "discrete",
658 }
659 }
660 }
661 #[derive(Debug, Copy, Clone)]
662 pub enum ValueDistributionScaling {
663 Linear,
664 Complex,
665 Circular,
666 }
667 impl ValueDistributionScaling {
668 pub fn name(&self) -> &'static str {
669 match self {
670 ValueDistributionScaling::Linear => "linear",
671 ValueDistributionScaling::Complex => "complex",
672 ValueDistributionScaling::Circular => "circular",
673 }
674 }
675 }
676}