<commit_before>use std::str;
use nom::{IResult,HexDisplay};
use ssh_parser::ssh;

use rparser::{RParser,R_STATUS_OK,R_STATUS_FAIL};

enum SSHConnectionState {
    Start,
    ClientIdent,
    ServerIdent,
    Next,

    Error
}

pub struct SSHParser<'a> {
    _name: Option<&'a[u8]>,

    state: SSHConnectionState,
}

impl<'a> SSHParser<'a> {
    pub fn new(name: &'a[u8]) -> SSHParser<'a> {
        SSHParser{
            _name: Some(name),
            state: SSHConnectionState::Start,
        }
    }

    fn parse_ident(&mut self, i: &[u8]) -> u32 {
        match ssh::parse_ssh_identification(i) {
            IResult::Done(rem,(ref crap, ref res)) => {
                // In version 2.0, the SSH server is allowed to send an arbitrary number of
                // UTF-8 lines before the final identification line containing the server
                // version.
                if crap.len() > 0 {
                    info!("Extra lines before SSH version:");
                    for line in crap.iter() {
                        info!("{}", line.to_hex(16));
                    }
                }
                debug!("parse_ssh: {:?}",res);
                self.state = match self.state {
                    SSHConnectionState::Start       => SSHConnectionState::ClientIdent,
                    SSHConnectionState::ClientIdent => SSHConnectionState::ServerIdent,
                    _ => { return R_STATUS_FAIL; },
                };
                info!("protocol\n{}", res.proto.to_hex(16));
                info!("software\n{}", res.software.to_hex(16));
            },
            e @ _ => warn!("parse_ssh: {:?}",e),
        };
        R_STATUS_OK
    }

    fn parse_packet(&mut self, i: &[u8]) -> u32 {
        match ssh::parse_ssh_packet(i) {
            IResult::Done(rem,ref res) => {
                debug!("parse_ssh: {:?}",res);
            },
            e @ _ => warn!("parse_ssh: {:?}",e),
        };
        R_STATUS_OK
    }
}

impl<'a> RParser for SSHParser<'a> {
    fn parse(&mut self, i: &[u8], _direction: u8) -> u32 {
        match self.state {
            SSHConnectionState::Start |
            SSHConnectionState::ClientIdent  => self.parse_ident(i),
            SSHConnectionState::ServerIdent |
            SSHConnectionState::Next         => self.parse_packet(i),
            SSHConnectionState::Error        => R_STATUS_FAIL,
        }
    }
}

pub fn ssh_probe(i: &[u8]) -> bool {
    if i.len() <= 2 { return false; }
    true
}

<commit_msg>SSH: split defragmentation buffers to client/server<commit_after>use std::str;
use nom::{IResult,HexDisplay};
use ssh_parser::ssh;

use rparser::{RParser,R_STATUS_OK,R_STATUS_FAIL};

enum SSHConnectionState {
    Start,
    ClientIdent,
    ServerIdent,
    Next,

    Error
}

pub struct SSHParser<'a> {
    _name: Option<&'a[u8]>,

    state: SSHConnectionState,
    buffer_clt: Vec<u8>,
    buffer_srv: Vec<u8>,
}

impl<'a> SSHParser<'a> {
    pub fn new(name: &'a[u8]) -> SSHParser<'a> {
        SSHParser{
            _name: Some(name),
            state: SSHConnectionState::Start,
            buffer_clt: Vec::new(),
            buffer_srv: Vec::new(),
        }
    }

    fn parse_ident(&mut self, i: &[u8]) -> u32 {
        match ssh::parse_ssh_identification(i) {
            IResult::Done(rem,(ref crap, ref res)) => {
                // In version 2.0, the SSH server is allowed to send an arbitrary number of
                // UTF-8 lines before the final identification line containing the server
                // version.
                if crap.len() > 0 {
                    info!("Extra lines before SSH version:");
                    for line in crap.iter() {
                        info!("{}", line.to_hex(16));
                    }
                }
                debug!("parse_ssh_identification: {:?}",res);
                self.state = match self.state {
                    SSHConnectionState::Start       => SSHConnectionState::ClientIdent,
                    SSHConnectionState::ClientIdent => SSHConnectionState::ServerIdent,
                    _ => { return R_STATUS_FAIL; },
                };
                info!("protocol\n{}", res.proto.to_hex(16));
                info!("software\n{}", res.software.to_hex(16));
            },
            e @ _ => {
                warn!("parse_ssh_identification: {:?}",e);
                self.state = SSHConnectionState::Error;
            },
        };
        R_STATUS_OK
    }

    fn parse_packet(&mut self, i: &[u8], direction:u8) -> u32 {
        debug!("parse_ssh_packet direction: {}", direction);
        debug!("\tbuffer_clt size: {}", self.buffer_clt.len());
        debug!("\tbuffer_srv size: {}", self.buffer_srv.len());
        let mut v : Vec<u8>;
        // Check if a record is being defragmented
        let self_buffer =
            if direction == 0 { &mut self.buffer_srv }
            else { &mut self.buffer_clt };
        let buf = match self_buffer.len() {
            0 => i,
            _ => {
                v = self_buffer.split_off(0);
                v.extend_from_slice(i);
                v.as_slice()
            },
        };
        // info!("parsing:\n{}", buf.to_hex(16));
        match ssh::parse_ssh_packet(buf) {
            IResult::Done(rem,ref res) => {
                debug!("parse_ssh_packet: {:?}",res);
            },
            IResult::Incomplete(_e) => {
                debug!("Defragmentation required (SSH packet): {:?}", _e);
                self_buffer.extend_from_slice(buf);
            },
            e @ _ => {
                warn!("parse_ssh_packet: {:?}",e);
                self.state = SSHConnectionState::Error;
            },
        };
        // info!("after parsing:\n{}", self_buffer.to_hex(16));
        R_STATUS_OK
    }
}

impl<'a> RParser for SSHParser<'a> {
    fn parse(&mut self, i: &[u8], direction: u8) -> u32 {
        match self.state {
            SSHConnectionState::Start |
            SSHConnectionState::ClientIdent  => self.parse_ident(i),
            SSHConnectionState::ServerIdent |
            SSHConnectionState::Next         => self.parse_packet(i,direction),
            SSHConnectionState::Error        => R_STATUS_FAIL,
        }
    }
}

pub fn ssh_probe(i: &[u8]) -> bool {
    if i.len() <= 2 { return false; }
    true
}

<|endoftext|>


<commit_before>use chrono::Utc;
use crate::client::Context;
use crate::model::id::{ChannelId, GuildId, UserId};
use std::{
    collections::HashMap,
    default::Default
};

#[cfg(feature = "cache")]
type Check = dyn Fn(&mut Context, Option<GuildId>, ChannelId, UserId) -> bool + Send + Sync + 'static;

#[cfg(not(feature = "cache"))]
type Check = Fn(&mut Context, ChannelId, UserId) -> bool + Send + Sync + 'static;

pub(crate) struct Ratelimit {
    pub delay: i64,
    pub limit: Option<(i64, i32)>,
}

#[derive(Default)]
pub(crate) struct MemberRatelimit {
    pub last_time: i64,
    pub set_time: i64,
    pub tickets: i32,
}

pub(crate) struct Bucket {
    pub ratelimit: Ratelimit,
    pub users: HashMap<u64, MemberRatelimit>,
    pub check: Option<Box<Check>>,
}

impl Bucket {
    pub fn take(&mut self, user_id: u64) -> i64 {
        let time = Utc::now().timestamp();
        let user = self.users
            .entry(user_id)
            .or_insert_with(MemberRatelimit::default);

        if let Some((timespan, limit)) = self.ratelimit.limit {
            if (user.tickets + 1) > limit {
                if time < (user.set_time + timespan) {
                    return (user.set_time + timespan) - time;
                } else {
                    user.tickets = 0;
                    user.set_time = time;
                }
            }
        }

        if time < user.last_time + self.ratelimit.delay {
            (user.last_time + self.ratelimit.delay) - time
        } else {
            user.tickets += 1;
            user.last_time = time;

            0
        }
    }
}
<commit_msg>Add a missing `dyn`<commit_after>use chrono::Utc;
use crate::client::Context;
use crate::model::id::{ChannelId, GuildId, UserId};
use std::{
    collections::HashMap,
    default::Default
};

#[cfg(feature = "cache")]
type Check = dyn Fn(&mut Context, Option<GuildId>, ChannelId, UserId) -> bool + Send + Sync + 'static;

#[cfg(not(feature = "cache"))]
type Check = dyn Fn(&mut Context, ChannelId, UserId) -> bool + Send + Sync + 'static;

pub(crate) struct Ratelimit {
    pub delay: i64,
    pub limit: Option<(i64, i32)>,
}

#[derive(Default)]
pub(crate) struct MemberRatelimit {
    pub last_time: i64,
    pub set_time: i64,
    pub tickets: i32,
}

pub(crate) struct Bucket {
    pub ratelimit: Ratelimit,
    pub users: HashMap<u64, MemberRatelimit>,
    pub check: Option<Box<Check>>,
}

impl Bucket {
    pub fn take(&mut self, user_id: u64) -> i64 {
        let time = Utc::now().timestamp();
        let user = self.users
            .entry(user_id)
            .or_insert_with(MemberRatelimit::default);

        if let Some((timespan, limit)) = self.ratelimit.limit {
            if (user.tickets + 1) > limit {
                if time < (user.set_time + timespan) {
                    return (user.set_time + timespan) - time;
                } else {
                    user.tickets = 0;
                    user.set_time = time;
                }
            }
        }

        if time < user.last_time + self.ratelimit.delay {
            (user.last_time + self.ratelimit.delay) - time
        } else {
            user.tickets += 1;
            user.last_time = time;

            0
        }
    }
}
<|endoftext|>


<commit_before>use num::Num;
use ncast::*;
use funs::exp::*;
use funs::trig::*;
use matrix::Mat4;

fn mat4_from_rotation<T:Copy Num NumCast Exp Trig>(axis: Vec3<T>, angle: T) -> Mat4<T> {
    let angle_rad = radians(&angle);
    let c = cos(&angle_rad);
    let s = sin(&angle_rad);

    let _0: T = cast(0);
    let _1: T = cast(1);
    let t = _1 - c;

    Mat4::new(t * axis.x * axis.x + c,          t * axis.x * axis.y + s * axis.z, t * axis.x * axis.z - s * axis.y, _0,
              t * axis.x * axis.y - s * axis.z, t * axis.y * axis.y + c,          t * axis.y * axis.z + s * axis.x, _0,
              t * axis.x * axis.z - s - axis.y, t * axis.y * axis.z - s * axis.x, t * axis.z * axis.z + c,          _0,
              _0, _0, _0, _1)
}<commit_msg>Fix function visibility<commit_after>use num::Num;
use ncast::*;
use funs::exp::*;
use funs::trig::*;
use matrix::Mat4;

pub fn mat4_from_rotation<T:Copy Num NumCast Exp Trig>(angle: T, axis: Vec3<T>) -> Mat4<T> {
    let angle_rad = radians(&angle);
    let c = cos(&angle_rad);
    let s = sin(&angle_rad);

    let _0: T = cast(0);
    let _1: T = cast(1);
    let t = _1 - c;

    Mat4::new(t * axis.x * axis.x + c,          t * axis.x * axis.y + s * axis.z, t * axis.x * axis.z - s * axis.y, _0,
              t * axis.x * axis.y - s * axis.z, t * axis.y * axis.y + c,          t * axis.y * axis.z + s * axis.x, _0,
              t * axis.x * axis.z - s - axis.y, t * axis.y * axis.z - s * axis.x, t * axis.z * axis.z + c,          _0,
              _0, _0, _0, _1)
}<|endoftext|>


<commit_before>//! ULP distance

use std::mem;
use std::num::{Float, Int};

use {Eq, Ulp};

/// Float distance in ULPs
pub trait Distance: Float {
    type Ulp: Int;

    /// Returns the absolute distance between two floats in ULPs
    fn distance(&self, &Self) -> Option<Self::Ulp>;
}

impl Distance for f32 {
    type Ulp = i32;

    fn distance(&self, rhs: &f32) -> Option<i32> {
        let &lhs = self;
        let &rhs = rhs;

        if lhs.is_nan() || rhs.is_nan() {
            // ULP idstance doesn't make sense for `NaN`s
            None
        } else {
            let lhs: i32 = unsafe {
                mem::transmute(lhs)
            };
            let rhs: i32 = unsafe {
                mem::transmute(rhs)
            };

            if lhs >> 31 != rhs >> 31 {
                // ULP distance will overflow if the sign bit doesn't match
                None
            } else {
                Some(
                    if lhs > rhs {
                        lhs - rhs
                    } else {
                        rhs - lhs
                    }
                )
            }
        }
    }
}

impl Distance for f64 {
    type Ulp = i64;

    fn distance(&self, rhs: &f64) -> Option<i64> {
        let &lhs = self;
        let &rhs = rhs;

        if lhs.is_nan() || rhs.is_nan() {
            // ULP idstance doesn't make sense for `NaN`s
            None
        } else {
            let ilhs: i64 = unsafe {
                mem::transmute(lhs)
            };
            let irhs: i64 = unsafe {
                mem::transmute(rhs)
            };

            if ilhs >> 63 != irhs >> 63 {
                // ULP distance will overflow if the sign bit doesn't match
                None
            } else {
                Some(
                    if ilhs > irhs {
                        ilhs - irhs
                    } else {
                        irhs - ilhs
                    }
                )
            }
        }
    }
}

impl<T: Distance> Eq<Ulp<T::Ulp>> for T {
    fn approx_eq(&self, rhs: &T, tol: Ulp<T::Ulp>) -> bool {
        let lhs = self;

        match lhs.distance(rhs) {
            Some(diff) => {
                diff <= tol.0
            },
            None => {
                // Check for `0 == -0`, if any side is a `NaN` this returns false
                lhs == rhs
            },
        }
    }
}

macro_rules! test {
    ($float:ident, $int:ident) => {
        mod $float {
            /// Given:
            /// - `x`: any float (minus `NaN`)
            /// - `tol`: any tolerance >= 0
            ///
            /// Test that `x.approx_eq(NaN)` is always false
            #[quickcheck]
            fn nan(x: $float, n: $int) -> bool {
                let tol = ::Ulp::tol(if n > 0 { n } else { -n });

                let zero: $float = 0.;
                let nan = zero / zero;

                !::eq(&nan, &x, tol) && !::eq(&x, &nan, tol)
            }

            /// Given:
            /// - `x`: any float (minus `NaN`)
            /// - `tol`: any tolerance >= 0
            ///
            /// Test that `x.approx_eq(x)` is always true
            #[quickcheck]
            fn same(x: $float, n: $int) -> bool {
                let tol = ::Ulp::tol(if n > 0 { n } else { -n });

                ::eq(&x, &x, tol)
            }

            /// Given:
            /// - `tol`: any tolerance >= 0
            ///
            /// Test that `NaN.approx_eq(NaN)` is always false
            #[quickcheck]
            fn nan_nan(n: $int) -> bool {
                let tol = ::Ulp::tol(if n > 0 { n } else { -n });

                let zero: $float = 0.;
                let nan = zero / zero;

                !::eq(&nan, &nan, tol)
            }
        }
    };
}

#[cfg(test)]
mod test {
    test!(f32, i32);
    test!(f64, i64);
}
<commit_msg>docs: document `Ulp` associated type<commit_after>//! ULP distance

use std::mem;
use std::num::{Float, Int};

use {Eq, Ulp};

/// Float distance in ULPs
pub trait Distance: Float {
    /// The units of least precision
    type Ulp: Int;

    /// Returns the absolute distance between two floats in ULPs
    fn distance(&self, &Self) -> Option<Self::Ulp>;
}

impl Distance for f32 {
    type Ulp = i32;

    fn distance(&self, rhs: &f32) -> Option<i32> {
        let &lhs = self;
        let &rhs = rhs;

        if lhs.is_nan() || rhs.is_nan() {
            // ULP idstance doesn't make sense for `NaN`s
            None
        } else {
            let lhs: i32 = unsafe {
                mem::transmute(lhs)
            };
            let rhs: i32 = unsafe {
                mem::transmute(rhs)
            };

            if lhs >> 31 != rhs >> 31 {
                // ULP distance will overflow if the sign bit doesn't match
                None
            } else {
                Some(
                    if lhs > rhs {
                        lhs - rhs
                    } else {
                        rhs - lhs
                    }
                )
            }
        }
    }
}

impl Distance for f64 {
    type Ulp = i64;

    fn distance(&self, rhs: &f64) -> Option<i64> {
        let &lhs = self;
        let &rhs = rhs;

        if lhs.is_nan() || rhs.is_nan() {
            // ULP idstance doesn't make sense for `NaN`s
            None
        } else {
            let ilhs: i64 = unsafe {
                mem::transmute(lhs)
            };
            let irhs: i64 = unsafe {
                mem::transmute(rhs)
            };

            if ilhs >> 63 != irhs >> 63 {
                // ULP distance will overflow if the sign bit doesn't match
                None
            } else {
                Some(
                    if ilhs > irhs {
                        ilhs - irhs
                    } else {
                        irhs - ilhs
                    }
                )
            }
        }
    }
}

impl<T: Distance> Eq<Ulp<T::Ulp>> for T {
    fn approx_eq(&self, rhs: &T, tol: Ulp<T::Ulp>) -> bool {
        let lhs = self;

        match lhs.distance(rhs) {
            Some(diff) => {
                diff <= tol.0
            },
            None => {
                // Check for `0 == -0`, if any side is a `NaN` this returns false
                lhs == rhs
            },
        }
    }
}

macro_rules! test {
    ($float:ident, $int:ident) => {
        mod $float {
            /// Given:
            /// - `x`: any float (minus `NaN`)
            /// - `tol`: any tolerance >= 0
            ///
            /// Test that `x.approx_eq(NaN)` is always false
            #[quickcheck]
            fn nan(x: $float, n: $int) -> bool {
                let tol = ::Ulp::tol(if n > 0 { n } else { -n });

                let zero: $float = 0.;
                let nan = zero / zero;

                !::eq(&nan, &x, tol) && !::eq(&x, &nan, tol)
            }

            /// Given:
            /// - `x`: any float (minus `NaN`)
            /// - `tol`: any tolerance >= 0
            ///
            /// Test that `x.approx_eq(x)` is always true
            #[quickcheck]
            fn same(x: $float, n: $int) -> bool {
                let tol = ::Ulp::tol(if n > 0 { n } else { -n });

                ::eq(&x, &x, tol)
            }

            /// Given:
            /// - `tol`: any tolerance >= 0
            ///
            /// Test that `NaN.approx_eq(NaN)` is always false
            #[quickcheck]
            fn nan_nan(n: $int) -> bool {
                let tol = ::Ulp::tol(if n > 0 { n } else { -n });

                let zero: $float = 0.;
                let nan = zero / zero;

                !::eq(&nan, &nan, tol)
            }
        }
    };
}

#[cfg(test)]
mod test {
    test!(f32, i32);
    test!(f64, i64);
}
<|endoftext|>


<commit_before>import std::time;
import std::time::tm;

import router::router;
import request::request;
import response::response;
import middleware::middleware;

import to_bytes::to_bytes;

type mre<T> = {
    m2: mongrel2::connection,
    router: router::router<T>,
    middleware: middleware::middleware<T>,
    mk_data: fn@() -> T,
};

fn mre<T: copy>(m2: mongrel2::connection,
          middleware: middleware::middleware<T>,
          mk_data: fn@() -> T) -> mre<T> {
    {
        m2: m2,
        router: router::router(),
        middleware: middleware,
        mk_data: mk_data,
    }
}

impl mre<T: copy> for mre<T> {
    fn run() {
        loop {
            let req = self.m2.recv();
            let rep = response::response(self.m2, req);

            let req = alt request::request(req, self.mk_data()) {
              ok(req) { req }
              err(e) {
                // Ignore this request if it's malformed.
                rep.http_400(e);
                cont;
              }
            };

            self.middleware.wrap(req, rep);

            // Ignore close requests for now.
            if req.is_disconnect() { cont; }

            alt req.find_header("METHOD") {
              none {
                // Error out the request if we didn't get a method.
                rep.http_400("missing method")
              }

              some(method) {
                alt self.router.find(method, req.path()) {
                  none { rep.http_404("") }

                  some((handler, m)) { handler(req, rep, m) }
                };
              }
            };
        }
    }
}
<commit_msg>Handle the m2 disconnect before middleware.<commit_after>import std::time;
import std::time::tm;
import m2_request = mongrel2::request;

import router::router;
import request::request;
import response::response;
import middleware::middleware;

import to_bytes::to_bytes;

type mre<T> = {
    m2: mongrel2::connection,
    router: router::router<T>,
    middleware: middleware::middleware<T>,
    mk_data: fn@() -> T,
};

fn mre<T: copy>(m2: mongrel2::connection,
          middleware: middleware::middleware<T>,
          mk_data: fn@() -> T) -> mre<T> {
    {
        m2: m2,
        router: router::router(),
        middleware: middleware,
        mk_data: mk_data,
    }
}

impl mre<T: copy> for mre<T> {
    fn run() {
        loop {
            let m2_req = self.m2.recv();

            // Ignore close requests for now.
            if m2_req.is_disconnect() { cont; }

            let rep = response::response(self.m2, m2_req);

            let req = alt request::request(m2_req, self.mk_data()) {
              ok(req) { req }
              err(e) {
                // Ignore this request if it's malformed.
                rep.http_400(e);
                cont;
              }
            };

            self.middleware.wrap(req, rep);

            alt req.find_header("METHOD") {
              none {
                // Error out the request if we didn't get a method.
                rep.http_400("missing method")
              }

              some(method) {
                alt self.router.find(method, req.path()) {
                  none { rep.http_404("") }

                  some((handler, m)) { handler(req, rep, m) }
                };
              }
            };
        }
    }
}
<|endoftext|>


<commit_before>use core::str::StrPrelude;

const BACKSPACE: u8 = 0x08;
const TAB: u8 = 0x09;
const NEWLINE: u8 = 0x0A;
const CR: u8 = 0x0D;
const WHITESPACE: u8 = 0x20;

const VGA_ADDRESS: int = 0xB8000;
const VGA_HEIGHT: u16 = 25;
const VGA_WIDTH: u16 = 80;

enum Color {
    Black = 0,
    Blue = 1,
    Green = 2,
    Cyan = 3,
    Red = 4,
    Pink = 5,
    Brown = 6,
    LightGray = 7,
    DarkGray = 8,
    LightBlue = 9,
    LightGreen = 10,
    LightCyan = 11,
    LightRed = 12,
    LightPink = 13,
    Yellow = 14,
    White = 15,
}

struct Cursor {
    height: u16,
    width: u16,
    x: u16,
    y: u16,
}

impl Cursor {

    pub fn new() -> Cursor {
        Cursor {height: VGA_HEIGHT, width: VGA_WIDTH, x: 0, y: 0}
    }

    pub fn back(&mut self) {
        if self.x > 0 {
            self.x -= 1;
        }
    }

    pub fn forward(&mut self) {
        self.x += 1;

        if self.x >= self.width {
            self.newline();
        }
    }

    pub fn cr(&mut self) {
        self.x = 0;
    }

    pub fn newline(&mut self) {
        self.x = 0;
        self.y += 1;
    }

    pub fn position(&self) -> u16 {
        self.y * self.width + self.x
    }

    pub fn reset(&mut self) {
        self.x = 0;
        self.y = 0;
        self.mov();
    }

    // handle a tab by increasing the cursor's X, but only to a point
    // where it is divisible by 8
    pub fn tab(&mut self) {
        self.x = (self.x + 8) & !(8 - 1);
    }

    pub fn mov(&mut self) {
        let position = self.position() as u8;

        unsafe {
            self.outb(0x3D4, 14);  // tell the VGA board we are setting the high cursor byte
            self.outb(0x3D5, position >> 8); // send the high cursor byte
            self.outb(0x3D4, 15);  // tell the VGA board we are setting the low cursor byte
            self.outb(0x3D5, position);
        }
    }

    unsafe fn outb(&mut self, port: u16, value: u8) {
        asm!("outb %al, %dx" :: "{dx}" (port), "{al}" (value) :: "volatile" );
    }
}

pub struct VGA {
    cursor: Cursor
}

impl VGA {
    pub fn new() -> VGA {
        VGA {cursor: Cursor::new()}
    }

    pub fn clear (&mut self) {
        let mut x: u16 = 0;

        loop {
            if x > 80 * 200 {
                break;
            }

            self.put(x, Black as u16, White as u16, WHITESPACE);
            x += 1;
        }
    }

    pub fn put(&mut self, position: u16, background: u16, foreground: u16, character: u8) {
        let pixel: u16 = (background << 12) | (foreground << 8) | character as u16;

        unsafe {
                *((VGA_ADDRESS + position as int * 2) as *mut u16) = pixel;
            }
    }

    pub fn putc(&mut self, character: u8) {

        if character == BACKSPACE {
            self.cursor.back();
        }

        else if character == TAB {
            self.cursor.tab();
        }

        else if character == NEWLINE {
            self.cursor.newline();
        }

        else if character == CR {
            self.cursor.cr();
        }

        else if character >= WHITESPACE {
            let position = self.cursor.position();
            self.put(position, Black as u16, White as u16, character);
            self.cursor.forward();
        }

        self.cursor.mov();
   }

    pub fn puts(&mut self, string: &str) {
        for character in string.bytes() {
            self.putc(character);
        }

    }
}
<commit_msg>VGA: rename "position" to "offset"<commit_after>use core::str::StrPrelude;

const BACKSPACE: u8 = 0x08;
const TAB: u8 = 0x09;
const NEWLINE: u8 = 0x0A;
const CR: u8 = 0x0D;
const WHITESPACE: u8 = 0x20;

const VGA_ADDRESS: int = 0xB8000;
const VGA_HEIGHT: u16 = 25;
const VGA_WIDTH: u16 = 80;

enum Color {
    Black = 0,
    Blue = 1,
    Green = 2,
    Cyan = 3,
    Red = 4,
    Pink = 5,
    Brown = 6,
    LightGray = 7,
    DarkGray = 8,
    LightBlue = 9,
    LightGreen = 10,
    LightCyan = 11,
    LightRed = 12,
    LightPink = 13,
    Yellow = 14,
    White = 15,
}

struct Cursor {
    height: u16,
    width: u16,
    x: u16,
    y: u16,
}

impl Cursor {

    pub fn new() -> Cursor {
        Cursor {height: VGA_HEIGHT, width: VGA_WIDTH, x: 0, y: 0}
    }

    pub fn back(&mut self) {
        if self.x > 0 {
            self.x -= 1;
        }
    }

    pub fn forward(&mut self) {
        self.x += 1;

        if self.x >= self.width {
            self.newline();
        }
    }

    pub fn cr(&mut self) {
        self.x = 0;
    }

    pub fn newline(&mut self) {
        self.x = 0;
        self.y += 1;
    }

    pub fn offset(&self) -> u16 {
        self.y * self.width + self.x
    }

    pub fn reset(&mut self) {
        self.x = 0;
        self.y = 0;
        self.mov();
    }

    // handle a tab by increasing the cursor's X, but only to a point
    // where it is divisible by 8
    pub fn tab(&mut self) {
        self.x = (self.x + 8) & !(8 - 1);
    }

    pub fn mov(&mut self) {
        let offset = self.offset() as u8;

        unsafe {
            self.outb(0x3D4, 14);  // tell the VGA board we are setting the high cursor byte
            self.outb(0x3D5, offset >> 8); // send the high cursor byte
            self.outb(0x3D4, 15);  // tell the VGA board we are setting the low cursor byte
            self.outb(0x3D5, offset);
        }
    }

    unsafe fn outb(&mut self, port: u16, value: u8) {
        asm!("outb %al, %dx" :: "{dx}" (port), "{al}" (value) :: "volatile" );
    }
}

pub struct VGA {
    cursor: Cursor
}

impl VGA {
    pub fn new() -> VGA {
        VGA {cursor: Cursor::new()}
    }

    pub fn clear (&mut self) {
        let mut x: u16 = 0;

        loop {
            if x > 80 * 200 {
                break;
            }

            self.put(x, Black as u16, White as u16, WHITESPACE);
            x += 1;
        }
    }

    pub fn put(&mut self, offset: u16, background: u16, foreground: u16, character: u8) {
        let pixel: u16 = (background << 12) | (foreground << 8) | character as u16;

        unsafe {
                *((VGA_ADDRESS + offset as int * 2) as *mut u16) = pixel;
            }
    }

    pub fn putc(&mut self, character: u8) {

        if character == BACKSPACE {
            self.cursor.back();
        }

        else if character == TAB {
            self.cursor.tab();
        }

        else if character == NEWLINE {
            self.cursor.newline();
        }

        else if character == CR {
            self.cursor.cr();
        }

        else if character >= WHITESPACE {
            let offset = self.cursor.offset();
            self.put(offset, Black as u16, White as u16, character);
            self.cursor.forward();
        }

        self.cursor.mov();
   }

    pub fn puts(&mut self, string: &str) {
        for character in string.bytes() {
            self.putc(character);
        }

    }
}
<|endoftext|>


<commit_before>/**
Katy Williamson kcw4sn
Ben Terner bt3ze
@virginia.edu

Final Project for CS4414 - Operating Systems
A parallel MST implementation on images in Rust

*/

/*
some documentation:
Pixel object is composed of r,g,b values, a color, and an x,y index that takes the place of its adjacency list
Point is just an (x,y) value to denote a pixel's location
Edge contains two points: source and dest, along with the edge cost between them

*/

extern mod extra;
use std::{os, num, hashmap} ;
use extra::{arc,priority_queue};

struct Pixel{
    r: int,
    b: int,
    g: int,
    color: int,
    x: int,
    y: int
}

impl Pixel {
    fn new(red: int, blue: int, green: int, x: int, y: int) -> Pixel {
        Pixel{
            r: red,
            b: blue,
            g: green,
            color: -1,
            x: x,
            y: y
        }
    }
}

impl Clone for Pixel{
    fn clone(&self) -> Pixel {
        Pixel{
            r: self.r,
            b: self.b,
            g: self.g,
            color: self.color,
            x: self.x,
            y: self.y
        }
    }
}

struct Point {
    x: int,
    y: int
}

impl Point{
    fn new(x: int, y: int)-> Point {
        Point {
            x: x,
            y: y
        }
    }
}

struct Edge {
    source: Point,
    dest: Point,
    cost: float
}

impl Edge {
    fn new(s: Point, d: Point, cost: float) -> Edge {
        Edge {
            source: s,
            dest: d,
            cost: cost
        }
    }
}

impl Ord for Edge {
    fn lt(&self, other: &Edge) -> bool {
        self.cost > other.cost
    }
}

fn edgeCost(a: &Pixel, b: &Pixel) -> float {
    num::sqrt( (
            (a.r-b.r)*(a.r-b.r) + (a.g-b.g)*(a.g-b.g) + (a.b-b.b)*(a.b-b.b) ) as float)
}

fn readImage( filename: &~str) -> ~ [ ~[Pixel]] {
    let mut retval: ~[~[Pixel]] = ~[];

    let file: &str = filename.to_owned();
//    let file2: ~str = file.to_owned();
    let split_filename: ~[&str] = file.split_iter('.').collect();
    let file_data: &str = split_filename[0] + ".txt";

    println(fmt!("The image name is [%?]", file));
    println(fmt!("The image data will be stored at [%?]", file_data));

    //read in the .txt associated with the file title
    let path = &PosixPath(file_data);

    match std::io::file_reader(path) {
	Ok(reader) => {
	    //run the java program to process the image
/*	    let program: &str = "java ImageReader";
	    let argv: ~[~str] = ~[file2];
	    let mut prog = std::run::Process::new(program, argv,
		std::run::ProcessOptions {
			env: None,
			dir: None,
			in_fd: None,
			out_fd: None,
			err_fd: None
		}
	    );
	    prog.finish();
*/
	    //parse out the array dimensions
    	    let dimensions_str: &str = reader.read_line();
    	    println(fmt!("dimensons: %s",dimensions_str));
	    let mut h: int = 0;
	    let mut w: int = 0;
	    match dimensions_str[0] as char {
		'H' => {
		    let split_dim: ~[&str] = dimensions_str.split_iter('W').collect();
		    h = from_str(split_dim[0].slice(1,split_dim[0].len())).unwrap();
		    w = from_str(split_dim[1]).unwrap();
		    println(fmt!("Dimensions passed: H %? W %?",h,w));
		    //let retval: ~[ ~[Pixel, ..w], ..h];
		}
		_ => {println("Dimensions corrupted! Abort");}
	    }

	    //fill in the retVal array with pixel data
            //let mut rowfirst = false;
	    for row in range(0,h){
//                if(!rowfirst) {
                retval.push(~[]);
                //rowfirst = true; }
		for col in range(0,w){
	    	    if !reader.eof() {
			let line: &str = reader.read_line();
			//println(line);
			let rpos:uint = match line.find('R') { Some(n)=>n,None=>line.len() };
			let gpos:uint = match line.find('G') { Some(n)=>n,None=>line.len() };
			let bpos:uint = match line.find('B') { Some(n)=>n,None=>line.len() };

			if rpos == line.len() || gpos == line.len() || bpos == line.len() {
			    println("Pixel data corrupted! Abort");
			}

			let R:int = from_str(line.slice(rpos+1,gpos)).unwrap();
			let G:int = from_str(line.slice(gpos+1,bpos)).unwrap();
			let B:int = from_str(line.slice(bpos+1,line.len())).unwrap();

			//println(fmt!("R %? G %? B %?",R,G,B));

			//fn new(red: int, blue: int, green: int, x: int, y: int) -> Pixel {
			retval[row].push(Pixel::new(R,G,B,col,row));

		    }
		    else {
			println("Data file corrupted! Abort");
		    }
		}
	    }
	},
	Err(err)   => { fail!(err) }
    }

    retval
}

fn main(){
    let argv =  os::args();
    println(argv.to_str());

    let pixels: ~[ ~[Pixel] ] = readImage(&argv[1]);
    let height = pixels.len() as int;
    let width = pixels[0].len() as int;

    println(fmt!("Dimensions received: H %? W %?",height,width));

    let mut find_arcs: ~[ ~[arc::RWArc<Pixel>] ] =  ~[];
    for h in range(0,height){
	find_arcs.push(~[]);
        for w in range(0,width){
 //           println(fmt!("pix %?",pixels[h][w]));
	    find_arcs[h].push(arc::RWArc::new(pixels[h][w]));
	}
    }

    let arcs = find_arcs; // now we have an immutable array that can be shared

    let corners = [ (0,0),(width-1,0),(0,height-1),(width-1,height-1) ];

    let mut color_index = 0;
    for &corner in corners.iter(){
        let (a,b) = corner;
        do arcs[b][a].write |pix| {
            pix.color = color_index;
        }
        color_index+=1;
    }

    for &corner in corners.iter() {
        let (a,b) = corner;
        let shared_arcs = arcs.clone();
        do spawn { // split into threads here
            let c = a;
            let d = b;
            let mut x=a;
            let mut y=b;

            let mut queue: priority_queue::PriorityQueue<Edge> =  priority_queue::PriorityQueue::new();
            let mut visited: hashmap::HashMap<(int,int),bool> = hashmap::HashMap::new();
            let mut newvisit: bool = true;
            let mut boundaries: ~[Edge] = ~[];
            let mut color: int = -1;
            do shared_arcs[b][a].read |pix| {
                color = pix.color;
            }

            println(fmt!("start at (%i,%i): color = %i",c,d,color));

            loop { // iterate through items in the queue, which contains all of the edges/vertices
                if(newvisit){
//                   println(fmt!("(%i,%i) : (%i,%i)",c,d,x,y));
                    let neighbors = [ (x,y-1),(x+1,y), (x,y+1), (x-1,y)];
                    for &coord in neighbors.iter() {
                        let (w,z) = coord;
                        if w >=0 && w < width && z >=0 && z < height { // bounds checking
                            // if neighbor at coord has not been colored
                            let mut newvertex = false;
                            let mut uncolored = false;
                            do shared_arcs[z][w].read |dest| {
                                if dest.color < 0 {
                                    uncolored = true;
                                }
                            }
                            if uncolored {
                                do shared_arcs[z][w].write |dest| {
                                    if dest.color < 0 {
                                        dest.color = color;
//                                        do shared_arcs[y][x].read |src| {
 //                                           dest.color = src.color;
  //                                      }
                                        newvertex = true;
                                    } else {
                                        // edge has crossed a cut during a race since we last checked if it was uncolored
                                        uncolored = false;
                                    }
                                }
                            }
                            if !uncolored { // this is an else to the above if
                                // we have found an edge that crosses a cut!
                                // here, somehow collect the edges that cross our cut
                                do shared_arcs[y][x].read |src| {
                                    do shared_arcs[z][w].read |dest| {
                                        boundaries.push( Edge::new(Point::new(x,y),Point::new(w,z),edgeCost(src,dest)));
                                    }
                                }
                            }
                            if newvertex { // then we have a new vertex
                                do shared_arcs[y][x].read |src| {
                                    do shared_arcs[z][w].read |dest| {
                                        queue.push( Edge::new(Point::new(x,y),Point::new(w,z),edgeCost(src,dest)));
                                    }
                                }
                            }
                        }
                    }
                }

                let edge = queue.maybe_pop();
                match edge {
                    Some(e) => {
                        println(fmt!("(%i,%i) pop (%i,%i)-%f-(%i,%i)",c,d,e.source.x,e.source.y,e.cost,e.dest.x,e.dest.y));
                        // not in any tree
                        let coord = (e.dest.x,e.dest.y);
//                        println(fmt!("before runtime error? %?",coord));
                        if !visited.contains_key(&coord){
 // use visited hashmap to figure out if we're at a new vertex.
                            visited.insert(coord,true);
                            x = e.dest.x;
                            y = e.dest.y;
                            newvisit = true;
//                            println(fmt!("%? %f",coord,e.cost));
                        } else {
                            newvisit = false;
                        }
                    },
                    None => { break; } // this should execute at the end when there are no more unvisited or uncolored nodes for a thread
                }
            }

            for e in boundaries.iter() {
                println(fmt!("(%i,%i:%i) boundary (%i,%i)-%f-(%i,%i)",c,d,color,e.source.x,e.source.y,e.cost,e.dest.x,e.dest.y));
            }
        }
    }

    for h in range(0,height){
        for w in range(0,width){
            do arcs[h][w].read |pix| {
                println(fmt!("color(%i,%i) %i",w,h,pix.color));
	    }
        }
    }
}
<commit_msg>changing machines.<commit_after>/**
Katy Williamson kcw4sn
Ben Terner bt3ze
@virginia.edu

Final Project for CS4414 - Operating Systems
A parallel MST implementation on images in Rust

*/

/*
some documentation:
Pixel object is composed of r,g,b values, a color, and an x,y index that takes the place of its adjacency list
Point is just an (x,y) value to denote a pixel's location
Edge contains two points: source and dest, along with the edge cost between them

*/

extern mod extra;
use std::{os, num, hashmap} ;
use extra::{arc,priority_queue};

struct Pixel{
    r: int,
    b: int,
    g: int,
    color: int,
    x: int,
    y: int
}

impl Pixel {
    fn new(red: int, blue: int, green: int, x: int, y: int) -> Pixel {
        Pixel{
            r: red,
            b: blue,
            g: green,
            color: -1,
            x: x,
            y: y
        }
    }
}

impl Clone for Pixel{
    fn clone(&self) -> Pixel {
        Pixel{
            r: self.r,
            b: self.b,
            g: self.g,
            color: self.color,
            x: self.x,
            y: self.y
        }
    }
}

struct Point {
    x: int,
    y: int
}

impl Point{
    fn new(x: int, y: int)-> Point {
        Point {
            x: x,
            y: y
        }
    }
}

struct Edge {
    source: Point,
    dest: Point,
    cost: float
}

impl Edge {
    fn new(s: Point, d: Point, cost: float) -> Edge {
        Edge {
            source: s,
            dest: d,
            cost: cost
        }
    }
}

impl Ord for Edge {
    fn lt(&self, other: &Edge) -> bool {
        self.cost > other.cost
    }
}

fn edgeCost(a: &Pixel, b: &Pixel) -> float {
    num::sqrt( (
            (a.r-b.r)*(a.r-b.r) + (a.g-b.g)*(a.g-b.g) + (a.b-b.b)*(a.b-b.b) ) as float)
}

fn readImage( filename: &~str) -> ~ [ ~[Pixel]] {
    let mut retval: ~[~[Pixel]] = ~[];

    let file: &str = filename.to_owned();
//    let file2: ~str = file.to_owned();
    let split_filename: ~[&str] = file.split_iter('.').collect();
    let file_data: &str = split_filename[0] + ".txt";

    println(fmt!("The image name is [%?]", file));
    println(fmt!("The image data will be stored at [%?]", file_data));

    //read in the .txt associated with the file title
    let path = &PosixPath(file_data);

    match std::io::file_reader(path) {
	Ok(reader) => {
	    //run the java program to process the image
/*	    let program: &str = "java ImageReader";
	    let argv: ~[~str] = ~[file2];
	    let mut prog = std::run::Process::new(program, argv,
		std::run::ProcessOptions {
			env: None,
			dir: None,
			in_fd: None,
			out_fd: None,
			err_fd: None
		}
	    );
	    prog.finish();
*/
	    //parse out the array dimensions
    	    let dimensions_str: &str = reader.read_line();
    	    println(fmt!("dimensons: %s",dimensions_str));
	    let mut h: int = 0;
	    let mut w: int = 0;
	    match dimensions_str[0] as char {
		'H' => {
		    let split_dim: ~[&str] = dimensions_str.split_iter('W').collect();
		    h = from_str(split_dim[0].slice(1,split_dim[0].len())).unwrap();
		    w = from_str(split_dim[1]).unwrap();
		    println(fmt!("Dimensions passed: H %? W %?",h,w));
		    //let retval: ~[ ~[Pixel, ..w], ..h];
		}
		_ => {println("Dimensions corrupted! Abort");}
	    }

	    //fill in the retVal array with pixel data
            //let mut rowfirst = false;
	    for row in range(0,h){
//                if(!rowfirst) {
                retval.push(~[]);
                //rowfirst = true; }
		for col in range(0,w){
	    	    if !reader.eof() {
			let line: &str = reader.read_line();
			//println(line);
			let rpos:uint = match line.find('R') { Some(n)=>n,None=>line.len() };
			let gpos:uint = match line.find('G') { Some(n)=>n,None=>line.len() };
			let bpos:uint = match line.find('B') { Some(n)=>n,None=>line.len() };

			if rpos == line.len() || gpos == line.len() || bpos == line.len() {
			    println("Pixel data corrupted! Abort");
			}

			let R:int = from_str(line.slice(rpos+1,gpos)).unwrap();
			let G:int = from_str(line.slice(gpos+1,bpos)).unwrap();
			let B:int = from_str(line.slice(bpos+1,line.len())).unwrap();

			//println(fmt!("R %? G %? B %?",R,G,B));

			//fn new(red: int, blue: int, green: int, x: int, y: int) -> Pixel {
			retval[row].push(Pixel::new(R,G,B,col,row));

		    }
		    else {
			println("Data file corrupted! Abort");
		    }
		}
	    }
	},
	Err(err)   => { fail!(err) }
    }

    retval
}

fn main(){
    let argv =  os::args();
    println(argv.to_str());

    let pixels: ~[ ~[Pixel] ] = readImage(&argv[1]);
    let height = pixels.len() as int;
    let width = pixels[0].len() as int;

    println(fmt!("Dimensions received: H %? W %?",height,width));

    let mut find_arcs: ~[ ~[arc::RWArc<Pixel>] ] =  ~[];
    for h in range(0,height){
	find_arcs.push(~[]);
        for w in range(0,width){
 //           println(fmt!("pix %?",pixels[h][w]));
	    find_arcs[h].push(arc::RWArc::new(pixels[h][w]));
	}
    }

    let arcs = find_arcs; // now we have an immutable array that can be shared

    let corners = [ (0,0),(width-1,0),(0,height-1),(width-1,height-1) ];

    let mut color_index = 0;
    for &corner in corners.iter(){
        let (a,b) = corner;
        do arcs[b][a].write |pix| {
            pix.color = color_index;
        }
        color_index+=1;
    }

    for &corner in corners.iter() {
        let (a,b) = corner;
        let shared_arcs = arcs.clone();
        do spawn { // split into threads here
            let c = a;
            let d = b;
            let mut x=a;
            let mut y=b;

            let mut queue: priority_queue::PriorityQueue<Edge> =  priority_queue::PriorityQueue::new();
            let mut visited: hashmap::HashMap<(int,int),bool> = hashmap::HashMap::new();
            let mut newvisit: bool = true;
            let mut boundaries: ~[Edge] = ~[];
            let mut color: int = -1;
            do shared_arcs[b][a].read |pix| {
                color = pix.color;
            }

            println(fmt!("start at (%i,%i): color = %i",c,d,color));

            loop { // iterate through items in the queue, which contains all of the edges/vertices
                if(newvisit){
//                   println(fmt!("(%i,%i) : (%i,%i)",c,d,x,y));
                    let neighbors = [ (x,y-1),(x+1,y), (x,y+1), (x-1,y)];
                    for &coord in neighbors.iter() {
                        let (w,z) = coord;
                        if w >=0 && w < width && z >=0 && z < height { // bounds checking
                            // if neighbor at coord has not been colored
                            let mut newvertex = false;
                            let mut uncolored = false;
                            do shared_arcs[z][w].read |dest| {
                                if dest.color < 0 {
                                    uncolored = true;
                                }
                            }
                            if uncolored {
                                do shared_arcs[z][w].write |dest| {
                                    if dest.color < 0 {
                                        dest.color = color;
                                        newvertex = true;
                                    } else {
                                        // edge has crossed a cut during a race since we last checked if it was uncolored
                                        uncolored = false;
                                    }
                                }
                            }
                            if !uncolored { // this is an else to the above if
                                // we have found an edge that crosses a cut!
                                // here, somehow collect the edges that cross our cut
                                do shared_arcs[y][x].read |src| {
                                    do shared_arcs[z][w].read |dest| {
//                                        if dest.color != color {
                                            boundaries.push( Edge::new(Point::new(x,y),Point::new(w,z),edgeCost(src,dest)));
  //                                      }
                                    }
                                }
                            }
                            if newvertex { // then we have a new vertex
                                do shared_arcs[y][x].read |src| {
                                    do shared_arcs[z][w].read |dest| {
                                        queue.push( Edge::new(Point::new(x,y),Point::new(w,z),edgeCost(src,dest)));
                                    }
                                }
                            }
                        }
                    }
                }

                let edge = queue.maybe_pop();
                match edge {
                    Some(e) => {
                        println(fmt!("(%i,%i) pop (%i,%i)-%f-(%i,%i)",c,d,e.source.x,e.source.y,e.cost,e.dest.x,e.dest.y));
                        // not in any tree
                        let coord = (e.dest.x,e.dest.y);
//                        println(fmt!("before runtime error? %?",coord));
                        if !visited.contains_key(&coord){
 // use visited hashmap to figure out if we're at a new vertex.
                            visited.insert(coord,true);
                            x = e.dest.x;
                            y = e.dest.y;
                            newvisit = true;
//                            println(fmt!("%? %f",coord,e.cost));
                        } else {
                            newvisit = false;
                        }
                    },
                    None => { break; } // this should execute at the end when there are no more unvisited or uncolored nodes for a thread
                }
            }

            for e in boundaries.iter() {
                println(fmt!("(%i,%i:%i) boundary (%i,%i)-%f-(%i,%i)",c,d,color,e.source.x,e.source.y,e.cost,e.dest.x,e.dest.y));
            }
        }
    }

    for h in range(0,height){
        for w in range(0,width){
            do arcs[h][w].read |pix| {
                println(fmt!("color(%i,%i) %i",w,h,pix.color));
	    }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

#[macro_use]
extern crate log;
extern crate osmpbfreader;
extern crate rustc_serialize;
extern crate docopt;
extern crate mimir;
extern crate rs_es;

use std::collections::HashSet;
use std::collections::HashMap;
use mimirsbrunn::rubber::Rubber;
use mimirsbrunn::objects::{Polygon, MultiPolygon};

pub type AdminsVec = Vec<mimir::Admin>;
pub type StreetsVec = Vec<mimir::Street>;
pub type ParsedPbf = osmpbfreader::OsmPbfReader<std::fs::File>;

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_input: String,
    flag_level: Vec<u32>,
    flag_connection_string: String,
    flag_import_way: bool,
}

static USAGE: &'static str = "
Usage:
    osm2mimir --help
    osm2mimir --input=<file> [--connection-string=<connection-string>] --level=<level> ... [--import-way]

Options:
    -h, --help            Show this message.
    -i, --input=<file>    OSM PBF file.
    -l, --level=<level>   Admin levels to keep.
    -w, --import-way      By default, streets are not imported
    -c, --connection-string=<connection-string>
                          Elasticsearch parameters, [default: http://localhost:9200/munin]
";

#[derive(Debug)]
struct AdminMatcher {
    admin_levels: HashSet<u32>,
}
impl AdminMatcher {
    pub fn new(levels: HashSet<u32>) -> AdminMatcher {
        AdminMatcher { admin_levels: levels }
    }

    pub fn is_admin(&self, obj: &osmpbfreader::OsmObj) -> bool {
        match *obj {
            osmpbfreader::OsmObj::Relation(ref rel) => {
                rel.tags.get("boundary").map_or(false, |v| v == "administrative") &&
                rel.tags.get("admin_level").map_or(false, |lvl| {
                    self.admin_levels.contains(&lvl.parse::<u32>().unwrap_or(0))
                })
            }
            _ => false,
        }
    }
}

struct BoundaryPart {
    nodes: Vec<osmpbfreader::Node>,
}

impl BoundaryPart {
    pub fn new(nodes: Vec<osmpbfreader::Node>) -> BoundaryPart {
        BoundaryPart { nodes: nodes }
    }
    pub fn first(&self) -> i64 {
        self.nodes.first().unwrap().id
    }
    pub fn last(&self) -> i64 {
        self.nodes.last().unwrap().id
    }
}

fn get_nodes(way: &osmpbfreader::Way,
             objects: &HashMap<osmpbfreader::OsmId, osmpbfreader::OsmObj>)
             -> Vec<osmpbfreader::Node> {
    way.nodes
       .iter()
       .filter_map(|node_id| objects.get(&osmpbfreader::OsmId::Node(*node_id)))
       .filter_map(|node_obj| if let &osmpbfreader::OsmObj::Node(ref node) = node_obj {
           Some(node.clone())
       } else {
           None
       })
       .collect()
}

fn build_boundary(relation: &osmpbfreader::Relation,
                  objects: &HashMap<osmpbfreader::OsmId, osmpbfreader::OsmObj>)
                  -> Option<MultiPolygon> {
    let mut boundary_parts: Vec<BoundaryPart> =
        relation.refs
                .iter()
                .filter(|rf| rf.role == "outer" || rf.role == "" || rf.role == "enclave")
                .filter_map(|refe| {
                    objects.get(&refe.member).or_else(|| {
                        warn!("missing element for relation {}", relation.id);
                        None
                    })
                })
                .filter_map(|way_obj| if let &osmpbfreader::OsmObj::Way(ref way) = way_obj {
                    Some(way)
                } else {
                    None
                })
                .map(|way| get_nodes(&way, objects))
                .filter(|nodes| nodes.len() > 1)
                .map(|nodes| BoundaryPart::new(nodes))
                .collect();
    let mut multipoly = MultiPolygon { polygons: Vec::new() };
    // we want to try build a polygon for a least each way
    while !boundary_parts.is_empty() {
        let mut current = -1;
        let mut first = 0;
        let mut nb_try = 0;

        let mut outer: Vec<osmpbfreader::Node> = Vec::new();
        // we try to close the polygon, if we can't we want to at least have tried one time per
        // way. We could improve that latter by trying to attach the way to both side of the
        // polygon
        let max_try = boundary_parts.len();
        while current != first && nb_try < max_try {
            let mut i = 0;
            while i < boundary_parts.len() {
                if outer.is_empty() {
                    // our polygon is empty, we initialise it with the current way
                    first = boundary_parts[i].first();
                    current = boundary_parts[i].last();
                    outer.append(&mut boundary_parts[i].nodes);
                    // this way has been used, we remove it from the pool
                    boundary_parts.remove(i);
                    continue;
                }
                if current == boundary_parts[i].first() {
                    // the start of current way touch the polygon, we add it and remove it from the
                    // pool
                    current = boundary_parts[i].last();
                    outer.append(&mut boundary_parts[i].nodes);
                    boundary_parts.remove(i);
                } else if current == boundary_parts[i].last() {
                    // the end of the current way touch the polygon, we reverse the way and add it
                    current = boundary_parts[i].first();
                    boundary_parts[i].nodes.reverse();
                    outer.append(&mut boundary_parts[i].nodes);
                    boundary_parts.remove(i);
                } else {
                    i += 1;
                    // didnt do anything, we want to explore the next way, if we had do something we
                    // will have removed the current way and there will be no need to increment
                }
                if current == first {
                    // our polygon is closed, we create it and add it to the multipolygon
                    let polygon = Polygon::new(outer.iter()
                                                    .map(|n| {
                                                        mimir::Coord {
                                                            lat: n.lat,
                                                            lon: n.lon,
                                                        }
                                                    })
                                                    .collect());
                    multipoly.polygons.push(polygon);
                    break;
                }
            }
            nb_try += 1;
        }
    }
    debug!("polygon for relation {};{}", relation.id, multipoly.to_wkt());
    if multipoly.polygons.is_empty() {
        None
    } else {
        Some(multipoly)
    }
}

fn parse_osm_pbf(path: &str) -> ParsedPbf {
    let path = std::path::Path::new(&path);
    osmpbfreader::OsmPbfReader::new(std::fs::File::open(&path).unwrap())
}

fn administrative_regions(pbf: &mut ParsedPbf, levels: HashSet<u32>) -> AdminsVec {
    let mut administrative_regions = AdminsVec::new();
    let matcher = AdminMatcher::new(levels);
    let objects = osmpbfreader::get_objs_and_deps(pbf, |o| matcher.is_admin(o)).unwrap();
    // load administratives regions
    for (_, obj) in &objects {
        if !matcher.is_admin(&obj) {
            continue;
        }
        if let &osmpbfreader::OsmObj::Relation(ref relation) = obj {
            let level = relation.tags
                                .get("admin_level")
                                .and_then(|s| s.parse().ok());
            let level = match level {
                None => {
                    info!("invalid admin_level for relation {}: admin_level {:?}",
                          relation.id,
                          relation.tags.get("admin_level"));
                    continue;
                }
                Some(l) => l,
            };
            // administrative region with name ?
            let name = match relation.tags.get("name") {
                Some(val) => val,
                None => {
                    warn!("adminstrative region without name for relation {}:  admin_level {} \
                           ignored.",
                          relation.id,
                          level);
                    continue;
                }
            };
            // admininstrative region without coordinates
            let coord_centre = relation.refs
                                       .iter()
                                       .find(|rf| rf.role == "admin_centre")
                                       .and_then(|r| {
                                           objects.get(&r.member).and_then(|value| {
                                               match value {
                                                   &osmpbfreader::OsmObj::Node(ref node) => {
                                                       Some(mimir::Coord {
                                                           lat: node.lat,
                                                           lon: node.lon,
                                                       })
                                                   }
                                                   _ => None,
                                               }
                                           })
                                       });

            let admin_id = match relation.tags.get("ref:INSEE") {
                Some(val) => format!("admin:fr:{}", val.trim_left_matches('0')),
                None => format!("admin:osm:{}", relation.id),
            };
            let zip_code = match relation.tags.get("addr:postcode") {
                Some(val) => &val[..],
                None => "",
            };
            let boundary = build_boundary(&relation, &objects);
            let admin = mimir::Admin {
                id: admin_id,
                level: level,
                name: name.to_string(),
                zip_code: zip_code.to_string(),
                // TODO weight value ?
                weight: 1,
                coord: coord_centre,
                boundary: boundary,
            };
            administrative_regions.push(admin);
        }
    }
    return administrative_regions;
}

fn streets(pbf: &mut ParsedPbf) -> StreetsVec {

    let is_valid_obj = |obj: &osmpbfreader::OsmObj| -> bool {
        match *obj {
            osmpbfreader::OsmObj::Way(ref way) => {
                way.tags.get("highway").map_or(false, |x| !x.is_empty()) &&
                way.tags.get("name").map_or(false, |x| !x.is_empty())
            }
            osmpbfreader::OsmObj::Relation(ref rel) => {
                rel.tags.get("type").map_or(false, |v| v == "associatedStreet")
            }
            _ => false,
        }
    };

    let mut objs_map = osmpbfreader::get_objs_and_deps(pbf, is_valid_obj).unwrap();
    // Sometimes, streets can be devided into several "way"s that still have the same street name.
    // The reason why a street is devided may be that a part of the street become a bridge/tunne/etc.
    // In this case, a "relation" tagged with (type = associatedStreet) is used to group all these "way"s.
    // In order not to have doublons in autocompleion, we should keep only one "way" in the relation
    // and remove all the rest way whose street name is the same.
    let mut objs_to_remove = Vec::<osmpbfreader::OsmId>::new();

    for (_, rel_obj) in &objs_map {
        if let &osmpbfreader::OsmObj::Relation(ref rel) = rel_obj {
            let mut found = false;
            for ref_obj in &rel.refs {
                if let &osmpbfreader::OsmId::Way(_) = &ref_obj.member {
                    if !found {
                        found = true;
                        continue;
                    }
                    objs_to_remove.push(ref_obj.member.clone());
                };
            }
        };
    }

    for osm_id in objs_to_remove {
        objs_map.remove(&osm_id);
    }

    objs_map.iter()
            .filter_map(|(_, obj)| {
                if let &osmpbfreader::OsmObj::Way(ref way) = obj {
                    way.tags.get("name").and_then(|way_name| {
                        Some(mimirsbrunn::Street {
                            id: way.id.to_string(),
                            street_name: way_name.to_string(),
                            name: way_name.to_string(),
                            weight: 1,
                            administrative_region: None,
                        })
                    })
                } else {
                    None
                }
            })
            .collect()

}
// TODO: template these two functions
fn index_admin(es_cnx_string: &str, admins: AdminsVec) {
    let mut rubber = Rubber::new(es_cnx_string);

    match rubber.clean_db_by_doc_type(&["admin"]) {
        Err(e) => panic!("failed to clean data by document type: {}", e),
        Ok(nb) => info!("Nb of cleaned indexed obj: {}", nb),
    }

    match rubber.bulk_index(admins.iter()) {
        Err(e) => panic!("failed to index admins of osm because: {}", e),
        Ok(nb) => info!("Nb of indexed adminstrative regions: {}", nb),
    }
}

fn index_ways(es_cnx_string: &str, streets: StreetsVec) {
    let mut rubber = Rubber::new(es_cnx_string);

    match rubber.clean_db_by_doc_type(&["street"]) {
        Err(e) => panic!("failed to clean data by document type: {}", e),
        Ok(nb) => info!("Nb of cleaned indexed obj: {}", nb),
    }

    match rubber.bulk_index(streets.iter()) {
        Err(e) => panic!("failed to index streets of osm because: {}", e),
        Ok(nb) => info!("Nb of indexed street: {}", nb),
    }
}

fn index_settings(es_cnx_string: &str) {
    let mut rubber = Rubber::new(es_cnx_string);
    rubber.create_index();
}

fn main() {
    mimir::logger_init().unwrap();
    debug!("importing adminstrative region into Mimir");
    let args: Args = docopt::Docopt::new(USAGE)
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| e.exit());

    let levels = args.flag_level.iter().cloned().collect();
    let mut parsed_pbf = parse_osm_pbf(&args.flag_input);

    let admins = administrative_regions(&mut parsed_pbf, levels);

    index_settings(&args.flag_connection_string);
    index_admin(&args.flag_connection_string, admins);

    let mut optinoal_streets: Option<StreetsVec> = None;
    if args.flag_import_way {
        optinoal_streets = Some(streets(&mut parsed_pbf));
    }

    if let Some(streets) = optinoal_streets {
        index_ways(&args.flag_connection_string, streets);
    }
}
<commit_msg>clean db before import<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

#[macro_use]
extern crate log;
extern crate osmpbfreader;
extern crate rustc_serialize;
extern crate docopt;
extern crate mimir;
extern crate rs_es;

use std::collections::HashSet;
use std::collections::HashMap;
use mimirsbrunn::rubber::Rubber;
use mimirsbrunn::objects::{Polygon, MultiPolygon};

pub type AdminsVec = Vec<mimir::Admin>;
pub type StreetsVec = Vec<mimir::Street>;
pub type ParsedPbf = osmpbfreader::OsmPbfReader<std::fs::File>;

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_input: String,
    flag_level: Vec<u32>,
    flag_connection_string: String,
    flag_import_way: bool,
}

static USAGE: &'static str = "
Usage:
    osm2mimir --help
    osm2mimir --input=<file> [--connection-string=<connection-string>] --level=<level> ... [--import-way]

Options:
    -h, --help            Show this message.
    -i, --input=<file>    OSM PBF file.
    -l, --level=<level>   Admin levels to keep.
    -w, --import-way      By default, streets are not imported
    -c, --connection-string=<connection-string>
                          Elasticsearch parameters, [default: http://localhost:9200/munin]
";

#[derive(Debug)]
struct AdminMatcher {
    admin_levels: HashSet<u32>,
}
impl AdminMatcher {
    pub fn new(levels: HashSet<u32>) -> AdminMatcher {
        AdminMatcher { admin_levels: levels }
    }

    pub fn is_admin(&self, obj: &osmpbfreader::OsmObj) -> bool {
        match *obj {
            osmpbfreader::OsmObj::Relation(ref rel) => {
                rel.tags.get("boundary").map_or(false, |v| v == "administrative") &&
                rel.tags.get("admin_level").map_or(false, |lvl| {
                    self.admin_levels.contains(&lvl.parse::<u32>().unwrap_or(0))
                })
            }
            _ => false,
        }
    }
}

struct BoundaryPart {
    nodes: Vec<osmpbfreader::Node>,
}

impl BoundaryPart {
    pub fn new(nodes: Vec<osmpbfreader::Node>) -> BoundaryPart {
        BoundaryPart { nodes: nodes }
    }
    pub fn first(&self) -> i64 {
        self.nodes.first().unwrap().id
    }
    pub fn last(&self) -> i64 {
        self.nodes.last().unwrap().id
    }
}

fn get_nodes(way: &osmpbfreader::Way,
             objects: &HashMap<osmpbfreader::OsmId, osmpbfreader::OsmObj>)
             -> Vec<osmpbfreader::Node> {
    way.nodes
       .iter()
       .filter_map(|node_id| objects.get(&osmpbfreader::OsmId::Node(*node_id)))
       .filter_map(|node_obj| if let &osmpbfreader::OsmObj::Node(ref node) = node_obj {
           Some(node.clone())
       } else {
           None
       })
       .collect()
}

fn build_boundary(relation: &osmpbfreader::Relation,
                  objects: &HashMap<osmpbfreader::OsmId, osmpbfreader::OsmObj>)
                  -> Option<MultiPolygon> {
    let mut boundary_parts: Vec<BoundaryPart> =
        relation.refs
                .iter()
                .filter(|rf| rf.role == "outer" || rf.role == "" || rf.role == "enclave")
                .filter_map(|refe| {
                    objects.get(&refe.member).or_else(|| {
                        warn!("missing element for relation {}", relation.id);
                        None
                    })
                })
                .filter_map(|way_obj| if let &osmpbfreader::OsmObj::Way(ref way) = way_obj {
                    Some(way)
                } else {
                    None
                })
                .map(|way| get_nodes(&way, objects))
                .filter(|nodes| nodes.len() > 1)
                .map(|nodes| BoundaryPart::new(nodes))
                .collect();
    let mut multipoly = MultiPolygon { polygons: Vec::new() };
    // we want to try build a polygon for a least each way
    while !boundary_parts.is_empty() {
        let mut current = -1;
        let mut first = 0;
        let mut nb_try = 0;

        let mut outer: Vec<osmpbfreader::Node> = Vec::new();
        // we try to close the polygon, if we can't we want to at least have tried one time per
        // way. We could improve that latter by trying to attach the way to both side of the
        // polygon
        let max_try = boundary_parts.len();
        while current != first && nb_try < max_try {
            let mut i = 0;
            while i < boundary_parts.len() {
                if outer.is_empty() {
                    // our polygon is empty, we initialise it with the current way
                    first = boundary_parts[i].first();
                    current = boundary_parts[i].last();
                    outer.append(&mut boundary_parts[i].nodes);
                    // this way has been used, we remove it from the pool
                    boundary_parts.remove(i);
                    continue;
                }
                if current == boundary_parts[i].first() {
                    // the start of current way touch the polygon, we add it and remove it from the
                    // pool
                    current = boundary_parts[i].last();
                    outer.append(&mut boundary_parts[i].nodes);
                    boundary_parts.remove(i);
                } else if current == boundary_parts[i].last() {
                    // the end of the current way touch the polygon, we reverse the way and add it
                    current = boundary_parts[i].first();
                    boundary_parts[i].nodes.reverse();
                    outer.append(&mut boundary_parts[i].nodes);
                    boundary_parts.remove(i);
                } else {
                    i += 1;
                    // didnt do anything, we want to explore the next way, if we had do something we
                    // will have removed the current way and there will be no need to increment
                }
                if current == first {
                    // our polygon is closed, we create it and add it to the multipolygon
                    let polygon = Polygon::new(outer.iter()
                                                    .map(|n| {
                                                        mimir::Coord {
                                                            lat: n.lat,
                                                            lon: n.lon,
                                                        }
                                                    })
                                                    .collect());
                    multipoly.polygons.push(polygon);
                    break;
                }
            }
            nb_try += 1;
        }
    }
    debug!("polygon for relation {};{}", relation.id, multipoly.to_wkt());
    if multipoly.polygons.is_empty() {
        None
    } else {
        Some(multipoly)
    }
}

fn parse_osm_pbf(path: &str) -> ParsedPbf {
    let path = std::path::Path::new(&path);
    osmpbfreader::OsmPbfReader::new(std::fs::File::open(&path).unwrap())
}

fn administrative_regions(pbf: &mut ParsedPbf, levels: HashSet<u32>) -> AdminsVec {
    let mut administrative_regions = AdminsVec::new();
    let matcher = AdminMatcher::new(levels);
    let objects = osmpbfreader::get_objs_and_deps(pbf, |o| matcher.is_admin(o)).unwrap();
    // load administratives regions
    for (_, obj) in &objects {
        if !matcher.is_admin(&obj) {
            continue;
        }
        if let &osmpbfreader::OsmObj::Relation(ref relation) = obj {
            let level = relation.tags
                                .get("admin_level")
                                .and_then(|s| s.parse().ok());
            let level = match level {
                None => {
                    info!("invalid admin_level for relation {}: admin_level {:?}",
                          relation.id,
                          relation.tags.get("admin_level"));
                    continue;
                }
                Some(l) => l,
            };
            // administrative region with name ?
            let name = match relation.tags.get("name") {
                Some(val) => val,
                None => {
                    warn!("adminstrative region without name for relation {}:  admin_level {} \
                           ignored.",
                          relation.id,
                          level);
                    continue;
                }
            };
            // admininstrative region without coordinates
            let coord_centre = relation.refs
                                       .iter()
                                       .find(|rf| rf.role == "admin_centre")
                                       .and_then(|r| {
                                           objects.get(&r.member).and_then(|value| {
                                               match value {
                                                   &osmpbfreader::OsmObj::Node(ref node) => {
                                                       Some(mimir::Coord {
                                                           lat: node.lat,
                                                           lon: node.lon,
                                                       })
                                                   }
                                                   _ => None,
                                               }
                                           })
                                       });

            let admin_id = match relation.tags.get("ref:INSEE") {
                Some(val) => format!("admin:fr:{}", val.trim_left_matches('0')),
                None => format!("admin:osm:{}", relation.id),
            };
            let zip_code = match relation.tags.get("addr:postcode") {
                Some(val) => &val[..],
                None => "",
            };
            let boundary = build_boundary(&relation, &objects);
            let admin = mimir::Admin {
                id: admin_id,
                level: level,
                name: name.to_string(),
                zip_code: zip_code.to_string(),
                // TODO weight value ?
                weight: 1,
                coord: coord_centre,
                boundary: boundary,
            };
            administrative_regions.push(admin);
        }
    }
    return administrative_regions;
}

fn streets(pbf: &mut ParsedPbf) -> StreetsVec {

    let is_valid_obj = |obj: &osmpbfreader::OsmObj| -> bool {
        match *obj {
            osmpbfreader::OsmObj::Way(ref way) => {
                way.tags.get("highway").map_or(false, |x| !x.is_empty()) &&
                way.tags.get("name").map_or(false, |x| !x.is_empty())
            }
            osmpbfreader::OsmObj::Relation(ref rel) => {
                rel.tags.get("type").map_or(false, |v| v == "associatedStreet")
            }
            _ => false,
        }
    };

    let mut objs_map = osmpbfreader::get_objs_and_deps(pbf, is_valid_obj).unwrap();
    // Sometimes, streets can be devided into several "way"s that still have the same street name.
    // The reason why a street is devided may be that a part of the street become a bridge/tunne/etc.
    // In this case, a "relation" tagged with (type = associatedStreet) is used to group all these "way"s.
    // In order not to have doublons in autocompleion, we should keep only one "way" in the relation
    // and remove all the rest way whose street name is the same.
    let mut objs_to_remove = Vec::<osmpbfreader::OsmId>::new();

    for (_, rel_obj) in &objs_map {
        if let &osmpbfreader::OsmObj::Relation(ref rel) = rel_obj {
            let mut found = false;
            for ref_obj in &rel.refs {
                if let &osmpbfreader::OsmId::Way(_) = &ref_obj.member {
                    if !found {
                        found = true;
                        continue;
                    }
                    objs_to_remove.push(ref_obj.member.clone());
                };
            }
        };
    }

    for osm_id in objs_to_remove {
        objs_map.remove(&osm_id);
    }

    objs_map.iter()
            .filter_map(|(_, obj)| {
                if let &osmpbfreader::OsmObj::Way(ref way) = obj {
                    way.tags.get("name").and_then(|way_name| {
                        Some(mimirsbrunn::Street {
                            id: way.id.to_string(),
                            street_name: way_name.to_string(),
                            name: way_name.to_string(),
                            weight: 1,
                            administrative_region: None,
                        })
                    })
                } else {
                    None
                }
            })
            .collect()

}
// TODO: template these two functions
fn index_admin(es_cnx_string: &str, admins: AdminsVec) {
    let mut rubber = Rubber::new(es_cnx_string);
    match rubber.clean_db_by_doc_type(&["admin"]) {
        Err(e) => panic!("failed to clean data for admin: {}", e),
        Ok(nb) => info!("Nb of cleaned indexed admins: {}", nb),
    }
    match rubber.bulk_index(admins.iter()) {
        Err(e) => panic!("failed to index admins of osm because: {}", e),
        Ok(nb) => info!("Nb of indexed adminstrative regions: {}", nb),
    }
}

fn index_ways(es_cnx_string: &str, streets: StreetsVec) {
    let mut rubber = Rubber::new(es_cnx_string);
    match rubber.clean_db_by_doc_type(&["street"]) {
        Err(e) => panic!("failed to clean data for street: {}", e),
        Ok(nb) => info!("Nb of cleaned indexed streets: {}", nb),
    }
    match rubber.bulk_index(streets.iter()) {
        Err(e) => panic!("failed to index streets of osm because: {}", e),
        Ok(nb) => info!("Nb of indexed street: {}", nb),
    }
}

fn index_settings(es_cnx_string: &str) {
    let mut rubber = Rubber::new(es_cnx_string);
    rubber.create_index();
}

fn main() {
    mimir::logger_init().unwrap();
    debug!("importing adminstrative region into Mimir");
    let args: Args = docopt::Docopt::new(USAGE)
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| e.exit());

    let levels = args.flag_level.iter().cloned().collect();
    let mut parsed_pbf = parse_osm_pbf(&args.flag_input);

    let admins = administrative_regions(&mut parsed_pbf, levels);

    index_settings(&args.flag_connection_string);
    index_admin(&args.flag_connection_string, admins);

    let mut optinoal_streets: Option<StreetsVec> = None;
    if args.flag_import_way {
        optinoal_streets = Some(streets(&mut parsed_pbf));
    }

    if let Some(streets) = optinoal_streets {
        index_ways(&args.flag_connection_string, streets);
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>Example of using reference instead of passing ownership<commit_after>fn main() {
    let s = String::from("Hello there!");

    // We're using reference here so the s is not invalidated
    let len = calculate_length(&s);
    println!("The length of {} is {}.", s, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}
<|endoftext|>