1use std::collections::BTreeMap;
66use std::fmt::Display;
67use std::sync::Arc;
68
69use chrono::DateTime;
70use serde_json::value::Value;
71use serde_json::Number;
72
73#[derive(Debug, Clone, PartialEq, Eq)]
75pub enum CellValue {
76 Null,
78 Bool(bool),
80 Number(Number),
82 String(String),
84 Array(Vec<CellValue>),
86}
87
88pub trait IntoCellValue {
93 fn to_cell_value(&self) -> CellValue;
94}
95
96pub trait StringCellValue {}
98
99impl StringCellValue for String {}
100
101impl<T> IntoCellValue for T
102where
103 T: StringCellValue + Display,
104{
105 fn to_cell_value(&self) -> CellValue {
106 CellValue::String(self.to_string())
107 }
108}
109
110impl IntoCellValue for i8 {
111 fn to_cell_value(&self) -> CellValue {
112 CellValue::Number(serde_json::Number::from(*self))
113 }
114}
115
116impl IntoCellValue for u8 {
117 fn to_cell_value(&self) -> CellValue {
118 CellValue::Number(serde_json::Number::from(*self))
119 }
120}
121
122impl IntoCellValue for i16 {
123 fn to_cell_value(&self) -> CellValue {
124 CellValue::Number(serde_json::Number::from(*self))
125 }
126}
127
128impl IntoCellValue for u16 {
129 fn to_cell_value(&self) -> CellValue {
130 CellValue::Number(serde_json::Number::from(*self))
131 }
132}
133
134impl IntoCellValue for i32 {
135 fn to_cell_value(&self) -> CellValue {
136 CellValue::Number(serde_json::Number::from(*self))
137 }
138}
139
140impl IntoCellValue for u32 {
141 fn to_cell_value(&self) -> CellValue {
142 CellValue::Number(serde_json::Number::from(*self))
143 }
144}
145
146impl IntoCellValue for i64 {
147 fn to_cell_value(&self) -> CellValue {
148 CellValue::Number(serde_json::Number::from(*self))
149 }
150}
151
152impl IntoCellValue for u64 {
153 fn to_cell_value(&self) -> CellValue {
154 CellValue::Number(serde_json::Number::from(*self))
155 }
156}
157
158impl IntoCellValue for isize {
159 fn to_cell_value(&self) -> CellValue {
160 CellValue::Number(serde_json::Number::from(*self))
161 }
162}
163
164impl IntoCellValue for usize {
165 fn to_cell_value(&self) -> CellValue {
166 CellValue::Number(serde_json::Number::from(*self))
167 }
168}
169
170impl IntoCellValue for f32 {
171 fn to_cell_value(&self) -> CellValue {
172 serde_json::Number::from_f64((*self).into())
173 .map(CellValue::Number)
174 .unwrap_or_else(|| CellValue::Null)
175 }
176}
177
178impl IntoCellValue for f64 {
179 fn to_cell_value(&self) -> CellValue {
180 serde_json::Number::from_f64(*self)
181 .map(CellValue::Number)
182 .unwrap_or_else(|| CellValue::Null)
183 }
184}
185
186impl IntoCellValue for bool {
187 fn to_cell_value(&self) -> CellValue {
188 CellValue::Bool(*self)
189 }
190}
191
192impl<T> IntoCellValue for DateTime<T>
193where
194 T: chrono::TimeZone,
195 <T as chrono::TimeZone>::Offset: Display,
196{
197 fn to_cell_value(&self) -> CellValue {
198 CellValue::String(self.to_rfc3339_opts(chrono::SecondsFormat::Micros, true))
199 }
200}
201
202impl<T> IntoCellValue for Option<T>
203where
204 T: IntoCellValue,
205{
206 fn to_cell_value(&self) -> CellValue {
207 if let Some(ref x) = self {
208 x.to_cell_value()
209 } else {
210 CellValue::Null
211 }
212 }
213}
214
215impl<T> IntoCellValue for Vec<T>
216where
217 T: IntoCellValue,
218{
219 fn to_cell_value(&self) -> CellValue {
220 CellValue::Array(self.iter().map(|item| item.to_cell_value()).collect())
221 }
222}
223
224pub trait CellVisitor {
226 fn visit_value(&mut self, name: &str, v: CellValue);
230}
231
232pub trait ColumnVisitor {
234 fn visit_column(&mut self, name: &str);
237}
238
239pub trait IntoRow<'s>: Sized {
242 type Serializer: Serializer<'s, Self>;
243 fn get_serializer() -> Self::Serializer;
244}
245
246pub trait Serializer<'a, T>
251where
252 Self: 'a,
253{
254 fn accept_cell_visitor<V: CellVisitor>(&self, value: &T, visitor: &mut V);
257
258 fn accept_column_visitor<V: ColumnVisitor>(&self, visitor: &mut V);
261
262 fn to_row(&self, value: &T) -> BTreeMap<String, CellValue> {
264 let mut r = RowVisitor {
265 values: BTreeMap::new(),
266 };
267 self.accept_cell_visitor(value, &mut r);
268 r.values
269 }
270
271 fn to_json(&self, value: &T) -> Value {
273 let mut j = JsonVisitor {
274 value: serde_json::map::Map::new(),
275 };
276 self.accept_cell_visitor(value, &mut j);
277 Value::Object(j.value)
278 }
279
280 fn columns(&self) -> Vec<String> {
283 let mut c = ColumnListVisitor { value: Vec::new() };
284 self.accept_column_visitor(&mut c);
285 c.value
286 }
287}
288
289#[doc(hidden)]
290pub trait SelfSerializer<'a>
291where
292 Self: 'a,
293{
294 fn accept_cell_visitor<V: CellVisitor>(&self, visitor: &mut V);
297
298 fn accept_column_visitor<V: ColumnVisitor>(visitor: &mut V);
301}
302
303#[doc(hidden)]
308pub struct DefaultSelfSerializer<T> {
309 _marker: core::marker::PhantomData<T>,
310}
311
312impl<'a, T> IntoRow<'a> for T
313where
314 T: SelfSerializer<'a>,
315{
316 type Serializer = DefaultSelfSerializer<Self>;
317 fn get_serializer() -> Self::Serializer {
318 DefaultSelfSerializer {
319 _marker: Default::default(),
320 }
321 }
322}
323
324impl<'a, T> Serializer<'a, T> for DefaultSelfSerializer<T>
325where
326 T: SelfSerializer<'a>,
327{
328 fn accept_cell_visitor<V: CellVisitor>(&self, value: &T, visitor: &mut V) {
329 value.accept_cell_visitor(visitor)
330 }
331
332 fn accept_column_visitor<V: ColumnVisitor>(&self, visitor: &mut V) {
333 T::accept_column_visitor(visitor)
334 }
335}
336
337impl<'s, T> IntoRow<'s> for Option<T>
338where
339 T: IntoRow<'s>,
340{
341 type Serializer = OptionSerializer;
342 fn get_serializer() -> Self::Serializer {
343 OptionSerializer
344 }
345}
346
347#[doc(hidden)]
348pub struct OptionSerializer;
349
350impl<'s, T> Serializer<'s, Option<T>> for OptionSerializer
351where
352 T: IntoRow<'s>,
353{
354 fn accept_cell_visitor<V: CellVisitor>(&self, value: &Option<T>, visitor: &mut V) {
355 if let Some(item) = value.as_ref() {
356 T::get_serializer().accept_cell_visitor(item, visitor);
357 } else {
358 let mut n = NullColumnVisitor { parent: visitor };
359 T::get_serializer().accept_column_visitor(&mut n);
360 }
361 }
362
363 fn accept_column_visitor<V: ColumnVisitor>(&self, visitor: &mut V) {
364 T::get_serializer().accept_column_visitor(visitor);
365 }
366}
367
368impl<'s, T> IntoRow<'s> for Arc<T>
369where
370 T: IntoRow<'s>,
371{
372 type Serializer = ArcSerializer;
373 fn get_serializer() -> Self::Serializer {
374 ArcSerializer
375 }
376}
377
378#[doc(hidden)]
379pub struct ArcSerializer;
380
381impl<'r, T> Serializer<'r, Arc<T>> for ArcSerializer
382where
383 T: IntoRow<'r>,
384{
385 fn accept_cell_visitor<V: CellVisitor>(&self, value: &Arc<T>, visitor: &mut V) {
386 T::get_serializer().accept_cell_visitor(&*value, visitor);
387 }
388
389 fn accept_column_visitor<V: ColumnVisitor>(&self, visitor: &mut V) {
390 T::get_serializer().accept_column_visitor(visitor);
391 }
392}
393
394pub trait AsForeignKey<'a, 'r>: Sized {
399 type CellReducer: CellReducer<'a, 'r, Self>;
400 fn get_cell_reducer(key: &'a str) -> Self::CellReducer;
401}
402
403impl<'a, 'r, T> AsForeignKey<'a, 'r> for T
404where
405 T: IntoRow<'r>,
406{
407 type CellReducer = SerializerCellReducer<'a, <T as IntoRow<'r>>::Serializer>;
408
409 fn get_cell_reducer(key: &'a str) -> Self::CellReducer {
410 SerializerCellReducer::new(T::get_serializer(), key)
411 }
412}
413
414impl<'a, 'r, T> AsForeignKey<'a, 'r> for Vec<T>
415where
416 T: AsForeignKey<'a, 'r>,
417{
418 type CellReducer = VecCellReducer<<T as AsForeignKey<'a, 'r>>::CellReducer>;
419 fn get_cell_reducer(key: &'a str) -> Self::CellReducer {
420 VecCellReducer {
421 nested: T::get_cell_reducer(key),
422 }
423 }
424}
425
426#[doc(hidden)]
427pub trait CellReducer<'a, 'r, T> {
428 fn reduce_to_cell(&self, value: &T) -> CellValue;
431}
432
433#[doc(hidden)]
434pub struct SerializerCellReducer<'a, S> {
435 serializer: S,
436 key: &'a str,
437}
438
439impl<'a, S> SerializerCellReducer<'a, S> {
440 pub fn new(serializer: S, key: &'a str) -> Self {
441 Self { serializer, key }
442 }
443}
444
445impl<'a, 'r, S, T> CellReducer<'a, 'r, T> for SerializerCellReducer<'a, S>
446where
447 S: Serializer<'r, T>,
448{
449 fn reduce_to_cell(&self, value: &T) -> CellValue {
450 let mut k = ForeignKeyVisitor {
451 target: self.key,
452 value: None,
453 };
454 self.serializer.accept_cell_visitor(value, &mut k);
455 k.value.unwrap_or(CellValue::Null)
456 }
457}
458
459#[doc(hidden)]
460pub struct VecCellReducer<C> {
461 nested: C,
462}
463
464impl<'a, 'r, T, C> CellReducer<'a, 'r, Vec<T>> for VecCellReducer<C>
465where
466 C: CellReducer<'a, 'r, T>,
467{
468 fn reduce_to_cell(&self, value: &Vec<T>) -> CellValue {
469 CellValue::Array(
470 value
471 .iter()
472 .map(|item| self.nested.reduce_to_cell(item))
473 .collect(),
474 )
475 }
476}
477
478#[doc(hidden)]
479pub struct ForeignKeyVisitor<'a> {
480 pub target: &'a str,
481 pub value: Option<CellValue>,
482}
483
484impl<'a> CellVisitor for ForeignKeyVisitor<'a> {
485 fn visit_value(&mut self, name: &str, v: CellValue) {
486 if name == self.target {
487 self.value = Some(v);
488 }
489 }
490}
491
492struct RowVisitor {
493 pub values: BTreeMap<String, CellValue>,
494}
495
496impl CellVisitor for RowVisitor {
497 fn visit_value(&mut self, name: &str, v: CellValue) {
498 self.values.insert(name.to_string(), v);
499 }
500}
501
502impl From<CellValue> for Value {
503 fn from(v: CellValue) -> Self {
504 match v {
505 CellValue::Null => Value::Null,
506 CellValue::Bool(b) => Value::Bool(b),
507 CellValue::Number(n) => Value::Number(n),
508 CellValue::String(s) => Value::String(s),
509 CellValue::Array(a) => Value::Array(a.into_iter().map(|x| x.into()).collect()),
510 }
511 }
512}
513
514struct JsonVisitor {
515 pub value: serde_json::map::Map<String, Value>,
516}
517
518impl CellVisitor for JsonVisitor {
519 fn visit_value(&mut self, name: &str, v: CellValue) {
520 self.value.insert(name.to_string(), v.into());
521 }
522}
523
524struct ColumnListVisitor {
525 pub value: Vec<String>,
526}
527
528impl ColumnVisitor for ColumnListVisitor {
529 fn visit_column(&mut self, name: &str) {
530 self.value.push(name.to_string())
531 }
532}
533
534struct NullColumnVisitor<'a, V> {
535 parent: &'a mut V,
536}
537
538impl<'a, V> ColumnVisitor for NullColumnVisitor<'a, V>
539where
540 V: CellVisitor,
541{
542 fn visit_column(&mut self, name: &str) {
543 self.parent.visit_value(name, CellValue::Null);
544 }
545}
546
547#[cfg_attr(
553 feature = "persian-rug",
554 doc = r##"
555This can be derived via the
556[`IntoRowWithPersianRug`](IntoRowWithPersianRug)
557derive macro for the case of a [`persian-rug`](::persian_rug)
558type.
559"##
560)]
561pub trait IntoRowWithContext<'a, A: 'a>: Sized {
562 type Serializer: Serializer<'a, Self>;
563 fn get_serializer(accessor: A) -> Self::Serializer;
565}
566
567pub trait AsForeignKeyWithContext<'a, 'r, A: 'r>: Sized {
573 type CellReducer: CellReducer<'a, 'r, Self>;
574 fn get_cell_reducer(accessor: A, key: &'a str) -> Self::CellReducer;
575}
576
577impl<'a, 'r, A, T> AsForeignKeyWithContext<'a, 'r, A> for Vec<T>
578where
579 T: AsForeignKeyWithContext<'a, 'r, A>,
580 A: 'r,
581{
582 type CellReducer = VecCellReducer<<T as AsForeignKeyWithContext<'a, 'r, A>>::CellReducer>;
583 fn get_cell_reducer(accessor: A, key: &'a str) -> Self::CellReducer {
584 VecCellReducer {
585 nested: T::get_cell_reducer(accessor, key),
586 }
587 }
588}
589
590impl<'s, T, A> IntoRowWithContext<'s, A> for Option<T>
591where
592 T: IntoRowWithContext<'s, A>,
593 A: 's + Clone,
594{
595 type Serializer = OptionSerializerWithContext<A>;
596 fn get_serializer(access: A) -> Self::Serializer {
597 OptionSerializerWithContext { access }
598 }
599}
600
601impl<'a, 's, T, A> AsForeignKeyWithContext<'a, 's, A> for Option<T>
602where
603 T: IntoRowWithContext<'s, A>,
604 A: 's + Clone,
605{
606 type CellReducer = SerializerCellReducer<'a, OptionSerializerWithContext<A>>;
607 fn get_cell_reducer(access: A, key: &'a str) -> Self::CellReducer {
608 SerializerCellReducer::new(OptionSerializerWithContext { access }, key)
609 }
610}
611
612#[doc(hidden)]
613pub struct OptionSerializerWithContext<A> {
614 access: A,
615}
616
617impl<'s, T, A> Serializer<'s, Option<T>> for OptionSerializerWithContext<A>
618where
619 T: IntoRowWithContext<'s, A>,
620 A: 's + Clone,
621{
622 fn accept_cell_visitor<V: CellVisitor>(&self, value: &Option<T>, visitor: &mut V) {
623 if let Some(item) = value.as_ref() {
624 T::get_serializer(self.access.clone()).accept_cell_visitor(item, visitor);
625 } else {
626 let mut n = NullColumnVisitor { parent: visitor };
627 T::get_serializer(self.access.clone()).accept_column_visitor(&mut n);
628 }
629 }
630
631 fn accept_column_visitor<V: ColumnVisitor>(&self, visitor: &mut V) {
632 T::get_serializer(self.access.clone()).accept_column_visitor(visitor);
633 }
634}
635
636pub use django_query_derive::IntoRow;
637
638#[cfg(feature = "persian-rug")]
639#[cfg_attr(docsrs, doc(cfg(feature = "persian-rug")))]
640pub use crate::persian_rug::IntoRowWithPersianRug;