Skip to content

Commit 0eb552a

Browse files
committed
wtf8, char: Replace uses of mem::transmute with more specific functions
1 parent d4d4206 commit 0eb552a

File tree

3 files changed

+35
-25
lines changed

3 files changed

+35
-25
lines changed

src/libcore/char.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,17 @@ pub fn from_u32(i: u32) -> Option<char> {
8484
if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
8585
None
8686
} else {
87-
Some(unsafe { transmute(i) })
87+
Some(unsafe { from_u32_unchecked(i) })
8888
}
8989
}
9090

91+
/// Converts a `u32` to an `char`, not checking whether it is a valid unicode
92+
/// codepoint.
93+
#[inline]
94+
pub unsafe fn from_u32_unchecked(i: u32) -> char {
95+
transmute(i)
96+
}
97+
9198
/// Converts a number to the character representing it.
9299
///
93100
/// # Return value
@@ -115,12 +122,11 @@ pub fn from_digit(num: u32, radix: u32) -> Option<char> {
115122
panic!("from_digit: radix is too high (maximum 36)");
116123
}
117124
if num < radix {
118-
unsafe {
119-
if num < 10 {
120-
Some(transmute('0' as u32 + num))
121-
} else {
122-
Some(transmute('a' as u32 + num - 10))
123-
}
125+
let num = num as u8;
126+
if num < 10 {
127+
Some((b'0' + num) as char)
128+
} else {
129+
Some((b'a' + num - 10) as char)
124130
}
125131
} else {
126132
None
@@ -318,16 +324,13 @@ impl Iterator for EscapeUnicode {
318324
Some('{')
319325
}
320326
EscapeUnicodeState::Value(offset) => {
321-
let v = match ((self.c as i32) >> (offset * 4)) & 0xf {
322-
i @ 0 ... 9 => '0' as i32 + i,
323-
i => 'a' as i32 + (i - 10)
324-
};
327+
let c = from_digit(((self.c as u32) >> (offset * 4)) & 0xf, 16).unwrap();
325328
if offset == 0 {
326329
self.state = EscapeUnicodeState::RightBrace;
327330
} else {
328331
self.state = EscapeUnicodeState::Value(offset - 1);
329332
}
330-
Some(unsafe { transmute(v) })
333+
Some(c)
331334
}
332335
EscapeUnicodeState::RightBrace => {
333336
self.state = EscapeUnicodeState::Done;

src/librustc_unicode/char.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use core::iter::Iterator;
3535
use tables::{derived_property, property, general_category, conversions, charwidth};
3636

3737
// stable reexports
38-
pub use core::char::{MAX, from_u32, from_digit, EscapeUnicode, EscapeDefault};
38+
pub use core::char::{MAX, from_u32, from_u32_unchecked, from_digit, EscapeUnicode, EscapeDefault};
3939

4040
// unstable reexports
4141
#[allow(deprecated)]

src/libstd/sys/common/wtf8.rs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,18 @@ use core::str::next_code_point;
3232

3333
use ascii::*;
3434
use borrow::Cow;
35+
use char;
3536
use cmp;
3637
use fmt;
3738
use hash::{Hash, Hasher};
3839
use iter::FromIterator;
3940
use mem;
4041
use ops;
42+
use rustc_unicode::str::{Utf16Item, utf16_items};
4143
use slice;
4244
use str;
4345
use string::String;
4446
use sys_common::AsInner;
45-
use rustc_unicode::str::{Utf16Item, utf16_items};
4647
use vec::Vec;
4748

4849
const UTF8_REPLACEMENT_CHARACTER: &'static [u8] = b"\xEF\xBF\xBD";
@@ -107,7 +108,7 @@ impl CodePoint {
107108
pub fn to_char(&self) -> Option<char> {
108109
match self.value {
109110
0xD800 ... 0xDFFF => None,
110-
_ => Some(unsafe { mem::transmute(self.value) })
111+
_ => Some(unsafe { char::from_u32_unchecked(self.value) })
111112
}
112113
}
113114

@@ -213,18 +214,16 @@ impl Wtf8Buf {
213214
// Attempt to not use an intermediate buffer by just pushing bytes
214215
// directly onto this string.
215216
let slice = slice::from_raw_parts_mut(
216-
self.bytes.as_mut_ptr().offset(cur_len as isize),
217-
4
217+
self.bytes.as_mut_ptr().offset(cur_len as isize), 4
218218
);
219-
let used = encode_utf8_raw(code_point.value, mem::transmute(slice))
220-
.unwrap_or(0);
219+
let used = encode_utf8_raw(code_point.value, slice).unwrap();
221220
self.bytes.set_len(cur_len + used);
222221
}
223222
}
224223

225224
#[inline]
226225
pub fn as_slice(&self) -> &Wtf8 {
227-
unsafe { mem::transmute(&*self.bytes) }
226+
unsafe { Wtf8::from_bytes_unchecked(&self.bytes) }
228227
}
229228

230229
/// Reserves capacity for at least `additional` more bytes to be inserted
@@ -457,7 +456,16 @@ impl Wtf8 {
457456
/// Since WTF-8 is a superset of UTF-8, this always succeeds.
458457
#[inline]
459458
pub fn from_str(value: &str) -> &Wtf8 {
460-
unsafe { mem::transmute(value.as_bytes()) }
459+
unsafe { Wtf8::from_bytes_unchecked(value.as_bytes()) }
460+
}
461+
462+
/// Creates a WTF-8 slice from a WTF-8 byte slice.
463+
///
464+
/// Since the byte slice is not checked for valid WTF-8, this functions is
465+
/// marked unsafe.
466+
#[inline]
467+
unsafe fn from_bytes_unchecked(value: &[u8]) -> &Wtf8 {
468+
mem::transmute(value)
461469
}
462470

463471
/// Returns the length, in WTF-8 bytes.
@@ -682,7 +690,7 @@ fn decode_surrogate(second_byte: u8, third_byte: u8) -> u16 {
682690
#[inline]
683691
fn decode_surrogate_pair(lead: u16, trail: u16) -> char {
684692
let code_point = 0x10000 + ((((lead - 0xD800) as u32) << 10) | (trail - 0xDC00) as u32);
685-
unsafe { mem::transmute(code_point) }
693+
unsafe { char::from_u32_unchecked(code_point) }
686694
}
687695

688696
/// Copied from core::str::StrPrelude::is_char_boundary
@@ -699,7 +707,7 @@ pub fn is_code_point_boundary(slice: &Wtf8, index: usize) -> bool {
699707
#[inline]
700708
pub unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 {
701709
// memory layout of an &[u8] and &Wtf8 are the same
702-
mem::transmute(slice::from_raw_parts(
710+
Wtf8::from_bytes_unchecked(slice::from_raw_parts(
703711
s.bytes.as_ptr().offset(begin as isize),
704712
end - begin
705713
))
@@ -821,7 +829,6 @@ mod tests {
821829
use prelude::v1::*;
822830
use borrow::Cow;
823831
use super::*;
824-
use mem::transmute;
825832

826833
#[test]
827834
fn code_point_from_u32() {
@@ -962,7 +969,7 @@ mod tests {
962969
string.push_wtf8(Wtf8::from_str(" 💩"));
963970
assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
964971

965-
fn w(value: &[u8]) -> &Wtf8 { unsafe { transmute(value) } }
972+
fn w(v: &[u8]) -> &Wtf8 { unsafe { Wtf8::from_bytes_unchecked(v) } }
966973

967974
let mut string = Wtf8Buf::new();
968975
string.push_wtf8(w(b"\xED\xA0\xBD")); // lead

0 commit comments

Comments
 (0)