1use std::{borrow::Cow, marker::PhantomData};
2
3use super::{DisableNodesField, EnableNodesField, NodesFieldSwitcherSealed};
4use crate::{
5 Object, ObjectType, OutputType, TypeName,
6 connection::{
7 ConnectionNameType, DefaultConnectionName, DefaultEdgeName, EdgeNameType, PageInfo,
8 edge::Edge,
9 },
10 types::connection::{CursorType, EmptyFields},
11};
12
13pub struct Connection<
17 Cursor,
18 Node,
19 ConnectionFields = EmptyFields,
20 EdgeFields = EmptyFields,
21 Name = DefaultConnectionName,
22 EdgeName = DefaultEdgeName,
23 NodesField = EnableNodesField,
24> where
25 Cursor: CursorType + Send + Sync,
26 Node: OutputType,
27 ConnectionFields: ObjectType,
28 EdgeFields: ObjectType,
29 Name: ConnectionNameType,
30 EdgeName: EdgeNameType,
31 NodesField: NodesFieldSwitcherSealed,
32{
33 _mark1: PhantomData<Name>,
34 _mark2: PhantomData<EdgeName>,
35 _mark3: PhantomData<NodesField>,
36 pub edges: Vec<Edge<Cursor, Node, EdgeFields, EdgeName>>,
38 pub additional_fields: ConnectionFields,
40 pub has_previous_page: bool,
42 pub has_next_page: bool,
44}
45
46impl<Cursor, Node, NodesField, EdgeFields, Name, EdgeName>
47 Connection<Cursor, Node, EmptyFields, EdgeFields, Name, EdgeName, NodesField>
48where
49 Cursor: CursorType + Send + Sync,
50 Node: OutputType,
51 EdgeFields: ObjectType,
52 Name: ConnectionNameType,
53 EdgeName: EdgeNameType,
54 NodesField: NodesFieldSwitcherSealed,
55{
56 #[inline]
58 pub fn new(has_previous_page: bool, has_next_page: bool) -> Self {
59 Connection {
60 _mark1: PhantomData,
61 _mark2: PhantomData,
62 _mark3: PhantomData,
63 additional_fields: EmptyFields,
64 has_previous_page,
65 has_next_page,
66 edges: Vec::new(),
67 }
68 }
69}
70
71impl<Cursor, Node, NodesField, ConnectionFields, EdgeFields, Name, EdgeName>
72 Connection<Cursor, Node, ConnectionFields, EdgeFields, Name, EdgeName, NodesField>
73where
74 Cursor: CursorType + Send + Sync,
75 Node: OutputType,
76 ConnectionFields: ObjectType,
77 EdgeFields: ObjectType,
78 Name: ConnectionNameType,
79 EdgeName: EdgeNameType,
80 NodesField: NodesFieldSwitcherSealed,
81{
82 #[inline]
84 pub fn with_additional_fields(
85 has_previous_page: bool,
86 has_next_page: bool,
87 additional_fields: ConnectionFields,
88 ) -> Self {
89 Connection {
90 _mark1: PhantomData,
91 _mark2: PhantomData,
92 _mark3: PhantomData,
93 additional_fields,
94 has_previous_page,
95 has_next_page,
96 edges: Vec::new(),
97 }
98 }
99}
100
101#[Object(internal, name_type, shareable)]
102impl<Cursor, Node, ConnectionFields, EdgeFields, Name, EdgeName>
103 Connection<Cursor, Node, ConnectionFields, EdgeFields, Name, EdgeName, DisableNodesField>
104where
105 Cursor: CursorType + Send + Sync,
106 Node: OutputType,
107 ConnectionFields: ObjectType,
108 EdgeFields: ObjectType,
109 Name: ConnectionNameType,
110 EdgeName: EdgeNameType,
111{
112 async fn page_info(&self) -> PageInfo {
114 PageInfo {
115 has_previous_page: self.has_previous_page,
116 has_next_page: self.has_next_page,
117 start_cursor: self.edges.first().map(|edge| edge.cursor.encode_cursor()),
118 end_cursor: self.edges.last().map(|edge| edge.cursor.encode_cursor()),
119 }
120 }
121
122 #[inline]
124 async fn edges(&self) -> &[Edge<Cursor, Node, EdgeFields, EdgeName>] {
125 &self.edges
126 }
127
128 #[graphql(flatten)]
129 #[inline]
130 async fn additional_fields(&self) -> &ConnectionFields {
131 &self.additional_fields
132 }
133}
134
135#[Object(internal, name_type, shareable)]
136impl<Cursor, Node, ConnectionFields, EdgeFields, Name, EdgeName>
137 Connection<Cursor, Node, ConnectionFields, EdgeFields, Name, EdgeName, EnableNodesField>
138where
139 Cursor: CursorType + Send + Sync,
140 Node: OutputType,
141 ConnectionFields: ObjectType,
142 EdgeFields: ObjectType,
143 Name: ConnectionNameType,
144 EdgeName: EdgeNameType,
145{
146 async fn page_info(&self) -> PageInfo {
148 PageInfo {
149 has_previous_page: self.has_previous_page,
150 has_next_page: self.has_next_page,
151 start_cursor: self.edges.first().map(|edge| edge.cursor.encode_cursor()),
152 end_cursor: self.edges.last().map(|edge| edge.cursor.encode_cursor()),
153 }
154 }
155
156 #[inline]
158 async fn edges(&self) -> &[Edge<Cursor, Node, EdgeFields, EdgeName>] {
159 &self.edges
160 }
161
162 async fn nodes(&self) -> Vec<&Node> {
164 self.edges.iter().map(|e| &e.node).collect()
165 }
166
167 #[graphql(flatten)]
168 #[inline]
169 async fn additional_fields(&self) -> &ConnectionFields {
170 &self.additional_fields
171 }
172}
173
174impl<Cursor, Node, ConnectionFields, EdgeFields, Name, EdgeName, NodesField> TypeName
175 for Connection<Cursor, Node, ConnectionFields, EdgeFields, Name, EdgeName, NodesField>
176where
177 Cursor: CursorType + Send + Sync,
178 Node: OutputType,
179 ConnectionFields: ObjectType,
180 EdgeFields: ObjectType,
181 Name: ConnectionNameType,
182 EdgeName: EdgeNameType,
183 NodesField: NodesFieldSwitcherSealed,
184{
185 #[inline]
186 fn type_name() -> Cow<'static, str> {
187 Name::type_name::<Node>().into()
188 }
189}