1+ use std:: path:: Path ;
2+
13use convert_case:: { Case , Casing } ;
24use proc_macro2:: TokenStream ;
35use quote:: format_ident;
@@ -39,31 +41,43 @@ impl Operator {
3941
4042 fn gen_helper ( & self ) -> TokenStream {
4143 let name_text = & self . name ;
42- let name_ident = format_ident ! ( "{}" , name_text. to_case( Case :: Pascal ) ) ;
43- let constr_ident = format_ident ! ( "{}" , name_text. to_case( Case :: Snake ) ) ;
44+ let ident_base = match name_text. as_str ( ) {
45+ "in" => "searchIn" ,
46+ _ => name_text,
47+ } ;
48+ let name_ident = format_ident ! ( "{}" , ident_base. to_case( Case :: Pascal ) ) ;
49+ let constr_ident = format_ident ! ( "{}" , ident_base. to_case( Case :: Snake ) ) ;
4450
4551 let mut required_args = TokenStream :: new ( ) ;
52+ let mut required_arg_names = TokenStream :: new ( ) ;
4653 let mut init_doc = TokenStream :: new ( ) ;
4754 let mut setters = TokenStream :: new ( ) ;
4855
4956 for arg in & self . arguments {
50- let ident = format_ident ! ( "{}" , arg. name. to_case( Case :: Snake ) ) ;
51- let rust_type = arg. rust_type ( ) ;
57+ let ident = format_ident ! (
58+ "{}" ,
59+ match arg. name. as_str( ) {
60+ // `box` is a reserved word
61+ "box" => "geo_box" . to_owned( ) ,
62+ _ => arg. name. to_case( Case :: Snake ) ,
63+ }
64+ ) ;
65+ let rust_type = arg. rust_type ( & self . name ) ;
5266 let type_ = rust_type. tokens ( ) ;
5367 let arg_name = & arg. name ;
5468 let init_expr = rust_type. bson_expr ( & ident) ;
5569
5670 if arg. optional . unwrap_or ( false ) {
57- let tvars = rust_type. variables ( ) ;
5871 setters. push ( parse_quote ! {
5972 #[ allow( missing_docs) ]
60- pub fn #ident<#tvars> ( mut self , #ident: #type_) -> Self {
61- self . stage . insert( #arg_name, #init_expr) ;
73+ pub fn #ident( mut self , #ident: #type_) -> Self {
74+ self . spec . insert( #arg_name, #init_expr) ;
6275 self
6376 }
6477 } ) ;
6578 } else {
6679 required_args. push ( parse_quote ! { #ident : #type_, } ) ;
80+ required_arg_names. push ( parse_quote ! { #ident, } ) ;
6781 init_doc. push ( parse_quote ! { #arg_name : #init_expr, } ) ;
6882 }
6983 }
@@ -73,21 +87,27 @@ impl Operator {
7387 "For more details, see the [{name_text} operator reference]({})." ,
7488 self . link
7589 ) ;
90+ let struct_doc = format ! (
91+ "`{name_text}` Atlas Search operator. Construct with \
92+ [`{constr_ident}`]({constr_ident}())."
93+ ) ;
7694 parse_quote ! {
77- #[ allow ( missing_docs ) ]
95+ #[ doc = #struct_doc ]
7896 pub struct #name_ident;
7997
80- impl AtlasSearch <#name_ident> {
81- #[ doc = #desc]
82- #[ doc = "" ]
83- #[ doc = #link]
84- pub fn #constr_ident( #required_args) -> Self {
85- AtlasSearch {
86- name: #name_text,
87- stage: doc! { #init_doc } ,
88- _t: PhantomData ,
89- }
90- }
98+ #[ doc = #desc]
99+ #[ doc = "" ]
100+ #[ doc = #link]
101+ #[ options_doc( #constr_ident, "into_stage" ) ]
102+ pub fn #constr_ident( #required_args) -> SearchOperator <#name_ident> {
103+ SearchOperator :: new(
104+ #name_text,
105+ doc! { #init_doc } ,
106+ )
107+ }
108+
109+ #[ export_doc( #constr_ident) ]
110+ impl SearchOperator <#name_ident> {
91111 #setters
92112 }
93113 }
@@ -107,80 +127,114 @@ struct Argument {
107127#[ derive( Debug , Deserialize ) ]
108128#[ serde( rename_all = "camelCase" ) ]
109129enum ArgumentType {
110- String ,
111- Object ,
112- SearchScore ,
113- SearchPath ,
114- SearchOperator ,
130+ Any ,
115131 Array ,
132+ BinData ,
133+ Bool ,
134+ Date ,
135+ Geometry ,
116136 Int ,
137+ Null ,
138+ Number ,
139+ Object ,
140+ ObjectId ,
141+ SearchOperator ,
142+ SearchPath ,
143+ SearchScore ,
144+ String ,
117145}
118146
119- static QUERY : & str = "query" ;
120- static TOKEN_ORDER : & str = "tokenOrder" ;
121- static MATCH_CRITERIA : & str = "matchCriteria" ;
122-
123147impl Argument {
124- fn rust_type ( & self ) -> ArgumentRustType {
125- if self . name == QUERY {
126- return ArgumentRustType :: StringOrArray ;
127- }
128- if self . name == TOKEN_ORDER {
129- return ArgumentRustType :: TokenOrder ;
130- }
131- if self . name == MATCH_CRITERIA {
132- return ArgumentRustType :: MatchCriteria ;
148+ fn rust_type ( & self , operator : & str ) -> ArgumentRustType {
149+ match ( operator, self . name . as_str ( ) ) {
150+ ( "autocomplete" | "text" , "query" ) => return ArgumentRustType :: StringOrArray ,
151+ ( "autocomplete" , "tokenOrder" ) => return ArgumentRustType :: TokenOrder ,
152+ ( "text" , "matchCriteria" ) => return ArgumentRustType :: MatchCriteria ,
153+ ( "equals" , "value" ) => return ArgumentRustType :: IntoBson ,
154+ ( "geoShape" , "relation" ) => return ArgumentRustType :: Relation ,
155+ ( "range" , "gt" | "gte" | "lt" | "lte" ) => return ArgumentRustType :: RangeValue ,
156+ ( "near" , "origin" ) => return ArgumentRustType :: NearOrigin ,
157+ _ => ( ) ,
133158 }
159+ use ArgumentType :: * ;
134160 match self . type_ . as_slice ( ) {
135- [ ArgumentType :: String ] => ArgumentRustType :: String ,
136- [ ArgumentType :: Object ] => ArgumentRustType :: Document ,
137- [ ArgumentType :: SearchScore ] => ArgumentRustType :: Document ,
138- [ ArgumentType :: SearchPath ] => ArgumentRustType :: StringOrArray ,
139- [ ArgumentType :: SearchOperator , ArgumentType :: Array ] => ArgumentRustType :: Operator ,
140- [ ArgumentType :: Int ] => ArgumentRustType :: I32 ,
161+ [ String ] => ArgumentRustType :: String ,
162+ [ Object ] => ArgumentRustType :: Document ,
163+ [ SearchScore ] => ArgumentRustType :: Document ,
164+ [ SearchPath ] => ArgumentRustType :: StringOrArray ,
165+ [ SearchOperator ] => ArgumentRustType :: SearchOperator ,
166+ [ SearchOperator , Array ] => ArgumentRustType :: SeachOperatorIter ,
167+ [ Int ] => ArgumentRustType :: I32 ,
168+ [ Geometry ] => ArgumentRustType :: Document ,
169+ [ Any , Array ] => ArgumentRustType :: IntoBson ,
170+ [ Object , Array ] => ArgumentRustType :: DocumentOrArray ,
171+ [ Number ] => ArgumentRustType :: BsonNumber ,
172+ [ String , Array ] => ArgumentRustType :: StringOrArray ,
173+ [ Bool ] => ArgumentRustType :: Bool ,
141174 _ => panic ! ( "Unexpected argument types: {:?}" , self . type_) ,
142175 }
143176 }
144177}
145178
146179enum ArgumentRustType {
147- String ,
180+ Bool ,
181+ BsonNumber ,
148182 Document ,
183+ DocumentOrArray ,
184+ I32 ,
185+ IntoBson ,
186+ MatchCriteria ,
187+ NearOrigin ,
188+ RangeValue ,
189+ Relation ,
190+ SearchOperator ,
191+ SeachOperatorIter ,
192+ String ,
149193 StringOrArray ,
150194 TokenOrder ,
151- MatchCriteria ,
152- Operator ,
153- I32 ,
154195}
155196
156197impl ArgumentRustType {
157198 fn tokens ( & self ) -> syn:: Type {
158199 match self {
159- Self :: String => parse_quote ! { impl AsRef <str > } ,
200+ Self :: Bool => parse_quote ! { bool } ,
201+ Self :: BsonNumber => parse_quote ! { impl BsonNumber } ,
160202 Self :: Document => parse_quote ! { Document } ,
203+ Self :: DocumentOrArray => parse_quote ! { impl DocumentOrArray } ,
204+ Self :: I32 => parse_quote ! { i32 } ,
205+ Self :: IntoBson => parse_quote ! { impl Into <Bson > } ,
206+ Self :: MatchCriteria => parse_quote ! { MatchCriteria } ,
207+ Self :: NearOrigin => parse_quote ! { impl NearOrigin } ,
208+ Self :: RangeValue => parse_quote ! { impl RangeValue } ,
209+ Self :: Relation => parse_quote ! { Relation } ,
210+ Self :: SearchOperator => parse_quote ! { impl SearchOperatorParam } ,
211+ Self :: SeachOperatorIter => {
212+ parse_quote ! { impl IntoIterator <Item = impl SearchOperatorParam > }
213+ }
214+ Self :: String => parse_quote ! { impl AsRef <str > } ,
161215 Self :: StringOrArray => parse_quote ! { impl StringOrArray } ,
162216 Self :: TokenOrder => parse_quote ! { TokenOrder } ,
163- Self :: MatchCriteria => parse_quote ! { MatchCriteria } ,
164- Self :: Operator => parse_quote ! { impl IntoIterator <Item = AtlasSearch <T >> } ,
165- Self :: I32 => parse_quote ! { i32 } ,
166- }
167- }
168-
169- fn variables ( & self ) -> TokenStream {
170- match self {
171- Self :: Operator => parse_quote ! { T } ,
172- _ => parse_quote ! { } ,
173217 }
174218 }
175219
176220 fn bson_expr ( & self , ident : & syn:: Ident ) -> syn:: Expr {
177221 match self {
222+ Self :: Document | Self :: I32 | Self :: Bool => parse_quote ! { #ident } ,
223+ Self :: IntoBson => parse_quote ! { #ident. into( ) } ,
224+ Self :: SeachOperatorIter => {
225+ parse_quote ! { #ident. into_iter( ) . map( |o| o. to_bson( ) ) . collect:: <Vec <_>>( ) }
226+ }
178227 Self :: String => parse_quote ! { #ident. as_ref( ) } ,
179- Self :: StringOrArray => parse_quote ! { #ident. to_bson( ) } ,
180- Self :: TokenOrder | Self :: MatchCriteria => parse_quote ! { #ident. name( ) } ,
181- Self :: Document | Self :: I32 => parse_quote ! { #ident } ,
182- Self :: Operator => {
183- parse_quote ! { #ident. into_iter( ) . map( Document :: from) . collect:: <Vec <_>>( ) }
228+ Self :: StringOrArray
229+ | Self :: DocumentOrArray
230+ | Self :: SearchOperator
231+ | Self :: NearOrigin
232+ | Self :: RangeValue
233+ | Self :: BsonNumber => {
234+ parse_quote ! { #ident. to_bson( ) }
235+ }
236+ Self :: TokenOrder | Self :: MatchCriteria | Self :: Relation => {
237+ parse_quote ! { #ident. name( ) }
184238 }
185239 }
186240 }
@@ -200,11 +254,14 @@ impl TokenStreamExt for TokenStream {
200254
201255fn main ( ) {
202256 let mut operators = TokenStream :: new ( ) ;
203- for path in [
204- "yaml/search/autocomplete.yaml" ,
205- "yaml/search/text.yaml" ,
206- "yaml/search/compound.yaml" ,
207- ] {
257+ let mut paths = Path :: new ( "yaml/search" )
258+ . read_dir ( )
259+ . unwrap ( )
260+ . map ( |e| e. unwrap ( ) . path ( ) )
261+ . filter ( |p| p. extension ( ) . is_some_and ( |e| e == "yaml" ) )
262+ . collect :: < Vec < _ > > ( ) ;
263+ paths. sort ( ) ;
264+ for path in paths {
208265 let contents = std:: fs:: read_to_string ( path) . unwrap ( ) ;
209266 let parsed = serde_yaml:: from_str :: < Operator > ( & contents)
210267 . unwrap ( )
@@ -215,6 +272,7 @@ fn main() {
215272 let file = parse_quote ! {
216273 //! This file was autogenerated. Do not manually edit.
217274 use super :: * ;
275+ use mongodb_internal_macros:: { export_doc, options_doc} ;
218276
219277 #operators
220278 } ;
0 commit comments