const_format/wrapper_types/
sliced.rs1use crate::{
2 fmt::{Error, Formatter},
3 wrapper_types::AsciiStr,
4};
5
6use core::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
7
8#[cfg_attr(feature = "__docsrs", doc(cfg(feature = "fmt")))]
30pub struct Sliced<T, R>(pub T, pub R);
31
32impl_fmt! {
33 impl['a,] Sliced<&'a str, Range<usize>>;
34 impl['a,] Sliced<&'a str, RangeFrom<usize>>;
35 impl['a,] Sliced<&'a str, RangeFull>;
36 impl['a,] Sliced<&'a str, RangeInclusive<usize>>;
37 impl['a,] Sliced<&'a str, RangeTo<usize>>;
38 impl['a,] Sliced<&'a str, RangeToInclusive<usize>>;
39
40 #[inline]
42 pub const fn const_debug_fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
43 f.write_str_range_debug(self.0, self.range())
44 }
45
46 #[inline]
48 pub const fn const_display_fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
49 f.write_str_range(self.0, self.range())
50 }
51}
52
53impl_fmt! {
54 impl['a,] Sliced<AsciiStr<'a>, Range<usize>>;
55 impl['a,] Sliced<AsciiStr<'a>, RangeFrom<usize>>;
56 impl['a,] Sliced<AsciiStr<'a>, RangeFull>;
57 impl['a,] Sliced<AsciiStr<'a>, RangeInclusive<usize>>;
58 impl['a,] Sliced<AsciiStr<'a>, RangeTo<usize>>;
59 impl['a,] Sliced<AsciiStr<'a>, RangeToInclusive<usize>>;
60
61 #[inline]
63 pub const fn const_debug_fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
64 f.write_ascii_range_debug(self.0, self.range())
65 }
66
67 #[inline]
69 pub const fn const_display_fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
70 f.write_ascii_range(self.0, self.range())
71 }
72}
73
74impl<T> Sliced<T, Range<usize>> {
75 #[inline(always)]
76 const fn range(&self) -> Range<usize> {
77 self.1.start..self.1.end
78 }
79}
80
81impl<T> Sliced<T, RangeFrom<usize>> {
82 #[inline(always)]
83 const fn range(&self) -> Range<usize> {
84 self.1.start..usize::MAX
85 }
86}
87
88impl<T> Sliced<T, RangeFull> {
89 #[inline(always)]
90 const fn range(&self) -> Range<usize> {
91 0..usize::MAX
92 }
93}
94
95const UM: usize = usize::MAX >> 1;
96
97impl<T> Sliced<T, RangeInclusive<usize>> {
98 #[inline(always)]
101 const fn range(&self) -> Range<usize> {
102 *self.1.start()..(*self.1.end() & UM) + 1
103 }
104}
105
106impl<T> Sliced<T, RangeTo<usize>> {
107 #[inline(always)]
108 const fn range(&self) -> Range<usize> {
109 0..self.1.end
110 }
111}
112
113impl<T> Sliced<T, RangeToInclusive<usize>> {
114 #[inline(always)]
117 const fn range(&self) -> Range<usize> {
118 0..(self.1.end & UM) + 1
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 use crate::fmt::{FormattingFlags, StrWriter};
127
128 macro_rules! test_case {
129 (
130 $writer:ident,
131 $str_val:expr,
132 $range:expr,
133 $expected:expr
134 ) => {{
135 const fn inner(fmt: &mut Formatter<'_>) -> Result<(), Error> {
136 let string = Sliced($str_val, $range);
137
138 try_!(string.const_display_fmt(fmt));
139 try_!(fmt.write_str(";"));
140 try_!(string.const_debug_fmt(fmt));
141
142 Ok(())
143 }
144 $writer.clear();
145 inner(&mut $writer.make_formatter(FormattingFlags::NEW)).unwrap();
146
147 assert_eq!($writer.as_str(), $expected, "range = {:?}", $range);
148 }};
149 }
150
151 const S: &str = "\x00\n\t3456789\x06\x07";
152
153 macro_rules! generate_test {
154 ($str_val:expr) => {
155 let writer: &mut StrWriter = &mut StrWriter::new([0u8; 512]);
156
157 test_case!(writer, $str_val, 2..9, "\t345678;\"\\t345678\"");
158
159 test_case!(
160 writer,
161 $str_val,
162 2..,
163 "\t3456789\x06\x07;\"\\t3456789\\x06\\x07\""
164 );
165
166 test_case!(
167 writer,
168 $str_val,
169 ..,
170 "\x00\n\t3456789\x06\x07;\"\\x00\\n\\t3456789\\x06\\x07\""
171 );
172
173 test_case!(
174 writer,
175 $str_val,
176 ..9,
177 "\x00\n\t345678;\"\\x00\\n\\t345678\""
178 );
179
180 test_case!(writer, $str_val, 2..=9, "\t3456789;\"\\t3456789\"");
181 test_case!(
182 writer,
183 $str_val,
184 2..=!0,
185 "\t3456789\x06\x07;\"\\t3456789\\x06\\x07\""
186 );
187
188 test_case!(
189 writer,
190 $str_val,
191 ..=9,
192 "\x00\n\t3456789;\"\\x00\\n\\t3456789\""
193 );
194 test_case!(
195 writer,
196 $str_val,
197 ..=!0,
198 "\x00\n\t3456789\x06\x07;\"\\x00\\n\\t3456789\\x06\\x07\""
199 );
200 };
201 }
202
203 #[test]
204 fn str_tests() {
205 generate_test!(S);
206 }
207 #[test]
208 fn asciistr_tests() {
209 const ASCII: AsciiStr<'_> = ascii_str!(S);
210 generate_test!(ASCII);
211 }
212}