-
-
-
-
-
-
-
@@ -789,8 +784,15 @@
-
-
+
+
+
+
+
+
+
+
+
diff --git a/unsafe_blocks/Cargo.toml b/unsafe_blocks/Cargo.toml
new file mode 100644
index 0000000..4c6d43e
--- /dev/null
+++ b/unsafe_blocks/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "unsafe_blocks"
+version = "0.1.0"
+authors = ["Timothy Warren "]
+edition = "2018"
+
+[dependencies]
diff --git a/unsafe_blocks/src/main.rs b/unsafe_blocks/src/main.rs
new file mode 100644
index 0000000..4227373
--- /dev/null
+++ b/unsafe_blocks/src/main.rs
@@ -0,0 +1,95 @@
+//! Unsafe Example
+//!
+//! In Rust, unsafe means less automated safety, not no safety. It's an
+//! escape hatch for code not normally allowed by the Rust compiler.
+//!
+//! Unsafe code allows the following 4 abilities:
+//!
+//! 1. Dereferencing raw pointers
+//! 2. Calling an unsafe function or method
+//! 3. Acessing/Mutating a mutable static variable (global)
+//! 4. Implementing an unsafe trait
+use std::slice;
+
+extern "C" {
+ fn abs(input: i32) -> i32;
+}
+
+// Immutable static variable (global) - safe
+static HELLO_WORLD: &str = "Hello, world!";
+
+// Mutable static variable - unsafe to access or mutate
+static mut COUNTER: u32 = 0;
+
+fn raw_pointer() {
+ let mut num = 5;
+
+ // Casting references to raw pointers
+ // Raw pointers can be created in safe code,
+ // but can only be dereferenced in unsafe code
+ let r1 = &num as *const i32;
+ let r2 = &mut num as *mut i32;
+
+ unsafe {
+ println!("r1 is: {}", *r1);
+ println!("r2 is: {}", *r2);
+ }
+}
+
+/// An unsafe function can only be called within an unsafe block
+/// This is essentially the same as wrapping the entire function in an unsafe block,
+/// as an unsafe block in the function body is redundant
+unsafe fn dangerous() {}
+
+/// A 'safe' function can wrap unsafe code
+fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
+ let len = slice.len();
+ let ptr = slice.as_mut_ptr(); // Get the raw pointer of the slice
+
+ assert!(mid <= len);
+
+ unsafe {
+ // These slice methods are unsafe because they require a valid pointer.
+ // Since the Rust compiler can not verify the safety of the pointers,
+ // the calls must be in an unsafe block. The function is still considered
+ // safe, though, because the original pointer is valid, and the bounds
+ // of the slice are verified with the assert call.
+ (
+ slice::from_raw_parts_mut(ptr, mid),
+ slice::from_raw_parts_mut(ptr.offset(mid as isize), len - mid)
+ )
+ }
+}
+
+/// A call to a function from a foreign programming language is considered
+/// unsafe, as rust can not verify the safety of the external code.
+/// While this can be wrapped in a 'safe' function, it is (unfortunately) up to the programmer
+/// to make sure the call is actually safe
+fn c_library_call() {
+ unsafe {
+ println!("Absolute value of -3 according to C: {}", abs(-3));
+ }
+}
+
+
+/// Mutable static variables (globals) are unsafe to access
+/// or mutate due to the possibility of data races in multithreaded code
+fn add_to_count(inc: u32) {
+ unsafe {
+ COUNTER += inc; // Mutating a mutable static variable is unsafe
+ }
+}
+
+
+fn main() {
+ raw_pointer();
+
+ add_to_count(3);
+
+ unsafe {
+ dangerous();
+ println!("COUNTER: {}", COUNTER); // Accessing a mutable static variable is unsafe
+ }
+
+ c_library_call();
+}