From 56218f5dfc3677be77bb52c0d298da2b12de99d3 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 19 Jul 2014 16:46:14 +0100 Subject: [PATCH] Implement FromBase64 for &[u8]. The algorithm was already based on bytes internally. Also use byte literals instead of casting u8 to char for matching. --- src/libserialize/base64.rs | 46 ++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/libserialize/base64.rs b/src/libserialize/base64.rs index 80a8a06edda6b..79c1d6554113f 100644 --- a/src/libserialize/base64.rs +++ b/src/libserialize/base64.rs @@ -161,7 +161,7 @@ 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, } @@ -169,7 +169,7 @@ pub enum FromBase64Error { 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"), } @@ -205,24 +205,31 @@ impl<'a> FromBase64 for &'a str { * } * ``` */ + #[inline] + fn from_base64(&self) -> Result, FromBase64Error> { + self.as_bytes().from_base64() + } +} + +impl<'a> FromBase64 for &'a [u8] { fn from_base64(&self) -> Result, 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; @@ -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)), } } @@ -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(),