Add unsafe example

This commit is contained in:
Timothy Warren 2019-02-07 11:40:56 -05:00
parent 6d65d88b76
commit 6cf7aa9000
5 changed files with 139 additions and 29 deletions

View File

@ -36,6 +36,7 @@
<cargoProject FILE="$PROJECT_DIR$/gui/Cargo.toml" />
<cargoProject FILE="$PROJECT_DIR$/blog/Cargo.toml" />
<cargoProject FILE="$PROJECT_DIR$/pattern_matching/Cargo.toml" />
<cargoProject FILE="$PROJECT_DIR$/unsafe_blocks/Cargo.toml" />
</component>
<component name="ComposerJsonPluginSettings">
<unboundedVersionInspectionSettings>

View File

@ -145,6 +145,10 @@
<sourceFolder url="file://$MODULE_DIR$/pattern_matching/examples" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/pattern_matching/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/pattern_matching/benches" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/unsafe_blocks/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/unsafe_blocks/examples" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/unsafe_blocks/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/unsafe_blocks/benches" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/add/add-one/target" />
<excludeFolder url="file://$MODULE_DIR$/add/adder/target" />
<excludeFolder url="file://$MODULE_DIR$/adder/target" />
@ -179,6 +183,7 @@
<excludeFolder url="file://$MODULE_DIR$/threads/target" />
<excludeFolder url="file://$MODULE_DIR$/trait_objects/target" />
<excludeFolder url="file://$MODULE_DIR$/twelve_days_of_christmas/target" />
<excludeFolder url="file://$MODULE_DIR$/unsafe_blocks/target" />
<excludeFolder url="file://$MODULE_DIR$/variables/target" />
</content>
<orderEntry type="inheritedJdk" />

View File

@ -2,6 +2,8 @@
<project version="4">
<component name="ChangeListManager">
<list default="true" id="c8f42924-1cd2-4b1c-bcff-602a3368bb16" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/unsafe_blocks/Cargo.toml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/unsafe_blocks/src/main.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/rust.iml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/rust.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
@ -15,10 +17,10 @@
<component name="FileEditorManager">
<leaf>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/pattern_matching/src/main.rs">
<entry file="file://$PROJECT_DIR$/unsafe_blocks/src/main.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="903">
<caret line="194" column="24" selection-start-line="194" selection-start-column="24" selection-end-line="194" selection-end-column="24" />
<state relative-caret-position="552">
<caret line="40" column="56" selection-start-line="40" selection-start-column="56" selection-end-line="40" selection-end-column="56" />
</state>
</provider>
</entry>
@ -52,7 +54,6 @@
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/rectangles/src/main.rs" />
<option value="$PROJECT_DIR$/enums/src/main.rs" />
<option value="$PROJECT_DIR$/modules/src/sound.rs" />
<option value="$PROJECT_DIR$/modules/src/performance_group.rs" />
@ -103,6 +104,7 @@
<option value="$PROJECT_DIR$/blog/src/main.rs" />
<option value="$PROJECT_DIR$/blog/Cargo.toml" />
<option value="$PROJECT_DIR$/pattern_matching/src/main.rs" />
<option value="$PROJECT_DIR$/unsafe_blocks/src/main.rs" />
</list>
</option>
</component>
@ -112,11 +114,11 @@
<annotation-enable>false</annotation-enable>
<other-services-enabled>false</other-services-enabled>
</component>
<component name="ProjectFrameBounds">
<option name="x" value="1680" />
<option name="y" value="-410" />
<component name="ProjectFrameBounds" extendedState="6">
<option name="x" value="1920" />
<option name="y" value="582" />
<option name="width" value="1050" />
<option name="height" value="1657" />
<option name="height" value="877" />
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="true">
<ConfirmationsSetting value="1" id="Add" />
@ -136,12 +138,12 @@
<path>
<item name="rust" type="3d21c010:ScopeViewTreeModel$ProjectNode" />
<item name="rust" type="2674bda8:ScopeViewTreeModel$GroupNode" />
<item name="pattern_matching" type="9f88c78c:ScopeViewTreeModel$FileNode" />
<item name="unsafe_blocks" type="9f88c78c:ScopeViewTreeModel$FileNode" />
</path>
<path>
<item name="rust" type="3d21c010:ScopeViewTreeModel$ProjectNode" />
<item name="rust" type="2674bda8:ScopeViewTreeModel$GroupNode" />
<item name="pattern_matching" type="9f88c78c:ScopeViewTreeModel$FileNode" />
<item name="unsafe_blocks" type="9f88c78c:ScopeViewTreeModel$FileNode" />
<item name="src" type="9f88c78c:ScopeViewTreeModel$FileNode" />
</path>
</expand>
@ -175,7 +177,7 @@
</component>
<component name="PropertiesComponent">
<property name="JavaScriptWeakerCompletionTypeGuess" value="true" />
<property name="com.android.tools.idea.instantapp.provision.ProvisionBeforeRunTaskProvider.myTimeStamp" value="1549488475930" />
<property name="com.android.tools.idea.instantapp.provision.ProvisionBeforeRunTaskProvider.myTimeStamp" value="1549557641362" />
<property name="javascript.nodejs.core.library.configured.version" value="7.1.0" />
<property name="js.eslint.eslintPackage" value="$USER_HOME$/.yarn-config/global/node_modules/.bin/eslint" />
<property name="js.eslint.nodeInterpreter" value="project" />
@ -203,7 +205,7 @@
</list>
</option>
</component>
<component name="RunManager" selected="Cargo Command.Run pattern_matching">
<component name="RunManager" selected="Cargo Command.Run unsafe_blocks">
<configuration name="&lt;template&gt;" type="TestNG" default="true" selected="false">
<option name="MAIN_CLASS_NAME" />
<option name="VM_PARAMETERS" value="-ea" />
@ -252,13 +254,13 @@
<envs />
<method v="2" />
</configuration>
<configuration name="Run twelve_days_of_christmas" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true">
<configuration name="Run unsafe_blocks" type="CargoCommandRunConfiguration" factoryName="Cargo Command" temporary="true">
<option name="channel" value="DEFAULT" />
<option name="command" value="run --package twelve_days_of_christmas --bin twelve_days_of_christmas" />
<option name="command" value="run --package unsafe_blocks --bin unsafe_blocks" />
<option name="allFeatures" value="false" />
<option name="nocapture" value="false" />
<option name="backtrace" value="SHORT" />
<option name="workingDirectory" value="file://$PROJECT_DIR$/twelve_days_of_christmas" />
<option name="workingDirectory" value="file://$PROJECT_DIR$/unsafe_blocks" />
<envs />
<method v="2" />
</configuration>
@ -281,11 +283,11 @@
</configuration>
<recent_temporary>
<list>
<item itemvalue="Cargo Command.Run unsafe_blocks" />
<item itemvalue="Cargo Command.Run pattern_matching" />
<item itemvalue="Cargo Command.Run blog" />
<item itemvalue="Cargo Command.Run gui" />
<item itemvalue="Cargo Command.Test lib::tests" />
<item itemvalue="Cargo Command.Run twelve_days_of_christmas" />
</list>
</recent_temporary>
</component>
@ -322,11 +324,11 @@
</history-entry>
</component>
<component name="ToolWindowManager">
<frame x="1680" y="-410" width="1050" height="1657" extended-state="6" />
<frame x="1920" y="-438" width="1080" height="1897" extended-state="6" />
<editor active="true" />
<layout>
<window_info content_ui="combo" id="Project" order="0" sideWeight="0.49586776" visible="true" weight="0.26141885" />
<window_info id="Structure" order="1" sideWeight="0.5041322" side_tool="true" visible="true" weight="0.26141885" />
<window_info content_ui="combo" id="Project" order="0" sideWeight="0.496614" visible="true" weight="0.2540132" />
<window_info id="Structure" order="1" sideWeight="0.503386" side_tool="true" visible="true" weight="0.2540132" />
<window_info id="Image Layers" order="2" />
<window_info id="Designer" order="3" />
<window_info id="Capture Tool" order="4" />
@ -334,7 +336,7 @@
<window_info id="Cargo" order="6" sideWeight="0.49791494" weight="0.3286119" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" weight="0.32979318" />
<window_info active="true" anchor="bottom" id="Run" order="2" visible="true" weight="0.29696578" />
<window_info active="true" anchor="bottom" id="Run" order="2" visible="true" weight="0.2571269" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
@ -356,13 +358,6 @@
<option name="version" value="1" />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/structs/src/main.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="624">
<caret line="39" lean-forward="true" selection-start-line="39" selection-end-line="39" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/slices/src/main.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="704">
@ -789,8 +784,15 @@
</entry>
<entry file="file://$PROJECT_DIR$/pattern_matching/src/main.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="903">
<caret line="194" column="24" selection-start-line="194" selection-start-column="24" selection-end-line="194" selection-end-column="24" />
<state relative-caret-position="2752">
<caret line="172" column="10" lean-forward="true" selection-start-line="172" selection-start-column="10" selection-end-line="172" selection-end-column="10" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/unsafe_blocks/src/main.rs">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="552">
<caret line="40" column="56" selection-start-line="40" selection-start-column="56" selection-end-line="40" selection-end-column="56" />
</state>
</provider>
</entry>

7
unsafe_blocks/Cargo.toml Normal file
View File

@ -0,0 +1,7 @@
[package]
name = "unsafe_blocks"
version = "0.1.0"
authors = ["Timothy Warren <twarren@nabancard.com>"]
edition = "2018"
[dependencies]

95
unsafe_blocks/src/main.rs Normal file
View File

@ -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();
}