From 33cf9ea4a2aebb015e81071968659bd51218c5af Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 27 Jun 2022 14:13:13 -0700 Subject: [PATCH] Add comments, fixes for `0` sentinel --- src/librustdoc/html/render/search_index.rs | 28 +++++++++++++++++++++- src/librustdoc/html/static/js/externs.js | 6 +++++ src/librustdoc/html/static/js/search.js | 7 +++--- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index f9192a5e648..d672f0bb599 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -234,7 +234,33 @@ pub(crate) fn build_index<'tcx>( )?; crate_data.serialize_field( "f", - &self.items.iter().map(|item| &item.search_type).collect::>(), + &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( "p", diff --git a/src/librustdoc/html/static/js/externs.js b/src/librustdoc/html/static/js/externs.js index 23947d002ab..ecbe15a59da 100644 --- a/src/librustdoc/html/static/js/externs.js +++ b/src/librustdoc/html/static/js/externs.js @@ -86,6 +86,9 @@ let Results; * A pair of [inputs, outputs], or 0 for null. This is stored in the search index. * The JavaScript deserializes this into FunctionSearchType. * + * Numeric IDs are *ONE-indexed* into the paths array (`p`). Zero is used as a sentinel for `null` + * because `null` is four bytes while `0` is one byte. + * * An input or output can be encoded as just a number if there is only one of them, AND * it has no generics. The no generics rule exists to avoid ambiguity: imagine if you had * a function with a single output, and that output had a single generic: @@ -114,6 +117,9 @@ let RawFunctionSearchType; * A single function input or output type. This is either a single path ID, or a pair of * [path ID, generics]. * + * Numeric IDs are *ONE-indexed* into the paths array (`p`). Zero is used as a sentinel for `null` + * because `null` is four bytes while `0` is one byte. + * * @typedef {number | [number, Array]} */ let RawFunctionType; diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 46fab7ee57b..75c7bd45a29 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1846,9 +1846,6 @@ function initSearch(rawSearchIndex) { function buildItemSearchTypeAll(types, lowercasePaths) { const PATH_INDEX_DATA = 0; const GENERICS_DATA = 1; - if (types === null) { - return []; - } return types.map(type => { let pathIndex, generics; if (typeof type === "number") { @@ -1859,6 +1856,7 @@ function initSearch(rawSearchIndex) { generics = buildItemSearchTypeAll(type[GENERICS_DATA], lowercasePaths); } return { + // `0` is used as a sentinel because it's fewer bytes than `null` name: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].name, ty: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].ty, generics: generics, @@ -1884,7 +1882,8 @@ function initSearch(rawSearchIndex) { function buildFunctionSearchType(functionSearchType, lowercasePaths) { const INPUTS_DATA = 0; const OUTPUT_DATA = 1; - if (functionSearchType === 0 || functionSearchType === null) { + // `0` is used as a sentinel because it's fewer bytes than `null` + if (functionSearchType === 0) { return null; } let inputs, output;