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> {}
80}
81
82#[diagnostic::on_unimplemented(
91 message = "`{K}` is not in this query's selection",
92 label = "a row can only be read by a key the query selected",
93 note = "add `{K}` to the query's selection list, or `.label(label::..)` the expression you meant — and in a generic helper give each column its own `Idx` parameter, since one shared index matches no row"
94)]
95pub trait Field<K, Idx>: field::Sealed<K, Idx> {
96 type Value;
97 type Rest;
98 fn peek(&self) -> &Self::Value;
99 fn pluck(self) -> (Self::Value, Self::Rest);
100}
101
102impl<K, V, Tail> field::Sealed<K, Here> for RowCons<K, V, Tail> {}
103
104impl<K, V, Tail> Field<K, Here> for RowCons<K, V, Tail> {
105 type Value = V;
106 type Rest = Tail;
107 fn peek(&self) -> &V {
108 &self.value
109 }
110 fn pluck(self) -> (V, Tail) {
111 (self.value, self.tail)
112 }
113}
114
115#[diagnostic::do_not_recommend]
116impl<K, Other, V, Tail, I> field::Sealed<K, There<I>> for RowCons<Other, V, Tail> where
117 Tail: Field<K, I>
118{
119}
120
121impl<K, Other, V, Tail, I> Field<K, There<I>> for RowCons<Other, V, Tail>
122where
123 Tail: Field<K, I>,
124{
125 type Value = <Tail as Field<K, I>>::Value;
126 type Rest = RowCons<Other, V, <Tail as Field<K, I>>::Rest>;
127 fn peek(&self) -> &Self::Value {
128 self.tail.peek()
129 }
130 fn pluck(self) -> (Self::Value, Self::Rest) {
131 let (value, rest) = self.tail.pluck();
132 (value, RowCons::new(self.value, rest))
133 }
134}
135
136#[doc(hidden)]
141pub struct NameChar<const C: char, Rest>(PhantomData<Rest>);
142
143#[doc(hidden)]
145pub struct NameEnd;
146
147#[doc(hidden)]
149#[macro_export]
150macro_rules! type_name {
151 () => { $crate::row::NameEnd };
152 ($c:literal $(, $rest:literal)*) => {
153 $crate::row::NameChar<$c, $crate::type_name!($($rest),*)>
154 };
155}
156
157pub trait Named: named::Sealed {
162 type Name;
163 const NAME: &'static str;
164}
165
166pub(crate) mod named {
167 pub trait Sealed {}
171}
172
173#[doc(hidden)]
174pub use named::Sealed as NamedSealed;
175
176pub trait Spelled: Named {}
181
182pub struct Anon;
185
186#[doc(hidden)]
187impl NamedSealed for Anon {}
188
189impl Named for Anon {
190 type Name = NameEnd;
191 const NAME: &'static str = "?";
192}
193
194pub trait FieldValue {
200 type Value;
201}
202
203mod take_named {
204 pub trait Sealed<F, Idx> {}
206}
207
208#[diagnostic::on_unimplemented(
211 message = "this query's rows have no field matching `{F}`",
212 label = "the selection needs a column of that name, decoding to that type",
213 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>`"
214)]
215pub trait TakeNamed<F, Idx>: take_named::Sealed<F, Idx> {
216 type Value;
217 type Rest;
218 fn take_named(self) -> (Self::Value, Self::Rest);
219}
220
221impl<F, K, V, Tail> take_named::Sealed<F, Here> for RowCons<K, V, Tail>
222where
223 K: Spelled,
224 F: Spelled<Name = <K as Named>::Name> + FieldValue<Value = V>,
225{
226}
227
228impl<F, K, V, Tail> TakeNamed<F, Here> for RowCons<K, V, Tail>
229where
230 K: Spelled,
231 F: Spelled<Name = <K as Named>::Name> + FieldValue<Value = V>,
232{
233 type Value = V;
234 type Rest = Tail;
235 fn take_named(self) -> (V, Tail) {
236 (self.value, self.tail)
237 }
238}
239
240#[diagnostic::do_not_recommend]
241impl<F, K, V, Tail, I> take_named::Sealed<F, There<I>> for RowCons<K, V, Tail> where
242 Tail: TakeNamed<F, I>
243{
244}
245
246impl<F, K, V, Tail, I> TakeNamed<F, There<I>> for RowCons<K, V, Tail>
247where
248 Tail: TakeNamed<F, I>,
249{
250 type Value = <Tail as TakeNamed<F, I>>::Value;
251 type Rest = RowCons<K, V, <Tail as TakeNamed<F, I>>::Rest>;
252 fn take_named(self) -> (Self::Value, Self::Rest) {
253 let (value, rest) = self.tail.take_named();
254 (value, RowCons::new(self.value, rest))
255 }
256}
257
258mod same_name {
259 pub trait Sealed<Other> {}
266
267 impl<A, B> Sealed<B> for A
268 where
269 A: super::Spelled,
270 B: super::Spelled<Name = <A as super::Named>::Name>,
271 {
272 }
273}
274
275#[diagnostic::on_unimplemented(
277 message = "`{Self}` can't stand in for `{Other}`",
278 label = "these two selected items must have the same name",
279 note = "matched by name: `.label(label::..)` whichever side is spelled wrong — and an unnamed expression (`Anon`) has no name to match with at all"
280)]
281pub trait SameNameAs<Other>: same_name::Sealed<Other> {}
282
283#[diagnostic::do_not_recommend]
284impl<A, B> SameNameAs<B> for A
285where
286 A: Spelled,
287 B: Spelled<Name = <A as Named>::Name>,
288{
289}
290
291#[diagnostic::on_unimplemented(
298 message = "these two selections don't produce the same row",
299 label = "must select the same names, in the same order, decoding to the same types"
300)]
301pub trait SameShape<Other> {}
302
303impl SameShape<RowNil> for RowNil {}
308
309impl<K1, K2, V, Tail1, Tail2> SameShape<RowCons<K2, V, Tail2>> for RowCons<K1, V, Tail1>
310where
311 K1: SameNameAs<K2>,
312 Tail1: SameShape<Tail2>,
313{
314}
315
316impl<A, B> SameShape<Row<B>> for Row<A> where A: SameShape<B> {}
317
318pub trait RowKey {
325 type Key;
326}
327
328#[diagnostic::do_not_recommend]
329impl<C: ColumnKey> RowKey for Column<C> {
330 type Key = C;
331}
332
333#[diagnostic::do_not_recommend]
334impl<K, Req, S: SqlType> RowKey for Keyed<K, Req, S> {
335 type Key = K;
336}
337
338#[diagnostic::do_not_recommend]
339impl<K, Inner> RowKey for Labeled<K, Inner> {
340 type Key = K;
341}
342
343mod column_names {
344 pub trait Sealed {}
350}
351
352pub trait ColumnNames: column_names::Sealed {
356 #[doc(hidden)]
359 fn push_names(out: &mut Vec<&'static str>);
360
361 fn names() -> Vec<&'static str> {
362 let mut out = Vec::new();
363 Self::push_names(&mut out);
364 out
365 }
366}
367
368impl column_names::Sealed for RowNil {}
369
370impl ColumnNames for RowNil {
371 fn push_names(_out: &mut Vec<&'static str>) {}
372}
373
374impl<K: Named, V, Tail: ColumnNames> column_names::Sealed for RowCons<K, V, Tail> {}
375
376impl<K: Named, V, Tail: ColumnNames> ColumnNames for RowCons<K, V, Tail> {
377 fn push_names(out: &mut Vec<&'static str>) {
378 out.push(<K as Named>::NAME);
379 Tail::push_names(out);
380 }
381}
382
383#[diagnostic::on_unimplemented(
390 message = "`{Self}` doesn't name a field",
391 label = "an unlabelled expression has no name to look up",
392 note = "give it one with `.label(label::..)`, or read it positionally with `into_tuple()`"
393)]
394pub trait LookupKey: RowKey {}
395
396#[diagnostic::do_not_recommend]
397impl<C: ColumnKey> LookupKey for Column<C> {}
398#[diagnostic::do_not_recommend]
399impl<K: Spelled, Req, S: SqlType> LookupKey for Keyed<K, Req, S> {}
400#[diagnostic::do_not_recommend]
401impl<K: Spelled, Inner> LookupKey for Labeled<K, Inner> {}
402
403pub struct Row<L>(L);
406
407impl<L> Row<L> {
408 #[doc(hidden)]
409 pub fn new(fields: L) -> Self {
410 Row(fields)
411 }
412
413 pub fn fields(&self) -> &L {
417 &self.0
418 }
419
420 pub fn get<K: LookupKey, Idx>(&self, _key: K) -> &<L as Field<K::Key, Idx>>::Value
424 where
425 L: Field<K::Key, Idx>,
426 {
427 self.0.peek()
428 }
429
430 pub fn take<K: LookupKey, Idx>(
433 self,
434 _key: K,
435 ) -> (
436 <L as Field<K::Key, Idx>>::Value,
437 Row<<L as Field<K::Key, Idx>>::Rest>,
438 )
439 where
440 L: Field<K::Key, Idx>,
441 {
442 let (value, rest) = self.0.pluck();
443 (value, Row::new(rest))
444 }
445
446 #[doc(hidden)]
450 pub fn peek_key<K, Idx>(&self) -> &<L as Field<K, Idx>>::Value
451 where
452 L: Field<K, Idx>,
453 {
454 self.0.peek()
455 }
456
457 #[doc(hidden)]
461 pub fn take_key<K, Idx>(self) -> (<L as Field<K, Idx>>::Value, Row<<L as Field<K, Idx>>::Rest>)
462 where
463 L: Field<K, Idx>,
464 {
465 let (value, rest) = self.0.pluck();
466 (value, Row::new(rest))
467 }
468
469 #[doc(hidden)]
470 pub fn take_named<F, Idx>(
471 self,
472 ) -> (
473 <L as TakeNamed<F, Idx>>::Value,
474 Row<<L as TakeNamed<F, Idx>>::Rest>,
475 )
476 where
477 L: TakeNamed<F, Idx>,
478 {
479 let (value, rest) = self.0.take_named();
480 (value, Row::new(rest))
481 }
482
483 pub fn into_struct<T, Idxs>(self) -> T
487 where
488 T: FromRow<L, Idxs>,
489 {
490 T::from_row(self)
491 }
492
493 pub fn into_tuple(self) -> L::Values
496 where
497 L: RowValues,
498 {
499 self.0.into_values()
500 }
501}
502
503pub trait DebugFields {
505 fn fmt_fields(&self, f: &mut std::fmt::DebugStruct<'_, '_>);
506}
507
508impl DebugFields for RowNil {
509 fn fmt_fields(&self, _f: &mut std::fmt::DebugStruct<'_, '_>) {}
510}
511
512impl<K: Named, V: std::fmt::Debug, Tail: DebugFields> DebugFields for RowCons<K, V, Tail> {
513 fn fmt_fields(&self, f: &mut std::fmt::DebugStruct<'_, '_>) {
514 f.field(K::NAME, &self.value);
515 self.tail.fmt_fields(f);
516 }
517}
518
519impl<L: DebugFields> std::fmt::Debug for Row<L> {
520 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
521 let mut s = f.debug_struct("Row");
522 self.0.fmt_fields(&mut s);
523 s.finish()
524 }
525}
526
527impl<K, V: Clone, Tail: Clone> Clone for RowCons<K, V, Tail> {
528 fn clone(&self) -> Self {
529 RowCons::new(self.value.clone(), self.tail.clone())
530 }
531}
532
533impl Clone for RowNil {
534 fn clone(&self) -> Self {
535 RowNil
536 }
537}
538
539impl<L: Clone> Clone for Row<L> {
540 fn clone(&self) -> Self {
541 Row(self.0.clone())
542 }
543}
544
545impl<K, V: PartialEq, Tail: PartialEq> PartialEq for RowCons<K, V, Tail> {
546 fn eq(&self, other: &Self) -> bool {
547 self.value == other.value && self.tail == other.tail
548 }
549}
550
551impl PartialEq for RowNil {
552 fn eq(&self, _other: &Self) -> bool {
553 true
554 }
555}
556
557impl<K, V: Eq, Tail: Eq> Eq for RowCons<K, V, Tail> {}
558impl Eq for RowNil {}
559
560impl<L: PartialEq> PartialEq for Row<L> {
561 fn eq(&self, other: &Self) -> bool {
562 self.0 == other.0
563 }
564}
565
566impl<L: Eq> Eq for Row<L> {}
567
568pub trait RowValues {
570 type Values;
571 fn into_values(self) -> Self::Values;
572}
573
574#[diagnostic::on_unimplemented(
577 message = "this row has no positional view",
578 label = "`into_tuple`/`into_tuples` stop at 32 fields, however they were selected",
579 note = "read it by key (`row.get(..)`) or fill a struct with `#[derive(FromRow)]`"
580)]
581pub trait Prepend<H> {
582 type Output;
583 fn prepend(self, head: H) -> Self::Output;
584}
585
586impl<H> Prepend<H> for () {
587 type Output = (H,);
588 fn prepend(self, head: H) -> (H,) {
589 (head,)
590 }
591}
592
593macro_rules! prepend_impls {
594 () => {};
595 ($first:ident $(, $rest:ident)*) => {
596 #[allow(non_snake_case)]
597 impl<H, $first $(, $rest)*> Prepend<H> for ($first, $($rest,)*) {
598 type Output = (H, $first, $($rest,)*);
599 fn prepend(self, head: H) -> Self::Output {
600 let ($first, $($rest,)*) = self;
601 (head, $first, $($rest,)*)
602 }
603 }
604 prepend_impls!($($rest),*);
605 };
606}
607prepend_impls!(
608 T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21,
609 T22, T23, T24, T25, T26, T27, T28, T29, T30, T31
610);
611
612impl RowValues for RowNil {
613 type Values = ();
614 fn into_values(self) {}
615}
616
617impl<K, V, Tail> RowValues for RowCons<K, V, Tail>
618where
619 Tail: RowValues,
620 Tail::Values: Prepend<V>,
621{
622 type Values = <Tail::Values as Prepend<V>>::Output;
623 fn into_values(self) -> Self::Values {
624 self.tail.into_values().prepend(self.value)
625 }
626}
627
628pub trait IntoTuples {
630 type Tuples;
631 fn into_tuples(self) -> Self::Tuples;
632}
633
634impl<L: RowValues> IntoTuples for Vec<Row<L>> {
635 type Tuples = Vec<L::Values>;
636 fn into_tuples(self) -> Vec<L::Values> {
637 self.into_iter().map(Row::into_tuple).collect()
638 }
639}
640
641pub trait FromRow<L, Idxs>: Sized {
646 fn from_row(row: Row<L>) -> Self;
647}
648
649pub trait IntoStructs {
651 type Fields;
652 fn into_structs<T, Idxs>(self) -> Vec<T>
653 where
654 T: FromRow<Self::Fields, Idxs>;
655}
656
657impl<L> IntoStructs for Vec<Row<L>> {
658 type Fields = L;
659 fn into_structs<T, Idxs>(self) -> Vec<T>
660 where
661 T: FromRow<L, Idxs>,
662 {
663 self.into_iter().map(Row::into_struct).collect()
664 }
665}
666
667macro_rules! expr_key {
671 ($key:ident, $accessor:ident, $method:ident, $doc:literal, $($ch:literal),+) => {
672 #[doc = $doc]
673 #[derive(Clone, Copy)]
674 pub struct $key;
675
676 #[doc(hidden)]
677 impl $crate::row::NamedSealed for $key {}
678
679 #[doc(hidden)]
680 impl $crate::row::Named for $key {
681 type Name = $crate::type_name!($($ch),+);
682 const NAME: &'static str = concat!($($ch),+);
683 }
684
685 #[doc(hidden)]
686 impl $crate::row::Spelled for $key {}
687
688 #[doc = $doc]
689 pub trait $accessor<Idx> {
690 type Value;
691 fn $method(&self) -> &Self::Value;
692 }
693
694 impl<L, Idx> $accessor<Idx> for $crate::row::Row<L>
695 where
696 L: $crate::row::Field<$key, Idx>,
697 {
698 type Value = <L as $crate::row::Field<$key, Idx>>::Value;
699 fn $method(&self) -> &Self::Value {
700 self.peek_key::<$key, Idx>()
701 }
702 }
703 };
704}
705pub(crate) use expr_key;