1/// A range bounded inclusively for counting parses performed
2///
3/// This is flexible in what can be converted to a [Range]:
4/// ```rust
5/// # #[cfg(feature = "std")] {
6/// # use winnow::prelude::*;
7/// # use winnow::token::any;
8/// # use winnow::combinator::repeat;
9/// # fn inner(input: &mut &str) -> ModalResult<char> {
10/// # any.parse_next(input)
11/// # }
12/// # let mut input = "0123456789012345678901234567890123456789";
13/// # let input = &mut input;
14/// let parser: Vec<_> = repeat(5, inner).parse_next(input).unwrap();
15/// # let mut input = "0123456789012345678901234567890123456789";
16/// # let input = &mut input;
17/// let parser: Vec<_> = repeat(.., inner).parse_next(input).unwrap();
18/// # let mut input = "0123456789012345678901234567890123456789";
19/// # let input = &mut input;
20/// let parser: Vec<_> = repeat(1.., inner).parse_next(input).unwrap();
21/// # let mut input = "0123456789012345678901234567890123456789";
22/// # let input = &mut input;
23/// let parser: Vec<_> = repeat(5..8, inner).parse_next(input).unwrap();
24/// # let mut input = "0123456789012345678901234567890123456789";
25/// # let input = &mut input;
26/// let parser: Vec<_> = repeat(5..=8, inner).parse_next(input).unwrap();
27/// # }
28/// ```
29#[derive(PartialEq, Eq, Copy, Clone)]
30pub struct Range {
31 pub(crate) start_inclusive: usize,
32 pub(crate) end_inclusive: Option<usize>,
33}
34
35impl Range {
36 #[inline(always)]
37 fn raw(start_inclusive: usize, end_inclusive: Option<usize>) -> Self {
38 Self {
39 start_inclusive,
40 end_inclusive,
41 }
42 }
43}
44
45impl crate::lib::std::ops::RangeBounds<usize> for Range {
46 #[inline(always)]
47 fn start_bound(&self) -> crate::lib::std::ops::Bound<&usize> {
48 crate::lib::std::ops::Bound::Included(&self.start_inclusive)
49 }
50
51 #[inline(always)]
52 fn end_bound(&self) -> crate::lib::std::ops::Bound<&usize> {
53 if let Some(end_inclusive: &usize) = &self.end_inclusive {
54 crate::lib::std::ops::Bound::Included(end_inclusive)
55 } else {
56 crate::lib::std::ops::Bound::Unbounded
57 }
58 }
59}
60
61impl From<usize> for Range {
62 #[inline(always)]
63 fn from(fixed: usize) -> Self {
64 (fixed..=fixed).into()
65 }
66}
67
68impl From<crate::lib::std::ops::Range<usize>> for Range {
69 #[inline(always)]
70 fn from(range: crate::lib::std::ops::Range<usize>) -> Self {
71 let start_inclusive: usize = range.start;
72 let end_inclusive: Option = Some(range.end.saturating_sub(1));
73 Self::raw(start_inclusive, end_inclusive)
74 }
75}
76
77impl From<crate::lib::std::ops::RangeFull> for Range {
78 #[inline(always)]
79 fn from(_: crate::lib::std::ops::RangeFull) -> Self {
80 let start_inclusive: usize = 0;
81 let end_inclusive: Option = None;
82 Self::raw(start_inclusive, end_inclusive)
83 }
84}
85
86impl From<crate::lib::std::ops::RangeFrom<usize>> for Range {
87 #[inline(always)]
88 fn from(range: crate::lib::std::ops::RangeFrom<usize>) -> Self {
89 let start_inclusive: usize = range.start;
90 let end_inclusive: Option = None;
91 Self::raw(start_inclusive, end_inclusive)
92 }
93}
94
95impl From<crate::lib::std::ops::RangeTo<usize>> for Range {
96 #[inline(always)]
97 fn from(range: crate::lib::std::ops::RangeTo<usize>) -> Self {
98 let start_inclusive: usize = 0;
99 let end_inclusive: Option = Some(range.end.saturating_sub(1));
100 Self::raw(start_inclusive, end_inclusive)
101 }
102}
103
104impl From<crate::lib::std::ops::RangeInclusive<usize>> for Range {
105 #[inline(always)]
106 fn from(range: crate::lib::std::ops::RangeInclusive<usize>) -> Self {
107 let start_inclusive: usize = *range.start();
108 let end_inclusive: Option = Some(*range.end());
109 Self::raw(start_inclusive, end_inclusive)
110 }
111}
112
113impl From<crate::lib::std::ops::RangeToInclusive<usize>> for Range {
114 #[inline(always)]
115 fn from(range: crate::lib::std::ops::RangeToInclusive<usize>) -> Self {
116 let start_inclusive: usize = 0;
117 let end_inclusive: Option = Some(range.end);
118 Self::raw(start_inclusive, end_inclusive)
119 }
120}
121
122impl crate::lib::std::fmt::Display for Range {
123 fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result {
124 self.start_inclusive.fmt(f)?;
125 match self.end_inclusive {
126 Some(e: usize) if e == self.start_inclusive => {}
127 Some(e: usize) => {
128 "..=".fmt(f)?;
129 e.fmt(f)?;
130 }
131 None => {
132 "..".fmt(f)?;
133 }
134 }
135 Ok(())
136 }
137}
138
139impl crate::lib::std::fmt::Debug for Range {
140 fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result {
141 write!(f, "{self}")
142 }
143}
144