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