Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Welcome

Welcome to my personal website, blog, and landing page for other self-hosted software. This website serves as a space to share musings, stories, and chronicles, about all of those things.

cover photo

About

My name is Matt. I am a software engineer living in the West. My interests include software, defense, EW, drones, and data security and privacy. Other personal interests of mine include linguistics, philosophy, and theology, to name a few.

Genealogy

The title of this website you may recognize as a surname. I am also interested in family history and genealogy. If you have some relation or interest to this surname, please feel free to reach out. I am planning a genealogical project.

Contact

Email: [email protected]

Celtic Camping

Derived from the boring history episode

Bushcraft a roundhouse. The shape helps with wind. The fire is central. The mutual body heat helps. The flooring is dried and dead leafs/pine/etc. The thatched roof allows smoke out but holds some back till it can be absorbed above. This keeps out insects and keeps heat in.

Camp with just a brat (Celtic cloak) and leather bag of essentials. Go somewhere safe on a Friday evening to camp and do this. The brat can be converted to a tent with stakes.

Dried meats, dried cheeses, fire starting kit including, flint, steel, and char cloth. Dry tinder in a bag carefully constructed from woven Build an underlayer of bedding out of bracken, dead and dried plant material, heather, fern, fibers, etc.

Build a fire and place stones in to warm them. Place them amid the sleeping area. They can discharge over night after the fire dies, amid the sleeping area.

The Celtic point is bodily conditioning, survival skills, naturalist skills, and spiritual growth, memorization, and reflection. Hypothetically, you could adapt over 3 days, or take a Monday off to adapt over 4 days. You could chain this with fasting.

On Mycotoxins

Mycotoxin results Future of the protocol

  • other binders, maybe for aflatoxin Killing protocol
  • nystatin, caprylic acid, oregano oil, undecyclenic acid, berberine Three day fast and reduced inflammation

Binders (rotate these, don’t take all at once):

  • Activated charcoal - 1-2g, 2x/day, away from food/meds (2+ hours)
  • Bentonite clay - 1-2 tsp in water, away from meals
  • Chlorella - 3-6g/day
  • Cholestyramine (prescription, but most effective for many mycotoxins)

Glutathione support:

  • Liposomal glutathione - 500-1000mg/day
  • NAC - 600-1200mg, 2x/day
  • Alpha-lipoic acid - 300-600mg/day

Liver support:

  • Milk thistle - 200-400mg standardized extract, 2-3x/day
  • Phosphatidylcholine - supports cell membranes

Anti-inflammatory (for neuro):

  • Curcumin (liposomal or with piperine) - 1000-2000mg/day
  • Omega-3s (high EPA/DHA) - 2-3g/day
  • Resveratrol - 200-500mg/day

Antifungal (if colonization confirmed):

  • Nystatin (prescription preferred)
  • Caprylic acid - 1000-2000mg with meals
  • Oregano oil - follow label, cycles of 2 weeks on/off

Critical notes:

  • Space binders 2+ hours from everything else
  • Start low, go slow - die-off can worsen symptoms temporarily
  • Stay hydrated, support drainage (sauna if tolerated)
  • Address the source or you’re spinning wheels

Working with a practitioner experienced in mold illness (CIRS protocol) would optimize this.

Most comparable OTC antifungals for gut:

Caprylic acid - Probably closest to nystatin functionally

  • Disrupts fungal cell membranes
  • Stays in the gut (not systemic)
  • Dose: 1000-2000mg with each meal
  • Look for delayed-release or time-release formulas so it reaches lower GI

Undecylenic acid (from castor oil)

  • Similar mechanism to caprylic acid, sometimes considered stronger
  • 200-250mg, 3x/day with meals
  • Often combined with caprylic acid in formulas

Saccharomyces boulardii (probiotic yeast)

  • Competes with pathogenic fungi
  • Produces caprylic acid naturally
  • 5-10 billion CFU/day
  • Won’t be killed by antifungals like bacteria-based probiotics

Oregano oil

  • Strong antimicrobial, including antifungal
  • 150-200mg standardized extract (minimum 70% carvacrol), 2-3x/day
  • Use cycles: 2 weeks on, 1-2 weeks off
  • Can be harsh on gut, take with food

Berberine

  • Broad antimicrobial including antifungal
  • 500mg, 2-3x/day
  • Also helps with blood sugar

Combination approach often works better - rotate or combine 2-3 of these rather than relying on just one. Start one at a time to monitor tolerance.

Stack Semantics

A friend of mine, Falco, “gifted” this to his every workplace. It’s a representation of a stack semantics shown at runtime.

branch name
commit ID
build number
build node (I guess this is hostname below)
timestamp

compiler info
- language
- compiler ID
- compiler version
- compiler target
- toolchain
- language standard
- language extensions
environment
- host
  - hostname
  - operating system
  - architecture
- processor
  - family
  - description
  - physical cores
  - logical cores

In rust, this can be implemented by passing these fields from build.rs with a little help from the vergen library.

Future Trips

  • Malta
  • Baja
  • Falklands
  • Hawaii
  • Costa Rica
  • Medellin, Colombia
  • Bahamas
  • American Samoa

National Parks

These national parks are off the list.

  • Bryce Canyon
  • Redwoods

State Parks

These state parks are off the list.

  • Alcatraz
  • Antelope Island
  • Castle Crags
  • Folsom Lake SRA
  • Muir Woods
  • Pismo State Beach

Deep Work

The Rust Programming Language

These are my notes as I go through the main Rust book.

My goal is that these notes be a “living” document. As I program more and more in Rust, I will update these notes. I will remove the obvious stuff people can grasp quickly. I will then add more info on nuances I uncover.

1 Getting Started

https://doc.rust-lang.org/book/

These are the interesting tidbits that stand out from the book.

Rust is an “expression based” language. File extension is .rs.

rustc rustfmt rustdoc

2 Programming a Guessing Game

This introduces a basic REPL.

Why is std::cmp::Ordering used for basic comparison of numbers?

.expect() and Result<T, E>

Result<T, E>is a type-parameterized enum. These kinds of enums have variants of Ok<T> and Err<E>. .expect() may be called on a Result<T> type. This will either unwrap it or fail with a message.

{var} is the “crab pincer” syntax for println!

3 Common Programming Concepts

3.1 Variables and Mutability

const is basically constexpr; its value/definition must be known at compile time. Normal variables are constants (immutable). mut are “normal”, mutable variables.

Variable Types

Mutable

let mut <var_name> = <value> for a variable proper

Immutable

let <var_name> = <value> for an immutable. These are clutch in applying transformations through shadowing.

Constants

Compared to variables (even immutable), constants can only be set to a constant expression, and they can be declared in any scope.

Shadowing lets you:

  1. Reuse names.
  2. Hide values in higher-scopes when you might be using a value derived from it in a narrower scope.
  3. “Change” the type of the variable (cannot do this by mutating a variable).
  4. Basically mutate it, but it is explicit, and it becomes implicitly immutable again immediately.

3.2 Data Types

isize and usize are word-length for the compile target’s architecture.

A byte literal b'A' is specifically for u8 bytes.

When compiled with --release, integers will overflow. Otherwise the program panics. Overflowing can be handled differently with methods:

  • wrapping_*
  • checked_*
  • overflowing_*
  • saturating_*

Rust’s char is 4 bytes and represents a Unicode scalar value. It ranges from U+0000 to U+D7FF and U+E000 to U+10FFFF inclusive.

Ranges

inclusive-exclusive: START...END inclusive-inclusive: START...=END

Tuples

Tuples are a primitive, compound type and allow destructuring. Indexing is also possible with a dot operator.

#![allow(unused)]
fn main() {
let tup = (1, 2.0, false);
let (x, y, z) = tup;
let y = tup.0;
}

The () empty tuple is called unit. This is like void in that it is returned implicitly if there are no other returns.

Arrays

Arrays are defined on the stack and have a fixed length. Otherwise you will need a vector.

Arrays can be initialized either as [type; length] or [value; length] with the latter’s value being repeated.

3.3 Functions

Parameters must have a type annotation. fn foo(some_var : i32){}

Expressions’ return value is their final expression.

{
	let x = 2;
	x + 6
} // returns 8

Of course, these are used as function bodies.

3.4 Comments

// comments can be inline. /// are documentation comments (Markdown-ready which compile to HTML through Cargo). Panics, Errors, Safety, and Examples are common headings. //! adds commentary to the containing item (such as a crate or module) rather than the below piece of code.

3.6 Macros

fn foo!(){}

dbg!() is a useful macro to print debug information of arguments and simultaneously return ownership.

3.5 Control Flow

if is an expression (with “arms” like match) so it may be used as a ternary. let number = if condition { 5 } else { 6 };. Because of this, all arms must return the same type.

Loops

loop, while, and for for is basically an enhanced for loop in C/++.

<LOOP> [expression] {
	<STATEMENT>; {STATEMENTS}...
}

Loops can have labels.

'label: loop {
	
}

You can break on these so to not break on the innermost loop.

break 'label;

You can return a value to make a loop an expression on a break.

break some_val;

With loops, a value may be added to the end of the break statement to return a value. This means the loop is an expression and can be assigned from.

Loops may have labels 'label: loop { ...; break 'label; } to specify non-innermost breaks.

while loops are also available.

for loops are more like C++ enhanced for loops.

They’re also like Python for loops with a range type. Ranges are provided by the standard library and apparently the literal looks like (x..y).

4 Understanding Ownership

4.1 What is Ownership?

String literals are on the stack, but Strings are allocated to the heap. Thus string literals are constexpr, basically. Because Strings are on the heap, String::push_str(self, str) is the name of the appending function.

Memory is automatically returned once the variable that owns it goes out of scope. This pattern is called RAII (resource acquisition is initialization) in C++. The actual “free” function called in rust at the end of scope is called drop. This means there must be only one “owner”.

Double free error: Another pointer to the same data on a heap goes out of scope.

Assigning one variable to another is actually an ambiguous operation.

On the heap:

Instead of shallow copys (copying structured data and pointer values), rust performs moves. The first variable becomes invalidated. Rust never automatically performs deep copies (clone()) which would copy all member pointers blocks of memory. Some data implements Clone though, then .clone() will perform a deep copy.

stack-only data:

If all data is on the stack, there is no difference between a deep and shallow copy. Thus, if stack-only data implements copy(), no move occurs, just copy semantics. The primitives types and tuples of only primitives implement the Copy trait.

Ownership and Functions

Passing arguments to parameters uses the exact same ambiguous semantics as variable assignments.

If anything is moved in rather than copied in, the drop at the end of the function scope could be problematic. You could return a tuple with the extra values of anything moved in to move it back out. That’s “too much ceremony” though, so you get references.

4.2 References and Borrowing

You can have as many immutable references to a variable as you like. Once you have an immutable reference, that’s the only reference you can have of it for the remainder of its scope.

A scope of a reference ends with its last usage, so a scope is not strictly a syntactic block. It can be confusingly more forgiving.

4.3 The Slice Type

A “string slice” is &str and the literal looks like &s[0..len]. The inclusive beginning and exclusive ending can be omitted, i.e. &s[..]. Indices can be variables, e.g. &s[2..i].

Immutable borrows of slices help ensure that the underlying data is not mutated later. This is as opposed to calculating some index and storing it in an unrelated variable.

Slicing can be performed on either &String or string slices &str. Deref coercion can implicitly convert a string reference to a string slice.

References to strings are equivalent to whole slices of strings. String literals are string slices.

There is a type for a general slice of a collection. It has a type of the form &[i32].

One can take a slice of a string or an array. A string slice is &str (not to be confused with the more specialized &String).

An array slice type is something like &[i32]. An array slice literal is something like &a[1..3]

4.4 Cloning

Copying stack allocations (most primitives) gives you a copy. Copying heap allocations (boxes/pointers) gives you a shallow copy. It also invalidates the original copy. To do a deep copy, call .clone().

Field Init Shorthand lets us pass arguments that match the name of a struct field without specifying the struct field.

fn factory(some_field : fieldType) -> Some_Struct {
	Some_Struct {
		some_field,
		some_field2 : some_field_other,
	}
};

Struct update syntax lets us create a struct by specifying a struct to base the rest of the values on (after explicitly setting some values). This syntax will move or copy individual fields to the new struct, so some fields of the old struct may become unusable.

#![allow(unused)]
fn main() {
let another_struct = Some_Struct {
	field1 : val1
	..old_struct
};
}

Tuple structs, e.g. struct Point(i32, i32) are like structs without names for fields. They let you define distinct types, but give you the dot operator and indexing of tuples.

struct Color(u8, u8, u8, u8);
let color = Color(0,1,2,3);

Order matters and they can be destructured, like tuples. Field names are not provided. Dot access operator is also valid.

Unit-like structs are structs with no fields. They can simply serve as a basis to implement traits on.

struct UnitStruct;
let unit_struct = UnitStruct;

These are probably good for defining traits on.

Storing references in a struct requires the use of lifetimes.

println!(structure:?) is permissible if the structure implements Debug. println!(structure:#?) for pretty-print is also permissible with Debug. These are different than `dbg!(…)``. This will instead print to stderr, and it takes and returns ownership, rather than borrowing.

Method Syntax

Similar to Python’s fucky OOP basically moving functions into a struct namespace creates a method, but the first param must be a &self (mutable or not). This is shorthand for self : &Self which is shorthand for whatever self actually is in the impl.

struct SomeStruct ...
...
impl SomeStruct {
	fn some_function(&self) {...}
}

Automatic referencing and dereferencing - all arrow operators or other notions just get wrapped up in a simple dot operator.

In methods &self is shorthand for self : &Self. In the receiver type, you can do any of:

  • an immutable borrow (reading)
  • a mutable borrow (mutating)
  • or taking ownership (consuming)

Taking ownership is rare and more for a special circumstance of preventing the method caller from using the original structure afterward.

A rust convention for getters is to simply use the field name. This makes it read-only and provides a space for manipulation before returning the private value.

automatic referencing and dereferencing is possible because the receiver type is explicit. (I.e. there is no -> operator like in C++, only ..)

All methods are associated functions. An associated function without a self is like a static/class method. You use :: on the type to invoke it.

Specifying no self parameter in an impl block, like Python creates a sort of static method on the structure. (Rust uses the word namespace for both this, accessed by ImplName:: and for namespaces proper from modules.)

6 Enums and Pattern Matching

Enums can be like C-style enums, but they can be more like Java record types. You can have individual, static instantiations/variants imbued with different data.

Variants’ data can even be of different types. These can even be structs or other enums.

pub enum Thing {
    Variant1,
    Variant2{named_field: i32},
    Variant3(i32)

}

Enums can have methods. Enums can be generic.

Option<T> is how the concept of null is implemented. None is the equivalent variant.

The Match Control Flow Construct

In match expressions, enums support value binding. Matches are exhaustive. The catch-all (default) case just uses a variable rather than a value as the match arm. Using _ is the same, but the compiler will not issue a warning if the value is not used.

To do nothing with a branch, use the unit value. _ => ()

Concise Control Flow with if let

if let is basically a degenerate form of a match. It avoids some boilerplate for contriving an equivalent match expression.

You match on one variant and may perform variable binding.

An else in an if let is equivalent to a _ in a match block.

7 Managing Growing Projects

In growth order, Modules -> Files -> Crates -> Packages -> Workspaces

Crates are a rust construct, while packages are a cargo construct. Workspaces are a development time grouping of interrelated packages that evolve together.

Packages must have at least one crate. Only one can be a library crate.

src/main.rs and src/lib.rs are special names that will be detected as the crate root for Cargo. Then the build result will use the name given in the package manifest. src/bin can have other executable crates.

Defining Modules to Control Scope and Privacy

Basically mod declares a submodule.

pub on a module and on its members allows you to use those members in the context where you “include” it with mod. Otherwise, it is still visible to sibling and child modules.

Modules

These introduce namespaces, are related to crates and allow access specification. (Rust calls it “Privacy Boundary”).

mod some_module {
	fn some_function(){
		...
	}
}
pub some_public_function () {
	crate::some_module::some_function() // absolute path
	some_module::some_function() // relative path
}

For privacy boundaries, modules, structs, funtions, etc are all private. A child item can access its parent’s fields (so siblings can access each other) however a parent cannot access its child (nested) private fields.

To make something public, use pub before the identifier. super can be used to access the immediate parent scope.

Structs need a specifier on each field. Enums only need one at the top-level identifier, and all its variants a public by default.

std:: actually specifies an absolute path to the standard library. It is not specified in [dependencies] however because it “ships with Rust.”

There is a top-level crate (with the same semantics as a module) named crate. From it, absolute paths to other modules within the crate can be accessed. crate::SomeModule::

Use

Bringing in the parent module and referring the target field with the parent’s namespace is idiomatic for functions. For structs and enums, it is idiomatic to refer to the entire path

use std::io; is an example of including packages. use rand::Rng; is an example of using traits. use std::cmp::Ordering; for an enumeration

as is used in the same way as Python to rename something included. pub use allows reexporting or making something that is private and nested some levels in the inner scope to be public to the outter/world.

Nested paths work with use.

use std
use std::io
use std::cmp
// OR
use std::{self,io,cmp} // Self works here too!

Glob Operator

This works for including things. It is not advised but convenient for writing test code, or for this “prelude pattern.”

use std::collections::*

File Separation

use <PKG>; with a semi-colon rather than block means loading defs from a file with the same name as the package.

8 Common Collections

Vectors

v : Vec<i32> = Vec::new(); // declaration by function
v = vec![1, 2, 3];	   // declaration by macro
v.push(4)
let elem : &i32 = &v[2]; // gets reference, good for crashing in error handling
let elem2 = v.get(3); // gets Option<&T>

Iterating over immutable references, then mutable
```Rust
let v = vec![100, 32, 57];
for i in &v {
    println!("{}", i);
}

let mut v = vec![100, 32, 57];
for i in &mut v {
    *i += 50;
}

Indexing with [] can cause a panic. .get() returns an Option.

You can iterate over a vector mutably or immutably. Regardless, you cannot mutate the vector reference itself at that point.

Wrapping different types in enum variants lets you make a vector of one enum type. Then you essentially have a vector of different types.

Strings

A string slice is str. Usually it is borrowed as &str. The data of the string is stored elsewhere.

String literals are stored in the program binary. They are one form of string slices.

Concatenate with +, format!(), .push_str(), and for single chars, .push().

+ looks weird, because the first argument is the String itself (consumes). The second is an &str.

When adding multiple, it looks weird, so format!() is a good idea.

Indexing into string slices requires a range. string[0..2] This is because indexing could represent bytes, characters, or graphemes. This is dangerous though, and could cause a panic at runtime. .chars() and .bytes() are useful methods for iteration.

.split_whitespace() is a solid method.

HashMaps

HashMaps are not in the prelude for the core language, but they can be included from the standard library. They also cover the idea of dictionaries/associative arrays in Rust.

use std::collections::HashMap;

One way to generate a HashMap is to create iterators from vectors with .to_iter() and then calling .zip(...) to create tuple pairs, and finally .collect() to return to an annotated HashMap<_,_>

.get() returns an Option<T> as usual.

.insert() for new values or for overridding

.entry() returns an Entry, from which or_insert() may be called to conditionally insert (only new values), and a ref to the value is returned.

.split_whitespace()

There’s a sort of “structured binding” for key-value pairs.

for (key, value) in &scores {
    println!("{}: {}", key, value);
}

HashMaps may either own their keys and values, or they may have references to them. entry(...).or_insert() is a decently powerful idiom for HashMaps.

9 Error Handling

Functions, many from the standard library, return a Result enumeration. These are generic and specialized for different modules, like std::io.

These errors must be handled (???: before end of scope or their lifetimes?). .unwrap() may be used as a more convenient alternative to a match expression to bind the success value or call panic!() on failure.

Result also contains an expect method to add error handling throughout the code. This is like unwrap but one can provide the message to panic.

The ? operator allows error propagation by either returning the wrapped Ok value or by returning the entire wrapping of the Err value. This uses a from() function to convert the returned Err to the calling functions return Err.

These can be chained as in File::open("hello.txt")?.read_to_string(&mut s)?;

std::ops::Try is the trait behind Option and Result.

fn main() -> Result<(), Box<dyn Error>> is main’s other valid return type.

Result

Result<T, E> unwrap_or_else() allows a closure for not sunny cases. unwrap() may simply panic. expect() is similar but you provide a message.

? is the error propagation operator. The function must have a Result return type. The operator also adds a From implementation to the error to convert it to the return type.

This may also be used with Option where the early return is None. These cannot be mixed and matched with Result though. Anything that implements FromResidual can actually be used.

Main may return Result<(), Box<dyn Error>. The latter is a trait object, but that is not explained here. Main may return anything that implements std::process::Termination. That gives a report function that returns an ExitCode.

Panic is good for tests, prototypes, or examples. It is also good when the caller has no way of course correction. For example, only having bad input to supply to a function. This is a contract violation.

Basically use Result if you can recover.

Panic!

The panic!("Message"); macro causes Rust to either unwind the stack and exit or to abort and leave the OS to clean up the memory.

To allow aborting, in Cargo.toml append to the appropriate profile.

[profile.release]
panic = 'abort'

RUST_BACKTRACE is an environment variable which if set to 1 (or further to ‘FULL’) will give backtraces at panicking.

10 Generics, Types, Traits, and Lifetimes

Generics Data Types

Use generics when you find that your code only differs by types (think a payload sender generic over two different parts of an application with different types).

Also, use generics if you are expressing logic of how some types relate to each other without using the type details. Say, collections.

Traits may be used as basically concepts/constraints, called trait bounds. <T: std::cmp::PartialOrd>

Type parameters may be applied to structs.

#![allow(unused)]
fn main() {
struct Point<X, Y>{
    x: X,
    y: Y,
}
}

Type parameters may be added to implementations. impl<T> Something<T>

Specifying the type parameter the first time ties it to the second specification. This lets the compiler know that this isn’t a simple implementation for a concrete type T. I.e. This disambiguates specialization of concrete types impl Something<f32>

At the same time, methods within the impl can have their own separate type parameter.

#![allow(unused)]
fn main() {
    fn mixup<X2, Y2>(other: Point<X2, Y2>) -> Point<X1, Y2> {
         Point<X1, Y2> {
             x: self.x,
             y: other.y
         }
    }
}

Enums may be generic. Option <T> has one parameter and Result<T, E> has two.

Monomorphization is Rust’s name for type erasure or name mangling.

Traits: Defining Shared Behavior

They are similar to interfaces.

Traits are functionality shareable with other types.

Trait definitions are a way to group method signatures together to define a set of behaviors necessary to accomplish some purpose.

The orphan rule as part of coherence means to implement a trait on a type, the trait or the type must be local.

Traits may provide default implementations in their definition.

This lends to the template method pattern. A default implementation may call other methods that have no default. Thus only those need to be implemented to give the higher level method.

An overriding trait method cannot call the default method.

impl Trait syntax is basically taking a trait as a function parameter. It is syntactic sugar for trait bound syntax which is the same but shows the trait as a type parameter.

Compare these. The latter restricts types to be the same. pub fn notify(item1: &impl Summary, item2: &impl Summary) { And pub fn notify<T: Summary>(item1: &T, item2: &T) {

Multiple trait bounds can be expressed with +.

Where clauses are nice.

You can return an impl Trait. The caller will only see the trait object.

Blanket implementation is implementing a trait on anything that implements another trait.

#![allow(unused)]
fn main() {
impl<T: Display> ToString for T {
    // --snip--
}
}

Lifetimes

Lifetime parameters only make sense on references.

It seems the generic lifetime parameters just link formal parameters with the return type. These are input lifetimes and output lifetime for functions.

There are lifetime elision rules that are not quite full lifetime inference.

  1. Every input parameter gets an input lifetime.
  2. If there is only one input lifetime, it is assigned to the output lifetime. (Having an output lifetime unrelated to input doesn’t make sense, because independently created references would become dangling)
  3. If self is present, it’s lifetime is assigned to the output lifetime (makes methods cleaner often).

11 Testing

Using attributes enables unit (and integration) tests. These are the #[] above some definitions.

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}

cargo test can be used to build the test module and run all unit tests in separate threads.

assert_eq!(), assert_ne!(), assert!(), are useful macros for unit tests. The first two provide a bit more detail to cargo by default.

Any string after the arguments is passed to format!() for more detailed. #[should_panic] can be attributed after a #[test] and can even be made to match on specific panic messages with a parameter.

#[test]
#[should_panic(expected = "some substring")]

Result<T,E> can also be returned by tests (so, Ok(value) for success or Err(message) for failure. This allows the ? to be used.

#[ignored] is useful.

#[cfg(test)] is on the module. #[test] is on the function.

assert!(), assert_eq!(), and assert_ne!() macros are available.

The latter two require their operands to have implemented both PartialEq and Debug for comparison and printing respectively.

#[should_panic] and #[should_panic, expected="..."] are useful.

Tests can also not be based on panicking. Then they return Result<T, E> (e.g. Result<(), String>). To check for an Err variant, use assert!(value.is_err()).

Tests run in parallel by default. This means if a test shares resources like a file, either copies of resources must be made, or tests must be run serially, or I guess some synchronization could be done.

Flags can be passed to: show success output, filter by name (including test module name), and run ignored tests.

#[ignore] goes after the test macro.

Unit Tests

#[cfg(test)] means to only compile the module when the configuration attribute includes the test parameter (this is provided by cargo test).

Integration Tests

For Cargo under tests/*.rs all files will be compiled as separate test crates ; however, source files under subfolders will not be (so common code may be extracted).

Modules here do not need the configuration attribute, since the folder path implies compilation specifically for testing.

Binary crates do not have integration tests, only library crates.

Unit test convention is to have the #[#cfg(test)] module in the source file alongside the code. This macro will only have the test code built with cargo test. This makes use super::*; common.

Integration tests are specifically for the public API and use a tests/ directory. Each file is a separate crate representing a separate integration. cargo test --test <file> will target only that integration.

Subdirectories under tests/ do not get handled as files directly under it do. This may be used to provide common code to share between integration tests.

Integration tests are only for library crates src/lib.rs. However, a binary crate that factors out its functionality may then use them.

Automated Tests

cargo test -- --test-threads=1 can be used to run tests serially (no parallelism). cargo test <PATTERN> will match test functions names on a pattern. Test modules become a part of this pattern. cargo test -- --ignored runs the ignored tests only.

12 Command Line Program

The configuration structure and run function are broken out into library code. The run function returns a Result<(), Box<dyn Error>> which can be propagated. That is handled with a process exit code in main.

Environment variables are accessed with env::var. CLI arguments are accessed with env::args(). It also uses std::process for exit codes.

std::env::var Printing to standard error may be done with eprintln!().

13 Functional Features

Closures

Closures are basically lambdas. let foo = || x + 2; The syntax can be annotated or pretty reduced. Closures pass arguments in the same three ways as functions. Explicitly taking ownership (moving/capturing) can be done with move.

Functions that take closures may have their parameters trait bound. There are three Fn traits. FnOnce means the closure gives back ownership of something it captured. The means it cannot be called again. FnMut mutates something it captures. It can be called more than once. Fn does neither, so it can be called more than once and concurrently.

Iterators

Iterators are used for functional programming style and allow the abstraction of often more mundane iteration tasks (such as on CLI arguments).

zero-cost abstraction coined by Stroustrup. This sort of means that lower-level code that is hand-written is subject to inoptimization and higher-level abstractions may be more optimized by the compiler (nothing is lost by using higher-level abstractions).

The iterator trait is pretty simple. It has an associated type though. That has its own syntax. iter(), iter_mut(), into_iter() provide the three forms of getting values. The first is an immutable reference and the last is ownership.

There are consuming adapters like .sum() and .collect(). These use up the iterator and produce a result based on all the items.

There are iterator adapters which produce a new iterator by changing the original. An example of this is .map() which takes a closure, applied for each item.

Then there is a good demonstration of improving the handling of env::args (an iterator) by directly using that rather than collecting it into a vec.

Also there is an example of, instead of declaring a temporary buffer, looping through lines, and filtering by assigning to the buffer, a simple iterator adapter .filter() is used. This shows that iterators are basically loops as objects which can have operations applied to them.

14 Cargo

crates.io Existing repos can be easily translated to cargo repos.

cargo new <PKG> or cargo new --lib <PKG>

In the package… cargo build cargo build –release cargo run cargo check cargo update cargo doc –open # builds and presents all dependency docs

Specifying dependencies uses SemVer.

[dependencies]
a_pkg = "3.4.1"

A bare version number is shorthand for “^3.4.1” which really matches any version that is API-compatible (so, up to the next minor release).

Locking

Cargo.lock contains version numbers of dependencies where the last stable build was made. These will not update unless cargo update is run.

Even with an update, the dependency will not roll to the next minor release unless the Cargo.toml file is actually changed.

Crates

Packages (the source repo started by Cargo) can either contain (or produce, in a sense) either binary crates or a single library crate.

Implicit Crate

There is a top-level crate (with the same semantics as a module) named crate. From it, absolute paths to other modules within the crate can be accessed. crate::SomeModule::

Automated Tests

cargo test -- --test-threads=1 can be used to run tests serially (no parallelism). cargo test <PATTERN> will match test functions names on a pattern. Test modules become a part of this pattern. cargo test -- --ignored runs the ignored tests only.

Release profiles

These are different configuration options in the TOML file for different kinds of releases of the software.

[profile.dev], [profile.release], etc.

Packaging

The [package] tag is used. Under this is specified common data with which to upload a software package to crates.io.

cargo login uses ~/.cargo/credentials to store the private API token.

???: Is there a way to spin up a common registry for Rust crates? There must be.

cargo yank --vers x.y.z locks prevents future projects from using your software version within their Cargo.lock file. It does not delete code. cargo yank --vers x.y.z --undo undoes this (unsurprisingly).

Workspaces

a set of packages that share the same Cargo.lock and output directory.

├── Cargo.lock
├── Cargo.toml
├── add-one
│   ├── Cargo.toml
│   └── src
│       └── lib.rs
├── adder
│   ├── Cargo.toml
│   └── src
│       └── main.rs
└── target

Different versions of dependencies within different TOML files will be resolved and will be decided within the top-level Cargo.lock file.

Dependency paths must be added in one crate’s toml file to another crate in order to use that crate. use statements must still be used.

cargo run -p <CRATE> allows one to run a specific crate in the workspace. cargo test -p <CRATE>

cargo install can be used to additionally install extensions to Cargo itself, so called cargo-<NAME>. These can then be run as cargo <SUBCOMMAND>.

Cargo packages are intended for developers, not system operation. (apparently)

15 Smart Pointers

Smart pointers own their data, unlike references.

Smart pointers are structs that implement Deref and Drop

  • String and Vec<T>
  • Box<T> - heap allocation
  • Rc<T> - reference counting
  • Ref<T>, RefMut<T>, RefCell<T> enforce borrowing rules at runtime rather than at compile time.

Standard pointers in Rust are like references but can own their data.

interior mutability pattern

Box<T> is a for simple heap allocation. It is useful in, say, creating recursive types.

A box in the standard library is basically a tuple of one element. This element implements Deref, so that the * operator may be called on it. This operator first gets a reference to the inner element (in the tuple). This would seem backwards. Then it de-references that to get and return the inner value.

Implicit Deref Coercions

Deref coercion is similar to automatic unboxing. It can do more though (or auto-unboxing is one type).

Passing references or pointers (such as Box<> values) may be automatically, implicitly dereferenced. It seems harry but makes the code look cleaner.

For example, Box<String> can be passed to &str and coerced to that type.

fn main() {
    let m = MyBox::new(String::from("Rust"));
    hello(&m);
}

Without deref coercion, you would need to write:

fn main() {
    let m = MyBox::new(String::from("Rust"));
    hello(&(*m)[..]);
}

There is also DerefMut. Per the book,

Rust does deref coercion when it finds types and trait implementations in three cases:

  • From &T to &U when T: Deref<Target=U>
  • From &mut T to &mut U when T: DerefMut<Target=U>
  • From &mut T to &U when T: Deref<Target=U>

Drop

Drop is the other trait included in the prelude to implement for a smart pointer. This executes right as the pointer goes out of scope.


impl Drop for CustomSmartPointer {
    fn drop(&mut self) { ... }}

It cannot be called manually if destruction is desired before end of scope. Instead, std::mem::drop() must be called. (Otherwise this would cause a double free error).

Reference Counting

std::rc::Rc is not brought into scope by the prelude. This allows multiple references to the same object (which will not be destructed until the final reference goes out of scope).

Declare a Rc<T> rather than Box<T> if ownership must be shared. Rc is for single-threaded applications only. Rc only allows immutable borrows.

For example, two pointers in two different objects point to the same data. Rc::clone(&some_rc) is convention over some_rc.clone() because it is unlike other cloning methods. Rather than make a deep-copy, it just bumps the reference count.

The count may be gotten with Rc::strong_count(&rc).

Interior Mutability

This can be done with RefCel<T>.

RefCell<> moves borrow checking to runtime. This is useful for example for creating mock objects which must conform to immutable signatures but hold mutable data. (See the explanation below.)

Cell<> does this for copying data and Mutex<> for thread-safe scenarios.

It’s weird because it looks like it defeats the purpose of immutability. I think the idea is that the RefCel itself, the pointer, is constant but can point to mutable data. This seems to be the canonical construct in rust with this power, called interior mutability.

Violating the borrow checker’s rules with this will cause a runtime panic, not a compilation error.

The example is a long one, showing mocking for testing. Instead of state verification, it shows that the methods called on the collaborator objects by the method under test can be wired to verify the object under test.

This can be chained with Rc to get a shared pointer to mutable data, i.e. Rc<RefCel<T>>. Calling .borrow() returns an immutable pointer, specifically a Ref<T>. Calling .borrow_mut() returns a mutable pointer, specifically a RefMut<T>.

Mutex<T> is the thread-safe version of RefCel<T>.

Using Rc<T> can create reference cycles, like a cycle in a linked list. When the two original pointers to the two data are dropped, the internal linkages between them remain (accounted for in the reference counting). This means the memory would never be unallocated.

A way to avoid this is with Weak<T>, which is a type related to Rc<T>.

These are almost like symlinks v. hard links. They increase the .weak_count() but not .strong_count(). So if a weak link remains but the strong count hits zero, the memory is still unallocated.

It is the same otherwise, but semantically it doesn’t express ownership.

For example, in a tree, the parent has an Rc<T> to children nodes. The children nodes have a Weak<T> to their parent.

To use a Weak<T>, you have to weak.borrow().upgrade() and check the Option<T>. Or Rc::downgrade(&strong)

16 Fearless Concurrency

handle : JoinHandle = thread::spawn(|| {}) Can move captures into the thread. handle.join().unwrap() thread::sleep(time::Duration::from_secs(1))

Also, to avoid move into threads.

thread::scope(|s| {
        s.spawn(|| {
            println!("Here's a vector: {v:?}");
        });
    });

Messaging Passing

use std::sync::mpsc let (rx, tx) = mpsc::channel();

You can give a transmitter to another thread. Threads must own their transmitter (or I guess receiver).

Sending data moves it to the other thread. Sending returns a Result<T, E> so you can check if the channel already closed.

You can call recv on the receiver, which blocks but will return a Result<T, E>. An error will be returned when thecloses.

try_recv will return immediately, either with Some(T) or an Err if there are no messages.

You can also clone transmitters, fulfilling the name multiple producer single consumer (MPSC). So, multiple threads can have their own producer/transmitter.

Shared Memory

Messaging passing is the equivalent of a single owner of data. Shared memory is like having multiple owners.

This can be done with a std::sync::Mutex. A good metaphor is acquiring a microphone in a panel in order to speak among a crowd.

Mutex::new(...) returns a Mutex<T>. Calling .lock() will block and return a LockResult. It will be an Err variant if another thread with the lock panicked. Otherwise it will be a MutexGuard. That is a smart pointer which can be dereferenced to access/modify the value you care about. It will also unlock the mutex on its Drop implementation.

The problem with Mutexes (Mutices?) is that you need a shared reference among threads to make them useful. Thus you must wrap them into a reference counting construct like Rc<T>. Rc<T> is not thread-safe, however, but Arc<T> is. This is an atomic Rc.

There are other atomic primitives.

Using Arc<Mutex<T>> is analgous to Rc<RefCel<T>> in single-threaded world. This is because Mutex<T>, like RefCel<T> actually provides interior mutability.

Mutexes can lead to deadlocks.

Send and Sync

Both std::marker::{Send,Sync} are “marker traits”. All they do is mark the thing that implements it. If something implements Send, it is safe to move to another thread. Rc<T> cannot implement this, for example, because sending a .clone() could have logical rammifications (both clones update the same count).

If it implements Sync, immutable references to it can be sent to another thread. (If &T: Send then T: Sync.)

Implementing these yourself is part of unsafe rust. A type built only of types that have these markers will then have these markers themselves.

17 Fundamentals of Asynchronous Programming: Async, Await, Futures, and Streams

There is a trait Future, which is the backbone of asynchronous Rust.

async marks functions as asynchronous. They can be interrupted and resumed. Calling .await on a future is a time (an “await point”) for the async function to either continue immediately or be interrupted. (This lets the async runtime know it is a good time.) This is because a future is expected to take some amount of time, so it may make sense to .await it.

async functions actually compile to regular functions that return an anonymous implementation of Future. In other words,

async fn foo() -> bool {
    true
}

becomes

fn foo() -> impl Future<Output = bool> {
    async {
        true
    }
}

So there are just async and async move blocks.

An async runtime is basically a statemachine with an executor which is the side that executes the statemachine. select! can be used to await multiple async functions.

Async becomes concurrent when wrapping in tasks. You can join on tasks much like threads. You can use an async runtine’s (separate) join function to join multiple task handles. This will wait until all are complete.

Async messages/channels are similar to mpsc. However the receiver is mutable. rx.recv() also produces a Future. You can receive an unknown number of values with while let.

while let Some(value) = rx.recv().await { println!("received '{value}'"); }

However, the transmitter must close to end this loop. It will only close at the end of the transmitting task if the transmitting task owns the transmitter. For this, you need to async move.

join() has related methods like join3() to add more Futures. join!(...) can take any known number of Futures join_all(...) can take an iterator (unknown) of Futures (but they must have the same <Output = ...> type). It is a tradeoff. To create an iterator of Futures, you use a trait object. This is similar to Box::new(dyn Future<Output = ...>) but you must pin it. Box::pin(my_future). You don’t actually need the heap allocation, just the pin, so you can use a Pin<&mut dyn Future<Output = ...>> type. You can construct that with pin!(async {...}).

You can race() futures like joining then, but only one completes. You can also yield_now() to introduce an await point at any time.

18 OOP

Rust supports OOP in that it:

  • provides objects and methods via structs, enums, and implementations.
  • provides encapsulation with pub
  • provides limited inheritance with default trait implementations
  • provides bounded parametric polymorphism using generics and trait bounds

Trait objects allow dynamic dispatch, whereas generics allow static dispatch. Dynamic dispatch has a runtime penalty, but it makes the code more re-usable.

Dynamic dispatch is done with dyn. Basically you use a pointer to a trait object. The indirection is necessary, because you do not know the size of the backing implementation. field : Box<dyn T>

State Pattern

There is then an example of the state pattern, which is one of the GoF patterns (I think). This has a wrapper object that holds a state value. That state value is really a pointer to a trait object. The trait has methods that define the state’s transition to other states. Thus when any of those methods are called, the current state may transition to another state per its encapsulated implementation. The wrapper object also implements the trait and just forwards it to its current state.

The pointer to the trait is also wrapped with Option. This is necessary during state transition for the rust ownership system. This is so the state can be .take(), replaced with none, and then the value can transitioned and reassigned to the pointer of the wrapper object.

Then the chapter shows that this is all not as efficient as a more rust-y way. This way is to just define each trait implementation (the various states) as separate structs. Those then have methods that consume themselves and construct the next struct. This is much simpler because, it seems, the consumption semantics of rust are utilized rather than all the .take() nonsense.

19 Patterns and Matching

Patterns are a language construct used in several contexts.

The most obvious is at the beginning of match arms. Also they are used with if let and while let. Actually they are used with simple if, like in tuple destructuring. They are also used with function parameters and closure parameters.

Named variables in a pattern will shadow variables outside the match arm’s scope.

Refutable patterns are those that may fail, because they have some structure that may mismatch the value given.

Irrefutable will always match/bind. These could be a simple variable or an _.

let requires an irrefutable pattern while if let requires a refutable pattern. Otherwise each expression would be meaningless. match allows one branch to have an irrefutable arm.

let else might be a valid construct without an if. Hmm.

Syntax

You can match literals and named variables. Because named variables shadow higher scope variables, you cannot use them as conditionals in the match arm directly. You need a MatchGuard.

A | can join different conditions in a pattern.

You can destructure structs as well. You can also use struct field init shorthand to capture a component in a new, independent variable. You can also match with a field of a structure at a certain value.

The wildcard _ never binds. A name starting with an _ does (and takes ownership). However an unused warning will never be issued for of.

The .. syntax is like a wildcard but for a range. It can even appear in the middle of a tuple.

A match guard is basically just a <pattern> if ... => { } This allows using outter, non-shadowed variables. It is an and with the pattern, and the pattern can have or with |.

There is also the @ syntax. This can be applied to binding in a pattern to also test the value. The book shows an example of a range. id : id_variable @ 3..=7

20 Advanced Features

Unsafe

There are five things that unsafe rust gives you.

  • dereferencing raw pointers
  • calling unsafe functions or methods
  • accessing/modifying mutable static variables
  • implementing unsafe traits
  • accessing fields of a union

Raw Pointers

Raw pointers are similar to C-pointers.

For immutable (*const i32): let ro = &raw const num For mutable (*mut i32): let rw = &raw mut num

With a numeric address (a usize), you can cast it as a raw pointer. let r1 = some_address as *const i32; They may be declared anywhere but only dereferenced in an unsafe {} block

Unsafe Functions

Declare unsafe functions as unsafe fn foo(){} which can only be called in an unsafe block.

#![allow(unused)]
fn main() {
unsafe {
    unsafe_function();
}

unsafe fn unsafe_function() {
}
}

This seems redundant but is sort of a handshake between the caller and the subroutine to help minimize the scope of the unsafe function. I guess this is similar to minimizing scopes or error handling and async functions. Break up scope as much as you can.

Their example is sort of trivial, but they show using an assert to first confirm some data is good (splittable at some index), and then using an unsafe std library function to split an array and get two immutable references at once.

Extern Blocks

Using an extern block to declare foreign functions (like prototypes/signatures) is marked unsafe.

#![allow(unused)]
fn main() {
unsafe extern "C" {
    fn abs(input: i32) -> i32;
}
}

Here “C” isn’t really just the language, it’s C’s ABI. So any language that uses C’s ABI can be linked to this.

Calls to extern blocks (foreign function interface) must be wrapped in unsafe blocks.

But since we know C’s abs function is safe, we can mark it as safe. Then it doesn’t require an unsafe block at the call site.

#![allow(unused)]
fn main() {
unsafe extern "C" {
    safe fn abs(input: i32) -> i32;
}
}

Providing a function from Rust callable by foreign languages does require unsafe in the no_mangle attribute. This is because, without the compiler mangling function names, they could collide. So you have to make sure that won’t happen yourself. I guess that relates to monomorphization. Just like async, extern goes after visibility but before fn.

#[unsafe(no_mangle)]
pub extern "C" fn call_from_c() {
    println!("Just called a Rust function from C!");
}

Mutable Static

Basically const and static are similar, but static has a fixed memory address. Const is more about the value, not about storing… Therefore unlike const, static can be mutable.

I guess too, const is like constexpr, whereas static is like traditional const.

If a static is made mutable, then accessing/modifying is inherently unsafe.

static mut COUNTER: u32 = 0;

fn add_to_count(inc: u32) {
    unsafe {
        COUNTER += inc;
    }
}

Unsafe Traits and Impls

As with other categories, this is two things. Both marking a trait as unsafe when “at least one if its methods has invariant that the compiler can’t verify.”

#![allow(unused)]
fn main() {
unsafe trait Foo {
    // methods
}
}

And marking unsafe implementations, such as implementing Send and Sync for a struct containing raw pointers.

#![allow(unused)]
fn main() {
unsafe impl Foo for i32 {
    //
}
}

Accessing Fields of a Union

???

Miri

You can add the nightly rustup component miri to do dynamic analysis against unsafe rust code.

Advanced Traits

Associated Types v. Generic Traits

“Associated types let the implementor absorb the decision to determine a type, so that callers don’t have to carry the type everywhere.”

The key insight is: “Associated types also become part of the trait’s contract: implementors of the trait must provide a type to stand in for the associated type placeholder.”

The mental model: use an associated type when the type is an output or consequence of the implementing type (one right answer), and use a generic parameter when the trait should be implementable for many different types simultaneously (like From<T>).

Basically this is an alternative to generic traits. The difference is you can only implement traits with associated types once. It semantically indicates a different relationship: one implementor has “one output type”.

It is used specifically to constrain design. That constrain buys you things. It allows the compiler to infer types in places. It makes trait bounds simpler/cleaner.

Better yet, it also removes the burden of the caller to determine/specify type parameters at call sites, because they are already fully known.

For example, Iter has an associated type Item. The one implementing Iter specifies its type. Otherwise, the caller (constructor of the implementor) must also provide the type parameter that makes sense with the iterator.

For example, HashMap<K, V> implements iterator with Item = (K, V). Then map.iter() can be used. With a hypothetical Iter<T>, that “bubbles up” or percolates up to the caller, so they would have to specify HashMap<K, V, I>, but I is already known by the internals of the HashMap.

Technically, you could forward a type parameter from the implement or to the associated type. This would return you to having HashMap<K, V, T> and defeat the purpose of an associated type.

On the contrary, associated types enable GAT, or generic associated types. This let’s you have something advanced, like iterating over items from an implementor whose lifetime is bound to the implementor. Seems… Complex.

Default Generic Type Parameters and Operator Overloading

This has a pretty badass example with using the newtype pattern to create millimeter and meter types around i32, and then implementing add for millimeters. That defaults to adding another millimeters to the RHS, however, another implementation can be used to implement adding meters. The associated type for both is the single, correct output type of millimeters.

Extra about custom literals…

TechniqueSyntaxNotes
ConstructorMeters::new(5.0)Most idiomatic
Into5.0.into()Requires type annotation
Macrom!(5.0)Closest to custom literals
Extension trait5.0_f64.m()Most fluent/ergonomic
Operator overloadingm!(5) + m!(3)Combine with any
The extension trait + operator overloading combo is as close to custom literal ergonomics as you’ll get in Rust today. There’s a long-standing desire for proper custom literals in the community, but it hasn’t made it into the language yet.

Disambiguating Between Methods with the Same Name

Implementors can implement multiple methods from different traits with the same name, and even their own method of the same name.

Their own, direct method is preferred.

To then specify one of the other methods, you use that reversed syntax similar to String::from, like

#![allow(unused)]
fn main() {
MyTrait::method(&my_obj);
}

Left off at… “However, associated functions that are not”

If you’re “overriding” an associated function from a trait with an implementor’s own method, then you have to use fully qualified syntax to invoke the associated function. So like…

#![allow(unused)]
fn main() {
<Dog as Animal>::baby_name();
}

Supertraits

Basically this is Java’s extend syntax, but on traits. It is syntactic sugar for taking a bound on Self. In other words,

#![allow(unused)]
fn main() {
trait Warrior: Fighter {}

// equivalent to

trait Warrior where Self: Fighter {}
}

Newtype Capability

Newtype let’s you get past the orphan rule. You can implement external traits on external types, because you’re implementing them on the wrapper.

But then, to make something like “embedding” (Go terminology), you would have to implement Deref on the wrapper.

Advanced Types

Newtype Pattern v. Type Aliases

Basically this just says, use newtype to not confuse units and to further minimally hide private APIs/restrict types.

Meanwhile, an actually type alias

Empty/Never Type

The type ! is used when something diverges or never returns. This can be coerced into any type. So like, a match arm that diverges will work with any return type. I guess that also explains let ... else { ... }

Unsized Types

str and trait objects are unsized. str is because different objects have different lengths, yet for one type, there must be one size.

So, these must be used behind a pointer of any kind. References are typical but others work.

Generics implicitly take a Sized bound, but you can overrideit with

#![allow(unused)]
fn main() {
fn too<T: ?Sized>(t: &T) {
    // t can be any pointer.
}
}

t must still be a pointer type despite the trait bound. The ? is special only for the Sized bound, which means may or may not.

Advanced Functions and Closures

You can take function pointers as arguments. This is type fn as opposed to traits like trait Fn.

#![allow(unused)]
fn main() {
fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 { f(arg) + f(arg) }
}

Function pointers can be coerced to those traits/closures. They are flexible as arguments, but the reciprocal is true for parameters. Requiring a function pointer as an argument makes you unable to pass closures. So accepting one of the closure traits is best.

The name of enum variants become initializer functions, which become function pointers, which can be coerced into closures. For example:

#![allow(unused)]
fn main() {
enum Color {
    RGB(u64),
    GrayScale
}
let color_list: Vec<Color> = (0u64..20u64).map(Color::RGB).collect();
}

Returning Closures

You can return a closure as a function pointer if it doesn’t capture anything. If it does, you can return it with the impl trait syntax. But if you are trying to call it more than once and return different opaque types, you need to use Box<dyn Fn(param) -> Retval>

Macros

There are declarative macros and 3 procedural macros. Declarative are the macro_rules!. Procedural include:

  • custom derive on structs and enums
  • attribute macro on any type
  • function-like macros

Macros can provide function overloading (taking a variable number of arguments anyway).

Macros must be written above where they are called, unlike functions.

Declarative macros are basically match expressions, but against rust code, and they cause code generation in the macro’s place.

#![allow(unused)]
fn main() {

`#[macro_export]`
macro_rules! guh {
    ( $() ) => { ... };
}
}

The Little Book of Rust Macros

Derive macros have way more steps.

  1. First you create a crate for your trait.
  2. Then you need to create a separate, sub-crate (conventionally named with _derive) .
  3. It must have proc-macro = true in its Cargo.toml
  4. You use a macro on your derivation function, tale in a TokenStream and return a TokenStream.
  5. Then you normally use the syn and quote crates to parse and generate rust code respectively.
  6. stringify! keeps expressions unevaluated for the macro.

Attribute macros are very similar, but more flexible. You use #[proc_macro_attribute] rather than #[process_macro_derive]. Then you write a function that takes two token streams, the first is the attribute and the second whatever is wraps.

Function-like are similar to derive in that they take one token stream. They use #[proc_macro].

Async / Await

Concurrent programming is writing code in such a way that it appears to do multiple things at once.

It is entirely within the program.

It cannot make the program faster, but it can make the program more responsive.

Threads are owned and managed by the OS. One process may have multiple threads. Threads share memory.

Tasks on the other hand are managed by the asynchronous runtime within the program.

The OS preemptively schedules threads to run. It context switches to do so. Tasks, at least with Rust’s tokio runtime are cooperative. They voluntarily yield control.

Green threads typically refer to tasks that are preemptive. Also, tasks are internally structurally different from threads.

Async IO is separate from, but often used with, async concurrency. It is also called “nonblocking IO”.

Instead of a thread blocking and waiting doe the OS while other threads run, the OS does not block the program with the async runtime. The async runtime returns control to a different task. Then when IO results are available, the runtime provides it to the waiting task.

Often programs use both async tasks and threads. Sometimes the async runtime uses multiple threads without them being written into the programming logic. This may be necessary because only threads can execute on multiple cores for parallelism.

Zero processing and synchronization requiring tasks present a challenge for scheduling algorithms.

Concurrency is a pattern controlled by the code and parallelism is a resource provided by the scheduler.

A task group could be an idea of assigning all tasks to one thread locked to one core, so they run concurrently but never in parallel.

Runtimes have a reactor/event loop/driver, scheduler, and _executor/runtime.

Calling await joins the future’s execution to the current async task.

Sleeping a task uses the runtime’s sleep method, not the thread sleep method.

Actually making tasks concurrent requires that the task be spawned, not awaited.

Spawning a task returns a JoinHandle future. Awaiting that future is like joining a thread.

Per John Moon

Style/idiom linting: cargo clippy on project Building configs into the binary: macro include_str Command line arguments: clap-rs Printing structs: #[derive(Debug)] then println!("{:?}", my_struct)

Rocket

The lifecycle is:

  1. routing
  2. validation
  3. processing
  4. response

Routes have #[get], put, post, delete, head, patch, or options.

There are two kinds of entrypoints. #[launch] and #[rocket::main]

Head requests are handled automatically if there is only a get route (no explicit head route).

Rocket will reinterpret web forms submitted by post as a different HTTP method if the content type and form’s first field fulfill some requirements. This gets around web browsers’ only supporting forms with get and post.

Dynamic paths use <variable> in the path of the route. A segment is one part of a route between slashes.

These dynamic segments bind to function parameters. Any type implementing FromParam can be used as the parameter. These are parameter guards.

With segment guards, a parameter may bind to the rest of a path. In the path, there is <path..>. The parameter must implement FromSegments.

There is an example of serving a static file with a route. There is an example of using a one line file server with no route (but still a mount point).

Ignore segments with <_> and <_..>.

Rocket forwards failed parameter bindings to the next route. A failure on the final forwarding guard triggers the error catcher.

You can bind to an Option<> or Result<> and not deal with forwarding. The rank parameter in a route may be necessary to resolve collisions.

Automatically assigned ranks have negative values (higher precedence). Basically the more specific a route and more specific a query, the higher the precedence. This uses a system of “colors”.

  • static
  • partial
  • wild
  • none

Exam

What inspires you to learn something new?

For me, there are several motivating factors: novelty, effectiveness and efficiency, helpfulness, and competitiveness. Novelty is the simplest, intrinsic motivation, or as a coworker termed it, “chasing the shiny”. I take a simple joy in discovering new ways to think about problems or finding elegant solutions. For example, at my most recent workplace, we switched from a pattern of using GNU make to using a new tool Earthly. The new tool was highly compatible with Docker (in a CI/CD or build context) but also provided the DAG semantics that GNU make provides.

There is also the matter of effectiveness at solving the problem at hand. That is, I want to learn the new thing that is “the tool for the job”. For example, on a recent project, I had to write a micro-service to integrate with gRPC, Helm, and NATS. Many on our team had opted for Java or Python for their services, but only Golang had native integrations for all three. I dove into it eagerly. As it turned out, Go was also more efficient, with a much faster turn-around for prototypes, compared to getting Java (and Maven) working in our environment.

I am also motivated by becoming more efficient. In terms of the “1% rule”, if I become 1% more efficient each day, the compound effect is enormous. For example, integrating AI into my workflow with Ollama and Continue has certainly granted this and more.

Similarly, remaining competitive with the market is a huge motivation for me to learn new things. For example, Rust and Go are two languages that are “hotter” on the market, especially with the Department of Defense aiming to replace legacy C++ systems with Rust, and the Linux kernel starting new modules in Rust instead of C. Aligning my own projects on my own time is one way I do this. For example, I have been switching my personal website from the static site generator Cobalt (written in rust) to Rocket (an actual rust library, similar to Python’s flask) plus MdBook (the rust library that the rust documentation is processed with).

Lastly, learning new things lets me be more helpful in the workplace. I had the privilege of working for several years with a “10x developer” (or so we liked to refer to him as), who always seemed to have a solution when I was spinning my wheels. It was very inspiring for me to become the same in my professional growth. Although I can’t dive into every technology, I can try to constantly add tools to my toolbox and increase my vocabulary to navigate new problems when they arise.

What’s one professional achievement you are particularly proud of, and why?

<p>I am particularly proud of my work on one software "candidate" (or "epic" in agile methodology terms) called the "diamond" because of its deadline, scope, and my execution of it. The diamond was a "symbology"  (or symbol) drawn on the HUD (heads-up display) of the A-10 aircraft. Anything in the pilot's line of sight that fell within the diamond was defined to be in range of the heat-seeking laser rockets. The diamond had been designed by some systems engineers but no implementation was started yet.</p><p><br></p><p>In terms of deadline, the diamond had been a "want-to-have" candidate that had been pushed out several times. We were nearing the end of our software release cycle, but I felt confident that with enough effort and focus, I could complete it. I volunteered to take it on. The estimate of time it would take has been one of my most accurate in my professional career, likely because I had had great exposure to the different subsystems of the A-10. On the last long day of the implementation phase, right before the "code freeze", I had my last successful test on the high fidelity test stand.</p><p><br></p><p>In terms of scope, the diamond touched three major subsystems of the aircraft. While it was displayed alone on the HUD through vector graphics (and an assembly language), command-and-control of the drawing hardware was done through another system. That system also plumbed values used for the diamond by yet another system. The data flow was complex, but fortunately, I had previously volunteered to work all of the various subsystems that it required, including legacy ones.</p><p><br></p><p>Lastly, in terms of my execution, it was a rare software problem that felt like "pure development". The effort was not wasted in monotonous tasking, such as for information foraging or software approvals. Once I had the data properly plumbed, it was a joy of algorithm design and mathematical calculation. I determined the correct formulas for drawing the vectors based on the input and translating that to the assembly language of the HUD.</p>

What new skill are you interested in learning?

<p>There are several new skills I am interested in learning, ultimately to center my technical stack and increase my knowledge of the domain. To center my technical stack, these include rust libraries focused on command-and-control, tooling for behavior-driven development and software architecture. To increase my knowledge of the domain, this includes things like launch stages, mission assurance, space observability, signal processing, etc.</p>

Please share how you resolved a conflict within your team.

<p>Our team had a long running issue of what versioning strategy should be used in a new system-of-systems. Many of the components we had inherited from other teams and times, and at least one was from an external party. This meant there were many different versioning strategies, such as SemVer or simply raw dates. Sometimes source repositories would use things like git submodules, or during build time, they would pull in dependencies from other projects.</p><p><br></p><p>We had a meeting about this, but there was not a clear agenda, and it was unclear who would take responsibility for making the final decision. Many of the positions in the meeting had overlap, but ultimately, no decision was made. An email chain begun by a grumpy systems engineer asked what progress was made and when would a ruling be made.</p><p><br></p><p>I captured the positions of the team members on how to do the versioning, and I explained in-depth how my solution would cover their needs. In particular, the boundaries of a source repository should not be determined by semantics (or what seems "sensible"), or by how big the repository is, or otherwise. Instead it should be handled by what can be versioned independently. I then broke out all of the components in the new system-of-systems, and how we might proceed implementing it. At the end of my explanation, I asked if this solution was sufficient, or if not, what particular shortcomings it had. Ultimately, the team lead agreed with my position and championed it, so it was implemented.</p>

What does the await operator do in Rust?

<p>Conceptually, it adds the execution of the future it is called on (some asynchronous task) to the current asynchronous task. If that asynchronous task can complete without blocking, it does so and returns immediately. If it must block, the async runtime may switch to another task.</p>

Menu

A curated selection from our recipe collection.

☕ Beverages

🥖 Appetizers

  • Artichoke Spinach Dip Artichoke hearts, fresh spinach, cashew cream, nutritional yeast, garlic, lemon juice, salt, pepper
  • Bacon Wrapped Dates Medjool dates, goat cheese, bacon strips, optional honey, optional almonds

🍞 Baked Goods

  • Banana Chocolate Chip Bread Ripe bananas, flour, sugar or sweetener, eggs, butter or oil, chocolate chips, baking soda, vanilla extract, salt

🍳 Breakfast

  • Egg Scramble Eggs, ground beef, sweet potato, black beans, green enchilada sauce, onions, cumin, chili powder
  • Proplto Pancakes Purple potatoes, eggs, protein powder, oat flour, baking powder, cinnamon, salt, milk

🎄 Seasonal Favorites

  • Eggnog Raw cultured cream, raw eggs, vanilla extract, nutmeg, raw honey, peppermint tea, cacao nibs
  • Gingerbread Fruitcake Muffins Pastry flour, baking soda, buttermilk, butter, allulose, eggs, molasses, dried fruits, chopped nuts, cinnamon, cloves, ginger, salt, vanilla extract

🍨 Desserts

  • Roasted Peaches Fresh peaches, honey, fresh mint leaves, vanilla ice cream, butter, optional cinnamon

🍽️ Main Dishes

🥗 Sides

  • Roasted Vegetables Mixed vegetables (Brussels sprouts, carrots, bell peppers, zucchini), olive oil, salt, pepper, herbs (rosemary, thyme), garlic
  • Cabbage Steaks Cabbage, olive oil, salt, pepper, garlic powder, optional balsamic glaze

Cookbook

This is a growing collection. From holiday traditions to camping food, these recipes have been tested and enjoyed with friends and family.

Beverages

Coffee, tea, and other drinks for all year round.

Pour-Over Black Coffee

Source: Matt

Ingredients

  • 20-25g freshly ground coffee (medium-fine grind)
  • 350ml hot water (195-205°F)

Instructions

  1. Place filter in dripper, rinse with hot water.
  2. Add ground coffee, create small well in center.
  3. Pour 50ml water in circular motion, let bloom 30 seconds.
  4. Continue pouring in slow circles until reaching 350ml total.
  5. Total brew time: 2.5-3.5 minutes.

London Fog

Source: Matt

Ingredients

  • 1 Earl Grey tea bag
  • 1 cup hot water
  • 1/2 cup steamed milk
  • 1 tsp manuka honey
  • Optional: vanilla extract

Instructions

  1. Steep Earl Grey tea in hot water for 3-4 minutes.
  2. Steam or heat milk until frothy.
  3. Remove tea bag, stir in honey.
  4. Pour steamed milk over tea.
  5. Optional: add a drop of vanilla extract.

French Press Black Coffee

Source: Matt

Ingredients

  • 30g coarse ground coffee
  • 500ml hot water (195-205°F)

Instructions

  1. Add ground coffee to French press.
  2. Pour hot water over grounds, stir gently.
  3. Place lid on press, don’t plunge yet.
  4. Steep for 4 minutes.
  5. Slowly press plunger down.
  6. Serve immediately.

Milkshake

Source: Matt

Ingredients

  • 240ml heavy cream
  • 120ml milk
  • 120g blackberries
  • 100g Medjool dates
  • 30g vanilla whey protein
  • 5ml vanilla extract
  • 10g manuka honey
  • 2 tbsp peanut butter

Appetizers

Starters and finger foods.

Artichoke Spinach Dip

Source: Abby

Description

Gluten-free and dairy-free version.

Ingredients

  • Artichoke hearts, chopped
  • Fresh spinach
  • Cashew cream or dairy-free cream cheese
  • Nutritional yeast
  • Garlic
  • Lemon juice
  • Salt, pepper
  • Optional: dairy-free parmesan

Instructions

  1. Sauté spinach and garlic until wilted.
  2. Mix with chopped artichokes and cashew cream.
  3. Add nutritional yeast, lemon juice, seasonings.
  4. Bake at 350°F for 20 minutes until bubbly.
  5. Serve with crackers or vegetables.

Bacon Wrapped Dates

Source: Abby

Ingredients

  • Medjool dates, pitted
  • Goat cheese
  • Bacon strips, cut in half
  • Optional: honey for drizzling
  • Optional: almonds to stuff inside

Instructions

  1. Stuff each date with goat cheese (and almond if using).
  2. Wrap with half strip of bacon, secure with toothpick.
  3. Bake at 400°F for 15-20 minutes until bacon is crispy.
  4. Optional: drizzle with honey before serving.

Baked Goods

Breads, muffins, and bars.

Banana Chocolate Chip Bread

Source: Abby

Ingredients

  • Ripe bananas, mashed (3-4)
  • Flour
  • Sugar or sweetener
  • Eggs
  • Butter or oil
  • Chocolate chips
  • Baking soda
  • Vanilla extract
  • Salt
  • Optional: walnuts

Chocolate Mint Protein Gunk Bars

Source: Abby

Ingredients

  • Protein powder (chocolate)
  • Oats
  • Nut butter (peanut or almond)
  • Honey or maple syrup
  • Cocoa powder
  • Peppermint extract
  • Dark chocolate chips
  • Salt

Instructions

  1. Mix all ingredients until well combined.
  2. Press into pan lined with parchment.
  3. Refrigerate until firm, cut into bars.
  4. Store in fridge or freezer.

Zucchini and Chocolate Chip Bread

Source: Abby

Ingredients

  • Grated zucchini (about 2 cups)
  • Flour
  • Sugar or sweetener
  • Eggs
  • Oil or butter
  • Chocolate chips
  • Baking soda
  • Cinnamon
  • Vanilla extract
  • Salt

Carrot, Fig, Macadamia Bread

Source: Abby

Ingredients

  • Grated carrots
  • Dried figs, chopped
  • Macadamia nuts, chopped
  • Flour
  • Eggs
  • Oil or butter
  • Sweetener
  • Baking powder
  • Spices (cinnamon, nutmeg, ginger)
  • Vanilla extract
  • Salt

Purple Potato, Pecan Bread

Source: Abby

Ingredients

  • Purple potatoes, cooked and mashed
  • Pecans, chopped
  • Flour
  • Eggs
  • Oil or butter
  • Sweetener
  • Baking powder
  • Cinnamon
  • Vanilla extract
  • Salt

Breakfast Recipes

Morning meals to start your day.

German Pancakes

Source: Abby

Ingredients

  • Eggs
  • Milk
  • Flour
  • Butter
  • Salt
  • Vanilla extract (optional)

Instructions

  1. Blend eggs, milk, flour, and salt until smooth.
  2. Heat butter in a pan, pour thin layer of batter.
  3. Cook until edges lift, flip and cook other side.
  4. Serve with jam, cream, or savory fillings.

Pancake, Fried Ham, Runny Egg, & Avocado

Source: Abby

Description

A hearty breakfast stack.

Ingredients

  • Pancake batter
  • Ham slices
  • Eggs
  • Avocado
  • Butter for cooking

Assembly

  1. Cook pancake as base.
  2. Fry ham until crispy.
  3. Fry egg to desired doneness.
  4. Stack: pancake, ham, egg, sliced avocado on top.

Egg Scramble

Source: Abby

Ingredients

  • Eggs
  • Ground beef
  • Sweet potato, diced
  • Black beans
  • Green enchilada sauce
  • Onions
  • Seasonings (cumin, chili powder)

Instructions

  1. Cook ground beef with onions and seasonings.
  2. Add diced sweet potato, cook until tender.
  3. Add black beans and enchilada sauce, heat through.
  4. Scramble eggs in the mixture.

Proplto Pancakes

Source: Matt

Ingredients

  • Purple potatoes, cooked and mashed
  • Eggs
  • Protein powder (vanilla or unflavored)
  • Oat flour
  • Baking powder
  • Cinnamon
  • Salt
  • Milk

Instructions

  1. Mix mashed purple potatoes with eggs.
  2. Add protein powder, oat flour, baking powder, cinnamon, salt.
  3. Add milk to desired consistency.
  4. Cook on griddle like regular pancakes.

Meals

Main dishes and complete meals for everyday cooking.

Meatloaf, Purple Cabbage Slaw, & Parsnip Puree

Source: Abby

Description

A complete meal with meatloaf, colorful slaw, and creamy root vegetable puree.

Ingredients

Meatloaf:

  • Ground beef
  • Eggs
  • Breadcrumbs or oats
  • Onion, garlic
  • Seasonings

Purple Cabbage Slaw:

  • Purple cabbage, shredded
  • Carrots, shredded
  • Vinegar-based dressing

Parsnip Puree:

  • Parsnips, peeled and chopped
  • Butter
  • Cream or milk
  • Salt, pepper

Pistachio Liver Burgers

Source: Abby

Ingredients

  • Beef liver
  • Lion’s mane mushrooms
  • Ground beef
  • Crushed pistachios
  • Seasonings

Greek Bowls

Source: Abby

Ingredients

  • Protein of choice
  • Cucumber
  • Tomatoes
  • Red onion
  • Feta cheese
  • Olives
  • Tzatziki sauce

Miso Oats with Ground Beef

Source: Abby

Ingredients

  • Rolled oats
  • Ground beef
  • Miso paste
  • Scallions
  • Seasonings

Salmon Bowl

Source: Abby

Ingredients

  • Salmon fillet
  • Coconut rice
  • Cabbage slaw
  • Fresh mango
  • Sesame seeds

Pad Se Ew

Source: Abby

Description

Thai stir-fried noodle dish.

Ingredients

  • Wide rice noodles
  • Protein (chicken, beef, or tofu)
  • Chinese broccoli (gai lan)
  • Eggs
  • Dark soy sauce
  • Light soy sauce
  • Oyster sauce
  • Sugar
  • Garlic

Sushi

Source: Abby

Description

Homemade sushi rolls.

Ingredients

  • Sushi rice
  • Nori sheets
  • Fresh fish (salmon, tuna)
  • Avocado
  • Cucumber
  • Rice vinegar
  • Soy sauce
  • Wasabi
  • Pickled ginger

Pesto Chicken and Spaghetti Squash

Source: Abby

Ingredients

  • Chicken breast
  • Spaghetti squash
  • Basil pesto
  • Parmesan cheese
  • Cherry tomatoes
  • Garlic

Steak & Air-Fried Broccoli

Source: Abby

Ingredients

  • Steak (your preferred cut)
  • Fresh broccoli florets
  • Olive oil
  • Salt, pepper
  • Garlic powder

Apple Salmon Salad

Source: Abby

Ingredients

  • Cooked salmon
  • Mixed greens
  • Apple, diced
  • Celery, chopped
  • Red onion, diced
  • Walnuts
  • Lemon vinaigrette

Peanut Butter Chicken

Source: Matt

Ingredients

  • Chicken pieces
  • Natural peanut butter
  • Coconut milk
  • Soy sauce
  • Garlic
  • Ginger
  • Lime juice
  • Vegetables (bell peppers, carrots)

Side Dishes

Vegetables, salads, and accompaniments for all year round.

Stuffing

Source: Abby

Ingredients

  • Bread cubes (day-old)
  • Celery
  • Onions
  • Butter
  • Broth
  • Herbs (sage, thyme, parsley)
  • Eggs

Vinaigrette

Source: Abby

Description

Basic salad dressing.

Ingredients

  • Olive oil (3 parts)
  • Vinegar or lemon juice (1 part)
  • Dijon mustard
  • Honey
  • Salt, pepper
  • Garlic (optional)

Kale Dish

Source: Abby

Ingredients

  • Kale, chopped
  • Garlic
  • Olive oil
  • Lemon juice
  • Red pepper flakes
  • Parmesan (optional)

Roasted Vegetables

Source: Abby

Ingredients

  • Mixed vegetables (Brussels sprouts, carrots, bell peppers, zucchini)
  • Olive oil
  • Salt, pepper
  • Herbs (rosemary, thyme)
  • Garlic

Cabbage Steaks

Source: Matt

Ingredients

  • Cabbage, cut into thick slices
  • Olive oil
  • Salt, pepper
  • Garlic powder
  • Optional: balsamic glaze

Instructions

  1. Brush cabbage steaks with oil, season.
  2. Roast at 400°F for 25-30 minutes, flipping once.
  3. Drizzle with balsamic if desired.

Coconut Rice

Source: Abby

Ingredients

  • White or jasmine rice
  • Coconut milk
  • Water
  • Salt
  • Optional: lime zest, cilantro

Slow Cooker & Crock Pot Recipes

Hearty meals for the slow cooker.

Beef Kombucha Squash Red Curry

Source: Abby

Ingredients

  • Beef chunks
  • Squash, cubed
  • Kombucha
  • Red curry paste
  • Coconut milk
  • Vegetables
  • Spices

Balsamic Chicken and Sausage

Source: Abby

Ingredients

  • Chicken pieces
  • Italian sausage
  • Balsamic vinegar
  • Garlic
  • Onions
  • Herbs (rosemary, thyme)

Pot Roast

Source: Abby

Ingredients

  • Chuck roast
  • Potatoes
  • Carrots
  • Onions
  • Beef broth
  • Worcestershire sauce
  • Herbs

Chicken Sweet Yellow Curry

Source: Abby

Ingredients

  • Chicken pieces
  • Yellow curry paste
  • Coconut milk
  • Cauliflower rice
  • Bell peppers
  • Onions
  • Ginger, garlic

Beef Shank and Lentil Indian Curry

Source: Abby

Ingredients

  • Beef shanks
  • Lentils
  • Curry spices (turmeric, cumin, coriander, garam masala)
  • Tomatoes
  • Onions
  • Ginger, garlic
  • Coconut milk

Pork Roast or Ribs with Butternut Squash

Source: Abby

Ingredients

  • Pork roast or ribs
  • Butternut squash, cubed
  • Apples
  • Onions
  • Broth
  • Herbs and spices

Gumbo

Source: Abby

Ingredients

  • Andouille sausage
  • Chicken
  • Shrimp
  • Okra
  • Bell peppers
  • Celery
  • Onions (the “holy trinity”)
  • Roux (flour and oil)
  • Cajun spices
  • Rice for serving

Lamb Roasted Roman Style

Source: Abby

Ingredients

  • Lamb roast
  • Garlic
  • Rosemary
  • Anchovies
  • White wine
  • Olive oil
  • Potatoes

Taco Soup

Source: Abby

Ingredients

  • Ground beef or turkey
  • Black beans
  • Pinto beans
  • Corn
  • Diced tomatoes
  • Green chilies
  • Taco seasoning
  • Beef broth
  • Toppings: cheese, sour cream, avocado

Turkey Chili

Source: Abby

Ingredients

  • Ground turkey
  • Kidney beans
  • Black beans
  • Tomatoes
  • Onions
  • Bell peppers
  • Chili powder
  • Cumin
  • Garlic

Chicken Tortilla Soup

Source: Abby (from Mom)

Ingredients

  • Chicken breast
  • Black beans
  • Corn
  • Tomatoes
  • Chicken broth
  • Onions
  • Garlic
  • Cumin, chili powder
  • Tortilla strips
  • Toppings: cheese, avocado, cilantro, lime

Oxtail Stew

Source: Abby

Ingredients

  • Oxtails
  • Root vegetables (carrots, parsnips, turnips)
  • Onions
  • Garlic
  • Tomatoes
  • Beef broth
  • Red wine
  • Herbs (bay leaf, thyme)

Desserts

Sweet treats and after-dinner delights.

Ruby Cake

Source: Abby

Ingredients

  • Flour
  • Sugar
  • Cocoa powder
  • Eggs
  • Butter or oil
  • Buttermilk
  • Red food coloring
  • Baking soda
  • Vanilla extract
  • Salt

Pumpkin Pie

Source: Abby

Ingredients

  • Pie crust
  • Pumpkin puree (fresh or canned)
  • Eggs
  • Heavy cream or evaporated milk
  • Sugar or sweetener
  • Cinnamon
  • Ginger
  • Nutmeg
  • Cloves
  • Salt

See also: Pumpkin Pie from Scratch

Roasted Peaches

Source: Abby

Ingredients

  • Fresh peaches, halved and pitted
  • Honey
  • Fresh mint leaves
  • Vanilla ice cream
  • Butter
  • Optional: cinnamon

Instructions

  1. Place peach halves cut-side up in baking dish.
  2. Drizzle with honey, dot with butter.
  3. Roast at 375°F for 20-25 minutes until tender.
  4. Serve warm with ice cream and fresh mint.

Red Wine Pears

Source: Abby

Ingredients

  • Pears, peeled (stems intact)
  • Red wine
  • Sugar or honey
  • Cinnamon stick
  • Star anise
  • Vanilla bean or extract
  • Orange peel

Instructions

  1. Combine wine, sweetener, and spices in pot.
  2. Add pears, simmer 20-30 minutes, turning occasionally.
  3. Remove pears, reduce liquid to syrup.
  4. Serve pears with syrup drizzled over.

Chocolate Fat Bomb Cookies

Source: Matt

Description

From Ketoconnect

Ingredients

  • 1/2 cup erythritol
  • 1/2 cup cocoa powder
  • 1/4 cup butter
  • 2 eggs
  • 1 tsp vanilla
  • 1 cup almond flour
  • 1 tsp baking powder
  • Pinch of salt

Mug Cakes

Source: Matt

Description

Originally from Ketoconnect

Fall Recipes

Seasonal recipes celebrating autumn harvest and flavors.

Miso Maple Acorn Squash

Source: Abby

Ingredients

  • Acorn squash, halved
  • Miso paste
  • Maple syrup
  • Butter
  • Sesame seeds

Instructions

  1. Roast squash halves at 400°F for 30 minutes.
  2. Mix miso, maple syrup, and melted butter.
  3. Brush mixture on squash, roast 10 more minutes.
  4. Garnish with sesame seeds.

Delicata Squash with Parmesan

Source: Abby

Ingredients

  • Delicata squash, sliced in rings
  • Olive oil
  • Parmesan cheese, grated
  • Salt, pepper
  • Fresh herbs (optional)

Roasted Kabocha Squash

Source: Abby

Ingredients

  • Kabocha squash, cut into wedges
  • Olive oil
  • Salt
  • Optional: honey, cinnamon

Butternut Squash Soup

Source: Abby

Ingredients

  • Butternut squash, cubed
  • Onion
  • Garlic
  • Vegetable or chicken broth
  • Coconut milk or cream
  • Sage, nutmeg
  • Salt, pepper

Spiced and Diced Sweet Potatoes

Source: Matt

Ingredients

  • Sweet potatoes, diced
  • Olive oil
  • Cinnamon
  • Nutmeg
  • Ginger
  • Salt

Eggnog

Source: Matt

Description

Adapted from Bumblebee Apothecary

Made for Abby and the Leons on December 12, 2024

Ingredients

  • 1 cup raw cultured cream
  • 2 raw eggs
  • 1 tsp vanilla extract
  • 1/4 tsp nutmeg
  • 3 tsp raw honey
  • 4 bags peppermint tea in maybe 1/3 cup water (extract would be better)
  • Cacao nibs for garnish

Gingerbread Fruitcake Muffins

Source: Matt

Description

Based on Keeper of the Home

Be sure to blend dry and wet separately then finally together.

Ingredients

  • 3 cups pastry flour
  • 1 tsp baking soda
  • 1 cup buttermilk
  • 1/2 cup butter
  • 1/2 cup allulose (brown)
  • 2 large eggs
  • 1.5 cups unsulphered molasses
  • 3 cups dried fruits
  • 1 cup chopped nuts
  • Cinnamon, cloves, ginger, salt, vanilla extract to taste

Based Meatloaf

Source: Matt

Description

From Based Cooking

Ingredients

  • 2 lbs ground beef
  • Beef liver
  • Beets
  • 4 eggs
  • 1/4 cup milk
  • Mustard, onion, garlic, tomato, hot sauce

Corned Beef and Cabbage

Source: Matt

Ingredients

  • 4 lbs corned beef brisket
  • 1 large head of cabbage, cut into wedges
  • 2 large onions, quartered
  • 1 lb rutabaga, peeled and cut into chunks
  • 1 lb celeriac, peeled and cut into chunks
  • 2 tbsp mustard seeds
  • 2 tbsp whole coriander seeds
  • 4 bay leaves
  • 1 tbsp ground ginger
  • Salt and pepper to taste
  • Water for cooking

Corned Beef

Source: Matt

Ingredients

  • Corned beef
  • Potatoes
  • Salt, pepper, cumin, coriander, cinnamon, nutmeg, ginger

Instructions

  1. Cut the corned beef into slices.
  2. Apply seasoning to all sides.
  3. Dice potatoes into one inch pieces.
  4. Lay the slices into a crockpot.
  5. Garnish with the potatoes.
  6. Slow cook.

Irish Lamb Root Stew

Source: Matt

Ingredients

  • 4 lbs lamb shoulder, cut into 1.5-inch cubes
  • 1/4 cup olive oil
  • 8 cups bone broth
  • 6 cloves garlic, minced
  • 2 lbs turnips, peeled and cut into chunks
  • 1 lb carrots, peeled and cut into chunks
  • 1 lb parsnips, peeled and cut into chunks
  • 2 tbsp fresh thyme leaves
  • 1/4 cup fresh parsley, chopped
  • 1 tsp ground cardamom
  • Salt and pepper to taste

Irish Soda Bread

Source: Matt

Ingredients

  • 170g wholemeal flour
  • 170g plain flour
  • 1/2 tsp salt
  • 1/2 tsp baking soda
  • 290ml buttermilk

Instructions

  1. Mix together the dry ingredients.
  2. Knead and flatten on a floury surface.
  3. Cut a cross in the top of each loaf.
  4. Bake at 280°C for 30 minutes.

Irish Green Milkshake

Source: Matt

A clean, minty, naturally green shake with an Irish-inspired spirit.

The spinach and matcha together should produce a strong natural green, making food coloring unlikely to be needed. Goat milk is nods to Ireland’s strong dairy tradition.

Serves: 2

Ingredients

AmountIngredient
160mlheavy cream
120mlgoat milk
20gbaby spinach
12mlmanuka honey
5mlvanilla extract
2mlpeppermint extract
3gmatcha powder
75ggreen apple, cored and chopped (approx. ½ medium)
15gbutterball lettuce leaves
2–3 dropsgreen food coloring (optional)

Method

  1. Wash the spinach, lettuce, and apple. Core and chop the apple.
  2. Pour the heavy cream and goat milk into a blender, then add the honey, vanilla extract, peppermint extract, and matcha powder.
  3. Add the spinach, apple, and lettuce.
  4. Blend on high until completely smooth, about 60 seconds.
  5. Taste and adjust honey if needed. Add food coloring only if a more vivid green is desired. Pour into a chilled glass and serve immediately.

Irish Whiskey Coffee

Source: Matt

Ingredients

  • 1.5 fl.oz. Irish cream
  • 1.5 fl.oz. Irish whiskey
  • 1 cup hot brewed coffee
  • 1 tablespoon whipped cream
  • 1 dash ground nutmeg

Goat Root Stir Fry

Source: Matt

Ingredients

The Meat:

  • Lamb loin chop
  • Lamb shoulder chop
  • Lamb leg chop

The Base:

  • 1 bunch collard greens
  • 1 bunch chard
  • Coconut aminos

The Roots:

  • One turnip
  • One radish
  • One beet
  • One rutabaga
  • One parsnip
  • One (midsize) carrot

Seasoning (in decreasing order):

  • Nutritional yeast
  • Dill
  • Cumin
  • Coriander
  • Ginger
  • Cardamom

Compote

Source: Matt

Ingredients

  • One pack raspberries
  • One pack blueberries
  • One pack blackberries
  • 3 tbsp manuka honey

Instructions

  1. Add all berries to a pot, fill with water until submerged.
  2. Bring to a boil, simmer for 20 minutes.
  3. Strain or blend, add to pitcher, mix in honey while hot.

Camping & Backpacking Recipes

Trail-ready food for outdoor adventures.

See Wikibooks: Camp Cooking

Cobblestacks v2

Source: Matt

Description

Originally from Eat Sleep Wild

Ingredients

  • 360g mashed banana (about 3 large)
  • 1 tsp vanilla extract
  • 200g porridge oats
  • 90g goji berries
  • 50g walnuts
  • 30g chia seeds
  • 80g pepita seeds
  • 60g sliced almonds
  • 25g ground flax seed meal
  • 1 tsp cinnamon
  • 1/4 tsp fine sea salt

Instructions

  1. Preheat oven to 180°C / 350°F. Grease and line 9″ x 13″ dish with parchment.
  2. Mash banana, stir in vanilla. Add remaining ingredients, mix well.
  3. Let sit 5-10 minutes for chia to absorb moisture.
  4. Press into dish with wet hands until compacted.
  5. Bake 22-26 minutes until firm and golden on edges.
  6. Cool 10 minutes, lift out, cool completely, slice into bars.
  7. Store in fridge for a week or freezer for 4-6 weeks.

Shepherd's Pie

Source: Abby

Description

Dehydrated backpacking version.

Ingredients

  • Ground beef or lamb, cooked and dehydrated
  • Mashed potatoes (instant or dehydrated)
  • Mixed vegetables, dehydrated
  • Gravy mix
  • Seasonings

Curried Cashew Couscous with Chicken

Source: Abby

Ingredients

  • Couscous
  • Chicken, cooked and dehydrated
  • Cashews, chopped
  • Curry powder
  • Dried vegetables
  • Bouillon

Miso Salmon & Rice

Source: Abby

Ingredients

  • Instant rice
  • Salmon (canned or dehydrated)
  • Miso paste packet
  • Dried seaweed
  • Sesame seeds

Thanksgiving Meal

Source: Abby

Description

Dehydrated Thanksgiving dinner for the trail.

Ingredients

  • Turkey, cooked and dehydrated
  • Instant mashed potatoes
  • Stuffing mix
  • Dried cranberries
  • Gravy mix

Jerky

Source: Abby

Ingredients

  • Lean meat (beef, venison, or turkey)
  • Soy sauce or coconut aminos
  • Worcestershire sauce
  • Spices (garlic, pepper, paprika)
  • Optional: liquid smoke

Veggie Bread

Source: Abby

Description

Dense, hearty bread with vegetables for backpacking.

Ingredients

  • Flour
  • Grated vegetables (zucchini, carrot)
  • Eggs
  • Oil
  • Baking powder
  • Seasonings

Protein Gunk

Source: Abby

Description

High-protein no-bake bars for the trail.

Ingredients

  • Protein powder
  • Nut butter
  • Honey or dates
  • Oats
  • Nuts and seeds
  • Optional: chocolate chips

See also: Backpacker’s Shepherd’s Pie (external link)

Miscellaneous Recipes

Drinks, snacks, sides, and external links.

Quick Tips

  • Salt garlic before mincing
  • Wet tortillas before frying

Recipes

From Wikibooks Cookbook

Balsamic Glazed Brussels Sprouts

Source: Matt

Ingredients

  • 1.5 lbs Brussels sprouts (halved)
  • 3 tbsp olive oil
  • Salt & pepper
  • 3 tbsp balsamic vinegar
  • 1-2 tbsp honey
  • 2 cloves garlic

Instructions

Roast Brussels sprouts with oil at 400°F for 20-25 min. Make glaze by simmering vinegar, honey, and garlic 3-5 min. Toss and serve.

Bone Broth

Source: Abby

Ingredients

  • Beef, chicken, or lamb bones (with marrow)
  • Water
  • Apple cider vinegar (2-3 tbsp)
  • Vegetables (onions, carrots, celery)
  • Herbs (bay leaf, thyme, parsley)
  • Salt, peppercorns

Instructions

  1. Roast bones at 400°F for 30 minutes.
  2. Place bones in large pot, cover with water.
  3. Add vinegar, let sit 30 minutes.
  4. Bring to boil, reduce to simmer.
  5. Simmer 12-24 hours (beef), 8-12 hours (chicken).
  6. Add vegetables and herbs last 2 hours.
  7. Strain, season, store or freeze.

The Copper Chronicle

These are some of my adventures and travels with Copper. From the stunning coastline of Big Sur to mountain adventures in Northern California, these are the stories of our explorations together.

Prelude Photos

Photo gallery from January 2024 - the beginning of our adventures.

January 26, 2024

Morning moment 1

Morning moment 2

Morning moment 3

Morning moment 4

Morning moment 5

Later that day 1

Later that day 2

Later that day 3

Afternoon

January 27, 2024

Next day begins 1

Next day begins 2

Next day begins 3

Next day begins 4

Midday 1

Midday 2

Midday 3

Midday 4

Midday 5

Midday 6

Afternoon exploration 1

Afternoon exploration 2

Later afternoon 1

Later afternoon 2

Evening approaches 1

Evening approaches 2

Evening 1

Evening 2

2024 April 05

On Friday, Daniel headed out for work after explaining the coffee situation. Candice took to her office, and I spent the day in the common room on the chair. She lent me a great laptop lap board/pad/holder. With that, I hit the workday. The whole day I debugged why my consumer code was not being interrupted properly. It was an easy day though I couldn’t solve it.

On our lunch break, Candice and I headed out to REI and Chipotle. We went back and forth between my looking at sleeping bags and knives. The sleeping bag I went with was ultimately the more expensive of the two. While I sorted the knives out, Candice went to grab the food. When I looked at the knives the first time, I sort of blabbered. When the worker came to help me though, she asked if I wanted to feel the handles.

It all sort of processed. “The hilt is light, this has a glass breaker, a belt cutter, a decent length blade, but no bevel. Clip too.”

At work’s end, we donned hiking clothes. Soon after, Abby arrived. She was not exactly as I remembered from the wedding, nor the picture Candice had shown me in January. She was bundled up for the weather, and her face reminded me of… a childhood friend of mine, Whitney. She could be a cousin or something.

They went to the kitchen sink while I lingered by the couch. When Candice left to handle something, I asked, “So how long have you known Candice?” She said since (I think) 2014, “but I know you have known her all your life.” I half-laughed and retold how Candice had just mentioned the childhood photo of us. Candice came in and redoubled the retelling of us bouncing on a bed at our grandparents.

The three of us drove over to… I don’t know, some trail along a nearby beach. I’d been asked about my work, but I really didn’t ever give the cohesive story. I was asked how I chose my career path, and I related the story about Aunt Paula. This eventually led to broaching the topic of Ciara’s employment. I told them both how I encouraged computer science, but I could only really pray after she went for environmental science.

After we got out, she asked, “So how do you like the Oura ring?” I told her, “You’ve got a keen eye. I like it.” She asked (I think) if I did anything with the data, and I told her, mostly in the beginning. I took steps to optimize the sleep and watch the changes. She asked what steps; I said blackout curtains, and one other thing before I was cut off. Perhaps it was with the 8sleep, since Candice soon brought that up. “You got da 8 sleep!” She said in this wowed tone that I liked.

We went out for a mile or two. Along the way, they recalled many stories of past hikes. I didn’t have much to share, but I asked some starter questions. I know more family stories maybe came up. At our stopping point, we talked about the beauty of the waves.

On the way back, I’d asked how many backpacking trips she’d done (10). I asked when her first one was (I think she said it was college for her). She also told me a story of when she got trapped in Peru for Covid and went backpacking. She asked her mom, “How much would you want for me back home?” Her mom asked, “How much?” …“$6000”.

After we got back, I felt much more levity with her. I think as I had first spoken about Aunt Paula and Ciara in the car, that had loosened me up. Speaking of Ciara, she was there when we got back.

We went to the Art after Dark in SLO. At the first stop, Abby tried to make conversation with me. I guess I was sort of out of it, or in my head, and just terribly quiet and awkward. We switched up who we were with several times and saw some neat stuff. I recall a close up dandelion painting and a barn painting that Ciara joked was my dream home. There was a horse statue that led to a long story about when I played Sybil Ludington in the Thirteen Colonies Play.

At another stop, Abby spent the time working with a vendor there. She made some oil based painting, and it was cute. I told her I ought to get something to remember the place as well. She offered her painting. We went to another stop with sleeping bags stood up almost like mummies. There was also a vase made of somehow encased spaghetti and pasta. Lastly we went to a room dedicated to some sort of African mythological ocean experience.

We then went to a sushi stop where we met up with Daniel. We got many delicious rolls. I’m glad Abby was in favor of just splitting the bill without itemizing so much. That was hard for Candice. Abby and I had some sort of fish liver at the end, and I thought it was not bad. She did not like it so much. Daniel’s friends there brought him 3 beers for free. I drove back Daniel in his truck and the girls went their way.

When we got back, we quickly went to work in the backyard setting up the fire pit. Abby and I were left alone for a bit, and I got talking about the knife experience at REI. Daniel came back, and he showed Abby and me his and Candice’s garden. He needed some gardening gloves. I asked when his birthday was, and Abby stepped in to guess.

Daniel was having trouble getting the fire started and left again. Abby pointed out that the wrapping on the starter log needed to be ignited too. She started it, and I felt pretty useless and emasculated as typical on this whole trip. Definitely it has given me areas to work on.

With the fire going, the five of us circled up. Clockwise, it was Candice, Abby, Ciara, Daniel, and I. We had a lot of good talk at this time, and Abby was doing the s’more prep. A marshmallow fell to the ground, and Abby cast it into the fire. I said, “That is your burnt offering.” :)

I said to Daniel, if we only had some whiskey. He busted out bourbon that they never drink. It was tasty, but Daniel did not like it one bit. I think Candice tried it and was saying how much it burned. Abby had no interest since alcohol is just unhealthy (except arguably for hormeosis).

Big Sur Photos

A photo gallery from our Big Sur adventure in April 2024.

Beach view

Coastal scenery

Morning at the campsite

Trail view


More Photos

Abby enjoying the view

Our campsite

Beautiful field

Hiking the trails

Rolling green hills

Trail through the wilderness

Waterfall discovery

Group photo

San Luis Obispo

Testimony

Cambria

Fencing

Her Birthday

The Hike

Twenty Qs

Independence Day

Rodeo

Projectile Day

Heat Wave Wedding

Stick Shift

Independence Day Photos

Photo gallery from our July 4th, 2024 celebration.

Planning and Preparation

Planning the celebration

More planning

Getting ready for the 4th

Final preparations

The Celebration

Evening festivities

Enjoying the evening

Fireworks Time

Fireworks display 1

Fireworks display 2

Apple Hill Photos

Photos from Apple Hill visits in 2024.

July 2024

Early summer visit

October 2024

Fall visit

November 2024

November visit 1

November visit 2

November visit 3

November visit 4

2024-08-28

Posing with Guns Up

I probably have some events out of order on this trip’s journal. I did not get to filling in my journal outline with memories till months after the events. I mentioned some of the events at the top of the retrospective.

I began preparation for the dove hunting trip in Yuma, Arizona. I picked up ammo, camo, hemp shorts, and a camel-pak knock-off.

Abby gave me a debrief. In terms of people, she laid out several geneological trees. This probably needs to be revised next year.

Larry(t)
|
|- Paul
|- Erik + Natalie
  |
  |-Grant

Craig + Nina
|
|-Pence? + Tony
|
|-Nicole (physical therapist) + Ein
|  |
|  |- Elliot, Wesley
|
|-Hannah + Steven

Sterlockson
|
|-Mark + Craig's sister
|  |
|  |-Daughter + Kurt
|  |-Daughter + Jared

Chuck (Erik's coworker) + wife with cookies

Peter + Jenny Sterenberg
|
|-Mia (Amelia Grace) + Matt
|-Mimi (in Scottsdale, working for Honeywell)

On Thursday, I drove down between 10:30 ~ 16:30, arriving at Candice’s place. Abby arrived and the girls caught up. I made myself useful, doing Daniel’s dishes.

The next day, I picked up Abby. We got to Nipomo and transferred all of our equipment to Bryan’s Forerunner. We also touched base with Tammy before beginning our 7 hour drive down. Bryan was a trooper and drove the entire way.

Driving in the Desert

I was told there would be some sort of onboarding/hazing ceremony. On the tail end of the drive down, we prepared for a stop. We took a right turn, passing an opened chainlink fence, into an empty, dirt field. There, we came upon an easy up with two guys sheltering in the shade beneath. Craig and Erik were smoking cigars and waiting for us.

Erik struck me as a jolly giant, and Craig reminded me of Adam Savage. Bryan set up beside them while Abby helped unload some things. While I fidgeted around, Erik handed me a shovel and a map scribbled on a scrap of paper. “Have you ever seen that movie holes?” I got the picture.

I headed back in the direction we came from, into the desolate wilderness. Counting the fence posts on the scribble, I looked back at the chainlink fence. Then following another landmark in the other dimension, I came to where I would dig. Before I got too carried away, Abby came up to me.

The conversation went something like, “Are you here to cheer me on?” “Is this something you would want help on?” “No, but if I’m spinning my wheels, you can steer me in the right direction.”

She eventually asked my rational of why I decided to dig where I was. Then she pointed out the fatal flaw. I was counting posts on the other side of the street, for no apparent reason. After accounting for that, my new X to mark the spot was much adjusted.

Eventually my shovel struck what Craig and Erik planted. I dug up an old metal crate, something like an ammo box. I brought it over to camp, and I picked through it. As I went over the pieces inside, the guys talked about the memories they brought up. One was Grant’s first hunting license, then there were several letters, and various nicknacks.

Once we wrapped up, we made the rest of the drive till our stay at the hotel in Yuma. I roomed with Craig. Despite being warned about snoring, there was nothing to fear after all.

Dove Hunting Photos

Photo gallery from our dove hunting adventure in August-September 2024.

Preparation and Arrival

Preparing for the hunt

Getting ready

Equipment check

At the location

The Hunt Begins

Early morning hunt

Success - first birds

More hunting

Afternoon session

Processing and Cooking

Cleaning the birds 1

Cleaning the birds 2

Bird preparation

Cleaning the birds 3

Ready to cook

The Harvest

First bird of the day

More birds collected

Successful hunt 1

Successful hunt 2

Successful hunt 3

Successful hunt 4

Final tally

Scouting

Frog Water

Dragon’s Milk

Retrospective

Shasta Trip

Gumboot Trailhead

Poetry

Photos

Photo gallery from our September 2024 trip to Shasta and Dunsmuir.

Evening Preparations

Evening preparation

Getting ready

Morning Adventures

Morning view 1

Morning view 2

Morning view 3

Trail exploration

More trails

Scenic overlook

Midday Exploration

Exploring the area

Beautiful scenery

Hiking

Mountain views

More mountain views

Trail marker

Scenic stop

Landmark

Afternoon Journey

Afternoon hike 1

Afternoon hike 2

Afternoon hike 3

Trail view

More trail views

Trail continuation

Rest stop 1

Rest stop 2

Rest stop 3

Rest stop 4

Rest stop 5

Rest stop 6

Late Afternoon

Late afternoon view

Evening approaching

Evening light 1

Evening light 2

Sunset time

Day Two

Day two morning 1

Day two morning 2

Additional Moments

Scenic vista 1

Scenic vista 2

Scenic vista 3

Scenic vista 4

Scenic vista 5

Pre-trip preparation

Evening at camp 1

Evening at camp 2

Night at camp 1

Night at camp 2

Morning activities

Trail start 1

Trail start 2

On the trail 1

On the trail 2

Midday break

Next day 1

Next day 2

Next day 3

Next day 4

Afternoon exploration 1

Afternoon exploration 2

Afternoon exploration 3

Afternoon exploration 4

Afternoon exploration 5

Afternoon exploration 6

Later in the day 1

Later in the day 2

Later in the day 3

Later in the day 4

Final day 1

Final day 2

Final day 3

Final day 4

Heading home

Candlelight Concert

Thanksgiving Photos

Photo gallery from Thanksgiving 2024.

November 30, 2024 - Thanksgiving Evening

Thanksgiving evening 1

Thanksgiving evening 2

Thanksgiving evening 3

December 1, 2024 - Day After

Morning after 1

Morning after 2

Morning after 3

Morning after 4

Morning after 5

Melodrama Photos

Photos from the Melodrama experience in December 2024.

Melodrama moment 1

Melodrama moment 2

Melodrama moment 3

New Years 2025

Photos from New Year’s celebrations in January 2025.

January 6, 2025

Blood glucose monitoring

Evening moment 1

Evening moment 2

January 13, 2025

Celebration 1

Celebration 2

Celebration 3

Celebration 4

Celebration 5

Celebration 6

Celebration 7

Celebration 8

Celebration 9

Celebration 10

Celebration 11

Saint Patrick’s Day 2025

Photo from Saint Patrick’s Day celebration on March 17, 2025.

Saint Patrick’s Day celebration

May 2025

Photos from May 2025.

May 12, 2025

May moment 1

May moment 2

Matheney Reunion 2025

Photos from the Matheney Family Reunion in July 2025.

July 6, 2025

Reunion evening 1

Reunion evening 2

Reunion evening 3

Reunion evening 4

July 9, 2025

Morning gathering 1

Morning gathering 2

Morning gathering 3

Mission Family Statement

Relationship Optimization Meeting

This is what we do (or try to) monthly.

  1. Prayer

  2. Specific compliments

E.g. You are very thoughtful and contributing when you decided to make baby blankets for your family.

  1. What’s working well

E.g. We are getting time together weekly and making progress on the workbook.

  1. What have you been working on?

E.g. Explaining inner state. E.g. Asserting protected time.

  1. Optimization

E.g. What can I do to make you more informed?

  1. Preferences

E.g. Which activities would you prefer we do together given our time constraints. We can plan and schedule together.

  1. Gratitude

E.g. I appreciate your thoroughness on following up about the ROM, verses, workbook, etc.

Resume

Professional Experience & Skills

Summary

Experienced software engineer with expertise in systems engineering, cloud infrastructure, and full-stack development. Passionate about building reliable, scalable solutions using modern technologies.

Technical Skills

Languages

  • Rust
  • Python
  • Go
  • JavaScript/TypeScript
  • HTML/CSS

Systems & Infrastructure

  • Linux/NixOS
  • Docker
  • Nginx
  • Git
  • CI/CD

Frameworks & Tools

  • Rocket (Rust)
  • React
  • Node.js
  • PostgreSQL
  • RESTful APIs

Professional Experience

Software Engineer

Example Company • 2020 - Present

  • Designed and implemented scalable backend services using Rust and Python
  • Managed infrastructure using NixOS and containerization technologies
  • Built and maintained CI/CD pipelines for automated testing and deployment
  • Collaborated with cross-functional teams to deliver high-quality software solutions

Systems Administrator

Previous Company • 2018 - 2020

  • Maintained Linux-based server infrastructure and monitoring systems
  • Automated routine tasks using shell scripting and Python
  • Implemented security best practices and access control policies
  • Provided technical support and documentation for development teams

Education

Bachelor of Science in Computer Science

University Name • 2014 - 2018

Focus on software engineering, algorithms, and systems programming.

Projects

Self-Hosted Infrastructure

Designed and deployed a complete self-hosted solution including:

  • Git hosting with Forgejo
  • Web server with Nginx and SSL/TLS
  • Calendar and contacts sync with Radicale
  • Declarative configuration management with NixOS

Personal Website & Blog

Built a simple, reliable website using mdbook focused on performance and maintainability.

Contact

Email: [email protected]

Git: forgejo.binning.net