based/
lib.rs

1/*! 
2# based
3
4`based` provides support for custom single-character digits.
5
6`based` does not support multi-character digits.
7
8# Examples
9
10```
11use based::{Base, NumeralSystem};
12
13let base16: Base = "0123456789abcdef".parse().unwrap();
14let val: usize = base16.decode("10").unwrap();
15assert_eq!(val, 16);
16assert_eq!(base16.encode(16 as usize).unwrap(), "10")
17```
18*/
19
20use std::num::TryFromIntError;
21
22mod single_base;
23pub use single_base::*;
24
25/**
26`StrError` is the error type produced when 
27[`NumeralSystem::decode`](NumeralSystem::decode) encounters an unknown character
28or fails to convert between two integer types.
29*/
30#[derive(Debug)]
31pub enum StrError {
32  /// Contains the unknown character.
33  UnknownChar(char),
34  Try(TryFromIntError)
35}
36
37impl std::fmt::Display for StrError {
38  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
39    match self {
40      StrError::UnknownChar(c) => write!(f, "Encountered char {} not in base", c),
41      StrError::Try(t) => t.fmt(f)
42    }   
43  }
44}
45
46impl std::error::Error for StrError {
47  fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
48    match self {
49      StrError::UnknownChar(_) => None,
50      StrError::Try(t) => Some(t)
51    }
52  }
53}
54
55impl From<TryFromIntError> for StrError {
56  fn from(err: TryFromIntError) -> StrError {
57    StrError::Try(err)
58  }
59}
60
61/// `NumeralSystem` provides conversions to and from representations in the given system.
62pub trait NumeralSystem<T> {
63
64  /**
65  Given a `NumeralSystem` and a number's representation
66  in that system, return the number.
67
68  Returns `Err` if this function encounters a character not in the system,
69  or if an int to int conversion fails.
70  */
71  fn decode(&self, rep: &str) -> Result<T, StrError>;
72
73  /** 
74  Given a `NumeralSystem` and a number, return the 
75  representation of that number in the system.
76
77  Returns `Err` if an int to int conversion fails.
78
79  This will interpret signed integers as if their bits represented their
80  unsigned counterparts.
81  */
82  fn encode(&self, val: T) -> Result<String, TryFromIntError>;
83}