Skip to content

Commit 15c5e34

Browse files
committed
search_index impl Display
1 parent d2acb42 commit 15c5e34

File tree

4 files changed

+114
-115
lines changed

4 files changed

+114
-115
lines changed

src/librustdoc/display.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ impl Wrapped<char> {
8282
pub(crate) fn with_square_brackets() -> Self {
8383
Self { prefix: '[', suffix: ']' }
8484
}
85+
86+
pub(crate) fn with_curly_brackets() -> Self {
87+
Self { prefix: '{', suffix: '}' }
88+
}
8589
}
8690

8791
impl<T: Display> Wrapped<T> {

src/librustdoc/html/render/mod.rs

Lines changed: 88 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ pub(crate) use self::context::*;
6767
pub(crate) use self::span_map::{LinkFromSrc, collect_spans_and_sources};
6868
pub(crate) use self::write_shared::*;
6969
use crate::clean::{self, ItemId, RenderedLink};
70-
use crate::display::{Joined as _, MaybeDisplay as _};
70+
use crate::display::{Joined as _, MaybeDisplay as _, Wrapped};
7171
use crate::error::Error;
7272
use crate::formats::Impl;
7373
use crate::formats::cache::Cache;
@@ -153,59 +153,35 @@ struct RenderType {
153153

154154
impl RenderType {
155155
fn size(&self) -> usize {
156-
let mut size = 1;
157-
if let Some(generics) = &self.generics {
158-
size += generics.iter().map(RenderType::size).sum::<usize>();
159-
}
160-
if let Some(bindings) = &self.bindings {
161-
for (_, constraints) in bindings.iter() {
162-
size += 1;
163-
size += constraints.iter().map(RenderType::size).sum::<usize>();
164-
}
165-
}
166-
size
156+
self.bindings
157+
.iter()
158+
.flatten()
159+
.map(|(_, constraints)| constraints)
160+
.chain(self.generics.iter())
161+
.map(|constraints| constraints.iter().map(RenderType::size).sum::<usize>() + 1)
162+
.sum()
167163
}
168-
// Types are rendered as lists of lists, because that's pretty compact.
169-
// The contents of the lists are always integers in self-terminating hex
170-
// form, handled by `RenderTypeId::write_to_string`, so no commas are
171-
// needed to separate the items.
172-
fn write_to_string(&self, string: &mut String) {
173-
fn write_optional_id(id: Option<RenderTypeId>, string: &mut String) {
174-
// 0 is a sentinel, everything else is one-indexed
175-
match id {
176-
Some(id) => id.write_to_string(string),
177-
None => string.push('`'),
178-
}
179-
}
180-
// Either just the type id, or `{type, generics, bindings?}`
181-
// where generics is a list of types,
182-
// and bindings is a list of `{id, typelist}` pairs.
183-
if self.generics.is_some() || self.bindings.is_some() {
184-
string.push('{');
185-
write_optional_id(self.id, string);
186-
string.push('{');
187-
for generic in self.generics.as_deref().unwrap_or_default() {
188-
generic.write_to_string(string);
189-
}
190-
string.push('}');
191-
if self.bindings.is_some() {
192-
string.push('{');
193-
for binding in self.bindings.as_deref().unwrap_or_default() {
194-
string.push('{');
195-
binding.0.write_to_string(string);
196-
string.push('{');
197-
for constraint in &binding.1[..] {
198-
constraint.write_to_string(string);
199-
}
200-
string.push_str("}}");
201-
}
202-
string.push('}');
164+
165+
fn write_bindings(&self) -> Option<impl fmt::Display> {
166+
let Some(bindings) = &self.bindings else {
167+
return None;
168+
};
169+
170+
Some(Wrapped::with_curly_brackets().wrap_fn(move |f| {
171+
for (binding, constraints) in bindings {
172+
Wrapped::with_curly_brackets()
173+
.wrap_fn(|f| {
174+
binding.write_to_string().fmt(f)?;
175+
Wrapped::with_curly_brackets()
176+
.wrap_fn(|f| constraints.iter().joined("", f))
177+
.fmt(f)
178+
})
179+
.fmt(f)?;
203180
}
204-
string.push('}');
205-
} else {
206-
write_optional_id(self.id, string);
207-
}
181+
Ok(())
182+
}))
208183
}
184+
209185
fn read_from_bytes(string: &[u8]) -> (RenderType, usize) {
210186
let mut i = 0;
211187
if string[i] == b'{' {
@@ -264,6 +240,40 @@ impl RenderType {
264240
}
265241
}
266242

243+
impl fmt::Display for RenderType {
244+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245+
// Types are rendered as lists of lists, because that's pretty compact.
246+
// The contents of the lists are always integers in self-terminating hex
247+
// form, handled by `RenderTypeId::write_to_string`, so no commas are
248+
// needed to separate the items.
249+
250+
fn write_optional_id(id: Option<RenderTypeId>) -> impl fmt::Display {
251+
// 0 is a sentinel, everything else is one-indexed
252+
match id {
253+
Some(id) => Either::Left(id.write_to_string()),
254+
None => Either::Right('`'),
255+
}
256+
}
257+
258+
// Either just the type id, or `{type, generics, bindings?}`
259+
// where generics is a list of types,
260+
// and bindings is a list of `{id, typelist}` pairs.
261+
if self.generics.is_some() || self.bindings.is_some() {
262+
Wrapped::with_curly_brackets()
263+
.wrap_fn(|f| {
264+
let id = write_optional_id(self.id);
265+
let generics = Wrapped::with_curly_brackets()
266+
.wrap_fn(|f| self.generics.iter().flatten().joined("", f));
267+
let bindings = self.write_bindings().maybe_display();
268+
write!(f, "{id}{generics}{bindings}")
269+
})
270+
.fmt(f)
271+
} else {
272+
write_optional_id(self.id).fmt(f)
273+
}
274+
}
275+
}
276+
267277
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
268278
enum RenderTypeId {
269279
DefId(DefId),
@@ -274,7 +284,7 @@ enum RenderTypeId {
274284
}
275285

276286
impl RenderTypeId {
277-
fn write_to_string(&self, string: &mut String) {
287+
fn write_to_string(&self) -> impl fmt::Display + use<> {
278288
let id: i32 = match &self {
279289
// 0 is a sentinel, everything else is one-indexed
280290
// concrete type
@@ -283,7 +293,7 @@ impl RenderTypeId {
283293
RenderTypeId::Index(idx) => (*idx).try_into().unwrap(),
284294
_ => panic!("must convert render types to indexes before serializing"),
285295
};
286-
search_index::encode::write_signed_vlqhex_to_string(id, string);
296+
search_index::encode::write_signed_vlqhex_to_string(id)
287297
}
288298
fn read_from_bytes(string: &[u8]) -> (Option<RenderTypeId>, usize) {
289299
let Some((value, offset)) = search_index::encode::read_signed_vlqhex_from_string(string)
@@ -311,13 +321,13 @@ pub(crate) struct IndexItemFunctionType {
311321

312322
impl IndexItemFunctionType {
313323
fn size(&self) -> usize {
314-
self.inputs.iter().map(RenderType::size).sum::<usize>()
315-
+ self.output.iter().map(RenderType::size).sum::<usize>()
316-
+ self
317-
.where_clause
318-
.iter()
319-
.map(|constraints| constraints.iter().map(RenderType::size).sum::<usize>())
320-
.sum::<usize>()
324+
self.where_clause
325+
.iter()
326+
.flatten()
327+
.chain(&self.inputs)
328+
.chain(&self.output)
329+
.map(RenderType::size)
330+
.sum()
321331
}
322332
fn read_from_string_without_param_names(string: &[u8]) -> (IndexItemFunctionType, usize) {
323333
let mut i = 0;
@@ -367,7 +377,7 @@ impl IndexItemFunctionType {
367377
i += 1;
368378
(IndexItemFunctionType { inputs, output, where_clause, param_names: Vec::new() }, i)
369379
}
370-
fn write_to_string_without_param_names<'a>(&'a self, string: &mut String) {
380+
fn write_to_string_without_param_names<'a>(&'a self) -> impl fmt::Display {
371381
// If we couldn't figure out a type, just write 0,
372382
// which is encoded as `` ` `` (see RenderTypeId::write_to_string).
373383
let has_missing = self
@@ -376,49 +386,26 @@ impl IndexItemFunctionType {
376386
.chain(self.output.iter())
377387
.any(|i| i.id.is_none() && i.generics.is_none());
378388
if has_missing {
379-
string.push('`');
389+
Either::Left('`')
380390
} else {
381-
string.push('{');
382-
match &self.inputs[..] {
383-
[one] if one.generics.is_none() && one.bindings.is_none() => {
384-
one.write_to_string(string);
385-
}
386-
_ => {
387-
string.push('{');
388-
for item in &self.inputs[..] {
389-
item.write_to_string(string);
390-
}
391-
string.push('}');
391+
Either::Right(Wrapped::with_curly_brackets().wrap_fn(|f| {
392+
fn write_render_types(types: &[RenderType]) -> impl fmt::Display {
393+
Wrapped::with_curly_brackets()
394+
.when(!matches!(types, [one] if one.generics.is_none() && one.bindings.is_none()))
395+
.wrap_fn(|f| types.iter().joined("", f))
392396
}
393-
}
394-
match &self.output[..] {
395-
[] if self.where_clause.is_empty() => {}
396-
[one] if one.generics.is_none() && one.bindings.is_none() => {
397-
one.write_to_string(string);
398-
}
399-
_ => {
400-
string.push('{');
401-
for item in &self.output[..] {
402-
item.write_to_string(string);
403-
}
404-
string.push('}');
405-
}
406-
}
407-
for constraint in &self.where_clause {
408-
if let [one] = &constraint[..]
409-
&& one.generics.is_none()
410-
&& one.bindings.is_none()
411-
{
412-
one.write_to_string(string);
413-
} else {
414-
string.push('{');
415-
for item in &constraint[..] {
416-
item.write_to_string(string);
417-
}
418-
string.push('}');
397+
398+
write_render_types(&self.inputs).fmt(f)?;
399+
if !(self.output.is_empty() && self.where_clause.is_empty()) {
400+
write_render_types(&self.output).fmt(f)?;
419401
}
420-
}
421-
string.push('}');
402+
self.where_clause
403+
.iter()
404+
.map(|constraints| write_render_types(constraints))
405+
.joined("", f)?;
406+
407+
Ok(())
408+
}))
422409
}
423410
}
424411
}

src/librustdoc/html/render/search_index.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ pub(crate) mod encode;
22

33
use std::collections::BTreeSet;
44
use std::collections::hash_map::Entry;
5+
use std::fmt::Write as _;
56
use std::path::Path;
67

78
use rustc_ast::join_path_syms;
@@ -509,7 +510,8 @@ impl SerializedSearchIndex {
509510
}
510511
let mut result =
511512
String::with_capacity(function_data.function_signature.len());
512-
func.write_to_string_without_param_names(&mut result);
513+
write!(result, "{}", func.write_to_string_without_param_names())
514+
.unwrap();
513515
result
514516
},
515517
param_names: function_data.param_names.clone(),
@@ -683,7 +685,8 @@ impl SerializedSearchIndex {
683685
}
684686
}
685687
let mut result = String::with_capacity(function_signature.len());
686-
func.write_to_string_without_param_names(&mut result);
688+
write!(result, "{}", func.write_to_string_without_param_names())
689+
.unwrap();
687690
result
688691
},
689692
param_names: param_names.clone(),
@@ -1929,9 +1932,7 @@ pub(crate) fn build_index(
19291932
if item.ty.is_fn_like() { 0 } else { 16 };
19301933
serialized_index.function_data[new_entry_id] = Some(FunctionData {
19311934
function_signature: {
1932-
let mut function_signature = String::new();
1933-
search_type.write_to_string_without_param_names(&mut function_signature);
1934-
function_signature
1935+
search_type.write_to_string_without_param_names().to_string()
19351936
},
19361937
param_names: search_type
19371938
.param_names

src/librustdoc/html/render/search_index/encode.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
pub(crate) fn write_signed_vlqhex_to_string(n: i32, string: &mut String) {
1+
use std::fmt::{self, Write as _};
2+
3+
pub(crate) fn write_signed_vlqhex_to_string(n: i32) -> impl fmt::Display {
24
let (sign, magnitude): (bool, u32) =
35
if n >= 0 { (false, n.try_into().unwrap()) } else { (true, (-n).try_into().unwrap()) };
46
// zig-zag encoding
@@ -25,14 +27,19 @@ pub(crate) fn write_signed_vlqhex_to_string(n: i32, string: &mut String) {
2527
shift = shift.wrapping_sub(4);
2628
mask >>= 4;
2729
}
28-
// now write the rest
29-
while shift < 32 {
30-
let hexit = (value & mask) >> shift;
31-
let hex = char::try_from(if shift == 0 { '`' } else { '@' } as u32 + hexit).unwrap();
32-
string.push(hex);
33-
shift = shift.wrapping_sub(4);
34-
mask >>= 4;
35-
}
30+
fmt::from_fn(move |f| {
31+
let mut shift = shift;
32+
let mut mask = mask;
33+
// now write the rest
34+
while shift < 32 {
35+
let hexit = (value & mask) >> shift;
36+
let hex = char::try_from(if shift == 0 { '`' } else { '@' } as u32 + hexit).unwrap();
37+
f.write_char(hex)?;
38+
shift = shift.wrapping_sub(4);
39+
mask >>= 4;
40+
}
41+
Ok(())
42+
})
3643
}
3744

3845
pub fn read_signed_vlqhex_from_string(string: &[u8]) -> Option<(i32, usize)> {

0 commit comments

Comments
 (0)