1use std::{borrow::Cow, marker::PhantomData};
6
7use async_graphql::{
8 Object, ObjectType, OutputType, TypeName,
9 connection::{
10 ConnectionNameType, CursorType, DefaultConnectionName, DefaultEdgeName, Edge, EdgeNameType,
11 EmptyFields, EnableNodesField, NodesFieldSwitcherSealed, PageInfo,
12 },
13};
14
15pub(crate) struct ScanConnection<
25 Cursor,
26 Node,
27 EdgeFields = EmptyFields,
28 Name = DefaultConnectionName,
29 EdgeName = DefaultEdgeName,
30 NodesField = EnableNodesField,
31> where
32 Cursor: CursorType + Send + Sync,
33 Node: OutputType,
34 EdgeFields: ObjectType,
35 Name: ConnectionNameType,
36 EdgeName: EdgeNameType,
37 NodesField: NodesFieldSwitcherSealed,
38{
39 _mark1: PhantomData<Name>,
40 _mark2: PhantomData<EdgeName>,
41 _mark3: PhantomData<NodesField>,
42 pub edges: Vec<Edge<Cursor, Node, EdgeFields, EdgeName>>,
43 pub has_previous_page: bool,
44 pub has_next_page: bool,
45 pub start_cursor: Option<String>,
46 pub end_cursor: Option<String>,
47}
48
49#[Object(name_type)]
50impl<Cursor, Node, EdgeFields, Name, EdgeName>
51 ScanConnection<Cursor, Node, EdgeFields, Name, EdgeName, EnableNodesField>
52where
53 Cursor: CursorType + Send + Sync,
54 Node: OutputType,
55 EdgeFields: ObjectType,
56 Name: ConnectionNameType,
57 EdgeName: EdgeNameType,
58{
59 async fn page_info(&self) -> PageInfo {
61 PageInfo {
64 has_previous_page: self.has_previous_page,
65 has_next_page: self.has_next_page,
66 start_cursor: self
67 .start_cursor
68 .clone()
69 .or_else(|| self.edges.first().map(|edge| edge.cursor.encode_cursor())),
70 end_cursor: self
71 .end_cursor
72 .clone()
73 .or_else(|| self.edges.last().map(|edge| edge.cursor.encode_cursor())),
74 }
75 }
76
77 #[inline]
79 async fn edges(&self) -> &[Edge<Cursor, Node, EdgeFields, EdgeName>] {
80 &self.edges
81 }
82
83 async fn nodes(&self) -> Vec<&Node> {
85 self.edges.iter().map(|e| &e.node).collect()
86 }
87}
88
89impl<Cursor, Node, NodesField, EdgeFields, Name, EdgeName>
90 ScanConnection<Cursor, Node, EdgeFields, Name, EdgeName, NodesField>
91where
92 Cursor: CursorType + Send + Sync,
93 Node: OutputType,
94 EdgeFields: ObjectType,
95 Name: ConnectionNameType,
96 EdgeName: EdgeNameType,
97 NodesField: NodesFieldSwitcherSealed,
98{
99 #[inline]
101 pub fn new(has_previous_page: bool, has_next_page: bool) -> Self {
102 ScanConnection {
103 _mark1: PhantomData,
104 _mark2: PhantomData,
105 _mark3: PhantomData,
106 edges: Vec::new(),
107 has_previous_page,
108 has_next_page,
109 start_cursor: None,
110 end_cursor: None,
111 }
112 }
113}
114
115impl<Cursor, Node, EdgeFields, Name, EdgeName, NodesField> TypeName
116 for ScanConnection<Cursor, Node, EdgeFields, Name, EdgeName, NodesField>
117where
118 Cursor: CursorType + Send + Sync,
119 Node: OutputType,
120 EdgeFields: ObjectType,
121 Name: ConnectionNameType,
122 EdgeName: EdgeNameType,
123 NodesField: NodesFieldSwitcherSealed,
124{
125 #[inline]
126 fn type_name() -> Cow<'static, str> {
127 Name::type_name::<Node>().into()
128 }
129}