1use heapless::{String, Vec};
7
8#[cfg(feature = "alloc")]
12use alloc::string::ToString;
13
14pub use crate::config::*;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
20#[repr(u8)]
21pub enum ParameterType {
22 #[default]
24 NotSet = 0,
25 Bool = 1,
27 Integer = 2,
29 Double = 3,
31 String = 4,
33 ByteArray = 5,
35 BoolArray = 6,
37 IntegerArray = 7,
39 DoubleArray = 8,
41 StringArray = 9,
43}
44
45#[derive(Debug, Clone, Default)]
51#[allow(clippy::large_enum_variant)]
52pub enum ParameterValue {
53 #[default]
55 NotSet,
56 Bool(bool),
58 Integer(i64),
60 Double(f64),
62 String(String<MAX_STRING_VALUE_LEN>),
64 ByteArray(Vec<u8, MAX_BYTE_ARRAY_LEN>),
66 BoolArray(Vec<bool, MAX_ARRAY_LEN>),
68 IntegerArray(Vec<i64, MAX_ARRAY_LEN>),
70 DoubleArray(Vec<f64, MAX_ARRAY_LEN>),
72 StringArray(Vec<String<MAX_STRING_VALUE_LEN>, MAX_ARRAY_LEN>),
74}
75
76impl ParameterValue {
77 pub fn param_type(&self) -> ParameterType {
79 match self {
80 Self::NotSet => ParameterType::NotSet,
81 Self::Bool(_) => ParameterType::Bool,
82 Self::Integer(_) => ParameterType::Integer,
83 Self::Double(_) => ParameterType::Double,
84 Self::String(_) => ParameterType::String,
85 Self::ByteArray(_) => ParameterType::ByteArray,
86 Self::BoolArray(_) => ParameterType::BoolArray,
87 Self::IntegerArray(_) => ParameterType::IntegerArray,
88 Self::DoubleArray(_) => ParameterType::DoubleArray,
89 Self::StringArray(_) => ParameterType::StringArray,
90 }
91 }
92
93 pub fn is_set(&self) -> bool {
95 !matches!(self, Self::NotSet)
96 }
97
98 pub fn as_bool(&self) -> Option<bool> {
100 match self {
101 Self::Bool(v) => Some(*v),
102 _ => None,
103 }
104 }
105
106 pub fn as_integer(&self) -> Option<i64> {
108 match self {
109 Self::Integer(v) => Some(*v),
110 _ => None,
111 }
112 }
113
114 pub fn as_double(&self) -> Option<f64> {
116 match self {
117 Self::Double(v) => Some(*v),
118 _ => None,
119 }
120 }
121
122 pub fn as_string(&self) -> Option<&str> {
124 match self {
125 Self::String(v) => Some(v.as_str()),
126 _ => None,
127 }
128 }
129
130 pub fn as_byte_array(&self) -> Option<&[u8]> {
132 match self {
133 Self::ByteArray(v) => Some(v.as_slice()),
134 _ => None,
135 }
136 }
137
138 pub fn as_bool_array(&self) -> Option<&[bool]> {
140 match self {
141 Self::BoolArray(v) => Some(v.as_slice()),
142 _ => None,
143 }
144 }
145
146 pub fn as_integer_array(&self) -> Option<&[i64]> {
148 match self {
149 Self::IntegerArray(v) => Some(v.as_slice()),
150 _ => None,
151 }
152 }
153
154 pub fn as_double_array(&self) -> Option<&[f64]> {
156 match self {
157 Self::DoubleArray(v) => Some(v.as_slice()),
158 _ => None,
159 }
160 }
161
162 pub fn from_bool(value: bool) -> Self {
164 Self::Bool(value)
165 }
166
167 pub fn from_integer(value: i64) -> Self {
169 Self::Integer(value)
170 }
171
172 pub fn from_double(value: f64) -> Self {
174 Self::Double(value)
175 }
176
177 pub fn from_string(value: &str) -> Option<Self> {
179 let mut s = String::new();
180 s.push_str(value).ok()?;
181 Some(Self::String(s))
182 }
183}
184
185#[derive(Debug, Clone, Copy, Default)]
187pub struct FloatingPointRange {
188 pub min: f64,
190 pub max: f64,
192 pub step: f64,
194}
195
196impl FloatingPointRange {
197 pub const fn new(min: f64, max: f64, step: f64) -> Self {
199 Self { min, max, step }
200 }
201
202 pub fn contains(&self, value: f64) -> bool {
204 value >= self.min && value <= self.max
205 }
206}
207
208#[derive(Debug, Clone, Copy, Default)]
210pub struct IntegerRange {
211 pub min: i64,
213 pub max: i64,
215 pub step: i64,
217}
218
219impl IntegerRange {
220 pub const fn new(min: i64, max: i64, step: i64) -> Self {
222 Self { min, max, step }
223 }
224
225 pub fn contains(&self, value: i64) -> bool {
227 value >= self.min && value <= self.max
228 }
229}
230
231#[derive(Debug, Clone, Copy, Default)]
233pub enum ParameterRange {
234 #[default]
236 None,
237 FloatingPoint(FloatingPointRange),
239 Integer(IntegerRange),
241}
242
243#[derive(Debug, Clone)]
247pub struct ParameterDescriptor {
248 pub name: String<MAX_PARAM_NAME_LEN>,
250 pub param_type: ParameterType,
252 pub description: String<MAX_STRING_VALUE_LEN>,
254 pub read_only: bool,
256 pub dynamic_typing: bool,
258 pub range: ParameterRange,
260}
261
262impl ParameterDescriptor {
263 pub fn new(name: &str, param_type: ParameterType) -> Option<Self> {
265 let mut n = String::new();
266 n.push_str(name).ok()?;
267 Some(Self {
268 name: n,
269 param_type,
270 description: String::new(),
271 read_only: false,
272 dynamic_typing: false,
273 range: ParameterRange::None,
274 })
275 }
276
277 pub fn with_description(mut self, desc: &str) -> Self {
279 self.description.clear();
280 let _ = self.description.push_str(desc);
281 self
282 }
283
284 pub fn with_read_only(mut self, read_only: bool) -> Self {
286 self.read_only = read_only;
287 self
288 }
289
290 pub fn with_dynamic_typing(mut self, dynamic: bool) -> Self {
292 self.dynamic_typing = dynamic;
293 self
294 }
295
296 pub fn with_integer_range(mut self, min: i64, max: i64, step: i64) -> Self {
298 self.range = ParameterRange::Integer(IntegerRange::new(min, max, step));
299 self
300 }
301
302 pub fn with_float_range(mut self, min: f64, max: f64, step: f64) -> Self {
304 self.range = ParameterRange::FloatingPoint(FloatingPointRange::new(min, max, step));
305 self
306 }
307
308 pub fn validate_range(&self, value: &ParameterValue) -> bool {
310 match (&self.range, value) {
311 (ParameterRange::None, _) => true,
312 (ParameterRange::Integer(range), ParameterValue::Integer(v)) => range.contains(*v),
313 (ParameterRange::FloatingPoint(range), ParameterValue::Double(v)) => range.contains(*v),
314 _ => true,
315 }
316 }
317}
318
319#[derive(Debug, Clone)]
321pub struct Parameter {
322 pub name: String<MAX_PARAM_NAME_LEN>,
324 pub value: ParameterValue,
326}
327
328impl Parameter {
329 pub fn new(name: &str, value: ParameterValue) -> Option<Self> {
331 let mut n = String::new();
332 n.push_str(name).ok()?;
333 Some(Self { name: n, value })
334 }
335
336 pub fn bool(name: &str, value: bool) -> Option<Self> {
338 Self::new(name, ParameterValue::Bool(value))
339 }
340
341 pub fn integer(name: &str, value: i64) -> Option<Self> {
343 Self::new(name, ParameterValue::Integer(value))
344 }
345
346 pub fn double(name: &str, value: f64) -> Option<Self> {
348 Self::new(name, ParameterValue::Double(value))
349 }
350
351 pub fn string(name: &str, value: &str) -> Option<Self> {
353 Self::new(name, ParameterValue::from_string(value)?)
354 }
355
356 pub fn param_type(&self) -> ParameterType {
358 self.value.param_type()
359 }
360
361 pub fn name(&self) -> &str {
363 &self.name
364 }
365}
366
367#[derive(Debug, Clone, Copy, PartialEq, Eq)]
369pub enum SetParameterResult {
370 Success,
372 ReadOnly,
374 TypeMismatch,
376 OutOfRange,
378 NotFound,
380 StorageFull,
382}
383
384impl SetParameterResult {
385 pub fn is_success(&self) -> bool {
387 matches!(self, Self::Success)
388 }
389}
390
391#[derive(Debug, Clone, Copy, PartialEq, Eq)]
397pub struct CapacityExceeded;
398
399pub trait ParameterVariant: Clone {
404 fn to_parameter_value(&self) -> ParameterValue;
406
407 fn try_to_parameter_value(&self) -> Result<ParameterValue, CapacityExceeded> {
419 Ok(self.to_parameter_value())
420 }
421
422 fn from_parameter_value(value: &ParameterValue) -> Option<Self>;
424
425 fn parameter_type() -> ParameterType;
427}
428
429impl ParameterVariant for bool {
432 fn to_parameter_value(&self) -> ParameterValue {
433 ParameterValue::Bool(*self)
434 }
435
436 fn from_parameter_value(value: &ParameterValue) -> Option<Self> {
437 value.as_bool()
438 }
439
440 fn parameter_type() -> ParameterType {
441 ParameterType::Bool
442 }
443}
444
445impl ParameterVariant for i64 {
446 fn to_parameter_value(&self) -> ParameterValue {
447 ParameterValue::Integer(*self)
448 }
449
450 fn from_parameter_value(value: &ParameterValue) -> Option<Self> {
451 value.as_integer()
452 }
453
454 fn parameter_type() -> ParameterType {
455 ParameterType::Integer
456 }
457}
458
459impl ParameterVariant for f64 {
460 fn to_parameter_value(&self) -> ParameterValue {
461 ParameterValue::Double(*self)
462 }
463
464 fn from_parameter_value(value: &ParameterValue) -> Option<Self> {
465 value.as_double()
466 }
467
468 fn parameter_type() -> ParameterType {
469 ParameterType::Double
470 }
471}
472
473impl ParameterVariant for String<MAX_STRING_VALUE_LEN> {
483 fn to_parameter_value(&self) -> ParameterValue {
484 ParameterValue::String(self.clone())
485 }
486
487 fn from_parameter_value(value: &ParameterValue) -> Option<Self> {
488 if let ParameterValue::String(s) = value {
489 Some(s.clone())
490 } else {
491 None
492 }
493 }
494
495 fn parameter_type() -> ParameterType {
496 ParameterType::String
497 }
498}
499
500#[cfg(feature = "alloc")]
502impl ParameterVariant for alloc::string::String {
503 fn to_parameter_value(&self) -> ParameterValue {
504 ParameterValue::from_string(self.as_str()).unwrap_or_default()
505 }
506
507 fn try_to_parameter_value(&self) -> Result<ParameterValue, CapacityExceeded> {
508 ParameterValue::from_string(self.as_str()).ok_or(CapacityExceeded)
509 }
510
511 fn from_parameter_value(value: &ParameterValue) -> Option<Self> {
512 value.as_string().map(|s| s.to_string())
513 }
514
515 fn parameter_type() -> ParameterType {
516 ParameterType::String
517 }
518}
519
520#[cfg(feature = "alloc")]
522impl ParameterVariant for alloc::vec::Vec<i64> {
523 fn to_parameter_value(&self) -> ParameterValue {
524 ParameterValue::IntegerArray(Vec::from_slice(self.as_slice()).unwrap_or_default())
525 }
526
527 fn try_to_parameter_value(&self) -> Result<ParameterValue, CapacityExceeded> {
528 Vec::from_slice(self.as_slice())
529 .map(ParameterValue::IntegerArray)
530 .map_err(|_| CapacityExceeded)
531 }
532
533 fn from_parameter_value(value: &ParameterValue) -> Option<Self> {
534 value.as_integer_array().map(|v| v.to_vec())
535 }
536
537 fn parameter_type() -> ParameterType {
538 ParameterType::IntegerArray
539 }
540}
541
542#[cfg(feature = "alloc")]
544impl ParameterVariant for alloc::vec::Vec<f64> {
545 fn to_parameter_value(&self) -> ParameterValue {
546 ParameterValue::DoubleArray(Vec::from_slice(self.as_slice()).unwrap_or_default())
547 }
548
549 fn try_to_parameter_value(&self) -> Result<ParameterValue, CapacityExceeded> {
550 Vec::from_slice(self.as_slice())
551 .map(ParameterValue::DoubleArray)
552 .map_err(|_| CapacityExceeded)
553 }
554
555 fn from_parameter_value(value: &ParameterValue) -> Option<Self> {
556 value.as_double_array().map(|v| v.to_vec())
557 }
558
559 fn parameter_type() -> ParameterType {
560 ParameterType::DoubleArray
561 }
562}
563
564#[cfg(feature = "alloc")]
566impl ParameterVariant for alloc::vec::Vec<bool> {
567 fn to_parameter_value(&self) -> ParameterValue {
568 ParameterValue::BoolArray(Vec::from_slice(self.as_slice()).unwrap_or_default())
569 }
570
571 fn try_to_parameter_value(&self) -> Result<ParameterValue, CapacityExceeded> {
572 Vec::from_slice(self.as_slice())
573 .map(ParameterValue::BoolArray)
574 .map_err(|_| CapacityExceeded)
575 }
576
577 fn from_parameter_value(value: &ParameterValue) -> Option<Self> {
578 value.as_bool_array().map(|v| v.to_vec())
579 }
580
581 fn parameter_type() -> ParameterType {
582 ParameterType::BoolArray
583 }
584}
585
586#[cfg(feature = "alloc")]
588impl ParameterVariant for alloc::vec::Vec<alloc::string::String> {
589 fn to_parameter_value(&self) -> ParameterValue {
590 let mut vec = Vec::new();
591 for s in self {
592 let mut h_string = String::new();
593 if h_string.push_str(s.as_str()).is_ok() {
594 let _ = vec.push(h_string);
595 }
596 }
597 ParameterValue::StringArray(vec)
598 }
599
600 fn try_to_parameter_value(&self) -> Result<ParameterValue, CapacityExceeded> {
601 let mut vec = Vec::new();
604 for s in self {
605 let mut h_string = String::new();
606 h_string
607 .push_str(s.as_str())
608 .map_err(|_| CapacityExceeded)?;
609 vec.push(h_string).map_err(|_| CapacityExceeded)?;
610 }
611 Ok(ParameterValue::StringArray(vec))
612 }
613
614 fn from_parameter_value(value: &ParameterValue) -> Option<Self> {
615 if let ParameterValue::StringArray(v) = value {
616 Some(v.iter().map(|s| s.as_str().to_string()).collect())
617 } else {
618 None
619 }
620 }
621
622 fn parameter_type() -> ParameterType {
623 ParameterType::StringArray
624 }
625}
626
627#[cfg(test)]
628mod tests {
629 use super::*;
630
631 #[test]
632 #[allow(clippy::approx_constant)]
633 fn test_parameter_value_types() {
634 let bool_val = ParameterValue::Bool(true);
635 assert_eq!(bool_val.param_type(), ParameterType::Bool);
636 assert_eq!(bool_val.as_bool(), Some(true));
637
638 let int_val = ParameterValue::Integer(42);
639 assert_eq!(int_val.param_type(), ParameterType::Integer);
640 assert_eq!(int_val.as_integer(), Some(42));
641
642 let double_val = ParameterValue::Double(3.14);
643 assert_eq!(double_val.param_type(), ParameterType::Double);
644 assert_eq!(double_val.as_double(), Some(3.14));
645 }
646
647 #[test]
648 fn test_parameter_value_string() {
649 let string_val = ParameterValue::from_string("hello").unwrap();
650 assert_eq!(string_val.param_type(), ParameterType::String);
651 assert_eq!(string_val.as_string(), Some("hello"));
652 }
653
654 #[test]
655 fn test_parameter_creation() {
656 let param = Parameter::bool("my_param", true).unwrap();
657 assert_eq!(param.name(), "my_param");
658 assert_eq!(param.param_type(), ParameterType::Bool);
659 assert_eq!(param.value.as_bool(), Some(true));
660 }
661
662 #[test]
663 fn test_parameter_descriptor() {
664 let desc = ParameterDescriptor::new("speed", ParameterType::Double)
665 .unwrap()
666 .with_description("Maximum speed in m/s")
667 .with_float_range(0.0, 10.0, 0.1);
668
669 assert_eq!(desc.name.as_str(), "speed");
670 assert_eq!(desc.param_type, ParameterType::Double);
671 assert!(!desc.read_only);
672
673 assert!(desc.validate_range(&ParameterValue::Double(5.0)));
675 assert!(!desc.validate_range(&ParameterValue::Double(15.0)));
676 }
677
678 #[test]
679 fn test_integer_range() {
680 let range = IntegerRange::new(0, 100, 1);
681 assert!(range.contains(50));
682 assert!(range.contains(0));
683 assert!(range.contains(100));
684 assert!(!range.contains(-1));
685 assert!(!range.contains(101));
686 }
687
688 #[test]
689 fn test_set_result() {
690 assert!(SetParameterResult::Success.is_success());
691 assert!(!SetParameterResult::ReadOnly.is_success());
692 }
693}
694
695#[cfg(test)]
700mod ghost_checks {
701 use super::*;
702 use nros_ghost_types::ParameterValueGhost;
703
704 fn ghost_from_value(v: &ParameterValue) -> ParameterValueGhost {
707 match v {
708 ParameterValue::NotSet => ParameterValueGhost::NotSet,
709 ParameterValue::Bool(b) => ParameterValueGhost::Bool(*b),
710 ParameterValue::Integer(i) => ParameterValueGhost::Integer(*i),
711 ParameterValue::Double(_) => ParameterValueGhost::Double,
712 ParameterValue::String(_) => ParameterValueGhost::String,
713 ParameterValue::ByteArray(_) => ParameterValueGhost::ByteArray,
714 ParameterValue::BoolArray(_) => ParameterValueGhost::BoolArray,
715 ParameterValue::IntegerArray(_) => ParameterValueGhost::IntegerArray,
716 ParameterValue::DoubleArray(_) => ParameterValueGhost::DoubleArray,
717 ParameterValue::StringArray(_) => ParameterValueGhost::StringArray,
718 }
719 }
720
721 #[test]
722 fn ghost_variant_coverage() {
723 let _ = ghost_from_value(&ParameterValue::NotSet);
725 let _ = ghost_from_value(&ParameterValue::Bool(true));
726 let _ = ghost_from_value(&ParameterValue::Integer(0));
727 let _ = ghost_from_value(&ParameterValue::Double(0.0));
728 let _ = ghost_from_value(&ParameterValue::String(String::new()));
729 let _ = ghost_from_value(&ParameterValue::ByteArray(Vec::new()));
730 let _ = ghost_from_value(&ParameterValue::BoolArray(Vec::new()));
731 let _ = ghost_from_value(&ParameterValue::IntegerArray(Vec::new()));
732 let _ = ghost_from_value(&ParameterValue::DoubleArray(Vec::new()));
733 let _ = ghost_from_value(&ParameterValue::StringArray(Vec::new()));
734 }
735
736 #[test]
737 fn ghost_bool_preserves() {
738 let ghost = ghost_from_value(&ParameterValue::Bool(true));
739 assert!(matches!(ghost, ParameterValueGhost::Bool(true)));
740 }
741
742 #[test]
743 fn ghost_integer_preserves() {
744 let ghost = ghost_from_value(&ParameterValue::Integer(42));
745 assert!(matches!(ghost, ParameterValueGhost::Integer(42)));
746 }
747}
748
749#[cfg(kani)]
754mod verification {
755 use super::*;
756
757 #[kani::proof]
760 fn parameter_i64_roundtrip() {
761 let val: i64 = kani::any();
762 let pv = ParameterValue::from_integer(val);
763 assert_eq!(pv.as_integer(), Some(val));
764 assert_eq!(pv.param_type(), ParameterType::Integer);
765 assert!(pv.is_set());
766 }
767
768 #[kani::proof]
769 fn parameter_bool_roundtrip() {
770 let val: bool = kani::any();
771 let pv = ParameterValue::from_bool(val);
772 assert_eq!(pv.as_bool(), Some(val));
773 assert_eq!(pv.param_type(), ParameterType::Bool);
774 assert!(pv.is_set());
775 }
776
777 #[kani::proof]
778 fn parameter_double_roundtrip() {
779 let val: f64 = kani::any();
780 let pv = ParameterValue::from_double(val);
781 let result = pv.as_double();
782 assert!(result.is_some());
783 assert_eq!(result.unwrap().to_bits(), val.to_bits());
784 assert_eq!(pv.param_type(), ParameterType::Double);
785 }
786
787 #[kani::proof]
788 fn parameter_not_set_default() {
789 let pv = ParameterValue::default();
790 assert!(!pv.is_set());
791 assert_eq!(pv.param_type(), ParameterType::NotSet);
792 assert!(pv.as_bool().is_none());
793 assert!(pv.as_integer().is_none());
794 assert!(pv.as_double().is_none());
795 assert!(pv.as_string().is_none());
796 }
797
798 #[kani::proof]
801 fn parameter_type_mismatch_bool() {
802 let val: i64 = kani::any();
803 let pv = ParameterValue::from_integer(val);
804 assert!(pv.as_bool().is_none());
805 assert!(pv.as_double().is_none());
806 assert!(pv.as_string().is_none());
807 }
808
809 #[kani::proof]
810 fn parameter_type_mismatch_integer() {
811 let val: bool = kani::any();
812 let pv = ParameterValue::from_bool(val);
813 assert!(pv.as_integer().is_none());
814 assert!(pv.as_double().is_none());
815 assert!(pv.as_string().is_none());
816 }
817
818 #[kani::proof]
821 fn integer_range_contains_bounds() {
822 let min: i64 = kani::any();
823 let max: i64 = kani::any();
824 kani::assume(min >= -1_000_000 && min <= 1_000_000);
826 kani::assume(max >= -1_000_000 && max <= 1_000_000);
827 kani::assume(min <= max);
828 let range = IntegerRange::new(min, max, 1);
829 assert!(range.contains(min));
831 assert!(range.contains(max));
832 }
833
834 #[kani::proof]
835 fn integer_range_outside_bounds() {
836 let min: i64 = kani::any();
837 let max: i64 = kani::any();
838 kani::assume(min <= max);
839 kani::assume(min > i64::MIN); kani::assume(max < i64::MAX); let range = IntegerRange::new(min, max, 1);
842 assert!(!range.contains(min - 1));
843 assert!(!range.contains(max + 1));
844 }
845
846 #[kani::proof]
849 fn float_range_contains_bounds() {
850 let min: f64 = kani::any();
851 let max: f64 = kani::any();
852 kani::assume(!min.is_nan() && !max.is_nan());
853 kani::assume(min <= max);
854 let range = FloatingPointRange::new(min, max, 0.0);
855 assert!(range.contains(min));
856 assert!(range.contains(max));
857 }
858
859 #[kani::proof]
862 fn set_result_success_only() {
863 assert!(SetParameterResult::Success.is_success());
865 assert!(!SetParameterResult::ReadOnly.is_success());
866 assert!(!SetParameterResult::TypeMismatch.is_success());
867 assert!(!SetParameterResult::OutOfRange.is_success());
868 assert!(!SetParameterResult::NotFound.is_success());
869 assert!(!SetParameterResult::StorageFull.is_success());
870 }
871}
872
873#[cfg(all(test, feature = "alloc"))]
876mod issue_0323_tests {
877 use super::*;
878
879 #[test]
883 fn oversize_string_is_rejected_not_silently_notset() {
884 let long = "x".repeat(MAX_STRING_VALUE_LEN + 1);
885 assert!(
886 matches!(long.to_parameter_value(), ParameterValue::NotSet),
887 "documenting the legacy infallible behaviour"
888 );
889 assert!(
890 long.try_to_parameter_value().is_err(),
891 "the fallible path must reject it"
892 );
893 }
894
895 #[test]
897 fn oversize_integer_array_is_rejected_not_silently_empty() {
898 let big: alloc::vec::Vec<i64> = (0..(MAX_ARRAY_LEN as i64 + 1)).collect();
899 match big.to_parameter_value() {
900 ParameterValue::IntegerArray(v) => {
901 assert!(v.is_empty(), "documenting the legacy empty-array behaviour")
902 }
903 other => panic!("unexpected {other:?}"),
904 }
905 assert!(big.try_to_parameter_value().is_err());
906 }
907
908 #[test]
910 fn oversize_string_array_element_is_rejected_not_skipped() {
911 let big: alloc::vec::Vec<alloc::string::String> =
912 (0..(MAX_ARRAY_LEN + 1)).map(|i| i.to_string()).collect();
913 assert!(big.try_to_parameter_value().is_err());
914 }
915}