about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustdoc/html/render/search_index.rs157
1 files 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::<Vec<_>>();
 
+            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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+                    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::<String>(),
-            )?;
-            crate_data.serialize_field(
-                "n",
-                &self.items.iter().map(|item| item.name.as_str()).collect::<Vec<_>>(),
-            )?;
-            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::<Vec<_>>(),
-            )?;
-            crate_data.serialize_field(
-                "d",
-                &self.items.iter().map(|item| &item.desc).collect::<Vec<_>>(),
-            )?;
-            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::<Vec<_>>(),
-            )?;
-            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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-                            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::<Vec<_>>(),
-            )?;
-            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::<Vec<_>>(),
-            )?;
+            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)?;