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