<commit_before>use std::error::Error;
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;
use std::fs::File as FSFile;
use std::io::Read;

use glob::glob;
use glob::Paths;

use storage::file::File;
use storage::file_id::*;

pub type BackendOperationResult = Result<(), StorageBackendError>;

pub struct StorageBackend {
    basepath: String,
}

impl StorageBackend {

    fn new(basepath: String) -> StorageBackend {
        StorageBackend {
            basepath: basepath,
        }
    }

    fn getFileList(&self) -> Option<Vec<FileID>> {
        let list = glob(&self.basepath[..]);

        if let Ok(globlist) = list {
            let mut v = vec![];
            for entry in globlist {
                if let Ok(path) = entry {
                    v.push(from_pathbuf(&path));
                } else {
                    // Entry is not a path
                }
            }

            Some(v)
        } else {
            None
        }
    }

    /*
     * Write a file to disk.
     *
     * The file is moved to this function as the file won't be edited afterwards
     */
    pub fn put_file(f: File) -> BackendOperationResult {
    }

    /*
     * Update a file. We have the UUID and can find the file on FS with it and
     * then replace its contents with the contents of the passed file object
     */
    pub fn update_file(f: File) -> BackendOperationResult {
    }

    /*
     * Find a file by its ID and return it if found. Return nothing if not
     * found, of course.
     *
     * TODO: Needs refactoring, as there might be an error when reading from
     * disk OR the id just does not exist.
     */
    pub fn get_file_by_id(id: FileID) -> Option<File> {
    }

}

#[derive(Debug)]
pub struct StorageBackendError {
    pub action: String,             // The file system action in words
    pub desc: String,               // A short description
    pub explanation: String,        // A long, user friendly description
    pub dataDump: Option<String>    // Data dump, if any
}

impl StorageBackendError {
    fn new(action: &'static str,
           desc  : &'static str,
           explan: &'static str,
           data  : Option<String>) -> StorageBackendError
    {
        StorageBackendError {
            action:         String::from(action),
            desc:           String::from(desc),
            explanation:    String::from(explan),
            dataDump:       data,
        }
    }
}

impl Error for StorageBackendError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for StorageBackendError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "StorageBackendError[{}]: {}\n\n{}",
               self.action, self.desc, self.explanation)
    }
}

<commit_msg>Rename function to match naming scheme<commit_after>use std::error::Error;
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;
use std::fs::File as FSFile;
use std::io::Read;

use glob::glob;
use glob::Paths;

use storage::file::File;
use storage::file_id::*;

pub type BackendOperationResult = Result<(), StorageBackendError>;

pub struct StorageBackend {
    basepath: String,
}

impl StorageBackend {

    fn new(basepath: String) -> StorageBackend {
        StorageBackend {
            basepath: basepath,
        }
    }

    fn get_file_ids(&self) -> Option<Vec<FileID>> {
        let list = glob(&self.basepath[..]);

        if let Ok(globlist) = list {
            let mut v = vec![];
            for entry in globlist {
                if let Ok(path) = entry {
                    v.push(from_pathbuf(&path));
                } else {
                    // Entry is not a path
                }
            }

            Some(v)
        } else {
            None
        }
    }

    /*
     * Write a file to disk.
     *
     * The file is moved to this function as the file won't be edited afterwards
     */
    pub fn put_file(f: File) -> BackendOperationResult {
    }

    /*
     * Update a file. We have the UUID and can find the file on FS with it and
     * then replace its contents with the contents of the passed file object
     */
    pub fn update_file(f: File) -> BackendOperationResult {
    }

    /*
     * Find a file by its ID and return it if found. Return nothing if not
     * found, of course.
     *
     * TODO: Needs refactoring, as there might be an error when reading from
     * disk OR the id just does not exist.
     */
    pub fn get_file_by_id(id: FileID) -> Option<File> {
    }

}

#[derive(Debug)]
pub struct StorageBackendError {
    pub action: String,             // The file system action in words
    pub desc: String,               // A short description
    pub explanation: String,        // A long, user friendly description
    pub dataDump: Option<String>    // Data dump, if any
}

impl StorageBackendError {
    fn new(action: &'static str,
           desc  : &'static str,
           explan: &'static str,
           data  : Option<String>) -> StorageBackendError
    {
        StorageBackendError {
            action:         String::from(action),
            desc:           String::from(desc),
            explanation:    String::from(explan),
            dataDump:       data,
        }
    }
}

impl Error for StorageBackendError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for StorageBackendError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "StorageBackendError[{}]: {}\n\n{}",
               self.action, self.desc, self.explanation)
    }
}

<|endoftext|>


<commit_before>mod terminal;
mod ansi;

use std::io::{self, Write};
use self::terminal::{Terminal, Event, Key};
use self::ansi::{clear, cursor};
use rff::choice::Choice;

#[derive(Debug)]
pub enum Error {
    CtrlC,
    Write(io::Error),
    Reset(terminal::Error)
}

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

impl From<terminal::Error> for Error {
    fn from(err: terminal::Error) -> Error {
        Error::Reset(err)
    }
}

pub struct Interface {
    choices: Vec<String>,
    matching: Vec<Choice>,
    search: String,
    terminal: Terminal
}

impl Interface {
    /// Creates a new Interface with the provided input choices.
    pub fn with_choices(choices: Vec<String>) -> Interface {
        let mut term = Terminal::from("/dev/tty").unwrap();
        term.set_raw_mode().unwrap();

        Interface {
            choices: choices,
            matching: Vec::new(),
            search: String::new(),
            terminal: term
        }
    }

    // Starts the interface
    pub fn run(&mut self) -> Result<&str, Error> {
        self.filter_choices();
        self.render()?;

        for event in self.terminal.events()? {
            match event? {
                Event::Key(Key::Ctrl('c')) => {
                    self.clear()?;
                    return Err(Error::CtrlC);
                },

                Event::Key(Key::Char('\n')) => {
                    break;
                },

                Event::Key(Key::Char(ch)) => {
                    self.search.push(ch);
                    self.filter_choices();
                    self.render()?;
                },

                Event::Key(Key::Backspace) => {
                    self.search.pop();
                    self.filter_choices();
                    self.render()?;
                },

                _ => {}
            };
        }

        self.clear()?;
        Ok(self.result())
    }

    fn filter_choices(&mut self) {
        let mut matches = self.choices.
            iter().
            cloned().
            filter_map(|choice| Choice::new(&self.search, choice)).
            collect::<Vec<_>>();

        matches.sort_by(|a, b| b.partial_cmp(a).unwrap());

        self.matching = matches;
    }

    fn render(&mut self) -> io::Result<()> {
        write!(self.terminal, "{}{}", clear::Screen, cursor::Column(1))?;
        write!(self.terminal, "> {}", self.search)?;

        let n = self.render_choices()?;

        if n > 0 {
            let column = format!("> {}", self.search).len() as u16;
            write!(self.terminal, "{}{}", cursor::Up(n), cursor::Column(column + 1))?;
        }

        Ok(())
    }

    fn render_choices(&mut self) -> io::Result<u16> {
        let max_width = self.terminal.max_width as usize;

        let choices = self.matching.
            iter().
            map(|c| c.text()).
            map(|c| {
                c.chars().take(max_width).collect::<String>()
            }).take(10);

        let number_of_choices = choices.len() as u16;

        for choice in choices {
            write!(self.terminal, "\r\n{}", choice)?;
        }

        Ok(number_of_choices)
    }

    fn clear(&mut self) -> Result<(), Error> {
        write!(self.terminal, "{}{}", cursor::Column(1), clear::Screen)?;
        self.terminal.reset()?;
        Ok(())
    }

    fn result(&mut self) -> &str {
        self.matching.iter().map(|c| c.text()).nth(0).unwrap_or("")
    }
}
<commit_msg>Introduce concept of selected match<commit_after>mod terminal;
mod ansi;

use std::io::{self, Write};
use self::terminal::{Terminal, Event, Key};
use self::ansi::{clear, cursor, style};
use rff::choice::Choice;

#[derive(Debug)]
pub enum Error {
    CtrlC,
    Write(io::Error),
    Reset(terminal::Error)
}

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

impl From<terminal::Error> for Error {
    fn from(err: terminal::Error) -> Error {
        Error::Reset(err)
    }
}

pub struct Interface {
    choices: Vec<String>,
    matching: Vec<Choice>,
    selected: usize,
    search: String,
    terminal: Terminal
}

impl Interface {
    /// Creates a new Interface with the provided input choices.
    pub fn with_choices(choices: Vec<String>) -> Interface {
        let mut term = Terminal::from("/dev/tty").unwrap();
        term.set_raw_mode().unwrap();

        Interface {
            choices: choices,
            matching: Vec::new(),
            selected: 0,
            search: String::new(),
            terminal: term
        }
    }

    // Starts the interface
    pub fn run(&mut self) -> Result<&str, Error> {
        self.filter_choices();
        self.render()?;

        for event in self.terminal.events()? {
            match event? {
                Event::Key(Key::Ctrl('c')) => {
                    self.clear()?;
                    return Err(Error::CtrlC);
                },

                Event::Key(Key::Char('\n')) => {
                    break;
                },

                Event::Key(Key::Char(ch)) => {
                    self.search.push(ch);
                    self.filter_choices();
                    self.render()?;
                },

                Event::Key(Key::Backspace) => {
                    self.search.pop();
                    self.filter_choices();
                    self.render()?;
                },

                _ => {}
            };
        }

        self.clear()?;
        Ok(self.result())
    }

    fn filter_choices(&mut self) {
        let mut matches = self.choices.
            iter().
            cloned().
            filter_map(|choice| Choice::new(&self.search, choice)).
            collect::<Vec<_>>();

        matches.sort_by(|a, b| b.partial_cmp(a).unwrap());

        self.matching = matches;
    }

    fn render(&mut self) -> io::Result<()> {
        write!(self.terminal, "{}{}", clear::Screen, cursor::Column(1))?;
        write!(self.terminal, "> {}", self.search)?;

        let n = self.render_choices()?;

        if n > 0 {
            let column = format!("> {}", self.search).len() as u16;
            write!(self.terminal, "{}{}", cursor::Up(n), cursor::Column(column + 1))?;
        }

        Ok(())
    }

    fn render_choices(&mut self) -> io::Result<u16> {
        let max_width = self.terminal.max_width as usize;

        let choices = self.matching.
            iter().
            map(|c| c.text()).
            map(|c| {
                c.chars().take(max_width).collect::<String>()
            }).take(10);

        let number_of_choices = choices.len() as u16;

        for (i, choice) in choices.enumerate() {
            write!(self.terminal, "\r\n")?;

            if i == self.selected {
                let invert = style::Invert;
                let reset = style::NoInvert;
                write!(self.terminal, "{}{}{}", invert, choice, reset)?;
            } else {
                write!(self.terminal, "{}", choice)?;
            }
        }

        Ok(number_of_choices)
    }

    fn clear(&mut self) -> Result<(), Error> {
        write!(self.terminal, "{}{}", cursor::Column(1), clear::Screen)?;
        self.terminal.reset()?;
        Ok(())
    }

    fn result(&mut self) -> &str {
        self.matching.iter().
            map(|c| c.text()).
            nth(self.selected).
            unwrap_or(&self.search)
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Read, BufRead};
use std::mem;

use futures::{Poll, Future};

/// A future which can be used to easily read the contents of a stream into a
/// vector until the delimiter is reached.
///
/// Created by the [`read_until`] function.
///
/// [`read_until`]: fn.read_until.html
pub struct ReadUntil {
    state: State,
}

enum State {
    Reading {
        a: A,
        byte: u8,
        buf: Vec<u8>,
    },
    Empty,
}

/// Creates a future which will read all the bytes associated with the I/O
/// object `A` into the buffer provided until the delimiter `byte` is reached.
/// This method is the async equivalent to [`BufRead::read_until`].
///
/// In case of an error the buffer and the object will be discarded, with
/// the error yielded. In the case of success the object will be destroyed and
/// the buffer will be returned, with all bytes up to, and including, the delimiter
/// (if found).
///
/// [`ButRead::read_until`]: https://doc.rust-lang.org/std/io/trait.BufRead.html#method.read_until
pub fn read_until(a: A, byte: u8, buf: Vec<u8>) -> ReadUntil
    where A: BufRead
{
    ReadUntil {
        state: State::Reading {
            a: a,
            byte: byte,
            buf: buf,
        }
    }
}

impl Future for ReadUntil
    where A: Read + BufRead
{
    type Item = (A, Vec<u8>);
    type Error = io::Error;

    fn poll(&mut self) -> Poll<(A, Vec<u8>), io::Error> {
        match self.state {
            State::Reading { ref mut a, byte, ref mut buf } => {
                // If we get `Ok(n)`, then we know the stream hit EOF or the delimiter.
                // If we got EOF (n == 0), then we return an error.
                // If we hit "would block" then all the read data so far
                // is in our buffer, and otherwise we propagate errors.
                // If we reached our delimiter (n != 0), then we are finished.
                let n = try_nb!(a.read_until(byte, buf));
                if n == 0 && buf.len() == 0 {
                    return Err(io::Error::new(io::ErrorKind::BrokenPipe, "Broken Pipe"));
                }
            },
            State::Empty => panic!("poll ReadUntil after it's done"),
        }

        match mem::replace(&mut self.state, State::Empty) {
            State::Reading { a, byte: _, buf } => Ok((a, buf).into()),
            State::Empty => unreachable!(),
        }
    }
}
<commit_msg>fix(read_until): Make `read_until` resemble `BufRead::read_until`<commit_after>use std::io::{self, Read, BufRead};
use std::mem;

use futures::{Poll, Future};

/// A future which can be used to easily read the contents of a stream into a
/// vector until the delimiter is reached.
///
/// Created by the [`read_until`] function.
///
/// [`read_until`]: fn.read_until.html
pub struct ReadUntil {
    state: State,
}

enum State {
    Reading {
        a: A,
        byte: u8,
        buf: Vec<u8>,
    },
    Empty,
}

/// Creates a future which will read all the bytes associated with the I/O
/// object `A` into the buffer provided until the delimiter `byte` is reached.
/// This method is the async equivalent to [`BufRead::read_until`].
///
/// In case of an error the buffer and the object will be discarded, with
/// the error yielded. In the case of success the object will be destroyed and
/// the buffer will be returned, with all bytes up to, and including, the delimiter
/// (if found).
///
/// [`ButRead::read_until`]: https://doc.rust-lang.org/std/io/trait.BufRead.html#method.read_until
pub fn read_until(a: A, byte: u8, buf: Vec<u8>) -> ReadUntil
    where A: BufRead
{
    ReadUntil {
        state: State::Reading {
            a: a,
            byte: byte,
            buf: buf,
        }
    }
}

impl Future for ReadUntil
    where A: Read + BufRead
{
    type Item = (A, Vec<u8>);
    type Error = io::Error;

    fn poll(&mut self) -> Poll<(A, Vec<u8>), io::Error> {
        match self.state {
            State::Reading { ref mut a, byte, ref mut buf } => {
                // If we get `Ok(n)`, then we know the stream hit EOF or the delimiter.
                // and just return it, as we are finished.
                // If we hit "would block" then all the read data so far
                // is in our buffer, and otherwise we propagate errors.
                try_nb!(a.read_until(byte, buf));
            },
            State::Empty => panic!("poll ReadUntil after it's done"),
        }

        match mem::replace(&mut self.state, State::Empty) {
            State::Reading { a, byte: _, buf } => Ok((a, buf).into()),
            State::Empty => unreachable!(),
        }
    }
}
<|endoftext|>


<commit_before>mod trajectory;
use trajectory::*;
mod energy;
use energy::*;

const LJ_EPS : f64 = 1.0;
const LJ_SIG : f64 = 1.0;

fn get_derived_pair_potential(distance: f64) -> f64 {
    let r = LJ_SIG/distance;
    let r3 = r*r*r;
    let r4 = r*r*r*r;
    return 24.0 * LJ_EPS / LJ_SIG * ( r4*r3 - 2.0*(r4*r4*r4*r) )
}

fn get_distance_with_pbc(x1: f64, x2: f64, length: f64, half_length: f64) -> f64 {
    let mut d = x1-x2;
    if d > half_length { d -= length }
    else if d < -half_length { d += length }
    return d;
}

fn main() {

    let mut trj_reader = TrjReader::new(&"2phases/10k_1step.xyz".to_string());
    let mut frame = trj_reader.next_frame();

    let volume = frame.box_x * frame.box_y * frame.box_z;
    let density = frame.num_particles as f64 / volume;

    let box_half_x = frame.box_x / 2.0;
    let box_half_y = frame.box_y / 2.0;
    let box_half_z = frame.box_z / 2.0;

    let mut frame_count = 0;
    let mut trace_xy_sum = 0.0;
    let mut trace_z_sum = 0.0;
    let mut p_normal_sum = 0.0;
    let mut p_tangial_sum = 0.0;
    let mut p_diff_sum = 0.0;

    let variable_without_name = frame.temperature/LJ_EPS * density;
    loop {
        frame_count += 1;

        let mut trace_xy = 0.0;
        let mut trace_z = 0.0;
        for i in 0..frame.num_particles {
            for j in i+1..frame.num_particles {
                let dist = get_particle_distance(frame.rx[i], frame.ry[i], frame.rz[i], frame.rx[j], frame.ry[j], frame.rz[j], frame.box_x, frame.box_y, frame.box_z, box_half_x, box_half_y, box_half_z);
                let dx = get_distance_with_pbc(frame.rx[i], frame.rx[j], frame.box_x, box_half_x);
                let dy = get_distance_with_pbc(frame.ry[i], frame.ry[j], frame.box_y, box_half_y);
                let dz = get_distance_with_pbc(frame.rz[i], frame.rz[j], frame.box_z, box_half_z);
                trace_xy += (dx * dx  + dy * dy) / dist * get_derived_pair_potential(dist);
                trace_z += (dz * dz) / dist * get_derived_pair_potential(dist);
            }
        }
        let p_tangial = variable_without_name - 1.0/(2.0*volume)*trace_xy;
        let p_normal = variable_without_name - 1.0/volume*trace_z;
        let p_diff = p_normal - p_tangial_sum;
        p_diff_sum += p_diff;
        p_tangial_sum += p_tangial;
        p_normal_sum += p_normal;
        trace_xy_sum += trace_xy;
        trace_z_sum += trace_z;

        ///////////////////////////////////

        if frame_count % 100 == 0 {
            print!(".");
        }

        if frame_count % 100 == 0 {
//            let trace_xy_avg = trace_xy_sum / frame_count as f64;
//            let trace_z_avg = trace_z_sum / frame_count as f64;
            let p_tangial = p_tangial_sum / frame_count as f64;
            let p_normal = p_normal_sum / frame_count as f64;
            let surface_tension = frame.box_z/2.0*(p_diff_sum/frame_count as f64);
            println!("{}  tangial: {}   normal: {}    diff: {}    tension:   {}", frame_count, p_tangial, p_normal, p_diff_sum/frame_count as f64, surface_tension);

            frame_count = 0;
            trace_xy_sum = 0.0;
            trace_z_sum = 0.0;
            p_tangial_sum = 0.0;
            p_normal_sum = 0.0

        }

        if !trj_reader.update_with_next(&mut frame) { break }
    }

}

//        for slab in 0..NUM_SLABS {
//
//            // calculate slab density
//            let slab_end_z = slab_height * slab as f64;
//            let slab_start_z = slab_end_z - slab_height;
//            let mut slab_particle_count = 0;
//            for i in 0..frame.num_particles {
//                if slab_start_z > frame.rz[i] && frame.rz[i] < slab_end_z {
//                    slab_particle_count += 1;
//                }
//            }
//            let slab_density = slab_particle_count as f64 / slab_volume;
//
//            for i in 0..frame.num_particles {
//                for j in i+1..frame.num_particles {
//
//                }
//            }
//
//            println!("Slab {}\tDensity: {}", slab, slab_density);
//        }<commit_msg>surface tension fix<commit_after>mod trajectory;
use trajectory::*;
mod energy;
use energy::*;

const LJ_EPS : f64 = 1.0;
const LJ_SIG : f64 = 1.0;

fn get_virial(distance_sqr: f64) -> f64 {
    let r2 = LJ_SIG.powi(2)/distance_sqr;
    let r6 = r2 * r2 * r2;
    return 48.0 * LJ_EPS / LJ_SIG * ( r6*r6 - 0.5*r6 )
}

fn get_distance_with_pbc(x1: f64, x2: f64, length: f64, half_length: f64) -> f64 {
    let mut d = x1-x2;
    if d > half_length { d -= length }
    else if d < -half_length { d += length }
    return d;
}

fn main() {

    let mut trj_reader = TrjReader::new(&"2phases/1kk_100step.xyz".to_string());
    let mut frame = trj_reader.next_frame();

    let volume = frame.box_x * frame.box_y * frame.box_z;
    let density = frame.num_particles as f64 / volume;
    let num_particles = frame.num_particles;

    let box_half_x = frame.box_x / 2.0;
    let box_half_y = frame.box_y / 2.0;
    let box_half_z = frame.box_z / 2.0;

    let mut frame_count = 0;
    let mut p_xy_sum = 0.0;
//    let mut p_y_sum = 0.0;
    let mut p_z_sum = 0.0;

    let variable_without_name = frame.temperature/LJ_EPS * density;

    loop {
        frame_count += 1;

        let mut trace_xy = 0.0;
//        let mut trace_y = 0.0;
        let mut trace_z = 0.0;
        for i in 0..num_particles {
            for j in i+1..num_particles {
                let dist_sqrt = get_particle_distance_squared(frame.rx[i], frame.ry[i], frame.rz[i], frame.rx[j], frame.ry[j], frame.rz[j], frame.box_x, frame.box_y, frame.box_z, box_half_x, box_half_y, box_half_z);
                let dist = dist_sqrt.sqrt();
                let dx = get_distance_with_pbc(frame.rx[i], frame.rx[j], frame.box_x, box_half_x);
                let dy = get_distance_with_pbc(frame.ry[i], frame.ry[j], frame.box_y, box_half_y);
                let dz = get_distance_with_pbc(frame.rz[i], frame.rz[j], frame.box_z, box_half_z);
                let virial = get_virial(dist_sqrt);
                trace_xy += (dx * dx + dy * dy) / dist * virial;
//                trace_y += (dy * dy) / dist * virial;
                trace_z += (dz * dz) / dist * virial;
            }
        }
        let p_xy = variable_without_name - 1.0/(2.0*volume)*(trace_xy/num_particles as f64);
//        let p_yy = variable_without_name - 1.0/volume*(trace_y/num_particles);
        let p_zz = variable_without_name - 1.0/volume*(trace_z/num_particles as f64);

        p_xy_sum += p_xy;
//        p_y_sum += p_yy;
        p_z_sum += p_zz;

        ///////////////////////////////////

        if frame_count % 100 == 0 {
            print!(".");
        }

        if frame_count % 100 == 0 {
            let p_z_avg = p_z_sum / frame_count as f64;
            let p_xy_avg = p_xy_sum / frame_count as f64;
            let p_diff = p_z_avg - p_xy_avg;
            let surface_tension = (frame.box_z/2.0)*p_diff;
            println!("{}  zz: {}   xy: {}    diff: {}    tension:   {}", frame_count, p_z_avg, p_xy_avg, p_diff, surface_tension);

            frame_count = 0;
            p_z_sum = 0.0;
            p_xy_sum = 0.0;
//            trace_xy_sum = 0.0;
//            trace_z_sum = 0.0;
//            p_tangial_sum = 0.0;
//            p_normal_sum = 0.0

        }

        if !trj_reader.update_with_next(&mut frame) { break }
    }

}

//        for slab in 0..NUM_SLABS {
//
//            // calculate slab density
//            let slab_end_z = slab_height * slab as f64;
//            let slab_start_z = slab_end_z - slab_height;
//            let mut slab_particle_count = 0;
//            for i in 0..frame.num_particles {
//                if slab_start_z > frame.rz[i] && frame.rz[i] < slab_end_z {
//                    slab_particle_count += 1;
//                }
//            }
//            let slab_density = slab_particle_count as f64 / slab_volume;
//
//            for i in 0..frame.num_particles {
//                for j in i+1..frame.num_particles {
//
//                }
//            }
//
//            println!("Slab {}\tDensity: {}", slab, slab_density);
//        }<|endoftext|>


<commit_before>use protobuf::*;

use test::*;

use test_oneof_proto::*;

#[test]
fn test1() {
    let mut test1 = TestOneof::new();
    test1.set_uint32_field(150);
    test_serialize_deserialize("28 96 01", &test1);
}
<commit_msg>follow rust master: fix compilation<commit_after>use protobuf::*;

use test::*;

use test_oneof_proto::*;

#[test]
fn test_simple() {
    let mut test_message = TestOneof::new();
    test_message.set_uint32_field(150);
    test_serialize_deserialize("28 96 01", &test_message);
}
<|endoftext|>


<commit_before>use sync::{Arc, Mutex};
use conn::{MyInnerConn, MyOpts, MyResult, Stmt, QueryResult};

struct MyInnerPool {
    opts: MyOpts,
    pool: Vec<MyInnerConn>,
    cap: uint,
    count: uint
}

impl MyInnerPool {
    fn new_conn(&mut self) -> MyResult<()> {
        match MyInnerConn::new(self.opts.clone()) {
            Ok(conn) => {
                self.pool.push(conn);
                Ok(())
            },
            Err(err) => Err(err)
        }
    }
}

#[deriving(Clone)]
pub struct MyPool {
    pool: Arc<Mutex<MyInnerPool>>
}

impl MyPool {
    pub fn new(cap: uint, opts: MyOpts) -> MyPool {
        let pool = MyInnerPool {
            opts: opts,
            pool: Vec::new(),
            cap: cap,
            count: 0
        };
        MyPool{ pool: Arc::new(Mutex::new(pool)) }
    }

    pub fn get_conn(&self) -> MyResult<MyPooledConn> {
        let mut pool = self.pool.lock();

        while pool.pool.is_empty() {
            if pool.cap == 0 || pool.count < pool.cap {
                match pool.new_conn() {
                    Ok(()) => {
                        pool.count += 1;
                        break;
                    },
                    Err(err) => return Err(err)
                }
            } else {
                pool.cond.wait();
            }
        }

        let mut conn = pool.pool.pop().unwrap();

        if !conn.ping() {
            try!(conn.reset());
        }

        Ok(MyPooledConn {pool: self.clone(), conn: Some(conn)})
    }
    fn query(&self, query: &str) -> MyResult<QueryResult> {
        let conn = try!(self.get_conn());
        conn.pooled_query(query)
    }
    fn prepare(&self, query: &str) -> MyResult<Stmt> {
        let conn = try!(self.get_conn());
        conn.pooled_prepare(query)
    }
}

pub struct MyPooledConn {
    pool: MyPool,
    conn: Option<MyInnerConn>
}

impl Drop for MyPooledConn {
    fn drop(&mut self) {
        let mut pool = self.pool.pool.lock();
        pool.pool.push(self.conn.take_unwrap());
        pool.cond.signal();
    }
}

impl MyPooledConn {
    pub fn query<'a>(&'a mut self, query: &str) -> MyResult<QueryResult<'a>> {
        self.conn.get_mut_ref().query(query)
    }
    pub fn prepare<'a>(&'a mut self, query: &str) -> MyResult<Stmt<'a>> {
        self.conn.get_mut_ref().prepare(query)
    }
    pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut MyInnerConn {
        self.conn.get_mut_ref()
    }
    pub fn get_ref<'a>(&'a self) -> &'a MyInnerConn {
        self.conn.get_ref()
    }
    fn pooled_query(mut self, query: &str) -> MyResult<QueryResult> {
        match self.get_mut_ref()._query(query) {
            Ok((columns, ok_packet)) => Ok(QueryResult::new_pooled(self, columns, ok_packet, false)),
            Err(err) => Err(err)
        }
    }
    fn pooled_prepare(mut self, query: &str) -> MyResult<Stmt> {
        match self.get_mut_ref()._prepare(query) {
            Ok(stmt) => Ok(Stmt::new_pooled(stmt, self)),
            Err(err) => Err(err)
        }
    }
}

#[cfg(test)]
mod test {
    use conn::{MyOpts};
    use std::default::{Default};
    use super::{MyPool};
    use super::super::value::{Bytes, Int};

    #[test]
    fn test_query() {
        let pool = MyPool::new(3, MyOpts{user: Some("root".to_string()),
                                         ..Default::default()});
        for _ in range(0, 10) {
            let pool = pool.clone();
            spawn(proc() {
                let conn = pool.get_conn();
                assert!(conn.is_ok());
                let mut conn = conn.unwrap();
                assert!(conn.query("SELECT 1").is_ok());
            });
        }
    }

    #[test]
    fn test_pooled_query() {
        let pool = MyPool::new(3, MyOpts{user: Some("root".to_string()),
                                         ..Default::default()});
        for _ in range(0, 10) {
            let pool = pool.clone();
            spawn(proc() {
                let result = pool.query("SELECT 1");
                assert!(result.is_ok());
                let mut result = result.unwrap();
                assert_eq!(result.next(), Some(Ok(vec![Bytes(vec![0x31u8])])));
            });
        }
    }

    #[test]
    fn test_prepared_query() {
        let pool = MyPool::new(3, MyOpts{user: Some("root".to_string()),
                                         ..Default::default()});
        for _ in range(0, 10) {
            let pool = pool.clone();
            spawn(proc() {
                let conn = pool.get_conn();
                assert!(conn.is_ok());
                let mut conn = conn.unwrap();
                let stmt = conn.prepare("SELECT 1");
                assert!(stmt.is_ok());
                let mut stmt = stmt.unwrap();
                assert!(stmt.execute([]).is_ok());
            });
        }
    }

    #[test]
    fn test_pooled_prepared_query() {
        let pool = MyPool::new(3, MyOpts{user: Some("root".to_string()),
                                         ..Default::default()});
        for _ in range(0, 10) {
            let pool = pool.clone();
            spawn(proc() {
                let stmt = pool.prepare("SELECT 1");
                assert!(stmt.is_ok());
                let mut stmt = stmt.unwrap();
                for _ in range(0, 5) {
                    let result = stmt.execute([]);
                    assert!(result.is_ok());
                    let mut result = result.unwrap();
                    assert_eq!(result.next(), Some(Ok(vec![Int(1)])));
                    assert_eq!(result.next(), None);
                }
            });
        }
    }

    #[test]
    fn test_zero_cap() {
        let pool = MyPool::new(0, MyOpts{user: Some("root".to_string()),
                                         ..Default::default()});
        for _ in range(0, 10) {
            let pool = pool.clone();
            spawn(proc() {
                let conn = pool.get_conn();
                assert!(conn.is_ok());
                let mut conn = conn.unwrap();
                assert!(conn.query("SELECT 1").is_ok());
            });
        }
    }
}
<commit_msg>Improve connection pooling strategy<commit_after>use sync::{Arc, Mutex};
use super::error::{MyStrError};
use conn::{MyInnerConn, MyOpts, MyResult, Stmt, QueryResult};

struct MyInnerPool {
    opts: MyOpts,
    pool: Vec<MyInnerConn>,
    min: uint,
    max: uint,
    count: uint
}

impl MyInnerPool {
    fn new(min: uint, max: uint, opts: MyOpts) -> MyResult<MyInnerPool> {
        if min > max || max == 0 {
            return Err(MyStrError("Invalid pool constraints".to_string()));
        }
        let mut pool = MyInnerPool {
            opts: opts,
            pool: Vec::with_capacity(max),
            max: max,
            min: min,
            count: 0
        };
        for _ in range(0, min) {
            try!(pool.new_conn());
        }
        Ok(pool)
    }
    fn new_conn(&mut self) -> MyResult<()> {
        match MyInnerConn::new(self.opts.clone()) {
            Ok(conn) => {
                self.pool.push(conn);
                Ok(())
            },
            Err(err) => Err(err)
        }
    }
}

#[deriving(Clone)]
pub struct MyPool {
    pool: Arc<Mutex<MyInnerPool>>
}

impl MyPool {
    pub fn new(opts: MyOpts) -> MyResult<MyPool> {
        MyPool::new_manual(10, 100, opts)
    }

    pub fn new_manual(min: uint, max: uint, opts: MyOpts) -> MyResult<MyPool> {
        let pool = try!(MyInnerPool::new(min, max, opts));
        Ok(MyPool{ pool: Arc::new(Mutex::new(pool)) })
    }

    pub fn get_conn(&self) -> MyResult<MyPooledConn> {
        let mut pool = self.pool.lock();

        while pool.pool.is_empty() {
            if pool.count < pool.max {
                match pool.new_conn() {
                    Ok(()) => {
                        pool.count += 1;
                        break;
                    },
                    Err(err) => return Err(err)
                }
            } else {
                pool.cond.wait();
            }
        }

        let mut conn = pool.pool.pop().unwrap();

        if !conn.ping() {
            try!(conn.reset());
        }

        Ok(MyPooledConn {pool: self.clone(), conn: Some(conn)})
    }
    fn query(&self, query: &str) -> MyResult<QueryResult> {
        let conn = try!(self.get_conn());
        conn.pooled_query(query)
    }
    fn prepare(&self, query: &str) -> MyResult<Stmt> {
        let conn = try!(self.get_conn());
        conn.pooled_prepare(query)
    }
}

pub struct MyPooledConn {
    pool: MyPool,
    conn: Option<MyInnerConn>
}

impl Drop for MyPooledConn {
    fn drop(&mut self) {
        let mut pool = self.pool.pool.lock();
        if pool.count > pool.min {
            pool.count -= 1;
        } else {
            pool.pool.push(self.conn.take_unwrap());
        }
        pool.cond.signal();
    }
}

impl MyPooledConn {
    pub fn query<'a>(&'a mut self, query: &str) -> MyResult<QueryResult<'a>> {
        self.conn.get_mut_ref().query(query)
    }
    pub fn prepare<'a>(&'a mut self, query: &str) -> MyResult<Stmt<'a>> {
        self.conn.get_mut_ref().prepare(query)
    }
    pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut MyInnerConn {
        self.conn.get_mut_ref()
    }
    pub fn get_ref<'a>(&'a self) -> &'a MyInnerConn {
        self.conn.get_ref()
    }
    fn pooled_query(mut self, query: &str) -> MyResult<QueryResult> {
        match self.get_mut_ref()._query(query) {
            Ok((columns, ok_packet)) => Ok(QueryResult::new_pooled(self, columns, ok_packet, false)),
            Err(err) => Err(err)
        }
    }
    fn pooled_prepare(mut self, query: &str) -> MyResult<Stmt> {
        match self.get_mut_ref()._prepare(query) {
            Ok(stmt) => Ok(Stmt::new_pooled(stmt, self)),
            Err(err) => Err(err)
        }
    }
}

#[cfg(test)]
mod test {
    use conn::{MyOpts};
    use std::default::{Default};
    use super::{MyPool};
    use super::super::value::{Bytes, Int};

    #[test]
    fn test_query() {
        let pool = MyPool::new(MyOpts{user: Some("root".to_string()),
                                      ..Default::default()});
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        for _ in range(0, 10) {
            let pool = pool.clone();
            spawn(proc() {
                let conn = pool.get_conn();
                assert!(conn.is_ok());
                let mut conn = conn.unwrap();
                assert!(conn.query("SELECT 1").is_ok());
            });
        }
    }

    #[test]
    fn test_pooled_query() {
        let pool = MyPool::new(MyOpts{user: Some("root".to_string()),
                                      ..Default::default()});
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        for _ in range(0, 10) {
            let pool = pool.clone();
            spawn(proc() {
                let result = pool.query("SELECT 1");
                assert!(result.is_ok());
                let mut result = result.unwrap();
                assert_eq!(result.next(), Some(Ok(vec![Bytes(vec![0x31u8])])));
            });
        }
    }

    #[test]
    fn test_prepared_query() {
        let pool = MyPool::new(MyOpts{user: Some("root".to_string()),
                                      ..Default::default()});
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        for _ in range(0, 10) {
            let pool = pool.clone();
            spawn(proc() {
                let conn = pool.get_conn();
                assert!(conn.is_ok());
                let mut conn = conn.unwrap();
                let stmt = conn.prepare("SELECT 1");
                assert!(stmt.is_ok());
                let mut stmt = stmt.unwrap();
                assert!(stmt.execute([]).is_ok());
            });
        }
    }

    #[test]
    fn test_pooled_prepared_query() {
        let pool = MyPool::new(MyOpts{user: Some("root".to_string()),
                                      ..Default::default()});
        assert!(pool.is_ok());
        let pool = pool.unwrap();
        for _ in range(0, 10) {
            let pool = pool.clone();
            spawn(proc() {
                let stmt = pool.prepare("SELECT 1");
                assert!(stmt.is_ok());
                let mut stmt = stmt.unwrap();
                for _ in range(0, 5) {
                    let result = stmt.execute([]);
                    assert!(result.is_ok());
                    let mut result = result.unwrap();
                    assert_eq!(result.next(), Some(Ok(vec![Int(1)])));
                    assert_eq!(result.next(), None);
                }
            });
        }
    }
}
<|endoftext|>


<commit_before>use super::*;
use crate::{error::*, layout::MatrixLayout};
use cauchy::*;
use num_traits::Zero;

pub trait Rcond_: Scalar + Sized {
    /// Estimates the the reciprocal of the condition number of the matrix in 1-norm.
    ///
    /// `anorm` should be the 1-norm of the matrix `a`.
    fn rcond(l: MatrixLayout, a: &[Self], anorm: Self::Real) -> Result<Self::Real>;
}

macro_rules! impl_rcond_real {
    ($scalar:ty, $gecon:path) => {
        impl Rcond_ for $scalar {
            fn rcond(l: MatrixLayout, a: &[Self], anorm: Self::Real) -> Result<Self::Real> {
                let (n, _) = l.size();
                let mut rcond = Self::Real::zero();
                let mut info = 0;

                let mut work = vec![Self::zero(); 4 * n as usize];
                let mut iwork = vec![0; n as usize];
                unsafe {
                    $gecon(
                        NormType::One as u8,
                        n,
                        a,
                        l.lda(),
                        anorm,
                        &mut rcond,
                        &mut work,
                        &mut iwork,
                        &mut info,
                    )
                };
                info.as_lapack_result()?;

                Ok(rcond)
            }
        }
    };
}

impl_rcond_real!(f32, lapack::sgecon);
impl_rcond_real!(f64, lapack::dgecon);

macro_rules! impl_rcond_complex {
    ($scalar:ty, $gecon:path) => {
        impl Rcond_ for $scalar {
            fn rcond(l: MatrixLayout, a: &[Self], anorm: Self::Real) -> Result<Self::Real> {
                let (n, _) = l.size();
                let mut rcond = Self::Real::zero();
                let mut info = 0;
                let mut work = vec![Self::zero(); 2 * n as usize];
                let mut rwork = vec![Self::Real::zero(); 2 * n as usize];
                unsafe {
                    $gecon(
                        NormType::One as u8,
                        n,
                        a,
                        l.lda(),
                        anorm,
                        &mut rcond,
                        &mut work,
                        &mut rwork,
                        &mut info,
                    )
                };
                info.as_lapack_result()?;

                Ok(rcond)
            }
        }
    };
}

impl_rcond_complex!(c32, lapack::cgecon);
impl_rcond_complex!(c64, lapack::zgecon);
<commit_msg>Handle norm type based on matrix layout<commit_after>use super::*;
use crate::{error::*, layout::MatrixLayout};
use cauchy::*;
use num_traits::Zero;

pub trait Rcond_: Scalar + Sized {
    /// Estimates the the reciprocal of the condition number of the matrix in 1-norm.
    ///
    /// `anorm` should be the 1-norm of the matrix `a`.
    fn rcond(l: MatrixLayout, a: &[Self], anorm: Self::Real) -> Result<Self::Real>;
}

macro_rules! impl_rcond_real {
    ($scalar:ty, $gecon:path) => {
        impl Rcond_ for $scalar {
            fn rcond(l: MatrixLayout, a: &[Self], anorm: Self::Real) -> Result<Self::Real> {
                let (n, _) = l.size();
                let mut rcond = Self::Real::zero();
                let mut info = 0;

                let mut work = vec![Self::zero(); 4 * n as usize];
                let mut iwork = vec![0; n as usize];
                let norm_type = match l {
                    MatrixLayout::C { .. } => NormType::Infinity,
                    MatrixLayout::F { .. } => NormType::One,
                } as u8;
                unsafe {
                    $gecon(
                        norm_type,
                        n,
                        a,
                        l.lda(),
                        anorm,
                        &mut rcond,
                        &mut work,
                        &mut iwork,
                        &mut info,
                    )
                };
                info.as_lapack_result()?;

                Ok(rcond)
            }
        }
    };
}

impl_rcond_real!(f32, lapack::sgecon);
impl_rcond_real!(f64, lapack::dgecon);

macro_rules! impl_rcond_complex {
    ($scalar:ty, $gecon:path) => {
        impl Rcond_ for $scalar {
            fn rcond(l: MatrixLayout, a: &[Self], anorm: Self::Real) -> Result<Self::Real> {
                let (n, _) = l.size();
                let mut rcond = Self::Real::zero();
                let mut info = 0;
                let mut work = vec![Self::zero(); 2 * n as usize];
                let mut rwork = vec![Self::Real::zero(); 2 * n as usize];
                let norm_type = match l {
                    MatrixLayout::C { .. } => NormType::Infinity,
                    MatrixLayout::F { .. } => NormType::One,
                } as u8;
                unsafe {
                    $gecon(
                        norm_type,
                        n,
                        a,
                        l.lda(),
                        anorm,
                        &mut rcond,
                        &mut work,
                        &mut rwork,
                        &mut info,
                    )
                };
                info.as_lapack_result()?;

                Ok(rcond)
            }
        }
    };
}

impl_rcond_complex!(c32, lapack::cgecon);
impl_rcond_complex!(c64, lapack::zgecon);
<|endoftext|>


<commit_before>//! Kata OS MemoryManager component support.

// Code here binds the camkes component to the rust code.
#![no_std]
#![allow(clippy::missing_safety_doc)]

use core::ops::Range;
use core::slice;
use kata_memory_interface::MemoryManagerError;
use kata_memory_interface::MemoryManagerInterface;
use kata_memory_interface::ObjDescBundle;
use kata_memory_interface::RawMemoryStatsData;
use kata_memory_manager::KataMemoryManager;
use kata_os_common::camkes::Camkes;
use kata_os_common::sel4_sys;
use log::trace;

use sel4_sys::seL4_BootInfo;
use sel4_sys::seL4_CNode_Delete;
use sel4_sys::seL4_CPtr;

static mut CAMKES: Camkes = Camkes::new("MemoryManager");

// NB: KATA_MEMORY cannot be used before setup is completed with a call to init()
static mut KATA_MEMORY: KataMemoryManager = KataMemoryManager::empty();

extern "C" {
    // Each CAmkES-component has a CNode setup at a well-known top-level slot.
    // We re-use that slot to receive CNode caps passed with alloc & free requests.
    static MEMORY_RECV_CNODE: seL4_CPtr;
}

#[no_mangle]
pub unsafe extern "C" fn pre_init() {
    // NB: set to max; the LoggerInterface will filter
    CAMKES.init_logger(log::LevelFilter::Trace);

    static mut HEAP_MEMORY: [u8; 8 * 1024] = [0; 8 * 1024];
    CAMKES.init_allocator(&mut HEAP_MEMORY);

    extern "C" {
        fn sel4runtime_bootinfo() -> *const seL4_BootInfo;
    }
    // The MemoryManager component is labeled to receive BootInfo); use
    // it to complete initialization of the MemoryManager interface.
    let bootinfo = &*sel4runtime_bootinfo();
    KATA_MEMORY.init(
        /*slots=*/Range::<seL4_CPtr> {
            start: bootinfo.untyped.start,
            end: bootinfo.untyped.end
        },
        /*untypeds=*/ bootinfo.untyped_descs(),
    );
    if let Ok(stats) = KATA_MEMORY.stats() {
        trace!("Global memory: {} allocated {} free",
            stats.allocated_bytes,
            stats.free_bytes,
        );
    }

    CAMKES.init_slot_allocator(bootinfo.empty.start, bootinfo.empty.end);

    // Delete the CAmkES-setup CNode; we're going to reuse the
    // well-known slot once it is empty (see memory__init below).
    let path = Camkes::top_level_path(MEMORY_RECV_CNODE);
    seL4_CNode_Delete(path.0, path.1, path.2 as u8).expect("recv_node");
}

#[no_mangle]
pub unsafe extern "C" fn memory__init() {
    // Point the receive path to the well-known slot that was emptied.
    // This will be used to receive CNode's from clients for alloc &
    // free requests.
    //
    // NB: this must be done here (rather than someplace like pre_init)
    // so it's in the context of the MemoryInterface thread (so we write
    // the correct ipc buffer).
    CAMKES.init_recv_path(&Camkes::top_level_path(MEMORY_RECV_CNODE));
}

// MemoryInterface glue stubs.

#[no_mangle]
pub unsafe extern "C" fn memory_alloc(
    c_raw_data_len: u32,
    c_raw_data: *const u8,
) -> MemoryManagerError {
    let recv_path = CAMKES.get_current_recv_path();
    // NB: make sure noone clobbers the setup done in memory__init
    CAMKES.assert_recv_path();

    let raw_slice = slice::from_raw_parts(c_raw_data, c_raw_data_len as usize);
    let ret_status = match postcard::from_bytes::<ObjDescBundle>(raw_slice) {
        Ok(mut bundle) => {
            // TODO(sleffler): verify we received a CNode in MEMORY_RECV_CNODE.
            bundle.cnode = recv_path.1;
            // NB: bundle.depth should reflect the received cnode
            KATA_MEMORY.alloc(&bundle).into()
        }
        Err(_) => MemoryManagerError::MmeDeserializeFailed,
    };
    // NB: must clear ReceivePath for next request
    CAMKES.clear_recv_path();
    ret_status
}

#[no_mangle]
pub unsafe extern "C" fn memory_free(
    c_raw_data_len: u32,
    c_raw_data: *const u8,
) -> MemoryManagerError {
    let recv_path = CAMKES.get_current_recv_path();
    // NB: make sure noone clobbers the setup done in memory__init
    CAMKES.assert_recv_path();

    let raw_slice = slice::from_raw_parts(c_raw_data, c_raw_data_len as usize);
    let ret_status = match postcard::from_bytes::<ObjDescBundle>(raw_slice) {
        Ok(mut bundle) => {
            // TODO(sleffler): verify we received a CNode in MEMORY_RECV_CNODE.
            bundle.cnode = recv_path.1;
            // NB: bundle.depth should reflect the received cnode
            KATA_MEMORY.free(&bundle).into()
        }
        Err(_) => MemoryManagerError::MmeDeserializeFailed,
    };
    // NB: must clear ReceivePath for next request
    CAMKES.clear_recv_path();
    ret_status
}

#[no_mangle]
pub unsafe extern "C" fn memory_stats(
    c_raw_resp_data: *mut RawMemoryStatsData,
) -> MemoryManagerError {
    // TODO(sleffler): verify no cap was received
    match KATA_MEMORY.stats() {
        Ok(stats) => {
              match postcard::to_slice(&stats, &mut (*c_raw_resp_data)[..]) {
                  Ok(_) => MemoryManagerError::MmeSuccess,
                  Err(_) => MemoryManagerError::MmeSerializeFailed,
              }
        }
        Err(e) => e.into(),
    }
}
<commit_msg>kata-memory-component: add debug asserts for attached capabilities<commit_after>//! Kata OS MemoryManager component support.

// Code here binds the camkes component to the rust code.
#![no_std]
#![allow(clippy::missing_safety_doc)]

use core::ops::Range;
use core::slice;
use kata_memory_interface::MemoryManagerError;
use kata_memory_interface::MemoryManagerInterface;
use kata_memory_interface::ObjDescBundle;
use kata_memory_interface::RawMemoryStatsData;
use kata_memory_manager::KataMemoryManager;
use kata_os_common::camkes::Camkes;
use kata_os_common::sel4_sys;
use log::trace;

use sel4_sys::seL4_BootInfo;
use sel4_sys::seL4_CNode_Delete;
use sel4_sys::seL4_CPtr;

static mut CAMKES: Camkes = Camkes::new("MemoryManager");

// NB: KATA_MEMORY cannot be used before setup is completed with a call to init()
static mut KATA_MEMORY: KataMemoryManager = KataMemoryManager::empty();

extern "C" {
    // Each CAmkES-component has a CNode setup at a well-known top-level slot.
    // We re-use that slot to receive CNode caps passed with alloc & free requests.
    static MEMORY_RECV_CNODE: seL4_CPtr;
}

#[no_mangle]
pub unsafe extern "C" fn pre_init() {
    // NB: set to max; the LoggerInterface will filter
    CAMKES.init_logger(log::LevelFilter::Trace);

    static mut HEAP_MEMORY: [u8; 8 * 1024] = [0; 8 * 1024];
    CAMKES.init_allocator(&mut HEAP_MEMORY);

    extern "C" {
        fn sel4runtime_bootinfo() -> *const seL4_BootInfo;
    }
    // The MemoryManager component is labeled to receive BootInfo); use
    // it to complete initialization of the MemoryManager interface.
    let bootinfo = &*sel4runtime_bootinfo();
    KATA_MEMORY.init(
        /*slots=*/Range::<seL4_CPtr> {
            start: bootinfo.untyped.start,
            end: bootinfo.untyped.end
        },
        /*untypeds=*/ bootinfo.untyped_descs(),
    );
    if let Ok(stats) = KATA_MEMORY.stats() {
        trace!("Global memory: {} allocated {} free",
            stats.allocated_bytes,
            stats.free_bytes,
        );
    }

    CAMKES.init_slot_allocator(bootinfo.empty.start, bootinfo.empty.end);

    // Delete the CAmkES-setup CNode; we're going to reuse the
    // well-known slot once it is empty (see memory__init below).
    let path = Camkes::top_level_path(MEMORY_RECV_CNODE);
    seL4_CNode_Delete(path.0, path.1, path.2 as u8).expect("recv_node");
}

#[no_mangle]
pub unsafe extern "C" fn memory__init() {
    // Point the receive path to the well-known slot that was emptied.
    // This will be used to receive CNode's from clients for alloc &
    // free requests.
    //
    // NB: this must be done here (rather than someplace like pre_init)
    // so it's in the context of the MemoryInterface thread (so we write
    // the correct ipc buffer).
    CAMKES.init_recv_path(&Camkes::top_level_path(MEMORY_RECV_CNODE));
}

// MemoryInterface glue stubs.

#[no_mangle]
pub unsafe extern "C" fn memory_alloc(
    c_raw_data_len: u32,
    c_raw_data: *const u8,
) -> MemoryManagerError {
    let recv_path = CAMKES.get_current_recv_path();
    // NB: make sure noone clobbers the setup done in memory__init
    CAMKES.assert_recv_path();

    let raw_slice = slice::from_raw_parts(c_raw_data, c_raw_data_len as usize);
    let ret_status = match postcard::from_bytes::<ObjDescBundle>(raw_slice) {
        Ok(mut bundle) => {
            // We must have a CNode for returning allocated objects.
            Camkes::debug_assert_slot_cnode("memory_alloc", &recv_path);

            bundle.cnode = recv_path.1;
            // NB: bundle.depth should reflect the received cnode
            KATA_MEMORY.alloc(&bundle).into()
        }
        Err(_) => MemoryManagerError::MmeDeserializeFailed,
    };
    // NB: must clear ReceivePath for next request
    CAMKES.clear_recv_path();
    ret_status
}

#[no_mangle]
pub unsafe extern "C" fn memory_free(
    c_raw_data_len: u32,
    c_raw_data: *const u8,
) -> MemoryManagerError {
    let recv_path = CAMKES.get_current_recv_path();
    // NB: make sure noone clobbers the setup done in memory__init
    CAMKES.assert_recv_path();

    let raw_slice = slice::from_raw_parts(c_raw_data, c_raw_data_len as usize);
    let ret_status = match postcard::from_bytes::<ObjDescBundle>(raw_slice) {
        Ok(mut bundle) => {
            // We must have a CNode for returning allocated objects.
            Camkes::debug_assert_slot_cnode("memory_free", &recv_path);

            bundle.cnode = recv_path.1;
            // NB: bundle.depth should reflect the received cnode
            KATA_MEMORY.free(&bundle).into()
        }
        Err(_) => MemoryManagerError::MmeDeserializeFailed,
    };
    // NB: must clear ReceivePath for next request
    CAMKES.clear_recv_path();
    ret_status
}

#[no_mangle]
pub unsafe extern "C" fn memory_stats(
    c_raw_resp_data: *mut RawMemoryStatsData,
) -> MemoryManagerError {
    let recv_path = CAMKES.get_current_recv_path();
    // NB: make sure noone clobbers the setup done in memory__init
    CAMKES.assert_recv_path();

    match KATA_MEMORY.stats() {
        Ok(stats) => {
            // Verify no cap was received
            Camkes::debug_assert_slot_empty("memory_stats", &recv_path);

            match postcard::to_slice(&stats, &mut (*c_raw_resp_data)[..]) {
                Ok(_) => MemoryManagerError::MmeSuccess,
                Err(_) => MemoryManagerError::MmeSerializeFailed,
            }
        }
        Err(e) => e.into(),
    }
}
<|endoftext|>


<commit_before>//! The AST pointer
//!
//! Provides `P<T>`, a frozen owned smart pointer, as a replacement for `@T` in
//! the AST.
//!
//! # Motivations and benefits
//!
//! * **Identity**: sharing AST nodes is problematic for the various analysis
//!   passes (e.g., one may be able to bypass the borrow checker with a shared
//!   `ExprKind::AddrOf` node taking a mutable borrow). The only reason `@T` in the
//!   AST hasn't caused issues is because of inefficient folding passes which
//!   would always deduplicate any such shared nodes. Even if the AST were to
//!   switch to an arena, this would still hold, i.e., it couldn't use `&'a T`,
//!   but rather a wrapper like `P<'a, T>`.
//!
//! * **Immutability**: `P<T>` disallows mutating its inner `T`, unlike `Box<T>`
//!   (unless it contains an `Unsafe` interior, but that may be denied later).
//!   This mainly prevents mistakes, but can also enforces a kind of "purity".
//!
//! * **Efficiency**: folding can reuse allocation space for `P<T>` and `Vec<T>`,
//!   the latter even when the input and output types differ (as it would be the
//!   case with arenas or a GADT AST using type parameters to toggle features).
//!
//! * **Maintainability**: `P<T>` provides a fixed interface - `Deref`,
//!   `and_then` and `map` - which can remain fully functional even if the
//!   implementation changes (using a special thread-local heap, for example).
//!   Moreover, a switch to, e.g., `P<'a, T>` would be easy and mostly automated.

use std::fmt::{self, Display, Debug};
use std::iter::FromIterator;
use std::ops::{Deref, DerefMut};
use std::{mem, ptr, slice, vec};

use serialize::{Encodable, Decodable, Encoder, Decoder};

use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
                                           HashStable};
/// An owned smart pointer.
#[derive(Hash, PartialEq, Eq)]
pub struct P<T: ?Sized> {
    ptr: Box<T>
}

#[allow(non_snake_case)]
/// Construct a `P<T>` from a `T` value.
pub fn P<T: 'static>(value: T) -> P<T> {
    P {
        ptr: Box::new(value)
    }
}

impl<T: 'static> P<T> {
    /// Move out of the pointer.
    /// Intended for chaining transformations not covered by `map`.
    pub fn and_then<U, F>(self, f: F) -> U where
        F: FnOnce(T) -> U,
    {
        f(*self.ptr)
    }
    /// Equivalent to and_then(|x| x)
    pub fn into_inner(self) -> T {
        *self.ptr
    }

    /// Produce a new `P<T>` from `self` without reallocating.
    pub fn map<F>(mut self, f: F) -> P<T> where
        F: FnOnce(T) -> T,
    {
        let p: *mut T = &mut *self.ptr;

        // Leak self in case of panic.
        // FIXME(eddyb) Use some sort of "free guard" that
        // only deallocates, without dropping the pointee,
        // in case the call the `f` below ends in a panic.
        mem::forget(self);

        unsafe {
            ptr::write(p, f(ptr::read(p)));

            // Recreate self from the raw pointer.
            P { ptr: Box::from_raw(p) }
        }
    }

    /// Optionally produce a new `P<T>` from `self` without reallocating.
    pub fn filter_map<F>(mut self, f: F) -> Option<P<T>> where
        F: FnOnce(T) -> Option<T>,
    {
        let p: *mut T = &mut *self.ptr;

        // Leak self in case of panic.
        // FIXME(eddyb) Use some sort of "free guard" that
        // only deallocates, without dropping the pointee,
        // in case the call the `f` below ends in a panic.
        mem::forget(self);

        unsafe {
            if let Some(v) = f(ptr::read(p)) {
                ptr::write(p, v);

                // Recreate self from the raw pointer.
                Some(P { ptr: Box::from_raw(p) })
            } else {
                None
            }
        }
    }
}

impl<T: ?Sized> Deref for P<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.ptr
    }
}

impl<T: ?Sized> DerefMut for P<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.ptr
    }
}

impl<T: 'static + Clone> Clone for P<T> {
    fn clone(&self) -> P<T> {
        P((**self).clone())
    }
}

impl<T: ?Sized + Debug> Debug for P<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.ptr, f)
    }
}

impl<T: Display> Display for P<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&**self, f)
    }
}

impl<T> fmt::Pointer for P<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Pointer::fmt(&self.ptr, f)
    }
}

impl<T: 'static + Decodable> Decodable for P<T> {
    fn decode<D: Decoder>(d: &mut D) -> Result<P<T>, D::Error> {
        Decodable::decode(d).map(P)
    }
}

impl<T: Encodable> Encodable for P<T> {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        (**self).encode(s)
    }
}

impl<T> P<[T]> {
    pub fn new() -> P<[T]> {
        P { ptr: Default::default() }
    }

    #[inline(never)]
    pub fn from_vec(v: Vec<T>) -> P<[T]> {
        P { ptr: v.into_boxed_slice() }
    }

    #[inline(never)]
    pub fn into_vec(self) -> Vec<T> {
        self.ptr.into_vec()
    }
}

impl<T> Default for P<[T]> {
    /// Creates an empty `P<[T]>`.
    fn default() -> P<[T]> {
        P::new()
    }
}

impl<T: Clone> Clone for P<[T]> {
    fn clone(&self) -> P<[T]> {
        P::from_vec(self.to_vec())
    }
}

impl<T> From<Vec<T>> for P<[T]> {
    fn from(v: Vec<T>) -> Self {
        P::from_vec(v)
    }
}

impl<T> Into<Vec<T>> for P<[T]> {
    fn into(self) -> Vec<T> {
        self.into_vec()
    }
}

impl<T> FromIterator<T> for P<[T]> {
    fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> P<[T]> {
        P::from_vec(iter.into_iter().collect())
    }
}

impl<T> IntoIterator for P<[T]> {
    type Item = T;
    type IntoIter = vec::IntoIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        self.into_vec().into_iter()
    }
}

impl<'a, T> IntoIterator for &'a P<[T]> {
    type Item = &'a T;
    type IntoIter = slice::Iter<'a, T>;
    fn into_iter(self) -> Self::IntoIter {
        self.ptr.into_iter()
    }
}

impl<T: Encodable> Encodable for P<[T]> {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        Encodable::encode(&**self, s)
    }
}

impl<T: Decodable> Decodable for P<[T]> {
    fn decode<D: Decoder>(d: &mut D) -> Result<P<[T]>, D::Error> {
        Ok(P::from_vec(Decodable::decode(d)?))
    }
}

impl<CTX, T> HashStable<CTX> for P<T>
    where T: ?Sized + HashStable<CTX>
{
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut CTX,
                                          hasher: &mut StableHasher<W>) {
        (**self).hash_stable(hcx, hasher);
    }
}
<commit_msg>Fix memory leak in P::filter_map<commit_after>//! The AST pointer
//!
//! Provides `P<T>`, a frozen owned smart pointer, as a replacement for `@T` in
//! the AST.
//!
//! # Motivations and benefits
//!
//! * **Identity**: sharing AST nodes is problematic for the various analysis
//!   passes (e.g., one may be able to bypass the borrow checker with a shared
//!   `ExprKind::AddrOf` node taking a mutable borrow). The only reason `@T` in the
//!   AST hasn't caused issues is because of inefficient folding passes which
//!   would always deduplicate any such shared nodes. Even if the AST were to
//!   switch to an arena, this would still hold, i.e., it couldn't use `&'a T`,
//!   but rather a wrapper like `P<'a, T>`.
//!
//! * **Immutability**: `P<T>` disallows mutating its inner `T`, unlike `Box<T>`
//!   (unless it contains an `Unsafe` interior, but that may be denied later).
//!   This mainly prevents mistakes, but can also enforces a kind of "purity".
//!
//! * **Efficiency**: folding can reuse allocation space for `P<T>` and `Vec<T>`,
//!   the latter even when the input and output types differ (as it would be the
//!   case with arenas or a GADT AST using type parameters to toggle features).
//!
//! * **Maintainability**: `P<T>` provides a fixed interface - `Deref`,
//!   `and_then` and `map` - which can remain fully functional even if the
//!   implementation changes (using a special thread-local heap, for example).
//!   Moreover, a switch to, e.g., `P<'a, T>` would be easy and mostly automated.

use std::fmt::{self, Display, Debug};
use std::iter::FromIterator;
use std::ops::{Deref, DerefMut};
use std::{mem, ptr, slice, vec};

use serialize::{Encodable, Decodable, Encoder, Decoder};

use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
                                           HashStable};
/// An owned smart pointer.
#[derive(Hash, PartialEq, Eq)]
pub struct P<T: ?Sized> {
    ptr: Box<T>
}

#[allow(non_snake_case)]
/// Construct a `P<T>` from a `T` value.
pub fn P<T: 'static>(value: T) -> P<T> {
    P {
        ptr: Box::new(value)
    }
}

impl<T: 'static> P<T> {
    /// Move out of the pointer.
    /// Intended for chaining transformations not covered by `map`.
    pub fn and_then<U, F>(self, f: F) -> U where
        F: FnOnce(T) -> U,
    {
        f(*self.ptr)
    }
    /// Equivalent to and_then(|x| x)
    pub fn into_inner(self) -> T {
        *self.ptr
    }

    /// Produce a new `P<T>` from `self` without reallocating.
    pub fn map<F>(mut self, f: F) -> P<T> where
        F: FnOnce(T) -> T,
    {
        let p: *mut T = &mut *self.ptr;

        // Leak self in case of panic.
        // FIXME(eddyb) Use some sort of "free guard" that
        // only deallocates, without dropping the pointee,
        // in case the call the `f` below ends in a panic.
        mem::forget(self);

        unsafe {
            ptr::write(p, f(ptr::read(p)));

            // Recreate self from the raw pointer.
            P { ptr: Box::from_raw(p) }
        }
    }

    /// Optionally produce a new `P<T>` from `self` without reallocating.
    pub fn filter_map<F>(mut self, f: F) -> Option<P<T>> where
        F: FnOnce(T) -> Option<T>,
    {
        let p: *mut T = &mut *self.ptr;

        // Leak self in case of panic.
        // FIXME(eddyb) Use some sort of "free guard" that
        // only deallocates, without dropping the pointee,
        // in case the call the `f` below ends in a panic.
        mem::forget(self);

        unsafe {
            if let Some(v) = f(ptr::read(p)) {
                ptr::write(p, v);

                // Recreate self from the raw pointer.
                Some(P { ptr: Box::from_raw(p) })
            } else {
                drop(Box::from_raw(p));
                None
            }
        }
    }
}

impl<T: ?Sized> Deref for P<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.ptr
    }
}

impl<T: ?Sized> DerefMut for P<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.ptr
    }
}

impl<T: 'static + Clone> Clone for P<T> {
    fn clone(&self) -> P<T> {
        P((**self).clone())
    }
}

impl<T: ?Sized + Debug> Debug for P<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.ptr, f)
    }
}

impl<T: Display> Display for P<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&**self, f)
    }
}

impl<T> fmt::Pointer for P<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Pointer::fmt(&self.ptr, f)
    }
}

impl<T: 'static + Decodable> Decodable for P<T> {
    fn decode<D: Decoder>(d: &mut D) -> Result<P<T>, D::Error> {
        Decodable::decode(d).map(P)
    }
}

impl<T: Encodable> Encodable for P<T> {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        (**self).encode(s)
    }
}

impl<T> P<[T]> {
    pub fn new() -> P<[T]> {
        P { ptr: Default::default() }
    }

    #[inline(never)]
    pub fn from_vec(v: Vec<T>) -> P<[T]> {
        P { ptr: v.into_boxed_slice() }
    }

    #[inline(never)]
    pub fn into_vec(self) -> Vec<T> {
        self.ptr.into_vec()
    }
}

impl<T> Default for P<[T]> {
    /// Creates an empty `P<[T]>`.
    fn default() -> P<[T]> {
        P::new()
    }
}

impl<T: Clone> Clone for P<[T]> {
    fn clone(&self) -> P<[T]> {
        P::from_vec(self.to_vec())
    }
}

impl<T> From<Vec<T>> for P<[T]> {
    fn from(v: Vec<T>) -> Self {
        P::from_vec(v)
    }
}

impl<T> Into<Vec<T>> for P<[T]> {
    fn into(self) -> Vec<T> {
        self.into_vec()
    }
}

impl<T> FromIterator<T> for P<[T]> {
    fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> P<[T]> {
        P::from_vec(iter.into_iter().collect())
    }
}

impl<T> IntoIterator for P<[T]> {
    type Item = T;
    type IntoIter = vec::IntoIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        self.into_vec().into_iter()
    }
}

impl<'a, T> IntoIterator for &'a P<[T]> {
    type Item = &'a T;
    type IntoIter = slice::Iter<'a, T>;
    fn into_iter(self) -> Self::IntoIter {
        self.ptr.into_iter()
    }
}

impl<T: Encodable> Encodable for P<[T]> {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        Encodable::encode(&**self, s)
    }
}

impl<T: Decodable> Decodable for P<[T]> {
    fn decode<D: Decoder>(d: &mut D) -> Result<P<[T]>, D::Error> {
        Ok(P::from_vec(Decodable::decode(d)?))
    }
}

impl<CTX, T> HashStable<CTX> for P<T>
    where T: ?Sized + HashStable<CTX>
{
    fn hash_stable<W: StableHasherResult>(&self,
                                          hcx: &mut CTX,
                                          hasher: &mut StableHasher<W>) {
        (**self).hash_stable(hcx, hasher);
    }
}
<|endoftext|>


<commit_before>//
extern crate termion;

//
use self::termion::event::{Event, Key, MouseEvent};
use self::termion::input::{TermRead, MouseTerminal};
use self::termion::raw::IntoRawMode;
use self::termion::terminal_size;

use std::io::{self, Write, stdin, Stdout};

//
use core::screen::Screen;
use core::codepointinfo::CodepointInfo;

use core::editor::Editor;

fn fill_screen(screen: &mut Screen, data: &[u8]) {

    screen.clear();

    let mut offset = 0;
    for c in data {

        let mut displayed_cp: char = *c as char;
        if *c as char == '\n' as char {
            displayed_cp = ' ';
        }

        let cpi = CodepointInfo {
            cp: *c as char,
            displayed_cp: displayed_cp,
            offset: offset,
        };

        let (ok, _) = screen.push(cpi);
        offset += 1;
        if ok == false {
            break;
        }
    }
}

fn draw_screen(screen: &Screen, stdout: &mut Stdout) {

    write!(stdout, "{}", termion::cursor::Goto(1, 1)).unwrap();

    for l in 0..screen.height {
        let line = &screen.line[l];

        for c in 0..line.width {
            let cpi = &line.chars[c];
            write!(stdout, "{}", cpi.displayed_cp).unwrap();
        }

        if l < screen.height - 1 {
            write!(stdout, "\r\n").unwrap();
        }
    }

    stdout.flush().unwrap();
}

fn draw_buffer(buf: &Option<&Box<::core::buffer::Buffer>>,
               mut scr: &mut Screen,
               mut stdout: &mut Stdout) {
    match *buf {
        Some(ref b) => {
            match b.byte_buffer {

                Some(ref byte_buf) => {
                    fill_screen(&mut scr, &byte_buf.data);
                    draw_screen(&scr, &mut stdout);
                }
                _ => {}
            }
        }
        _ => {}
    }
}

fn terminal_clear_current_line(mut stdout: &mut Stdout, nr: u16) {
    for _ in 0..nr {
        write!(stdout, " ").unwrap();
    }
}

fn terminal_goto_line(mut stdout: &mut Stdout, x: u16, y: u16) {
    write!(stdout, "{}", termion::cursor::Goto(x, y)).unwrap();
}

fn terminal_clear_screen(stdout: &mut Stdout, clear_toggle_flag: &mut bool) {
    if *clear_toggle_flag == true {
        write!(stdout, "{}", termion::clear::All).unwrap();
        stdout.flush().unwrap();
    }
    *clear_toggle_flag = false;
}

pub fn main_loop(editor: &mut Editor) {

    let mut stdout = MouseTerminal::from(io::stdout().into_raw_mode().unwrap());

    write!(stdout, "{}{}", termion::cursor::Hide, termion::clear::All).unwrap();

    stdout.flush().unwrap();

    let mut keys: Vec<Event> = Vec::new();

    let mut quit = false;
    let mut clear_toggle_flag = true;

    // select file
    let mut bid = 2;
    let mut buf = editor.buffer_map.get(&bid);

    while !quit {
        let (width, height) = terminal_size().unwrap();
        let mut scr = Screen::new(width as usize, height as usize);

        terminal_clear_screen(&mut stdout, &mut clear_toggle_flag);
        draw_buffer(&buf, &mut scr, &mut stdout);

        for evt in stdin().events() {

            keys.push(evt.unwrap());
            let evt = keys[keys.len() - 1].clone();

            draw_buffer(&buf, &mut scr, &mut stdout);

            // Print recieved Events...
            let mut status = String::new();
            match evt {

                Event::Key(k) => {
                    match k {
                        // Exit.
                        Key::Ctrl('r') => {
                            keys.clear();
                        }

                        Key::Ctrl('c') => {
                            if keys.len() > 1 {
                                if let Event::Key(prev_event) = keys[keys.len() - 2] {
                                    if let Key::Ctrl(prev_char) = prev_event {
                                        if prev_char == 'x' {
                                            quit = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        Key::Char(c) => {
                            if c == '\n' {
                                status = format!("'{}'", "<newline>");
                            } else {
                                status = format!("'{}'", c);
                            }
                        }
                        Key::Alt(c) => status = format!("Alt-{}", c),
                        Key::Ctrl(c) => status = format!("Ctrl-{}", c),

                        Key::F(1) => {
                            if bid > 0 {
                                bid -= 1;
                            }
                            buf = editor.buffer_map.get(&bid);
                            clear_toggle_flag = true;
                        }

                        Key::F(2) => {
                            bid = ::std::cmp::min(bid + 1, (editor.buffer_map.len() - 1) as u64);
                            buf = editor.buffer_map.get(&bid);
                            clear_toggle_flag = true;
                        }

                        Key::F(f) => status = format!("F{:?}", f),
                        Key::Left => status = format!("<left>"),
                        Key::Right => status = format!("<right>"),
                        Key::Up => status = format!("<up>"),
                        Key::Down => status = format!("<down>"),
                        Key::Backspace => status = format!("<backspace>"),
                        Key::Home => status = format!("<Home>"),
                        Key::End => status = format!("<End>"),
                        Key::PageUp => status = format!("<PageUp>"),
                        Key::PageDown => status = format!("<PageDown>"),
                        Key::Delete => status = format!("<Delete>"),
                        Key::Insert => status = format!("<Insert>"),
                        Key::Esc => status = format!("<Esc>"),
                        _ => status = format!("Other"),
                    }
                }

                Event::Mouse(m) => {
                    match m {
                        MouseEvent::Press(mb, x, y) => {
                            status = format!("MouseEvent::Press => MouseButton {:?} @ ({}, {})",
                                             mb,
                                             x,
                                             y);
                        }

                        MouseEvent::Release(x, y) => {
                            status = format!("MouseEvent::Release => @ ({}, {})", x, y);
                        }

                        MouseEvent::Hold(x, y) => {
                            status = format!("MouseEvent::Hold => @ ({}, {})", x, y);
                        }
                    };
                }

                Event::Unsupported(_) => {}
            }

            /* display status */
            // select/clear last line
            terminal_goto_line(&mut stdout, 1, height);
            terminal_clear_current_line(&mut stdout, width);
            let file_name = match buf {
                Some(ref b) => {
                    match b.byte_buffer {
                        Some(ref bb) => bb.file_name.as_str(),
                        None => "",
                    }
                }
                None => "",
            };
            print!("file: {} : event {}", file_name, status);
            stdout.flush().unwrap();
        }
    }

    // quit
    // clear, restore cursor
    write!(stdout, "{}{}", termion::clear::All, termion::cursor::Show).unwrap();
    stdout.flush().unwrap();
}
<commit_msg>cleanup : add display_status_line<commit_after>//
extern crate termion;

//
use self::termion::event::{Event, Key, MouseEvent};
use self::termion::input::{TermRead, MouseTerminal};
use self::termion::raw::IntoRawMode;
use self::termion::terminal_size;

use std::io::{self, Write, stdin, Stdout};

//
use core::screen::Screen;
use core::codepointinfo::CodepointInfo;

use core::editor::Editor;

fn fill_screen(screen: &mut Screen, data: &[u8]) {

    screen.clear();

    let mut offset = 0;
    for c in data {

        let mut displayed_cp: char = *c as char;
        if *c as char == '\n' as char {
            displayed_cp = ' ';
        }

        let cpi = CodepointInfo {
            cp: *c as char,
            displayed_cp: displayed_cp,
            offset: offset,
        };

        let (ok, _) = screen.push(cpi);
        offset += 1;
        if ok == false {
            break;
        }
    }
}

fn draw_screen(screen: &Screen, stdout: &mut Stdout) {

    write!(stdout, "{}", termion::cursor::Goto(1, 1)).unwrap();

    for l in 0..screen.height {
        let line = &screen.line[l];

        for c in 0..line.width {
            let cpi = &line.chars[c];
            write!(stdout, "{}", cpi.displayed_cp).unwrap();
        }

        if l < screen.height - 1 {
            write!(stdout, "\r\n").unwrap();
        }
    }

    stdout.flush().unwrap();
}

fn draw_buffer(buf: &Option<&Box<::core::buffer::Buffer>>,
               mut scr: &mut Screen,
               mut stdout: &mut Stdout) {
    match *buf {
        Some(ref b) => {
            match b.byte_buffer {

                Some(ref byte_buf) => {
                    fill_screen(&mut scr, &byte_buf.data);
                    draw_screen(&scr, &mut stdout);
                }
                _ => {}
            }
        }
        _ => {}
    }
}

fn terminal_clear_current_line(mut stdout: &mut Stdout, nr: u16) {
    for _ in 0..nr {
        write!(stdout, " ").unwrap();
    }
}

fn terminal_goto_line(mut stdout: &mut Stdout, x: u16, y: u16) {
    write!(stdout, "{}", termion::cursor::Goto(x, y)).unwrap();
}

fn terminal_clear_screen(stdout: &mut Stdout, clear_toggle_flag: &mut bool) {
    if *clear_toggle_flag == true {
        write!(stdout, "{}", termion::clear::All).unwrap();
        stdout.flush().unwrap();
    }
    *clear_toggle_flag = false;
}

pub fn main_loop(editor: &mut Editor) {

    let mut stdout = MouseTerminal::from(io::stdout().into_raw_mode().unwrap());

    write!(stdout, "{}{}", termion::cursor::Hide, termion::clear::All).unwrap();
    stdout.flush().unwrap();

    let mut keys: Vec<Event> = Vec::new();

    let mut quit = false;
    let mut clear_toggle_flag = true;

    //
    let display_status = true;

    // select file
    let mut bid = 2;
    let mut buf = editor.buffer_map.get(&bid);

    while !quit {
        let (width, height) = terminal_size().unwrap();
        let mut scr = Screen::new(width as usize, height as usize);

        terminal_clear_screen(&mut stdout, &mut clear_toggle_flag);
        write!(stdout, "{}{}", termion::cursor::Hide, termion::clear::All).unwrap();
        stdout.flush().unwrap();

        draw_buffer(&buf, &mut scr, &mut stdout);
        if display_status == true {
            display_status_line(&buf, "", height, width, &mut stdout);
        }

        for evt in stdin().events() {

            keys.push(evt.unwrap());
            let evt = keys[keys.len() - 1].clone();

            terminal_clear_screen(&mut stdout, &mut clear_toggle_flag);
            write!(stdout, "{}{}", termion::cursor::Hide, termion::clear::All).unwrap();
            stdout.flush().unwrap();

            draw_buffer(&buf, &mut scr, &mut stdout);

            // Print recieved Events...
            let mut status = String::new();
            match evt {

                Event::Key(k) => {
                    match k {
                        // Exit.
                        Key::Ctrl('r') => {
                            keys.clear();
                        }

                        Key::Ctrl('c') => {
                            if keys.len() > 1 {
                                if let Event::Key(prev_event) = keys[keys.len() - 2] {
                                    if let Key::Ctrl(prev_char) = prev_event {
                                        if prev_char == 'x' {
                                            quit = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        Key::Char(c) => {
                            if c == '\n' {
                                status = format!("'{}'", "<newline>");
                            } else {
                                status = format!("'{}'", c);
                            }
                        }
                        Key::Alt(c) => status = format!("Alt-{}", c),
                        Key::Ctrl(c) => status = format!("Ctrl-{}", c),

                        Key::F(1) => {
                            if bid > 0 {
                                bid -= 1;
                            }
                            buf = editor.buffer_map.get(&bid);
                            clear_toggle_flag = true;
                            break;
                        }

                        Key::F(2) => {
                            bid = ::std::cmp::min(bid + 1, (editor.buffer_map.len() - 1) as u64);
                            buf = editor.buffer_map.get(&bid);
                            clear_toggle_flag = true;
                            break;
                        }

                        Key::F(f) => status = format!("F{:?}", f),
                        Key::Left => status = format!("<left>"),
                        Key::Right => status = format!("<right>"),
                        Key::Up => status = format!("<up>"),
                        Key::Down => status = format!("<down>"),
                        Key::Backspace => status = format!("<backspace>"),
                        Key::Home => status = format!("<Home>"),
                        Key::End => status = format!("<End>"),
                        Key::PageUp => status = format!("<PageUp>"),
                        Key::PageDown => status = format!("<PageDown>"),
                        Key::Delete => status = format!("<Delete>"),
                        Key::Insert => status = format!("<Insert>"),
                        Key::Esc => status = format!("<Esc>"),
                        _ => status = format!("Other"),
                    }
                }

                Event::Mouse(m) => {
                    match m {
                        MouseEvent::Press(mb, x, y) => {
                            status = format!("MouseEvent::Press => MouseButton {:?} @ ({}, {})",
                                             mb,
                                             x,
                                             y);
                        }

                        MouseEvent::Release(x, y) => {
                            status = format!("MouseEvent::Release => @ ({}, {})", x, y);
                        }

                        MouseEvent::Hold(x, y) => {
                            status = format!("MouseEvent::Hold => @ ({}, {})", x, y);
                        }
                    };
                }

                Event::Unsupported(_) => {}
            }

            if display_status == true {
                display_status_line(&buf, &status, height, width, &mut stdout);
            }
        }
    }

    // quit
    // clear, restore cursor
    write!(stdout, "{}{}", termion::clear::All, termion::cursor::Show).unwrap();
    stdout.flush().unwrap();
}

fn display_status_line(buf: &Option<&Box<::core::buffer::Buffer>>,
                       status: &str,
                       line: u16,
                       width: u16,
                       mut stdout: &mut Stdout) {
    // select/clear last line
    let name = match *buf {
        Some(ref b) => b.name.as_str(),
        None => "",
    };

    let file_name = match *buf {
        Some(ref b) => {
            match b.byte_buffer {
                Some(ref bb) => bb.file_name.as_str(),
                None => "",
            }
        }
        None => "",
    };

    terminal_goto_line(&mut stdout, 1, line);
    terminal_clear_current_line(&mut stdout, width);

    let status_str = format!("buffer_name '{}', file: '{}', event '{}'",
                             name,
                             file_name,
                             status);

    print!("{}", status_str);
    stdout.flush().unwrap();
}
<|endoftext|>


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

use core::PackageSet;
use util::{CargoResult, human};

// Validate that there are no duplicated native libraries among packages and
// that all packages with `links` also have a build script.
pub fn validate(deps: &PackageSet) -> CargoResult<()> {
    let mut map = HashMap::new();

    for dep in deps.iter() {
        let lib = match dep.manifest().links() {
            Some(lib) => lib,
            None => continue,
        };
        match map.get(&lib) {
            Some(previous) => {
                return Err(human(format!("native library `{}` is being linked \
                                          to by more than one package, and \
                                          can only be linked to by one \
                                          package\n\n  {}\n  {}",
                                         lib, previous, dep.package_id())))
            }
            None => {}
        }
        if !dep.manifest().targets().iter().any(|t| t.is_custom_build()) {
            return Err(human(format!("package `{}` specifies that it links to \
                                      `{}` but does not have a custom build \
                                      script", dep.package_id(), lib)))
        }
        map.insert(lib, dep.package_id());
    }

    Ok(())
}
<commit_msg>Auto merge of #2159 - Manishearth:native-diag, r=alexcrichton<commit_after>use std::collections::HashMap;

use core::{PackageId, PackageSet};
use util::{CargoResult, human};

// Validate that there are no duplicated native libraries among packages and
// that all packages with `links` also have a build script.
pub fn validate(deps: &PackageSet) -> CargoResult<()> {
    let mut map: HashMap<_, &PackageId> = HashMap::new();

    for dep in deps.iter() {
        let lib = match dep.manifest().links() {
            Some(lib) => lib,
            None => continue,
        };
        match map.get(&lib) {
            Some(previous) => {
                let depid = dep.package_id();
                if previous.name() == depid.name()
                    && previous.source_id() == depid.source_id() {
                    return Err(human(format!("native library `{}` is being \
                                              linked to by more than one \
                                              version of the same package, but \
                                              it can only be linked \
                                              once; try updating \
                                              or pinning your dependencies to \
                                              ensure that this package only \
                                              shows up once\n\n  {}\n  {}",
                                             lib, previous, dep.package_id())))
                } else {
                    return Err(human(format!("native library `{}` is being \
                                              linked to by more than one \
                                              package, and can only be linked \
                                              to by one package\n\n  {}\n  {}",
                                             lib, previous, dep.package_id())))
                }
            }
            None => {}
        }
        if !dep.manifest().targets().iter().any(|t| t.is_custom_build()) {
            return Err(human(format!("package `{}` specifies that it links to \
                                      `{}` but does not have a custom build \
                                      script", dep.package_id(), lib)))
        }
        map.insert(lib, dep.package_id());
    }

    Ok(())
}
<|endoftext|>