added more examples
This commit is contained in:
parent
c1e100650c
commit
a7536995cc
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
/target
|
/target
|
||||||
|
hello.txt
|
||||||
|
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -71,7 +71,7 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rusty-playground"
|
name = "rustyplayground"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rand",
|
"rand",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rusty-playground"
|
name = "rustyplayground"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["aj <andrewjpack@gmail.com>"]
|
authors = ["aj <andrewjpack@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
62
src/collections.rs
Normal file
62
src/collections.rs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
// tuples and arrays
|
||||||
|
// both stack-based
|
||||||
|
pub fn compound() {
|
||||||
|
let tup = (500, 'a');
|
||||||
|
let (_, second) = tup;
|
||||||
|
println!("tuple: {}/{}", tup.0, second);
|
||||||
|
|
||||||
|
// all of same type, [u8; 4] = 4 u8 types
|
||||||
|
let _arr: [u8; 4] = [1, 2, 3, 4];
|
||||||
|
let repeater = [3; 5]; // broadcasts 5 elements of 3
|
||||||
|
println!("Retrieving from array: {}", repeater[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn vectors() {
|
||||||
|
let v: Vec<i32> = Vec::new();
|
||||||
|
let mut v = vec![1, 2, 3, 4];
|
||||||
|
v.push(5);
|
||||||
|
|
||||||
|
let mut v: Vec<_> = v.iter().map(|x| x + 1).collect();
|
||||||
|
|
||||||
|
println!("{:?}", v);
|
||||||
|
println!("2nd element is {}, {}",
|
||||||
|
&v[1], // will crash with index-out-of-bounds
|
||||||
|
v.get(1).unwrap() // get an option to handle gracefully
|
||||||
|
);
|
||||||
|
|
||||||
|
for i in &mut v{
|
||||||
|
*i += 1;
|
||||||
|
println!("item: {}", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hash() {
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
|
||||||
|
map.insert("a".to_string(), 5);
|
||||||
|
|
||||||
|
map.insert("b".to_string(), 6);
|
||||||
|
map.insert("b".to_string(), 7); // overwrites
|
||||||
|
|
||||||
|
// map.insert("c".to_string(), 10);
|
||||||
|
map.entry("c".to_string()).or_insert(8);
|
||||||
|
|
||||||
|
println!("{:?}", map);
|
||||||
|
|
||||||
|
for (key, val) in map {
|
||||||
|
println!("{}: {}", key, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
let text = "hello world wonderful world";
|
||||||
|
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
|
||||||
|
for word in text.split_whitespace() {
|
||||||
|
let count = map.entry(word).or_insert(0);
|
||||||
|
*count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{:?}", map);
|
||||||
|
}
|
@ -13,6 +13,7 @@ mod iterate {
|
|||||||
impl Iterator for Counter {
|
impl Iterator for Counter {
|
||||||
type Item = u32;
|
type Item = u32;
|
||||||
|
|
||||||
|
/// Get next item from the iterator
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
if self.count < 5 {
|
if self.count < 5 {
|
||||||
self.count += 1;
|
self.count += 1;
|
||||||
|
28
src/lib.rs
Normal file
28
src/lib.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//! Crate documentation
|
||||||
|
|
||||||
|
/// Print hello world to the screen
|
||||||
|
/// # Title
|
||||||
|
pub fn print_hello(){
|
||||||
|
println!("Hello World!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return sum of input
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// let z = rustyplayground::add(1, 2);
|
||||||
|
///
|
||||||
|
/// assert_eq!(3, z)
|
||||||
|
/// ```
|
||||||
|
pub fn add(x: isize, y: isize) -> isize {
|
||||||
|
x + y
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod new_mod {
|
||||||
|
//! # Documented module
|
||||||
|
//!
|
||||||
|
|
||||||
|
pub fn fun() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
35
src/lifetimes.rs
Normal file
35
src/lifetimes.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
// declare lifetime after function name like generic type
|
||||||
|
// both parameters have same lifetime and must be alive when returned
|
||||||
|
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
|
||||||
|
if x.len() > y.len() {
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// doesn't change lifetimes of parameters, just annotates enough
|
||||||
|
// that the compiler can reject stuff that won't work
|
||||||
|
|
||||||
|
// structs can have reference members
|
||||||
|
// annotate with lifetimes to ensure struct doesn't outlive reference
|
||||||
|
struct ImportantExcerpt<'a> {
|
||||||
|
part: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
// generic types, trait bounds and lifetimes
|
||||||
|
fn longest_with_an_announcement<'a, T>(
|
||||||
|
x: &'a str,
|
||||||
|
y: &'a str,
|
||||||
|
ann: T,
|
||||||
|
) -> &'a str
|
||||||
|
where
|
||||||
|
T: Display,
|
||||||
|
{
|
||||||
|
println!("Announcement! {}", ann);
|
||||||
|
if x.len() > y.len() {
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
y
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,20 @@ macro_rules! log {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! simple_vec {
|
||||||
|
// comma is literal, comma indicates zero or more
|
||||||
|
( $( $x:expr ),* ) => {
|
||||||
|
{
|
||||||
|
let mut temp_vec = Vec::new();
|
||||||
|
$(
|
||||||
|
temp_vec.push($x);
|
||||||
|
)*
|
||||||
|
temp_vec
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! expr_stringer {
|
macro_rules! expr_stringer {
|
||||||
// This macro takes an expression of type `expr` and prints
|
// This macro takes an expression of type `expr` and prints
|
||||||
|
178
src/main.rs
178
src/main.rs
@ -1,20 +1,32 @@
|
|||||||
use std::io;
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{self, Read, ErrorKind};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
// use rustyplayground;
|
||||||
|
|
||||||
mod iterate;
|
mod iterate;
|
||||||
mod macros;
|
mod macros;
|
||||||
|
mod structs;
|
||||||
|
mod collections;
|
||||||
|
mod threads;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
basics();
|
// rustyplayground::print_hello();
|
||||||
compare();
|
// basics();
|
||||||
loops();
|
// compare();
|
||||||
vars();
|
// loops();
|
||||||
compound();
|
// vars();
|
||||||
|
// collections::compound();
|
||||||
|
// collections::vectors();
|
||||||
|
collections::hash();
|
||||||
|
threads::start_threads();
|
||||||
|
threads::thread_channel();
|
||||||
|
|
||||||
println!("testing returns: {}", returning(2));
|
// println!("testing returns: {}", returning(2));
|
||||||
strings();
|
// strings();
|
||||||
nullables();
|
// nullables();
|
||||||
|
|
||||||
|
nested_error_matching();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn basics() {
|
fn basics() {
|
||||||
@ -47,9 +59,9 @@ fn basics() {
|
|||||||
let r_num = rand::thread_rng().gen_range(1, 101);
|
let r_num = rand::thread_rng().gen_range(1, 101);
|
||||||
println!("random number: {}", r_num);
|
println!("random number: {}", r_num);
|
||||||
|
|
||||||
let vec = build_vector3(1, 2, 3);
|
let vec = structs::build_vector3(1, 2, 3);
|
||||||
println!("Vector: {}/{}/{}", vec.x, vec.y, vec.z);
|
println!("Vector: {}/{}/{}", vec.x, vec.y, vec.z);
|
||||||
let vec2 = update_x(vec);
|
let vec2 = structs::update_x(vec);
|
||||||
println!("Vector2: {:#?}", vec2)
|
println!("Vector2: {:#?}", vec2)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,16 +122,6 @@ fn vars() {
|
|||||||
let _f = 2.0; // defaults to 64 bit
|
let _f = 2.0; // defaults to 64 bit
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compound() {
|
|
||||||
let tup = (500, 'a');
|
|
||||||
let (_, second) = tup;
|
|
||||||
println!("tuple: {}/{}", tup.0, second);
|
|
||||||
|
|
||||||
let _arr: [u8; 4] = [1, 2, 3, 4];
|
|
||||||
let repeater = [3; 5]; // stretches to 5 elements of 3
|
|
||||||
println!("Retrieving from array: {}", repeater[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn returning(input: i32) -> i32 {
|
fn returning(input: i32) -> i32 {
|
||||||
let _stuff = 0;
|
let _stuff = 0;
|
||||||
|
|
||||||
@ -132,51 +134,28 @@ fn returning(input: i32) -> i32 {
|
|||||||
|
|
||||||
fn strings() {
|
fn strings() {
|
||||||
let mut s = String::from("hello");
|
let mut s = String::from("hello");
|
||||||
|
let s2 = "world!".to_string();
|
||||||
|
let s3 = String::from("hello");
|
||||||
|
|
||||||
|
// cannot [] index strings due to utf-8 encoding
|
||||||
|
|
||||||
s.push_str(", world!");
|
s.push_str(", world!");
|
||||||
println!("Sliced: {}", &s[4..8]);
|
println!("Sliced: {}", &s[4..8]); // slice
|
||||||
}
|
println!("Appended: {}", s3 + " 2"); // takes ownership of s3
|
||||||
|
println!("{}",
|
||||||
|
format!("{} {}", s, s2)
|
||||||
|
);
|
||||||
|
|
||||||
#[derive(Debug)]
|
let s4 = "abcd".to_string();
|
||||||
struct Vector3 {
|
for i in s4.chars() {
|
||||||
x: i32,
|
println!("{}", i);
|
||||||
y: i32,
|
|
||||||
z: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Vector3 {
|
|
||||||
fn dot(&self, other: &Vector3) -> i32 {
|
|
||||||
self.x * other.x
|
|
||||||
+
|
|
||||||
self.y * other.y
|
|
||||||
+
|
|
||||||
self.z * other.z
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn build_vector3(x: i32, y: i32, z: i32) -> Vector3 {
|
for i in s4.bytes() {
|
||||||
Vector3 {
|
println!("{}", i);
|
||||||
x, y, z
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_x(vec: Vector3) -> Vector3 {
|
|
||||||
Vector3 {
|
|
||||||
x: 5,
|
|
||||||
..vec
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ColourChannel {
|
|
||||||
Red,
|
|
||||||
Green,
|
|
||||||
Blue
|
|
||||||
}
|
|
||||||
|
|
||||||
enum IpAddr {
|
|
||||||
V4(u8, u8, u8, u8),
|
|
||||||
V6(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
fn nullables() {
|
fn nullables() {
|
||||||
let _some_number = Some(5);
|
let _some_number = Some(5);
|
||||||
let _some_string = Some("a string");
|
let _some_string = Some("a string");
|
||||||
@ -184,7 +163,71 @@ fn nullables() {
|
|||||||
let _absent_number: Option<i32> = None;
|
let _absent_number: Option<i32> = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn nested_error_matching() {
|
||||||
|
let f = File::open("hello.txt");
|
||||||
|
|
||||||
|
// .unwrap() get inner value or panic
|
||||||
|
// .expect() as above but with custom error message
|
||||||
|
|
||||||
|
let f = match f {
|
||||||
|
Ok(file) => file,
|
||||||
|
Err(error) => match error.kind() {
|
||||||
|
ErrorKind::NotFound => match File::create("hello.txt") {
|
||||||
|
Ok(fc) => fc,
|
||||||
|
Err(e) => panic!("Problem creating the file: {:?}", e),
|
||||||
|
},
|
||||||
|
other_error => {
|
||||||
|
panic!("Problem opening the file: {:?}", other_error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let f = File::open("hello.txt").unwrap_or_else(|error| {
|
||||||
|
if error.kind() == ErrorKind::NotFound {
|
||||||
|
File::create("hello.txt").unwrap_or_else(|error| {
|
||||||
|
panic!("Problem creating the file: {:?}", error);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
panic!("Problem opening the file: {:?}", error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_err() -> Result<String, io::Error> {
|
||||||
|
let f = File::open("hello.txt");
|
||||||
|
|
||||||
|
let mut f = match f {
|
||||||
|
Ok(file) => file,
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut s = String::new();
|
||||||
|
|
||||||
|
match f.read_to_string(&mut s) {
|
||||||
|
Ok(_) => Ok(s),
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_err_operator() -> Result<String, io::Error> {
|
||||||
|
let mut f = File::open("hello.txt")?;
|
||||||
|
let mut s = String::new();
|
||||||
|
f.read_to_string(&mut s)?; // continue if ok, return error if not, convert to return type if required
|
||||||
|
Ok(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_err_operator_shorter() -> Result<String, io::Error> {
|
||||||
|
|
||||||
|
// can also be done with fs::read_to_string()
|
||||||
|
|
||||||
|
let mut s = String::new();
|
||||||
|
File::open("hello.txt")?.read_to_string(&mut s)?; // continue if ok, return error if not, convert to return type if required
|
||||||
|
Ok(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
// #[warn(unused_imports)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -192,4 +235,21 @@ mod tests {
|
|||||||
fn test1() {
|
fn test1() {
|
||||||
assert_eq!(2, 1 + 1);
|
assert_eq!(2, 1 + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[ignore]
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "index out of bounds")] // check that panic message is substring of actual
|
||||||
|
fn test_panic() {
|
||||||
|
let arr = vec![1, 2, 3];
|
||||||
|
arr[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_result() -> Result<(), String> {
|
||||||
|
if 2 + 2 == 4 {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err("Error".to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
11
src/pointers.rs
Normal file
11
src/pointers.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
// indireaction of box lets list be a fixed size
|
||||||
|
enum List {
|
||||||
|
Cons(i32, Box<List>),
|
||||||
|
Nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn box_ptr() {
|
||||||
|
let b = Box::new(5); // implements deref and drop
|
||||||
|
println!("b = {}", b);
|
||||||
|
}
|
84
src/structs.rs
Normal file
84
src/structs.rs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// and enums
|
||||||
|
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
pub trait Euclidean {
|
||||||
|
fn cross();
|
||||||
|
fn magnitude() {
|
||||||
|
println!("Hello World");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Vector3 {
|
||||||
|
pub x: i32,
|
||||||
|
pub y: i32,
|
||||||
|
pub z: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Vector3 {
|
||||||
|
fn dot(&self, other: &Vector3) -> i32 {
|
||||||
|
self.x * other.x
|
||||||
|
+
|
||||||
|
self.y * other.y
|
||||||
|
+
|
||||||
|
self.z * other.z
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Euclidean for Vector3 {
|
||||||
|
fn cross() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIELD INIT SHORTHAND
|
||||||
|
pub fn build_vector3(x: i32, y: i32, z: i32) -> Vector3 {
|
||||||
|
Vector3 {
|
||||||
|
x, y, z
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// STRUCT UPDATE SYNTAX
|
||||||
|
pub fn update_x(vec: Vector3) -> Vector3 {
|
||||||
|
Vector3 {
|
||||||
|
x: 5,
|
||||||
|
..vec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// use trait as a parameter type
|
||||||
|
pub fn compound_mag(x: &impl Euclidean,
|
||||||
|
y: &(impl Euclidean + Display)) // multiple required traits
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// above is sugar for below, restrictions on generic types
|
||||||
|
pub fn compound_mag_long<T: Euclidean + Display>(x: &T)
|
||||||
|
-> impl Display // specify just traits of a return type
|
||||||
|
{
|
||||||
|
5 // for display trait
|
||||||
|
}
|
||||||
|
|
||||||
|
// use where for easier reading
|
||||||
|
pub fn compound_mag_where<T>(x: &T)
|
||||||
|
where T: Euclidean + Display {
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ColourChannel {
|
||||||
|
Red,
|
||||||
|
Green,
|
||||||
|
Blue
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum IpAddr {
|
||||||
|
V4(u8, u8, u8, u8),
|
||||||
|
V6(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
// can add methods to enums as well
|
||||||
|
impl IpAddr {
|
||||||
|
fn print(&self) {
|
||||||
|
println!("{:?}", self);
|
||||||
|
}
|
||||||
|
}
|
57
src/threads.rs
Normal file
57
src/threads.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::sync::mpsc;
|
||||||
|
|
||||||
|
// 1:1 threads
|
||||||
|
pub fn start_threads() {
|
||||||
|
|
||||||
|
let v = vec![1, 2, 3, 4];
|
||||||
|
|
||||||
|
// use move to transfer data into new thread
|
||||||
|
let handle = thread::spawn(move || {
|
||||||
|
println!("{:?}", v);
|
||||||
|
for i in v {
|
||||||
|
println!("{} from separate thread", i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
handle.join().unwrap();
|
||||||
|
thread::sleep(Duration::from_millis(5));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn thread_channel() {
|
||||||
|
|
||||||
|
let (tx, rx) = mpsc::channel();
|
||||||
|
|
||||||
|
// use move to transfer data into new thread
|
||||||
|
thread::spawn(move || {
|
||||||
|
tx.send("Hello message!".to_string()).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
let rec = rx.recv().unwrap();
|
||||||
|
println!("{}", rec);
|
||||||
|
|
||||||
|
// MULTIPLE
|
||||||
|
|
||||||
|
let (tx, rx) = mpsc::channel();
|
||||||
|
|
||||||
|
// use move to transfer data into new thread
|
||||||
|
thread::spawn(move || {
|
||||||
|
let vals = vec![
|
||||||
|
String::from("h"),
|
||||||
|
String::from("e"),
|
||||||
|
String::from("l"),
|
||||||
|
String::from("l"),
|
||||||
|
String::from("o"),
|
||||||
|
];
|
||||||
|
|
||||||
|
for val in vals {
|
||||||
|
tx.send(val).unwrap();
|
||||||
|
thread::sleep(Duration::from_millis(200));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for rec in rx {
|
||||||
|
println!("{}", rec);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user