1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
//! 定义 utf8 错误类型。
use crate::error::Error;
use crate::fmt;
/// 尝试将 [`u8`] 的序列解释为字符串时可能发生的错误。
///
/// 这样,例如 [`String`] 和 [`&str`] 的 `from_utf8` 系列函数和方法都利用了此错误。
///
/// [`String`]: ../../std/string/struct.String.html#method.from_utf8
/// [`&str`]: super::from_utf8
///
/// # Examples
///
/// 此错误类型的方法可用于创建类似于 `String::from_utf8_lossy` 的功能,而无需分配堆内存:
///
///
/// ```
/// fn from_utf8_lossy<F>(mut input: &[u8], mut push: F) where F: FnMut(&str) {
/// loop {
/// match std::str::from_utf8(input) {
/// Ok(valid) => {
/// push(valid);
/// break
/// }
/// Err(error) => {
/// let (valid, after_valid) = input.split_at(error.valid_up_to());
/// unsafe {
/// push(std::str::from_utf8_unchecked(valid))
/// }
/// push("\u{FFFD}");
///
/// if let Some(invalid_sequence_length) = error.error_len() {
/// input = &after_valid[invalid_sequence_length..]
/// } else {
/// break
/// }
/// }
/// }
/// }
/// }
/// ```
///
///
#[derive(Copy, Eq, PartialEq, Clone, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Utf8Error {
pub(super) valid_up_to: usize,
pub(super) error_len: Option<u8>,
}
impl Utf8Error {
/// 返回给定字符串中的索引,直到对其进行有效 UTF-8 验证为止。
///
/// 它是使 `from_utf8(&input[..index])` 返回 `Ok(_)` 的最大索引。
///
///
/// # Examples
///
/// 基本用法:
///
/// ```
/// use std::str;
///
/// // vector 中的一些无效字节
/// let sparkle_heart = vec![0, 159, 146, 150];
///
/// // std::str::from_utf8 返回一个 Utf8Error
/// let error = str::from_utf8(&sparkle_heart).unwrap_err();
///
/// // 第二个字节在这里无效
/// assert_eq!(1, error.valid_up_to());
/// ```
///
#[stable(feature = "utf8_error", since = "1.5.0")]
#[rustc_const_stable(feature = "const_str_from_utf8_shared", since = "1.63.0")]
#[must_use]
#[inline]
pub const fn valid_up_to(&self) -> usize {
self.valid_up_to
}
/// 提供有关失败的更多信息:
///
/// * `None`: 意外到达输入的结尾。
/// `self.valid_up_to()` 是从输入的末尾开始的 1 到 3 个字节。
/// 如果字节流 (例如文件或网络套接字) 正在以增量方式进行解码,则这可能是有效的 `char`,其 UTF-8 字节序列跨越了多个块。
///
///
/// * `Some(len)`: 遇到意外字节。
/// 提供的长度是从 `valid_up_to()` 给定的索引处开始的无效字节序列的长度。
/// 如果有损解码,则应在该序列之后 (插入 [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] 之后) 恢复解码。
///
/// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html
///
///
///
#[stable(feature = "utf8_error_error_len", since = "1.20.0")]
#[rustc_const_stable(feature = "const_str_from_utf8_shared", since = "1.63.0")]
#[must_use]
#[inline]
pub const fn error_len(&self) -> Option<usize> {
// FIXME: 这应该再次成为 `map`,一旦它是 `const`
match self.error_len {
Some(len) => Some(len as usize),
None => None,
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for Utf8Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(error_len) = self.error_len {
write!(
f,
"invalid utf-8 sequence of {} bytes from index {}",
error_len, self.valid_up_to
)
} else {
write!(f, "incomplete utf-8 byte sequence from index {}", self.valid_up_to)
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for Utf8Error {
#[allow(deprecated)]
fn description(&self) -> &str {
"invalid utf-8: corrupt contents"
}
}
/// 使用 [`from_str`] 解析 `bool` 失败时返回错误
///
/// [`from_str`]: super::FromStr::from_str
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ParseBoolError;
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for ParseBoolError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
"provided string was not `true` or `false`".fmt(f)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for ParseBoolError {
#[allow(deprecated)]
fn description(&self) -> &str {
"failed to parse bool"
}
}