@@ -50,6 +50,7 @@ pub struct Release {
5050 pub ( crate ) build_time : Option < DateTime < Utc > > ,
5151 pub ( crate ) stars : i32 ,
5252 pub ( crate ) has_unyanked_releases : Option < bool > ,
53+ pub ( crate ) href : Option < & ' static str > ,
5354}
5455
5556#[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
@@ -124,6 +125,7 @@ pub(crate) async fn get_releases(
124125 build_time : row. get ( 5 ) ,
125126 stars : row. get :: < Option < i32 > , _ > ( 6 ) . unwrap_or ( 0 ) ,
126127 has_unyanked_releases : None ,
128+ href : None ,
127129 } )
128130 . try_collect ( )
129131 . await ?)
@@ -142,13 +144,28 @@ struct SearchResult {
142144 pub next_page : Option < String > ,
143145}
144146
147+ fn rust_lib_release ( name : & str , description : & str , href : & ' static str ) -> ReleaseStatus {
148+ ReleaseStatus :: Available ( Release {
149+ name : name. to_string ( ) ,
150+ version : String :: new ( ) ,
151+ description : Some ( description. to_string ( ) ) ,
152+ build_time : None ,
153+ target_name : None ,
154+ rustdoc_status : false ,
155+ stars : 0 ,
156+ has_unyanked_releases : None ,
157+ href : Some ( href) ,
158+ } )
159+ }
160+
145161/// Get the search results for a crate search query
146162///
147163/// This delegates to the crates.io search API.
148164async fn get_search_results (
149165 conn : & mut sqlx:: PgConnection ,
150166 registry : & RegistryApi ,
151167 query_params : & str ,
168+ query : & str ,
152169) -> Result < SearchResult , anyhow:: Error > {
153170 let crate :: registry_api:: Search { crates, meta } = registry. search ( query_params) . await ?;
154171
@@ -206,28 +223,68 @@ async fn get_search_results(
206223 rustdoc_status : row. rustdoc_status . unwrap_or ( false ) ,
207224 stars : row. stars . unwrap_or ( 0 ) ,
208225 has_unyanked_releases : row. has_unyanked_releases ,
226+ href : None ,
209227 } ,
210228 )
211229 } )
212230 . try_collect ( )
213231 . await ?;
214232
233+ // start with the original names from crates.io to keep the original ranking,
234+ // extend with the release/build information from docs.rs
235+ // Crates that are not on docs.rs yet will not be returned.
236+ let mut results = Vec :: new ( ) ;
237+ match query {
238+ "std" | "libstd" => {
239+ results. push ( rust_lib_release (
240+ "std" ,
241+ "Rust standard library" ,
242+ "https://doc.rust-lang.org/stable/std" ,
243+ ) ) ;
244+ }
245+ "core" | "libcore" => {
246+ results. push ( rust_lib_release (
247+ "core" ,
248+ "Rust core library" ,
249+ "https://doc.rust-lang.org/stable/core" ,
250+ ) ) ;
251+ }
252+ "alloc" | "liballoc" => {
253+ results. push ( rust_lib_release (
254+ "core" ,
255+ "Rust alloc library" ,
256+ "https://doc.rust-lang.org/stable/alloc" ,
257+ ) ) ;
258+ }
259+ "proc_macro" | "proc-macro" | "libproc_macro" | "libproc-macro" => {
260+ results. push ( rust_lib_release (
261+ "proc_macro" ,
262+ "Rust proc_macro library" ,
263+ "https://doc.rust-lang.org/stable/proc_macro" ,
264+ ) ) ;
265+ }
266+ "test" | "libtest" => {
267+ results. push ( rust_lib_release (
268+ "test" ,
269+ "Rust test library" ,
270+ "https://doc.rust-lang.org/stable/test" ,
271+ ) ) ;
272+ }
273+ _ => { }
274+ }
275+
215276 let names: Vec < String > =
216277 Arc :: into_inner ( names) . expect ( "Arc still borrowed in `get_search_results`" ) ;
278+ results. extend ( names. into_iter ( ) . map ( |name| {
279+ if let Some ( release) = crates. remove ( & name) {
280+ ReleaseStatus :: Available ( release)
281+ } else {
282+ ReleaseStatus :: NotAvailable ( name)
283+ }
284+ } ) ) ;
285+
217286 Ok ( SearchResult {
218- // start with the original names from crates.io to keep the original ranking,
219- // extend with the release/build information from docs.rs
220- // Crates that are not on docs.rs yet will not be returned.
221- results : names
222- . into_iter ( )
223- . map ( |name| {
224- if let Some ( release) = crates. remove ( & name) {
225- ReleaseStatus :: Available ( release)
226- } else {
227- ReleaseStatus :: NotAvailable ( name)
228- }
229- } )
230- . collect ( ) ,
287+ results,
231288 prev_page : meta. prev_page ,
232289 next_page : meta. next_page ,
233290 } )
@@ -589,15 +646,15 @@ pub(crate) async fn search_handler(
589646 }
590647 }
591648
592- get_search_results ( & mut conn, & registry, query_params) . await ?
649+ get_search_results ( & mut conn, & registry, query_params, "" ) . await ?
593650 } else if !query. is_empty ( ) {
594651 let query_params: String = form_urlencoded:: Serializer :: new ( String :: new ( ) )
595652 . append_pair ( "q" , & query)
596653 . append_pair ( "sort" , & sort_by)
597654 . append_pair ( "per_page" , & RELEASES_IN_RELEASES . to_string ( ) )
598655 . finish ( ) ;
599656
600- get_search_results ( & mut conn, & registry, & query_params) . await ?
657+ get_search_results ( & mut conn, & registry, & query_params, & query ) . await ?
601658 } else {
602659 return Err ( AxumNope :: NoResults ) ;
603660 } ;
@@ -2231,4 +2288,55 @@ mod tests {
22312288 Ok ( ( ) )
22322289 } ) ;
22332290 }
2291+
2292+ #[ test]
2293+ fn test_search_std ( ) {
2294+ async_wrapper ( |env| async move {
2295+ let web = env. web_app ( ) . await ;
2296+
2297+ async fn inner ( web : & axum:: Router , krate : & str ) -> Result < ( ) , anyhow:: Error > {
2298+ let full = kuchikiki:: parse_html ( ) . one (
2299+ web. get ( & format ! ( "/releases/search?query={krate}" ) )
2300+ . await ?
2301+ . text ( )
2302+ . await ?,
2303+ ) ;
2304+ let items = full
2305+ . select ( "ul a.release" )
2306+ . expect ( "missing list items" )
2307+ . collect :: < Vec < _ > > ( ) ;
2308+
2309+ // empty because expand_rebuild_queue is not set
2310+ let item_element = items. first ( ) . unwrap ( ) ;
2311+ let item = item_element. as_node ( ) ;
2312+ assert_eq ! (
2313+ item. select( ".name" )
2314+ . unwrap( )
2315+ . next( )
2316+ . unwrap( )
2317+ . text_contents( ) ,
2318+ "std"
2319+ ) ;
2320+ assert_eq ! (
2321+ item. select( ".description" )
2322+ . unwrap( )
2323+ . next( )
2324+ . unwrap( )
2325+ . text_contents( ) ,
2326+ "Rust standard library" ,
2327+ ) ;
2328+ assert_eq ! (
2329+ item_element. attributes. borrow( ) . get( "href" ) . unwrap( ) ,
2330+ "https://doc.rust-lang.org/stable/std"
2331+ ) ;
2332+
2333+ Ok ( ( ) )
2334+ }
2335+
2336+ inner ( & web, "std" ) . await ?;
2337+ inner ( & web, "libstd" ) . await ?;
2338+
2339+ Ok ( ( ) )
2340+ } ) ;
2341+ }
22342342}
0 commit comments