<commit_before>#![cfg_attr(all(feature="serde_type"), feature(proc_macro))]

extern crate iron;
extern crate router;
extern crate env_logger;
extern crate handlebars;
extern crate handlebars_iron as hbs;
#[cfg(not(feature = "serde_type"))]
extern crate rustc_serialize;
#[cfg(feature = "serde_type")]
extern crate serde;
#[cfg(feature = "serde_type")]
extern crate serde_json;
#[cfg(feature = "serde_type")]
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate maplit;

use iron::prelude::*;
use iron::status;
use router::Router;
use hbs::{Template, HandlebarsEngine, DirectorySource, MemorySource};
use handlebars::{Handlebars, RenderContext, RenderError, Helper};

#[cfg(not(feature = "serde_type"))]
mod data {
    use rustc_serialize::json::{ToJson, Json};
    use std::collections::BTreeMap;

    pub struct Team {
        name: String,
        pts: u16,
    }

    impl ToJson for Team {
        fn to_json(&self) -> Json {
            let mut m: BTreeMap<String, Json> = BTreeMap::new();
            m.insert("name".to_string(), self.name.to_json());
            m.insert("pts".to_string(), self.pts.to_json());
            m.to_json()
        }
    }

    pub fn make_data() -> BTreeMap<String, Json> {
        let mut data = BTreeMap::new();

        data.insert("year".to_string(), "2015".to_json());

        let teams = vec![Team {
                             name: "Jiangsu Sainty".to_string(),
                             pts: 43u16,
                         },
                         Team {
                             name: "Beijing Guoan".to_string(),
                             pts: 27u16,
                         },
                         Team {
                             name: "Guangzhou Evergrand".to_string(),
                             pts: 22u16,
                         },
                         Team {
                             name: "Shandong Luneng".to_string(),
                             pts: 12u16,
                         }];

        data.insert("teams".to_string(), teams.to_json());
        data.insert("engine".to_string(), "rustc_serialize".to_json());
        data
    }
}

#[cfg(feature = "serde_type")]
mod data {
    use handlebars::to_json;
    use serde_json::value::{Value, Map};

    #[derive(Serialize, Debug)]
    pub struct Team {
        name: String,
        pts: u16,
    }

    pub fn make_data() -> Map<String, Value> {
        let mut data = Map::new();

        data.insert("year".to_string(), to_json(&"2015".to_owned()));

        let teams = vec![Team {
                             name: "Jiangsu Sainty".to_string(),
                             pts: 43u16,
                         },
                         Team {
                             name: "Beijing Guoan".to_string(),
                             pts: 27u16,
                         },
                         Team {
                             name: "Guangzhou Evergrand".to_string(),
                             pts: 22u16,
                         },
                         Team {
                             name: "Shandong Luneng".to_string(),
                             pts: 12u16,
                         }];

        data.insert("teams".to_string(), to_json(&teams));
        data.insert("engine".to_string(), to_json(&"serde_json".to_owned()));
        data
    }
}

use data::*;

/// the handlers
fn index(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::new("some/path/hello", data)).set_mut(status::Ok);
    Ok(resp)
}

fn memory(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::new("memory", data)).set_mut(status::Ok);
    Ok(resp)
}

fn temp(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::with(include_str!("templates/some/path/hello.hbs"), data))
        .set_mut(status::Ok);
    Ok(resp)
}

fn plain(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "It works")))
}

fn main() {
    env_logger::init().unwrap();

    let mut hbse = HandlebarsEngine::new();

    // add a directory source, all files with .hbs suffix will be loaded as template
    hbse.add(Box::new(DirectorySource::new("./examples/templates/", ".hbs")));

    let mem_templates = btreemap! {
        "memory".to_owned() => include_str!("templates/some/path/hello.hbs").to_owned()
    };
    // add a memory based source
    hbse.add(Box::new(MemorySource(mem_templates)));

    // load templates from all registered sources
    if let Err(r) = hbse.reload() {
        panic!("{}", r);
    }

    hbse.handlebars_mut().register_helper("some_helper",
                                          Box::new(|_: &Helper,
                                                    _: &Handlebars,
                                                    _: &mut RenderContext|
                                                    -> Result<(), RenderError> {
                                              Ok(())
                                          }));

    let mut router = Router::new();
    router.get("/", index, "index")
          .get("/mem", memory, "memory")
          .get("/temp", temp, "temp")
          .get("/plain", plain, "plain");
    let mut chain = Chain::new(router);
    chain.link_after(hbse);
    println!("Server running at http://localhost:3000/");
    Iron::new(chain).http("localhost:3000").unwrap();
}
<commit_msg>(test) use re-exported handlebars<commit_after>#![cfg_attr(all(feature="serde_type"), feature(proc_macro))]

extern crate iron;
extern crate router;
extern crate env_logger;
extern crate handlebars_iron as hbs;
#[cfg(not(feature = "serde_type"))]
extern crate rustc_serialize;
#[cfg(feature = "serde_type")]
extern crate serde;
#[cfg(feature = "serde_type")]
extern crate serde_json;
#[cfg(feature = "serde_type")]
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate maplit;

use iron::prelude::*;
use iron::status;
use router::Router;
use hbs::{Template, HandlebarsEngine, DirectorySource, MemorySource};
use hbs::handlebars::{Handlebars, RenderContext, RenderError, Helper};

#[cfg(not(feature = "serde_type"))]
mod data {
    use rustc_serialize::json::{ToJson, Json};
    use std::collections::BTreeMap;

    pub struct Team {
        name: String,
        pts: u16,
    }

    impl ToJson for Team {
        fn to_json(&self) -> Json {
            let mut m: BTreeMap<String, Json> = BTreeMap::new();
            m.insert("name".to_string(), self.name.to_json());
            m.insert("pts".to_string(), self.pts.to_json());
            m.to_json()
        }
    }

    pub fn make_data() -> BTreeMap<String, Json> {
        let mut data = BTreeMap::new();

        data.insert("year".to_string(), "2015".to_json());

        let teams = vec![Team {
                             name: "Jiangsu Sainty".to_string(),
                             pts: 43u16,
                         },
                         Team {
                             name: "Beijing Guoan".to_string(),
                             pts: 27u16,
                         },
                         Team {
                             name: "Guangzhou Evergrand".to_string(),
                             pts: 22u16,
                         },
                         Team {
                             name: "Shandong Luneng".to_string(),
                             pts: 12u16,
                         }];

        data.insert("teams".to_string(), teams.to_json());
        data.insert("engine".to_string(), "rustc_serialize".to_json());
        data
    }
}

#[cfg(feature = "serde_type")]
mod data {
    use hbs::handlebars::to_json;
    use serde_json::value::{Value, Map};

    #[derive(Serialize, Debug)]
    pub struct Team {
        name: String,
        pts: u16,
    }

    pub fn make_data() -> Map<String, Value> {
        let mut data = Map::new();

        data.insert("year".to_string(), to_json(&"2015".to_owned()));

        let teams = vec![Team {
                             name: "Jiangsu Sainty".to_string(),
                             pts: 43u16,
                         },
                         Team {
                             name: "Beijing Guoan".to_string(),
                             pts: 27u16,
                         },
                         Team {
                             name: "Guangzhou Evergrand".to_string(),
                             pts: 22u16,
                         },
                         Team {
                             name: "Shandong Luneng".to_string(),
                             pts: 12u16,
                         }];

        data.insert("teams".to_string(), to_json(&teams));
        data.insert("engine".to_string(), to_json(&"serde_json".to_owned()));
        data
    }
}

use data::*;

/// the handlers
fn index(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::new("some/path/hello", data)).set_mut(status::Ok);
    Ok(resp)
}

fn memory(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::new("memory", data)).set_mut(status::Ok);
    Ok(resp)
}

fn temp(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::with(include_str!("templates/some/path/hello.hbs"), data))
        .set_mut(status::Ok);
    Ok(resp)
}

fn plain(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "It works")))
}

fn main() {
    env_logger::init().unwrap();

    let mut hbse = HandlebarsEngine::new();

    // add a directory source, all files with .hbs suffix will be loaded as template
    hbse.add(Box::new(DirectorySource::new("./examples/templates/", ".hbs")));

    let mem_templates = btreemap! {
        "memory".to_owned() => include_str!("templates/some/path/hello.hbs").to_owned()
    };
    // add a memory based source
    hbse.add(Box::new(MemorySource(mem_templates)));

    // load templates from all registered sources
    if let Err(r) = hbse.reload() {
        panic!("{}", r);
    }

    hbse.handlebars_mut().register_helper("some_helper",
                                          Box::new(|_: &Helper,
                                                    _: &Handlebars,
                                                    _: &mut RenderContext|
                                                    -> Result<(), RenderError> {
                                                       Ok(())
                                                   }));

    let mut router = Router::new();
    router.get("/", index, "index")
        .get("/mem", memory, "memory")
        .get("/temp", temp, "temp")
        .get("/plain", plain, "plain");
    let mut chain = Chain::new(router);
    chain.link_after(hbse);
    println!("Server running at http://localhost:3000/");
    Iron::new(chain).http("localhost:3000").unwrap();
}
<|endoftext|>


<commit_before>use std::fs;

use std::io;
use std::io::{BufRead, Read, Write};

use std::path;

use hyper;

use resource_loaders;

pub struct Loader {
  prefix: String,
  cache_dir: String,
  client: hyper::Client
}

impl Loader {
  pub fn new(prefix: &str, cache_dir: &str) -> Loader {
    fs::create_dir_all(cache_dir).unwrap();

    return Loader {
      prefix: prefix.to_owned(),
      cache_dir: cache_dir.to_owned(),
      client: hyper::Client::new()
    };
  }

  pub fn default() -> Loader {
    return Loader::new("http://developers.eveonline.com/ccpwgl/assetpath/967762", ".cache");
  }

  fn load_from_cache(&self, path: &str) -> Option<(String, Vec<u8>)> {
    let file = self.cache_dir.clone() + path;

    let mut f = match fs::File::open(file) {
      Ok(f) => io::BufReader::new(f), _ => return None
    };

    let mut mime = String::new();
    f.read_line(&mut mime).unwrap();

    return Some((mime.trim().to_owned(), load_from_stream(&mut f)));
  }

  fn load_from_cdn(&self, path: &str) -> Option<(String, Vec<u8>)> {
    let url = self.prefix.clone() + path;

    let mut response = match self.client.get(&url).send() {
      Ok(r) => r, _ => return None
    };

    let extension = path::Path::new(path).extension().map(|x| x.to_str().unwrap()).unwrap_or("");

    let mime = match extension {
      "wbg" => "application/x-ccp-wbg".to_owned(),
      "red" => "application/x-ccp-red".to_owned(),
      _ => {
        let headers = response.headers.clone();

        match headers.get::<hyper::header::ContentType>() {
          Some(&hyper::header::ContentType(ref s)) => s.clone(),
          None => "application/octet-stream".parse().unwrap()
        }.to_string()
      }
    };

    let data = load_from_stream(&mut response);

    let file = self.cache_dir.clone() + path;

    fs::create_dir_all(path::Path::new(file.as_str()).parent().unwrap()).unwrap();
    let mut f = fs::File::create(file).unwrap();

    write_to_stream(&mut f, &mime, &data);

    return Some((mime, data));
  }
}

impl resource_loaders::ResourceLoader for Loader {
  fn load(&self, path: &str) -> Option<(String, Vec<u8>)> {
    let result = self.load_from_cache(path);

    return match result {
      None => self.load_from_cdn(path),
      Some(s) => Some(s)
    };
  }
}

fn load_from_stream(read: &mut Read) -> Vec<u8> {
  let mut body = Vec::new();

  read.read_to_end(&mut body).unwrap();

  return body;
}

fn write_to_stream(write: &mut Write, mime: &String, data: &Vec<u8>) {
  write.write_all(format!("{}\n", mime).as_bytes()).unwrap();
  write.write_all(data.as_slice()).unwrap();
}<commit_msg>Check for 200 OK before trying to do anything with it<commit_after>use std::fs;

use std::io;
use std::io::{BufRead, Read, Write};

use std::path;

use hyper;

use resource_loaders;

pub struct Loader {
  prefix: String,
  cache_dir: String,
  client: hyper::Client
}

impl Loader {
  pub fn new(prefix: &str, cache_dir: &str) -> Loader {
    fs::create_dir_all(cache_dir).unwrap();

    return Loader {
      prefix: prefix.to_owned(),
      cache_dir: cache_dir.to_owned(),
      client: hyper::Client::new()
    };
  }

  pub fn default() -> Loader {
    return Loader::new("http://developers.eveonline.com/ccpwgl/assetpath/967762", ".cache");
  }

  fn load_from_cache(&self, path: &str) -> Option<(String, Vec<u8>)> {
    let file = self.cache_dir.clone() + path;

    let mut f = match fs::File::open(file) {
      Ok(f) => io::BufReader::new(f), _ => return None
    };

    let mut mime = String::new();
    f.read_line(&mut mime).unwrap();

    return Some((mime.trim().to_owned(), load_from_stream(&mut f)));
  }

  fn load_from_cdn(&self, path: &str) -> Option<(String, Vec<u8>)> {
    let url = self.prefix.clone() + path;

    let mut response = match self.client.get(&url).send() {
      Ok(r) => r, _ => return None
    };

    if response.status != hyper::status::StatusCode::Ok {
      return None;
    }

    let extension = path::Path::new(path).extension().map(|x| x.to_str().unwrap()).unwrap_or("");

    let mime = match extension {
      "wbg" => "application/x-ccp-wbg".to_owned(),
      "red" => "application/x-ccp-red".to_owned(),
      _ => {
        let headers = response.headers.clone();

        match headers.get::<hyper::header::ContentType>() {
          Some(&hyper::header::ContentType(ref s)) => s.clone(),
          None => "application/octet-stream".parse().unwrap()
        }.to_string()
      }
    };

    let data = load_from_stream(&mut response);

    let file = self.cache_dir.clone() + path;

    fs::create_dir_all(path::Path::new(file.as_str()).parent().unwrap()).unwrap();
    let mut f = fs::File::create(file).unwrap();

    write_to_stream(&mut f, &mime, &data);

    return Some((mime, data));
  }
}

impl resource_loaders::ResourceLoader for Loader {
  fn load(&self, path: &str) -> Option<(String, Vec<u8>)> {
    let result = self.load_from_cache(path);

    return match result {
      None => self.load_from_cdn(path),
      Some(s) => Some(s)
    };
  }
}

fn load_from_stream(read: &mut Read) -> Vec<u8> {
  let mut body = Vec::new();

  read.read_to_end(&mut body).unwrap();

  return body;
}

fn write_to_stream(write: &mut Write, mime: &String, data: &Vec<u8>) {
  write.write_all(format!("{}\n", mime).as_bytes()).unwrap();
  write.write_all(data.as_slice()).unwrap();
}<|endoftext|>


<commit_before>extern crate polydraw;

use polydraw::os::win;
use polydraw::os::wgl;
use polydraw::os::gl;

fn main() {
   let width: usize = 1280;
   let height: usize = 720;

   let window = win::Window::create(width, height, "Win Min", "WinMinClass");
   window.show_normal();

   let dc = window.dc();
   println!("DC: {:?}", dc);

   match wgl::init_pixel_format(dc) {
      Ok(_) => {},
      Err(e) => {
         panic!(e.description);
      }
   };

   let context = match wgl::Context::create(dc) {
      Ok(current) => current,
      Err(e) => {
         panic!(e.description);
      }
   };

   println!("RC: {:?}", context.rc);

   let current = match wgl::Context::current() {
      Ok(current) => current,
      Err(e) => {
         panic!(e.description);
      }
   };

   gl::load(wgl::Loader::new());

   loop {
      let message = match win::Message::get() {
         Some(message) => message,
         None => break
      };

      message.translate();
      message.dispatch();

      gl::clear_color(0.0, 0.7, 1.0, 1.0);
      gl::clear();
      gl::flush();

      wgl::swap_buffers(dc);
   }
}
<commit_msg>Do not store current context<commit_after>extern crate polydraw;

use polydraw::os::win;
use polydraw::os::wgl;
use polydraw::os::gl;

fn main() {
   let width: usize = 1280;
   let height: usize = 720;

   let window = win::Window::create(width, height, "Win Min", "WinMinClass");
   window.show_normal();

   let dc = window.dc();
   println!("DC: {:?}", dc);

   match wgl::init_pixel_format(dc) {
      Ok(_) => {},
      Err(e) => {
         panic!(e.description);
      }
   };

   let context = match wgl::Context::create(dc) {
      Ok(context) => context,
      Err(e) => {
         panic!(e.description);
      }
   };

   println!("RC: {:?}", context.rc);

   match wgl::Context::current() {
      Ok(_) => {},
      Err(e) => {
         panic!(e.description);
      }
   };

   gl::load(wgl::Loader::new());

   loop {
      let message = match win::Message::get() {
         Some(message) => message,
         None => break
      };

      message.translate();
      message.dispatch();

      gl::clear_color(0.0, 0.7, 1.0, 1.0);
      gl::clear();
      gl::flush();

      wgl::swap_buffers(dc);
   }
}
<|endoftext|>


<commit_before>use std::iter::FromIterator;

pub fn decode_at_index(s: String, k: i32) -> String {
    let mut length = 0_usize;
    let mut cache = Vec::new();
    let mut result = String::new();
    for c in s.chars() {
        if let Some(times) = c.to_digit(10) {
            length *= times as usize;

            result += &String::from_iter(cache);
            result = result.repeat(times as usize);
            cache = vec![];
        } else {
            length += 1;
            cache.push(c);
        }
        println!("{}", result);
        if length == k as usize {
            //result += &String::from_iter(cache);
            return c.to_string();
        }
    }

    result
}

fn main() {
    dbg!(decode_at_index("leet2code3".to_string(), 10));
    dbg!(decode_at_index("ha22".to_string(), 10));
}
<commit_msg>a hammer, interesting puzzle<commit_after>pub fn decode_at_index(s: String, k: i32) -> String {
    use std::iter::FromIterator;
    let mut length = 0_usize;
    let mut cache = Vec::new();
    let mut result = String::new();
    let mut cache_clean = false;
    for c in s.chars() {
        if let Some(times) = c.to_digit(10) {
            length *= times as usize;
            //result += &String::from_iter(cache);
            //result = result.repeat(times as usize);
            cache_clean = true;
        } else {
            if cache_clean {
                cache = vec![];
                cache_clean = false;
            }
            length += 1;
            cache.push(c);
        }

        //println!("{}", result);
        if length == k as usize {
            return cache.pop().unwrap().to_string();
        }

        if length > k as usize {
            println!("{}", length);
            return result.get(k as usize - 1..k as usize).unwrap().into();
        }
    }

    result
}

fn inner_helper(s: &str, mut k: i32, last_cache: Vec<char>) -> String {
    let mut cache = last_cache;
    for (ind, c) in s.chars().enumerate() {
        if let Some(times) = c.to_digit(10) {
            if times as i32 * cache.len() as i32 >= k {
                return cache[(k % cache.len() as i32) as usize].into();
            } else {
                return inner_helper(
                    &s[ind..s.len()],
                    k - times as i32 * cache.len() as i32,
                    cache,
                );
            }
        } else {
            k -= 1;
            if k == 0 {
                return c.into();
            }
        }
    }
}

fn main() {
    dbg!(decode_at_index("leet2code3".to_string(), 10));
    dbg!(decode_at_index("ha22".to_string(), 5));
    dbg!(decode_at_index("a2345678999999999999999".to_string(), 1));
    dbg!(decode_at_index("a23".to_string(), 6));
}
<|endoftext|>


<commit_before>// Copyright (c) 2015-2016 Ivo Wetzel

// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::cmp;
use std::collections::{BinaryHeap, HashSet, VecDeque};
use super::super::Config;

/// Maximum message ordering id before wrap around happens.
const MAX_ORDER_ID: u16 = 4096;

/// Number of bytes used in a single message header.
const MESSAGE_HEADER_BYTES: usize = 4;

/// Enum for specification of a message handling algorithm.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum MessageKind {
    /// Message that is going be send exactly once and ignored in case its
    /// containing packet is lost. No guarantees are made as for the order in
    /// which a message of this kind is going to be received by a remote queue.
    Instant = 0,

    /// Message that is going to be re-send in case its containing packet is
    /// lost. No guarantees are made as for the order in which a message of
    /// this kind is going to be received by a remote queue.
    Reliable = 1,

    /// Message that is going to be re-send in case its containing packet is
    /// lost and is also guaranteed to arrive in-order, meaning that if you send
    /// two `Ordered` messages and the second arrives first in the remote queue
    /// , the remote queue will buffer the second message until the first one
    /// arrives and then make both of them available to the application at
    /// once.
    Ordered = 2,

    /// Invalid message which for some reason could not be parsed correctly
    /// from the available packet data.
    Invalid = 3
}

/// Structure for handling messages inside a `MessageQueue` with support for
/// insertion into a binary min heap for order checking on received messages.
#[derive(Debug, Eq, PartialEq)]
struct Message {
    kind: MessageKind,
    order: u16,
    size: u16,
    data: Vec<u8>
}

impl Ord for Message {
    // Explicitly implement the trait so the queue becomes a min-heap
    // instead of a max-heap.
    fn cmp(&self, other: &Message) -> cmp::Ordering {
        other.order.cmp(&self.order)
    }
}

impl PartialOrd for Message {
    fn partial_cmp(&self, other: &Message) -> Option<cmp::Ordering> {
        Some(self.cmp(other))
    }
}

/// Consuming iterator over the received messages of a `MessageQueue`.
pub struct MessageIterator<'a> {
    messages: &'a mut VecDeque<Message>
}

impl<'a> Iterator for MessageIterator<'a> {

    type Item = Vec<u8>;

    fn next(&mut self) -> Option<Self::Item> {
        match self.messages.pop_front() {
            Some(m) => Some(m.data),
            None => None
        }
    }

}

/// Implementation of a queue that manages the sending and receiving of both
/// reliable and unreliable message types and also supports optional in order
/// transmission.
#[derive(Debug)]
pub struct MessageQueue {

    /// The queue's configuration
    config: Config,

    /// The local order id which gets attached to all messages send as kind
    /// `MessageKind::Ordered`
    local_order_id: u16,

    /// The remote order id that is expected for the next incoming message of
    /// kind `MessageKind::Ordered`
    remote_order_id: u16,

    /// Queue of outgoing messages of the kind `MessageKind::Instant`
    i_queue: VecDeque<Message>,

    /// Queue of outgoing messages of the kind `MessageKind::Reliable`
    r_queue: VecDeque<Message>,

    /// Queue of outgoing messages of the kind `MessageKind::Ordered`
    o_queue: VecDeque<Message>,

    /// Ordered queue of incoming messages
    recv_queue: VecDeque<Message>,

    /// Binary Min-Heap to manage incomging, out of order messages
    o_recv_heap: BinaryHeap<Message>,

    /// Set for avoiding duplication of out of order messages
    o_recv_set: HashSet<u16>

}

impl MessageQueue {

    /// Creates a new queue for sending and receiving messages.
    pub fn new(config: Config) -> MessageQueue {
        MessageQueue {
            config: config,
            local_order_id: 0,
            remote_order_id: 0,
            i_queue: VecDeque::new(),
            r_queue: VecDeque::new(),
            o_queue: VecDeque::new(),
            recv_queue: VecDeque::new(),
            o_recv_heap: BinaryHeap::new(),
            o_recv_set: HashSet::new()
        }
    }

    /// Overrides the queue's existing configuration.
    pub fn set_config(&mut self, config: Config) {
        self.config = config;
    }

    /// Returns a consuming iterator over all received messages in the queue.
    pub fn received(&mut self) -> MessageIterator {
        MessageIterator { messages: &mut self.recv_queue }
    }

    /// Clears the queue of received messages, dismissing any messages which
    /// have not been fetched via `MessageQueue::received()`.
    pub fn dismiss(&mut self) {
        self.recv_queue.clear();
    }

    /// Pushes a message of the specified `kind` along with its `data` into the
    /// queue. The message will eventually get serialized via
    /// `MessageQueue::send_packet()`.
    pub fn send(&mut self, kind: MessageKind, data: Vec<u8>) {

        let message = Message {
            kind: kind,
            order: self.local_order_id,
            size: data.len() as u16,
            data: data
        };

        match kind {
            MessageKind::Instant => self.i_queue.push_back(message),
            MessageKind::Reliable => self.r_queue.push_back(message),
            MessageKind::Ordered => {

                self.o_queue.push_back(message);
                self.local_order_id += 1;

                if self.local_order_id == MAX_ORDER_ID {
                    self.local_order_id = 0;
                }

            },
            MessageKind::Invalid => {}
        }

    }

    /// Serializes a number of internally queued messages into the
    /// `available` space within the `packet`.
    ///
    /// The used algorithm first tries to fill the available space with the
    /// desired quotas for each `MessageKind` as defined in the queues
    /// configuration.
    ///
    /// Afterwards the remaining available space is filled by alternating
    /// between the different message kinds until there is finally no more
    /// space left to insert any further messages into the packet.
    ///
    /// For example, if we have `512` bytes available inside the packer and we
    /// specify that 60% of the packet data should be filled with
    /// `MessageKind::Instant` messages, then we will try to fill the
    /// buffer with at most `307` bytes of instant messages, at first.
    ///
    /// Then, after the other quotas have been taken into account, we'll try to
    /// fit more instant messages into the remaining available space within the
    /// packet.
    pub fn send_packet(&mut self, packet: &mut Vec<u8>, available: usize) {

        // First we are trying to fill the packet by using the set quotas
        let mut written = 0;
        write_messages(
            &mut self.i_queue, packet,
            (available as f32 / 100.0 * self.config.message_quota_instant) as usize,
            &mut written
        );

        write_messages(
            &mut self.r_queue, packet,
            (available as f32 / 100.0 * self.config.message_quota_reliable) as usize,
            &mut written
        );

        write_messages(
            &mut self.o_queue, packet,
            (available as f32 / 100.0 * self.config.message_quota_ordered) as usize,
            &mut written
        );

        // After that, we try to fill the remaining packet space by trying to
        // add one message of each kind until no more messages can be fit in
        let mut more = true;
        while more {
            more = false;
            more |= write_message(&mut self.i_queue, packet, available, &mut written);
            more |= write_message(&mut self.r_queue, packet, available, &mut written);
            more |= write_message(&mut self.o_queue, packet, available, &mut written);
        }

    }

    /// Parses the contents of a packet into messages, appending all valid
    /// messages into the internal receive queue.
    pub fn receive_packet(&mut self, packet: &[u8]) {
        for m in messages_from_packet(packet) {
            match m.kind {
                MessageKind::Instant => self.recv_queue.push_back(m),
                MessageKind::Reliable => self.recv_queue.push_back(m),
                MessageKind::Ordered => self.receive_ordered_message(m),
                MessageKind::Invalid => { /* ignore all other messages */ }
            }
        }
    }

    /// Parses the contents of a lost packet into messages, dropping all
    /// messages of the type `MessageKind::Instant` and prepending all
    /// remaining valid messages into the internal send queues for
    /// re-transmission.
    pub fn lost_packet(&mut self, packet: &[u8]) {
        for m in messages_from_packet(packet) {
            match m.kind {
                MessageKind::Instant => { /* ignore lost instant messages */ },
                MessageKind::Reliable => self.r_queue.push_front(m),
                MessageKind::Ordered => self.o_queue.push_front(m),
                MessageKind::Invalid => { /* ignore all other messages */ }
            }
        }
    }

    /// Resets the queue, clearing all its internal structures and order ids.
    pub fn reset(&mut self) {
        self.local_order_id = 0;
        self.remote_order_id = 0;
        self.i_queue.clear();
        self.r_queue.clear();
        self.o_queue.clear();
        self.recv_queue.clear();
        self.o_recv_heap.clear();
        self.o_recv_set.clear();
    }

    // Internal Message Handling ----------------------------------------------

    fn receive_ordered_message(&mut self, m: Message) {

        // Check if the order ID matches the currently expected on
        if m.order == self.remote_order_id {

            // Received the message in order
            self.recv_queue.push_back(m);

            self.remote_order_id += 1;
            if self.remote_order_id == MAX_ORDER_ID {
                self.remote_order_id = 0;
            }

            // Now check our heap for further messages we have received
            // out of order and check if they are next in the expected
            // order
            let mut matches = true;
            while matches {

                // TODO refactor

                // Check if the order id of the minimal item in the heap
                // matches the expected next remote order id
                matches = if let Some(msg) = self.o_recv_heap.peek() {
                    msg.order == self.remote_order_id

                } else {
                    false
                };

                // We found another message, matching the next expected order id
                if matches {

                    // Unset duplication marker
                    self.o_recv_set.remove(&self.remote_order_id);

                    // Remove it from the heap and push it into the recv queue
                    let msg = self.o_recv_heap.pop().unwrap();
                    self.recv_queue.push_back(msg);

                    self.remote_order_id += 1;
                    if self.remote_order_id == MAX_ORDER_ID {
                        self.remote_order_id = 0;
                    }

                }

            }

        // Otherwise check if the message order is more recent and if not, we
        // simply drop it. If it IS more recent, then we have received a future
        // message out of order.
        } else if order_is_more_recent(m.order, self.remote_order_id) {

            // Now, before we insert the message into the min-heap, we check
            // that there's no other message with the same order id in the heap
            // already. Duplicates would require additional peek / pop later on
            // when removing messages from the heap, so we resort to a Set here.
            if self.o_recv_set.contains(&m.order) == false {
                self.o_recv_set.insert(m.order);
                self.o_recv_heap.push(m);
            }

        }

    }

}

// Static Helpers -------------------------------------------------------------
fn order_is_more_recent(a: u16, b: u16) -> bool {
    (a > b) && (a - b <= MAX_ORDER_ID / 2)
    || (b > a) && (b - a > MAX_ORDER_ID / 2)
}

fn messages_from_packet(packet: &[u8]) -> Vec<Message> {

    let available = packet.len();
    let mut index = 0;
    let mut messages = Vec::new();

    // Consume as long as message headers can be present
    while index < available && available - index >= MESSAGE_HEADER_BYTES {

        // Upper 4 bits of kind are bits 9..11 of order
        let order_high = ((packet[index] & 0xF0) as u16) << 4;
        let order_low = packet[index + 1] as u16;

        // Byte 2 is the size
        let size_high = (packet[index + 2] as u16) << 8;
        let size = size_high | packet[index + 3] as u16;

        // Read available data
        messages.push(Message {

            // Lower 4 bits of byte 0 are the MessageKind
            kind: match packet[index] & 0x0F {
                0 => MessageKind::Instant,
                1 => MessageKind::Reliable,
                2 => MessageKind::Ordered,
                _ => MessageKind::Invalid
            },

            order: order_high | order_low,
            size: size,
            data: packet[
                index + MESSAGE_HEADER_BYTES..cmp::min(
                    index + MESSAGE_HEADER_BYTES + size as usize,
                    available
                )
            ].to_vec()

        });

        index += size as usize + MESSAGE_HEADER_BYTES;

    }

    messages

}

fn write_messages(
    queue: &mut VecDeque<Message>,
    packet: &mut Vec<u8>,
    available: usize,
    written: &mut usize
) {
    let mut used = 0;
    while write_message(queue, packet, available, &mut used) {}
    *written += used;
}

fn write_message(
    queue: &mut VecDeque<Message>,
    packet: &mut Vec<u8>,
    available: usize,
    written: &mut usize

) -> bool {

    if queue.is_empty() == false {

        let required = {
            (queue.front().unwrap().size as usize) + MESSAGE_HEADER_BYTES
        };

        // If adding this message would exceed the available bytes, exit
        if required > available - *written {
            false

        // Remove and serialize the message into the packet
        } else {
            let message = queue.pop_front().unwrap();
            packet.push(
                ((message.order & 0x0F00) >> 4) as u8 | (message.kind as u8)
            );
            packet.push(message.order as u8);
            packet.push((message.size >> 8) as u8);
            packet.push(message.size as u8);
            packet.extend(message.data.iter().cloned());
            *written += required;
            true
        }

    } else {
        false
    }

}

<commit_msg>Switch to extend_from_slice when constructing messages.<commit_after>// Copyright (c) 2015-2016 Ivo Wetzel

// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::cmp;
use std::collections::{BinaryHeap, HashSet, VecDeque};
use super::super::Config;

/// Maximum message ordering id before wrap around happens.
const MAX_ORDER_ID: u16 = 4096;

/// Number of bytes used in a single message header.
const MESSAGE_HEADER_BYTES: usize = 4;

/// Enum for specification of a message handling algorithm.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum MessageKind {
    /// Message that is going be send exactly once and ignored in case its
    /// containing packet is lost. No guarantees are made as for the order in
    /// which a message of this kind is going to be received by a remote queue.
    Instant = 0,

    /// Message that is going to be re-send in case its containing packet is
    /// lost. No guarantees are made as for the order in which a message of
    /// this kind is going to be received by a remote queue.
    Reliable = 1,

    /// Message that is going to be re-send in case its containing packet is
    /// lost and is also guaranteed to arrive in-order, meaning that if you send
    /// two `Ordered` messages and the second arrives first in the remote queue
    /// , the remote queue will buffer the second message until the first one
    /// arrives and then make both of them available to the application at
    /// once.
    Ordered = 2,

    /// Invalid message which for some reason could not be parsed correctly
    /// from the available packet data.
    Invalid = 3
}

/// Structure for handling messages inside a `MessageQueue` with support for
/// insertion into a binary min heap for order checking on received messages.
#[derive(Debug, Eq, PartialEq)]
struct Message {
    kind: MessageKind,
    order: u16,
    size: u16,
    data: Vec<u8>
}

impl Ord for Message {
    // Explicitly implement the trait so the queue becomes a min-heap
    // instead of a max-heap.
    fn cmp(&self, other: &Message) -> cmp::Ordering {
        other.order.cmp(&self.order)
    }
}

impl PartialOrd for Message {
    fn partial_cmp(&self, other: &Message) -> Option<cmp::Ordering> {
        Some(self.cmp(other))
    }
}

/// Consuming iterator over the received messages of a `MessageQueue`.
pub struct MessageIterator<'a> {
    messages: &'a mut VecDeque<Message>
}

impl<'a> Iterator for MessageIterator<'a> {

    type Item = Vec<u8>;

    fn next(&mut self) -> Option<Self::Item> {
        match self.messages.pop_front() {
            Some(m) => Some(m.data),
            None => None
        }
    }

}

/// Implementation of a queue that manages the sending and receiving of both
/// reliable and unreliable message types and also supports optional in order
/// transmission.
#[derive(Debug)]
pub struct MessageQueue {

    /// The queue's configuration
    config: Config,

    /// The local order id which gets attached to all messages send as kind
    /// `MessageKind::Ordered`
    local_order_id: u16,

    /// The remote order id that is expected for the next incoming message of
    /// kind `MessageKind::Ordered`
    remote_order_id: u16,

    /// Queue of outgoing messages of the kind `MessageKind::Instant`
    i_queue: VecDeque<Message>,

    /// Queue of outgoing messages of the kind `MessageKind::Reliable`
    r_queue: VecDeque<Message>,

    /// Queue of outgoing messages of the kind `MessageKind::Ordered`
    o_queue: VecDeque<Message>,

    /// Ordered queue of incoming messages
    recv_queue: VecDeque<Message>,

    /// Binary Min-Heap to manage incomging, out of order messages
    o_recv_heap: BinaryHeap<Message>,

    /// Set for avoiding duplication of out of order messages
    o_recv_set: HashSet<u16>

}

impl MessageQueue {

    /// Creates a new queue for sending and receiving messages.
    pub fn new(config: Config) -> MessageQueue {
        MessageQueue {
            config: config,
            local_order_id: 0,
            remote_order_id: 0,
            i_queue: VecDeque::new(),
            r_queue: VecDeque::new(),
            o_queue: VecDeque::new(),
            recv_queue: VecDeque::new(),
            o_recv_heap: BinaryHeap::new(),
            o_recv_set: HashSet::new()
        }
    }

    /// Overrides the queue's existing configuration.
    pub fn set_config(&mut self, config: Config) {
        self.config = config;
    }

    /// Returns a consuming iterator over all received messages in the queue.
    pub fn received(&mut self) -> MessageIterator {
        MessageIterator { messages: &mut self.recv_queue }
    }

    /// Clears the queue of received messages, dismissing any messages which
    /// have not been fetched via `MessageQueue::received()`.
    pub fn dismiss(&mut self) {
        self.recv_queue.clear();
    }

    /// Pushes a message of the specified `kind` along with its `data` into the
    /// queue. The message will eventually get serialized via
    /// `MessageQueue::send_packet()`.
    pub fn send(&mut self, kind: MessageKind, data: Vec<u8>) {

        let message = Message {
            kind: kind,
            order: self.local_order_id,
            size: data.len() as u16,
            data: data
        };

        match kind {
            MessageKind::Instant => self.i_queue.push_back(message),
            MessageKind::Reliable => self.r_queue.push_back(message),
            MessageKind::Ordered => {

                self.o_queue.push_back(message);
                self.local_order_id += 1;

                if self.local_order_id == MAX_ORDER_ID {
                    self.local_order_id = 0;
                }

            },
            MessageKind::Invalid => {}
        }

    }

    /// Serializes a number of internally queued messages into the
    /// `available` space within the `packet`.
    ///
    /// The used algorithm first tries to fill the available space with the
    /// desired quotas for each `MessageKind` as defined in the queues
    /// configuration.
    ///
    /// Afterwards the remaining available space is filled by alternating
    /// between the different message kinds until there is finally no more
    /// space left to insert any further messages into the packet.
    ///
    /// For example, if we have `512` bytes available inside the packer and we
    /// specify that 60% of the packet data should be filled with
    /// `MessageKind::Instant` messages, then we will try to fill the
    /// buffer with at most `307` bytes of instant messages, at first.
    ///
    /// Then, after the other quotas have been taken into account, we'll try to
    /// fit more instant messages into the remaining available space within the
    /// packet.
    pub fn send_packet(&mut self, packet: &mut Vec<u8>, available: usize) {

        // First we are trying to fill the packet by using the set quotas
        let mut written = 0;
        write_messages(
            &mut self.i_queue, packet,
            (available as f32 / 100.0 * self.config.message_quota_instant) as usize,
            &mut written
        );

        write_messages(
            &mut self.r_queue, packet,
            (available as f32 / 100.0 * self.config.message_quota_reliable) as usize,
            &mut written
        );

        write_messages(
            &mut self.o_queue, packet,
            (available as f32 / 100.0 * self.config.message_quota_ordered) as usize,
            &mut written
        );

        // After that, we try to fill the remaining packet space by trying to
        // add one message of each kind until no more messages can be fit in
        let mut more = true;
        while more {
            more = false;
            more |= write_message(&mut self.i_queue, packet, available, &mut written);
            more |= write_message(&mut self.r_queue, packet, available, &mut written);
            more |= write_message(&mut self.o_queue, packet, available, &mut written);
        }

    }

    /// Parses the contents of a packet into messages, appending all valid
    /// messages into the internal receive queue.
    pub fn receive_packet(&mut self, packet: &[u8]) {
        for m in messages_from_packet(packet) {
            match m.kind {
                MessageKind::Instant => self.recv_queue.push_back(m),
                MessageKind::Reliable => self.recv_queue.push_back(m),
                MessageKind::Ordered => self.receive_ordered_message(m),
                MessageKind::Invalid => { /* ignore all other messages */ }
            }
        }
    }

    /// Parses the contents of a lost packet into messages, dropping all
    /// messages of the type `MessageKind::Instant` and prepending all
    /// remaining valid messages into the internal send queues for
    /// re-transmission.
    pub fn lost_packet(&mut self, packet: &[u8]) {
        for m in messages_from_packet(packet) {
            match m.kind {
                MessageKind::Instant => { /* ignore lost instant messages */ },
                MessageKind::Reliable => self.r_queue.push_front(m),
                MessageKind::Ordered => self.o_queue.push_front(m),
                MessageKind::Invalid => { /* ignore all other messages */ }
            }
        }
    }

    /// Resets the queue, clearing all its internal structures and order ids.
    pub fn reset(&mut self) {
        self.local_order_id = 0;
        self.remote_order_id = 0;
        self.i_queue.clear();
        self.r_queue.clear();
        self.o_queue.clear();
        self.recv_queue.clear();
        self.o_recv_heap.clear();
        self.o_recv_set.clear();
    }

    // Internal Message Handling ----------------------------------------------

    fn receive_ordered_message(&mut self, m: Message) {

        // Check if the order ID matches the currently expected on
        if m.order == self.remote_order_id {

            // Received the message in order
            self.recv_queue.push_back(m);

            self.remote_order_id += 1;
            if self.remote_order_id == MAX_ORDER_ID {
                self.remote_order_id = 0;
            }

            // Now check our heap for further messages we have received
            // out of order and check if they are next in the expected
            // order
            let mut matches = true;
            while matches {

                // TODO refactor

                // Check if the order id of the minimal item in the heap
                // matches the expected next remote order id
                matches = if let Some(msg) = self.o_recv_heap.peek() {
                    msg.order == self.remote_order_id

                } else {
                    false
                };

                // We found another message, matching the next expected order id
                if matches {

                    // Unset duplication marker
                    self.o_recv_set.remove(&self.remote_order_id);

                    // Remove it from the heap and push it into the recv queue
                    let msg = self.o_recv_heap.pop().unwrap();
                    self.recv_queue.push_back(msg);

                    self.remote_order_id += 1;
                    if self.remote_order_id == MAX_ORDER_ID {
                        self.remote_order_id = 0;
                    }

                }

            }

        // Otherwise check if the message order is more recent and if not, we
        // simply drop it. If it IS more recent, then we have received a future
        // message out of order.
        } else if order_is_more_recent(m.order, self.remote_order_id) {

            // Now, before we insert the message into the min-heap, we check
            // that there's no other message with the same order id in the heap
            // already. Duplicates would require additional peek / pop later on
            // when removing messages from the heap, so we resort to a Set here.
            if self.o_recv_set.contains(&m.order) == false {
                self.o_recv_set.insert(m.order);
                self.o_recv_heap.push(m);
            }

        }

    }

}

// Static Helpers -------------------------------------------------------------
fn order_is_more_recent(a: u16, b: u16) -> bool {
    (a > b) && (a - b <= MAX_ORDER_ID / 2)
    || (b > a) && (b - a > MAX_ORDER_ID / 2)
}

fn messages_from_packet(packet: &[u8]) -> Vec<Message> {

    let available = packet.len();
    let mut index = 0;
    let mut messages = Vec::new();

    // Consume as long as message headers can be present
    while index < available && available - index >= MESSAGE_HEADER_BYTES {

        // Upper 4 bits of kind are bits 9..11 of order
        let order_high = ((packet[index] & 0xF0) as u16) << 4;
        let order_low = packet[index + 1] as u16;

        // Byte 2 is the size
        let size_high = (packet[index + 2] as u16) << 8;
        let size = size_high | packet[index + 3] as u16;

        // Read available data
        messages.push(Message {

            // Lower 4 bits of byte 0 are the MessageKind
            kind: match packet[index] & 0x0F {
                0 => MessageKind::Instant,
                1 => MessageKind::Reliable,
                2 => MessageKind::Ordered,
                _ => MessageKind::Invalid
            },

            order: order_high | order_low,
            size: size,
            data: packet[
                index + MESSAGE_HEADER_BYTES..cmp::min(
                    index + MESSAGE_HEADER_BYTES + size as usize,
                    available
                )
            ].to_vec()

        });

        index += size as usize + MESSAGE_HEADER_BYTES;

    }

    messages

}

fn write_messages(
    queue: &mut VecDeque<Message>,
    packet: &mut Vec<u8>,
    available: usize,
    written: &mut usize
) {
    let mut used = 0;
    while write_message(queue, packet, available, &mut used) {}
    *written += used;
}

fn write_message(
    queue: &mut VecDeque<Message>,
    packet: &mut Vec<u8>,
    available: usize,
    written: &mut usize

) -> bool {

    if queue.is_empty() == false {

        let required = {
            (queue.front().unwrap().size as usize) + MESSAGE_HEADER_BYTES
        };

        // If adding this message would exceed the available bytes, exit
        if required > available - *written {
            false

        // Remove and serialize the message into the packet
        } else {
            let message = queue.pop_front().unwrap();
            packet.push(
                ((message.order & 0x0F00) >> 4) as u8 | (message.kind as u8)
            );
            packet.push(message.order as u8);
            packet.push((message.size >> 8) as u8);
            packet.push(message.size as u8);
            packet.extend_from_slice(&message.data[..]);
            *written += required;
            true
        }

    } else {
        false
    }

}

<|endoftext|>


<commit_before>extern crate rand;

use std::path::Path;
use rand::{Rng, ThreadRng};

const NOUN_FORMAT_CHAR: u8 = b'%';
const ADJECTIVE_FORMAT_CHAR: u8 = b'#';
const ADVERB_FORMAT_CHAR: u8 = b'@';
const ABSTRACT_FORMAT_CHAR: u8 = b'$';

mod phrase;
use self::phrase::Phrase;
// Phrase is just a wrapper around a String with a method to load a Vec of them from a file

pub struct TemplateManager {
    // this is a struct that handles all of the actual text generation
    // we use Vec<Phrase> so we can use Rng.choose()
    templates: Vec<Phrase>,
    nouns: Vec<Phrase>,
    adjectives: Vec<Phrase>,
    adverbs: Vec<Phrase>,
    abstracts: Vec<Phrase>,
}

impl TemplateManager {
    pub fn new<P0, P1, P2, P3, P4>(template_path: P0, noun_path: P1, adj_path: P2, adv_path: P3, abstract_path: P4) -> TemplateManager
        where P0: AsRef<Path>, P1: AsRef<Path>, P2: AsRef<Path>, P3: AsRef<Path>, P4: AsRef<Path>
    // given paths to all of the lists of stuff, create a new Template_manager
    {
        TemplateManager {
            templates: Phrase::load_from_file(template_path),
            nouns: Phrase::load_from_file(noun_path),
            adjectives: Phrase::load_from_file(adj_path),
            adverbs: Phrase::load_from_file(adv_path),
            abstracts: Phrase::load_from_file(abstract_path),
        }
    }

    fn get_noun_phrase(&self, mut rng: &mut ThreadRng) -> Vec<u8> {
        // we juggle Vec<u8>s around here because they're easy to iterate through and replace bytes
        // this method and its friends get_adjective_phrase and get_adverb_phrase choose a random phrase from the Vec<Phrase>s
        if let Some(ref noun_phrase) = rng.choose(&self.nouns) {
            noun_phrase.text.clone().into_bytes()
        } else {
            panic!("couldn't get a noun phrase")
        }
    }

    fn get_adjective_phrase(&self, mut rng: &mut ThreadRng) -> Vec<u8> {
        if let Some(ref adj_phrase) = rng.choose(&self.adjectives) {
            adj_phrase.text.clone().into_bytes()
        } else {
            panic!("couldn't get an adjective phrase")
        }
    }

    fn get_adverb_phrase(&self, mut rng: &mut ThreadRng) -> Vec<u8> {
        if let Some(ref adv_phrase) = rng.choose(&self.adverbs) {
            adv_phrase.text.clone().into_bytes()
        } else {
            panic!("couldn't get an adjective phrase")
        }
    }

    fn get_abstract_phrase(&self, mut rng: &mut ThreadRng) -> Vec<u8> {
        if let Some(ref abstract_phrase) = rng.choose(&self.abstracts) {
            abstract_phrase.text.clone().into_bytes()
        } else {
            panic!("couldn't get an abstract phrase")
        }
    }

    fn format_phrase(&self, phrase: Vec<u8>, mut rng: &mut ThreadRng) -> Vec<u8> {
        // this method iterates through a Vec<u8> and replaces any of the FORMAT_CHARs with a phrase
        // it's recursive so that adjectives can be things like "%-driven"
        let mut new_bytes: Vec<u8> = Vec::new();
        for byte in &phrase {
            match *byte {
                NOUN_FORMAT_CHAR => {
                    for noun_byte in &self.format_phrase(self.get_noun_phrase(&mut rng), &mut rng) {
                        new_bytes.push(*noun_byte);
                    }
                },
                ADJECTIVE_FORMAT_CHAR => {
                    for adj_byte in &self.format_phrase(self.get_adjective_phrase(&mut rng), &mut rng) {
                        new_bytes.push(*adj_byte);
                    }
                },
                ADVERB_FORMAT_CHAR => {
                    for adv_byte in &self.format_phrase(self.get_adverb_phrase(&mut rng), &mut rng) {
                        new_bytes.push(*adv_byte);
                    }
                },
                ABSTRACT_FORMAT_CHAR => {
                    for abstract_byte in &self.format_phrase(self.get_abstract_phrase(&mut rng), &mut rng) {
                        new_bytes.push(*abstract_byte);
                    }
                },
                _ => {
                    new_bytes.push(*byte);
                }
            }
        }
        new_bytes
    }

    pub fn make_formatted_quote(&self, mut rng: &mut ThreadRng) -> String {
        // this is the big wrapper method that main.rs/main() calls
        // it returns a fully formatted phrase that can be tweeted
        // note: I can't figure out how to have the Template_handler own rng
        // because getting a random value mutates the rng
        // so instead it's owned by main() and these methods just pass refs to it back and forth
        if let Some(ref template) = rng.choose(&self.templates) {
            String::from_utf8(self.format_phrase(template.text.clone().into_bytes(), &mut rng)).unwrap()
        } else {
            panic!("couldn't get a template")
        }
    }
}
<commit_msg>shut up clippy<commit_after>extern crate rand;

use std::path::Path;
use rand::{Rng, ThreadRng};

const NOUN_FORMAT_CHAR: u8 = b'%';
const ADJECTIVE_FORMAT_CHAR: u8 = b'#';
const ADVERB_FORMAT_CHAR: u8 = b'@';
const ABSTRACT_FORMAT_CHAR: u8 = b'$';

mod phrase;
use self::phrase::Phrase;
// Phrase is just a wrapper around a String with a method to load a Vec of them from a file

pub struct TemplateManager {
    // this is a struct that handles all of the actual text generation
    // we use Vec<Phrase> so we can use Rng.choose()
    templates: Vec<Phrase>,
    nouns: Vec<Phrase>,
    adjectives: Vec<Phrase>,
    adverbs: Vec<Phrase>,
    abstracts: Vec<Phrase>,
}

impl TemplateManager {
    pub fn new<P0, P1, P2, P3, P4>(template_path: P0, noun_path: P1, adj_path: P2, adv_path: P3, abstract_path: P4) -> TemplateManager
        where P0: AsRef<Path>, P1: AsRef<Path>, P2: AsRef<Path>, P3: AsRef<Path>, P4: AsRef<Path>
    // given paths to all of the lists of stuff, create a new Template_manager
    {
        TemplateManager {
            templates: Phrase::load_from_file(template_path),
            nouns: Phrase::load_from_file(noun_path),
            adjectives: Phrase::load_from_file(adj_path),
            adverbs: Phrase::load_from_file(adv_path),
            abstracts: Phrase::load_from_file(abstract_path),
        }
    }

    fn get_noun_phrase(&self, mut rng: &mut ThreadRng) -> Vec<u8> {
        // we juggle Vec<u8>s around here because they're easy to iterate through and replace bytes
        // this method and its friends get_adjective_phrase and get_adverb_phrase choose a random phrase from the Vec<Phrase>s
        if let Some(noun_phrase) = rng.choose(&self.nouns) {
            noun_phrase.text.clone().into_bytes()
        } else {
            panic!("couldn't get a noun phrase")
        }
    }

    fn get_adjective_phrase(&self, mut rng: &mut ThreadRng) -> Vec<u8> {
        if let Some(adj_phrase) = rng.choose(&self.adjectives) {
            adj_phrase.text.clone().into_bytes()
        } else {
            panic!("couldn't get an adjective phrase")
        }
    }

    fn get_adverb_phrase(&self, mut rng: &mut ThreadRng) -> Vec<u8> {
        if let Some(adv_phrase) = rng.choose(&self.adverbs) {
            adv_phrase.text.clone().into_bytes()
        } else {
            panic!("couldn't get an adjective phrase")
        }
    }

    fn get_abstract_phrase(&self, mut rng: &mut ThreadRng) -> Vec<u8> {
        if let Some(abstract_phrase) = rng.choose(&self.abstracts) {
            abstract_phrase.text.clone().into_bytes()
        } else {
            panic!("couldn't get an abstract phrase")
        }
    }

    fn format_phrase(&self, phrase: Vec<u8>, mut rng: &mut ThreadRng) -> Vec<u8> {
        // this method iterates through a Vec<u8> and replaces any of the FORMAT_CHARs with a phrase
        // it's recursive so that adjectives can be things like "%-driven"
        let mut new_bytes: Vec<u8> = Vec::new();
        for byte in &phrase {
            match *byte {
                NOUN_FORMAT_CHAR => {
                    for noun_byte in &self.format_phrase(self.get_noun_phrase(&mut rng), &mut rng) {
                        new_bytes.push(*noun_byte);
                    }
                },
                ADJECTIVE_FORMAT_CHAR => {
                    for adj_byte in &self.format_phrase(self.get_adjective_phrase(&mut rng), &mut rng) {
                        new_bytes.push(*adj_byte);
                    }
                },
                ADVERB_FORMAT_CHAR => {
                    for adv_byte in &self.format_phrase(self.get_adverb_phrase(&mut rng), &mut rng) {
                        new_bytes.push(*adv_byte);
                    }
                },
                ABSTRACT_FORMAT_CHAR => {
                    for abstract_byte in &self.format_phrase(self.get_abstract_phrase(&mut rng), &mut rng) {
                        new_bytes.push(*abstract_byte);
                    }
                },
                _ => {
                    new_bytes.push(*byte);
                }
            }
        }
        new_bytes
    }

    pub fn make_formatted_quote(&self, mut rng: &mut ThreadRng) -> String {
        // this is the big wrapper method that main.rs/main() calls
        // it returns a fully formatted phrase that can be tweeted
        // note: I can't figure out how to have the Template_handler own rng
        // because getting a random value mutates the rng
        // so instead it's owned by main() and these methods just pass refs to it back and forth
        if let Some(template) = rng.choose(&self.templates) {
            String::from_utf8(self.format_phrase(template.text.clone().into_bytes(), &mut rng)).unwrap()
        } else {
            panic!("couldn't get a template")
        }
    }
}
<|endoftext|>


<commit_before>//! Tidy check to enforce various stylistic guidelines on the Rust codebase.
//!
//! Example checks are:
//!
//! * No lines over 100 characters.
//! * No files with over 3000 lines.
//! * No tabs.
//! * No trailing whitespace.
//! * No CR characters.
//! * No `TODO` or `XXX` directives.
//! * No unexplained ` ```ignore ` or ` ```rust,ignore ` doc tests.
//!
//! A number of these checks can be opted-out of with various directives of the form:
//! `// ignore-tidy-CHECK-NAME`.

use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

const COLS: usize = 100;

const LINES: usize = 3000;

const UNEXPLAINED_IGNORE_DOCTEST_INFO: &str = r#"unexplained "```ignore" doctest; try one:

* make the test actually pass, by adding necessary imports and declarations, or
* use "```text", if the code is not Rust code, or
* use "```compile_fail,Ennnn", if the code is expected to fail at compile time, or
* use "```should_panic", if the code is expected to fail at run time, or
* use "```no_run", if the code should type-check but not necessary linkable/runnable, or
* explain it like "```ignore (cannot-test-this-because-xxxx)", if the annotation cannot be avoided.

"#;

const LLVM_UNREACHABLE_INFO: &str = r"\
C++ code used llvm_unreachable, which triggers undefined behavior
when executed when assertions are disabled.
Use llvm::report_fatal_error for increased robustness.";

/// Parser states for `line_is_url`.
#[derive(PartialEq)]
#[allow(non_camel_case_types)]
enum LIUState {
    EXP_COMMENT_START,
    EXP_LINK_LABEL_OR_URL,
    EXP_URL,
    EXP_END,
}

/// Returns `true` if `line` appears to be a line comment containing an URL,
/// possibly with a Markdown link label in front, and nothing else.
/// The Markdown link label, if present, may not contain whitespace.
/// Lines of this form are allowed to be overlength, because Markdown
/// offers no way to split a line in the middle of a URL, and the lengths
/// of URLs to external references are beyond our control.
fn line_is_url(line: &str) -> bool {
    use self::LIUState::*;
    let mut state: LIUState = EXP_COMMENT_START;

    for tok in line.split_whitespace() {
        match (state, tok) {
            (EXP_COMMENT_START, "//") => state = EXP_LINK_LABEL_OR_URL,
            (EXP_COMMENT_START, "///") => state = EXP_LINK_LABEL_OR_URL,
            (EXP_COMMENT_START, "//!") => state = EXP_LINK_LABEL_OR_URL,

            (EXP_LINK_LABEL_OR_URL, w)
                if w.len() >= 4 && w.starts_with('[') && w.ends_with("]:")
                => state = EXP_URL,

            (EXP_LINK_LABEL_OR_URL, w)
                if w.starts_with("http://") || w.starts_with("https://")
                => state = EXP_END,

            (EXP_URL, w)
                if w.starts_with("http://") || w.starts_with("https://") || w.starts_with("../")
                => state = EXP_END,

            (_, _) => return false,
        }
    }

    state == EXP_END
}

/// Returns `true` if `line` is allowed to be longer than the normal limit.
/// Currently there is only one exception, for long URLs, but more
/// may be added in the future.
fn long_line_is_ok(line: &str) -> bool {
    if line_is_url(line) {
        return true;
    }

    false
}

enum Directive {
    /// By default, tidy always warns against style issues.
    Deny,

    /// `Ignore(false)` means that an `ignore-tidy-*` directive
    /// has been provided, but is unnecessary. `Ignore(true)`
    /// means that it is necessary (i.e. a warning would be
    /// produced if `ignore-tidy-*` was not present).
    Ignore(bool),
}

fn contains_ignore_directive(contents: &String, check: &str) -> Directive {
    if contents.contains(&format!("// ignore-tidy-{}", check)) ||
        contents.contains(&format!("# ignore-tidy-{}", check)) {
        Directive::Ignore(false)
    } else {
        Directive::Deny
    }
}

macro_rules! suppressible_tidy_err {
    ($err:ident, $skip:ident, $msg:expr) => {
        if let Directive::Deny = $skip {
            $err($msg);
        } else {
            $skip = Directive::Ignore(true);
        }
    };
}

pub fn check(path: &Path, bad: &mut bool) {
    let mut contents = String::new();
    super::walk(path, &mut super::filter_dirs, &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        let extensions = [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h"];
        if extensions.iter().all(|e| !filename.ends_with(e)) ||
           filename.starts_with(".#") {
            return
        }

        contents.truncate(0);
        t!(t!(File::open(file), file).read_to_string(&mut contents));

        if contents.is_empty() {
            tidy_error!(bad, "{}: empty file", file.display());
        }

        let mut skip_cr = contains_ignore_directive(&contents, "cr");
        let mut skip_tab = contains_ignore_directive(&contents, "tab");
        let mut skip_line_length = contains_ignore_directive(&contents, "linelength");
        let mut skip_file_length = contains_ignore_directive(&contents, "filelength");
        let mut skip_end_whitespace = contains_ignore_directive(&contents, "end-whitespace");
        let mut skip_copyright = contains_ignore_directive(&contents, "copyright");
        let mut leading_new_lines = false;
        let mut trailing_new_lines = 0;
        let mut lines = 0;
        for (i, line) in contents.split('\n').enumerate() {
            let mut err = |msg: &str| {
                tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg);
            };
            if line.chars().count() > COLS && !long_line_is_ok(line) {
                suppressible_tidy_err!(
                    err,
                    skip_line_length,
                    &format!("line longer than {} chars", COLS)
                );
            }
            if line.contains('\t') {
                suppressible_tidy_err!(err, skip_tab, "tab character");
            }
            if line.ends_with(' ') || line.ends_with('\t') {
                suppressible_tidy_err!(err, skip_end_whitespace, "trailing whitespace");
            }
            if line.contains('\r') {
                suppressible_tidy_err!(err, skip_cr, "CR character");
            }
            if filename != "style.rs" {
                if line.contains("TODO") {
                    err("TODO is deprecated; use FIXME")
                }
                if line.contains("//") && line.contains(" XXX") {
                    err("XXX is deprecated; use FIXME")
                }
            }
            if (line.starts_with("// Copyright") ||
                line.starts_with("# Copyright") ||
                line.starts_with("Copyright"))
                && (line.contains("Rust Developers") ||
                    line.contains("Rust Project Developers")) {
                suppressible_tidy_err!(
                    err,
                    skip_copyright,
                    "copyright notices attributed to the Rust Project Developers are deprecated"
                );
            }
            if line.ends_with("```ignore") || line.ends_with("```rust,ignore") {
                err(UNEXPLAINED_IGNORE_DOCTEST_INFO);
            }
            if filename.ends_with(".cpp") && line.contains("llvm_unreachable") {
                err(LLVM_UNREACHABLE_INFO);
            }
            if line.is_empty() {
                if i == 0 {
                    leading_new_lines = true;
                }
                trailing_new_lines += 1;
            } else {
                trailing_new_lines = 0;
            }
            lines = i;
        }
        if leading_new_lines {
            tidy_error!(bad, "{}: leading newline", file.display());
        }
        match trailing_new_lines {
            0 => tidy_error!(bad, "{}: missing trailing newline", file.display()),
            1 => {}
            n => tidy_error!(bad, "{}: too many trailing newlines ({})", file.display(), n),
        };
        if !skip_file_length && lines > LINES {
            tidy_error!(
                bad,
                "{}: too many lines ({}) (add `// ignore-tidy-filelength` to the file to \
                 suppress this error)",
                file.display(),
                lines
            );
        }

        if let Directive::Ignore(false) = skip_cr {
            tidy_error!(bad, "{}: ignoring CR characters unnecessarily", file.display());
        }
        if let Directive::Ignore(false) = skip_tab {
            tidy_error!(bad, "{}: ignoring tab characters unnecessarily", file.display());
        }
        if let Directive::Ignore(false) = skip_line_length {
            tidy_error!(bad, "{}: ignoring line length unnecessarily", file.display());
        }
        if let Directive::Ignore(false) = skip_file_length {
            tidy_error!(bad, "{}: ignoring file length unnecessarily", file.display());
        }
        if let Directive::Ignore(false) = skip_end_whitespace {
            tidy_error!(bad, "{}: ignoring trailing whitespace unnecessarily", file.display());
        }
        if let Directive::Ignore(false) = skip_copyright {
            tidy_error!(bad, "{}: ignoring copyright unnecessarily", file.display());
        }
    })
}
<commit_msg>Fix false position on style.rs itself<commit_after>//! Tidy check to enforce various stylistic guidelines on the Rust codebase.
//!
//! Example checks are:
//!
//! * No lines over 100 characters.
//! * No files with over 3000 lines.
//! * No tabs.
//! * No trailing whitespace.
//! * No CR characters.
//! * No `TODO` or `XXX` directives.
//! * No unexplained ` ```ignore ` or ` ```rust,ignore ` doc tests.
//!
//! A number of these checks can be opted-out of with various directives of the form:
//! `// ignore-tidy-CHECK-NAME`.

use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

const COLS: usize = 100;

const LINES: usize = 3000;

const UNEXPLAINED_IGNORE_DOCTEST_INFO: &str = r#"unexplained "```ignore" doctest; try one:

* make the test actually pass, by adding necessary imports and declarations, or
* use "```text", if the code is not Rust code, or
* use "```compile_fail,Ennnn", if the code is expected to fail at compile time, or
* use "```should_panic", if the code is expected to fail at run time, or
* use "```no_run", if the code should type-check but not necessary linkable/runnable, or
* explain it like "```ignore (cannot-test-this-because-xxxx)", if the annotation cannot be avoided.

"#;

const LLVM_UNREACHABLE_INFO: &str = r"\
C++ code used llvm_unreachable, which triggers undefined behavior
when executed when assertions are disabled.
Use llvm::report_fatal_error for increased robustness.";

/// Parser states for `line_is_url`.
#[derive(PartialEq)]
#[allow(non_camel_case_types)]
enum LIUState {
    EXP_COMMENT_START,
    EXP_LINK_LABEL_OR_URL,
    EXP_URL,
    EXP_END,
}

/// Returns `true` if `line` appears to be a line comment containing an URL,
/// possibly with a Markdown link label in front, and nothing else.
/// The Markdown link label, if present, may not contain whitespace.
/// Lines of this form are allowed to be overlength, because Markdown
/// offers no way to split a line in the middle of a URL, and the lengths
/// of URLs to external references are beyond our control.
fn line_is_url(line: &str) -> bool {
    use self::LIUState::*;
    let mut state: LIUState = EXP_COMMENT_START;

    for tok in line.split_whitespace() {
        match (state, tok) {
            (EXP_COMMENT_START, "//") => state = EXP_LINK_LABEL_OR_URL,
            (EXP_COMMENT_START, "///") => state = EXP_LINK_LABEL_OR_URL,
            (EXP_COMMENT_START, "//!") => state = EXP_LINK_LABEL_OR_URL,

            (EXP_LINK_LABEL_OR_URL, w)
                if w.len() >= 4 && w.starts_with('[') && w.ends_with("]:")
                => state = EXP_URL,

            (EXP_LINK_LABEL_OR_URL, w)
                if w.starts_with("http://") || w.starts_with("https://")
                => state = EXP_END,

            (EXP_URL, w)
                if w.starts_with("http://") || w.starts_with("https://") || w.starts_with("../")
                => state = EXP_END,

            (_, _) => return false,
        }
    }

    state == EXP_END
}

/// Returns `true` if `line` is allowed to be longer than the normal limit.
/// Currently there is only one exception, for long URLs, but more
/// may be added in the future.
fn long_line_is_ok(line: &str) -> bool {
    if line_is_url(line) {
        return true;
    }

    false
}

enum Directive {
    /// By default, tidy always warns against style issues.
    Deny,

    /// `Ignore(false)` means that an `ignore-tidy-*` directive
    /// has been provided, but is unnecessary. `Ignore(true)`
    /// means that it is necessary (i.e. a warning would be
    /// produced if `ignore-tidy-*` was not present).
    Ignore(bool),
}

fn contains_ignore_directive(contents: &String, check: &str) -> Directive {
    if contents.contains(&format!("// ignore-tidy-{}", check)) ||
        contents.contains(&format!("# ignore-tidy-{}", check)) {
        Directive::Ignore(false)
    } else {
        Directive::Deny
    }
}

macro_rules! suppressible_tidy_err {
    ($err:ident, $skip:ident, $msg:expr) => {
        if let Directive::Deny = $skip {
            $err($msg);
        } else {
            $skip = Directive::Ignore(true);
        }
    };
}

pub fn check(path: &Path, bad: &mut bool) {
    let mut contents = String::new();
    super::walk(path, &mut super::filter_dirs, &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        let extensions = [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h"];
        if extensions.iter().all(|e| !filename.ends_with(e)) ||
           filename.starts_with(".#") {
            return
        }

        contents.truncate(0);
        t!(t!(File::open(file), file).read_to_string(&mut contents));

        if contents.is_empty() {
            tidy_error!(bad, "{}: empty file", file.display());
        }

        let mut skip_cr = contains_ignore_directive(&contents, "cr");
        let mut skip_tab = contains_ignore_directive(&contents, "tab");
        let mut skip_line_length = contains_ignore_directive(&contents, "linelength");
        let mut skip_file_length = contains_ignore_directive(&contents, "filelength");
        let mut skip_end_whitespace = contains_ignore_directive(&contents, "end-whitespace");
        let mut skip_copyright = contains_ignore_directive(&contents, "copyright");
        let mut leading_new_lines = false;
        let mut trailing_new_lines = 0;
        let mut lines = 0;
        for (i, line) in contents.split('\n').enumerate() {
            let mut err = |msg: &str| {
                tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg);
            };
            if line.chars().count() > COLS && !long_line_is_ok(line) {
                suppressible_tidy_err!(
                    err,
                    skip_line_length,
                    &format!("line longer than {} chars", COLS)
                );
            }
            if line.contains('\t') {
                suppressible_tidy_err!(err, skip_tab, "tab character");
            }
            if line.ends_with(' ') || line.ends_with('\t') {
                suppressible_tidy_err!(err, skip_end_whitespace, "trailing whitespace");
            }
            if line.contains('\r') {
                suppressible_tidy_err!(err, skip_cr, "CR character");
            }
            if filename != "style.rs" {
                if line.contains("TODO") {
                    err("TODO is deprecated; use FIXME")
                }
                if line.contains("//") && line.contains(" XXX") {
                    err("XXX is deprecated; use FIXME")
                }
            }
            if (line.starts_with("// Copyright") ||
                line.starts_with("# Copyright") ||
                line.starts_with("Copyright"))
                && (line.contains("Rust Developers") ||
                    line.contains("Rust Project Developers")) {
                suppressible_tidy_err!(
                    err,
                    skip_copyright,
                    "copyright notices attributed to the Rust Project Developers are deprecated"
                );
            }
            if line.ends_with("```ignore") || line.ends_with("```rust,ignore") {
                err(UNEXPLAINED_IGNORE_DOCTEST_INFO);
            }
            if filename.ends_with(".cpp") && line.contains("llvm_unreachable") {
                err(LLVM_UNREACHABLE_INFO);
            }
            if line.is_empty() {
                if i == 0 {
                    leading_new_lines = true;
                }
                trailing_new_lines += 1;
            } else {
                trailing_new_lines = 0;
            }
            lines = i;
        }
        if leading_new_lines {
            tidy_error!(bad, "{}: leading newline", file.display());
        }
        match trailing_new_lines {
            0 => tidy_error!(bad, "{}: missing trailing newline", file.display()),
            1 => {}
            n => tidy_error!(bad, "{}: too many trailing newlines ({})", file.display(), n),
        };
        if lines > LINES {
            let mut err = |_| {
                tidy_error!(
                    bad,
                    "{}: too many lines ({}) (add `// \
                     ignore-tidy-filelength` to the file to suppress this error)",
                    file.display(),
                    lines
                );
            };
            suppressible_tidy_err!(err, skip_file_length, "");
        }

        if let Directive::Ignore(false) = skip_cr {
            tidy_error!(bad, "{}: ignoring CR characters unnecessarily", file.display());
        }
        if let Directive::Ignore(false) = skip_tab {
            tidy_error!(bad, "{}: ignoring tab characters unnecessarily", file.display());
        }
        if let Directive::Ignore(false) = skip_line_length {
            tidy_error!(bad, "{}: ignoring line length unnecessarily", file.display());
        }
        if let Directive::Ignore(false) = skip_file_length {
            tidy_error!(bad, "{}: ignoring file length unnecessarily", file.display());
        }
        if let Directive::Ignore(false) = skip_end_whitespace {
            tidy_error!(bad, "{}: ignoring trailing whitespace unnecessarily", file.display());
        }
        if let Directive::Ignore(false) = skip_copyright {
            tidy_error!(bad, "{}: ignoring copyright unnecessarily", file.display());
        }
    })
}
<|endoftext|>


<commit_before>type Node<T> = Option<Box<Link<T>>>;

struct Link<T> {
    value: T,
    next: Node<T>,
}

struct LinkedList<T> {
    head: Node<T>,
}

impl<T> LinkedList<T> {
    fn lookup<'a>(&'a self, base: &'a Node<T>, offset: usize) -> Option<&Box<Link<T>>> {
        match *base {
            Some(ref n) if offset == 0 => Some(n),
            Some(ref n) => self.lookup(&n.next, offset - 1),
            _ => None,
        }
    }

    pub fn new() -> LinkedList<T> {
        LinkedList{head: None}
    }

    pub fn insert(&mut self, value: T) {
        let h = self.head.take();
        self.head = Some(Box::new(Link{value: value, next: h}))
    }

    pub fn remove(&mut self) {
        match self.head.take() {
            Some(h) => { self.head = h.next },
            None => { }
        }
    }

    pub fn remove_at(&mut self, index: usize) {
        match index {
            0 => self.remove(),
            i @ _ => {
                // Iterate through to node of i - 1
                // Set node.next = node.next.next in a safe way;
            }
        }
    }

    pub fn insert_at(&mut self, index: usize, value: T) {
        match index {
            0 => self.insert(value),
            i @ _ => {
                // Iterate through to node of i - 1
                // Set node.next = Node(value: value, next: node.next) in a safe way;
            }
        }
    }

    pub fn get(&self, index: usize) -> Option<&T> {
        match self.lookup(&self.head, index) {
            Some(ref n) => Some(&n.value),
            None => None,
        }
    }
}

#[test]
fn it_works() {
    let mut ll: LinkedList<i32> = LinkedList::new();
    assert_eq!(ll.get(0), None);
}

#[test]
fn insertion() {
    let mut ll: LinkedList<i32> = LinkedList::new();
    assert_eq!(ll.get(0), None);

    ll.insert(1);
    assert_eq!(ll.get(0), Some(&1));

    ll.insert(2);
    assert_eq!(ll.get(0), Some(&2));
}

#[test]
fn removal() {
    let mut ll: LinkedList<i32> = LinkedList::new();
    ll.insert(1);
    ll.insert(2);

    assert_eq!(ll.get(0), Some(&2));

    ll.remove();
    assert_eq!(ll.get(0), Some(&1));

    ll.remove();
    assert_eq!(ll.get(0), None);
}

#[test]
fn lookup() {
    let mut ll: LinkedList<i32> = LinkedList::new();
    ll.insert(3);
    ll.insert(2);
    ll.insert(1);

    assert_eq!(ll.get(0), Some(&1));
    assert_eq!(ll.get(1), Some(&2));
    assert_eq!(ll.get(2), Some(&3));
    assert_eq!(ll.get(3), None);
}
<commit_msg>totally failed trying to get insert_after compiling<commit_after>type Node<T> = Option<Box<Link<T>>>;

struct Link<T: PartialEq> {
    value: T,
    next: Node<T>,
}

struct LinkedList<T: PartialEq> {
    head: Node<T>,
}

impl<T: PartialEq> LinkedList<T> {
    fn lookup<'a>(&'a self, base: &'a Node<T>, offset: usize) -> Option<&Box<Link<T>>> {
        match *base {
            Some(ref n) if offset == 0 => Some(n),
            Some(ref n) => self.lookup(&n.next, offset - 1),
            _ => None,
        }
    }

    pub fn new() -> LinkedList<T> {
        LinkedList{head: None}
    }

    pub fn insert(&mut self, value: T) {
        let h = self.head.take();
        self.head = Some(Box::new(Link{value: value, next: h}))
    }

    pub fn remove(&mut self) {
        match self.head.take() {
            Some(h) => { self.head = h.next },
            None => { }
        }
    }

    pub fn remove_after(&mut self, find: T) {
    }

    pub fn insert_after(&mut self, find: T, value: T) {
    }

    pub fn get(&self, index: usize) -> Option<&T> {
        match self.lookup(&self.head, index) {
            Some(ref n) => Some(&n.value),
            None => None,
        }
    }
}

#[test]
fn it_works() {
    let mut ll: LinkedList<i32> = LinkedList::new();
    assert_eq!(ll.get(0), None);
}

#[test]
fn insertion() {
    let mut ll: LinkedList<i32> = LinkedList::new();
    assert_eq!(ll.get(0), None);

    ll.insert(1);
    assert_eq!(ll.get(0), Some(&1));

    ll.insert(2);
    assert_eq!(ll.get(0), Some(&2));
}

#[test]
fn removal() {
    let mut ll: LinkedList<i32> = LinkedList::new();
    ll.insert(1);
    ll.insert(2);

    assert_eq!(ll.get(0), Some(&2));

    ll.remove();
    assert_eq!(ll.get(0), Some(&1));

    ll.remove();
    assert_eq!(ll.get(0), None);
}

#[test]
fn lookup() {
    let mut ll: LinkedList<i32> = LinkedList::new();
    ll.insert(3);
    ll.insert(2);
    ll.insert(1);

    assert_eq!(ll.get(0), Some(&1));
    assert_eq!(ll.get(1), Some(&2));
    assert_eq!(ll.get(2), Some(&3));
    assert_eq!(ll.get(3), None);
}
<|endoftext|>


<commit_before>extern crate libc;

use libc::c_char;
use libc::c_void;
use libc::free;
use libc::malloc;
use libc::memcpy;
use std::ffi::CStr;

#[no_mangle]
pub extern fn hello() {
    println!("hello")
}

#[no_mangle]
pub extern fn add(a: i64, b: i64) -> i64 {
    a + b
}

#[no_mangle]
pub extern fn length(str: *const c_char) -> i64 {
    let c_str = unsafe { CStr::from_ptr(str) };
    c_str.to_bytes().len() as i64
}

#[no_mangle]
pub extern fn duplicate(count: i64, msg: *const c_char) -> *mut c_char {
    let len = length(msg);

    unsafe {
        let out = malloc((count * len + 1) as usize);

        for i in 0..count {
            memcpy(out.offset((i * len) as isize), msg as *mut c_void,
                len as usize);
        }
        out as *mut c_char
    }
}

#[no_mangle]
pub extern fn release(msg: *const c_char) {
    unsafe { free(msg as *mut c_void) }
}
<commit_msg>remove duplication in imports<commit_after>extern crate libc;

use libc::{
    c_char,
    c_void,
    free,
    malloc,
    memcpy,
};

use std::ffi::CStr;

#[no_mangle]
pub extern fn hello() {
    println!("hello")
}

#[no_mangle]
pub extern fn add(a: i64, b: i64) -> i64 {
    a + b
}

#[no_mangle]
pub extern fn length(str: *const c_char) -> i64 {
    let c_str = unsafe { CStr::from_ptr(str) };
    c_str.to_bytes().len() as i64
}

#[no_mangle]
pub extern fn duplicate(count: i64, msg: *const c_char) -> *mut c_char {
    let len = length(msg);

    unsafe {
        let out = malloc((count * len + 1) as usize);

        for i in 0..count {
            memcpy(out.offset((i * len) as isize), msg as *mut c_void,
                len as usize);
        }
        out as *mut c_char
    }
}

#[no_mangle]
pub extern fn release(msg: *const c_char) {
    unsafe { free(msg as *mut c_void) }
}
<|endoftext|>