From 36fa557a5e8ab96876157b44d199ad9b8e93d72c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 1 Sep 2023 14:46:47 +0200 Subject: [PATCH] Merge all loops into one when generating search index --- src/librustdoc/html/render/search_index.rs | 157 +++++++++------------ 1 file changed, 65 insertions(+), 92 deletions(-) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index a7771c31f85..2bbfb64ecb5 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -265,102 +265,75 @@ pub(crate) fn build_index<'tcx>( }) .collect::>(); + let mut names = Vec::with_capacity(self.items.len()); + let mut types = String::with_capacity(self.items.len()); + let mut full_paths = Vec::with_capacity(self.items.len()); + let mut descriptions = Vec::with_capacity(self.items.len()); + let mut parents = Vec::with_capacity(self.items.len()); + let mut functions = Vec::with_capacity(self.items.len()); + let mut deprecated = Vec::with_capacity(self.items.len()); + + for (index, item) in self.items.iter().enumerate() { + let n = item.ty as u8; + let c = char::try_from(n + b'A').expect("item types must fit in ASCII"); + assert!(c <= 'z', "item types must fit within ASCII printables"); + types.push(c); + + assert_eq!( + item.parent.is_some(), + item.parent_idx.is_some(), + "`{}` is missing idx", + item.name + ); + // 0 is a sentinel, everything else is one-indexed + parents.push(item.parent_idx.map(|x| x + 1).unwrap_or(0)); + + names.push(item.name.as_str()); + descriptions.push(&item.desc); + + if !item.path.is_empty() { + full_paths.push((index, &item.path)); + } + + // Fake option to get `0` out as a sentinel instead of `null`. + // We want to use `0` because it's three less bytes. + enum FunctionOption<'a> { + Function(&'a IndexItemFunctionType), + None, + } + impl<'a> Serialize for FunctionOption<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + FunctionOption::None => 0.serialize(serializer), + FunctionOption::Function(ty) => ty.serialize(serializer), + } + } + } + functions.push(match &item.search_type { + Some(ty) => FunctionOption::Function(ty), + None => FunctionOption::None, + }); + + if item.deprecation.is_some() { + deprecated.push(index); + } + } + let has_aliases = !self.aliases.is_empty(); let mut crate_data = serializer.serialize_struct("CrateData", if has_aliases { 9 } else { 8 })?; crate_data.serialize_field("doc", &self.doc)?; - crate_data.serialize_field( - "t", - &self - .items - .iter() - .map(|item| { - let n = item.ty as u8; - let c = char::try_from(n + b'A').expect("item types must fit in ASCII"); - assert!(c <= 'z', "item types must fit within ASCII printables"); - c - }) - .collect::(), - )?; - crate_data.serialize_field( - "n", - &self.items.iter().map(|item| item.name.as_str()).collect::>(), - )?; - crate_data.serialize_field( - "q", - &self - .items - .iter() - .enumerate() - // Serialize as an array of item indices and full paths - .filter_map( - |(index, item)| { - if item.path.is_empty() { None } else { Some((index, &item.path)) } - }, - ) - .collect::>(), - )?; - crate_data.serialize_field( - "d", - &self.items.iter().map(|item| &item.desc).collect::>(), - )?; - crate_data.serialize_field( - "i", - &self - .items - .iter() - .map(|item| { - assert_eq!( - item.parent.is_some(), - item.parent_idx.is_some(), - "`{}` is missing idx", - item.name - ); - // 0 is a sentinel, everything else is one-indexed - item.parent_idx.map(|x| x + 1).unwrap_or(0) - }) - .collect::>(), - )?; - crate_data.serialize_field( - "f", - &self - .items - .iter() - .map(|item| { - // Fake option to get `0` out as a sentinel instead of `null`. - // We want to use `0` because it's three less bytes. - enum FunctionOption<'a> { - Function(&'a IndexItemFunctionType), - None, - } - impl<'a> Serialize for FunctionOption<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - match self { - FunctionOption::None => 0.serialize(serializer), - FunctionOption::Function(ty) => ty.serialize(serializer), - } - } - } - match &item.search_type { - Some(ty) => FunctionOption::Function(ty), - None => FunctionOption::None, - } - }) - .collect::>(), - )?; - crate_data.serialize_field( - "c", - &self - .items - .iter() - .enumerate() - // Serialize as an array of deprecated item indices - .filter_map(|(index, item)| item.deprecation.map(|_| index)) - .collect::>(), - )?; + crate_data.serialize_field("t", &types)?; + crate_data.serialize_field("n", &names)?; + // Serialize as an array of item indices and full paths + crate_data.serialize_field("q", &full_paths)?; + crate_data.serialize_field("d", &descriptions)?; + crate_data.serialize_field("i", &parents)?; + crate_data.serialize_field("f", &functions)?; + crate_data.serialize_field("c", &deprecated)?; crate_data.serialize_field("p", &paths)?; if has_aliases { crate_data.serialize_field("a", &self.aliases)?;