<commit_before>use ast::Expr;
use ast::ExprType::*;
use ast::Function;
use ast::Program;
use ast::Stmt;
use ast::StmtType::*;
use ast::visit::Visitor;

use error::err;
use error::unimplemented;
use error::ErrorCode;
use error::ParseError;

use lexer::position::Position;

use parser::Parser;

use sym::Sym::*;
use sym::SymbolTable;

struct SemCheck<'a> {
    program: &'a Program,
    global: SymbolTable,
}

impl<'a> Visitor for SemCheck<'a> {
    type Returns = ();

    fn visit_stmt(&mut self, s: &Stmt) -> Result<(), ParseError> {
        match s.node {
            StmtReturn(ref expr) => {
                if expr.is_none() {
                    return err(s.pos, "no return value given".to_string(),
                        ErrorCode::ExpectedValue);
                }

                try!(self.visit_expr(&expr.as_ref().unwrap()));

                Ok(())
            }

            StmtBlock(ref stmts) => {
                for stmt in stmts {
                    try!(self.visit_stmt(stmt));
                }

                Ok(())
            }

            _ => unimplemented(s.pos)
        }
    }

    fn visit_expr(&mut self, e: &Expr) -> Result<(), ParseError> {
        match e.node {
            ExprLitInt(val) => {
                Ok(())
            }

            _ => unimplemented(e.pos)
        }
    }
}

impl<'a> SemCheck<'a> {
    pub fn new(prog: &Program) -> SemCheck {
        SemCheck { program: prog, global: SymbolTable::new() }
    }

    pub fn check(&mut self) -> Result<(), ParseError> {
        self.check_main()
    }

    fn check_main(&mut self) -> Result<(), ParseError> {
        let fct = self.program.function("main");

        if fct.is_none() {
            return err(Position::new(1, 1), "main not found".to_string(),
                ErrorCode::MainDefinition)
        }

        let fct = fct.unwrap();

        if !valid_main_definition(fct) {
            return err(fct.position, "definition of main not correct".to_string(),
                ErrorCode::MainDefinition)
        }

        try!(self.visit_stmt(&fct.block));

        Ok(())
    }
}

fn valid_main_definition(fct: &Function) -> bool {
    fct.type_params.empty() && fct.params.len() == 0 && fct.return_type.is_int()
}

#[cfg(test)]
fn ck(code: &'static str) -> Result<(), ParseError> {
    let prog = Parser::from_str(code).parse().unwrap();

    SemCheck::new(&prog).check()
}

#[test]
fn test_main_undefined() {
    assert!(ck("fn foo() {}").is_err());
}

#[test]
fn test_main_definition_invalid() {
    assert!(ck("fn main(x:int) {}").is_err());
}

#[test]
fn test_main_no_return_value() {
    assert!(ck("fn main() {}").is_err());
    assert!(ck("fn main() -> int { return; }").is_err());
}

#[test]
fn test_main() {
    assert!(ck("fn main() -> int { return 0; }").is_ok());
}

<commit_msg>reworked semantic check<commit_after>use ast::Elem::*;
use ast::Expr;
use ast::ExprType::*;
use ast::Function;
use ast::Program;
use ast::Stmt;
use ast::StmtType::*;
use ast::visit::Visitor;

use error::err;
use error::unimplemented;
use error::ErrorCode;
use error::ParseError;

use lexer::position::Position;

use parser::Parser;

use sym::Sym::*;
use sym::SymbolTable;

type SemResult = Result<(), ParseError>;

struct SemCheck {
    global: SymbolTable,
}

impl Visitor for SemCheck {
    type Returns = ();

    fn visit_stmt(&mut self, s: &Stmt) -> SemResult {
        match s.node {
            StmtReturn(ref expr) => {
                if expr.is_none() {
                    return err(s.pos, "no return value given".to_string(),
                        ErrorCode::ExpectedValue);
                }

                try!(self.visit_expr(&expr.as_ref().unwrap()));

                Ok(())
            }

            StmtBlock(ref stmts) => {
                for stmt in stmts {
                    try!(self.visit_stmt(stmt));
                }

                Ok(())
            }

            _ => unimplemented(s.pos)
        }
    }

    fn visit_expr(&mut self, e: &Expr) -> SemResult {
        match e.node {
            ExprLitInt(val) => {
                Ok(())
            }

            _ => unimplemented(e.pos)
        }
    }
}

impl SemCheck {
    pub fn new() -> SemCheck {
        SemCheck { global: SymbolTable::new() }
    }

    pub fn check_program(&mut self, prog: &Program) -> SemResult {
        // check all functions
        try!(self.check_fcts(prog));

        // check main definition
        self.check_main_fct(prog)
    }

    fn check_main_fct(&mut self, prog: &Program) -> SemResult {
        let fct = prog.function("main");

        if let Some(fct) = fct {
            return if valid_main_definition(fct) {
                Ok(())
            } else {
                err(fct.position, "definition of main not correct".to_string(),
                    ErrorCode::MainDefinition)
            }
        }

        // if no function found --> error
        err(Position::new(1, 1), "main not found".to_string(),
            ErrorCode::MainDefinition)
    }

    fn check_fcts(&mut self, prog: &Program) -> SemResult {
        for elem in &prog.elements {
            try!(match *elem {
                // only allow fct's as top level element
                ElemFunction(ref fct) => self.check_fct(fct),

                _ => unimplemented(Position::new(1, 1))
            })
        }

        Ok(())
    }

    fn check_fct(&mut self, fct: &Function) -> SemResult {
        self.visit_stmt(&fct.block)
    }
}

fn valid_main_definition(fct: &Function) -> bool {
    // no type params
    fct.type_params.empty() &&

        // no function params
        fct.params.len() == 0 &&

        // needs to return int
        fct.return_type.is_int()
}

#[cfg(test)]
fn ck(code: &'static str) -> SemResult {
    let prog = Parser::from_str(code).parse().unwrap();

    SemCheck::new().check_program(&prog)
}

#[test]
fn test_main_undefined() {
    assert!(ck("fn foo() {}").is_err());
}

#[test]
fn test_main_definition_invalid() {
    assert!(ck("fn main(x:int) {}").is_err());
}

#[test]
fn test_main_no_return_value() {
    assert!(ck("fn main() {}").is_err());
    assert!(ck("fn main() -> int { return; }").is_err());
}

#[test]
fn test_main() {
    assert!(ck("fn main() -> int { return 0; }").is_ok());
}

<|endoftext|>


<commit_before>
pub enum SharkState {
    Ignorant,
    ChasingPlayer,
    Dead,
}

pub struct Shark {
    pub sensor_distance: f64,
    pub state: SharkState,
    pub bite_damage: f64,
}

impl Shark {
    pub fn update(&mut self, player_pos: [f64, ..2], shark_pos: [f64, ..2]) {
        let (dx, dy) = (player_pos[0] - shark_pos[0], player_pos[1] - shark_pos[1]);
        let d = (dx * dx + dy * dy).sqrt();
        if d < self.sensor_distance {
            self.state = ChasingPlayer;
        }
    }
}
<commit_msg>Added attack function<commit_after>use player::Player;

pub enum SharkState {
    Ignorant,
    ChasingPlayer,
    Dead,
}

pub struct Shark {
    pub sensor_distance: f64,
    pub state: SharkState,
    pub bite_damage: f64,
}

impl Shark {
    pub fn update(&mut self, player_pos: [f64, ..2], shark_pos: [f64, ..2]) {
        let (dx, dy) = (player_pos[0] - shark_pos[0], player_pos[1] - shark_pos[1]);
        let d = (dx * dx + dy * dy).sqrt();
        if d < self.sensor_distance {
            self.state = ChasingPlayer;
        }
    }

    pub fn attack(&mut self, player: &mut Player) {
        player.blood -= self.bite_damage;
    }
}

<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::io;
use std::fmt;
use std::error::Error;
use std::borrow::Cow;
use std::ops::Add;

use nix;
use term;
use dbus;
use serde;

pub type StratisResult<T> = Result<T, StratisError>;

// Use distinct 'newtype' types for sectors and sector offsets for type safety.
// When needed, these can still be derefed to u64.
// Derive a bunch of stuff so we can do ops on them.
//
custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct Sectors(pub u64);
}

// `SumSectors` can be discarded once `std::iter::Sum` is stable.
pub trait SumSectors: Iterator
    where Sectors: Add<Self::Item, Output = Sectors>
{
    fn sum_sectors(self) -> Sectors
        where Self: Sized
    {
        self.fold(Sectors(0), Add::add)
    }
}

impl<T: Iterator> SumSectors for T where Sectors: Add<T::Item, Output = Sectors> {}

impl serde::Serialize for Sectors {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer
    {
        serializer.serialize_u64(**self)
    }
}

impl serde::Deserialize for Sectors {
    fn deserialize<D>(deserializer: &mut D) -> Result<Sectors, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(Sectors(val))
    }
}

custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct SectorOffset(pub u64);
}

// An error type for errors generated within Stratis
//
#[derive(Debug)]
pub struct InternalError(pub Cow<'static, str>);

impl fmt::Display for InternalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self.0)
    }
}

impl Error for InternalError {
    fn description(&self) -> &str {
        &self.0
    }
}

// Define a common error enum.
// See http://blog.burntsushi.net/rust-error-handling/
#[derive(Debug)]
pub enum StratisError {
    Stratis(InternalError),
    Io(io::Error),
    Nix(nix::Error),
    Dbus(dbus::Error),
    Term(term::Error),
}

impl fmt::Display for StratisError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            StratisError::Stratis(ref err) => write!(f, "Stratis error: {}", err.0),
            StratisError::Io(ref err) => write!(f, "IO error: {}", err),
            StratisError::Nix(ref err) => write!(f, "Nix error: {}", err.errno().desc()),
            StratisError::Dbus(ref err) => {
                write!(f, "Dbus error: {}", err.message().unwrap_or("Unknown"))
            }
            StratisError::Term(ref err) => write!(f, "Term error: {}", err),
        }
    }
}

impl Error for StratisError {
    fn description(&self) -> &str {
        match *self {
            StratisError::Stratis(ref err) => &err.0,
            StratisError::Io(ref err) => err.description(),
            StratisError::Nix(ref err) => err.errno().desc(),
            StratisError::Dbus(ref err) => err.message().unwrap_or("D-Bus Error"),
            StratisError::Term(ref err) => Error::description(err),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            StratisError::Stratis(ref err) => Some(err),
            StratisError::Io(ref err) => Some(err),
            StratisError::Nix(ref err) => Some(err),
            StratisError::Dbus(ref err) => Some(err),
            StratisError::Term(ref err) => Some(err),
        }
    }
}

impl From<InternalError> for StratisError {
    fn from(err: InternalError) -> StratisError {
        StratisError::Stratis(err)
    }
}

impl From<io::Error> for StratisError {
    fn from(err: io::Error) -> StratisError {
        StratisError::Io(err)
    }
}

impl From<nix::Error> for StratisError {
    fn from(err: nix::Error) -> StratisError {
        StratisError::Nix(err)
    }
}

impl From<dbus::Error> for StratisError {
    fn from(err: dbus::Error) -> StratisError {
        StratisError::Dbus(err)
    }
}

impl From<term::Error> for StratisError {
    fn from(err: term::Error) -> StratisError {
        StratisError::Term(err)
    }
}
<commit_msg>It looks like std::iter::Sum is stable and we can delete SumSectors.<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::io;
use std::fmt;
use std::error::Error;
use std::borrow::Cow;

use nix;
use term;
use dbus;
use serde;

pub type StratisResult<T> = Result<T, StratisError>;

// Use distinct 'newtype' types for sectors and sector offsets for type safety.
// When needed, these can still be derefed to u64.
// Derive a bunch of stuff so we can do ops on them.
//
custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct Sectors(pub u64);
}

impl serde::Serialize for Sectors {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer
    {
        serializer.serialize_u64(**self)
    }
}

impl serde::Deserialize for Sectors {
    fn deserialize<D>(deserializer: &mut D) -> Result<Sectors, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(Sectors(val))
    }
}

custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct SectorOffset(pub u64);
}

// An error type for errors generated within Stratis
//
#[derive(Debug)]
pub struct InternalError(pub Cow<'static, str>);

impl fmt::Display for InternalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self.0)
    }
}

impl Error for InternalError {
    fn description(&self) -> &str {
        &self.0
    }
}

// Define a common error enum.
// See http://blog.burntsushi.net/rust-error-handling/
#[derive(Debug)]
pub enum StratisError {
    Stratis(InternalError),
    Io(io::Error),
    Nix(nix::Error),
    Dbus(dbus::Error),
    Term(term::Error),
}

impl fmt::Display for StratisError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            StratisError::Stratis(ref err) => write!(f, "Stratis error: {}", err.0),
            StratisError::Io(ref err) => write!(f, "IO error: {}", err),
            StratisError::Nix(ref err) => write!(f, "Nix error: {}", err.errno().desc()),
            StratisError::Dbus(ref err) => {
                write!(f, "Dbus error: {}", err.message().unwrap_or("Unknown"))
            }
            StratisError::Term(ref err) => write!(f, "Term error: {}", err),
        }
    }
}

impl Error for StratisError {
    fn description(&self) -> &str {
        match *self {
            StratisError::Stratis(ref err) => &err.0,
            StratisError::Io(ref err) => err.description(),
            StratisError::Nix(ref err) => err.errno().desc(),
            StratisError::Dbus(ref err) => err.message().unwrap_or("D-Bus Error"),
            StratisError::Term(ref err) => Error::description(err),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            StratisError::Stratis(ref err) => Some(err),
            StratisError::Io(ref err) => Some(err),
            StratisError::Nix(ref err) => Some(err),
            StratisError::Dbus(ref err) => Some(err),
            StratisError::Term(ref err) => Some(err),
        }
    }
}

impl From<InternalError> for StratisError {
    fn from(err: InternalError) -> StratisError {
        StratisError::Stratis(err)
    }
}

impl From<io::Error> for StratisError {
    fn from(err: io::Error) -> StratisError {
        StratisError::Io(err)
    }
}

impl From<nix::Error> for StratisError {
    fn from(err: nix::Error) -> StratisError {
        StratisError::Nix(err)
    }
}

impl From<dbus::Error> for StratisError {
    fn from(err: dbus::Error) -> StratisError {
        StratisError::Dbus(err)
    }
}

impl From<term::Error> for StratisError {
    fn from(err: term::Error) -> StratisError {
        StratisError::Term(err)
    }
}
<|endoftext|>


<commit_before>use std::io;

use glium;

use data;
use mvp;

pub fn mat4_id() -> mvp::Matrix4 {
    // TODO lazy_static!
    [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
}

pub fn ortho_projection(screen_size: data::Size) -> mvp::Matrix4 {
    let o_w = 2.0 / screen_size.width as f32;
    let o_h = 2.0 / screen_size.height as f32;

    // TODO make this better?
    [[o_w, 0.0, 0.0, 0.0], [0.0, o_h, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
}

pub fn read_file(filename: &str) -> io::Result<(String)> {
    use std::io::Read;
    use std::fs::File;

    let mut file = try!(File::open(filename));
    let mut src = String::new();
    try!(file.read_to_string(&mut src));
    Ok(src)
}

pub fn read_png_to_texture(file_bytes: &[u8]) -> glium::texture::RawImage2d<u8> {
    use image;

    let image = image::load(io::Cursor::new(file_bytes), image::PNG).unwrap().to_rgba();
    let image_dimensions = image.dimensions();
    glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(), image_dimensions)
}

pub fn indices(length: usize) -> Vec<u16> {
    (0..length)
        .into_iter()
        .flat_map(|i| {
            vec![0, 1, 2, 0, 2, 3].into_iter().map(|j| (j + i * 4) as u16).collect::<Vec<u16>>()
        })
        .collect()
}
<commit_msg>chore(utils): clean up; add read_bytes<commit_after>use std::io;

use glium;

use data;
use mvp;

pub fn mat4_id() -> mvp::Matrix4 {
    // TODO lazy_static!
    [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
}

pub fn ortho_projection(screen_size: data::Size) -> mvp::Matrix4 {
    let o_w = 2.0 / screen_size.width as f32;
    let o_h = 2.0 / screen_size.height as f32;

    // TODO make this better?
    [[o_w, 0.0, 0.0, 0.0], [0.0, o_h, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
}

pub fn read_file(path: &str) -> io::Result<(String)> {
    use std::io::Read;
    use std::fs::File;

    let mut file = try!(File::open(path));
    let mut string = String::new();
    try!(file.read_to_string(&mut string));
    Ok(string)
}

pub fn read_bytes(path: &str) -> io::Result<Vec<u8>> {
    use std::io::Read;
    use std::fs::File;

    let mut file = try!(File::open(path));
    let mut bytes = Vec::new();
    try!(file.read_to_end(&mut bytes));
    Ok(bytes)
}

pub fn read_png_to_texture(bytes: &[u8]) -> glium::texture::RawImage2d<u8> {
    use image;

    let image = image::load(io::Cursor::new(bytes), image::PNG).unwrap().to_rgba();
    let image_dimensions = image.dimensions();
    glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(), image_dimensions)
}

pub fn indices(length: usize) -> Vec<u16> {
    (0..length)
        .into_iter()
        .flat_map(|i| {
            vec![0, 1, 2, 0, 2, 3].into_iter().map(|j| (j + i * 4) as u16).collect::<Vec<u16>>()
        })
        .collect()
}
<|endoftext|>


<commit_before>use c_types;
use c_ares_sys;

use types::AddressFamily;
use std::ffi::CStr;
use std::mem;
use std::os::raw::c_int;
use std::net::{
    Ipv4Addr,
    Ipv6Addr,
    SocketAddrV4,
    SocketAddrV6,
};
use std::str;

// Convert an address family into a more strongly typed AddressFamily.
pub fn address_family(family: c_int) -> Option<AddressFamily> {
    match family {
        c_types::AF_INET => Some(AddressFamily::INET),
        c_types::AF_INET6 => Some(AddressFamily::INET6),
        _ => None,
    }
}

// Get an in_addr from an Ipv4Addr.
#[cfg(unix)]
pub fn ipv4_as_in_addr(ipv4: &Ipv4Addr) -> c_types::in_addr {
    c_types::in_addr { s_addr: u32::from(*ipv4).to_be() }
}

#[cfg(windows)]
pub fn ipv4_as_in_addr(ipv4: &Ipv4Addr) -> c_types::in_addr {
    c_types::in_addr { S_un: u32::from(*ipv4).to_be() }
}

// Get an Ipv4Addr from an in_addr.
#[cfg(unix)]
pub fn ipv4_from_in_addr(in_addr: &c_types::in_addr) -> Ipv4Addr {
    Ipv4Addr::from(u32::from_be(in_addr.s_addr))
}

#[cfg(windows)]
pub fn ipv4_from_in_addr(in_addr: &c_types::in_addr) -> Ipv4Addr {
    Ipv4Addr::from(u32::from_be(in_addr.S_un))
}

// Get an in6_addr from an Ipv6Addr.
pub fn ipv6_as_in6_addr(ipv6: &Ipv6Addr) -> c_types::in6_addr {
    let segments = ipv6.segments();
    let mut in6_addr: c_types::in6_addr = unsafe { mem::uninitialized() };
    in6_addr.s6_addr[0] = (segments[0] >> 8) as u8;
    in6_addr.s6_addr[1] = segments[0] as u8;
    in6_addr.s6_addr[2] = (segments[1] >> 8) as u8;
    in6_addr.s6_addr[3] = segments[1] as u8;
    in6_addr.s6_addr[4] = (segments[2] >> 8) as u8;
    in6_addr.s6_addr[5] = segments[2] as u8;
    in6_addr.s6_addr[6] = (segments[3] >> 8) as u8;
    in6_addr.s6_addr[7] = segments[3] as u8;
    in6_addr.s6_addr[8] = (segments[4] >> 8) as u8;
    in6_addr.s6_addr[9] = segments[4] as u8;
    in6_addr.s6_addr[10] = (segments[5] >> 8) as u8;
    in6_addr.s6_addr[11] = segments[5] as u8;
    in6_addr.s6_addr[12] = (segments[6] >> 8) as u8;
    in6_addr.s6_addr[13] = segments[6] as u8;
    in6_addr.s6_addr[14] = (segments[7] >> 8) as u8;
    in6_addr.s6_addr[15] = segments[7] as u8;
    in6_addr
}

// Get a sockaddr_in from a SocketAddrV4.
#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "openbsd",
          target_os = "netbsd",
          target_os = "bitrig"))]
pub fn socket_addrv4_as_sockaddr_in(
    sock_v4: &SocketAddrV4) -> c_types::sockaddr_in {
    let in_addr = ipv4_as_in_addr(sock_v4.ip());
    c_types::sockaddr_in {
        sin_len: mem::size_of::<c_types::sockaddr_in>() as u8,
        sin_family: c_types::AF_INET as c_types::sa_family_t,
        sin_port: sock_v4.port().to_be(),
        sin_addr: in_addr,
        sin_zero: [0; 8],
    }
}

#[cfg(not(any(target_os = "macos",
              target_os = "ios",
              target_os = "freebsd",
              target_os = "dragonfly",
              target_os = "openbsd",
              target_os = "netbsd",
              target_os = "bitrig")))]
pub fn socket_addrv4_as_sockaddr_in(
    sock_v4: &SocketAddrV4) -> c_types::sockaddr_in {
    let in_addr = ipv4_as_in_addr(sock_v4.ip());
    c_types::sockaddr_in {
        sin_family: c_types::AF_INET as c_types::sa_family_t,
        sin_port: sock_v4.port().to_be(),
        sin_addr: in_addr,
        sin_zero: [0; 8],
    }
}

// Get a sockaddr_in6 from a SocketAddrV6.
#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "openbsd",
          target_os = "netbsd",
          target_os = "bitrig"))]
pub fn socket_addrv6_as_sockaddr_in6(
    sock_v6: &SocketAddrV6) -> c_types::sockaddr_in6 {
    let in6_addr = ipv6_as_in6_addr(sock_v6.ip());
    c_types::sockaddr_in6 {
        sin6_len: mem::size_of::<c_types::sockaddr_in6>() as u8,
        sin6_family: c_types::AF_INET6 as c_types::sa_family_t,
        sin6_port: sock_v6.port().to_be(),
        sin6_addr: in6_addr,
        sin6_flowinfo: sock_v6.flowinfo(),
        sin6_scope_id: sock_v6.scope_id(),
    }
}

#[cfg(all(unix,not(any(target_os = "macos",
                       target_os = "ios",
                       target_os = "freebsd",
                       target_os = "dragonfly",
                       target_os = "openbsd",
                       target_os = "netbsd",
                       target_os = "bitrig"))))]
pub fn socket_addrv6_as_sockaddr_in6(
    sock_v6: &SocketAddrV6) -> c_types::sockaddr_in6 {
    let in6_addr = ipv6_as_in6_addr(sock_v6.ip());
    c_types::sockaddr_in6 {
        sin6_family: c_types::AF_INET6 as c_types::sa_family_t,
        sin6_port: sock_v6.port().to_be(),
        sin6_addr: in6_addr,
        sin6_flowinfo: sock_v6.flowinfo(),
        sin6_scope_id: sock_v6.scope_id(),
    }
}

#[cfg(windows)]
pub fn socket_addrv6_as_sockaddr_in6(
    sock_v6: &SocketAddrV6) -> c_types::sockaddr_in6 {
    let in6_addr = ipv6_as_in6_addr(sock_v6.ip());
    c_types::sockaddr_in6 {
        sin6_family: c_types::AF_INET6 as i16,
        sin6_port: sock_v6.port().to_be(),
        sin6_addr: in6_addr,
        sin6_flowinfo: sock_v6.flowinfo(),
        sin6_scope_id: sock_v6.scope_id(),
    }
}

/// Get the version number of the underlying `c-ares` library.
///
/// The version is returned as both a string and an integer.  The integer is
/// built up as 24bit number, with 8 separate bits used for major number, minor
/// number and patch number.  For example, the version string "1.2.3" is
/// returned as hexadecimal number 0x010203 (decimal 66051).
pub fn version() -> (&'static str, u32) {
    let mut int_version: c_int = 0;
    let str_version = unsafe {
        let ptr = c_ares_sys::ares_version(&mut int_version);
        let buf = CStr::from_ptr(ptr).to_bytes();
        str::from_utf8_unchecked(buf)
    };
    (str_version, int_version as u32)
}
<commit_msg>AF_UNSPEC<commit_after>use c_types;
use c_ares_sys;

use types::AddressFamily;
use std::ffi::CStr;
use std::mem;
use std::os::raw::c_int;
use std::net::{
    Ipv4Addr,
    Ipv6Addr,
    SocketAddrV4,
    SocketAddrV6,
};
use std::str;

// Convert an address family into a more strongly typed AddressFamily.
pub fn address_family(family: c_int) -> Option<AddressFamily> {
    match family {
        c_types::AF_INET => Some(AddressFamily::INET),
        c_types::AF_INET6 => Some(AddressFamily::INET6),
        c_types::AF_UNSPEC => Some(AddressFamily::UNSPEC),
        _ => None,
    }
}

// Get an in_addr from an Ipv4Addr.
#[cfg(unix)]
pub fn ipv4_as_in_addr(ipv4: &Ipv4Addr) -> c_types::in_addr {
    c_types::in_addr { s_addr: u32::from(*ipv4).to_be() }
}

#[cfg(windows)]
pub fn ipv4_as_in_addr(ipv4: &Ipv4Addr) -> c_types::in_addr {
    c_types::in_addr { S_un: u32::from(*ipv4).to_be() }
}

// Get an Ipv4Addr from an in_addr.
#[cfg(unix)]
pub fn ipv4_from_in_addr(in_addr: &c_types::in_addr) -> Ipv4Addr {
    Ipv4Addr::from(u32::from_be(in_addr.s_addr))
}

#[cfg(windows)]
pub fn ipv4_from_in_addr(in_addr: &c_types::in_addr) -> Ipv4Addr {
    Ipv4Addr::from(u32::from_be(in_addr.S_un))
}

// Get an in6_addr from an Ipv6Addr.
pub fn ipv6_as_in6_addr(ipv6: &Ipv6Addr) -> c_types::in6_addr {
    let segments = ipv6.segments();
    let mut in6_addr: c_types::in6_addr = unsafe { mem::uninitialized() };
    in6_addr.s6_addr[0] = (segments[0] >> 8) as u8;
    in6_addr.s6_addr[1] = segments[0] as u8;
    in6_addr.s6_addr[2] = (segments[1] >> 8) as u8;
    in6_addr.s6_addr[3] = segments[1] as u8;
    in6_addr.s6_addr[4] = (segments[2] >> 8) as u8;
    in6_addr.s6_addr[5] = segments[2] as u8;
    in6_addr.s6_addr[6] = (segments[3] >> 8) as u8;
    in6_addr.s6_addr[7] = segments[3] as u8;
    in6_addr.s6_addr[8] = (segments[4] >> 8) as u8;
    in6_addr.s6_addr[9] = segments[4] as u8;
    in6_addr.s6_addr[10] = (segments[5] >> 8) as u8;
    in6_addr.s6_addr[11] = segments[5] as u8;
    in6_addr.s6_addr[12] = (segments[6] >> 8) as u8;
    in6_addr.s6_addr[13] = segments[6] as u8;
    in6_addr.s6_addr[14] = (segments[7] >> 8) as u8;
    in6_addr.s6_addr[15] = segments[7] as u8;
    in6_addr
}

// Get a sockaddr_in from a SocketAddrV4.
#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "openbsd",
          target_os = "netbsd",
          target_os = "bitrig"))]
pub fn socket_addrv4_as_sockaddr_in(
    sock_v4: &SocketAddrV4) -> c_types::sockaddr_in {
    let in_addr = ipv4_as_in_addr(sock_v4.ip());
    c_types::sockaddr_in {
        sin_len: mem::size_of::<c_types::sockaddr_in>() as u8,
        sin_family: c_types::AF_INET as c_types::sa_family_t,
        sin_port: sock_v4.port().to_be(),
        sin_addr: in_addr,
        sin_zero: [0; 8],
    }
}

#[cfg(not(any(target_os = "macos",
              target_os = "ios",
              target_os = "freebsd",
              target_os = "dragonfly",
              target_os = "openbsd",
              target_os = "netbsd",
              target_os = "bitrig")))]
pub fn socket_addrv4_as_sockaddr_in(
    sock_v4: &SocketAddrV4) -> c_types::sockaddr_in {
    let in_addr = ipv4_as_in_addr(sock_v4.ip());
    c_types::sockaddr_in {
        sin_family: c_types::AF_INET as c_types::sa_family_t,
        sin_port: sock_v4.port().to_be(),
        sin_addr: in_addr,
        sin_zero: [0; 8],
    }
}

// Get a sockaddr_in6 from a SocketAddrV6.
#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "openbsd",
          target_os = "netbsd",
          target_os = "bitrig"))]
pub fn socket_addrv6_as_sockaddr_in6(
    sock_v6: &SocketAddrV6) -> c_types::sockaddr_in6 {
    let in6_addr = ipv6_as_in6_addr(sock_v6.ip());
    c_types::sockaddr_in6 {
        sin6_len: mem::size_of::<c_types::sockaddr_in6>() as u8,
        sin6_family: c_types::AF_INET6 as c_types::sa_family_t,
        sin6_port: sock_v6.port().to_be(),
        sin6_addr: in6_addr,
        sin6_flowinfo: sock_v6.flowinfo(),
        sin6_scope_id: sock_v6.scope_id(),
    }
}

#[cfg(all(unix,not(any(target_os = "macos",
                       target_os = "ios",
                       target_os = "freebsd",
                       target_os = "dragonfly",
                       target_os = "openbsd",
                       target_os = "netbsd",
                       target_os = "bitrig"))))]
pub fn socket_addrv6_as_sockaddr_in6(
    sock_v6: &SocketAddrV6) -> c_types::sockaddr_in6 {
    let in6_addr = ipv6_as_in6_addr(sock_v6.ip());
    c_types::sockaddr_in6 {
        sin6_family: c_types::AF_INET6 as c_types::sa_family_t,
        sin6_port: sock_v6.port().to_be(),
        sin6_addr: in6_addr,
        sin6_flowinfo: sock_v6.flowinfo(),
        sin6_scope_id: sock_v6.scope_id(),
    }
}

#[cfg(windows)]
pub fn socket_addrv6_as_sockaddr_in6(
    sock_v6: &SocketAddrV6) -> c_types::sockaddr_in6 {
    let in6_addr = ipv6_as_in6_addr(sock_v6.ip());
    c_types::sockaddr_in6 {
        sin6_family: c_types::AF_INET6 as i16,
        sin6_port: sock_v6.port().to_be(),
        sin6_addr: in6_addr,
        sin6_flowinfo: sock_v6.flowinfo(),
        sin6_scope_id: sock_v6.scope_id(),
    }
}

/// Get the version number of the underlying `c-ares` library.
///
/// The version is returned as both a string and an integer.  The integer is
/// built up as 24bit number, with 8 separate bits used for major number, minor
/// number and patch number.  For example, the version string "1.2.3" is
/// returned as hexadecimal number 0x010203 (decimal 66051).
pub fn version() -> (&'static str, u32) {
    let mut int_version: c_int = 0;
    let str_version = unsafe {
        let ptr = c_ares_sys::ares_version(&mut int_version);
        let buf = CStr::from_ptr(ptr).to_bytes();
        str::from_utf8_unchecked(buf)
    };
    (str_version, int_version as u32)
}
<|endoftext|>


<commit_before>use libc::c_char;
use std::ffi::c_str_to_bytes;
use std::str;

pub fn _string(raw_ptr: *const c_char) -> String {
    let bytes = unsafe { c_str_to_bytes(&raw_ptr) };
    return str::from_utf8(bytes).unwrap().to_string();
}
<commit_msg>conform to rfc 592<commit_after>use libc::c_char;
use std::ffi::CStr;
use std::str;

pub fn _string(raw_ptr: *const c_char) -> String {
    let c_str = unsafe { CStr::from_ptr(raw_ptr) };
    return str::from_utf8(c_str.to_bytes()).unwrap().to_string();
}
<|endoftext|>


<commit_before>use std;
use std::io;
use std::convert::From;

use std::net::SocketAddr;

use mioco::udp::UdpSocket;
use trust_dns::op::{Message, Query, MessageType};
use trust_dns::error::{DecodeError, EncodeError};
use trust_dns::serialize::binary::{BinDecoder, BinEncoder, BinSerializable};

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Io(err: io::Error) {
            from()
            from(kind: io::ErrorKind) -> (io::Error::new(kind, "Io"))
            description(err.description())
        }
        Decode(err: DecodeError) {
            from()
            description(err.description())
        }
        Encode(err: EncodeError) {
            from()
            description(err.description())
        }
    }
}

pub type Result<T> = std::result::Result<T, Error>;

pub trait CloneExt {
    fn clone(&self) -> Self;
}

impl CloneExt for Query {
    fn clone(&self) -> Query {
        let mut ret = Query::new();
        ret.name(self.get_name().clone())
            .query_type(self.get_query_type())
            .query_class(self.get_query_class());
        ret
    }
}

pub trait MessageExt {
    fn to_bytes(&self) -> Result<Vec<u8>>;
    fn from_bytes(buf: &[u8]) -> Result<Message>;
    fn from_udp(sock: &mut UdpSocket) -> Result<(Message, SocketAddr)>;
    fn new_resp(&self) -> Message;
    fn copy_resp_from(&mut self, other: &Message);
    fn is_resp_for(&self, other: &Message) -> bool;
}
impl MessageExt for Message {
    fn to_bytes(&self) -> Result<Vec<u8>> {
        let mut ret = Vec::<u8>::new();
        {
            let mut encoder = BinEncoder::new(&mut ret);
            try!(self.emit(&mut encoder));
        }
        Ok(ret)
    }
    fn from_bytes(buf: &[u8]) -> Result<Message> {
        let mut decoder = BinDecoder::new(buf);
        let msg = try!(Message::read(&mut decoder));
        Ok(msg)
    }
    fn from_udp(sock: &mut UdpSocket) -> Result<(Message, SocketAddr)> {
        let mut buf = [0u8; 1024 * 16];
        let (l, addr) = try!(sock.recv(&mut buf));
        let msg = try!(Message::from_bytes(&buf[0..l]));
        Ok((msg, addr))
    }
    fn new_resp(&self) -> Message {
        let mut ret : Message = Message::new();
        ret.message_type(MessageType::Response);
        ret.id(self.get_id());
        ret.op_code(self.get_op_code());
        ret.recursion_desired(self.is_recursion_desired());
        for q in self.get_queries() {
            ret.add_query(q.clone());
        }
        ret
    }
    fn copy_resp_from(&mut self, other: &Message) {
        self.response_code(other.get_response_code());
        self.add_all_answers(other.get_answers());
        self.add_all_name_servers(other.get_name_servers());
        for rec in other.get_additional() {
            self.add_additional(rec.clone());
        }
    }
    fn is_resp_for(&self, other: &Message) -> bool {
        assert_eq!(other.get_message_type(), MessageType::Query);
        if self.get_message_type() != MessageType::Response {
            return false;
        }
        if other.get_id() != self.get_id() {
            return false;
        }
        if other.get_op_code() != self.get_op_code() {
            return false;
        }
        assert_eq!(other.get_queries().len(), 1);
        if self.get_queries().len() != 1 {
            return false;
        }
        if other.get_queries()[0] != self.get_queries()[0] {
            return false;
        }
        true
    }
}
<commit_msg>Do not forward OPT record<commit_after>use std;
use std::io;
use std::convert::From;

use std::net::SocketAddr;

use mioco::udp::UdpSocket;
use trust_dns::op::{Message, Query, MessageType};
use trust_dns::error::{DecodeError, EncodeError};
use trust_dns::rr::RecordType;
use trust_dns::serialize::binary::{BinDecoder, BinEncoder, BinSerializable};

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Io(err: io::Error) {
            from()
            from(kind: io::ErrorKind) -> (io::Error::new(kind, "Io"))
            description(err.description())
        }
        Decode(err: DecodeError) {
            from()
            description(err.description())
        }
        Encode(err: EncodeError) {
            from()
            description(err.description())
        }
    }
}

pub type Result<T> = std::result::Result<T, Error>;

pub trait CloneExt {
    fn clone(&self) -> Self;
}

impl CloneExt for Query {
    fn clone(&self) -> Query {
        let mut ret = Query::new();
        ret.name(self.get_name().clone())
            .query_type(self.get_query_type())
            .query_class(self.get_query_class());
        ret
    }
}

pub trait MessageExt {
    fn to_bytes(&self) -> Result<Vec<u8>>;
    fn from_bytes(buf: &[u8]) -> Result<Message>;
    fn from_udp(sock: &mut UdpSocket) -> Result<(Message, SocketAddr)>;
    fn new_resp(&self) -> Message;
    fn copy_resp_from(&mut self, other: &Message);
    fn is_resp_for(&self, other: &Message) -> bool;
}
impl MessageExt for Message {
    fn to_bytes(&self) -> Result<Vec<u8>> {
        let mut ret = Vec::<u8>::new();
        {
            let mut encoder = BinEncoder::new(&mut ret);
            try!(self.emit(&mut encoder));
        }
        Ok(ret)
    }
    fn from_bytes(buf: &[u8]) -> Result<Message> {
        let mut decoder = BinDecoder::new(buf);
        let msg = try!(Message::read(&mut decoder));
        Ok(msg)
    }
    fn from_udp(sock: &mut UdpSocket) -> Result<(Message, SocketAddr)> {
        let mut buf = [0u8; 1024 * 16];
        let (l, addr) = try!(sock.recv(&mut buf));
        let msg = try!(Message::from_bytes(&buf[0..l]));
        Ok((msg, addr))
    }
    fn new_resp(&self) -> Message {
        let mut ret : Message = Message::new();
        ret.message_type(MessageType::Response);
        ret.id(self.get_id());
        ret.op_code(self.get_op_code());
        ret.recursion_desired(self.is_recursion_desired());
        for q in self.get_queries() {
            ret.add_query(q.clone());
        }
        ret
    }
    fn copy_resp_from(&mut self, other: &Message) {
        self.response_code(other.get_response_code());
        self.add_all_answers(other.get_answers());
        self.add_all_name_servers(other.get_name_servers());
        for rec in other.get_additional() {
            if rec.get_rr_type() == RecordType::OPT {
                // RFC 2671 4.1: OPT should never be cached nor forwarded
                continue;
            }
            self.add_additional(rec.clone());
        }
    }
    fn is_resp_for(&self, other: &Message) -> bool {
        assert_eq!(other.get_message_type(), MessageType::Query);
        if self.get_message_type() != MessageType::Response {
            return false;
        }
        if other.get_id() != self.get_id() {
            return false;
        }
        if other.get_op_code() != self.get_op_code() {
            return false;
        }
        assert_eq!(other.get_queries().len(), 1);
        if self.get_queries().len() != 1 {
            return false;
        }
        if other.get_queries()[0] != self.get_queries()[0] {
            return false;
        }
        true
    }
}
<|endoftext|>


<commit_before>use rgtk::*;
use serialize::json;
use std::collections::HashSet;
use std::io::fs;
use std::io::fs::PathExtensions;
use std::os::homedir;

pub struct State<'a> {
    pub projects: HashSet<String>,
    pub expansions: HashSet<String>,
    pub selection: Option<String>,
    pub tree_store: &'a gtk::TreeStore,
    pub tree_model: &'a gtk::TreeModel,
    pub tree_selection: &'a gtk::TreeSelection,
    pub rename_button: &'a gtk::Button,
    pub remove_button: &'a gtk::Button,
}

#[deriving(Decodable, Encodable)]
struct Prefs {
    projects: Vec<String>,
    expansions: Vec<String>,
    selection: Option<String>
}

fn get_data_dir() -> Path {
    let home = homedir();
    let mut path = match home {
        Some(p) => p,
        None => Path::new(".")
    };
    path.push(".solidoak");
    path
}

fn get_prefs_file() -> Path {
    let mut path = get_data_dir();
    path.push("prefs.json");
    path
}

fn get_prefs(state: &State) -> Prefs {
    Prefs {
        projects: state.projects.clone().into_iter().collect(),
        expansions: state.expansions.clone().into_iter().collect(),
        selection: state.selection.clone()
    }
}

pub fn are_siblings(path1: &String, path2: &String) -> bool {
    let parent_path1 = Path::new(path1).dir_path();
    let parent_path2 = Path::new(path2).dir_path();

    let parent1 = parent_path1.as_str();
    let parent2 = parent_path2.as_str();

    parent1.is_some() && parent2.is_some() &&
    parent1.unwrap() == parent2.unwrap()
}

pub fn get_selected_path(state: &State) -> Option<String> {
    let mut iter = gtk::TreeIter::new().unwrap();

    let path = if state.tree_selection.get_selected(state.tree_model, &mut iter) {
        state.tree_model.get_value(&iter, 1).get_string()
    } else {
        None
    };

    iter.drop();
    path
}

pub fn create_data_dir() {
    let path = get_data_dir();
    if !path.exists() {
        match fs::mkdir(&path, ::std::io::USER_DIR) {
            Ok(_) => {},
            Err(e) => { println!("Error creating directory: {}", e) }
        };
    }
}

pub fn write_prefs(state: &State) {
    let prefs = get_prefs(state);
    let json_str = json::encode(&prefs);

    let prefs_path = get_prefs_file();
    let mut f = fs::File::create(&prefs_path);
    match f.write_str(json_str.as_slice()) {
        Ok(_) => {},
        Err(e) => println!("Error writing prefs: {}", e)
    };
}

pub fn read_prefs(state: &mut State) {
    let prefs_path = get_prefs_file();
    let mut f = fs::File::open(&prefs_path);
    let prefs_option : Option<Prefs> = match f.read_to_string() {
        Ok(json_str) => {
            match json::decode(json_str.as_slice()) {
                Ok(object) => Some(object),
                Err(e) => {
                    println!("Error decoding prefs: {}", e);
                    None
                }
            }
        },
        Err(_) => None
    };

    if let Some(prefs) = prefs_option {
        state.projects.clear();
        for path in prefs.projects.iter() {
            state.projects.insert(path.clone());
        }

        state.expansions.clear();
        for path in prefs.expansions.iter() {
            state.expansions.insert(path.clone());
        }

        state.selection = prefs.selection;
    }
}
<commit_msg>Save prefs with pretty printing<commit_after>use rgtk::*;
use serialize::{Encodable, json};
use std::collections::HashSet;
use std::io::fs;
use std::io::fs::PathExtensions;
use std::os::homedir;

pub struct State<'a> {
    pub projects: HashSet<String>,
    pub expansions: HashSet<String>,
    pub selection: Option<String>,
    pub tree_store: &'a gtk::TreeStore,
    pub tree_model: &'a gtk::TreeModel,
    pub tree_selection: &'a gtk::TreeSelection,
    pub rename_button: &'a gtk::Button,
    pub remove_button: &'a gtk::Button,
}

#[deriving(Decodable, Encodable)]
struct Prefs {
    projects: Vec<String>,
    expansions: Vec<String>,
    selection: Option<String>
}

fn get_data_dir() -> Path {
    let home = homedir();
    let mut path = match home {
        Some(p) => p,
        None => Path::new(".")
    };
    path.push(".solidoak");
    path
}

fn get_prefs_file() -> Path {
    let mut path = get_data_dir();
    path.push("prefs.json");
    path
}

fn get_prefs(state: &State) -> Prefs {
    Prefs {
        projects: state.projects.clone().into_iter().collect(),
        expansions: state.expansions.clone().into_iter().collect(),
        selection: state.selection.clone()
    }
}

pub fn are_siblings(path1: &String, path2: &String) -> bool {
    let parent_path1 = Path::new(path1).dir_path();
    let parent_path2 = Path::new(path2).dir_path();

    let parent1 = parent_path1.as_str();
    let parent2 = parent_path2.as_str();

    parent1.is_some() && parent2.is_some() &&
    parent1.unwrap() == parent2.unwrap()
}

pub fn get_selected_path(state: &State) -> Option<String> {
    let mut iter = gtk::TreeIter::new().unwrap();

    let path = if state.tree_selection.get_selected(state.tree_model, &mut iter) {
        state.tree_model.get_value(&iter, 1).get_string()
    } else {
        None
    };

    iter.drop();
    path
}

pub fn create_data_dir() {
    let path = get_data_dir();
    if !path.exists() {
        match fs::mkdir(&path, ::std::io::USER_DIR) {
            Ok(_) => {},
            Err(e) => { println!("Error creating directory: {}", e) }
        };
    }
}

pub fn write_prefs(state: &State) {
    let prefs = get_prefs(state);

    let mut buffer: Vec<u8> = Vec::new();
    {
        let mut encoder = json::PrettyEncoder::new(&mut buffer);
        prefs.encode(&mut encoder).ok().expect("Error encoding prefs.");
    }
    let json_str = String::from_utf8(buffer).unwrap();

    let prefs_path = get_prefs_file();
    let mut f = fs::File::create(&prefs_path);
    match f.write_str(json_str.as_slice()) {
        Ok(_) => {},
        Err(e) => println!("Error writing prefs: {}", e)
    };
}

pub fn read_prefs(state: &mut State) {
    let prefs_path = get_prefs_file();
    let mut f = fs::File::open(&prefs_path);
    let prefs_option : Option<Prefs> = match f.read_to_string() {
        Ok(json_str) => {
            match json::decode(json_str.as_slice()) {
                Ok(object) => Some(object),
                Err(e) => {
                    println!("Error decoding prefs: {}", e);
                    None
                }
            }
        },
        Err(_) => None
    };

    if let Some(prefs) = prefs_option {
        state.projects.clear();
        for path in prefs.projects.iter() {
            state.projects.insert(path.clone());
        }

        state.expansions.clear();
        for path in prefs.expansions.iter() {
            state.expansions.insert(path.clone());
        }

        state.selection = prefs.selection;
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::hash::Hash;

use parser::Spanning;
use ast::{InputValue, ToInputValue};

/// Serializable value returned from query and field execution.
///
/// Used by the execution engine and resolvers to build up the response
/// structure. Similar to the `Json` type found in the serialize crate.
///
/// It is also similar to the `InputValue` type, but can not contain enum
/// values or variables. Also, lists and objects do not contain any location
/// information since they are generated by resolving fields and values rather
/// than parsing a source query.
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub enum Value {
    Null,
    Int(i32),
    Float(f64),
    String(String),
    Boolean(bool),
    List(Vec<Value>),
    Object(HashMap<String, Value>),
}

impl Value {
    // CONSTRUCTORS

    /// Construct a null value.
    pub fn null() -> Value { Value::Null }

    /// Construct an integer value.
    pub fn int(i: i32) -> Value { Value::Int(i) }

    /// Construct a floating point value.
    pub fn float(f: f64) -> Value { Value::Float(f) }

    /// Construct a string value.
    pub fn string<T: AsRef<str>>(s: T) -> Value { Value::String(s.as_ref().to_owned()) }

    /// Construct a boolean value.
    pub fn boolean(b: bool) -> Value { Value::Boolean(b) }

    /// Construct a list value.
    pub fn list(l: Vec<Value>) -> Value { Value::List(l) }

    /// Construct an object value.
    pub fn object<K>(o: HashMap<K, Value>) -> Value
        where K: AsRef<str> + Eq + Hash
    {
        Value::Object(
            o.into_iter().map(|(k, v)| (k.as_ref().to_owned(), v)).collect()
        )
    }

    // DISCRIMINATORS

    /// Does this value represent null?
    pub fn is_null(&self) -> bool {
        match *self {
            Value::Null => true,
            _ => false,
        }
    }

    /// View the underlying object value, if present.
    pub fn as_object_value(&self) -> Option<&HashMap<String, Value>> {
        match *self {
            Value::Object(ref o) => Some(o),
            _ => None,
        }
    }

    /// Mutable view into the underlying object value, if present.
    pub fn as_mut_object_value(&mut self) -> Option<&mut HashMap<String, Value>> {
        match *self {
            Value::Object(ref mut o) => Some(o),
            _ => None,
        }
    }

    /// View the underlying list value, if present.
    pub fn as_list_value(&self) -> Option<&Vec<Value>> {
        match *self {
            Value::List(ref l) => Some(l),
            _ => None,
        }
    }

    /// View the underlying string value, if present.
    pub fn as_string_value(&self) -> Option<&str> {
        match *self {
            Value::String(ref s) => Some(s),
            _ => None,
        }
    }
}

impl ToInputValue for Value {
    fn to(&self) -> InputValue {
        match *self {
            Value::Null => InputValue::Null,
            Value::Int(i) => InputValue::Int(i),
            Value::Float(f) => InputValue::Float(f),
            Value::String(ref s) => InputValue::String(s.clone()),
            Value::Boolean(b) => InputValue::Boolean(b),
            Value::List(ref l) => InputValue::List(l.iter().map(|x|
                Spanning::unlocated(x.to())).collect()),
            Value::Object(ref o) => InputValue::Object(o.iter().map(|(k,v)|
                (Spanning::unlocated(k.clone()), Spanning::unlocated(v.to()))).collect()),
        }
    }
}
<commit_msg>Try to avoid cloning in Value::object<commit_after>use std::collections::HashMap;
use std::hash::Hash;

use parser::Spanning;
use ast::{InputValue, ToInputValue};

/// Serializable value returned from query and field execution.
///
/// Used by the execution engine and resolvers to build up the response
/// structure. Similar to the `Json` type found in the serialize crate.
///
/// It is also similar to the `InputValue` type, but can not contain enum
/// values or variables. Also, lists and objects do not contain any location
/// information since they are generated by resolving fields and values rather
/// than parsing a source query.
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub enum Value {
    Null,
    Int(i32),
    Float(f64),
    String(String),
    Boolean(bool),
    List(Vec<Value>),
    Object(HashMap<String, Value>),
}

impl Value {
    // CONSTRUCTORS

    /// Construct a null value.
    pub fn null() -> Value { Value::Null }

    /// Construct an integer value.
    pub fn int(i: i32) -> Value { Value::Int(i) }

    /// Construct a floating point value.
    pub fn float(f: f64) -> Value { Value::Float(f) }

    /// Construct a string value.
    pub fn string<T: AsRef<str>>(s: T) -> Value { Value::String(s.as_ref().to_owned()) }

    /// Construct a boolean value.
    pub fn boolean(b: bool) -> Value { Value::Boolean(b) }

    /// Construct a list value.
    pub fn list(l: Vec<Value>) -> Value { Value::List(l) }

    /// Construct an object value.
    pub fn object<K>(o: HashMap<K, Value>) -> Value
        where K: Into<String> + Eq + Hash
    {
        Value::Object(
            o.into_iter().map(|(k, v)| (k.into(), v)).collect()
        )
    }

    // DISCRIMINATORS

    /// Does this value represent null?
    pub fn is_null(&self) -> bool {
        match *self {
            Value::Null => true,
            _ => false,
        }
    }

    /// View the underlying object value, if present.
    pub fn as_object_value(&self) -> Option<&HashMap<String, Value>> {
        match *self {
            Value::Object(ref o) => Some(o),
            _ => None,
        }
    }

    /// Mutable view into the underlying object value, if present.
    pub fn as_mut_object_value(&mut self) -> Option<&mut HashMap<String, Value>> {
        match *self {
            Value::Object(ref mut o) => Some(o),
            _ => None,
        }
    }

    /// View the underlying list value, if present.
    pub fn as_list_value(&self) -> Option<&Vec<Value>> {
        match *self {
            Value::List(ref l) => Some(l),
            _ => None,
        }
    }

    /// View the underlying string value, if present.
    pub fn as_string_value(&self) -> Option<&str> {
        match *self {
            Value::String(ref s) => Some(s),
            _ => None,
        }
    }
}

impl ToInputValue for Value {
    fn to(&self) -> InputValue {
        match *self {
            Value::Null => InputValue::Null,
            Value::Int(i) => InputValue::Int(i),
            Value::Float(f) => InputValue::Float(f),
            Value::String(ref s) => InputValue::String(s.clone()),
            Value::Boolean(b) => InputValue::Boolean(b),
            Value::List(ref l) => InputValue::List(l.iter().map(|x|
                Spanning::unlocated(x.to())).collect()),
            Value::Object(ref o) => InputValue::Object(o.iter().map(|(k,v)|
                (Spanning::unlocated(k.clone()), Spanning::unlocated(v.to()))).collect()),
        }
    }
}
<|endoftext|>


<commit_before>use iron::prelude::*;
use maud::{Markup, PreEscaped, Render};
use pulldown_cmark;

use user::User;

static STYLES: &'static str = r#"
html {
    box-sizing: border-box;
    font: 100%/1.5 "Liberation Serif", "Times New Roman", serif;
    background: linear-gradient(to bottom, #445 0%, #001 100%);
}

@media (min-width: 450px) {
    html {
        font-size: 125%;
    }
}

@media (min-width: 750px) {
    html {
        font-size: 150%;
    }
}

input, button {
    font-size: 1rem;
    line-height: 1.5;
}

* {
    box-sizing: inherit;
}

body {
    margin: 0 auto;
    max-width: 30rem;
    min-height: 100vh;
    padding: 0.5rem 1.5rem;
    box-shadow: 0 0 0 8px #ccc, 0 0 0 16px #999, 0 0 0 20px #666;
    background: #fff;
}

a {
    text-decoration: none;
    color: #910;
}

a:hover, a:focus, a:active {
    text-shadow: 0 0 2px #fff, 0 0 8px #d60;
}

h1 {
    /* A E S T H E T I C */
    margin: 0 0 1rem;
    white-space: nowrap;
    font-family: "Comic Sans MS", sans-serif;
    font-size: 1.75rem;
    letter-spacing: 0.5rem;
}

@media (min-width: 600px) {
    h1 {
        font-size: 3rem;
        letter-spacing: 0.75rem;
    }
}

h1 a {
    color: #f90;
    text-transform: uppercase;
    text-shadow: 2px 2px #000, -2px -2px #faa;
    transition: text-shadow 0.2s;
}

h1 a:hover, h1 a:focus, h1 a:active {
    text-shadow: 16px 16px #000, -16px -16px #faa;
    transition: text-shadow 0.2s;
}

.karkinos {
    font-family: "Comic Sans MS", sans-serif;
}

#q {
    width: 100%;
    padding: 0.25rem 0.5rem;
    border: 1px solid #000;
    box-shadow: 0 0 0 0 #f90, 0 0 0 0 #666;
    transition: box-shadow 0.2s;
}

#q:focus {
    border-color: #f90;
    box-shadow: -2px -2px 0 2px #f90, 2px 2px 0 3px #666;
    transition: box-shadow 0.2s;
}

table {
    border-spacing: 0.5rem;
}

th {
    text-align: right;
    vertical-align: top;
}
"#;

pub fn layout(r: &Request, title: Option<&str>, body: Markup) -> Markup {
    let url = r.url.clone().into_generic_url();
    html! {
        (PreEscaped("<!DOCTYPE html>"))
        html {
            meta charset="utf-8" /
            title {
                @if let Some(title) = title {
                    (title) " - "
                }
                "Karkinos"
            }
            meta name="viewport" content="width=device-width" /
            style (PreEscaped(STYLES))
            body {
                h1 a href="/" "🦀Karkinos"
                @if let Some(title) = title {
                    h2 a href=(url.path()) title="Link to this page" (title)
                }
                (body)
            }
        }
    }
}

pub fn home(r: &Request) -> Markup {
    layout(r, None, html! {
        form action=(url_for!(r, "search")) {
            input name="q" id="q" type="search" placeholder="Enter a username" /
        }
        script (PreEscaped("document.getElementById('q').select()"))
        p {
            span.karkinos "KARKINOS"
            " is a database of people interested in the "
            a href="https://www.rust-lang.org" "Rust programming language"
            ". It uses the same data as "
            a href="http://rustaceans.org" "rustaceans.org"
            ", but presents it through a different interface."
        }
        p "I created Karkinos for these reasons:"
        ul {
            li "To provide access for users who browse with JavaScript disabled;"
            li "To rewrite the backend in Rust (instead of Node.js);"
            li {
                "As a proving ground for my template engine, "
                a href="https://github.com/lfairy/maud" "Maud"
                ";"
            }
            li "To screw around with CSS (this is the most important reason)."
        }
        p {
            "Karkinos is named after a very special "
            a href="https://en.wikipedia.org/wiki/Cancer_(constellation)#Names" "giant crab"
            "."
        }
        p {
            "The source code for this site can be found on "
            a href="https://github.com/lfairy/karkinos" "GitHub"
            "."
        }
    })
}

pub fn not_found(r: &Request) -> Markup {
    layout(r, Some("Not found"), html! {
        p {
            "The page at "
            strong (r.url)
            " could not be found."
        }
        p a href="/" "‹ Back to home page"
    })
}

pub fn user(r: &Request, id: &str, user: &User) -> Markup {
    let title = if let Some(ref name) = user.name {
        format!("{} ({})", name, id)
    } else {
        id.to_string()
    };
    layout(r, Some(&title), html! {
        table {
            @if let Some(ref nick) = user.irc {
                tr {
                    th "IRC"
                    td {
                        (nick)
                        @if !user.irc_channels.is_empty() {
                            " on "
                            @for (i, channel) in user.irc_channels.iter().enumerate() {
                                @if i > 0 { ", " }
                                a href={ "irc://irc.mozilla.org/" (channel) } {
                                    "#" (channel)
                                }
                            }
                        }
                    }
                }
            }
            @if let Some(ref x) = user.discourse {
                tr {
                    th "Discourse"
                    td a href={ "https://users.rust-lang.org/users/" (x) } (x)
                }
            }
            @if let Some(ref x) = user.reddit {
                tr {
                    th "Reddit"
                    td a href={ "https://reddit.com/user/" (x) } (x)
                }
            }
            @if let Some(ref x) = user.twitter {
                tr {
                    th "Twitter"
                    td a href={ "https://twitter.com/" (x) } (x)
                }
            }
            @if let Some(ref x) = user.website {
                tr {
                    th "Website"
                    td a href=(x) (x)
                }
            }
            @if let Some(ref x) = user.blog {
                tr {
                    th "Blog"
                    td a href=(x) (x)
                }
            }
            @if let Some(ref x) = user.email {
                tr {
                    th "Email"
                    td a href={ "mailto:" (x) } (x)
                }
            }
        }
        @if let Some(ref x) = user.notes {
            div.notes (Markdown(x))
        }
    })
}

pub fn user_not_found(r: &Request, id: &str) -> Markup {
    layout(r, Some(id), html! {
        p {
            "The user "
            strong (id)
            " could not be found."
        }
        p a href="/" "<< Back to home page"
    })
}

struct Markdown<'a>(&'a str);

impl<'a> Render for Markdown<'a> {
    fn render_to(&self, buffer: &mut String) {
        let parser = pulldown_cmark::Parser::new(self.0);
        pulldown_cmark::html::push_html(buffer, parser);
    }
}
<commit_msg>De-uglify the "user not found" page as well<commit_after>use iron::prelude::*;
use maud::{Markup, PreEscaped, Render};
use pulldown_cmark;

use user::User;

static STYLES: &'static str = r#"
html {
    box-sizing: border-box;
    font: 100%/1.5 "Liberation Serif", "Times New Roman", serif;
    background: linear-gradient(to bottom, #445 0%, #001 100%);
}

@media (min-width: 450px) {
    html {
        font-size: 125%;
    }
}

@media (min-width: 750px) {
    html {
        font-size: 150%;
    }
}

input, button {
    font-size: 1rem;
    line-height: 1.5;
}

* {
    box-sizing: inherit;
}

body {
    margin: 0 auto;
    max-width: 30rem;
    min-height: 100vh;
    padding: 0.5rem 1.5rem;
    box-shadow: 0 0 0 8px #ccc, 0 0 0 16px #999, 0 0 0 20px #666;
    background: #fff;
}

a {
    text-decoration: none;
    color: #910;
}

a:hover, a:focus, a:active {
    text-shadow: 0 0 2px #fff, 0 0 8px #d60;
}

h1 {
    /* A E S T H E T I C */
    margin: 0 0 1rem;
    white-space: nowrap;
    font-family: "Comic Sans MS", sans-serif;
    font-size: 1.75rem;
    letter-spacing: 0.5rem;
}

@media (min-width: 600px) {
    h1 {
        font-size: 3rem;
        letter-spacing: 0.75rem;
    }
}

h1 a {
    color: #f90;
    text-transform: uppercase;
    text-shadow: 2px 2px #000, -2px -2px #faa;
    transition: text-shadow 0.2s;
}

h1 a:hover, h1 a:focus, h1 a:active {
    text-shadow: 16px 16px #000, -16px -16px #faa;
    transition: text-shadow 0.2s;
}

.karkinos {
    font-family: "Comic Sans MS", sans-serif;
}

#q {
    width: 100%;
    padding: 0.25rem 0.5rem;
    border: 1px solid #000;
    box-shadow: 0 0 0 0 #f90, 0 0 0 0 #666;
    transition: box-shadow 0.2s;
}

#q:focus {
    border-color: #f90;
    box-shadow: -2px -2px 0 2px #f90, 2px 2px 0 3px #666;
    transition: box-shadow 0.2s;
}

table {
    border-spacing: 0.5rem;
}

th {
    text-align: right;
    vertical-align: top;
}
"#;

pub fn layout(r: &Request, title: Option<&str>, body: Markup) -> Markup {
    let url = r.url.clone().into_generic_url();
    html! {
        (PreEscaped("<!DOCTYPE html>"))
        html {
            meta charset="utf-8" /
            title {
                @if let Some(title) = title {
                    (title) " - "
                }
                "Karkinos"
            }
            meta name="viewport" content="width=device-width" /
            style (PreEscaped(STYLES))
            body {
                h1 a href="/" "🦀Karkinos"
                @if let Some(title) = title {
                    h2 a href=(url.path()) title="Link to this page" (title)
                }
                (body)
            }
        }
    }
}

pub fn home(r: &Request) -> Markup {
    layout(r, None, html! {
        form action=(url_for!(r, "search")) {
            input name="q" id="q" type="search" placeholder="Enter a username" /
        }
        script (PreEscaped("document.getElementById('q').select()"))
        p {
            span.karkinos "KARKINOS"
            " is a database of people interested in the "
            a href="https://www.rust-lang.org" "Rust programming language"
            ". It uses the same data as "
            a href="http://rustaceans.org" "rustaceans.org"
            ", but presents it through a different interface."
        }
        p "I created Karkinos for these reasons:"
        ul {
            li "To provide access for users who browse with JavaScript disabled;"
            li "To rewrite the backend in Rust (instead of Node.js);"
            li {
                "As a proving ground for my template engine, "
                a href="https://github.com/lfairy/maud" "Maud"
                ";"
            }
            li "To screw around with CSS (this is the most important reason)."
        }
        p {
            "Karkinos is named after a very special "
            a href="https://en.wikipedia.org/wiki/Cancer_(constellation)#Names" "giant crab"
            "."
        }
        p {
            "The source code for this site can be found on "
            a href="https://github.com/lfairy/karkinos" "GitHub"
            "."
        }
    })
}

pub fn not_found(r: &Request) -> Markup {
    layout(r, Some("Not found"), html! {
        p {
            "The page at "
            strong (r.url)
            " could not be found."
        }
        p a href="/" "‹ Back to home page"
    })
}

pub fn user(r: &Request, id: &str, user: &User) -> Markup {
    let title = if let Some(ref name) = user.name {
        format!("{} ({})", name, id)
    } else {
        id.to_string()
    };
    layout(r, Some(&title), html! {
        table {
            @if let Some(ref nick) = user.irc {
                tr {
                    th "IRC"
                    td {
                        (nick)
                        @if !user.irc_channels.is_empty() {
                            " on "
                            @for (i, channel) in user.irc_channels.iter().enumerate() {
                                @if i > 0 { ", " }
                                a href={ "irc://irc.mozilla.org/" (channel) } {
                                    "#" (channel)
                                }
                            }
                        }
                    }
                }
            }
            @if let Some(ref x) = user.discourse {
                tr {
                    th "Discourse"
                    td a href={ "https://users.rust-lang.org/users/" (x) } (x)
                }
            }
            @if let Some(ref x) = user.reddit {
                tr {
                    th "Reddit"
                    td a href={ "https://reddit.com/user/" (x) } (x)
                }
            }
            @if let Some(ref x) = user.twitter {
                tr {
                    th "Twitter"
                    td a href={ "https://twitter.com/" (x) } (x)
                }
            }
            @if let Some(ref x) = user.website {
                tr {
                    th "Website"
                    td a href=(x) (x)
                }
            }
            @if let Some(ref x) = user.blog {
                tr {
                    th "Blog"
                    td a href=(x) (x)
                }
            }
            @if let Some(ref x) = user.email {
                tr {
                    th "Email"
                    td a href={ "mailto:" (x) } (x)
                }
            }
        }
        @if let Some(ref x) = user.notes {
            div.notes (Markdown(x))
        }
    })
}

pub fn user_not_found(r: &Request, id: &str) -> Markup {
    layout(r, Some(id), html! {
        p {
            "The user "
            strong (id)
            " could not be found."
        }
        p a href="/" "‹ Back to home page"
    })
}

struct Markdown<'a>(&'a str);

impl<'a> Render for Markdown<'a> {
    fn render_to(&self, buffer: &mut String) {
        let parser = pulldown_cmark::Parser::new(self.0);
        pulldown_cmark::html::push_html(buffer, parser);
    }
}
<|endoftext|>


<commit_before>extern crate router;
extern crate persistent;

use std::io::Read;

use iron::prelude::*;
use iron::status;
use router::Router;
use rustc_serialize::json::{self, Json};

use super::{Globals, Index, Mapping, Document, query};

fn index_not_found_response() -> Response {
    let mut response = Response::with((status::NotFound, "{\"message\": \"Index not found\"}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    return response;
}

pub fn view_home(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "Hello World!")))
}

pub fn view_count(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

    // Lock index array
    let indices = glob.indices.lock().unwrap();

    // Find index
    let index = match indices.get(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Load query from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let data = if !payload.is_empty() {
        Some(match Json::from_str(&payload) {
            Ok(data) => data,
            Err(error) => {
                // TODO: What specifically is bad about the JSON?
                let mut response = Response::with((status::BadRequest,
                                                   "{\"message\": \"Couldn't parse JSON\"}"));
                response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                return Ok(response);
            }
        })
    } else {
        None
    };

    println!("{:?}", query::parse_query(data.unwrap().as_object().unwrap().get("query").unwrap()));

    // TODO: Run query

    // Temporary count and return numbers
    let mut count = 0;
    for mapping in index.mappings.values() {
        count += mapping.docs.len();
    }

    let mut response = Response::with((status::Ok, format!("{{\"count\": {}}}", count)));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_search(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

    // Lock index array
    let indices = glob.indices.lock().unwrap();

    // Find index
    let index = match indices.get(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Load query from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let data = if !payload.is_empty() {
        Some(match Json::from_str(&payload) {
            Ok(data) => data,
            Err(error) => {
                // TODO: What specifically is bad about the JSON?
                let mut response = Response::with((status::BadRequest,
                                                   "{\"message\": \"Couldn't parse JSON\"}"));
                response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                return Ok(response);
            }
        })
    } else {
        None
    };

    println!("{:?}", query::parse_query(data.unwrap().as_object().unwrap().get("query").unwrap()));

    // TODO: Run query

    let mut response = Response::with((status::Ok, "{\"hits\": {\"total\": 0, \"hits\": []}}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_get_doc(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
    let mapping_name = req.extensions.get::<Router>().unwrap().find("mapping").unwrap_or("");
    let doc_id = req.extensions.get::<Router>().unwrap().find("doc").unwrap_or("");

    // Lock index array
    let indices = glob.indices.lock().unwrap();

    // Find index
    let index = match indices.get(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Find mapping
    let mapping = match index.mappings.get(mapping_name) {
        Some(mapping) => mapping,
        None => {
            let mut response = Response::with((status::NotFound,
                                               "{\"message\": \"Mapping not found\"}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            return Ok(response);
        }
    };

    // Find document
    let doc = match mapping.docs.get(doc_id) {
        Some(doc) => doc,
        None => {
            let mut response = Response::with((status::NotFound,
                                               "{\"message\": \"Document not found\"}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            return Ok(response);
        }
    };

    let mut response = Response::with((status::Ok, json::encode(&doc.data).unwrap()));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_put_doc(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
    let mapping_name = req.extensions.get::<Router>().unwrap().find("mapping").unwrap_or("");
    let ref doc_id = req.extensions.get::<Router>().unwrap().find("doc").unwrap_or("");

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    // Find index
    let mut index = match indices.get_mut(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Find mapping
    let mut mapping = match index.mappings.get_mut(mapping_name) {
        Some(mapping) => mapping,
        None => {
            let mut response = Response::with((status::NotFound,
                                               "{\"message\": \"Mapping not found\"}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            return Ok(response);
        }
    };

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let data = if !payload.is_empty() {
        Some(match Json::from_str(&payload) {
            Ok(data) => data,
            Err(error) => {
                // TODO: What specifically is bad about the JSON?
                let mut response = Response::with((status::BadRequest,
                                                   "{\"message\": \"Couldn't parse JSON\"}"));
                response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                return Ok(response);
            }
        })
    } else {
        None
    };

    // Create and insert document
    if let Some(data) = data {
        let doc = Document::from_json(data);
        mapping.docs.insert(doc_id.clone().to_owned(), doc);
    }

    let mut response = Response::with((status::Ok, "{}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_put_index(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let ref index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let data = if !payload.is_empty() {
        Some(match Json::from_str(&payload) {
            Ok(data) => data,
            Err(error) => {
                // TODO: What specifically is bad about the JSON?
                let mut response = Response::with((status::BadRequest,
                                                   "{\"message\": \"Couldn't parse JSON\"}"));
                response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                return Ok(response);
            }
        })
    } else {
        None
    };

    // Create index
    indices.insert(index_name.clone().to_owned(), Index::new());

    let mut response = Response::with((status::Ok, "{\"acknowledged\": true}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_put_mapping(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
    let ref mapping_name = req.extensions.get::<Router>().unwrap().find("mapping").unwrap_or("");

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    // Find index
    let mut index = match indices.get_mut(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    if payload.is_empty() {
        // TODO: Better error
        let mut response = Response::with((status::Ok, "{\"acknowledged\": false}"));
        response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
        return Ok(response)
    }

    let data = match Json::from_str(&payload) {
        Ok(data) => data,
        Err(error) => {
            // TODO: What specifically is bad about the JSON?
            let mut response = Response::with((status::BadRequest,
                                               "{\"message\": \"Couldn't parse JSON\"}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            return Ok(response);
        }
    };

    let data = data.as_object().unwrap().get(*mapping_name).unwrap();

    // Insert mapping
    let mapping = Mapping::from_json(&data);
    println!("{:#?}", mapping);
    index.mappings.insert(mapping_name.clone().to_owned(), mapping);

    let mut response = Response::with((status::Ok, "{\"acknowledged\": true}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_post_bulk(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    for payload_part in payload.split('\n') {
        let data = if !payload.is_empty() {
            Some(Json::from_str(&payload))
        } else {
            None
        };
    }

    let mut response = Response::with((status::Ok, "{\"acknowledged\": true}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn get_router() -> Router {
    router!(get "/" => view_home,
            get "/:index/_count" => view_count,
            get "/:index/_search" => view_search,
            get "/:index/:mapping/:doc" => view_get_doc,
            put "/:index/:mapping/:doc" => view_put_doc,
            put "/:index" => view_put_index,
            put "/:index/_mapping/:mapping" => view_put_mapping,
            post "/_bulk" => view_post_bulk)
}
<commit_msg>Pretty print query debug<commit_after>extern crate router;
extern crate persistent;

use std::io::Read;

use iron::prelude::*;
use iron::status;
use router::Router;
use rustc_serialize::json::{self, Json};

use super::{Globals, Index, Mapping, Document, query};

fn index_not_found_response() -> Response {
    let mut response = Response::with((status::NotFound, "{\"message\": \"Index not found\"}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    return response;
}

pub fn view_home(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "Hello World!")))
}

pub fn view_count(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

    // Lock index array
    let indices = glob.indices.lock().unwrap();

    // Find index
    let index = match indices.get(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Load query from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let data = if !payload.is_empty() {
        Some(match Json::from_str(&payload) {
            Ok(data) => data,
            Err(error) => {
                // TODO: What specifically is bad about the JSON?
                let mut response = Response::with((status::BadRequest,
                                                   "{\"message\": \"Couldn't parse JSON\"}"));
                response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                return Ok(response);
            }
        })
    } else {
        None
    };

    println!("{:#?}", query::parse_query(data.unwrap().as_object().unwrap().get("query").unwrap()));

    // TODO: Run query

    // Temporary count and return numbers
    let mut count = 0;
    for mapping in index.mappings.values() {
        count += mapping.docs.len();
    }

    let mut response = Response::with((status::Ok, format!("{{\"count\": {}}}", count)));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_search(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

    // Lock index array
    let indices = glob.indices.lock().unwrap();

    // Find index
    let index = match indices.get(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Load query from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let data = if !payload.is_empty() {
        Some(match Json::from_str(&payload) {
            Ok(data) => data,
            Err(error) => {
                // TODO: What specifically is bad about the JSON?
                let mut response = Response::with((status::BadRequest,
                                                   "{\"message\": \"Couldn't parse JSON\"}"));
                response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                return Ok(response);
            }
        })
    } else {
        None
    };

    println!("{:#?}", query::parse_query(data.unwrap().as_object().unwrap().get("query").unwrap()));

    // TODO: Run query

    let mut response = Response::with((status::Ok, "{\"hits\": {\"total\": 0, \"hits\": []}}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_get_doc(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
    let mapping_name = req.extensions.get::<Router>().unwrap().find("mapping").unwrap_or("");
    let doc_id = req.extensions.get::<Router>().unwrap().find("doc").unwrap_or("");

    // Lock index array
    let indices = glob.indices.lock().unwrap();

    // Find index
    let index = match indices.get(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Find mapping
    let mapping = match index.mappings.get(mapping_name) {
        Some(mapping) => mapping,
        None => {
            let mut response = Response::with((status::NotFound,
                                               "{\"message\": \"Mapping not found\"}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            return Ok(response);
        }
    };

    // Find document
    let doc = match mapping.docs.get(doc_id) {
        Some(doc) => doc,
        None => {
            let mut response = Response::with((status::NotFound,
                                               "{\"message\": \"Document not found\"}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            return Ok(response);
        }
    };

    let mut response = Response::with((status::Ok, json::encode(&doc.data).unwrap()));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_put_doc(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
    let mapping_name = req.extensions.get::<Router>().unwrap().find("mapping").unwrap_or("");
    let ref doc_id = req.extensions.get::<Router>().unwrap().find("doc").unwrap_or("");

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    // Find index
    let mut index = match indices.get_mut(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Find mapping
    let mut mapping = match index.mappings.get_mut(mapping_name) {
        Some(mapping) => mapping,
        None => {
            let mut response = Response::with((status::NotFound,
                                               "{\"message\": \"Mapping not found\"}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            return Ok(response);
        }
    };

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let data = if !payload.is_empty() {
        Some(match Json::from_str(&payload) {
            Ok(data) => data,
            Err(error) => {
                // TODO: What specifically is bad about the JSON?
                let mut response = Response::with((status::BadRequest,
                                                   "{\"message\": \"Couldn't parse JSON\"}"));
                response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                return Ok(response);
            }
        })
    } else {
        None
    };

    // Create and insert document
    if let Some(data) = data {
        let doc = Document::from_json(data);
        mapping.docs.insert(doc_id.clone().to_owned(), doc);
    }

    let mut response = Response::with((status::Ok, "{}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_put_index(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let ref index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let data = if !payload.is_empty() {
        Some(match Json::from_str(&payload) {
            Ok(data) => data,
            Err(error) => {
                // TODO: What specifically is bad about the JSON?
                let mut response = Response::with((status::BadRequest,
                                                   "{\"message\": \"Couldn't parse JSON\"}"));
                response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
                return Ok(response);
            }
        })
    } else {
        None
    };

    // Create index
    indices.insert(index_name.clone().to_owned(), Index::new());

    let mut response = Response::with((status::Ok, "{\"acknowledged\": true}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_put_mapping(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // URL parameters
    let index_name = req.extensions.get::<Router>().unwrap().find("index").unwrap_or("");
    let ref mapping_name = req.extensions.get::<Router>().unwrap().find("mapping").unwrap_or("");

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    // Find index
    let mut index = match indices.get_mut(index_name) {
        Some(index) => index,
        None => {
            return Ok(index_not_found_response());
        }
    };

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    if payload.is_empty() {
        // TODO: Better error
        let mut response = Response::with((status::Ok, "{\"acknowledged\": false}"));
        response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
        return Ok(response)
    }

    let data = match Json::from_str(&payload) {
        Ok(data) => data,
        Err(error) => {
            // TODO: What specifically is bad about the JSON?
            let mut response = Response::with((status::BadRequest,
                                               "{\"message\": \"Couldn't parse JSON\"}"));
            response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
            return Ok(response);
        }
    };

    let data = data.as_object().unwrap().get(*mapping_name).unwrap();

    // Insert mapping
    let mapping = Mapping::from_json(&data);
    println!("{:#?}", mapping);
    index.mappings.insert(mapping_name.clone().to_owned(), mapping);

    let mut response = Response::with((status::Ok, "{\"acknowledged\": true}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn view_post_bulk(req: &mut Request) -> IronResult<Response> {
    let ref glob = req.get::<persistent::Read<Globals>>().unwrap();

    // Lock index array
    let mut indices = glob.indices.lock().unwrap();

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    for payload_part in payload.split('\n') {
        let data = if !payload.is_empty() {
            Some(Json::from_str(&payload))
        } else {
            None
        };
    }

    let mut response = Response::with((status::Ok, "{\"acknowledged\": true}"));
    response.headers.set_raw("Content-Type", vec![b"application/json".to_vec()]);
    Ok(response)
}

pub fn get_router() -> Router {
    router!(get "/" => view_home,
            get "/:index/_count" => view_count,
            get "/:index/_search" => view_search,
            get "/:index/:mapping/:doc" => view_get_doc,
            put "/:index/:mapping/:doc" => view_put_doc,
            put "/:index" => view_put_index,
            put "/:index/_mapping/:mapping" => view_put_mapping,
            post "/_bulk" => view_post_bulk)
}
<|endoftext|>