Sfoglia il codice sorgente

Add a wrapper types for fragments

Simon Sapin 8 anni fa
parent
commit
9d8acc3980
2 ha cambiato i file con 17 aggiunte e 9 eliminazioni
  1. 1 0
      make_base64_decode_table.py
  2. 16 9
      src/lib.rs

+ 1 - 0
make_base64_decode_table.py

@@ -6,6 +6,7 @@ import string
 
 # https://tools.ietf.org/html/rfc4648#section-4
 alphabet = string.ascii_uppercase + string.ascii_lowercase + string.digits + "+/"
+assert len(alphabet) == 64
 
 reverse_table = [-1] * 256
 for i, symbol in enumerate(alphabet):

+ 16 - 9
src/lib.rs

@@ -23,6 +23,12 @@ impl<E> From<InvalidBase64> for DecodeError<E> {
     fn from(e: InvalidBase64) -> Self { DecodeError::InvalidBase64(e) }
 }
 
+/// The URL’s fragment identifier (after `#`) encoded as in the original input.
+///
+/// It needs to be either percent-encoded to obtain the same string as in a parsed URL,
+/// or percent-decoded to interpret it as text.
+pub struct UrlFragmentIdentifier<'a>(pub &'a str);
+
 impl<'a> DataUrl<'a> {
     /// <https://fetch.spec.whatwg.org/#data-url-processor>
     /// but starting from a string rather than a Url, to avoid extra string copies.
@@ -45,11 +51,8 @@ impl<'a> DataUrl<'a> {
 
     /// Streaming-decode the data URL’s body to `write_body_bytes`,
     /// and return the URL’s fragment identifier is returned if it has one.
-    ///
-    /// The fragment is represented as in the origin input.
-    /// It needs to be either percent-encoded to obtain the same string as in a parsed URL,
-    /// or percent-decoded to interpret it as text.
-    pub fn decode<F, E>(&self, write_body_bytes: F) -> Result<Option<&'a str>, DecodeError<E>>
+    pub fn decode<F, E>(&self, write_body_bytes: F)
+                        -> Result<Option<UrlFragmentIdentifier<'a>>, DecodeError<E>>
         where F: FnMut(&[u8]) -> Result<(), E>
     {
         if self.base64 {
@@ -60,7 +63,10 @@ impl<'a> DataUrl<'a> {
         }
     }
 
-    pub fn decode_to_vec(&self) -> Result<(Vec<u8>, Option<&str>), InvalidBase64> {
+    /// Return the decoded body and the URL’s fragment identifier
+    pub fn decode_to_vec(&self)
+        -> Result<(Vec<u8>, Option<UrlFragmentIdentifier<'a>>), InvalidBase64>
+    {
         enum Impossible {}
         let mut body = Vec::new();
         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
 /// would be percent-decoded here.
 /// We skip that round-trip and pass it through unchanged.
 fn decode_without_base64<F, E>(encoded_body_plus_fragment: &str, mut write_bytes: F)
-                               -> Result<Option<&str>, E>
+                               -> Result<Option<UrlFragmentIdentifier>, E>
     where F: FnMut(&[u8]) -> Result<(), E>
 {
     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
 
                 b'#' => {
                     let fragment_start = i + 1;
-                    return Ok(Some(&encoded_body_plus_fragment[fragment_start..]))
+                    let fragment = &encoded_body_plus_fragment[fragment_start..];
+                    return Ok(Some(UrlFragmentIdentifier(fragment)))
                 }
 
                 // Ignore over '\t' | '\n' | '\r'
@@ -232,7 +239,7 @@ fn decode_without_base64<F, E>(encoded_body_plus_fragment: &str, mut write_bytes
 /// <https://infra.spec.whatwg.org/#isomorphic-decode> composed with
 /// <https://infra.spec.whatwg.org/#forgiving-base64-decode>.
 fn decode_with_base64<F, E>(encoded_body_plus_fragment: &str, mut write_bytes: F)
-                            -> Result<Option<&str>, DecodeError<E>>
+                            -> Result<Option<UrlFragmentIdentifier>, DecodeError<E>>
     where F: FnMut(&[u8]) -> Result<(), E>
 {
     let mut bit_buffer: u32 = 0;