Skip to content

Commit ce795d9

Browse files
committed
rustdoc: collapse edit distance state into an object
1 parent dfd9e5e commit ce795d9

File tree

1 file changed

+86
-80
lines changed

1 file changed

+86
-80
lines changed

Diff for: src/librustdoc/html/static/js/search.js

+86-80
Original file line numberDiff line numberDiff line change
@@ -90,91 +90,97 @@ function printTab(nb) {
9090
* algorithm should not matter to the caller of the methods, which is why it is not noted in the
9191
* documentation.
9292
*/
93-
let editDistanceCurrent = [];
94-
let editDistancePrev = [];
95-
let editDistancePrevPrev = [];
96-
function editDistance(a, b, limit) {
97-
// Ensure that `b` is the shorter string, minimizing memory use.
98-
if (a.length < b.length) {
99-
const aTmp = a;
100-
a = b;
101-
b = aTmp;
102-
}
103-
104-
const minDist = a.length - b.length;
105-
// If we know the limit will be exceeded, we can return early.
106-
if (minDist > limit) {
107-
return limit + 1;
108-
}
109-
110-
// Strip common prefix.
111-
// We know that `b` is the shorter string, so we don't need to check
112-
// `a.length`.
113-
while (b.length > 0 && b[0] === a[0]) {
114-
a = a.substring(1);
115-
b = b.substring(1);
116-
}
117-
// Strip common suffix.
118-
while (b.length > 0 && b[b.length - 1] === a[a.length - 1]) {
119-
a = a.substring(0, a.length - 1);
120-
b = b.substring(0, b.length - 1);
121-
}
122-
123-
// If either string is empty, the distance is the length of the other.
124-
// We know that `b` is the shorter string, so we don't need to check `a`.
125-
if (b.length === 0) {
126-
return minDist;
127-
}
128-
129-
const aLength = a.length;
130-
const bLength = b.length;
131-
132-
for (let i = 0; i <= bLength; ++i) {
133-
editDistanceCurrent[i] = 0;
134-
editDistancePrev[i] = i;
135-
editDistancePrevPrev[i] = Number.MAX_VALUE;
136-
}
137-
138-
// row by row
139-
for (let i = 1; i <= aLength; ++i) {
140-
editDistanceCurrent[0] = i;
141-
const aIdx = i - 1;
142-
143-
// column by column
144-
for (let j = 1; j <= bLength; ++j) {
145-
const bIdx = j - 1;
146-
147-
// There is no cost to substitute a character with itself.
148-
const substitutionCost = a[aIdx] === b[bIdx] ? 0 : 1;
149-
150-
editDistanceCurrent[j] = Math.min(
151-
// deletion
152-
editDistancePrev[j] + 1,
153-
// insertion
154-
editDistanceCurrent[j - 1] + 1,
155-
// substitution
156-
editDistancePrev[j - 1] + substitutionCost
157-
);
158-
159-
if ((i > 1) && (j > 1) && (a[aIdx] === b[bIdx - 1]) && (a[aIdx - 1] === b[bIdx])) {
160-
// transposition
161-
editDistanceCurrent[j] = Math.min(
162-
editDistanceCurrent[j],
163-
editDistancePrevPrev[j - 2] + 1
93+
const editDistanceState = {
94+
current: [],
95+
prev: [],
96+
prevPrev: [],
97+
calculate: function calculate(a, b, limit) {
98+
// Ensure that `b` is the shorter string, minimizing memory use.
99+
if (a.length < b.length) {
100+
const aTmp = a;
101+
a = b;
102+
b = aTmp;
103+
}
104+
105+
const minDist = a.length - b.length;
106+
// If we know the limit will be exceeded, we can return early.
107+
if (minDist > limit) {
108+
return limit + 1;
109+
}
110+
111+
// Strip common prefix.
112+
// We know that `b` is the shorter string, so we don't need to check
113+
// `a.length`.
114+
while (b.length > 0 && b[0] === a[0]) {
115+
a = a.substring(1);
116+
b = b.substring(1);
117+
}
118+
// Strip common suffix.
119+
while (b.length > 0 && b[b.length - 1] === a[a.length - 1]) {
120+
a = a.substring(0, a.length - 1);
121+
b = b.substring(0, b.length - 1);
122+
}
123+
124+
// If either string is empty, the distance is the length of the other.
125+
// We know that `b` is the shorter string, so we don't need to check `a`.
126+
if (b.length === 0) {
127+
return minDist;
128+
}
129+
130+
const aLength = a.length;
131+
const bLength = b.length;
132+
133+
for (let i = 0; i <= bLength; ++i) {
134+
this.current[i] = 0;
135+
this.prev[i] = i;
136+
this.prevPrev[i] = Number.MAX_VALUE;
137+
}
138+
139+
// row by row
140+
for (let i = 1; i <= aLength; ++i) {
141+
this.current[0] = i;
142+
const aIdx = i - 1;
143+
144+
// column by column
145+
for (let j = 1; j <= bLength; ++j) {
146+
const bIdx = j - 1;
147+
148+
// There is no cost to substitute a character with itself.
149+
const substitutionCost = a[aIdx] === b[bIdx] ? 0 : 1;
150+
151+
this.current[j] = Math.min(
152+
// deletion
153+
this.prev[j] + 1,
154+
// insertion
155+
this.current[j - 1] + 1,
156+
// substitution
157+
this.prev[j - 1] + substitutionCost
164158
);
159+
160+
if ((i > 1) && (j > 1) && (a[aIdx] === b[bIdx - 1]) && (a[aIdx - 1] === b[bIdx])) {
161+
// transposition
162+
this.current[j] = Math.min(
163+
this.current[j],
164+
this.prevPrev[j - 2] + 1
165+
);
166+
}
165167
}
168+
169+
// Rotate the buffers, reusing the memory
170+
const prevPrevTmp = this.prevPrev;
171+
this.prevPrev = this.prev;
172+
this.prev = this.current;
173+
this.current = prevPrevTmp;
166174
}
167175

168-
// Rotate the buffers, reusing the memory
169-
const prevPrevTmp = editDistancePrevPrev;
170-
editDistancePrevPrev = editDistancePrev;
171-
editDistancePrev = editDistanceCurrent;
172-
editDistanceCurrent = prevPrevTmp;
173-
}
176+
// `prev` because we already rotated the buffers.
177+
const distance = this.prev[bLength];
178+
return distance <= limit ? distance : (limit + 1);
179+
},
180+
};
174181

175-
// `prev` because we already rotated the buffers.
176-
const distance = editDistancePrev[bLength];
177-
return distance <= limit ? distance : (limit + 1);
182+
function editDistance(a, b, limit) {
183+
return editDistanceState.calculate(a, b, limit);
178184
}
179185

180186
function initSearch(rawSearchIndex) {

0 commit comments

Comments
 (0)