Try Live
Add Docs
Rankings
Pricing
Docs
Install
Install
Docs
Pricing
More...
More...
Try Live
Rankings
Enterprise
Create API Key
Add Docs
Rust
https://github.com/rust-lang/rust
Admin
Empowering everyone to build reliable and efficient software.
Tokens:
1,122,167
Snippets:
4,917
Trust Score:
9
Update:
2 weeks ago
Context
Skills
Chat
Benchmark
75.2
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Rust Programming Language The Rust programming language is a systems programming language focused on safety, speed, and concurrency. This repository contains the official Rust compiler (`rustc`), the standard library (`std`), and comprehensive documentation. Rust's rich type system and ownership model guarantee memory safety and thread safety at compile-time, eliminating entire classes of bugs without requiring garbage collection. The repository is organized into several major components: the `compiler/` directory contains the rustc compiler implementation with modules for parsing, type checking, borrow checking, and code generation (LLVM, Cranelift, GCC backends); the `library/` directory contains the standard library (`std`), core library (`core`), and allocation library (`alloc`); and `src/tools/` contains essential development tools including Clippy (linter), rustfmt (formatter), Miri (interpreter), and rust-analyzer (IDE support). ## Option Type - Representing Optional Values The `Option<T>` type represents an optional value that can either contain a value (`Some(T)`) or be empty (`None`). It is the idiomatic Rust way to handle nullable values without null pointer exceptions, forcing explicit handling of the absence of a value at compile time. ```rust // Basic Option usage with pattern matching fn divide(numerator: f64, denominator: f64) -> Option<f64> { if denominator == 0.0 { None } else { Some(numerator / denominator) } } fn main() { // Pattern matching to handle Option let result = divide(10.0, 2.0); match result { Some(x) => println!("Result: {x}"), // Output: Result: 5 None => println!("Cannot divide by 0"), } // Using the ? operator for early return fn add_last_numbers(stack: &mut Vec<i32>) -> Option<i32> { Some(stack.pop()? + stack.pop()?) } let mut nums = vec![1, 2, 3]; assert_eq!(add_last_numbers(&mut nums), Some(5)); // 3 + 2 // Common Option methods let some_value: Option<i32> = Some(5); let none_value: Option<i32> = None; // unwrap_or provides a default value assert_eq!(some_value.unwrap_or(0), 5); assert_eq!(none_value.unwrap_or(0), 0); // map transforms the inner value let doubled = some_value.map(|x| x * 2); assert_eq!(doubled, Some(10)); // and_then for chaining operations that return Option let result = some_value.and_then(|x| if x > 0 { Some(x * 2) } else { None }); assert_eq!(result, Some(10)); } ``` ## Result Type - Error Handling The `Result<T, E>` type is used for returning and propagating errors. It has two variants: `Ok(T)` representing success with a value, and `Err(E)` representing an error with an error value. Result is the standard way to handle recoverable errors in Rust. ```rust use std::fs::File; use std::io::{self, Read}; // Function returning Result for error handling fn read_file_contents(path: &str) -> Result<String, io::Error> { let mut file = File::open(path)?; // ? propagates errors let mut contents = String::new(); file.read_to_string(&mut contents)?; Ok(contents) } fn main() -> Result<(), Box<dyn std::error::Error>> { // Pattern matching on Result match read_file_contents("config.txt") { Ok(contents) => println!("File contents: {contents}"), Err(e) => eprintln!("Error reading file: {e}"), } // Using combinators let result: Result<i32, &str> = Ok(10); // map transforms the Ok value let doubled = result.map(|x| x * 2); assert_eq!(doubled, Ok(20)); // map_err transforms the Err value let err_result: Result<i32, &str> = Err("error"); let mapped_err = err_result.map_err(|e| format!("Failed: {e}")); assert_eq!(mapped_err, Err(String::from("Failed: error"))); // and_then for chaining fallible operations let chained = Ok(5).and_then(|x| if x > 0 { Ok(x * 2) } else { Err("negative") }); assert_eq!(chained, Ok(10)); // unwrap_or_else for handling errors with a closure let value = Err("error").unwrap_or_else(|_| 42); assert_eq!(value, 42); Ok(()) } ``` ## Vec - Dynamic Array `Vec<T>` is a contiguous growable array type with heap-allocated contents. It provides O(1) indexing, amortized O(1) push/pop operations, and is the most commonly used collection type in Rust. ```rust fn main() { // Creating vectors let mut v: Vec<i32> = Vec::new(); let v2 = vec![1, 2, 3, 4, 5]; let v3 = vec![0; 10]; // 10 zeroes // Adding elements v.push(1); v.push(2); v.push(3); // Accessing elements let third = v[2]; // Panics if out of bounds let third_safe = v.get(2); // Returns Option<&T> match v.get(10) { Some(value) => println!("Value: {value}"), None => println!("Index out of bounds"), } // Iterating for item in &v { println!("{item}"); } // Mutable iteration for item in &mut v { *item *= 2; } // Removing elements let last = v.pop(); // Returns Option<T> assert_eq!(last, Some(6)); // 3 * 2 // Other useful methods let mut nums = vec![3, 1, 4, 1, 5, 9, 2, 6]; nums.sort(); assert_eq!(nums, vec![1, 1, 2, 3, 4, 5, 6, 9]); nums.dedup(); // Remove consecutive duplicates assert_eq!(nums, vec![1, 2, 3, 4, 5, 6, 9]); // Capacity management let mut v = Vec::with_capacity(10); assert!(v.capacity() >= 10); v.extend([1, 2, 3]); v.shrink_to_fit(); // Slicing let slice = &v[1..3]; assert_eq!(slice, &[2, 3]); } ``` ## HashMap - Key-Value Storage `HashMap<K, V>` stores a mapping of keys to values using a hashing function. It provides average O(1) lookup, insertion, and removal operations, making it ideal for caching and associative data storage. ```rust use std::collections::HashMap; fn main() { // Creating a HashMap let mut scores: HashMap<String, i32> = HashMap::new(); // Inserting values scores.insert(String::from("Blue"), 10); scores.insert(String::from("Yellow"), 50); // Accessing values let team_name = String::from("Blue"); let score = scores.get(&team_name); // Returns Option<&V> assert_eq!(score, Some(&10)); // Using entry API for conditional insertion scores.entry(String::from("Blue")).or_insert(25); // Won't change existing scores.entry(String::from("Green")).or_insert(25); // Inserts new // Updating based on old value let text = "hello world wonderful world"; let mut word_count: HashMap<&str, i32> = HashMap::new(); for word in text.split_whitespace() { let count = word_count.entry(word).or_insert(0); *count += 1; } assert_eq!(word_count.get("world"), Some(&2)); // Iterating over key-value pairs for (key, value) in &scores { println!("{key}: {value}"); } // Removing entries let removed = scores.remove("Blue"); assert_eq!(removed, Some(10)); // Check if key exists if scores.contains_key("Yellow") { println!("Yellow team exists!"); } // Creating from iterators let teams = vec![String::from("Red"), String::from("Blue")]; let initial_scores = vec![10, 20]; let scores: HashMap<_, _> = teams.into_iter().zip(initial_scores.into_iter()).collect(); } ``` ## File I/O - Reading and Writing Files The `std::fs` module provides cross-platform filesystem manipulation operations including reading, writing, creating, and managing files and directories. ```rust use std::fs::{self, File, OpenOptions}; use std::io::{self, BufRead, BufReader, BufWriter, Read, Write}; use std::path::Path; fn main() -> io::Result<()> { // Simple file reading (loads entire file into memory) let contents = fs::read_to_string("input.txt")?; println!("File contents: {contents}"); // Simple file writing fs::write("output.txt", "Hello, world!")?; // Reading bytes let bytes = fs::read("input.txt")?; // More control with File struct let mut file = File::create("data.txt")?; file.write_all(b"Hello, world!")?; // Reading with File let mut file = File::open("data.txt")?; let mut contents = String::new(); file.read_to_string(&mut contents)?; // Buffered reading for efficiency (line by line) let file = File::open("data.txt")?; let reader = BufReader::new(file); for line in reader.lines() { let line = line?; println!("Line: {line}"); } // Buffered writing let file = File::create("buffered.txt")?; let mut writer = BufWriter::new(file); writer.write_all(b"Buffered content")?; writer.flush()?; // Ensure data is written // Appending to a file let mut file = OpenOptions::new() .append(true) .create(true) .open("log.txt")?; writeln!(file, "Log entry")?; // File metadata let metadata = fs::metadata("data.txt")?; println!("File size: {} bytes", metadata.len()); println!("Is directory: {}", metadata.is_dir()); // Directory operations fs::create_dir_all("path/to/nested/dir")?; for entry in fs::read_dir(".")? { let entry = entry?; println!("Found: {:?}", entry.path()); } // Copying and removing fs::copy("data.txt", "data_backup.txt")?; fs::remove_file("data_backup.txt")?; fs::remove_dir_all("path")?; Ok(()) } ``` ## Threading - Concurrent Execution The `std::thread` module provides native OS thread support. Rust's ownership system prevents data races at compile time, making concurrent programming safer. ```rust use std::thread; use std::time::Duration; use std::sync::{Arc, Mutex, mpsc}; fn main() { // Spawning a basic thread let handle = thread::spawn(|| { for i in 1..5 { println!("Thread: count {i}"); thread::sleep(Duration::from_millis(1)); } }); // Main thread continues for i in 1..3 { println!("Main: count {i}"); thread::sleep(Duration::from_millis(1)); } // Wait for thread to complete handle.join().unwrap(); // Moving data into threads let data = vec![1, 2, 3]; let handle = thread::spawn(move || { println!("Vector: {:?}", data); }); handle.join().unwrap(); // Named threads with builder let builder = thread::Builder::new() .name("worker".to_string()) .stack_size(32 * 1024); let handle = builder.spawn(|| { println!("Thread name: {:?}", thread::current().name()); }).unwrap(); handle.join().unwrap(); // Shared state with Arc and Mutex let counter = Arc::new(Mutex::new(0)); let mut handles = vec![]; for _ in 0..10 { let counter = Arc::clone(&counter); let handle = thread::spawn(move || { let mut num = counter.lock().unwrap(); *num += 1; }); handles.push(handle); } for handle in handles { handle.join().unwrap(); } println!("Counter: {}", *counter.lock().unwrap()); // Message passing with channels let (tx, rx) = mpsc::channel(); let tx2 = tx.clone(); thread::spawn(move || { tx.send("hello from thread 1").unwrap(); }); thread::spawn(move || { tx2.send("hello from thread 2").unwrap(); }); for received in rx { println!("Got: {received}"); } } ``` ## Iterators - Composable Data Processing Iterators provide a way to process sequences of elements lazily and composably. The `Iterator` trait is at the core of Rust's functional programming capabilities. ```rust fn main() { let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // Basic iteration for num in &numbers { println!("{num}"); } // Map - transform each element let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect(); assert_eq!(doubled, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); // Filter - keep elements matching predicate let evens: Vec<&i32> = numbers.iter().filter(|x| *x % 2 == 0).collect(); assert_eq!(evens, vec![&2, &4, &6, &8, &10]); // Chaining operations let result: i32 = numbers .iter() .filter(|x| *x % 2 == 0) // Keep evens .map(|x| x * x) // Square them .sum(); // Sum all assert_eq!(result, 220); // 4 + 16 + 36 + 64 + 100 // fold - reduce to single value let sum = numbers.iter().fold(0, |acc, x| acc + x); assert_eq!(sum, 55); // find - get first matching element let first_even = numbers.iter().find(|x| *x % 2 == 0); assert_eq!(first_even, Some(&2)); // any/all - boolean checks let has_even = numbers.iter().any(|x| x % 2 == 0); let all_positive = numbers.iter().all(|x| *x > 0); assert!(has_even && all_positive); // enumerate - get index with element for (index, value) in numbers.iter().enumerate() { println!("Index {index}: {value}"); } // zip - combine two iterators let a = [1, 2, 3]; let b = ["a", "b", "c"]; let zipped: Vec<_> = a.iter().zip(b.iter()).collect(); assert_eq!(zipped, vec![(&1, &"a"), (&2, &"b"), (&3, &"c")]); // take/skip - limit elements let first_three: Vec<_> = numbers.iter().take(3).collect(); let skip_three: Vec<_> = numbers.iter().skip(3).take(3).collect(); // Creating iterators let range: Vec<i32> = (1..=5).collect(); // 1, 2, 3, 4, 5 let repeated: Vec<i32> = std::iter::repeat(42).take(3).collect(); // 42, 42, 42 // Custom iterator struct Counter { count: usize, max: usize } impl Iterator for Counter { type Item = usize; fn next(&mut self) -> Option<Self::Item> { if self.count < self.max { self.count += 1; Some(self.count) } else { None } } } let counter = Counter { count: 0, max: 5 }; let sum: usize = counter.sum(); assert_eq!(sum, 15); } ``` ## Network Programming - TCP and UDP The `std::net` module provides networking primitives for TCP and UDP communication, enabling client-server applications and network protocols. ```rust use std::net::{TcpListener, TcpStream, UdpSocket, SocketAddr}; use std::io::{Read, Write, BufRead, BufReader}; use std::thread; // TCP Server fn run_tcp_server() -> std::io::Result<()> { let listener = TcpListener::bind("127.0.0.1:8080")?; println!("Server listening on port 8080"); for stream in listener.incoming() { let stream = stream?; thread::spawn(move || { handle_client(stream).unwrap_or_else(|e| eprintln!("Error: {e}")); }); } Ok(()) } fn handle_client(mut stream: TcpStream) -> std::io::Result<()> { let mut buffer = [0; 1024]; let bytes_read = stream.read(&mut buffer)?; let request = String::from_utf8_lossy(&buffer[..bytes_read]); println!("Received: {request}"); stream.write_all(b"HTTP/1.1 200 OK\r\n\r\nHello, World!")?; stream.flush()?; Ok(()) } // TCP Client fn tcp_client() -> std::io::Result<()> { let mut stream = TcpStream::connect("127.0.0.1:8080")?; stream.write_all(b"GET / HTTP/1.1\r\n\r\n")?; let mut response = String::new(); stream.read_to_string(&mut response)?; println!("Response: {response}"); Ok(()) } // UDP Socket fn udp_example() -> std::io::Result<()> { // UDP Server let server_socket = UdpSocket::bind("127.0.0.1:8081")?; // UDP Client let client_socket = UdpSocket::bind("127.0.0.1:0")?; // Random available port client_socket.send_to(b"Hello, UDP!", "127.0.0.1:8081")?; // Server receives let mut buf = [0; 1024]; let (amt, src) = server_socket.recv_from(&mut buf)?; println!("Received {} bytes from {}: {}", amt, src, String::from_utf8_lossy(&buf[..amt])); // Server responds server_socket.send_to(b"Got it!", src)?; Ok(()) } // Non-blocking I/O fn non_blocking_tcp() -> std::io::Result<()> { let listener = TcpListener::bind("127.0.0.1:8082")?; listener.set_nonblocking(true)?; loop { match listener.accept() { Ok((stream, addr)) => { println!("New connection from {addr}"); // Handle connection... } Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => { // No connection available, do other work thread::sleep(std::time::Duration::from_millis(100)); } Err(e) => return Err(e), } } } fn main() -> std::io::Result<()> { // Example usage (run server and client in separate threads/processes) println!("Network examples ready"); Ok(()) } ``` ## Process Management - Spawning External Commands The `std::process` module provides functionality for spawning and managing child processes, capturing their output, and handling their I/O streams. ```rust use std::process::{Command, Stdio, exit}; use std::io::{Write, BufRead, BufReader}; fn main() -> std::io::Result<()> { // Simple command execution let output = Command::new("echo") .arg("Hello, world!") .output()?; println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); println!("exit status: {}", output.status); // Check if command succeeded let status = Command::new("ls") .arg("-la") .status()?; if status.success() { println!("Command succeeded"); } // Environment variables and working directory let output = Command::new("printenv") .env("MY_VAR", "hello") .env_clear() // Clear all inherited env vars .env("PATH", "/usr/bin") .current_dir("/tmp") .output()?; // Piping between commands (echo | grep) let echo_child = Command::new("echo") .arg("line1\nline2\nline3") .stdout(Stdio::piped()) .spawn()?; let echo_stdout = echo_child.stdout.unwrap(); let grep_output = Command::new("grep") .arg("line2") .stdin(Stdio::from(echo_stdout)) .output()?; println!("Grep result: {}", String::from_utf8_lossy(&grep_output.stdout)); // Interactive process with stdin/stdout let mut child = Command::new("cat") .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn()?; // Write to child's stdin if let Some(ref mut stdin) = child.stdin { stdin.write_all(b"Hello from parent\n")?; } child.stdin.take(); // Close stdin to signal EOF // Read from child's stdout let output = child.wait_with_output()?; println!("Child output: {}", String::from_utf8_lossy(&output.stdout)); // Reading output line by line let mut child = Command::new("ls") .arg("-la") .stdout(Stdio::piped()) .spawn()?; let stdout = child.stdout.take().unwrap(); let reader = BufReader::new(stdout); for line in reader.lines() { println!("Line: {}", line?); } child.wait()?; // Terminate current process // exit(0); // Success // exit(1); // Failure Ok(()) } ``` ## Path Manipulation - Cross-Platform Paths The `std::path` module provides types for working with filesystem paths in a platform-independent way, handling differences between Unix and Windows path formats. ```rust use std::path::{Path, PathBuf}; use std::ffi::OsStr; fn main() { // Creating paths let path = Path::new("/usr/local/bin/rustc"); let mut path_buf = PathBuf::from("/home/user"); // Building paths path_buf.push("documents"); path_buf.push("file.txt"); assert_eq!(path_buf, PathBuf::from("/home/user/documents/file.txt")); // Path components let path = Path::new("/tmp/foo/bar.txt"); assert_eq!(path.parent(), Some(Path::new("/tmp/foo"))); assert_eq!(path.file_name(), Some(OsStr::new("bar.txt"))); assert_eq!(path.file_stem(), Some(OsStr::new("bar"))); assert_eq!(path.extension(), Some(OsStr::new("txt"))); // Changing extension let mut path = PathBuf::from("foo.txt"); path.set_extension("rs"); assert_eq!(path, PathBuf::from("foo.rs")); // Joining paths let base = Path::new("/usr"); let full = base.join("local").join("bin"); assert_eq!(full, PathBuf::from("/usr/local/bin")); // Checking path properties let path = Path::new("/tmp/test.txt"); println!("Is absolute: {}", path.is_absolute()); println!("Is relative: {}", path.is_relative()); println!("Exists: {}", path.exists()); println!("Is file: {}", path.is_file()); println!("Is directory: {}", path.is_dir()); // Iterating over components let path = Path::new("/usr/local/bin"); for component in path.components() { println!("Component: {:?}", component); } // Converting to/from strings let path = Path::new("/tmp/test.txt"); if let Some(s) = path.to_str() { println!("Path as str: {s}"); } // Handle paths that may not be valid UTF-8 let os_str = path.as_os_str(); println!("Path as OsStr: {:?}", os_str); // Ancestors iterator let path = Path::new("/usr/local/bin/rustc"); for ancestor in path.ancestors() { println!("Ancestor: {:?}", ancestor); } // Prints: /usr/local/bin/rustc, /usr/local/bin, /usr/local, /usr, / // Strip prefix let path = Path::new("/usr/local/bin"); let stripped = path.strip_prefix("/usr").unwrap(); assert_eq!(stripped, Path::new("local/bin")); // Canonicalize (resolve symlinks, get absolute path) if let Ok(canonical) = std::fs::canonicalize(".") { println!("Current directory: {:?}", canonical); } } ``` ## Building from Source The Rust compiler is bootstrapped using a Python script called `x.py`. Building from source allows customization of the compiler and standard library, though using pre-built binaries via rustup is recommended for most users. ```bash # Clone the repository git clone https://github.com/rust-lang/rust.git cd rust # Configure with interactive setup (recommended for first-time) ./x.py setup # Or configure manually with specific options ./configure --build=x86_64-unknown-linux-gnu \ --enable-full-tools \ --enable-profiler \ --set rust.debug-assertions=false # Build the compiler (stage 1) ./x.py build # Build and install ./x.py build && ./x.py install # Build documentation ./x.py doc # Run tests ./x.py test # Build specific components ./x.py build library/std ./x.py build compiler/rustc # Clean build artifacts ./x.py clean # Check code without building (faster feedback) ./x.py check # Format the codebase ./x.py fmt # Build with specific configuration profile ./x.py build --config compiler ./x.py build --config library ./x.py build --config tools # Cross-compilation example ./x.py build --target aarch64-unknown-linux-gnu ``` ## Macros - Code Generation Rust's macro system enables metaprogramming through `macro_rules!` declarative macros and procedural macros. The standard library provides essential macros for common operations. ```rust // Using standard library macros fn main() { // println! and print! for output println!("Hello, world!"); println!("Formatted: {} + {} = {}", 1, 2, 3); println!("Debug: {:?}", vec![1, 2, 3]); println!("Pretty debug: {:#?}", vec![1, 2, 3]); print!("No newline"); // format! for string creation let s = format!("Value: {}", 42); assert_eq!(s, "Value: 42"); // vec! for vector creation let v = vec![1, 2, 3]; let zeros = vec![0; 5]; // [0, 0, 0, 0, 0] // panic! for unrecoverable errors // panic!("Something went wrong: {}", "details"); // assert! macros for testing assert!(1 + 1 == 2); assert_eq!(2 + 2, 4); assert_ne!(1, 2); debug_assert!(expensive_check()); // Only in debug builds // dbg! for quick debugging let x = dbg!(5 * 2); // Prints: [src/main.rs:25] 5 * 2 = 10 // todo! and unimplemented! for placeholders fn work_in_progress() -> i32 { todo!("implement this later") } // include! macros for file inclusion // let data = include_str!("data.txt"); // Include as string // let bytes = include_bytes!("image.png"); // Include as bytes // cfg! for conditional compilation checks if cfg!(target_os = "linux") { println!("Running on Linux"); } // env! for compile-time environment variables let version = env!("CARGO_PKG_VERSION"); println!("Version: {version}"); // concat! for string concatenation const GREETING: &str = concat!("Hello", ", ", "world!"); // stringify! converts tokens to string let code = stringify!(1 + 2); // "1 + 2" } fn expensive_check() -> bool { true } // Custom macro_rules! example macro_rules! create_function { ($func_name:ident) => { fn $func_name() { println!("Called: {}", stringify!($func_name)); } }; } create_function!(foo); create_function!(bar); // Variadic macro macro_rules! sum { ($($x:expr),*) => { { let mut total = 0; $(total += $x;)* total } }; } fn test_macros() { foo(); // Prints: Called: foo bar(); // Prints: Called: bar let result = sum!(1, 2, 3, 4, 5); assert_eq!(result, 15); } ``` ## Summary The Rust programming language and its standard library provide a comprehensive foundation for systems programming with memory safety guarantees. Key use cases include: building high-performance network services using the `std::net` module with TCP/UDP support; creating reliable command-line tools with robust error handling via `Result` and `Option`; developing concurrent applications with safe threading primitives from `std::thread` and `std::sync`; and cross-platform file system operations through `std::fs`. The ownership system, combined with the borrow checker, prevents data races and memory bugs at compile time. Integration patterns typically involve using the `Result` type for fallible operations with the `?` operator for ergonomic error propagation; leveraging iterators for efficient, lazy data processing pipelines; employing `Arc<Mutex<T>>` for shared mutable state across threads; and using channels (`mpsc`) for message-passing concurrency. The standard library's collections (`Vec`, `HashMap`, `HashSet`) provide efficient data structures, while the `Path` and `PathBuf` types ensure cross-platform path handling. For extending beyond the standard library, the Cargo package manager integrates seamlessly with the crates.io ecosystem, enabling access to thousands of community-maintained libraries.