1use super::PyBufferContiguity;
2
3pub(super) const CONTIGUITY_UNDEFINED: u8 = PyBufferContiguity::Undefined as u8;
4pub(super) const CONTIGUITY_C: u8 = PyBufferContiguity::C as u8;
5pub(super) const CONTIGUITY_F: u8 = PyBufferContiguity::F as u8;
6pub(super) const CONTIGUITY_ANY: u8 = PyBufferContiguity::Any as u8;
7
8pub struct PyBufferFlags<
9 const FORMAT: bool,
10 const SHAPE: bool,
11 const STRIDE: bool,
12 const INDIRECT: bool,
13 const WRITABLE: bool,
14 const CONTIGUITY: u8,
15>;
16
17#[diagnostic::on_unimplemented(
18 message = "format information has already been requested for this buffer request",
19 note = "remove the extra `.format()` call"
20)]
21pub trait CanRequestFormat {}
22#[diagnostic::do_not_recommend]
23impl<
24 const SHAPE: bool,
25 const STRIDE: bool,
26 const INDIRECT: bool,
27 const WRITABLE: bool,
28 const CONTIGUITY: u8,
29> CanRequestFormat for PyBufferFlags<false, SHAPE, STRIDE, INDIRECT, WRITABLE, CONTIGUITY>
30{
31}
32
33#[diagnostic::on_unimplemented(
34 message = "shape information has already been requested for this buffer request",
35 note = "remove the extra `.nd()` call"
36)]
37pub trait CanRequestShape {}
38#[diagnostic::do_not_recommend]
39impl<
40 const FORMAT: bool,
41 const STRIDE: bool,
42 const INDIRECT: bool,
43 const WRITABLE: bool,
44 const CONTIGUITY: u8,
45> CanRequestShape for PyBufferFlags<FORMAT, false, STRIDE, INDIRECT, WRITABLE, CONTIGUITY>
46{
47}
48
49#[diagnostic::on_unimplemented(
50 message = "stride information has already been requested for this buffer request",
51 note = "remove the extra `.strides()` call"
52)]
53pub trait CanRequestStrides {}
54#[diagnostic::do_not_recommend]
55impl<
56 const FORMAT: bool,
57 const SHAPE: bool,
58 const INDIRECT: bool,
59 const WRITABLE: bool,
60 const CONTIGUITY: u8,
61> CanRequestStrides for PyBufferFlags<FORMAT, SHAPE, false, INDIRECT, WRITABLE, CONTIGUITY>
62{
63}
64
65#[diagnostic::on_unimplemented(
66 message = "suboffsets can only be requested on a direct unconstrained buffer request",
67 note = "call `.indirect()` before any contiguity builder, and only once"
68)]
69pub trait CanRequestIndirect {}
70#[diagnostic::do_not_recommend]
71impl<const FORMAT: bool, const SHAPE: bool, const STRIDE: bool, const WRITABLE: bool>
72 CanRequestIndirect
73 for PyBufferFlags<FORMAT, SHAPE, STRIDE, false, WRITABLE, { CONTIGUITY_UNDEFINED }>
74{
75}
76
77#[diagnostic::on_unimplemented(
78 message = "writability has already been requested for this buffer request",
79 note = "remove the extra `.writable()` call"
80)]
81pub trait CanRequestWritable {}
82#[diagnostic::do_not_recommend]
83impl<
84 const FORMAT: bool,
85 const SHAPE: bool,
86 const STRIDE: bool,
87 const INDIRECT: bool,
88 const CONTIGUITY: u8,
89> CanRequestWritable for PyBufferFlags<FORMAT, SHAPE, STRIDE, INDIRECT, false, CONTIGUITY>
90{
91}
92
93#[diagnostic::on_unimplemented(
94 message = "contiguity has already been constrained for this buffer request",
95 note = "only one of `.c_contiguous()`, `.f_contiguous()`, or `.any_contiguous()` may be used"
96)]
97pub trait CanRequestContiguity {}
98#[diagnostic::do_not_recommend]
99impl<
100 const FORMAT: bool,
101 const SHAPE: bool,
102 const STRIDE: bool,
103 const INDIRECT: bool,
104 const WRITABLE: bool,
105> CanRequestContiguity
106 for PyBufferFlags<FORMAT, SHAPE, STRIDE, INDIRECT, WRITABLE, { CONTIGUITY_UNDEFINED }>
107{
108}
109
110#[diagnostic::on_unimplemented(
111 message = "C contiguity is not guaranteed by the requested buffer flags",
112 note = "use `.c_contiguous()` when building a buffer request to guarantee C contiguity"
113)]
114pub trait GuaranteesCContiguous {}
115#[diagnostic::do_not_recommend]
116impl<
117 const FORMAT: bool,
118 const SHAPE: bool,
119 const STRIDE: bool,
120 const INDIRECT: bool,
121 const WRITABLE: bool,
122> GuaranteesCContiguous
123 for PyBufferFlags<FORMAT, SHAPE, STRIDE, INDIRECT, WRITABLE, { CONTIGUITY_C }>
124{
125}
126
127#[diagnostic::on_unimplemented(
128 message = "Fortran contiguity is not guaranteed by the requested buffer flags",
129 note = "use `.f_contiguous()` when building a buffer request to guarantee Fortran contiguity"
130)]
131pub trait GuaranteesFContiguous {}
132#[diagnostic::do_not_recommend]
133impl<
134 const FORMAT: bool,
135 const SHAPE: bool,
136 const STRIDE: bool,
137 const INDIRECT: bool,
138 const WRITABLE: bool,
139> GuaranteesFContiguous
140 for PyBufferFlags<FORMAT, SHAPE, STRIDE, INDIRECT, WRITABLE, { CONTIGUITY_F }>
141{
142}
143
144#[diagnostic::on_unimplemented(
146 message = "format information is not available with the requested buffer flags",
147 note = "use `.format()` when building a buffer request to request format information",
148 note = "`PyBufferRequest::simple()` and `PyBufferRequest::simple().writable()` also imply u8 format"
149)]
150pub trait IncludesFormat {
151 const ASSUME_U8: bool;
152}
153
154#[diagnostic::do_not_recommend]
155impl<
156 const SHAPE: bool,
157 const STRIDE: bool,
158 const INDIRECT: bool,
159 const WRITABLE: bool,
160 const CONTIGUITY: u8,
161> IncludesFormat for PyBufferFlags<true, SHAPE, STRIDE, INDIRECT, WRITABLE, CONTIGUITY>
162{
163 const ASSUME_U8: bool = false;
164}
165
166#[diagnostic::do_not_recommend]
168impl<const WRITABLE: bool> IncludesFormat
169 for PyBufferFlags<false, false, false, false, WRITABLE, { CONTIGUITY_UNDEFINED }>
170{
171 const ASSUME_U8: bool = true;
172}
173
174#[diagnostic::on_unimplemented(
175 message = "shape information is not available with the requested buffer flags",
176 note = "use `.nd()` when building a buffer request to request shape information"
177)]
178pub trait IncludesShape {}
179#[diagnostic::do_not_recommend]
180impl<
181 const FORMAT: bool,
182 const STRIDE: bool,
183 const INDIRECT: bool,
184 const WRITABLE: bool,
185 const CONTIGUITY: u8,
186> IncludesShape for PyBufferFlags<FORMAT, true, STRIDE, INDIRECT, WRITABLE, CONTIGUITY>
187{
188}
189
190#[diagnostic::on_unimplemented(
191 message = "strides information is not available with the requested buffer flags",
192 note = "use `.strides()` when building a buffer request to request stride information"
193)]
194pub trait IncludesStrides {}
195#[diagnostic::do_not_recommend]
196impl<
197 const FORMAT: bool,
198 const SHAPE: bool,
199 const INDIRECT: bool,
200 const WRITABLE: bool,
201 const CONTIGUITY: u8,
202> IncludesStrides for PyBufferFlags<FORMAT, SHAPE, true, INDIRECT, WRITABLE, CONTIGUITY>
203{
204}
205
206#[diagnostic::on_unimplemented(
207 message = "suboffsets information is not available with the requested buffer flags",
208 note = "use `.indirect()` when building a buffer request to request suboffset information"
209)]
210pub trait IncludesSuboffsets {}
211#[diagnostic::do_not_recommend]
212impl<
213 const FORMAT: bool,
214 const SHAPE: bool,
215 const STRIDE: bool,
216 const WRITABLE: bool,
217 const CONTIGUITY: u8,
218> IncludesSuboffsets for PyBufferFlags<FORMAT, SHAPE, STRIDE, true, WRITABLE, CONTIGUITY>
219{
220}
221
222pub trait Sealed {}
223impl<
224 const FORMAT: bool,
225 const SHAPE: bool,
226 const STRIDE: bool,
227 const INDIRECT: bool,
228 const WRITABLE: bool,
229 const CONTIGUITY: u8,
230> Sealed for PyBufferFlags<FORMAT, SHAPE, STRIDE, INDIRECT, WRITABLE, CONTIGUITY>
231{
232}
233
234pub trait PyBufferRequestType: Sealed {
236 const IS_SIMPLE: bool;
238
239 const CONTIGUITY: PyBufferContiguity;
241
242 const WRITABLE: bool;
244
245 type WithFormat: PyBufferRequestType + IncludesFormat;
247
248 type WithShape: PyBufferRequestType + IncludesShape;
250
251 type WithStrides: PyBufferRequestType + IncludesShape + IncludesStrides;
253
254 type WithIndirect: PyBufferRequestType + IncludesShape + IncludesStrides + IncludesSuboffsets;
256
257 type WithWritable: PyBufferRequestType;
259
260 type WithCContiguous: PyBufferRequestType;
262
263 type WithFContiguous: PyBufferRequestType;
265
266 type WithAnyContiguous: PyBufferRequestType;
268}
269
270impl<
271 const FORMAT: bool,
272 const SHAPE: bool,
273 const STRIDE: bool,
274 const INDIRECT: bool,
275 const WRITABLE: bool,
276 const CONTIGUITY_REQ: u8,
277> PyBufferRequestType for PyBufferFlags<FORMAT, SHAPE, STRIDE, INDIRECT, WRITABLE, CONTIGUITY_REQ>
278{
279 const IS_SIMPLE: bool = !FORMAT && !SHAPE;
280
281 const CONTIGUITY: PyBufferContiguity = match CONTIGUITY_REQ {
282 CONTIGUITY_UNDEFINED => PyBufferContiguity::Undefined,
283 CONTIGUITY_C => PyBufferContiguity::C,
284 CONTIGUITY_F => PyBufferContiguity::F,
285 CONTIGUITY_ANY => PyBufferContiguity::Any,
286 _ => panic!("invalid buffer contiguity"),
287 };
288 const WRITABLE: bool = WRITABLE;
289
290 type WithFormat = PyBufferFlags<true, SHAPE, STRIDE, INDIRECT, WRITABLE, CONTIGUITY_REQ>;
291 type WithShape = PyBufferFlags<FORMAT, true, STRIDE, INDIRECT, WRITABLE, CONTIGUITY_REQ>;
292 type WithStrides = PyBufferFlags<FORMAT, true, true, INDIRECT, WRITABLE, CONTIGUITY_REQ>;
293 type WithIndirect = PyBufferFlags<FORMAT, true, true, true, WRITABLE, CONTIGUITY_UNDEFINED>;
294 type WithWritable = PyBufferFlags<FORMAT, SHAPE, STRIDE, INDIRECT, true, CONTIGUITY_REQ>;
295 type WithCContiguous = PyBufferFlags<FORMAT, true, true, false, WRITABLE, CONTIGUITY_C>;
296 type WithFContiguous = PyBufferFlags<FORMAT, true, true, false, WRITABLE, CONTIGUITY_F>;
297 type WithAnyContiguous = PyBufferFlags<FORMAT, true, true, false, WRITABLE, CONTIGUITY_ANY>;
298}