Introduction to Rust
Rustyll is built with Rust, a modern systems programming language that offers exceptional performance without sacrificing safety. This page provides a quick introduction to Rust for those interested in contributing to Rustyll or understanding how it works under the hood.
Why Rust for Rustyll?
Rust offers several advantages that make it perfect for a static site generator:
- Performance: Rust is blazingly fast, often matching or exceeding C/C++ performance
- Memory safety: Rust’s ownership system prevents memory leaks and data races without a garbage collector
- Concurrency: Rust makes parallel programming safer and more accessible
- Cargo ecosystem: Rust’s package manager makes distribution and dependency management simple
- Cross-platform: Rustyll works on Windows, macOS, and Linux with the same codebase
These advantages translate to Rustyll being 10-100x faster than Jekyll for most sites.
Getting Started with Rust
If you want to contribute to Rustyll or better understand its codebase, you’ll need to learn some Rust basics:
Installing Rust
Install Rust using rustup, the Rust toolchain installer:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
On Windows, download and run rustup-init.exe from the Rust website.
Key Rust Concepts for Rustyll
Understanding these Rust concepts will help you navigate the Rustyll codebase:
Ownership and Borrowing
Rust’s most distinctive feature is its ownership system:
fn main() {
// String is owned by s1
let s1 = String::from("hello");
// Ownership moves to s2
let s2 = s1;
// This would fail - s1 no longer owns the string
// println!("{}", s1);
// Borrowing with references
let s3 = String::from("world");
let len = calculate_length(&s3);
println!("The length of '{}' is {}.", s3, len);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
Traits
Traits are Rust’s version of interfaces:
trait Plugin {
fn name(&self) -> &str;
fn process(&self, content: &str) -> String;
}
struct MarkdownPlugin;
impl Plugin for MarkdownPlugin {
fn name(&self) -> &str {
"markdown"
}
fn process(&self, content: &str) -> String {
// Convert markdown to HTML
format!("<p>{}</p>", content)
}
}
Error Handling
Rust uses Result and Option types for error handling:
fn read_config(path: &str) -> Result<Config, std::io::Error> {
let content = std::fs::read_to_string(path)?;
// Parse config...
Ok(Config::default())
}
fn main() {
match read_config("_config.yml") {
Ok(config) => println!("Config loaded"),
Err(e) => eprintln!("Failed to load config: {}", e),
}
// Or using the ? operator in functions that return Result
fn build_site() -> Result<(), std::io::Error> {
let config = read_config("_config.yml")?;
// Continue with site build...
Ok(())
}
}
Concurrency with Rayon
Rustyll uses Rayon for parallel processing:
use rayon::prelude::*;
fn process_posts(posts: Vec<Post>) -> Vec<ProcessedPost> {
posts.par_iter() // Parallel iterator
.map(|post| process_post(post))
.collect()
}
Building Rustyll from Source
To build Rustyll from source:
# Clone the repository
git clone https://github.com/rustyll/rustyll.git
cd rustyll
# Build in development mode
cargo build
# Build with optimizations for production
cargo build --release
# Run tests
cargo test
Contributing to Rustyll
Contributions to Rustyll are welcome! Here’s how to get started:
- Fork the repository on GitHub
- Create a new branch for your feature or bugfix
- Make your changes
- Add tests for your changes
- Run the test suite with
cargo test
- Commit your changes
- Push to your fork
- Submit a pull request
For more details, see the Contributing Guide.
Resources for Learning Rust
Here are some excellent resources for learning Rust:
- The Rust Book - The official Rust programming guide
- Rust by Example - Learn Rust with annotated examples
- Rustlings - Small exercises to get you used to reading and writing Rust code
- Exercism’s Rust Track - Practice exercises with mentor feedback
Rust vs Ruby (Jekyll)
For those familiar with Jekyll’s Ruby codebase, here’s a comparison of common patterns:
Concept | Ruby (Jekyll) | Rust (Rustyll) |
---|---|---|
Classes | class Page |
struct Page and impl Page
|
Mixins | include Convertible |
impl Convertible for Page |
Iteration | pages.each { \|p\| ... } |
for page in pages { ... } |
Error handling | begin/rescue |
Result<T, E> and ?
|
Concurrency | Threads (GIL limited) | Rayon (thread pool) |
Memory mgmt | Garbage collection | Ownership system |
Understanding Rustyll’s Architecture
Rustyll’s architecture leverages Rust’s strengths:
-
Core types:
Site
,Page
,Post
,Layout
, etc. -
Traits:
Renderable
,Convertible
,Plugin
, etc. - Parallel processing: Using Rayon for concurrent operations
- Error handling: Robust error reporting and recovery
- Plugin system: Extensible via Rust crates
This architecture enables Rustyll’s exceptional performance while maintaining Jekyll compatibility.