paths-as-strings 0.1.1

paths_as_strings is a small crate with two public free-functions for unambiguously and universally encoding Paths as UTF-8 strings, and then decoding them back into Paths.
Documentation
use std::path::PathBuf;
use std::borrow::Cow;
use separator::Separatable;
use walkdir::WalkDir;

struct EncodedPath {
    original_path: PathBuf,
    encoded_path: String,
}

fn main() {
    let start_dir = if std::env::args().len() > 1 {
        PathBuf::from(std::env::args().nth(1).unwrap())
    } else {
        std::env::current_dir().expect("Could not determine current directory.")
    };

    println!("Counting paths below {} according to encoding needs.", start_dir.display());

    let mut total_paths = 0;
    let mut num_not_encoded = 0;
    let mut num_encoded = 0;
    let mut encoded_paths = Vec::new();

    // Recursively walk from start_dir, ignoring any errors (which occur for
    // such things as 'permission denied'.
    for entry in WalkDir::new(start_dir).into_iter().filter_map(|e| e.ok()) {
        total_paths += 1;
        let pb = entry.into_path();
        let possibly_encoded_path = paths_as_strings::encode_path(&pb);

        match possibly_encoded_path {
            Cow::Borrowed(_s) => num_not_encoded += 1,
            Cow::Owned(encoded_path) => {
                num_encoded += 1;
                let round_tripped = paths_as_strings::decode_path(&encoded_path)
                    .expect("Decoding the encoded string should always work in this program.");
                println!("  Found a path requiring encoding : {:?}", pb);
                println!("  Encoded form is                 : {:?}", encoded_path);
                // println!("  Round tripped back to path is   : {:?}", round_tripped);
                // Assert here, so the program will stop with the offender as the last thing printed.
                // Of course, this assert should always succeed.
                assert_eq!(pb, round_tripped);

                // Accumulate these for printing them all at the end.
                let pre = EncodedPath { original_path: pb.clone(), encoded_path };
                encoded_paths.push(pre);
            }
        }

        if total_paths % 1000 == 0 {
            print_msg(num_not_encoded, num_encoded);
        }
    }

    println!("\nCounting complete. Totals follow:");
    print_msg(num_not_encoded, num_encoded);


    if num_encoded > 0 {
        let percentage = 100f64 * num_encoded as f64 / f64::from(total_paths);

        println!("\n{} out of {} paths needed encoding (and were successfully round-tripped).",
                 num_encoded, total_paths.separated_string());
        println!("This represents {}% of the total path count.\n", percentage);

        // for ep in encoded_paths {
        //     println!("Original path: {:?}", ep.original_path);
        //     println!("Encoded form : {:?}", ep.encoded_path);
        // }
    }
}

fn print_msg(num_not_encoded: usize, num_encoded: usize) {
    println!("num_not_encoded = {}, num_encoded = {}", num_not_encoded, num_encoded);
}