Skip to content

Commit f15d6d2

Browse files
committed
auto merge of #15810 : SimonSapin/rust/base64-from-bytes, r=alexcrichton
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
2 parents 8748a69 + 56218f5 commit f15d6d2

File tree

1 file changed

+29
-17
lines changed

1 file changed

+29
-17
lines changed

src/libserialize/base64.rs

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -161,15 +161,15 @@ pub trait FromBase64 {
161161
/// Errors that can occur when decoding a base64 encoded string
162162
pub enum FromBase64Error {
163163
/// The input contained a character not part of the base64 format
164-
InvalidBase64Character(char, uint),
164+
InvalidBase64Byte(u8, uint),
165165
/// The input had an invalid length
166166
InvalidBase64Length,
167167
}
168168

169169
impl fmt::Show for FromBase64Error {
170170
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171171
match *self {
172-
InvalidBase64Character(ch, idx) =>
172+
InvalidBase64Byte(ch, idx) =>
173173
write!(f, "Invalid character '{}' at position {}", ch, idx),
174174
InvalidBase64Length => write!(f, "Invalid length"),
175175
}
@@ -205,24 +205,31 @@ impl<'a> FromBase64 for &'a str {
205205
* }
206206
* ```
207207
*/
208+
#[inline]
209+
fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error> {
210+
self.as_bytes().from_base64()
211+
}
212+
}
213+
214+
impl<'a> FromBase64 for &'a [u8] {
208215
fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error> {
209216
let mut r = Vec::new();
210217
let mut buf: u32 = 0;
211218
let mut modulus = 0i;
212219

213-
let mut it = self.bytes().enumerate();
214-
for (idx, byte) in it {
220+
let mut it = self.iter().enumerate();
221+
for (idx, &byte) in it {
215222
let val = byte as u32;
216223

217-
match byte as char {
218-
'A'..'Z' => buf |= val - 0x41,
219-
'a'..'z' => buf |= val - 0x47,
220-
'0'..'9' => buf |= val + 0x04,
221-
'+'|'-' => buf |= 0x3E,
222-
'/'|'_' => buf |= 0x3F,
223-
'\r'|'\n' => continue,
224-
'=' => break,
225-
_ => return Err(InvalidBase64Character(self.char_at(idx), idx)),
224+
match byte {
225+
b'A'..b'Z' => buf |= val - 0x41,
226+
b'a'..b'z' => buf |= val - 0x47,
227+
b'0'..b'9' => buf |= val + 0x04,
228+
b'+' | b'-' => buf |= 0x3E,
229+
b'/' | b'_' => buf |= 0x3F,
230+
b'\r' | b'\n' => continue,
231+
b'=' => break,
232+
_ => return Err(InvalidBase64Byte(self[idx], idx)),
226233
}
227234

228235
buf <<= 6;
@@ -235,10 +242,10 @@ impl<'a> FromBase64 for &'a str {
235242
}
236243
}
237244

238-
for (idx, byte) in it {
239-
match byte as char {
240-
'='|'\r'|'\n' => continue,
241-
_ => return Err(InvalidBase64Character(self.char_at(idx), idx)),
245+
for (idx, &byte) in it {
246+
match byte {
247+
b'=' | b'\r' | b'\n' => continue,
248+
_ => return Err(InvalidBase64Byte(self[idx], idx)),
242249
}
243250
}
244251

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

318+
#[test]
319+
fn test_from_base64_bytes() {
320+
assert_eq!(b"Zm9vYmFy".from_base64().unwrap().as_slice(), "foobar".as_bytes());
321+
}
322+
311323
#[test]
312324
fn test_from_base64_newlines() {
313325
assert_eq!("Zm9v\r\nYmFy".from_base64().unwrap().as_slice(),

0 commit comments

Comments
 (0)