Skip to content

Instantly share code, notes, and snippets.

@danneu
Created January 4, 2018 09:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danneu/2ec3f601183cc9c3ba84bf06d92274df to your computer and use it in GitHub Desktop.
Save danneu/2ec3f601183cc9c3ba84bf06d92274df to your computer and use it in GitHub Desktop.
// Since an Encoder and Decoder live as long as a Codec, I'd
// like for them both to share a reference to one instread
// of cloning it.
//
// And do I want refs or slices in this sort of situation? I seem to pick one at random.
// EXAMPLE
fn main() {
let base2 = Codec::new("01".chars().collect());
println!("{:?} {:?}", base2.encode(420), base2.decode(base2.encode(420).as_ref()));
let base16 = Codec::new("0123456789abcdef".chars().collect());
println!("{:?} {:?}", base16.encode(420), base16.decode(base16.encode(420).as_ref()));
}
// PUBLIC
pub struct Codec {
encoder: Encoder,
decoder: Decoder
}
impl Codec {
pub fn new(alphabet: Vec<char>) -> Codec {
Codec {
encoder: Encoder::new(alphabet.clone()),
decoder: Decoder::new(alphabet)
}
}
pub fn encode(&self, x: u64) -> String {
self.encoder.encode(x)
}
pub fn decode(&self, x: &str) -> Option<u64> {
self.decoder.decode(x)
}
}
// PRIVATE
struct Encoder {
alphabet: Vec<char>
}
impl Encoder {
fn new(alphabet: Vec<char>) -> Encoder { Encoder { alphabet } }
fn encode(&self, n: u64) -> String {
let radix = self.alphabet.len();
let mut n = n;
let mut s = String::new();
while n >= radix as u64 {
let rem = n % (radix as u64);
s.push(self.alphabet[rem as usize]);
n = ((n / radix as u64) as i64) as u64;
}
s.push(self.alphabet[n as usize]);
s.chars().rev().collect()
}
}
struct Decoder {
alphabet: Vec<char>
}
impl Decoder {
fn new(alphabet: Vec<char>) -> Decoder { Decoder { alphabet } }
fn decode(&self, s: &str) -> Option<u64> {
let radix = self.alphabet.len();
let mut idxs: Vec<usize> = Vec::with_capacity(s.len());
for a in s.chars() {
match self.alphabet.iter().position(|&b: &char| a == b) {
None => return None,
Some(idx) => idxs.push(idx)
}
}
return Some(idxs
.into_iter()
.rev() // TODO: RevVec
.enumerate()
.map(|(power, n): (usize, usize)| {
(n as u64 * ((radix as f64).powi(power as i32) as u64))
})
.sum())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment