1use crate::{Slice, SliceBorrowed, SliceOf, SliceOwned};
2
3macro_rules! either {
4 ( [][$($t:tt)*] ) => {$($t)*};
5 ( [$($t:tt)*][$($_:tt)*] ) => {$($t)*};
6}
7
8macro_rules! def_window {
9 ( $owned:ident, [$($lt:lifetime)?], $sized:ty, $item:ty, $fn:ident ) => {
10 paste::paste! {
11 #[doc = concat!("[`Slice", stringify!($owned), "::windows`].")]
13 #[derive(Clone, Copy)]
14 pub struct [<Windows $owned>]<'a, S: ?Sized> {
15 pub data: &'a S,
17 size: usize,
18 i: usize,
19 }
20
21 impl<'a, S> [<Windows $owned>]<'a, S>
22 where
23 S: [<Slice $owned>] + ?Sized,
24 {
25 #[doc = concat!("[`Slice", stringify!($owned), "::windows`].")]
27 pub fn new(data: &'a S, size: usize) -> Self {
28 if size == 0 {
29 panic!("cannot call `windows` with size = 0");
30 }
31
32 Self {
33 data,
34 size,
35 i: 0,
36 }
37 }
38 }
39
40 impl<'a, S> Slice for [<Windows $owned>]<'a, S>
41 where
42 S: [<Slice $owned>] + ?Sized,
43 {
44 type Output = SliceOf<&'a S>;
45
46 fn len(&self) -> usize {
47 self.data.len() - self.size + 1
48 }
49
50 fn get_with<W: FnMut(&Self::Output) -> R, R>(
51 &self,
52 index: usize,
53 f: &mut W
54 ) -> Option<R> {
55 Some(f(&self.get_owned(index)?))
56 }
57 }
58
59 impl<'a, S> SliceOwned for [<Windows $owned>]<'a, S>
60 where
61 S: [<Slice $owned>] + ?Sized,
62 {
63 fn get_owned(&self, index: usize) -> Option<Self::Output> {
64 if index > Slice::len(self) {
65 None
66 } else {
67 self.data.slice(index..index+self.size)
68 }
69 }
70 }
71
72 impl<'a, S> Iterator for [<Windows $owned>]<'a, S>
73 where
74 S: [<Slice $owned>] + ?Sized,
75 {
76 type Item = SliceOf<&'a S>;
77
78 fn next(&mut self) -> Option<Self::Item> {
79 if self.i > self.data.len() {
80 None
81 } else {
82 let start = self.i;
83 self.i += 1;
84 self.get_owned(start)
85 }
86 }
87
88 fn size_hint(&self) -> (usize, Option<usize>) {
89 let len = Slice::len(self);
90 (len, Some(len))
91 }
92 }
93
94 impl<'a, S> ExactSizeIterator
95 for [<Windows $owned>]<'a, S>
96 where
97 S: [<Slice $owned>] + ?Sized {}
98
99 type [<ArrayWindow $owned>]<$($lt,)? S> = either!([$(&$lt S)?][S]);
100 #[doc = concat!("[`Slice", stringify!($owned), "::array_windows`].")]
102 #[derive(Clone, Copy)]
103 pub struct [<ArrayWindows $owned>]<$($lt,)? S: $sized, const N: usize> {
104 pub data: [<ArrayWindow $owned>]<$($lt,)? S>,
106 i: usize,
107 }
108
109 impl<$($lt,)? S, const N: usize> [<ArrayWindows $owned>]<$($lt,)? S, N>
110 where
111 S: [<Slice $owned>] + $sized,
112 {
113 #[doc = concat!("[`Slice", stringify!($owned), "::array_windows`].")]
115 pub fn new(data: either!([$(&$lt S)?][S])) -> Self {
116 if N == 0 {
118 panic!("cannot call `windows` with size = 0");
119 }
120
121 Self {
122 data,
123 i: 0,
124 }
125 }
126 }
127
128 impl<$($lt,)? S, const N: usize> Slice for [<ArrayWindows $owned>]<$($lt,)? S, N>
129 where
130 S: [<Slice $owned>] + $sized,
131 {
132 type Output = [$item; N];
133
134 fn len(&self) -> usize {
135 self.data.len() - N + 1
136 }
137
138 fn get_with<W: FnMut(&Self::Output) -> R, R>(
139 &self,
140 index: usize,
141 f: &mut W
142 ) -> Option<R> {
143 Some(f(&self.get_owned(index)?))
144 }
145 }
146
147 impl<$($lt,)? S, const N: usize> SliceOwned for [<ArrayWindows $owned>]<$($lt,)? S, N>
148 where
149 S: [<Slice $owned>] + $sized,
150 {
151 fn get_owned(&self, index: usize) -> Option<Self::Output> {
152 if index > Slice::len(self) {
153 None
154 } else {
155 Some(core::array::from_fn(|i| self.data.$fn(index + i).unwrap()))
156 }
157 }
158 }
159
160 impl<$($lt,)? S, const N: usize> Iterator for [<ArrayWindows $owned>]<$($lt,)? S, N>
161 where
162 S: [<Slice $owned>] + $sized,
163 {
164 type Item = [$item; N];
165
166 fn next(&mut self) -> Option<Self::Item> {
167 if self.i + N > self.data.len() {
168 None
169 } else {
170 let start = self.i;
171 self.i += 1;
172 self.get_owned(start)
173 }
174 }
175
176 fn size_hint(&self) -> (usize, Option<usize>) {
177 let len = self.data.len() - N + 1;
178 (len, Some(len))
179 }
180 }
181
182 impl<$($lt,)? S, const N: usize> ExactSizeIterator
183 for [<ArrayWindows $owned>]<$($lt,)? S, N>
184 where
185 S: [<Slice $owned>] + $sized {}
186 }
187 };
188}
189
190def_window!(Owned, [], Sized, S::Output, get_owned);
191def_window!(Borrowed, ['a], ?Sized, &'a S::Output, get);