<commit_before>use core::{DungeonGenerator, RoomType, Room, Rectangle};
use rand::{SeedableRng, StdRng, Rng};
use std::collections::VecDeque;
use std::cmp::{min, max};

/// Simple Binary Space Partioning dungeon generation algorithm:
///
///  1. Workspace splitting to random rectangles with the help of binary tree
///  2. In every rectangle generating a random room
///  3. Coridors generating with the help of the binary tree, generated at the first step
pub struct BSPGenerator {
    bs_max_deep: u32,
    deny_split_deep: u32,
    split_chance_dec: u32,
    split_max_coeff: u32,
    split_default_chance: u32,
    min_room_splittable_size: u32,
    coridor_width: u32,
}

impl Default for BSPGenerator {
    fn default() -> BSPGenerator {
        BSPGenerator {
            bs_max_deep: 5,
            deny_split_deep: 3,
            split_chance_dec: 30,
            split_max_coeff: 70,
            split_default_chance: 100,
            min_room_splittable_size: 150,
            coridor_width: 15,
        }
    }
}

impl BSPGenerator {
    /// levels of binary tree
    pub fn bs_max_deep(mut self, value: u32) -> Self {
        self.bs_max_deep = value;
        self
    }

    /// level of tree from which node can deny split
    pub fn deny_split_deep(mut self, value: u32) -> Self {
        self.deny_split_deep = value;
        self
    }

    /// split chance decreasment per tree level starting "deny_split_deep"
    pub fn split_chance_dec(mut self, value: u32) -> Self {
        self.split_chance_dec = value;
        self
    }

    /// max splitting coefficient
    pub fn split_max_coeff(mut self, value: u32) -> Self {
        self.split_max_coeff = value;
        self
    }

    /// default splitting chance
    pub fn split_default_chance(mut self, value: u32) -> Self {
        self.split_default_chance = value;
        self
    }

    /// minimum splittable size of subdungeon
    pub fn min_room_splittable_size(mut self, value: u32) -> Self {
        self.min_room_splittable_size = value;
        self
    }

    /// constant width of corridors
    pub fn coridor_width(mut self, value: u32) -> Self {
        self.coridor_width = value;
        self
    }

    fn generate_coridor_vert(&mut self, bx1: Rectangle, bx2: Rectangle, rng: &mut StdRng, rooms: &mut Vec<Room>) {
        let max_min_x = max(bx1[0], bx2[0]);
        let min_max_x = min(bx1[0]+bx1[2], bx2[0]+bx2[2])-self.coridor_width;
        let mut coridor = [0,0,self.coridor_width,0];
        coridor[1] = bx1[1] + bx1[3];
        coridor[3] = bx2[1] - bx1[1] - bx1[3];
        if max_min_x < min_max_x {
            // I like coridor
            coridor[0] = rng.gen_range(max_min_x, min_max_x);
        }
        else {
            // L like coridor
            coridor[0] = rng.gen_range(bx1[0], bx1[0]+bx1[2]);
            coridor[3] += bx2[3]/2;
            let mut h_coridor = [0,coridor[1]+coridor[3]-self.coridor_width,0,self.coridor_width];
            if max_min_x == bx1[0] {
                h_coridor[0] = min_max_x;
                h_coridor[2] = coridor[0] - h_coridor[0];
            }
            else {
                h_coridor[0] = coridor[0];
                h_coridor[2] = max_min_x - coridor[0];
            }
            rooms.push(Room::new(RoomType::Coridor, h_coridor));
        }
        rooms.push(Room::new(RoomType::Coridor, coridor));
    }

    fn generate_coridor_hor(&mut self, bx1: Rectangle, bx2: Rectangle, rng: &mut StdRng, rooms: &mut Vec<Room>) {
        let max_min_y = max(bx1[1], bx2[1]);
        let min_max_y = min(bx1[1]+bx1[3], bx2[1]+bx2[3])-self.coridor_width;
        let mut coridor = [0,0,0,self.coridor_width];
        coridor[0] = bx1[0] + bx1[2];
        coridor[2] = bx2[0] - bx1[0] - bx1[2];
        if max_min_y < min_max_y {
            // - like coridor
            coridor[1] = rng.gen_range(max_min_y, min_max_y);
        }
        else {
            // L like coridor
            coridor[1] = rng.gen_range(bx1[1], bx1[1]+bx1[3]);
            coridor[2] += bx2[2]/2;
            let mut v_coridor = [coridor[0]+coridor[2]-self.coridor_width,0,self.coridor_width,0];
            if max_min_y == bx1[1] {
                v_coridor[1] = min_max_y;
                v_coridor[3] = coridor[1] - v_coridor[1];
            }
            else {
                v_coridor[1] = coridor[1];
                v_coridor[3] = max_min_y - coridor[1];
            }
            rooms.push(Room::new(RoomType::Coridor, v_coridor));
        }
        rooms.push(Room::new(RoomType::Coridor, coridor));
    }

}

#[derive(Default, Clone, Copy, Debug)]
struct SubDungeon {
    pub x: u32,
    pub y: u32,
    pub width: u32,
    pub height: u32,
    pub deep: u32,
    pub childs: Option<[usize; 2]>,
    pub parent: Option<usize>,
    pub bounding_rect: Option<Rectangle>,
}

impl SubDungeon {
    pub fn new(x: u32, y: u32, w: u32, h: u32, deep: u32, parent: Option<usize>) -> SubDungeon {
        SubDungeon {
            x: x,
            y: y,
            width: w,
            height: h,
            deep: deep,
            childs: None,
            parent: parent,
            bounding_rect: None,
        }
    }
}

impl DungeonGenerator for BSPGenerator {
    fn generate(&mut self, seed: &[usize], width: u32, height: u32) -> Vec<Room> {
        let mut rng: StdRng = SeedableRng::from_seed(seed);
        let mut dungeon = Vec::<SubDungeon>::new();
        dungeon.push(SubDungeon::new(0, 0, width, height, 0, None));
        let mut queue = VecDeque::<usize>::new();
        queue.push_back(0);
        // generating subdungeons
        while !queue.is_empty() {
            // current index in queue
            let i = queue.pop_front().unwrap();
            // checking now deep we are
            let deep = dungeon[i].deep;
            // counting split chance
            let mut sp = self.split_default_chance;
            if deep >= self.deny_split_deep {
                if deep > self.bs_max_deep {
                    break;
                }
                let deny_split_chance = (deep - self.deny_split_deep + 1)*self.split_chance_dec;
                sp = if deny_split_chance > 100 {
                    0
                }
                else {
                    sp - deny_split_chance
                };
            }
            let w = dungeon[i].width;
            let h = dungeon[i].height;
            // will it be splited, or not?
            let b = ((w > self.min_room_splittable_size) || (h > self.min_room_splittable_size)) && (rng.gen_range(0, 100) < sp);
            if b {
                // How fair will be split
                let coef = rng.gen_range(100 - self.split_max_coeff, self.split_max_coeff);
                let x1 = dungeon[i].x;
                let y1 = dungeon[i].y;
                let mut x2 = x1;
                let mut y2 = y1;
                let mut w1 = w;
                let mut h1 = h;
                // Split vertical or not
                if (h < self.min_room_splittable_size) || ((w > self.min_room_splittable_size) && (rng.gen_range(0, 2) == 1)) {
                    x2 = x1 + w*coef/100;
                    w1 = x2 - x1;
                }
                else {
                    y2 = y1 + h*coef/100;
                    h1 = y2 - y1;
                }
                dungeon.push(SubDungeon::new(x1, y1, w1, h1, deep+1, Some(i)));
                dungeon.push(SubDungeon::new(x2, y2, w-(x2-x1), h-(y2-y1), deep+1, Some(i)));
                dungeon[i].childs = Some([dungeon.len()-2, dungeon.len()-1]);
                queue.push_back(dungeon.len()-2);
                queue.push_back(dungeon.len()-1);
            }
        }
        // generation rooms
        let mut rooms = Vec::<Room>::new();
        queue.clear();
        for i in 0..dungeon.len() {
            //let has_childs = dungeon[i].childs.is_some();
            if dungeon[i].childs.is_none() {
                let parent = {
                    let d = dungeon[i];
                    // generation rooms
                    let mut room = [0,0,0,0];
                    room[2] = rng.gen_range(15*d.width/20, 18*d.width/20);
                    room[3] = rng.gen_range(15*d.height/20, 18*d.height/20);
                    room[0] = rng.gen_range(d.x + d.width/20, d.x + d.width - room[2] - d.width/20);
                    room[1] = rng.gen_range(d.y + d.height/20, d.y + d.height - room[3] - d.height/20);
                    rooms.push(Room::new(RoomType::BasicRoom, room));
                    dungeon[i].bounding_rect = Some(room.clone());
                    dungeon[i].parent.unwrap()
                };
                // push parent to generate corridor
                let childs = dungeon[parent].childs.unwrap();
                if (dungeon[childs[0]].bounding_rect.is_some()) && (dungeon[childs[1]].bounding_rect.is_some()) {
                    queue.push_back(parent);
                }
            }
        }
        // generating coridors
        while !queue.is_empty() {
            let i = queue.pop_front().unwrap();
            let p = dungeon[i];
            //println!("{:?}", p);
            let childs = p.childs.unwrap();
            let (ch1, ch2) = (dungeon[childs[0]], dungeon[childs[1]]);
            //println!("{:?}", ch1);
            //println!("{:?}", ch2);
            let (bx1, bx2) = (ch1.bounding_rect.unwrap(), ch2.bounding_rect.unwrap());
            if ch1.x == ch2.x {
                self.generate_coridor_vert(bx1, bx2, &mut rng, &mut rooms);
            }
            else {
                self.generate_coridor_hor(bx1, bx2, &mut rng, &mut rooms);
            }
            // generation bounding box for parent subdungeon
            dungeon[i].bounding_rect = {
                if rng.gen_range(0, 2) == 1 {
                    Some(bx1.clone())
                }
                else {
                    Some(bx2.clone())
                }
            };
            // if both childs have bouinding rect => add parent to queue
            if let Some(pp) = dungeon[i].parent {
                let childs = dungeon[pp].childs.unwrap();
                if (dungeon[childs[0]].bounding_rect.is_some()) && (dungeon[childs[1]].bounding_rect.is_some()) {
                    queue.push_back(pp);
                }
            }
        }
        rooms
    }
}
<commit_msg>fix room size<commit_after>use core::{DungeonGenerator, RoomType, Room, Rectangle};
use rand::{SeedableRng, StdRng, Rng};
use std::collections::VecDeque;
use std::cmp::{min, max};

/// Simple Binary Space Partioning dungeon generation algorithm:
///
///  1. Workspace splitting to random rectangles with the help of binary tree
///  2. In every rectangle generating a random room
///  3. Coridors generating with the help of the binary tree, generated at the first step
pub struct BSPGenerator {
    bs_max_deep: u32,
    deny_split_deep: u32,
    split_chance_dec: u32,
    split_max_coeff: u32,
    split_default_chance: u32,
    min_room_splittable_size: u32,
    coridor_width: u32,
}

impl Default for BSPGenerator {
    fn default() -> BSPGenerator {
        BSPGenerator {
            bs_max_deep: 5,
            deny_split_deep: 3,
            split_chance_dec: 30,
            split_max_coeff: 70,
            split_default_chance: 100,
            min_room_splittable_size: 150,
            coridor_width: 15,
        }
    }
}

impl BSPGenerator {
    /// levels of binary tree
    pub fn bs_max_deep(mut self, value: u32) -> Self {
        self.bs_max_deep = value;
        self
    }

    /// level of tree from which node can deny split
    pub fn deny_split_deep(mut self, value: u32) -> Self {
        self.deny_split_deep = value;
        self
    }

    /// split chance decreasment per tree level starting "deny_split_deep"
    pub fn split_chance_dec(mut self, value: u32) -> Self {
        self.split_chance_dec = value;
        self
    }

    /// max splitting coefficient
    pub fn split_max_coeff(mut self, value: u32) -> Self {
        self.split_max_coeff = value;
        self
    }

    /// default splitting chance
    pub fn split_default_chance(mut self, value: u32) -> Self {
        self.split_default_chance = value;
        self
    }

    /// minimum splittable size of subdungeon
    pub fn min_room_splittable_size(mut self, value: u32) -> Self {
        self.min_room_splittable_size = value;
        self
    }

    /// constant width of corridors
    pub fn coridor_width(mut self, value: u32) -> Self {
        self.coridor_width = value;
        self
    }

    fn generate_coridor_vert(&mut self, bx1: Rectangle, bx2: Rectangle, rng: &mut StdRng, rooms: &mut Vec<Room>) {
        let max_min_x = max(bx1[0], bx2[0]);
        let min_max_x = min(bx1[0]+bx1[2], bx2[0]+bx2[2])-self.coridor_width;
        let mut coridor = [0,0,self.coridor_width,0];
        coridor[1] = bx1[1] + bx1[3];
        coridor[3] = bx2[1] - bx1[1] - bx1[3];
        if max_min_x < min_max_x {
            // I like coridor
            coridor[0] = rng.gen_range(max_min_x, min_max_x);
        }
        else {
            // L like coridor
            coridor[0] = rng.gen_range(bx1[0], bx1[0]+bx1[2]);
            coridor[3] += bx2[3]/2;
            let mut h_coridor = [0,coridor[1]+coridor[3]-self.coridor_width,0,self.coridor_width];
            if max_min_x == bx1[0] {
                h_coridor[0] = min_max_x;
                h_coridor[2] = coridor[0] - h_coridor[0];
            }
            else {
                h_coridor[0] = coridor[0];
                h_coridor[2] = max_min_x - coridor[0];
            }
            rooms.push(Room::new(RoomType::Coridor, h_coridor));
        }
        rooms.push(Room::new(RoomType::Coridor, coridor));
    }

    fn generate_coridor_hor(&mut self, bx1: Rectangle, bx2: Rectangle, rng: &mut StdRng, rooms: &mut Vec<Room>) {
        let max_min_y = max(bx1[1], bx2[1]);
        let min_max_y = min(bx1[1]+bx1[3], bx2[1]+bx2[3])-self.coridor_width;
        let mut coridor = [0,0,0,self.coridor_width];
        coridor[0] = bx1[0] + bx1[2];
        coridor[2] = bx2[0] - bx1[0] - bx1[2];
        if max_min_y < min_max_y {
            // - like coridor
            coridor[1] = rng.gen_range(max_min_y, min_max_y);
        }
        else {
            // L like coridor
            coridor[1] = rng.gen_range(bx1[1], bx1[1]+bx1[3]);
            coridor[2] += bx2[2]/2;
            let mut v_coridor = [coridor[0]+coridor[2]-self.coridor_width,0,self.coridor_width,0];
            if max_min_y == bx1[1] {
                v_coridor[1] = min_max_y;
                v_coridor[3] = coridor[1] - v_coridor[1];
            }
            else {
                v_coridor[1] = coridor[1];
                v_coridor[3] = max_min_y - coridor[1];
            }
            rooms.push(Room::new(RoomType::Coridor, v_coridor));
        }
        rooms.push(Room::new(RoomType::Coridor, coridor));
    }

}

#[derive(Default, Clone, Copy, Debug)]
struct SubDungeon {
    pub x: u32,
    pub y: u32,
    pub width: u32,
    pub height: u32,
    pub deep: u32,
    pub childs: Option<[usize; 2]>,
    pub parent: Option<usize>,
    pub bounding_rect: Option<Rectangle>,
}

impl SubDungeon {
    pub fn new(x: u32, y: u32, w: u32, h: u32, deep: u32, parent: Option<usize>) -> SubDungeon {
        SubDungeon {
            x: x,
            y: y,
            width: w,
            height: h,
            deep: deep,
            childs: None,
            parent: parent,
            bounding_rect: None,
        }
    }
}

impl DungeonGenerator for BSPGenerator {
    fn generate(&mut self, seed: &[usize], width: u32, height: u32) -> Vec<Room> {
        let mut rng: StdRng = SeedableRng::from_seed(seed);
        let mut dungeon = Vec::<SubDungeon>::new();
        dungeon.push(SubDungeon::new(0, 0, width, height, 0, None));
        let mut queue = VecDeque::<usize>::new();
        queue.push_back(0);
        // generating subdungeons
        while !queue.is_empty() {
            // current index in queue
            let i = queue.pop_front().unwrap();
            // checking now deep we are
            let deep = dungeon[i].deep;
            // counting split chance
            let mut sp = self.split_default_chance;
            if deep >= self.deny_split_deep {
                if deep > self.bs_max_deep {
                    break;
                }
                let deny_split_chance = (deep - self.deny_split_deep + 1)*self.split_chance_dec;
                sp = if deny_split_chance > 100 {
                    0
                }
                else {
                    sp - deny_split_chance
                };
            }
            let w = dungeon[i].width;
            let h = dungeon[i].height;
            // will it be splited, or not?
            let b = ((w > self.min_room_splittable_size) || (h > self.min_room_splittable_size)) && (rng.gen_range(0, 100) < sp);
            if b {
                // How fair will be split
                let coef = rng.gen_range(100 - self.split_max_coeff, self.split_max_coeff);
                let x1 = dungeon[i].x;
                let y1 = dungeon[i].y;
                let mut x2 = x1;
                let mut y2 = y1;
                let mut w1 = w;
                let mut h1 = h;
                // Split vertical or not
                if (h < self.min_room_splittable_size) || ((w > self.min_room_splittable_size) && (rng.gen_range(0, 2) == 1)) {
                    x2 = x1 + w*coef/100;
                    w1 = x2 - x1;
                }
                else {
                    y2 = y1 + h*coef/100;
                    h1 = y2 - y1;
                }
                dungeon.push(SubDungeon::new(x1, y1, w1, h1, deep+1, Some(i)));
                dungeon.push(SubDungeon::new(x2, y2, w-(x2-x1), h-(y2-y1), deep+1, Some(i)));
                dungeon[i].childs = Some([dungeon.len()-2, dungeon.len()-1]);
                queue.push_back(dungeon.len()-2);
                queue.push_back(dungeon.len()-1);
            }
        }
        // generation rooms
        let mut rooms = Vec::<Room>::new();
        queue.clear();
        for i in 0..dungeon.len() {
            //let has_childs = dungeon[i].childs.is_some();
            if dungeon[i].childs.is_none() {
                let parent = {
                    let d = dungeon[i];
                    // generation rooms
                    let mut room = [0,0,0,0];
                    room[2] = rng.gen_range(10*d.width/20, 16*d.width/20);
                    room[3] = rng.gen_range(10*d.height/20, 16*d.height/20);
                    room[0] = rng.gen_range(d.x + d.width/20, d.x + d.width - room[2] - d.width/20);
                    room[1] = rng.gen_range(d.y + d.height/20, d.y + d.height - room[3] - d.height/20);
                    rooms.push(Room::new(RoomType::BasicRoom, room));
                    dungeon[i].bounding_rect = Some(room.clone());
                    dungeon[i].parent.unwrap()
                };
                // push parent to generate corridor
                let childs = dungeon[parent].childs.unwrap();
                if (dungeon[childs[0]].bounding_rect.is_some()) && (dungeon[childs[1]].bounding_rect.is_some()) {
                    queue.push_back(parent);
                }
            }
        }
        // generating coridors
        while !queue.is_empty() {
            let i = queue.pop_front().unwrap();
            let p = dungeon[i];
            //println!("{:?}", p);
            let childs = p.childs.unwrap();
            let (ch1, ch2) = (dungeon[childs[0]], dungeon[childs[1]]);
            //println!("{:?}", ch1);
            //println!("{:?}", ch2);
            let (bx1, bx2) = (ch1.bounding_rect.unwrap(), ch2.bounding_rect.unwrap());
            if ch1.x == ch2.x {
                self.generate_coridor_vert(bx1, bx2, &mut rng, &mut rooms);
            }
            else {
                self.generate_coridor_hor(bx1, bx2, &mut rng, &mut rooms);
            }
            // generation bounding box for parent subdungeon
            dungeon[i].bounding_rect = {
                if rng.gen_range(0, 2) == 1 {
                    Some(bx1.clone())
                }
                else {
                    Some(bx2.clone())
                }
            };
            // if both childs have bouinding rect => add parent to queue
            if let Some(pp) = dungeon[i].parent {
                let childs = dungeon[pp].childs.unwrap();
                if (dungeon[childs[0]].bounding_rect.is_some()) && (dungeon[childs[1]].bounding_rect.is_some()) {
                    queue.push_back(pp);
                }
            }
        }
        rooms
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 FaultyRAM
//
// 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.

//! Types for safely allocating memory.

#![cfg_attr(feature = "clippy", allow(inline_always))]

use core::{fmt, intrinsics, isize};
use core::ptr::Unique;
use super::error::Error;
use super::result::Result;

extern "C" {
    #[allocator]
    fn __rust_allocate(len: usize, align: usize) -> *mut u8;
    fn __rust_allocate_zeroed(len: usize, align: usize) -> *mut u8;
    fn __rust_deallocate(ptr: *mut u8, old_len: usize, align: usize);
    fn __rust_reallocate(ptr: *mut u8, old_len: usize, len: usize, align: usize) -> *mut u8;
    fn __rust_reallocate_inplace(ptr: *mut u8, old_len: usize, len: usize, align: usize) -> usize;
}

#[cfg_attr(feature = "clippy", allow(cast_sign_loss))]
#[inline(always)]
/// Performs sanity checks on the length of a requested memory allocation.
fn check_len(len: usize) -> Result<()> {
    if len == 0 {
        Err(Error::ZeroLength)
    } else if len > isize::MAX as usize {
        Err(Error::NotEnoughMemory)
    } else {
        Ok(())
    }
}

#[inline(always)]
/// Performs sanity checks on the length and alignment of a requested memory allocation.
fn check_len_and_align(len: usize, align: usize) -> Result<()> {
    check_len(len).and_then(
        |_| if usize::is_power_of_two(align) {
            Ok(())
        } else {
            Err(Error::BadAlignment)
        }
    )
}

#[allow(missing_copy_implementations)]
/// An owned, allocated block of memory.
pub struct Allocation {
    /// A raw pointer to the allocated block of memory.
    ptr: Unique<u8>,
    /// The length in bytes of the allocation.
    len: usize,
    /// The alignment in bytes of the allocation.
    align: usize,
}

#[cfg_attr(feature = "clippy", allow(len_without_is_empty))]
impl Allocation {
    #[inline]
    /// Allocates a block of memory using the specified length and alignment.
    pub fn new(len: usize, align: usize) -> Result<Allocation> {
        check_len_and_align(len, align).and_then(
            |_| {
                let ptr = unsafe { __rust_allocate(len, align) };
                if ptr.is_null() {
                    Err(Error::NotEnoughMemory)
                } else {
                    Ok(
                        Allocation {
                            ptr: unsafe { Unique::new(ptr) },
                            len: len,
                            align: align,
                        }
                    )
                }
            }
        )
    }

    #[inline]
    /// Allocates a block of memory with all bytes initialized to zero, using the specified length
    /// and alignment.
    pub fn zeroed(len: usize, align: usize) -> Result<Allocation> {
        check_len_and_align(len, align).and_then(
            |_| {
                let ptr = unsafe { __rust_allocate_zeroed(len, align) };
                if ptr.is_null() {
                    Err(Error::NotEnoughMemory)
                } else {
                    Ok(
                        Allocation {
                            ptr: unsafe { Unique::new(ptr) },
                            len: len,
                            align: align,
                        }
                    )
                }
            }
        )
    }

    #[inline]
    /// Resizes an existing allocation.
    ///
    /// On failure, returns an error without modifying the existing allocation.
    pub fn resize(&mut self, new_len: usize) -> Result<()> {
        check_len(new_len).and_then(
            |_| {
                let ptr =
                    unsafe { __rust_reallocate(self.as_mut_ptr(), self.len, new_len, self.align) };
                if ptr.is_null() {
                    Err(Error::NotEnoughMemory)
                } else {
                    self.ptr = unsafe { Unique::new(ptr) };
                    self.len = new_len;
                    Ok(())
                }
            }
        )
    }

    #[inline]
    /// Resizes an existing allocation without moving it.
    ///
    /// On failure, returns an error without modifying the existing allocation.
    pub fn resize_in_place(&mut self, new_len: usize) -> Result<()> {
        check_len(new_len).and_then(
            |_| {
                self.len = unsafe {
                    __rust_reallocate_inplace(self.as_mut_ptr(), self.len, new_len, self.align)
                };
                Ok(())
            }
        )
    }

    /// Creates a new memory allocation with the same length, alignment and contents as an
    /// existing allocation.
    pub fn duplicate(&self) -> Result<Allocation> {
        Allocation::new(self.len, self.align).map(
            |mut new_alloc| {
                unsafe {
                    intrinsics::copy_nonoverlapping(
                        self.as_ptr(),
                        new_alloc.as_mut_ptr(),
                        self.len,
                    );
                }
                new_alloc
            }
        )
    }

    /// Returns a raw pointer to the allocated block of memory.
    pub fn as_ptr(&self) -> *const u8 {
        unsafe { &*self.ptr.as_ptr() }
    }

    /// Returns a mutable raw pointer to the allocated block of memory.
    pub fn as_mut_ptr(&mut self) -> *mut u8 {
        self.ptr.as_ptr()
    }

    /// Returns the length in bytes of the allocated block of memory.
    pub fn len(&self) -> usize {
        self.len
    }

    /// Returns the alignment in bytes of the allocated block of memory.
    pub fn align(&self) -> usize {
        self.align
    }
}

impl Drop for Allocation {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            __rust_deallocate(self.as_mut_ptr(), self.len, self.align);
        }
    }
}

impl fmt::Debug for Allocation {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Allocation")
            .field("ptr", &self.ptr.as_ptr())
            .field("len", &self.len)
            .field("align", &self.align)
            .finish()
    }
}
<commit_msg>Convert allocations from/into raw values<commit_after>// Copyright (c) 2017 FaultyRAM
//
// 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.

//! Types for safely allocating memory.

#![cfg_attr(feature = "clippy", allow(inline_always))]

use core::{fmt, intrinsics, isize, mem};
use core::ptr::Unique;
use super::error::Error;
use super::result::Result;

extern "C" {
    #[allocator]
    fn __rust_allocate(len: usize, align: usize) -> *mut u8;
    fn __rust_allocate_zeroed(len: usize, align: usize) -> *mut u8;
    fn __rust_deallocate(ptr: *mut u8, old_len: usize, align: usize);
    fn __rust_reallocate(ptr: *mut u8, old_len: usize, len: usize, align: usize) -> *mut u8;
    fn __rust_reallocate_inplace(ptr: *mut u8, old_len: usize, len: usize, align: usize) -> usize;
}

#[cfg_attr(feature = "clippy", allow(cast_sign_loss))]
#[inline(always)]
/// Performs sanity checks on the length of a requested memory allocation.
fn check_len(len: usize) -> Result<()> {
    if len == 0 {
        Err(Error::ZeroLength)
    } else if len > isize::MAX as usize {
        Err(Error::NotEnoughMemory)
    } else {
        Ok(())
    }
}

#[inline(always)]
/// Performs sanity checks on the length and alignment of a requested memory allocation.
fn check_len_and_align(len: usize, align: usize) -> Result<()> {
    check_len(len).and_then(
        |_| if usize::is_power_of_two(align) {
            Ok(())
        } else {
            Err(Error::BadAlignment)
        }
    )
}

#[allow(missing_copy_implementations)]
/// An owned, allocated block of memory.
pub struct Allocation {
    /// A raw pointer to the allocated block of memory.
    ptr: Unique<u8>,
    /// The length in bytes of the allocation.
    len: usize,
    /// The alignment in bytes of the allocation.
    align: usize,
}

#[cfg_attr(feature = "clippy", allow(len_without_is_empty))]
impl Allocation {
    #[inline]
    /// Allocates a block of memory using the specified length and alignment.
    pub fn new(len: usize, align: usize) -> Result<Allocation> {
        check_len_and_align(len, align).and_then(
            |_| {
                let ptr = unsafe { __rust_allocate(len, align) };
                if ptr.is_null() {
                    Err(Error::NotEnoughMemory)
                } else {
                    Ok(
                        Allocation {
                            ptr: unsafe { Unique::new(ptr) },
                            len: len,
                            align: align,
                        }
                    )
                }
            }
        )
    }

    #[inline]
    /// Allocates a block of memory with all bytes initialized to zero, using the specified length
    /// and alignment.
    pub fn zeroed(len: usize, align: usize) -> Result<Allocation> {
        check_len_and_align(len, align).and_then(
            |_| {
                let ptr = unsafe { __rust_allocate_zeroed(len, align) };
                if ptr.is_null() {
                    Err(Error::NotEnoughMemory)
                } else {
                    Ok(
                        Allocation {
                            ptr: unsafe { Unique::new(ptr) },
                            len: len,
                            align: align,
                        }
                    )
                }
            }
        )
    }

    #[inline]
    /// Takes ownership of a raw pointer, length and alignment, and treats the three as an
    /// existing allocation.
    ///
    /// This is unsafe because it assumes that the pointer refers to memory allocated via the Rust
    /// allocation model using the given length and alignment. Undefined behavior will occur if
    /// these assumptions do not hold true.
    pub unsafe fn from_raw(ptr: *mut u8, len: usize, align: usize) -> Allocation {
        Allocation {
            ptr: Unique::new(ptr),
            len: len,
            align: align,
        }
    }

    #[cfg_attr(feature = "clippy", allow(mem_forget))]
    #[inline]
    /// Consumes an allocation without freeing associated memory, returning its pointer, length
    /// and alignment.
    ///
    /// Care must be taken to ensure that the memory is correctly freed after calling this method.
    /// This can be done by reconstructing the allocation via `Allocation::from_raw` and dropping
    /// it immediately afterwards.
    pub fn into_raw(self) -> (*mut u8, usize, usize) {
        let ret = (self.ptr.as_ptr(), self.len, self.align);
        mem::forget(self);
        ret
    }

    #[inline]
    /// Resizes an existing allocation.
    ///
    /// On failure, returns an error without modifying the existing allocation.
    pub fn resize(&mut self, new_len: usize) -> Result<()> {
        check_len(new_len).and_then(
            |_| {
                let ptr =
                    unsafe { __rust_reallocate(self.as_mut_ptr(), self.len, new_len, self.align) };
                if ptr.is_null() {
                    Err(Error::NotEnoughMemory)
                } else {
                    self.ptr = unsafe { Unique::new(ptr) };
                    self.len = new_len;
                    Ok(())
                }
            }
        )
    }

    #[inline]
    /// Resizes an existing allocation without moving it.
    ///
    /// On failure, returns an error without modifying the existing allocation.
    pub fn resize_in_place(&mut self, new_len: usize) -> Result<()> {
        check_len(new_len).and_then(
            |_| {
                self.len = unsafe {
                    __rust_reallocate_inplace(self.as_mut_ptr(), self.len, new_len, self.align)
                };
                Ok(())
            }
        )
    }

    /// Creates a new memory allocation with the same length, alignment and contents as an
    /// existing allocation.
    pub fn duplicate(&self) -> Result<Allocation> {
        Allocation::new(self.len, self.align).map(
            |mut new_alloc| {
                unsafe {
                    intrinsics::copy_nonoverlapping(
                        self.as_ptr(),
                        new_alloc.as_mut_ptr(),
                        self.len,
                    );
                }
                new_alloc
            }
        )
    }

    /// Returns a raw pointer to the allocated block of memory.
    pub fn as_ptr(&self) -> *const u8 {
        unsafe { &*self.ptr.as_ptr() }
    }

    /// Returns a mutable raw pointer to the allocated block of memory.
    pub fn as_mut_ptr(&mut self) -> *mut u8 {
        self.ptr.as_ptr()
    }

    /// Returns the length in bytes of the allocated block of memory.
    pub fn len(&self) -> usize {
        self.len
    }

    /// Returns the alignment in bytes of the allocated block of memory.
    pub fn align(&self) -> usize {
        self.align
    }
}

impl Drop for Allocation {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            __rust_deallocate(self.as_mut_ptr(), self.len, self.align);
        }
    }
}

impl fmt::Debug for Allocation {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Allocation")
            .field("ptr", &self.ptr.as_ptr())
            .field("len", &self.len)
            .field("align", &self.align)
            .finish()
    }
}
<|endoftext|>


<commit_before>use std::result::Result as RResult;

use serde::Serialize;
use serde::Serializer;
use serde::Deserialize;
use serde::Deserializer;
use serde::de::Visitor;
use serde::de::Error as SerdeError;
use serde::ser::MapVisitor;
use serde::de::MapVisitor as DeserializeMapVisitor;

use date::Date;

#[derive(Clone, Debug)]
pub struct Annotation {
    entry: Date,
    description: String
}

impl Annotation {

    pub fn new(entry: Date, description: String) -> Annotation {
        Annotation {
            entry: entry,
            description: description,
        }
    }

    pub fn entry(&self) -> &Date {
        &self.entry
    }

    pub fn description(&self) -> &String {
        &self.description
    }

}

impl Serialize for Annotation {

    fn serialize<S>(&self, serializer: &mut S) -> RResult<(), S::Error>
        where S: Serializer
    {
        serializer.serialize_struct("Annotation", AnnotationVisitor {
            value: self,
            state: 0,
        })
    }

}

struct AnnotationVisitor<'a> {
    value: &'a Annotation,
    state: u8,
}

impl<'a> MapVisitor for AnnotationVisitor<'a> {

    fn visit<S>(&mut self, serializer: &mut S) -> RResult<Option<()>, S::Error>
        where S: Serializer
    {
        match self.state {
            0 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("entry", &self.value.entry))))
            },
            1 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("description", &self.value.description))))
            },
            _ => {
                Ok(None)
            }
        }
    }

}

impl Deserialize for Annotation {

    fn deserialize<D>(deserializer: &mut D) -> RResult<Annotation, D::Error>
        where D: Deserializer
    {
        static FIELDS: &'static [&'static str] = &[
            "entry",
            "description"
        ];

        deserializer.deserialize_struct("Annotation", FIELDS, AnnotationDeserializeVisitor)
    }

}

struct AnnotationDeserializeVisitor;

impl Visitor for AnnotationDeserializeVisitor {
    type Value = Annotation;

    fn visit_map<V>(&mut self, mut visitor: V) -> RResult<Annotation, V::Error>
        where V: DeserializeMapVisitor
    {
        let mut entry       = None;
        let mut description = None;

        loop {
            let key : Option<String> = try!(visitor.visit_key());
            if key.is_none() {
                break;
            }
            let key = key.unwrap();

            match &key[..] {
                "entry" => {
                    entry = Some(try!(visitor.visit_value()));
                },
                "description" => {
                    description = Some(try!(visitor.visit_value()));
                },

                field => {
                    use serde::de::impls::IgnoredAny;

                    debug!("field '{}' ignored", field);
                    let _: IgnoredAny = try!(visitor.visit_value());
                }
            }
        }

        let entry = match entry {
            Some(entry) => entry,
            None => try!(visitor.missing_field("entry")),
        };

        let description = match description {
            Some(description) => description,
            None => try!(visitor.missing_field("description")),
        };

        try!(visitor.end());

        Ok(Annotation::new(entry, description))
    }
}

#[cfg(test)]
mod test {
}
<commit_msg>Add documentation for Annotation type<commit_after>use std::result::Result as RResult;

use serde::Serialize;
use serde::Serializer;
use serde::Deserialize;
use serde::Deserializer;
use serde::de::Visitor;
use serde::de::Error as SerdeError;
use serde::ser::MapVisitor;
use serde::de::MapVisitor as DeserializeMapVisitor;

use date::Date;

/// Annotation type for task annotations.
/// Each annotation in taskwarrior consists of a date and a description,
/// the date is named "entry", the description "description" in the JSON export.
#[derive(Clone, Debug)]
pub struct Annotation {
    entry: Date,
    description: String
}

impl Annotation {

    /// Create a new Annotation object
    pub fn new(entry: Date, description: String) -> Annotation {
        Annotation {
            entry: entry,
            description: description,
        }
    }

    /// Get the entry date
    pub fn entry(&self) -> &Date {
        &self.entry
    }

    /// Get the description text
    pub fn description(&self) -> &String {
        &self.description
    }

}

impl Serialize for Annotation {

    fn serialize<S>(&self, serializer: &mut S) -> RResult<(), S::Error>
        where S: Serializer
    {
        serializer.serialize_struct("Annotation", AnnotationVisitor {
            value: self,
            state: 0,
        })
    }

}

/// Helper type for the `Serialize` implementation
struct AnnotationVisitor<'a> {
    value: &'a Annotation,
    state: u8,
}

impl<'a> MapVisitor for AnnotationVisitor<'a> {

    fn visit<S>(&mut self, serializer: &mut S) -> RResult<Option<()>, S::Error>
        where S: Serializer
    {
        match self.state {
            0 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("entry", &self.value.entry))))
            },
            1 => {
                self.state += 1;
                Ok(Some(try!(serializer.serialize_struct_elt("description", &self.value.description))))
            },
            _ => {
                Ok(None)
            }
        }
    }

}

impl Deserialize for Annotation {

    fn deserialize<D>(deserializer: &mut D) -> RResult<Annotation, D::Error>
        where D: Deserializer
    {
        static FIELDS: &'static [&'static str] = &[
            "entry",
            "description"
        ];

        deserializer.deserialize_struct("Annotation", FIELDS, AnnotationDeserializeVisitor)
    }

}

/// Helper type for the `Deserialize` implementation
struct AnnotationDeserializeVisitor;

impl Visitor for AnnotationDeserializeVisitor {
    type Value = Annotation;

    fn visit_map<V>(&mut self, mut visitor: V) -> RResult<Annotation, V::Error>
        where V: DeserializeMapVisitor
    {
        let mut entry       = None;
        let mut description = None;

        loop {
            let key : Option<String> = try!(visitor.visit_key());
            if key.is_none() {
                break;
            }
            let key = key.unwrap();

            match &key[..] {
                "entry" => {
                    entry = Some(try!(visitor.visit_value()));
                },
                "description" => {
                    description = Some(try!(visitor.visit_value()));
                },

                field => {
                    use serde::de::impls::IgnoredAny;

                    debug!("field '{}' ignored", field);
                    let _: IgnoredAny = try!(visitor.visit_value());
                }
            }
        }

        let entry = match entry {
            Some(entry) => entry,
            None => try!(visitor.missing_field("entry")),
        };

        let description = match description {
            Some(description) => description,
            None => try!(visitor.missing_field("description")),
        };

        try!(visitor.end());

        Ok(Annotation::new(entry, description))
    }
}

#[cfg(test)]
mod test {
}
<|endoftext|>


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

use std::fmt::Debug;
use std::os::unix::io::RawFd;
use std::path::{Path, PathBuf};

use chrono::{DateTime, Utc};
use uuid::Uuid;

use devicemapper::{Device, Sectors};

use super::errors::EngineResult;
use super::types::{BlockDevState, DevUuid, FilesystemUuid, Name, PoolUuid, RenameAction};

pub trait Filesystem: Debug {
    /// path of the device node
    fn devnode(&self) -> PathBuf;
}

pub trait BlockDev: Debug {
    /// Get the path of the device node for this device.
    fn devnode(&self) -> PathBuf;

    /// Get the user-settable string associated with this blockdev.
    fn user_info(&self) -> Option<&str>;

    /// Set the user-settable string associated with this blockdev.
    fn set_user_info(&mut self, user_info: Option<&str>) -> bool;

    /// Get the hardware ID for this blockdev.
    fn hardware_info(&self) -> Option<&str>;

    /// The time that this blockdev was initialized by Stratis, rounded down
    /// to the nearest second.
    fn initialization_time(&self) -> DateTime<Utc>;

    /// The usable size of the device, not counting Stratis overhead.
    fn total_size(&self) -> Sectors;

    /// The current state of the blockdev.
    fn state(&self) -> BlockDevState;
}

pub trait Pool: Debug {
    /// Creates the filesystems specified by specs.
    /// Returns a list of the names of filesystems actually created.
    /// Returns an error if any of the specified names are already in use
    /// for filesystems in this pool. If the same name is passed multiple
    /// times, the size associated with the last item is used.
    fn create_filesystems<'a, 'b>(&'a mut self,
                                  pool_name: &str,
                                  specs: &[(&'b str, Option<Sectors>)])
                                  -> EngineResult<Vec<(&'b str, FilesystemUuid)>>;

    /// Adds blockdevs specified by paths to pool.
    /// Returns a list of uuids corresponding to devices actually added.
    /// Returns an error if a blockdev can not be added because it is owned
    /// or there was an error while reading or writing a blockdev.
    fn add_blockdevs(&mut self,
                     pool_name: &str,
                     paths: &[&Path],
                     force: bool)
                     -> EngineResult<Vec<DevUuid>>;

    /// Destroy the pool.
    /// Precondition: All filesystems belonging to this pool must be
    /// unmounted.
    fn destroy(self) -> EngineResult<()>;

    /// Ensures that all designated filesystems are gone from pool.
    /// Returns a list of the filesystems found, and actually destroyed.
    /// This list will be a subset of the uuids passed in fs_uuids.
    /// Precondition: All filesystems given must be unmounted.
    fn destroy_filesystems<'a>(&'a mut self,
                               pool_name: &str,
                               fs_uuids: &[FilesystemUuid])
                               -> EngineResult<Vec<FilesystemUuid>>;

    /// Rename filesystem
    /// Rename pool with uuid to new_name.
    /// Raises an error if the mapping can't be applied because
    /// new_name is already in use.
    /// The result indicate whether an action was performed, and if not, why.
    fn rename_filesystem(&mut self,
                         pool_name: &str,
                         uuid: FilesystemUuid,
                         new_name: &str)
                         -> EngineResult<RenameAction>;

    /// Snapshot filesystem
    /// Create a CoW snapshot of the origin
    fn snapshot_filesystem(&mut self,
                           pool_name: &str,
                           origin_uuid: FilesystemUuid,
                           snapshot_name: &str)
                           -> EngineResult<FilesystemUuid>;

    /// The total number of Sectors belonging to this pool.
    /// There are no exclusions, so this number includes overhead sectors
    /// of all sorts, sectors allocated for every sort of metadata by
    /// Stratis or devicemapper and therefore not available to the user for
    /// storing their data. There is no larger physical size number that can be
    /// associated with a pool.
    fn total_physical_size(&self) -> Sectors;

    /// The number of Sectors in this pool that are currently in use by the
    /// pool for some purpose, be it to store metadata, to store user data,
    /// or to reserve for some other purpose.
    fn total_physical_used(&self) -> EngineResult<Sectors>;

    /// Get all the filesystems belonging to this pool.
    fn filesystems(&self) -> Vec<(Name, FilesystemUuid, &Filesystem)>;

    /// Get the filesystem in this pool with this UUID.
    fn get_filesystem(&self, uuid: FilesystemUuid) -> Option<(Name, &Filesystem)>;

    /// Get the mutable filesystem in this pool with this UUID.
    fn get_mut_filesystem(&mut self, uuid: FilesystemUuid) -> Option<(Name, &mut Filesystem)>;

    /// Get all the blockdevs that make up this pool.
    fn blockdevs(&self) -> Vec<(Uuid, &BlockDev)>;

    /// Get the blockdev in this pool with this UUID.
    fn get_blockdev(&self, uuid: DevUuid) -> Option<&BlockDev>;

    /// Get the mutable filesystem in this pool with this UUID.
    fn get_mut_blockdev(&mut self, uuid: DevUuid) -> Option<&mut BlockDev>;

    /// Save the state of the pool. FIXME, see #614.
    fn save_state(&mut self, pool_name: &str) -> EngineResult<()>;
}

pub trait Engine: Debug {
    /// Create a Stratis pool.
    /// Returns the UUID of the newly created pool.
    /// Returns an error if the redundancy code does not correspond to a
    /// supported redundancy.
    fn create_pool(&mut self,
                   name: &str,
                   blockdev_paths: &[&Path],
                   redundancy: Option<u16>,
                   force: bool)
                   -> EngineResult<PoolUuid>;

    /// Evaluate a device node & devicemapper::Device to see if it's a valid
    /// stratis device.  If all the devices are present in the pool and the pool isn't already
    /// up and running, it will get setup and the pool uuid will be returned.
    fn block_evaluate(&mut self,
                      dev_node: PathBuf,
                      device: Device)
                      -> EngineResult<Option<PoolUuid>>;

    /// Destroy a pool.
    /// Ensures that the pool of the given UUID is absent on completion.
    /// Returns true if some action was necessary, otherwise false.
    fn destroy_pool(&mut self, uuid: PoolUuid) -> EngineResult<bool>;

    /// Rename pool with uuid to new_name.
    /// Raises an error if the mapping can't be applied because
    /// new_name is already in use.
    /// Returns true if it was necessary to perform an action, false if not.
    fn rename_pool(&mut self, uuid: PoolUuid, new_name: &str) -> EngineResult<RenameAction>;

    /// Find the pool designated by uuid.
    fn get_pool(&self, uuid: PoolUuid) -> Option<(Name, &Pool)>;

    /// Get a mutable referent to the pool designated by uuid.
    fn get_mut_pool(&mut self, uuid: PoolUuid) -> Option<(Name, &mut Pool)>;

    /// Configure the simulator, for the real engine, this is a null op.
    /// denominator: the probably of failure is 1/denominator.
    fn configure_simulator(&mut self, denominator: u32) -> EngineResult<()>;

    /// Check pools' current state and take appropriate actions
    fn check(&mut self) -> ();

    /// Get all pools belonging to this engine.
    fn pools(&self) -> Vec<(Name, PoolUuid, &Pool)>;

    /// If the engine would like to include an event in the message loop, it
    /// may return an Eventable from this method.
    fn get_eventable(&mut self) -> EngineResult<Option<Box<Eventable>>>;

    /// Notify the engine that an event has occurred on the Eventable.
    fn evented(&mut self) -> EngineResult<()>;
}

/// Allows an Engine to include a fd in the event loop. See
/// Engine::get_eventable() and Engine::evented().
pub trait Eventable {
    /// Get fd the engine would like to monitor for activity
    fn get_pollable_fd(&mut self) -> RawFd;

    /// Assuming level-triggered semantics, clear the event that caused the
    /// Eventable to trigger.
    fn clear_event(&mut self) -> EngineResult<()>;
}
<commit_msg>Add a clarifying comment to Pool::blockdevs<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::fmt::Debug;
use std::os::unix::io::RawFd;
use std::path::{Path, PathBuf};

use chrono::{DateTime, Utc};
use uuid::Uuid;

use devicemapper::{Device, Sectors};

use super::errors::EngineResult;
use super::types::{BlockDevState, DevUuid, FilesystemUuid, Name, PoolUuid, RenameAction};

pub trait Filesystem: Debug {
    /// path of the device node
    fn devnode(&self) -> PathBuf;
}

pub trait BlockDev: Debug {
    /// Get the path of the device node for this device.
    fn devnode(&self) -> PathBuf;

    /// Get the user-settable string associated with this blockdev.
    fn user_info(&self) -> Option<&str>;

    /// Set the user-settable string associated with this blockdev.
    fn set_user_info(&mut self, user_info: Option<&str>) -> bool;

    /// Get the hardware ID for this blockdev.
    fn hardware_info(&self) -> Option<&str>;

    /// The time that this blockdev was initialized by Stratis, rounded down
    /// to the nearest second.
    fn initialization_time(&self) -> DateTime<Utc>;

    /// The usable size of the device, not counting Stratis overhead.
    fn total_size(&self) -> Sectors;

    /// The current state of the blockdev.
    fn state(&self) -> BlockDevState;
}

pub trait Pool: Debug {
    /// Creates the filesystems specified by specs.
    /// Returns a list of the names of filesystems actually created.
    /// Returns an error if any of the specified names are already in use
    /// for filesystems in this pool. If the same name is passed multiple
    /// times, the size associated with the last item is used.
    fn create_filesystems<'a, 'b>(&'a mut self,
                                  pool_name: &str,
                                  specs: &[(&'b str, Option<Sectors>)])
                                  -> EngineResult<Vec<(&'b str, FilesystemUuid)>>;

    /// Adds blockdevs specified by paths to pool.
    /// Returns a list of uuids corresponding to devices actually added.
    /// Returns an error if a blockdev can not be added because it is owned
    /// or there was an error while reading or writing a blockdev.
    fn add_blockdevs(&mut self,
                     pool_name: &str,
                     paths: &[&Path],
                     force: bool)
                     -> EngineResult<Vec<DevUuid>>;

    /// Destroy the pool.
    /// Precondition: All filesystems belonging to this pool must be
    /// unmounted.
    fn destroy(self) -> EngineResult<()>;

    /// Ensures that all designated filesystems are gone from pool.
    /// Returns a list of the filesystems found, and actually destroyed.
    /// This list will be a subset of the uuids passed in fs_uuids.
    /// Precondition: All filesystems given must be unmounted.
    fn destroy_filesystems<'a>(&'a mut self,
                               pool_name: &str,
                               fs_uuids: &[FilesystemUuid])
                               -> EngineResult<Vec<FilesystemUuid>>;

    /// Rename filesystem
    /// Rename pool with uuid to new_name.
    /// Raises an error if the mapping can't be applied because
    /// new_name is already in use.
    /// The result indicate whether an action was performed, and if not, why.
    fn rename_filesystem(&mut self,
                         pool_name: &str,
                         uuid: FilesystemUuid,
                         new_name: &str)
                         -> EngineResult<RenameAction>;

    /// Snapshot filesystem
    /// Create a CoW snapshot of the origin
    fn snapshot_filesystem(&mut self,
                           pool_name: &str,
                           origin_uuid: FilesystemUuid,
                           snapshot_name: &str)
                           -> EngineResult<FilesystemUuid>;

    /// The total number of Sectors belonging to this pool.
    /// There are no exclusions, so this number includes overhead sectors
    /// of all sorts, sectors allocated for every sort of metadata by
    /// Stratis or devicemapper and therefore not available to the user for
    /// storing their data. There is no larger physical size number that can be
    /// associated with a pool.
    fn total_physical_size(&self) -> Sectors;

    /// The number of Sectors in this pool that are currently in use by the
    /// pool for some purpose, be it to store metadata, to store user data,
    /// or to reserve for some other purpose.
    fn total_physical_used(&self) -> EngineResult<Sectors>;

    /// Get all the filesystems belonging to this pool.
    fn filesystems(&self) -> Vec<(Name, FilesystemUuid, &Filesystem)>;

    /// Get the filesystem in this pool with this UUID.
    fn get_filesystem(&self, uuid: FilesystemUuid) -> Option<(Name, &Filesystem)>;

    /// Get the mutable filesystem in this pool with this UUID.
    fn get_mut_filesystem(&mut self, uuid: FilesystemUuid) -> Option<(Name, &mut Filesystem)>;

    /// Get _all_ the blockdevs that belong to this pool.
    /// All really means all. For example, it does not exclude cache blockdevs.
    fn blockdevs(&self) -> Vec<(Uuid, &BlockDev)>;

    /// Get the blockdev in this pool with this UUID.
    fn get_blockdev(&self, uuid: DevUuid) -> Option<&BlockDev>;

    /// Get the mutable filesystem in this pool with this UUID.
    fn get_mut_blockdev(&mut self, uuid: DevUuid) -> Option<&mut BlockDev>;

    /// Save the state of the pool. FIXME, see #614.
    fn save_state(&mut self, pool_name: &str) -> EngineResult<()>;
}

pub trait Engine: Debug {
    /// Create a Stratis pool.
    /// Returns the UUID of the newly created pool.
    /// Returns an error if the redundancy code does not correspond to a
    /// supported redundancy.
    fn create_pool(&mut self,
                   name: &str,
                   blockdev_paths: &[&Path],
                   redundancy: Option<u16>,
                   force: bool)
                   -> EngineResult<PoolUuid>;

    /// Evaluate a device node & devicemapper::Device to see if it's a valid
    /// stratis device.  If all the devices are present in the pool and the pool isn't already
    /// up and running, it will get setup and the pool uuid will be returned.
    fn block_evaluate(&mut self,
                      dev_node: PathBuf,
                      device: Device)
                      -> EngineResult<Option<PoolUuid>>;

    /// Destroy a pool.
    /// Ensures that the pool of the given UUID is absent on completion.
    /// Returns true if some action was necessary, otherwise false.
    fn destroy_pool(&mut self, uuid: PoolUuid) -> EngineResult<bool>;

    /// Rename pool with uuid to new_name.
    /// Raises an error if the mapping can't be applied because
    /// new_name is already in use.
    /// Returns true if it was necessary to perform an action, false if not.
    fn rename_pool(&mut self, uuid: PoolUuid, new_name: &str) -> EngineResult<RenameAction>;

    /// Find the pool designated by uuid.
    fn get_pool(&self, uuid: PoolUuid) -> Option<(Name, &Pool)>;

    /// Get a mutable referent to the pool designated by uuid.
    fn get_mut_pool(&mut self, uuid: PoolUuid) -> Option<(Name, &mut Pool)>;

    /// Configure the simulator, for the real engine, this is a null op.
    /// denominator: the probably of failure is 1/denominator.
    fn configure_simulator(&mut self, denominator: u32) -> EngineResult<()>;

    /// Check pools' current state and take appropriate actions
    fn check(&mut self) -> ();

    /// Get all pools belonging to this engine.
    fn pools(&self) -> Vec<(Name, PoolUuid, &Pool)>;

    /// If the engine would like to include an event in the message loop, it
    /// may return an Eventable from this method.
    fn get_eventable(&mut self) -> EngineResult<Option<Box<Eventable>>>;

    /// Notify the engine that an event has occurred on the Eventable.
    fn evented(&mut self) -> EngineResult<()>;
}

/// Allows an Engine to include a fd in the event loop. See
/// Engine::get_eventable() and Engine::evented().
pub trait Eventable {
    /// Get fd the engine would like to monitor for activity
    fn get_pollable_fd(&mut self) -> RawFd;

    /// Assuming level-triggered semantics, clear the event that caused the
    /// Eventable to trigger.
    fn clear_event(&mut self) -> EngineResult<()>;
}
<|endoftext|>


<commit_before>#![allow(non_camel_case_types)]
#![allow(dead_code)]
#![allow(missing_copy_implementations)]

use libc::types::os::arch::c95::c_uint;

use cass_result::CassResult;
use cass_value::CassValue;
use cass_row::CassRow;
use cass_schema::CassSchemaMeta;
use cass_schema::CassSchema;
use cass_schema::CassSchemaMetaField;

use cass_types::cass_bool_t;

pub enum CassIterator { }

pub enum CassIteratorType {
    RESULT = 0,
    ROW = 1,
    COLLECTION = 2,
    MAP = 3,
    SCHEMA_META = 4,
    SCHEMA_META_FIELD = 5
}

extern "C" {
    pub fn cass_iterator_free(iterator: *mut CassIterator);
    pub fn cass_iterator_type(iterator: *mut CassIterator) -> CassIteratorType;
    pub fn cass_iterator_from_result(result: *const CassResult) -> *mut CassIterator;
    pub fn cass_iterator_from_row(row: *const CassRow) -> *mut CassIterator;
    pub fn cass_iterator_from_collection(value: *const CassValue) -> *mut CassIterator;
    pub fn cass_iterator_from_map(value: *const CassValue) -> *mut CassIterator;
    pub fn cass_iterator_from_schema(schema: *const CassSchema) -> *mut CassIterator;
    pub fn cass_iterator_from_schema_meta(meta: *const CassSchemaMeta) -> *mut CassIterator;
    pub fn cass_iterator_fields_from_schema_meta(meta: *const CassSchemaMeta) -> *mut CassIterator;
    pub fn cass_iterator_next(iterator: *mut CassIterator) -> cass_bool_t;
    pub fn cass_iterator_get_row(iterator: *mut CassIterator) -> *const CassRow;
    pub fn cass_iterator_get_column(iterator: *mut CassIterator) -> *const CassValue;
    pub fn cass_iterator_get_value(iterator: *mut CassIterator)-> *const CassValue;
    pub fn cass_iterator_get_map_key(iterator: *mut CassIterator) -> *const CassValue;
    pub fn cass_iterator_get_map_value(iterator: *mut CassIterator) -> *const CassValue;
    pub fn cass_iterator_get_schema_meta(iterator: *mut CassIterator) -> *const CassSchemaMeta;
    pub fn cass_iterator_get_schema_meta_field(iterator: *mut CassIterator) -> *const CassSchemaMetaField;
}
<commit_msg>deriving show on iteratortype<commit_after>#![allow(non_camel_case_types)]
#![allow(dead_code)]
#![allow(missing_copy_implementations)]

use libc::types::os::arch::c95::c_uint;

use cass_result::CassResult;
use cass_value::CassValue;
use cass_row::CassRow;
use cass_schema::CassSchemaMeta;
use cass_schema::CassSchema;
use cass_schema::CassSchemaMetaField;

use cass_types::cass_bool_t;

pub enum CassIterator { }

#[derive(Show)]
pub enum CassIteratorType {
    RESULT = 0,
    ROW = 1,
    COLLECTION = 2,
    MAP = 3,
    SCHEMA_META = 4,
    SCHEMA_META_FIELD = 5
}

extern "C" {
    pub fn cass_iterator_free(iterator: *mut CassIterator);
    pub fn cass_iterator_type(iterator: *mut CassIterator) -> CassIteratorType;
    pub fn cass_iterator_from_result(result: *const CassResult) -> *mut CassIterator;
    pub fn cass_iterator_from_row(row: *const CassRow) -> *mut CassIterator;
    pub fn cass_iterator_from_collection(value: *const CassValue) -> *mut CassIterator;
    pub fn cass_iterator_from_map(value: *const CassValue) -> *mut CassIterator;
    pub fn cass_iterator_from_schema(schema: *const CassSchema) -> *mut CassIterator;
    pub fn cass_iterator_from_schema_meta(meta: *const CassSchemaMeta) -> *mut CassIterator;
    pub fn cass_iterator_fields_from_schema_meta(meta: *const CassSchemaMeta) -> *mut CassIterator;
    pub fn cass_iterator_next(iterator: *mut CassIterator) -> cass_bool_t;
    pub fn cass_iterator_get_row(iterator: *mut CassIterator) -> *const CassRow;
    pub fn cass_iterator_get_column(iterator: *mut CassIterator) -> *const CassValue;
    pub fn cass_iterator_get_value(iterator: *mut CassIterator)-> *const CassValue;
    pub fn cass_iterator_get_map_key(iterator: *mut CassIterator) -> *const CassValue;
    pub fn cass_iterator_get_map_value(iterator: *mut CassIterator) -> *const CassValue;
    pub fn cass_iterator_get_schema_meta(iterator: *mut CassIterator) -> *const CassSchemaMeta;
    pub fn cass_iterator_get_schema_meta_field(iterator: *mut CassIterator) -> *const CassSchemaMetaField;
}
<|endoftext|>


<commit_before>
use geom::{Rect,Px};

#[derive(Copy,Clone)]
pub struct Colour(u32);
impl Colour
{
	pub fn from_argb32(argb32: u32) -> Colour { Colour(argb32) }
	pub fn from_rgb(r: u8, g: u8, b: u8) -> Colour {
		let argb32 = 0 << 24 | (r as u32) << 16 | (g as u32) << 8 | (b as u32);
		Colour( argb32 )
	}
	//pub fn black() -> Colour { Colour(0) }
	//pub fn ltgray() -> Colour { Colour(0xDD_DD_DD) }
	//pub fn gray() -> Colour { Colour(0x55_55_55) }
	//pub fn white() -> Colour { Colour(0xFF_FF_FF) }
	pub fn as_argb32(&self) -> u32 { self.0 }

	pub fn theme_text() -> Colour { Colour(0x00_000000) }
	pub fn theme_text_alt() -> Colour { Colour(0x00_606060) }
	pub fn theme_border_main() -> Colour { Colour(0x00_C0C0C0) }
	pub fn theme_border_alt() -> Colour { Colour(0x00_E0E0E0) }
	pub fn theme_text_bg() -> Colour { Colour(0xF8FFF8) }
	pub fn theme_body_bg() -> Colour { Colour(0x002000) }

	/// Alpha value, 0 = opaque, 255 = transparent
	pub fn alpha(&self) -> u8 {
		(self.0 >> 24) as u8
	}
	pub fn red  (&self) -> u8 { (self.0 >> 16) as u8 }
	pub fn green(&self) -> u8 { (self.0 >>  8) as u8 }
	pub fn blue (&self) -> u8 { (self.0 >>  0) as u8 }

	pub fn blend_alpha(lower: Colour, upper: Colour, alpha: u8) -> Colour {
		let alpha: u32 = alpha as u32;
		if alpha == 0 {
			upper
		}
		else if alpha == 255 {
			lower
		}
		else {
			let r = Self::blend_component( alpha, lower.red(),   upper.red() );
			let g = Self::blend_component( alpha, lower.green(), upper.green() );
			let b = Self::blend_component( alpha, lower.blue(),  upper.blue() );
			Colour::from_rgb(r,g,b)
		}
	}
	pub fn blend(lower: Colour, upper: Colour) -> Colour {
		Colour::blend_alpha(lower, upper, upper.alpha())
	}
	fn blend_component(alpha: u32, lower: u8, upper: u8) -> u8 {
		let val_by_255 = lower as u32 * alpha + upper as u32 * (255 - alpha);
		(val_by_255 / 255) as u8
	}
}

#[derive(Default)]
pub struct Surface
{
	width: usize,
	dirty: ::std::cell::Cell<Rect<Px>>,
	data: ::std::cell::RefCell<Vec<u32>>,
}

impl Surface
{
	fn height(&self) -> u32 {
		if self.width == 0 {
			assert_eq!(self.data.borrow().len(), 0);
			0
		}
		else {
			(self.data.borrow().len() / self.width) as u32
		}
	}

	/// Blit to the passed GUI window
	pub fn blit_to_win(&self, win: &::syscalls::gui::Window)
	{
		let dirty: Rect<Px> = self.dirty.get();
		self.dirty.set(Default::default());
		let first_row = dirty.y().0 as usize;
		let row_count = dirty.height().0 as usize;

		// TODO: Need to support "stride" for this API, allowing true partial blits.
		win.blit_rect(
			0, first_row as u32,
			self.width as u32, row_count as u32,
			&self.data.borrow()[first_row*self.width..][..row_count*self.width],
			self.width
			);
	}
	/// Resize the surface (clearing existing content)
	pub fn resize(&mut self, dims: ::syscalls::gui::Dims) {
		self.width = dims.w as usize;
		*self.data.borrow_mut() = vec![Colour::theme_body_bg().as_argb32(); (dims.w as usize * dims.h as usize)];
		// On resize, set dirty area to full area of the surface
		self.dirty.set( self.rect() );
	}
	/// Obtain a rect covering the entire surface
	pub fn rect(&self) -> Rect<Px> {
		Rect::new(0, 0, self.width as u32, self.height())
	}
	/// Obtain a view into this surface
	pub fn slice(&self, rect: Rect<Px>) -> SurfaceView {
		let rect = self.rect().intersect(&rect);
		kernel_log!("Surface::slice - rect={:?}", rect);
		SurfaceView { surf: self, rect: rect }
	}

	fn foreach_scanlines<F: FnMut(usize, &mut [u32])>(&self, rect: Rect<Px>, mut f: F) {
		// Update dirty region with this rect
		//let mut dr = self.dirty.borrow_mut();
		if self.dirty.get().is_empty() {
			self.dirty.set(rect);
		}
		else {
			self.dirty.set( self.dirty.get().union(&rect) );
		}

		//kernel_log!("foreach_scanlines(rect={:?}, F={})", rect, type_name!(F));
		for (i, row) in self.data.borrow_mut().chunks_mut(self.width).skip(rect.y().0 as usize).take(rect.height().0 as usize).enumerate()
		{
			//kernel_log!("{}: {}  {}..{}", i, rect.y().0 as usize + i, rect.x().0, rect.x2().0);
			f( i, &mut row[rect.x().0 as usize .. rect.x2().0 as usize] );
		}
	}
}

pub struct SurfaceView<'a>
{
	surf: &'a Surface,
	rect: Rect<Px>,
}
impl<'a> SurfaceView<'a>
{
	/// Obtain a full rectangle of this surface
	pub fn rect(&self) -> Rect<Px> {
		Rect::new(0, 0, self.width(), self.height())
	}
	pub fn width(&self) -> u32 { self.rect.width().0 }
	pub fn height(&self) -> u32 { self.rect.height().0 }

	/// Create a sub-view of the surface
	pub fn slice(&self, rect: Rect<Px>) -> SurfaceView {
		SurfaceView {
			surf: self.surf,
			rect: self.rect.intersect(&rect.offset(self.rect.x(), self.rect.y())),
		}
	}

	/// Iterate over scanlines in a rect (scanlines are [u32] xRGB32)
	pub fn foreach_scanlines<F: FnMut(usize, &mut [u32])>(&self, rect: Rect<Px>, f: F) {
		self.surf.foreach_scanlines( self.rect.relative(&rect), f )
	}

	/// Fill a region with a solid colour
	pub fn fill_rect(&self, rect: Rect<Px>, colour: Colour) {
		self.foreach_scanlines(rect, |_, line|
			for px in line.iter_mut() {
				*px = colour.as_argb32();
			}
			);
	}

	/// Draw characters yielded from the passed iterator using the default font
	pub fn draw_text<It: Iterator<Item=char>>(&self, mut rect: Rect<Px>, chars: It, colour: Colour) -> usize {
		let mut st = S_FONT.get_renderer();
		let mut chars = chars.peekable();
		kernel_log!("draw_text: rect = {:?}", rect);
		while let Some( (w,_h) ) = st.render_grapheme(&mut chars, colour)
		{
			self.foreach_scanlines(rect, |i, line| {
				for (d,s) in line.iter_mut().zip( st.buffer(i, w as usize) )
				{
					*d = Colour::blend( Colour::from_argb32(*d), Colour::from_argb32(*s) ).as_argb32();
				}
				});
			rect = rect.offset(::geom::Px(w), ::geom::Px(0));
		}
		rect.x().0 as usize
	}
}

// --------------------------------------------------------------------
// Fallback/simple monospace font (Classic VGA, aka CP437)
// --------------------------------------------------------------------

static S_FONT: MonoFont = MonoFont::new();
struct MonoFont;
impl MonoFont {
	const fn new() -> MonoFont { MonoFont }
	fn get_renderer(&self) -> MonoFontRender {
		MonoFontRender { buffer: [0; 8*16], }
	}
}

include!("../../Graphics/font_cp437_8x16.rs");

struct MonoFontRender {
	buffer: [u32; 8*16],
}
impl MonoFontRender
{
	pub fn render_grapheme<It: Iterator<Item=char>>(&mut self, it: &mut ::std::iter::Peekable<It>, colour: Colour) -> Option<(u32,u32)> {
		self.buffer = [0xFF_000000; 8*16];
		if let Some(ch) = it.next()
		{
			self.render_char(colour, ch);
			while it.peek().map(|c| c.is_combining()).unwrap_or(false)
			{
				self.render_char(colour, it.next().unwrap());
			}
			Some( (8,16) )
		}
		else {
			None
		}
	}
	pub fn buffer(&self, row: usize, width: usize) -> &[u32] {
		&self.buffer[row * 8..][..width]
	}

	/// Actually does the rendering
	fn render_char(&mut self, colour: Colour, cp: char)
	{
		let idx = unicode_to_cp437(cp);
		//kernel_log!("render_char - '{}' = {:#x}", cp, idx);

		let bitmap = &S_FONTDATA[idx as usize];

		// Actual render!
		for row in (0 .. 16)
		{
			let byte = &bitmap[row as usize];
			let base = row * 8;
			let r = &mut self.buffer[base .. base + 8];
			for col in (0usize .. 8)
			{
				if (byte >> 7-col) & 1 != 0 {
					r[col] = colour.as_argb32();
				}
			}
		}
	}
}

/// Trait to provde 'is_combining', used by render code
trait UnicodeCombining
{
	fn is_combining(&self) -> bool;
}

impl UnicodeCombining for char
{
	fn is_combining(&self) -> bool
	{
		match *self as u32
		{
		// Ranges from wikipedia:Combining_Character
		0x0300 ... 0x036F => true,
		0x1AB0 ... 0x1AFF => true,
		0x1DC0 ... 0x1DFF => true,
		0x20D0 ... 0x20FF => true,
		0xFE20 ... 0xFE2F => true,
		_ => false,
		}
	}
}
<commit_msg>Usermode/wtk - Use partial blit to reduce latency<commit_after>
use geom::{Rect,Px};

#[derive(Copy,Clone)]
pub struct Colour(u32);
impl Colour
{
	pub fn from_argb32(argb32: u32) -> Colour { Colour(argb32) }
	pub fn from_rgb(r: u8, g: u8, b: u8) -> Colour {
		let argb32 = 0 << 24 | (r as u32) << 16 | (g as u32) << 8 | (b as u32);
		Colour( argb32 )
	}
	//pub fn black() -> Colour { Colour(0) }
	//pub fn ltgray() -> Colour { Colour(0xDD_DD_DD) }
	//pub fn gray() -> Colour { Colour(0x55_55_55) }
	//pub fn white() -> Colour { Colour(0xFF_FF_FF) }
	pub fn as_argb32(&self) -> u32 { self.0 }

	pub fn theme_text() -> Colour { Colour(0x00_000000) }
	pub fn theme_text_alt() -> Colour { Colour(0x00_606060) }
	pub fn theme_border_main() -> Colour { Colour(0x00_C0C0C0) }
	pub fn theme_border_alt() -> Colour { Colour(0x00_E0E0E0) }
	pub fn theme_text_bg() -> Colour { Colour(0xF8FFF8) }
	pub fn theme_body_bg() -> Colour { Colour(0x002000) }

	/// Alpha value, 0 = opaque, 255 = transparent
	pub fn alpha(&self) -> u8 {
		(self.0 >> 24) as u8
	}
	pub fn red  (&self) -> u8 { (self.0 >> 16) as u8 }
	pub fn green(&self) -> u8 { (self.0 >>  8) as u8 }
	pub fn blue (&self) -> u8 { (self.0 >>  0) as u8 }

	pub fn blend_alpha(lower: Colour, upper: Colour, alpha: u8) -> Colour {
		let alpha: u32 = alpha as u32;
		if alpha == 0 {
			upper
		}
		else if alpha == 255 {
			lower
		}
		else {
			let r = Self::blend_component( alpha, lower.red(),   upper.red() );
			let g = Self::blend_component( alpha, lower.green(), upper.green() );
			let b = Self::blend_component( alpha, lower.blue(),  upper.blue() );
			Colour::from_rgb(r,g,b)
		}
	}
	pub fn blend(lower: Colour, upper: Colour) -> Colour {
		Colour::blend_alpha(lower, upper, upper.alpha())
	}
	fn blend_component(alpha: u32, lower: u8, upper: u8) -> u8 {
		let val_by_255 = lower as u32 * alpha + upper as u32 * (255 - alpha);
		(val_by_255 / 255) as u8
	}
}

#[derive(Default)]
pub struct Surface
{
	width: usize,
	dirty: ::std::cell::Cell<Rect<Px>>,
	data: ::std::cell::RefCell<Vec<u32>>,
}

impl Surface
{
	fn height(&self) -> u32 {
		if self.width == 0 {
			assert_eq!(self.data.borrow().len(), 0);
			0
		}
		else {
			(self.data.borrow().len() / self.width) as u32
		}
	}

	/// Blit to the passed GUI window
	pub fn blit_to_win(&self, win: &::syscalls::gui::Window)
	{
		let dirty: Rect<Px> = self.dirty.get();
		self.dirty.set(Default::default());
		let first_row = dirty.y().0 as usize;
		let row_count = dirty.height().0 as usize;
		let first_col = dirty.x().0 as usize;
		let col_count = dirty.width().0 as usize;

		// Blit just the dirty region
		win.blit_rect(
			first_col as u32, first_row as u32,
			col_count as u32, row_count as u32,
			&self.data.borrow()[first_row*self.width + first_col .. ][ .. row_count*self.width],
			self.width
			);
	}
	/// Resize the surface (clearing existing content)
	pub fn resize(&mut self, dims: ::syscalls::gui::Dims) {
		self.width = dims.w as usize;
		*self.data.borrow_mut() = vec![Colour::theme_body_bg().as_argb32(); (dims.w as usize * dims.h as usize)];
		// On resize, set dirty area to full area of the surface
		self.dirty.set( self.rect() );
	}
	/// Obtain a rect covering the entire surface
	pub fn rect(&self) -> Rect<Px> {
		Rect::new(0, 0, self.width as u32, self.height())
	}
	/// Obtain a view into this surface
	pub fn slice(&self, rect: Rect<Px>) -> SurfaceView {
		let rect = self.rect().intersect(&rect);
		kernel_log!("Surface::slice - rect={:?}", rect);
		SurfaceView { surf: self, rect: rect }
	}

	fn foreach_scanlines<F: FnMut(usize, &mut [u32])>(&self, rect: Rect<Px>, mut f: F) {
		// Update dirty region with this rect
		//let mut dr = self.dirty.borrow_mut();
		if self.dirty.get().is_empty() {
			self.dirty.set(rect);
		}
		else {
			self.dirty.set( self.dirty.get().union(&rect) );
		}

		//kernel_log!("foreach_scanlines(rect={:?}, F={})", rect, type_name!(F));
		for (i, row) in self.data.borrow_mut().chunks_mut(self.width).skip(rect.y().0 as usize).take(rect.height().0 as usize).enumerate()
		{
			//kernel_log!("{}: {}  {}..{}", i, rect.y().0 as usize + i, rect.x().0, rect.x2().0);
			f( i, &mut row[rect.x().0 as usize .. rect.x2().0 as usize] );
		}
	}
}

pub struct SurfaceView<'a>
{
	surf: &'a Surface,
	rect: Rect<Px>,
}
impl<'a> SurfaceView<'a>
{
	/// Obtain a full rectangle of this surface
	pub fn rect(&self) -> Rect<Px> {
		Rect::new(0, 0, self.width(), self.height())
	}
	pub fn width(&self) -> u32 { self.rect.width().0 }
	pub fn height(&self) -> u32 { self.rect.height().0 }

	/// Create a sub-view of the surface
	pub fn slice(&self, rect: Rect<Px>) -> SurfaceView {
		SurfaceView {
			surf: self.surf,
			rect: self.rect.intersect(&rect.offset(self.rect.x(), self.rect.y())),
		}
	}

	/// Iterate over scanlines in a rect (scanlines are [u32] xRGB32)
	pub fn foreach_scanlines<F: FnMut(usize, &mut [u32])>(&self, rect: Rect<Px>, f: F) {
		self.surf.foreach_scanlines( self.rect.relative(&rect), f )
	}

	/// Fill a region with a solid colour
	pub fn fill_rect(&self, rect: Rect<Px>, colour: Colour) {
		self.foreach_scanlines(rect, |_, line|
			for px in line.iter_mut() {
				*px = colour.as_argb32();
			}
			);
	}

	/// Draw characters yielded from the passed iterator using the default font
	pub fn draw_text<It: Iterator<Item=char>>(&self, mut rect: Rect<Px>, chars: It, colour: Colour) -> usize {
		let mut st = S_FONT.get_renderer();
		let mut chars = chars.peekable();
		kernel_log!("draw_text: rect = {:?}", rect);
		while let Some( (w,_h) ) = st.render_grapheme(&mut chars, colour)
		{
			self.foreach_scanlines(rect, |i, line| {
				for (d,s) in line.iter_mut().zip( st.buffer(i, w as usize) )
				{
					*d = Colour::blend( Colour::from_argb32(*d), Colour::from_argb32(*s) ).as_argb32();
				}
				});
			rect = rect.offset(::geom::Px(w), ::geom::Px(0));
		}
		rect.x().0 as usize
	}
}

// --------------------------------------------------------------------
// Fallback/simple monospace font (Classic VGA, aka CP437)
// --------------------------------------------------------------------

static S_FONT: MonoFont = MonoFont::new();
struct MonoFont;
impl MonoFont {
	const fn new() -> MonoFont { MonoFont }
	fn get_renderer(&self) -> MonoFontRender {
		MonoFontRender { buffer: [0; 8*16], }
	}
}

include!("../../Graphics/font_cp437_8x16.rs");

struct MonoFontRender {
	buffer: [u32; 8*16],
}
impl MonoFontRender
{
	pub fn render_grapheme<It: Iterator<Item=char>>(&mut self, it: &mut ::std::iter::Peekable<It>, colour: Colour) -> Option<(u32,u32)> {
		self.buffer = [0xFF_000000; 8*16];
		if let Some(ch) = it.next()
		{
			self.render_char(colour, ch);
			while it.peek().map(|c| c.is_combining()).unwrap_or(false)
			{
				self.render_char(colour, it.next().unwrap());
			}
			Some( (8,16) )
		}
		else {
			None
		}
	}
	pub fn buffer(&self, row: usize, width: usize) -> &[u32] {
		&self.buffer[row * 8..][..width]
	}

	/// Actually does the rendering
	fn render_char(&mut self, colour: Colour, cp: char)
	{
		let idx = unicode_to_cp437(cp);
		//kernel_log!("render_char - '{}' = {:#x}", cp, idx);

		let bitmap = &S_FONTDATA[idx as usize];

		// Actual render!
		for row in (0 .. 16)
		{
			let byte = &bitmap[row as usize];
			let base = row * 8;
			let r = &mut self.buffer[base .. base + 8];
			for col in (0usize .. 8)
			{
				if (byte >> 7-col) & 1 != 0 {
					r[col] = colour.as_argb32();
				}
			}
		}
	}
}

/// Trait to provde 'is_combining', used by render code
trait UnicodeCombining
{
	fn is_combining(&self) -> bool;
}

impl UnicodeCombining for char
{
	fn is_combining(&self) -> bool
	{
		match *self as u32
		{
		// Ranges from wikipedia:Combining_Character
		0x0300 ... 0x036F => true,
		0x1AB0 ... 0x1AFF => true,
		0x1DC0 ... 0x1DFF => true,
		0x20D0 ... 0x20FF => true,
		0xFE20 ... 0xFE2F => true,
		_ => false,
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

// The outlines relation `T: 'a` or `'a: 'b`.

use middle::infer::InferCtxt;
use middle::ty::{self, RegionEscape, Ty};

#[derive(Debug)]
pub enum Component<'tcx> {
    Region(ty::Region),
    Param(ty::ParamTy),
    UnresolvedInferenceVariable(ty::InferTy),

    // Projections like `T::Foo` are tricky because a constraint like
    // `T::Foo: 'a` can be satisfied in so many ways. There may be a
    // where-clause that says `T::Foo: 'a`, or the defining trait may
    // include a bound like `type Foo: 'static`, or -- in the most
    // conservative way -- we can prove that `T: 'a` (more generally,
    // that all components in the projection outlive `'a`). This code
    // is not in a position to judge which is the best technique, so
    // we just product the projection as a component and leave it to
    // the consumer to decide (but see `EscapingProjection` below).
    Projection(ty::ProjectionTy<'tcx>),

    // In the case where a projection has escaping regions -- meaning
    // regions bound within the type itself -- we always use
    // the most conservative rule, which requires that all components
    // outlive the bound. So for example if we had a type like this:
    //
    //     for<'a> Trait1<  <T as Trait2<'a,'b>>::Foo  >
    //                      ~~~~~~~~~~~~~~~~~~~~~~~~~
    //
    // then the inner projection (underlined) has an escaping region
    // `'a`. We consider that outer trait `'c` to meet a bound if `'b`
    // outlives `'b: 'c`, and we don't consider whether the trait
    // declares that `Foo: 'static` etc. Therefore, we just return the
    // free components of such a projection (in this case, `'b`).
    //
    // However, in the future, we may want to get smarter, and
    // actually return a "higher-ranked projection" here. Therefore,
    // we mark that these components are part of an escaping
    // projection, so that implied bounds code can avoid relying on
    // them. This gives us room to improve the regionck reasoning in
    // the future without breaking backwards compat.
    EscapingProjection(Vec<Component<'tcx>>),

    RFC1214(Vec<Component<'tcx>>),
}

/// Returns all the things that must outlive `'a` for the condition
/// `ty0: 'a` to hold.
pub fn components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
                           ty0: Ty<'tcx>)
                           -> Vec<Component<'tcx>> {
    let mut components = vec![];
    compute_components(infcx, ty0, &mut components);
    debug!("outlives({:?}) = {:?}", ty0, components);
    components
}

fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
                               ty0: Ty<'tcx>,
                               out: &mut Vec<Component<'tcx>>) {
    // Descend through the types, looking for the various "base"
    // components and collecting them into `out`. This is not written
    // with `collect()` because of the need to sometimes skip subtrees
    // in the `subtys` iterator (e.g., when encountering a
    // projection).
    let mut subtys = ty0.walk();
    while let Some(ty) = subtys.next() {
        match ty.sty {
            ty::TyClosure(_, ref substs) => {
                // FIXME(#27086). We do not accumulate from substs, since they
                // don't represent reachable data. This means that, in
                // practice, some of the lifetime parameters might not
                // be in scope when the body runs, so long as there is
                // no reachable data with that lifetime. For better or
                // worse, this is consistent with fn types, however,
                // which can also encapsulate data in this fashion
                // (though it's somewhat harder, and typically
                // requires virtual dispatch).
                //
                // Note that changing this (in a naive way, at least)
                // causes regressions for what appears to be perfectly
                // reasonable code like this:
                //
                // ```
                // fn foo<'a>(p: &Data<'a>) {
                //    bar(|q: &mut Parser| q.read_addr())
                // }
                // fn bar(p: Box<FnMut(&mut Parser)+'static>) {
                // }
                // ```
                //
                // Note that `p` (and `'a`) are not used in the
                // closure at all, but to meet the requirement that
                // the closure type `C: 'static` (so it can be coerced
                // to the object type), we get the requirement that
                // `'a: 'static` since `'a` appears in the closure
                // type `C`.
                //
                // A smarter fix might "prune" unused `func_substs` --
                // this would avoid breaking simple examples like
                // this, but would still break others (which might
                // indeed be invalid, depending on your POV). Pruning
                // would be a subtle process, since we have to see
                // what func/type parameters are used and unused,
                // taking into consideration UFCS and so forth.

                for &upvar_ty in &substs.upvar_tys {
                    compute_components(infcx, upvar_ty, out);
                }
                subtys.skip_current_subtree();
            }
            ty::TyBareFn(..) | ty::TyTrait(..) => {
                subtys.skip_current_subtree();
                let subcomponents = capture_components(infcx, ty);
                out.push(Component::RFC1214(subcomponents));
            }
            ty::TyParam(p) => {
                out.push(Component::Param(p));
                subtys.skip_current_subtree();
            }
            ty::TyProjection(ref data) => {
                // For projections, we prefer to generate an
                // obligation like `<P0 as Trait<P1...Pn>>::Foo: 'a`,
                // because this gives the regionck more ways to prove
                // that it holds. However, regionck is not (at least
                // currently) prepared to deal with higher-ranked
                // regions that may appear in the
                // trait-ref. Therefore, if we see any higher-ranke
                // regions, we simply fallback to the most restrictive
                // rule, which requires that `Pi: 'a` for all `i`.

                if !data.has_escaping_regions() {
                    // best case: no escaping regions, so push the
                    // projection and skip the subtree (thus
                    // generating no constraints for Pi).
                    out.push(Component::Projection(*data));
                } else {
                    // fallback case: continue walking through and
                    // constrain Pi.
                    let subcomponents = capture_components(infcx, ty);
                    out.push(Component::EscapingProjection(subcomponents));
                }
                subtys.skip_current_subtree();
            }
            ty::TyInfer(_) => {
                let ty = infcx.resolve_type_vars_if_possible(&ty);
                if let ty::TyInfer(infer_ty) = ty.sty {
                    out.push(Component::UnresolvedInferenceVariable(infer_ty));
                } else {
                    compute_components(infcx, ty, out);
                }
            }

            // Most types do not introduce any region binders, nor
            // involve any other subtle cases, and so the WF relation
            // simply constraints any regions referenced directly by
            // the type and then visits the types that are lexically
            // contained within. (The comments refer to relevant rules
            // from RFC1214.)
            ty::TyBool(..) |        // OutlivesScalar
            ty::TyChar(..) |        // OutlivesScalar
            ty::TyInt(..) |         // OutlivesScalar
            ty::TyUint(..) |        // OutlivesScalar
            ty::TyFloat(..) |       // OutlivesScalar
            ty::TyEnum(..) |        // OutlivesNominalType
            ty::TyStruct(..) |      // OutlivesNominalType
            ty::TyBox(..) |         // OutlivesNominalType (ish)
            ty::TyStr(..) |         // OutlivesScalar (ish)
            ty::TyArray(..) |       // ...
            ty::TySlice(..) |       // ...
            ty::TyRawPtr(..) |      // ...
            ty::TyRef(..) |         // OutlivesReference
            ty::TyTuple(..) |       // ...
            ty::TyError(..) => {
                push_region_constraints(out, ty.regions());
            }
        }
    }
}

fn capture_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
                               ty: Ty<'tcx>)
                               -> Vec<Component<'tcx>> {
    let mut temp = vec![];
    push_region_constraints(&mut temp, ty.regions());
    for subty in ty.walk_shallow() {
        compute_components(infcx, subty, &mut temp);
    }
    temp
}

fn push_region_constraints<'tcx>(out: &mut Vec<Component<'tcx>>, regions: Vec<ty::Region>) {
    for r in regions {
        if !r.is_bound() {
            out.push(Component::Region(r));
        }
    }
}
<commit_msg>outlives.rs: remove use of ty.walk and replace with recursive of ty.walk_shallow, add add'l comments.<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

// The outlines relation `T: 'a` or `'a: 'b`. This code frequently
// refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that
// RFC for reference.

use middle::infer::InferCtxt;
use middle::ty::{self, RegionEscape, Ty};

#[derive(Debug)]
pub enum Component<'tcx> {
    Region(ty::Region),
    Param(ty::ParamTy),
    UnresolvedInferenceVariable(ty::InferTy),

    // Projections like `T::Foo` are tricky because a constraint like
    // `T::Foo: 'a` can be satisfied in so many ways. There may be a
    // where-clause that says `T::Foo: 'a`, or the defining trait may
    // include a bound like `type Foo: 'static`, or -- in the most
    // conservative way -- we can prove that `T: 'a` (more generally,
    // that all components in the projection outlive `'a`). This code
    // is not in a position to judge which is the best technique, so
    // we just product the projection as a component and leave it to
    // the consumer to decide (but see `EscapingProjection` below).
    Projection(ty::ProjectionTy<'tcx>),

    // In the case where a projection has escaping regions -- meaning
    // regions bound within the type itself -- we always use
    // the most conservative rule, which requires that all components
    // outlive the bound. So for example if we had a type like this:
    //
    //     for<'a> Trait1<  <T as Trait2<'a,'b>>::Foo  >
    //                      ~~~~~~~~~~~~~~~~~~~~~~~~~
    //
    // then the inner projection (underlined) has an escaping region
    // `'a`. We consider that outer trait `'c` to meet a bound if `'b`
    // outlives `'b: 'c`, and we don't consider whether the trait
    // declares that `Foo: 'static` etc. Therefore, we just return the
    // free components of such a projection (in this case, `'b`).
    //
    // However, in the future, we may want to get smarter, and
    // actually return a "higher-ranked projection" here. Therefore,
    // we mark that these components are part of an escaping
    // projection, so that implied bounds code can avoid relying on
    // them. This gives us room to improve the regionck reasoning in
    // the future without breaking backwards compat.
    EscapingProjection(Vec<Component<'tcx>>),

    RFC1214(Vec<Component<'tcx>>),
}

/// Returns all the things that must outlive `'a` for the condition
/// `ty0: 'a` to hold.
pub fn components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
                           ty0: Ty<'tcx>)
                           -> Vec<Component<'tcx>> {
    let mut components = vec![];
    compute_components(infcx, ty0, &mut components);
    debug!("outlives({:?}) = {:?}", ty0, components);
    components
}

fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
                               ty: Ty<'tcx>,
                               out: &mut Vec<Component<'tcx>>) {
    // Descend through the types, looking for the various "base"
    // components and collecting them into `out`. This is not written
    // with `collect()` because of the need to sometimes skip subtrees
    // in the `subtys` iterator (e.g., when encountering a
    // projection).
    match ty.sty {
        ty::TyClosure(_, ref substs) => {
            // FIXME(#27086). We do not accumulate from substs, since they
            // don't represent reachable data. This means that, in
            // practice, some of the lifetime parameters might not
            // be in scope when the body runs, so long as there is
            // no reachable data with that lifetime. For better or
            // worse, this is consistent with fn types, however,
            // which can also encapsulate data in this fashion
            // (though it's somewhat harder, and typically
            // requires virtual dispatch).
            //
            // Note that changing this (in a naive way, at least)
            // causes regressions for what appears to be perfectly
            // reasonable code like this:
            //
            // ```
            // fn foo<'a>(p: &Data<'a>) {
            //    bar(|q: &mut Parser| q.read_addr())
            // }
            // fn bar(p: Box<FnMut(&mut Parser)+'static>) {
            // }
            // ```
            //
            // Note that `p` (and `'a`) are not used in the
            // closure at all, but to meet the requirement that
            // the closure type `C: 'static` (so it can be coerced
            // to the object type), we get the requirement that
            // `'a: 'static` since `'a` appears in the closure
            // type `C`.
            //
            // A smarter fix might "prune" unused `func_substs` --
            // this would avoid breaking simple examples like
            // this, but would still break others (which might
            // indeed be invalid, depending on your POV). Pruning
            // would be a subtle process, since we have to see
            // what func/type parameters are used and unused,
            // taking into consideration UFCS and so forth.

            for &upvar_ty in &substs.upvar_tys {
                compute_components(infcx, upvar_ty, out);
            }
        }

        // Bare functions and traits are both binders. In the RFC,
        // this means we would add the bound regions to the "bound
        // regions list".  In our representation, no such list is
        // maintained explicitly, because bound regions themselves can
        // be readily identified. However, because the outlives
        // relation did not used to be applied to fn/trait-object
        // arguments, we due wrap the resulting components in an
        // RFC1214 wrapper so we can issue warnings.
        ty::TyBareFn(..) | ty::TyTrait(..) => {
            // OutlivesFunction, OutlivesObject, OutlivesFragment
            let subcomponents = capture_components(infcx, ty);
            out.push(Component::RFC1214(subcomponents));
        }

        // OutlivesTypeParameterEnv -- the actual checking that `X:'a`
        // is implied by the environment is done in regionck.
        ty::TyParam(p) => {
            out.push(Component::Param(p));
        }

        // For projections, we prefer to generate an obligation like
        // `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the
        // regionck more ways to prove that it holds. However,
        // regionck is not (at least currently) prepared to deal with
        // higher-ranked regions that may appear in the
        // trait-ref. Therefore, if we see any higher-ranke regions,
        // we simply fallback to the most restrictive rule, which
        // requires that `Pi: 'a` for all `i`.
        ty::TyProjection(ref data) => {
            if !data.has_escaping_regions() {
                // best case: no escaping regions, so push the
                // projection and skip the subtree (thus generating no
                // constraints for Pi). This defers the choice between
                // the rules OutlivesProjectionEnv,
                // OutlivesProjectionTraitDef, and
                // OutlivesProjectionComponents to regionck.
                out.push(Component::Projection(*data));
            } else {
                // fallback case: hard code
                // OutlivesProjectionComponents.  Continue walking
                // through and constrain Pi.
                let subcomponents = capture_components(infcx, ty);
                out.push(Component::EscapingProjection(subcomponents));
            }
        }

        // If we encounter an inference variable, try to resolve it
        // and proceed with resolved version. If we cannot resolve it,
        // then record the unresolved variable as a component.
        ty::TyInfer(_) => {
            let ty = infcx.resolve_type_vars_if_possible(&ty);
            if let ty::TyInfer(infer_ty) = ty.sty {
                out.push(Component::UnresolvedInferenceVariable(infer_ty));
            } else {
                compute_components(infcx, ty, out);
            }
        }

        // Most types do not introduce any region binders, nor
        // involve any other subtle cases, and so the WF relation
        // simply constraints any regions referenced directly by
        // the type and then visits the types that are lexically
        // contained within. (The comments refer to relevant rules
        // from RFC1214.)
        ty::TyBool(..) |        // OutlivesScalar
        ty::TyChar(..) |        // OutlivesScalar
        ty::TyInt(..) |         // OutlivesScalar
        ty::TyUint(..) |        // OutlivesScalar
        ty::TyFloat(..) |       // OutlivesScalar
        ty::TyEnum(..) |        // OutlivesNominalType
        ty::TyStruct(..) |      // OutlivesNominalType
        ty::TyBox(..) |         // OutlivesNominalType (ish)
        ty::TyStr(..) |         // OutlivesScalar (ish)
        ty::TyArray(..) |       // ...
        ty::TySlice(..) |       // ...
        ty::TyRawPtr(..) |      // ...
        ty::TyRef(..) |         // OutlivesReference
        ty::TyTuple(..) |       // ...
        ty::TyError(..) => {
            push_region_constraints(out, ty.regions());
            for subty in ty.walk_shallow() {
                compute_components(infcx, subty, out);
            }
        }
    }
}

fn capture_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
                               ty: Ty<'tcx>)
                               -> Vec<Component<'tcx>> {
    let mut temp = vec![];
    push_region_constraints(&mut temp, ty.regions());
    for subty in ty.walk_shallow() {
        compute_components(infcx, subty, &mut temp);
    }
    temp
}

fn push_region_constraints<'tcx>(out: &mut Vec<Component<'tcx>>, regions: Vec<ty::Region>) {
    for r in regions {
        if !r.is_bound() {
            out.push(Component::Region(r));
        }
    }
}
<|endoftext|>


<commit_before>//! # Software components that communicate using trees

pub use self::processor::*;
pub use self::component::*;

mod processor;
mod component;
<commit_msg>Convenience: if you use the component module, get the tree namespace as well.<commit_after>//! # Software components that communicate using trees

pub use self::processor::*;
pub use self::component::*;
pub use super::tree::*;

mod processor;
mod component;
<|endoftext|>