##// END OF EJS Templates
rhg: reduce verbosity in path_encode by using a trait for writing...
Arseniy Alekseyev -
r51439:96d31efd default
parent child Browse files
Show More
@@ -36,22 +36,31 b' enum dir_state {'
36 36 DDEFAULT,
37 37 }
38 38
39 trait Sink {
40 fn write_byte(&mut self, c: u8);
41 fn write_bytes(&mut self, c: &[u8]);
42 }
43
39 44 fn inset(bitset: &[u32; 8], c: u8) -> bool {
40 45 bitset[(c as usize) >> 5] & (1 << (c & 31)) != 0
41 46 }
42 47
43 fn charcopy(dest: Option<&mut [u8]>, destlen: &mut usize, c: u8) {
44 if let Some(slice) = dest {
45 slice[*destlen] = c
46 }
47 *destlen += 1
48 struct Dest<'a> {
49 dest: Option<&'a mut [u8]>,
50 pub len: usize,
48 51 }
49 52
50 fn memcopy(dest: Option<&mut [u8]>, destlen: &mut usize, src: &[u8]) {
51 if let Some(slice) = dest {
52 slice[*destlen..*destlen + src.len()].copy_from_slice(src)
53 impl<'a> Dest<'a> {
54 pub fn create(buf: &'a mut [u8]) -> Dest<'a> {
55 Dest {
56 dest: Some(buf),
57 len: 0,
53 58 }
54 *destlen += src.len();
59 }
60
61 pub fn create_measure() -> Dest<'a> {
62 Dest { dest: None, len: 0 }
63 }
55 64 }
56 65
57 66 fn rewrap_option<'a, 'b: 'a>(
@@ -63,38 +72,49 b" fn rewrap_option<'a, 'b: 'a>("
63 72 }
64 73 }
65 74
66 fn hexencode(mut dest: Option<&mut [u8]>, destlen: &mut usize, c: u8) {
75 impl<'a> Sink for Dest<'a> {
76 fn write_byte(&mut self, c: u8) {
77 if let Some(slice) = rewrap_option(&mut self.dest) {
78 slice[self.len] = c
79 }
80 self.len += 1
81 }
82
83 fn write_bytes(&mut self, src: &[u8]) {
84 if let Some(slice) = rewrap_option(&mut self.dest) {
85 slice[self.len..self.len + src.len()].copy_from_slice(src)
86 }
87 self.len += src.len();
88 }
89 }
90
91 fn hexencode(dest: &mut impl Sink, c: u8) {
67 92 let hexdigit = b"0123456789abcdef";
68 charcopy(
69 rewrap_option(&mut dest),
70 destlen,
71 hexdigit[(c as usize) >> 4],
72 );
73 charcopy(dest, destlen, hexdigit[(c as usize) & 15]);
93 dest.write_byte(hexdigit[(c as usize) >> 4]);
94 dest.write_byte(hexdigit[(c as usize) & 15]);
74 95 }
75 96
76 97 /* 3-byte escape: tilde followed by two hex digits */
77 fn escape3(mut dest: Option<&mut [u8]>, destlen: &mut usize, c: u8) {
78 charcopy(rewrap_option(&mut dest), destlen, b'~');
79 hexencode(dest, destlen, c);
98 fn escape3(dest: &mut impl Sink, c: u8) {
99 dest.write_byte(b'~');
100 hexencode(dest, c);
80 101 }
81 102
82 fn encode_dir(mut dest: Option<&mut [u8]>, src: &[u8]) -> usize {
103 fn encode_dir(dest: &mut impl Sink, src: &[u8]) {
83 104 let mut state = dir_state::DDEFAULT;
84 105 let mut i = 0;
85 let mut destlen = 0;
86 106
87 107 while i < src.len() {
88 108 match state {
89 109 dir_state::DDOT => match src[i] {
90 110 b'd' | b'i' => {
91 111 state = dir_state::DHGDI;
92 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
112 dest.write_byte(src[i]);
93 113 i += 1;
94 114 }
95 115 b'h' => {
96 116 state = dir_state::DH;
97 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
117 dest.write_byte(src[i]);
98 118 i += 1;
99 119 }
100 120 _ => {
@@ -104,7 +124,7 b' fn encode_dir(mut dest: Option<&mut [u8]'
104 124 dir_state::DH => {
105 125 if src[i] == b'g' {
106 126 state = dir_state::DHGDI;
107 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
127 dest.write_byte(src[i]);
108 128 i += 1;
109 129 } else {
110 130 state = dir_state::DDEFAULT;
@@ -112,8 +132,8 b' fn encode_dir(mut dest: Option<&mut [u8]'
112 132 }
113 133 dir_state::DHGDI => {
114 134 if src[i] == b'/' {
115 memcopy(rewrap_option(&mut dest), &mut destlen, b".hg");
116 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
135 dest.write_bytes(b".hg");
136 dest.write_byte(src[i]);
117 137 i += 1;
118 138 }
119 139 state = dir_state::DDEFAULT;
@@ -122,66 +142,64 b' fn encode_dir(mut dest: Option<&mut [u8]'
122 142 if src[i] == b'.' {
123 143 state = dir_state::DDOT
124 144 }
125 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
145 dest.write_byte(src[i]);
126 146 i += 1;
127 147 }
128 148 }
129 149 }
130 destlen
131 150 }
132 151
133 152 fn _encode(
134 153 twobytes: &[u32; 8],
135 154 onebyte: &[u32; 8],
136 mut dest: Option<&mut [u8]>,
155 dest: &mut impl Sink,
137 156 src: &[u8],
138 157 encodedir: bool,
139 ) -> usize {
158 ) {
140 159 let mut state = path_state::START;
141 160 let mut i = 0;
142 let mut destlen = 0;
143 161 let len = src.len();
144 162
145 163 while i < len {
146 164 match state {
147 165 path_state::START => match src[i] {
148 166 b'/' => {
149 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
167 dest.write_byte(src[i]);
150 168 i += 1;
151 169 }
152 170 b'.' => {
153 171 state = path_state::LDOT;
154 escape3(rewrap_option(&mut dest), &mut destlen, src[i]);
172 escape3(dest, src[i]);
155 173 i += 1;
156 174 }
157 175 b' ' => {
158 176 state = path_state::DEFAULT;
159 escape3(rewrap_option(&mut dest), &mut destlen, src[i]);
177 escape3(dest, src[i]);
160 178 i += 1;
161 179 }
162 180 b'a' => {
163 181 state = path_state::A;
164 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
182 dest.write_byte(src[i]);
165 183 i += 1;
166 184 }
167 185 b'c' => {
168 186 state = path_state::C;
169 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
187 dest.write_byte(src[i]);
170 188 i += 1;
171 189 }
172 190 b'l' => {
173 191 state = path_state::L;
174 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
192 dest.write_byte(src[i]);
175 193 i += 1;
176 194 }
177 195 b'n' => {
178 196 state = path_state::N;
179 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
197 dest.write_byte(src[i]);
180 198 i += 1;
181 199 }
182 200 b'p' => {
183 201 state = path_state::P;
184 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
202 dest.write_byte(src[i]);
185 203 i += 1;
186 204 }
187 205 _ => {
@@ -191,7 +209,7 b' fn _encode('
191 209 path_state::A => {
192 210 if src[i] == b'u' {
193 211 state = path_state::AU;
194 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
212 dest.write_byte(src[i]);
195 213 i += 1;
196 214 } else {
197 215 state = path_state::DEFAULT;
@@ -208,18 +226,14 b' fn _encode('
208 226 path_state::THIRD => {
209 227 state = path_state::DEFAULT;
210 228 match src[i] {
211 b'.' | b'/' | b'\0' => escape3(
212 rewrap_option(&mut dest),
213 &mut destlen,
214 src[i - 1],
215 ),
229 b'.' | b'/' | b'\0' => escape3(dest, src[i - 1]),
216 230 _ => i -= 1,
217 231 }
218 232 }
219 233 path_state::C => {
220 234 if src[i] == b'o' {
221 235 state = path_state::CO;
222 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
236 dest.write_byte(src[i]);
223 237 i += 1;
224 238 } else {
225 239 state = path_state::DEFAULT;
@@ -242,41 +256,25 b' fn _encode('
242 256 i += 1;
243 257 } else {
244 258 state = path_state::DEFAULT;
245 charcopy(
246 rewrap_option(&mut dest),
247 &mut destlen,
248 src[i - 1],
249 );
259 dest.write_byte(src[i - 1]);
250 260 }
251 261 }
252 262 path_state::COMLPTn => {
253 263 state = path_state::DEFAULT;
254 264 match src[i] {
255 265 b'.' | b'/' | b'\0' => {
256 escape3(
257 rewrap_option(&mut dest),
258 &mut destlen,
259 src[i - 2],
260 );
261 charcopy(
262 rewrap_option(&mut dest),
263 &mut destlen,
264 src[i - 1],
265 );
266 escape3(dest, src[i - 2]);
267 dest.write_byte(src[i - 1]);
266 268 }
267 269 _ => {
268 memcopy(
269 rewrap_option(&mut dest),
270 &mut destlen,
271 &src[i - 2..i],
272 );
270 dest.write_bytes(&src[i - 2..i]);
273 271 }
274 272 }
275 273 }
276 274 path_state::L => {
277 275 if src[i] == b'p' {
278 276 state = path_state::LP;
279 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
277 dest.write_byte(src[i]);
280 278 i += 1;
281 279 } else {
282 280 state = path_state::DEFAULT;
@@ -293,7 +291,7 b' fn _encode('
293 291 path_state::N => {
294 292 if src[i] == b'u' {
295 293 state = path_state::NU;
296 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
294 dest.write_byte(src[i]);
297 295 i += 1;
298 296 } else {
299 297 state = path_state::DEFAULT;
@@ -310,7 +308,7 b' fn _encode('
310 308 path_state::P => {
311 309 if src[i] == b'r' {
312 310 state = path_state::PR;
313 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
311 dest.write_byte(src[i]);
314 312 i += 1;
315 313 } else {
316 314 state = path_state::DEFAULT;
@@ -327,12 +325,12 b' fn _encode('
327 325 path_state::LDOT => match src[i] {
328 326 b'd' | b'i' => {
329 327 state = path_state::HGDI;
330 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
328 dest.write_byte(src[i]);
331 329 i += 1;
332 330 }
333 331 b'h' => {
334 332 state = path_state::H;
335 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
333 dest.write_byte(src[i]);
336 334 i += 1;
337 335 }
338 336 _ => {
@@ -342,30 +340,30 b' fn _encode('
342 340 path_state::DOT => match src[i] {
343 341 b'/' | b'\0' => {
344 342 state = path_state::START;
345 memcopy(rewrap_option(&mut dest), &mut destlen, b"~2e");
346 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
343 dest.write_bytes(b"~2e");
344 dest.write_byte(src[i]);
347 345 i += 1;
348 346 }
349 347 b'd' | b'i' => {
350 348 state = path_state::HGDI;
351 charcopy(rewrap_option(&mut dest), &mut destlen, b'.');
352 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
349 dest.write_byte(b'.');
350 dest.write_byte(src[i]);
353 351 i += 1;
354 352 }
355 353 b'h' => {
356 354 state = path_state::H;
357 memcopy(rewrap_option(&mut dest), &mut destlen, b".h");
355 dest.write_bytes(b".h");
358 356 i += 1;
359 357 }
360 358 _ => {
361 359 state = path_state::DEFAULT;
362 charcopy(rewrap_option(&mut dest), &mut destlen, b'.');
360 dest.write_byte(b'.');
363 361 }
364 362 },
365 363 path_state::H => {
366 364 if src[i] == b'g' {
367 365 state = path_state::HGDI;
368 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
366 dest.write_byte(src[i]);
369 367 i += 1;
370 368 } else {
371 369 state = path_state::DEFAULT;
@@ -375,13 +373,9 b' fn _encode('
375 373 if src[i] == b'/' {
376 374 state = path_state::START;
377 375 if encodedir {
378 memcopy(
379 rewrap_option(&mut dest),
380 &mut destlen,
381 b".hg",
382 );
376 dest.write_bytes(b".hg");
383 377 }
384 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
378 dest.write_byte(src[i]);
385 379 i += 1
386 380 } else {
387 381 state = path_state::DEFAULT;
@@ -390,18 +384,18 b' fn _encode('
390 384 path_state::SPACE => match src[i] {
391 385 b'/' | b'\0' => {
392 386 state = path_state::START;
393 memcopy(rewrap_option(&mut dest), &mut destlen, b"~20");
394 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
387 dest.write_bytes(b"~20");
388 dest.write_byte(src[i]);
395 389 i += 1;
396 390 }
397 391 _ => {
398 392 state = path_state::DEFAULT;
399 charcopy(rewrap_option(&mut dest), &mut destlen, b' ');
393 dest.write_byte(b' ');
400 394 }
401 395 },
402 396 path_state::DEFAULT => {
403 397 while i != len && inset(onebyte, src[i]) {
404 charcopy(rewrap_option(&mut dest), &mut destlen, src[i]);
398 dest.write_byte(src[i]);
405 399 i += 1;
406 400 }
407 401 if i == len {
@@ -418,17 +412,13 b' fn _encode('
418 412 }
419 413 b'/' => {
420 414 state = path_state::START;
421 charcopy(rewrap_option(&mut dest), &mut destlen, b'/');
415 dest.write_byte(b'/');
422 416 i += 1;
423 417 }
424 418 _ => {
425 419 if inset(onebyte, src[i]) {
426 420 loop {
427 charcopy(
428 rewrap_option(&mut dest),
429 &mut destlen,
430 src[i],
431 );
421 dest.write_byte(src[i]);
432 422 i += 1;
433 423 if !(i < len && inset(onebyte, src[i])) {
434 424 break;
@@ -437,22 +427,14 b' fn _encode('
437 427 } else if inset(twobytes, src[i]) {
438 428 let c = src[i];
439 429 i += 1;
440 charcopy(
441 rewrap_option(&mut dest),
442 &mut destlen,
443 b'_',
444 );
445 charcopy(
446 rewrap_option(&mut dest),
447 &mut destlen,
448 if c == b'_' { b'_' } else { c + 32 },
449 );
430 dest.write_byte(b'_');
431 dest.write_byte(if c == b'_' {
432 b'_'
450 433 } else {
451 escape3(
452 rewrap_option(&mut dest),
453 &mut destlen,
454 src[i],
455 );
434 c + 32
435 });
436 } else {
437 escape3(dest, src[i]);
456 438 i += 1;
457 439 }
458 440 }
@@ -464,17 +446,13 b' fn _encode('
464 446 path_state::START => (),
465 447 path_state::A => (),
466 448 path_state::AU => (),
467 path_state::THIRD => {
468 escape3(rewrap_option(&mut dest), &mut destlen, src[i - 1])
469 }
449 path_state::THIRD => escape3(dest, src[i - 1]),
470 450 path_state::C => (),
471 451 path_state::CO => (),
472 path_state::COMLPT => {
473 charcopy(rewrap_option(&mut dest), &mut destlen, src[i - 1])
474 }
452 path_state::COMLPT => dest.write_byte(src[i - 1]),
475 453 path_state::COMLPTn => {
476 escape3(rewrap_option(&mut dest), &mut destlen, src[i - 2]);
477 charcopy(rewrap_option(&mut dest), &mut destlen, src[i - 1]);
454 escape3(dest, src[i - 2]);
455 dest.write_byte(src[i - 1]);
478 456 }
479 457 path_state::L => (),
480 458 path_state::LP => (),
@@ -484,19 +462,18 b' fn _encode('
484 462 path_state::PR => (),
485 463 path_state::LDOT => (),
486 464 path_state::DOT => {
487 memcopy(rewrap_option(&mut dest), &mut destlen, b"~2e");
465 dest.write_bytes(b"~2e");
488 466 }
489 467 path_state::H => (),
490 468 path_state::HGDI => (),
491 469 path_state::SPACE => {
492 memcopy(rewrap_option(&mut dest), &mut destlen, b"~20");
470 dest.write_bytes(b"~20");
493 471 }
494 472 path_state::DEFAULT => (),
495 };
496 destlen
473 }
497 474 }
498 475
499 fn basic_encode(dest: Option<&mut [u8]>, src: &[u8]) -> usize {
476 fn basic_encode(dest: &mut impl Sink, src: &[u8]) {
500 477 let twobytes: [u32; 8] = [0, 0, 0x87ff_fffe, 0, 0, 0, 0, 0];
501 478 let onebyte: [u32; 8] =
502 479 [1, 0x2bff_3bfa, 0x6800_0001, 0x2fff_ffff, 0, 0, 0, 0];
@@ -505,24 +482,22 b' fn basic_encode(dest: Option<&mut [u8]>,'
505 482
506 483 const MAXSTOREPATHLEN: usize = 120;
507 484
508 fn lower_encode(mut dest: Option<&mut [u8]>, src: &[u8]) -> usize {
485 fn lower_encode(dest: &mut impl Sink, src: &[u8]) {
509 486 let onebyte: [u32; 8] =
510 487 [1, 0x2bff_fbfb, 0xe800_0001, 0x2fff_ffff, 0, 0, 0, 0];
511 488 let lower: [u32; 8] = [0, 0, 0x07ff_fffe, 0, 0, 0, 0, 0];
512 let mut destlen = 0;
513 489 for c in src {
514 490 if inset(&onebyte, *c) {
515 charcopy(rewrap_option(&mut dest), &mut destlen, *c)
491 dest.write_byte(*c)
516 492 } else if inset(&lower, *c) {
517 charcopy(rewrap_option(&mut dest), &mut destlen, *c + 32)
493 dest.write_byte(*c + 32)
518 494 } else {
519 escape3(rewrap_option(&mut dest), &mut destlen, *c)
495 escape3(dest, *c)
520 496 }
521 497 }
522 destlen
523 498 }
524 499
525 fn aux_encode(dest: Option<&mut [u8]>, src: &[u8]) -> usize {
500 fn aux_encode(dest: &mut impl Sink, src: &[u8]) {
526 501 let twobytes = [0; 8];
527 502 let onebyte: [u32; 8] = [!0, 0xffff_3ffe, !0, !0, !0, !0, !0, !0];
528 503 _encode(&twobytes, &onebyte, dest, src, false)
@@ -531,7 +506,6 b' fn aux_encode(dest: Option<&mut [u8]>, s'
531 506 fn hash_mangle(src: &[u8], sha: &[u8]) -> Vec<u8> {
532 507 let dirprefixlen = 8;
533 508 let maxshortdirslen = 68;
534 let mut destlen = 0;
535 509
536 510 let last_slash = src.iter().rposition(|b| *b == b'/');
537 511 let last_dot: Option<usize> = {
@@ -539,25 +513,23 b' fn hash_mangle(src: &[u8], sha: &[u8]) -'
539 513 src[s..].iter().rposition(|b| *b == b'.').map(|i| i + s)
540 514 };
541 515
542 let mut dest = vec![0; MAXSTOREPATHLEN];
543 memcopy(Some(&mut dest), &mut destlen, b"dh/");
516 let mut dest_vec = vec![0; MAXSTOREPATHLEN];
517 let mut dest = Dest::create(&mut dest_vec);
518 dest.write_bytes(b"dh/");
544 519
545 520 if let Some(last_slash) = last_slash {
546 521 for slice in src[..last_slash].split(|b| *b == b'/') {
547 522 let slice = &slice[..std::cmp::min(slice.len(), dirprefixlen)];
548 if destlen + slice.len() > maxshortdirslen + 3 {
523 if dest.len + slice.len() > maxshortdirslen + 3 {
549 524 break;
550 525 } else {
551 memcopy(Some(&mut dest), &mut destlen, slice);
552 if dest[destlen - 1] == b'.' || dest[destlen - 1] == b' ' {
553 dest[destlen - 1] = b'_'
526 dest.write_bytes(slice);
554 527 }
555 }
556 charcopy(Some(&mut dest), &mut destlen, b'/');
528 dest.write_byte(b'/');
557 529 }
558 530 }
559 531
560 let used = destlen + 40 + {
532 let used = dest.len + 40 + {
561 533 if let Some(l) = last_dot {
562 534 src.len() - l
563 535 } else {
@@ -577,46 +549,51 b' fn hash_mangle(src: &[u8], sha: &[u8]) -'
577 549 Some(l) => l + 1,
578 550 None => 0,
579 551 };
580 memcopy(
581 Some(&mut dest),
582 &mut destlen,
583 &src[start..][..basenamelen],
584 )
552 dest.write_bytes(&src[start..][..basenamelen])
585 553 }
586 554 }
587 555 for c in sha {
588 hexencode(Some(&mut dest), &mut destlen, *c);
556 hexencode(&mut dest, *c);
589 557 }
590 558 if let Some(l) = last_dot {
591 memcopy(Some(&mut dest), &mut destlen, &src[l..]);
559 dest.write_bytes(&src[l..]);
592 560 }
593 if destlen == dest.len() {
594 dest
561 let destlen = dest.len;
562 if destlen == dest_vec.len() {
563 dest_vec
595 564 } else {
596 565 // sometimes the path are shorter than MAXSTOREPATHLEN
597 dest[..destlen].to_vec()
566 dest_vec[..destlen].to_vec()
598 567 }
599 568 }
600 569
601 570 const MAXENCODE: usize = 4096 * 4;
602 571 fn hash_encode(src: &[u8]) -> Vec<u8> {
603 572 let dired = &mut [0; MAXENCODE];
573 let mut dired_dest = Dest::create(dired);
604 574 let lowered = &mut [0; MAXENCODE];
575 let mut lowered_dest = Dest::create(lowered);
605 576 let auxed = &mut [0; MAXENCODE];
577 let mut auxed_dest = Dest::create(auxed);
606 578 let baselen = (src.len() - 5) * 3;
607 579 if baselen >= MAXENCODE {
608 580 panic!("path_encode::hash_encore: string too long: {}", baselen)
609 581 };
610 let dirlen = encode_dir(Some(&mut dired[..]), src);
582 encode_dir(&mut dired_dest, src);
583 let dirlen = dired_dest.len;
611 584 let sha = Sha1::digest(&dired[..dirlen]);
612 let lowerlen = lower_encode(Some(&mut lowered[..]), &dired[..dirlen][5..]);
613 let auxlen = aux_encode(Some(&mut auxed[..]), &lowered[..lowerlen]);
585 lower_encode(&mut lowered_dest, &dired[..dirlen][5..]);
586 let lowerlen = lowered_dest.len;
587 aux_encode(&mut auxed_dest, &lowered[..lowerlen]);
588 let auxlen = auxed_dest.len;
614 589 hash_mangle(&auxed[..auxlen], &sha)
615 590 }
616 591
617 592 pub fn path_encode(path: &[u8]) -> Vec<u8> {
618 593 let newlen = if path.len() <= MAXSTOREPATHLEN {
619 basic_encode(None, path)
594 let mut measure = Dest::create_measure();
595 basic_encode(&mut measure, path);
596 measure.len
620 597 } else {
621 598 MAXSTOREPATHLEN + 1
622 599 };
@@ -625,7 +602,9 b' pub fn path_encode(path: &[u8]) -> Vec<u'
625 602 path.to_vec()
626 603 } else {
627 604 let mut res = vec![0; newlen];
628 basic_encode(Some(&mut res), path);
605 let mut dest = Dest::create(&mut res);
606 basic_encode(&mut dest, path);
607 assert!(dest.len == newlen);
629 608 res
630 609 }
631 610 } else {
General Comments 0
You need to be logged in to leave comments. Login now