Skip to content

Commit 0349f2a

Browse files
committed
libstd: Change slice_shift_char, shift_char, pop_char, shift_byte and pop_byte to return an Option instead of failing
1 parent 62f1d68 commit 0349f2a

File tree

3 files changed

+63
-43
lines changed

3 files changed

+63
-43
lines changed

src/libglob/lib.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -369,11 +369,11 @@ impl Pattern {
369369
return EntirePatternDoesntMatch;
370370
}
371371

372-
let (c, next) = file.slice_shift_char();
373-
if require_literal(c) {
372+
let (some_c, next) = file.slice_shift_char();
373+
if require_literal(some_c.unwrap()) {
374374
return SubPatternDoesntMatch;
375375
}
376-
prev_char.set(Some(c));
376+
prev_char.set(some_c);
377377
file = next;
378378
}
379379
}
@@ -382,7 +382,8 @@ impl Pattern {
382382
return EntirePatternDoesntMatch;
383383
}
384384

385-
let (c, next) = file.slice_shift_char();
385+
let (some_c, next) = file.slice_shift_char();
386+
let c = some_c.unwrap();
386387
let matches = match *token {
387388
AnyChar => {
388389
!require_literal(c)
@@ -403,7 +404,7 @@ impl Pattern {
403404
if !matches {
404405
return SubPatternDoesntMatch;
405406
}
406-
prev_char.set(Some(c));
407+
prev_char.set(some_c);
407408
file = next;
408409
}
409410
}

src/libstd/str.rs

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,6 +1355,7 @@ pub mod raw {
13551355
use libc;
13561356
use ptr;
13571357
use ptr::RawPtr;
1358+
use option::{Option, Some, None};
13581359
use str::{is_utf8, OwnedStr, StrSlice};
13591360
use vec;
13601361
use vec::{MutableVector, ImmutableVector, OwnedVector};
@@ -1465,22 +1466,28 @@ pub mod raw {
14651466

14661467
/// Removes the last byte from a string and returns it.
14671468
/// The caller must preserve the valid UTF-8 property.
1468-
pub unsafe fn pop_byte(s: &mut ~str) -> u8 {
1469+
pub unsafe fn pop_byte(s: &mut ~str) -> Option<u8> {
14691470
let len = s.len();
1470-
assert!((len > 0u));
1471-
let b = s[len - 1u];
1472-
s.set_len(len - 1);
1473-
return b;
1471+
if len == 0u {
1472+
return None;
1473+
} else {
1474+
let b = s[len - 1u];
1475+
s.set_len(len - 1);
1476+
return Some(b);
1477+
}
14741478
}
14751479

14761480
/// Removes the first byte from a string and returns it.
14771481
/// The caller must preserve the valid UTF-8 property.
1478-
pub unsafe fn shift_byte(s: &mut ~str) -> u8 {
1482+
pub unsafe fn shift_byte(s: &mut ~str) -> Option<u8> {
14791483
let len = s.len();
1480-
assert!((len > 0u));
1481-
let b = s[0];
1482-
*s = s.slice(1, len).to_owned();
1483-
return b;
1484+
if len == 0u {
1485+
return None;
1486+
} else {
1487+
let b = s[0];
1488+
*s = s.slice(1, len).to_owned();
1489+
return Some(b);
1490+
}
14841491
}
14851492

14861493
/// Access the str in its vector representation.
@@ -2291,7 +2298,7 @@ pub trait StrSlice<'a> {
22912298
/// assert_eq!(c, 'ö');
22922299
/// assert_eq!(s2, "we 老虎 Léopard");
22932300
/// ```
2294-
fn slice_shift_char(&self) -> (char, &'a str);
2301+
fn slice_shift_char(&self) -> (Option<char>, &'a str);
22952302

22962303
/// Levenshtein Distance between two strings.
22972304
fn lev_distance(&self, t: &str) -> uint;
@@ -2744,10 +2751,14 @@ impl<'a> StrSlice<'a> for &'a str {
27442751
}
27452752

27462753
#[inline]
2747-
fn slice_shift_char(&self) -> (char, &'a str) {
2748-
let CharRange {ch, next} = self.char_range_at(0u);
2749-
let next_s = unsafe { raw::slice_bytes(*self, next, self.len()) };
2750-
return (ch, next_s);
2754+
fn slice_shift_char(&self) -> (Option<char>, &'a str) {
2755+
if self.is_empty() {
2756+
return (None, *self);
2757+
} else {
2758+
let CharRange {ch, next} = self.char_range_at(0u);
2759+
let next_s = unsafe { raw::slice_bytes(*self, next, self.len()) };
2760+
return (Some(ch), next_s);
2761+
}
27512762
}
27522763

27532764
fn lev_distance(&self, t: &str) -> uint {
@@ -2815,14 +2826,14 @@ pub trait OwnedStr {
28152826
/// # Failure
28162827
///
28172828
/// If the string does not contain any characters
2818-
fn pop_char(&mut self) -> char;
2829+
fn pop_char(&mut self) -> Option<char>;
28192830

28202831
/// Remove the first character from a string and return it
28212832
///
28222833
/// # Failure
28232834
///
28242835
/// If the string does not contain any characters
2825-
fn shift_char(&mut self) -> char;
2836+
fn shift_char(&mut self) -> Option<char>;
28262837

28272838
/// Prepend a char to a string
28282839
fn unshift_char(&mut self, ch: char);
@@ -2925,19 +2936,26 @@ impl OwnedStr for ~str {
29252936
}
29262937

29272938
#[inline]
2928-
fn pop_char(&mut self) -> char {
2939+
fn pop_char(&mut self) -> Option<char> {
29292940
let end = self.len();
2930-
assert!(end > 0u);
2931-
let CharRange {ch, next} = self.char_range_at_reverse(end);
2932-
unsafe { self.set_len(next); }
2933-
return ch;
2941+
if end == 0u {
2942+
return None;
2943+
} else {
2944+
let CharRange {ch, next} = self.char_range_at_reverse(end);
2945+
unsafe { self.set_len(next); }
2946+
return Some(ch);
2947+
}
29342948
}
29352949

29362950
#[inline]
2937-
fn shift_char(&mut self) -> char {
2938-
let CharRange {ch, next} = self.char_range_at(0u);
2939-
*self = self.slice(next, self.len()).to_owned();
2940-
return ch;
2951+
fn shift_char(&mut self) -> Option<char> {
2952+
if self.is_empty() {
2953+
return None;
2954+
} else {
2955+
let CharRange {ch, next} = self.char_range_at(0u);
2956+
*self = self.slice(next, self.len()).to_owned();
2957+
return Some(ch);
2958+
}
29412959
}
29422960

29432961
#[inline]
@@ -3148,22 +3166,23 @@ mod tests {
31483166
let mut data = ~"ประเทศไทย中华";
31493167
let cc = data.pop_char();
31503168
assert_eq!(~"ประเทศไทย中", data);
3151-
assert_eq!('华', cc);
3169+
assert_eq!(Some('华'), cc);
31523170
}
31533171
31543172
#[test]
31553173
fn test_pop_char_2() {
31563174
let mut data2 = ~"";
31573175
let cc2 = data2.pop_char();
31583176
assert_eq!(~"", data2);
3159-
assert_eq!('华', cc2);
3177+
assert_eq!(Some('华'), cc2);
31603178
}
31613179
31623180
#[test]
3163-
#[should_fail]
3164-
fn test_pop_char_fail() {
3181+
fn test_pop_char_empty() {
31653182
let mut data = ~"";
3166-
let _cc3 = data.pop_char();
3183+
let cc3 = data.pop_char();
3184+
assert_eq!(~"", data);
3185+
assert_eq!(None, cc3);
31673186
}
31683187
31693188
#[test]
@@ -3182,7 +3201,7 @@ mod tests {
31823201
let mut data = ~"ประเทศไทย中";
31833202
let cc = data.shift_char();
31843203
assert_eq!(~"ระเทศไทย中", data);
3185-
assert_eq!('ป', cc);
3204+
assert_eq!(Some('ป'), cc);
31863205
}
31873206
31883207
#[test]
@@ -3611,15 +3630,15 @@ mod tests {
36113630
let mut s = ~"ABC";
36123631
let b = unsafe{raw::shift_byte(&mut s)};
36133632
assert_eq!(s, ~"BC");
3614-
assert_eq!(b, 65u8);
3633+
assert_eq!(b, Some(65u8));
36153634
}
36163635
36173636
#[test]
36183637
fn test_pop_byte() {
36193638
let mut s = ~"ABC";
36203639
let b = unsafe{raw::pop_byte(&mut s)};
36213640
assert_eq!(s, ~"AB");
3622-
assert_eq!(b, 67u8);
3641+
assert_eq!(b, Some(67u8));
36233642
}
36243643
36253644
#[test]

src/test/run-pass/utf8_chars.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ pub fn main() {
4242
assert!((!str::is_utf8([0xf0_u8, 0xff_u8, 0xff_u8, 0x10_u8])));
4343

4444
let mut stack = ~"a×c€";
45-
assert_eq!(stack.pop_char(), '€');
46-
assert_eq!(stack.pop_char(), 'c');
45+
assert_eq!(stack.pop_char(), Some('€'));
46+
assert_eq!(stack.pop_char(), Some('c'));
4747
stack.push_char('u');
4848
assert!(stack == ~"a×u");
49-
assert_eq!(stack.shift_char(), 'a');
50-
assert_eq!(stack.shift_char(), '×');
49+
assert_eq!(stack.shift_char(), Some('a'));
50+
assert_eq!(stack.shift_char(), Some('×'));
5151
stack.unshift_char('ß');
5252
assert!(stack == ~"ßu");
5353
}

0 commit comments

Comments
 (0)