Arrow Rust Crash Course
Through these projects you will learn what you need to contribute to the Arrow Rust codebase.
Attempt these steps without looking them up first! You'll only learn by trying them yourself.
You're meant to struggle a bit - don't worry! The compiler will help :)
When you're ready for help, many of the instructions link to helpful resources or Rust docs.
Level 0 - Libraries, Tests, Refs
1) Compile the Hello, Cargo! project
2) Create src/lib.rs and add it as a library to Cargo.toml
Solution
3) Add a function to src/lib.rs
which takes an unsigned integer as an argument and returns the sum.
fn add_one(x: u32) -> u32 {
// what are two ways to return a value from this function?
// ...
}
Solution
4) Add a unit test to the bottom of lib.rs
for add_one
- Unit tests validate the internal workings of a module
- Use
assert_eq!
to compare the result with the expected result
Solution
5) Add an integration test for add_one
- This should go into a new file:
tests/integration_test.rs
Solution
- You may get the following compilation error:
error[E0603]: function `add_one` is private
--> tests/integration_test.rs:4:23
|
4 | assert_eq!(adder::add_one(x), x+1);
| ^^^^^^^ private function
- To test this function in
integration_test.rs
, we need to makeadd_one
public.pub fn add_one(x: u32) -> u32
- This emphasizes what integration tests are for!
- Integration tests should validate the public interfaces (inputs and outputs) of a module
- These tests provide confidence that other modules can interact with this module's public interfaces without causing an error
- By proving this, we verify module integration, the inter-operation of multiple modules as a successful whole
6) Modify add_one
to instead update x
in place, with no return value.
- You'll learn more about
mut
, references, and&mut
! - Hint: https://www.educative.io/answers/how-to-use-references-in-rust
Solution
Level 1 - Generics, Traits, Imports
1) Write a function which returns the largest element of a vector of type u32
fn largest(xs: &[u32]) -> u32
- Why should
largest
take a pointer to the list (&[u32]
) instead of the list ([u32]
)?- Consider the size of a pointer versus the size of the list
- Why not a mutable pointer
&mut
?
Solution
2) Modify largest
to return the largest element of a vector of any type
- This one is tricky!
- You'll learn about Generics and
trait
s, specificallyPartialOrd
andCopy
Solution
- Run the same unit tests again, should pass!
- Try changing the unit tests to add together other types: f32, u8, i16, etc.
3) Add a data structure called Ticket
.
Ticket
should have two fields:u32 id
DateTime<UTC> timestamp
- We need to import an external crate:
chrono
- Add
chrono
to yourcargo.toml
under[dependencies]
- Alternatively run
cargo add chrono
from your project root
- Alternatively run
- Importing DateTime and Utc to your file
- Add
Solution
4) Create a unit test ut_largest_ticket
which does the following:
- Creates a vector
tickets
with the following twoTicket
elements:Ticket { id: 1, timestamp: Utc::now() }
Ticket { id: 2, timestamp: Utc::now() + Duration::minutes(30) }
- Passes this
Ticket
vector to thelargest
function. - assert_eq! that the ID of the returned element is
2
.
Solution
- Should fail to compile!
5) The compiler doesn't know how to compare two Ticket
objects yet.
- Add
#[derive(Debug, Eq, Copy, Clone)]
aboveTicket
Solution
6) The compiler needs to be told how to determine if one Ticket
is "larger" than another.
- We'll say that the "largest" ticket should be the one with the later timestamp.
- Implement the
PartialOrd
,Ord
, andPartialEq
traits for theTicket
object. - Traits define behaviors for types.
Solution
7) Run the unit tests again.
- Should pass!
Level 2
- Coming Soon
Option
,trait
,enum