##// END OF EJS Templates
rust-index: add an abstraction to support bytes added at runtimes...
rust-index: add an abstraction to support bytes added at runtimes In order to support appending data to the Rust index, we need to abstract data access away from the immutable (on-disk) bytes, to seemlessly fetch either from the preexisting data or from the newly added data.

File last commit:

r51264:3f513754 stable
r52081:1ef4a36a default
Show More
path_encode.rs
639 lines | 18.5 KiB | application/rls-services+xml | RustLexer
Simon Sapin
rust: Use a maintained crate for SHA-1 hashing...
r48171 use sha1::{Digest, Sha1};
Antoine Cezar
hg-core: add path_encode...
r46110
#[derive(PartialEq, Debug)]
#[allow(non_camel_case_types)]
Raphaël Gomès
rust-clippy: fix most warnings in `hg-core`...
r50825 #[allow(clippy::upper_case_acronyms)]
Antoine Cezar
hg-core: add path_encode...
r46110 enum path_state {
START, /* first byte of a path component */
A, /* "AUX" */
AU,
THIRD, /* third of a 3-byte sequence, e.g. "AUX", "NUL" */
C, /* "CON" or "COMn" */
CO,
COMLPT, /* "COM" or "LPT" */
COMLPTn,
L,
LP,
N,
NU,
P, /* "PRN" */
PR,
LDOT, /* leading '.' */
DOT, /* '.' in a non-leading position */
H, /* ".h" */
HGDI, /* ".hg", ".d", or ".i" */
SPACE,
DEFAULT, /* byte of a path component after the first */
}
/* state machine for dir-encoding */
#[allow(non_camel_case_types)]
Raphaël Gomès
rust-clippy: fix most warnings in `hg-core`...
r50825 #[allow(clippy::upper_case_acronyms)]
Antoine Cezar
hg-core: add path_encode...
r46110 enum dir_state {
DDOT,
DH,
DHGDI,
DDEFAULT,
}
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 trait Sink {
fn write_byte(&mut self, c: u8);
fn write_bytes(&mut self, c: &[u8]);
}
Antoine Cezar
hg-core: add path_encode...
r46110 fn inset(bitset: &[u32; 8], c: u8) -> bool {
bitset[(c as usize) >> 5] & (1 << (c & 31)) != 0
}
Arseniy Alekseyev
rhg: in path_encode add a DestArr type...
r51055 const MAXENCODE: usize = 4096 * 4;
Arseniy Alekseyev
rhg: in path_encode, make DestArr generic over its size
r51056 struct DestArr<const N: usize> {
buf: [u8; N],
Arseniy Alekseyev
rhg: in path_encode add a DestArr type...
r51055 pub len: usize,
}
Arseniy Alekseyev
rhg: in path_encode, make DestArr generic over its size
r51056 impl<const N: usize> DestArr<N> {
Arseniy Alekseyev
rhg: in path_encode add a DestArr type...
r51055 pub fn create() -> Self {
DestArr {
Arseniy Alekseyev
rhg: in path_encode, make DestArr generic over its size
r51056 buf: [0; N],
Arseniy Alekseyev
rhg: in path_encode add a DestArr type...
r51055 len: 0,
}
}
pub fn contents(&self) -> &[u8] {
&self.buf[..self.len]
}
}
Arseniy Alekseyev
rhg: in path_encode, make DestArr generic over its size
r51056 impl<const N: usize> Sink for DestArr<N> {
Arseniy Alekseyev
rhg: in path_encode add a DestArr type...
r51055 fn write_byte(&mut self, c: u8) {
self.buf[self.len] = c;
self.len += 1;
}
fn write_bytes(&mut self, src: &[u8]) {
self.buf[self.len..self.len + src.len()].copy_from_slice(src);
self.len += src.len();
}
}
Arseniy Alekseyev
rhg: in path_encode, split Dest into VecDest and MeasureDest...
r51058 struct MeasureDest {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 pub len: usize,
Antoine Cezar
hg-core: add path_encode...
r46110 }
Arseniy Alekseyev
rhg: in path_encode, use Vec directly instead of VecDest...
r51059 impl Sink for Vec<u8> {
Arseniy Alekseyev
rhg: in path_encode, split Dest into VecDest and MeasureDest...
r51058 fn write_byte(&mut self, c: u8) {
Arseniy Alekseyev
rhg: in path_encode, use Vec directly instead of VecDest...
r51059 self.push(c)
Arseniy Alekseyev
rhg: in path_encode, split Dest into VecDest and MeasureDest...
r51058 }
fn write_bytes(&mut self, src: &[u8]) {
Arseniy Alekseyev
rhg: in path_encode, use Vec directly instead of VecDest...
r51059 self.extend_from_slice(src)
Antoine Cezar
hg-core: add path_encode...
r46110 }
}
Arseniy Alekseyev
rhg: in path_encode, split Dest into VecDest and MeasureDest...
r51058 impl MeasureDest {
fn create() -> Self {
Self { len: 0 }
}
}
impl Sink for MeasureDest {
fn write_byte(&mut self, _c: u8) {
self.len += 1;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 }
fn write_bytes(&mut self, src: &[u8]) {
self.len += src.len();
}
}
fn hexencode(dest: &mut impl Sink, c: u8) {
Antoine Cezar
hg-core: add path_encode...
r46110 let hexdigit = b"0123456789abcdef";
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(hexdigit[(c as usize) >> 4]);
dest.write_byte(hexdigit[(c as usize) & 15]);
Antoine Cezar
hg-core: add path_encode...
r46110 }
/* 3-byte escape: tilde followed by two hex digits */
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 fn escape3(dest: &mut impl Sink, c: u8) {
dest.write_byte(b'~');
hexencode(dest, c);
Antoine Cezar
hg-core: add path_encode...
r46110 }
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 fn encode_dir(dest: &mut impl Sink, src: &[u8]) {
Antoine Cezar
hg-core: add path_encode...
r46110 let mut state = dir_state::DDEFAULT;
let mut i = 0;
while i < src.len() {
match state {
dir_state::DDOT => match src[i] {
b'd' | b'i' => {
state = dir_state::DHGDI;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
b'h' => {
state = dir_state::DH;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
_ => {
state = dir_state::DDEFAULT;
}
},
dir_state::DH => {
if src[i] == b'g' {
state = dir_state::DHGDI;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
} else {
state = dir_state::DDEFAULT;
}
}
dir_state::DHGDI => {
if src[i] == b'/' {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_bytes(b".hg");
dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
state = dir_state::DDEFAULT;
}
dir_state::DDEFAULT => {
if src[i] == b'.' {
state = dir_state::DDOT
}
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
}
}
}
fn _encode(
twobytes: &[u32; 8],
onebyte: &[u32; 8],
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest: &mut impl Sink,
Antoine Cezar
hg-core: add path_encode...
r46110 src: &[u8],
encodedir: bool,
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 ) {
Antoine Cezar
hg-core: add path_encode...
r46110 let mut state = path_state::START;
let mut i = 0;
let len = src.len();
while i < len {
match state {
path_state::START => match src[i] {
b'/' => {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
b'.' => {
state = path_state::LDOT;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 escape3(dest, src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
b' ' => {
state = path_state::DEFAULT;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 escape3(dest, src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
b'a' => {
state = path_state::A;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
b'c' => {
state = path_state::C;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
b'l' => {
state = path_state::L;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
b'n' => {
state = path_state::N;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
b'p' => {
state = path_state::P;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
_ => {
state = path_state::DEFAULT;
}
},
path_state::A => {
if src[i] == b'u' {
state = path_state::AU;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
} else {
state = path_state::DEFAULT;
}
}
path_state::AU => {
if src[i] == b'x' {
state = path_state::THIRD;
i += 1;
} else {
state = path_state::DEFAULT;
}
}
path_state::THIRD => {
state = path_state::DEFAULT;
match src[i] {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 b'.' | b'/' | b'\0' => escape3(dest, src[i - 1]),
Antoine Cezar
hg-core: add path_encode...
r46110 _ => i -= 1,
}
}
path_state::C => {
if src[i] == b'o' {
state = path_state::CO;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
} else {
state = path_state::DEFAULT;
}
}
path_state::CO => {
if src[i] == b'm' {
state = path_state::COMLPT;
i += 1;
} else if src[i] == b'n' {
state = path_state::THIRD;
i += 1;
} else {
state = path_state::DEFAULT;
}
}
path_state::COMLPT => {
if src[i] >= b'1' && src[i] <= b'9' {
state = path_state::COMLPTn;
i += 1;
} else {
state = path_state::DEFAULT;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i - 1]);
Antoine Cezar
hg-core: add path_encode...
r46110 }
}
path_state::COMLPTn => {
state = path_state::DEFAULT;
match src[i] {
b'.' | b'/' | b'\0' => {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 escape3(dest, src[i - 2]);
dest.write_byte(src[i - 1]);
Antoine Cezar
hg-core: add path_encode...
r46110 }
_ => {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_bytes(&src[i - 2..i]);
Antoine Cezar
hg-core: add path_encode...
r46110 }
}
}
path_state::L => {
if src[i] == b'p' {
state = path_state::LP;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
} else {
state = path_state::DEFAULT;
}
}
path_state::LP => {
if src[i] == b't' {
state = path_state::COMLPT;
i += 1;
} else {
state = path_state::DEFAULT;
}
}
path_state::N => {
if src[i] == b'u' {
state = path_state::NU;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
} else {
state = path_state::DEFAULT;
}
}
path_state::NU => {
if src[i] == b'l' {
state = path_state::THIRD;
i += 1;
} else {
state = path_state::DEFAULT;
}
}
path_state::P => {
if src[i] == b'r' {
state = path_state::PR;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
} else {
state = path_state::DEFAULT;
}
}
path_state::PR => {
if src[i] == b'n' {
state = path_state::THIRD;
i += 1;
} else {
state = path_state::DEFAULT;
}
}
path_state::LDOT => match src[i] {
b'd' | b'i' => {
state = path_state::HGDI;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
b'h' => {
state = path_state::H;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
_ => {
state = path_state::DEFAULT;
}
},
path_state::DOT => match src[i] {
b'/' | b'\0' => {
state = path_state::START;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_bytes(b"~2e");
dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
b'd' | b'i' => {
state = path_state::HGDI;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(b'.');
dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
b'h' => {
state = path_state::H;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_bytes(b".h");
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
_ => {
state = path_state::DEFAULT;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(b'.');
Antoine Cezar
hg-core: add path_encode...
r46110 }
},
path_state::H => {
if src[i] == b'g' {
state = path_state::HGDI;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
} else {
state = path_state::DEFAULT;
}
}
path_state::HGDI => {
if src[i] == b'/' {
state = path_state::START;
if encodedir {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_bytes(b".hg");
Antoine Cezar
hg-core: add path_encode...
r46110 }
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1
} else {
state = path_state::DEFAULT;
}
}
path_state::SPACE => match src[i] {
b'/' | b'\0' => {
state = path_state::START;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_bytes(b"~20");
dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
_ => {
state = path_state::DEFAULT;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(b' ');
Antoine Cezar
hg-core: add path_encode...
r46110 }
},
path_state::DEFAULT => {
while i != len && inset(onebyte, src[i]) {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
if i == len {
break;
}
match src[i] {
b'.' => {
state = path_state::DOT;
i += 1
}
b' ' => {
state = path_state::SPACE;
i += 1
}
b'/' => {
state = path_state::START;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(b'/');
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
_ => {
if inset(onebyte, src[i]) {
loop {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
if !(i < len && inset(onebyte, src[i])) {
break;
}
}
} else if inset(twobytes, src[i]) {
let c = src[i];
i += 1;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(b'_');
dest.write_byte(if c == b'_' {
b'_'
} else {
c + 32
});
Antoine Cezar
hg-core: add path_encode...
r46110 } else {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 escape3(dest, src[i]);
Antoine Cezar
hg-core: add path_encode...
r46110 i += 1;
}
}
}
}
}
}
match state {
path_state::START => (),
path_state::A => (),
path_state::AU => (),
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 path_state::THIRD => escape3(dest, src[i - 1]),
Antoine Cezar
hg-core: add path_encode...
r46110 path_state::C => (),
path_state::CO => (),
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 path_state::COMLPT => dest.write_byte(src[i - 1]),
Antoine Cezar
hg-core: add path_encode...
r46110 path_state::COMLPTn => {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 escape3(dest, src[i - 2]);
dest.write_byte(src[i - 1]);
Antoine Cezar
hg-core: add path_encode...
r46110 }
path_state::L => (),
path_state::LP => (),
path_state::N => (),
path_state::NU => (),
path_state::P => (),
path_state::PR => (),
path_state::LDOT => (),
path_state::DOT => {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_bytes(b"~2e");
Antoine Cezar
hg-core: add path_encode...
r46110 }
path_state::H => (),
path_state::HGDI => (),
path_state::SPACE => {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_bytes(b"~20");
Antoine Cezar
hg-core: add path_encode...
r46110 }
path_state::DEFAULT => (),
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 }
Antoine Cezar
hg-core: add path_encode...
r46110 }
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 fn basic_encode(dest: &mut impl Sink, src: &[u8]) {
Antoine Cezar
hg-core: add path_encode...
r46110 let twobytes: [u32; 8] = [0, 0, 0x87ff_fffe, 0, 0, 0, 0, 0];
let onebyte: [u32; 8] =
[1, 0x2bff_3bfa, 0x6800_0001, 0x2fff_ffff, 0, 0, 0, 0];
_encode(&twobytes, &onebyte, dest, src, true)
}
const MAXSTOREPATHLEN: usize = 120;
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 fn lower_encode(dest: &mut impl Sink, src: &[u8]) {
Antoine Cezar
hg-core: add path_encode...
r46110 let onebyte: [u32; 8] =
[1, 0x2bff_fbfb, 0xe800_0001, 0x2fff_ffff, 0, 0, 0, 0];
let lower: [u32; 8] = [0, 0, 0x07ff_fffe, 0, 0, 0, 0, 0];
for c in src {
if inset(&onebyte, *c) {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(*c)
Antoine Cezar
hg-core: add path_encode...
r46110 } else if inset(&lower, *c) {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(*c + 32)
Antoine Cezar
hg-core: add path_encode...
r46110 } else {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 escape3(dest, *c)
Antoine Cezar
hg-core: add path_encode...
r46110 }
}
}
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 fn aux_encode(dest: &mut impl Sink, src: &[u8]) {
Antoine Cezar
hg-core: add path_encode...
r46110 let twobytes = [0; 8];
let onebyte: [u32; 8] = [!0, 0xffff_3ffe, !0, !0, !0, !0, !0, !0];
_encode(&twobytes, &onebyte, dest, src, false)
}
fn hash_mangle(src: &[u8], sha: &[u8]) -> Vec<u8> {
let dirprefixlen = 8;
let maxshortdirslen = 68;
let last_slash = src.iter().rposition(|b| *b == b'/');
Arseniy Alekseyev
rhg: in path_encode, simplify a bit more...
r51062 let basename_start = match last_slash {
Some(slash) => slash + 1,
None => 0,
};
let basename = &src[basename_start..];
let ext = match basename.iter().rposition(|b| *b == b'.') {
None => &[],
Some(dot) => &basename[dot..],
Antoine Cezar
hg-core: add path_encode...
r46110 };
Arseniy Alekseyev
rhg: in path_encode, use Vec directly instead of VecDest...
r51059 let mut dest = Vec::with_capacity(MAXSTOREPATHLEN);
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_bytes(b"dh/");
Antoine Cezar
hg-core: add path_encode...
r46110
Arseniy Alekseyev
rhg: fix a bug in path_encode...
r50991 if let Some(last_slash) = last_slash {
for slice in src[..last_slash].split(|b| *b == b'/') {
Antoine Cezar
hg-core: add path_encode...
r46110 let slice = &slice[..std::cmp::min(slice.len(), dirprefixlen)];
Arseniy Alekseyev
rhg: in path_encode, use Vec directly instead of VecDest...
r51059 if dest.len() + slice.len() > maxshortdirslen + 3 {
Antoine Cezar
hg-core: add path_encode...
r46110 break;
Arseniy Alekseyev
rhg: don't crash on empty directory names in path_encode, just in case...
r51264 }
if let Some(last_char) = slice.last() {
if *last_char == b'.' || *last_char == b' ' {
Arseniy Alekseyev
rhg: fix a bug in path encoding, demonstrated in the parent commit
r51263 dest.write_bytes(&slice[0..slice.len() - 1]);
dest.write_byte(b'_');
} else {
dest.write_bytes(slice);
}
Arseniy Alekseyev
rhg: don't crash on empty directory names in path_encode, just in case...
r51264 };
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 dest.write_byte(b'/');
Antoine Cezar
hg-core: add path_encode...
r46110 }
}
Arseniy Alekseyev
rhg: in path_encode, simplify a bit more...
r51062 let used = dest.len() + 40 + ext.len();
Antoine Cezar
hg-core: add path_encode...
r46110
if MAXSTOREPATHLEN > used {
let slop = MAXSTOREPATHLEN - used;
Arseniy Alekseyev
rhg: in path_encode, simplify a bit more...
r51062 let len = std::cmp::min(basename.len(), slop);
dest.write_bytes(&basename[..len])
Antoine Cezar
hg-core: add path_encode...
r46110 }
for c in sha {
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 hexencode(&mut dest, *c);
Antoine Cezar
hg-core: add path_encode...
r46110 }
Arseniy Alekseyev
rhg: in path_encode, simplify a bit more...
r51062 dest.write_bytes(ext);
Arseniy Alekseyev
rhg: in path_encode, be a bit more conservative about memory usage...
r51061 dest.shrink_to_fit();
Arseniy Alekseyev
rhg: in path_encode, use Vec directly instead of VecDest...
r51059 dest
Antoine Cezar
hg-core: add path_encode...
r46110 }
fn hash_encode(src: &[u8]) -> Vec<u8> {
Arseniy Alekseyev
rhg: in path_encode, make DestArr generic over its size
r51056 let mut dired: DestArr<MAXENCODE> = DestArr::create();
let mut lowered: DestArr<MAXENCODE> = DestArr::create();
let mut auxed: DestArr<MAXENCODE> = DestArr::create();
Antoine Cezar
hg-core: add path_encode...
r46110 let baselen = (src.len() - 5) * 3;
if baselen >= MAXENCODE {
panic!("path_encode::hash_encore: string too long: {}", baselen)
};
Arseniy Alekseyev
rhg: in path_encode add a DestArr type...
r51055 encode_dir(&mut dired, src);
let sha = Sha1::digest(dired.contents());
lower_encode(&mut lowered, &dired.contents()[5..]);
aux_encode(&mut auxed, lowered.contents());
hash_mangle(auxed.contents(), &sha)
Antoine Cezar
hg-core: add path_encode...
r46110 }
pub fn path_encode(path: &[u8]) -> Vec<u8> {
let newlen = if path.len() <= MAXSTOREPATHLEN {
Arseniy Alekseyev
rhg: in path_encode, split Dest into VecDest and MeasureDest...
r51058 let mut measure = MeasureDest::create();
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 basic_encode(&mut measure, path);
measure.len
Antoine Cezar
hg-core: add path_encode...
r46110 } else {
Arseniy Alekseyev
rhg: small refactor: stop using a magical constant "+ 1"...
r51060 return hash_encode(path);
Antoine Cezar
hg-core: add path_encode...
r46110 };
if newlen <= MAXSTOREPATHLEN {
if newlen == path.len() {
path.to_vec()
} else {
Arseniy Alekseyev
rhg: in path_encode, use Vec directly instead of VecDest...
r51059 let mut dest = Vec::with_capacity(newlen);
Arseniy Alekseyev
rhg: reduce verbosity in path_encode by using a trait for writing...
r51054 basic_encode(&mut dest, path);
Arseniy Alekseyev
rhg: in path_encode, use Vec directly instead of VecDest...
r51059 assert!(dest.len() == newlen);
dest
Antoine Cezar
hg-core: add path_encode...
r46110 }
} else {
Raphaël Gomès
rust-clippy: fix most warnings in `hg-core`...
r50825 hash_encode(path)
Antoine Cezar
hg-core: add path_encode...
r46110 }
}
Arseniy Alekseyev
rhg: demonstrate a bug in path_encode...
r50990
#[cfg(test)]
mod tests {
use super::*;
use crate::utils::hg_path::HgPathBuf;
#[test]
Arseniy Alekseyev
rhg: show a bug in the rust implementation of path_encode introduced recently...
r51262 fn test_dirname_ends_with_underscore() {
let input = b"data/dir1234.foo/ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ.i";
Arseniy Alekseyev
rhg: fix a bug in path encoding, demonstrated in the parent commit
r51263 let expected = b"dh/dir1234_/abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij.if2e9ce59e095eff5f8f334dc809e65606a0aa50b.i";
Arseniy Alekseyev
rhg: show a bug in the rust implementation of path_encode introduced recently...
r51262 let res = path_encode(input);
assert_eq!(
HgPathBuf::from_bytes(&res),
HgPathBuf::from_bytes(expected)
);
}
#[test]
Arseniy Alekseyev
rhg: demonstrate a bug in path_encode...
r50990 fn test_long_filename_at_root() {
let input = b"data/ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ.i";
let expected = b"dh/abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij.i708243a2237a7afae259ea3545a72a2ef11c247b.i";
let res = path_encode(input);
assert_eq!(
HgPathBuf::from_bytes(&res),
HgPathBuf::from_bytes(expected)
);
}
}