๐Ÿฆ€ Functional Rust
๐ŸŽฌ Rust Ownership in 30 seconds Visual walkthrough of ownership, moves, and automatic memory management.
๐Ÿ“ Text version (for readers / accessibility)

โ€ข Each value in Rust has exactly one owner โ€” when the owner goes out of scope, the value is dropped

โ€ข Assignment moves ownership by default; the original binding becomes invalid

โ€ข Borrowing (&T / &mut T) lets you reference data without taking ownership

โ€ข The compiler enforces: many shared references OR one mutable reference, never both

โ€ข No garbage collector needed โ€” memory is freed deterministically at scope exit

555: Owning References Pattern

Difficulty: 4 Level: Intermediate-Advanced Build a struct that owns its data and simultaneously provides borrowed views into it โ€” without self-referential pointers.

The Problem This Solves

A common pattern in parsing, indexing, and query engines is: you load data once, then hand out many cheap views into it. In languages with GC, this is trivial โ€” everything is a reference. In Rust, the naive approach (store both the `Vec` and a `&[T]` pointing into it) is self-referential and rejected by the borrow checker. The solution is to separate data from metadata. The struct owns the data (e.g. a `Vec<u8>`), and views are expressed as indices or byte-offsets rather than raw references. When you need a `&[u8]`, you reconstruct it from the stored indices at call time. The lifetime of the returned reference is tied to `&self`, not stored inside `self` โ€” and that is exactly what the borrow checker needs to see. This pattern appears in `ParsedDocument`, query builders, arena allocators, and any cache that serves sub-slices of a larger buffer.

The Intuition

Instead of storing `&str` slices (which would require the struct to borrow from itself), store `(start, end)` byte pairs. When the caller asks for a token, compute `&self.source[start..end]` on the fly. The returned `&str` borrows from `self`, so its lifetime is tied to the struct's lifetime โ€” no self-referential pointer needed. For query builder patterns, store the source data in the struct and return iterators or references with lifetime `'a` tied to `&'a self`. The caller can consume results as long as the builder lives.

How It Works in Rust

Index-based view โ€” store positions, not pointers:
struct ParsedDocument {
 source: String,
 token_spans: Vec<(usize, usize)>,  // (start, end) byte positions
}

impl ParsedDocument {
 fn get_token(&self, i: usize) -> Option<&str> {
     self.token_spans.get(i).map(|&(s, e)| &self.source[s..e])
 }
}
`&self.source[s..e]` has lifetime `'self` โ€” perfectly fine. Iterator returning borrowed data โ€” the `'a` on `&'a self` flows into the `impl Iterator`:
impl QueryBuilder {
 fn filter<'a>(&'a self, pred: impl Fn(&i32) -> bool)
     -> impl Iterator<Item = &'a i32>
 {
     self.source.iter().filter(move |&&ref x| pred(x))
 }
}
The iterator holds a reference to `self.source`, so it can't outlive the builder. Owned + metadata tuple โ€” return ownership and computed metadata together:
fn process_and_view(data: Vec<String>) -> (Vec<String>, Vec<usize>) {
 let lengths: Vec<usize> = data.iter().map(|s| s.len()).collect();
 (data, lengths)
}
Compute what you need from `&data`, then move `data` into the return tuple. No lifetime juggling needed.

What This Unlocks

Key Differences

ConceptOCamlRust
Sub-string view`String.sub` (copies) or `Bytes.sub_string``&s[start..end]` (zero-copy borrow)
Self-referential structNot a problem (GC)Forbidden; use indices instead
Returning borrowed iteratorGC handles refs`impl Iterator<Item = &'a T>` with explicit lifetime
Owned + borrowed tupleNatural (everything is reference)Return `(Vec<T>, Vec<usize>)` โ€” compute metadata before moving
//! # 555. Owning References Pattern
//! Combining ownership and borrowing for efficient data access.

/// A view into an owned collection โ€” stores offset without extra allocation
struct OwnedSlice<T> {
    data: Vec<T>,
    start: usize,
    end: usize,
}

impl<T: Clone + std::fmt::Debug> OwnedSlice<T> {
    fn new(data: Vec<T>) -> Self {
        let end = data.len();
        OwnedSlice { data, start: 0, end }
    }

    fn slice(&self, start: usize, end: usize) -> &[T] {
        &self.data[self.start + start..self.start + end.min(self.end - self.start)]
    }

    fn len(&self) -> usize { self.end - self.start }

    fn into_inner(self) -> Vec<T> { self.data }
}

/// Builder that owns source data, returns borrowed results
struct QueryBuilder {
    source: Vec<i32>,
}

impl QueryBuilder {
    fn new(data: Vec<i32>) -> Self { QueryBuilder { source: data } }

    fn filter<'a>(&'a self, pred: impl Fn(&i32) -> bool) -> impl Iterator<Item = &'a i32> {
        self.source.iter().filter(move |&&ref x| pred(x))
    }

    fn max(&self) -> Option<&i32> { self.source.iter().max() }
    fn min(&self) -> Option<&i32> { self.source.iter().min() }
}

/// Pattern: owned data + borrowed view returned
fn process_and_view(data: Vec<String>) -> (Vec<String>, Vec<usize>) {
    let lengths: Vec<usize> = data.iter().map(|s| s.len()).collect();
    (data, lengths) // own data + computed metadata
}

fn main() {
    let os = OwnedSlice::new(vec![10, 20, 30, 40, 50]);
    println!("slice [1..4]: {:?}", os.slice(1, 4));
    println!("len: {}", os.len());
    let inner = os.into_inner();
    println!("inner: {:?}", inner);

    let qb = QueryBuilder::new(vec![1, 5, 3, 7, 2, 8, 4, 6]);
    let evens: Vec<_> = qb.filter(|&x| x % 2 == 0).collect();
    println!("evens: {:?}", evens);
    println!("max: {:?}, min: {:?}", qb.max(), qb.min());

    let words = vec!["hello".to_string(), "world".to_string(), "rust".to_string()];
    let (owned_words, lengths) = process_and_view(words);
    println!("words: {:?}", owned_words);
    println!("lengths: {:?}", lengths);
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_owned_slice() {
        let os = OwnedSlice::new(vec![1, 2, 3, 4, 5]);
        assert_eq!(os.slice(1, 3), &[2, 3]);
        assert_eq!(os.len(), 5);
    }

    #[test]
    fn test_query_builder() {
        let qb = QueryBuilder::new(vec![3, 1, 4, 1, 5]);
        assert_eq!(qb.max(), Some(&5));
        assert_eq!(qb.min(), Some(&1));
    }
}
(* Owning references pattern in OCaml *)
(* OCaml data structures always own their contents via GC *)

type 'a owned_view = {
  source: 'a;
  start: int;
  length: int;
}

let make_view source start len = { source; start; length = len }

let get_element view i =
  if i < view.length then
    Some (Array.get view.source (view.start + i))
  else None

let () =
  let data = [|10; 20; 30; 40; 50|] in
  let view = make_view data 1 3 in
  for i = 0 to view.length - 1 do
    match get_element view i with
    | Some v -> Printf.printf "view[%d] = %d\n" i v
    | None -> ()
  done