1use super::IntegerType;
4use num_bigint::BigInt;
5
6pub trait InnerSubtypeConstraint: Sized {
8 fn validate_components(self) -> Result<Self, crate::error::InnerSubtypeConstraintError> {
11 self.validate_and_decode_containing(None)
12 }
13
14 fn validate_and_decode_containing(
20 self,
21 decode_containing_with: Option<crate::Codec>,
22 ) -> Result<Self, crate::error::InnerSubtypeConstraintError>;
23}
24
25#[derive(Debug, Copy, Clone)]
37#[non_exhaustive]
38pub struct Constraints {
39 value: Option<Extensible<Value>>,
40 size: Option<Extensible<Size>>,
41 permitted_alphabet: Option<Extensible<PermittedAlphabet>>,
42 extensible: bool,
43}
44
45impl Constraints {
46 pub const NONE: Self = Self {
48 value: None,
49 size: None,
50 permitted_alphabet: None,
51 extensible: false,
52 };
53
54 #[must_use]
56 pub const fn new(constraints: &[Constraint]) -> Self {
57 let mut value: Option<Extensible<Value>> = None;
58 let mut size: Option<Extensible<Size>> = None;
59 let mut permitted_alphabet: Option<Extensible<PermittedAlphabet>> = None;
60 let mut extensible = false;
61 let mut i = 0;
62 while i < constraints.len() {
63 match constraints[i] {
64 Constraint::Value(v) => {
65 value = match value {
66 Some(value) => Some(value.intersect(&v)),
67 None => Some(v),
68 };
69 }
70 Constraint::Size(s) => {
71 size = if let Some(size) = size {
72 Some(size.intersect(&s))
73 } else {
74 Some(s)
75 };
76 }
77 Constraint::PermittedAlphabet(p) => {
78 permitted_alphabet = if let Some(perm) = permitted_alphabet {
79 Some(perm.intersect(&p))
80 } else {
81 Some(p)
82 };
83 }
84 Constraint::Extensible => {
85 extensible = true;
86 }
87 }
88 i += 1;
89 }
90 Self {
91 value,
92 size,
93 permitted_alphabet,
94 extensible,
95 }
96 }
97
98 #[must_use]
100 pub const fn default() -> Self {
101 Self::NONE
102 }
103
104 #[must_use]
106 pub const fn intersect(&self, rhs: Constraints) -> Self {
107 let value = match (self.value, rhs.value) {
108 (Some(value), Some(rhs_value)) => Some(value.intersect(&rhs_value)),
109 (Some(value), None) => Some(value),
110 (None, Some(rhs_value)) => Some(rhs_value),
111 (None, None) => None,
112 };
113 let size = match (self.size, rhs.size) {
114 (Some(size), Some(rhs_size)) => Some(size.intersect(&rhs_size)),
115 (Some(size), None) => Some(size),
116 (None, Some(rhs_size)) => Some(rhs_size),
117 (None, None) => None,
118 };
119 let permitted_alphabet = match (self.permitted_alphabet, rhs.permitted_alphabet) {
120 (Some(perm), Some(rhs_perm)) => Some(perm.intersect(&rhs_perm)),
121 (Some(perm), None) => Some(perm),
122 (None, Some(rhs_perm)) => Some(rhs_perm),
123 (None, None) => None,
124 };
125 let extensible = self.extensible || rhs.extensible;
126
127 Self {
128 value,
129 size,
130 permitted_alphabet,
131 extensible,
132 }
133 }
134
135 #[must_use]
137 pub const fn size(&self) -> Option<&Extensible<Size>> {
138 self.size.as_ref()
139 }
140
141 #[must_use]
143 pub const fn permitted_alphabet(&self) -> Option<&Extensible<PermittedAlphabet>> {
144 self.permitted_alphabet.as_ref()
145 }
146
147 #[must_use]
149 pub const fn extensible(&self) -> bool {
150 if self.extensible {
151 return true;
152 }
153 if let Some(value) = &self.value
154 && value.extensible.is_some()
155 {
156 return true;
157 }
158 if let Some(size) = &self.size
159 && size.extensible.is_some()
160 {
161 return true;
162 }
163 if let Some(permitted_alphabet) = &self.permitted_alphabet
164 && permitted_alphabet.extensible.is_some()
165 {
166 return true;
167 }
168 false
169 }
170
171 #[must_use]
173 pub const fn value(&self) -> Option<&Extensible<Value>> {
174 self.value.as_ref()
175 }
176}
177
178#[derive(Debug, Copy, Clone, PartialEq)]
180pub enum Constraint {
181 Value(Extensible<Value>),
183 Size(Extensible<Size>),
185 PermittedAlphabet(Extensible<PermittedAlphabet>),
187 Extensible,
190}
191
192#[derive(Debug, Clone, Copy, PartialEq)]
194#[allow(missing_docs)]
195pub enum ConstraintDiscriminant {
196 Value,
197 Size,
198 PermittedAlphabet,
199 Extensible,
200}
201impl ConstraintDiscriminant {
202 #[must_use]
204 pub const fn eq(&self, other: &ConstraintDiscriminant) -> bool {
205 *self as isize == *other as isize
206 }
207}
208
209impl Constraint {
210 #[must_use]
212 pub const fn kind(&self) -> ConstraintDiscriminant {
213 match self {
214 Self::Value(_) => ConstraintDiscriminant::Value,
215 Self::Size(_) => ConstraintDiscriminant::Size,
216 Self::PermittedAlphabet(_) => ConstraintDiscriminant::PermittedAlphabet,
217 Self::Extensible => ConstraintDiscriminant::Extensible,
218 }
219 }
220 #[must_use]
222 pub const fn variant_as_isize(&self) -> isize {
223 match self {
224 Self::Value(_) => 0,
225 Self::Size(_) => 1,
226 Self::PermittedAlphabet(_) => 2,
227 Self::Extensible => 3,
228 }
229 }
230
231 #[must_use]
233 pub const fn as_value(&self) -> Option<&Extensible<Value>> {
234 match self {
235 Self::Value(integer) => Some(integer),
236 _ => None,
237 }
238 }
239
240 #[must_use]
242 pub const fn as_permitted_alphabet(&self) -> Option<&Extensible<PermittedAlphabet>> {
243 match self {
244 Self::PermittedAlphabet(alphabet) => Some(alphabet),
245 _ => None,
246 }
247 }
248
249 #[must_use]
251 pub const fn to_size(&self) -> Option<&Extensible<Size>> {
252 match self {
253 Self::Size(size) => Some(size),
254 _ => None,
255 }
256 }
257
258 #[must_use]
260 pub const fn to_value(&self) -> Option<&Extensible<Value>> {
261 match self {
262 Self::Value(integer) => Some(integer),
263 _ => None,
264 }
265 }
266
267 #[must_use]
269 pub const fn is_extensible(&self) -> bool {
270 match self {
271 Self::Value(value) => value.extensible.is_some(),
272 Self::Size(size) => size.extensible.is_some(),
273 Self::PermittedAlphabet(alphabet) => alphabet.extensible.is_some(),
274 Self::Extensible => true,
275 }
276 }
277}
278
279#[derive(Debug, Default, Copy, Clone, PartialEq)]
284pub struct Extensible<T: 'static> {
285 pub constraint: T,
287 pub extensible: Option<&'static [T]>,
291}
292
293impl<T> Extensible<T> {
294 pub const fn new(constraint: T) -> Self {
297 Self {
298 constraint,
299 extensible: None,
300 }
301 }
302
303 pub const fn new_extensible(constraint: T, constraints: &'static [T]) -> Self {
306 Self {
307 constraint,
308 extensible: Some(constraints),
309 }
310 }
311
312 #[must_use]
315 pub const fn set_extensible(self, extensible: bool) -> Self {
316 let extensible = if extensible {
317 let empty: &[T] = &[];
318 Some(empty)
319 } else {
320 None
321 };
322
323 self.extensible_with_constraints(extensible)
324 }
325
326 #[must_use]
329 pub const fn extensible_with_constraints(mut self, constraints: Option<&'static [T]>) -> Self {
330 self.extensible = constraints;
331 self
332 }
333}
334
335macro_rules! impl_extensible {
336 ($($type:ty),+) => {
337 $(
338 impl Extensible<$type> {
339 #[must_use] pub const fn intersect(&self, other: &Self) -> Self {
341 let extensible = match (self.extensible, other.extensible) {
345 (Some(a), Some(_)) => Some(a),
346 (Some(_), None) => None,
347 (None, Some(_)) => None,
348 (None, None) => None,
349 };
350 let constraint = self.constraint.intersect(&other.constraint);
351 match extensible {
352 Some(ext_ref) => Self::new_extensible(constraint, ext_ref),
353 None => Self::new(constraint),
354 }
355 }
356 }
357 impl From<$type> for Extensible<$type> {
358 fn from(value: $type) -> Self {
359 Self {
360 constraint: value,
361 extensible: None,
362 }
363 }
364 }
365 )+
366 };
367}
368impl_extensible!(Value, Size, PermittedAlphabet);
369
370#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
372pub struct Value {
373 pub(crate) value: Bounded<i128>,
375 pub(crate) signed: bool,
377 pub(crate) range: Option<u8>,
379}
380
381impl Value {
382 #[must_use]
384 pub const fn new(value: Bounded<i128>) -> Self {
385 let (signed, range) = value.range_in_bytes();
386 Self {
387 value,
388 signed,
389 range,
390 }
391 }
392 #[must_use]
394 pub const fn get_sign(&self) -> bool {
395 self.signed
396 }
397 #[must_use]
399 pub const fn get_range(&self) -> Option<u8> {
400 self.range
401 }
402 #[must_use]
404 pub const fn intersect(&self, other: &Self) -> Self {
405 let value = match self.value.intersect(other.value) {
406 Some(value) => value,
407 None => Bounded::Range {
409 start: Some(1),
410 end: Some(-1),
411 },
412 };
413 let (signed, range) = value.range_in_bytes();
414 Self {
415 value,
416 signed,
417 range,
418 }
419 }
420}
421
422impl core::ops::Deref for Value {
423 type Target = Bounded<i128>;
424
425 fn deref(&self) -> &Self::Target {
426 &self.value
427 }
428}
429
430macro_rules! from_primitives {
431 ($($int:ty),+ $(,)?) => {
432 $(
433 impl From<Bounded<$int>> for Value {
434 fn from(bounded: Bounded<$int>) -> Self {
435 Self::new(match bounded {
436 Bounded::Range { start, end } => Bounded::Range {
437 start: start.map(From::from),
438 end: end.map(From::from),
439 },
440 Bounded::Single(value) => Bounded::Single(value.into()),
441 Bounded::None => Bounded::None,
442 })
443 }
444 }
445 )+
446 }
447}
448
449from_primitives! {
450 u8, u16, u32, u64,
451 i8, i16, i32, i64, i128,
452}
453
454impl TryFrom<Bounded<usize>> for Value {
455 type Error = <i128 as TryFrom<usize>>::Error;
456
457 fn try_from(bounded: Bounded<usize>) -> Result<Self, Self::Error> {
458 Ok(Self::new(match bounded {
459 Bounded::Range { start, end } => Bounded::Range {
460 start: start.map(TryFrom::try_from).transpose()?,
461 end: end.map(TryFrom::try_from).transpose()?,
462 },
463 Bounded::Single(value) => Bounded::Single(value.try_into()?),
464 Bounded::None => Bounded::None,
465 }))
466 }
467}
468
469#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
471pub struct Size(pub(crate) Bounded<usize>);
472
473impl Size {
474 #[must_use]
476 pub const fn new(range: Bounded<usize>) -> Self {
477 Self(range)
478 }
479
480 #[must_use]
482 pub const fn fixed(length: usize) -> Self {
483 Self(Bounded::Single(length))
484 }
485
486 #[must_use]
488 pub const fn is_fixed(&self) -> bool {
489 matches!(self.0, Bounded::Single(_))
490 }
491 #[must_use]
493 pub const fn is_range(&self) -> bool {
494 matches!(self.0, Bounded::Range { .. })
495 }
496 #[must_use]
498 pub const fn intersect(&self, other: &Self) -> Self {
499 match self.0.intersect(other.0) {
500 Some(value) => Self(value),
501 None => Self(Bounded::Single(0)),
503 }
504 }
505}
506
507impl core::ops::Deref for Size {
508 type Target = Bounded<usize>;
509
510 fn deref(&self) -> &Self::Target {
511 &self.0
512 }
513}
514
515impl core::ops::DerefMut for Size {
516 fn deref_mut(&mut self) -> &mut Self::Target {
517 &mut self.0
518 }
519}
520
521#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
523pub struct PermittedAlphabet(&'static [u32]);
524
525impl PermittedAlphabet {
526 #[must_use]
528 pub const fn new(range: &'static [u32]) -> Self {
529 Self(range)
530 }
531
532 #[must_use]
534 pub const fn as_inner(&self) -> &'static [u32] {
535 self.0
536 }
537 #[must_use]
543 pub const fn intersect(&self, other: &Self) -> Self {
544 Self(other.0)
545 }
546}
547
548impl core::ops::Deref for PermittedAlphabet {
549 type Target = [u32];
550
551 fn deref(&self) -> &Self::Target {
552 self.0
553 }
554}
555
556#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
558pub enum Bounded<T> {
559 #[default]
561 None,
562 Single(T),
564 Range {
566 start: Option<T>,
568 end: Option<T>,
570 },
571}
572
573impl<T> Bounded<T> {
574 const fn unsigned_octet_size_by_range(value: u128) -> Option<u8> {
577 match value {
578 x if x <= u8::MAX as u128 => Some(1),
579 x if x <= u16::MAX as u128 => Some(2),
580 x if x <= u32::MAX as u128 => Some(4),
581 x if x <= u64::MAX as u128 => Some(8),
582 _ => None,
583 }
584 }
585 const fn signed_octet_size_by_range(value: i128) -> Option<u8> {
588 match value {
589 x if x >= i8::MIN as i128 && x <= i8::MAX as i128 => Some(1),
590 x if x >= i16::MIN as i128 && x <= i16::MAX as i128 => Some(2),
591 x if x >= i32::MIN as i128 && x <= i32::MAX as i128 => Some(4),
592 x if x >= i64::MIN as i128 && x <= i64::MAX as i128 => Some(8),
593 _ => None,
594 }
595 }
596 pub const fn start_from(value: T) -> Self {
598 Self::Range {
599 start: Some(value),
600 end: None,
601 }
602 }
603
604 pub const fn up_to(value: T) -> Self {
606 Self::Range {
607 start: None,
608 end: Some(value),
609 }
610 }
611
612 pub const fn single_value(value: T) -> Self {
614 Self::Single(value)
615 }
616
617 pub const fn as_start(&self) -> Option<&T> {
619 match &self {
620 Self::Range { start, .. } => start.as_ref(),
621 Self::Single(value) => Some(value),
622 _ => None,
623 }
624 }
625
626 pub const fn as_end(&self) -> Option<&T> {
628 match &self {
629 Self::Range { end, .. } => end.as_ref(),
630 Self::Single(value) => Some(value),
631 _ => None,
632 }
633 }
634
635 pub const fn start_and_end(&self) -> (Option<&T>, Option<&T>) {
637 match &self {
638 Self::Range { start, end } => (start.as_ref(), end.as_ref()),
639 Self::Single(value) => (Some(value), Some(value)),
640 _ => (None, None),
641 }
642 }
643}
644
645impl<T: Copy + IntegerType> Bounded<T> {
646 pub const fn minimum(&self) -> T {
649 match self.as_start() {
650 Some(value) => *value,
651 None => T::ZERO,
652 }
653 }
654}
655
656macro_rules! impl_bounded_range {
657 ($($type:ty),+) => {
658 $(
659 impl Bounded<$type> {
660 pub const fn range(&self) -> Option<$type> {
662 match self {
663 Self::Single(_) => Some(1),
664 Self::Range {
665 start: Some(start),
666 end: Some(end),
667 } => Some(end.wrapping_sub(*start).saturating_add(1)),
668 _ => None,
669 }
670 }
671 pub const fn effective_value(&self, value: $type) -> either::Either<$type, $type> {
676 match self {
677 Self::Range {
678 start: Some(start), ..
679 } => {
680 debug_assert!(value >= *start);
681 either::Left(value - *start)
682 }
683 _ => either::Right(value),
684 }
685 }
686 pub const fn intersect(&self, other: Self) -> Option<Self> {
704 match self {
705 Self::None => Some(other),
706 Self::Single(a) => match other {
707 Self::None => Some(Self::Single(*a)),
708 Self::Single(b) => if *a == b { Some(Self::Single(*a)) } else { None },
709 Self::Range { start, end } => {
710 let within_start = if let Some(s) = start.as_ref() {
711 *a >= *s
712 } else {
713 true
714 };
715 let within_end = if let Some(e) = end.as_ref() {
716 *a <= *e
717 } else {
718 true
719 };
720 if within_start && within_end {
721 Some(Self::Single(*a))
722 } else {
723 None
724 }
725 },
726 },
727 Self::Range { start: self_start, end: self_end } => match other {
728 Self::None => Some(*self),
729
730 Self::Single(b) => {
731 let within_start = match self_start.as_ref() {
732 Some(s) => b >= *s,
733 None => true,
734 };
735 let within_end = match self_end.as_ref() {
736 Some(e) => b <= *e,
737 None => true,
738 };
739 if within_start && within_end {
740 Some(Self::Single(b))
741 } else {
742 None
743 }
744 },
745
746 Self::Range { start: other_start, end: other_end } => {
747 let new_start = match (self_start, other_start) {
749 (None, None) => None,
750 (Some(a), None) => Some(*a),
751 (None, Some(b)) => Some(b),
752 (Some(a), Some(b)) => Some(max(*a as i128, b as i128) as $type),
753 };
754
755 let new_end = match (self_end, other_end) {
757 (None, None) => None,
758 (Some(a), None) => Some(*a),
759 (None, Some(b)) => Some(b),
760 (Some(a), Some(b)) => Some(min(*a as i128, b as i128) as $type),
761 };
762
763 match (new_start, new_end) {
764 (Some(start), Some(end)) => {
765 if start <= end {
766 Some(Self::Range { start: Some(start), end: Some(end) })
767 } else {
768 None
770 }
771 },
772 _ => Some(Self::Range { start: new_start, end: new_end }),
773 }
774 },
775 },
776 }
777 }
778 }
779 )+
780 };
781}
782impl_bounded_range!(i128, usize);
783
784impl From<Value> for Constraint {
785 fn from(size: Value) -> Self {
786 Self::Value(size.into())
787 }
788}
789
790impl From<Extensible<Value>> for Constraint {
791 fn from(size: Extensible<Value>) -> Self {
792 Self::Value(size)
793 }
794}
795
796impl From<Size> for Constraint {
797 fn from(size: Size) -> Self {
798 Self::Size(size.into())
799 }
800}
801
802impl From<Extensible<Size>> for Constraint {
803 fn from(size: Extensible<Size>) -> Self {
804 Self::Size(size)
805 }
806}
807
808impl From<PermittedAlphabet> for Constraint {
809 fn from(size: PermittedAlphabet) -> Self {
810 Self::PermittedAlphabet(size.into())
811 }
812}
813
814impl From<Extensible<PermittedAlphabet>> for Constraint {
815 fn from(size: Extensible<PermittedAlphabet>) -> Self {
816 Self::PermittedAlphabet(size)
817 }
818}
819const fn max(a: i128, b: i128) -> i128 {
820 [a, b][(a < b) as usize]
821}
822
823const fn max_unsigned(a: u128, b: u128) -> u128 {
824 [a, b][(a < b) as usize]
825}
826const fn min(a: i128, b: i128) -> i128 {
827 [a, b][(a > b) as usize]
828}
829
830impl Bounded<i128> {
831 #[must_use]
833 pub const fn range_in_bytes(&self) -> (bool, Option<u8>) {
834 match self {
835 Self::Single(value) => {
836 let is_signed = *value < 0;
837 let octet_size = if is_signed {
838 Self::signed_octet_size_by_range(*value)
839 } else {
840 Self::unsigned_octet_size_by_range(*value as u128)
841 };
842 (is_signed, octet_size)
843 }
844 Self::Range {
845 start: Some(start),
846 end: Some(end),
847 } => {
848 let is_signed = *start < 0;
849 let (octets_start, octets_end) = if is_signed {
850 (
851 Self::signed_octet_size_by_range(*start),
852 Self::signed_octet_size_by_range(*end),
853 )
854 } else {
855 (
856 Self::unsigned_octet_size_by_range(*start as u128),
857 Self::unsigned_octet_size_by_range(*end as u128),
858 )
859 };
860
861 let octets = match (octets_start, octets_end) {
862 (Some(start), Some(end)) => {
863 Some(max_unsigned(start as u128, end as u128) as u8)
864 }
865 (_, None) | (None, _) => None,
866 };
867
868 (is_signed, octets)
869 }
870 Self::Range {
871 start: Some(start),
872 end: None,
873 } => (*start < 0, None),
874 Self::Range { start: None, .. } | Self::None => (true, None),
875 }
876 }
877 #[inline(always)]
880 pub fn in_bound<I: IntegerType>(&self, element: &I) -> bool {
881 match &self {
882 Self::Range { start, end } => {
883 start.as_ref().is_none_or(|&start| {
884 if let Some(e) = element.to_i128() {
885 e >= start
886 } else if let Some(e) = element.to_bigint() {
887 e >= BigInt::from(start)
888 } else {
889 false
890 }
891 }) && end.as_ref().is_none_or(|&end| {
892 if let Some(e) = element.to_i128() {
893 e <= end
894 } else if let Some(e) = element.to_bigint() {
895 e <= BigInt::from(end)
896 } else {
897 false
898 }
899 })
900 }
901 Self::Single(value) => {
902 if let Some(e) = element.to_i128() {
903 e == *value
904 } else {
905 false
906 }
907 }
908 Self::None => true,
909 }
910 }
911}
912
913impl<T: PartialEq + PartialOrd> Bounded<T> {
914 pub fn new(start: T, end: T) -> Self {
919 debug_assert!(start <= end);
920 Self::const_new(start, end)
921 }
922
923 pub const fn const_new(start: T, end: T) -> Self {
930 Self::Range {
931 start: Some(start),
932 end: Some(end),
933 }
934 }
935
936 pub fn contains(&self, element: &T) -> bool {
938 match &self {
939 Self::Single(value) => value == element,
940 Self::Range { start, end } => {
941 start.as_ref().is_none_or(|start| element >= start)
942 && end.as_ref().is_none_or(|end| element <= end)
943 }
944 Self::None => true,
945 }
946 }
947
948 pub fn contains_or<E>(&self, element: &T, error: E) -> Result<(), E> {
951 self.contains_or_else(element, || error)
952 }
953
954 pub fn contains_or_else<E>(&self, element: &T, error: impl FnOnce() -> E) -> Result<(), E> {
957 if self.contains(element) {
958 Ok(())
959 } else {
960 Err((error)())
961 }
962 }
963}
964
965impl<T: core::fmt::Display> core::fmt::Display for Bounded<T> {
966 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
967 match self {
968 Self::Range { start, end } => match (start.as_ref(), end.as_ref()) {
969 (Some(start), Some(end)) => write!(f, "{start}..{end}"),
970 (Some(start), None) => write!(f, "{start}.."),
971 (None, Some(end)) => write!(f, "..{end}"),
972 (None, None) => write!(f, ".."),
973 },
974 Self::Single(value) => value.fmt(f),
975 Self::None => write!(f, ".."),
976 }
977 }
978}
979
980#[cfg(test)]
981mod tests {
982 use super::*;
983
984 #[test]
985 fn range() {
986 let constraints = Bounded::new(0, 255usize);
987 assert_eq!(256, constraints.range().unwrap());
988 }
989
990 #[test]
991 #[allow(clippy::too_many_lines)]
992 fn test_bounded_intersections() {
993 let none = Bounded::<i128>::None;
995 let single = Bounded::<i128>::Single(5);
996 let range_both = Bounded::<i128>::Range {
997 start: Some(1),
998 end: Some(10),
999 };
1000 let range_start = Bounded::<i128>::Range {
1001 start: Some(1),
1002 end: None,
1003 };
1004 let range_end = Bounded::<i128>::Range {
1005 start: None,
1006 end: Some(10),
1007 };
1008 let range_none = Bounded::<i128>::Range {
1009 start: None,
1010 end: None,
1011 };
1012
1013 assert_eq!(none.intersect(none), Some(none));
1015 assert_eq!(none.intersect(single), Some(single));
1016 assert_eq!(none.intersect(range_both), Some(range_both));
1017 assert_eq!(none.intersect(range_start), Some(range_start));
1018 assert_eq!(none.intersect(range_end), Some(range_end));
1019 assert_eq!(none.intersect(range_none), Some(range_none));
1020
1021 assert_eq!(single.intersect(none), Some(single));
1023 assert_eq!(single.intersect(single), Some(single));
1024 assert_eq!(single.intersect(Bounded::<i128>::Single(6)), None);
1025
1026 assert_eq!(
1028 single.intersect(Bounded::<i128>::Range {
1029 start: Some(1),
1030 end: Some(10)
1031 }),
1032 Some(single)
1033 );
1034 assert_eq!(
1036 single.intersect(Bounded::<i128>::Range {
1037 start: Some(6),
1038 end: Some(10)
1039 }),
1040 None
1041 );
1042 assert_eq!(
1044 single.intersect(Bounded::<i128>::Range {
1045 start: Some(1),
1046 end: Some(4)
1047 }),
1048 None
1049 );
1050
1051 assert_eq!(
1053 single.intersect(Bounded::<i128>::Range {
1054 start: Some(1),
1055 end: None
1056 }),
1057 Some(single)
1058 );
1059 assert_eq!(
1060 single.intersect(Bounded::<i128>::Range {
1061 start: Some(6),
1062 end: None
1063 }),
1064 None
1065 );
1066
1067 assert_eq!(
1069 single.intersect(Bounded::<i128>::Range {
1070 start: None,
1071 end: Some(10)
1072 }),
1073 Some(single)
1074 );
1075 assert_eq!(
1076 single.intersect(Bounded::<i128>::Range {
1077 start: None,
1078 end: Some(4)
1079 }),
1080 None
1081 );
1082
1083 assert_eq!(single.intersect(range_none), Some(single));
1085
1086 assert_eq!(range_both.intersect(none), Some(range_both));
1088
1089 assert_eq!(
1091 range_both.intersect(Bounded::<i128>::Single(5)),
1092 Some(Bounded::<i128>::Single(5))
1093 );
1094 assert_eq!(range_both.intersect(Bounded::<i128>::Single(0)), None);
1095 assert_eq!(range_both.intersect(Bounded::<i128>::Single(11)), None);
1096
1097 assert_eq!(
1099 Bounded::<i128>::Range {
1100 start: Some(1),
1101 end: Some(10)
1102 }
1103 .intersect(Bounded::<i128>::Range {
1104 start: Some(5),
1105 end: Some(15)
1106 }),
1107 Some(Bounded::<i128>::Range {
1108 start: Some(5),
1109 end: Some(10)
1110 })
1111 );
1112 assert_eq!(
1113 Bounded::<i128>::Range {
1114 start: Some(1),
1115 end: Some(10)
1116 }
1117 .intersect(Bounded::<i128>::Range {
1118 start: Some(0),
1119 end: Some(5)
1120 }),
1121 Some(Bounded::<i128>::Range {
1122 start: Some(1),
1123 end: Some(5)
1124 })
1125 );
1126
1127 assert_eq!(
1129 Bounded::<i128>::Range {
1130 start: Some(1),
1131 end: Some(5)
1132 }
1133 .intersect(Bounded::<i128>::Range {
1134 start: Some(6),
1135 end: Some(10)
1136 }),
1137 None
1138 );
1139
1140 assert_eq!(
1142 Bounded::<i128>::Range {
1143 start: Some(1),
1144 end: Some(10)
1145 }
1146 .intersect(Bounded::<i128>::Range {
1147 start: Some(5),
1148 end: None
1149 }),
1150 Some(Bounded::<i128>::Range {
1151 start: Some(5),
1152 end: Some(10)
1153 })
1154 );
1155 assert_eq!(
1156 Bounded::<i128>::Range {
1157 start: Some(1),
1158 end: Some(10)
1159 }
1160 .intersect(Bounded::<i128>::Range {
1161 start: Some(11),
1162 end: None
1163 }),
1164 None
1165 );
1166
1167 assert_eq!(
1169 Bounded::<i128>::Range {
1170 start: Some(1),
1171 end: Some(10)
1172 }
1173 .intersect(Bounded::<i128>::Range {
1174 start: None,
1175 end: Some(5)
1176 }),
1177 Some(Bounded::<i128>::Range {
1178 start: Some(1),
1179 end: Some(5)
1180 })
1181 );
1182 assert_eq!(
1183 Bounded::<i128>::Range {
1184 start: Some(6),
1185 end: Some(10)
1186 }
1187 .intersect(Bounded::<i128>::Range {
1188 start: None,
1189 end: Some(5)
1190 }),
1191 None
1192 );
1193
1194 assert_eq!(range_both.intersect(range_none), Some(range_both));
1196
1197 assert_eq!(range_start.intersect(none), Some(range_start));
1199
1200 assert_eq!(
1202 Bounded::<i128>::Range {
1203 start: Some(1),
1204 end: None
1205 }
1206 .intersect(Bounded::<i128>::Single(5)),
1207 Some(Bounded::<i128>::Single(5))
1208 );
1209 assert_eq!(
1210 Bounded::<i128>::Range {
1211 start: Some(6),
1212 end: None
1213 }
1214 .intersect(Bounded::<i128>::Single(5)),
1215 None
1216 );
1217
1218 assert_eq!(
1220 Bounded::<i128>::Range {
1221 start: Some(1),
1222 end: None
1223 }
1224 .intersect(Bounded::<i128>::Range {
1225 start: Some(5),
1226 end: None
1227 }),
1228 Some(Bounded::<i128>::Range {
1229 start: Some(5),
1230 end: None
1231 })
1232 );
1233
1234 assert_eq!(
1236 Bounded::<i128>::Range {
1237 start: Some(1),
1238 end: None
1239 }
1240 .intersect(Bounded::<i128>::Range {
1241 start: None,
1242 end: Some(10)
1243 }),
1244 Some(Bounded::<i128>::Range {
1245 start: Some(1),
1246 end: Some(10)
1247 })
1248 );
1249
1250 assert_eq!(range_start.intersect(range_none), Some(range_start));
1252
1253 assert_eq!(range_end.intersect(none), Some(range_end));
1255
1256 assert_eq!(
1258 Bounded::<i128>::Range {
1259 start: None,
1260 end: Some(10)
1261 }
1262 .intersect(Bounded::<i128>::Single(5)),
1263 Some(Bounded::<i128>::Single(5))
1264 );
1265 assert_eq!(
1266 Bounded::<i128>::Range {
1267 start: None,
1268 end: Some(5)
1269 }
1270 .intersect(Bounded::<i128>::Single(10)),
1271 None
1272 );
1273
1274 assert_eq!(
1276 Bounded::<i128>::Range {
1277 start: None,
1278 end: Some(10)
1279 }
1280 .intersect(Bounded::<i128>::Range {
1281 start: None,
1282 end: Some(5)
1283 }),
1284 Some(Bounded::<i128>::Range {
1285 start: None,
1286 end: Some(5)
1287 })
1288 );
1289
1290 assert_eq!(range_none.intersect(none), Some(range_none));
1292 assert_eq!(range_none.intersect(single), Some(single));
1293 assert_eq!(range_none.intersect(range_both), Some(range_both));
1294 assert_eq!(range_none.intersect(range_start), Some(range_start));
1295 assert_eq!(range_none.intersect(range_end), Some(range_end));
1296 assert_eq!(range_none.intersect(range_none), Some(range_none));
1297
1298 let u_single = Bounded::<usize>::Single(5);
1300 let u_range = Bounded::<usize>::Range {
1301 start: Some(1),
1302 end: Some(10),
1303 };
1304
1305 assert_eq!(
1306 u_range.intersect(Bounded::<usize>::Range {
1307 start: Some(5),
1308 end: Some(15),
1309 }),
1310 Some(Bounded::<usize>::Range {
1311 start: Some(5),
1312 end: Some(10),
1313 })
1314 );
1315
1316 assert_eq!(
1317 Bounded::<usize>::Range {
1318 start: Some(1),
1319 end: Some(5)
1320 }
1321 .intersect(Bounded::<usize>::Range {
1322 start: Some(6),
1323 end: Some(10)
1324 }),
1325 None
1326 );
1327
1328 assert_eq!(u_range.intersect(u_single), Some(u_single));
1329 }
1330 #[test]
1331 fn range_in_bytes_none() {
1332 let bounded = Bounded::<i128>::None;
1333 assert_eq!(bounded.range_in_bytes(), (true, None));
1334 }
1335 #[test]
1336 fn range_in_bytes_range() {
1337 let bounded = Bounded::<i128>::Range {
1338 start: Some(0i128),
1339 end: Some(0i128),
1340 };
1341 assert_eq!(bounded.range_in_bytes(), (false, Some(1u8)));
1342
1343 let bounded = Bounded::<i128>::Range {
1344 start: Some(-1i128),
1345 end: Some(-1i128),
1346 };
1347 assert_eq!(bounded.range_in_bytes(), (true, Some(1u8)));
1348
1349 let boundary_test_values = [
1350 (
1351 i8::MIN as i128,
1352 i8::MAX as i128,
1353 (true, Some(1u8)),
1354 (true, Some(2u8)),
1355 (true, Some(2u8)),
1356 "i8 range",
1357 ),
1358 (
1359 i16::MIN as i128,
1360 i16::MAX as i128,
1361 (true, Some(2u8)),
1362 (true, Some(4u8)),
1363 (true, Some(4u8)),
1364 "i16 range",
1365 ),
1366 (
1367 i32::MIN as i128,
1368 i32::MAX as i128,
1369 (true, Some(4u8)),
1370 (true, Some(8u8)),
1371 (true, Some(8u8)),
1372 "i32 range",
1373 ),
1374 (
1375 i64::MIN as i128,
1376 i64::MAX as i128,
1377 (true, Some(8u8)),
1378 (true, None),
1379 (true, None),
1380 "i64 range",
1381 ),
1382 (
1383 u8::MIN as i128,
1384 u8::MAX as i128,
1385 (false, Some(1u8)),
1386 (true, Some(2u8)),
1387 (false, Some(2u8)),
1388 "u8 range",
1389 ),
1390 (
1391 u16::MIN as i128,
1392 u16::MAX as i128,
1393 (false, Some(2u8)),
1394 (true, Some(4u8)),
1395 (false, Some(4u8)),
1396 "u16 range",
1397 ),
1398 (
1399 u32::MIN as i128,
1400 u32::MAX as i128,
1401 (false, Some(4u8)),
1402 (true, Some(8u8)),
1403 (false, Some(8u8)),
1404 "u32 range",
1405 ),
1406 (
1407 u64::MIN as i128,
1408 u64::MAX as i128,
1409 (false, Some(8u8)),
1410 (true, None),
1411 (false, None),
1412 "u64 range",
1413 ),
1414 ];
1415
1416 for (lower, upper, expected, expected_one_down, expected_one_up, name) in
1417 boundary_test_values.into_iter()
1418 {
1419 let bounded = Bounded::<i128>::Range {
1421 start: Some(lower),
1422 end: Some(upper),
1423 };
1424 assert_eq!(bounded.range_in_bytes(), expected, "testing {}", name);
1425
1426 let bounded = Bounded::<i128>::Range {
1428 start: Some(lower - 1),
1429 end: Some(upper),
1430 };
1431 assert_eq!(
1432 bounded.range_in_bytes(),
1433 expected_one_down,
1434 "testing {}, one down",
1435 name
1436 );
1437
1438 let bounded = Bounded::<i128>::Range {
1440 start: Some(lower),
1441 end: Some(upper + 1),
1442 };
1443 assert_eq!(
1444 bounded.range_in_bytes(),
1445 expected_one_up,
1446 "testing {}, one up",
1447 name
1448 );
1449 }
1450 }
1451 #[test]
1452 fn range_in_bytes_range_with_none() {
1453 let test_values = [
1454 (None, None, true),
1455 (Some(-1i128), None, true),
1456 (Some(0i128), None, false),
1457 (Some(1i128), None, false),
1458 (None, Some(-1i128), true),
1459 (None, Some(0i128), true),
1460 (None, Some(1i128), true),
1461 ];
1462
1463 for (lower, upper, expected_signedness) in test_values.into_iter() {
1464 let bounded = Bounded::<i128>::Range {
1465 start: lower,
1466 end: upper,
1467 };
1468 assert_eq!(
1469 bounded.range_in_bytes(),
1470 (expected_signedness, None),
1471 "testing lower={:?} upper={:?}",
1472 lower,
1473 upper
1474 );
1475 }
1476 }
1477 #[test]
1478 fn range_in_bytes_single() {
1479 let test_values = [
1480 (-1i128, (true, Some(1u8))),
1481 (0i128, (false, Some(1u8))),
1482 (1i128, (false, Some(1u8))),
1483 (i8::MIN as i128, (true, Some(1u8))),
1484 (i8::MAX as i128, (false, Some(1u8))),
1485 (u8::MAX as i128, (false, Some(1u8))),
1486 ((i8::MIN as i128) - 1, (true, Some(2u8))),
1487 ((u8::MAX as i128) + 1, (false, Some(2u8))),
1488 (i16::MIN as i128, (true, Some(2u8))),
1489 (i16::MAX as i128, (false, Some(2u8))),
1490 (u16::MAX as i128, (false, Some(2u8))),
1491 ((i16::MIN as i128) - 1, (true, Some(4u8))),
1492 ((u16::MAX as i128) + 1, (false, Some(4u8))),
1493 (i32::MIN as i128, (true, Some(4u8))),
1494 (i32::MAX as i128, (false, Some(4u8))),
1495 (u32::MAX as i128, (false, Some(4u8))),
1496 ((i32::MIN as i128) - 1, (true, Some(8u8))),
1497 ((u32::MAX as i128) + 1, (false, Some(8u8))),
1498 (i64::MIN as i128, (true, Some(8u8))),
1499 (i64::MAX as i128, (false, Some(8u8))),
1500 (u64::MAX as i128, (false, Some(8u8))),
1501 ((i64::MIN as i128) - 1, (true, None)),
1502 ((u64::MAX as i128) + 1, (false, None)),
1503 ];
1504
1505 for (value, expected) in test_values.into_iter() {
1506 let bounded = Bounded::<i128>::Single(value);
1507 assert_eq!(bounded.range_in_bytes(), expected, "testing {}", value);
1508 }
1509 }
1510}