std Library Tour

It’s time for a tour of some interesting parts in std.

We will focus on parts we have not otherwise covered.

Collections

Contains a number of valuable data structures. In particular:

  • Vec for storing sequences of values.

  • HashMap for storing key value pairs.

When seeking to optimize code other options may be appropriate.

Entry

Calling .entry() on a HashMap accesses this API and allows for 'insert or update' access.

use std::collections::HashMap;

fn main() {
    let mut map: HashMap<&str, u32> = HashMap::new();
    map.entry("foo").or_insert(1);
    map.entry("bar").or_insert_with(|| {
        let mut value = 1;
        value += 1;
        value
    });
    println!("{:?}", map);
}

PhantomData

Zero-sized types are used to mark things that "act like" they own a T.

These are useful for types which require markers, generics, or use unsafe code.

use std::marker::PhantomData;

struct HttpRequest<ResponseValue> {
    // Eventually returns this type.
    response_value: PhantomData<ResponseValue>,
}

fn main() {}

Command

A process builder, providing fine-grained control over how a new process should be spawned.

Used for interacting with other executables.

use std::process::Command;

fn main() {
    Command::new("ls")
            .args(&["-l", "-a"])
            .spawn()
            .expect("ls command failed to start");
}

Synchronization Primitives

Provides types such a Mutex, RwLock, CondVar, Arc and Barrier s.

use std::sync::Mutex;

fn main() {

    let mut mutex = Mutex::new(0);
    
    // Use a new scope to force a drop.
    {
        let mut val = mutex.get_mut().unwrap();
        *val += 1;
    }
    
    println!("{}", *mutex.lock().unwrap());
}

Read and Write

Generic read and write functionality to files, sockets, buffers, and anything in between.

Also part of std::io::prelude (use std::io::prelude::*).

use std::io::{Read, Write};

fn main() {
    // File, Socket, Vector, ...
    let mut buffer: Vec<u8> = vec![];
    
    buffer.write(b"some bytes").unwrap();
    
    let mut read_in = String::new();
    buffer.as_slice().read_to_string(&mut read_in).unwrap();
    
    println!("{}", read_in);
}

Filesystem Manipulation

Path handling and file manipulation.

use std::fs::{File, canonicalize};
use std::io::Write;

fn main() {
    let mut file = File::create("foo.txt").unwrap();
    file.write_all(b"Hello, world!").unwrap();
    
    let path = canonicalize("foo.txt").unwrap();
        
    let components: Vec<_> = path.components().collect();
    println!("{:?}", components);
}