1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use std::collections::HashMap;

pub fn encode(alphabet: &str, input: Vec<i16>) -> String {
  if input.len() == 0 {
    return String::new();
  }

  let base = alphabet.len() as i16;
  let mut alphabet_map = HashMap::with_capacity(alphabet.len());

  for (i, c) in alphabet.chars().enumerate() {
    alphabet_map.insert(i, c);
  }

  let mut digits: Vec<i16> = Vec::with_capacity(input.len());

  digits.push(0);

  for c in &input {
    let mut j = 0;
    let mut carry = *c;
    while j < digits.len() {
      carry = carry + (digits[j] << 8);
      digits[j] = carry % base;
      carry = (carry / base) | 0;
      j+=1;
    }

    while carry > 0 {
      digits.push(carry % base);
      carry = (carry / base) | 0;
    }
  }

  let mut k = 0;
  while k < input.len()-1 {
    if input[k] == 0 {
      digits.push(0);
      k = k + 1;
    } else {
      break;
    }
  }

  let digits_len = digits.len();
  let mut output = String::with_capacity(digits_len);
  for i in (0..digits_len).rev() {
    let chr = alphabet_map.get(&(digits[i] as usize)).unwrap();
    output.push(*chr);
  }

  return output;
}

pub fn decode(alphabet: &str, input: &str) -> Vec<i16> {
  if input.len() == 0 {
    return vec![];
  }

  let base = alphabet.len() as i16;
  let leader = alphabet.chars().nth(0).unwrap();
  let mut alphabet_map = HashMap::new();

  for (i, c) in alphabet.chars().enumerate() {
    alphabet_map.insert(c, i as i16);
  }

  let mut bytes = vec![0];
  for c in input.chars() {
    let mut carry = alphabet_map.get(&c).unwrap().clone();
    for b in &mut bytes {
      carry = carry + *b * base;
      *b = carry & 0xff;
      carry = carry >> 8;
    }

    while carry > 0 {
      bytes.push(carry & 0xff);
      carry = carry >> 8;
    }
  }

  let mut k = 0;
  while k < input.len()-1 {
    if input.chars().nth(k).unwrap() == leader {
      bytes.push(0);
      k = k + 1;
    } else {
      break;
    }
  }

  bytes.reverse();
  bytes
}

#[cfg(test)]
mod test {
    use super::encode;
    use super::decode;
    extern crate rustc_serialize;
    use self::rustc_serialize::json::{self, Json};
    use std::fs::File;
    use std::io::Read;

    #[test]
    fn works() {
      let mut file = File::open("./fixtures/fixtures.json").unwrap();
      let mut data = String::new();
      file.read_to_string(&mut data).unwrap();

      let json = Json::from_str(&data).unwrap();
      let alphabets = json.as_object().unwrap().get("alphabets").unwrap().as_object().unwrap();
      let valid = json.as_object().unwrap().get("valid").unwrap().as_array().unwrap();
      for  value in valid {
        let obj = value.as_object().unwrap();
        let alphabet_name = obj.get("alphabet").unwrap().to_string();
        let alphabet_name: String = json::decode(&alphabet_name).unwrap();
        let input = obj.get("string").unwrap().to_string();
        let input: String = json::decode(&input).unwrap();
        let alphabet = alphabets.get(&alphabet_name).unwrap().to_string();
        let alphabet: String = json::decode(&alphabet).unwrap();
        let decoded = decode(&alphabet, &input);
        let encoded = encode(&alphabet, decoded);
        assert_eq!(encoded, input);
      }
    }
}