1use std::marker::PhantomData;
28
29use crate::expr::{Column, ColumnKey, Keyed, Labeled, SqlType};
30use crate::scope::{Here, There};
31
32pub struct RowNil;
34
35pub struct RowCons<K, V, Tail> {
37 value: V,
38 tail: Tail,
39 _key: PhantomData<fn() -> K>,
40}
41
42impl<K, V, Tail> RowCons<K, V, Tail> {
43 pub fn value(&self) -> &V {
48 &self.value
49 }
50
51 pub fn tail(&self) -> &Tail {
53 &self.tail
54 }
55
56 #[doc(hidden)]
57 pub fn new(value: V, tail: Tail) -> Self {
58 RowCons {
59 value,
60 tail,
61 _key: PhantomData,
62 }
63 }
64
65 #[doc(hidden)]
68 pub fn into_cell(self) -> (V, Tail) {
69 (self.value, self.tail)
70 }
71}
72
73mod field {
74 pub trait Sealed<K, Idx> {}
81}
82
83#[diagnostic::on_unimplemented(
92 message = "`{K}` is not in this query's selection",
93 label = "a row can only be read by a key the query selected",
94 note = "add `{K}` to the query's selection list, or `.label(label::..)` the expression you meant. In a generic helper, give each column its own `Idx` parameter, since one shared index matches no row"
95)]
96pub trait Field<K, Idx>: field::Sealed<K, Idx> {
97 type Value;
98 type Rest;
99 fn peek(&self) -> &Self::Value;
100 fn pluck(self) -> (Self::Value, Self::Rest);
101}
102
103impl<K, V, Tail> field::Sealed<K, Here> for RowCons<K, V, Tail> {}
104
105impl<K, V, Tail> Field<K, Here> for RowCons<K, V, Tail> {
106 type Value = V;
107 type Rest = Tail;
108 fn peek(&self) -> &V {
109 &self.value
110 }
111 fn pluck(self) -> (V, Tail) {
112 (self.value, self.tail)
113 }
114}
115
116#[diagnostic::do_not_recommend]
117impl<K, Other, V, Tail, I> field::Sealed<K, There<I>> for RowCons<Other, V, Tail> where
118 Tail: Field<K, I>
119{
120}
121
122impl<K, Other, V, Tail, I> Field<K, There<I>> for RowCons<Other, V, Tail>
123where
124 Tail: Field<K, I>,
125{
126 type Value = <Tail as Field<K, I>>::Value;
127 type Rest = RowCons<Other, V, <Tail as Field<K, I>>::Rest>;
128 fn peek(&self) -> &Self::Value {
129 self.tail.peek()
130 }
131 fn pluck(self) -> (Self::Value, Self::Rest) {
132 let (value, rest) = self.tail.pluck();
133 (value, RowCons::new(self.value, rest))
134 }
135}
136
137#[doc(hidden)]
142pub struct NameChar<const C: char, Rest>(PhantomData<Rest>);
143
144#[doc(hidden)]
146pub struct NameEnd;
147
148#[doc(hidden)]
150#[macro_export]
151macro_rules! type_name {
152 () => { $crate::row::NameEnd };
153 ($c:literal $(, $rest:literal)*) => {
154 $crate::row::NameChar<$c, $crate::type_name!($($rest),*)>
155 };
156}
157
158pub trait Named: named::Sealed {
163 type Name;
164 const NAME: &'static str;
165}
166
167pub(crate) mod named {
168 pub trait Sealed {}
172}
173
174#[doc(hidden)]
175pub use named::Sealed as NamedSealed;
176
177pub trait Spelled: Named {}
182
183pub struct Anon;
186
187#[doc(hidden)]
188impl NamedSealed for Anon {}
189
190impl Named for Anon {
191 type Name = NameEnd;
192 const NAME: &'static str = "?";
193}
194
195pub trait FieldValue {
201 type Value;
202}
203
204mod take_named {
205 pub trait Sealed<F, Idx> {}
207}
208
209#[diagnostic::on_unimplemented(
212 message = "this query's rows have no field matching `{F}`",
213 label = "the selection needs a column of that name, decoding to that type",
214 note = "a computed expression is matched by name only once `.label(label::..)` gives it one, and a LEFT/RIGHT/FULL JOIN makes a column decode as `Option<T>`, so a struct filled from one declares `Option<T>`"
215)]
216pub trait TakeNamed<F, Idx>: take_named::Sealed<F, Idx> {
217 type Value;
218 type Rest;
219 fn take_named(self) -> (Self::Value, Self::Rest);
220}
221
222impl<F, K, V, Tail> take_named::Sealed<F, Here> for RowCons<K, V, Tail>
223where
224 K: Spelled,
225 F: Spelled<Name = <K as Named>::Name> + FieldValue<Value = V>,
226{
227}
228
229impl<F, K, V, Tail> TakeNamed<F, Here> for RowCons<K, V, Tail>
230where
231 K: Spelled,
232 F: Spelled<Name = <K as Named>::Name> + FieldValue<Value = V>,
233{
234 type Value = V;
235 type Rest = Tail;
236 fn take_named(self) -> (V, Tail) {
237 (self.value, self.tail)
238 }
239}
240
241#[diagnostic::do_not_recommend]
242impl<F, K, V, Tail, I> take_named::Sealed<F, There<I>> for RowCons<K, V, Tail> where
243 Tail: TakeNamed<F, I>
244{
245}
246
247impl<F, K, V, Tail, I> TakeNamed<F, There<I>> for RowCons<K, V, Tail>
248where
249 Tail: TakeNamed<F, I>,
250{
251 type Value = <Tail as TakeNamed<F, I>>::Value;
252 type Rest = RowCons<K, V, <Tail as TakeNamed<F, I>>::Rest>;
253 fn take_named(self) -> (Self::Value, Self::Rest) {
254 let (value, rest) = self.tail.take_named();
255 (value, RowCons::new(self.value, rest))
256 }
257}
258
259mod same_name {
260 pub trait Sealed<Other> {}
267
268 impl<A, B> Sealed<B> for A
269 where
270 A: super::Spelled,
271 B: super::Spelled<Name = <A as super::Named>::Name>,
272 {
273 }
274}
275
276#[diagnostic::on_unimplemented(
278 message = "`{Self}` can't stand in for `{Other}`",
279 label = "these two selected items must have the same name",
280 note = "the two lists are compared position by position, so the usual cause is two columns in a different order rather than a wrong name",
281 note = "where a name really does differ, `.label(label::..)` renames whichever side is wrong",
282 note = "an unnamed expression (`Anon`) has no name to match with, so two of them never stand in for each other"
283)]
284pub trait SameNameAs<Other>: same_name::Sealed<Other> {}
285
286#[diagnostic::do_not_recommend]
287impl<A, B> SameNameAs<B> for A
288where
289 A: Spelled,
290 B: Spelled<Name = <A as Named>::Name>,
291{
292}
293
294#[diagnostic::on_unimplemented(
301 message = "these two selections don't produce the same row",
302 label = "must select the same names, in the same order, decoding to the same types",
303 note = "the two lists are walked together, so what fails is one position. Compare them in order"
304)]
305pub trait SameShape<Other> {}
306
307impl SameShape<RowNil> for RowNil {}
312
313impl<K1, K2, V, Tail1, Tail2> SameShape<RowCons<K2, V, Tail2>> for RowCons<K1, V, Tail1>
314where
315 K1: SameNameAs<K2>,
316 Tail1: SameShape<Tail2>,
317{
318}
319
320impl<A, B> SameShape<Row<B>> for Row<A> where A: SameShape<B> {}
321
322pub trait RowKey {
329 type Key;
330}
331
332#[diagnostic::do_not_recommend]
333impl<C: ColumnKey> RowKey for Column<C> {
334 type Key = C;
335}
336
337#[diagnostic::do_not_recommend]
338impl<K, Req, S: SqlType> RowKey for Keyed<K, Req, S> {
339 type Key = K;
340}
341
342#[diagnostic::do_not_recommend]
343impl<K, Inner> RowKey for Labeled<K, Inner> {
344 type Key = K;
345}
346
347mod column_names {
348 pub trait Sealed {}
353}
354
355pub trait ColumnNames: column_names::Sealed {
360 #[doc(hidden)]
363 fn push_names(out: &mut Vec<&'static str>);
364
365 fn names() -> Vec<&'static str> {
366 let mut out = Vec::new();
367 Self::push_names(&mut out);
368 out
369 }
370}
371
372impl column_names::Sealed for RowNil {}
373
374impl ColumnNames for RowNil {
375 fn push_names(_out: &mut Vec<&'static str>) {}
376}
377
378impl<K: Named, V, Tail: ColumnNames> column_names::Sealed for RowCons<K, V, Tail> {}
379
380impl<K: Named, V, Tail: ColumnNames> ColumnNames for RowCons<K, V, Tail> {
381 fn push_names(out: &mut Vec<&'static str>) {
382 out.push(<K as Named>::NAME);
383 Tail::push_names(out);
384 }
385}
386
387#[diagnostic::on_unimplemented(
394 message = "`{Self}` doesn't name a field",
395 label = "an unlabelled expression has no name to look up",
396 note = "give it one with `.label(label::..)`, or read it positionally with `into_tuple()`"
397)]
398pub trait LookupKey: RowKey {}
399
400#[diagnostic::do_not_recommend]
401impl<C: ColumnKey> LookupKey for Column<C> {}
402#[diagnostic::do_not_recommend]
403impl<K: Spelled, Req, S: SqlType> LookupKey for Keyed<K, Req, S> {}
404#[diagnostic::do_not_recommend]
405impl<K: Spelled, Inner> LookupKey for Labeled<K, Inner> {}
406
407pub struct Row<L>(L);
410
411impl<L> Row<L> {
412 #[doc(hidden)]
413 pub fn new(fields: L) -> Self {
414 Row(fields)
415 }
416
417 pub fn fields(&self) -> &L {
421 &self.0
422 }
423
424 pub fn get<K: LookupKey, Idx>(&self, _key: K) -> &<L as Field<K::Key, Idx>>::Value
428 where
429 L: Field<K::Key, Idx>,
430 {
431 self.0.peek()
432 }
433
434 pub fn take<K: LookupKey, Idx>(
437 self,
438 _key: K,
439 ) -> (
440 <L as Field<K::Key, Idx>>::Value,
441 Row<<L as Field<K::Key, Idx>>::Rest>,
442 )
443 where
444 L: Field<K::Key, Idx>,
445 {
446 let (value, rest) = self.0.pluck();
447 (value, Row::new(rest))
448 }
449
450 #[doc(hidden)]
454 pub fn peek_key<K, Idx>(&self) -> &<L as Field<K, Idx>>::Value
455 where
456 L: Field<K, Idx>,
457 {
458 self.0.peek()
459 }
460
461 #[doc(hidden)]
465 pub fn take_key<K, Idx>(self) -> (<L as Field<K, Idx>>::Value, Row<<L as Field<K, Idx>>::Rest>)
466 where
467 L: Field<K, Idx>,
468 {
469 let (value, rest) = self.0.pluck();
470 (value, Row::new(rest))
471 }
472
473 #[doc(hidden)]
474 pub fn take_named<F, Idx>(
475 self,
476 ) -> (
477 <L as TakeNamed<F, Idx>>::Value,
478 Row<<L as TakeNamed<F, Idx>>::Rest>,
479 )
480 where
481 L: TakeNamed<F, Idx>,
482 {
483 let (value, rest) = self.0.take_named();
484 (value, Row::new(rest))
485 }
486
487 pub fn into_struct<T, Idxs>(self) -> T
491 where
492 T: FromRow<L, Idxs>,
493 {
494 T::from_row(self)
495 }
496
497 pub fn into_tuple(self) -> L::Values
500 where
501 L: RowValues,
502 {
503 self.0.into_values()
504 }
505}
506
507pub trait DebugFields {
509 fn fmt_fields(&self, f: &mut std::fmt::DebugStruct<'_, '_>);
510}
511
512impl DebugFields for RowNil {
513 fn fmt_fields(&self, _f: &mut std::fmt::DebugStruct<'_, '_>) {}
514}
515
516impl<K: Named, V: std::fmt::Debug, Tail: DebugFields> DebugFields for RowCons<K, V, Tail> {
517 fn fmt_fields(&self, f: &mut std::fmt::DebugStruct<'_, '_>) {
518 f.field(K::NAME, &self.value);
519 self.tail.fmt_fields(f);
520 }
521}
522
523impl<L: DebugFields> std::fmt::Debug for Row<L> {
524 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
525 let mut s = f.debug_struct("Row");
526 self.0.fmt_fields(&mut s);
527 s.finish()
528 }
529}
530
531impl<K, V: Clone, Tail: Clone> Clone for RowCons<K, V, Tail> {
532 fn clone(&self) -> Self {
533 RowCons::new(self.value.clone(), self.tail.clone())
534 }
535}
536
537impl Clone for RowNil {
538 fn clone(&self) -> Self {
539 RowNil
540 }
541}
542
543impl<L: Clone> Clone for Row<L> {
544 fn clone(&self) -> Self {
545 Row(self.0.clone())
546 }
547}
548
549impl<K, V: PartialEq, Tail: PartialEq> PartialEq for RowCons<K, V, Tail> {
550 fn eq(&self, other: &Self) -> bool {
551 self.value == other.value && self.tail == other.tail
552 }
553}
554
555impl PartialEq for RowNil {
556 fn eq(&self, _other: &Self) -> bool {
557 true
558 }
559}
560
561impl<K, V: Eq, Tail: Eq> Eq for RowCons<K, V, Tail> {}
562impl Eq for RowNil {}
563
564impl<L: PartialEq> PartialEq for Row<L> {
565 fn eq(&self, other: &Self) -> bool {
566 self.0 == other.0
567 }
568}
569
570impl<L: Eq> Eq for Row<L> {}
571
572pub trait RowValues {
574 type Values;
575 fn into_values(self) -> Self::Values;
576}
577
578#[diagnostic::on_unimplemented(
581 message = "this row has no positional view",
582 label = "`into_tuple`/`into_tuples` stop at 32 fields, however they were selected",
583 note = "read it by key (`row.get(..)`) or fill a struct with `#[derive(FromRow)]`"
584)]
585pub trait Prepend<H> {
586 type Output;
587 fn prepend(self, head: H) -> Self::Output;
588}
589
590impl<H> Prepend<H> for () {
591 type Output = (H,);
592 fn prepend(self, head: H) -> (H,) {
593 (head,)
594 }
595}
596
597macro_rules! prepend_impls {
598 () => {};
599 ($first:ident $(, $rest:ident)*) => {
600 #[allow(non_snake_case)]
601 impl<H, $first $(, $rest)*> Prepend<H> for ($first, $($rest,)*) {
602 type Output = (H, $first, $($rest,)*);
603 fn prepend(self, head: H) -> Self::Output {
604 let ($first, $($rest,)*) = self;
605 (head, $first, $($rest,)*)
606 }
607 }
608 prepend_impls!($($rest),*);
609 };
610}
611prepend_impls!(
612 T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21,
613 T22, T23, T24, T25, T26, T27, T28, T29, T30, T31
614);
615
616impl RowValues for RowNil {
617 type Values = ();
618 fn into_values(self) {}
619}
620
621impl<K, V, Tail> RowValues for RowCons<K, V, Tail>
622where
623 Tail: RowValues,
624 Tail::Values: Prepend<V>,
625{
626 type Values = <Tail::Values as Prepend<V>>::Output;
627 fn into_values(self) -> Self::Values {
628 self.tail.into_values().prepend(self.value)
629 }
630}
631
632pub trait IntoTuples {
634 type Tuples;
635 fn into_tuples(self) -> Self::Tuples;
636}
637
638impl<L: RowValues> IntoTuples for Vec<Row<L>> {
639 type Tuples = Vec<L::Values>;
640 fn into_tuples(self) -> Vec<L::Values> {
641 self.into_iter().map(Row::into_tuple).collect()
642 }
643}
644
645pub trait FromRow<L, Idxs>: Sized {
650 fn from_row(row: Row<L>) -> Self;
651}
652
653pub trait IntoStructs {
655 type Fields;
656 fn into_structs<T, Idxs>(self) -> Vec<T>
657 where
658 T: FromRow<Self::Fields, Idxs>;
659}
660
661impl<L> IntoStructs for Vec<Row<L>> {
662 type Fields = L;
663 fn into_structs<T, Idxs>(self) -> Vec<T>
664 where
665 T: FromRow<L, Idxs>,
666 {
667 self.into_iter().map(Row::into_struct).collect()
668 }
669}
670
671macro_rules! expr_key {
675 ($key:ident, $accessor:ident, $method:ident, $doc:literal, $($ch:literal),+) => {
676 #[doc = $doc]
677 #[derive(Clone, Copy)]
678 pub struct $key;
679
680 #[doc(hidden)]
681 impl $crate::row::NamedSealed for $key {}
682
683 #[doc(hidden)]
684 impl $crate::row::Named for $key {
685 type Name = $crate::type_name!($($ch),+);
686 const NAME: &'static str = concat!($($ch),+);
687 }
688
689 #[doc(hidden)]
690 impl $crate::row::Spelled for $key {}
691
692 #[doc = $doc]
693 pub trait $accessor<Idx> {
694 type Value;
695 fn $method(&self) -> &Self::Value;
696 }
697
698 impl<L, Idx> $accessor<Idx> for $crate::row::Row<L>
699 where
700 L: $crate::row::Field<$key, Idx>,
701 {
702 type Value = <L as $crate::row::Field<$key, Idx>>::Value;
703 fn $method(&self) -> &Self::Value {
704 self.peek_key::<$key, Idx>()
705 }
706 }
707 };
708}
709pub(crate) use expr_key;