<commit_before>#![crate_name = "macaroons"]
#![crate_type = "lib"]

#![feature(core)]
#![feature(collections)]

pub mod caveat;
pub use caveat::{Caveat, Predicate};
pub use sodiumoxide::crypto::auth::hmacsha256::{Key, Tag};

extern crate sodiumoxide;
use sodiumoxide::crypto::auth::hmacsha256::authenticate;

extern crate "rustc-serialize" as serialize;
use serialize::base64::{self, FromBase64, ToBase64};

// Macaroons personalize the HMAC key using this string
// "macaroons-key-generator" padded to 32-bytes with zeroes
const KEY_GENERATOR: [u8; 32] = [0x6d,0x61,0x63,0x61,0x72,0x6f,0x6f,0x6e
                                ,0x73,0x2d,0x6b,0x65,0x79,0x2d,0x67,0x65
                                ,0x6e,0x65,0x72,0x61,0x74,0x6f,0x72,0x00
                                ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00];

const PACKET_PREFIX_LENGTH: usize = 4;
const MAX_PACKET_LENGTH:    usize = 65535;

pub struct Token {
  pub location:   Vec<u8>,
  pub identifier: Vec<u8>,
  pub caveats:    Option<Vec<Caveat>>,
  pub tag:        Tag
}

struct Packet {
  pub field: Vec<u8>,
  pub value: Vec<u8>
}

impl Token {
  pub fn new(key: Vec<u8>, identifier: Vec<u8>, location: Vec<u8>) -> Token {
    let Tag(personalized_key) = authenticate(&key, &Key(KEY_GENERATOR));
    let tag = authenticate(&identifier, &Key(personalized_key));

    Token {
      identifier: identifier,
      location:   location,
      caveats:    None,
      tag:        tag
    }
  }

  pub fn deserialize(macaroon: Vec<u8>) -> Vec<u8> {
    let mut location:   Option<Vec<u8>> = None;
    //let mut identifier: Option<Vec<u8>> = None;

    let mut token_data = macaroon.as_slice().from_base64().unwrap();
    let packet = Token::depacketize(&mut token_data);

    match std::str::from_utf8(packet.field.as_slice()).unwrap() {
      "location"   => { location = Some(packet.value) },
      //"identifier" => { identifier = Some(value) },
      _ => ()
    }

    location.unwrap()
  }

  fn depacketize(data: &mut Vec<u8>) -> Packet {
    let length_str = std::str::from_utf8(&data[0 .. PACKET_PREFIX_LENGTH]).unwrap();
    let packet_length: usize = std::num::from_str_radix(length_str, 16).unwrap();

    let mut packet = data[PACKET_PREFIX_LENGTH .. packet_length].to_vec();

    let pos = packet.iter().position(|&byte| byte == 32).unwrap();
    let mut value = packet.split_off(pos);
    value.remove(0);

    // TODO: ensure this is a newline
    value.pop();

    Packet { field: packet, value: value }
  }

  pub fn add_caveat(&self, caveat: Caveat) -> Token {<commit_msg>Use byte string literal syntax<commit_after>#![crate_name = "macaroons"]
#![crate_type = "lib"]

#![feature(core)]
#![feature(collections)]

pub mod caveat;
pub use caveat::{Caveat, Predicate};
pub use sodiumoxide::crypto::auth::hmacsha256::{Key, Tag};

extern crate sodiumoxide;
use sodiumoxide::crypto::auth::hmacsha256::authenticate;

extern crate "rustc-serialize" as serialize;
use serialize::base64::{self, FromBase64, ToBase64};

// Macaroons personalize the HMAC key using this string
// "macaroons-key-generator" padded to 32-bytes with zeroes
const KEY_GENERATOR: [u8; 32] = [0x6d,0x61,0x63,0x61,0x72,0x6f,0x6f,0x6e
                                ,0x73,0x2d,0x6b,0x65,0x79,0x2d,0x67,0x65
                                ,0x6e,0x65,0x72,0x61,0x74,0x6f,0x72,0x00
                                ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00];

const PACKET_PREFIX_LENGTH: usize = 4;
const MAX_PACKET_LENGTH:    usize = 65535;

pub struct Token {
  pub location:   Vec<u8>,
  pub identifier: Vec<u8>,
  pub caveats:    Option<Vec<Caveat>>,
  pub tag:        Tag
}

struct Packet {
  pub field: Vec<u8>,
  pub value: Vec<u8>
}

impl Token {
  pub fn new(key: Vec<u8>, identifier: Vec<u8>, location: Vec<u8>) -> Token {
    let Tag(personalized_key) = authenticate(&key, &Key(KEY_GENERATOR));
    let tag = authenticate(&identifier, &Key(personalized_key));

    Token {
      identifier: identifier,
      location:   location,
      caveats:    None,
      tag:        tag
    }
  }

  pub fn deserialize(macaroon: Vec<u8>) -> Vec<u8> {
    let mut location:   Option<Vec<u8>> = None;
    //let mut identifier: Option<Vec<u8>> = None;

    let mut token_data = macaroon.as_slice().from_base64().unwrap();
    let packet = Token::depacketize(&mut token_data);

    match packet.field.as_slice() {
      b"location" => { location = Some(packet.value) },
      //"identifier" => { identifier = Some(value) },
      _ => ()
    }

    location.unwrap()
  }

  fn depacketize(data: &mut Vec<u8>) -> Packet {
    let length_str = std::str::from_utf8(&data[0 .. PACKET_PREFIX_LENGTH]).unwrap();
    let packet_length: usize = std::num::from_str_radix(length_str, 16).unwrap();

    let mut packet = data[PACKET_PREFIX_LENGTH .. packet_length].to_vec();

    let pos = packet.iter().position(|&byte| byte == 32).unwrap();
    let mut value = packet.split_off(pos);
    value.remove(0);

    // TODO: ensure this is a newline
    value.pop();

    Packet { field: packet, value: value }
  }

  pub fn add_caveat(&self, caveat: Caveat) -> Token {
{'fraction_non_alphanumeric': 0.1478790259230165, 'fraction_numerical': 0.0516496465043205, 'mean_word_length': 3.3905172413793103, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1614463', 'n_tokens_mistral': 1984, 'n_tokens_neox': 1866, 'n_words': 386}