Skip to content

Commit 9d8acc3

Browse files
committed
Add a wrapper types for fragments
1 parent 1cff0dd commit 9d8acc3

File tree

2 files changed

+17
-9
lines changed

2 files changed

+17
-9
lines changed

make_base64_decode_table.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
# https://tools.ietf.org/html/rfc4648#section-4
88
alphabet = string.ascii_uppercase + string.ascii_lowercase + string.digits + "+/"
9+
assert len(alphabet) == 64
910

1011
reverse_table = [-1] * 256
1112
for i, symbol in enumerate(alphabet):

src/lib.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ impl<E> From<InvalidBase64> for DecodeError<E> {
2323
fn from(e: InvalidBase64) -> Self { DecodeError::InvalidBase64(e) }
2424
}
2525

26+
/// The URL’s fragment identifier (after `#`) encoded as in the original input.
27+
///
28+
/// It needs to be either percent-encoded to obtain the same string as in a parsed URL,
29+
/// or percent-decoded to interpret it as text.
30+
pub struct UrlFragmentIdentifier<'a>(pub &'a str);
31+
2632
impl<'a> DataUrl<'a> {
2733
/// <https://fetch.spec.whatwg.org/#data-url-processor>
2834
/// but starting from a string rather than a Url, to avoid extra string copies.
@@ -45,11 +51,8 @@ impl<'a> DataUrl<'a> {
4551

4652
/// Streaming-decode the data URL’s body to `write_body_bytes`,
4753
/// and return the URL’s fragment identifier is returned if it has one.
48-
///
49-
/// The fragment is represented as in the origin input.
50-
/// It needs to be either percent-encoded to obtain the same string as in a parsed URL,
51-
/// or percent-decoded to interpret it as text.
52-
pub fn decode<F, E>(&self, write_body_bytes: F) -> Result<Option<&'a str>, DecodeError<E>>
54+
pub fn decode<F, E>(&self, write_body_bytes: F)
55+
-> Result<Option<UrlFragmentIdentifier<'a>>, DecodeError<E>>
5356
where F: FnMut(&[u8]) -> Result<(), E>
5457
{
5558
if self.base64 {
@@ -60,7 +63,10 @@ impl<'a> DataUrl<'a> {
6063
}
6164
}
6265

63-
pub fn decode_to_vec(&self) -> Result<(Vec<u8>, Option<&str>), InvalidBase64> {
66+
/// Return the decoded body and the URL’s fragment identifier
67+
pub fn decode_to_vec(&self)
68+
-> Result<(Vec<u8>, Option<UrlFragmentIdentifier<'a>>), InvalidBase64>
69+
{
6470
enum Impossible {}
6571
let mut body = Vec::new();
6672
let result = self.decode::<_, Impossible>(|bytes| Ok(body.extend_from_slice(bytes)));
@@ -183,7 +189,7 @@ fn remove_suffix<'a, Eq>(haystack: &'a str, needle: &str, eq: Eq) -> Option<&'a
183189
/// would be percent-decoded here.
184190
/// We skip that round-trip and pass it through unchanged.
185191
fn decode_without_base64<F, E>(encoded_body_plus_fragment: &str, mut write_bytes: F)
186-
-> Result<Option<&str>, E>
192+
-> Result<Option<UrlFragmentIdentifier>, E>
187193
where F: FnMut(&[u8]) -> Result<(), E>
188194
{
189195
let bytes = encoded_body_plus_fragment.as_bytes();
@@ -216,7 +222,8 @@ fn decode_without_base64<F, E>(encoded_body_plus_fragment: &str, mut write_bytes
216222

217223
b'#' => {
218224
let fragment_start = i + 1;
219-
return Ok(Some(&encoded_body_plus_fragment[fragment_start..]))
225+
let fragment = &encoded_body_plus_fragment[fragment_start..];
226+
return Ok(Some(UrlFragmentIdentifier(fragment)))
220227
}
221228

222229
// Ignore over '\t' | '\n' | '\r'
@@ -232,7 +239,7 @@ fn decode_without_base64<F, E>(encoded_body_plus_fragment: &str, mut write_bytes
232239
/// <https://infra.spec.whatwg.org/#isomorphic-decode> composed with
233240
/// <https://infra.spec.whatwg.org/#forgiving-base64-decode>.
234241
fn decode_with_base64<F, E>(encoded_body_plus_fragment: &str, mut write_bytes: F)
235-
-> Result<Option<&str>, DecodeError<E>>
242+
-> Result<Option<UrlFragmentIdentifier>, DecodeError<E>>
236243
where F: FnMut(&[u8]) -> Result<(), E>
237244
{
238245
let mut bit_buffer: u32 = 0;

0 commit comments

Comments
 (0)