for &byte in s.as_bytes() { if byte == b'_' { continue;
}
if num_acc.checked_mul_ext(base) { return Err(Error::IntegerOutOfBounds);
}
let digit = bytes.decode_hex(byte)?;
if digit >= base { return Err(Error::ExpectedInteger);
}
if f(&mut num_acc, digit) { return Err(Error::IntegerOutOfBounds);
}
}
Ok(num_acc)
}
let res = if sign > 0 {
calc_num(self, s, base, T::checked_add_ext)
} else {
calc_num(self, s, base, T::checked_sub_ext)
};
let _ = self.advance(num_bytes);
res
}
pubfn any_num(&mutself) -> Result<AnyNum> { // We are not doing float comparisons here in the traditional sense. // Instead, this code checks if a f64 fits inside an f32. #[allow(clippy::float_cmp)] fn any_float(f: f64) -> Result<AnyNum> { if f == f64::from(f as f32) {
Ok(AnyNum::F32(f as f32))
} else {
Ok(AnyNum::F64(f))
}
}
let bytes_backup = self.bytes;
let first_byte = self.peek_or_eof()?; let is_signed = first_byte == b'-' || first_byte == b'+'; let is_float = self.next_bytes_is_float();
if is_float { let f = self.float::<f64>()?;
any_float(f)
} else { let max_u8 = LargeUInt::from(std::u8::MAX); let max_u16 = LargeUInt::from(std::u16::MAX); let max_u32 = LargeUInt::from(std::u32::MAX); #[cfg_attr(not(feature = "integer128"), allow(clippy::useless_conversion))] let max_u64 = LargeUInt::from(std::u64::MAX);
let min_i8 = LargeSInt::from(std::i8::MIN); let max_i8 = LargeSInt::from(std::i8::MAX); let min_i16 = LargeSInt::from(std::i16::MIN); let max_i16 = LargeSInt::from(std::i16::MAX); let min_i32 = LargeSInt::from(std::i32::MIN); let max_i32 = LargeSInt::from(std::i32::MAX); #[cfg_attr(not(feature = "integer128"), allow(clippy::useless_conversion))] let min_i64 = LargeSInt::from(std::i64::MIN); #[cfg_attr(not(feature = "integer128"), allow(clippy::useless_conversion))] let max_i64 = LargeSInt::from(std::i64::MAX);
if is_signed { matchself.signed_integer::<LargeSInt>() {
Ok(x) => { if x >= min_i8 && x <= max_i8 {
Ok(AnyNum::I8(x as i8))
} elseif x >= min_i16 && x <= max_i16 {
Ok(AnyNum::I16(x as i16))
} elseif x >= min_i32 && x <= max_i32 {
Ok(AnyNum::I32(x as i32))
} elseif x >= min_i64 && x <= max_i64 {
Ok(AnyNum::I64(x as i64))
} else { #[cfg(feature = "integer128")]
{
Ok(AnyNum::I128(x))
} #[cfg(not(feature = "integer128"))]
{
Ok(AnyNum::I64(x))
}
}
}
Err(_) => { self.bytes = bytes_backup;
any_float(self.float::<f64>()?)
}
}
} else { matchself.unsigned_integer::<LargeUInt>() {
Ok(x) => { if x <= max_u8 {
Ok(AnyNum::U8(x as u8))
} elseif x <= max_u16 {
Ok(AnyNum::U16(x as u16))
} elseif x <= max_u32 {
Ok(AnyNum::U32(x as u32))
} elseif x <= max_u64 {
Ok(AnyNum::U64(x as u64))
} else { #[cfg(feature = "integer128")]
{
Ok(AnyNum::U128(x))
} #[cfg(not(feature = "integer128"))]
{
Ok(AnyNum::U64(x))
}
}
}
Err(_) => { self.bytes = bytes_backup;
self.parse_escape()?
} else { // Check where the end of the char (') is and try to // interpret the rest as UTF-8
let max = self.bytes.len().min(5); let pos: usize = self.bytes[..max]
.iter()
.position(|&x| x == b'\'')
.ok_or(Error::ExpectedChar)?; let s = from_utf8(&self.bytes[0..pos]).map_err(Error::from)?; letmut chars = s.chars();
let first = chars.next().ok_or(Error::ExpectedChar)?; if chars.next().is_some() { return Err(Error::ExpectedChar);
}
let _ = self.advance(pos);
first
};
if !self.consume("'") { return Err(Error::ExpectedChar);
}
/// Only returns true if the char after `ident` cannot belong /// to an identifier. pubfn check_ident(&mutself, ident: &str) -> bool { self.test_for(ident) && !self.check_ident_other_char(ident.len())
}
/// Should only be used on a working copy pubfn check_tuple_struct(mutself) -> Result<bool> { ifself.identifier().is_err() { // if there's no field ident, this is a tuple struct return Ok(true);
}
self.skip_ws()?;
// if there is no colon after the ident, this can only be a unit struct self.eat_byte().map(|c| c != b':')
}
/// Only returns true if the char after `ident` cannot belong /// to an identifier. pubfn consume_ident(&mutself, ident: &str) -> bool { ifself.check_ident(ident) { let _ = self.advance(ident.len());
loop { let ident = self.identifier()?; let extension = Extensions::from_ident(ident).ok_or_else(|| {
Error::NoSuchExtension(String::from_utf8_lossy(ident).into_owned())
})?;
extensions |= extension;
let comma = self.comma()?;
// If we have no comma but another item, return an error if !comma && self.check_ident_other_char(0) { return Err(Error::ExpectedComma);
}
// If there's no comma, assume the list ended. // If there is, it might be a trailing one, thus we only // continue the loop if we get an ident char. if !comma || !self.check_ident_other_char(0) { break;
}
}
pubfn float<T>(&mutself) -> Result<T> where
T: FromStr,
{ for literal in &["inf", "+inf", "-inf", "NaN", "+NaN", "-NaN"] { ifself.consume_ident(literal) { return FromStr::from_str(literal).map_err(|_| unreachable!()); // must not fail
}
}
let num_bytes = self.next_bytes_contained_in(is_float_char);
// Since `rustc` allows `1_0.0_1`, lint against underscores in floats iflet Some(err_bytes) = self.bytes[0..num_bytes].iter().position(|b| *b == b'_') { let _ = self.advance(err_bytes);
return Err(Error::FloatUnderscore);
}
let s = unsafe { from_utf8_unchecked(&self.bytes[0..num_bytes]) }; let res = FromStr::from_str(s).map_err(|_| Error::ExpectedFloat);
let _ = self.advance(num_bytes);
res
}
pubfn identifier(&mutself) -> Result<&'a [u8]> { let next = self.peek_or_eof()?; if !is_ident_first_char(next) { if is_ident_raw_char(next) { let ident_bytes = &self.bytes[..self.next_bytes_contained_in(is_ident_raw_char)];
// If the next two bytes signify the start of a raw string literal, // return an error. let length = if next == b'r' { matchself.bytes.get(1).ok_or(Error::Eof)? {
b'"' => return Err(Error::ExpectedIdentifier),
b'#' => { let after_next = self.bytes.get(2).copied().unwrap_or_default(); // Note: it's important to check this before advancing forward, so that // the value-type deserializer can fall back to parsing it differently. if !is_ident_raw_char(after_next) { return Err(Error::ExpectedIdentifier);
} // skip "r#" let _ = self.advance(2); self.next_bytes_contained_in(is_ident_raw_char)
}
_ => { let std_ident_length = self.next_bytes_contained_in(is_ident_other_char); let raw_ident_length = self.next_bytes_contained_in(is_ident_raw_char);
loop { let _ = self.advance(i + 1); let character = self.parse_escape()?; match character.len_utf8() { 1 => s.push(character as u8),
len => { let start = s.len();
s.extend(repeat(0).take(len));
character.encode_utf8(&mut s[start..]);
}
}
let (new_i, end_or_escape) = self
.bytes
.iter()
.enumerate()
.find(|&(_, &b)| b == b'\\' || b == b'"')
.ok_or(Error::ExpectedStringEnd)?;
i = new_i;
s.extend_from_slice(&self.bytes[..i]);
if *end_or_escape == b'"' { let _ = self.advance(i + 1);
let s = String::from_utf8(s).map_err(Error::from)?; break Ok(ParsedStr::Allocated(s));
}
}
}
}
fn raw_string(&mutself) -> Result<ParsedStr<'a>> { let num_hashes = self.bytes.iter().take_while(|&&b| b == b'#').count(); let hashes = &self.bytes[..num_hashes]; let _ = self.advance(num_hashes);
if !self.consume("\"") { return Err(Error::ExpectedString);
}
let ending = [&[b'"'], hashes].concat(); let i = self
.bytes
.windows(num_hashes + 1)
.position(|window| window == ending.as_slice())
.ok_or(Error::ExpectedStringEnd)?;
let s = from_utf8(&self.bytes[..i]).map_err(Error::from)?;
// Advance by the number of bytes of the string // + `num_hashes` + 1 for the `"`. let _ = self.advance(i + num_hashes + 1);
fn decode_ascii_escape(&mutself) -> Result<u8> { letmut n = 0; for _ in0..2 {
n <<= 4; let byte = self.eat_byte()?; let decoded = self.decode_hex(byte)?;
n |= decoded;
}
Ok(n)
}
#[inline] fn decode_hex(&self, c: u8) -> Result<u8> { match c {
c @ b'0'..=b'9' => Ok(c - b'0'),
c @ b'a'..=b'f' => Ok(10 + c - b'a'),
c @ b'A'..=b'F' => Ok(10 + c - b'A'),
_ => Err(Error::InvalidEscape("Non-hex digit found")),
}
}
let byte = self.decode_hex(byte)?;
bytes <<= 4;
bytes |= u32::from(byte);
num_digits += 1;
}
if num_digits == 0 { return Err(Error::InvalidEscape( "Expected 1-6 digits, got 0 digits in Unicode escape",
));
}
self.expect_byte(
b'}',
Error::InvalidEscape("No } at the end of Unicode escape"),
)?;
char_from_u32(bytes).ok_or(Error::InvalidEscape("Not a valid char"))?
}
_ => { return Err(Error::InvalidEscape("Unknown escape character"));
}
};
Ok(c)
}
fn skip_comment(&mutself) -> Result<bool> { ifself.consume("/") { matchself.eat_byte()? {
b'/' => { let bytes = self.bytes.iter().take_while(|&&b| b != b'\n').count();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.