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"
    }
}