<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/.

// Code to handle initial setup steps for a pool.
// Initial setup steps are steps that do not alter the environment.

use std::collections::{HashMap, HashSet};
use std::fs::OpenOptions;
use std::path::{Path, PathBuf};

use serde_json;

use devicemapper::{devnode_to_devno, Device, Sectors};

use stratis::{ErrorEnum, StratisError, StratisResult};

use super::super::super::types::{BlockDevTier, DevUuid, PoolUuid};

use super::super::serde_structs::{BackstoreSave, BlockDevSave, PoolSave};

use super::blockdev::StratBlockDev;
use super::device::{blkdev_size, is_stratis_device};
use super::metadata::BDA;
use super::util::get_stratis_block_devices;

/// Find all Stratis devices.
///
/// Returns a map of pool uuids to a map of devices to devnodes for each pool.
pub fn find_all() -> StratisResult<HashMap<PoolUuid, HashMap<Device, PathBuf>>> {
    let mut pool_map = HashMap::new();

    for devnode in get_stratis_block_devices()? {
        match devnode_to_devno(&devnode)? {
            None => continue,
            Some(devno) => {
                is_stratis_device(&devnode)?.and_then(|pool_uuid| {
                    pool_map
                        .entry(pool_uuid)
                        .or_insert_with(HashMap::new)
                        .insert(Device::from(devno), devnode)
                });
            }
        }
    }
    Ok(pool_map)
}

/// Get the most recent metadata from a set of Devices for a given pool UUID.
/// Returns None if no metadata found for this pool.
#[allow(implicit_hasher)]
pub fn get_metadata(
    pool_uuid: PoolUuid,
    devnodes: &HashMap<Device, PathBuf>,
) -> StratisResult<Option<PoolSave>> {
    // Get pairs of device nodes and matching BDAs
    // If no BDA, or BDA UUID does not match pool UUID, skip.
    // If there is an error reading the BDA, error. There could have been
    // vital information on that BDA, for example, it may have contained
    // the newest metadata.
    let mut bdas = Vec::new();
    for devnode in devnodes.values() {
        let bda = BDA::load(&mut OpenOptions::new().read(true).open(devnode)?)?;
        if let Some(bda) = bda {
            if bda.pool_uuid() == pool_uuid {
                bdas.push((devnode, bda));
            }
        }
    }

    // Most recent time should never be None if this was a properly
    // created pool; this allows for the method to be called in other
    // circumstances.
    let most_recent_time = {
        match bdas.iter()
            .filter_map(|&(_, ref bda)| bda.last_update_time())
            .max()
        {
            Some(time) => time,
            None => return Ok(None),
        }
    };

    // Try to read from all available devnodes that could contain most
    // recent metadata. In the event of errors, continue to try until all are
    // exhausted.
    for &(devnode, ref bda) in bdas.iter()
        .filter(|&&(_, ref bda)| bda.last_update_time() == Some(most_recent_time))
    {
        let poolsave = OpenOptions::new()
            .read(true)
            .open(devnode)
            .ok()
            .and_then(|mut f| bda.load_state(&mut f).ok())
            .and_then(|opt| opt)
            .and_then(|data| serde_json::from_slice(&data).ok());

        if poolsave.is_some() {
            return Ok(poolsave);
        }
    }

    // If no data has yet returned, we have an error. That is, we should have
    // some metadata, because we have a most recent time, but we failed to
    // get any.
    let err_str = "timestamp indicates data was written, but no data successfully read";
    Err(StratisError::Engine(ErrorEnum::NotFound, err_str.into()))
}

/// Get all the blockdevs corresponding to this pool that can be obtained from
/// the given devices. Sort the blockdevs in the order in which they were
/// recorded in the metadata.
/// Returns an error if a BDA can not be read or can not be found on any
/// blockdev in devnodes.
/// Returns an error if the blockdevs obtained do not match the metadata.
/// Returns a tuple, of which the first are the data devs, and the second
/// are the devs that support the cache tier.
/// Precondition: Every device in devnodes has already been determined to
/// belong to the pool with the specified pool uuid.
#[allow(implicit_hasher)]
pub fn get_blockdevs(
    pool_uuid: PoolUuid,
    backstore_save: &BackstoreSave,
    devnodes: &HashMap<Device, PathBuf>,
) -> StratisResult<(Vec<StratBlockDev>, Vec<StratBlockDev>)> {
    let recorded_data_map: HashMap<DevUuid, (usize, &BlockDevSave)> = backstore_save
        .data_devs
        .iter()
        .enumerate()
        .map(|(i, bds)| (bds.uuid, (i, bds)))
        .collect();

    let recorded_cache_map: HashMap<DevUuid, (usize, &BlockDevSave)> =
        match backstore_save.cache_devs {
            Some(ref cache_devs) => cache_devs
                .iter()
                .enumerate()
                .map(|(i, bds)| (bds.uuid, (i, bds)))
                .collect(),
            None => HashMap::new(),
        };

    let mut segment_table: HashMap<DevUuid, Vec<(Sectors, Sectors)>> = HashMap::new();
    for seg in &backstore_save.data_segments {
        segment_table
            .entry(seg.0)
            .or_insert_with(Vec::default)
            .push((seg.1, seg.2))
    }
    if let Some(ref segs) = backstore_save.cache_segments {
        for seg in segs {
            segment_table
                .entry(seg.0)
                .or_insert_with(Vec::default)
                .push((seg.1, seg.2))
        }
    }
    if let Some(ref segs) = backstore_save.meta_segments {
        for seg in segs {
            segment_table
                .entry(seg.0)
                .or_insert_with(Vec::default)
                .push((seg.1, seg.2))
        }
    }

    // Construct a single StratBlockDev. Return the tier to which the
    // blockdev has been found to belong. Returns an error if the block
    // device has shrunk, no metadata can be found for the block device,
    // or it is impossible to set up the device because the recorded
    // allocation information is impossible.
    fn get_blockdev(
        device: Device,
        devnode: &Path,
        bda: BDA,
        data_map: &HashMap<DevUuid, (usize, &BlockDevSave)>,
        cache_map: &HashMap<DevUuid, (usize, &BlockDevSave)>,
        segment_table: &HashMap<DevUuid, Vec<(Sectors, Sectors)>>,
    ) -> StratisResult<(BlockDevTier, StratBlockDev)> {
        // Return an error if apparent size of Stratis block device appears to
        // have decreased since metadata was recorded or if size of block
        // device could not be obtained.
        blkdev_size(&OpenOptions::new().read(true).open(devnode)?).and_then(|actual_size| {
            let actual_size_sectors = actual_size.sectors();
            let recorded_size = bda.dev_size();
            if actual_size_sectors < recorded_size {
                let err_msg = format!(
                    "Stratis device with device number {}, devnode {}, pool UUID {} and device UUID {} had recorded size ({}), but actual size is less at ({})",
                    device,
                    devnode.display(),
                    bda.pool_uuid(),
                    bda.dev_uuid(),
                    recorded_size,
                    actual_size
                );
                Err(StratisError::Engine(ErrorEnum::Error, err_msg))
            } else {
                Ok(())
            }
        })?;

        let dev_uuid = bda.dev_uuid();

        // Locate the device in the metadata using its uuid. Return the device
        // metadata and whether it was a cache or a datadev.
        let (tier, &(_, bd_save)) = data_map
            .get(&dev_uuid)
            .map(|bd_save| (BlockDevTier::Data, bd_save))
            .or_else(|| {
                cache_map
                    .get(&dev_uuid)
                    .map(|bd_save| (BlockDevTier::Cache, bd_save))
            })
            .ok_or_else(|| {
                let err_msg = format!(
                        "Stratis device with device number {}, devnode {}, pool UUID {} and device UUID {} had no record in pool metadata",
                        device,
                        devnode.display(),
                        bda.pool_uuid(),
                        bda.dev_uuid()
                    );
                StratisError::Engine(ErrorEnum::NotFound, err_msg)
            })?;

        // This should always succeed since the actual size is at
        // least the recorded size, so all segments should be
        // available to be allocated. If this fails, the most likely
        // conclusion is metadata corruption.
        let segments = segment_table.get(&dev_uuid);
        Ok((
            tier,
            StratBlockDev::new(
                device,
                devnode.to_owned(),
                bda,
                segments.unwrap_or(&vec![]),
                bd_save.user_info.clone(),
                bd_save.hardware_info.clone(),
            )?,
        ))
    }

    let (mut datadevs, mut cachedevs): (Vec<StratBlockDev>, Vec<StratBlockDev>) = (vec![], vec![]);
    for (device, devnode) in devnodes {
        let bda = BDA::load(&mut OpenOptions::new().read(true).open(devnode)?)?.ok_or_else(|| {
            StratisError::Engine(ErrorEnum::NotFound,
                                                 format!("Device {} with devnode {} was previously determined to belong to pool with uuid {} but no BDA was found",
                                                 device,
                                                 devnode.display(),
                                                 pool_uuid))
        })?;

        get_blockdev(
            *device,
            devnode,
            bda,
            &recorded_data_map,
            &recorded_cache_map,
            &segment_table,
        ).map(|(tier, blockdev)| {
            match tier {
                BlockDevTier::Data => &mut datadevs,
                BlockDevTier::Cache => &mut cachedevs,
            }.push(blockdev)
        })?;
    }

    // Verify that devices located are congruent with the metadata recorded
    // and generally consistent with expectations. If all seems correct,
    // sort the devices according to their order in the metadata.
    fn check_and_sort_devs(
        mut devs: Vec<StratBlockDev>,
        dev_map: &HashMap<DevUuid, (usize, &BlockDevSave)>,
    ) -> StratisResult<Vec<StratBlockDev>> {
        let mut uuids = HashSet::new();
        let mut duplicate_uuids = Vec::new();
        for dev in &devs {
            let dev_uuid = dev.uuid();
            if !uuids.insert(dev_uuid) {
                duplicate_uuids.push(dev_uuid);
            }
        }

        if !duplicate_uuids.is_empty() {
            let err_msg = format!(
                "The following list of Stratis UUIDs were each claimed by more than one Stratis device: {:?}",
                duplicate_uuids
            );
            return Err(StratisError::Engine(ErrorEnum::Invalid, err_msg.into()));
        }

        let recorded_uuids: HashSet<_> = dev_map.keys().cloned().collect();
        if uuids != recorded_uuids {
            let err_msg = format!(
                "UUIDs of devices found ({:?}) did not correspond with UUIDs specified in the metadata for this group of devices ({:?})",
                uuids,
                recorded_uuids
            );
            return Err(StratisError::Engine(ErrorEnum::Invalid, err_msg.into()));
        }

        // Sort the devices according to their original location in the
        // metadata. Use a faster unstable sort, because the order of
        // devs before the sort is arbitrary and does not need to be
        // preserved.
        devs.sort_unstable_by_key(|dev| dev_map[&dev.uuid()].0);
        Ok(devs)
    }

    let datadevs = check_and_sort_devs(datadevs, &recorded_data_map)?;
    let cachedevs = check_and_sort_devs(cachedevs, &recorded_cache_map)?;

    Ok((datadevs, cachedevs))
}
<commit_msg>find_all: Remove redundant check if Stratis device<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/.

// Code to handle initial setup steps for a pool.
// Initial setup steps are steps that do not alter the environment.

use std::collections::{HashMap, HashSet};
use std::fs::OpenOptions;
use std::path::{Path, PathBuf};

use serde_json;

use devicemapper::{devnode_to_devno, Device, Sectors};

use stratis::{ErrorEnum, StratisError, StratisResult};

use super::super::super::types::{BlockDevTier, DevUuid, PoolUuid};

use super::super::serde_structs::{BackstoreSave, BlockDevSave, PoolSave};

use super::blockdev::StratBlockDev;
use super::device::blkdev_size;
use super::metadata::{StaticHeader, BDA};
use super::util::get_stratis_block_devices;

/// Find all Stratis devices.
///
/// Returns a map of pool uuids to a map of devices to devnodes for each pool.
pub fn find_all() -> StratisResult<HashMap<PoolUuid, HashMap<Device, PathBuf>>> {
    let mut pool_map = HashMap::new();

    for devnode in get_stratis_block_devices()? {
        match devnode_to_devno(&devnode)? {
            None => continue,
            Some(devno) => {
                if let Some((pool_uuid, _)) = StaticHeader::device_identifiers(
                    &mut OpenOptions::new().read(true).open(&devnode)?,
                )? {
                    pool_map
                        .entry(pool_uuid)
                        .or_insert_with(HashMap::new)
                        .insert(Device::from(devno), devnode);
                }
            }
        }
    }
    Ok(pool_map)
}

/// Get the most recent metadata from a set of Devices for a given pool UUID.
/// Returns None if no metadata found for this pool.
#[allow(implicit_hasher)]
pub fn get_metadata(
    pool_uuid: PoolUuid,
    devnodes: &HashMap<Device, PathBuf>,
) -> StratisResult<Option<PoolSave>> {
    // Get pairs of device nodes and matching BDAs
    // If no BDA, or BDA UUID does not match pool UUID, skip.
    // If there is an error reading the BDA, error. There could have been
    // vital information on that BDA, for example, it may have contained
    // the newest metadata.
    let mut bdas = Vec::new();
    for devnode in devnodes.values() {
        let bda = BDA::load(&mut OpenOptions::new().read(true).open(devnode)?)?;
        if let Some(bda) = bda {
            if bda.pool_uuid() == pool_uuid {
                bdas.push((devnode, bda));
            }
        }
    }

    // Most recent time should never be None if this was a properly
    // created pool; this allows for the method to be called in other
    // circumstances.
    let most_recent_time = {
        match bdas.iter()
            .filter_map(|&(_, ref bda)| bda.last_update_time())
            .max()
        {
            Some(time) => time,
            None => return Ok(None),
        }
    };

    // Try to read from all available devnodes that could contain most
    // recent metadata. In the event of errors, continue to try until all are
    // exhausted.
    for &(devnode, ref bda) in bdas.iter()
        .filter(|&&(_, ref bda)| bda.last_update_time() == Some(most_recent_time))
    {
        let poolsave = OpenOptions::new()
            .read(true)
            .open(devnode)
            .ok()
            .and_then(|mut f| bda.load_state(&mut f).ok())
            .and_then(|opt| opt)
            .and_then(|data| serde_json::from_slice(&data).ok());

        if poolsave.is_some() {
            return Ok(poolsave);
        }
    }

    // If no data has yet returned, we have an error. That is, we should have
    // some metadata, because we have a most recent time, but we failed to
    // get any.
    let err_str = "timestamp indicates data was written, but no data successfully read";
    Err(StratisError::Engine(ErrorEnum::NotFound, err_str.into()))
}

/// Get all the blockdevs corresponding to this pool that can be obtained from
/// the given devices. Sort the blockdevs in the order in which they were
/// recorded in the metadata.
/// Returns an error if a BDA can not be read or can not be found on any
/// blockdev in devnodes.
/// Returns an error if the blockdevs obtained do not match the metadata.
/// Returns a tuple, of which the first are the data devs, and the second
/// are the devs that support the cache tier.
/// Precondition: Every device in devnodes has already been determined to
/// belong to the pool with the specified pool uuid.
#[allow(implicit_hasher)]
pub fn get_blockdevs(
    pool_uuid: PoolUuid,
    backstore_save: &BackstoreSave,
    devnodes: &HashMap<Device, PathBuf>,
) -> StratisResult<(Vec<StratBlockDev>, Vec<StratBlockDev>)> {
    let recorded_data_map: HashMap<DevUuid, (usize, &BlockDevSave)> = backstore_save
        .data_devs
        .iter()
        .enumerate()
        .map(|(i, bds)| (bds.uuid, (i, bds)))
        .collect();

    let recorded_cache_map: HashMap<DevUuid, (usize, &BlockDevSave)> =
        match backstore_save.cache_devs {
            Some(ref cache_devs) => cache_devs
                .iter()
                .enumerate()
                .map(|(i, bds)| (bds.uuid, (i, bds)))
                .collect(),
            None => HashMap::new(),
        };

    let mut segment_table: HashMap<DevUuid, Vec<(Sectors, Sectors)>> = HashMap::new();
    for seg in &backstore_save.data_segments {
        segment_table
            .entry(seg.0)
            .or_insert_with(Vec::default)
            .push((seg.1, seg.2))
    }
    if let Some(ref segs) = backstore_save.cache_segments {
        for seg in segs {
            segment_table
                .entry(seg.0)
                .or_insert_with(Vec::default)
                .push((seg.1, seg.2))
        }
    }
    if let Some(ref segs) = backstore_save.meta_segments {
        for seg in segs {
            segment_table
                .entry(seg.0)
                .or_insert_with(Vec::default)
                .push((seg.1, seg.2))
        }
    }

    // Construct a single StratBlockDev. Return the tier to which the
    // blockdev has been found to belong. Returns an error if the block
    // device has shrunk, no metadata can be found for the block device,
    // or it is impossible to set up the device because the recorded
    // allocation information is impossible.
    fn get_blockdev(
        device: Device,
        devnode: &Path,
        bda: BDA,
        data_map: &HashMap<DevUuid, (usize, &BlockDevSave)>,
        cache_map: &HashMap<DevUuid, (usize, &BlockDevSave)>,
        segment_table: &HashMap<DevUuid, Vec<(Sectors, Sectors)>>,
    ) -> StratisResult<(BlockDevTier, StratBlockDev)> {
        // Return an error if apparent size of Stratis block device appears to
        // have decreased since metadata was recorded or if size of block
        // device could not be obtained.
        blkdev_size(&OpenOptions::new().read(true).open(devnode)?).and_then(|actual_size| {
            let actual_size_sectors = actual_size.sectors();
            let recorded_size = bda.dev_size();
            if actual_size_sectors < recorded_size {
                let err_msg = format!(
                    "Stratis device with device number {}, devnode {}, pool UUID {} and device UUID {} had recorded size ({}), but actual size is less at ({})",
                    device,
                    devnode.display(),
                    bda.pool_uuid(),
                    bda.dev_uuid(),
                    recorded_size,
                    actual_size
                );
                Err(StratisError::Engine(ErrorEnum::Error, err_msg))
            } else {
                Ok(())
            }
        })?;

        let dev_uuid = bda.dev_uuid();

        // Locate the device in the metadata using its uuid. Return the device
        // metadata and whether it was a cache or a datadev.
        let (tier, &(_, bd_save)) = data_map
            .get(&dev_uuid)
            .map(|bd_save| (BlockDevTier::Data, bd_save))
            .or_else(|| {
                cache_map
                    .get(&dev_uuid)
                    .map(|bd_save| (BlockDevTier::Cache, bd_save))
            })
            .ok_or_else(|| {
                let err_msg = format!(
                        "Stratis device with device number {}, devnode {}, pool UUID {} and device UUID {} had no record in pool metadata",
                        device,
                        devnode.display(),
                        bda.pool_uuid(),
                        bda.dev_uuid()
                    );
                StratisError::Engine(ErrorEnum::NotFound, err_msg)
            })?;

        // This should always succeed since the actual size is at
        // least the recorded size, so all segments should be
        // available to be allocated. If this fails, the most likely
        // conclusion is metadata corruption.
        let segments = segment_table.get(&dev_uuid);
        Ok((
            tier,
            StratBlockDev::new(
                device,
                devnode.to_owned(),
                bda,
                segments.unwrap_or(&vec![]),
                bd_save.user_info.clone(),
                bd_save.hardware_info.clone(),
            )?,
        ))
    }

    let (mut datadevs, mut cachedevs): (Vec<StratBlockDev>, Vec<StratBlockDev>) = (vec![], vec![]);
    for (device, devnode) in devnodes {
        let bda = BDA::load(&mut OpenOptions::new().read(true).open(devnode)?)?.ok_or_else(|| {
            StratisError::Engine(ErrorEnum::NotFound,
                                                 format!("Device {} with devnode {} was previously determined to belong to pool with uuid {} but no BDA was found",
                                                 device,
                                                 devnode.display(),
                                                 pool_uuid))
        })?;

        get_blockdev(
            *device,
            devnode,
            bda,
            &recorded_data_map,
            &recorded_cache_map,
            &segment_table,
        ).map(|(tier, blockdev)| {
            match tier {
                BlockDevTier::Data => &mut datadevs,
                BlockDevTier::Cache => &mut cachedevs,
            }.push(blockdev)
        })?;
    }

    // Verify that devices located are congruent with the metadata recorded
    // and generally consistent with expectations. If all seems correct,
    // sort the devices according to their order in the metadata.
    fn check_and_sort_devs(
        mut devs: Vec<StratBlockDev>,
        dev_map: &HashMap<DevUuid, (usize, &BlockDevSave)>,
    ) -> StratisResult<Vec<StratBlockDev>> {
        let mut uuids = HashSet::new();
        let mut duplicate_uuids = Vec::new();
        for dev in &devs {
            let dev_uuid = dev.uuid();
            if !uuids.insert(dev_uuid) {
                duplicate_uuids.push(dev_uuid);
            }
        }

        if !duplicate_uuids.is_empty() {
            let err_msg = format!(
                "The following list of Stratis UUIDs were each claimed by more than one Stratis device: {:?}",
                duplicate_uuids
            );
            return Err(StratisError::Engine(ErrorEnum::Invalid, err_msg.into()));
        }

        let recorded_uuids: HashSet<_> = dev_map.keys().cloned().collect();
        if uuids != recorded_uuids {
            let err_msg = format!(
                "UUIDs of devices found ({:?}) did not correspond with UUIDs specified in the metadata for this group of devices ({:?})",
                uuids,
                recorded_uuids
            );
            return Err(StratisError::Engine(ErrorEnum::Invalid, err_msg.into()));
        }

        // Sort the devices according to their original location in the
        // metadata. Use a faster unstable sort, because the order of
        // devs before the sort is arbitrary and does not need to be
        // preserved.
        devs.sort_unstable_by_key(|dev| dev_map[&dev.uuid()].0);
        Ok(devs)
    }

    let datadevs = check_and_sort_devs(datadevs, &recorded_data_map)?;
    let cachedevs = check_and_sort_devs(cachedevs, &recorded_cache_map)?;

    Ok((datadevs, cachedevs))
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Code for interacting with the system's VGA buffer.
#![crate_name = "sos_vga"]

#![feature( no_std
          , const_fn
          , core_slice_ext
          , core_str_ext
          , slice_patterns
          , unique
          )]
#![cfg_attr( feature = "system_term"
           , feature(lang_items) )]
#![no_std]

#[cfg(feature = "system_term")]
extern crate spin;

use core::mem;
use core::fmt::{Write, Result};
use core::ptr::Unique;

#[cfg(feature = "system_term")]
use spin::Mutex;

/// The system's global VGA terminal
#[cfg(feature = "system_term")]
pub static CONSOLE: Mutex<Terminal>
    = Mutex::new(unsafe { Terminal::new(
         Palette::new(Color::LightGreen, Color::Black )
       , 0xB8000
    )});

// TODO: support varying VGA screen sizes?
pub const X_MAX: usize = 80;
pub const Y_MAX: usize = 25;

/// The type signature fot the actual VGA buffer
pub type Buffer = [[Char; X_MAX]; Y_MAX];

const ANSI_ESCAPE: &'static str = "\x1b";
const FG_MASK: u8 = 0b0000_1111;
const BG_MASK: u8 = 0b1111_0000;

/// VGA color codes
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
#[repr(u8)]
pub enum Color { Black = 0
               , Blue = 1
               , Green = 2
               , Cyan = 3
               , Red = 4
               , Magenta = 5
               , Brown = 6
               , LightGrey = 7
               , DarkGrey = 8
               , LightBlue = 9
               , LightGreen = 10
               , LightCyan = 11
               , LightRed = 12
               , LightMagenta = 13
               , Yellow = 14
               , White = 15
               }

#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
pub struct Palette(u8);

impl Palette {
    /// Returns a `Palette` with the given foreground and background color.
    pub const fn new(fg: Color, bg: Color) -> Self {
        Palette( (bg as u8) << 4 | (fg as u8) )
    }

    /// Returns a new `Palette` with this palette's background color, and
    /// the specified foreground color.
    pub fn set_foreground(&self, fg: Color) -> Self {
        Palette( ( self.0 & BG_MASK) | (fg as u8 & FG_MASK) )
    }

    /// Returns a new `Palette` with this palette's foreground color, and
    /// the specified background color.
    pub fn set_background(&self, bg: Color) -> Self {
        Palette( ( (bg as u8) << 4 & BG_MASK) | (self.0 & FG_MASK) )
    }

    /// Returns this `Palette`'s foreground color.
    pub fn foreground(&self) -> Color {
        unsafe { mem::transmute(self.0 & FG_MASK) }
    }

    /// Returns this `Palette`'s background color.
    pub fn background(&self) -> Color {
        unsafe { mem::transmute((self.0 & BG_MASK) >> 4) }
    }

}
/// A colored VGA character.
#[derive(Copy, Clone)]
#[repr(C)]
pub struct Char { pub ascii: u8
                , pub colors: Palette
                }

pub struct Terminal { buffer: Unique<Buffer>
                    , x: usize
                    , y: usize
                    , colors: Palette
                    }
impl Terminal {

    /// Constructs a new `Terminal` for abuffer starting at the given address.
    ///
    /// # Arguments:
    ///   - `colors`: the default color palette for the terminal
    ///   - `buffer_start`: the address of the to the memory location where
    ///      the terminal's VGA buffer begins
    ///
    /// # Unsafe due to:
    ///   - Casting a raw address to an array
    pub const unsafe fn new(colors: Palette, buffer_start: usize)
                            -> Terminal {
        Terminal { x: 0, y: 0
                 , colors: colors
                 , buffer: Unique::new(buffer_start as *mut _)
                 }
    }

    #[inline]
    fn buffer(&mut self) -> &mut  Buffer {
        unsafe { self.buffer.get_mut() }
    }

    /// Set the color palette used for writing subsequent characters.
    pub fn set_colors(&mut self, bg: Color, fg: Color) -> &mut Self {
        self.colors = Palette::new(bg,fg);
        self
    }

    /// Scrolls the terminal one row.
    fn scroll(&mut self) {
        // construct an iterator over the whole buffer
        let mut rows = self.buffer()
                           .iter_mut();

        // the current row in the buffer
        let mut current = rows.next()
                           .unwrap();

        while let Some(next) = rows.next() {
            // while there are rows remaining in the iterator, swap the
            // next row with the current one (moving it back by one)
            mem::swap(current, next);
            // and advance our pointer to the current row.
            current = next;
        }

        // empty the last line in the buffer
        unsafe { *current = mem::zeroed() }
    }

    /// Clear the terminal
    pub fn clear(&mut self) -> &mut Self {
        // to clear the terminal, we just zero out the whole buffer.
        unsafe { *(self.buffer()) = mem::zeroed(); }
        self
    }

    /// Write the given byte to the terminal, and advance the cursor position.
    pub fn write_byte(&mut self, byte: u8) -> &mut Self {
        if byte == b'\n' {
            // if the byte is a newline, we just advance to the next line
            // and reset the column position.
            self.x = 0;
            self.y += 1;
        } else {
            // otherwise, it's a regular character, so we just set the
            // byte at the current position in the buffer to that
            // character (with the current color palette)
            self.buffer()[self.y][self.x]
                = Char { ascii: byte
                       , colors: self.colors };
            // and advance our column position by one
            self.x += 1;

            if self.x >= X_MAX {
                // if we've reached the end of the line, advance to the next
                self.x = 0;
                self.y += 1;
            }
        }
        if self.y >= Y_MAX {
            // if we've reached the bottom of the terminal, scroll.
            self.scroll();
            self.y = Y_MAX- 1;
        }
        self
    }

    fn handle_ansi_escape(&self, escape_code: &str) -> Result {
        match escape_code.as_bytes() {
            // `\x1b[3Nm` sets the foreground color to N.
            [0x1b, b'[', b'3', n, b'm'] => {
                unsafe { self.colors
                             .set_foreground(mem::transmute(n - 48)); }
                Ok(())
            }
            // `\x1b[4Nm` sets the background color to N
          , [0x1b, b'[', b'4', n, b'm'] => {
                unsafe { self.colors
                             .set_background(mem::transmute(n - 48)); }
                Ok(())
            }
          , _ => unimplemented!()
        }
        // let escape_seq: &str = bytes.take_while(|b| b != b'm')
        //                       .collect::<&str>();
        // match escape_seq {
        //     [b'3', n] => unsafe {
        //         self.colors.set_foreground(mem::transmute(n - 48))
        //     }
        // }
        // while let Some(byte) = bytes.next() {
        //     match *byte {
        //         // we've recieved an ANSI escape sequence.
        //         // this basically enters a mediocre FSM for matching ANSI
        //         // control codes.
        //         0x1b => match *next_ansi_byte!(bytes) {
        //             // handle multi-char ANSI escapes
        //             b'[' => match *next_ansi_byte!(bytes) {
        //                 // foreground color code
        //                 fg @ 30 ... 37 => {
        //                     if !(*next_ansi_byte!(bytes) == b'm') {
        //                         unsafe {
        //                             let color: vga::Color
        //                                 = mem::transmute(fg - 30);
        //                             self.colors
        //                                 .set_foreground(color);
        //                         }
        //
        //                     }
        //                 }
        //                 // background color code
        //               , 40 ... 47 => {
        //
        //                 }
        //               , _ => unimplemented!()
        //             }
        //           , _    => unimplemented!()
        //         }
        //         // otherwise, treat the byte as a normal ASCII char
        //       , b => { self.write_byte(b); }
        //     }
        // }

    }

}

struct AnsiEscapeIter<'a> { curr_slice: &'a str
                          , in_escape: bool
                          }

impl<'a> AnsiEscapeIter<'a> {

    pub fn new(s: &'a str) -> Self {
        AnsiEscapeIter { curr_slice: s
                       , in_escape: false
                       }
    }
}

impl<'a> Iterator for AnsiEscapeIter<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<Self::Item> {
        if self.curr_slice.len() == 0 {
            // if the remaining string is empty, we just return `None`
            None
        } else {
            // otherwise, find the next index to chunk on.
            let maybe_idx
                = if self.in_escape {
                     // if we're in an escape code, we split the chunk at the
                     // index of the next 'm' character, adding 1 so that the
                     // 'm' is in the escape code chunk.
                    self.curr_slice.find('m')
                        .map(|idx| idx + 1)
                } else {
                    // otherwise, split at the next ANSI escape sequence
                    self.curr_slice.find(ANSI_ESCAPE)
                };

            // if we found another index to chunk on, map over that index;
            // otherwise, we just yield the rest of the string
            maybe_idx.map_or(
                Some(self.curr_slice) // remainder (if no index to chunk on)
              , |idx| { // otherwise, chunk along that index...
                    let (chunk, next_slice) = self.curr_slice
                                                  .split_at(idx);
                    self.curr_slice = next_slice; // update current chunk
                    Some(chunk)                   // return the chunk
                })
        }

    }
}

impl Write for Terminal {

    fn write_str(&mut self, s: &str) -> Result {

        if s.contains(ANSI_ESCAPE) {
            // if the segment contains an ANSI escape, construct an iterator
            // over each chunk containing either an escape sequence or text
            for segment in AnsiEscapeIter::new(s) {
                if segment.starts_with(ANSI_ESCAPE) {
                    // if the current segment is an ANSI escape code,
                    // try to handle the escape and fail if it is malformed
                    try!(self.handle_ansi_escape(segment))
                } else {
                    // otherwise, just write each chunk in the string.
                    for byte in segment.as_bytes() {
                        self.write_byte(*byte);
                    }
                }
            }
        } else {
            // otherwise, if there are no ANSI escape codes,
            // we can just write each byte in the string.
            for byte in s.as_bytes() {
                self.write_byte(*byte);
            }
        }
        Ok(())
    }

}

#[cfg(feature = "system_term")]
#[macro_export]
macro_rules! println {
    ($fmt:expr) => (print!(concat!($fmt, "\n")));
    ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
}

#[cfg(feature = "system_term")]
#[macro_export]
macro_rules! print {
    ($($arg:tt)*) => ({
            use core::fmt::Write;
            $crate::CONSOLE.lock()
                           .write_fmt(format_args!($($arg)*))
                           .unwrap();
    });
}

#[cfg(feature = "system_term")]
/// Required for Rust stack unwinding
#[lang = "eh_personality"]
#[no_mangle] #[inline(never)] #[cold]
pub extern "C" fn eh_personality() {
    // TODO: add support for stack unwinding
    println!("eh")
}
<commit_msg>Fix eh_personality naming issue<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Code for interacting with the system's VGA buffer.
#![crate_name = "sos_vga"]

#![feature( no_std
          , const_fn
          , core_slice_ext
          , core_str_ext
          , slice_patterns
          , unique
          )]
#![cfg_attr( feature = "system_term"
           , feature(lang_items) )]
#![no_std]

#[cfg(feature = "system_term")]
extern crate spin;

use core::mem;
use core::fmt::{Write, Result};
use core::ptr::Unique;

#[cfg(feature = "system_term")]
use spin::Mutex;

/// The system's global VGA terminal
#[cfg(feature = "system_term")]
pub static CONSOLE: Mutex<Terminal>
    = Mutex::new(unsafe { Terminal::new(
         Palette::new(Color::LightGreen, Color::Black )
       , 0xB8000
    )});

// TODO: support varying VGA screen sizes?
pub const X_MAX: usize = 80;
pub const Y_MAX: usize = 25;

/// The type signature fot the actual VGA buffer
pub type Buffer = [[Char; X_MAX]; Y_MAX];

const ANSI_ESCAPE: &'static str = "\x1b";
const FG_MASK: u8 = 0b0000_1111;
const BG_MASK: u8 = 0b1111_0000;

/// VGA color codes
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
#[repr(u8)]
pub enum Color { Black = 0
               , Blue = 1
               , Green = 2
               , Cyan = 3
               , Red = 4
               , Magenta = 5
               , Brown = 6
               , LightGrey = 7
               , DarkGrey = 8
               , LightBlue = 9
               , LightGreen = 10
               , LightCyan = 11
               , LightRed = 12
               , LightMagenta = 13
               , Yellow = 14
               , White = 15
               }

#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
pub struct Palette(u8);

impl Palette {
    /// Returns a `Palette` with the given foreground and background color.
    pub const fn new(fg: Color, bg: Color) -> Self {
        Palette( (bg as u8) << 4 | (fg as u8) )
    }

    /// Returns a new `Palette` with this palette's background color, and
    /// the specified foreground color.
    pub fn set_foreground(&self, fg: Color) -> Self {
        Palette( ( self.0 & BG_MASK) | (fg as u8 & FG_MASK) )
    }

    /// Returns a new `Palette` with this palette's foreground color, and
    /// the specified background color.
    pub fn set_background(&self, bg: Color) -> Self {
        Palette( ( (bg as u8) << 4 & BG_MASK) | (self.0 & FG_MASK) )
    }

    /// Returns this `Palette`'s foreground color.
    pub fn foreground(&self) -> Color {
        unsafe { mem::transmute(self.0 & FG_MASK) }
    }

    /// Returns this `Palette`'s background color.
    pub fn background(&self) -> Color {
        unsafe { mem::transmute((self.0 & BG_MASK) >> 4) }
    }

}
/// A colored VGA character.
#[derive(Copy, Clone)]
#[repr(C)]
pub struct Char { pub ascii: u8
                , pub colors: Palette
                }

pub struct Terminal { buffer: Unique<Buffer>
                    , x: usize
                    , y: usize
                    , colors: Palette
                    }
impl Terminal {

    /// Constructs a new `Terminal` for abuffer starting at the given address.
    ///
    /// # Arguments:
    ///   - `colors`: the default color palette for the terminal
    ///   - `buffer_start`: the address of the to the memory location where
    ///      the terminal's VGA buffer begins
    ///
    /// # Unsafe due to:
    ///   - Casting a raw address to an array
    pub const unsafe fn new(colors: Palette, buffer_start: usize)
                            -> Terminal {
        Terminal { x: 0, y: 0
                 , colors: colors
                 , buffer: Unique::new(buffer_start as *mut _)
                 }
    }

    #[inline]
    fn buffer(&mut self) -> &mut  Buffer {
        unsafe { self.buffer.get_mut() }
    }

    /// Set the color palette used for writing subsequent characters.
    pub fn set_colors(&mut self, bg: Color, fg: Color) -> &mut Self {
        self.colors = Palette::new(bg,fg);
        self
    }

    /// Scrolls the terminal one row.
    fn scroll(&mut self) {
        // construct an iterator over the whole buffer
        let mut rows = self.buffer()
                           .iter_mut();

        // the current row in the buffer
        let mut current = rows.next()
                           .unwrap();

        while let Some(next) = rows.next() {
            // while there are rows remaining in the iterator, swap the
            // next row with the current one (moving it back by one)
            mem::swap(current, next);
            // and advance our pointer to the current row.
            current = next;
        }

        // empty the last line in the buffer
        unsafe { *current = mem::zeroed() }
    }

    /// Clear the terminal
    pub fn clear(&mut self) -> &mut Self {
        // to clear the terminal, we just zero out the whole buffer.
        unsafe { *(self.buffer()) = mem::zeroed(); }
        self
    }

    /// Write the given byte to the terminal, and advance the cursor position.
    pub fn write_byte(&mut self, byte: u8) -> &mut Self {
        if byte == b'\n' {
            // if the byte is a newline, we just advance to the next line
            // and reset the column position.
            self.x = 0;
            self.y += 1;
        } else {
            // otherwise, it's a regular character, so we just set the
            // byte at the current position in the buffer to that
            // character (with the current color palette)
            self.buffer()[self.y][self.x]
                = Char { ascii: byte
                       , colors: self.colors };
            // and advance our column position by one
            self.x += 1;

            if self.x >= X_MAX {
                // if we've reached the end of the line, advance to the next
                self.x = 0;
                self.y += 1;
            }
        }
        if self.y >= Y_MAX {
            // if we've reached the bottom of the terminal, scroll.
            self.scroll();
            self.y = Y_MAX- 1;
        }
        self
    }

    fn handle_ansi_escape(&self, escape_code: &str) -> Result {
        match escape_code.as_bytes() {
            // `\x1b[3Nm` sets the foreground color to N.
            [0x1b, b'[', b'3', n, b'm'] => {
                unsafe { self.colors
                             .set_foreground(mem::transmute(n - 48)); }
                Ok(())
            }
            // `\x1b[4Nm` sets the background color to N
          , [0x1b, b'[', b'4', n, b'm'] => {
                unsafe { self.colors
                             .set_background(mem::transmute(n - 48)); }
                Ok(())
            }
          , _ => unimplemented!()
        }
        // let escape_seq: &str = bytes.take_while(|b| b != b'm')
        //                       .collect::<&str>();
        // match escape_seq {
        //     [b'3', n] => unsafe {
        //         self.colors.set_foreground(mem::transmute(n - 48))
        //     }
        // }
        // while let Some(byte) = bytes.next() {
        //     match *byte {
        //         // we've recieved an ANSI escape sequence.
        //         // this basically enters a mediocre FSM for matching ANSI
        //         // control codes.
        //         0x1b => match *next_ansi_byte!(bytes) {
        //             // handle multi-char ANSI escapes
        //             b'[' => match *next_ansi_byte!(bytes) {
        //                 // foreground color code
        //                 fg @ 30 ... 37 => {
        //                     if !(*next_ansi_byte!(bytes) == b'm') {
        //                         unsafe {
        //                             let color: vga::Color
        //                                 = mem::transmute(fg - 30);
        //                             self.colors
        //                                 .set_foreground(color);
        //                         }
        //
        //                     }
        //                 }
        //                 // background color code
        //               , 40 ... 47 => {
        //
        //                 }
        //               , _ => unimplemented!()
        //             }
        //           , _    => unimplemented!()
        //         }
        //         // otherwise, treat the byte as a normal ASCII char
        //       , b => { self.write_byte(b); }
        //     }
        // }

    }

}

struct AnsiEscapeIter<'a> { curr_slice: &'a str
                          , in_escape: bool
                          }

impl<'a> AnsiEscapeIter<'a> {

    pub fn new(s: &'a str) -> Self {
        AnsiEscapeIter { curr_slice: s
                       , in_escape: false
                       }
    }
}

impl<'a> Iterator for AnsiEscapeIter<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<Self::Item> {
        if self.curr_slice.len() == 0 {
            // if the remaining string is empty, we just return `None`
            None
        } else {
            // otherwise, find the next index to chunk on.
            let maybe_idx
                = if self.in_escape {
                     // if we're in an escape code, we split the chunk at the
                     // index of the next 'm' character, adding 1 so that the
                     // 'm' is in the escape code chunk.
                    self.curr_slice.find('m')
                        .map(|idx| idx + 1)
                } else {
                    // otherwise, split at the next ANSI escape sequence
                    self.curr_slice.find(ANSI_ESCAPE)
                };

            // if we found another index to chunk on, map over that index;
            // otherwise, we just yield the rest of the string
            maybe_idx.map_or(
                Some(self.curr_slice) // remainder (if no index to chunk on)
              , |idx| { // otherwise, chunk along that index...
                    let (chunk, next_slice) = self.curr_slice
                                                  .split_at(idx);
                    self.curr_slice = next_slice; // update current chunk
                    Some(chunk)                   // return the chunk
                })
        }

    }
}

impl Write for Terminal {

    fn write_str(&mut self, s: &str) -> Result {

        if s.contains(ANSI_ESCAPE) {
            // if the segment contains an ANSI escape, construct an iterator
            // over each chunk containing either an escape sequence or text
            for segment in AnsiEscapeIter::new(s) {
                if segment.starts_with(ANSI_ESCAPE) {
                    // if the current segment is an ANSI escape code,
                    // try to handle the escape and fail if it is malformed
                    try!(self.handle_ansi_escape(segment))
                } else {
                    // otherwise, just write each chunk in the string.
                    for byte in segment.as_bytes() {
                        self.write_byte(*byte);
                    }
                }
            }
        } else {
            // otherwise, if there are no ANSI escape codes,
            // we can just write each byte in the string.
            for byte in s.as_bytes() {
                self.write_byte(*byte);
            }
        }
        Ok(())
    }

}

#[cfg(feature = "system_term")]
#[macro_export]
macro_rules! println {
    ($fmt:expr) => (print!(concat!($fmt, "\n")));
    ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
}

#[cfg(feature = "system_term")]
#[macro_export]
macro_rules! print {
    ($($arg:tt)*) => ({
            use core::fmt::Write;
            $crate::CONSOLE.lock()
                           .write_fmt(format_args!($($arg)*))
                           .unwrap();
    });
}

/// Required for Rust stack unwinding
#[cfg(feature = "system_term")]
#[lang = "eh_personality"]
#[no_mangle] #[inline(never)] #[cold]
pub extern "C" fn rust_eh_personality() {
    // TODO: add support for stack unwinding
    println!("eh")
}
<|endoftext|>


<commit_before>// Copyright 2014 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.

//! A module for working with borrowed data.
//!
//! # The `BorrowFrom` traits
//!
//! In general, there may be several ways to "borrow" a piece of data.  The
//! typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
//! (a mutable borrow). But types like `Vec<T>` provide additional kinds of
//! borrows: the borrowed slices `&[T]` and `&mut [T]`.
//!
//! When writing generic code, it is often desirable to abstract over all ways
//! of borrowing data from a given type. That is the role of the `BorrowFrom`
//! trait: if `T: BorrowFrom<U>`, then `&T` can be borrowed from `&U`.  A given
//! type can be borrowed as multiple different types. In particular, `Vec<T>:
//! BorrowFrom<Vec<T>>` and `[T]: BorrowFrom<Vec<T>>`.
//!
//! # The `ToOwned` trait
//!
//! Some types make it possible to go from borrowed to owned, usually by
//! implementing the `Clone` trait. But `Clone` works only for going from `&T`
//! to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
//! from any borrow of a given type.
//!
//! # The `Cow` (clone-on-write) type
//!
//! The type `Cow` is a smart pointer providing clone-on-write functionality: it
//! can enclose and provide immutable access to borrowed data, and clone the
//! data lazily when mutation or ownership is required. The type is designed to
//! work with general borrowed data via the `BorrowFrom` trait.
//!
//! `Cow` implements both `Deref`, which means that you can call
//! non-mutating methods directly on the data it encloses. If mutation
//! is desired, `to_mut` will obtain a mutable references to an owned
//! value, cloning if necessary.

#![unstable = "recently added as part of collections reform"]

use clone::Clone;
use cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use fmt;
use kinds::Sized;
use ops::Deref;
use option::Option;
use self::Cow::*;

/// A trait for borrowing data.
pub trait BorrowFrom<Sized? Owned> for Sized? {
    /// Immutably borrow from an owned value.
    fn borrow_from(owned: &Owned) -> &Self;
}

/// A trait for mutably borrowing data.
pub trait BorrowFromMut<Sized? Owned> for Sized? : BorrowFrom<Owned> {
    /// Mutably borrow from an owned value.
    fn borrow_from_mut(owned: &mut Owned) -> &mut Self;
}

impl<Sized? T> BorrowFrom<T> for T {
    fn borrow_from(owned: &T) -> &T { owned }
}

impl<Sized? T> BorrowFromMut<T> for T {
    fn borrow_from_mut(owned: &mut T) -> &mut T { owned }
}

impl<'a, Sized? T> BorrowFrom<&'a T> for T {
    fn borrow_from<'b>(owned: &'b &'a T) -> &'b T { &**owned }
}

impl<'a, Sized? T> BorrowFrom<&'a mut T> for T {
    fn borrow_from<'b>(owned: &'b &'a mut T) -> &'b T { &**owned }
}

impl<'a, Sized? T> BorrowFromMut<&'a mut T> for T {
    fn borrow_from_mut<'b>(owned: &'b mut &'a mut T) -> &'b mut T { &mut **owned }
}

impl<'a, T, Sized? B> BorrowFrom<Cow<'a, T, B>> for B where B: ToOwned<T> {
    fn borrow_from<'b>(owned: &'b Cow<'a, T, B>) -> &'b B {
        &**owned
    }
}

/// Trait for moving into a `Cow`
pub trait IntoCow<'a, T, Sized? B> {
    /// Moves `self` into `Cow`
    fn into_cow(self) -> Cow<'a, T, B>;
}

impl<'a, T, Sized? B> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned<T> {
    fn into_cow(self) -> Cow<'a, T, B> {
        self
    }
}

/// A generalization of Clone to borrowed data.
pub trait ToOwned<Owned> for Sized?: BorrowFrom<Owned> {
    /// Create owned data from borrowed data, usually by copying.
    fn to_owned(&self) -> Owned;
}

impl<T> ToOwned<T> for T where T: Clone {
    fn to_owned(&self) -> T { self.clone() }
}

/// A clone-on-write smart pointer.
///
/// # Example
///
/// ```rust
/// use std::borrow::Cow;
///
/// fn abs_all(input: &mut Cow<Vec<int>, [int]>) {
///     for i in range(0, input.len()) {
///         let v = input[i];
///         if v < 0 {
///             // clones into a vector the first time (if not already owned)
///             input.to_mut()[i] = -v;
///         }
///     }
/// }
/// ```
pub enum Cow<'a, T, Sized? B: 'a> where B: ToOwned<T> {
    /// Borrowed data.
    Borrowed(&'a B),

    /// Owned data.
    Owned(T)
}

impl<'a, T, Sized? B> Cow<'a, T, B> where B: ToOwned<T> {
    /// Acquire a mutable reference to the owned form of the data.
    ///
    /// Copies the data if it is not already owned.
    pub fn to_mut(&mut self) -> &mut T {
        match *self {
            Borrowed(borrowed) => {
                *self = Owned(borrowed.to_owned());
                self.to_mut()
            }
            Owned(ref mut owned) => owned
        }
    }

    /// Extract the owned data.
    ///
    /// Copies the data if it is not already owned.
    pub fn into_owned(self) -> T {
        match self {
            Borrowed(borrowed) => borrowed.to_owned(),
            Owned(owned) => owned
        }
    }

    /// Returns true if this `Cow` wraps a borrowed value
    pub fn is_borrowed(&self) -> bool {
        match *self {
            Borrowed(_) => true,
            _ => false,
        }
    }

    /// Returns true if this `Cow` wraps an owned value
    pub fn is_owned(&self) -> bool {
        match *self {
            Owned(_) => true,
            _ => false,
        }
    }
}

impl<'a, T, Sized? B> Deref<B> for Cow<'a, T, B> where B: ToOwned<T>  {
    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => BorrowFrom::borrow_from(owned)
        }
    }
}

impl<'a, T, Sized? B> Eq for Cow<'a, T, B> where B: Eq + ToOwned<T> {}

impl<'a, T, Sized? B> Ord for Cow<'a, T, B> where B: Ord + ToOwned<T> {
    #[inline]
    fn cmp(&self, other: &Cow<'a, T, B>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

impl<'a, 'b, T, U, Sized? B, Sized? C> PartialEq<Cow<'b, U, C>> for Cow<'a, T, B> where
    B: PartialEq<C> + ToOwned<T>,
    C: ToOwned<U>,
{
    #[inline]
    fn eq(&self, other: &Cow<'b, U, C>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

impl<'a, T, Sized? B> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwned<T> {
    #[inline]
    fn partial_cmp(&self, other: &Cow<'a, T, B>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
}

impl<'a, T, Sized? B> fmt::Show for Cow<'a, T, B> where B: fmt::Show + ToOwned<T>, T: fmt::Show {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Show::fmt(b, f),
            Owned(ref o) => fmt::Show::fmt(o, f),
        }
    }
}
<commit_msg>rollup merge of #19359: japaric/clone-cow<commit_after>// Copyright 2014 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.

//! A module for working with borrowed data.
//!
//! # The `BorrowFrom` traits
//!
//! In general, there may be several ways to "borrow" a piece of data.  The
//! typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
//! (a mutable borrow). But types like `Vec<T>` provide additional kinds of
//! borrows: the borrowed slices `&[T]` and `&mut [T]`.
//!
//! When writing generic code, it is often desirable to abstract over all ways
//! of borrowing data from a given type. That is the role of the `BorrowFrom`
//! trait: if `T: BorrowFrom<U>`, then `&T` can be borrowed from `&U`.  A given
//! type can be borrowed as multiple different types. In particular, `Vec<T>:
//! BorrowFrom<Vec<T>>` and `[T]: BorrowFrom<Vec<T>>`.
//!
//! # The `ToOwned` trait
//!
//! Some types make it possible to go from borrowed to owned, usually by
//! implementing the `Clone` trait. But `Clone` works only for going from `&T`
//! to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
//! from any borrow of a given type.
//!
//! # The `Cow` (clone-on-write) type
//!
//! The type `Cow` is a smart pointer providing clone-on-write functionality: it
//! can enclose and provide immutable access to borrowed data, and clone the
//! data lazily when mutation or ownership is required. The type is designed to
//! work with general borrowed data via the `BorrowFrom` trait.
//!
//! `Cow` implements both `Deref`, which means that you can call
//! non-mutating methods directly on the data it encloses. If mutation
//! is desired, `to_mut` will obtain a mutable references to an owned
//! value, cloning if necessary.

#![unstable = "recently added as part of collections reform"]

use clone::Clone;
use cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use fmt;
use kinds::Sized;
use ops::Deref;
use option::Option;
use self::Cow::*;

/// A trait for borrowing data.
pub trait BorrowFrom<Sized? Owned> for Sized? {
    /// Immutably borrow from an owned value.
    fn borrow_from(owned: &Owned) -> &Self;
}

/// A trait for mutably borrowing data.
pub trait BorrowFromMut<Sized? Owned> for Sized? : BorrowFrom<Owned> {
    /// Mutably borrow from an owned value.
    fn borrow_from_mut(owned: &mut Owned) -> &mut Self;
}

impl<Sized? T> BorrowFrom<T> for T {
    fn borrow_from(owned: &T) -> &T { owned }
}

impl<Sized? T> BorrowFromMut<T> for T {
    fn borrow_from_mut(owned: &mut T) -> &mut T { owned }
}

impl<'a, Sized? T> BorrowFrom<&'a T> for T {
    fn borrow_from<'b>(owned: &'b &'a T) -> &'b T { &**owned }
}

impl<'a, Sized? T> BorrowFrom<&'a mut T> for T {
    fn borrow_from<'b>(owned: &'b &'a mut T) -> &'b T { &**owned }
}

impl<'a, Sized? T> BorrowFromMut<&'a mut T> for T {
    fn borrow_from_mut<'b>(owned: &'b mut &'a mut T) -> &'b mut T { &mut **owned }
}

impl<'a, T, Sized? B> BorrowFrom<Cow<'a, T, B>> for B where B: ToOwned<T> {
    fn borrow_from<'b>(owned: &'b Cow<'a, T, B>) -> &'b B {
        &**owned
    }
}

/// Trait for moving into a `Cow`
pub trait IntoCow<'a, T, Sized? B> {
    /// Moves `self` into `Cow`
    fn into_cow(self) -> Cow<'a, T, B>;
}

impl<'a, T, Sized? B> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned<T> {
    fn into_cow(self) -> Cow<'a, T, B> {
        self
    }
}

/// A generalization of Clone to borrowed data.
pub trait ToOwned<Owned> for Sized?: BorrowFrom<Owned> {
    /// Create owned data from borrowed data, usually by copying.
    fn to_owned(&self) -> Owned;
}

impl<T> ToOwned<T> for T where T: Clone {
    fn to_owned(&self) -> T { self.clone() }
}

/// A clone-on-write smart pointer.
///
/// # Example
///
/// ```rust
/// use std::borrow::Cow;
///
/// fn abs_all(input: &mut Cow<Vec<int>, [int]>) {
///     for i in range(0, input.len()) {
///         let v = input[i];
///         if v < 0 {
///             // clones into a vector the first time (if not already owned)
///             input.to_mut()[i] = -v;
///         }
///     }
/// }
/// ```
pub enum Cow<'a, T, Sized? B: 'a> where B: ToOwned<T> {
    /// Borrowed data.
    Borrowed(&'a B),

    /// Owned data.
    Owned(T)
}

impl<'a, T, Sized? B> Clone for Cow<'a, T, B> where B: ToOwned<T> {
    fn clone(&self) -> Cow<'a, T, B> {
        match *self {
            Borrowed(b) => Borrowed(b),
            Owned(ref o) => {
                let b: &B = BorrowFrom::borrow_from(o);
                Owned(b.to_owned())
            },
        }
    }
}

impl<'a, T, Sized? B> Cow<'a, T, B> where B: ToOwned<T> {
    /// Acquire a mutable reference to the owned form of the data.
    ///
    /// Copies the data if it is not already owned.
    pub fn to_mut(&mut self) -> &mut T {
        match *self {
            Borrowed(borrowed) => {
                *self = Owned(borrowed.to_owned());
                self.to_mut()
            }
            Owned(ref mut owned) => owned
        }
    }

    /// Extract the owned data.
    ///
    /// Copies the data if it is not already owned.
    pub fn into_owned(self) -> T {
        match self {
            Borrowed(borrowed) => borrowed.to_owned(),
            Owned(owned) => owned
        }
    }

    /// Returns true if this `Cow` wraps a borrowed value
    pub fn is_borrowed(&self) -> bool {
        match *self {
            Borrowed(_) => true,
            _ => false,
        }
    }

    /// Returns true if this `Cow` wraps an owned value
    pub fn is_owned(&self) -> bool {
        match *self {
            Owned(_) => true,
            _ => false,
        }
    }
}

impl<'a, T, Sized? B> Deref<B> for Cow<'a, T, B> where B: ToOwned<T>  {
    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => BorrowFrom::borrow_from(owned)
        }
    }
}

impl<'a, T, Sized? B> Eq for Cow<'a, T, B> where B: Eq + ToOwned<T> {}

impl<'a, T, Sized? B> Ord for Cow<'a, T, B> where B: Ord + ToOwned<T> {
    #[inline]
    fn cmp(&self, other: &Cow<'a, T, B>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

impl<'a, 'b, T, U, Sized? B, Sized? C> PartialEq<Cow<'b, U, C>> for Cow<'a, T, B> where
    B: PartialEq<C> + ToOwned<T>,
    C: ToOwned<U>,
{
    #[inline]
    fn eq(&self, other: &Cow<'b, U, C>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

impl<'a, T, Sized? B> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwned<T> {
    #[inline]
    fn partial_cmp(&self, other: &Cow<'a, T, B>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
}

impl<'a, T, Sized? B> fmt::Show for Cow<'a, T, B> where B: fmt::Show + ToOwned<T>, T: fmt::Show {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Show::fmt(b, f),
            Owned(ref o) => fmt::Show::fmt(o, f),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 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.

//! A double-ended queue implemented as a circular buffer

use core::prelude::*;

use core::util::replace;

static initial_capacity: uint = 32u; // 2^5

pub struct Deque<T> {
    priv nelts: uint,
    priv lo: uint,
    priv hi: uint,
    priv elts: ~[Option<T>]
}

impl<T> Container for Deque<T> {
    /// Return the number of elements in the deque
    fn len(&const self) -> uint { self.nelts }

    /// Return true if the deque contains no elements
    fn is_empty(&const self) -> bool { self.len() == 0 }
}

impl<T> Mutable for Deque<T> {
    /// Clear the deque, removing all values.
    fn clear(&mut self) {
        for self.elts.each_mut |x| { *x = None }
        self.nelts = 0;
        self.lo = 0;
        self.hi = 0;
    }
}

pub impl<T> Deque<T> {
    /// Create an empty Deque
    fn new() -> Deque<T> {
        Deque{nelts: 0, lo: 0, hi: 0,
              elts: vec::from_fn(initial_capacity, |_| None)}
    }

    /// Return a reference to the first element in the deque
    ///
    /// Fails if the deque is empty
    fn peek_front<'a>(&'a self) -> &'a T { get(self.elts, self.lo) }

    /// Return a reference to the last element in the deque
    ///
    /// Fails if the deque is empty
    fn peek_back<'a>(&'a self) -> &'a T { get(self.elts, self.hi - 1u) }

    /// Retrieve an element in the deque by index
    ///
    /// Fails if there is no element with the given index
    fn get<'a>(&'a self, i: int) -> &'a T {
        let idx = (self.lo + (i as uint)) % self.elts.len();
        get(self.elts, idx)
    }

    /// Iterate over the elements in the deque
    fn each(&self, f: &fn(&T) -> bool) -> bool {
        self.eachi(|_i, e| f(e))
    }

    /// Iterate over the elements in the deque by index
    fn eachi(&self, f: &fn(uint, &T) -> bool) -> bool {
        uint::range(0, self.nelts, |i| f(i, self.get(i as int)))
    }

    /// Remove and return the first element in the deque
    ///
    /// Fails if the deque is empty
    fn pop_front(&mut self) -> T {
        let result = self.elts[self.lo].swap_unwrap();
        self.lo = (self.lo + 1u) % self.elts.len();
        self.nelts -= 1u;
        result
    }

    /// Remove and return the last element in the deque
    ///
    /// Fails if the deque is empty
    fn pop_back(&mut self) -> T {
        if self.hi == 0u {
            self.hi = self.elts.len() - 1u;
        } else { self.hi -= 1u; }
        let result = self.elts[self.hi].swap_unwrap();
        self.elts[self.hi] = None;
        self.nelts -= 1u;
        result
    }

    /// Prepend an element to the deque
    fn add_front(&mut self, t: T) {
        let oldlo = self.lo;
        if self.lo == 0u {
            self.lo = self.elts.len() - 1u;
        } else { self.lo -= 1u; }
        if self.lo == self.hi {
            self.elts = grow(self.nelts, oldlo, self.elts);
            self.lo = self.elts.len() - 1u;
            self.hi = self.nelts;
        }
        self.elts[self.lo] = Some(t);
        self.nelts += 1u;
    }

    /// Append an element to the deque
    fn add_back(&mut self, t: T) {
        if self.lo == self.hi && self.nelts != 0u {
            self.elts = grow(self.nelts, self.lo, self.elts);
            self.lo = 0u;
            self.hi = self.nelts;
        }
        self.elts[self.hi] = Some(t);
        self.hi = (self.hi + 1u) % self.elts.len();
        self.nelts += 1u;
    }
}

/// Grow is only called on full elts, so nelts is also len(elts), unlike
/// elsewhere.
fn grow<T>(nelts: uint, lo: uint, elts: &mut [Option<T>]) -> ~[Option<T>] {
    assert_eq!(nelts, elts.len());
    let mut rv = ~[];

    do rv.grow_fn(nelts + 1) |i| {
        replace(&mut elts[(lo + i) % nelts], None)
    }

    rv
}

fn get<'r, T>(elts: &'r [Option<T>], i: uint) -> &'r T {
    match elts[i] { Some(ref t) => t, _ => fail!() }
}

#[cfg(test)]
mod tests {
    use super::*;
    use core::cmp::Eq;
    use core::kinds::Copy;

    #[test]
    fn test_simple() {
        let mut d = Deque::new();
        assert_eq!(d.len(), 0u);
        d.add_front(17);
        d.add_front(42);
        d.add_back(137);
        assert_eq!(d.len(), 3u);
        d.add_back(137);
        assert_eq!(d.len(), 4u);
        debug!(d.peek_front());
        assert_eq!(*d.peek_front(), 42);
        debug!(d.peek_back());
        assert_eq!(*d.peek_back(), 137);
        let mut i: int = d.pop_front();
        debug!(i);
        assert_eq!(i, 42);
        i = d.pop_back();
        debug!(i);
        assert_eq!(i, 137);
        i = d.pop_back();
        debug!(i);
        assert_eq!(i, 137);
        i = d.pop_back();
        debug!(i);
        assert_eq!(i, 17);
        assert_eq!(d.len(), 0u);
        d.add_back(3);
        assert_eq!(d.len(), 1u);
        d.add_front(2);
        assert_eq!(d.len(), 2u);
        d.add_back(4);
        assert_eq!(d.len(), 3u);
        d.add_front(1);
        assert_eq!(d.len(), 4u);
        debug!(d.get(0));
        debug!(d.get(1));
        debug!(d.get(2));
        debug!(d.get(3));
        assert_eq!(*d.get(0), 1);
        assert_eq!(*d.get(1), 2);
        assert_eq!(*d.get(2), 3);
        assert_eq!(*d.get(3), 4);
    }

    #[test]
    fn test_boxes() {
        let a: @int = @5;
        let b: @int = @72;
        let c: @int = @64;
        let d: @int = @175;

        let mut deq = Deque::new();
        assert_eq!(deq.len(), 0);
        deq.add_front(a);
        deq.add_front(b);
        deq.add_back(c);
        assert_eq!(deq.len(), 3);
        deq.add_back(d);
        assert_eq!(deq.len(), 4);
        assert_eq!(*deq.peek_front(), b);
        assert_eq!(*deq.peek_back(), d);
        assert_eq!(deq.pop_front(), b);
        assert_eq!(deq.pop_back(), d);
        assert_eq!(deq.pop_back(), c);
        assert_eq!(deq.pop_back(), a);
        assert_eq!(deq.len(), 0);
        deq.add_back(c);
        assert_eq!(deq.len(), 1);
        deq.add_front(b);
        assert_eq!(deq.len(), 2);
        deq.add_back(d);
        assert_eq!(deq.len(), 3);
        deq.add_front(a);
        assert_eq!(deq.len(), 4);
        assert_eq!(*deq.get(0), a);
        assert_eq!(*deq.get(1), b);
        assert_eq!(*deq.get(2), c);
        assert_eq!(*deq.get(3), d);
    }

    #[cfg(test)]
    fn test_parameterized<T:Copy + Eq>(a: T, b: T, c: T, d: T) {
        let mut deq = Deque::new();
        assert_eq!(deq.len(), 0);
        deq.add_front(a);
        deq.add_front(b);
        deq.add_back(c);
        assert_eq!(deq.len(), 3);
        deq.add_back(d);
        assert_eq!(deq.len(), 4);
        assert_eq!(*deq.peek_front(), b);
        assert_eq!(*deq.peek_back(), d);
        assert_eq!(deq.pop_front(), b);
        assert_eq!(deq.pop_back(), d);
        assert_eq!(deq.pop_back(), c);
        assert_eq!(deq.pop_back(), a);
        assert_eq!(deq.len(), 0);
        deq.add_back(c);
        assert_eq!(deq.len(), 1);
        deq.add_front(b);
        assert_eq!(deq.len(), 2);
        deq.add_back(d);
        assert_eq!(deq.len(), 3);
        deq.add_front(a);
        assert_eq!(deq.len(), 4);
        assert_eq!(*deq.get(0), a);
        assert_eq!(*deq.get(1), b);
        assert_eq!(*deq.get(2), c);
        assert_eq!(*deq.get(3), d);
    }

    #[deriving(Eq)]
    enum Taggy { One(int), Two(int, int), Three(int, int, int), }

    #[deriving(Eq)]
    enum Taggypar<T> {
        Onepar(int), Twopar(int, int), Threepar(int, int, int),
    }

    #[deriving(Eq)]
    struct RecCy {
        x: int,
        y: int,
        t: Taggy
    }

    #[test]
    fn test_param_int() {
        test_parameterized::<int>(5, 72, 64, 175);
    }

    #[test]
    fn test_param_at_int() {
        test_parameterized::<@int>(@5, @72, @64, @175);
    }

    #[test]
    fn test_param_taggy() {
        test_parameterized::<Taggy>(One(1), Two(1, 2), Three(1, 2, 3),
                                    Two(17, 42));
    }

    #[test]
    fn test_param_taggypar() {
        test_parameterized::<Taggypar<int>>(Onepar::<int>(1),
                                            Twopar::<int>(1, 2),
                                            Threepar::<int>(1, 2, 3),
                                            Twopar::<int>(17, 42));
    }

    #[test]
    fn test_param_reccy() {
        let reccy1 = RecCy { x: 1, y: 2, t: One(1) };
        let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) };
        let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) };
        let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) };
        test_parameterized::<RecCy>(reccy1, reccy2, reccy3, reccy4);
    }

    #[test]
    fn test_eachi() {
        let mut deq = Deque::new();
        deq.add_back(1);
        deq.add_back(2);
        deq.add_back(3);

        for deq.eachi |i, e| {
            assert_eq!(*e, i + 1);
        }

        deq.pop_front();

        for deq.eachi |i, e| {
            assert_eq!(*e, i + 2);
        }

    }
}
<commit_msg>extra: Add reserve and reserve_at_least to extra::deque<commit_after>// Copyright 2012-2013 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.

//! A double-ended queue implemented as a circular buffer

use core::prelude::*;

use core::util::replace;

static initial_capacity: uint = 32u; // 2^5

pub struct Deque<T> {
    priv nelts: uint,
    priv lo: uint,
    priv hi: uint,
    priv elts: ~[Option<T>]
}

impl<T> Container for Deque<T> {
    /// Return the number of elements in the deque
    fn len(&const self) -> uint { self.nelts }

    /// Return true if the deque contains no elements
    fn is_empty(&const self) -> bool { self.len() == 0 }
}

impl<T> Mutable for Deque<T> {
    /// Clear the deque, removing all values.
    fn clear(&mut self) {
        for self.elts.each_mut |x| { *x = None }
        self.nelts = 0;
        self.lo = 0;
        self.hi = 0;
    }
}

pub impl<T> Deque<T> {
    /// Create an empty Deque
    fn new() -> Deque<T> {
        Deque{nelts: 0, lo: 0, hi: 0,
              elts: vec::from_fn(initial_capacity, |_| None)}
    }

    /// Return a reference to the first element in the deque
    ///
    /// Fails if the deque is empty
    fn peek_front<'a>(&'a self) -> &'a T { get(self.elts, self.lo) }

    /// Return a reference to the last element in the deque
    ///
    /// Fails if the deque is empty
    fn peek_back<'a>(&'a self) -> &'a T { get(self.elts, self.hi - 1u) }

    /// Retrieve an element in the deque by index
    ///
    /// Fails if there is no element with the given index
    fn get<'a>(&'a self, i: int) -> &'a T {
        let idx = (self.lo + (i as uint)) % self.elts.len();
        get(self.elts, idx)
    }

    /// Iterate over the elements in the deque
    fn each(&self, f: &fn(&T) -> bool) -> bool {
        self.eachi(|_i, e| f(e))
    }

    /// Iterate over the elements in the deque by index
    fn eachi(&self, f: &fn(uint, &T) -> bool) -> bool {
        uint::range(0, self.nelts, |i| f(i, self.get(i as int)))
    }

    /// Remove and return the first element in the deque
    ///
    /// Fails if the deque is empty
    fn pop_front(&mut self) -> T {
        let result = self.elts[self.lo].swap_unwrap();
        self.lo = (self.lo + 1u) % self.elts.len();
        self.nelts -= 1u;
        result
    }

    /// Remove and return the last element in the deque
    ///
    /// Fails if the deque is empty
    fn pop_back(&mut self) -> T {
        if self.hi == 0u {
            self.hi = self.elts.len() - 1u;
        } else { self.hi -= 1u; }
        let result = self.elts[self.hi].swap_unwrap();
        self.elts[self.hi] = None;
        self.nelts -= 1u;
        result
    }

    /// Prepend an element to the deque
    fn add_front(&mut self, t: T) {
        let oldlo = self.lo;
        if self.lo == 0u {
            self.lo = self.elts.len() - 1u;
        } else { self.lo -= 1u; }
        if self.lo == self.hi {
            self.elts = grow(self.nelts, oldlo, self.elts);
            self.lo = self.elts.len() - 1u;
            self.hi = self.nelts;
        }
        self.elts[self.lo] = Some(t);
        self.nelts += 1u;
    }

    /// Append an element to the deque
    fn add_back(&mut self, t: T) {
        if self.lo == self.hi && self.nelts != 0u {
            self.elts = grow(self.nelts, self.lo, self.elts);
            self.lo = 0u;
            self.hi = self.nelts;
        }
        self.elts[self.hi] = Some(t);
        self.hi = (self.hi + 1u) % self.elts.len();
        self.nelts += 1u;
    }

    /// Reserve capacity for exactly `n` elements in the given deque,
    /// doing nothing if `self`'s capacity is already equal to or greater
    /// than the requested capacity
    ///
    /// # Arguments
    ///
    /// * n - The number of elements to reserve space for
    fn reserve(&mut self, n: uint) {
        vec::reserve(&mut self.elts, n);
    }

    /// Reserve capacity for at least `n` elements in the given deque,
    /// over-allocating in case the caller needs to reserve additional
    /// space.
    ///
    /// Do nothing if `self`'s capacity is already equal to or greater
    /// than the requested capacity.
    ///
    /// # Arguments
    ///
    /// * n - The number of elements to reserve space for
    fn reserve_at_least(&mut self, n: uint) {
        vec::reserve_at_least(&mut self.elts, n);
    }
}

/// Grow is only called on full elts, so nelts is also len(elts), unlike
/// elsewhere.
fn grow<T>(nelts: uint, lo: uint, elts: &mut [Option<T>]) -> ~[Option<T>] {
    assert_eq!(nelts, elts.len());
    let mut rv = ~[];

    do rv.grow_fn(nelts + 1) |i| {
        replace(&mut elts[(lo + i) % nelts], None)
    }

    rv
}

fn get<'r, T>(elts: &'r [Option<T>], i: uint) -> &'r T {
    match elts[i] { Some(ref t) => t, _ => fail!() }
}

#[cfg(test)]
mod tests {
    use super::*;
    use core::cmp::Eq;
    use core::kinds::Copy;
    use core::vec::capacity;

    #[test]
    fn test_simple() {
        let mut d = Deque::new();
        assert_eq!(d.len(), 0u);
        d.add_front(17);
        d.add_front(42);
        d.add_back(137);
        assert_eq!(d.len(), 3u);
        d.add_back(137);
        assert_eq!(d.len(), 4u);
        debug!(d.peek_front());
        assert_eq!(*d.peek_front(), 42);
        debug!(d.peek_back());
        assert_eq!(*d.peek_back(), 137);
        let mut i: int = d.pop_front();
        debug!(i);
        assert_eq!(i, 42);
        i = d.pop_back();
        debug!(i);
        assert_eq!(i, 137);
        i = d.pop_back();
        debug!(i);
        assert_eq!(i, 137);
        i = d.pop_back();
        debug!(i);
        assert_eq!(i, 17);
        assert_eq!(d.len(), 0u);
        d.add_back(3);
        assert_eq!(d.len(), 1u);
        d.add_front(2);
        assert_eq!(d.len(), 2u);
        d.add_back(4);
        assert_eq!(d.len(), 3u);
        d.add_front(1);
        assert_eq!(d.len(), 4u);
        debug!(d.get(0));
        debug!(d.get(1));
        debug!(d.get(2));
        debug!(d.get(3));
        assert_eq!(*d.get(0), 1);
        assert_eq!(*d.get(1), 2);
        assert_eq!(*d.get(2), 3);
        assert_eq!(*d.get(3), 4);
    }

    #[test]
    fn test_boxes() {
        let a: @int = @5;
        let b: @int = @72;
        let c: @int = @64;
        let d: @int = @175;

        let mut deq = Deque::new();
        assert_eq!(deq.len(), 0);
        deq.add_front(a);
        deq.add_front(b);
        deq.add_back(c);
        assert_eq!(deq.len(), 3);
        deq.add_back(d);
        assert_eq!(deq.len(), 4);
        assert_eq!(*deq.peek_front(), b);
        assert_eq!(*deq.peek_back(), d);
        assert_eq!(deq.pop_front(), b);
        assert_eq!(deq.pop_back(), d);
        assert_eq!(deq.pop_back(), c);
        assert_eq!(deq.pop_back(), a);
        assert_eq!(deq.len(), 0);
        deq.add_back(c);
        assert_eq!(deq.len(), 1);
        deq.add_front(b);
        assert_eq!(deq.len(), 2);
        deq.add_back(d);
        assert_eq!(deq.len(), 3);
        deq.add_front(a);
        assert_eq!(deq.len(), 4);
        assert_eq!(*deq.get(0), a);
        assert_eq!(*deq.get(1), b);
        assert_eq!(*deq.get(2), c);
        assert_eq!(*deq.get(3), d);
    }

    #[cfg(test)]
    fn test_parameterized<T:Copy + Eq>(a: T, b: T, c: T, d: T) {
        let mut deq = Deque::new();
        assert_eq!(deq.len(), 0);
        deq.add_front(a);
        deq.add_front(b);
        deq.add_back(c);
        assert_eq!(deq.len(), 3);
        deq.add_back(d);
        assert_eq!(deq.len(), 4);
        assert_eq!(*deq.peek_front(), b);
        assert_eq!(*deq.peek_back(), d);
        assert_eq!(deq.pop_front(), b);
        assert_eq!(deq.pop_back(), d);
        assert_eq!(deq.pop_back(), c);
        assert_eq!(deq.pop_back(), a);
        assert_eq!(deq.len(), 0);
        deq.add_back(c);
        assert_eq!(deq.len(), 1);
        deq.add_front(b);
        assert_eq!(deq.len(), 2);
        deq.add_back(d);
        assert_eq!(deq.len(), 3);
        deq.add_front(a);
        assert_eq!(deq.len(), 4);
        assert_eq!(*deq.get(0), a);
        assert_eq!(*deq.get(1), b);
        assert_eq!(*deq.get(2), c);
        assert_eq!(*deq.get(3), d);
    }

    #[deriving(Eq)]
    enum Taggy { One(int), Two(int, int), Three(int, int, int), }

    #[deriving(Eq)]
    enum Taggypar<T> {
        Onepar(int), Twopar(int, int), Threepar(int, int, int),
    }

    #[deriving(Eq)]
    struct RecCy {
        x: int,
        y: int,
        t: Taggy
    }

    #[test]
    fn test_param_int() {
        test_parameterized::<int>(5, 72, 64, 175);
    }

    #[test]
    fn test_param_at_int() {
        test_parameterized::<@int>(@5, @72, @64, @175);
    }

    #[test]
    fn test_param_taggy() {
        test_parameterized::<Taggy>(One(1), Two(1, 2), Three(1, 2, 3),
                                    Two(17, 42));
    }

    #[test]
    fn test_param_taggypar() {
        test_parameterized::<Taggypar<int>>(Onepar::<int>(1),
                                            Twopar::<int>(1, 2),
                                            Threepar::<int>(1, 2, 3),
                                            Twopar::<int>(17, 42));
    }

    #[test]
    fn test_param_reccy() {
        let reccy1 = RecCy { x: 1, y: 2, t: One(1) };
        let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) };
        let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) };
        let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) };
        test_parameterized::<RecCy>(reccy1, reccy2, reccy3, reccy4);
    }

    #[test]
    fn test_eachi() {
        let mut deq = Deque::new();
        deq.add_back(1);
        deq.add_back(2);
        deq.add_back(3);

        for deq.eachi |i, e| {
            assert_eq!(*e, i + 1);
        }

        deq.pop_front();

        for deq.eachi |i, e| {
            assert_eq!(*e, i + 2);
        }

    }

    #[test]
    fn test_reserve() {
        let mut d = Deque::new();
        d.add_back(0u64);
        d.reserve(50);
        assert_eq!(capacity(&mut d.elts), 50);
        let mut d = Deque::new();
        d.add_back(0u32);
        d.reserve(50);
        assert_eq!(capacity(&mut d.elts), 50);
    }

    #[test]
    fn test_reserve_at_least() {
        let mut d = Deque::new();
        d.add_back(0u64);
        d.reserve_at_least(50);
        assert_eq!(capacity(&mut d.elts), 64);
        let mut d = Deque::new();
        d.add_back(0u32);
        d.reserve_at_least(50);
        assert_eq!(capacity(&mut d.elts), 64);
    }

}
<|endoftext|>


<commit_before>use std::io::{Error, ErrorKind};
use byteorder::{ReadBytesExt, LittleEndian};
use std::io::Read;
use std::mem;

#[derive(Debug)]
pub struct MamHeader{
    pub signature: u32,
    pub uncompressed_size: u32
}

pub fn read_mam_head<R: Read>(mut buffer: R)->Result<MamHeader,Error>{
    let mut header: MamHeader = unsafe {
        mem::zeroed()
    };

    header.signature = buffer.read_u32::<LittleEndian>()?;
    header.uncompressed_size = buffer.read_u32::<LittleEndian>()?;

    Ok(header)
}
<commit_msg>added prefetch header struct<commit_after>use std::io::{Error, ErrorKind};
use byteorder::{ReadBytesExt, LittleEndian};
use std::io::Read;
use std::mem;

#[derive(Debug)]
pub struct MamHeader{
    pub signature: u32,
    pub uncompressed_size: u32
}

#[derive(Debug)]
pub struct PrefetchHeader{
    pub version: u32,
    pub signature: u32,
    pub unknown1: u32,
    pub filesize: u32,
    pub filename: [u16; 30],
    pub hash: u32,
    pub unknon2: u32
}

pub fn read_mam_head<R: Read>(mut buffer: R)->Result<MamHeader,Error>{
    let mut header: MamHeader = unsafe {
        mem::zeroed()
    };

    header.signature = buffer.read_u32::<LittleEndian>()?;
    header.uncompressed_size = buffer.read_u32::<LittleEndian>()?;

    Ok(header)
}
<|endoftext|>


<commit_before>// Copyright 2013 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.

use std::cast;
use std::libc::{c_int, c_void};

use uvll;
use super::{Loop, UvHandle};
use std::rt::rtio::{Callback, PausableIdleCallback};

pub struct IdleWatcher {
    handle: *uvll::uv_idle_t,
    idle_flag: bool,
    closed: bool,
    callback: ~Callback,
}

impl IdleWatcher {
    pub fn new(loop_: &mut Loop, cb: ~Callback) -> ~IdleWatcher {
        let handle = UvHandle::alloc(None::<IdleWatcher>, uvll::UV_IDLE);
        assert_eq!(unsafe {
            uvll::uv_idle_init(loop_.handle, handle)
        }, 0);
        let me = ~IdleWatcher {
            handle: handle,
            idle_flag: false,
            closed: false,
            callback: cb,
        };
        return me.install();
    }

    pub fn onetime(loop_: &mut Loop, f: proc()) {
        let handle = UvHandle::alloc(None::<IdleWatcher>, uvll::UV_IDLE);
        unsafe {
            assert_eq!(uvll::uv_idle_init(loop_.handle, handle), 0);
            let data: *c_void = cast::transmute(~f);
            uvll::set_data_for_uv_handle(handle, data);
            assert_eq!(uvll::uv_idle_start(handle, onetime_cb), 0)
        }

        extern fn onetime_cb(handle: *uvll::uv_idle_t, status: c_int) {
            assert_eq!(status, 0);
            unsafe {
                let data = uvll::get_data_for_uv_handle(handle);
                let f: ~proc() = cast::transmute(data);
                (*f)();
                assert_eq!(uvll::uv_idle_stop(handle), 0);
                uvll::uv_close(handle, close_cb);
            }
        }

        extern fn close_cb(handle: *uvll::uv_handle_t) {
            unsafe { uvll::free_handle(handle) }
        }
    }
}

impl PausableIdleCallback for IdleWatcher {
    fn pause(&mut self) {
        if self.idle_flag == true {
            assert_eq!(unsafe {uvll::uv_idle_stop(self.handle) }, 0);
            self.idle_flag = false;
        }
    }
    fn resume(&mut self) {
        if self.idle_flag == false {
            assert_eq!(unsafe { uvll::uv_idle_start(self.handle, idle_cb) }, 0)
            self.idle_flag = true;
        }
    }
}

impl UvHandle<uvll::uv_idle_t> for IdleWatcher {
    fn uv_handle(&self) -> *uvll::uv_idle_t { self.handle }
}

extern fn idle_cb(handle: *uvll::uv_idle_t, status: c_int) {
    assert_eq!(status, 0);
    let idle: &mut IdleWatcher = unsafe { UvHandle::from_uv_handle(&handle) };
    idle.callback.call();
}

impl Drop for IdleWatcher {
    fn drop(&mut self) {
        self.pause();
        self.close_async_();
    }
}

#[cfg(test)]
mod test {
    use std::cast;
    use std::cell::RefCell;
    use std::rc::Rc;
    use std::rt::rtio::{Callback, PausableIdleCallback};
    use std::rt::task::{BlockedTask, Task};
    use std::rt::local::Local;
    use super::IdleWatcher;
    use super::super::local_loop;

    type Chan = Rc<RefCell<(Option<BlockedTask>, uint)>>;

    struct MyCallback(Rc<RefCell<(Option<BlockedTask>, uint)>>, uint);
    impl Callback for MyCallback {
        fn call(&mut self) {
            let task = match *self {
                MyCallback(ref rc, n) => {
                    let mut slot = rc.borrow_mut();
                    match *slot.get() {
                        (ref mut task, ref mut val) => {
                            *val = n;
                            match task.take() {
                                Some(t) => t,
                                None => return
                            }
                        }
                    }
                }
            };
            let _ = task.wake().map(|t| t.reawaken());
        }
    }

    fn mk(v: uint) -> (~IdleWatcher, Chan) {
        let rc = Rc::new(RefCell::new((None, 0)));
        let cb = ~MyCallback(rc.clone(), v);
        let cb = cb as ~Callback:;
        let cb = unsafe { cast::transmute(cb) };
        (IdleWatcher::new(&mut local_loop().loop_, cb), rc)
    }

    fn sleep(chan: &Chan) -> uint {
        let task: ~Task = Local::take();
        task.deschedule(1, |task| {
            let mut slot = chan.borrow_mut();
            match *slot.get() {
                (ref mut slot, _) => {
                    assert!(slot.is_none());
                    *slot = Some(task);
                }
            }
            Ok(())
        });

        let slot = chan.borrow();
        match *slot.get() { (_, n) => n }
    }

    #[test]
    fn not_used() {
        let (_idle, _chan) = mk(1);
    }

    #[test]
    fn smoke_test() {
        let (mut idle, chan) = mk(1);
        idle.resume();
        assert_eq!(sleep(&chan), 1);
    }

    #[test] #[should_fail]
    fn smoke_fail() {
        // By default, the test harness is capturing our stderr output through a
        // channel. This means that when we start failing and "print" our error
        // message, we could be switched to running on another test. The
        // IdleWatcher assumes that we're already running on the same task, so
        // it can cause serious problems and internal race conditions.
        //
        // To fix this bug, we just set our stderr to a null writer which will
        // never reschedule us, so we're guaranteed to stay on the same
        // task/event loop.
        use std::io;
        drop(io::stdio::set_stderr(~io::util::NullWriter));

        let (mut idle, _chan) = mk(1);
        idle.resume();
        fail!();
    }

    #[test]
    fn fun_combinations_of_methods() {
        let (mut idle, chan) = mk(1);
        idle.resume();
        assert_eq!(sleep(&chan), 1);
        idle.pause();
        idle.resume();
        idle.resume();
        assert_eq!(sleep(&chan), 1);
        idle.pause();
        idle.pause();
        idle.resume();
        assert_eq!(sleep(&chan), 1);
    }

    #[test]
    fn pause_pauses() {
        let (mut idle1, chan1) = mk(1);
        let (mut idle2, chan2) = mk(2);
        idle2.resume();
        assert_eq!(sleep(&chan2), 2);
        idle2.pause();
        idle1.resume();
        assert_eq!(sleep(&chan1), 1);
    }
}
<commit_msg>rustuv: Remove usage of get()<commit_after>// Copyright 2013 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.

use std::cast;
use std::libc::{c_int, c_void};

use uvll;
use super::{Loop, UvHandle};
use std::rt::rtio::{Callback, PausableIdleCallback};

pub struct IdleWatcher {
    handle: *uvll::uv_idle_t,
    idle_flag: bool,
    closed: bool,
    callback: ~Callback,
}

impl IdleWatcher {
    pub fn new(loop_: &mut Loop, cb: ~Callback) -> ~IdleWatcher {
        let handle = UvHandle::alloc(None::<IdleWatcher>, uvll::UV_IDLE);
        assert_eq!(unsafe {
            uvll::uv_idle_init(loop_.handle, handle)
        }, 0);
        let me = ~IdleWatcher {
            handle: handle,
            idle_flag: false,
            closed: false,
            callback: cb,
        };
        return me.install();
    }

    pub fn onetime(loop_: &mut Loop, f: proc()) {
        let handle = UvHandle::alloc(None::<IdleWatcher>, uvll::UV_IDLE);
        unsafe {
            assert_eq!(uvll::uv_idle_init(loop_.handle, handle), 0);
            let data: *c_void = cast::transmute(~f);
            uvll::set_data_for_uv_handle(handle, data);
            assert_eq!(uvll::uv_idle_start(handle, onetime_cb), 0)
        }

        extern fn onetime_cb(handle: *uvll::uv_idle_t, status: c_int) {
            assert_eq!(status, 0);
            unsafe {
                let data = uvll::get_data_for_uv_handle(handle);
                let f: ~proc() = cast::transmute(data);
                (*f)();
                assert_eq!(uvll::uv_idle_stop(handle), 0);
                uvll::uv_close(handle, close_cb);
            }
        }

        extern fn close_cb(handle: *uvll::uv_handle_t) {
            unsafe { uvll::free_handle(handle) }
        }
    }
}

impl PausableIdleCallback for IdleWatcher {
    fn pause(&mut self) {
        if self.idle_flag == true {
            assert_eq!(unsafe {uvll::uv_idle_stop(self.handle) }, 0);
            self.idle_flag = false;
        }
    }
    fn resume(&mut self) {
        if self.idle_flag == false {
            assert_eq!(unsafe { uvll::uv_idle_start(self.handle, idle_cb) }, 0)
            self.idle_flag = true;
        }
    }
}

impl UvHandle<uvll::uv_idle_t> for IdleWatcher {
    fn uv_handle(&self) -> *uvll::uv_idle_t { self.handle }
}

extern fn idle_cb(handle: *uvll::uv_idle_t, status: c_int) {
    assert_eq!(status, 0);
    let idle: &mut IdleWatcher = unsafe { UvHandle::from_uv_handle(&handle) };
    idle.callback.call();
}

impl Drop for IdleWatcher {
    fn drop(&mut self) {
        self.pause();
        self.close_async_();
    }
}

#[cfg(test)]
mod test {
    use std::cast;
    use std::cell::RefCell;
    use std::rc::Rc;
    use std::rt::rtio::{Callback, PausableIdleCallback};
    use std::rt::task::{BlockedTask, Task};
    use std::rt::local::Local;
    use super::IdleWatcher;
    use super::super::local_loop;

    type Chan = Rc<RefCell<(Option<BlockedTask>, uint)>>;

    struct MyCallback(Rc<RefCell<(Option<BlockedTask>, uint)>>, uint);
    impl Callback for MyCallback {
        fn call(&mut self) {
            let task = match *self {
                MyCallback(ref rc, n) => {
                    match *rc.borrow_mut().deref_mut() {
                        (ref mut task, ref mut val) => {
                            *val = n;
                            match task.take() {
                                Some(t) => t,
                                None => return
                            }
                        }
                    }
                }
            };
            let _ = task.wake().map(|t| t.reawaken());
        }
    }

    fn mk(v: uint) -> (~IdleWatcher, Chan) {
        let rc = Rc::new(RefCell::new((None, 0)));
        let cb = ~MyCallback(rc.clone(), v);
        let cb = cb as ~Callback:;
        let cb = unsafe { cast::transmute(cb) };
        (IdleWatcher::new(&mut local_loop().loop_, cb), rc)
    }

    fn sleep(chan: &Chan) -> uint {
        let task: ~Task = Local::take();
        task.deschedule(1, |task| {
            match *chan.borrow_mut().deref_mut() {
                (ref mut slot, _) => {
                    assert!(slot.is_none());
                    *slot = Some(task);
                }
            }
            Ok(())
        });

        match *chan.borrow() { (_, n) => n }
    }

    #[test]
    fn not_used() {
        let (_idle, _chan) = mk(1);
    }

    #[test]
    fn smoke_test() {
        let (mut idle, chan) = mk(1);
        idle.resume();
        assert_eq!(sleep(&chan), 1);
    }

    #[test] #[should_fail]
    fn smoke_fail() {
        // By default, the test harness is capturing our stderr output through a
        // channel. This means that when we start failing and "print" our error
        // message, we could be switched to running on another test. The
        // IdleWatcher assumes that we're already running on the same task, so
        // it can cause serious problems and internal race conditions.
        //
        // To fix this bug, we just set our stderr to a null writer which will
        // never reschedule us, so we're guaranteed to stay on the same
        // task/event loop.
        use std::io;
        drop(io::stdio::set_stderr(~io::util::NullWriter));

        let (mut idle, _chan) = mk(1);
        idle.resume();
        fail!();
    }

    #[test]
    fn fun_combinations_of_methods() {
        let (mut idle, chan) = mk(1);
        idle.resume();
        assert_eq!(sleep(&chan), 1);
        idle.pause();
        idle.resume();
        idle.resume();
        assert_eq!(sleep(&chan), 1);
        idle.pause();
        idle.pause();
        idle.resume();
        assert_eq!(sleep(&chan), 1);
    }

    #[test]
    fn pause_pauses() {
        let (mut idle1, chan1) = mk(1);
        let (mut idle2, chan2) = mk(2);
        idle2.resume();
        assert_eq!(sleep(&chan2), 2);
        idle2.pause();
        idle1.resume();
        assert_eq!(sleep(&chan1), 1);
    }
}
<|endoftext|>