<commit_before>//! A language server scaffold, exposing a synchronous crossbeam-channel based API.
//! This crate handles protocol handshaking and parsing messages, while you
//! control the message dispatch loop yourself.
//!
//! Run with `RUST_LOG=gen_lsp_server=debug` to see all the messages.
//!
//! ```no_run
//! use crossbeam_channel::{Sender, Receiver};
//! use lsp_types::{ServerCapabilities, InitializeParams, request::{GotoDefinition, GotoDefinitionResponse}};
//! use gen_lsp_server::{run_server, stdio_transport, handle_shutdown, RawMessage, RawResponse};
//!
//! fn main() -> Result<(), failure::Error> {
//!     let (receiver, sender, io_threads) = stdio_transport();
//!     run_server(
//!         ServerCapabilities::default(),
//!         receiver,
//!         sender,
//!         main_loop,
//!     )?;
//!     io_threads.join()?;
//!     Ok(())
//! }
//!
//! fn main_loop(
//!     _params: InitializeParams,
//!     receiver: &Receiver<RawMessage>,
//!     sender: &Sender<RawMessage>,
//! ) -> Result<(), failure::Error> {
//!     for msg in receiver {
//!         match msg {
//!             RawMessage::Request(req) => {
//!                 let req = match handle_shutdown(req, sender) {
//!                     None => return Ok(()),
//!                     Some(req) => req,
//!                 };
//!                 match req.cast::<GotoDefinition>() {
//!                     Ok((id, _params)) => {
//!                         let resp = RawResponse::ok::<GotoDefinition>(
//!                             id,
//!                             &Some(GotoDefinitionResponse::Array(Vec::new())),
//!                         );
//!                         sender.send(RawMessage::Response(resp))?;
//!                         continue;
//!                     },
//!                     Err(req) => req,
//!                 };
//!                 // ...
//!             }
//!             RawMessage::Response(_resp) => (),
//!             RawMessage::Notification(_not) => (),
//!         }
//!     }
//!     Ok(())
//! }
//! ```

use std::error::Error;

mod msg;
mod stdio;

use crossbeam_channel::{Receiver, Sender};
use lsp_types::{
    notification::{Exit, Initialized},
    request::{Initialize, Shutdown},
    InitializeParams, InitializeResult, ServerCapabilities,
};

pub type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;
pub use crate::{
    msg::{ErrorCode, RawMessage, RawNotification, RawRequest, RawResponse, RawResponseError},
    stdio::{stdio_transport, Threads},
};

/// Main entry point: runs the server from initialization to shutdown.
/// To attach server to standard input/output streams, use the `stdio_transport`
/// function to create corresponding `sender` and `receiver` pair.
///
/// `server` should use the `handle_shutdown` function to handle the `Shutdown`
/// request.
pub fn run_server(
    caps: ServerCapabilities,
    receiver: Receiver<RawMessage>,
    sender: Sender<RawMessage>,
    server: impl FnOnce(InitializeParams, &Receiver<RawMessage>, &Sender<RawMessage>) -> Result<()>,
) -> Result<()> {
    log::info!("lsp server initializes");
    let params = initialize(&receiver, &sender, caps)?;
    log::info!("lsp server initialized, serving requests");
    server(params, &receiver, &sender)?;
    log::info!("lsp server waiting for exit notification");
    match receiver.recv() {
        Ok(RawMessage::Notification(n)) => n
            .cast::<Exit>()
            .map_err(|n| format!("unexpected notification during shutdown: {:?}", n))?,
        m => Err(format!("unexpected message during shutdown: {:?}", m))?,
    }
    log::info!("lsp server shutdown complete");
    Ok(())
}

/// If `req` is `Shutdown`, respond to it and return `None`, otherwise return `Some(req)`
pub fn handle_shutdown(req: RawRequest, sender: &Sender<RawMessage>) -> Option<RawRequest> {
    match req.cast::<Shutdown>() {
        Ok((id, ())) => {
            let resp = RawResponse::ok::<Shutdown>(id, &());
            let _ = sender.send(RawMessage::Response(resp));
            None
        }
        Err(req) => Some(req),
    }
}

fn initialize(
    receiver: &Receiver<RawMessage>,
    sender: &Sender<RawMessage>,
    caps: ServerCapabilities,
) -> Result<InitializeParams> {
    let (id, params) = match receiver.recv() {
        Ok(RawMessage::Request(req)) => match req.cast::<Initialize>() {
            Err(req) => Err(format!("expected initialize request, got {:?}", req))?,
            Ok(req) => req,
        },
        msg => Err(format!("expected initialize request, got {:?}", msg))?,
    };
    let resp = RawResponse::ok::<Initialize>(id, &InitializeResult { capabilities: caps });
    sender.send(RawMessage::Response(resp)).unwrap();
    match receiver.recv() {
        Ok(RawMessage::Notification(n)) => {
            n.cast::<Initialized>().map_err(|_| "expected initialized notification")?;
        }
        _ => Err(format!("expected initialized notification"))?,
    }
    Ok(params)
}
<commit_msg>Fix a doc test<commit_after>//! A language server scaffold, exposing a synchronous crossbeam-channel based API.
//! This crate handles protocol handshaking and parsing messages, while you
//! control the message dispatch loop yourself.
//!
//! Run with `RUST_LOG=gen_lsp_server=debug` to see all the messages.
//!
//! ```no_run
//! use std::error::Error;
//! use crossbeam_channel::{Sender, Receiver};
//! use lsp_types::{ServerCapabilities, InitializeParams, request::{GotoDefinition, GotoDefinitionResponse}};
//! use gen_lsp_server::{run_server, stdio_transport, handle_shutdown, RawMessage, RawResponse};
//!
//! fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
//!     let (receiver, sender, io_threads) = stdio_transport();
//!     run_server(
//!         ServerCapabilities::default(),
//!         receiver,
//!         sender,
//!         main_loop,
//!     )?;
//!     io_threads.join()?;
//!     Ok(())
//! }
//!
//! fn main_loop(
//!     _params: InitializeParams,
//!     receiver: &Receiver<RawMessage>,
//!     sender: &Sender<RawMessage>,
//! ) -> Result<(), Box<dyn Error + Send + Sync>> {
//!     for msg in receiver {
//!         match msg {
//!             RawMessage::Request(req) => {
//!                 let req = match handle_shutdown(req, sender) {
//!                     None => return Ok(()),
//!                     Some(req) => req,
//!                 };
//!                 match req.cast::<GotoDefinition>() {
//!                     Ok((id, _params)) => {
//!                         let resp = RawResponse::ok::<GotoDefinition>(
//!                             id,
//!                             &Some(GotoDefinitionResponse::Array(Vec::new())),
//!                         );
//!                         sender.send(RawMessage::Response(resp))?;
//!                         continue;
//!                     },
//!                     Err(req) => req,
//!                 };
//!                 // ...
//!             }
//!             RawMessage::Response(_resp) => (),
//!             RawMessage::Notification(_not) => (),
//!         }
//!     }
//!     Ok(())
//! }
//! ```

use std::error::Error;

mod msg;
mod stdio;

use crossbeam_channel::{Receiver, Sender};
use lsp_types::{
    notification::{Exit, Initialized},
    request::{Initialize, Shutdown},
    InitializeParams, InitializeResult, ServerCapabilities,
};

pub type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;
pub use crate::{
    msg::{ErrorCode, RawMessage, RawNotification, RawRequest, RawResponse, RawResponseError},
    stdio::{stdio_transport, Threads},
};

/// Main entry point: runs the server from initialization to shutdown.
/// To attach server to standard input/output streams, use the `stdio_transport`
/// function to create corresponding `sender` and `receiver` pair.
///
/// `server` should use the `handle_shutdown` function to handle the `Shutdown`
/// request.
pub fn run_server(
    caps: ServerCapabilities,
    receiver: Receiver<RawMessage>,
    sender: Sender<RawMessage>,
    server: impl FnOnce(InitializeParams, &Receiver<RawMessage>, &Sender<RawMessage>) -> Result<()>,
) -> Result<()> {
    log::info!("lsp server initializes");
    let params = initialize(&receiver, &sender, caps)?;
    log::info!("lsp server initialized, serving requests");
    server(params, &receiver, &sender)?;
    log::info!("lsp server waiting for exit notification");
    match receiver.recv() {
        Ok(RawMessage::Notification(n)) => n
            .cast::<Exit>()
            .map_err(|n| format!("unexpected notification during shutdown: {:?}", n))?,
        m => Err(format!("unexpected message during shutdown: {:?}", m))?,
    }
    log::info!("lsp server shutdown complete");
    Ok(())
}

/// If `req` is `Shutdown`, respond to it and return `None`, otherwise return `Some(req)`
pub fn handle_shutdown(req: RawRequest, sender: &Sender<RawMessage>) -> Option<RawRequest> {
    match req.cast::<Shutdown>() {
        Ok((id, ())) => {
            let resp = RawResponse::ok::<Shutdown>(id, &());
            let _ = sender.send(RawMessage::Response(resp));
            None
        }
        Err(req) => Some(req),
    }
}

fn initialize(
    receiver: &Receiver<RawMessage>,
    sender: &Sender<RawMessage>,
    caps: ServerCapabilities,
) -> Result<InitializeParams> {
    let (id, params) = match receiver.recv() {
        Ok(RawMessage::Request(req)) => match req.cast::<Initialize>() {
            Err(req) => Err(format!("expected initialize request, got {:?}", req))?,
            Ok(req) => req,
        },
        msg => Err(format!("expected initialize request, got {:?}", msg))?,
    };
    let resp = RawResponse::ok::<Initialize>(id, &InitializeResult { capabilities: caps });
    sender.send(RawMessage::Response(resp)).unwrap();
    match receiver.recv() {
        Ok(RawMessage::Notification(n)) => {
            n.cast::<Initialized>().map_err(|_| "expected initialized notification")?;
        }
        _ => Err(format!("expected initialized notification"))?,
    }
    Ok(params)
}
<|endoftext|>


<commit_before>use common::communicate::{ClientToServer, ServerToClient, TerrainBlockSend, spark_socket_sender};
use common::process_events::process_channel;
use gaia_thread::{ServerToGaia, LoadReason};
use nanomsg::Endpoint;
use server::Server;
use std::sync::mpsc::{Sender, Receiver};
use std::sync::Mutex;
use time;

pub fn client_thread(
  client_endpoints: &mut Vec<Endpoint>,
  server: &Server,
  ups_from_client: &Receiver<ClientToServer>,
  ups_to_gaia: &Mutex<Sender<ServerToGaia>>,
) {
  // TODO: Proper exit semantics for this and other threads.
  loop {
    let update = ups_from_client.recv().unwrap();
    match update {
      ClientToServer::Init(client_url) => {
        let (client, endpoint) = spark_socket_sender(client_url);
        client_endpoints.push(endpoint);
        let player_position = server.player.lock().unwrap().position;
        server.to_client.lock().unwrap().as_mut().map(|client| {
          client.send(ServerToClient::UpdatePlayer(player_position)).unwrap();
        });
        server.inform_client(&client);
        *server.to_client.lock().unwrap() = Some(client);
      },
      ClientToServer::StartJump => {
        let mut player = server.player.lock().unwrap();
        if !player.is_jumping {
          player.is_jumping = true;
          // this 0.3 is duplicated in a few places
          player.accel.y = player.accel.y + 0.3;
        }
      },
      ClientToServer::StopJump => {
        let mut player = server.player.lock().unwrap();
        if player.is_jumping {
          player.is_jumping = false;
          // this 0.3 is duplicated in a few places
          player.accel.y = player.accel.y - 0.3;
        }
      },
      ClientToServer::Walk(v) => {
        println!("{} got walk", time::precise_time_ns());
        let mut player = server.player.lock().unwrap();
        player.walk(v);
      },
      ClientToServer::RotatePlayer(v) => {
        let mut player = server.player.lock().unwrap();
        player.rotate_lateral(v.x);
        player.rotate_vertical(v.y);
      },
      ClientToServer::RequestBlock(position, lod) => {
        ups_to_gaia.lock().unwrap().send(
          ServerToGaia::Load(position, lod, LoadReason::ForClient)
        ).unwrap();
      },
    };
  }
}
<commit_msg>Remove debug println.<commit_after>use common::communicate::{ClientToServer, ServerToClient, TerrainBlockSend, spark_socket_sender};
use common::process_events::process_channel;
use gaia_thread::{ServerToGaia, LoadReason};
use nanomsg::Endpoint;
use server::Server;
use std::sync::mpsc::{Sender, Receiver};
use std::sync::Mutex;
use time;

pub fn client_thread(
  client_endpoints: &mut Vec<Endpoint>,
  server: &Server,
  ups_from_client: &Receiver<ClientToServer>,
  ups_to_gaia: &Mutex<Sender<ServerToGaia>>,
) {
  // TODO: Proper exit semantics for this and other threads.
  loop {
    let update = ups_from_client.recv().unwrap();
    match update {
      ClientToServer::Init(client_url) => {
        let (client, endpoint) = spark_socket_sender(client_url);
        client_endpoints.push(endpoint);
        let player_position = server.player.lock().unwrap().position;
        server.to_client.lock().unwrap().as_mut().map(|client| {
          client.send(ServerToClient::UpdatePlayer(player_position)).unwrap();
        });
        server.inform_client(&client);
        *server.to_client.lock().unwrap() = Some(client);
      },
      ClientToServer::StartJump => {
        let mut player = server.player.lock().unwrap();
        if !player.is_jumping {
          player.is_jumping = true;
          // this 0.3 is duplicated in a few places
          player.accel.y = player.accel.y + 0.3;
        }
      },
      ClientToServer::StopJump => {
        let mut player = server.player.lock().unwrap();
        if player.is_jumping {
          player.is_jumping = false;
          // this 0.3 is duplicated in a few places
          player.accel.y = player.accel.y - 0.3;
        }
      },
      ClientToServer::Walk(v) => {
        let mut player = server.player.lock().unwrap();
        player.walk(v);
      },
      ClientToServer::RotatePlayer(v) => {
        let mut player = server.player.lock().unwrap();
        player.rotate_lateral(v.x);
        player.rotate_vertical(v.y);
      },
      ClientToServer::RequestBlock(position, lod) => {
        ups_to_gaia.lock().unwrap().send(
          ServerToGaia::Load(position, lod, LoadReason::ForClient)
        ).unwrap();
      },
    };
  }
}
<|endoftext|>


<commit_before>#![feature(test)]
extern crate test;

#[macro_use]
extern crate nom;

use nom::IResult;
use std::env;
use std::fs::File;

#[derive(Debug)]
struct Request<'a> {
    method:  &'a [u8],
    uri:     &'a [u8],
    version: &'a [u8],
}

#[derive(Debug)]
struct Header<'a> {
    name:  &'a [u8],
    value: Vec<&'a [u8]>,
}

fn is_token(c: u8) -> bool {
    match c {
        128...255 => false,
        0...31    => false,
        b'('      => false,
        b')'      => false,
        b'<'      => false,
        b'>'      => false,
        b'@'      => false,
        b','      => false,
        b';'      => false,
        b':'      => false,
        b'\\'     => false,
        b'"'      => false,
        b'/'      => false,
        b'['      => false,
        b']'      => false,
        b'?'      => false,
        b'='      => false,
        b'{'      => false,
        b'}'      => false,
        b' '      => false,
        _         => true,
    }
}

fn not_line_ending(c: u8) -> bool {
    c != b'\r' && c != b'\n'
}

fn is_space(c: u8) -> bool {
    c == b' '
}

fn is_not_space(c: u8)        -> bool { c != b' ' }
fn is_horizontal_space(c: u8) -> bool { c == b' ' || c == b'\t' }

fn is_version(c: u8) -> bool {
    c >= b'0' && c <= b'9' || c == b'.'
}

named!(line_ending, alt!(tag!("\r\n") | tag!("\n")));

fn request_line<'a>(input: &'a [u8]) -> IResult<&'a[u8], Request<'a>> {
  chain!(input,
    method: take_while1!(is_token)     ~
            take_while1!(is_space)     ~
    url:    take_while1!(is_not_space) ~
            take_while1!(is_space)     ~
    version: http_version              ~
    line_ending,

    || Request {
        method: method,
        uri:    url,
        version: version,
    })
}

named!(http_version, chain!(
    tag!("HTTP/")                    ~
    version: take_while1!(is_version),

    || version));

named!(message_header_value, chain!(
          take_while1!(is_horizontal_space) ~
    data: take_while1!(not_line_ending)     ~
    line_ending,

    || data));

fn message_header<'a>(input: &'a [u8]) -> IResult<&'a[u8], Header<'a>> {
  chain!(input,
    name:   take_while1!(is_token) ~
            char!(':') ~
    values: many1!(message_header_value),

    || Header {
        name: name,
        value: values,
    })
}

fn request<'a>(input: &'a [u8]) -> IResult<&'a[u8], (Request<'a>, Vec<Header<'a>>)> {
  chain!(input,
    req: request_line           ~
    h:   many1!(message_header) ~
         line_ending,

    || (req, h))
}

fn parse(data:&[u8]) -> Option<Vec<(Request, Vec<Header>)>> {
  let mut buf = &data[..];
  let mut v = Vec::new();
  loop {
    match request(buf) {
      IResult::Done(b, r) => {
        buf = b;
        v.push(r);

        if b.is_empty() {

    //println!("{}", i);
          break;
        }
      },
      IResult::Error(e) => return None/*panic!("{:?}", e)*/,
      IResult::Incomplete(_) => return None/*panic!("Incomplete!")*/,
    }
  }

  Some(v)
}

use test::Bencher;

/*
#[bench]
fn small_test(b: &mut Bencher) {
  let data = include_bytes!("../../http-requests.txt");
  b.iter(||{
    parse(data)
  });
}

#[bench]
fn bigger_test(b: &mut Bencher) {
  let data = include_bytes!("../../bigger.txt");
  b.iter(||{
    parse(data)
  });
}
*/

#[bench]
fn one_test(b: &mut Bencher) {
  let data = &b"GET / HTTP/1.1
Host: www.reddit.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive"[..];
  b.iter(||{
    parse(data)
  });
}

fn main() {
    let mut contents: Vec<u8> = Vec::new();

    {
        use std::io::Read;

        let mut file = File::open(env::args().nth(1).expect("File to read")).ok().expect("Failed to open file");

        let _ = file.read_to_end(&mut contents).unwrap();
    }

    let mut buf = &contents[..];
    loop { parse(buf); }
}

<commit_msg>benches/http: silence warnings<commit_after>#![feature(test)]
extern crate test;

#[macro_use]
extern crate nom;

use nom::IResult;
use std::env;
use std::fs::File;

#[derive(Debug)]
struct Request<'a> {
    method:  &'a [u8],
    uri:     &'a [u8],
    version: &'a [u8],
}

#[derive(Debug)]
struct Header<'a> {
    name:  &'a [u8],
    value: Vec<&'a [u8]>,
}

fn is_token(c: u8) -> bool {
    match c {
        128...255 => false,
        0...31    => false,
        b'('      => false,
        b')'      => false,
        b'<'      => false,
        b'>'      => false,
        b'@'      => false,
        b','      => false,
        b';'      => false,
        b':'      => false,
        b'\\'     => false,
        b'"'      => false,
        b'/'      => false,
        b'['      => false,
        b']'      => false,
        b'?'      => false,
        b'='      => false,
        b'{'      => false,
        b'}'      => false,
        b' '      => false,
        _         => true,
    }
}

fn not_line_ending(c: u8) -> bool {
    c != b'\r' && c != b'\n'
}

fn is_space(c: u8) -> bool {
    c == b' '
}

fn is_not_space(c: u8)        -> bool { c != b' ' }
fn is_horizontal_space(c: u8) -> bool { c == b' ' || c == b'\t' }

fn is_version(c: u8) -> bool {
    c >= b'0' && c <= b'9' || c == b'.'
}

named!(line_ending, alt!(tag!("\r\n") | tag!("\n")));

fn request_line<'a>(input: &'a [u8]) -> IResult<&'a[u8], Request<'a>> {
  chain!(input,
    method: take_while1!(is_token)     ~
            take_while1!(is_space)     ~
    url:    take_while1!(is_not_space) ~
            take_while1!(is_space)     ~
    version: http_version              ~
    line_ending,

    || Request {
        method: method,
        uri:    url,
        version: version,
    })
}

named!(http_version, chain!(
    tag!("HTTP/")                    ~
    version: take_while1!(is_version),

    || version));

named!(message_header_value, chain!(
          take_while1!(is_horizontal_space) ~
    data: take_while1!(not_line_ending)     ~
    line_ending,

    || data));

fn message_header<'a>(input: &'a [u8]) -> IResult<&'a[u8], Header<'a>> {
  chain!(input,
    name:   take_while1!(is_token) ~
            char!(':') ~
    values: many1!(message_header_value),

    || Header {
        name: name,
        value: values,
    })
}

fn request<'a>(input: &'a [u8]) -> IResult<&'a[u8], (Request<'a>, Vec<Header<'a>>)> {
  chain!(input,
    req: request_line           ~
    h:   many1!(message_header) ~
         line_ending,

    || (req, h))
}

fn parse(data:&[u8]) -> Option<Vec<(Request, Vec<Header>)>> {
  let mut buf = &data[..];
  let mut v = Vec::new();
  loop {
    match request(buf) {
      IResult::Done(b, r) => {
        buf = b;
        v.push(r);

        if b.is_empty() {

    //println!("{}", i);
          break;
        }
      },
      IResult::Error(_) => return None/*panic!("{:?}", e)*/,
      IResult::Incomplete(_) => return None/*panic!("Incomplete!")*/,
    }
  }

  Some(v)
}

use test::Bencher;

/*
#[bench]
fn small_test(b: &mut Bencher) {
  let data = include_bytes!("../../http-requests.txt");
  b.iter(||{
    parse(data)
  });
}

#[bench]
fn bigger_test(b: &mut Bencher) {
  let data = include_bytes!("../../bigger.txt");
  b.iter(||{
    parse(data)
  });
}
*/

#[bench]
fn one_test(b: &mut Bencher) {
  let data = &b"GET / HTTP/1.1
Host: www.reddit.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive"[..];
  b.iter(||{
    parse(data)
  });
}

fn main() {
    let mut contents: Vec<u8> = Vec::new();

    {
        use std::io::Read;

        let mut file = File::open(env::args().nth(1).expect("File to read")).ok().expect("Failed to open file");

        let _ = file.read_to_end(&mut contents).unwrap();
    }

    let buf = &contents[..];
    loop { parse(buf); }
}

<|endoftext|>


<commit_before>use crate::{
    analysis::{
        bounds::Bounds,
        imports::Imports,
        properties::{get_property_ref_modes, Property},
        rust_type::*,
    },
    config::{self, GObject},
    env::Env,
    library,
    traits::*,
};
use std::collections::HashSet;

pub fn analyze(
    env: &Env,
    props: &[library::Property],
    type_tid: library::TypeId,
    obj: &GObject,
    imports: &mut Imports,
) -> Vec<Property> {
    if !obj.generate_builder {
        return Vec::new();
    }

    let mut names = HashSet::<String>::new();
    let mut builder_properties = analyze_properties(env, props, obj, imports, &mut names);

    for &super_tid in env.class_hierarchy.supertypes(type_tid) {
        let type_ = env.type_(super_tid);

        let super_properties = match type_ {
            library::Type::Class(class) => &class.properties,
            library::Type::Interface(iface) => &iface.properties,
            _ => continue,
        };
        let super_obj =
            if let Some(super_obj) = env.config.objects.get(&super_tid.full_name(&env.library)) {
                super_obj
            } else {
                continue;
            };

        let new_builder_properties =
            analyze_properties(env, super_properties, super_obj, imports, &mut names);
        builder_properties.extend(new_builder_properties);
    }

    builder_properties
}

fn analyze_properties(
    env: &Env,
    props: &[library::Property],
    obj: &GObject,
    imports: &mut Imports,
    names: &mut HashSet<String>,
) -> Vec<Property> {
    let mut builder_properties = Vec::new();

    for prop in props {
        if names.contains(&prop.name) {
            continue;
        }
        let configured_properties = obj.properties.matched(&prop.name);
        if configured_properties.iter().any(|f| f.ignore) {
            continue;
        }

        if env.is_totally_deprecated(prop.deprecated_version) {
            continue;
        }
        let builder = analyze_property(env, prop, &configured_properties, imports);
        if let Some(builder) = builder {
            builder_properties.push(builder);
            names.insert(prop.name.clone());
        }
    }

    builder_properties
}

fn analyze_property(
    env: &Env,
    prop: &library::Property,
    configured_properties: &[&config::properties::Property],
    imports: &mut Imports,
) -> Option<Property> {
    let prop_version = configured_properties
        .iter()
        .filter_map(|f| f.version)
        .min()
        .or(prop.version)
        .or_else(|| Some(env.config.min_cfg_version));

    let for_builder = prop.construct_only || prop.construct || prop.writable;
    if !for_builder {
        return None;
    }
    imports.set_defaults(prop_version, &None);
    let type_str = used_rust_type(env, prop.typ, false);
    if let Ok(ref s) = type_str {
        if !s.contains("GString") {
            imports.add_used_type(s);
        }
    }

    let (get_out_ref_mode, set_in_ref_mode, nullable) = get_property_ref_modes(env, prop);

    let mut bounds = Bounds::default();
    if let Some(bound) = Bounds::type_for(env, prop.typ, nullable) {
        imports.add("glib::object::IsA");
        bounds.add_parameter(&prop.name, &type_str.into_string(), bound, false);
    }

    Some(Property {
        name: prop.name.clone(),
        var_name: String::new(),
        typ: prop.typ,
        is_get: false,
        func_name: String::new(),
        nullable,
        get_out_ref_mode,
        set_in_ref_mode,
        set_bound: None,
        bounds,
        version: prop_version,
        deprecated_version: prop.deprecated_version,
    })
}
<commit_msg>Add forgotten `imports.reset_defaults();` in class_builder<commit_after>use crate::{
    analysis::{
        bounds::Bounds,
        imports::Imports,
        properties::{get_property_ref_modes, Property},
        rust_type::*,
    },
    config::{self, GObject},
    env::Env,
    library,
    traits::*,
};
use std::collections::HashSet;

pub fn analyze(
    env: &Env,
    props: &[library::Property],
    type_tid: library::TypeId,
    obj: &GObject,
    imports: &mut Imports,
) -> Vec<Property> {
    if !obj.generate_builder {
        return Vec::new();
    }

    let mut names = HashSet::<String>::new();
    let mut builder_properties = analyze_properties(env, props, obj, imports, &mut names);

    for &super_tid in env.class_hierarchy.supertypes(type_tid) {
        let type_ = env.type_(super_tid);

        let super_properties = match type_ {
            library::Type::Class(class) => &class.properties,
            library::Type::Interface(iface) => &iface.properties,
            _ => continue,
        };
        let super_obj =
            if let Some(super_obj) = env.config.objects.get(&super_tid.full_name(&env.library)) {
                super_obj
            } else {
                continue;
            };

        let new_builder_properties =
            analyze_properties(env, super_properties, super_obj, imports, &mut names);
        builder_properties.extend(new_builder_properties);
    }

    builder_properties
}

fn analyze_properties(
    env: &Env,
    props: &[library::Property],
    obj: &GObject,
    imports: &mut Imports,
    names: &mut HashSet<String>,
) -> Vec<Property> {
    let mut builder_properties = Vec::new();

    for prop in props {
        if names.contains(&prop.name) {
            continue;
        }
        let configured_properties = obj.properties.matched(&prop.name);
        if configured_properties.iter().any(|f| f.ignore) {
            continue;
        }

        if env.is_totally_deprecated(prop.deprecated_version) {
            continue;
        }
        let builder = analyze_property(env, prop, &configured_properties, imports);
        if let Some(builder) = builder {
            builder_properties.push(builder);
            names.insert(prop.name.clone());
        }
    }

    builder_properties
}

fn analyze_property(
    env: &Env,
    prop: &library::Property,
    configured_properties: &[&config::properties::Property],
    imports: &mut Imports,
) -> Option<Property> {
    let prop_version = configured_properties
        .iter()
        .filter_map(|f| f.version)
        .min()
        .or(prop.version)
        .or_else(|| Some(env.config.min_cfg_version));

    let for_builder = prop.construct_only || prop.construct || prop.writable;
    if !for_builder {
        return None;
    }
    imports.set_defaults(prop_version, &None);
    let type_str = used_rust_type(env, prop.typ, false);
    if let Ok(ref s) = type_str {
        if !s.contains("GString") {
            imports.add_used_type(s);
        }
    }

    let (get_out_ref_mode, set_in_ref_mode, nullable) = get_property_ref_modes(env, prop);

    let mut bounds = Bounds::default();
    if let Some(bound) = Bounds::type_for(env, prop.typ, nullable) {
        imports.add("glib::object::IsA");
        bounds.add_parameter(&prop.name, &type_str.into_string(), bound, false);
    }

    imports.reset_defaults();

    Some(Property {
        name: prop.name.clone(),
        var_name: String::new(),
        typ: prop.typ,
        is_get: false,
        func_name: String::new(),
        nullable,
        get_out_ref_mode,
        set_in_ref_mode,
        set_bound: None,
        bounds,
        version: prop_version,
        deprecated_version: prop.deprecated_version,
    })
}
<|endoftext|>


<commit_before>// Copyright © 2017 Cormac O'Brien
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software
// and associated documentation files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

extern crate chrono;
extern crate cgmath;
extern crate env_logger;
#[macro_use]
extern crate gfx;
extern crate gfx_device_gl;
extern crate gfx_window_glutin;
extern crate glutin;
extern crate richter;

use chrono::Utc;
use gfx::Device;
use gfx::Factory;
use gfx::traits::FactoryExt;
use glutin::GlContext;
use glutin::GlRequest;
use glutin::Api::OpenGl;

type ColorFormat = gfx::format::Srgba8;
type DepthFormat = gfx::format::DepthStencil;

gfx_defines!{
    vertex Vertex {
        position: [f32; 3] = "v_position",
        texcoord: [f32; 2] = "v_texcoord",
    }

    constant Locals {
        transform: [[f32; 4]; 4] = "u_transform",
    }

    pipeline pipe {
        vertex_buffer: gfx::VertexBuffer<Vertex> = (),
        transform: gfx::Global<[[f32; 4]; 4]> = "u_transform",
        sampler: gfx::TextureSampler<[f32; 4]> = "u_texture",
        out_color: gfx::RenderTarget<ColorFormat> = "Target0",
        out_depth: gfx::DepthTarget<DepthFormat> = gfx::preset::depth::LESS_EQUAL_WRITE,
    }
}

impl From<[f32; 5]> for Vertex {
    fn from(src: [f32; 5]) -> Self {
        Vertex {
            position: [src[0], src[1], src[2]],
            texcoord: [src[3], src[4]],
        }
    }
}

struct Face {
    vertex_id: usize,
    vertex_count: usize,
    tex_id: usize,
}

impl From<(usize, usize, usize)> for Face {
    fn from(src: (usize, usize, usize)) -> Self {
        Face {
            vertex_id: src.0,
            vertex_count: src.1,
            tex_id: src.2,
        }
    }
}

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

    let mut events_loop = glutin::EventsLoop::new();
    let window_builder = glutin::WindowBuilder::new().with_title("BSP renderer: gfx-rs backend");
    let context_builder = glutin::ContextBuilder::new()
        .with_gl(GlRequest::Specific(OpenGl, (3, 3)))
        .with_vsync(true);

    let (window, mut device, mut factory, color, depth) =
        gfx_window_glutin::init::<ColorFormat, DepthFormat>(
            window_builder,
            context_builder,
            &events_loop,
        );

    let mut encoder: gfx::Encoder<gfx_device_gl::Resources, gfx_device_gl::CommandBuffer> =
        factory.create_command_buffer().into();

    let shader_set = factory
        .create_shader_set(
            r#"
#version 430

layout (location = 0) in vec3 v_position;
layout (location = 1) in vec2 v_texcoord;

out vec2 f_texcoord;

uniform mat4 u_transform;

void main() {
    f_texcoord = v_texcoord;
    gl_Position = u_transform * vec4(-v_position.y, v_position.z, -v_position.x, 1.0);
}
"#
                .as_bytes(),
            r#"
#version 430

in vec2 f_texcoord;

uniform sampler2D u_texture;

out vec4 Target0;

void main() {
    Target0 = texture(u_texture, f_texcoord);
}"#
                .as_bytes(),
        )
        .unwrap();

    let rasterizer = gfx::state::Rasterizer {
        front_face: gfx::state::FrontFace::Clockwise,
        cull_face: gfx::state::CullFace::Back,
        method: gfx::state::RasterMethod::Fill,
        offset: None,
        samples: Some(gfx::state::MultiSample),
    };

    let pso = factory
        .create_pipeline_state(
            &shader_set,
            gfx::Primitive::TriangleList,
            rasterizer,
            pipe::new(),
        )
        .unwrap();

    let mut pak = richter::pak::Pak::new();
    pak.add("pak0.pak").unwrap();
    let (worldmodel, _, _) = richter::bsp::load(pak.open("maps/e1m1.bsp").unwrap()).unwrap();

    let textures = worldmodel
        .bsp_data()
        .textures()
        .iter()
        .map(|tex| {
            let mipmap_full =
                richter::engine::indexed_to_rgba(tex.mipmap(richter::bsp::BspTextureMipmap::Full));
            let (width, height) = tex.dimensions();

            let (_, view) =
                factory
                    .create_texture_immutable_u8::<ColorFormat>(
                        gfx::texture::Kind::D2(
                            width as u16,
                            height as u16,
                            gfx::texture::AaMode::Single,
                        ),
                        &[&mipmap_full],
                    )
                    .unwrap();

            view
        })
        .collect::<Vec<_>>();

    let (face_data, vertex_data): (Vec<Face>, Vec<Vertex>) =
        worldmodel.bsp_data().gen_render_data_interleaved();
    let vertex_buffer = factory.create_vertex_buffer(&vertex_data);

    let sampler = factory.create_sampler(gfx::texture::SamplerInfo::new(
        gfx::texture::FilterMethod::Scale,
        gfx::texture::WrapMode::Tile,
    ));

    let (fb_width, fb_height) = window.window().get_inner_size_pixels().unwrap();

    let mut data = pipe::Data {
        vertex_buffer: vertex_buffer,
        transform: cgmath::perspective(
            cgmath::Deg(75.0),
            fb_width as f32 / fb_height as f32,
            1.0,
            1024.0,
        ).into(),
        sampler: (textures[0].clone(), sampler),
        out_color: color,
        out_depth: depth,
    };

    let start_time = Utc::now();
    let mut exit = false;
    loop {
        events_loop.poll_events(|event| if let glutin::Event::WindowEvent {
            event, ..
        } = event
        {
            match event {
                glutin::WindowEvent::Closed => exit = true,
                _ => (),
            }
        });

        if exit {
            break;
        }

        let frame_time = Utc::now().signed_duration_since(start_time);
        encoder.clear(&data.out_color, [0.0, 0.0, 0.0, 1.0]);
        for f in face_data.iter() {
            let slice = gfx::Slice {
                start: 0,
                end: f.vertex_count as u32,
                base_vertex: f.vertex_id as u32,
                instances: None,
                buffer: gfx::IndexBuffer::Auto,
            };

            let frame = worldmodel.bsp_data().texture_frame_for_time(
                f.tex_id,
                frame_time,
            );
            data.sampler.0 = textures[f.tex_id].clone();
            encoder.draw(&slice, &pso, &data);
        }
        encoder.flush(&mut device);
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}
<commit_msg>bsp-gfx now has movements controls<commit_after>// Copyright © 2017 Cormac O'Brien
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software
// and associated documentation files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

extern crate chrono;
extern crate cgmath;
extern crate env_logger;
#[macro_use]
extern crate gfx;
extern crate gfx_device_gl;
extern crate gfx_window_glutin;
extern crate glutin;
extern crate richter;

use cgmath::Angle;
use cgmath::Deg;
use cgmath::Euler;
use cgmath::Matrix3;
use cgmath::Matrix4;
use cgmath::Rad;
use cgmath::Vector3;
use chrono::Utc;
use gfx::Device;
use gfx::Factory;
use gfx::traits::FactoryExt;
use glutin::GlContext;
use glutin::GlRequest;
use glutin::Api::OpenGl;

type ColorFormat = gfx::format::Srgba8;
type DepthFormat = gfx::format::DepthStencil;

gfx_defines!{
    vertex Vertex {
        position: [f32; 3] = "v_position",
        texcoord: [f32; 2] = "v_texcoord",
    }

    constant Locals {
        transform: [[f32; 4]; 4] = "u_transform",
    }

    pipeline pipe {
        vertex_buffer: gfx::VertexBuffer<Vertex> = (),
        transform: gfx::Global<[[f32; 4]; 4]> = "u_transform",
        sampler: gfx::TextureSampler<[f32; 4]> = "u_texture",
        out_color: gfx::RenderTarget<ColorFormat> = "Target0",
        out_depth: gfx::DepthTarget<DepthFormat> = gfx::preset::depth::LESS_EQUAL_WRITE,
    }
}

impl From<[f32; 5]> for Vertex {
    fn from(src: [f32; 5]) -> Self {
        Vertex {
            position: [src[0], src[1], src[2]],
            texcoord: [src[3], src[4]],
        }
    }
}

struct Face {
    vertex_id: usize,
    vertex_count: usize,
    tex_id: usize,
}

impl From<(usize, usize, usize)> for Face {
    fn from(src: (usize, usize, usize)) -> Self {
        Face {
            vertex_id: src.0,
            vertex_count: src.1,
            tex_id: src.2,
        }
    }
}

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

    let mut events_loop = glutin::EventsLoop::new();
    let window_builder = glutin::WindowBuilder::new().with_title("BSP renderer: gfx-rs backend");
    let context_builder = glutin::ContextBuilder::new()
        .with_gl(GlRequest::Specific(OpenGl, (3, 3)))
        .with_vsync(true);

    let (window, mut device, mut factory, color, depth) =
        gfx_window_glutin::init::<ColorFormat, DepthFormat>(
            window_builder,
            context_builder,
            &events_loop,
        );

    let mut encoder: gfx::Encoder<gfx_device_gl::Resources, gfx_device_gl::CommandBuffer> =
        factory.create_command_buffer().into();

    let shader_set = factory
        .create_shader_set(
            r#"
#version 430

layout (location = 0) in vec3 v_position;
layout (location = 1) in vec2 v_texcoord;

out vec2 f_texcoord;

uniform mat4 u_transform;

void main() {
    f_texcoord = v_texcoord;
    // gl_Position = u_transform * vec4(v_position.xyz, 1.0);
    gl_Position = u_transform * vec4(-v_position.y, v_position.z, -v_position.x, 1.0);
}
"#
                .as_bytes(),
            r#"
#version 430

in vec2 f_texcoord;

uniform sampler2D u_texture;

out vec4 Target0;

void main() {
    Target0 = texture(u_texture, f_texcoord);
}"#
                .as_bytes(),
        )
        .unwrap();

    let rasterizer = gfx::state::Rasterizer {
        front_face: gfx::state::FrontFace::Clockwise,
        cull_face: gfx::state::CullFace::Back,
        method: gfx::state::RasterMethod::Fill,
        offset: None,
        samples: Some(gfx::state::MultiSample),
    };

    let pso = factory
        .create_pipeline_state(
            &shader_set,
            gfx::Primitive::TriangleList,
            rasterizer,
            pipe::new(),
        )
        .unwrap();

    let mut pak = richter::pak::Pak::new();
    pak.add("pak0.pak").unwrap();
    let (worldmodel, _, _) = richter::bsp::load(pak.open("maps/e1m1.bsp").unwrap()).unwrap();

    let textures = worldmodel
        .bsp_data()
        .textures()
        .iter()
        .map(|tex| {
            let mipmap_full =
                richter::engine::indexed_to_rgba(tex.mipmap(richter::bsp::BspTextureMipmap::Full));
            let (width, height) = tex.dimensions();

            let (_, view) =
                factory
                    .create_texture_immutable_u8::<ColorFormat>(
                        gfx::texture::Kind::D2(
                            width as u16,
                            height as u16,
                            gfx::texture::AaMode::Single,
                        ),
                        &[&mipmap_full],
                    )
                    .unwrap();

            view
        })
        .collect::<Vec<_>>();

    let (face_data, vertex_data): (Vec<Face>, Vec<Vertex>) =
        worldmodel.bsp_data().gen_render_data_interleaved();
    let vertex_buffer = factory.create_vertex_buffer(&vertex_data);

    let sampler = factory.create_sampler(gfx::texture::SamplerInfo::new(
        gfx::texture::FilterMethod::Scale,
        gfx::texture::WrapMode::Tile,
    ));

    let (fb_width, fb_height) = window.window().get_inner_size_pixels().unwrap();

    let perspective = cgmath::perspective(
        cgmath::Rad::from(Deg(75.0)),
        fb_width as f32 / fb_height as f32,
        1.0,
        1024.0,
    );

    let mut data = pipe::Data {
        vertex_buffer: vertex_buffer,
        transform: perspective.into(),
        sampler: (textures[0].clone(), sampler),
        out_color: color,
        out_depth: depth,
    };

    let mut move_forward = false;
    let mut move_back = false;
    let mut move_left = false;
    let mut move_right = false;
    let mut move_up = false;
    let mut move_down = false;

    let mut look_left = false;
    let mut look_right = false;
    let mut look_up = false;
    let mut look_down = false;

    let mut camera_pos = Vector3::new(0.0, 0.0, 0.0);
    let mut camera_angles = Euler::new(Rad(0.0), Rad(0.0), Rad(0.0));

    let start_time = Utc::now();
    let mut prev_frame_time = Utc::now().signed_duration_since(start_time);
    let mut exit = false;
    loop {
        let frame_time = Utc::now().signed_duration_since(start_time);
        let frame_duration = frame_time - prev_frame_time;

        events_loop.poll_events(|event| if let glutin::Event::WindowEvent {
            event, ..
        } = event
        {
            match event {
                glutin::WindowEvent::Closed => exit = true,
                glutin::WindowEvent::KeyboardInput { device_id, input } => {
                    let pressed = match input.state {
                        glutin::ElementState::Pressed => true,
                        glutin::ElementState::Released => false,
                    };

                    if let Some(key) = input.virtual_keycode {
                        match key {
                            glutin::VirtualKeyCode::W => move_forward = pressed,
                            glutin::VirtualKeyCode::A => move_left = pressed,
                            glutin::VirtualKeyCode::S => move_back = pressed,
                            glutin::VirtualKeyCode::D => move_right = pressed,
                            glutin::VirtualKeyCode::Space => move_up = pressed,
                            glutin::VirtualKeyCode::LControl => move_down = pressed,
                            glutin::VirtualKeyCode::Up => look_up = pressed,
                            glutin::VirtualKeyCode::Down => look_down = pressed,
                            glutin::VirtualKeyCode::Left => look_left = pressed,
                            glutin::VirtualKeyCode::Right => look_right = pressed,
                            _ => (),
                        }
                    }
                }
                _ => (),
            }
        });

        if exit {
            break;
        }

        // turn rate of Pi radians per second
        let turn_rate = Rad(::std::f32::consts::PI) * frame_duration.num_milliseconds() as f32 /
            1000.0;

        if look_up {
            camera_angles.x -= turn_rate;
            if camera_angles.x < Rad::from(Deg(-90.0)) {
                camera_angles.x = Rad::from(Deg(-90.0));
            }
        }

        if look_down {
            camera_angles.x += turn_rate;
            if camera_angles.x > Rad::from(Deg(90.0)) {
                camera_angles.x = Rad::from(Deg(90.0));
            }
        }

        if look_right {
            camera_angles.y += turn_rate;
        }

        if look_left {
            camera_angles.y -= turn_rate;
        }

        let rotation = Matrix3::from(camera_angles);

        let mut move_vector = Vector3::new(0.0, 0.0, 0.0);

        if move_forward {
            move_vector.x -= camera_angles.y.sin();
            move_vector.z += camera_angles.y.cos();
        }

        if move_back {
            move_vector.x += camera_angles.y.sin();
            move_vector.z -= camera_angles.y.cos();
        }

        if move_left {
            move_vector.x += camera_angles.y.cos();
            move_vector.z += camera_angles.y.sin();
        }

        if move_right {
            move_vector.x -= camera_angles.y.cos();
            move_vector.z -= camera_angles.y.sin();
        }

        if move_up {
            move_vector.y -= 1.0;
        }

        if move_down {
            move_vector.y += 1.0;
        }

        camera_pos += move_vector;

        encoder.clear(&data.out_color, [0.0, 0.0, 0.0, 1.0]);
        encoder.clear_depth(&data.out_depth, 1.0);
        for f in face_data.iter() {
            let slice = gfx::Slice {
                start: 0,
                end: f.vertex_count as u32,
                base_vertex: f.vertex_id as u32,
                instances: None,
                buffer: gfx::IndexBuffer::Auto,
            };

            let frame = worldmodel.bsp_data().texture_frame_for_time(
                f.tex_id,
                frame_time,
            );
            data.sampler.0 = textures[frame].clone();
            data.transform = (perspective * Matrix4::from(rotation) *
                                  Matrix4::from_translation(camera_pos)).into();
            encoder.draw(&slice, &pso, &data);
        }
        encoder.flush(&mut device);
        window.swap_buffers().unwrap();
        device.cleanup();

        prev_frame_time = frame_time;
    }
}
<|endoftext|>


<commit_before>use test::Bencher;

use protocol::{Request, Command};

#[test]
fn test_request_get_serialization() {
    let mut request = Request::new(Command::Get);
    request.set_key(b"Hello");

    let expected: Vec<u8> = vec![
        0x80, 0x00, 0x00, 0x05,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x05,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x48, 0x65, 0x6c, 0x6c,
        0x6f,
    ];

    let mut result: Vec<u8> = vec![];
    request.write(&mut result).unwrap();
    assert_eq!(result, expected);
}

#[test]
fn test_request_add_serialization() {
    let mut request = Request::new(Command::Add);
    request.set_key(b"Hello");
    request.set_value(b"World");
    request.set_extras(&vec![0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x0e, 0x10]);

    let expected: Vec<u8> = vec![
        0x80, 0x02, 0x00, 0x05,
        0x08, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x12,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0xde, 0xad, 0xbe, 0xef,
        0x00, 0x00, 0x0e, 0x10,
        0x48, 0x65, 0x6c, 0x6c,
        0x6f, 0x57, 0x6f, 0x72,
        0x6c, 0x64,
    ];

    let mut result: Vec<u8> = vec![];
    request.write(&mut result).unwrap();
    assert_eq!(result, expected);
}

#[bench]
fn bench_request_get_serialization(b: &mut Bencher) {
    let mut request = Request::new(Command::Get);
    request.set_key(b"Hello");

    b.iter(|| {
        let mut result: Vec<u8> = vec![];
        request.write(&mut result).unwrap();
    });
}
<commit_msg>More tests for requests serialization<commit_after>use test::Bencher;

use protocol::{Request, Command};

#[test]
fn test_request_get_serialization() {
    let mut request = Request::new(Command::Get);
    request.set_key(b"Hello");

    let expected: Vec<u8> = vec![
        0x80, 0x00, 0x00, 0x05,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x05,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x48, 0x65, 0x6c, 0x6c,
        0x6f,
    ];

    let mut result: Vec<u8> = vec![];
    request.write(&mut result).unwrap();
    assert_eq!(result, expected);
}

#[test]
fn test_request_add_serialization() {
    let mut request = Request::new(Command::Add);
    request.set_key(b"Hello");
    request.set_value(b"World");
    request.set_extras(&vec![0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x0e, 0x10]);

    let expected: Vec<u8> = vec![
        0x80, 0x02, 0x00, 0x05,
        0x08, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x12,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0xde, 0xad, 0xbe, 0xef,
        0x00, 0x00, 0x0e, 0x10,
        0x48, 0x65, 0x6c, 0x6c,
        0x6f, 0x57, 0x6f, 0x72,
        0x6c, 0x64,
    ];

    let mut result: Vec<u8> = vec![];
    request.write(&mut result).unwrap();
    assert_eq!(result, expected);
}

#[test]
fn test_request_delete_serialization() {
    let mut request = Request::new(Command::Delete);
    request.set_key(b"Hello");

    let expected: Vec<u8> = vec![
        0x80, 0x04, 0x00, 0x05,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x05,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x48, 0x65, 0x6c, 0x6c,
        0x6f,
    ];

    let mut result: Vec<u8> = vec![];
    request.write(&mut result).unwrap();
    assert_eq!(result, expected);
}

#[test]
fn test_request_incr_serialization() {
    let mut request = Request::new(Command::Increment);
    request.set_key(b"counter");
    request.set_extras(&[
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x10,
    ]);

    let expected: Vec<u8> = vec![
        0x80, 0x05, 0x00, 0x07,
        0x14, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x1b,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x10,
        0x63, 0x6f, 0x75, 0x6e,
        0x74, 0x65, 0x72,
    ];

    let mut result: Vec<u8> = vec![];
    request.write(&mut result).unwrap();
    assert_eq!(result, expected);
}

#[test]
fn test_request_quit_serialization() {
    let request = Request::new(Command::Quit);

    let expected: Vec<u8> = vec![
        0x80, 0x07, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
    ];

    let mut result: Vec<u8> = vec![];
    request.write(&mut result).unwrap();
    assert_eq!(result, expected);
}

#[test]
fn test_request_noop_serialization() {
    let request = Request::new(Command::Noop);

    let expected: Vec<u8> = vec![
        0x80, 0x0a, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
    ];

    let mut result: Vec<u8> = vec![];
    request.write(&mut result).unwrap();
    assert_eq!(result, expected);
}

#[test]
fn test_request_version_serialization() {
    let request = Request::new(Command::Version);

    let expected: Vec<u8> = vec![
        0x80, 0x0b, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
    ];

    let mut result: Vec<u8> = vec![];
    request.write(&mut result).unwrap();
    assert_eq!(result, expected);
}

#[bench]
fn bench_request_get_serialization(b: &mut Bencher) {
    let mut request = Request::new(Command::Get);
    request.set_key(b"Hello");

    b.iter(|| {
        let mut result: Vec<u8> = vec![];
        request.write(&mut result).unwrap();
    });
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(parse_generics_poc)]

#[macro_use] extern crate custom_derive;
#[macro_use] extern crate parse_macros;

macro_rules! Clone_mac {
    (
        () $($tail:tt)*
    ) => {
        parse_item! {
            then Clone_mac! { @item },
            $($tail)*
        }
    };

    (
        @item
        enum {
            attrs: $_attrs:tt,
            vis: $_vis:tt,
            name: $name:ident,
            generics: {
                constr: [$($constr:tt)*],
                params: [$($params:tt)*],
                ltimes: $_ltimes:tt,
                tnames: [$($tnames:ident,)*],
            },
            where: {
                preds: [$($preds:tt)*],
            },
            variants: [$($vars:tt,)*],
            $($_enum_tail:tt)*
        }
    ) => {
        Clone_mac! {
            @inject_where
            (impl<$($constr)*> Clone for $name<$($params)*>),
            where ($($tnames: Clone,)* $($preds)*)
            ({
                fn clone(&self) -> Self {
                    match *self {
                        $(
                            Clone_mac!(@var_match_pat $name, $vars)
                            => Clone_mac!(@var_match_body $name, $vars),
                        )*
                    }
                }
            })
        }
    };

    (
        @var_match_pat
        $name:ident,
        {
            ord: $_ord:tt,
            attrs: $_attrs:tt,
            kind: unitary,
            name: $vname:ident,
            fields: (),
            num_fields: 0,
        }
    ) => {
        $name::$vname
    };

    (
        @var_match_body
        $name:ident,
        {
            ord: $_ord:tt,
            attrs: $_attrs:tt,
            kind: unitary,
            name: $vname:ident,
            fields: (),
            num_fields: 0,
        }
    ) => {
        $name::$vname
    };

    (
        @var_match_pat
        $name:ident,
        {
            ord: $_ord:tt,
            attrs: $_attrs:tt,
            kind: tuple,
            name: $vname:ident,
            fields: [
                $(
                    {
                        ord: ($_ford:tt, $ford_ident:ident),
                        attrs: $_fattrs:tt,
                        vis: $_fvis:tt,
                        ty: $_fty:ty,
                    },
                )+
            ],
            num_fields: $_num_fields:tt,
        }
    ) => {
        $name::$vname($(ref $ford_ident,)+)
    };

    (
        @var_match_body
        $name:ident,
        {
            ord: $_ord:tt,
            attrs: $_attrs:tt,
            kind: tuple,
            name: $vname:ident,
            fields: [
                $(
                    {
                        ord: ($_ford:tt, $ford_ident:ident),
                        attrs: $_fattrs:tt,
                        vis: $_fvis:tt,
                        ty: $_fty:ty,
                    },
                )+
            ],
            num_fields: $_num_fields:tt,
        }
    ) => {
        $name::$vname($(Clone::clone($ford_ident),)+)
    };

    (
        @var_match_pat
        $name:ident,
        {
            ord: $_ord:tt,
            attrs: $_attrs:tt,
            kind: record,
            name: $vname:ident,
            fields: [
                $(
                    {
                        ord: $_ford:tt,
                        attrs: $_fattrs:tt,
                        vis: $_fvis:tt,
                        ty: $_fty:ty,
                        name: $fname:ident,
                    },
                )+
            ],
            num_fields: $_num_fields:tt,
        }
    ) => {
        $name::$vname { $(ref $fname,)+ }
    };

    (
        @var_match_body
        $name:ident,
        {
            ord: $_ord:tt,
            attrs: $_attrs:tt,
            kind: record,
            name: $vname:ident,
            fields: [
                $(
                    {
                        ord: $_ford:tt,
                        attrs: $_fattrs:tt,
                        vis: $_fvis:tt,
                        ty: $_fty:ty,
                        name: $fname:ident,
                    },
                )+
            ],
            num_fields: $_num_fields:tt,
        }
    ) => {
        $name::$vname { $($fname: Clone::clone($fname),)+ }
    };

    (
        @inject_where
        ($($before:tt)*),
        where ($(,)*)
        ($($after:tt)*)
    ) => {
        Clone_mac! {
            @as_item
            $($before)* $($after)*
        }
    };

    (
        @inject_where
        ($($before:tt)*),
        where ($($preds:tt)+)
        ($($after:tt)*)
    ) => {
        Clone_mac! {
            @as_item
            $($before)* where $($preds)* $($after)*
        }
    };

    (@as_item $i:item) => { $i };
}

custom_derive! {
    #[derive(Copy, Clone_mac)]
    enum EnumA {}
}

custom_derive! {
    #[derive(Copy, Clone_mac)]
    enum EnumB { A }
}

custom_derive! {
    #[derive(Copy, Clone_mac)]
    enum EnumC { A, B, C }
}

custom_derive! {
    #[derive(Copy, Clone_mac)]
    enum EnumD { A, B(i32), C(u8, u8, u8) }
}

custom_derive! {
    #[derive(Copy, Clone_mac)]
    enum EnumE { A { r: u8, g: u8, b: u8, } }
}

fn main() {
    if false { let _: EnumA = panic!(); }
    let _ = EnumB::A.clone();
    let _ = EnumC::A.clone();
    let _ = EnumC::B.clone();
    let _ = EnumC::C.clone();
    let _ = EnumD::A.clone();
    let _ = EnumD::B(42).clone();
    let _ = EnumD::C(1, 2, 3).clone();
    let _ = (EnumE::A { r: 1, g: 2, b: 3 }).clone();
}
<commit_msg>Expanded derive_clone to cover structs.<commit_after>#![feature(plugin)]
#![plugin(parse_generics_poc)]

#[macro_use] extern crate custom_derive;
#[macro_use] extern crate parse_macros;

macro_rules! Clone_mac {
    (
        () $($tail:tt)*
    ) => {
        parse_item! {
            then Clone_mac! { @item },
            $($tail)*
        }
    };

    (
        @item
        enum {
            attrs: $_attrs:tt,
            vis: $_vis:tt,
            name: $name:ident,
            generics: {
                constr: [$($constr:tt)*],
                params: [$($params:tt)*],
                ltimes: $_ltimes:tt,
                tnames: [$($tnames:ident,)*],
            },
            where: {
                preds: [$($preds:tt)*],
            },
            variants: [$($vars:tt,)*],
            $($_enum_tail:tt)*
        }
    ) => {
        Clone_mac! {
            @inject_where
            (impl<$($constr)*> Clone for $name<$($params)*>),
            where ($($tnames: Clone,)* $($preds)*)
            ({
                fn clone(&self) -> Self {
                    match *self {
                        $(
                            Clone_mac!(@var_match_pat $name, $vars)
                            => Clone_mac!(@var_match_body $name, $vars),
                        )*
                    }
                }
            })
        }
    };

    (
        @item
        struct {
            attrs: $_attrs:tt,
            vis: $_vis:tt,
            name: $name:ident,
            generics: {
                constr: [$($constr:tt)*],
                params: [$($params:tt)*],
                ltimes: $_ltimes:tt,
                tnames: [$($tnames:ident,)*],
            },
            where: {
                preds: [$($preds:tt)*],
            },
            kind: unitary,
            fields: [],
            $($_struct_tail:tt)*
        }
    ) => {
        Clone_mac! {
            @inject_where
            (impl<$($constr)*> Clone for $name<$($params)*>),
            where ($($tnames: Clone,)* $($preds)*)
            ({
                fn clone(&self) -> Self {
                    $name
                }
            })
        }
    };

    (
        @item
        struct {
            attrs: $_attrs:tt,
            vis: $_vis:tt,
            name: $name:ident,
            generics: {
                constr: [$($constr:tt)*],
                params: [$($params:tt)*],
                ltimes: $_ltimes:tt,
                tnames: [$($tnames:ident,)*],
            },
            where: {
                preds: [$($preds:tt)*],
            },
            kind: tuple,
            fields: [$(
                {
                    ord: ($_ford:tt, $ford_ident:ident),
                    attrs: $_fattrs:tt,
                    vis: $_fvis:tt,
                    ty: $_fty:ty,
                },
            )*],
            $($_struct_tail:tt)*
        }
    ) => {
        Clone_mac! {
            @inject_where
            (impl<$($constr)*> Clone for $name<$($params)*>),
            where ($($tnames: Clone,)* $($preds)*)
            ({
                fn clone(&self) -> Self {
                    match *self {
                        $name($(ref $ford_ident),*) => $name($(Clone::clone($ford_ident)),*)
                    }
                }
            })
        }
    };

    (
        @item
        struct {
            attrs: $_attrs:tt,
            vis: $_vis:tt,
            name: $name:ident,
            generics: {
                constr: [$($constr:tt)*],
                params: [$($params:tt)*],
                ltimes: $_ltimes:tt,
                tnames: [$($tnames:ident,)*],
            },
            where: {
                preds: [$($preds:tt)*],
            },
            kind: record,
            fields: [$(
                {
                    ord: $_ford:tt,
                    attrs: $_fattrs:tt,
                    vis: $_fvis:tt,
                    name: $fname:ident,
                    ty: $_fty:ty,
                },
            )*],
            $($_struct_tail:tt)*
        }
    ) => {
        Clone_mac! {
            @inject_where
            (impl<$($constr)*> Clone for $name<$($params)*>),
            where ($($tnames: Clone,)* $($preds)*)
            ({
                fn clone(&self) -> Self {
                    match *self {
                        $name { $(ref $fname),* } => $name { $($fname: Clone::clone($fname)),* }
                    }
                }
            })
        }
    };

    (
        @var_match_pat
        $name:ident,
        {
            ord: $_ord:tt,
            attrs: $_attrs:tt,
            kind: unitary,
            name: $vname:ident,
            fields: (),
            num_fields: 0,
        }
    ) => {
        $name::$vname
    };

    (
        @var_match_body
        $name:ident,
        {
            ord: $_ord:tt,
            attrs: $_attrs:tt,
            kind: unitary,
            name: $vname:ident,
            fields: (),
            num_fields: 0,
        }
    ) => {
        $name::$vname
    };

    (
        @var_match_pat
        $name:ident,
        {
            ord: $_ord:tt,
            attrs: $_attrs:tt,
            kind: tuple,
            name: $vname:ident,
            fields: [
                $(
                    {
                        ord: ($_ford:tt, $ford_ident:ident),
                        attrs: $_fattrs:tt,
                        vis: $_fvis:tt,
                        ty: $_fty:ty,
                    },
                )+
            ],
            num_fields: $_num_fields:tt,
        }
    ) => {
        $name::$vname($(ref $ford_ident,)+)
    };

    (
        @var_match_body
        $name:ident,
        {
            ord: $_ord:tt,
            attrs: $_attrs:tt,
            kind: tuple,
            name: $vname:ident,
            fields: [
                $(
                    {
                        ord: ($_ford:tt, $ford_ident:ident),
                        attrs: $_fattrs:tt,
                        vis: $_fvis:tt,
                        ty: $_fty:ty,
                    },
                )+
            ],
            num_fields: $_num_fields:tt,
        }
    ) => {
        $name::$vname($(Clone::clone($ford_ident),)+)
    };

    (
        @var_match_pat
        $name:ident,
        {
            ord: $_ord:tt,
            attrs: $_attrs:tt,
            kind: record,
            name: $vname:ident,
            fields: [
                $(
                    {
                        ord: $_ford:tt,
                        attrs: $_fattrs:tt,
                        vis: $_fvis:tt,
                        ty: $_fty:ty,
                        name: $fname:ident,
                    },
                )+
            ],
            num_fields: $_num_fields:tt,
        }
    ) => {
        $name::$vname { $(ref $fname,)+ }
    };

    (
        @var_match_body
        $name:ident,
        {
            ord: $_ord:tt,
            attrs: $_attrs:tt,
            kind: record,
            name: $vname:ident,
            fields: [
                $(
                    {
                        ord: $_ford:tt,
                        attrs: $_fattrs:tt,
                        vis: $_fvis:tt,
                        ty: $_fty:ty,
                        name: $fname:ident,
                    },
                )+
            ],
            num_fields: $_num_fields:tt,
        }
    ) => {
        $name::$vname { $($fname: Clone::clone($fname),)+ }
    };

    (
        @inject_where
        ($($before:tt)*),
        where ($(,)*)
        ($($after:tt)*)
    ) => {
        Clone_mac! {
            @as_item
            $($before)* $($after)*
        }
    };

    (
        @inject_where
        ($($before:tt)*),
        where ($($preds:tt)+)
        ($($after:tt)*)
    ) => {
        Clone_mac! {
            @as_item
            $($before)* where $($preds)* $($after)*
        }
    };

    (@as_item $i:item) => { $i };
}

custom_derive! {
    #[derive(Clone_mac)]
    enum EnumA {}
}

custom_derive! {
    #[derive(Clone_mac)]
    enum EnumB { A }
}

custom_derive! {
    #[derive(Clone_mac)]
    enum EnumC { A, B, C }
}

custom_derive! {
    #[derive(Clone_mac)]
    enum EnumD { A, B(i32), C(u8, u8, u8) }
}

custom_derive! {
    #[derive(Clone_mac)]
    enum EnumE { A { r: u8, g: u8, b: u8, } }
}

custom_derive! {
    #[derive(Clone_mac)]
    enum EnumF<T> { A { r: T, g: T, b: T, } }
}

custom_derive! {
    #[derive(Clone_mac)]
    struct StructA;
}

custom_derive! {
    #[derive(Clone_mac)]
    struct StructB(i32);
}

custom_derive! {
    #[derive(Clone_mac)]
    struct StructC(i32, u8, String);
}

custom_derive! {
    #[derive(Clone_mac)]
    struct StructD {
        /// The red stuff.
        r: u8,
        pub g: u8,
        b: u8,
    }
}

custom_derive! {
    #[derive(Copy, Clone_mac)]
    struct StructE<T> {
        /// The red stuff.
        r: T,
        pub g: T,
        b: T,
    }
}

fn main() {
    if false { let _: EnumA = panic!(); }
    let _ = EnumB::A.clone();
    let _ = EnumC::A.clone();
    let _ = EnumC::B.clone();
    let _ = EnumC::C.clone();
    let _ = EnumD::A.clone();
    let _ = EnumD::B(42).clone();
    let _ = EnumD::C(1, 2, 3).clone();
    let _ = (EnumE::A { r: 1, g: 2, b: 3 }).clone();
    let _ = (EnumF::A { r: 1, g: 2, b: 3 }).clone();
    let _ = StructA.clone();
    let _ = StructB(42).clone();
    let _ = StructC(42, 2, String::from("hi!")).clone();
    let _ = (StructD { r: 1, g: 2, b: 3 }).clone();
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2016 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Initial 32-bit bootloader for x86_64
#![crate_name = "boot"]
#![crate_type = "staticlib"]
#![feature(asm)]
#![feature(lang_items)]
#![no_std]

const TABLE_LENGTH: usize = 512;

type Table = [u64; TABLE_LENGTH];

use core::fmt::Arguments;

#[lang = "panic_fmt"]
extern fn panic_fmt(fmt: Arguments, file: &'static str, line: u32) -> ! {
	loop {}
}

extern {
	static mut pml4_table: Table;
	static mut pdp_table: Table;
	static mut pd_table: Table;
	static mut page_table: Table;
    //
	// static low_end: u8;
	// static kernel_size: u8; // &kernel_size == kernel size in pages
}

#[no_mangle]
pub unsafe extern fn create_page_tables() {
    // recursive map last PML4 entry
    pml4_table[511] = (&pml4_table as *const Table as u64) | 3;
    // map first PML4 entry to PDP table
    pml4_table[0] = (&pdp_table as *const Table as u64) | 3;
    // map first PDPT entry to PD table
    pdp_table[0] = (&pd_table as *const Table as u64) | 3;

    // map the PD table
    // TODO: implement this in Rust
    asm!("
        // map each PD table entry to its own 2mB page
        mov         ecx, 0
    .pd_table_map: // maps the PD table ----------------------------------------
        mov     eax, 0x200000   // 2 mB
        mul     ecx             // times the start address of the page
        or      eax, 0b10000011 // check if present + writable + huge
        mov     [pd_table + ecx * 8], eax // map nth entry from pd -> own page
        // increment counter and check if done
        inc     ecx
        cmp     ecx, 512
        jne     .pd_table_map
        " :::: "volatile", "intel");
}
<commit_msg>[boot] implement page-table mapping in pure Rust<commit_after>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2016-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Initial 32-bit bootloader for x86_64
#![crate_name = "boot"]
#![crate_type = "staticlib"]
#![feature(asm)]
#![feature(lang_items)]
#![feature(naked_functions)]
#![no_std]

const TABLE_LENGTH: usize = 512;

type Table = [u64; TABLE_LENGTH];

use core::fmt::Arguments;

#[lang = "panic_fmt"]
extern fn panic_fmt(fmt: Arguments, file: &'static str, line: u32) -> ! {
	loop {}
}

extern {
    static mut pml4_table: Table;
    static mut pdp_table: Table;
    static mut pd_table: Table;
    static mut page_table: Table;
    //
    // static low_end: u8;
    // static kernel_size: u8; // &kernel_size == kernel size in pages
}

#[no_mangle]
#[naked]
pub unsafe extern fn create_page_tables() {
    const HUGE_PAGE_SIZE: u64 = 2 * 1024 * 1024; // 2 MiB

    //-- map the PML4 and PDP tables -----------------------------------------
    // recursive map last PML4 entry
    pml4_table[511] = (&pml4_table as *const Table as u64) | 3;
    // map first PML4 entry to PDP table
    pml4_table[0] = (&pdp_table as *const Table as u64) | 3;
    // map first PDPT entry to PD table
    pdp_table[0] = (&pd_table as *const Table as u64) | 3;

    //-- map the PD table ----------------------------------------------------
    for (number, entry) in pd_table.iter_mut().enumerate() {
        // set each PD entry equal to the start address of the page (the page
        // number times the page's size)
        let addr = number as u64 * HUGE_PAGE_SIZE;
        // with the appropriate flags (present + writable + huge)
        // TODO: do we want to do this using bitflags, or is that too
        //       heavyweight for the boot module?
        //          - eliza, 1/23/2017
        *entry = addr | 0b10000011;
    }
}
<|endoftext|>


<commit_before>use clap::{App, Arg, Format, ArgMatches};
use std::io::{self, Write};
use std::process::exit;
use std::fs;
use crowbook::Book;

/// Prints an error on stderr and exit the program
pub fn print_error(s: &str) -> ! {
    writeln!(&mut io::stderr(), "{} {}", Format::Error(lformat!("Error:")), s).unwrap();
    exit(0);
}

/// Gets the book options in a (key, value) list, or print an error
pub fn get_book_options<'a>(matches: &'a ArgMatches) -> Vec<(&'a str, &'a str)> {
    let mut output = vec!();
    if let Some(iter) = matches.values_of("set") {
        let v:Vec<_> = iter.collect();
        if v.len() %2 != 0 {
            print_error(&lformat!("An odd number of arguments was passed to --set, but it takes a list of key value pairs."));
        }

        for i in 0..v.len()/2 {
            let key = v[i * 2];
            let value = v[i * 2 + 1];
            output.push((key, value));
        }
    }
    if matches.is_present("proofread") {
        output.push(("proofread", "true"));
    }
    output
}

/// Sets the book options according to command line arguments
/// Also print these options to a string, so it can be used at
/// the creation of a book to check that parameters are OK and t
/// then print them to file
pub fn set_book_options(book: &mut Book, matches: &ArgMatches) -> String {
    let mut output = String::new();
    let options = get_book_options(matches);

    for (key, value) in options {
        let res = book.options.set(key, value);
        if let Err(err) = res {
            print_error(&lformat!("Error in setting key {}: {}", key, err));
        }
        output.push_str(&format!("{}: {}\n", key, value));
    }
    output
}

/// create a book file with the command line arguments
/// and exit the process at the end
pub fn create_book(matches: &ArgMatches) -> ! {
    let mut f:Box<Write> = if let Some(book) = matches.value_of("BOOK") {
        if fs::metadata(book).is_ok() {
            print_error(&lformat!("Could not create file {}: it already exists!", book));
        }
        Box::new(fs::File::create(book).unwrap())
    } else {
        Box::new(io::stdout())
    };

    if let Some(values) = matches.values_of("create") {
        if matches.is_present("set") {
            let mut book = Book::new(&[]);
            let s = set_book_options(&mut book, matches);
            f.write_all(&s.as_bytes()).unwrap();
        } else {
            f.write_all(b"author: Your name
title: Your title
lang: en

# Uncomment and fill to generate files
# output.html: some_file.html
# output.epub: some_file.epub
# output.pdf: some_file.pdf

# Uncomment and fill to set cover image (for Epub)
# cover: some_cover.png\n").unwrap();
        }
        f.write_all(b"\n# List of chapters\n").unwrap();
        for file in values {
            f.write_all(&format!("+ {}\n", file).as_bytes()).unwrap();
        }
        if let Some(s) = matches.value_of("BOOK") {
            println!("{}", lformat!("Created {}, now you'll have to complete it!", s));
        }
        exit(0);
    } else {
        unreachable!(); // because Clap takes care of it
    }
}

pub fn create_matches<'a>() -> (ArgMatches<'a>, String, String) {
    lazy_static! {
        static ref HELP: String = lformat!("Print help information");
        static ref VERSION: String = lformat!("Print version information");
        static ref ABOUT: String = lformat!("Render a Markdown book in EPUB, PDF or HTML.");
        static ref SINGLE: String = lformat!("Use a single Markdown file instead of a book configuration file");
        static ref VERBOSE: String = lformat!("Print warnings in parsing/rendering");
        static ref QUIET: String = lformat!("Don't print info/error messages");
        static ref PROOFREAD: String = lformat!("Enable proofreading");
        static ref DEBUG: String = lformat!("Print debugging information");
        static ref CREATE: String = lformat!("Create a new book with existing Markdown files");
        static ref OUTPUT: String = lformat!("Specify output file");
        static ref TO: String = lformat!("Generate specific format");
        static ref SET: String = lformat!("Set a list of book options");
        static ref LIST_OPTIONS: String = lformat!("List all possible options");
        static ref LIST_OPTIONS_MD: String = lformat!("List all possible options, formatted in Markdown");
        static ref PRINT_TEMPLATE: String = lformat!("Prints the default content of a template");
        static ref BOOK: String = lformat!("File containing the book configuration file, or a Markdown file when called with --single");
    }

    let mut app = App::new("crowbook")
        .version(env!("CARGO_PKG_VERSION"))
        .author("Élisabeth Henry <liz.henry@ouvaton.org>")
        .about(ABOUT.as_str())
        .arg(Arg::from_usage("-s, --single")
             .help(SINGLE.as_str()))
        .arg(Arg::from_usage("-v, --verbose")
             .help(VERBOSE.as_str()))
        .arg(Arg::from_usage("-q, --quiet")
             .help(QUIET.as_str())
             .conflicts_with("verbose")
             .conflicts_with("debug"))
        .arg(Arg::from_usage("-h, --help")
             .help(HELP.as_str()))
        .arg(Arg::from_usage("-V, --version")
             .help(VERSION.as_str()))
        .arg(Arg::from_usage("-p, --proofread")
             .help(PROOFREAD.as_str()))
        .arg(Arg::from_usage("-d, --debug")
             .help(DEBUG.as_str())
             .conflicts_with("verbose")
             .hidden(true))
        .arg(Arg::from_usage("-c, --create [FILES]...")
             .help(CREATE.as_str()))
        .arg(Arg::from_usage("-o, --output [FILE]")
             .help(OUTPUT.as_str())
             .requires("to"))
        .arg(Arg::from_usage("-t, --to [FORMAT]")
             .help(TO.as_str())
             .possible_values(&["epub", "pdf", "html", "tex", "odt", "proofread.html", "proofread.html_dir", "proofread.pdf", "proofread.tex"]))
        .arg(Arg::from_usage("--set [KEY_VALUES]")
             .help(SET.as_str())
             .min_values(2))
        .arg(Arg::from_usage("-l --list-options")
             .help(LIST_OPTIONS.as_str()))
        .arg(Arg::from_usage("--list-options-md")
             .help(LIST_OPTIONS_MD.as_str())
             .hidden(true))
        .arg(Arg::from_usage("--print-template [TEMPLATE]")
             .help(PRINT_TEMPLATE.as_str()))
        .arg(Arg::with_name("BOOK")
             .index(1)
             .help(BOOK.as_str()));

    // Write help and version now since it `app` is moved when `get_matches` is run
    let mut help = vec!();
    app.write_help(&mut help).unwrap();
    let help = String::from_utf8(help).unwrap();
    let mut version = vec!();
    app.write_version(&mut version).unwrap();
    let version = String::from_utf8(version).unwrap();

    let matches = app.get_matches();

    pre_check(&matches);
    (matches, help, version)
}

/// Pre-check the matches to see if there isn't illegal options not detected by clap
fn pre_check(matches: &ArgMatches) {
    if matches.is_present("files") && !matches.is_present("create") {
        print_error(&lformat!("A list of additional files is only valid with the --create option."));
    }
}
<commit_msg>Use template instead of default clap help<commit_after>use clap::{App, Arg, Format, ArgMatches, AppSettings};
use std::io::{self, Write};
use std::process::exit;
use std::fs;
use crowbook::Book;

/// Prints an error on stderr and exit the program
pub fn print_error(s: &str) -> ! {
    writeln!(&mut io::stderr(), "{} {}", Format::Error(lformat!("Error:")), s).unwrap();
    exit(0);
}

/// Gets the book options in a (key, value) list, or print an error
pub fn get_book_options<'a>(matches: &'a ArgMatches) -> Vec<(&'a str, &'a str)> {
    let mut output = vec!();
    if let Some(iter) = matches.values_of("set") {
        let v:Vec<_> = iter.collect();
        if v.len() %2 != 0 {
            print_error(&lformat!("An odd number of arguments was passed to --set, but it takes a list of key value pairs."));
        }

        for i in 0..v.len()/2 {
            let key = v[i * 2];
            let value = v[i * 2 + 1];
            output.push((key, value));
        }
    }
    if matches.is_present("proofread") {
        output.push(("proofread", "true"));
    }
    output
}

/// Sets the book options according to command line arguments
/// Also print these options to a string, so it can be used at
/// the creation of a book to check that parameters are OK and t
/// then print them to file
pub fn set_book_options(book: &mut Book, matches: &ArgMatches) -> String {
    let mut output = String::new();
    let options = get_book_options(matches);

    for (key, value) in options {
        let res = book.options.set(key, value);
        if let Err(err) = res {
            print_error(&lformat!("Error in setting key {}: {}", key, err));
        }
        output.push_str(&format!("{}: {}\n", key, value));
    }
    output
}

/// create a book file with the command line arguments
/// and exit the process at the end
pub fn create_book(matches: &ArgMatches) -> ! {
    let mut f:Box<Write> = if let Some(book) = matches.value_of("BOOK") {
        if fs::metadata(book).is_ok() {
            print_error(&lformat!("Could not create file {}: it already exists!", book));
        }
        Box::new(fs::File::create(book).unwrap())
    } else {
        Box::new(io::stdout())
    };

    if let Some(values) = matches.values_of("create") {
        if matches.is_present("set") {
            let mut book = Book::new(&[]);
            let s = set_book_options(&mut book, matches);
            f.write_all(&s.as_bytes()).unwrap();
        } else {
            f.write_all(b"author: Your name
title: Your title
lang: en

# Uncomment and fill to generate files
# output.html: some_file.html
# output.epub: some_file.epub
# output.pdf: some_file.pdf

# Uncomment and fill to set cover image (for Epub)
# cover: some_cover.png\n").unwrap();
        }
        f.write_all(b"\n# List of chapters\n").unwrap();
        for file in values {
            f.write_all(&format!("+ {}\n", file).as_bytes()).unwrap();
        }
        if let Some(s) = matches.value_of("BOOK") {
            println!("{}", lformat!("Created {}, now you'll have to complete it!", s));
        }
        exit(0);
    } else {
        unreachable!(); // because Clap takes care of it
    }
}

pub fn create_matches<'a>() -> (ArgMatches<'a>, String, String) {
    lazy_static! {
        static ref HELP: String = lformat!("Print help information");
        static ref VERSION: String = lformat!("Print version information");
        static ref ABOUT: String = lformat!("Render a Markdown book in EPUB, PDF or HTML.");
        static ref SINGLE: String = lformat!("Use a single Markdown file instead of a book configuration file");
        static ref VERBOSE: String = lformat!("Print warnings in parsing/rendering");
        static ref QUIET: String = lformat!("Don't print info/error messages");
        static ref PROOFREAD: String = lformat!("Enable proofreading");
        static ref DEBUG: String = lformat!("Print debugging information");
        static ref CREATE: String = lformat!("Create a new book with existing Markdown files");
        static ref OUTPUT: String = lformat!("Specify output file");
        static ref TO: String = lformat!("Generate specific format");
        static ref SET: String = lformat!("Set a list of book options");
        static ref LIST_OPTIONS: String = lformat!("List all possible options");
        static ref LIST_OPTIONS_MD: String = lformat!("List all possible options, formatted in Markdown");
        static ref PRINT_TEMPLATE: String = lformat!("Prints the default content of a template");
        static ref BOOK: String = lformat!("File containing the book configuration file, or a Markdown file when called with --single");
        static ref TEMPLATE: String = lformat!("\
{{bin}} {{version}} by {{author}}
{{about}}

USAGE:
    {{usage}}

FLAGS:
{{flags}}

OPTIONS:
{{options}}

ARGS:
{{positionals}}
");
    }

    let app = App::new("crowbook")
        .version(env!("CARGO_PKG_VERSION"))
        .author("Élisabeth Henry <liz.henry@ouvaton.org>")
        .setting(AppSettings::UnifiedHelpMessage)
        .setting(AppSettings::HidePossibleValuesInHelp)
        .about(ABOUT.as_str())
        .arg(Arg::from_usage("-s, --single")
             .help(SINGLE.as_str()))
        .arg(Arg::from_usage("-v, --verbose")
             .help(VERBOSE.as_str()))
        .arg(Arg::from_usage("-q, --quiet")
             .help(QUIET.as_str())
             .conflicts_with("verbose")
             .conflicts_with("debug"))
        .arg(Arg::from_usage("-h, --help")
             .help(HELP.as_str()))
        .arg(Arg::from_usage("-V, --version")
             .help(VERSION.as_str()))
        .arg(Arg::from_usage("-p, --proofread")
             .help(PROOFREAD.as_str()))
        .arg(Arg::from_usage("-d, --debug")
             .help(DEBUG.as_str())
             .conflicts_with("verbose")
             .hidden(true))
        .arg(Arg::from_usage("-c, --create [FILES]...")
             .help(CREATE.as_str()))
        .arg(Arg::from_usage("-o, --output [FILE]")
             .help(OUTPUT.as_str())
             .requires("to"))
        .arg(Arg::from_usage("-t, --to [FORMAT]")
             .help(TO.as_str())
             .possible_values(&["epub", "pdf", "html", "tex", "odt", "proofread.html", "proofread.html_dir", "proofread.pdf", "proofread.tex"]))
        .arg(Arg::from_usage("--set [KEY_VALUES]")
             .help(SET.as_str())
             .min_values(2))
        .arg(Arg::from_usage("-l --list-options")
             .help(LIST_OPTIONS.as_str()))
        .arg(Arg::from_usage("--list-options-md")
             .help(LIST_OPTIONS_MD.as_str())
             .hidden(true))
        .arg(Arg::from_usage("--print-template [TEMPLATE]")
             .help(PRINT_TEMPLATE.as_str()))
        .arg(Arg::with_name("BOOK")
             .index(1)
             .help(BOOK.as_str()))
        .template(TEMPLATE.as_str());

    // Write help and version now since it `app` is moved when `get_matches` is run
    let mut help = vec!();
    app.write_help(&mut help).unwrap();
    let help = String::from_utf8(help).unwrap();
    let mut version = vec!();
    app.write_version(&mut version).unwrap();
    let version = String::from_utf8(version).unwrap();

    let matches = app.get_matches();

    pre_check(&matches);
    (matches, help, version)
}

/// Pre-check the matches to see if there isn't illegal options not detected by clap
fn pre_check(matches: &ArgMatches) {
    if matches.is_present("files") && !matches.is_present("create") {
        print_error(&lformat!("A list of additional files is only valid with the --create option."));
    }
}
<|endoftext|>