11use std:: { borrow:: Cow , collections:: BTreeSet } ;
22
33use anyhow:: Context ;
4- use bincode:: { Decode , Encode } ;
54use camino:: Utf8Path ;
65use guppy:: {
76 PackageId ,
@@ -18,7 +17,9 @@ use crate::{
1817 DiagnosticSink ,
1918 rustdoc:: {
2019 annotations:: AnnotatedItems ,
21- queries:: { CrateData , CrateItemIndex , LazyCrateItemIndex } ,
20+ queries:: {
21+ CrateData , CrateItemIndex , ImportPath2Id , LazyCrateItemIndex , LazyImportPath2Id ,
22+ } ,
2223 } ,
2324} ;
2425
@@ -381,12 +382,12 @@ impl ToolchainCache {
381382 external_crates : Cow :: Borrowed ( external_crates) ,
382383 paths : Cow :: Borrowed ( paths) ,
383384 format_version,
384- items : CachedItems :: Borrowed ( items) ,
385+ items : RkyvCowBytes :: Borrowed ( items) ,
385386 secondary_indexes : Some ( SecondaryIndexes {
386387 import_index : Cow :: Borrowed ( import_index) ,
387388 // Standard library crates don't have Pavex annotations.
388389 annotated_items : None ,
389- import_path2id : Cow :: Borrowed ( import_path2id) ,
390+ import_path2id : RkyvCowBytes :: Borrowed ( import_path2id) ,
390391 re_exports : Cow :: Borrowed ( re_exports) ,
391392 } ) ,
392393 }
@@ -590,7 +591,7 @@ impl ThirdPartyCrateCache {
590591 Some ( annotated_items) ,
591592 ) => Some ( SecondaryIndexes {
592593 import_index : Cow :: Borrowed ( import_index) ,
593- import_path2id : Cow :: Borrowed ( import_path2id) ,
594+ import_path2id : RkyvCowBytes :: Borrowed ( import_path2id) ,
594595 re_exports : Cow :: Borrowed ( re_exports) ,
595596 annotated_items : Some ( Cow :: Borrowed ( annotated_items) ) ,
596597 } ) ,
@@ -602,7 +603,7 @@ impl ThirdPartyCrateCache {
602603 external_crates : Cow :: Borrowed ( external_crates) ,
603604 paths : Cow :: Borrowed ( paths) ,
604605 format_version,
605- items : CachedItems :: Borrowed ( items) ,
606+ items : RkyvCowBytes :: Borrowed ( items) ,
606607 secondary_indexes,
607608 }
608609 . hydrate ( package_metadata. id ( ) . to_owned ( ) )
@@ -787,47 +788,56 @@ pub(in crate::rustdoc) struct CacheEntry<'a> {
787788 external_crates : Cow < ' a , [ u8 ] > ,
788789 paths : Cow < ' a , [ u8 ] > ,
789790 format_version : i64 ,
790- items : CachedItems < ' a > ,
791+ items : RkyvCowBytes < ' a > ,
791792 secondary_indexes : Option < SecondaryIndexes < ' a > > ,
792793}
793794
794795#[ derive( Debug ) ]
795- /// `rkyv`-serialized `HashMap<Id, Item> `.
796- pub ( in crate :: rustdoc) enum CachedItems < ' a > {
796+ /// A `Cow` variant to work with `rkyv`'s `AlignedVec `.
797+ pub ( in crate :: rustdoc) enum RkyvCowBytes < ' a > {
797798 Borrowed ( & ' a [ u8 ] ) ,
798799 Owned ( AlignedVec ) ,
799800}
800801
801- impl ToSql for CachedItems < ' _ > {
802+ impl ToSql for RkyvCowBytes < ' _ > {
802803 fn to_sql ( & self ) -> rusqlite:: Result < rusqlite:: types:: ToSqlOutput < ' _ > > {
803804 let s = match self {
804- CachedItems :: Borrowed ( items) => items,
805- CachedItems :: Owned ( s) => s. as_slice ( ) ,
805+ RkyvCowBytes :: Borrowed ( items) => items,
806+ RkyvCowBytes :: Owned ( s) => s. as_slice ( ) ,
806807 } ;
807808 Ok ( ToSqlOutput :: Borrowed ( rusqlite:: types:: ValueRef :: Blob ( s) ) )
808809 }
809810}
810811
811- impl < ' a > CachedItems < ' a > {
812+ impl < ' a > RkyvCowBytes < ' a > {
812813 pub fn into_owned ( self ) -> AlignedVec {
813814 match self {
814- CachedItems :: Borrowed ( items) => {
815+ RkyvCowBytes :: Borrowed ( items) => {
815816 let mut v = AlignedVec :: with_capacity ( items. len ( ) ) ;
816817 v. extend_from_slice ( items) ;
817818 v
818819 }
819- CachedItems :: Owned ( aligned_vec) => aligned_vec,
820+ RkyvCowBytes :: Owned ( aligned_vec) => aligned_vec,
820821 }
821822 }
822823}
823824
824- #[ derive( Debug , Encode , Decode ) ]
825+ impl < ' a > AsRef < [ u8 ] > for RkyvCowBytes < ' a > {
826+ fn as_ref ( & self ) -> & [ u8 ] {
827+ match self {
828+ RkyvCowBytes :: Borrowed ( items) => items,
829+ RkyvCowBytes :: Owned ( aligned_vec) => aligned_vec. as_slice ( ) ,
830+ }
831+ }
832+ }
833+
834+ #[ derive( Debug ) ]
825835/// Data that can be computed starting from the raw JSON documentation for a crate,
826836/// without having to re-invoke `rustdoc`.
827837pub ( in crate :: rustdoc) struct SecondaryIndexes < ' a > {
828838 import_index : Cow < ' a , [ u8 ] > ,
829839 annotated_items : Option < Cow < ' a , [ u8 ] > > ,
830- import_path2id : Cow < ' a , [ u8 ] > ,
840+ import_path2id : RkyvCowBytes < ' a > ,
831841 re_exports : Cow < ' a , [ u8 ] > ,
832842}
833843
@@ -837,13 +847,24 @@ impl<'a> CacheEntry<'a> {
837847 let import_index = bincode:: serde:: encode_to_vec ( & krate. import_index , BINCODE_CONFIG ) ?;
838848 let annotated_items =
839849 bincode:: serde:: encode_to_vec ( & krate. annotated_items , BINCODE_CONFIG ) ?;
840- let import_path2id = bincode:: serde:: encode_to_vec ( & krate. import_path2id , BINCODE_CONFIG ) ?;
841850 let re_exports = bincode:: serde:: encode_to_vec ( & krate. external_re_exports , BINCODE_CONFIG ) ?;
842851
852+ // Serialize the items HashMap using rkyv for zero-copy deserialization later.
853+ let ImportPath2Id :: Eager ( import_path2id) = & krate. import_path2id else {
854+ anyhow:: bail!(
855+ "The crate's import path<>id map is not deserialized. Are we trying to cache \
856+ the same crate twice? This is a bug."
857+ ) ;
858+ } ;
859+ let import_path2id =
860+ rkyv:: to_bytes :: < rkyv:: rancor:: Error > ( & import_path2id. 0 ) . map_err ( |e| {
861+ anyhow:: anyhow!( e) . context ( "Failed to serialize import path<>id map with rkyv" )
862+ } ) ?;
863+
843864 cached. secondary_indexes = Some ( SecondaryIndexes {
844865 import_index : Cow :: Owned ( import_index) ,
845866 annotated_items : Some ( Cow :: Owned ( annotated_items) ) ,
846- import_path2id : Cow :: Owned ( import_path2id) ,
867+ import_path2id : RkyvCowBytes :: Owned ( import_path2id) ,
847868 re_exports : Cow :: Owned ( re_exports) ,
848869 } ) ;
849870 Ok ( cached)
@@ -861,7 +882,7 @@ impl<'a> CacheEntry<'a> {
861882
862883 // Serialize the items HashMap using rkyv for zero-copy deserialization later.
863884 let items = rkyv:: to_bytes :: < rkyv:: rancor:: Error > ( & index. index )
864- . map_err ( |e| anyhow:: anyhow!( "Failed to serialize items with rkyv: {e} " ) ) ?;
885+ . map_err ( |e| anyhow:: anyhow!( e ) . context ( "Failed to serialize crate items with rkyv" ) ) ?;
865886
866887 let external_crates =
867888 bincode:: serde:: encode_to_vec ( & crate_data. external_crates , BINCODE_CONFIG ) ?;
@@ -872,7 +893,7 @@ impl<'a> CacheEntry<'a> {
872893 external_crates : Cow :: Owned ( external_crates) ,
873894 paths : Cow :: Owned ( paths) ,
874895 format_version : crate_data. format_version as i64 ,
875- items : CachedItems :: Owned ( items) ,
896+ items : RkyvCowBytes :: Owned ( items) ,
876897 secondary_indexes : None ,
877898 } )
878899 }
@@ -908,13 +929,6 @@ impl<'a> CacheEntry<'a> {
908929 krate : crate_data,
909930 } ;
910931
911- let import_path2id = tracing:: trace_span!( "Deserialize import_path2id" )
912- . in_scope ( || {
913- bincode:: decode_from_slice ( & secondary_indexes. import_path2id , BINCODE_CONFIG )
914- } )
915- . context ( "Failed to deserialize import_path2id" ) ?
916- . 0 ;
917-
918932 let import_index =
919933 bincode:: decode_from_slice ( & secondary_indexes. import_index , BINCODE_CONFIG )
920934 . context ( "Failed to deserialize import_index" ) ?
@@ -935,7 +949,9 @@ impl<'a> CacheEntry<'a> {
935949 let krate = crate :: rustdoc:: Crate {
936950 core,
937951 annotated_items,
938- import_path2id,
952+ import_path2id : ImportPath2Id :: Lazy ( LazyImportPath2Id (
953+ secondary_indexes. import_path2id . into_owned ( ) ,
954+ ) ) ,
939955 external_re_exports : re_exports,
940956 import_index,
941957 crate_id2package_id : Default :: default ( ) ,
0 commit comments