<commit_before>// Extern crates.
use piston::*;
use piston::game_window::keycode;
use graphics::*;

// Local crate.
use action;
use settings;
use object;
use Object = object::Object;
use text;
use game_state;

pub struct SnakeApp {
    // Tells where the surface is.
    surface_y: Option<f64>,
    game_state: Option<game_state::GameState>,
    camera_pos: Option<[f64, ..2]>,
    camera_follow_percentage: Option<f64>,
    player_index: Option<uint>,
    blood_bar_index: Option<uint>,
    air_bar_index: Option<uint>,
    // Contains the game objects.
    objects: Vec<Object>,
}

impl Game<GameWindowSDL2> for SnakeApp {
    fn render(&self, c: &Context, gl: &mut Gl) {
        // Get camera coordinates.
        let (cam_x, cam_y) = if self.camera_pos.is_some() {
                let camera_pos = self.camera_pos.unwrap();
                (camera_pos[0], camera_pos[1] + 0.4)
            } else { (0.0, 0.0) };

        // Render surface.
        let surface_y = self.surface_y.unwrap();
        c.rect(-1.0, surface_y - cam_y, 2.0, 0.05).color(settings::BLUE).fill(gl);

        // Render objects in layers.
        let cam = &c.trans(-cam_x, -cam_y);
        for i in range(0u, settings::NUMBER_OF_LAYERS) {
            for obj in self.objects.iter() {
                if obj.layer == i { obj.render(cam, c, gl); }
            }
        }

        let text_c = c.flip_v_local();
        let text_c = text_c.zoom(0.0025);
        match self.game_state.unwrap() {
            game_state::Win => {
                let pos = settings::YOU_WIN_POS;
                text::text(settings::YOU_WIN_TEXT,
                    &text_c
                    .trans(pos[0], pos[1])
                    .color(settings::YOU_WIN_TEXT_COLOR)
                , gl);
            },
            game_state::Loose => {
                let pos = settings::YOU_LOOSE_POS;
                text::text(settings::YOU_LOOSE_TEXT,
                    &text_c
                    .trans(pos[0], pos[1])
                    .color(settings::YOU_LOOSE_TEXT_COLOR)
                , gl);
            },
            game_state::Play => {

            },
        }

        // TEST
        // text::text("restart", &c.flip_v_local().zoom(0.001).color(settings::BLACK), gl);
    }

    fn update(&mut self, dt: f64, _asset_store: &mut AssetStore) {
        self.update_objects(dt);
        self.fill_air();
        self.win();
        self.loose();
        self.show_blood();
        self.show_air();
        self.follow_player(dt);
    }

    fn load(&mut self, _asset_store: &mut AssetStore) {
        self.camera_follow_percentage = Some(settings::CAMERA_FOLLOW_PERCENTAGE);
        self.camera_pos = Some(settings::INITIAL_CAMERA_POS);
        self.surface_y = Some(settings::SURFACE_Y);
        self.game_state = Some(settings::INITIAL_GAME_STATE);

        // Add player.
        self.objects.push(Object::player(
            settings::ORIGIN,
            settings::BLUE,
            settings::PLAYER_INITIAL_BLOOD,
            settings::PLAYER_INITIAL_AIR,
            [settings::PLAYER_ACCELERATION_LEFT, settings::PLAYER_ACCELERATION_RIGHT],
            [settings::PLAYER_ACCELERATION_UP, settings::PLAYER_ACCELERATION_DOWN]
        ));
        self.objects.push(Object::bar_background());
        self.player_index = Some(0);

        // Add blood and air bar.
        self.add_bars();

        // Add air bottles.
        self.add_air_bottles();

        // Add snakes.
        self.add_snakes();
    }

    fn key_press(&mut self, key: keycode::KeyCode, _asset_store: &mut AssetStore) {
        // TEST
        // println!("Key pressed {}", key);

        if self.game_state.unwrap() != game_state::Play { return; }

        match (key, self.player_index) {
            (keycode::RightKey, Some(player_index)) => {
                self.objects.get_mut(player_index).move_right();
            },
            (keycode::UpKey, Some(player_index)) => {
                self.objects.get_mut(player_index).move_up();
            },
            (keycode::LeftKey, Some(player_index)) => {
                self.objects.get_mut(player_index).move_left();
            },
            (keycode::DownKey, Some(player_index)) => {
                self.objects.get_mut(player_index).move_down();
            },
            _ => {},
        }
    }

    fn key_release(&mut self, key: keycode::KeyCode, asset_store: &mut AssetStore) {
        // TEST
        // println!("Key released {}", key);

        if key == keycode::EnterKey || key == keycode::SpaceKey {
            match self.game_state.unwrap() {
                game_state::Win | game_state::Loose => self.restart(asset_store),
                _ => {},
            }
        }
    }
}

impl SnakeApp {
    pub fn new() -> SnakeApp {
        SnakeApp {
            camera_pos: None,
            camera_follow_percentage: None,
            game_state: None,
            surface_y: None,
            objects: Vec::new(),
            player_index: None,
            blood_bar_index: None,
            air_bar_index: None,
        }
    }

    pub fn add_bars(&mut self) {
        self.objects.push(Object::bar(
            settings::AIR_BAR_POS,
            "air",
            settings::AIR_BAR_TEXT_COLOR,
            settings::AIR_BAR_BACKGROUND_COLOR,
            settings::AIR_BAR_BAR_COLOR,
            settings::AIR_BAR_INITIAL_VALUE
        ));
        self.air_bar_index = Some(self.objects.len() - 1);
        self.objects.push(Object::bar(
            settings::BLOOD_BAR_POS,
            "blood",
            settings::BLOOD_BAR_TEXT_COLOR,
            settings::BLOOD_BAR_BACKGROUND_COLOR,
            settings::BLOOD_BAR_BAR_COLOR,
            settings::BLOOD_BAR_INITIAL_VALUE
        ));
        self.blood_bar_index = Some(self.objects.len() - 1);
    }

    pub fn add_snakes(&mut self) {
        if settings::SNAKE_1_ADD { self.objects.push(Object::snake(settings::SNAKE_1_POS, settings::SNAKE_1_SETTINGS)); }
        if settings::SNAKE_2_ADD { self.objects.push(Object::snake(settings::SNAKE_2_POS, settings::SNAKE_2_SETTINGS)); }
    }

    pub fn add_air_bottles(&mut self) {
        let air_bottles = settings::AIR_BOTTLE_POS;
        let n = air_bottles.len() / 2;
        for i in range(0, n) {
            self.objects.push(Object::air_bottle([air_bottles[i * 2], air_bottles[i * 2 + 1]]));
        }
    }

    fn follow_player(&mut self, dt: f64) {
        if self.camera_pos.is_none() { return; }
        // Make camera follow player.
        let camera_pos = self.camera_pos.unwrap();
        let camera_follow_percentage = self.camera_follow_percentage.unwrap();
        let player_pos = self.player_pos();
        let (dx, dy) = (player_pos[0] - camera_pos[0], player_pos[1] - camera_pos[1]);
        let dx = camera_follow_percentage * dt * dx;
        let dy = camera_follow_percentage * dt * dy;
        self.camera_pos = Some([camera_pos[0] + dx, camera_pos[1] + dy]);
    }

    fn show_blood(&mut self) {
        if self.blood_bar_index == None { return; }
        // Show blood.
        let player_blood = self.player_blood();
        let blood_bar_index = self.blood_bar_index.unwrap();
        let blood_bar = self.objects.get_mut(blood_bar_index);
        match blood_bar.data {
            object::BarData(ref mut bar) => {
                bar.value = player_blood;
            },
            _ => {},
        }
    }

    fn show_air(&mut self) {
        if self.air_bar_index == None { return; }
        // Show air.
        let player_air = self.player_air();
        let air_bar_index = self.air_bar_index.unwrap();
        let air_bar = self.objects.get_mut(air_bar_index);
        match air_bar.data {
            object::BarData(ref mut bar) => {
                bar.value = player_air;
            },
            _ => {},
        }
    }

    fn win(&mut self) {
        let player_pos = self.player_pos();
        // When player reaches surface, win.
        if player_pos[1] >= self.surface_y.unwrap() {
            self.game_state = Some(game_state::Win);
            return;
        }
    }

    fn loose(&mut self) {
        let blood = self.player_blood();
        let air = self.player_air();
        if blood < 0.0 || air < 0.0 {
            self.game_state = Some(game_state::Loose);
            return;
        }
    }

    fn restart(&mut self, asset_store: &mut AssetStore) {
        *self = SnakeApp::new();
        self.load(asset_store);
    }

    fn update_objects(&mut self, dt: f64) {
        if self.game_state.unwrap() != game_state::Play { return; }

        // Update states of objects.
        let player_pos = self.player_pos();
        let mut attack_damage: f64 = 0.0;
        for obj in self.objects.mut_iter() {
            match obj.update(dt, player_pos) {
                action::Passive => {},
                action::Attack(attack) => { attack_damage += attack; },
            }
        }
        // Bite player.
        self.bite_player(attack_damage);

        // Decrease the player's air with time.
        let air = self.player_air();
        self.set_player_air(air - dt * settings::PLAYER_LOOSE_AIR_SPEED);
    }

    fn player_pos(&self) -> [f64, ..2] {
        let player_index = self.player_index.unwrap();
        self.objects.get(player_index).pos
    }

    fn player_blood(&self) -> f64 {
        let player_index = self.player_index.unwrap();
        self.objects.get(player_index).blood().unwrap()
    }

    fn player_air(&self) -> f64 {
        let player_index = self.player_index.unwrap();
        self.objects.get(player_index).air().unwrap()
    }

    fn set_player_air(&mut self, val: f64) {
        let player_index = self.player_index.unwrap();
        *self.objects.get_mut(player_index).air_mut().unwrap() = val;
    }

    fn bite_player(&mut self, damage: f64) {
        let player_index = self.player_index.unwrap();
        self.objects.get_mut(player_index).player_mut().unwrap().bite(damage);
    }

    fn fill_air(&mut self) {
        let player_pos = self.player_pos();
        let mut air = self.player_air();
        for obj in self.objects.mut_iter() {
            let pos = obj.pos;
            match obj.air_bottle_mut() {
                None => {},
                Some(air_bottle) => {
                    let dx = pos[0] - player_pos[0];
                    let dy = pos[1] - player_pos[1];
                    let d = dx * dx + dy * dy;
                    if d <= settings::AIR_BOTTLE_RADIUS * settings::AIR_BOTTLE_RADIUS {
                        air += air_bottle.fill_up;
                        air_bottle.fill_up = 0.0;
                    }
                },
            }
        }

        air = if air > 1.0 { 1.0 } else { air };
        self.set_player_air(air);
    }
}

<commit_msg>Can switch to GLFW back-end with just one line<commit_after>// Extern crates.
use piston::*;
use piston::game_window::keycode;
use graphics::*;

// Local crate.
use action;
use settings;
use object;
use Object = object::Object;
use text;
use game_state;

pub struct SnakeApp {
    // Tells where the surface is.
    surface_y: Option<f64>,
    game_state: Option<game_state::GameState>,
    camera_pos: Option<[f64, ..2]>,
    camera_follow_percentage: Option<f64>,
    player_index: Option<uint>,
    blood_bar_index: Option<uint>,
    air_bar_index: Option<uint>,
    // Contains the game objects.
    objects: Vec<Object>,
}

// use following line to switch to GLFW back-end
//impl Game<GameWindowGLFW> for SnakeApp
impl Game<GameWindowSDL2> for SnakeApp {
    fn render(&self, c: &Context, gl: &mut Gl) {
        // Get camera coordinates.
        let (cam_x, cam_y) = if self.camera_pos.is_some() {
                let camera_pos = self.camera_pos.unwrap();
                (camera_pos[0], camera_pos[1] + 0.4)
            } else { (0.0, 0.0) };

        // Render surface.
        let surface_y = self.surface_y.unwrap();
        c.rect(-1.0, surface_y - cam_y, 2.0, 0.05).color(settings::BLUE).fill(gl);

        // Render objects in layers.
        let cam = &c.trans(-cam_x, -cam_y);
        for i in range(0u, settings::NUMBER_OF_LAYERS) {
            for obj in self.objects.iter() {
                if obj.layer == i { obj.render(cam, c, gl); }
            }
        }

        let text_c = c.flip_v_local();
        let text_c = text_c.zoom(0.0025);
        match self.game_state.unwrap() {
            game_state::Win => {
                let pos = settings::YOU_WIN_POS;
                text::text(settings::YOU_WIN_TEXT,
                    &text_c
                    .trans(pos[0], pos[1])
                    .color(settings::YOU_WIN_TEXT_COLOR)
                , gl);
            },
            game_state::Loose => {
                let pos = settings::YOU_LOOSE_POS;
                text::text(settings::YOU_LOOSE_TEXT,
                    &text_c
                    .trans(pos[0], pos[1])
                    .color(settings::YOU_LOOSE_TEXT_COLOR)
                , gl);
            },
            game_state::Play => {

            },
        }

        // TEST
        // text::text("restart", &c.flip_v_local().zoom(0.001).color(settings::BLACK), gl);
    }

    fn update(&mut self, dt: f64, _asset_store: &mut AssetStore) {
        self.update_objects(dt);
        self.fill_air();
        self.win();
        self.loose();
        self.show_blood();
        self.show_air();
        self.follow_player(dt);
    }

    fn load(&mut self, _asset_store: &mut AssetStore) {
        self.camera_follow_percentage = Some(settings::CAMERA_FOLLOW_PERCENTAGE);
        self.camera_pos = Some(settings::INITIAL_CAMERA_POS);
        self.surface_y = Some(settings::SURFACE_Y);
        self.game_state = Some(settings::INITIAL_GAME_STATE);

        // Add player.
        self.objects.push(Object::player(
            settings::ORIGIN,
            settings::BLUE,
            settings::PLAYER_INITIAL_BLOOD,
            settings::PLAYER_INITIAL_AIR,
            [settings::PLAYER_ACCELERATION_LEFT, settings::PLAYER_ACCELERATION_RIGHT],
            [settings::PLAYER_ACCELERATION_UP, settings::PLAYER_ACCELERATION_DOWN]
        ));
        self.objects.push(Object::bar_background());
        self.player_index = Some(0);

        // Add blood and air bar.
        self.add_bars();

        // Add air bottles.
        self.add_air_bottles();

        // Add snakes.
        self.add_snakes();
    }

    fn key_press(&mut self, key: keycode::KeyCode, _asset_store: &mut AssetStore) {
        // TEST
        // println!("Key pressed {}", key);

        if self.game_state.unwrap() != game_state::Play { return; }

        match (key, self.player_index) {
            (keycode::RightKey, Some(player_index)) => {
                self.objects.get_mut(player_index).move_right();
            },
            (keycode::UpKey, Some(player_index)) => {
                self.objects.get_mut(player_index).move_up();
            },
            (keycode::LeftKey, Some(player_index)) => {
                self.objects.get_mut(player_index).move_left();
            },
            (keycode::DownKey, Some(player_index)) => {
                self.objects.get_mut(player_index).move_down();
            },
            _ => {},
        }
    }

    fn key_release(&mut self, key: keycode::KeyCode, asset_store: &mut AssetStore) {
        // TEST
        // println!("Key released {}", key);

        if key == keycode::EnterKey || key == keycode::SpaceKey {
            match self.game_state.unwrap() {
                game_state::Win | game_state::Loose => self.restart(asset_store),
                _ => {},
            }
        }
    }
}

impl SnakeApp {
    pub fn new() -> SnakeApp {
        SnakeApp {
            camera_pos: None,
            camera_follow_percentage: None,
            game_state: None,
            surface_y: None,
            objects: Vec::new(),
            player_index: None,
            blood_bar_index: None,
            air_bar_index: None,
        }
    }

    pub fn add_bars(&mut self) {
        self.objects.push(Object::bar(
            settings::AIR_BAR_POS,
            "air",
            settings::AIR_BAR_TEXT_COLOR,
            settings::AIR_BAR_BACKGROUND_COLOR,
            settings::AIR_BAR_BAR_COLOR,
            settings::AIR_BAR_INITIAL_VALUE
        ));
        self.air_bar_index = Some(self.objects.len() - 1);
        self.objects.push(Object::bar(
            settings::BLOOD_BAR_POS,
            "blood",
            settings::BLOOD_BAR_TEXT_COLOR,
            settings::BLOOD_BAR_BACKGROUND_COLOR,
            settings::BLOOD_BAR_BAR_COLOR,
            settings::BLOOD_BAR_INITIAL_VALUE
        ));
        self.blood_bar_index = Some(self.objects.len() - 1);
    }

    pub fn add_snakes(&mut self) {
        if settings::SNAKE_1_ADD { self.objects.push(Object::snake(settings::SNAKE_1_POS, settings::SNAKE_1_SETTINGS)); }
        if settings::SNAKE_2_ADD { self.objects.push(Object::snake(settings::SNAKE_2_POS, settings::SNAKE_2_SETTINGS)); }
    }

    pub fn add_air_bottles(&mut self) {
        let air_bottles = settings::AIR_BOTTLE_POS;
        let n = air_bottles.len() / 2;
        for i in range(0, n) {
            self.objects.push(Object::air_bottle([air_bottles[i * 2], air_bottles[i * 2 + 1]]));
        }
    }

    fn follow_player(&mut self, dt: f64) {
        if self.camera_pos.is_none() { return; }
        // Make camera follow player.
        let camera_pos = self.camera_pos.unwrap();
        let camera_follow_percentage = self.camera_follow_percentage.unwrap();
        let player_pos = self.player_pos();
        let (dx, dy) = (player_pos[0] - camera_pos[0], player_pos[1] - camera_pos[1]);
        let dx = camera_follow_percentage * dt * dx;
        let dy = camera_follow_percentage * dt * dy;
        self.camera_pos = Some([camera_pos[0] + dx, camera_pos[1] + dy]);
    }

    fn show_blood(&mut self) {
        if self.blood_bar_index == None { return; }
        // Show blood.
        let player_blood = self.player_blood();
        let blood_bar_index = self.blood_bar_index.unwrap();
        let blood_bar = self.objects.get_mut(blood_bar_index);
        match blood_bar.data {
            object::BarData(ref mut bar) => {
                bar.value = player_blood;
            },
            _ => {},
        }
    }

    fn show_air(&mut self) {
        if self.air_bar_index == None { return; }
        // Show air.
        let player_air = self.player_air();
        let air_bar_index = self.air_bar_index.unwrap();
        let air_bar = self.objects.get_mut(air_bar_index);
        match air_bar.data {
            object::BarData(ref mut bar) => {
                bar.value = player_air;
            },
            _ => {},
        }
    }

    fn win(&mut self) {
        let player_pos = self.player_pos();
        // When player reaches surface, win.
        if player_pos[1] >= self.surface_y.unwrap() {
            self.game_state = Some(game_state::Win);
            return;
        }
    }

    fn loose(&mut self) {
        let blood = self.player_blood();
        let air = self.player_air();
        if blood < 0.0 || air < 0.0 {
            self.game_state = Some(game_state::Loose);
            return;
        }
    }

    fn restart(&mut self, asset_store: &mut AssetStore) {
        *self = SnakeApp::new();
        self.load(asset_store);
    }

    fn update_objects(&mut self, dt: f64) {
        if self.game_state.unwrap() != game_state::Play { return; }

        // Update states of objects.
        let player_pos = self.player_pos();
        let mut attack_damage: f64 = 0.0;
        for obj in self.objects.mut_iter() {
            match obj.update(dt, player_pos) {
                action::Passive => {},
                action::Attack(attack) => { attack_damage += attack; },
            }
        }
        // Bite player.
        self.bite_player(attack_damage);

        // Decrease the player's air with time.
        let air = self.player_air();
        self.set_player_air(air - dt * settings::PLAYER_LOOSE_AIR_SPEED);
    }

    fn player_pos(&self) -> [f64, ..2] {
        let player_index = self.player_index.unwrap();
        self.objects.get(player_index).pos
    }

    fn player_blood(&self) -> f64 {
        let player_index = self.player_index.unwrap();
        self.objects.get(player_index).blood().unwrap()
    }

    fn player_air(&self) -> f64 {
        let player_index = self.player_index.unwrap();
        self.objects.get(player_index).air().unwrap()
    }

    fn set_player_air(&mut self, val: f64) {
        let player_index = self.player_index.unwrap();
        *self.objects.get_mut(player_index).air_mut().unwrap() = val;
    }

    fn bite_player(&mut self, damage: f64) {
        let player_index = self.player_index.unwrap();
        self.objects.get_mut(player_index).player_mut().unwrap().bite(damage);
    }

    fn fill_air(&mut self) {
        let player_pos = self.player_pos();
        let mut air = self.player_air();
        for obj in self.objects.mut_iter() {
            let pos = obj.pos;
            match obj.air_bottle_mut() {
                None => {},
                Some(air_bottle) => {
                    let dx = pos[0] - player_pos[0];
                    let dy = pos[1] - player_pos[1];
                    let d = dx * dx + dy * dy;
                    if d <= settings::AIR_BOTTLE_RADIUS * settings::AIR_BOTTLE_RADIUS {
                        air += air_bottle.fill_up;
                        air_bottle.fill_up = 0.0;
                    }
                },
            }
        }

        air = if air > 1.0 { 1.0 } else { air };
        self.set_player_air(air);
    }
}

<|endoftext|>


<commit_before>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
pub type SQLCHAR = ::c_uchar;
pub type SQLSCHAR = ::c_schar;
pub type SQLDATE = ::c_uchar;
pub type SQLDECIMAL = ::c_uchar;
pub type SQLDOUBLE = ::c_double;
pub type SQLFLOAT = ::c_double;
pub type SQLINTEGER = ::c_long;
pub type SQLUINTEGER = ::c_ulong;
#[cfg(target_arch = "x86_64")]
pub type SQLLEN = ::INT64;
#[cfg(target_arch = "x86_64")]
pub type SQLULEN = ::UINT64;
#[cfg(target_arch = "x86_64")]
pub type SQLSETPOSIROW = ::UINT64;
#[cfg(target_arch = "x86")]
pub type SQLLEN = SQLINTEGER;
#[cfg(target_arch = "x86")]
pub type SQLULEN = SQLUINTEGER;
#[cfg(target_arch = "x86")]
pub type SQLSETPOSIROW = SQLUSMALLINT;
pub type SQLROWCOUNT = SQLULEN;
pub type SQLROWSETSIZE = SQLULEN;
pub type SQLTRANSID = SQLULEN;
pub type SQLROWOFFSET = SQLLEN;
pub type SQLNUMERIC = ::c_uchar;
pub type SQLPOINTER = *mut ::c_void;
pub type SQLREAL = ::c_float;
pub type SQLSMALLINT = ::c_short;
pub type SQLUSMALLINT = ::c_ushort;
pub type SQLTIME = ::c_uchar;
pub type SQLTIMESTAMP = ::c_uchar;
pub type SQLVARCHAR = ::c_uchar;
pub type SQLRETURN = SQLSMALLINT;
pub type SQLHANDLE = *mut ::c_void;
pub type SQLHENV = SQLHANDLE;
pub type SQLHDBC = SQLHANDLE;
pub type SQLHSTMT = SQLHANDLE;
pub type SQLHDESC = SQLHANDLE;
//pub type UCHAR = ::c_uchar;
pub type SCHAR = ::c_schar;
//pub type SQLSCHAR = SCHAR;
pub type SDWORD = ::c_long;
pub type SWORD = ::c_short;
pub type UDWORD = ::c_ulong;
//pub type UWORD = ::c_ushort;
#[cfg(target_arch = "x86")]
pub type SQLUINTEGER = ::UDWORD;
pub type SLONG = ::c_long;
pub type SSHORT = ::c_short;
//pub type ULONG = ::c_ulong;
//pub type USHORT = ::c_ushort;
pub type SDOUBLE = ::c_double;
pub type LDOUBLE = ::c_double;
pub type SFLOAT = ::c_float;
pub type PTR = *mut ::c_void;
pub type HENV = *mut ::c_void;
pub type HDBC = *mut ::c_void;
pub type HSTMT = *mut ::c_void;
pub type RETCODE = ::c_short;
pub type SQLHWND = ::HWND;
STRUCT!{struct DATE_STRUCT {
    year: SQLSMALLINT,
    month: SQLUSMALLINT,
    day: SQLUSMALLINT,
}}
pub type SQL_DATE_STRUCT = DATE_STRUCT;
STRUCT!{struct TIME_STRUCT {
    hour: SQLUSMALLINT,
    minute: SQLUSMALLINT,
    second: SQLUSMALLINT,
}}
pub type SQL_TIME_STRUCT = TIME_STRUCT;
STRUCT!{struct TIMESTAMP_STRUCT {
    year: SQLSMALLINT,
    month: SQLUSMALLINT,
    day: SQLUSMALLINT,
    hour: SQLUSMALLINT,
    minute: SQLUSMALLINT,
    second: SQLUSMALLINT,
    fraction: SQLUINTEGER,
}}
pub type SQL_TIMESTAMP_STRUCT = TIMESTAMP_STRUCT;
ENUM!{enum SQLINTERVAL {
    SQL_IS_YEAR = 1,
    SQL_IS_MONTH = 2,
    SQL_IS_DAY = 3,
    SQL_IS_HOUR = 4,
    SQL_IS_MINUTE = 5,
    SQL_IS_SECOND = 6,
    SQL_IS_YEAR_TO_MONTH = 7,
    SQL_IS_DAY_TO_HOUR = 8,
    SQL_IS_DAY_TO_MINUTE = 9,
    SQL_IS_DAY_TO_SECOND = 10,
    SQL_IS_HOUR_TO_MINUTE = 11,
    SQL_IS_HOUR_TO_SECOND = 12,
    SQL_IS_MINUTE_TO_SECOND = 13,
}}
STRUCT!{struct SQL_YEAR_MONTH_STRUCT {
    year: SQLUINTEGER,
    month: SQLUINTEGER,
}}
STRUCT!{struct SQL_DAY_SECOND_STRUCT {
    day: SQLUINTEGER,
    hour: SQLUINTEGER,
    minute: SQLUINTEGER,
    second: SQLUINTEGER,
    fraction: SQLUINTEGER,
}}
STRUCT!{struct SQL_INTERVAL_STRUCT {
    interval_type: SQLINTERVAL,
    interval_sign: SQLSMALLINT,
    intval: [u32; 5],
}}
UNION!{SQL_INTERVAL_STRUCT, intval, year_month, year_month_mut, SQL_YEAR_MONTH_STRUCT}
UNION!{SQL_INTERVAL_STRUCT, intval, day_second, day_second_mut, SQL_DAY_SECOND_STRUCT}
pub type ODBCINT64 = ::__int64;
pub type SQLBIGINT = ODBCINT64;
pub type SQLUBIGINT = ::__uint64;
pub const SQL_MAX_NUMERIC_LEN: usize = 16;
STRUCT!{struct SQL_NUMERIC_STRUCT {
    precision: SQLCHAR,
    scale: SQLSCHAR,
    sign: SQLCHAR,
    val: [SQLCHAR; SQL_MAX_NUMERIC_LEN],
}}
pub type SQLGUID = ::GUID;
pub type BOOKMARK = SQLULEN;
pub type SQLWCHAR = ::wchar_t;
<commit_msg>Fix a silly<commit_after>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
pub type SQLCHAR = ::c_uchar;
pub type SQLSCHAR = ::c_schar;
pub type SQLDATE = ::c_uchar;
pub type SQLDECIMAL = ::c_uchar;
pub type SQLDOUBLE = ::c_double;
pub type SQLFLOAT = ::c_double;
pub type SQLINTEGER = ::c_long;
pub type SQLUINTEGER = ::c_ulong;
#[cfg(target_arch = "x86_64")]
pub type SQLLEN = ::INT64;
#[cfg(target_arch = "x86_64")]
pub type SQLULEN = ::UINT64;
#[cfg(target_arch = "x86_64")]
pub type SQLSETPOSIROW = ::UINT64;
#[cfg(target_arch = "x86")]
pub type SQLLEN = SQLINTEGER;
#[cfg(target_arch = "x86")]
pub type SQLULEN = SQLUINTEGER;
#[cfg(target_arch = "x86")]
pub type SQLSETPOSIROW = SQLUSMALLINT;
pub type SQLROWCOUNT = SQLULEN;
pub type SQLROWSETSIZE = SQLULEN;
pub type SQLTRANSID = SQLULEN;
pub type SQLROWOFFSET = SQLLEN;
pub type SQLNUMERIC = ::c_uchar;
pub type SQLPOINTER = *mut ::c_void;
pub type SQLREAL = ::c_float;
pub type SQLSMALLINT = ::c_short;
pub type SQLUSMALLINT = ::c_ushort;
pub type SQLTIME = ::c_uchar;
pub type SQLTIMESTAMP = ::c_uchar;
pub type SQLVARCHAR = ::c_uchar;
pub type SQLRETURN = SQLSMALLINT;
pub type SQLHANDLE = *mut ::c_void;
pub type SQLHENV = SQLHANDLE;
pub type SQLHDBC = SQLHANDLE;
pub type SQLHSTMT = SQLHANDLE;
pub type SQLHDESC = SQLHANDLE;
//pub type UCHAR = ::c_uchar;
pub type SCHAR = ::c_schar;
//pub type SQLSCHAR = SCHAR;
pub type SDWORD = ::c_long;
pub type SWORD = ::c_short;
pub type UDWORD = ::c_ulong;
//pub type UWORD = ::c_ushort;
//#[cfg(target_arch = "x86")]
//pub type SQLUINTEGER = ::UDWORD;
pub type SLONG = ::c_long;
pub type SSHORT = ::c_short;
//pub type ULONG = ::c_ulong;
//pub type USHORT = ::c_ushort;
pub type SDOUBLE = ::c_double;
pub type LDOUBLE = ::c_double;
pub type SFLOAT = ::c_float;
pub type PTR = *mut ::c_void;
pub type HENV = *mut ::c_void;
pub type HDBC = *mut ::c_void;
pub type HSTMT = *mut ::c_void;
pub type RETCODE = ::c_short;
pub type SQLHWND = ::HWND;
STRUCT!{struct DATE_STRUCT {
    year: SQLSMALLINT,
    month: SQLUSMALLINT,
    day: SQLUSMALLINT,
}}
pub type SQL_DATE_STRUCT = DATE_STRUCT;
STRUCT!{struct TIME_STRUCT {
    hour: SQLUSMALLINT,
    minute: SQLUSMALLINT,
    second: SQLUSMALLINT,
}}
pub type SQL_TIME_STRUCT = TIME_STRUCT;
STRUCT!{struct TIMESTAMP_STRUCT {
    year: SQLSMALLINT,
    month: SQLUSMALLINT,
    day: SQLUSMALLINT,
    hour: SQLUSMALLINT,
    minute: SQLUSMALLINT,
    second: SQLUSMALLINT,
    fraction: SQLUINTEGER,
}}
pub type SQL_TIMESTAMP_STRUCT = TIMESTAMP_STRUCT;
ENUM!{enum SQLINTERVAL {
    SQL_IS_YEAR = 1,
    SQL_IS_MONTH = 2,
    SQL_IS_DAY = 3,
    SQL_IS_HOUR = 4,
    SQL_IS_MINUTE = 5,
    SQL_IS_SECOND = 6,
    SQL_IS_YEAR_TO_MONTH = 7,
    SQL_IS_DAY_TO_HOUR = 8,
    SQL_IS_DAY_TO_MINUTE = 9,
    SQL_IS_DAY_TO_SECOND = 10,
    SQL_IS_HOUR_TO_MINUTE = 11,
    SQL_IS_HOUR_TO_SECOND = 12,
    SQL_IS_MINUTE_TO_SECOND = 13,
}}
STRUCT!{struct SQL_YEAR_MONTH_STRUCT {
    year: SQLUINTEGER,
    month: SQLUINTEGER,
}}
STRUCT!{struct SQL_DAY_SECOND_STRUCT {
    day: SQLUINTEGER,
    hour: SQLUINTEGER,
    minute: SQLUINTEGER,
    second: SQLUINTEGER,
    fraction: SQLUINTEGER,
}}
STRUCT!{struct SQL_INTERVAL_STRUCT {
    interval_type: SQLINTERVAL,
    interval_sign: SQLSMALLINT,
    intval: [u32; 5],
}}
UNION!{SQL_INTERVAL_STRUCT, intval, year_month, year_month_mut, SQL_YEAR_MONTH_STRUCT}
UNION!{SQL_INTERVAL_STRUCT, intval, day_second, day_second_mut, SQL_DAY_SECOND_STRUCT}
pub type ODBCINT64 = ::__int64;
pub type SQLBIGINT = ODBCINT64;
pub type SQLUBIGINT = ::__uint64;
pub const SQL_MAX_NUMERIC_LEN: usize = 16;
STRUCT!{struct SQL_NUMERIC_STRUCT {
    precision: SQLCHAR,
    scale: SQLSCHAR,
    sign: SQLCHAR,
    val: [SQLCHAR; SQL_MAX_NUMERIC_LEN],
}}
pub type SQLGUID = ::GUID;
pub type BOOKMARK = SQLULEN;
pub type SQLWCHAR = ::wchar_t;
<|endoftext|>


<commit_before>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use imp_prelude::*;
use error::{ShapeError, ErrorKind, from_kind};

/// Stack arrays along the given axis.
///
/// ***Errors*** if the arrays have mismatching shapes, apart from along `axis`.
/// (may be made more flexible in the future).

/// ***Errors*** if `arrays` is empty, if `axis` is out of bounds,
/// if the result is larger than is possible to represent.
///
/// ```
/// use ndarray::{arr2, Axis, stack};
///
/// let a = arr2(&[[2., 2.],
///                [3., 3.]]);
/// assert!(
///     stack(Axis(0), &[a.view(), a.view()])
///     == Ok(arr2(&[[2., 2.],
///                  [3., 3.],
///                  [2., 2.],
///                  [3., 3.]]))
/// );
/// ```
pub fn stack<'a, A, D>(axis: Axis, arrays: &[ArrayView<'a, A, D>])
    -> Result<OwnedArray, ShapeError>
    where A: Copy,
          D: RemoveAxis
{
    if arrays.len() == 0 {
        return Err(from_kind(ErrorKind::Unsupported));
    }
    let mut res_dim = arrays[0].dim();
    if axis.axis() >= res_dim.ndim() {
        return Err(from_kind(ErrorKind::OutOfBounds));
    }
    let common_dim = res_dim.remove_axis(axis);
    if arrays.iter().any(|a| a.dim().remove_axis(axis) != common_dim) {
        return Err(from_kind(ErrorKind::IncompatibleShape));
    }

    let stacked_dim = arrays.iter()
                            .fold(0, |acc, a| acc + a.shape().axis(axis));
    res_dim.set_axis(axis, stacked_dim);

    // we can safely use uninitialized values here because they are Copy
    // and we will only ever write to them
    let size = res_dim.size();
    let mut v = Vec::with_capacity(size);
    unsafe {
        v.set_len(size);
    }
    let mut res = try!(OwnedArray::from_vec_dim(res_dim, v));

    {
        let mut assign_view = res.view_mut();
        for array in arrays {
            let len = array.shape().axis(axis);
            let (mut front, rest) = assign_view.split_at(axis, len);
            front.assign(array);
            assign_view = rest;
        }
    }
    Ok(res)
}

/// Stack arrays along the given axis.
///
/// Uses the [`stack`][1] function, calling `ArrayView::from(&a)` on each
/// argument `a`.
///
/// [1]: fn.stack.html
///
/// ***Panics*** if the `stack` function would return an error.
///
/// ```
/// #[macro_use(stack)]
/// extern crate ndarray;
///
/// use ndarray::{arr2, Axis, stack};
///
/// # fn main() {
///
/// let a = arr2(&[[2., 2.],
///                [3., 3.]]);
/// assert!(
///     stack![Axis(0), a, a]
///     == arr2(&[[2., 2.],
///               [3., 3.],
///               [2., 2.],
///               [3., 3.]])
/// );
/// # }
/// ```
#[macro_export]
macro_rules! stack {
    ($axis:expr, $( $array:expr ),+ ) => {
        ndarray::stack($axis, &[ $(ndarray::ArrayView::from(&$array) ),* ]).unwrap()
    }
}
<commit_msg>Fix a bug in the stack![] macro<commit_after>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use imp_prelude::*;
use error::{ShapeError, ErrorKind, from_kind};

/// Stack arrays along the given axis.
///
/// ***Errors*** if the arrays have mismatching shapes, apart from along `axis`.
/// (may be made more flexible in the future).

/// ***Errors*** if `arrays` is empty, if `axis` is out of bounds,
/// if the result is larger than is possible to represent.
///
/// ```
/// use ndarray::{arr2, Axis, stack};
///
/// let a = arr2(&[[2., 2.],
///                [3., 3.]]);
/// assert!(
///     stack(Axis(0), &[a.view(), a.view()])
///     == Ok(arr2(&[[2., 2.],
///                  [3., 3.],
///                  [2., 2.],
///                  [3., 3.]]))
/// );
/// ```
pub fn stack<'a, A, D>(axis: Axis, arrays: &[ArrayView<'a, A, D>])
    -> Result<OwnedArray, ShapeError>
    where A: Copy,
          D: RemoveAxis
{
    if arrays.len() == 0 {
        return Err(from_kind(ErrorKind::Unsupported));
    }
    let mut res_dim = arrays[0].dim();
    if axis.axis() >= res_dim.ndim() {
        return Err(from_kind(ErrorKind::OutOfBounds));
    }
    let common_dim = res_dim.remove_axis(axis);
    if arrays.iter().any(|a| a.dim().remove_axis(axis) != common_dim) {
        return Err(from_kind(ErrorKind::IncompatibleShape));
    }

    let stacked_dim = arrays.iter()
                            .fold(0, |acc, a| acc + a.shape().axis(axis));
    res_dim.set_axis(axis, stacked_dim);

    // we can safely use uninitialized values here because they are Copy
    // and we will only ever write to them
    let size = res_dim.size();
    let mut v = Vec::with_capacity(size);
    unsafe {
        v.set_len(size);
    }
    let mut res = try!(OwnedArray::from_vec_dim(res_dim, v));

    {
        let mut assign_view = res.view_mut();
        for array in arrays {
            let len = array.shape().axis(axis);
            let (mut front, rest) = assign_view.split_at(axis, len);
            front.assign(array);
            assign_view = rest;
        }
    }
    Ok(res)
}

/// Stack arrays along the given axis.
///
/// Uses the [`stack`][1] function, calling `ArrayView::from(&a)` on each
/// argument `a`.
///
/// [1]: fn.stack.html
///
/// ***Panics*** if the `stack` function would return an error.
///
/// ```
/// #[macro_use(stack)]
/// extern crate ndarray;
///
/// use ndarray::{arr2, Axis, stack};
///
/// # fn main() {
///
/// let a = arr2(&[[2., 2.],
///                [3., 3.]]);
/// assert!(
///     stack![Axis(0), a, a]
///     == arr2(&[[2., 2.],
///               [3., 3.],
///               [2., 2.],
///               [3., 3.]])
/// );
/// # }
/// ```
#[macro_export]
macro_rules! stack {
    ($axis:expr, $( $array:expr ),+ ) => {
        $crate::stack($axis, &[ $($crate::ArrayView::from(&$array) ),* ]).unwrap()
    }
}
<|endoftext|>


<commit_before>use crate::utils::{
    add_extra_ty_param_bound, add_extra_where_clauses, MultiFieldData, State,
};
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{DeriveInput, Ident, Result};

pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
    let state = State::new(
        input,
        trait_name,
        quote!(::core::iter),
        trait_name.to_lowercase(),
    )?;
    let multi_field_data = state.enabled_fields_data();
    let MultiFieldData {
        input_type,
        field_types,
        trait_path,
        method_ident,
        ..
    } = multi_field_data.clone();

    let op_trait_name = if trait_name == "Sum" { "Add" } else { "Mul" };
    let op_trait_ident = Ident::new(op_trait_name, Span::call_site());
    let op_path = quote!(::core::ops::#op_trait_ident);
    let op_method_ident =
        Ident::new(&(op_trait_name.to_lowercase()), Span::call_site());
    let type_params: Vec<_> = input
        .generics
        .type_params()
        .map(|t| t.ident.clone())
        .collect();
    let generics = if type_params.is_empty() {
        input.generics.clone()
    } else {
        let generic_type = quote!(<#(#type_params),*>);
        let generics = add_extra_ty_param_bound(&input.generics, trait_path);
        let operator_where_clause = quote! {
            where #input_type#generic_type: #op_path<Output=#input_type#generic_type>
        };
        add_extra_where_clauses(&generics, operator_where_clause)
    };
    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

    let initializers: Vec<_> = field_types
        .iter()
        .map(|field_type| quote!(#trait_path::#method_ident(::core::iter::empty::<#field_type>())))
        .collect();
    let identity = multi_field_data.initializer(&initializers);

    Ok(quote!(
        impl#impl_generics #trait_path for #input_type#ty_generics #where_clause {
            #[inline]
            fn #method_ident<I: ::core::iter::Iterator<Item = Self>>(iter: I) -> Self {
                iter.fold(#identity, #op_path::#op_method_ident)
            }
        }
    ))
}
<commit_msg>Fix const param compilation error for Sum-like<commit_after>use crate::utils::{
    add_extra_ty_param_bound, add_extra_where_clauses, MultiFieldData, State,
};
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{DeriveInput, Ident, Result};

pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
    let state = State::new(
        input,
        trait_name,
        quote!(::core::iter),
        trait_name.to_lowercase(),
    )?;
    let multi_field_data = state.enabled_fields_data();
    let MultiFieldData {
        input_type,
        field_types,
        trait_path,
        method_ident,
        ..
    } = multi_field_data.clone();

    let op_trait_name = if trait_name == "Sum" { "Add" } else { "Mul" };
    let op_trait_ident = Ident::new(op_trait_name, Span::call_site());
    let op_path = quote!(::core::ops::#op_trait_ident);
    let op_method_ident =
        Ident::new(&(op_trait_name.to_lowercase()), Span::call_site());
    let type_params: Vec<_> = input
        .generics
        .type_params()
        .map(|t| t.ident.clone())
        .collect();
    let const_params: Vec<_> = input
        .generics
        .const_params()
        .map(|t| t.ident.clone())
        .collect();
    let generics = if type_params.is_empty() {
        input.generics.clone()
    } else {
        let generic_params = quote!(<#(#type_params),* #(,#const_params)*>);
        let generics = add_extra_ty_param_bound(&input.generics, trait_path);
        let operator_where_clause = quote! {
            where #input_type#generic_params: #op_path<Output=#input_type#generic_params>
        };
        add_extra_where_clauses(&generics, operator_where_clause)
    };
    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

    let initializers: Vec<_> = field_types
        .iter()
        .map(|field_type| quote!(#trait_path::#method_ident(::core::iter::empty::<#field_type>())))
        .collect();
    let identity = multi_field_data.initializer(&initializers);

    Ok(quote!(
        impl#impl_generics #trait_path for #input_type#ty_generics #where_clause {
            #[inline]
            fn #method_ident<I: ::core::iter::Iterator<Item = Self>>(iter: I) -> Self {
                iter.fold(#identity, #op_path::#op_method_ident)
            }
        }
    ))
}
<|endoftext|>


<commit_before>//! This test file ensures that all of the lifetimes work the way we
//! want, and that there are no regressions. It's a "does this compile?"
//! test.

extern crate ropey;

use ropey::{Rope, RopeSlice};

const TEXT: &str = include_str!("test_text.txt");

fn main() {
    let rope = Rope::from_str(TEXT);

    let (a, b, c, d, e, f, count, line, string) = {
        // The lifetimes of intermediate slices shouldn't matter.  The
        // lifetimes of the things produced by the calls below should be
        // tied to the lifetime of the original rope, not the lifetimes of
        // the slices they were created from.  Therefore, this should all
        // compile.

        let a = rope.slice(4..500).slice(4..400).slice(4..300);
        let b = rope.slice(4..500).slice(4..400).as_str();
        let c = rope.slice(4..500).slice(4..400).line(1);
        let d = rope.slice(4..500).slice(4..400).chunk_at_byte(50);
        let e = rope.slice(4..500).slice(4..400).chunk_at_char(50);
        let f = rope.slice(4..500).slice(4..400).chunk_at_line_break(3);

        // Same for iterators.  In addition, the items _yielded_ by the
        // iterators should also be tied to the lifetime of the original
        // rope, not to the iterators or slices they came from.

        let mut count = 0;
        for _ in rope.slice(4..500).slice(4..400).bytes() {
            count += 1;
        }
        for _ in rope.slice(4..500).slice(4..400).chars() {
            count += 1;
        }

        let mut line = RopeSlice::from_str("");
        for l in rope.slice(4..500).slice(4..400).lines() {
            line = l;
        }
        line = line.slice(..).slice(..);

        let mut string = "";
        for c in rope.slice(4..500).slice(4..400).chunks() {
            string = c;
        }

        (a, b, c, d, e, f, count, line, string)
    };

    println!(
        "{} {:?} {} {:?} {:?} {:?} {} {} {}",
        a, b, c, d, e, f, count, line, string
    );
}
<commit_msg>Added another lifetime test case.<commit_after>//! This test file ensures that all of the lifetimes work the way we
//! want, and that there are no regressions. It's a "does this compile?"
//! test.

extern crate ropey;

use ropey::{Rope, RopeSlice};

const TEXT: &str = include_str!("test_text.txt");

fn main() {
    let rope = Rope::from_str(TEXT);

    let (a, b, c, d, e, f, g, count, line, string) = {
        // The lifetimes of intermediate slices shouldn't matter.  The
        // lifetimes of the things produced by the calls below should be
        // tied to the lifetime of the original rope, not the lifetimes of
        // the slices they were created from.  Therefore, this should all
        // compile.

        let a = rope.slice(4..500).slice(4..400).slice(4..300);
        let b = rope.slice(4..500).slice(4..400).as_str();
        let c = rope.slice(4..500).slice(4..400).line(1);
        let d = rope.line(1).slice(4..20).slice(4..10);
        let e = rope.slice(4..500).slice(4..400).chunk_at_byte(50);
        let f = rope.slice(4..500).slice(4..400).chunk_at_char(50);
        let g = rope.slice(4..500).slice(4..400).chunk_at_line_break(3);

        // Same for iterators.  In addition, the items _yielded_ by the
        // iterators should also be tied to the lifetime of the original
        // rope, not to the iterators or slices they came from.

        let mut count = 0;
        for _ in rope.slice(4..500).slice(4..400).bytes() {
            count += 1;
        }
        for _ in rope.slice(4..500).slice(4..400).chars() {
            count += 1;
        }

        let mut line = RopeSlice::from_str("");
        for l in rope.slice(4..500).slice(4..400).lines() {
            line = l;
        }
        line = line.slice(..).slice(..);

        let mut string = "";
        for c in rope.slice(4..500).slice(4..400).chunks() {
            string = c;
        }

        (a, b, c, d, e, f, g, count, line, string)
    };

    println!(
        "{} {:?} {} {} {:?} {:?} {:?} {} {} {}",
        a, b, c, d, e, f, g, count, line, string
    );
}
<|endoftext|>


<commit_before>/*
 * Cymbalum, Molecular Simulation in Rust
 * Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
*/
#![allow(non_snake_case)]
//! Testing physical properties of a Lennard-Jones gaz of Helium.
extern crate cymbalum;
use self::cymbalum::*;

use std::sync::{Once, ONCE_INIT};
static START: Once = ONCE_INIT;

use std::path::Path;

fn get_universe() -> Universe {
    let data_dir = Path::new(file!()).parent().unwrap();
    let configuration = data_dir.join("data").join("helium.xyz");
    let mut universe = Universe::from_file(configuration.to_str().unwrap()).unwrap();
    universe.set_cell(UnitCell::cubic(10.0));

    let mut velocities = BoltzmanVelocities::new(units::from(300.0, "K").unwrap());
    velocities.init(&mut universe);
    return universe;
}

fn get_universe_with_interaction() -> Universe {
    let mut universe = get_universe();
    universe.add_pair_interaction("He", "He",
        Box::new(LennardJones{
            sigma: units::from(2.0, "A").unwrap(),
            epsilon: units::from(0.2, "kJ/mol").unwrap()
        })
    );

    return universe;
}

#[test]
fn constant_energy_velocity_verlet() {
    START.call_once(|| {Logger::stdout();});
    let mut universe = get_universe_with_interaction();
    let mut simulation = Simulation::new(
        MolecularDynamics::from_integrator(
            VelocityVerlet::new(units::from(1.0, "fs").unwrap())
        )
    );
    let E_initial = universe.total_energy();
    simulation.run(&mut universe, 1000);
    let E_final = universe.total_energy();
    assert!(f64::abs((E_initial - E_final)/E_final) < 1e-3);
}

#[test]
fn constant_energy_verlet() {
    START.call_once(|| {Logger::stdout();});
    let mut universe = get_universe_with_interaction();
    let mut simulation = Simulation::new(
        MolecularDynamics::from_integrator(
            Verlet::new(units::from(1.0, "fs").unwrap())
        )
    );
    let E_initial = universe.total_energy();
    simulation.run(&mut universe, 1000);
    let E_final = universe.total_energy();
    assert!(f64::abs((E_initial - E_final)/E_final) < 1e-2);
}

#[test]
fn constant_energy_leap_frog() {
    START.call_once(|| {Logger::stdout();});
    let mut universe = get_universe_with_interaction();
    let mut simulation = Simulation::new(
        MolecularDynamics::from_integrator(
            LeapFrog::new(units::from(1.0, "fs").unwrap())
        )
    );
    let E_initial = universe.total_energy();
    simulation.run(&mut universe, 1000);
    let E_final = universe.total_energy();
    assert!(f64::abs((E_initial - E_final)/E_final) < 1e-3);
}

#[test]
fn perfect_gaz() {
    START.call_once(|| {Logger::stdout();});
    let mut universe = get_universe_with_interaction();
    let mut simulation = Simulation::new(
        MolecularDynamics::from_integrator(
            VelocityVerlet::new(units::from(1.0, "fs").unwrap())
        )
    );

    // dilating the universe!
    for particle in universe.iter_mut() {
        particle.position = 10.0 * particle.position;
    }
    universe.set_cell(UnitCell::cubic(100.0));

    simulation.run(&mut universe, 1000);
    let P = universe.pressure();
    let V = universe.volume();
    let T = universe.temperature();
    let N = universe.size() as f64;

    assert!(f64::abs(P * V - N * constants::K_BOLTZMANN * T) < 1e-3);
}

#[test]
fn berendsen_barostat() {
    START.call_once(|| {Logger::stdout();});
    let mut universe = get_universe_with_interaction();
    let mut simulation = Simulation::new(
        MolecularDynamics::from_integrator(
            BerendsenBarostat::new(
                units::from(1.0, "fs").unwrap(),
                units::from(5000.0, "bar").unwrap()
            )
        )
    );

    simulation.run(&mut universe, 1000);
    let pressure = units::from(5000.0, "bar").unwrap();
    assert!(f64::abs((universe.pressure() - pressure)/pressure) < 5e-2);
}

#[test]
fn cutoff_computation() {
    START.call_once(|| {Logger::stdout();});
    let mut universe = get_universe();

    universe.add_pair_interaction("He", "He",
        Box::new(CutoffComputation::new(
            Box::new(LennardJones{
                sigma: units::from(2.0, "A").unwrap(),
                epsilon: units::from(0.2, "kJ/mol").unwrap()
            }),
            units::from(7.0, "A").unwrap()
        ))
    );

    let mut simulation = Simulation::new(
        MolecularDynamics::from_integrator(
            VelocityVerlet::new(units::from(1.0, "fs").unwrap())
        )
    );
    simulation.run(&mut universe, 100);

    let E_initial = universe.total_energy();
    simulation.run(&mut universe, 1000);
    let E_final = universe.total_energy();
    assert!(f64::abs((E_initial - E_final)/E_final) < 1e-3);
}

#[test]
fn table_computation() {
    START.call_once(|| {Logger::stdout();});
    let mut universe = get_universe();

    universe.add_pair_interaction("He", "He",
        Box::new(TableComputation::new(
            Box::new(LennardJones{
                sigma: units::from(2.0, "A").unwrap(),
                epsilon: units::from(0.2, "kJ/mol").unwrap()
            }),
            1000,
            units::from(7.0, "A").unwrap()
        ))
    );

    let mut simulation = Simulation::new(
        MolecularDynamics::from_integrator(
            VelocityVerlet::new(units::from(1.0, "fs").unwrap())
        )
    );
    simulation.run(&mut universe, 100);

    let E_initial = universe.total_energy();
    simulation.run(&mut universe, 1000);
    let E_final = universe.total_energy();
    assert!(f64::abs((E_initial - E_final)/E_final) < 1e-3);
}
<commit_msg>Fix Travis build.<commit_after>/*
 * Cymbalum, Molecular Simulation in Rust
 * Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
*/
#![allow(non_snake_case)]
//! Testing physical properties of a Lennard-Jones gaz of Helium.
extern crate cymbalum;
use self::cymbalum::*;

use std::sync::{Once, ONCE_INIT};
static START: Once = ONCE_INIT;

use std::path::Path;

fn get_universe() -> Universe {
    let data_dir = Path::new(file!()).parent().unwrap();
    let configuration = data_dir.join("data").join("helium.xyz");
    let mut universe = Universe::from_file(configuration.to_str().unwrap()).unwrap();
    universe.set_cell(UnitCell::cubic(10.0));

    let mut velocities = BoltzmanVelocities::new(units::from(300.0, "K").unwrap());
    velocities.init(&mut universe);
    return universe;
}

fn get_universe_with_interaction() -> Universe {
    let mut universe = get_universe();
    universe.add_pair_interaction("He", "He",
        Box::new(LennardJones{
            sigma: units::from(2.0, "A").unwrap(),
            epsilon: units::from(0.2, "kJ/mol").unwrap()
        })
    );

    return universe;
}

#[test]
fn constant_energy_velocity_verlet() {
    START.call_once(|| {Logger::stdout();});
    let mut universe = get_universe_with_interaction();
    let mut simulation = Simulation::new(
        MolecularDynamics::from_integrator(
            VelocityVerlet::new(units::from(1.0, "fs").unwrap())
        )
    );
    let E_initial = universe.total_energy();
    simulation.run(&mut universe, 1000);
    let E_final = universe.total_energy();
    assert!(f64::abs((E_initial - E_final)/E_final) < 1e-3);
}

#[test]
fn constant_energy_verlet() {
    START.call_once(|| {Logger::stdout();});
    let mut universe = get_universe_with_interaction();
    let mut simulation = Simulation::new(
        MolecularDynamics::from_integrator(
            Verlet::new(units::from(1.0, "fs").unwrap())
        )
    );
    let E_initial = universe.total_energy();
    simulation.run(&mut universe, 1000);
    let E_final = universe.total_energy();
    assert!(f64::abs((E_initial - E_final)/E_final) < 1e-2);
}

#[test]
fn constant_energy_leap_frog() {
    START.call_once(|| {Logger::stdout();});
    let mut universe = get_universe_with_interaction();
    let mut simulation = Simulation::new(
        MolecularDynamics::from_integrator(
            LeapFrog::new(units::from(1.0, "fs").unwrap())
        )
    );
    let E_initial = universe.total_energy();
    simulation.run(&mut universe, 1000);
    let E_final = universe.total_energy();
    assert!(f64::abs((E_initial - E_final)/E_final) < 1e-3);
}

#[test]
fn perfect_gaz() {
    START.call_once(|| {Logger::stdout();});
    let mut universe = get_universe_with_interaction();
    let mut simulation = Simulation::new(
        MolecularDynamics::from_integrator(
            VelocityVerlet::new(units::from(1.0, "fs").unwrap())
        )
    );

    // dilating the universe!
    for particle in universe.iter_mut() {
        particle.position = 10.0 * particle.position;
    }
    universe.set_cell(UnitCell::cubic(100.0));

    simulation.run(&mut universe, 1000);
    let P = universe.pressure();
    let V = universe.volume();
    let T = universe.temperature();
    let N = universe.size() as f64;

    assert!(f64::abs(P * V - N * constants::K_BOLTZMANN * T) < 1e-3);
}

#[test]
fn berendsen_barostat() {
    START.call_once(|| {Logger::stdout();});
    let mut universe = get_universe_with_interaction();
    let mut simulation = Simulation::new(
        MolecularDynamics::from_integrator(
            BerendsenBarostat::new(
                units::from(1.0, "fs").unwrap(),
                units::from(5000.0, "bar").unwrap()
            )
        )
    );

    simulation.run(&mut universe, 1000);
    let pressure = units::from(5000.0, "bar").unwrap();
    assert!(f64::abs((universe.pressure() - pressure)/pressure) < 5e-2);
}

#[test]
fn cutoff_computation() {
    START.call_once(|| {Logger::stdout();});
    let mut universe = get_universe();

    universe.add_pair_interaction("He", "He",
        Box::new(CutoffComputation::new(
            Box::new(LennardJones{
                sigma: units::from(2.0, "A").unwrap(),
                epsilon: units::from(0.2, "kJ/mol").unwrap()
            }),
            units::from(7.0, "A").unwrap()
        ))
    );

    let mut simulation = Simulation::new(
        MolecularDynamics::from_integrator(
            VelocityVerlet::new(units::from(1.0, "fs").unwrap())
        )
    );
    simulation.run(&mut universe, 100);

    let E_initial = universe.total_energy();
    simulation.run(&mut universe, 1000);
    let E_final = universe.total_energy();
    assert!(f64::abs((E_initial - E_final)/E_final) < 2e-3);
}

#[test]
fn table_computation() {
    START.call_once(|| {Logger::stdout();});
    let mut universe = get_universe();

    universe.add_pair_interaction("He", "He",
        Box::new(TableComputation::new(
            Box::new(LennardJones{
                sigma: units::from(2.0, "A").unwrap(),
                epsilon: units::from(0.2, "kJ/mol").unwrap()
            }),
            1000,
            units::from(7.0, "A").unwrap()
        ))
    );

    let mut simulation = Simulation::new(
        MolecularDynamics::from_integrator(
            VelocityVerlet::new(units::from(1.0, "fs").unwrap())
        )
    );
    simulation.run(&mut universe, 100);

    let E_initial = universe.total_energy();
    simulation.run(&mut universe, 1000);
    let E_final = universe.total_energy();
    assert!(f64::abs((E_initial - E_final)/E_final) < 2e-3);
}
<|endoftext|>


<commit_before>use std::cell::UnsafeCell;
use std::rc::Rc;
use amy::Registrar;
use std::collections::HashSet;

/// Creates a throttler from which sub throttles may be created.
/// Note that all created throttle's have a lifetime tied to the
/// throttler. This invariant must be maintained or undefined
/// behaviour will occur.
pub struct Throttler {
    id: usize,
    fid: usize,
    dl_data: Rc<UnsafeCell<ThrottleData>>,
    ul_data: Rc<UnsafeCell<ThrottleData>>,
}

const URATE: usize = 15;

impl Throttler {
    /// Creates a new throttler and sets two timers on reg,
    /// one for updating the tokens, the other for flushing out
    /// blocked peers.
    pub fn new(
        dl_rate: Option<i64>,
        ul_rate: Option<i64>,
        max_tokens: usize,
        reg: &Registrar,
    ) -> Throttler {
        let id = reg.set_interval(URATE).unwrap();
        let fid = reg.set_interval(50).unwrap();
        let ut = ThrottleData::new(ul_rate, max_tokens);
        let dt = ThrottleData::new(dl_rate, max_tokens);
        Throttler {
            id,
            fid,
            ul_data: Rc::new(UnsafeCell::new(ut)),
            dl_data: Rc::new(UnsafeCell::new(dt)),
        }
    }

    #[cfg(test)]
    pub fn test(dl_rate: Option<i64>, ul_rate: Option<i64>, max_tokens: usize) -> Throttler {
        let ut = ThrottleData::new(ul_rate, max_tokens);
        let dt = ThrottleData::new(dl_rate, max_tokens);
        Throttler {
            id: 0,
            fid: 0,
            ul_data: Rc::new(UnsafeCell::new(ut)),
            dl_data: Rc::new(UnsafeCell::new(dt)),
        }
    }

    pub fn update(&mut self) -> (u64, u64) {
        let ul = self.ul_data().add_tokens();
        let dl = self.dl_data().add_tokens();
        (ul, dl)
    }

    pub fn get_throttle(&self, id: usize) -> Throttle {
        Throttle {
            ul_data: self.ul_data.clone(),
            dl_data: self.dl_data.clone(),
            id,
        }
    }

    pub fn ul_rate(&mut self) -> Option<i64> {
        self.ul_data().rate
    }

    pub fn dl_rate(&mut self) -> Option<i64> {
        self.dl_data().rate
    }

    pub fn set_ul_rate(&mut self, rate: Option<i64>) {
        self.ul_data().rate = rate;
    }

    pub fn set_dl_rate(&mut self, rate: Option<i64>) {
        self.dl_data().rate = rate;
    }

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

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

    pub fn flush_ul(&mut self) -> Vec<usize> {
        self.ul_data().throttled.drain().collect()
    }

    pub fn flush_dl(&mut self) -> Vec<usize> {
        self.dl_data().throttled.drain().collect()
    }

    fn ul_data<'f>(&self) -> &'f mut ThrottleData {
        unsafe { self.ul_data.get().as_mut().unwrap() }
    }

    fn dl_data<'f>(&self) -> &'f mut ThrottleData {
        unsafe { self.dl_data.get().as_mut().unwrap() }
    }
}

struct ThrottleData {
    rate: Option<i64>,
    tokens: usize,
    max_tokens: usize,
    last_used: u64,
    throttled: HashSet<usize>,
}

/// Throttle mechanism based on the token bucket algorithm.
/// Expected to be called every millisecond, and operates on
/// a KB/s rate scale.
#[derive(Clone)]
pub struct Throttle {
    pub id: usize,
    ul_data: Rc<UnsafeCell<ThrottleData>>,
    dl_data: Rc<UnsafeCell<ThrottleData>>,
}

unsafe impl Send for Throttle {}

impl Throttle {
    pub fn new_sibling(&self, id: usize) -> Throttle {
        Throttle {
            ul_data: self.ul_data.clone(),
            dl_data: self.dl_data.clone(),
            id,
        }
    }

    pub fn get_bytes_dl(&mut self, amnt: usize) -> Result<(), ()> {
        let res = self.dl_data().get_tokens(amnt);
        if res.is_err() {
            self.dl_data().throttled.insert(self.id);
        }
        res
    }

    pub fn get_bytes_ul(&mut self, amnt: usize) -> Result<(), ()> {
        let res = self.ul_data().get_tokens(amnt);
        if res.is_err() {
            self.ul_data().throttled.insert(self.id);
        }
        res
    }

    pub fn ul_rate(&self) -> Option<i64> {
        self.ul_data().rate
    }

    pub fn dl_rate(&self) -> Option<i64> {
        self.dl_data().rate
    }

    // TODO: Make this an HTB
    pub fn set_ul_rate(&mut self, rate: Option<i64>) {
        self.ul_data().rate = rate;
    }

    pub fn set_dl_rate(&mut self, rate: Option<i64>) {
        self.dl_data().rate = rate;
    }

    pub fn restore_bytes_dl(&mut self, amnt: usize) {
        self.dl_data().restore_tokens(amnt);
    }

    pub fn restore_bytes_ul(&mut self, amnt: usize) {
        self.ul_data().restore_tokens(amnt);
    }

    fn ul_data(&self) -> &'static mut ThrottleData {
        unsafe { self.ul_data.get().as_mut().unwrap() }
    }

    fn dl_data(&self) -> &'static mut ThrottleData {
        unsafe { self.dl_data.get().as_mut().unwrap() }
    }
}

impl Drop for Throttle {
    fn drop(&mut self) {
        self.ul_data().throttled.remove(&self.id);
        self.dl_data().throttled.remove(&self.id);
    }
}

impl ThrottleData {
    /// Creates a new Throttle with the given rate and max token amount.
    fn new(rate: Option<i64>, max_tokens: usize) -> ThrottleData {
        ThrottleData {
            tokens: 0,
            rate,
            max_tokens,
            throttled: HashSet::new(),
            last_used: 0,
        }
    }

    /// Adds some amount of tokens back.
    fn restore_tokens(&mut self, amnt: usize) {
        self.last_used -= amnt as u64;
        self.tokens += amnt;
    }

    /// This method must be called every URATE milliseconds and returns
    /// (self.last_used) * 1000/URATE - the bits/s, clearing self.last_used
    fn add_tokens(&mut self) -> u64 {
        let drained = self.last_used as u64;
        self.last_used = 0;
        self.tokens += if let Some(r) = self.rate {
            if r > 0 {
                (r as usize * URATE) / 1000
            } else {
                0
            }
        } else {
            0
        };
        if self.tokens >= self.max_tokens {
            self.tokens = self.max_tokens;
        }
        drained
    }

    /// Attempt to extract amnt tokens from the throttler.
    fn get_tokens(&mut self, amnt: usize) -> Result<(), ()> {
        match self.rate {
            None => {
                self.last_used += amnt as u64;
                Ok(())
            }
            Some(i) if i < 0 => {
                self.last_used += amnt as u64;
                Ok(())
            }
            Some(_) => {
                if amnt > self.tokens {
                    Err(())
                } else {
                    self.last_used += amnt as u64;
                    self.tokens -= amnt;
                    Ok(())
                }
            }
        }
    }
}
<commit_msg>Implement HTB for throttling<commit_after>use std::cell::UnsafeCell;
use std::rc::Rc;
use amy::Registrar;
use std::collections::HashSet;

/// Creates a throttler from which sub throttles may be created.
/// Note that all created throttle's have a lifetime tied to the
/// throttler. This invariant must be maintained or undefined
/// behaviour will occur.
pub struct Throttler {
    id: usize,
    fid: usize,
    dl_data: Rc<UnsafeCell<ThrottleData>>,
    ul_data: Rc<UnsafeCell<ThrottleData>>,
}

const URATE: usize = 15;

impl Throttler {
    /// Creates a new throttler and sets two timers on reg,
    /// one for updating the tokens, the other for flushing out
    /// blocked peers.
    pub fn new(
        dl_rate: Option<i64>,
        ul_rate: Option<i64>,
        max_tokens: usize,
        reg: &Registrar,
    ) -> Throttler {
        let id = reg.set_interval(URATE).unwrap();
        let fid = reg.set_interval(50).unwrap();
        let ut = ThrottleData::new(ul_rate, max_tokens);
        let dt = ThrottleData::new(dl_rate, max_tokens);
        Throttler {
            id,
            fid,
            ul_data: Rc::new(UnsafeCell::new(ut)),
            dl_data: Rc::new(UnsafeCell::new(dt)),
        }
    }

    #[cfg(test)]
    pub fn test(dl_rate: Option<i64>, ul_rate: Option<i64>, max_tokens: usize) -> Throttler {
        let ut = ThrottleData::new(ul_rate, max_tokens);
        let dt = ThrottleData::new(dl_rate, max_tokens);
        Throttler {
            id: 0,
            fid: 0,
            ul_data: Rc::new(UnsafeCell::new(ut)),
            dl_data: Rc::new(UnsafeCell::new(dt)),
        }
    }

    pub fn update(&mut self) -> (u64, u64) {
        let ul = self.ul_data().add_tokens();
        let dl = self.dl_data().add_tokens();
        (ul, dl)
    }

    pub fn get_throttle(&self, id: usize) -> Throttle {
        Throttle {
            ul_data: self.ul_data.clone(),
            ul_tier: Rc::new(UnsafeCell::new(ThrottleData::new(
                None,
                self.ul_data().max_tokens,
            ))),
            dl_data: self.dl_data.clone(),
            dl_tier: Rc::new(UnsafeCell::new(ThrottleData::new(
                None,
                self.dl_data().max_tokens,
            ))),
            id,
        }
    }

    pub fn ul_rate(&mut self) -> Option<i64> {
        self.ul_data().rate
    }

    pub fn dl_rate(&mut self) -> Option<i64> {
        self.dl_data().rate
    }

    pub fn set_ul_rate(&mut self, rate: Option<i64>) {
        self.ul_data().rate = rate;
    }

    pub fn set_dl_rate(&mut self, rate: Option<i64>) {
        self.dl_data().rate = rate;
    }

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

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

    pub fn flush_ul(&mut self) -> Vec<usize> {
        self.ul_data().throttled.drain().collect()
    }

    pub fn flush_dl(&mut self) -> Vec<usize> {
        self.dl_data().throttled.drain().collect()
    }

    fn ul_data<'f>(&self) -> &'f mut ThrottleData {
        unsafe { self.ul_data.get().as_mut().unwrap() }
    }

    fn dl_data<'f>(&self) -> &'f mut ThrottleData {
        unsafe { self.dl_data.get().as_mut().unwrap() }
    }
}

struct ThrottleData {
    rate: Option<i64>,
    tokens: usize,
    epoch: usize,
    max_tokens: usize,
    last_used: u64,
    throttled: HashSet<usize>,
}

/// Throttle mechanism based on the token bucket algorithm.
/// Expected to be called every millisecond, and operates on
/// a KB/s rate scale.
#[derive(Clone)]
pub struct Throttle {
    pub id: usize,
    ul_tier: Rc<UnsafeCell<ThrottleData>>,
    dl_tier: Rc<UnsafeCell<ThrottleData>>,
    ul_data: Rc<UnsafeCell<ThrottleData>>,
    dl_data: Rc<UnsafeCell<ThrottleData>>,
}

unsafe impl Send for Throttle {}

impl Throttle {
    pub fn new_sibling(&self, id: usize) -> Throttle {
        Throttle {
            ul_data: self.ul_data.clone(),
            ul_tier: self.ul_tier.clone(),
            dl_data: self.dl_data.clone(),
            dl_tier: self.dl_tier.clone(),
            id,
        }
    }

    pub fn get_bytes_dl(&mut self, amnt: usize) -> Result<(), ()> {
        while self.dl_tier().epoch != self.dl_data().epoch {
            self.dl_tier().add_tokens();
        }
        if self.dl_rate() == Some(-1) {
            self.dl_tier().last_used += amnt as u64;
            self.dl_data().last_used += amnt as u64;
            return Ok(());
        }
        let pres = self.dl_data().get_tokens(amnt);
        if pres.is_err() {
            self.dl_data().throttled.insert(self.id);
            return Err(());
        }

        let res = self.dl_tier().get_tokens(amnt);
        if res.is_err() {
            self.dl_data().restore_tokens(amnt);
            self.dl_data().throttled.insert(self.id);
            return Err(());
        }
        Ok(())
    }

    pub fn get_bytes_ul(&mut self, amnt: usize) -> Result<(), ()> {
        while self.ul_tier().epoch != self.ul_data().epoch {
            self.ul_tier().add_tokens();
        }
        if self.ul_rate() == Some(-1) {
            self.ul_tier().last_used += amnt as u64;
            self.ul_data().last_used += amnt as u64;
            return Ok(());
        }
        let pres = self.ul_data().get_tokens(amnt);
        if pres.is_err() {
            self.ul_data().throttled.insert(self.id);
            return Err(());
        }

        let res = self.ul_tier().get_tokens(amnt);
        if res.is_err() {
            self.ul_data().restore_tokens(amnt);
            self.ul_data().throttled.insert(self.id);
            return Err(());
        }
        Ok(())
    }

    pub fn ul_rate(&self) -> Option<i64> {
        self.ul_tier().rate
    }

    pub fn dl_rate(&self) -> Option<i64> {
        self.dl_tier().rate
    }

    pub fn set_ul_rate(&mut self, rate: Option<i64>) {
        self.ul_tier().rate = rate;
    }

    pub fn set_dl_rate(&mut self, rate: Option<i64>) {
        self.dl_tier().rate = rate;
    }

    pub fn restore_bytes_dl(&mut self, amnt: usize) {
        self.dl_data().restore_tokens(amnt);
        self.dl_tier().restore_tokens(amnt);
    }

    pub fn restore_bytes_ul(&mut self, amnt: usize) {
        self.ul_data().restore_tokens(amnt);
        self.ul_tier().restore_tokens(amnt);
    }

    fn ul_data(&self) -> &'static mut ThrottleData {
        unsafe { self.ul_data.get().as_mut().unwrap() }
    }

    fn ul_tier(&self) -> &'static mut ThrottleData {
        unsafe { self.ul_tier.get().as_mut().unwrap() }
    }

    fn dl_data(&self) -> &'static mut ThrottleData {
        unsafe { self.dl_data.get().as_mut().unwrap() }
    }

    fn dl_tier(&self) -> &'static mut ThrottleData {
        unsafe { self.dl_tier.get().as_mut().unwrap() }
    }
}

impl Drop for Throttle {
    fn drop(&mut self) {
        self.ul_data().throttled.remove(&self.id);
        self.dl_data().throttled.remove(&self.id);
    }
}

impl ThrottleData {
    /// Creates a new Throttle with the given rate and max token amount.
    fn new(rate: Option<i64>, max_tokens: usize) -> ThrottleData {
        ThrottleData {
            tokens: 0,
            rate,
            max_tokens,
            throttled: HashSet::with_capacity(0),
            last_used: 0,
            epoch: 0,
        }
    }

    /// Adds some amount of tokens back.
    fn restore_tokens(&mut self, amnt: usize) {
        self.last_used -= amnt as u64;
        self.tokens += amnt;
    }

    /// This method must be called every URATE milliseconds and returns
    /// (self.last_used) * 1000/URATE - the bits/s, clearing self.last_used
    fn add_tokens(&mut self) -> u64 {
        self.epoch = self.epoch.wrapping_add(1);
        let drained = self.last_used as u64;
        self.last_used = 0;
        self.tokens += if let Some(r) = self.rate {
            if r > 0 {
                (r as usize * URATE) / 1000
            } else {
                0
            }
        } else {
            0
        };
        if self.tokens >= self.max_tokens {
            self.tokens = self.max_tokens;
        }
        drained
    }

    /// Attempt to extract amnt tokens from the throttler.
    fn get_tokens(&mut self, amnt: usize) -> Result<(), ()> {
        match self.rate {
            None => {
                self.last_used += amnt as u64;
                Ok(())
            }
            Some(i) if i < 0 => {
                self.last_used += amnt as u64;
                Ok(())
            }
            Some(_) => {
                if amnt > self.tokens {
                    Err(())
                } else {
                    self.last_used += amnt as u64;
                    self.tokens -= amnt;
                    Ok(())
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//! The interface for interacting with TMUX sessions. All the commands that are
/// built up during the parsing phase get matched to functions here. The
/// functions in this module all build up strings the get passed to a private
/// call. The private call converts them to CStrings and makes an "unsafe" system
/// call. All functions go through this `call` function as a common gateway to
/// system calls and can all be easily logged there.

pub mod config;

use libc::system;
use std::ffi::CString;
use std::process::{Command, ExitStatus};

/// The program to call commands on.
static TMUX_NAME: &'static str = "tmux";

/// The gateway to calling any functions on tmux. All public functions in this
/// module will be fed through this `call` function. This functions purpose is to
/// turn string based tmux function calls in to a `CString` and call out to the
/// system with it.
///
/// command: The command we will send to tmux on the host system for execution.
///
/// # Examples
///
/// ```
/// call("new-window -t muxed -c ~/Projects/muxed/".to_string());
/// ```
///
/// # Safety
///
/// This function will make an `unsafe` call out to the system to execute tmux
/// related commands.
fn call(command: String) -> () {
    let line = format!("{} {} {}", TMUX_NAME, command, ">/dev/null");
    let system_call = CString::new(line.clone()).unwrap();
    //println!("{}", line.clone());
    unsafe { system(system_call.as_ptr()); };
}

/// Attach is called as the last function in a set of commands. After the tmux
/// env has been setup by all previous commands this attaches the user to their
/// daemonized tmux session.
///
/// # Examples
///
/// ```
/// let session_name = "muxed".to_string();
/// tmux::attach(muxed);
/// ```
/// session_name: The active tmux session name.
pub fn attach(session_name: &String) -> () {
    call(format!("attach -t {}", session_name));
}

/// New session is the first call made in any sequence of commands. It initiates
/// a new tmux session with a default first window name.
/// *Why a randomized first window name?*
///   This is because the `new-session` tmux command does not support the `-c`
/// flag as `new-window` and `split-window` do. So if the first window requires
/// being changed to a default directory `send-keys` must be used after the
/// session and first window are opened. This means the first window is treated in
/// a different code path than any other window that is opened.
/// Instead I've opted to open the session with a randomized (no conflicts)
/// named window, and we close this window out before attaching the user. This
/// allows for us to treat all user defined windows the same.
///
/// session_name: The name of the session being created.
/// tmp_name: The named first window that we will close out.
///
/// # Examples
///
/// ```
/// use rand::random;
///
/// let session_name = "muxed".to_string();
/// let tmp_window_name = random::<u16>().to_string();
/// tmux::new_session(session_name, tmp_window_name);
/// ```
///
/// session_name: The active tmux session name.
/// tmp_name: The name for the temp initial window that is created with a new
/// session.
pub fn new_session(session_name: &String, window_name: &String) -> () {
    call(format!("new -d -s {} -n {}", session_name, window_name));
}

/// Split window acts as the command to target named windows in a session to
/// send a make separate a single pane into two panes. Split window should target
/// a specific pane even if only a single pane exists.
///
/// # Examples
///
/// ```
/// let target = "muxed:cargo.0".to_string();
/// tmux::split_window(target, None);
/// ```
///
/// target: A string represented by the {named_session}:{named_window}.{pane}
/// root: An `Option<String>` passed to the -c argument to change the current
/// directory.
pub fn split_window(target: &String) -> () {
    call(format!("split-window -t {}", target));
}

/// New window opens a new window in the named session with the provided window
/// name.
///
/// # Examples
///
/// ```
/// tmux::new_window("muxed".to_string(), "vim".to_string(), None);
/// ```
///
/// session_name: The active tmux session name.
/// window_name: The desired window name for the new window.
/// root: An `Option<String>` passed to the -c argument to change the current
/// directory.
pub fn new_window(session_name: &String, window_name: &String) -> () {
    call(format!("new-window -t {} -n {}", session_name, window_name));
}

/// The layout function will adjust the layout of a tmux window that already has
/// multiple panes. Currently it will only accept standard tmux layout types.
///
/// Possible layout options: even-horizontal, even-vertical, main-horizontal,
/// main-vertical, or tiled.
///
/// # Examples
///
/// ```
/// tmux::layout("muxed:cargo.0".to_string(), "main-vertical".to_string(), None);
/// ```
///
/// target: A string represented by the {named_session}:{named_window}.{pane}
/// layout: The predefined tmux named layout.
pub fn layout(target: &String, layout: &String) -> () {
    call(format!("select-layout -t {} {}", target, layout));
}

/// Send Keys executes literal key commands in specified target windows. This is
/// the execution method to perform actions like tailing logs, starting servers,
/// or opening editors.
///
/// `KPEnter` represent the keyboard press of the "Enter" key. So the execution
/// is a user input command followed by "enter"
///
/// # Examples
///
/// ```
/// tmux::send_keys("muxed:cargo.0".to_string(), "vim .".to_string());
/// ```
///
/// target: A string represented by the {named_session}:{named_window}.{pane}
/// exec: The system command to be executed in a particular pane.
pub fn send_keys(target: &String, exec: &String) -> () {
    call(format!("send-keys -t {} '{}' KPEnter", target, exec));
}

/// This is used to re-select the first window before
/// attaching to the session.
///
/// # Examples
///
/// ```
/// tmux::select_window("muxed:cargo.0".to_string());
/// ```
///
/// target: A string represented by the {named_session}:{named_window}.{pane}
pub fn select_window(target: &String) -> () {
    call(format!("select-window -t {}", target));
}

/// This is used to re-select the top pane in the first window before
/// attaching to the session.
///
/// # Examples
///
/// ```
/// tmux::select_pane("muxed:cargo.top".to_string());
/// ```
///
/// target: A string represented by the {named_session}:{named_window}.{pane}
pub fn select_pane(target: &String) -> () {
    call(format!("select-pane -t {}", target));
}

/// List Windows is used firgure out if a named session is already running.
///
/// # Examples
///
/// ```
/// tmux::has_session("muxed".to_string());
/// => ExitStatus
/// ```
///
/// target: A string represented by the {named_session}
pub fn has_session(target: &String) -> ExitStatus {
    let output = Command::new(TMUX_NAME)
                     .arg("has-session")
                     .arg("-t")
                     .arg(target)
                     .output()
                     .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    output.status
}

/// Read the tmux config and return a config object
///
/// # Examples
///
/// ```
/// tmux::get_config();
/// => "some-option false\npane-base-index 0"
/// ```
pub fn get_config() -> String {
    let output = Command::new(TMUX_NAME)
                     .args(&["start-server", ";", "show-options", "-g"])
                     .output()
                     .unwrap_or_else(|e| { panic!("couldn't get tmux options: {}", e) });

    String::from_utf8_lossy(&output.stdout).to_string()
}
<commit_msg>refactor(tmux/mod.rs): Use a safer command interop<commit_after>//! The interface for interacting with TMUX sessions. All the commands that are
/// built up during the parsing phase get matched to functions here. The
/// functions in this module all build up strings the get passed to a private
/// call. The private call converts them to CStrings and makes an "unsafe" system
/// call. All functions go through this `call` function as a common gateway to
/// system calls and can all be easily logged there.

pub mod config;

use libc::system;
use std::ffi::CString;
use std::process::{Command, ExitStatus};

/// The program to call commands on.
static TMUX_NAME: &'static str = "tmux";

/// The gateway to calling any functions on tmux. All public functions in this
/// module will be fed through this `call` function. This functions purpose is to
/// turn string based tmux function calls in to a `CString` and call out to the
/// system with it.
///
/// command: The command we will send to tmux on the host system for execution.
///
/// # Examples
///
/// ```
/// call("new-window -t muxed -c ~/Projects/muxed/".to_string());
/// ```
///
/// # Safety
///
/// This function will make an `unsafe` call out to the system to execute tmux
/// related commands.
fn call(command: String) -> () {
    let line = format!("{} {} {}", TMUX_NAME, command, ">/dev/null");
    let system_call = CString::new(line.clone()).unwrap();
    //println!("{}", line.clone());
    unsafe { system(system_call.as_ptr()); };
}

fn call1(args: &[&str]) -> () {
    //println!("{}", line.clone());
    Command::new(TMUX_NAME).args(args).output()
}

/// Attach is called as the last function in a set of commands. After the tmux
/// env has been setup by all previous commands this attaches the user to their
/// daemonized tmux session.
///
/// # Examples
///
/// ```
/// let session_name = "muxed".to_string();
/// tmux::attach(muxed);
/// ```
/// session_name: The active tmux session name.
pub fn attach(session_name: &String) -> () {
    call(format!("attach -t {}", session_name));
}

/// New session is the first call made in any sequence of commands. It initiates
/// a new tmux session with a default first window name.
/// *Why a randomized first window name?*
///   This is because the `new-session` tmux command does not support the `-c`
/// flag as `new-window` and `split-window` do. So if the first window requires
/// being changed to a default directory `send-keys` must be used after the
/// session and first window are opened. This means the first window is treated in
/// a different code path than any other window that is opened.
/// Instead I've opted to open the session with a randomized (no conflicts)
/// named window, and we close this window out before attaching the user. This
/// allows for us to treat all user defined windows the same.
///
/// session_name: The name of the session being created.
/// tmp_name: The named first window that we will close out.
///
/// # Examples
///
/// ```
/// use rand::random;
///
/// let session_name = "muxed".to_string();
/// let tmp_window_name = random::<u16>().to_string();
/// tmux::new_session(session_name, tmp_window_name);
/// ```
///
/// session_name: The active tmux session name.
/// tmp_name: The name for the temp initial window that is created with a new
/// session.
pub fn new_session(session_name: &String, window_name: &String) -> () {
    call(format!("new -d -s {} -n {}", session_name, window_name));
}

/// Split window acts as the command to target named windows in a session to
/// send a make separate a single pane into two panes. Split window should target
/// a specific pane even if only a single pane exists.
///
/// # Examples
///
/// ```
/// let target = "muxed:cargo.0".to_string();
/// tmux::split_window(target, None);
/// ```
///
/// target: A string represented by the {named_session}:{named_window}.{pane}
/// root: An `Option<String>` passed to the -c argument to change the current
/// directory.
pub fn split_window(target: &String) -> () {
    call(format!("split-window -t {}", target));
}

/// New window opens a new window in the named session with the provided window
/// name.
///
/// # Examples
///
/// ```
/// tmux::new_window("muxed".to_string(), "vim".to_string(), None);
/// ```
///
/// session_name: The active tmux session name.
/// window_name: The desired window name for the new window.
/// root: An `Option<String>` passed to the -c argument to change the current
/// directory.
pub fn new_window(session_name: &String, window_name: &String) -> () {
    call(format!("new-window -t {} -n {}", session_name, window_name));
}

/// The layout function will adjust the layout of a tmux window that already has
/// multiple panes. Currently it will only accept standard tmux layout types.
///
/// Possible layout options: even-horizontal, even-vertical, main-horizontal,
/// main-vertical, or tiled.
///
/// # Examples
///
/// ```
/// tmux::layout("muxed:cargo.0".to_string(), "main-vertical".to_string(), None);
/// ```
///
/// target: A string represented by the {named_session}:{named_window}.{pane}
/// layout: The predefined tmux named layout.
pub fn layout(target: &String, layout: &String) -> () {
    call(format!("select-layout -t {} {}", target, layout));
}

/// Send Keys executes literal key commands in specified target windows. This is
/// the execution method to perform actions like tailing logs, starting servers,
/// or opening editors.
///
/// `KPEnter` represent the keyboard press of the "Enter" key. So the execution
/// is a user input command followed by "enter"
///
/// # Examples
///
/// ```
/// tmux::send_keys("muxed:cargo.0".to_string(), "vim .".to_string());
/// ```
///
/// target: A string represented by the {named_session}:{named_window}.{pane}
/// exec: The system command to be executed in a particular pane.
pub fn send_keys(target: &String, exec: &String) -> () {
    call(format!("send-keys -t {} '{}' KPEnter", target, exec));
}

/// This is used to re-select the first window before
/// attaching to the session.
///
/// # Examples
///
/// ```
/// tmux::select_window("muxed:cargo.0".to_string());
/// ```
///
/// target: A string represented by the {named_session}:{named_window}.{pane}
pub fn select_window(target: &String) -> () {
    call(format!("select-window -t {}", target));
}

/// This is used to re-select the top pane in the first window before
/// attaching to the session.
///
/// # Examples
///
/// ```
/// tmux::select_pane("muxed:cargo.top".to_string());
/// ```
///
/// target: A string represented by the {named_session}:{named_window}.{pane}
pub fn select_pane(target: &String) -> () {
    call(format!("select-pane -t {}", target));
}

/// List Windows is used firgure out if a named session is already running.
///
/// # Examples
///
/// ```
/// tmux::has_session("muxed".to_string());
/// => ExitStatus
/// ```
///
/// target: A string represented by the {named_session}
pub fn has_session(target: &String) -> ExitStatus {
    let output = Command::new(TMUX_NAME)
                     .arg("has-session")
                     .arg("-t")
                     .arg(target)
                     .output()
                     .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    output.status
}

/// Read the tmux config and return a config object
///
/// # Examples
///
/// ```
/// tmux::get_config();
/// => "some-option false\npane-base-index 0"
/// ```
pub fn get_config() -> String {
    let output = Command::new(TMUX_NAME)
                     .args(&["start-server", ";", "show-options", "-g"])
                     .output()
                     .unwrap_or_else(|e| { panic!("couldn't get tmux options: {}", e) });

    String::from_utf8_lossy(&output.stdout).to_string()
}
<|endoftext|>


<commit_before>#[macro_use]
mod macros;

use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::Item;

#[test]
fn test_macro_variable_attr() {
    // mimics the token stream corresponding to `$attr fn f() {}`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { #[test] })),
        TokenTree::Ident(Ident::new("fn", Span::call_site())),
        TokenTree::Ident(Ident::new("f", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
        TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
    ]);

    snapshot!(tokens as Item, @r###"
    Item::Fn {
        attrs: [
            Attribute {
                style: Outer,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "test",
                            arguments: None,
                        },
                    ],
                },
                tokens: TokenStream(``),
            },
        ],
        vis: Inherited,
        sig: Signature {
            ident: "f",
            generics: Generics,
            output: Default,
        },
        block: Block,
    }
    "###);
}

#[test]
fn test_negative_impl() {
    // Rustc parses all of the following.

    #[cfg(any())]
    impl ! {}
    let tokens = quote! {
        impl ! {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Type::Never,
    }
    "###);

    #[cfg(any())]
    #[rustfmt::skip]
    impl !Trait {}
    let tokens = quote! {
        impl !Trait {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Verbatim(`! Trait`),
    }
    "###);

    #[cfg(any())]
    impl !Trait for T {}
    let tokens = quote! {
        impl !Trait for T {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        trait_: Some((
            Some,
            Path {
                segments: [
                    PathSegment {
                        ident: "Trait",
                        arguments: None,
                    },
                ],
            },
        )),
        self_ty: Type::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "T",
                        arguments: None,
                    },
                ],
            },
        },
    }
    "###);

    #[cfg(any())]
    #[rustfmt::skip]
    impl !! {}
    let tokens = quote! {
        impl !! {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Verbatim(`! !`),
    }
    "###);
}

#[test]
fn test_macro_variable_impl() {
    // mimics the token stream corresponding to `impl $trait for $ty {}`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Ident(Ident::new("impl", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::None, quote!(Trait))),
        TokenTree::Ident(Ident::new("for", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::None, quote!(Type))),
        TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
    ]);

    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        trait_: Some((
            None,
            Path {
                segments: [
                    PathSegment {
                        ident: "Trait",
                        arguments: None,
                    },
                ],
            },
        )),
        self_ty: Type::Group {
            elem: Type::Path {
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Type",
                            arguments: None,
                        },
                    ],
                },
            },
        },
    }
    "###);
}
<commit_msg>Add test of empty supertrait list<commit_after>#[macro_use]
mod macros;

use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::{Item, ItemTrait};

#[test]
fn test_macro_variable_attr() {
    // mimics the token stream corresponding to `$attr fn f() {}`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { #[test] })),
        TokenTree::Ident(Ident::new("fn", Span::call_site())),
        TokenTree::Ident(Ident::new("f", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
        TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
    ]);

    snapshot!(tokens as Item, @r###"
    Item::Fn {
        attrs: [
            Attribute {
                style: Outer,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "test",
                            arguments: None,
                        },
                    ],
                },
                tokens: TokenStream(``),
            },
        ],
        vis: Inherited,
        sig: Signature {
            ident: "f",
            generics: Generics,
            output: Default,
        },
        block: Block,
    }
    "###);
}

#[test]
fn test_negative_impl() {
    // Rustc parses all of the following.

    #[cfg(any())]
    impl ! {}
    let tokens = quote! {
        impl ! {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Type::Never,
    }
    "###);

    #[cfg(any())]
    #[rustfmt::skip]
    impl !Trait {}
    let tokens = quote! {
        impl !Trait {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Verbatim(`! Trait`),
    }
    "###);

    #[cfg(any())]
    impl !Trait for T {}
    let tokens = quote! {
        impl !Trait for T {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        trait_: Some((
            Some,
            Path {
                segments: [
                    PathSegment {
                        ident: "Trait",
                        arguments: None,
                    },
                ],
            },
        )),
        self_ty: Type::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "T",
                        arguments: None,
                    },
                ],
            },
        },
    }
    "###);

    #[cfg(any())]
    #[rustfmt::skip]
    impl !! {}
    let tokens = quote! {
        impl !! {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Verbatim(`! !`),
    }
    "###);
}

#[test]
fn test_macro_variable_impl() {
    // mimics the token stream corresponding to `impl $trait for $ty {}`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Ident(Ident::new("impl", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::None, quote!(Trait))),
        TokenTree::Ident(Ident::new("for", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::None, quote!(Type))),
        TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
    ]);

    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        trait_: Some((
            None,
            Path {
                segments: [
                    PathSegment {
                        ident: "Trait",
                        arguments: None,
                    },
                ],
            },
        )),
        self_ty: Type::Group {
            elem: Type::Path {
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Type",
                            arguments: None,
                        },
                    ],
                },
            },
        },
    }
    "###);
}

#[test]
fn test_supertraits() {
    // Rustc parses all of the following.

    #[rustfmt::skip]
    let tokens = quote!(trait Trait where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(trait Trait: where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
        colon_token: Some,
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(trait Trait: Sized where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
        colon_token: Some,
        supertraits: [
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Sized",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(trait Trait: Sized + where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
        colon_token: Some,
        supertraits: [
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Sized",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);
}
<|endoftext|>