Rust Programming Cookbook
上QQ阅读APP看书,第一时间看更新

How to do it...

In just a few steps, we are unsafe:

  1. Create a new library project using cargo new unsafe-ways --lib. Open the project using Visual Studio Code or another editor. 
  2. Open src/libr.rs to add the following function before the test module:
#![allow(dead_code)]
use std::slice;

fn split_into_equal_parts<T>(slice: &mut [T], parts: usize) -> Vec<&mut [T]> {
let len = slice.len();
assert!(parts <= len);
let step = len / parts;
unsafe {
let ptr = slice.as_mut_ptr();

(0..step + 1)
.map(|i| {
let offset = (i * step) as isize;
let a = ptr.offset(offset);
slice::from_raw_parts_mut(a, step)
})
.collect()
}
}
  1. With that ready, we now have to add some tests inside mod tests {}:

#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_split_into_equal_parts() {
let mut v = vec![1, 2, 3, 4, 5, 6];
assert_eq!(
split_into_equal_parts(&mut v, 3),
&[&[1, 2], &[3, 4], &[5, 6]]
);
}
}
  1. Recalling the unsafe superpowers, we could try and change the way we are reading memory. Let's add this test to see how it works:
#[test]
fn test_str_to_bytes_horribly_unsafe() {
let bytes = unsafe { std::mem::transmute::<&str, &[u8]>("Going
off the menu") };
assert_eq!(
bytes,
&[
71, 111, 105, 110, 103, 32, 111, 102, 102, 32, 116,
104, 101, 32, 109, 101, 110, 117
]
);
}

  1. The last step is to see the positive test results after running cargo test:
$ cargo test
Compiling unsafe-ways v0.1.0 (Rust-Cookbook/Chapter02/unsafe-ways)
Finished dev [unoptimized + debuginfo] target(s) in 0.41s
Running target/debug/deps/unsafe_ways-e7a1d3ffcc456d53

running 2 tests
test tests::test_str_to_bytes_horribly_unsafe ... ok
test tests::test_split_into_equal_parts ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

Doc-tests unsafe-ways

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

Safety is an important concept in Rust, so let's find out what we trade off by using unsafe.