Data Structures#
Rust’s standard library covers the most common containers, all generic and allocation-aware.
Arrays#
Fixed length, stack-allocated.
let xs: [i32; 5] = [1, 2, 3, 4, 5];
let zeros = [0u8; 1024];
Slices#
A view into contiguous memory. &[T] is read-only, &mut [T] is
writable.
let xs = vec![1, 2, 3, 4];
let sub: &[i32] = &xs[1..3];
Vec#
A growable, heap-allocated array.
let mut v: Vec<i32> = Vec::new();
v.push(1);
v.extend([2, 3, 4]);
let n = v.len();
Strings#
String owns; &str borrows. Both are guaranteed UTF-8.
let owned: String = String::from("hello");
let borrowed: &str = &owned;
HashMap / Set#
use std::collections::{HashMap, HashSet};
let mut counts: HashMap<&str, i32> = HashMap::new();
*counts.entry("a").or_insert(0) += 1;
let s: HashSet<i32> = HashSet::from([1, 2, 3]);
Structs#
struct Person {
name: String,
age: u32,
}
impl Person {
fn new(name: &str, age: u32) -> Self {
Self { name: name.into(), age }
}
}
Enums#
Tagged unions; the foundation of Option and Result.
enum Shape {
Circle(f64),
Rect { w: f64, h: f64 },
Square(f64),
}
Option and Result#
fn first_word(s: &str) -> Option<&str> {
s.split_whitespace().next()
}
fn parse(s: &str) -> Result<i32, std::num::ParseIntError> {
s.parse::<i32>()
}
Tabular (third-party)#
polars is the operator’s default for tabular workloads in
Rust. Lazy or eager columnar DataFrames built on Apache Arrow;
faster than pandas on most operations and at home in both
single-machine and streaming pipelines. Third-party
(cargo add polars), not in the standard library.
Series#
A Series is a 1-D labelled column of one dtype. Construct
from a name and a slice.
use polars::prelude::*;
let s = Series::new("latency_ms".into(), &[10_i64, 20, 30]);
Type-cast to a typed iterator.
let xs: Vec<i64> = s.i64()?.into_no_null_iter().collect();
Aggregations are method calls.
let mean = s.mean(); // Option<f64>
let max = s.max::<i64>()?;
DataFrame#
A DataFrame is a 2-D labelled table; each column is a
Series. Construct from columns with the df! macro.
use polars::prelude::*;
let df = df!(
"host" => &["a", "b", "c"],
"port" => &[80_i64, 443, 22],
"open" => &[true, true, false],
)?;
Read from CSV (eager).
let df = CsvReadOptions::default()
.with_has_header(true)
.try_into_reader_with_file_path(Some("hosts.csv".into()))?
.finish()?;
Lazy scan + filter + collect; the query planner pushes the filter to the scanner.
let df = LazyCsvReader::new("hosts.csv")
.with_has_header(true)
.finish()?
.filter(col("open").eq(true))
.select([col("host"), col("port")])
.collect()?;
Filter rows on a boolean mask.
let opened = df.clone().lazy().filter(col("open").eq(true)).collect()?;
Add a computed column.
let with_https = df.clone().lazy()
.with_column(col("port").eq(443).alias("is_https"))
.collect()?;
Group and aggregate.
let by_open = df.clone().lazy()
.group_by([col("open")])
.agg([col("port").mean().alias("avg_port")])
.collect()?;
Join two DataFrames on a key.
let merged = df.clone().lazy()
.join(scans.lazy(), [col("host")], [col("host")], JoinArgs::new(JoinType::Left))
.collect()?;
Pivot long to wide.
use polars::prelude::*;
let wide = pivot::pivot(&events, ["event"], Some(["host"]), Some(["count"]), false, None, None)?;
Method surface (everyday)#
Call |
Effect |
|---|---|
|
|
|
Column names. |
|
Per-column dtypes. |
|
First N rows. |
|
Last N rows. |
|
Summary statistics. |
|
Sort by column. |
|
Deduplicate rows. |
|
Drop a column. |
|
Rename a column. |
|
Boolean-mask row filter. |
|
Add or replace a column (lazy). |
|
Split-apply-combine. |
|
SQL-style join. |
I/O#
Reader / writer |
Format |
|---|---|
|
CSV. |
|
Apache Parquet (preferred for large data). |
|
Newline-delimited JSON. |
|
Apache Arrow IPC. |
|
Lazy variants that compose with the query planner. |
The wider Rust tabular / columnar ecosystem. Polars is the operator’s default; the rest are the right tool when the workload is SQL, on-cluster, or interop-first.
Crate |
When to reach for it |
|---|---|
DataFrames built on Arrow; eager and lazy. The default. |
|
The native Rust implementation of the Apache Arrow columnar format. The interchange layer everything else sits on; reach for it directly when building a custom reader / writer. |
|
In-process SQL + DataFrame query engine over Arrow. The right tool when the question reads as SQL or when the operator wants a query planner. |
|
Fast database → Arrow / pandas / polars loader; the fastest path from Postgres / MySQL / SQLite / Oracle into an in-memory DataFrame. |
|
In-process DuckDB bindings; embed an analytical SQL engine inside a Rust binary with zero-copy Arrow interchange. |
|
Standalone Apache Parquet reader / writer; sits beneath polars / datafusion but is the right dependency on its own when the operator only needs columnar I/O. |
References#
DataFrame for the pandas equivalent.
Apache Arrow — the columnar format polars sits on.