Rust
Waterford Tech Meetup January 2025
Photographer - David Bergin
What?
fn main() {
println!("Hello, world");
}
Rust
Photographer - David Bergin
Why?
Alright so,… Where did it come from?
Walking to the 21st Floor Graydon Pondered…
I wonder if the elevator
code was written in C?
It was probably
another bug with
memory management!
We computer people
couldn’t even make an
elevator that works
without crashing
I know what I’ll do, I’ll create a new programming
language and name it Rust after a fungi that is
overengineered for survival!!
Rust was born as a…
A general purpose programming language built for
performance, reliability and productivity.
Rust focuses on empowerment…
write high-performance, low-level code with guarantees of
safety and reliability.
free devs to focus on building robust applications without
worrying about common pitfalls like memory errors or race
conditions
Empowerment?
• Fearless Concurrency
• Memory Safety
• Modern Syntax
• Cargo Package Manager
• Interoperability
• “Fearless” Refactoring
• Documentation and Community
Rust is…
Typically referred to as a systems level programming language
with an emphasis on memory safety
Systems Programming?
Low-level software that interacts closely with hardware, such as operating systems, drivers,
networking stacks, and embedded systems.
Requires high performance, precise control over resources, and efficient memory management,
making them critical for infrastructure and performance-sensitive applications.
Systems Programming?
• Assembly
• Used for hardware-level programming but lacks abstraction and portability.
• C
• Known for its low-level control and performance but prone to memory safety issues.
• C++
• Adds object-oriented features to C but retains similar risks of unsafe memory usage.
• Go
• Focused on simplicity and concurrency but lacks Rust's fine-grained control over memory.
How do I rust…
rustup.rs
cargo new calc --lib
So….. Memory…..
We need
to talk….
About the stack and the
heap…
We got this!
What is the stack and what
is heap? – The stack
• Both the stack and the heap are parts of
memory available to your code to use at
runtime, but they are structured in different
ways
• The stack stores known, fixed size data such
as integers, booleans and characters
• The stack is last in, first out, pushing to add
and popping to remove
• Working with the stack is very fast!
fn main() {
let first = 22;
let second = 33;
let sum = add(first, second);
println!("the sum of of {first} and {second} are {sum}");
}
fn add(a: i32, b: i32) -> i32 {
return a + b;
}
main()
first – i32 22
second – i32 33
sum – i32 ?
fn main() {
let first = 22;
let second = 33;
let sum = add(first, second);
println!("the sum of of {first} and {second} are {sum}");
}
fn add(a: i32, b: i32) -> i32 {
return a + b;
}
main()
first – i32 22
second – i32 33
sum – i32 ?
add()
a – i32 22
b – i32 33
return address 0x23f
fn main() {
let first = 22;
let second = 33;
let sum = add(first, second);
println!("the sum of of {first} and {second} are {sum}");
}
fn add(a: i32, b: i32) -> i32 {
return a + b;
}
main()
first – i32 22
second – i32 33
sum – i32 55
The Heap
The Heap
// a string could be retrieved from input
// so undefined size at compile time
let s1: String = String::from("hello");
What is memory safety on the stack?
#include <stdio.h>
int main(){
int initial_value = 60;
int items[5] = {1,2,3,4,5};
printf("initial value is %dn", initial_value);
}
What is memory safety on the stack?
Output: initial value is 60
#include <stdio.h>
int main(){
int initial_value = 60;
int items[5] = {1,2,3,4,5};
printf("initial value is %dn", initial_value);
}
What is memory safety on the stack?
#include <stdio.h>
int main(){
int initial_value = 60;
int items[5] = {1,2,3,4,5};
items[5] = 6; // put one too many in items
printf("initial value is %dn", initial_value);
}
What is memory safety? (-fno-stack-protector)
#include <stdio.h>
int main(){
int initial_value = 60;
int items[5] = {1,2,3,4,5};
items[5] = 6; // put one too many in items
printf("initial value is %dn", initial_value);
}
Output: initial value is 6, instead of 60
This all happens on the stack!
What is memory safety? (-fno-stack-protector)
• To make this happen, we have to disable
compile time protections
• It is a simple example to illustrate how
lower level languages can open doors to
bugs
Dynamic memory allocation – The Heap
int main() {
// Dynamically allocate memory for an array of 10 integers
// This all happens on THE HEAP
int *ptr = (int *)malloc(10 * sizeof(int));
if (ptr == NULL) {
printf("Memory allocation failedn");
return -1;
}
// Populate the allocated memory
for (int i = 0; i < 10; i++) {
ptr[i] = i;
printf ("%d", ptr[i]);
}
// Forget to free the allocated memory?
free(ptr); // <-- If this line is missing, causing a MEMORY LEAK
ptr = NULL; // if this line is missing, causes DANGLING POINTER
return 0;
}
“Some of the most infamous cyber events in history – the Morris worm of 1988, the Slammer worm of
2003, the Heartbleed vulnerability in 2014, the Trident exploit of 2016, the Blastpass exploit of 2023 –
were headline-grabbing cyberattacks that caused real-world damage to the systems that society relies on
every day. Underlying all of them is a common root cause: memory safety vulnerabilities.”
Focus on Memory
Safety in Rust
• Three Use Cases:
• Memory Leaks
• Dangling Pointers
• Data Races
Come again?
• Rust is a systems programming language
• It was created with reliability and performance at it’s core
• One of the main facets of this reliability is memory safety
• We have 2 areas of memory where we are concerned
• The Stack and the Heap
• Dynamic allocation of memory can cause issues such as:
• Memory leaks when forgetting to free memory
• Dangling pointers when we forget to nullify pointers
• Data Races: multiple pointers attempting to access data at once can
cause“data races”
• Even the White House is worried, so what makes Rust more
memory safe?
Well to improve performance, Rust does not use
Garbage Collection to manage memory.
(This is also to enable memory restricted use cases)
Rust has… Ownership!
What is Ownership?
JS Example that shows multiple owners…
fn main(){
let s1 = String::from("hello");
let s2 = s1;
println!("{s1}, world");
}
Ownership is a set of rules that govern how a Rust program manages memory
• Each value in Rust has an owner.
• There can only be one owner at a time.
• When the owner goes out of scope, the value will be dropped and memory freed
We will be introduced to the idea of MOVE and BORROW
fn main(){
let s1 = String::from("hello");
let s2 = s1;
println!("{s1}, world");
}
This is compiler output!!!
fn main(){
let s1 = String::from("hello");
let s2 = s1;
println!("{s1}, world");
}
The compiler throws an error because we’ve
moved OWNERSHIP from s1 to s2 and then
attempted to us s1 after that.
Rust invalidates the first variable, it’s known as
a MOVE.
S1 Invalidated
fn main(){
let s1 = String::from("hello");
let s2 = s1;
println!("{s1}, world");
}
This is the a rule of ownership, a value on the heap can only
have one owner
This prevents us creating multiple references to objects on
the heap, thus reducing the possibility of a MEMORY LEAK
S1 Invalidated
This gets even weirder with
functions
Well, weird, from a certain point of view
fn main() {
let s1 = String::from("hello");
let len = calculate_length(s1);
// will get same error here
println!("The length of '{s1}' is {len}.");
}
fn calculate_length(s: String) -> usize {
s.len()
}
fn main() {
let s1 = String::from("hello");
let len = calculate_length(s1);
// will get same error here
println!("The length of '{s1}' is {len}.");
}
fn calculate_length(s: String) -> usize {
s.len()
}
Again, this is compiler output
fn main() {
let s1 = String::from("hello");
let len = calculate_length(s1);
// will get same error here
println!("The length of '{s1}' is {len}.");
}
fn calculate_length(s: String) -> usize {
s.len()
}
We are transferring OWNERSHIP of
“s1”from main to the function we are
calling
When that function ends, ”s” is
DROPPED as it’s new owner is no
longer in scope, even though it is still in
scope in main.
So, we can’t pass a variable to a function and
use it afterwards?
References and
Borrowing
• We must create a REFERENCE and pass that to our function
• And use this REFERENCE to BORROW
• We can create a reference using &
fn main() {
let s1 = String::from("hello");
let len = calculate_length(s1);
// will get same error here
println!("The length of '{s1}' is {len}.");
}
fn calculate_length(s: String) -> usize {
s.len()
}
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);// & HERE!
println!("The length of '{s1}' is {len}.");
}
fn calculate_length(s: &String) -> usize { // & HERE!
s.len() // rust automatically dereferences
}
Passing a reference does not change ownership
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);// & HERE!
println!("The length of '{s1}' is {len}.");
}
fn calculate_length(s: &String) -> usize { // & HERE!
s.len() // rust automatically dereferences
}
We call the action of creating a reference and passing it
around - BORROWING
We cannot edit what we have borrowed, well we can but
not without making changes, but first….
Recap
• Rust enforces a single owner on data stored in the heap
• Reassigning, s2=s1, will MOVE and change ownership,
invalidating the original owner
• This ensures we have no dangling REFERENCES causing
MEMORY LEAKS
• The Rust compiler impressively protects both the stack and the
heap
• We can use REFERENCES to BORROW a value in another
function
• However, these REFERENCES are IMMUTABLE!
Immutability
Why don’t you just marry immutability?
In Rust, everything is immutable by default
Immutability
• Rust enforces immutability by
default, that is, you cannot change,
for example, the value of a variable
• We need to intentionally define a
variable as mutable, that is, we can
change the value of the variable
Mutable References
• References are immutable by default, so the following would
throw a compile error
fn main() {
let mut s = String::from("hello");
change(&s);
}
fn change(some_string: &String) {
some_string.push_str(", world");
}
Mutable References
• To allow editing of our value via reference, we can use mutable
references
fn main() {
let mut s = String::from("hello");
change(&s);
}
fn change(some_string: &String) {
some_string.push_str(", world");
}
fn main() {
let mut s = String::from("hello");
change(&mut s);
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}
Mutable References
• BUT, we cannot have more than 2 simultaneous mutable
references AND the compiler enforces this:
fn main() {
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;
println!("{}, {}", r1, r2);
}
Mutable References
• Disallowing multiple simultaneous references solves our last (for
today…) memory safety concern, data races
• A data race is similar to a race condition and happens when these
three behaviours occur:
• Two or more pointers access the same data at the same time.
• At least one of the pointers is being used to write to the data.
• There’s no mechanism being used to synchronize access to the data.
• Data races cause undefined behaviour and can be difficult to
diagnose and fix when you’re trying to track them down at runtime
Recap
• We’ve seen how the rust compiler can
• Prevent numerous memory safety concerns at compile time
• Even when dealing with dynamically allocated memory in the heap
• That was a slog, some easy slides
Who is using
rust?
The Linux
Kernal
Who is using
rust?
Google
At Google, we have been seeing increased Rust adoption,
especially in our consumer applications and platforms
https://google.github.io/comprehensive-rust/
Who is using
rust?
Android
The transition to memory-safe languages such as Rust as
part of its secure-by-design approach has led to the
percentage of memory-safe vulnerabilities discovered in
Android dropping from 76% to 24% over a period of six years.
Who is using
rust?
GitHub
Who is using
rust?
AWS
Who is using
rust?
YOU, in
lambda ;)
https://rust-lambda.com/
Who is using
rust?
More
https://github.com/omarabid/rust-companies
Snake…. You
should have used
Rust!
DARPA on Rust
https://www.darpa.mil/news-events/2024-07-31a
Questions? (or beer?)

Introduction to Rust - Waterford Tech Meetup 2025

  • 1.
  • 2.
  • 3.
  • 4.
  • 6.
    Alright so,… Wheredid it come from?
  • 7.
    Walking to the21st Floor Graydon Pondered… I wonder if the elevator code was written in C? It was probably another bug with memory management! We computer people couldn’t even make an elevator that works without crashing I know what I’ll do, I’ll create a new programming language and name it Rust after a fungi that is overengineered for survival!!
  • 8.
    Rust was bornas a… A general purpose programming language built for performance, reliability and productivity.
  • 9.
    Rust focuses onempowerment… write high-performance, low-level code with guarantees of safety and reliability. free devs to focus on building robust applications without worrying about common pitfalls like memory errors or race conditions
  • 10.
    Empowerment? • Fearless Concurrency •Memory Safety • Modern Syntax • Cargo Package Manager • Interoperability • “Fearless” Refactoring • Documentation and Community
  • 11.
    Rust is… Typically referredto as a systems level programming language with an emphasis on memory safety
  • 12.
    Systems Programming? Low-level softwarethat interacts closely with hardware, such as operating systems, drivers, networking stacks, and embedded systems. Requires high performance, precise control over resources, and efficient memory management, making them critical for infrastructure and performance-sensitive applications.
  • 13.
    Systems Programming? • Assembly •Used for hardware-level programming but lacks abstraction and portability. • C • Known for its low-level control and performance but prone to memory safety issues. • C++ • Adds object-oriented features to C but retains similar risks of unsafe memory usage. • Go • Focused on simplicity and concurrency but lacks Rust's fine-grained control over memory.
  • 14.
    How do Irust… rustup.rs
  • 15.
  • 16.
  • 17.
    We need to talk…. Aboutthe stack and the heap… We got this!
  • 18.
    What is thestack and what is heap? – The stack • Both the stack and the heap are parts of memory available to your code to use at runtime, but they are structured in different ways • The stack stores known, fixed size data such as integers, booleans and characters • The stack is last in, first out, pushing to add and popping to remove • Working with the stack is very fast!
  • 19.
    fn main() { letfirst = 22; let second = 33; let sum = add(first, second); println!("the sum of of {first} and {second} are {sum}"); } fn add(a: i32, b: i32) -> i32 { return a + b; } main() first – i32 22 second – i32 33 sum – i32 ?
  • 20.
    fn main() { letfirst = 22; let second = 33; let sum = add(first, second); println!("the sum of of {first} and {second} are {sum}"); } fn add(a: i32, b: i32) -> i32 { return a + b; } main() first – i32 22 second – i32 33 sum – i32 ? add() a – i32 22 b – i32 33 return address 0x23f
  • 21.
    fn main() { letfirst = 22; let second = 33; let sum = add(first, second); println!("the sum of of {first} and {second} are {sum}"); } fn add(a: i32, b: i32) -> i32 { return a + b; } main() first – i32 22 second – i32 33 sum – i32 55
  • 22.
  • 23.
  • 24.
    // a stringcould be retrieved from input // so undefined size at compile time let s1: String = String::from("hello");
  • 25.
    What is memorysafety on the stack? #include <stdio.h> int main(){ int initial_value = 60; int items[5] = {1,2,3,4,5}; printf("initial value is %dn", initial_value); }
  • 26.
    What is memorysafety on the stack? Output: initial value is 60 #include <stdio.h> int main(){ int initial_value = 60; int items[5] = {1,2,3,4,5}; printf("initial value is %dn", initial_value); }
  • 27.
    What is memorysafety on the stack? #include <stdio.h> int main(){ int initial_value = 60; int items[5] = {1,2,3,4,5}; items[5] = 6; // put one too many in items printf("initial value is %dn", initial_value); }
  • 28.
    What is memorysafety? (-fno-stack-protector) #include <stdio.h> int main(){ int initial_value = 60; int items[5] = {1,2,3,4,5}; items[5] = 6; // put one too many in items printf("initial value is %dn", initial_value); } Output: initial value is 6, instead of 60 This all happens on the stack!
  • 29.
    What is memorysafety? (-fno-stack-protector) • To make this happen, we have to disable compile time protections • It is a simple example to illustrate how lower level languages can open doors to bugs
  • 30.
    Dynamic memory allocation– The Heap int main() { // Dynamically allocate memory for an array of 10 integers // This all happens on THE HEAP int *ptr = (int *)malloc(10 * sizeof(int)); if (ptr == NULL) { printf("Memory allocation failedn"); return -1; } // Populate the allocated memory for (int i = 0; i < 10; i++) { ptr[i] = i; printf ("%d", ptr[i]); } // Forget to free the allocated memory? free(ptr); // <-- If this line is missing, causing a MEMORY LEAK ptr = NULL; // if this line is missing, causes DANGLING POINTER return 0; }
  • 31.
    “Some of themost infamous cyber events in history – the Morris worm of 1988, the Slammer worm of 2003, the Heartbleed vulnerability in 2014, the Trident exploit of 2016, the Blastpass exploit of 2023 – were headline-grabbing cyberattacks that caused real-world damage to the systems that society relies on every day. Underlying all of them is a common root cause: memory safety vulnerabilities.”
  • 32.
    Focus on Memory Safetyin Rust • Three Use Cases: • Memory Leaks • Dangling Pointers • Data Races
  • 33.
    Come again? • Rustis a systems programming language • It was created with reliability and performance at it’s core • One of the main facets of this reliability is memory safety • We have 2 areas of memory where we are concerned • The Stack and the Heap • Dynamic allocation of memory can cause issues such as: • Memory leaks when forgetting to free memory • Dangling pointers when we forget to nullify pointers • Data Races: multiple pointers attempting to access data at once can cause“data races” • Even the White House is worried, so what makes Rust more memory safe?
  • 34.
    Well to improveperformance, Rust does not use Garbage Collection to manage memory. (This is also to enable memory restricted use cases)
  • 35.
  • 36.
    What is Ownership? JSExample that shows multiple owners…
  • 37.
    fn main(){ let s1= String::from("hello"); let s2 = s1; println!("{s1}, world"); } Ownership is a set of rules that govern how a Rust program manages memory • Each value in Rust has an owner. • There can only be one owner at a time. • When the owner goes out of scope, the value will be dropped and memory freed We will be introduced to the idea of MOVE and BORROW
  • 38.
    fn main(){ let s1= String::from("hello"); let s2 = s1; println!("{s1}, world"); } This is compiler output!!!
  • 39.
    fn main(){ let s1= String::from("hello"); let s2 = s1; println!("{s1}, world"); } The compiler throws an error because we’ve moved OWNERSHIP from s1 to s2 and then attempted to us s1 after that. Rust invalidates the first variable, it’s known as a MOVE. S1 Invalidated
  • 40.
    fn main(){ let s1= String::from("hello"); let s2 = s1; println!("{s1}, world"); } This is the a rule of ownership, a value on the heap can only have one owner This prevents us creating multiple references to objects on the heap, thus reducing the possibility of a MEMORY LEAK S1 Invalidated
  • 41.
    This gets evenweirder with functions Well, weird, from a certain point of view
  • 42.
    fn main() { lets1 = String::from("hello"); let len = calculate_length(s1); // will get same error here println!("The length of '{s1}' is {len}."); } fn calculate_length(s: String) -> usize { s.len() }
  • 43.
    fn main() { lets1 = String::from("hello"); let len = calculate_length(s1); // will get same error here println!("The length of '{s1}' is {len}."); } fn calculate_length(s: String) -> usize { s.len() } Again, this is compiler output
  • 44.
    fn main() { lets1 = String::from("hello"); let len = calculate_length(s1); // will get same error here println!("The length of '{s1}' is {len}."); } fn calculate_length(s: String) -> usize { s.len() } We are transferring OWNERSHIP of “s1”from main to the function we are calling When that function ends, ”s” is DROPPED as it’s new owner is no longer in scope, even though it is still in scope in main.
  • 45.
    So, we can’tpass a variable to a function and use it afterwards?
  • 46.
    References and Borrowing • Wemust create a REFERENCE and pass that to our function • And use this REFERENCE to BORROW • We can create a reference using &
  • 47.
    fn main() { lets1 = String::from("hello"); let len = calculate_length(s1); // will get same error here println!("The length of '{s1}' is {len}."); } fn calculate_length(s: String) -> usize { s.len() } fn main() { let s1 = String::from("hello"); let len = calculate_length(&s1);// & HERE! println!("The length of '{s1}' is {len}."); } fn calculate_length(s: &String) -> usize { // & HERE! s.len() // rust automatically dereferences } Passing a reference does not change ownership
  • 48.
    fn main() { lets1 = String::from("hello"); let len = calculate_length(&s1);// & HERE! println!("The length of '{s1}' is {len}."); } fn calculate_length(s: &String) -> usize { // & HERE! s.len() // rust automatically dereferences } We call the action of creating a reference and passing it around - BORROWING We cannot edit what we have borrowed, well we can but not without making changes, but first….
  • 49.
    Recap • Rust enforcesa single owner on data stored in the heap • Reassigning, s2=s1, will MOVE and change ownership, invalidating the original owner • This ensures we have no dangling REFERENCES causing MEMORY LEAKS • The Rust compiler impressively protects both the stack and the heap • We can use REFERENCES to BORROW a value in another function • However, these REFERENCES are IMMUTABLE!
  • 50.
    Immutability Why don’t youjust marry immutability? In Rust, everything is immutable by default
  • 51.
    Immutability • Rust enforcesimmutability by default, that is, you cannot change, for example, the value of a variable • We need to intentionally define a variable as mutable, that is, we can change the value of the variable
  • 52.
    Mutable References • Referencesare immutable by default, so the following would throw a compile error fn main() { let mut s = String::from("hello"); change(&s); } fn change(some_string: &String) { some_string.push_str(", world"); }
  • 53.
    Mutable References • Toallow editing of our value via reference, we can use mutable references fn main() { let mut s = String::from("hello"); change(&s); } fn change(some_string: &String) { some_string.push_str(", world"); } fn main() { let mut s = String::from("hello"); change(&mut s); } fn change(some_string: &mut String) { some_string.push_str(", world"); }
  • 54.
    Mutable References • BUT,we cannot have more than 2 simultaneous mutable references AND the compiler enforces this: fn main() { let mut s = String::from("hello"); let r1 = &mut s; let r2 = &mut s; println!("{}, {}", r1, r2); }
  • 55.
    Mutable References • Disallowingmultiple simultaneous references solves our last (for today…) memory safety concern, data races • A data race is similar to a race condition and happens when these three behaviours occur: • Two or more pointers access the same data at the same time. • At least one of the pointers is being used to write to the data. • There’s no mechanism being used to synchronize access to the data. • Data races cause undefined behaviour and can be difficult to diagnose and fix when you’re trying to track them down at runtime
  • 56.
    Recap • We’ve seenhow the rust compiler can • Prevent numerous memory safety concerns at compile time • Even when dealing with dynamically allocated memory in the heap • That was a slog, some easy slides
  • 57.
  • 58.
    Who is using rust? Google AtGoogle, we have been seeing increased Rust adoption, especially in our consumer applications and platforms https://google.github.io/comprehensive-rust/
  • 59.
    Who is using rust? Android Thetransition to memory-safe languages such as Rust as part of its secure-by-design approach has led to the percentage of memory-safe vulnerabilities discovered in Android dropping from 76% to 24% over a period of six years.
  • 60.
  • 61.
  • 62.
    Who is using rust? YOU,in lambda ;) https://rust-lambda.com/
  • 63.
  • 64.
  • 65.
  • 67.