Skip to content

Instantly share code, notes, and snippets.

Created August 28, 2019 16:54
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
// This file performs the stegasaurus recovery routine in order to fetch the tax brackets from
// your provided photograph.
use serde::Deserialize;
use std::fs;
use std::io::Cursor;
use std::path::Path;
#[derive(Debug, Deserialize)]
pub struct Bracket {
pub limit: Option<i32>,
pub rate: i32,
pub fn default_brackets() -> &'static [Bracket] {
static BRACKETS: &[Bracket] = &[
Bracket {
limit: Some(10_000),
rate: 0,
Bracket {
limit: Some(30_000),
rate: 10,
Bracket {
limit: Some(100_000),
rate: 25,
Bracket {
limit: None,
rate: 40,
pub fn from_path(path: impl AsRef<Path>) -> crate::Result<Vec<Bracket>> {
let cursor = Cursor::new(extract(path)?);
fn extract(path: impl AsRef<Path>) -> crate::Result<Vec<u8>> {
let carrier = fs::read(path)?;
let mut buffer = Vec::new();
stegasaurus::recover(&carrier, &mut buffer)?;
// This program makes use of a library called stegasaurus (sic) to support steganographic storage
// of tax brackets. In essence, it's possible to store your modified tax brackets in a family
// photograph and send that photo to the tax office to get your tax amount. That way, they can't
// directly observe what your brackets are.
mod bracket;
mod tax;
use structopt::StructOpt;
// In theory, we want to avoid floats to store monetary amounts, and we want to avoid possible
// rounding errors resulting from using integers. Hence the fixed-precision number. Whether this
// is better than a rational representation or not, I have no idea.
type Decimal = fixed::FixedI64<fixed::frac::U32>;
// I just don't want to write this more than once. Of course, that's true of the last type, too...
// Note that it's not so much that these names can't be shortened (by adding more uses like on
// line four above) but just that I don't want to add a line for something I'm only going to have
// in one place ever.
type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
#[derive(Debug, StructOpt)]
struct Opt {
income: i32,
brackets: Option<String>,
// Possible failure modes:
// 1. Unable to read from brackets file.
// 2. Unable to parse tax brackets from file.
fn main() -> Result<()> {
let opt = Opt::from_args();
let tax = match opt.brackets {
None => tax::calculate(opt.income, bracket::default_brackets()),
Some(path) => tax::calculate(opt.income, bracket::from_path(path)?),
println!("{}", tax);
// This file presents the logic used to perform the tax calculations themselves. If you look down
// at the bottom, you can also see an example of inline unit testing.
use crate::{bracket::Bracket, Decimal};
use std::borrow::Borrow;
use std::fmt::{self, Display};
pub fn calculate<I, B>(n: i32, brackets: I) -> Tax
I: IntoIterator<Item = B>,
B: Borrow<Bracket>,
let mut tax = Tax::new(n);
// Not gonna lie: I just had an epiphany and realized what the Borrow trait is for.
.for_each(|bracket| tax.apply(bracket.borrow()));
pub struct Tax {
amt: i32,
app: i32,
tax: Decimal,
impl Tax {
pub fn new(n: i32) -> Self {
Self {
amt: n,
app: 0,
tax: Decimal::from(0),
pub fn apply(&mut self, bracket: &Bracket) {
// All the money has been taxed.
if == self.amt {
match bracket.limit {
None => {
let n = Decimal::from(self.amt -; += n * Decimal::from(bracket.rate) / Decimal::from(100); += n.saturating_to_num::<i32>();
Some(limit) => {
let n = Decimal::from(limit.min(self.amt) -; += n * Decimal::from(bracket.rate) / Decimal::from(100); += n.saturating_to_num::<i32>();
fn bill(&self) -> i32 {
impl Display for Tax {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let bill = self.bill();
let rate = f64::from(bill) / f64::from(self.amt) * 100.0;
write!(f, "{} ({:.1}%)", bill, rate)
mod tests {
use crate::{bracket::default_brackets, tax};
// Not the world's best name for a test.
fn it_works() {
assert_eq!(tax::calculate(0, default_brackets()).bill(), 0);
assert_eq!(tax::calculate(10000, default_brackets()).bill(), 0);
assert_eq!(tax::calculate(10009, default_brackets()).bill(), 0);
assert_eq!(tax::calculate(10010, default_brackets()).bill(), 1);
assert_eq!(tax::calculate(12000, default_brackets()).bill(), 200);
assert_eq!(tax::calculate(56789, default_brackets()).bill(), 8697);
assert_eq!(tax::calculate(1234567, default_brackets()).bill(), 473326);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment