Rust - unsafe
We can use the unsafe functions like this
use std::collections::HashMap;
fn main() {
let map = HashMap::new();
let mut map = explain("empty", map);
map.insert(String::from("a"), 1);
explain("added 1", map);
}
fn explain<K, V>(name: &str, map: HashMap<K, V>) -> HashMap<K, V> {
let arr: [usize; 6] = unsafe { std::mem::transmute(map) };
println!("{}: bucket mask 0x{:x}, ctrl 0x{:x}, growth_left: {}, items: {}",
name, arr[2], arr[3], arr[4], arr[5]);
unsafe{ std::mem::transmute(arr) }
}
Sometimes rust will provide both safe and unsafe version, eg from_utf8, and from_utf8_unchecked, the unchecked version will be much faster, but it does not provide safety check
Unsafe can also be used for naked pointers
fn main() {
let mut age = 18;
let r1 = &age as *const i32;
let r2 = &mut age as *mut i32;
unsafe {
println!("r1: {}, r2: {}", *r1, *r2);
}
}
fn immutable_mutable_cant_coexist() {
let mut age = 18;
let r1 = &age;
// this is wrong
// let r2 = &mut age;
}
unsafe can be used for FFI
use std::mem::transmute;
fn main() {
let data = unsafe {
let p = libc::malloc(4);
let arr: &mut [u8; 4] = transmute(p);
arr
};
data.copy_from_slice(&[1, 2, 3, 4]);
println!("data: {:?}", data);
unsafe { libc::free(transmute(data)) };
}
unsafe should not be used for static mut, and in macro
when using unsafe function, should comment in code why it is safe here
fn main() {
let mut s = "harry-potter".to_string();
let r = s.as_mut();
if let Some((s1, s2)) = split(r, '-') {
println!("s1: {}, s2: {}", s1, s2);
}
}
fn split(s: &str, sep: char) -> Option<(&str, &str)> {
let pos = s.find(sep);
pos.map(|pos| {
let len = s.len();
let sep_len = sep.len_utf8();
// safety: pos is from find, so it is at the boundary
// the code below is thus safe to use
unsafe { (s.get_unchecked(0..pos), s.get_unchecked(pos + sep_len..len)) }
})
}