Skip to content

Commit 1482cf5

Browse files
committed
Base64 API changes
There's now an enum to pick the character set instead of a url_safe bool. from_base64 now returns a Result<~[u8], ~str> and returns an Err instead of killing the task when it is called on invalid input. Fixed documentation examples.
1 parent 5a8a30f commit 1482cf5

File tree

1 file changed

+57
-34
lines changed

1 file changed

+57
-34
lines changed

src/libextra/base64.rs

Lines changed: 57 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,35 @@
1010

1111
//! Base64 binary-to-text encoding
1212
13+
/// Available encoding character sets
14+
pub enum CharacterSet {
15+
/// The standard character set (uses '+' and '/')
16+
Standard,
17+
/// The URL safe character set (uses '-' and '_')
18+
UrlSafe
19+
}
20+
1321
/// Contains configuration parameters for to_base64
1422
pub struct Config {
15-
/// True to use the url-safe encoding format ('-' and '_'), false to use
16-
/// the standard encoding format ('+' and '/')
17-
pub url_safe: bool,
23+
/// Character set to use
24+
char_set: CharacterSet,
1825
/// True to pad output with '=' characters
19-
pub pad: bool,
26+
pad: bool,
2027
/// Some(len) to wrap lines at len, None to disable line wrapping
21-
pub line_length: Option<uint>
28+
line_length: Option<uint>
2229
}
2330

2431
/// Configuration for RFC 4648 standard base64 encoding
2532
pub static standard: Config =
26-
Config {url_safe: false, pad: true, line_length: None};
33+
Config {char_set: Standard, pad: true, line_length: None};
2734

2835
/// Configuration for RFC 4648 base64url encoding
2936
pub static url_safe: Config =
30-
Config {url_safe: true, pad: false, line_length: None};
37+
Config {char_set: UrlSafe, pad: false, line_length: None};
3138

3239
/// Configuration for RFC 2045 MIME base64 encoding
3340
pub static mime: Config =
34-
Config {url_safe: false, pad: true, line_length: Some(76)};
41+
Config {char_set: Standard, pad: true, line_length: Some(76)};
3542

3643
static STANDARD_CHARS: [char, ..64] = [
3744
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
@@ -63,7 +70,8 @@ impl<'self> ToBase64 for &'self [u8] {
6370
* # Example
6471
*
6572
* ~~~ {.rust}
66-
* use std::base64::{ToBase64, standard};
73+
* extern mod extra;
74+
* use extra::base64::{ToBase64, standard};
6775
*
6876
* fn main () {
6977
* let str = [52,32].to_base64(standard);
@@ -72,9 +80,9 @@ impl<'self> ToBase64 for &'self [u8] {
7280
* ~~~
7381
*/
7482
fn to_base64(&self, config: Config) -> ~str {
75-
let chars = match config.url_safe {
76-
true => URLSAFE_CHARS,
77-
false => STANDARD_CHARS
83+
let chars = match config.char_set {
84+
Standard => STANDARD_CHARS,
85+
UrlSafe => URLSAFE_CHARS
7886
};
7987

8088
let mut s = ~"";
@@ -151,7 +159,8 @@ impl<'self> ToBase64 for &'self str {
151159
* # Example
152160
*
153161
* ~~~ {.rust}
154-
* use std::base64::{ToBase64, standard};
162+
* extern mod extra;
163+
* use extra::base64::{ToBase64, standard};
155164
*
156165
* fn main () {
157166
* let str = "Hello, World".to_base64(standard);
@@ -169,7 +178,7 @@ impl<'self> ToBase64 for &'self str {
169178
pub trait FromBase64 {
170179
/// Converts the value of `self`, interpreted as base64 encoded data, into
171180
/// an owned vector of bytes, returning the vector.
172-
fn from_base64(&self) -> ~[u8];
181+
fn from_base64(&self) -> Result<~[u8], ~str>;
173182
}
174183

175184
impl<'self> FromBase64 for &'self [u8] {
@@ -180,7 +189,8 @@ impl<'self> FromBase64 for &'self [u8] {
180189
* # Example
181190
*
182191
* ~~~ {.rust}
183-
* use std::base64::{ToBase64, FromBase64, standard};
192+
* extern mod extra;
193+
* use extra::base64::{ToBase64, FromBase64, standard};
184194
*
185195
* fn main () {
186196
* let str = [52,32].to_base64(standard);
@@ -190,7 +200,7 @@ impl<'self> FromBase64 for &'self [u8] {
190200
* }
191201
* ~~~
192202
*/
193-
fn from_base64(&self) -> ~[u8] {
203+
fn from_base64(&self) -> Result<~[u8], ~str> {
194204
let mut r = ~[];
195205
let mut buf: u32 = 0;
196206
let mut modulus = 0;
@@ -208,7 +218,7 @@ impl<'self> FromBase64 for &'self [u8] {
208218
'/'|'_' => buf |= 0x3F,
209219
'\r'|'\n' => loop,
210220
'=' => break,
211-
_ => fail!("Invalid Base64 character")
221+
_ => return Err(~"Invalid Base64 character")
212222
}
213223

214224
buf <<= 6;
@@ -222,7 +232,7 @@ impl<'self> FromBase64 for &'self [u8] {
222232
}
223233

224234
if !it.all(|&byte| {byte as char == '='}) {
225-
fail!("Invalid Base64 character");
235+
return Err(~"Invalid Base64 character");
226236
}
227237

228238
match modulus {
@@ -234,10 +244,10 @@ impl<'self> FromBase64 for &'self [u8] {
234244
r.push((buf >> 8 ) as u8);
235245
}
236246
0 => (),
237-
_ => fail!("Invalid Base64 length")
247+
_ => return Err(~"Invalid Base64 length")
238248
}
239249

240-
r
250+
Ok(r)
241251
}
242252
}
243253

@@ -255,7 +265,8 @@ impl<'self> FromBase64 for &'self str {
255265
* This converts a string literal to base64 and back.
256266
*
257267
* ~~~ {.rust}
258-
* use std::base64::{ToBase64, FromBase64, standard};
268+
* extern mod extra;
269+
* use extra::base64::{ToBase64, FromBase64, standard};
259270
* use std::str;
260271
*
261272
* fn main () {
@@ -268,7 +279,7 @@ impl<'self> FromBase64 for &'self str {
268279
* }
269280
* ~~~
270281
*/
271-
fn from_base64(&self) -> ~[u8] {
282+
fn from_base64(&self) -> Result<~[u8], ~str> {
272283
self.as_bytes().from_base64()
273284
}
274285
}
@@ -306,36 +317,48 @@ fn test_to_base64_url_safe() {
306317
307318
#[test]
308319
fn test_from_base64_basic() {
309-
assert_eq!("".from_base64(), "".as_bytes().to_owned());
310-
assert_eq!("Zg==".from_base64(), "f".as_bytes().to_owned());
311-
assert_eq!("Zm8=".from_base64(), "fo".as_bytes().to_owned());
312-
assert_eq!("Zm9v".from_base64(), "foo".as_bytes().to_owned());
313-
assert_eq!("Zm9vYg==".from_base64(), "foob".as_bytes().to_owned());
314-
assert_eq!("Zm9vYmE=".from_base64(), "fooba".as_bytes().to_owned());
315-
assert_eq!("Zm9vYmFy".from_base64(), "foobar".as_bytes().to_owned());
320+
assert_eq!("".from_base64().get(), "".as_bytes().to_owned());
321+
assert_eq!("Zg==".from_base64().get(), "f".as_bytes().to_owned());
322+
assert_eq!("Zm8=".from_base64().get(), "fo".as_bytes().to_owned());
323+
assert_eq!("Zm9v".from_base64().get(), "foo".as_bytes().to_owned());
324+
assert_eq!("Zm9vYg==".from_base64().get(), "foob".as_bytes().to_owned());
325+
assert_eq!("Zm9vYmE=".from_base64().get(), "fooba".as_bytes().to_owned());
326+
assert_eq!("Zm9vYmFy".from_base64().get(), "foobar".as_bytes().to_owned());
316327
}
317328
318329
#[test]
319330
fn test_from_base64_newlines() {
320-
assert_eq!("Zm9v\r\nYmFy".from_base64(), "foobar".as_bytes().to_owned());
331+
assert_eq!("Zm9v\r\nYmFy".from_base64().get(),
332+
"foobar".as_bytes().to_owned());
321333
}
322334
323335
#[test]
324336
fn test_from_base64_urlsafe() {
325-
assert_eq!("-_8".from_base64(), "+/8=".from_base64());
337+
assert_eq!("-_8".from_base64().get(), "+/8=".from_base64().get());
338+
}
339+
340+
#[test]
341+
fn test_from_base64_invalid_char() {
342+
assert!("Zm$=".from_base64().is_err())
343+
assert!("Zg==$".from_base64().is_err());
344+
}
345+
346+
#[test]
347+
fn test_from_base64_invalid_padding() {
348+
assert!("Z===".from_base64().is_err());
326349
}
327350

328351
#[test]
329352
fn test_base64_random() {
330-
use std::rand::random;
353+
use std::rand::{task_rng, random, RngUtil};
331354
use std::vec;
332355

333356
for 1000.times {
334357
let v: ~[u8] = do vec::build |push| {
335-
for 100.times {
358+
for task_rng().gen_uint_range(1, 100).times {
336359
push(random());
337360
}
338361
};
339-
assert_eq!(v.to_base64(standard).from_base64(), v);
362+
assert_eq!(v.to_base64(standard).from_base64().get(), v);
340363
}
341364
}

0 commit comments

Comments
 (0)