MCPcopy Create free account
hub / github.com/archlinux/alpm / parser

Method parser

alpm-types/src/checksum.rs:319–401  ·  view source on GitHub ↗

Recognizes an ASCII hexadecimal [`Checksum`] from a string slice. Consumes all input. See [`Checksum::from_str`]. # Errors Returns an error if `input` is not the output of a _hash function_ in hexadecimal (or decimal in case of CRC-32/CKSUM) form.

(input: &mut &str)

Source from the content-addressed store, hash-verified

317 /// # Errors
318 ///
319 /// Returns an error if `input` does not start with the output of a _hash function_
320 /// in hexadecimal (or decimal in case of CRC-32/CKSUM) form.
321 fn parser(input: &mut &str) -> ModalResult<Self> {
322 /// Consume 1 hex digit and return its hex value.
323 ///
324 /// Accepts uppercase or lowercase.
325 #[inline]
326 fn hex_digit(input: &mut &str) -> ModalResult<u8> {
327 one_of(('0'..='9', 'a'..='f', 'A'..='F'))
328 .map(|d: char|
329 // unwraps are unreachable: their invariants are always
330 // upheld because the above character set can never
331 // consume anything but a single valid hex digit
332 d.to_digit(16).unwrap().try_into().unwrap())
333 .context(StrContext::Expected(StrContextValue::Description(
334 "ASCII hex digit",
335 )))
336 .parse_next(input)
337 }
338
339 let hex_pair = (hex_digit, hex_digit).map(|(first, second)|
340 // shift is infallible because hex_digit cannot return >0b00001111
341 (first << 4) + second);
342
343 // output size in bytes
344 let digest_bytes = <D as Digest>::output_size();
345
346 let digest = match D::ENCODING {
347 DigestEncoding::Hex => {
348 // Consume exactly the number of hex pairs that our Digest type expects
349 let digest = repeat(digest_bytes, hex_pair)
350 .context(StrContext::Label("hash digest"))
351 .context(StrContext::Expected(StrContextValue::Description(
352 "a hex hash digest with the appropriate length for the given algorithm.",
353 )))
354 .parse_next(input)?;
355
356 // Handle the case that there's another hex char after the expected number of digits
357 // This is one of the few cases that we consider a hard error.
358 cut_err(not(hex_digit))
359 .context(StrContext::Expected(StrContextValue::Description(
360 "end of checksum (checksum is too long).",
361 )))
362 .parse_next(input)?;
363
364 digest
365 }
366 DigestEncoding::Dec => {
367 // output size in bits
368 let digest_bits = digest_bytes * 8;
369
370 // The following logic parses a decimal integer for consumption by a digest.
371 // We chose to use a [`u128::MAX`] as this is the currently largest number type in
372 // the rust std library. In reality we only use this for CRC-32/CKSUM which is
373 // 4 bytes, but it's nice to keep this a bit more generic.
374
375 // Determine the maximum allowed value based on the number of allowed
376 // `digest_bytes`.

Callers

nothing calls this directly

Calls 1

valueMethod · 0.45

Tested by

no test coverage detected