<commit_before>//! Formatting helpers for the logger middleware.

use std::default::Default;
use std::str::Chars;
use std::iter::Peekable;
use std::fmt::Formatter;

use self::FormatText::{Method, URI, Status, ResponseTime, RemoteAddr, RequestTime};

/// A formatting style for the `Logger`, consisting of multiple
/// `FormatText`s concatenated into one line.
#[derive(Clone)]
pub struct Format(Vec<FormatText>);

impl Default for Format {
    /// Return the default formatting style for the `Logger`:
    ///
    /// ```ignore
    /// {method} {uri} -> {status} ({response-time})
    /// // This will be written as: {method} {uri} -> {status} ({response-time})
    /// ```
    fn default() -> Format {
        Format::new("{method} {uri} {status} ({response-time})").unwrap()
    }
}

impl Format {
    /// Create a `Format` from a format string, which can contain the fields
    /// `{method}`, `{uri}`, `{status}`, `{response-time}`, `{ip-addr}` and
    /// `{request-time}`.
    ///
    /// Returns `None` if the format string syntax is incorrect.
    pub fn new(s: &str) -> Option<Format> {

        let parser = FormatParser::new(s.chars().peekable());

        let mut results = Vec::new();

        for unit in parser {
            match unit {
                Some(unit) => results.push(unit),
                None => return None
            }
        }

        Some(Format(results))
    }
}

pub trait ContextDisplay<'a> {
    type Item;
    type Display: fmt::Display;
    fn display_with(&'a self,
                    render: &'a Fn(&mut Formatter, &Self::Item) -> Result<(), fmt::Error>)
                    -> Self::Display;
}

impl<'a> ContextDisplay<'a> for Format {
    type Item = FormatText;
    type Display = FormatDisplay<'a>;
    fn display_with(&'a self,
                    render: &'a Fn(&mut Formatter, &FormatText) -> Result<(), fmt::Error>)
                    -> FormatDisplay<'a> {
        FormatDisplay {
            format: self,
            render: render,
        }
    }
}

struct FormatParser<'a> {
    // The characters of the format string.
    chars: Peekable<Chars<'a>>,

    // A reusable buffer for parsing style attributes.
    object_buffer: String,

    finished: bool
}

impl<'a> FormatParser<'a> {
    fn new(chars: Peekable<Chars>) -> FormatParser {
        FormatParser {
            chars: chars,

            // No attributes are longer than 14 characters, so we can avoid reallocating.
            object_buffer: String::with_capacity(14),

            finished: false
        }
    }
}

// Some(None) means there was a parse error and this FormatParser should be abandoned.
impl<'a> Iterator for FormatParser<'a> {
    type Item = Option<FormatText>;

    fn next(&mut self) -> Option<Option<FormatText>> {
        // If the parser has been cancelled or errored for some reason.
        if self.finished { return None }

        // Try to parse a new FormatText.
        match self.chars.next() {
            // Parse a recognized object.
            //
            // The allowed forms are:
            //   - {method}
            //   - {uri}
            //   - {status}
            //   - {response-time}
            //   - {ip-addr}
            //   - {request-time}
            Some('{') => {
                self.object_buffer.clear();

                let mut chr = self.chars.next();
                while chr != None {
                    match chr.unwrap() {
                        // Finished parsing, parse buffer.
                        '}' => break,
                        c => self.object_buffer.push(c.clone())
                    }

                    chr = self.chars.next();
                }

                let text = match self.object_buffer.as_ref() {
                    "method" => Method,
                    "uri" => URI,
                    "status" => Status,
                    "response-time" => ResponseTime,
                    "request-time" => RequestTime,
                    "ip-addr" => RemoteAddr,
                    _ => {
                        // Error, so mark as finished.
                        self.finished = true;
                        return Some(None);
                    }
                };

                Some(Some(text))
            }

            // Parse a regular string part of the format string.
            Some(c) => {
                let mut buffer = String::new();
                buffer.push(c);

                loop {
                    match self.chars.peek() {
                        // Done parsing.
                        Some(&'{') | None => return Some(Some(FormatText::Str(buffer))),

                        Some(_) => {
                            buffer.push(self.chars.next().unwrap())
                        }
                    }
                }
            },

            // Reached end of the format string.
            None => None
        }
    }
}

/// A string of text to be logged. This is either one of the data
/// fields supported by the `Logger`, or a custom `String`.
#[derive(Clone)]
#[doc(hidden)]
pub enum FormatText {
    Str(String),
    Method,
    URI,
    Status,
    ResponseTime,
    RemoteAddr,
    RequestTime
}

pub struct FormatDisplay<'a> {
    format: &'a Format,
    render: &'a Fn(&mut Formatter, &FormatText) -> Result<(), fmt::Error>,
}

use std::fmt;
impl<'a> fmt::Display for FormatDisplay<'a> {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        let Format(ref format) = *self.format;
        for unit in format {
            (self.render)(fmt, unit)?;
        }
        Ok(())
    }
}
<commit_msg>Fix deprecated error<commit_after>//! Formatting helpers for the logger middleware.

use std::default::Default;
use std::str::Chars;
use std::iter::Peekable;
use std::fmt::Formatter;

use self::FormatText::{Method, URI, Status, ResponseTime, RemoteAddr, RequestTime};

/// A formatting style for the `Logger`, consisting of multiple
/// `FormatText`s concatenated into one line.
#[derive(Clone)]
pub struct Format(Vec<FormatText>);

impl Default for Format {
    /// Return the default formatting style for the `Logger`:
    ///
    /// ```ignore
    /// {method} {uri} -> {status} ({response-time})
    /// // This will be written as: {method} {uri} -> {status} ({response-time})
    /// ```
    fn default() -> Format {
        Format::new("{method} {uri} {status} ({response-time})").unwrap()
    }
}

impl Format {
    /// Create a `Format` from a format string, which can contain the fields
    /// `{method}`, `{uri}`, `{status}`, `{response-time}`, `{ip-addr}` and
    /// `{request-time}`.
    ///
    /// Returns `None` if the format string syntax is incorrect.
    pub fn new(s: &str) -> Option<Format> {

        let parser = FormatParser::new(s.chars().peekable());

        let mut results = Vec::new();

        for unit in parser {
            match unit {
                Some(unit) => results.push(unit),
                None => return None
            }
        }

        Some(Format(results))
    }
}

pub trait ContextDisplay<'a> {
    type Item;
    type Display: fmt::Display;
    fn display_with(&'a self,
                    render: &'a dyn Fn(&mut Formatter, &Self::Item) -> Result<(), fmt::Error>)
                    -> Self::Display;
}

impl<'a> ContextDisplay<'a> for Format {
    type Item = FormatText;
    type Display = FormatDisplay<'a>;
    fn display_with(&'a self,
                    render: &'a dyn Fn(&mut Formatter, &FormatText) -> Result<(), fmt::Error>)
                    -> FormatDisplay<'a> {
        FormatDisplay {
            format: self,
            render: render,
        }
    }
}

struct FormatParser<'a> {
    // The characters of the format string.
    chars: Peekable<Chars<'a>>,

    // A reusable buffer for parsing style attributes.
    object_buffer: String,

    finished: bool
}

impl<'a> FormatParser<'a> {
    fn new(chars: Peekable<Chars>) -> FormatParser {
        FormatParser {
            chars: chars,

            // No attributes are longer than 14 characters, so we can avoid reallocating.
            object_buffer: String::with_capacity(14),

            finished: false
        }
    }
}

// Some(None) means there was a parse error and this FormatParser should be abandoned.
impl<'a> Iterator for FormatParser<'a> {
    type Item = Option<FormatText>;

    fn next(&mut self) -> Option<Option<FormatText>> {
        // If the parser has been cancelled or errored for some reason.
        if self.finished { return None }

        // Try to parse a new FormatText.
        match self.chars.next() {
            // Parse a recognized object.
            //
            // The allowed forms are:
            //   - {method}
            //   - {uri}
            //   - {status}
            //   - {response-time}
            //   - {ip-addr}
            //   - {request-time}
            Some('{') => {
                self.object_buffer.clear();

                let mut chr = self.chars.next();
                while chr != None {
                    match chr.unwrap() {
                        // Finished parsing, parse buffer.
                        '}' => break,
                        c => self.object_buffer.push(c.clone())
                    }

                    chr = self.chars.next();
                }

                let text = match self.object_buffer.as_ref() {
                    "method" => Method,
                    "uri" => URI,
                    "status" => Status,
                    "response-time" => ResponseTime,
                    "request-time" => RequestTime,
                    "ip-addr" => RemoteAddr,
                    _ => {
                        // Error, so mark as finished.
                        self.finished = true;
                        return Some(None);
                    }
                };

                Some(Some(text))
            }

            // Parse a regular string part of the format string.
            Some(c) => {
                let mut buffer = String::new();
                buffer.push(c);

                loop {
                    match self.chars.peek() {
                        // Done parsing.
                        Some(&'{') | None => return Some(Some(FormatText::Str(buffer))),

                        Some(_) => {
                            buffer.push(self.chars.next().unwrap())
                        }
                    }
                }
            },

            // Reached end of the format string.
            None => None
        }
    }
}

/// A string of text to be logged. This is either one of the data
/// fields supported by the `Logger`, or a custom `String`.
#[derive(Clone)]
#[doc(hidden)]
pub enum FormatText {
    Str(String),
    Method,
    URI,
    Status,
    ResponseTime,
    RemoteAddr,
    RequestTime
}

pub struct FormatDisplay<'a> {
    format: &'a Format,
    render: &'a dyn Fn(&mut Formatter, &FormatText) -> Result<(), fmt::Error>,
}

use std::fmt;
impl<'a> fmt::Display for FormatDisplay<'a> {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        let Format(ref format) = *self.format;
        for unit in format {
            (self.render)(fmt, unit)?;
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::cmp::min;
use std::ascii::AsciiExt;

#[derive(Clone, Debug,PartialEq)]
pub struct Quality(pub f32);

impl Quality {
    pub fn to_f32(&self) -> f32 {
        let Quality(q) = *self;
        q
    }
}

#[derive(Clone, Debug,PartialEq)]
pub struct Substring(pub usize,pub usize);

#[derive(Clone, Debug,PartialEq)]
pub struct Match<'a> {
    pub quality: Quality,
    pub range: Substring,
    pub original: &'a String,

}

impl <'a>Match<'a>{
    pub fn new(quality: Quality, range: Substring, original: &'a String) -> Match<'a> {
        Match { quality: quality, range: range, original: original }
    }

    pub fn origin_only(original: &'a String) -> Match<'a> {
        Match::new(Quality(1.0), Substring(0,0), original)
    }
}

pub fn score<'a>(choice: &'a String, query: &String) -> Option<Match<'a>> {
    let choice_length = choice.len() as f32;
    let query_length = query.len() as f32;

    if query_length == 0.0 { return Some(Match::new(Quality(1.0), Substring(0,0), choice)) }
    let lower_choice = choice.to_ascii_lowercase();

    match compute_match_length(&lower_choice, query) {
        Some((start, match_length)) => {
            let quality = Quality( (query_length / match_length as f32) / choice_length);
            let substring = Substring(start, start+match_length);
            Some(Match::new(quality, substring, choice))
        },
        None => None,
    }
}

fn compute_match_length(choice: &String, query: &String) -> Option<(usize, usize)> {
    if query.len() == 0 {
        return None;
    }
    let (first, rest) = query.slice_shift_char().unwrap();

    let impossible_match = choice.len() + 1;
    let mut shortest_match = impossible_match;
    let mut shortest_start = impossible_match;

    for_each_beginning(choice, first, |beginning| {
        match match_length_from(choice, rest, beginning) {
            Some(length) => {
                             shortest_match = min(length, shortest_match);
                             shortest_start = beginning;
            },
            None => {},
        };
    });

    if shortest_match == impossible_match {None} else {Some((shortest_start, shortest_match))}
}

fn for_each_beginning<F: FnMut(usize)>(choice: &String, beginning: char, mut f: F) {
    for (idx, character) in choice.chars().enumerate() {
        if character == beginning {
            f(idx);
        }
    }
}

fn match_length_from(choice: &String, query: &str, beginning: usize) -> Option<usize> {
    let mut match_index = beginning;

    for query_char in query.chars() {
       match find_first_after(choice, query_char, match_index + 1) {
           Some(n) => match_index = n,
           None => return None,
       };
    }
    Some(match_index - beginning + 1)
}

fn find_first_after(choice: &String, query: char, offset: usize) -> Option<usize> {
    choice[offset..]
        .find(query)
        .map(|index| index + offset)
}
<commit_msg>The Substring can slice up string based on range.<commit_after>use std::cmp::min;
use std::ascii::AsciiExt;

#[derive(Clone, Debug,PartialEq)]
pub struct Quality(pub f32);

impl Quality {
    pub fn to_f32(&self) -> f32 {
        let Quality(q) = *self;
        q
    }
}

#[derive(Clone, Debug,PartialEq)]
pub struct Substring(pub usize,pub usize);

impl Substring {
    pub fn slice(&self, input: &String) -> (String, String, String) {
       let Substring(start, end) = *self;
       (input[0..start].to_string(),
        input[start..end].to_string(),
        input[end..].to_string())
    }
}

#[derive(Clone, Debug,PartialEq)]
pub struct Match<'a> {
    pub quality: Quality,
    pub range: Substring,
    pub original: &'a String,

}

impl <'a>Match<'a>{
    pub fn new(quality: Quality, range: Substring, original: &'a String) -> Match<'a> {
        Match { quality: quality, range: range, original: original }
    }

    pub fn origin_only(original: &'a String) -> Match<'a> {
        Match::new(Quality(1.0), Substring(0,0), original)
    }
}

pub fn score<'a>(choice: &'a String, query: &String) -> Option<Match<'a>> {
    let choice_length = choice.len() as f32;
    let query_length = query.len() as f32;

    if query_length == 0.0 { return Some(Match::new(Quality(1.0), Substring(0,0), choice)) }
    let lower_choice = choice.to_ascii_lowercase();

    match compute_match_length(&lower_choice, query) {
        Some((start, match_length)) => {
            let quality = Quality( (query_length / match_length as f32) / choice_length);
            let substring = Substring(start, start+match_length);
            Some(Match::new(quality, substring, choice))
        },
        None => None,
    }
}

fn compute_match_length(choice: &String, query: &String) -> Option<(usize, usize)> {
    if query.len() == 0 {
        return None;
    }
    let (first, rest) = query.slice_shift_char().unwrap();

    let impossible_match = choice.len() + 1;
    let mut shortest_match = impossible_match;
    let mut shortest_start = impossible_match;

    for_each_beginning(choice, first, |beginning| {
        match match_length_from(choice, rest, beginning) {
            Some(length) => {
                             shortest_match = min(length, shortest_match);
                             shortest_start = beginning;
            },
            None => {},
        };
    });

    if shortest_match == impossible_match {None} else {Some((shortest_start, shortest_match))}
}

fn for_each_beginning<F: FnMut(usize)>(choice: &String, beginning: char, mut f: F) {
    for (idx, character) in choice.chars().enumerate() {
        if character == beginning {
            f(idx);
        }
    }
}

fn match_length_from(choice: &String, query: &str, beginning: usize) -> Option<usize> {
    let mut match_index = beginning;

    for query_char in query.chars() {
       match find_first_after(choice, query_char, match_index + 1) {
           Some(n) => match_index = n,
           None => return None,
       };
    }
    Some(match_index - beginning + 1)
}

fn find_first_after(choice: &String, query: char, offset: usize) -> Option<usize> {
    choice[offset..]
        .find(query)
        .map(|index| index + offset)
}
<|endoftext|>


<commit_before>use crate::config::Config;
use crate::stack::Stack;
use crate::workspace::{Workspace, WorkspaceConfig};
use crate::xlib_window_system::XlibWindowSystem;
use crate::ewmh;
use std::fs::{File, remove_file};
use std::path::Path;
use std::default::Default;
use serde::{Serialize, Deserialize};
use x11::xlib::Window;
use anyhow::{Context, Result};

#[derive(Serialize, Deserialize)]
pub struct WmState {
    workspaces: Vec<Workspace>,
    struts: Vec<Window>,
    cur: usize,
    screens: usize
}

impl WmState {
    pub fn new(ws_cfg_list: Vec<WorkspaceConfig>, xws: &XlibWindowSystem) -> Result<WmState> {
        let state_file_path = Path::new(concat!(env!("HOME"), "/.xr3wm/.tmp"));
        if state_file_path.exists() {
            match WmState::from_file(state_file_path) {
                Ok(state) => {
                    state.all_ws().iter().for_each(|workspace| {
                        workspace.all().iter().for_each(|&window| {
                            xws.request_window_events(window);
                        })
                    });

                    return Ok(state);
                },
                Err(e) => error!("failed to restore previous state: {}", e)
            }
        }

        debug!("creating default WmState");
        Ok(WmState {
            workspaces: ws_cfg_list
                .into_iter()
                .map(|c| {
                    Workspace {
                        tag: c.tag.clone(),
                        screen: c.screen,
                        managed: Stack::new(Some(c.layout)),
                        ..Default::default()
                    }
                })
                .collect(),
            struts: Vec::new(),
            cur: 0,
            screens: xws.get_screen_infos().len()
        })
    }

    fn from_file<P: AsRef<Path>>(path: P) -> Result<WmState> {
        let file = File::open(&path)
            .context("failed to open wm state serialization file")?;

        debug!("loading previous wm state");
        let ws: WmState = serde_json::from_reader(file)
            .context("failed to deserialize wm state")?;

        remove_file(path).ok();

        Ok(ws)
    }

    pub fn get_ws_mut(&mut self, index: usize) -> Option<&mut Workspace> {
        self.workspaces.get_mut(index)
    }

    pub fn current_ws(&self) -> &Workspace {
        self.workspaces.get(self.cur).unwrap()
    }

    pub fn current_ws_mut(&mut self) -> &mut Workspace {
        self.workspaces.get_mut(self.cur).unwrap()
    }

    pub fn all_ws(&self) -> &Vec<Workspace> {
        &self.workspaces
    }

    pub fn all_visible_ws(&self) -> Vec<&Workspace> {
        self.workspaces
            .iter()
            .filter(|ws| ws.is_visible())
            .collect()
    }

    pub fn get_ws_index(&self) -> usize {
        self.cur
    }

    pub fn ws_count(&self) -> usize {
        self.workspaces.len()
    }

    pub fn contains(&self, window: Window) -> bool {
        self.workspaces.iter().any(|ws| ws.contains(window))
    }

    pub fn is_unmanaged(&self, window: Window) -> bool {
        self.workspaces.iter().any(|ws| ws.is_unmanaged(window))
    }

    pub fn add_window(&mut self, index: Option<usize>, xws: &XlibWindowSystem, config: &Config, window: Window) {
        if !self.contains(window) {
            let parent = xws.transient_for(window)
                .and_then(|x| self.find_window(x));

            let workspace = parent
                .or_else(|| index.or_else(|| Some(self.get_ws_index())))
                .and_then(|idx| self.get_ws_mut(idx))
                .expect("valid workspace");

            workspace.add_window(xws, config, window);

            if parent.is_some() {
                workspace.focus_window(xws, config, window);
            }

            ewmh::set_client_list(xws, &self.workspaces);
        }
    }

    pub fn focus_window(&mut self, xws: &XlibWindowSystem, config: &Config, window: Window) {
        if let Some(index) = self.find_window(window) {
            if self.cur != index {
                self.get_ws_mut(index)
                    .expect("valid workspace")
                    .focus_window(xws, config, window);
                self.switch_to(xws, config, index, false);
            } else {
                self.current_ws_mut().focus_window(xws, config, window);
            }
        }
    }

    pub fn switch_to(&mut self, xws: &XlibWindowSystem, config: &Config, index: usize, center_pointer: bool) {
        if self.cur != index && index < self.workspaces.len() {
            // implies that the target workspace is on another screen
            if self.workspaces[index].visible {
                if config.greedy_view {
                    self.switch_screens(xws, index);
                    self.workspaces[self.cur].show(xws, config);
                } else if center_pointer {
                    self.workspaces[index].center_pointer(xws);
                }
            } else {
                self.workspaces[index].screen = self.workspaces[self.cur].screen;
                self.workspaces[index].show(xws, config);
                self.workspaces[self.cur].hide(xws);
            }

            self.workspaces[self.cur].unfocus(xws, config);
            self.workspaces[index].focus(xws, config);

            self.cur = index;

            ewmh::set_current_desktop(xws, index);
            ewmh::set_desktop_viewport(xws, self.all_ws());
        }
    }

    pub fn switch_to_screen(&mut self, xws: &XlibWindowSystem, config: &Config, screen: usize) {
        if screen > self.screens - 1 {
            return;
        }

        let idx_workspace = self.workspaces.iter()
            .enumerate()
            .filter(|&(i, workspace)| workspace.screen == screen && workspace.visible && i != self.cur)
            .map(|(i, _)| i)
            .last();

        if let Some(index) = idx_workspace {
            self.workspaces[self.cur].unfocus(xws, config);
            self.workspaces[index].focus(xws, config);

            self.workspaces[index].center_pointer(xws);
            self.cur = index;

            ewmh::set_current_desktop(xws, index);
        }
    }

    pub fn move_window_to(&mut self, xws: &XlibWindowSystem, config: &Config, index: usize) {
        if index == self.cur || index >= self.ws_count() {
            return;
        }

        if let Some(window) = self.current_ws().focused_window() {
            self.remove_window(xws, config, window);

            if let Some(workspace) = self.get_ws_mut(index) {
                workspace.add_window(xws, config, window);
                workspace.unfocus(xws, config);
            }
        }
    }

    pub fn move_window_to_screen(&mut self,
                                 xws: &XlibWindowSystem,
                                 config: &Config,
                                 screen: usize) {
        if let Some((index, _)) = self.workspaces.iter().enumerate().find(|&(_, ws)| ws.screen == screen) {
            self.move_window_to(xws, config, index);
        }
    }

    pub fn remove_window(&mut self, xws: &XlibWindowSystem, config: &Config, window: Window) {
        if let Some(idx) = self.find_window(window) {
            self.workspaces.get_mut(idx)
                .expect("valid workspace")
                .remove_window(xws, config, window);
            ewmh::set_client_list(xws, &self.workspaces);
        }
    }
/*
    pub fn hide_window(&mut self, window: Window) {
        if let Some(idx) = self.find_window(window) {
            self.list.get_mut(idx)
                .expect("valid workspace")
                .hide_window(window);
        }
    }
*/
    pub fn rescreen(&mut self, xws: &XlibWindowSystem, config: &Config) {
        let new_screens = xws.get_screen_infos().len();
        let prev_screens = self.screens;

        if new_screens == prev_screens {
            return;
        }

        self.screens = new_screens;
        debug!("rescreen {}", new_screens);

        // move and hide workspaces if their screens got removed
        if new_screens < prev_screens {
            for workspace in self.workspaces.iter_mut().filter(|x| x.screen > new_screens - 1) {
                workspace.screen = 0;
                workspace.hide(xws);
            }
        } else {
            debug!("finding workspace to rescreen");
            // assign the first hidden workspace to the new screen
            for screen in prev_screens..new_screens {
                debug!("rescreen for screen {}", screen);
                if let Some(workspace) = self.workspaces.iter_mut().find(|ws| !ws.is_visible()) {
                    debug!("moving workspace {}", workspace.tag);
                    workspace.screen = screen;
                    workspace.show(xws, config);
                }
            }
        }

        ewmh::set_desktop_viewport(xws, self.all_ws());
    }

    pub fn find_window(&self, window: Window) -> Option<usize> {
        self.workspaces.iter().enumerate().find(|(_, workspace)| workspace.contains(window)).map(|(idx, _)| idx)
    }

    pub fn get_parent_mut(&mut self, window: Window) -> Option<&mut Workspace> {
        self.workspaces.iter_mut().find(|workspace| workspace.contains(window))
    }

    fn switch_screens(&mut self, xws: &XlibWindowSystem, dest: usize) {
        let screen = self.current_ws().get_screen();
        self.workspaces[self.cur].screen = self.workspaces[dest].screen;
        self.workspaces[dest].screen = screen;

        ewmh::set_desktop_viewport(xws, self.all_ws());
    }

    pub fn redraw(&self, xws: &XlibWindowSystem, config: &Config) {
        self.all_visible_ws()
            .iter()
            .for_each(|ws| ws.redraw(xws, config));
    }

    pub fn add_strut(&mut self, window: Window) {
        if !self.struts.contains(&window) {
            self.struts.push(window);
        }
    }

    pub fn try_remove_strut(&mut self, window: Window) -> bool {
        if let Some((idx,_)) = self.struts.iter()
            .enumerate()
            .find(|(_,&x)| x == window)
        {
            self.struts.swap_remove(idx);
            true
        } else {
            false
        }
    }
}
<commit_msg>Fix switching to hidden workspaces on focus change<commit_after>use crate::config::Config;
use crate::stack::Stack;
use crate::workspace::{Workspace, WorkspaceConfig};
use crate::xlib_window_system::XlibWindowSystem;
use crate::ewmh;
use std::fs::{File, remove_file};
use std::path::Path;
use std::default::Default;
use serde::{Serialize, Deserialize};
use x11::xlib::Window;
use anyhow::{Context, Result};

#[derive(Serialize, Deserialize)]
pub struct WmState {
    workspaces: Vec<Workspace>,
    struts: Vec<Window>,
    cur: usize,
    screens: usize
}

impl WmState {
    pub fn new(ws_cfg_list: Vec<WorkspaceConfig>, xws: &XlibWindowSystem) -> Result<WmState> {
        let state_file_path = Path::new(concat!(env!("HOME"), "/.xr3wm/.tmp"));
        if state_file_path.exists() {
            match WmState::from_file(state_file_path) {
                Ok(state) => {
                    state.all_ws().iter().for_each(|workspace| {
                        workspace.all().iter().for_each(|&window| {
                            xws.request_window_events(window);
                        })
                    });

                    return Ok(state);
                },
                Err(e) => error!("failed to restore previous state: {}", e)
            }
        }

        debug!("creating default WmState");
        Ok(WmState {
            workspaces: ws_cfg_list
                .into_iter()
                .map(|c| {
                    Workspace {
                        tag: c.tag.clone(),
                        screen: c.screen,
                        managed: Stack::new(Some(c.layout)),
                        ..Default::default()
                    }
                })
                .collect(),
            struts: Vec::new(),
            cur: 0,
            screens: xws.get_screen_infos().len()
        })
    }

    fn from_file<P: AsRef<Path>>(path: P) -> Result<WmState> {
        let file = File::open(&path)
            .context("failed to open wm state serialization file")?;

        debug!("loading previous wm state");
        let ws: WmState = serde_json::from_reader(file)
            .context("failed to deserialize wm state")?;

        remove_file(path).ok();

        Ok(ws)
    }

    pub fn get_ws_mut(&mut self, index: usize) -> Option<&mut Workspace> {
        self.workspaces.get_mut(index)
    }

    pub fn current_ws(&self) -> &Workspace {
        self.workspaces.get(self.cur).unwrap()
    }

    pub fn current_ws_mut(&mut self) -> &mut Workspace {
        self.workspaces.get_mut(self.cur).unwrap()
    }

    pub fn all_ws(&self) -> &Vec<Workspace> {
        &self.workspaces
    }

    pub fn all_visible_ws(&self) -> Vec<&Workspace> {
        self.workspaces
            .iter()
            .filter(|ws| ws.is_visible())
            .collect()
    }

    pub fn get_ws_index(&self) -> usize {
        self.cur
    }

    pub fn ws_count(&self) -> usize {
        self.workspaces.len()
    }

    pub fn contains(&self, window: Window) -> bool {
        self.workspaces.iter().any(|ws| ws.contains(window))
    }

    pub fn is_unmanaged(&self, window: Window) -> bool {
        self.workspaces.iter().any(|ws| ws.is_unmanaged(window))
    }

    pub fn add_window(&mut self, index: Option<usize>, xws: &XlibWindowSystem, config: &Config, window: Window) {
        if !self.contains(window) {
            let parent = xws.transient_for(window)
                .and_then(|x| self.find_window(x));

            let workspace = parent
                .or_else(|| index.or_else(|| Some(self.get_ws_index())))
                .and_then(|idx| self.get_ws_mut(idx))
                .expect("valid workspace");

            workspace.add_window(xws, config, window);

            if parent.is_some() {
                workspace.focus_window(xws, config, window);
            }

            ewmh::set_client_list(xws, &self.workspaces);
        }
    }

    pub fn focus_window(&mut self, xws: &XlibWindowSystem, config: &Config, window: Window) {
        if let Some(index) = self.find_window(window) {
            if self.cur != index {
                let workspace = self.get_ws_mut(index)
                    .expect("valid workspace");

                workspace.focus_window(xws, config, window);

                if workspace.is_visible() {
                    self.switch_to(xws, config, index, false);
                }
            } else {
                self.current_ws_mut().focus_window(xws, config, window);
            }
        }
    }

    pub fn switch_to(&mut self, xws: &XlibWindowSystem, config: &Config, index: usize, center_pointer: bool) {
        if self.cur != index && index < self.workspaces.len() {
            // implies that the target workspace is on another screen
            if self.workspaces[index].visible {
                if config.greedy_view {
                    self.switch_screens(xws, index);
                    self.workspaces[self.cur].show(xws, config);
                } else if center_pointer {
                    self.workspaces[index].center_pointer(xws);
                }
            } else {
                self.workspaces[index].screen = self.workspaces[self.cur].screen;
                self.workspaces[index].show(xws, config);
                self.workspaces[self.cur].hide(xws);
            }

            self.workspaces[self.cur].unfocus(xws, config);
            self.workspaces[index].focus(xws, config);

            self.cur = index;

            ewmh::set_current_desktop(xws, index);
            ewmh::set_desktop_viewport(xws, self.all_ws());
        }
    }

    pub fn switch_to_screen(&mut self, xws: &XlibWindowSystem, config: &Config, screen: usize) {
        if screen > self.screens - 1 {
            return;
        }

        let idx_workspace = self.workspaces.iter()
            .enumerate()
            .filter(|&(i, workspace)| workspace.screen == screen && workspace.visible && i != self.cur)
            .map(|(i, _)| i)
            .last();

        if let Some(index) = idx_workspace {
            self.workspaces[self.cur].unfocus(xws, config);
            self.workspaces[index].focus(xws, config);

            self.workspaces[index].center_pointer(xws);
            self.cur = index;

            ewmh::set_current_desktop(xws, index);
        }
    }

    pub fn move_window_to(&mut self, xws: &XlibWindowSystem, config: &Config, index: usize) {
        if index == self.cur || index >= self.ws_count() {
            return;
        }

        if let Some(window) = self.current_ws().focused_window() {
            self.remove_window(xws, config, window);

            if let Some(workspace) = self.get_ws_mut(index) {
                workspace.add_window(xws, config, window);
                workspace.unfocus(xws, config);
            }
        }
    }

    pub fn move_window_to_screen(&mut self,
                                 xws: &XlibWindowSystem,
                                 config: &Config,
                                 screen: usize) {
        if let Some((index, _)) = self.workspaces.iter().enumerate().find(|&(_, ws)| ws.screen == screen) {
            self.move_window_to(xws, config, index);
        }
    }

    pub fn remove_window(&mut self, xws: &XlibWindowSystem, config: &Config, window: Window) {
        if let Some(idx) = self.find_window(window) {
            self.workspaces.get_mut(idx)
                .expect("valid workspace")
                .remove_window(xws, config, window);
            ewmh::set_client_list(xws, &self.workspaces);
        }
    }
/*
    pub fn hide_window(&mut self, window: Window) {
        if let Some(idx) = self.find_window(window) {
            self.list.get_mut(idx)
                .expect("valid workspace")
                .hide_window(window);
        }
    }
*/
    pub fn rescreen(&mut self, xws: &XlibWindowSystem, config: &Config) {
        let new_screens = xws.get_screen_infos().len();
        let prev_screens = self.screens;

        if new_screens == prev_screens {
            return;
        }

        self.screens = new_screens;
        debug!("rescreen {}", new_screens);

        // move and hide workspaces if their screens got removed
        if new_screens < prev_screens {
            for workspace in self.workspaces.iter_mut().filter(|x| x.screen > new_screens - 1) {
                workspace.screen = 0;
                workspace.hide(xws);
            }
        } else {
            debug!("finding workspace to rescreen");
            // assign the first hidden workspace to the new screen
            for screen in prev_screens..new_screens {
                debug!("rescreen for screen {}", screen);
                if let Some(workspace) = self.workspaces.iter_mut().find(|ws| !ws.is_visible()) {
                    debug!("moving workspace {}", workspace.tag);
                    workspace.screen = screen;
                    workspace.show(xws, config);
                }
            }
        }

        ewmh::set_desktop_viewport(xws, self.all_ws());
    }

    pub fn find_window(&self, window: Window) -> Option<usize> {
        self.workspaces.iter().enumerate().find(|(_, workspace)| workspace.contains(window)).map(|(idx, _)| idx)
    }

    pub fn get_parent_mut(&mut self, window: Window) -> Option<&mut Workspace> {
        self.workspaces.iter_mut().find(|workspace| workspace.contains(window))
    }

    fn switch_screens(&mut self, xws: &XlibWindowSystem, dest: usize) {
        let screen = self.current_ws().get_screen();
        self.workspaces[self.cur].screen = self.workspaces[dest].screen;
        self.workspaces[dest].screen = screen;

        ewmh::set_desktop_viewport(xws, self.all_ws());
    }

    pub fn redraw(&self, xws: &XlibWindowSystem, config: &Config) {
        self.all_visible_ws()
            .iter()
            .for_each(|ws| ws.redraw(xws, config));
    }

    pub fn add_strut(&mut self, window: Window) {
        if !self.struts.contains(&window) {
            self.struts.push(window);
        }
    }

    pub fn try_remove_strut(&mut self, window: Window) -> bool {
        if let Some((idx,_)) = self.struts.iter()
            .enumerate()
            .find(|(_,&x)| x == window)
        {
            self.struts.swap_remove(idx);
            true
        } else {
            false
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::ascii::AsciiExt;
use string_intern::{Symbol, Validator};

struct UpstreamValidator;
pub type Upstream = Symbol<UpstreamValidator>;

struct HandlerValidator;
pub type HandlerName = Symbol<HandlerValidator>;

struct DiskPoolValidator;
pub type DiskPoolName = Symbol<DiskPoolValidator>;

struct SessionPoolValidator;
pub type SessionPoolName = Symbol<SessionPoolValidator>;

struct OldValidator;
pub type Atom = Symbol<OldValidator>;

struct SessionIdValidator;
pub type SessionId = Symbol<SessionIdValidator>;

struct TopicValidator;
pub type Topic = Symbol<TopicValidator>;

struct LatticeNamespaceValidator;
/// Name of the lattice namespace (set of keys)
pub type Lattice = Symbol<LatticeNamespaceValidator>;

struct LatticeKeyValidator;
/// Key in lattice namespace (set of CRDT variables),
/// logically should validate same as Topic
pub type LatticeKey = Symbol<LatticeKeyValidator>;

struct LatticeVarValidator;
/// CRDT variable name in lattice
pub type LatticeVar = Symbol<LatticeVarValidator>;

quick_error! {
    #[derive(Debug)]
    pub enum BadIdent {
        InvalidChar {
            description("invalid character in identifier")
        }
    }
}

fn valid_ident(val: &str) -> bool {
    val.chars().all(|c| c.is_ascii() &&
        (c.is_alphanumeric() || c == '-' || c == '_'))
}

fn valid_var(val: &str) -> bool {
    if val.len() == 0 {
        return false;
    }
    let first = val.chars().next().unwrap();
    return (first.is_ascii() && first.is_alphabetic() || first == '_') &&
        val.chars().all(|c| c.is_ascii() && (c.is_alphanumeric() || c == '_'))
}

fn valid_namespace(val: &str) -> bool {
    val.chars().all(|c| c.is_ascii() &&
        (c.is_alphanumeric() || c == '-' || c == '_' || c == '.'))
}

fn valid_topic(val: &str) -> bool {
    val.chars().all(|c| c.is_ascii() &&
        (c.is_alphanumeric() || c == '-' || c == '_' || c == '.' || c == ':'))
}

fn valid_sid(val: &str) -> bool {
    val.chars().all(|c| c.is_ascii() &&
        (c.is_alphanumeric() || c == '-' || c == '_' || c == ':'))
}

impl Validator for UpstreamValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_ident(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "upstream{:?}", value.as_ref())
    }
}

impl Validator for HandlerValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_ident(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "handler{:?}", value.as_ref())
    }
}

impl Validator for DiskPoolValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_ident(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "disk{:?}", value.as_ref())
    }
}

impl Validator for SessionPoolValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_ident(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "sessionpool{:?}", value.as_ref())
    }
}

impl Validator for OldValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_ident(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "old{:?}", value.as_ref())
    }
}

impl Validator for TopicValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_topic(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "topic{:?}", value.as_ref())
    }
}

impl Validator for LatticeKeyValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_topic(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "latkey{:?}", value.as_ref())
    }
}

impl Validator for LatticeNamespaceValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_namespace(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "lattice{:?}", value.as_ref())
    }
}

impl Validator for LatticeVarValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_var(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "key{:?}", value.as_ref())
    }
}

impl Validator for SessionIdValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_sid(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "sessionid{:?}", value.as_ref())
    }
}
<commit_msg>drop old Atom intern<commit_after>use std::fmt;
use std::ascii::AsciiExt;
use string_intern::{Symbol, Validator};

struct UpstreamValidator;
pub type Upstream = Symbol<UpstreamValidator>;

struct HandlerValidator;
pub type HandlerName = Symbol<HandlerValidator>;

struct DiskPoolValidator;
pub type DiskPoolName = Symbol<DiskPoolValidator>;

struct SessionPoolValidator;
pub type SessionPoolName = Symbol<SessionPoolValidator>;

struct SessionIdValidator;
pub type SessionId = Symbol<SessionIdValidator>;

struct TopicValidator;
pub type Topic = Symbol<TopicValidator>;

struct LatticeNamespaceValidator;
/// Name of the lattice namespace (set of keys)
pub type Lattice = Symbol<LatticeNamespaceValidator>;

struct LatticeKeyValidator;
/// Key in lattice namespace (set of CRDT variables),
/// logically should validate same as Topic
pub type LatticeKey = Symbol<LatticeKeyValidator>;

struct LatticeVarValidator;
/// CRDT variable name in lattice
pub type LatticeVar = Symbol<LatticeVarValidator>;

quick_error! {
    #[derive(Debug)]
    pub enum BadIdent {
        InvalidChar {
            description("invalid character in identifier")
        }
    }
}

fn valid_ident(val: &str) -> bool {
    val.chars().all(|c| c.is_ascii() &&
        (c.is_alphanumeric() || c == '-' || c == '_'))
}

fn valid_var(val: &str) -> bool {
    if val.len() == 0 {
        return false;
    }
    let first = val.chars().next().unwrap();
    return (first.is_ascii() && first.is_alphabetic() || first == '_') &&
        val.chars().all(|c| c.is_ascii() && (c.is_alphanumeric() || c == '_'))
}

fn valid_namespace(val: &str) -> bool {
    val.chars().all(|c| c.is_ascii() &&
        (c.is_alphanumeric() || c == '-' || c == '_' || c == '.'))
}

fn valid_topic(val: &str) -> bool {
    val.chars().all(|c| c.is_ascii() &&
        (c.is_alphanumeric() || c == '-' || c == '_' || c == '.' || c == ':'))
}

fn valid_sid(val: &str) -> bool {
    val.chars().all(|c| c.is_ascii() &&
        (c.is_alphanumeric() || c == '-' || c == '_' || c == ':'))
}

impl Validator for UpstreamValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_ident(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "upstream{:?}", value.as_ref())
    }
}

impl Validator for HandlerValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_ident(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "handler{:?}", value.as_ref())
    }
}

impl Validator for DiskPoolValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_ident(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "disk{:?}", value.as_ref())
    }
}

impl Validator for SessionPoolValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_ident(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "sessionpool{:?}", value.as_ref())
    }
}

impl Validator for TopicValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_topic(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "topic{:?}", value.as_ref())
    }
}

impl Validator for LatticeKeyValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_topic(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "latkey{:?}", value.as_ref())
    }
}

impl Validator for LatticeNamespaceValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_namespace(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "lattice{:?}", value.as_ref())
    }
}

impl Validator for LatticeVarValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_var(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "key{:?}", value.as_ref())
    }
}

impl Validator for SessionIdValidator {
    type Err = BadIdent;
    fn validate_symbol(val: &str) -> Result<(), Self::Err> {
        if !valid_sid(val) {
            return Err(BadIdent::InvalidChar);
        }
        Ok(())
    }
    fn display(value: &Symbol<Self>, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "sessionid{:?}", value.as_ref())
    }
}
<|endoftext|>


<commit_before>pub mod tileset;

extern crate find_folder;
extern crate image as im;

use piston_window::*;
use gfx_device_gl::Resources;
use gfx_device_gl::CommandBuffer;
use gfx_graphics::GfxGraphics;
use std::fs::File;
use std::io::prelude::*;
use std::str::FromStr;
use self::tileset::{Tileset, TILESET_HEIGHT, TILE_HEIGHT, TILESET_WIDTH, TILE_WIDTH};
use ::level::Level;

pub fn read_tileset(path: &str, mut w: &mut PistonWindow) -> Tileset {

    let mut tileset = Tileset::new();

    let mut ts = match im::open(path) {
        Ok(x) => x,
        Err(i) => panic!("{:?}", i),
    };

    for i in 0..(TILESET_HEIGHT / TILE_HEIGHT) {
        for j in 0..(TILESET_WIDTH / TILE_WIDTH) {

            let tile = ts.crop(j * TILE_WIDTH, i * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT).to_rgba();

            tileset.get_set().push(
                Texture::from_image(
                    &mut w.factory,
                    &tile,
                    &TextureSettings::new()
            ).unwrap());
        }
    }

    tileset
}

pub fn read_level(path: &str) -> Level {
    let mut f = match File::open(path) {
        Ok(res) => res,
        Err(e) => panic!(e),
    };

    let mut buffer = String::new();

    match f.read_to_string(&mut buffer) {
        Ok(_) => (),
        Err(e) => panic!("{:?}", e),
    };

    let mut rows = buffer.split("\n").filter(|s| !s.is_empty());

    let first_row = match rows.next() {
        Some(x) => x,
        None => panic!("No valid Level-File"),
    };

    let mut sizes = first_row.split(" ");

    let x = match sizes.next() {
        Some(x) => x,
        None => panic!("No valid Level-File"),
    };
    let x_new = match usize::from_str(x) {
        Ok(a) => a,
        Err(_) => panic!("No valid Level-File"),
    };

    let y = match sizes.next() {
        Some(x) => x,
        None => panic!("No valid Level-File"),
    };
    let y_new = match usize::from_str(y) {
        Ok(a) => a,
        Err(_) => panic!("No valid Level-File"),
    };

    let mut level = Level::with_size(x_new, y_new);

    let mut i = 0;
    let mut j = 0;
    // Zeilen
    for s in rows {
        j = 0;
        // Spalten
        for c in s.split(" ").filter(|s| !s.is_empty()) {
            let n = match u32::from_str(c) {
                Ok(a) => a,
                Err(e) => panic!("{:?}", e),
            };
            level.get_data()[i][j] = n;
            j += 1;
        }
        i += 1;
    }

    level
}

pub fn render_level(
    tileset: &Tileset,
    g: &mut GfxGraphics<Resources,CommandBuffer>,
    view: math::Matrix2d,
    level: &mut Level)
{
    for i in 0..level.get_y() {
        for j in 0..level.get_x() {
            let tile = match tileset.get_texture(level.get_data()[i][j]) {
                Some(x) => x,
                None => panic!("No texture found."),
            };

            render_tile(&tile, g, view, j as u32 * 16 + j as u32, i as u32 * 16 + i as u32);
        }
    }
}

pub fn render_tile(
    texture: &Texture<Resources>,
    g: &mut GfxGraphics<Resources, CommandBuffer>,
    view: math::Matrix2d,
    x_coord: u32,
    y_coord: u32)
{
    // Skaliere Tile um Faktor 4
    image(texture, view.scale(4.0, 4.0).trans(x_coord as f64, y_coord as f64), g);
}
<commit_msg>Weitere plattformunabhängige Anpassung<commit_after>pub mod tileset;

extern crate find_folder;
extern crate image as im;

use piston_window::*;
use gfx_device_gl::Resources;
use gfx_device_gl::CommandBuffer;
use gfx_graphics::GfxGraphics;
use std::fs::File;
use std::io::prelude::*;
use std::str::FromStr;
use self::tileset::{Tileset, TILESET_HEIGHT, TILE_HEIGHT, TILESET_WIDTH, TILE_WIDTH};
use ::level::Level;

pub fn read_tileset(path: &str, mut w: &mut PistonWindow) -> Tileset {

    let mut tileset = Tileset::new();

    let mut ts = match im::open(path) {
        Ok(x) => x,
        Err(i) => panic!("{:?}", i),
    };

    for i in 0..(TILESET_HEIGHT / TILE_HEIGHT) {
        for j in 0..(TILESET_WIDTH / TILE_WIDTH) {

            let tile = ts.crop(j * TILE_WIDTH, i * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT).to_rgba();

            tileset.get_set().push(
                Texture::from_image(
                    &mut w.factory,
                    &tile,
                    &TextureSettings::new()
            ).unwrap());
        }
    }

    tileset
}

pub fn read_level(path: &str) -> Level {
    let mut f = match File::open(path) {
        Ok(res) => res,
        Err(e) => panic!(e),
    };

    let mut buffer = String::new();

    match f.read_to_string(&mut buffer) {
        Ok(_) => (),
        Err(e) => panic!("{:?}", e),
    };

    let mut rows = buffer.lines().filter(|s| !s.is_empty());

    let first_row = match rows.next() {
        Some(x) => x,
        None => panic!("No valid Level-File"),
    };

    let mut sizes = first_row.split(" ");

    let x = match sizes.next() {
        Some(x) => x,
        None => panic!("No valid Level-File"),
    };
    let x_new = match usize::from_str(x) {
        Ok(a) => a,
        Err(_) => panic!("No valid Level-File"),
    };

    let y = match sizes.next() {
        Some(x) => x,
        None => panic!("No valid Level-File"),
    };
    let y_new = match usize::from_str(y) {
        Ok(a) => a,
        Err(_) => panic!("No valid Level-File"),
    };

    let mut level = Level::with_size(x_new, y_new);

    let mut i = 0;
    let mut j = 0;
    // Zeilen
    for s in rows {
        j = 0;
        // Spalten
        for c in s.split(" ").filter(|s| !s.is_empty()) {
            let n = match u32::from_str(c) {
                Ok(a) => a,
                Err(e) => panic!("{:?}", e),
            };
            level.get_data()[i][j] = n;
            j += 1;
        }
        i += 1;
    }

    level
}

pub fn render_level(
    tileset: &Tileset,
    g: &mut GfxGraphics<Resources,CommandBuffer>,
    view: math::Matrix2d,
    level: &mut Level)
{
    for i in 0..level.get_y() {
        for j in 0..level.get_x() {
            let tile = match tileset.get_texture(level.get_data()[i][j]) {
                Some(x) => x,
                None => panic!("No texture found."),
            };

            render_tile(&tile, g, view, j as u32 * 16 + j as u32, i as u32 * 16 + i as u32);
        }
    }
}

pub fn render_tile(
    texture: &Texture<Resources>,
    g: &mut GfxGraphics<Resources, CommandBuffer>,
    view: math::Matrix2d,
    x_coord: u32,
    y_coord: u32)
{
    // Skaliere Tile um Faktor 4
    image(texture, view.scale(4.0, 4.0).trans(x_coord as f64, y_coord as f64), g);
}
<|endoftext|>


<commit_before>use net2::{TcpBuilder, TcpStreamExt};
#[cfg(unix)]
use nix::{
    errno::Errno, sys::select, sys::socket, sys::time::{TimeVal, TimeValLike},
};
use std::io;
use std::mem;
use std::net::{SocketAddr, TcpStream, ToSocketAddrs};
#[cfg(unix)]
use std::os::unix::prelude::*;
use std::time::Duration;
#[cfg(target_os = "windows")]
use std::{os::raw::*, os::windows::prelude::*, ptr};
#[cfg(target_os = "windows")]
use winapi::um::winsock2::*;

pub struct MyTcpBuilder<T> {
    address: T,
    bind_address: Option<SocketAddr>,
    connect_timeout: Option<Duration>,
    read_timeout: Option<Duration>,
    write_timeout: Option<Duration>,
    keepalive_time_ms: Option<u32>,
    nodelay: bool,
}

impl<T: ToSocketAddrs> MyTcpBuilder<T> {
    pub fn keepalive_time_ms(&mut self, keepalive_time_ms: Option<u32>) -> &mut Self {
        self.keepalive_time_ms = keepalive_time_ms;
        self
    }

    pub fn nodelay(&mut self, nodelay: bool) -> &mut Self {
        self.nodelay = nodelay;
        self
    }

    pub fn write_timeout(&mut self, write_timeout: Option<Duration>) -> &mut Self {
        self.write_timeout = write_timeout;
        self
    }

    pub fn read_timeout(&mut self, read_timeout: Option<Duration>) -> &mut Self {
        self.read_timeout = read_timeout;
        self
    }

    pub fn bind_address<U>(&mut self, bind_address: Option<U>) -> &mut Self
    where
        U: Into<SocketAddr>,
    {
        self.bind_address = bind_address.map(Into::into);
        self
    }

    pub fn connect_timeout(&mut self, timeout: Option<Duration>) -> &mut Self {
        self.connect_timeout = timeout;
        self
    }

    pub fn new(address: T) -> MyTcpBuilder<T> {
        MyTcpBuilder {
            address,
            bind_address: None,
            connect_timeout: None,
            read_timeout: None,
            write_timeout: None,
            keepalive_time_ms: None,
            nodelay: true,
        }
    }

    pub fn connect(self) -> io::Result<TcpStream> {
        let MyTcpBuilder {
            address,
            bind_address,
            connect_timeout,
            read_timeout,
            write_timeout,
            keepalive_time_ms,
            nodelay,
        } = self;
        let err_msg = if bind_address.is_none() {
            "could not connect to any address"
        } else {
            "could not connect to any address with specified bind address"
        };
        let err = io::Error::new(io::ErrorKind::Other, err_msg);
        address
            .to_socket_addrs()?
            .fold(Err(err), |prev, sock_addr| {
                prev.or_else(|_| {
                    let builder = if sock_addr.is_ipv4() {
                        TcpBuilder::new_v4()?
                    } else {
                        TcpBuilder::new_v6()?
                    };
                    if let Some(bind_address) = bind_address {
                        if bind_address.is_ipv4() == sock_addr.is_ipv4() {
                            builder.bind(bind_address)?;
                        }
                    }
                    if let Some(connect_timeout) = connect_timeout {
                        #[cfg(unix)]
                        connect_fd_timeout(builder.as_raw_fd(), &sock_addr, connect_timeout)?;
                        #[cfg(target_os = "windows")]
                        connect_fd_timeout(builder.as_raw_socket(), &sock_addr, connect_timeout)?;
                        builder.to_tcp_stream()
                    } else {
                        builder.connect(sock_addr)
                    }
                })
            })
            .and_then(|stream| {
                stream.set_read_timeout(read_timeout)?;
                stream.set_write_timeout(write_timeout)?;
                stream.set_keepalive_ms(keepalive_time_ms)?;
                stream.set_nodelay(nodelay)?;
                Ok(stream)
            })
    }
}

#[cfg(unix)]
fn set_non_blocking(fd: RawFd, non_blocking: bool) -> io::Result<()> {
    let stream = unsafe { TcpStream::from_raw_fd(fd) };
    let result = stream.set_nonblocking(non_blocking);
    mem::forget(stream);
    result
}

#[cfg(target_os = "windows")]
fn set_non_blocking(socket: RawSocket, non_blocking: bool) -> io::Result<()> {
    let stream = unsafe { TcpStream::from_raw_socket(socket) };
    let result = stream.set_nonblocking(non_blocking);
    mem::forget(stream);
    result
}

#[cfg(unix)]
fn connect_fd_timeout(fd: RawFd, sock_addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
    set_non_blocking(fd, true)?;

    let inet_addr = socket::InetAddr::from_std(sock_addr);
    let sock_addr = socket::SockAddr::Inet(inet_addr);
    match socket::connect(fd, &sock_addr) {
        Ok(_) => (),
        Err(err) => match err {
            ::nix::Error::Sys(Errno::EALREADY) | ::nix::Error::Sys(Errno::EINPROGRESS) => (),
            ::nix::Error::Sys(errno) => return Err(io::Error::from_raw_os_error(errno as i32)),
            _ => return Err(io::Error::new(io::ErrorKind::Other, err)),
        },
    }

    let mut fd_set = select::FdSet::new();
    let socket_fd = fd;
    fd_set.insert(socket_fd);
    let mut timeout_timeval = TimeVal::microseconds(timeout.as_secs() as i64 * 1000 * 1000);

    let select_res = select::select(
        socket_fd + 1,
        None,
        Some(&mut fd_set),
        None,
        Some(&mut timeout_timeval),
    );

    let select_res = select_res.map_err(|err| match err {
        ::nix::Error::Sys(errno) => io::Error::from_raw_os_error(errno as i32),
        _ => io::Error::new(io::ErrorKind::Other, err),
    })?;

    if select_res == -1 {
        return Err(io::Error::last_os_error());
    }

    if select_res != 1 {
        return Err(io::ErrorKind::TimedOut.into());
    }

    let socket_error_code = socket::getsockopt(socket_fd, socket::sockopt::SocketError);

    let socket_error_code = socket_error_code.map_err(|err| match err {
        ::nix::Error::Sys(errno) => io::Error::from_raw_os_error(errno as i32),
        _ => io::Error::new(io::ErrorKind::Other, err),
    })?;

    if socket_error_code != 0 {
        return Err(io::Error::from_raw_os_error(socket_error_code));
    }

    set_non_blocking(fd, false)
}

#[cfg(target_os = "windows")]
fn connect_fd_timeout(
    socket: RawSocket,
    sock_addr: &SocketAddr,
    timeout: Duration,
) -> io::Result<()> {
    set_non_blocking(socket, true)?;
    let (name, name_len) = match *sock_addr {
        SocketAddr::V4(ref a) => (a as *const _ as *const _, mem::size_of_val(a) as c_int),
        SocketAddr::V6(ref a) => (a as *const _ as *const _, mem::size_of_val(a) as c_int),
    };
    let result = unsafe { connect(socket as usize, name, name_len) };
    if result == SOCKET_ERROR {
        let err = io::Error::last_os_error();
        match err.raw_os_error() {
            Some(WSAEWOULDBLOCK) => {
                let mut write_fds = fd_set {
                    fd_count: 1,
                    fd_array: [0; FD_SETSIZE],
                };
                write_fds.fd_array[0] = socket as usize;
                let mut err_fds = write_fds.clone();
                let timeout = timeval {
                    tv_sec: timeout.as_secs() as c_long,
                    tv_usec: 0,
                };

                let result =
                    unsafe { select(0, ptr::null_mut(), &mut write_fds, &mut err_fds, &timeout) };

                if result == 0 {
                    return Err(io::ErrorKind::TimedOut.into());
                } else if result == SOCKET_ERROR {
                    return Err(io::Error::last_os_error());
                } else {
                    let mut error = None;
                    for i in 0..(err_fds.fd_count as usize) {
                        if err_fds.fd_array[i] as u64 == socket {
                            error = Some(true);
                        }
                    }
                    for i in 0..(write_fds.fd_count as usize) {
                        if write_fds.fd_array[i] as u64 == socket {
                            error = Some(false);
                        }
                    }
                    match error {
                        Some(false) => (),
                        Some(true) => {
                            let mut opt_val = 0i32;
                            let mut opt_len = mem::size_of::<i32>() as c_int;
                            let result = unsafe {
                                getsockopt(
                                    socket as usize,
                                    SOL_SOCKET,
                                    SO_ERROR,
                                    &mut opt_val as *mut _ as *mut _,
                                    &mut opt_len,
                                )
                            };
                            return Err(io::Error::from_raw_os_error(result));
                        }
                        None => unreachable!(),
                    }
                }
            }
            _ => return Err(err),
        }
    }
    set_non_blocking(socket, false)
}
<commit_msg>Cast rust RawSocket to usize to compare with winapi socket<commit_after>use net2::{TcpBuilder, TcpStreamExt};
#[cfg(unix)]
use nix::{
    errno::Errno, sys::select, sys::socket, sys::time::{TimeVal, TimeValLike},
};
use std::io;
use std::mem;
use std::net::{SocketAddr, TcpStream, ToSocketAddrs};
#[cfg(unix)]
use std::os::unix::prelude::*;
use std::time::Duration;
#[cfg(target_os = "windows")]
use std::{os::raw::*, os::windows::prelude::*, ptr};
#[cfg(target_os = "windows")]
use winapi::um::winsock2::*;

pub struct MyTcpBuilder<T> {
    address: T,
    bind_address: Option<SocketAddr>,
    connect_timeout: Option<Duration>,
    read_timeout: Option<Duration>,
    write_timeout: Option<Duration>,
    keepalive_time_ms: Option<u32>,
    nodelay: bool,
}

impl<T: ToSocketAddrs> MyTcpBuilder<T> {
    pub fn keepalive_time_ms(&mut self, keepalive_time_ms: Option<u32>) -> &mut Self {
        self.keepalive_time_ms = keepalive_time_ms;
        self
    }

    pub fn nodelay(&mut self, nodelay: bool) -> &mut Self {
        self.nodelay = nodelay;
        self
    }

    pub fn write_timeout(&mut self, write_timeout: Option<Duration>) -> &mut Self {
        self.write_timeout = write_timeout;
        self
    }

    pub fn read_timeout(&mut self, read_timeout: Option<Duration>) -> &mut Self {
        self.read_timeout = read_timeout;
        self
    }

    pub fn bind_address<U>(&mut self, bind_address: Option<U>) -> &mut Self
    where
        U: Into<SocketAddr>,
    {
        self.bind_address = bind_address.map(Into::into);
        self
    }

    pub fn connect_timeout(&mut self, timeout: Option<Duration>) -> &mut Self {
        self.connect_timeout = timeout;
        self
    }

    pub fn new(address: T) -> MyTcpBuilder<T> {
        MyTcpBuilder {
            address,
            bind_address: None,
            connect_timeout: None,
            read_timeout: None,
            write_timeout: None,
            keepalive_time_ms: None,
            nodelay: true,
        }
    }

    pub fn connect(self) -> io::Result<TcpStream> {
        let MyTcpBuilder {
            address,
            bind_address,
            connect_timeout,
            read_timeout,
            write_timeout,
            keepalive_time_ms,
            nodelay,
        } = self;
        let err_msg = if bind_address.is_none() {
            "could not connect to any address"
        } else {
            "could not connect to any address with specified bind address"
        };
        let err = io::Error::new(io::ErrorKind::Other, err_msg);
        address
            .to_socket_addrs()?
            .fold(Err(err), |prev, sock_addr| {
                prev.or_else(|_| {
                    let builder = if sock_addr.is_ipv4() {
                        TcpBuilder::new_v4()?
                    } else {
                        TcpBuilder::new_v6()?
                    };
                    if let Some(bind_address) = bind_address {
                        if bind_address.is_ipv4() == sock_addr.is_ipv4() {
                            builder.bind(bind_address)?;
                        }
                    }
                    if let Some(connect_timeout) = connect_timeout {
                        #[cfg(unix)]
                        connect_fd_timeout(builder.as_raw_fd(), &sock_addr, connect_timeout)?;
                        #[cfg(target_os = "windows")]
                        connect_fd_timeout(builder.as_raw_socket(), &sock_addr, connect_timeout)?;
                        builder.to_tcp_stream()
                    } else {
                        builder.connect(sock_addr)
                    }
                })
            })
            .and_then(|stream| {
                stream.set_read_timeout(read_timeout)?;
                stream.set_write_timeout(write_timeout)?;
                stream.set_keepalive_ms(keepalive_time_ms)?;
                stream.set_nodelay(nodelay)?;
                Ok(stream)
            })
    }
}

#[cfg(unix)]
fn set_non_blocking(fd: RawFd, non_blocking: bool) -> io::Result<()> {
    let stream = unsafe { TcpStream::from_raw_fd(fd) };
    let result = stream.set_nonblocking(non_blocking);
    mem::forget(stream);
    result
}

#[cfg(target_os = "windows")]
fn set_non_blocking(socket: RawSocket, non_blocking: bool) -> io::Result<()> {
    let stream = unsafe { TcpStream::from_raw_socket(socket) };
    let result = stream.set_nonblocking(non_blocking);
    mem::forget(stream);
    result
}

#[cfg(unix)]
fn connect_fd_timeout(fd: RawFd, sock_addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
    set_non_blocking(fd, true)?;

    let inet_addr = socket::InetAddr::from_std(sock_addr);
    let sock_addr = socket::SockAddr::Inet(inet_addr);
    match socket::connect(fd, &sock_addr) {
        Ok(_) => (),
        Err(err) => match err {
            ::nix::Error::Sys(Errno::EALREADY) | ::nix::Error::Sys(Errno::EINPROGRESS) => (),
            ::nix::Error::Sys(errno) => return Err(io::Error::from_raw_os_error(errno as i32)),
            _ => return Err(io::Error::new(io::ErrorKind::Other, err)),
        },
    }

    let mut fd_set = select::FdSet::new();
    let socket_fd = fd;
    fd_set.insert(socket_fd);
    let mut timeout_timeval = TimeVal::microseconds(timeout.as_secs() as i64 * 1000 * 1000);

    let select_res = select::select(
        socket_fd + 1,
        None,
        Some(&mut fd_set),
        None,
        Some(&mut timeout_timeval),
    );

    let select_res = select_res.map_err(|err| match err {
        ::nix::Error::Sys(errno) => io::Error::from_raw_os_error(errno as i32),
        _ => io::Error::new(io::ErrorKind::Other, err),
    })?;

    if select_res == -1 {
        return Err(io::Error::last_os_error());
    }

    if select_res != 1 {
        return Err(io::ErrorKind::TimedOut.into());
    }

    let socket_error_code = socket::getsockopt(socket_fd, socket::sockopt::SocketError);

    let socket_error_code = socket_error_code.map_err(|err| match err {
        ::nix::Error::Sys(errno) => io::Error::from_raw_os_error(errno as i32),
        _ => io::Error::new(io::ErrorKind::Other, err),
    })?;

    if socket_error_code != 0 {
        return Err(io::Error::from_raw_os_error(socket_error_code));
    }

    set_non_blocking(fd, false)
}

#[cfg(target_os = "windows")]
fn connect_fd_timeout(
    socket: RawSocket,
    sock_addr: &SocketAddr,
    timeout: Duration,
) -> io::Result<()> {
    set_non_blocking(socket, true)?;
    let (name, name_len) = match *sock_addr {
        SocketAddr::V4(ref a) => (a as *const _ as *const _, mem::size_of_val(a) as c_int),
        SocketAddr::V6(ref a) => (a as *const _ as *const _, mem::size_of_val(a) as c_int),
    };
    let result = unsafe { connect(socket as usize, name, name_len) };
    if result == SOCKET_ERROR {
        let err = io::Error::last_os_error();
        match err.raw_os_error() {
            Some(WSAEWOULDBLOCK) => {
                let mut write_fds = fd_set {
                    fd_count: 1,
                    fd_array: [0; FD_SETSIZE],
                };
                write_fds.fd_array[0] = socket as usize;
                let mut err_fds = write_fds.clone();
                let timeout = timeval {
                    tv_sec: timeout.as_secs() as c_long,
                    tv_usec: 0,
                };

                let result =
                    unsafe { select(0, ptr::null_mut(), &mut write_fds, &mut err_fds, &timeout) };

                if result == 0 {
                    return Err(io::ErrorKind::TimedOut.into());
                } else if result == SOCKET_ERROR {
                    return Err(io::Error::last_os_error());
                } else {
                    let mut error = None;
                    for i in 0..(err_fds.fd_count as usize) {
                        if err_fds.fd_array[i] == socket as usize {
                            error = Some(true);
                        }
                    }
                    for i in 0..(write_fds.fd_count as usize) {
                        if write_fds.fd_array[i] == socket as usize {
                            error = Some(false);
                        }
                    }
                    match error {
                        Some(false) => (),
                        Some(true) => {
                            let mut opt_val = 0i32;
                            let mut opt_len = mem::size_of::<i32>() as c_int;
                            let result = unsafe {
                                getsockopt(
                                    socket as usize,
                                    SOL_SOCKET,
                                    SO_ERROR,
                                    &mut opt_val as *mut _ as *mut _,
                                    &mut opt_len,
                                )
                            };
                            return Err(io::Error::from_raw_os_error(result));
                        }
                        None => unreachable!(),
                    }
                }
            }
            _ => return Err(err),
        }
    }
    set_non_blocking(socket, false)
}
<|endoftext|>


<commit_before>use dao::TableName;
use column::Column;
use dao::ColumnName;
use types::SqlType;

#[derive(Debug, PartialEq, Clone)]
pub struct Table {
    pub name: TableName,

    /// comment of this table
    pub comment: Option<String>,

    /// columns of this table
    pub columns: Vec<Column>,

    /// views can also be generated
    pub is_view: bool,

    pub table_key: Vec<TableKey>,
}

impl Table {
    pub fn complete_name(&self) -> String {
        self.name.complete_name()
    }

    pub fn get_primary_column_names(&self) -> Vec<&ColumnName> {
        let mut primary: Vec<&ColumnName> = vec![];
        for key in &self.table_key {
            match *key {
                TableKey::PrimaryKey(ref pk) => for col in &pk.columns {
                    primary.push(col)
                },
                _ => (),
            }
        }
        primary
    }

    fn get_primary_columns(&self) -> Vec<&Column> {
        self.get_primary_column_names()
            .iter()
            .filter_map(|column_name| self.get_column(column_name))
            .collect()
    }

    pub fn get_primary_column_types(&self) -> Vec<&SqlType> {
        self.get_primary_columns()
            .iter()
            .map(|column| &column.specification.sql_type)
            .collect()
    }

    pub fn get_foreign_keys(&self) -> Vec<&ForeignKey> {
        let mut foreign: Vec<&ForeignKey> = vec![];
        for key in &self.table_key {
            match *key {
                TableKey::ForeignKey(ref fk) => foreign.push(fk),
                _ => (),
            }
        }
        foreign
    }

    pub fn get_foreign_key_to_table(&self, table_name: &TableName) -> Option<&ForeignKey> {
        let foreign_keys: Vec<&ForeignKey> = self.get_foreign_keys();
        for fk in foreign_keys {
            if fk.foreign_table == *table_name {
                return Some(fk);
            }
        }
        None
    }

    fn get_foreign_columns_to_table(&self, table_name: &TableName) -> Vec<&Column> {
        self.get_foreign_column_names_to_table(table_name)
            .iter()
            .filter_map(|column_name| self.get_column(column_name))
            .collect()
    }

    pub fn get_foreign_column_types_to_table(&self, table_name: &TableName) -> Vec<&SqlType> {
        self.get_foreign_columns_to_table(table_name)
            .iter()
            .map(|column| &column.specification.sql_type)
            .collect()
    }

    pub fn get_foreign_column_names_to_table(&self, table_name: &TableName) -> Vec<&ColumnName> {
        let mut foreign_columns = vec![];
        let foreign_keys = self.get_foreign_key_to_table(table_name);
        for fk in &foreign_keys {
            for fk_column in &fk.columns {
                foreign_columns.push(fk_column);
            }
        }
        foreign_columns
    }

    pub fn get_foreign_column_names(&self) -> Vec<&ColumnName> {
        let mut foreign_columns = vec![];
        let foreign_keys = self.get_foreign_keys();
        for fk in &foreign_keys {
            for fk_column in &fk.columns {
                foreign_columns.push(fk_column);
            }
        }
        foreign_columns
    }

    pub fn get_referred_columns_to_table(
        &self,
        table_name: &TableName,
    ) -> Option<&Vec<ColumnName>> {
        let foreign_keys: Vec<&ForeignKey> = self.get_foreign_keys();
        for fk in foreign_keys {
            if fk.foreign_table == *table_name {
                return Some(&fk.referred_columns);
            }
        }
        None
    }

    pub fn get_column(&self, column_name: &ColumnName) -> Option<&Column> {
        self.columns.iter().find(|c| c.name == *column_name)
    }
}

#[derive(Debug, PartialEq, Clone)]
pub struct PrimaryKey {
    pub name: Option<String>,
    pub columns: Vec<ColumnName>,
}

#[derive(Debug, PartialEq, Clone)]
pub struct UniqueKey {
    pub name: Option<String>,
    pub columns: Vec<ColumnName>,
}

#[derive(Debug, PartialEq, Clone)]
pub struct ForeignKey {
    pub name: Option<String>,
    pub columns: Vec<ColumnName>,
    // referred foreign table
    pub foreign_table: TableName,
    // referred column of the foreign table
    pub referred_columns: Vec<ColumnName>,
}

#[derive(Debug, PartialEq, Clone)]
pub struct Key {
    pub name: Option<String>,
    pub columns: Vec<ColumnName>,
}

#[derive(Debug, PartialEq, Clone)]
pub enum TableKey {
    PrimaryKey(PrimaryKey),
    UniqueKey(UniqueKey),
    Key(Key),
    ForeignKey(ForeignKey),
}

#[derive(Debug)]
pub struct SchemaContent {
    pub schema: String,
    pub tablenames: Vec<TableName>,
    pub views: Vec<TableName>,
}
<commit_msg>Add comment about foreign keys<commit_after>use dao::TableName;
use column::Column;
use dao::ColumnName;
use types::SqlType;

#[derive(Debug, PartialEq, Clone)]
pub struct Table {
    pub name: TableName,

    /// comment of this table
    pub comment: Option<String>,

    /// columns of this table
    pub columns: Vec<Column>,

    /// views can also be generated
    pub is_view: bool,

    pub table_key: Vec<TableKey>,
}

impl Table {
    pub fn complete_name(&self) -> String {
        self.name.complete_name()
    }

    pub fn get_primary_column_names(&self) -> Vec<&ColumnName> {
        let mut primary: Vec<&ColumnName> = vec![];
        for key in &self.table_key {
            match *key {
                TableKey::PrimaryKey(ref pk) => for col in &pk.columns {
                    primary.push(col)
                },
                _ => (),
            }
        }
        primary
    }

    fn get_primary_columns(&self) -> Vec<&Column> {
        self.get_primary_column_names()
            .iter()
            .filter_map(|column_name| self.get_column(column_name))
            .collect()
    }

    pub fn get_primary_column_types(&self) -> Vec<&SqlType> {
        self.get_primary_columns()
            .iter()
            .map(|column| &column.specification.sql_type)
            .collect()
    }

    pub fn get_foreign_keys(&self) -> Vec<&ForeignKey> {
        let mut foreign: Vec<&ForeignKey> = vec![];
        for key in &self.table_key {
            match *key {
                TableKey::ForeignKey(ref fk) => foreign.push(fk),
                _ => (),
            }
        }
        foreign
    }

    pub fn get_foreign_key_to_table(&self, table_name: &TableName) -> Option<&ForeignKey> {
        let foreign_keys: Vec<&ForeignKey> = self.get_foreign_keys();
        for fk in foreign_keys {
            if fk.foreign_table == *table_name {
                return Some(fk);
            }
        }
        None
    }

    fn get_foreign_columns_to_table(&self, table_name: &TableName) -> Vec<&Column> {
        self.get_foreign_column_names_to_table(table_name)
            .iter()
            .filter_map(|column_name| self.get_column(column_name))
            .collect()
    }

    pub fn get_foreign_column_types_to_table(&self, table_name: &TableName) -> Vec<&SqlType> {
        self.get_foreign_columns_to_table(table_name)
            .iter()
            .map(|column| &column.specification.sql_type)
            .collect()
    }

    pub fn get_foreign_column_names_to_table(&self, table_name: &TableName) -> Vec<&ColumnName> {
        let mut foreign_columns = vec![];
        let foreign_keys = self.get_foreign_key_to_table(table_name);
        for fk in &foreign_keys {
            for fk_column in &fk.columns {
                foreign_columns.push(fk_column);
            }
        }
        foreign_columns
    }

    ///
    pub fn get_foreign_column_names(&self) -> Vec<&ColumnName> {
        let mut foreign_columns = vec![];
        let foreign_keys = self.get_foreign_keys();
        for fk in &foreign_keys {
            for fk_column in &fk.columns {
                foreign_columns.push(fk_column);
            }
        }
        foreign_columns
    }

    /// return the local columns of this table
    pub fn get_referred_columns_to_table(
        &self,
        table_name: &TableName,
    ) -> Option<&Vec<ColumnName>> {
        let foreign_keys: Vec<&ForeignKey> = self.get_foreign_keys();
        for fk in foreign_keys {
            if fk.foreign_table == *table_name {
                return Some(&fk.referred_columns);
            }
        }
        None
    }

    pub fn get_column(&self, column_name: &ColumnName) -> Option<&Column> {
        self.columns.iter().find(|c| c.name == *column_name)
    }
}

#[derive(Debug, PartialEq, Clone)]
pub struct PrimaryKey {
    pub name: Option<String>,
    pub columns: Vec<ColumnName>,
}

#[derive(Debug, PartialEq, Clone)]
pub struct UniqueKey {
    pub name: Option<String>,
    pub columns: Vec<ColumnName>,
}

/// example:
///     category { id, name }
///     product { product_id, name, category_id }
///
/// if the table in context is product and the foreign table is category
/// ForeignKey{
///     name: product_category_fkey
///     columns: [category_id]
///     foreign_table: category
///     referred_columns: [id]
/// }
#[derive(Debug, PartialEq, Clone)]
pub struct ForeignKey {
    pub name: Option<String>,
    // the local columns
    pub columns: Vec<ColumnName>,
    // referred foreign table
    pub foreign_table: TableName,
    // referred column of the foreign table
    // this is most likely the primary key of the table in context
    pub referred_columns: Vec<ColumnName>,
}

#[derive(Debug, PartialEq, Clone)]
pub struct Key {
    pub name: Option<String>,
    pub columns: Vec<ColumnName>,
}

#[derive(Debug, PartialEq, Clone)]
pub enum TableKey {
    PrimaryKey(PrimaryKey),
    UniqueKey(UniqueKey),
    Key(Key),
    ForeignKey(ForeignKey),
}

#[derive(Debug)]
pub struct SchemaContent {
    pub schema: String,
    pub tablenames: Vec<TableName>,
    pub views: Vec<TableName>,
}
<|endoftext|>


<commit_before>// Copyright (c) 2020 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use crate::{agent_error::ImlAgentError, env, lustre::search_rootpath};
use futures::{future::try_join_all, future::Future, stream, StreamExt, TryStreamExt};
use iml_wire_types::{FidError, FidItem};
use liblustreapi::LlapiFid;
use std::path::PathBuf;
use structopt::clap::arg_enum;
use tokio::{fs, process::Command};

struct Work {
    fid: FidItem,
    src_file: String,
    dest_file: String,
}

const LARGEFILE: u64 = 1024 * 1024 * 1024;

fn do_rsync<'a>(
    work_list: &'a [Work],
) -> impl Future<Output = Result<Vec<FidError>, ImlAgentError>> + 'a {
    stream::iter(work_list)
        .map(|work| async move {
            let output = Command::new("rsync")
                .arg("-a")
                .arg("-t")
                .arg("-X")
                .arg(&work.src_file)
                .arg(&work.dest_file)
                .output()
                .await?;

            Ok::<_, ImlAgentError>(FidError {
                fid: work.fid.fid.clone(),
                data: work.fid.data.clone(),
                errno: output.status.code().unwrap_or(1) as i16,
            })
        })
        .chunks(10)
        .map(Ok)
        .try_fold(vec![], |mut acc, xs| async {
            let xs = try_join_all(xs).await?;

            acc.extend(xs);

            Ok::<_, ImlAgentError>(acc)
        })
}

async fn archive_fids(
    llapi: LlapiFid,
    dest_src: &str,
    fid_list: Vec<FidItem>,
) -> Result<Vec<FidError>, ImlAgentError> {
    let mut result = vec![];

    let mut rsync_list: Vec<Work> = vec![];
    let mpi_path = format!("{}/mpirun", env::get_openmpi_path());
    let mpi_count = env::get_openmpi_count();

    for fid in fid_list {
        let fid_path = match llapi.fid2path(&fid.fid) {
            Ok(x) => x,
            Err(_) => {
                tracing::error!("llapi: failed on fid {}", &fid.fid);
                continue;
            }
        };

        let src_file = format!("{}/{}", llapi.mntpt(), &fid_path);
        let dest_file = format!("{}/{}", &dest_src, &fid_path);
        let mut dest_dir = PathBuf::from(&dest_file);

        dest_dir.pop();
        if !dest_dir.is_dir() {
            fs::create_dir_all(&dest_dir).await?;
        }

        let md = fs::metadata(&src_file).await?;
        /* invoking mpifileutils is slow, so only do it for directories
         * and big files, otherwise just use rsync
         */
        if md.is_dir() || (md.len() > LARGEFILE) {
            let output = Command::new(&mpi_path)
                .arg("--allow-run-as-root")
                .arg("-c")
                .arg(format!("{}", mpi_count))
                .arg("--hostfile")
                .arg("/etc/iml/filesync-hostfile")
                .arg("dsync")
                .arg("-S")
                .arg(src_file)
                .arg(dest_file)
                .output()
                .await?;

            if !output.status.success() {
                let FidItem { fid, data } = fid;
                result.push(FidError {
                    fid,
                    data,
                    errno: output.status.code().unwrap_or(1) as i16,
                });
            }
            tracing::debug!(
                "dsync exited with {} {} {}",
                output.status,
                std::str::from_utf8(&output.stdout)?,
                std::str::from_utf8(&output.stderr)?
            );
        } else {
            rsync_list.push(Work {
                fid,
                src_file,
                dest_file,
            });

            if rsync_list.len() >= 500 {
                let mut rsync_res = do_rsync(&rsync_list).await?;

                result.append(&mut rsync_res);
                rsync_res.clear();
                rsync_list.clear();
            }
        }
    }

    let mut rsync_res = do_rsync(&rsync_list).await?;

    result.append(&mut rsync_res);

    Ok(result)
}

async fn restore_fids(
    llapi: LlapiFid,
    dest_src: &str,
    fid_list: Vec<FidItem>,
) -> Result<Vec<FidError>, ImlAgentError> {
    let mut result = vec![];
    let mpi_path = format!("{}/mpirun", env::get_openmpi_path());
    let mpi_count = env::get_openmpi_count();

    for fid in fid_list {
        let fid_path = llapi.fid2path(&fid.fid)?;
        let src_file = format!("{}/{}", llapi.mntpt(), &fid_path);
        let dest_file = format!("{}/{}", &dest_src, &fid_path);
        let mut dest_dir = PathBuf::from(&src_file);

        dest_dir.pop();
        fs::create_dir_all(&dest_dir).await?;

        let md = fs::metadata(&dest_file).await?;
        /* invoking mpifileutils is slow, so only do it for directories
         * and big files, otherwise just use rsync
         */
        let output;
        if md.is_dir() || (md.len() > LARGEFILE) {
            output = Command::new(&mpi_path)
                .arg("--allow-run-as-root")
                .arg("-c")
                .arg(format!("{}", mpi_count))
                .arg("--hostfile")
                .arg("/etc/iml/filesync-hostfile")
                .arg("dsync")
                .arg("-S")
                .arg(dest_file)
                .arg(src_file)
                .output();
        } else {
            output = Command::new("rsync").arg(dest_file).arg(src_file).output();
        }

        let output = output.await?;

        if !output.status.success() {
            // TODO: handle termination conditions without defaulting to 0
            let res = FidError {
                fid: fid.fid.clone(),
                data: fid.data.clone(),
                errno: output.status.code().unwrap_or(1) as i16,
            };
            result.push(res);
        }
        tracing::debug!(
            "exited with {} {} {}",
            output.status,
            std::str::from_utf8(&output.stdout)?,
            std::str::from_utf8(&output.stderr)?
        );
    }

    Ok(result)
}

arg_enum! {
    #[derive(Debug, serde::Deserialize, Clone, Copy, PartialEq)]
    #[serde(rename_all = "lowercase")]
    pub enum ActionType {
    Push,
    Pull,
    }
}

#[derive(Debug, serde::Deserialize)]
pub struct TaskArgs {
    pub remote: String,
    pub action: ActionType,
}
/// Process FIDs
pub async fn process_fids(
    (fsname_or_mntpath, task_args, fid_list): (String, TaskArgs, Vec<FidItem>),
) -> Result<Vec<FidError>, ImlAgentError> {
    let llapi = search_rootpath(fsname_or_mntpath).await?;
    match task_args.action {
        ActionType::Push => archive_fids(llapi.clone(), &task_args.remote, fid_list).await,
        ActionType::Pull => restore_fids(llapi.clone(), &task_args.remote, fid_list).await,
    }
}
<commit_msg>Disable xattr copy in rsync (#2320)<commit_after>// Copyright (c) 2020 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use crate::{agent_error::ImlAgentError, env, lustre::search_rootpath};
use futures::{future::try_join_all, future::Future, stream, StreamExt, TryStreamExt};
use iml_wire_types::{FidError, FidItem};
use liblustreapi::LlapiFid;
use std::path::PathBuf;
use structopt::clap::arg_enum;
use tokio::{fs, process::Command};

struct Work {
    fid: FidItem,
    src_file: String,
    dest_file: String,
}

const LARGEFILE: u64 = 1024 * 1024 * 1024;

fn do_rsync<'a>(
    work_list: &'a [Work],
) -> impl Future<Output = Result<Vec<FidError>, ImlAgentError>> + 'a {
    stream::iter(work_list)
        .map(|work| async move {
            let output = Command::new("rsync")
                .arg("-a")
                .arg("-t")
                .arg(&work.src_file)
                .arg(&work.dest_file)
                .output()
                .await?;

            Ok::<_, ImlAgentError>(FidError {
                fid: work.fid.fid.clone(),
                data: work.fid.data.clone(),
                errno: output.status.code().unwrap_or(1) as i16,
            })
        })
        .chunks(10)
        .map(Ok)
        .try_fold(vec![], |mut acc, xs| async {
            let xs = try_join_all(xs).await?;

            acc.extend(xs);

            Ok::<_, ImlAgentError>(acc)
        })
}

async fn archive_fids(
    llapi: LlapiFid,
    dest_src: &str,
    fid_list: Vec<FidItem>,
) -> Result<Vec<FidError>, ImlAgentError> {
    let mut result = vec![];

    let mut rsync_list: Vec<Work> = vec![];
    let mpi_path = format!("{}/mpirun", env::get_openmpi_path());
    let mpi_count = env::get_openmpi_count();

    for fid in fid_list {
        let fid_path = match llapi.fid2path(&fid.fid) {
            Ok(x) => x,
            Err(_) => {
                tracing::error!("llapi: failed on fid {}", &fid.fid);
                continue;
            }
        };

        let src_file = format!("{}/{}", llapi.mntpt(), &fid_path);
        let dest_file = format!("{}/{}", &dest_src, &fid_path);
        let mut dest_dir = PathBuf::from(&dest_file);

        dest_dir.pop();
        if !dest_dir.is_dir() {
            fs::create_dir_all(&dest_dir).await?;
        }

        let md = fs::metadata(&src_file).await?;
        /* invoking mpifileutils is slow, so only do it for directories
         * and big files, otherwise just use rsync
         */
        if md.is_dir() || (md.len() > LARGEFILE) {
            let output = Command::new(&mpi_path)
                .arg("--allow-run-as-root")
                .arg("-c")
                .arg(format!("{}", mpi_count))
                .arg("--hostfile")
                .arg("/etc/iml/filesync-hostfile")
                .arg("dsync")
                .arg("-S")
                .arg(src_file)
                .arg(dest_file)
                .output()
                .await?;

            if !output.status.success() {
                let FidItem { fid, data } = fid;
                result.push(FidError {
                    fid,
                    data,
                    errno: output.status.code().unwrap_or(1) as i16,
                });
            }
            tracing::debug!(
                "dsync exited with {} {} {}",
                output.status,
                std::str::from_utf8(&output.stdout)?,
                std::str::from_utf8(&output.stderr)?
            );
        } else {
            rsync_list.push(Work {
                fid,
                src_file,
                dest_file,
            });

            if rsync_list.len() >= 500 {
                let mut rsync_res = do_rsync(&rsync_list).await?;

                result.append(&mut rsync_res);
                rsync_res.clear();
                rsync_list.clear();
            }
        }
    }

    let mut rsync_res = do_rsync(&rsync_list).await?;

    result.append(&mut rsync_res);

    Ok(result)
}

async fn restore_fids(
    llapi: LlapiFid,
    dest_src: &str,
    fid_list: Vec<FidItem>,
) -> Result<Vec<FidError>, ImlAgentError> {
    let mut result = vec![];
    let mpi_path = format!("{}/mpirun", env::get_openmpi_path());
    let mpi_count = env::get_openmpi_count();

    for fid in fid_list {
        let fid_path = llapi.fid2path(&fid.fid)?;
        let src_file = format!("{}/{}", llapi.mntpt(), &fid_path);
        let dest_file = format!("{}/{}", &dest_src, &fid_path);
        let mut dest_dir = PathBuf::from(&src_file);

        dest_dir.pop();
        fs::create_dir_all(&dest_dir).await?;

        let md = fs::metadata(&dest_file).await?;
        /* invoking mpifileutils is slow, so only do it for directories
         * and big files, otherwise just use rsync
         */
        let output;
        if md.is_dir() || (md.len() > LARGEFILE) {
            output = Command::new(&mpi_path)
                .arg("--allow-run-as-root")
                .arg("-c")
                .arg(format!("{}", mpi_count))
                .arg("--hostfile")
                .arg("/etc/iml/filesync-hostfile")
                .arg("dsync")
                .arg("-S")
                .arg(dest_file)
                .arg(src_file)
                .output();
        } else {
            output = Command::new("rsync").arg(dest_file).arg(src_file).output();
        }

        let output = output.await?;

        if !output.status.success() {
            // TODO: handle termination conditions without defaulting to 0
            let res = FidError {
                fid: fid.fid.clone(),
                data: fid.data.clone(),
                errno: output.status.code().unwrap_or(1) as i16,
            };
            result.push(res);
        }
        tracing::debug!(
            "exited with {} {} {}",
            output.status,
            std::str::from_utf8(&output.stdout)?,
            std::str::from_utf8(&output.stderr)?
        );
    }

    Ok(result)
}

arg_enum! {
    #[derive(Debug, serde::Deserialize, Clone, Copy, PartialEq)]
    #[serde(rename_all = "lowercase")]
    pub enum ActionType {
    Push,
    Pull,
    }
}

#[derive(Debug, serde::Deserialize)]
pub struct TaskArgs {
    pub remote: String,
    pub action: ActionType,
}
/// Process FIDs
pub async fn process_fids(
    (fsname_or_mntpath, task_args, fid_list): (String, TaskArgs, Vec<FidItem>),
) -> Result<Vec<FidError>, ImlAgentError> {
    let llapi = search_rootpath(fsname_or_mntpath).await?;
    match task_args.action {
        ActionType::Push => archive_fids(llapi.clone(), &task_args.remote, fid_list).await,
        ActionType::Pull => restore_fids(llapi.clone(), &task_args.remote, fid_list).await,
    }
}
<|endoftext|>


<commit_before>const HEAP_START: usize = 0x00100000;
const HEAP_END: usize = 0x00EFFFFF;

static mut heap_ptr: usize = HEAP_START;

extern {
    fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8;
}

#[no_mangle]
pub unsafe extern fn rust_allocate(size: usize, align: usize) -> *mut u8 {
    let mut new_heap_ptr = heap_ptr;
    if heap_ptr % align != 0 {
        new_heap_ptr += (align - (heap_ptr % align));
    }

    if new_heap_ptr + size >= HEAP_END {
        0 as *mut u8
    }
    else {
        heap_ptr = new_heap_ptr + size;
        new_heap_ptr as *mut u8
    }
}

#[no_mangle]
pub unsafe extern fn rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
    let new_ptr = rust_allocate(size, align);
    if !ptr.is_null() {
        memcpy(ptr, new_ptr, old_size);
    }
    ptr
}

#[allow(unused_varibles)]
#[no_mangle]
pub extern fn rust_reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> usize {
    old_size
}

#[allow(unused_varibles)]
#[no_mangle]
pub extern fn rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {}

#[allow(unused_varibles)]
#[no_mangle]
pub extern fn rust_usable_size(size: usize, align: usize) -> usize {
    size
}

#[no_mangle]
pub extern fn rust_stats_print() {}
<commit_msg>Working heap, no modulo<commit_after>const HEAP_START: usize = 0x00100000;
const HEAP_END: usize = 0x00EFFFFF;

use core;

static mut heap_ptr: usize = HEAP_START;

extern {
    fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8;
}

#[no_mangle]
pub unsafe extern fn rust_allocate(size: usize, align: usize) -> *mut u8 {
    let mut new_heap_ptr = heap_ptr;
    // if heap_ptr % align != 0 {
    //     new_heap_ptr += (align - (heap_ptr % align));
    // }

    if new_heap_ptr + size >= HEAP_END {
        core::ptr::null_mut()
    }
    else {
        heap_ptr = new_heap_ptr + size;
        new_heap_ptr as *mut u8
    }
}

#[no_mangle]
pub unsafe extern fn rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
    let new_ptr = rust_allocate(size, align);
    if !ptr.is_null() {
        memcpy(ptr, new_ptr, old_size);
    }
    ptr
}

#[allow(unused_varibles)]
#[no_mangle]
pub extern fn rust_reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> usize {
    old_size
}

#[allow(unused_varibles)]
#[no_mangle]
pub extern fn rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {}

#[allow(unused_varibles)]
#[no_mangle]
pub extern fn rust_usable_size(size: usize, align: usize) -> usize {
    size
}

#[no_mangle]
pub extern fn rust_stats_print() {}
<|endoftext|>