Skip to content

Commit

Permalink
auto merge of #15810 : SimonSapin/rust/base64-from-bytes, r=alexcrichton
Browse files Browse the repository at this point in the history
The algorithm was already based on bytes internally.

Also use byte literals instead of casting u8 to char for matching.

[breaking-change] The `InvalidBase64Character` variant of the `FromBase64Error` enum was renamed to `InvalidBase64Byte`, and contains a `u8` instead of a `char`.

r? @alexcrichton
  • Loading branch information
bors committed Jul 20, 2014
2 parents 8748a69 + 56218f5 commit f15d6d2
Showing 1 changed file with 29 additions and 17 deletions.
46 changes: 29 additions & 17 deletions src/libserialize/base64.rs
Expand Up @@ -161,15 +161,15 @@ pub trait FromBase64 {
/// Errors that can occur when decoding a base64 encoded string
pub enum FromBase64Error {
/// The input contained a character not part of the base64 format
InvalidBase64Character(char, uint),
InvalidBase64Byte(u8, uint),
/// The input had an invalid length
InvalidBase64Length,
}

impl fmt::Show for FromBase64Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
InvalidBase64Character(ch, idx) =>
InvalidBase64Byte(ch, idx) =>
write!(f, "Invalid character '{}' at position {}", ch, idx),
InvalidBase64Length => write!(f, "Invalid length"),
}
Expand Down Expand Up @@ -205,24 +205,31 @@ impl<'a> FromBase64 for &'a str {
* }
* ```
*/
#[inline]
fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error> {
self.as_bytes().from_base64()
}
}

impl<'a> FromBase64 for &'a [u8] {
fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error> {
let mut r = Vec::new();
let mut buf: u32 = 0;
let mut modulus = 0i;

let mut it = self.bytes().enumerate();
for (idx, byte) in it {
let mut it = self.iter().enumerate();
for (idx, &byte) in it {
let val = byte as u32;

match byte as char {
'A'..'Z' => buf |= val - 0x41,
'a'..'z' => buf |= val - 0x47,
'0'..'9' => buf |= val + 0x04,
'+'|'-' => buf |= 0x3E,
'/'|'_' => buf |= 0x3F,
'\r'|'\n' => continue,
'=' => break,
_ => return Err(InvalidBase64Character(self.char_at(idx), idx)),
match byte {
b'A'..b'Z' => buf |= val - 0x41,
b'a'..b'z' => buf |= val - 0x47,
b'0'..b'9' => buf |= val + 0x04,
b'+' | b'-' => buf |= 0x3E,
b'/' | b'_' => buf |= 0x3F,
b'\r' | b'\n' => continue,
b'=' => break,
_ => return Err(InvalidBase64Byte(self[idx], idx)),
}

buf <<= 6;
Expand All @@ -235,10 +242,10 @@ impl<'a> FromBase64 for &'a str {
}
}

for (idx, byte) in it {
match byte as char {
'='|'\r'|'\n' => continue,
_ => return Err(InvalidBase64Character(self.char_at(idx), idx)),
for (idx, &byte) in it {
match byte {
b'=' | b'\r' | b'\n' => continue,
_ => return Err(InvalidBase64Byte(self[idx], idx)),
}
}

Expand Down Expand Up @@ -308,6 +315,11 @@ mod tests {
assert_eq!("Zm9vYmFy".from_base64().unwrap().as_slice(), "foobar".as_bytes());
}

#[test]
fn test_from_base64_bytes() {
assert_eq!(b"Zm9vYmFy".from_base64().unwrap().as_slice(), "foobar".as_bytes());
}

#[test]
fn test_from_base64_newlines() {
assert_eq!("Zm9v\r\nYmFy".from_base64().unwrap().as_slice(),
Expand Down

0 comments on commit f15d6d2

Please sign in to comment.