|
| 1 | +//! Utilities for serializing and deserializing strings. |
| 2 | +
|
| 3 | +use core::fmt; |
| 4 | + |
1 | 5 | #[derive(Debug)]
|
| 6 | +/// A fragment of an escaped string |
2 | 7 | pub enum EscapedStringFragment<'a> {
|
| 8 | + /// A series of characters which weren't escaped in the input. |
3 | 9 | NotEscaped(&'a str),
|
| 10 | + /// A character which was escaped in the input. |
4 | 11 | Escaped(char),
|
5 | 12 | }
|
6 | 13 |
|
7 | 14 | #[derive(Debug)]
|
| 15 | +/// Errors occuring while unescaping strings. |
8 | 16 | pub enum StringUnescapeError {
|
| 17 | + /// Failed to unescape a character due to an invalid escape sequence. |
9 | 18 | InvalidEscapeSequence,
|
10 | 19 | }
|
11 | 20 |
|
| 21 | +impl fmt::Display for StringUnescapeError { |
| 22 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 23 | + match self { |
| 24 | + StringUnescapeError::InvalidEscapeSequence => write!( |
| 25 | + f, |
| 26 | + "Failed to unescape a character due to an invalid escape sequence." |
| 27 | + ), |
| 28 | + } |
| 29 | + } |
| 30 | +} |
| 31 | + |
| 32 | +#[cfg(feature = "std")] |
| 33 | +impl std::error::Error for StringUnescapeError {} |
| 34 | + |
12 | 35 | fn unescape_next_fragment(
|
13 | 36 | escaped_string: &str,
|
14 | 37 | ) -> Result<(EscapedStringFragment<'_>, &str), StringUnescapeError> {
|
@@ -55,22 +78,41 @@ fn unescape_next_fragment(
|
55 | 78 | })
|
56 | 79 | }
|
57 | 80 |
|
58 |
| -/// A borrowed escaped string |
| 81 | +/// A borrowed escaped string. `EscapedStr` can be used to borrow an escaped string from the input, |
| 82 | +/// even when deserialized using `from_str_escaped` or `from_slice_escaped`. |
| 83 | +/// |
| 84 | +/// ``` |
| 85 | +/// #[derive(serde::Deserialize)] |
| 86 | +/// struct Event<'a> { |
| 87 | +/// name: heapless::String<16>, |
| 88 | +/// #[serde(borrow)] |
| 89 | +/// description: serde_json_core::str::EscapedStr<'a>, |
| 90 | +/// } |
| 91 | +/// |
| 92 | +/// serde_json_core::de::from_str_escaped::<Event<'_>>( |
| 93 | +/// r#"{ "name": "Party\u0021", "description": "I'm throwing a party! Hopefully the \u2600 shines!" }"#, |
| 94 | +/// &mut [0; 8], |
| 95 | +/// ) |
| 96 | +/// .unwrap(); |
| 97 | +/// ``` |
59 | 98 | #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
60 | 99 | #[serde(rename = "__serde_json_core_escaped_string__")]
|
61 | 100 | pub struct EscapedStr<'a>(pub &'a str);
|
62 | 101 |
|
63 | 102 | impl<'a> EscapedStr<'a> {
|
64 | 103 | pub(crate) const NAME: &'static str = "__serde_json_core_escaped_string__";
|
65 | 104 |
|
| 105 | + /// Returns an iterator over the `EscapedStringFragment`s of an escaped string. |
66 | 106 | pub fn fragments(&self) -> EscapedStringFragmentIter<'a> {
|
67 | 107 | EscapedStringFragmentIter(self.0)
|
68 | 108 | }
|
69 | 109 | }
|
70 | 110 |
|
| 111 | +/// An iterator over the `EscapedStringFragment`s of an escaped string. |
71 | 112 | pub struct EscapedStringFragmentIter<'a>(&'a str);
|
72 | 113 |
|
73 | 114 | impl<'a> EscapedStringFragmentIter<'a> {
|
| 115 | + /// Views the underlying data as a subslice of the original data. |
74 | 116 | pub fn as_str(&self) -> EscapedStr<'a> {
|
75 | 117 | EscapedStr(self.0)
|
76 | 118 | }
|
|
0 commit comments