├── LICENSE ├── README.md ├── c++_to_rust ├── build.sh └── src │ ├── add.h │ ├── add.rs │ ├── hello.h │ ├── hello.rs │ └── main.cpp ├── c_to_rust ├── build.sh └── src │ ├── add.h │ ├── add.rs │ ├── hello.h │ ├── hello.rs │ └── main.c ├── fizzbuzz └── src │ └── fizzbuzz.rs ├── functional └── src │ └── main.rs ├── generics ├── cargo.toml └── src │ └── main.rs ├── graph └── src │ └── main.rs ├── iterator_fun └── src │ └── main.rs ├── lifetimes └── src │ └── main.rs ├── lifetimes2 └── src │ └── main.rs ├── low_level ├── .cargo │ └── config ├── Cargo.lock ├── Cargo.toml ├── README.md ├── deploy.sh └── src │ ├── fpga_hk.rs │ └── main.rs ├── pointer_fun └── src │ └── main.rs ├── pointer_fun2 └── src │ └── main.rs ├── presentation ├── presentation.pdf ├── presentation.tex └── video.mp4 ├── rust_to_c ├── Cargo.toml ├── build.rs └── src │ ├── add.c │ └── main.rs ├── stack └── src │ └── main.rs ├── string └── src │ └── main.rs ├── string2 └── src │ └── main.rs ├── struct └── src │ └── main.rs ├── thread └── src │ └── main.rs ├── thread2 └── src │ └── main.rs ├── thread3 └── src │ └── main.rs ├── thread4 └── src │ └── main.rs ├── traits └── src │ └── main.rs ├── tree └── src │ └── main.rs └── vector └── src └── main.rs /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Gerald Stanje 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## rust_snippets: 2 | This repo shows some examples which I implemented in order to learn the Rust Programming Language. 3 | 4 | ## References: 5 | **http://www.rust-compare.com/site/interfaces.html** 6 | 7 | **http://nercury.github.io/rust/guide/2015/01/19/ownership.html** 8 | 9 | **http://scattered-thoughts.net/blog/2015/06/04/three-months-of-rust** 10 | 11 | **http://blog.rust-lang.org/2015/05/11/traits.html** 12 | 13 | **https://github.com/pnkfelix/rust-examples-icfp2014** -------------------------------------------------------------------------------- /c++_to_rust/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | all() { 4 | rustc src/add.rs 5 | rustc src/hello.rs 6 | g++ -Wall -o main src/main.cpp -L $(pwd) -ladd -lhello -lSystem -lpthread -lc -lm 7 | } 8 | 9 | 10 | clean() { 11 | rm libadd.a 12 | rm libhello.a 13 | rm main 14 | } 15 | 16 | case $1 in all|clean) "$1" ;; *) printf >&2 '%s: unknown command\n' "$1"; exit 1;; esac -------------------------------------------------------------------------------- /c++_to_rust/src/add.h: -------------------------------------------------------------------------------- 1 | #ifndef _ADD_H 2 | #define _ADD_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | int add(int a, int b); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif -------------------------------------------------------------------------------- /c++_to_rust/src/add.rs: -------------------------------------------------------------------------------- 1 | #![crate_type = "staticlib"] 2 | 3 | #![feature(libc)] 4 | extern crate libc; 5 | use libc::{c_int}; 6 | 7 | #[no_mangle] 8 | pub extern "C" fn add(a: c_int, b: c_int) -> c_int { 9 | return a + b; 10 | } -------------------------------------------------------------------------------- /c++_to_rust/src/hello.h: -------------------------------------------------------------------------------- 1 | #ifndef _HELLO_H 2 | #define _HELLO_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | void hello(const char *str); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif -------------------------------------------------------------------------------- /c++_to_rust/src/hello.rs: -------------------------------------------------------------------------------- 1 | #![crate_type = "staticlib"] 2 | 3 | #![feature(libc)] 4 | extern crate libc; 5 | use std::ffi::CStr; 6 | 7 | #[no_mangle] 8 | pub extern "C" fn hello(name: *const libc::c_char) { 9 | let buf = unsafe { CStr::from_ptr(name).to_bytes() }; 10 | let str_name = String::from_utf8(buf.to_vec()).unwrap(); 11 | println!("Hello from Rust: {}!", str_name); 12 | } -------------------------------------------------------------------------------- /c++_to_rust/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "add.h" 3 | #include "hello.h" 4 | 5 | int main(int argc, char *argv[]) { 6 | int res = add(2, 3); 7 | std::cout << res << std::endl; 8 | 9 | hello("hello world"); 10 | } -------------------------------------------------------------------------------- /c_to_rust/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | all() { 4 | rustc src/add.rs 5 | rustc src/hello.rs 6 | gcc -Wall -o main src/main.c -L $(pwd) -ladd -lhello -lSystem -lpthread -lc -lm 7 | } 8 | 9 | 10 | clean() { 11 | rm libadd.a 12 | rm libhello.a 13 | rm main 14 | } 15 | 16 | case $1 in all|clean) "$1" ;; *) printf >&2 '%s: unknown command\n' "$1"; exit 1;; esac -------------------------------------------------------------------------------- /c_to_rust/src/add.h: -------------------------------------------------------------------------------- 1 | #ifndef _ADD_H 2 | #define _ADD_H 3 | 4 | int add(int a, int b); 5 | 6 | #endif -------------------------------------------------------------------------------- /c_to_rust/src/add.rs: -------------------------------------------------------------------------------- 1 | #![crate_type = "staticlib"] 2 | 3 | #![feature(libc)] 4 | extern crate libc; 5 | use libc::{c_int}; 6 | 7 | #[no_mangle] 8 | pub extern "C" fn add(a: c_int, b: c_int) -> c_int { 9 | return a + b; 10 | } -------------------------------------------------------------------------------- /c_to_rust/src/hello.h: -------------------------------------------------------------------------------- 1 | #ifndef _HELLO_H 2 | #define _HELLO_H 3 | 4 | void hello(const char *str); 5 | 6 | #endif -------------------------------------------------------------------------------- /c_to_rust/src/hello.rs: -------------------------------------------------------------------------------- 1 | #![crate_type = "staticlib"] 2 | 3 | #![feature(libc)] 4 | extern crate libc; 5 | use std::ffi::CStr; 6 | 7 | #[no_mangle] 8 | pub extern "C" fn hello(name: *const libc::c_char) { 9 | let buf = unsafe { CStr::from_ptr(name).to_bytes() }; 10 | let str_name = String::from_utf8(buf.to_vec()).unwrap(); 11 | println!("Hello from Rust: {}!", str_name); 12 | } -------------------------------------------------------------------------------- /c_to_rust/src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "add.h" 4 | #include "hello.h" 5 | 6 | int main(int argc, char *argv[]) { 7 | int res = add(2, 3); 8 | printf("%d", res); 9 | 10 | hello("hello world"); 11 | } -------------------------------------------------------------------------------- /fizzbuzz/src/fizzbuzz.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | for i in 1..101 { 3 | let value = i.to_string(); 4 | println!("{}", match (i % 3, i % 5) { 5 | (0,0) => "FizzBuzz", 6 | (0,_) => "Fizz", 7 | (_,0) => "Buzz", 8 | _ => value.as_ref(), 9 | }); 10 | } 11 | } -------------------------------------------------------------------------------- /functional/src/main.rs: -------------------------------------------------------------------------------- 1 | struct MyStruct { 2 | a: u32, 3 | b: u32, 4 | } 5 | 6 | fn main() { 7 | let mut vec : Vec = Vec::new(); 8 | 9 | vec.push(MyStruct{a: 1, b: 2}); 10 | vec.push(MyStruct{a: 2, b: 2}); 11 | 12 | for e in vec.into_iter().filter(|x| x.a > 1) { 13 | println!("{}", e.b); 14 | } 15 | } -------------------------------------------------------------------------------- /generics/cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "main" 3 | version = "0.1.0" 4 | authors = ["Gerald Stanje "] 5 | 6 | [dependencies] 7 | num = "*" -------------------------------------------------------------------------------- /generics/src/main.rs: -------------------------------------------------------------------------------- 1 | use num::traits::One; 2 | use std::ops::Add; 3 | 4 | extern crate num; 5 | 6 | struct TwoNums { 7 | a: T, 8 | b: T 9 | } 10 | 11 | // You implement function for struct TwuNums which accept type T with following traits: Add and One 12 | impl TwoNums where T: Add + One { 13 | fn new(a: T, b: T) -> TwoNums { 14 | TwoNums {a: a, b: b} 15 | } 16 | } 17 | 18 | // inside your funcion which accepts type your type T Rust expects that you pass to add() the variable 19 | // with the same Type 20 | impl TwoNums where T: Add + One { 21 | fn succ(self) -> TwoNums { 22 | let a = self.a.add(One::one()); 23 | let b = self.b.add(One::one()); 24 | TwoNums::new(a, b) 25 | } 26 | } 27 | 28 | fn main() { 29 | let num: TwoNums = TwoNums::new(1.0, 2.0); 30 | let snum: TwoNums = num.succ(); 31 | println!("{}", snum.a); 32 | println!("{}", snum.b); 33 | } 34 | -------------------------------------------------------------------------------- /graph/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(vec_resize)] 2 | 3 | use std::iter::repeat; 4 | use std::collections::VecDeque; 5 | use std::collections::BinaryHeap; 6 | use std::cmp::Ordering; 7 | 8 | fn max(a: u32, b: u32) -> u32 { if a > b { a } else { b } } 9 | 10 | #[derive(Clone)] 11 | struct Edge { 12 | vertex: u32, 13 | weight: f32, 14 | } 15 | 16 | impl Edge { 17 | pub fn new(vertex_: u32, weight_: f32) -> Edge { 18 | Edge{vertex: vertex_, weight: weight_,} 19 | } 20 | } 21 | 22 | impl Ord for Edge { 23 | fn cmp(&self, other: &Self) -> Ordering { 24 | self.partial_cmp(other).unwrap() 25 | } 26 | } 27 | 28 | impl Eq for Edge {} 29 | 30 | impl PartialOrd for Edge { 31 | fn partial_cmp(&self, other: &Self) -> Option { 32 | (self.weight, self.vertex).partial_cmp(&(other.weight, other.vertex)) 33 | } 34 | } 35 | 36 | impl PartialEq for Edge { 37 | fn eq(&self, other: &Self) -> bool { 38 | (self.weight, &self.vertex) == (other.weight, &other.vertex) 39 | } 40 | } 41 | 42 | struct Graph { 43 | nodes: Vec>, 44 | } 45 | 46 | impl Graph { 47 | pub fn new() -> Graph { Graph{nodes: Vec::new(),} } 48 | 49 | pub fn add_edge(&mut self, src: u32, dst: u32, weight: f32) { 50 | let len = self.nodes.len(); 51 | 52 | if (max(src, dst)) > len as u32 { 53 | let new_len = (max(src, dst) + 1) as usize; 54 | self.nodes.extend(repeat(Vec::new()).take(new_len - len)) 55 | } 56 | self.nodes[src as usize].push(Edge::new(dst, weight)); 57 | } 58 | 59 | pub fn bfs(&self, src: u32) { 60 | let mut queue: VecDeque = VecDeque::new(); 61 | let len = self.nodes.len(); 62 | let mut visited = vec!(false ; len); 63 | 64 | queue.push_front(src); 65 | 66 | while let Some(current) = queue.pop_back() { 67 | if !visited[current as usize] { 68 | println!("current: {}" , current); 69 | visited[current as usize] = true; 70 | } else { continue ; } 71 | 72 | for n in &self.nodes[current as usize] { 73 | let neighbor: u32 = n.vertex; 74 | queue.push_front(neighbor); 75 | } 76 | } 77 | } 78 | 79 | pub fn dfs(&self, src: u32) { 80 | let mut stack: Vec = Vec::new(); 81 | let len = self.nodes.len() as usize; 82 | let mut visited = vec!(false ; len); 83 | 84 | stack.push(src); 85 | 86 | while let Some(current) = stack.pop() { 87 | if !visited[current as usize] { 88 | println!("current: {}" , current); 89 | visited[current as usize] = true; 90 | } else { continue ; } 91 | 92 | for n in &self.nodes[current as usize] { 93 | let neighbor: u32 = n.vertex; 94 | stack.push(neighbor); 95 | } 96 | } 97 | } 98 | 99 | pub fn dijkstra(&self, src: u32, dst: u32) { 100 | let mut dist: Vec = Vec::new(); 101 | let mut prev: Vec = Vec::new(); 102 | let mut q = BinaryHeap::new(); 103 | const MAX_WEIGHT: f32 = std::f32::MAX; 104 | 105 | // init dist, prev table 106 | // would only work in rust nightly 107 | dist.resize(self.nodes.len(), MAX_WEIGHT); 108 | prev.resize(self.nodes.len(), 0); 109 | 110 | // We're at `start`, with a zero cost 111 | dist[src as usize] = 0.0; 112 | q.push(Edge::new(src, dist[src as usize])); 113 | 114 | while let Some(u) = q.pop() { 115 | // loop for all edges connected to 116 | for v in self.nodes[u.vertex as usize].iter() { 117 | 118 | let alt: f32 = dist[u.vertex as usize] + v.weight; // accumulate shortest dist from source 119 | 120 | // The variable alt is the length of the path from the root node to the neighbor node v 121 | // if it were to go through u. If this path is shorter than the current shortest path 122 | // recorded for v, that current path is replaced with this alt path. 123 | if alt < dist[v.vertex as usize] { 124 | dist[v.vertex as usize] = alt; // keep the shortest dist from src to v 125 | prev[v.vertex as usize] = u.vertex; 126 | 127 | q.push(Edge::new(v.vertex, dist[v.vertex as usize])); // Add unvisited v into the Q to be processed 128 | } 129 | } 130 | } 131 | 132 | let mut shortest_path: Vec = Vec::new(); 133 | let mut curr: u32 = dst; 134 | 135 | shortest_path.push(curr); 136 | 137 | while curr != src { 138 | curr = prev[curr as usize]; 139 | shortest_path.push(curr); 140 | } 141 | 142 | shortest_path.reverse(); 143 | 144 | for v in shortest_path.iter() { 145 | println!("current: {}", v); 146 | } 147 | } 148 | } 149 | 150 | fn main() { 151 | let mut g1 = Graph::new(); 152 | g1.add_edge(0, 1, 1.0); 153 | g1.add_edge(0, 2, 4.0); 154 | g1.add_edge(1, 0, 1.0); 155 | g1.add_edge(1, 2, 2.0); 156 | g1.add_edge(1, 3, 6.0); 157 | g1.add_edge(2, 0, 4.0); 158 | g1.add_edge(2, 1, 2.0); 159 | g1.add_edge(2, 3, 3.0); 160 | g1.add_edge(3, 1, 6.0); 161 | g1.add_edge(3, 2, 3.0); 162 | 163 | println!("bfs"); 164 | g1.bfs(0); 165 | 166 | println!(""); 167 | 168 | println!("dfs"); 169 | g1.dfs(0); 170 | 171 | println!(""); 172 | 173 | println!("dijkstra"); 174 | g1.dijkstra(0, 3); 175 | } -------------------------------------------------------------------------------- /iterator_fun/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut nums = vec![1, 2, 3]; 3 | 4 | for num in nums.iter_mut() { 5 | *num *= 2; 6 | } 7 | 8 | for num in &mut nums { 9 | *num *= 2; 10 | } 11 | 12 | for num in &nums { 13 | println!("{}", num); 14 | } 15 | 16 | // x.iter() ... iter() borrows x and returns an iterator to it 17 | // and once the iterator is dropped you can use x again 18 | for num in nums.iter() { 19 | println!("{}", num); 20 | } 21 | 22 | // x.into_iter() ... it borrows x and returns borrowed references into x 23 | // with into_iter you can never use x again because it moved away 24 | for num in nums.into_iter() { 25 | println!("{}", num); 26 | } 27 | 28 | // if &x is in scope, you can't mutate x or move it 29 | // if &mut x is in scope, you can only mutate x through that &mut 30 | // and if (y = x) is in scope (if x has been moved out of), you can't use x at all 31 | // .iter() is &; .iter_mut() is &mut; and .into_iter() moves 32 | 33 | //for num in nums.iter() { 34 | // println!("{}", num); 35 | //} 36 | } -------------------------------------------------------------------------------- /lifetimes/src/main.rs: -------------------------------------------------------------------------------- 1 | // this function basically says that it takes in two references and they must be at least the same lifetime (or live longer) 2 | // fn at line 13 just means that it takes a reference to a Car that has some arbitrary lifetime 'a, and it returns a string 3 | // that has the same lifetime 'a 4 | // so effectively that means that the string it returns lives as long as the car that was passed to it 5 | // which makes sense, since it's returning a reference to a member of the Car 6 | 7 | struct Car { 8 | // `String` is a heap allocated string 9 | manufacturer: String, 10 | model: String, 11 | year: i32, 12 | } 13 | 14 | fn get_model<'a>(car: &'a Car) -> &'a str { 15 | &car.model 16 | } 17 | 18 | struct Test 19 | { 20 | val: i32, 21 | } 22 | 23 | trait Double 24 | { 25 | fn double(&self) -> i32; 26 | } 27 | 28 | impl Double for Test 29 | { 30 | fn double(&self) -> i32 31 | { 32 | self.val * 2 33 | } 34 | } 35 | 36 | fn do_stuff<'a, F>(obj: &'a Double, f: F) 37 | where F: Fn(&'a Double) -> i32 38 | { 39 | println!("{}", f(obj)); 40 | } 41 | 42 | fn main() { 43 | let car = Car { 44 | // construct a `String` from a reference to a string (`&'static str`) 45 | // by copying of the data 46 | manufacturer: "Tesla".to_string(), 47 | model: "Model S P85D".to_string(), 48 | year: 2015, 49 | }; 50 | 51 | let model: &str = get_model(&car); 52 | 53 | println!("Car model: {}", model); 54 | 55 | let asd = Test{ val: 42 }; 56 | do_stuff(&asd, Double::double); 57 | } -------------------------------------------------------------------------------- /lifetimes2/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::collections::hash_map::Values; 3 | 4 | // the contents of the method called values doesn't matter for the borrow checker, just its signature 5 | struct Foo { 6 | pub map: HashMap, 7 | pub bar: Bar, 8 | } 9 | 10 | struct Bar { 11 | pub count: usize, 12 | } 13 | 14 | impl Bar { 15 | pub fn update<'a>(&mut self, values: Values<'a, i32, String>) { 16 | self.count = values.len(); 17 | } 18 | } 19 | 20 | impl Foo { 21 | pub fn new() -> Foo { 22 | Foo{ 23 | map: HashMap::new(), 24 | bar: Bar{count: 0}, 25 | } 26 | } 27 | 28 | #[allow(dead_code)] 29 | pub fn values<'a>(&'a self) -> Values<'a, i32, String> { 30 | self.map.values() 31 | } 32 | 33 | pub fn update(&mut self) { 34 | // OK 35 | // self.map.values() only borrows self.map 36 | self.bar.update(self.map.values()); 37 | 38 | // Not OK 39 | // `self.map.values()` but not call a function because self.values() borrows the whole `self` 40 | // self.bar.update(self.values()); 41 | } 42 | } 43 | 44 | fn main() { 45 | let mut foo = Foo::new(); 46 | println!("Got count: {}", foo.bar.count); 47 | 48 | { 49 | foo.map.insert(5, "Hello".into()); 50 | foo.update(); 51 | println!("Got count: {}", foo.bar.count); 52 | } 53 | } -------------------------------------------------------------------------------- /low_level/.cargo/config: -------------------------------------------------------------------------------- 1 | [target.arm-unknown-linux-gnueabihf] 2 | linker = "arm-linux-gnueabihf-gcc" -------------------------------------------------------------------------------- /low_level/Cargo.lock: -------------------------------------------------------------------------------- 1 | [root] 2 | name = "rust_blink" 3 | version = "0.1.0" 4 | dependencies = [ 5 | "libc 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 6 | "mmap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 7 | ] 8 | 9 | [[package]] 10 | name = "libc" 11 | version = "0.1.7" 12 | source = "registry+https://github.com/rust-lang/crates.io-index" 13 | 14 | [[package]] 15 | name = "mmap" 16 | version = "0.1.1" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | dependencies = [ 19 | "libc 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 20 | "tempdir 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 21 | ] 22 | 23 | [[package]] 24 | name = "rand" 25 | version = "0.3.8" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | dependencies = [ 28 | "libc 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 29 | ] 30 | 31 | [[package]] 32 | name = "tempdir" 33 | version = "0.3.4" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | dependencies = [ 36 | "rand 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 37 | ] 38 | 39 | -------------------------------------------------------------------------------- /low_level/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust_blink" 3 | version = "0.1.0" 4 | authors = ["Gerald Stanje "] 5 | 6 | [dependencies] 7 | libc = "*" 8 | mmap = "*" -------------------------------------------------------------------------------- /low_level/README.md: -------------------------------------------------------------------------------- 1 | ## Goal: 2 | 3 | This project shows how to cross compile your Rust application for ARM devices. 4 | 5 | ## Installation: 6 | 7 | * Install the Rust Cross Compiler (Rust 1.0.0) for ARM (armv7l): 8 | ``` 9 | $ git clone https://github.com/rust-lang/rust 10 | $ cd rust 11 | $ git checkout stable 12 | $ ./configure --target=arm-unknown-linux-gnueabihf,x86_64-unknown-linux-gnu 13 | $ make -j$(nproc) 14 | $ sudo make install 15 | ``` 16 | 17 | * Build Cargo: 18 | ``` 19 | $ mkdir local_cargo 20 | $ curl -sSf https://static.rust-lang.org/rustup.sh | sh -s -- --prefix=local_cargo 21 | ``` 22 | 23 | * Reference: 24 | https://github.com/japaric/ruststrap/blob/master/1-how-to-cross-compile.md 25 | 26 | ## Cross compile your Rust App with Cargo: 27 | ``` 28 | $ cargo build --target=arm-unknown-linux-gnueabihf 29 | ``` 30 | 31 | ## Run the deploy script: 32 | Set the Cargo Path and the IP address of your ARM device to RP_IP. 33 | 34 | ``` 35 | $ ./deploy 36 | ``` -------------------------------------------------------------------------------- /low_level/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RP_IP="172.31.133.136" 4 | CARGO_PATH="../../local_cargo/bin/cargo" 5 | 6 | ${CARGO_PATH} clean 7 | ${CARGO_PATH} build --target=arm-unknown-linux-gnueabihf 8 | scp target/arm-unknown-linux-gnueabihf/debug/rust_blink root@${RP_IP}:/home 9 | -------------------------------------------------------------------------------- /low_level/src/fpga_hk.rs: -------------------------------------------------------------------------------- 1 | use std::ptr; 2 | use std::fs; 3 | use std::io::{Write, SeekFrom, Seek}; 4 | use std::os::unix::prelude::AsRawFd; 5 | use mmap::{MemoryMap, MapOption}; 6 | use libc; 7 | use std::f32; 8 | use std::default::Default; 9 | 10 | const HK_BASE_ADDR: isize = 0x000000; 11 | 12 | struct hk_reg { 13 | id: u32, 14 | dna_low: u32, 15 | dna_high: u32, 16 | reserved1: u32, 17 | exp_dir_p: u32, 18 | exp_dir_n: u32, 19 | exp_out_p: u32, 20 | exp_out_n: u32, 21 | exp_in_p: u32, 22 | exp_in_n: u32, 23 | reserved2: u32, 24 | reserved3: u32, 25 | led_ctrl: u32, // 0x30 26 | } 27 | 28 | pub struct fpgaHk { 29 | mmap: MemoryMap, 30 | hkReg: *mut hk_reg, 31 | } 32 | 33 | impl fpgaHk { 34 | pub fn new() -> fpgaHk { 35 | let size: usize = 0x400000; 36 | 37 | let mut f = fs::OpenOptions::new().read(true) 38 | .write(true) 39 | .open("/dev/uio0") 40 | .unwrap(); 41 | 42 | let mmap_opts = &[ 43 | // Then make the mapping *public* so it is written back to the file 44 | MapOption::MapNonStandardFlags(libc::MAP_SHARED), 45 | MapOption::MapReadable, 46 | MapOption::MapWritable, 47 | MapOption::MapFd(f.as_raw_fd()), 48 | ]; 49 | 50 | let mmap = MemoryMap::new(size, mmap_opts).unwrap(); 51 | 52 | let data = mmap.data(); 53 | 54 | if data.is_null() { 55 | panic!("Could not access data from memory mapped file") 56 | } 57 | 58 | let hkReg: *mut hk_reg; 59 | 60 | unsafe { 61 | hkReg = data.offset(HK_BASE_ADDR) as *mut hk_reg; 62 | } 63 | 64 | fpgaHk {mmap: mmap, hkReg: hkReg} 65 | } 66 | 67 | pub fn toggle(&mut self, led_pin: u32) { 68 | unsafe { 69 | (*self.hkReg).led_ctrl ^= 1 << led_pin; 70 | } 71 | } 72 | 73 | pub fn set_exp_p_dir(&mut self, dir: u32) { 74 | unsafe { 75 | (*self.hkReg).exp_dir_p = dir; 76 | } 77 | } 78 | 79 | pub fn toggle_exp_p_gpo(&mut self, pin: u32) { 80 | unsafe { 81 | (*self.hkReg).exp_out_p ^= 1 << pin; 82 | } 83 | } 84 | 85 | pub fn clear_exp_p_gpo(&mut self, pin: u32) { 86 | unsafe { 87 | (*self.hkReg).exp_out_p = !(1 << pin); 88 | } 89 | } 90 | 91 | pub fn set_exp_p_gpo(&mut self, pin: u32) { 92 | unsafe { 93 | (*self.hkReg).exp_out_p |= 1 << pin; 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /low_level/src/main.rs: -------------------------------------------------------------------------------- 1 | // from crates.io 2 | extern crate mmap; 3 | extern crate libc; 4 | 5 | use std::thread; 6 | use std::env; 7 | mod fpga_hk; 8 | 9 | fn main() { 10 | if let Some(arg1) = env::args().nth(1) { 11 | let mut hk = fpga_awg::fpgaHk::new(); 12 | 13 | while (true) { 14 | hk.toggle(1); 15 | thread::sleep_ms(arg1.parse::().unwrap()); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /pointer_fun/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut x = 5; 3 | 4 | add_one(&mut x); 5 | println!("add one: {}" , x); 6 | 7 | add_two(&mut x); 8 | println!("add two: {}" , x); 9 | } 10 | 11 | fn add_one(num: &mut i32) { *num += 1; } 12 | 13 | fn add_two(num: *mut i32) { unsafe { *num += 2; } } -------------------------------------------------------------------------------- /pointer_fun2/src/main.rs: -------------------------------------------------------------------------------- 1 | const n: usize = (16*1024); 2 | 3 | struct foo { 4 | chaMem: *mut [u32; n], 5 | } 6 | 7 | impl foo { 8 | pub fn new() -> foo { 9 | let mem: *mut [u32; n] = unsafe { ::std::mem::transmute(Box::new([1; n])) }; 10 | foo {chaMem: mem} 11 | } 12 | 13 | pub fn get_sig_ptr(&mut self, cha_signal: *mut *mut u32) { 14 | unsafe { 15 | *cha_signal = self.chaMem as *mut _; 16 | } 17 | } 18 | 19 | pub fn get_sig_ptr2(&mut self) -> *mut u32 { 20 | return self.chaMem as *mut _; 21 | } 22 | 23 | pub fn get_sig_ptr3(&mut self) -> *mut [u32; n] { 24 | return self.chaMem; 25 | } 26 | 27 | pub fn get_sig_ptr4(&mut self) -> &mut [u32; n] { 28 | unsafe { 29 | return &mut *(self.chaMem); 30 | } 31 | } 32 | } 33 | 34 | // This code is editable and runnable! 35 | fn main() { 36 | let mut f = foo::new(); 37 | 38 | let mut cha_signal1: *mut u32 = ::std::ptr::null_mut(); 39 | f.get_sig_ptr(&mut cha_signal1); 40 | 41 | for i in 1..n { 42 | println!("{}", unsafe { *cha_signal1.offset(i as isize) }); // (*cha_signal)[i] 43 | } 44 | 45 | let mut cha_signal2: *mut u32 = f.get_sig_ptr2(); 46 | 47 | for i in 1..n { 48 | println!("{}", unsafe { *cha_signal2.offset(i as isize) }); 49 | } 50 | 51 | let mut cha_signal3: *mut [u32; n] = f.get_sig_ptr3(); 52 | 53 | for i in 1..n { 54 | println!("{}", unsafe { (*cha_signal3)[i] }); 55 | } 56 | 57 | // preferred version 58 | let mut cha_signal4: &mut [u32; n] = f.get_sig_ptr4(); 59 | 60 | for i in 1..n { 61 | println!("{}", cha_signal4[i]); 62 | } 63 | } -------------------------------------------------------------------------------- /presentation/presentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geraldstanje/rust_snippets/9f570b89dc8c4b4c697b69d74f437c344cd25509/presentation/presentation.pdf -------------------------------------------------------------------------------- /presentation/presentation.tex: -------------------------------------------------------------------------------- 1 | \documentclass{beamer} % 2 | \usetheme{CambridgeUS} 3 | \usepackage[latin1]{inputenc} 4 | \usefonttheme{professionalfonts} 5 | \usepackage{times} 6 | \usepackage{tikz} 7 | \usepackage{amsmath} 8 | \usepackage{verbatim} 9 | \usepackage{graphicx} 10 | \usepackage{multimedia} 11 | \usepackage{listings} 12 | %\usepackage{movie15} 13 | %\usepackage{media9} 14 | \usetikzlibrary{arrows,shapes} 15 | 16 | \author{Gerald Stanje} 17 | \title{From C++ to Rust} 18 | 19 | \title[] %optional 20 | {From C++ to Rust} 21 | 22 | \subtitle{A high level overview about two Systems Programming Languages} 23 | 24 | \author[] % (optional, for multiple authors) 25 | {Gerald Stanje} 26 | 27 | \begin{document} 28 | 29 | \frame{\titlepage} 30 | 31 | % For every picture that defines or uses external nodes, you'll have to 32 | % apply the 'remember picture' style. To avoid some typing, we'll apply 33 | % the style to all pictures. 34 | \tikzstyle{every picture}+=[remember picture] 35 | 36 | % By default all math in TikZ nodes are set in inline mode. Change this to 37 | % displaystyle so that we don't get small fractions. 38 | \everymath{\displaystyle} 39 | 40 | % Slide 1 41 | \begin{frame} 42 | \frametitle{Content} 43 | 44 | \tikzstyle{na} = [baseline=-.5ex] 45 | 46 | \begin{itemize} 47 | \item Systems Programming 48 | \item Memory management in C++ 49 | \item Static Analysis 50 | \item Rust 51 | \item Ownership in Rust 52 | \item Borrow in Rust 53 | \item Concurrency in Rust 54 | \item Cargo 55 | \end{itemize} 56 | 57 | \end{frame} 58 | 59 | % Slide 2 60 | \begin{frame} 61 | \frametitle{System Programming} 62 | 63 | \begin{itemize} 64 | \item Programmer needs very explicit control over the hardware 65 | \begin{itemize} 66 | \item How much memory is used? 67 | \item What code is generated? 68 | \item When the memory is allocated or freed? 69 | \end{itemize} 70 | \item Used to build: operating systems, compilers, device drivers, factory automation, robots, high performance mathematical software, games 71 | \end{itemize} 72 | 73 | \end{frame} 74 | 75 | % Slide 3 76 | \begin{frame} 77 | \frametitle{Memory management in C++ is hard} 78 | 79 | \movie[externalviewer]{Video}{video.mp4} 80 | 81 | \end{frame} 82 | 83 | % Slide 4 84 | \begin{frame}[fragile] 85 | \frametitle{C++ Safety} 86 | \lstset{language=C++, 87 | basicstyle=\ttfamily, 88 | keywordstyle=\color{blue}\ttfamily, 89 | stringstyle=\color{red}\ttfamily, 90 | commentstyle=\color{green}\ttfamily, 91 | morecomment=[l][\color{magenta}]{\#} 92 | } 93 | \begin{lstlisting} 94 | int main() { 95 | vector vec; 96 | vec.push_back("FC"); 97 | auto& elem = vec[0]; 98 | vec.push_back("Bayern Munich"); 99 | cout << elem << endl; 100 | } 101 | \end{lstlisting} 102 | 103 | \end{frame} 104 | 105 | % Slide 5 106 | \begin{frame}[fragile] 107 | \frametitle{C++ Safety} 108 | \lstset{language=C++, 109 | basicstyle=\ttfamily, 110 | keywordstyle=\color{blue}\ttfamily, 111 | stringstyle=\color{red}\ttfamily, 112 | commentstyle=\color{green}\ttfamily, 113 | morecomment=[l][\color{magenta}]{\#} 114 | } 115 | \begin{lstlisting} 116 | int main() { 117 | vector vec; 118 | vec.push_back("FC"); 119 | auto& elem = vec[0]; 120 | vec.push_back("Bayern Munich"); 121 | cout << elem << endl; 122 | } 123 | \end{lstlisting} 124 | 125 | \begin{figure} 126 | \centering 127 | \includegraphics[scale=0.25]{safety.png} 128 | \end{figure} 129 | 130 | \end{frame} 131 | 132 | % Slide 6 133 | \begin{frame} 134 | \frametitle{Static Analysis} 135 | 136 | \begin{itemize} 137 | \item Lots of free, open source and commercial offerings for static analysis of C++ source 138 | \begin{itemize} 139 | \item cppcheck 140 | \item clang-analyse 141 | \item coverity 142 | \end{itemize} 143 | \item Analyzers for code guideline profiles 144 | \begin{itemize} 145 | \item bounds 146 | \item types 147 | \item lifetimes 148 | \end{itemize} 149 | \item Downside: False Positives $\rightarrow$ cannot see if a certain condition can never happen if e.g. it depends on input. 150 | \end{itemize} 151 | 152 | \end{frame} 153 | 154 | % Slide 7 155 | \begin{frame} 156 | \frametitle{What is Rust?} 157 | 158 | \begin{itemize} 159 | \item systems programming language 160 | \item blazingly fast 161 | \item compiled binary 162 | \item immutable by default 163 | \item prevents almost all crashes: no segmentation faults, no null pointers, no dangling pointers 164 | \item eliminates data races: two parallel processes access memory location in parallel, at least one process writes to the memory. 165 | \item uses LLVM in the backend 166 | \end{itemize} 167 | 168 | \end{frame} 169 | 170 | % Slide 8 171 | \begin{frame}[fragile] 172 | \frametitle{Ownership in Rust} 173 | 174 | \begin{itemize} 175 | \item Exactly one owner per allocation 176 | \item Memory freed when the owner leaves scope 177 | \begin{itemize} 178 | \item All references must be out of scope too 179 | \end{itemize} 180 | \item Ownership may be transferred (move) 181 | \begin{itemize} 182 | \item Invalidates prior owner 183 | \end{itemize} 184 | \end{itemize} 185 | 186 | \lstset{language=Java, 187 | basicstyle=\ttfamily, 188 | keywordstyle=\color{blue}\ttfamily, 189 | stringstyle=\color{red}\ttfamily, 190 | commentstyle=\color{green}\ttfamily, 191 | morecomment=[l][\color{magenta}]{\#} 192 | } 193 | \begin{lstlisting} 194 | fn print(a: Vec) {} 195 | 196 | fn main() { 197 | let s = Vec::new(); 198 | a.push(1); 199 | a.push(2); 200 | 201 | print(s); 202 | print(s); // error: s is no longer the 203 | // owner of the vector 204 | } 205 | \end{lstlisting} 206 | 207 | \end{frame} 208 | 209 | % Slide 9 210 | \begin{frame}[fragile] 211 | \frametitle{Shared Borrow in Rust} 212 | 213 | \begin{itemize} 214 | \item Ownership may be temporary (borrow) 215 | \begin{itemize} 216 | \item References are created with \& 217 | \end{itemize} 218 | \item Borrowing prevents moving 219 | \item Shared references are immutable 220 | \end{itemize} 221 | 222 | \lstset{language=Java, 223 | basicstyle=\ttfamily, 224 | keywordstyle=\color{blue}\ttfamily, 225 | stringstyle=\color{red}\ttfamily, 226 | commentstyle=\color{green}\ttfamily, 227 | morecomment=[l][\color{magenta}]{\#} 228 | } 229 | \begin{lstlisting} 230 | fn print(a: &Vec) {} 231 | 232 | fn main() { 233 | let a = Vec::new(); 234 | a.push(1); 235 | a.push(2); 236 | 237 | print(&a); 238 | print(&a); 239 | } 240 | \end{lstlisting} 241 | 242 | \end{frame} 243 | 244 | % Slide 10 245 | %\begin{frame}[fragile] 246 | %\frametitle{Borrow in Rust} 247 | 248 | %\begin{itemize} 249 | % \item Borrows values are valid for a lifetime 250 | %\end{itemize} 251 | 252 | %\lstset{language=Java, 253 | % basicstyle=\ttfamily, 254 | % keywordstyle=\color{blue}\ttfamily, 255 | % stringstyle=\color{red}\ttfamily, 256 | % commentstyle=\color{green}\ttfamily, 257 | % morecomment=[l][\color{magenta}]{\#} 258 | %} 259 | %\begin{lstlisting} 260 | %fn print(a: &Vec) {} 261 | 262 | %fn main() { 263 | % let a = Vec::new(); 264 | % a.push(1); 265 | % a.push(2); 266 | 267 | % { 268 | % let b = &a; 269 | % } 270 | 271 | % print(a); 272 | %} 273 | %\end{lstlisting} 274 | 275 | %\end{frame} 276 | 277 | % Slide 11 278 | \begin{frame}[fragile] 279 | \frametitle{Mutable Borrow in Rust} 280 | 281 | \begin{itemize} 282 | %\item Cannot have both shared and mutable reference at the same time 283 | \item There can only be one unique reference to a var. that is mutable 284 | \item Borrows values are valid for a lifetime 285 | \end{itemize} 286 | 287 | \lstset{language=Java, 288 | basicstyle=\ttfamily, 289 | keywordstyle=\color{blue}\ttfamily, 290 | stringstyle=\color{red}\ttfamily, 291 | commentstyle=\color{green}\ttfamily, 292 | morecomment=[l][\color{magenta}]{\#} 293 | } 294 | \begin{lstlisting} 295 | fn muliply(vec: &mut Vec) { 296 | for e in vec.iter_mut() { *e *= 2; } 297 | } 298 | 299 | fn main() { 300 | let mut vec: Vec = vec![1, 2]; 301 | { 302 | let mut vec2 = &mut vec; 303 | muliply(&mut vec2); 304 | } 305 | muliply(&mut vec); 306 | } 307 | \end{lstlisting} 308 | 309 | \end{frame} 310 | 311 | % Slide 12 312 | \begin{frame}[fragile] 313 | \frametitle{Concurrency in Rust} 314 | 315 | \begin{itemize} 316 | \item Using ownership to prevent data races 317 | \item Parallelism is achieved at the granularity of an OS thread 318 | \item Safety is achieved by requiring that a 'move' owns captured variables 319 | %\begin{itemize} 320 | % \item a move owns its environment 321 | %\end{itemize} 322 | \end{itemize} 323 | 324 | \lstset{language=Java, 325 | basicstyle=\ttfamily, 326 | keywordstyle=\color{blue}\ttfamily, 327 | stringstyle=\color{red}\ttfamily, 328 | commentstyle=\color{green}\ttfamily, 329 | morecomment=[l][\color{magenta}]{\#} 330 | } 331 | \begin{lstlisting} 332 | fn main() { 333 | let mut a = Vec::new(); 334 | // 'move' instructs the closure to move out of 335 | // its environment 336 | thread::spawn(move || { 337 | a.push("foo"); 338 | }); 339 | a.push("bar"); // error: using a moved value 340 | } 341 | \end{lstlisting} 342 | 343 | \end{frame} 344 | 345 | % Slide 13 346 | \begin{frame}[fragile] 347 | \frametitle{Concurrency in Rust} 348 | 349 | \begin{itemize} 350 | \item Threads can communicate with channels 351 | \end{itemize} 352 | 353 | \lstset{language=Java, 354 | basicstyle=\ttfamily, 355 | keywordstyle=\color{blue}\ttfamily, 356 | stringstyle=\color{red}\ttfamily, 357 | commentstyle=\color{green}\ttfamily, 358 | morecomment=[l][\color{magenta}]{\#} 359 | } 360 | \begin{lstlisting} 361 | fn main() { 362 | let (tx, rx) = mpsc::channel(); 363 | let x = Box::new(5); // allocate 5 on the heap 364 | 365 | thread::spawn(move || { 366 | let result = 5 + *x; 367 | tx.send(result); 368 | }); 369 | 370 | let result = rx.recv().unwrap(); 371 | println!("{}", result); 372 | } 373 | \end{lstlisting} 374 | 375 | \end{frame} 376 | 377 | % Slide 14 378 | %\begin{frame}[fragile] 379 | %\frametitle{Unsafe in Rust} 380 | 381 | %\begin{itemize} 382 | % \item Unsafe blocks in Rust are used to bypass protections put in place by the compiler 383 | % \item Dereferencing raw pointers 384 | %\end{itemize} 385 | 386 | %\lstset{language=Java, 387 | % basicstyle=\ttfamily, 388 | % keywordstyle=\color{blue}\ttfamily, 389 | % stringstyle=\color{red}\ttfamily, 390 | % commentstyle=\color{green}\ttfamily, 391 | % morecomment=[l][\color{magenta}]{\#} 392 | %} 393 | %\begin{lstlisting} 394 | %fn main() { 395 | % let raw_p: *const u32 = &10; 396 | 397 | % unsafe { 398 | % assert!(*raw_p == 10); 399 | % } 400 | %} 401 | %\end{lstlisting} 402 | 403 | %\end{frame} 404 | 405 | % Slide 15 406 | \begin{frame}[fragile] 407 | \frametitle{Cargo} 408 | 409 | \lstset{language=Bash, 410 | basicstyle=\ttfamily, 411 | keywordstyle=\color{blue}\ttfamily, 412 | stringstyle=\color{red}\ttfamily, 413 | commentstyle=\color{green}\ttfamily, 414 | morecomment=[l][\color{magenta}]{\#} 415 | } 416 | 417 | \begin{itemize} 418 | \item Package manager, similar to pip in Python 419 | \item Download and manage dependencies 420 | \item Build the project 421 | \begin{itemize} 422 | \item Create Cargo.toml 423 | \begin{lstlisting} 424 | $ cargo new hello_word --bin 425 | \end{lstlisting} 426 | \item Cargo.toml 427 | \begin{lstlisting} 428 | [package] 429 | name = "hello_world" 430 | version = "0.1.0" 431 | authors = ["Gerald Stanje"] 432 | [dependencies] 433 | regex = "0.1.33" 434 | \end{lstlisting} 435 | \item Build project 436 | \begin{lstlisting} 437 | $ cargo build --release 438 | Compiling hello_world v0.1.0 (file:///ho 439 | me/geri/code/hello_world) 440 | \end{lstlisting} 441 | \end{itemize} 442 | \end{itemize} 443 | 444 | \end{frame} 445 | 446 | \end{document} -------------------------------------------------------------------------------- /presentation/video.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geraldstanje/rust_snippets/9f570b89dc8c4b4c697b69d74f437c344cd25509/presentation/video.mp4 -------------------------------------------------------------------------------- /rust_to_c/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust_to_c" 3 | version = "0.1.0" 4 | authors = ["Gerald Stanje "] 5 | build = "build.rs" 6 | 7 | [dependencies] 8 | libc = "0.1" 9 | 10 | [build-dependencies] 11 | gcc = "0.3" 12 | -------------------------------------------------------------------------------- /rust_to_c/build.rs: -------------------------------------------------------------------------------- 1 | extern crate gcc; 2 | 3 | fn main() { 4 | gcc::Config::new().file("src/add.c").compile("libadd.a"); 5 | } 6 | -------------------------------------------------------------------------------- /rust_to_c/src/add.c: -------------------------------------------------------------------------------- 1 | int add(int input1, int input2) { 2 | return input1 + input2; 3 | } 4 | -------------------------------------------------------------------------------- /rust_to_c/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate libc; 2 | 3 | extern { 4 | fn add(input1: libc::c_int, input2: libc::c_int) -> libc::c_int; 5 | } 6 | 7 | #[test] 8 | fn it_works() { 9 | assert_eq!(3, unsafe { add(1, 2) }); 10 | } 11 | 12 | fn main() { 13 | let input1 = 4; 14 | let input2 = 3; 15 | let output = unsafe { add(input1, input2) }; 16 | println!("{} + {} = {}", input1, input2, output); 17 | } 18 | -------------------------------------------------------------------------------- /stack/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(box_syntax)] 2 | 3 | struct Node { 4 | data: T, 5 | next: Option>>, 6 | } 7 | 8 | struct Stack { 9 | head: Option>>, 10 | } 11 | 12 | impl Stack { 13 | fn new() -> Stack { 14 | Stack { head: None } 15 | } 16 | 17 | fn push(&mut self, elem: T) { 18 | self.head = Some(box Node { 19 | data: elem, 20 | next: self.head.take(), 21 | }); 22 | } 23 | 24 | fn pop(&mut self) -> Option { 25 | match self.head.take() { 26 | None => None, 27 | Some(mut head) => { 28 | self.head = head.next.take(); 29 | Some(head.data) 30 | } 31 | } 32 | } 33 | } 34 | 35 | fn print(input_num: Option) { 36 | let num = match input_num { 37 | Some(num) => num, 38 | None => { 39 | println!("stack empty"); 40 | return; 41 | } 42 | }; 43 | 44 | println!("{}", num); 45 | } 46 | 47 | fn main() { 48 | let mut stack = Stack::new(); 49 | 50 | stack.push(1); 51 | stack.push(2); 52 | stack.push(3); 53 | print(stack.pop()); 54 | stack.push(4); 55 | print(stack.pop()); 56 | print(stack.pop()); 57 | stack.push(5); 58 | print(stack.pop()); 59 | print(stack.pop()); 60 | print(stack.pop()); 61 | } 62 | -------------------------------------------------------------------------------- /string/src/main.rs: -------------------------------------------------------------------------------- 1 | pub fn sort(word: &'static str) -> String { 2 | let mut chars: Vec = word.chars().collect(); 3 | chars.sort(); 4 | return chars.into_iter().collect(); 5 | } 6 | 7 | fn extract_numbers(s: &str) -> Vec { 8 | let mut num = String::new(); 9 | let mut m = vec![]; 10 | 11 | for c in s.chars() { 12 | if c.is_numeric() { 13 | num.push(c); 14 | } 15 | else { 16 | if !num.is_empty() { 17 | m.push(num.clone()); 18 | num.clear(); 19 | } 20 | } 21 | } 22 | 23 | if !num.is_empty() { 24 | m.push(num); 25 | } 26 | 27 | return m; 28 | } 29 | 30 | fn main() { 31 | let mystr1: &'static str = "This is a readonly string"; 32 | 33 | for c in mystr1.chars().rev() { 34 | print!("{}", c); 35 | } 36 | 37 | println!(""); 38 | 39 | let mut mystr2 = String::new(); 40 | for c in mystr1.chars() { 41 | mystr2.push(c); 42 | } 43 | 44 | println!("{}", mystr2); 45 | 46 | mystr2 = "Hello World".to_string(); 47 | 48 | println!("{}", mystr2); 49 | 50 | let num: u32 = 12; 51 | 52 | mystr2 = num.to_string(); 53 | 54 | println!("{}", mystr2); 55 | 56 | let str = sort("abzerfdsgyiof"); 57 | print!("{}", str); 58 | 59 | let mystr3 = "x12y7".to_string(); 60 | let m: Vec = extract_numbers(&mystr3); // -> ( "12", "7" ) 61 | 62 | println!(""); 63 | 64 | for x in m.iter() { 65 | println!("{}", x); 66 | } 67 | } -------------------------------------------------------------------------------- /string2/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::borrow::Cow; 2 | 3 | fn remove_spaces<'a>(input: &'a str) -> Cow<'a, str> { 4 | if input.contains(' ') { 5 | let mut buf = String::with_capacity(input.len()); 6 | 7 | for c in input.chars() { 8 | if c != ' ' { 9 | buf.push(c); 10 | } 11 | } 12 | 13 | return Cow::Owned(buf); 14 | } 15 | 16 | return Cow::Borrowed(input); 17 | } 18 | 19 | fn main() { 20 | let s = remove_spaces("I love Rustlang"); 21 | println!("{}", s); 22 | } -------------------------------------------------------------------------------- /struct/src/main.rs: -------------------------------------------------------------------------------- 1 | struct Rectangle { 2 | width: i32, 3 | height: i32, 4 | } 5 | 6 | impl Rectangle { 7 | fn new(w: i32, h: i32) -> Rectangle { 8 | Rectangle { width: w, height: h } 9 | } 10 | 11 | fn area(&self) -> f32 { 12 | return (self.width * self.height) as f32; 13 | } 14 | } 15 | 16 | 17 | fn main() { 18 | let r = Rectangle::new(3, 2); 19 | 20 | println!("{}", r.area()); 21 | } -------------------------------------------------------------------------------- /thread/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::thread; 2 | 3 | static NTHREADS: i32 = 10; 4 | 5 | // This is the `main` thread 6 | fn main() { 7 | let mut thread_vec: Vec<_> = Vec::new(); 8 | 9 | for i in 0..NTHREADS { 10 | // Spawn up another thread 11 | let child = thread::spawn(move || { 12 | println!("this is thread number {}", i) 13 | }); 14 | thread_vec.push(child); 15 | } 16 | 17 | for handle in thread_vec { 18 | // .unwrap() will propagate a panic from the child thread to the whole program 19 | // .unwrap() just panics on None/Err(e) 20 | // And returns the value from Some(x)/Ok(x) 21 | 22 | handle.join().unwrap(); 23 | } 24 | } -------------------------------------------------------------------------------- /thread2/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::thread; 2 | 3 | fn main() { 4 | let mut thread_vec: Vec<_> = Vec::new(); 5 | let nums = [1, 2]; 6 | let noms = ["gerald", "chriss", "martin", "mike"]; 7 | 8 | let mut odds = nums.iter().map(|&x| x * 2 - 1); 9 | 10 | for num in odds { 11 | let child = thread::spawn(move || { 12 | println!("{} says hello from a thread!", noms[num]); 13 | }); 14 | thread_vec.push(child); 15 | } 16 | 17 | for handle in thread_vec { 18 | // .unwrap() will propagate a panic from the child thread to the whole program 19 | // .unwrap() just panics on None/Err(e) 20 | // And returns the value from Some(x)/Ok(x) 21 | 22 | handle.join().unwrap(); 23 | } 24 | } -------------------------------------------------------------------------------- /thread3/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::sync::{Arc, Mutex}; 2 | use std::thread; 3 | 4 | // calculate pi multithreaded 5 | // based on riemann integration 6 | 7 | // This code is editable and runnable! 8 | fn main() { 9 | const NUM_THREADS: u64 = 6; 10 | const NUM_STEPS: u64 = 100_000; 11 | const THREAD_STEPS: u64 = NUM_STEPS / NUM_THREADS; 12 | const STEP: f64 = 1.0 / NUM_STEPS as f64; 13 | 14 | let pi: Arc> = Arc::new(Mutex::new(0.0f64)); 15 | 16 | let guards: Vec<_> = (0..NUM_THREADS).map(|i| { 17 | let lower: u64 = THREAD_STEPS *i; 18 | let upper: u64 = THREAD_STEPS * (i+1); 19 | let pi_ref = pi.clone(); 20 | 21 | thread::spawn(move || { 22 | for j in lower..upper { 23 | let x: f64 = (j as f64 + 0.5) * STEP; 24 | let mut lock = pi_ref.lock().unwrap(); 25 | *lock += 4.0/(1.0 + x*x) * STEP; 26 | } 27 | }) 28 | }).collect(); 29 | 30 | for g in guards { g.join().unwrap(); } 31 | 32 | println!("Pi = {:.10}", *pi.lock().unwrap()); 33 | } -------------------------------------------------------------------------------- /thread4/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::sync::Arc; 3 | use std::thread; 4 | 5 | // This code is editable and runnable! 6 | fn main() { 7 | let mut thread_vec: Vec<_> = Vec::new(); 8 | 9 | let mut movie_reviews: HashMap = HashMap::new(); 10 | movie_reviews.insert(0, "Terminator"); 11 | movie_reviews.insert(1, "Lord of the Rings"); 12 | movie_reviews.insert(2, "Rambo"); 13 | movie_reviews.insert(3, "Die Hard"); 14 | 15 | // this is a atomic refer counter 16 | // if the ref counter gets 0, the hashmap can get destroyed 17 | let arc = Arc::new(movie_reviews); 18 | 19 | for i in 0..4 { 20 | let arc1 = arc.clone(); 21 | 22 | let child = thread::spawn(move || { 23 | println!("{}", arc1[&(i as u8)]); 24 | }); 25 | 26 | thread_vec.push(child); 27 | } 28 | 29 | for handle in thread_vec { 30 | handle.join().unwrap(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /traits/src/main.rs: -------------------------------------------------------------------------------- 1 | trait Polygon { 2 | // Static method signature; `Self` refers to the implementor type 3 | fn new(width: i32, height: i32) -> Self; 4 | 5 | fn area(&self) -> f32; 6 | } 7 | 8 | struct Rectangle { width: i32, height: i32 } 9 | 10 | impl Polygon for Rectangle { 11 | fn new(w: i32, h: i32) -> Rectangle { 12 | Rectangle { width: w, height: h } 13 | } 14 | 15 | fn area(&self) -> f32 { 16 | return (self.width * self.height) as f32; 17 | } 18 | } 19 | 20 | struct Triangle { width: i32, height: i32 } 21 | 22 | impl Polygon for Triangle { 23 | fn new(w: i32, h: i32) -> Triangle { 24 | Triangle { width: w, height: h } 25 | } 26 | 27 | fn area(&self) -> f32 { 28 | return self.width as f32 * self.height as f32 / 2.0; 29 | } 30 | } 31 | 32 | fn main() { 33 | let r: Rectangle = Polygon::new(2, 3); 34 | println!("{}", r.area()); 35 | 36 | let t: Triangle = Triangle::new(2, 3); 37 | println!("{}", t.area()); 38 | } 39 | -------------------------------------------------------------------------------- /tree/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | use std::collections::VecDeque; 3 | 4 | #[derive(Debug)] 5 | struct NodeInfo<'a,T: 'a + Debug> { 6 | depth: u32, 7 | iter: &'a Tree, 8 | } 9 | 10 | impl<'a,T: 'a + Debug> NodeInfo<'a,T> { 11 | fn new(t: u32, it: &'a Tree) -> Self { NodeInfo { depth: t, iter: it, } } 12 | } 13 | 14 | #[derive(Debug)] 15 | struct Tree { 16 | data: T, 17 | children: Vec>, 18 | } 19 | 20 | impl Tree { 21 | fn new(t: T, c: Vec>) -> Self { Tree { data: t, children: c, } } 22 | fn leaf(t: T) -> Self { Tree { data: t, children: vec![], } } 23 | } 24 | 25 | // Note that path elements are listed backwards (right-to-left) because we pop 26 | // them off the end. 27 | fn seek_path(t: &Tree, mut path: Vec) -> &Tree { 28 | if let Some(index) = path.pop() { 29 | seek_path(&t.children[index], path) 30 | } else { 31 | t 32 | } 33 | } 34 | 35 | fn print_tree(t: &Tree) { 36 | let mut q: VecDeque> = VecDeque::new(); 37 | let mut depth_old: u32 = 0; 38 | 39 | q.push_back(NodeInfo::new(depth_old, t)); 40 | 41 | while let Some(mut u) = q.pop_front() { 42 | if u.depth > depth_old { 43 | println!(""); 44 | print!("{:?}", u.iter.data); 45 | print!(" "); 46 | } 47 | else { 48 | print!("{:?}", u.iter.data); 49 | print!(" "); 50 | } 51 | 52 | depth_old = u.depth; 53 | u.depth += 1; 54 | 55 | for kid in u.iter.children.iter() { 56 | q.push_back(NodeInfo::new(u.depth, kid)); 57 | } 58 | } 59 | 60 | println!(""); 61 | } 62 | 63 | fn main() { 64 | let t = Tree::new("a", vec![Tree::leaf("b"), 65 | Tree::leaf("c"), 66 | Tree::new("d", vec![Tree::leaf("e")])]); 67 | print_tree(&t); 68 | 69 | println!["{:?}", seek_path(&t, vec![0usize])]; 70 | println!["{:?}", seek_path(&t, vec![2usize])]; 71 | println!["{:?}", seek_path(&t, vec![0usize, 2usize])]; 72 | } 73 | -------------------------------------------------------------------------------- /vector/src/main.rs: -------------------------------------------------------------------------------- 1 | fn create1() -> Vec<&'static str> { 2 | let mut m = vec![]; 3 | for n in 0..10 { 4 | m.push("hello"); 5 | } 6 | m.clone() 7 | } 8 | 9 | fn create2(t: &str) -> Vec<&str> { 10 | let mut m = vec![]; 11 | for n in 0..10 { 12 | m.push(t); 13 | } 14 | m.clone() 15 | } 16 | 17 | fn create3(t: &str) -> Vec<&str> { 18 | vec![t; 10] 19 | } 20 | 21 | fn main() { 22 | let mut u = create1(); 23 | 24 | for n in u.iter() { 25 | println!("{}", n); 26 | } 27 | 28 | let mut v = create2("hello"); 29 | 30 | for n in v.iter() { 31 | println!("{}", n); 32 | } 33 | 34 | let w = create3("hello"); 35 | for n in &w { 36 | println!("{}", n); 37 | } 38 | } --------------------------------------------------------------------------------