Rust decimal to roman numeral kata I just wrote this decimal to Roman numeral converter, inspired by Kevlin Henney's talk &quot;Get Kata&quot;.
I have been reading the Rust docs little by little and this is one of my first attempts at some code.
I'd like to get feedback on style, general rust idioms and how I could have implemented this algorithm in a more succinct manner.
Code also available here.
use std::env;
use std::io;
use std::io::BufWriter;
use std::io::Write;

static BASE10_NUMERALS: [&amp;str; 7] = [&quot;I&quot;, &quot;X&quot;, &quot;C&quot;, &quot;M&quot;, &quot;X̄&quot;, &quot;C̄&quot;, &quot;M̄&quot;];

static CENTRE_NUMERALS: [&amp;str; 6] = [&quot;V&quot;, &quot;L&quot;, &quot;D&quot;, &quot;V̄&quot;, &quot;L̄&quot;, &quot;D̄&quot;];

struct Bases {
    base: usize
}


impl Iterator for Bases {
    type Item = usize;

    fn next(&amp;mut self) -&gt; Option&lt;usize&gt; {
        self.base = self.base - 1;
        Some(self.base)
    }
}

fn iter_bases(largest_base: usize) -&gt; Bases {
    Bases { base: largest_base }
}


fn encode((decimal_number, base, ): (char, usize, )) -&gt; String {
    let digit = decimal_number.to_digit(10).unwrap();
    let max_base = CENTRE_NUMERALS.len();

    if base &gt;= max_base {
        BASE10_NUMERALS[BASE10_NUMERALS.len() - 1]
            //This pow function is the main limiter for decimal size
            .repeat((10_u32.pow((base - max_base) as u32) * digit) as usize)
    } else {
        if digit == 9 {
            format!(&quot;{}{}&quot;
                    , if base == 3 { &quot;Ī&quot;} else { BASE10_NUMERALS[base] }
                    , BASE10_NUMERALS[base + 1]
            )
        } else if digit &gt;= 5 {
            format!(&quot;{}{}&quot;, CENTRE_NUMERALS[
                base], BASE10_NUMERALS[base]
                        .repeat((digit - 5) as usize))
        } else if digit == 4 {
            format!(&quot;{}{}&quot;, BASE10_NUMERALS[base], CENTRE_NUMERALS[base])
        } else {
            // Less than 4
            BASE10_NUMERALS[base].repeat(digit as usize)
        }
    }
}


fn main() {
    let args: Vec&lt;String&gt; = env::args().collect();
    let mut writer = BufWriter::new(io::stdout());
    let input = &amp;args[1];
    for roman_numeral in input
        .chars()
        .zip(iter_bases(input.len()))
        .map(encode) {
        writer.write(roman_numeral.as_bytes())
            .expect(&quot;Unable to write to stdout&quot;);
    }
}
cargo fmt and cargo clippy
Use cargo fmt to format your code according to the official Rust
Style Guide.
Clippy's suggestions:

collapse else { if .. } into else if ..;

change self.base = self.base - 1 to self.base -= 1;

use write_all instead of write when writing a slice of bytes,
since the latter only makes one writing attempt:

io::Write::write(_vectored) and io::Read::read(_vectored) are
not guaranteed to process the entire buffer. They return how many
bytes were processed, which might be smaller than a given buffer’s
length. If you don’t need to deal with partial-write/read, use
write_all/read_exact instead.  (source)



The interface
Instead of passing in a tuple, it is preferable to pass separate
parameters:
fn encode(decimal_number: char, base: usize) -&gt; String {
    // ...
}

Now, we notice that the interface is fairly curious.  A better
self-explanatory interface might simply be:
fn to_roman(number: u32) -&gt; String {
    // ...
}

which can be coded to encapsulate calls to encode while avoiding
repetitive allocation.
Grouping use declarations
It's common to group use declarations together:
use std::{
    env,
    io::{self, BufWriter, Write},
};

The Bases utility
Bases is not necessary — you can use (0..n).rev() to iterate
from n - 1 to 0.