juniper_eager_loading/
association.rs

1use crate::{HasMany, HasManyThrough, HasOne, HasOneInner, OptionHasOne};
2
3/// Methods available for all association types.
4pub trait Association<T> {
5    /// Store the loaded child on the association.
6    fn loaded_child(&mut self, child: T);
7
8    /// The association should have been loaded by now, if not store an error inside the
9    /// association (if applicable for the particular association).
10    fn assert_loaded_otherwise_failed(&mut self);
11}
12
13// --
14// -- impl for HasOne
15// --
16impl<T> Association<T> for HasOne<T> {
17    fn loaded_child(&mut self, child: T) {
18        has_one_loaded_child(self, child)
19    }
20
21    fn assert_loaded_otherwise_failed(&mut self) {
22        has_one_assert_loaded_otherwise_failed(self)
23    }
24}
25
26impl<T> Association<T> for HasOne<Box<T>> {
27    fn loaded_child(&mut self, child: T) {
28        has_one_loaded_child(self, Box::new(child))
29    }
30
31    fn assert_loaded_otherwise_failed(&mut self) {
32        has_one_assert_loaded_otherwise_failed(self)
33    }
34}
35
36fn has_one_loaded_child<T>(association: &mut HasOne<T>, child: T) {
37    std::mem::replace(&mut association.0, HasOneInner::Loaded(child));
38}
39
40fn has_one_assert_loaded_otherwise_failed<T>(association: &mut HasOne<T>) {
41    association.0.assert_loaded_otherwise_failed()
42}
43
44// --
45// -- impl for OptionHasOne
46// --
47impl<T> Association<T> for OptionHasOne<T> {
48    fn loaded_child(&mut self, child: T) {
49        option_has_one_loaded_child(self, Some(child));
50    }
51
52    fn assert_loaded_otherwise_failed(&mut self) {
53        option_has_one_assert_loaded_otherwise_failed(self)
54    }
55}
56
57impl<T> Association<T> for OptionHasOne<Box<T>> {
58    fn loaded_child(&mut self, child: T) {
59        option_has_one_loaded_child(self, Some(Box::new(child)));
60    }
61
62    fn assert_loaded_otherwise_failed(&mut self) {
63        option_has_one_assert_loaded_otherwise_failed(self)
64    }
65}
66
67fn option_has_one_loaded_child<T>(association: &mut OptionHasOne<T>, child: Option<T>) {
68    std::mem::replace(&mut association.0, child);
69}
70
71fn option_has_one_assert_loaded_otherwise_failed<T>(association: &mut OptionHasOne<T>) {
72    match association.0 {
73        Some(_) => {}
74        None => {
75            std::mem::replace(&mut association.0, None);
76        }
77    }
78}
79
80// --
81// -- impl for HasMany
82// --
83impl<T> Association<T> for HasMany<T> {
84    fn loaded_child(&mut self, child: T) {
85        self.0.push(child);
86    }
87
88    fn assert_loaded_otherwise_failed(&mut self) {
89        // cannot fail, defaults to an empty vec
90    }
91}
92
93// --
94// -- impl for HasManyThrough
95// --
96impl<T> Association<T> for HasManyThrough<T> {
97    fn loaded_child(&mut self, child: T) {
98        self.0.push(child);
99    }
100
101    fn assert_loaded_otherwise_failed(&mut self) {
102        // cannot fail, defaults to an empty vec
103    }
104}
105
106// NOTE: We don't have to implement Association for HasMany<Box<T>> or HasManyThrough<Box<T>>
107// because they already have indirection through the inner Vec. So recursive types are supported.