Skip to content

Instantly share code, notes, and snippets.

@afilini
Created January 29, 2020 16:40
Show Gist options
  • Save afilini/eb9586d1036f9bae187bfb1df05d78b8 to your computer and use it in GitHub Desktop.
Save afilini/eb9586d1036f9bae187bfb1df05d78b8 to your computer and use it in GitHub Desktop.
Generic amount types in Rust
use std::collections::BTreeMap;
#[derive(Debug)]
struct LiquidAmount(BTreeMap<String, u64>);
type BitcoinAmount = u64;
macro_rules! liquid_amount {
( $( $key:expr => $val:expr ),* ) => {{
let mut map = BTreeMap::new();
$( *map.entry($key.into()).or_insert(0) += $val; )*
LiquidAmount(map)
}}
}
impl std::ops::Add for LiquidAmount {
type Output = Self;
fn add(mut self, other: Self) -> Self {
for (key, val) in other.0 {
*self.0.entry(key.into()).or_insert(0) += val;
}
self
}
}
trait GenericAmount: std::ops::Add + std::marker::Sized {}
impl GenericAmount for BitcoinAmount {}
impl GenericAmount for LiquidAmount {}
fn get_liquid_amount() -> LiquidAmount {
liquid_amount!("btc" => 10, "beer" => 1)
}
fn get_bitcoin_amount() -> BitcoinAmount {
42
}
fn sum_amounts<A: GenericAmount>(lhs: A, rhs: A) -> <A as std::ops::Add>::Output {
lhs + rhs
}
fn main() {
let la_1 = get_liquid_amount();
let la_2 = get_liquid_amount();
let ba_1 = get_bitcoin_amount();
let ba_2 = get_bitcoin_amount();
let la_1 = sum_amounts(la_1, la_2);
let ba_1 = sum_amounts(ba_1, ba_2);
println!("liquid: {:?}", la_1);
println!("bitcoin: {:?}", ba_1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment