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 16 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
609);
610
611impl RowValues for RowNil {
612 type Values = ();
613 fn into_values(self) {}
614}
615
616impl<K, V, Tail> RowValues for RowCons<K, V, Tail>
617where
618 Tail: RowValues,
619 Tail::Values: Prepend<V>,
620{
621 type Values = <Tail::Values as Prepend<V>>::Output;
622 fn into_values(self) -> Self::Values {
623 self.tail.into_values().prepend(self.value)
624 }
625}
626
627pub trait IntoTuples {
629 type Tuples;
630 fn into_tuples(self) -> Self::Tuples;
631}
632
633impl<L: RowValues> IntoTuples for Vec<Row<L>> {
634 type Tuples = Vec<L::Values>;
635 fn into_tuples(self) -> Vec<L::Values> {
636 self.into_iter().map(Row::into_tuple).collect()
637 }
638}
639
640pub trait FromRow<L, Idxs>: Sized {
645 fn from_row(row: Row<L>) -> Self;
646}
647
648pub trait IntoStructs {
650 type Fields;
651 fn into_structs<T, Idxs>(self) -> Vec<T>
652 where
653 T: FromRow<Self::Fields, Idxs>;
654}
655
656impl<L> IntoStructs for Vec<Row<L>> {
657 type Fields = L;
658 fn into_structs<T, Idxs>(self) -> Vec<T>
659 where
660 T: FromRow<L, Idxs>,
661 {
662 self.into_iter().map(Row::into_struct).collect()
663 }
664}
665
666macro_rules! expr_key {
670 ($key:ident, $accessor:ident, $method:ident, $doc:literal, $($ch:literal),+) => {
671 #[doc = $doc]
672 #[derive(Clone, Copy)]
673 pub struct $key;
674
675 #[doc(hidden)]
676 impl $crate::row::NamedSealed for $key {}
677
678 #[doc(hidden)]
679 impl $crate::row::Named for $key {
680 type Name = $crate::type_name!($($ch),+);
681 const NAME: &'static str = concat!($($ch),+);
682 }
683
684 #[doc(hidden)]
685 impl $crate::row::Spelled for $key {}
686
687 #[doc = $doc]
688 pub trait $accessor<Idx> {
689 type Value;
690 fn $method(&self) -> &Self::Value;
691 }
692
693 impl<L, Idx> $accessor<Idx> for $crate::row::Row<L>
694 where
695 L: $crate::row::Field<$key, Idx>,
696 {
697 type Value = <L as $crate::row::Field<$key, Idx>>::Value;
698 fn $method(&self) -> &Self::Value {
699 self.peek_key::<$key, Idx>()
700 }
701 }
702 };
703}
704pub(crate) use expr_key;