<commit_before>//! A pure-Rust library to work with GPT partition tables.
//!
//! It provides support for manipulating (R/W) GPT headers and partition
//! tables. Raw disk devices as well as disk images are supported.
//!
//! ```rust,no_run
//! extern crate gpt;
//!
//! fn inspect_disk() {
//!     let diskpath = std::path::Path::new("/dev/sdz");
//!     let cfg = gpt::GptConfig::new().writable(false);
//!
//!     let disk = cfg.open(diskpath).expect("failed to open disk");
//!
//!     println!("Disk header: {:#?}", disk.primary_header());
//!     println!("Partition layout: {:#?}", disk.partitions());
//! }
//! ```

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate uuid;

pub mod disk;
pub mod header;
pub mod partition;
mod partition_types;

use std::io::Write;
use std::{fs, io, path};

/// Configuration options to open a GPT disk.
#[derive(Debug, Eq, PartialEq)]
pub struct GptConfig {
    /// Logical block size.
    lb_size: disk::LogicalBlockSize,
    /// Whether to open a GPT partition table in writable mode.
    writable: bool,
    /// Whether to expect and parse an initialized disk image.
    initialized: bool,
}

impl GptConfig {
    // TODO(lucab): complete support for skipping backup
    // header, etc, then expose all config knobs here.

    /// Create a new default configuration.
    pub fn new() -> Self {
        GptConfig::default()
    }

    /// Whether to open a GPT partition table in writable mode.
    pub fn writable(self, writable: bool) -> Self {
        let mut cfg = self;
        cfg.writable = writable;
        cfg
    }

    /// Whether to assume an initialized GPT disk and read its
    /// partition table on open.
    pub fn initialized(self, initialized: bool) -> Self {
        let mut cfg = self;
        cfg.initialized = initialized;
        cfg
    }

    /// Size of logical blocks (sectors) for this disk.
    pub fn logical_block_size(self, lb_size: disk::LogicalBlockSize) -> Self {
        let mut cfg = self;
        cfg.lb_size = lb_size;
        cfg
    }

    /// Open the GPT disk at the given path and inspect it according
    /// to configuration options.
    pub fn open(self, diskpath: &path::Path) -> io::Result<GptDisk> {
        // Uninitialized disk, no headers/table to parse.
        if !self.initialized {
            let file = fs::OpenOptions::new()
                .write(self.writable)
                .read(true)
                .open(diskpath)?;
            let empty = GptDisk {
                config: self,
                file,
                guid: uuid::Uuid::new_v4(),
                path: diskpath.to_path_buf(),
                primary_header: None,
                backup_header: None,
                partitions: vec![],
            };
            return Ok(empty);
        }

        // Proper GPT disk, fully inspect its layout.
        let mut file = fs::OpenOptions::new()
            .write(self.writable)
            .read(true)
            .open(diskpath)?;
        let h1 = header::read_primary_header(&mut file, self.lb_size)?;
        let h2 = header::read_backup_header(&mut file, self.lb_size)?;
        let table = partition::file_read_partitions(&mut file, &h1, self.lb_size)?;
        let disk = GptDisk {
            config: self,
            file,
            guid: h1.disk_guid,
            path: diskpath.to_path_buf(),
            primary_header: Some(h1),
            backup_header: Some(h2),
            partitions: table,
        };
        Ok(disk)
    }
}

impl Default for GptConfig {
    fn default() -> Self {
        Self {
            lb_size: disk::DEFAULT_SECTOR_SIZE,
            initialized: true,
            writable: false,
        }
    }
}

/// A file-backed GPT disk.
#[derive(Debug)]
pub struct GptDisk {
    config: GptConfig,
    file: fs::File,
    guid: uuid::Uuid,
    path: path::PathBuf,
    primary_header: Option<header::Header>,
    backup_header: Option<header::Header>,
    partitions: Vec<partition::Partition>,
}

impl GptDisk {
    /// Retrieve primary header, if any.
    pub fn primary_header(&self) -> &Option<header::Header> {
        &self.primary_header
    }

    /// Retrieve backup header, if any.
    pub fn backup_header(&self) -> &Option<header::Header> {
        &self.primary_header
    }

    /// Retrieve partition entries.
    pub fn partitions(&self) -> &[partition::Partition] {
        &self.partitions
    }

    /// Retrieve disk UUID.
    pub fn guid(&self) -> &uuid::Uuid {
        &self.guid
    }

    /// Retrieve disk logical block size.
    pub fn logical_block_size(&self) -> &disk::LogicalBlockSize {
        &self.config.lb_size
    }

    /// Update disk UUID.
    ///
    /// If no UUID is specified, a new random one is generated.
    /// No changes are recorded to disk until `write()` is called.
    pub fn update_guid(&mut self, uuid: Option<uuid::Uuid>) -> io::Result<&Self> {
        let guid = match uuid {
            Some(u) => u,
            None => {
                let u = uuid::Uuid::new_v4();
                debug!("Generated random uuid: {}", u);
                u
            }
        };
        self.guid = guid;
        Ok(self)
    }

    /// Update current partition table.
    ///
    /// No changes are recorded to disk until `write()` is called.
    pub fn update_partitions(&mut self, pp: Vec<partition::Partition>) -> io::Result<&Self> {
        // TODO(lucab): validate partitions.
        let bak = header::find_backup_lba(&mut self.file, self.config.lb_size)?;
        let h1 = header::Header::compute_new(true, &pp, self.guid, bak)?;
        let h2 = header::Header::compute_new(false, &pp, self.guid, bak)?;
        self.primary_header = Some(h1);
        self.backup_header = Some(h2);
        self.partitions = pp;
        self.config.initialized = true;
        Ok(self)
    }

    /// Persist state to disk, consuming this disk object.
    ///
    /// This is a destructive action, as it overwrite headers and
    /// partitions entries on disk. All writes are flushed to disk
    /// before returning the underlying `File` object.
    pub fn write(mut self) -> io::Result<fs::File> {
        if !self.config.writable {
            return Err(io::Error::new(
                io::ErrorKind::Other,
                "disk not opened in writable mode",
            ));
        }
        if !self.config.initialized {
            return Err(io::Error::new(io::ErrorKind::Other, "disk not initialized"));
        }
        let bak = header::find_backup_lba(&mut self.file, self.config.lb_size)?;
        let h2 = header::Header::compute_new(true, &[], self.guid, bak)?;
        let h1 = header::Header::compute_new(true, &[], self.guid, bak)?;
        // TODO(lucab): write partition entries to disk.
        h2.write_backup(&mut self.file, self.config.lb_size)?;
        h1.write_primary(&mut self.file, self.config.lb_size)?;
        self.file.flush()?;
        self.primary_header = Some(h1);
        self.backup_header = Some(h2);

        Ok(self.file)
    }
}
<commit_msg>gpt/config: take mutable self everywhere<commit_after>//! A pure-Rust library to work with GPT partition tables.
//!
//! It provides support for manipulating (R/W) GPT headers and partition
//! tables. Raw disk devices as well as disk images are supported.
//!
//! ```rust,no_run
//! extern crate gpt;
//!
//! fn inspect_disk() {
//!     let diskpath = std::path::Path::new("/dev/sdz");
//!     let cfg = gpt::GptConfig::new().writable(false);
//!
//!     let disk = cfg.open(diskpath).expect("failed to open disk");
//!
//!     println!("Disk header: {:#?}", disk.primary_header());
//!     println!("Partition layout: {:#?}", disk.partitions());
//! }
//! ```

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate uuid;

pub mod disk;
pub mod header;
pub mod partition;
mod partition_types;

use std::io::Write;
use std::{fs, io, path};

/// Configuration options to open a GPT disk.
#[derive(Debug, Eq, PartialEq)]
pub struct GptConfig {
    /// Logical block size.
    lb_size: disk::LogicalBlockSize,
    /// Whether to open a GPT partition table in writable mode.
    writable: bool,
    /// Whether to expect and parse an initialized disk image.
    initialized: bool,
}

impl GptConfig {
    // TODO(lucab): complete support for skipping backup
    // header, etc, then expose all config knobs here.

    /// Create a new default configuration.
    pub fn new() -> Self {
        GptConfig::default()
    }

    /// Whether to open a GPT partition table in writable mode.
    pub fn writable(mut self, writable: bool) -> Self {
        self.writable = writable;
        self
    }

    /// Whether to assume an initialized GPT disk and read its
    /// partition table on open.
    pub fn initialized(mut self, initialized: bool) -> Self {
        self.initialized = initialized;
        self
    }

    /// Size of logical blocks (sectors) for this disk.
    pub fn logical_block_size(mut self, lb_size: disk::LogicalBlockSize) -> Self {
        self.lb_size = lb_size;
        self
    }

    /// Open the GPT disk at the given path and inspect it according
    /// to configuration options.
    pub fn open(self, diskpath: &path::Path) -> io::Result<GptDisk> {
        // Uninitialized disk, no headers/table to parse.
        if !self.initialized {
            let file = fs::OpenOptions::new()
                .write(self.writable)
                .read(true)
                .open(diskpath)?;
            let empty = GptDisk {
                config: self,
                file,
                guid: uuid::Uuid::new_v4(),
                path: diskpath.to_path_buf(),
                primary_header: None,
                backup_header: None,
                partitions: vec![],
            };
            return Ok(empty);
        }

        // Proper GPT disk, fully inspect its layout.
        let mut file = fs::OpenOptions::new()
            .write(self.writable)
            .read(true)
            .open(diskpath)?;
        let h1 = header::read_primary_header(&mut file, self.lb_size)?;
        let h2 = header::read_backup_header(&mut file, self.lb_size)?;
        let table = partition::file_read_partitions(&mut file, &h1, self.lb_size)?;
        let disk = GptDisk {
            config: self,
            file,
            guid: h1.disk_guid,
            path: diskpath.to_path_buf(),
            primary_header: Some(h1),
            backup_header: Some(h2),
            partitions: table,
        };
        Ok(disk)
    }
}

impl Default for GptConfig {
    fn default() -> Self {
        Self {
            lb_size: disk::DEFAULT_SECTOR_SIZE,
            initialized: true,
            writable: false,
        }
    }
}

/// A file-backed GPT disk.
#[derive(Debug)]
pub struct GptDisk {
    config: GptConfig,
    file: fs::File,
    guid: uuid::Uuid,
    path: path::PathBuf,
    primary_header: Option<header::Header>,
    backup_header: Option<header::Header>,
    partitions: Vec<partition::Partition>,
}

impl GptDisk {
    /// Retrieve primary header, if any.
    pub fn primary_header(&self) -> &Option<header::Header> {
        &self.primary_header
    }

    /// Retrieve backup header, if any.
    pub fn backup_header(&self) -> &Option<header::Header> {
        &self.primary_header
    }

    /// Retrieve partition entries.
    pub fn partitions(&self) -> &[partition::Partition] {
        &self.partitions
    }

    /// Retrieve disk UUID.
    pub fn guid(&self) -> &uuid::Uuid {
        &self.guid
    }

    /// Retrieve disk logical block size.
    pub fn logical_block_size(&self) -> &disk::LogicalBlockSize {
        &self.config.lb_size
    }

    /// Update disk UUID.
    ///
    /// If no UUID is specified, a new random one is generated.
    /// No changes are recorded to disk until `write()` is called.
    pub fn update_guid(&mut self, uuid: Option<uuid::Uuid>) -> io::Result<&Self> {
        let guid = match uuid {
            Some(u) => u,
            None => {
                let u = uuid::Uuid::new_v4();
                debug!("Generated random uuid: {}", u);
                u
            }
        };
        self.guid = guid;
        Ok(self)
    }

    /// Update current partition table.
    ///
    /// No changes are recorded to disk until `write()` is called.
    pub fn update_partitions(&mut self, pp: Vec<partition::Partition>) -> io::Result<&Self> {
        // TODO(lucab): validate partitions.
        let bak = header::find_backup_lba(&mut self.file, self.config.lb_size)?;
        let h1 = header::Header::compute_new(true, &pp, self.guid, bak)?;
        let h2 = header::Header::compute_new(false, &pp, self.guid, bak)?;
        self.primary_header = Some(h1);
        self.backup_header = Some(h2);
        self.partitions = pp;
        self.config.initialized = true;
        Ok(self)
    }

    /// Persist state to disk, consuming this disk object.
    ///
    /// This is a destructive action, as it overwrite headers and
    /// partitions entries on disk. All writes are flushed to disk
    /// before returning the underlying `File` object.
    pub fn write(mut self) -> io::Result<fs::File> {
        if !self.config.writable {
            return Err(io::Error::new(
                io::ErrorKind::Other,
                "disk not opened in writable mode",
            ));
        }
        if !self.config.initialized {
            return Err(io::Error::new(io::ErrorKind::Other, "disk not initialized"));
        }
        let bak = header::find_backup_lba(&mut self.file, self.config.lb_size)?;
        let h2 = header::Header::compute_new(true, &[], self.guid, bak)?;
        let h1 = header::Header::compute_new(true, &[], self.guid, bak)?;
        // TODO(lucab): write partition entries to disk.
        h2.write_backup(&mut self.file, self.config.lb_size)?;
        h1.write_primary(&mut self.file, self.config.lb_size)?;
        self.file.flush()?;
        self.primary_header = Some(h1);
        self.backup_header = Some(h2);

        Ok(self.file)
    }
}
<|endoftext|>


<commit_before>//! Crate for using Delta-L encryption
#![warn(missing_docs)]
pub use self::Mode::{Encrypt, Decrypt};
pub use self::DeltaLError::{Io, InvalidHeader, ChecksumMismatch};

use std::hash::{Hasher, SipHasher};

use std::fmt;
use std::io;
use std::io::{Seek, SeekFrom, Read, Write};

use std::error::Error;

/// Convenient `Result` type for `DeltaLError`
pub type Result<T> = ::std::result::Result<T, DeltaLError>;

/// Describes errors that can occur during encryption and decryption
#[derive(Debug)]
pub enum DeltaLError{
    /// Errors that are just plain IO errors
    Io(io::Error),
    /// Invalid header error
    InvalidHeader,
    /// Checksum mismatch error
    ChecksumMismatch(Vec<u8>),
}

impl fmt::Display for DeltaLError{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
        match *self{
            Io(ref err)          => err.fmt(f),
            InvalidHeader        => write!(f, "The header was not valid."),
            ChecksumMismatch(..) => write!(f, "The checksum of the output file did not match the checksum in the header."),
        }
    }
}

impl Error for DeltaLError{
    fn description(&self) -> &str{
        match *self{
            Io(ref err)          => err.description(),
            InvalidHeader        => "header wasn't valid",
            ChecksumMismatch(..) => "checksum of output file didn't match header checksum",
        }
    }
}

impl From<io::Error> for DeltaLError{
    fn from(e: io::Error) -> DeltaLError{
        DeltaLError::Io(e)
    }
}

/// Specifies whether to encrypt or decrypt
#[derive(Debug, Copy, Clone)]
pub enum Mode{
    /// Specifies that we're encrypting
    Encrypt{
        /// Specifies whether to enable checksum verification
        checksum: bool
    },
    /// Specifies that we're decrypting
    Decrypt,
}

/// Provides interface for Delta-L encryption/decryption
#[derive(Debug, Copy, Clone)]
pub struct DeltaL{
    mode    : Mode,
    passhash: [u8; 8],
}

impl DeltaL{
    /// Creates a `DeltaL` instance
    pub fn new(mode: Mode) -> DeltaL{
        DeltaL{
            mode     : mode,
            passhash: [0; 8],
        }
    }

    /// Enables/disables checksum, if mode is `Encrypt`
    pub fn set_checksum(&mut self, checksum_flag: bool) -> bool{
        if let Encrypt{ref mut checksum} = self.mode{
            *checksum = checksum_flag;
            true
        }else{
            false
        }
    }

    /// Sets the passphrase for the `DeltaL`
    pub fn set_passphrase(&mut self, passphrase: &str){
        self.passhash = hash_as_array(passphrase.as_bytes())
    }

    fn offset(&self, (i, b): (usize, u8)) -> u8{
        if self.is_mode_encrypt(){
            b.wrapping_add(self.passhash[i % 8])
        }else{
            b.wrapping_sub(self.passhash[i % 8])
        }
    }

    /// Returns ".delta" for encryption and ".dec" for decryption
    pub fn get_mode_standard_extension(&self) -> &'static str{
        match self.mode{
            Encrypt{..} => ".delta",
            Decrypt     => ".dec",
        }
    }

    /// Returns whether the mode is `Encrypt`
    pub fn is_mode_encrypt(&self) -> bool{
        match self.mode{
            Encrypt{..} => true,
            _           => false,
        }
    }

    /// Codes the file in from_path to the file in to_path
    pub fn execute<R: Read + Seek>(&self, mut src: R) -> Result<Vec<u8>>{
        let mut buffer = Vec::<u8>::new();

        try!(src.seek(SeekFrom::Start(0)));
        try!(src.read_to_end(&mut buffer));

        let mut coded_buffer: Vec<u8>;

        let mut skip = 0;
        let mut checksum: Option<[u8; 8]> = None;

        // Do header related things
        if let Encrypt{checksum} = self.mode {
            coded_buffer = Vec::with_capacity(buffer.len());

            // Makes delta symbol: Δ
            coded_buffer.push(206);
            coded_buffer.push(148);

            // Capital L (76) if checksum is enabled, lowercase (108) if disabled
            if checksum {
                coded_buffer.reserve(12);

                coded_buffer.push(76);
                coded_buffer.push(10); // Push a newline

                coded_buffer.extend_from_slice(&hash_as_array(&buffer));
            } else {
                coded_buffer.reserve(4);

                coded_buffer.push(108);
                coded_buffer.push(10); // Push a newline
            }
        } else { // if `Decrypt`
            if buffer.len() > 3 && (buffer[0], buffer[1], buffer[3]) == (206, 148, 10) {
                match buffer[2]{
                    76 if buffer.len() > 11 => {
                        checksum = Some(slice_to_array(&buffer[4..12]));
                        skip = 12;
                    },
                    108 => {
                        skip = 4;
                    },
                    _ => return Err(InvalidHeader)
                }
                coded_buffer = Vec::with_capacity(buffer.len() - skip);
            }else{
                return Err(InvalidHeader)
            }
        }

        {
            let mut last: u8 = 0;

            let mut diff: Box<FnMut(u8) -> u8> = match self.mode {
                Encrypt{..} => Box::new(|b: u8| {
                    // Add last byte when encrypting
                    let ret = b.wrapping_add(last);
                    last = b;
                    ret
                }),
                Decrypt => Box::new(|b: u8| {
                    // Subtract byte last read when decrypting
                    last = b.wrapping_sub(last);
                    last
                })
            };

            coded_buffer.append(&mut buffer.into_iter()
                .skip(skip)
                .enumerate()
                .map(|x| diff(self.offset(x)))
                .collect());
        }

        if let Some(check) = checksum {
            if check != hash_as_array(&coded_buffer){
                return Err(ChecksumMismatch(coded_buffer))
            }
        }

        Ok(coded_buffer)
    }
}

#[inline]
fn slice_to_array(slice: &[u8]) -> [u8; 8]{
    [slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7]]
}

fn hash_as_array(to_be_hashed: &[u8]) -> [u8; 8]{
    let mut siphasher = SipHasher::new();
    siphasher.write(to_be_hashed);

    unsafe {::std::mem::transmute::<u64, [u8; 8]>(siphasher.finish())}
}
<commit_msg>Optimise algorithm<commit_after>//! Crate for using Delta-L encryption
#![warn(missing_docs)]
pub use self::Mode::{Encrypt, Decrypt};
pub use self::DeltaLError::{Io, InvalidHeader, ChecksumMismatch};

use std::hash::{Hasher, SipHasher};

use std::fmt;
use std::io;
use std::io::{Seek, SeekFrom, Read, Write};

use std::error::Error;

/// Convenient `Result` type for `DeltaLError`
pub type Result<T> = ::std::result::Result<T, DeltaLError>;

/// Describes errors that can occur during encryption and decryption
#[derive(Debug)]
pub enum DeltaLError{
    /// Errors that are just plain IO errors
    Io(io::Error),
    /// Invalid header error
    InvalidHeader,
    /// Checksum mismatch error
    ChecksumMismatch(Vec<u8>),
}

impl fmt::Display for DeltaLError{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
        match *self{
            Io(ref err)          => err.fmt(f),
            InvalidHeader        => write!(f, "The header was not valid."),
            ChecksumMismatch(..) => write!(f, "The checksum of the output file did not match the checksum in the header."),
        }
    }
}

impl Error for DeltaLError{
    fn description(&self) -> &str{
        match *self{
            Io(ref err)          => err.description(),
            InvalidHeader        => "header wasn't valid",
            ChecksumMismatch(..) => "checksum of output file didn't match header checksum",
        }
    }
}

impl From<io::Error> for DeltaLError{
    fn from(e: io::Error) -> DeltaLError{
        DeltaLError::Io(e)
    }
}

/// Specifies whether to encrypt or decrypt
#[derive(Debug, Copy, Clone)]
pub enum Mode{
    /// Specifies that we're encrypting
    Encrypt{
        /// Specifies whether to enable checksum verification
        checksum: bool
    },
    /// Specifies that we're decrypting
    Decrypt,
}

/// Provides interface for Delta-L encryption/decryption
#[derive(Debug, Copy, Clone)]
pub struct DeltaL{
    mode    : Mode,
    passhash: [u8; 8],
}

macro_rules! handle {
    ($passhash:expr, $wrapping:ident, $skip:ident, $coded_buffer:ident, $buffer:ident, $diff:expr) => {{
        let mut diff = $diff;

        $coded_buffer.append(&mut $buffer.into_iter()
            .skip($skip)
            .enumerate()
            .map(|(i, b)| diff(<u8>::$wrapping(b, $passhash[i % 8])))
            .collect());
    }};
}

impl DeltaL{
    /// Creates a `DeltaL` instance
    pub fn new(mode: Mode) -> DeltaL{
        DeltaL{
            mode     : mode,
            passhash: [0; 8],
        }
    }

    /// Enables/disables checksum, if mode is `Encrypt`
    pub fn set_checksum(&mut self, checksum_flag: bool) -> bool{
        if let Encrypt{ref mut checksum} = self.mode{
            *checksum = checksum_flag;
            true
        }else{
            false
        }
    }

    /// Sets the passphrase for the `DeltaL`
    pub fn set_passphrase(&mut self, passphrase: &str){
        self.passhash = hash_as_array(passphrase.as_bytes())
    }

    /// Returns ".delta" for encryption and ".dec" for decryption
    pub fn get_mode_standard_extension(&self) -> &'static str{
        match self.mode{
            Encrypt{..} => ".delta",
            Decrypt     => ".dec",
        }
    }

    /// Returns whether the mode is `Encrypt`
    pub fn is_mode_encrypt(&self) -> bool{
        match self.mode{
            Encrypt{..} => true,
            _           => false,
        }
    }

    /// Codes the file in from_path to the file in to_path
    pub fn execute<R: Read + Seek>(&self, mut src: R) -> Result<Vec<u8>>{
        let mut buffer = Vec::<u8>::new();

        try!(src.seek(SeekFrom::Start(0)));
        try!(src.read_to_end(&mut buffer));

        let mut coded_buffer: Vec<u8>;

        let mut skip = 0;
        let mut checksum: Option<[u8; 8]> = None;

        // Do header related things
        if let Encrypt{checksum} = self.mode {
            coded_buffer = Vec::with_capacity(buffer.len() + 12);

            // Makes delta symbol: Δ
            coded_buffer.push(206);
            coded_buffer.push(148);

            // Capital L (76) if checksum is enabled, lowercase (108) if disabled
            if checksum {
                coded_buffer.push(76);
                coded_buffer.push(10); // Push a newline

                coded_buffer.extend_from_slice(&hash_as_array(&buffer));
            } else {
                coded_buffer.push(108);
                coded_buffer.push(10); // Push a newline
            }
        } else { // if `Decrypt`
            if buffer.len() > 3 && (buffer[0], buffer[1], buffer[3]) == (206, 148, 10) {
                match buffer[2]{
                    76 if buffer.len() > 11 => {
                        checksum = Some(slice_to_array(&buffer[4..12]));
                        skip = 12;
                    },
                    108 => {
                        skip = 4;
                    },
                    _ => return Err(InvalidHeader)
                }
                coded_buffer = Vec::with_capacity(buffer.len() - skip);
            }else{
                return Err(InvalidHeader)
            }
        }

        {
            let mut last: u8 = 0;

            match self.mode{
                Encrypt{..} => {
                    handle!(self.passhash, wrapping_add, skip, coded_buffer, buffer, |b: u8| {
                        // Add last byte when encrypting
                        let ret = b.wrapping_add(last);
                        last = b;
                        ret
                    });
                },
                Decrypt     => {
                    handle!(self.passhash, wrapping_sub, skip, coded_buffer, buffer, |b: u8| {
                        // Subtract byte last read when decrypting
                        last = b.wrapping_sub(last);
                        last
                    });
                }
            }
        }

        if let Some(check) = checksum {
            if check != hash_as_array(&coded_buffer){
                return Err(ChecksumMismatch(coded_buffer))
            }
        }

        Ok(coded_buffer)
    }
}

#[inline]
fn slice_to_array(slice: &[u8]) -> [u8; 8]{
    [slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7]]
}

fn hash_as_array(to_be_hashed: &[u8]) -> [u8; 8]{
    let mut siphasher = SipHasher::new();
    siphasher.write(to_be_hashed);

    unsafe {::std::mem::transmute::<u64, [u8; 8]>(siphasher.finish())}
}
<|endoftext|>


<commit_before>//! Rust bindings for the [OpenEXR](http://openexr.com) C++ library.
//!
//! OpenEXR is a bitmap image file format that can store high dynamic range
//! (HDR) images along with other arbitrary per-pixel data. It is used heavily
//! in the VFX and 3D animation industries.
//!
//! Although this wrapper's API differs a little from the C++ library, it tries
//! not to differ wildly.  Therefore the
//! [C++ OpenEXR documentation](https://github.com/openexr/openexr/tree/develop/OpenEXR/doc)
//! is still useful as an introduction and rough reference.  Moreover, the
//! file format itself is also documented there.
//!
//! # Overview
//!
//! There are three primary parts to this crate:
//!
//! * The various [input](input/index.html) and [output](output/index.html)
//!   types.  These are used for reading and writing OpenEXR files.  They
//!   utilize the Header and FrameBuffer(Mut) types, listed below.
//!
//! * [`Header`](struct.Header.html): this is used for querying and specifying
//!   the properties of an OpenEXR file (such as resolution, channels, etc.), for
//!   reading and writing respectively.
//!
//! * [`FrameBuffer`](frame_buffer/struct.FrameBuffer.html) and
//!   [`FrameBufferMut`](frame_buffer/struct.FrameBufferMut.html):
//!   these are intermediaries that tell the OpenEXR APIs how to interpret
//!   your in-memory image data.  Rather than passing your image data to the
//!   APIs directly, you construct a `FrameBuffer` that that points at and
//!   describes it, and then you pass that FrameBuffer.
//!
//! # Examples
//!
//! Writing a scanline floating point RGB file.
//!
//! ```no_run
//! # use openexr::{FrameBuffer, Header, ScanlineOutputFile, PixelType};
//! #
//! // Pixel data for a 256x256 floating point RGB image.
//! let pixel_data = vec![(0.82f32, 1.78f32, 0.21f32); 256 * 256];
//!
//! // Create a file to write to.  The `Header` determines the properties of the
//! // file, like resolution and what channels it has.
//! let mut file = std::fs::File::create("output_file.exr").unwrap();
//! let mut output_file = ScanlineOutputFile::new(
//!     &mut file,
//!     Header::new()
//!         .set_resolution(256, 256)
//!         .add_channel("R", PixelType::FLOAT)
//!         .add_channel("G", PixelType::FLOAT)
//!         .add_channel("B", PixelType::FLOAT)).unwrap();
//!
//! // Create a `FrameBuffer` that points at our pixel data and describes it as
//! // RGB data.
//! let mut fb = FrameBuffer::new(256, 256);
//! fb.insert_channels(&["R", "G", "B"], &pixel_data);
//!
//! // Write pixel data to the file.
//! output_file.write_pixels(&fb).unwrap();
//! ```
//!
//! Reading a floating point RGB file.
//!
//! ```no_run
//! # use openexr::{FrameBufferMut, InputFile};
//!
//! // Open the EXR file.
//! let mut file = std::fs::File::open("input_file.exr").unwrap();
//! let mut input_file = InputFile::new(&mut file).unwrap();
//!
//! // Get the image dimensions, so we know how large of a buffer to make.
//! let (width, height) = input_file.header().data_dimensions();
//!
//! // Buffer to read pixel data into.
//! let mut pixel_data = vec![(0.0f32, 0.0f32, 0.0f32); (width*height) as usize];
//!
//! // New scope because `FrameBuffer` mutably borrows `pixel_data`, so we need
//! // it to go out of scope before we can access our `pixel_data` again.
//! {
//!     // Create `FrameBufferMut` that points at our pixel data and describes
//!     // it as RGB data.
//!     let mut fb = FrameBufferMut::new(width, height);
//!     fb.insert_channels(&[("R", 0.0), ("G", 0.0), ("B", 0.0)], &mut pixel_data);
//!
//!     // Read pixel data from the file.
//!     input_file.read_pixels(&mut fb).unwrap();
//! }
//! ```

#![warn(missing_docs)]
#![cfg_attr(feature = "unstable", feature(plugin))]
#![cfg_attr(feature = "unstable", plugin(clippy))]

extern crate half;
extern crate libc;
extern crate openexr_sys;

mod cexr_type_aliases;
mod stream_io;

pub mod error;
pub mod frame_buffer;
pub mod header;
pub mod input;
pub mod output;
pub mod threads;

pub use cexr_type_aliases::{Box2i, PixelType};
pub use error::{Error, Result};
pub use frame_buffer::{FrameBuffer, FrameBufferMut};
pub use header::{Envmap, Header};
pub use input::InputFile;
pub use output::ScanlineOutputFile;
<commit_msg>Fix dead link (#40)<commit_after>//! Rust bindings for the [OpenEXR](http://openexr.com) C++ library.
//!
//! OpenEXR is a bitmap image file format that can store high dynamic range
//! (HDR) images along with other arbitrary per-pixel data. It is used heavily
//! in the VFX and 3D animation industries.
//!
//! Although this wrapper's API differs a little from the C++ library, it tries
//! not to differ wildly.  Therefore the
//! [C++ OpenEXR documentation](https://github.com/openexr/openexr/tree/develop/OpenEXR/doc)
//! is still useful as an introduction and rough reference.  Moreover, the
//! file format itself is also documented there.
//!
//! # Overview
//!
//! There are three primary parts to this crate:
//!
//! * The various [input](input/index.html) and [output](output/index.html)
//!   types.  These are used for reading and writing OpenEXR files.  They
//!   utilize the Header and FrameBuffer(Mut) types, listed below.
//!
//! * [`Header`](header/struct.Header.html): this is used for querying and specifying
//!   the properties of an OpenEXR file (such as resolution, channels, etc.), for
//!   reading and writing respectively.
//!
//! * [`FrameBuffer`](frame_buffer/struct.FrameBuffer.html) and
//!   [`FrameBufferMut`](frame_buffer/struct.FrameBufferMut.html):
//!   these are intermediaries that tell the OpenEXR APIs how to interpret
//!   your in-memory image data.  Rather than passing your image data to the
//!   APIs directly, you construct a `FrameBuffer` that that points at and
//!   describes it, and then you pass that FrameBuffer.
//!
//! # Examples
//!
//! Writing a scanline floating point RGB file.
//!
//! ```no_run
//! # use openexr::{FrameBuffer, Header, ScanlineOutputFile, PixelType};
//! #
//! // Pixel data for a 256x256 floating point RGB image.
//! let pixel_data = vec![(0.82f32, 1.78f32, 0.21f32); 256 * 256];
//!
//! // Create a file to write to.  The `Header` determines the properties of the
//! // file, like resolution and what channels it has.
//! let mut file = std::fs::File::create("output_file.exr").unwrap();
//! let mut output_file = ScanlineOutputFile::new(
//!     &mut file,
//!     Header::new()
//!         .set_resolution(256, 256)
//!         .add_channel("R", PixelType::FLOAT)
//!         .add_channel("G", PixelType::FLOAT)
//!         .add_channel("B", PixelType::FLOAT)).unwrap();
//!
//! // Create a `FrameBuffer` that points at our pixel data and describes it as
//! // RGB data.
//! let mut fb = FrameBuffer::new(256, 256);
//! fb.insert_channels(&["R", "G", "B"], &pixel_data);
//!
//! // Write pixel data to the file.
//! output_file.write_pixels(&fb).unwrap();
//! ```
//!
//! Reading a floating point RGB file.
//!
//! ```no_run
//! # use openexr::{FrameBufferMut, InputFile};
//!
//! // Open the EXR file.
//! let mut file = std::fs::File::open("input_file.exr").unwrap();
//! let mut input_file = InputFile::new(&mut file).unwrap();
//!
//! // Get the image dimensions, so we know how large of a buffer to make.
//! let (width, height) = input_file.header().data_dimensions();
//!
//! // Buffer to read pixel data into.
//! let mut pixel_data = vec![(0.0f32, 0.0f32, 0.0f32); (width*height) as usize];
//!
//! // New scope because `FrameBuffer` mutably borrows `pixel_data`, so we need
//! // it to go out of scope before we can access our `pixel_data` again.
//! {
//!     // Create `FrameBufferMut` that points at our pixel data and describes
//!     // it as RGB data.
//!     let mut fb = FrameBufferMut::new(width, height);
//!     fb.insert_channels(&[("R", 0.0), ("G", 0.0), ("B", 0.0)], &mut pixel_data);
//!
//!     // Read pixel data from the file.
//!     input_file.read_pixels(&mut fb).unwrap();
//! }
//! ```

#![warn(missing_docs)]
#![cfg_attr(feature = "unstable", feature(plugin))]
#![cfg_attr(feature = "unstable", plugin(clippy))]

extern crate half;
extern crate libc;
extern crate openexr_sys;

mod cexr_type_aliases;
mod stream_io;

pub mod error;
pub mod frame_buffer;
pub mod header;
pub mod input;
pub mod output;
pub mod threads;

pub use cexr_type_aliases::{Box2i, PixelType};
pub use error::{Error, Result};
pub use frame_buffer::{FrameBuffer, FrameBufferMut};
pub use header::{Envmap, Header};
pub use input::InputFile;
pub use output::ScanlineOutputFile;
<|endoftext|>


<commit_before>pub extern crate semver;

use std::collections::HashMap;
use std::error::Error;
use std::fmt;
use std::io;
use std::io::prelude::*;
use std::net::SocketAddr;

pub use self::typemap::TypeMap;
mod typemap;

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum Scheme {
    Http,
    Https,
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum Host<'a> {
    Name(&'a str),
    Socket(SocketAddr),
}

#[derive(PartialEq, Hash, Eq, Debug, Clone)]
pub enum Method {
    Get,
    Post,
    Put,
    Delete,
    Head,
    Connect,
    Options,
    Trace,

    // RFC-5789
    Patch,
    Purge,

    // WebDAV, Subversion, UPNP
    Other(String),
}

impl fmt::Display for Method {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let s = match *self {
            Method::Get => "GET",
            Method::Post => "POST",
            Method::Put => "PUT",
            Method::Delete => "DELETE",
            Method::Head => "HEAD",
            Method::Connect => "CONNECT",
            Method::Options => "OPTIONS",
            Method::Trace => "TRACE",
            Method::Patch => "PATCH",
            Method::Purge => "PURGE",
            Method::Other(ref s) => s,
        };
        fmt.write_str(s)
    }
}

/// A Dictionary for extensions provided by the server or middleware
pub type Extensions = TypeMap;

pub trait Request {
    /// The version of HTTP being used
    fn http_version(&self) -> semver::Version;

    /// The version of the conduit spec being used
    fn conduit_version(&self) -> semver::Version;

    /// The request method, such as GET, POST, PUT, DELETE or PATCH
    fn method(&self) -> Method;

    /// The scheme part of the request URL
    fn scheme(&self) -> Scheme;

    /// The host part of the requested URL
    fn host<'a>(&'a self) -> Host<'a>;

    /// The initial part of the request URL's path that corresponds
    /// to a virtual root. This allows an application to have a
    /// virtual location that consumes part of the path.
    fn virtual_root<'a>(&'a self) -> Option<&'a str>;

    /// The remainder of the path.
    fn path<'a>(&'a self) -> &'a str;

    /// The portion of the request URL that follows the "?"
    fn query_string<'a>(&'a self) -> Option<&'a str>;

    /// The remote IP address of the client or the last proxy that
    /// sent the request.
    fn remote_addr(&self) -> SocketAddr;

    /// The byte-size of the body, if any
    fn content_length(&self) -> Option<u64>;

    /// The request's headers, as conduit::Headers.
    fn headers<'a>(&'a self) -> &'a dyn Headers;

    /// A Reader for the body of the request
    fn body<'a>(&'a mut self) -> &'a mut dyn Read;

    /// A readable map of extensions
    fn extensions<'a>(&'a self) -> &'a Extensions;

    /// A mutable map of extensions
    fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions;
}

pub trait Headers {
    /// Find the value of a given header. Multi-line headers are represented
    /// as an array.
    fn find(&self, key: &str) -> Option<Vec<&str>>;

    /// Returns true if a particular header exists
    fn has(&self, key: &str) -> bool;

    /// Iterate over all of the available headers.
    fn all(&self) -> Vec<(&str, Vec<&str>)>;
}

pub struct Response {
    /// The status code as a tuple of the return code and status string
    pub status: (u32, &'static str),

    /// A Map of the headers
    pub headers: HashMap<String, Vec<String>>,

    /// A Writer for body of the response
    pub body: Box<dyn WriteBody + Send>,
}

/// A Handler takes a request and returns a response or an error.
/// By default, a bare function implements `Handler`.
pub trait Handler: Sync + Send + 'static {
    fn call(&self, request: &mut dyn Request) -> Result<Response, Box<dyn Error + Send>>;
}

impl<F, E> Handler for F
where
    F: Fn(&mut dyn Request) -> Result<Response, E> + Sync + Send + 'static,
    E: Error + Send + 'static,
{
    fn call(&self, request: &mut dyn Request) -> Result<Response, Box<dyn Error + Send>> {
        (*self)(request).map_err(|e| Box::new(e) as Box<dyn Error + Send>)
    }
}

/// A trait which writes the response body out to a `Write`r.
///
/// This is implemented for all `Read`ers.
pub trait WriteBody {
    fn write_body(&mut self, out: &mut dyn Write) -> io::Result<u64>;
}

impl<R> WriteBody for R
where
    R: Read,
{
    fn write_body(&mut self, out: &mut dyn Write) -> io::Result<u64> {
        io::copy(self, out)
    }
}
<commit_msg>Enable warnings for 2018 idioms<commit_after>#![warn(rust_2018_idioms)]

pub extern crate semver;

use std::collections::HashMap;
use std::error::Error;
use std::fmt;
use std::io;
use std::io::prelude::*;
use std::net::SocketAddr;

pub use self::typemap::TypeMap;
mod typemap;

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum Scheme {
    Http,
    Https,
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum Host<'a> {
    Name(&'a str),
    Socket(SocketAddr),
}

#[derive(PartialEq, Hash, Eq, Debug, Clone)]
pub enum Method {
    Get,
    Post,
    Put,
    Delete,
    Head,
    Connect,
    Options,
    Trace,

    // RFC-5789
    Patch,
    Purge,

    // WebDAV, Subversion, UPNP
    Other(String),
}

impl fmt::Display for Method {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match *self {
            Method::Get => "GET",
            Method::Post => "POST",
            Method::Put => "PUT",
            Method::Delete => "DELETE",
            Method::Head => "HEAD",
            Method::Connect => "CONNECT",
            Method::Options => "OPTIONS",
            Method::Trace => "TRACE",
            Method::Patch => "PATCH",
            Method::Purge => "PURGE",
            Method::Other(ref s) => s,
        };
        fmt.write_str(s)
    }
}

/// A Dictionary for extensions provided by the server or middleware
pub type Extensions = TypeMap;

pub trait Request {
    /// The version of HTTP being used
    fn http_version(&self) -> semver::Version;

    /// The version of the conduit spec being used
    fn conduit_version(&self) -> semver::Version;

    /// The request method, such as GET, POST, PUT, DELETE or PATCH
    fn method(&self) -> Method;

    /// The scheme part of the request URL
    fn scheme(&self) -> Scheme;

    /// The host part of the requested URL
    fn host<'a>(&'a self) -> Host<'a>;

    /// The initial part of the request URL's path that corresponds
    /// to a virtual root. This allows an application to have a
    /// virtual location that consumes part of the path.
    fn virtual_root<'a>(&'a self) -> Option<&'a str>;

    /// The remainder of the path.
    fn path<'a>(&'a self) -> &'a str;

    /// The portion of the request URL that follows the "?"
    fn query_string<'a>(&'a self) -> Option<&'a str>;

    /// The remote IP address of the client or the last proxy that
    /// sent the request.
    fn remote_addr(&self) -> SocketAddr;

    /// The byte-size of the body, if any
    fn content_length(&self) -> Option<u64>;

    /// The request's headers, as conduit::Headers.
    fn headers<'a>(&'a self) -> &'a dyn Headers;

    /// A Reader for the body of the request
    fn body<'a>(&'a mut self) -> &'a mut dyn Read;

    /// A readable map of extensions
    fn extensions<'a>(&'a self) -> &'a Extensions;

    /// A mutable map of extensions
    fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions;
}

pub trait Headers {
    /// Find the value of a given header. Multi-line headers are represented
    /// as an array.
    fn find(&self, key: &str) -> Option<Vec<&str>>;

    /// Returns true if a particular header exists
    fn has(&self, key: &str) -> bool;

    /// Iterate over all of the available headers.
    fn all(&self) -> Vec<(&str, Vec<&str>)>;
}

pub struct Response {
    /// The status code as a tuple of the return code and status string
    pub status: (u32, &'static str),

    /// A Map of the headers
    pub headers: HashMap<String, Vec<String>>,

    /// A Writer for body of the response
    pub body: Box<dyn WriteBody + Send>,
}

/// A Handler takes a request and returns a response or an error.
/// By default, a bare function implements `Handler`.
pub trait Handler: Sync + Send + 'static {
    fn call(&self, request: &mut dyn Request) -> Result<Response, Box<dyn Error + Send>>;
}

impl<F, E> Handler for F
where
    F: Fn(&mut dyn Request) -> Result<Response, E> + Sync + Send + 'static,
    E: Error + Send + 'static,
{
    fn call(&self, request: &mut dyn Request) -> Result<Response, Box<dyn Error + Send>> {
        (*self)(request).map_err(|e| Box::new(e) as Box<dyn Error + Send>)
    }
}

/// A trait which writes the response body out to a `Write`r.
///
/// This is implemented for all `Read`ers.
pub trait WriteBody {
    fn write_body(&mut self, out: &mut dyn Write) -> io::Result<u64>;
}

impl<R> WriteBody for R
where
    R: Read,
{
    fn write_body(&mut self, out: &mut dyn Write) -> io::Result<u64> {
        io::copy(self, out)
    }
}
<|endoftext|>


<commit_before>//! A crate for permuted vectors.
//!
//! Permuted vectors consist of a vector, together with a permutation of its elements.
//! In particular, `vec.sort()` sorts the permutation, not the vector.
//! This allows the vector to be updated, and
//! if the updates preserve sort order, then the next `vec.sort()`
//! will be O(n) rather than O(n log n).

/// The type of permuted vectors.
#[derive(Clone,Debug)]
pub struct PermutedVec<T> {
    // The contents of the vector.
    contents: Vec<T>,
    // The permutation
    permutation: Vec<usize>,
    // The inverse permutation.
    inverse: Vec<usize>,
}

/// The type of permuted iterators over a permuted vector.
#[derive(Clone,Debug)]
pub struct PermutedIter<'a, T> where T: 'a {
    // Where are we in the iterator
    index: usize,
    // The contents of the iterator
    contents: &'a[T],
    // The permutation
    permutation: &'a[usize],
}

impl<'a, T> Iterator for PermutedIter<'a, T> where T: 'a {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        let sorted_index = self.index;
        self.index = self.index + 1;
        self.permutation.get(sorted_index).and_then(|&index| self.contents.get(index))
    }
}

impl<T> PermutedVec<T> where T: Ord {
    /// Create a new, empty presorted vector.
    pub fn new() -> PermutedVec<T> {
        PermutedVec {
            contents: Vec::new(),
            permutation: Vec::new(),
            inverse: Vec::new(),
        }
    }

    /// An iterator over the permuted vector
    pub fn permuted_iter(&self) -> PermutedIter<T> {
        PermutedIter {
            index: 0,
            contents: &self.contents,
            permutation: &self.permutation,
        }
    }

    /// Is the permuted vector already sorted?
    pub fn is_sorted(&self) -> bool {
        let iter_1 = self.permuted_iter();
        let mut iter_2 = self.permuted_iter();
        iter_2.next();
        iter_1.zip(iter_2).all(|(value_1, value_2)|value_1 <= value_2)
    }

    /// The invariant maintained by the datatype
    fn invariant(&self) -> bool {
        self.inverse.iter().enumerate().all(|(index, &sorted_index)|
            self.permutation[sorted_index] == index
        ) && self.permutation.iter().enumerate().all(|(sorted_index, &index)|
            self.inverse[index] == sorted_index
        )
    }

    /// Sort the permutation on the vector
    pub fn sort(&mut self) {
        if !self.is_sorted() {
            let contents = &self.contents;
            self.permutation.sort_by(|&index_1, &index_2| contents[index_1].cmp(&contents[index_2]));
            for (sorted_index, &index) in self.permutation.iter().enumerate() {
                self.inverse[index] = sorted_index;
            }
            debug_assert!(self.invariant());
            debug_assert!(self.is_sorted());
        }
    }

    /// A sorted iterator over the vector.
    /// If the vector is already definitely sorted, this is a constant time operation.
    pub fn sorted_iter(&mut self) -> PermutedIter<T> {
        self.sort();
        self.permuted_iter()
    }

    /// Get the `i`th element of the vector.
    /// Returns `None` if the vector contains fewer than `i` elements.
    pub fn get(&self, index: usize) -> Option<&T> {
        self.contents.get(index)
    }

    /// Set the `i`th element of the vector.
    /// Panics if the vector contains fewer than `i` elements.
    pub fn set(&mut self, index: usize, value: T) {
        self.contents[index] = value;
    }

    /// Append an element to the end of the vector.
    pub fn push(&mut self, value: T) {
        let index = self.contents.len();
        self.contents.push(value);
        self.permutation.push(index);
        self.inverse.push(index);
        debug_assert!(self.invariant());
    }

    /// The length of the vector.
    pub fn len(&self) -> usize {
        self.contents.len()
    }
}

impl<T> From<Vec<T>> for PermutedVec<T> {
    fn from(vec: Vec<T>) -> PermutedVec<T> {
        let len = vec.len();
        PermutedVec {
            contents: vec,
            permutation: (0..len).collect(),
            inverse: (0..len).collect(),
        }
    }
}

#[test]
fn test_push() {
    let mut vec = PermutedVec::new();
    assert_eq!(vec.len(), 0);
    assert_eq!(vec.get(0), None);
    assert_eq!(vec.is_sorted(), true);

    vec.push(0);
    assert_eq!(vec.len(), 1);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), None);
    assert_eq!(vec.is_sorted(), true);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0]);

    vec.push(30);
    assert_eq!(vec.len(), 2);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), None);
    assert_eq!(vec.is_sorted(), true);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &30]);

    vec.push(20);
    assert_eq!(vec.len(), 3);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), Some(&20));
    assert_eq!(vec.get(3), None);
    assert_eq!(vec.is_sorted(), false);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &20, &30]);

    assert_eq!(vec.len(), 3);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), Some(&20));
    assert_eq!(vec.get(3), None);
    assert_eq!(vec.is_sorted(), true);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &20, &30]);

    vec.push(10);
    assert_eq!(vec.len(), 4);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), Some(&20));
    assert_eq!(vec.get(3), Some(&10));
    assert_eq!(vec.get(4), None);
    assert_eq!(vec.is_sorted(), false);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &10, &20, &30]);

    assert_eq!(vec.len(), 4);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), Some(&20));
    assert_eq!(vec.get(3), Some(&10));
    assert_eq!(vec.get(4), None);
    assert_eq!(vec.is_sorted(), true);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &10, &20, &30]);
}

#[test]
fn test_set() {
    let mut vec = PermutedVec::from(vec![0, 30, 20, 10]);
    assert_eq!(vec.len(), 4);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), Some(&20));
    assert_eq!(vec.get(3), Some(&10));
    assert_eq!(vec.get(4), None);
    assert_eq!(vec.is_sorted(), false);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &10, &20, &30]);

    vec.set(2, 21);
    assert_eq!(vec.len(), 4);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), Some(&21));
    assert_eq!(vec.get(3), Some(&10));
    assert_eq!(vec.get(4), None);
    assert_eq!(vec.is_sorted(), true);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &10, &21, &30]);

    vec.set(2, 31);
    assert_eq!(vec.len(), 4);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), Some(&31));
    assert_eq!(vec.get(3), Some(&10));
    assert_eq!(vec.get(4), None);
    assert_eq!(vec.is_sorted(), false);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &10, &30, &31]);

    vec.set(2, 1);
    assert_eq!(vec.len(), 4);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), Some(&1));
    assert_eq!(vec.get(3), Some(&10));
    assert_eq!(vec.get(4), None);
    assert_eq!(vec.is_sorted(), false);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &1, &10, &30]);
}
<commit_msg>Removed unused permutation inverse.<commit_after>//! A crate for permuted vectors.
//!
//! Permuted vectors consist of a vector, together with a permutation of its elements.
//! In particular, `vec.sort()` sorts the permutation, not the vector.
//! This allows the vector to be updated, and
//! if the updates preserve sort order, then the next `vec.sort()`
//! will be O(n) rather than O(n log n).

/// The type of permuted vectors.
#[derive(Clone,Debug)]
pub struct PermutedVec<T> {
    // The contents of the vector.
    contents: Vec<T>,
    // The permutation
    permutation: Vec<usize>,
}

/// The type of permuted iterators over a permuted vector.
#[derive(Clone,Debug)]
pub struct PermutedIter<'a, T> where T: 'a {
    // Where are we in the iterator
    index: usize,
    // The contents of the iterator
    contents: &'a[T],
    // The permutation
    permutation: &'a[usize],
}

impl<'a, T> Iterator for PermutedIter<'a, T> where T: 'a {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        let sorted_index = self.index;
        self.index = self.index + 1;
        self.permutation.get(sorted_index).and_then(|&index| self.contents.get(index))
    }
}

impl<T> PermutedVec<T> where T: Ord {
    /// Create a new, empty presorted vector.
    pub fn new() -> PermutedVec<T> {
        PermutedVec {
            contents: Vec::new(),
            permutation: Vec::new(),
        }
    }

    /// An iterator over the permuted vector
    pub fn permuted_iter(&self) -> PermutedIter<T> {
        PermutedIter {
            index: 0,
            contents: &self.contents,
            permutation: &self.permutation,
        }
    }

    /// Is the permuted vector already sorted?
    pub fn is_sorted(&self) -> bool {
        let iter_1 = self.permuted_iter();
        let mut iter_2 = self.permuted_iter();
        iter_2.next();
        iter_1.zip(iter_2).all(|(value_1, value_2)|value_1 <= value_2)
    }

    /// Sort the permutation on the vector
    pub fn sort(&mut self) {
        if !self.is_sorted() {
            let contents = &self.contents;
            self.permutation.sort_by(|&index_1, &index_2| (&contents[index_1], index_1).cmp(&(&contents[index_2], index_2)));
            debug_assert!(self.is_sorted());
        }
    }

    /// A sorted iterator over the vector.
    /// If the vector is already definitely sorted, this is a constant time operation.
    pub fn sorted_iter(&mut self) -> PermutedIter<T> {
        self.sort();
        self.permuted_iter()
    }

    /// Get the `i`th element of the vector.
    /// Returns `None` if the vector contains fewer than `i` elements.
    pub fn get(&self, index: usize) -> Option<&T> {
        self.contents.get(index)
    }

    /// Set the `i`th element of the vector.
    /// Panics if the vector contains fewer than `i` elements.
    pub fn set(&mut self, index: usize, value: T) {
        self.contents[index] = value;
    }

    /// Append an element to the end of the vector.
    pub fn push(&mut self, value: T) {
        let index = self.contents.len();
        self.contents.push(value);
        self.permutation.push(index);
    }

    /// The length of the vector.
    pub fn len(&self) -> usize {
        self.contents.len()
    }
}

impl<T> From<Vec<T>> for PermutedVec<T> {
    fn from(vec: Vec<T>) -> PermutedVec<T> {
        let len = vec.len();
        PermutedVec {
            contents: vec,
            permutation: (0..len).collect(),
        }
    }
}

#[test]
fn test_push() {
    let mut vec = PermutedVec::new();
    assert_eq!(vec.len(), 0);
    assert_eq!(vec.get(0), None);
    assert_eq!(vec.is_sorted(), true);

    vec.push(0);
    assert_eq!(vec.len(), 1);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), None);
    assert_eq!(vec.is_sorted(), true);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0]);

    vec.push(30);
    assert_eq!(vec.len(), 2);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), None);
    assert_eq!(vec.is_sorted(), true);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &30]);

    vec.push(20);
    assert_eq!(vec.len(), 3);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), Some(&20));
    assert_eq!(vec.get(3), None);
    assert_eq!(vec.is_sorted(), false);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &20, &30]);

    assert_eq!(vec.len(), 3);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), Some(&20));
    assert_eq!(vec.get(3), None);
    assert_eq!(vec.is_sorted(), true);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &20, &30]);

    vec.push(10);
    assert_eq!(vec.len(), 4);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), Some(&20));
    assert_eq!(vec.get(3), Some(&10));
    assert_eq!(vec.get(4), None);
    assert_eq!(vec.is_sorted(), false);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &10, &20, &30]);

    assert_eq!(vec.len(), 4);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), Some(&20));
    assert_eq!(vec.get(3), Some(&10));
    assert_eq!(vec.get(4), None);
    assert_eq!(vec.is_sorted(), true);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &10, &20, &30]);
}

#[test]
fn test_set() {
    let mut vec = PermutedVec::from(vec![0, 30, 20, 10]);
    assert_eq!(vec.len(), 4);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), Some(&20));
    assert_eq!(vec.get(3), Some(&10));
    assert_eq!(vec.get(4), None);
    assert_eq!(vec.is_sorted(), false);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &10, &20, &30]);

    vec.set(2, 21);
    assert_eq!(vec.len(), 4);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), Some(&21));
    assert_eq!(vec.get(3), Some(&10));
    assert_eq!(vec.get(4), None);
    assert_eq!(vec.is_sorted(), true);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &10, &21, &30]);

    vec.set(2, 31);
    assert_eq!(vec.len(), 4);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), Some(&31));
    assert_eq!(vec.get(3), Some(&10));
    assert_eq!(vec.get(4), None);
    assert_eq!(vec.is_sorted(), false);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &10, &30, &31]);

    vec.set(2, 1);
    assert_eq!(vec.len(), 4);
    assert_eq!(vec.get(0), Some(&0));
    assert_eq!(vec.get(1), Some(&30));
    assert_eq!(vec.get(2), Some(&1));
    assert_eq!(vec.get(3), Some(&10));
    assert_eq!(vec.get(4), None);
    assert_eq!(vec.is_sorted(), false);
    assert_eq!(vec.sorted_iter().collect::<Vec<&usize>>(), vec![&0, &1, &10, &30]);
}
<|endoftext|>


<commit_before>#![feature(rust_2018_preview, uniform_paths)]
//! Simple efficient composable primitives for pretty printing.
//!
//! The implementation is derived from the paper ["A New Approach to Optimal Code Formatting"][pp-paper]
//! by Phillip M. Yelland.
//!
//! [pp-paper]: https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/44667.pdf

extern crate unicode_width;

mod knot_column;
mod knot_set;
mod linear_value;
mod resolved_layout;
mod shared_string;

use std::borrow::Borrow;
use std::collections as col;
use std::fmt;
use std::rc;

use shared_string::SharedString;

const OVERFLOW_COST: f32 = 100.0;
const NEWLINE_COST: f32 = 1.0;

/// The primary representation of pretty-printed text. Logically, it represents a set of
/// possible permissible layouts of text.
///
/// Layouts are constructed with four different primitives:
///
/// 1. Text
///
///    A literal string which is laid out as written. Its length is obtained using the
///    `unicode-width` package.
///
/// 2. Stack
///
///    Vertically stacks two layouts. The left margins of the two layouts will be
///    aligned.
///
/// 3. Juxtapose
///
///    Horizontally juxtapose two layouts. The left margin of the second layout
///    will be aligned with the end of the first layout's last line.
///
/// 4. Choice
///
///    Creates a choice between two or more layouts. The choice is made at layout
///    time based on the cost of each possible layout. See the `layout` method.
#[derive(Clone)]
pub struct Layout(rc::Rc<LayoutContents>);

impl Layout {
  fn with_contents(contents: LayoutContents) -> Layout {
    Layout(rc::Rc::new(contents))
  }

  fn contents(&self) -> &LayoutContents {
    &*self.0
  }

  /// Create a text layout value. This is a literal string with no layout variance.
  pub fn text(lit_text: impl Into<String>) -> Layout {
    Layout::with_contents(LayoutContents::Text(lit_text.into().into()))
  }

  fn choice_pair(first: &Layout, second: &Layout) -> Layout {
    // We should canonicalize this so that the choices are always in the same order.
    Layout::with_contents(LayoutContents::Choice(first.clone(), second.clone()))
  }

  fn stack_pair(top: &Layout, bottom: &Layout) -> Layout {
    Layout::with_contents(LayoutContents::Stack(top.clone(), bottom.clone()))
  }

  /// Create a layout that is the juxtaposition of two other layouts.
  ///
  /// This lays out the latter layout immediately to the right of the last line
  /// of the left layout.
  pub fn juxtapose_pair(left: &Layout, right: &Layout) -> Layout {
    let mut builder = JuxtaposeBuilder::new(right);
    builder.juxtapose(left)
  }

  /// Creates a layout that is the lowest-cost choice of layouts provided.
  pub fn choices<S, T>(items: S) -> Layout
  where
    S: AsRef<[T]>,
    T: Borrow<Layout>,
  {
    let items = items.as_ref();
    assert!(items.len() > 0);
    let mut curr_layout = items[0].borrow().clone();
    for item in &items[1..] {
      curr_layout = Layout::choice_pair(&curr_layout, item.borrow());
    }

    curr_layout
  }

  /// Create a stack of the layouts, where each of the layouts are
  /// vertically stacked on top of each other in the order provided.
  pub fn stack<'a, S, T>(items: S) -> Layout
  where
    S: AsRef<[T]>,
    T: Borrow<Layout>,
  {
    let items = items.as_ref();
    assert!(items.len() > 0);
    let mut curr_layout = items[0].borrow().clone();
    for item in &items[1..] {
      curr_layout = Layout::stack_pair(&curr_layout, item.borrow());
    }
    curr_layout
  }

  /// Creates a juxtoposition of layouts, with each layout immediately
  /// following the last line of the previous layout.
  pub fn juxtapose<S, T>(items: S) -> Layout
  where
    S: AsRef<[T]>,
    T: Borrow<Layout>,
  {
    let items = items.as_ref();
    assert!(items.len() > 0);
    let mut curr_layout = items[0].borrow().clone();
    for item in &items[1..] {
      curr_layout = Layout::juxtapose_pair(&curr_layout, item.borrow());
    }
    curr_layout
  }

  /// Lays out the contents of this layout for a text buffer of width margin.
  pub fn layout(&self, margin: u16) -> String {
    self.layout_with_costs(margin, OVERFLOW_COST, NEWLINE_COST)
  }

  /// Lays out the contents of this layout for a text buffer of width margin, and with
  /// newline costs and overflow costs as provided.
  ///
  /// For each character over the margin width, the overflow cost is incurred. For each
  /// newline in the result, the newline cost is incurred. The layout chosen is that with
  /// the smallest overall cost.
  pub fn layout_with_costs(&self, margin: u16, overflow_cost: f32, newline_cost: f32) -> String {
    let final_layout = knot_set::do_layout(self, overflow_cost, newline_cost, margin);
    return final_layout.to_text(0);
  }

  #[doc(hidden)]
  pub fn debug_num_nodes(&self) -> usize {
    let mut counter = NodeCounter::new();
    counter.visit_node(self);
    counter.get_count()
  }

  fn wrap_inner<T: Borrow<Layout>>(layouts: &[T]) -> (Layout, Vec<(Layout, Option<Layout>)>) {
    if layouts.len() == 1 {
      let singleton = layouts[0].borrow();
      (
        singleton.borrow().clone(),
        vec![(singleton.borrow().clone(), None)],
      )
    } else {
      let first = layouts[0].borrow();
      let rest = &layouts[1..];
      let (block, line_blocks) = Layout::wrap_inner(rest);

      let mut new_line_pairs: Vec<_> = line_blocks
        .into_iter()
        .map(|(l, b)| {
          (
            Layout::juxtapose(&[first.borrow(), &Layout::text(" "), &l]),
            b,
          )
        }).collect();
      new_line_pairs.push((first.borrow().clone(), Some(block)));

      let new_choices: Vec<_> = new_line_pairs
        .iter()
        .map(|(k, v)| match v {
          Some(b) => Layout::stack_pair(k, b),
          None => k.clone(),
        }).collect();

      (Layout::choices(&new_choices), new_line_pairs)
    }
  }

  pub fn wrap<S, T>(layouts: S) -> Layout
  where
    S: AsRef<[T]>,
    T: Borrow<Layout>,
  {
    let slice = layouts.as_ref();
    let (result, _) = Layout::wrap_inner(slice);
    result
  }
}

impl fmt::Debug for Layout {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    <LayoutContents as fmt::Debug>::fmt(&*self.0, f)
  }
}

#[derive(Debug)]
enum LayoutContents {
  Text(SharedString),
  Choice(Layout, Layout),
  Stack(Layout, Layout),
  Juxtapose(SharedString, Layout),
}

struct JuxtaposeBuilder {
  right: Layout,
  memo: col::BTreeMap<*const LayoutContents, Layout>,
}

impl JuxtaposeBuilder {
  fn new(right: &Layout) -> Self {
    JuxtaposeBuilder {
      right: right.clone(),
      memo: col::BTreeMap::new(),
    }
  }

  fn juxtapose(&mut self, left: &Layout) -> Layout {
    if let Some(v) = self.memo.get(&(left.contents() as *const LayoutContents)) {
      return v.clone();
    }

    let new_layout = match left.contents() {
      LayoutContents::Text(t) => {
        Layout::with_contents(LayoutContents::Juxtapose(t.clone(), self.right.clone()))
      }
      LayoutContents::Choice(first, second) => Layout::with_contents(LayoutContents::Choice(
        self.juxtapose(first),
        self.juxtapose(second),
      )),
      LayoutContents::Stack(top, bottom) => {
        Layout::with_contents(LayoutContents::Stack(top.clone(), self.juxtapose(bottom)))
      }
      LayoutContents::Juxtapose(text, jux_right) => Layout::with_contents(
        LayoutContents::Juxtapose(text.clone(), self.juxtapose(jux_right)),
      ),
    };

    self
      .memo
      .insert(left.contents() as *const LayoutContents, new_layout.clone());
    new_layout
  }
}

struct NodeCounter {
  seen: col::BTreeSet<*const LayoutContents>,
}

impl NodeCounter {
  fn new() -> Self {
    NodeCounter {
      seen: col::BTreeSet::new(),
    }
  }
  fn visit_node(&mut self, layout: &Layout) {
    if self.seen.insert(layout.contents() as *const LayoutContents) {
      use LayoutContents::*;
      match layout.contents() {
        Text(_) => {}
        Choice(first, second) => {
          self.visit_node(first);
          self.visit_node(second);
        }
        Stack(top, bottom) => {
          self.visit_node(top);
          self.visit_node(bottom);
        }
        Juxtapose(_left, right) => {
          self.visit_node(right);
        }
      }
    }
  }

  fn get_count(&self) -> usize {
    self.seen.len()
  }
}

#[cfg(test)]
mod test {
  use super::Layout;

  #[test]
  fn test_simple_set() {
    let foo = Layout::text("foo");
    let pair = Layout::juxtapose(&[&foo, &foo]);
    assert_eq!(pair.layout(10), "foofoo");
  }

  #[test]
  fn test_simple_stack() {
    let foo = Layout::text("foo");
    let pair = Layout::stack(&[&foo, &foo]);
    assert_eq!(pair.layout(10), "foo\nfoo");
  }

  #[test]
  fn test_simple_choice() {
    let foo = Layout::text("foo");
    let pair = Layout::choices(&[
      &Layout::juxtapose(&[&foo, &foo]),
      &Layout::stack(&[&foo, &foo]),
    ]);
    assert_eq!(pair.layout(10), "foofoo");
    assert_eq!(pair.layout(4), "foo\nfoo");
  }

  #[test]
  fn test_wrap() {
    let lorem = &"Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    Nullam suscipit dolor sed dolor facilisis ultrices ut id nisl. Nam
    malesuada malesuada dolor, eget dapibus nibh euismod at. Vestibulum
    aliquam aliquam mi at tincidunt. Sed imperdiet eget purus in egestas.
    Suspendisse id odio in augue cursus tempor. Duis imperdiet imperdiet eros
    et lobortis. Vestibulum vestibulum condimentum dui, sit amet fringilla libero
    commodo at. Sed aliquam mauris vitae egestas convallis. Integer sed est vitae
    nibh pellentesque sodales. Suspendisse sit amet dignissim arcu. Quisque hendrerit
    pellentesque egestas. Nulla at elementum est. Maecenas lectus turpis, placerat
    vitae est sit amet, mattis pharetra orci. Praesent.";
    let words: Vec<_> = lorem.split_whitespace().map(|k| Layout::text(k)).collect();
    let layout = Layout::wrap(words);
    println!("{}", layout.debug_num_nodes());
    assert_eq!(layout.layout(80).chars().filter(|c| c == &'\n').count(), 9);
    assert_eq!(layout.layout(100).chars().filter(|c| c == &'\n').count(), 7);
  }

  #[test]
  fn test_large_stack() {
    let foo = Layout::text("foo");
    let bar = Layout::text("bar");
    let foo_stack = Layout::stack(&[&foo, &bar]);
    let foo_jux = Layout::juxtapose(&[&foo, &bar]);
    let foo_choice = Layout::choices(&[&foo_stack, &foo_jux]);

    let choice = Layout::juxtapose(&vec![&foo_choice; 1000]);

    println!("Done creating layout.");
    println!("Num nodes: {}", choice.debug_num_nodes());

    choice.layout(500);
  }
}
<commit_msg>Fix small errors with wrap words.<commit_after>#![feature(rust_2018_preview, uniform_paths)]
//! Simple efficient composable primitives for pretty printing.
//!
//! The implementation is derived from the paper ["A New Approach to Optimal Code Formatting"][pp-paper]
//! by Phillip M. Yelland.
//!
//! [pp-paper]: https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/44667.pdf

extern crate unicode_width;

mod knot_column;
mod knot_set;
mod linear_value;
mod resolved_layout;
mod shared_string;

use std::borrow::Borrow;
use std::collections as col;
use std::fmt;
use std::rc;

use shared_string::SharedString;

const OVERFLOW_COST: f32 = 100.0;
const NEWLINE_COST: f32 = 1.0;

/// The primary representation of pretty-printed text. Logically, it represents a set of
/// possible permissible layouts of text.
///
/// Layouts are constructed with four different primitives:
///
/// 1. Text
///
///    A literal string which is laid out as written. Its length is obtained using the
///    `unicode-width` package.
///
/// 2. Stack
///
///    Vertically stacks two layouts. The left margins of the two layouts will be
///    aligned.
///
/// 3. Juxtapose
///
///    Horizontally juxtapose two layouts. The left margin of the second layout
///    will be aligned with the end of the first layout's last line.
///
/// 4. Choice
///
///    Creates a choice between two or more layouts. The choice is made at layout
///    time based on the cost of each possible layout. See the `layout` method.
#[derive(Clone)]
pub struct Layout(rc::Rc<LayoutContents>);

impl Layout {
  fn with_contents(contents: LayoutContents) -> Layout {
    Layout(rc::Rc::new(contents))
  }

  fn contents(&self) -> &LayoutContents {
    &*self.0
  }

  /// Create a text layout value. This is a literal string with no layout variance.
  pub fn text(lit_text: impl Into<String>) -> Layout {
    Layout::with_contents(LayoutContents::Text(lit_text.into().into()))
  }

  fn choice_pair(first: &Layout, second: &Layout) -> Layout {
    // We should canonicalize this so that the choices are always in the same order.
    Layout::with_contents(LayoutContents::Choice(first.clone(), second.clone()))
  }

  fn stack_pair(top: &Layout, bottom: &Layout) -> Layout {
    Layout::with_contents(LayoutContents::Stack(top.clone(), bottom.clone()))
  }

  /// Create a layout that is the juxtaposition of two other layouts.
  ///
  /// This lays out the latter layout immediately to the right of the last line
  /// of the left layout.
  pub fn juxtapose_pair(left: &Layout, right: &Layout) -> Layout {
    let mut builder = JuxtaposeBuilder::new(right);
    builder.juxtapose(left)
  }

  /// Creates a layout that is the lowest-cost choice of layouts provided.
  pub fn choices<S, T>(items: S) -> Layout
  where
    S: AsRef<[T]>,
    T: Borrow<Layout>,
  {
    let items = items.as_ref();
    assert!(items.len() > 0);
    let mut curr_layout = items[0].borrow().clone();
    for item in &items[1..] {
      curr_layout = Layout::choice_pair(&curr_layout, item.borrow());
    }

    curr_layout
  }

  /// Create a stack of the layouts, where each of the layouts are
  /// vertically stacked on top of each other in the order provided.
  pub fn stack<'a, S, T>(items: S) -> Layout
  where
    S: AsRef<[T]>,
    T: Borrow<Layout>,
  {
    let items = items.as_ref();
    if items.len() == 0 {
      return Layout::text("");
    }
    assert!(items.len() > 0);
    let mut curr_layout = items[0].borrow().clone();
    for item in &items[1..] {
      curr_layout = Layout::stack_pair(&curr_layout, item.borrow());
    }
    curr_layout
  }

  /// Creates a juxtoposition of layouts, with each layout immediately
  /// following the last line of the previous layout.
  pub fn juxtapose<S, T>(items: S) -> Layout
  where
    S: AsRef<[T]>,
    T: Borrow<Layout>,
  {
    let items = items.as_ref();
    assert!(items.len() > 0);
    let mut curr_layout = items[0].borrow().clone();
    for item in &items[1..] {
      curr_layout = Layout::juxtapose_pair(&curr_layout, item.borrow());
    }
    curr_layout
  }

  /// Lays out the contents of this layout for a text buffer of width margin.
  pub fn layout(&self, margin: u16) -> String {
    self.layout_with_costs(margin, OVERFLOW_COST, NEWLINE_COST)
  }

  /// Lays out the contents of this layout for a text buffer of width margin, and with
  /// newline costs and overflow costs as provided.
  ///
  /// For each character over the margin width, the overflow cost is incurred. For each
  /// newline in the result, the newline cost is incurred. The layout chosen is that with
  /// the smallest overall cost.
  pub fn layout_with_costs(&self, margin: u16, overflow_cost: f32, newline_cost: f32) -> String {
    let final_layout = knot_set::do_layout(self, overflow_cost, newline_cost, margin);
    return final_layout.to_text(0);
  }

  #[doc(hidden)]
  pub fn debug_num_nodes(&self) -> usize {
    let mut counter = NodeCounter::new();
    counter.visit_node(self);
    counter.get_count()
  }

  fn wrap_inner<T: Borrow<Layout>>(layouts: &[T]) -> (Layout, Vec<(Layout, Option<Layout>)>) {
    if layouts.len() == 0 {
      (Layout::text(""), vec![])
    } else if layouts.len() == 1 {
      let singleton = layouts[0].borrow();
      (
        singleton.borrow().clone(),
        vec![(singleton.borrow().clone(), None)],
      )
    } else {
      let first = layouts[0].borrow();
      let rest = &layouts[1..];
      let (block, line_blocks) = Layout::wrap_inner(rest);

      let mut new_line_pairs: Vec<_> = line_blocks
        .into_iter()
        .map(|(l, b)| {
          (
            Layout::juxtapose(&[first.borrow(), &Layout::text(" "), &l]),
            b,
          )
        }).collect();
      new_line_pairs.push((first.borrow().clone(), Some(block)));

      let new_choices: Vec<_> = new_line_pairs
        .iter()
        .map(|(k, v)| match v {
          Some(b) => Layout::stack_pair(k, b),
          None => k.clone(),
        }).collect();

      (Layout::choices(&new_choices), new_line_pairs)
    }
  }

  pub fn wrap<S, T>(layouts: S) -> Layout
  where
    S: AsRef<[T]>,
    T: Borrow<Layout>,
  {
    let slice = layouts.as_ref();
    let (result, _) = Layout::wrap_inner(slice);
    result
  }
}

impl fmt::Debug for Layout {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    <LayoutContents as fmt::Debug>::fmt(&*self.0, f)
  }
}

#[derive(Debug)]
enum LayoutContents {
  Text(SharedString),
  Choice(Layout, Layout),
  Stack(Layout, Layout),
  Juxtapose(SharedString, Layout),
}

struct JuxtaposeBuilder {
  right: Layout,
  memo: col::BTreeMap<*const LayoutContents, Layout>,
}

impl JuxtaposeBuilder {
  fn new(right: &Layout) -> Self {
    JuxtaposeBuilder {
      right: right.clone(),
      memo: col::BTreeMap::new(),
    }
  }

  fn juxtapose(&mut self, left: &Layout) -> Layout {
    if let Some(v) = self.memo.get(&(left.contents() as *const LayoutContents)) {
      return v.clone();
    }

    let new_layout = match left.contents() {
      LayoutContents::Text(t) => {
        Layout::with_contents(LayoutContents::Juxtapose(t.clone(), self.right.clone()))
      }
      LayoutContents::Choice(first, second) => Layout::with_contents(LayoutContents::Choice(
        self.juxtapose(first),
        self.juxtapose(second),
      )),
      LayoutContents::Stack(top, bottom) => {
        Layout::with_contents(LayoutContents::Stack(top.clone(), self.juxtapose(bottom)))
      }
      LayoutContents::Juxtapose(text, jux_right) => Layout::with_contents(
        LayoutContents::Juxtapose(text.clone(), self.juxtapose(jux_right)),
      ),
    };

    self
      .memo
      .insert(left.contents() as *const LayoutContents, new_layout.clone());
    new_layout
  }
}

struct NodeCounter {
  seen: col::BTreeSet<*const LayoutContents>,
}

impl NodeCounter {
  fn new() -> Self {
    NodeCounter {
      seen: col::BTreeSet::new(),
    }
  }
  fn visit_node(&mut self, layout: &Layout) {
    if self.seen.insert(layout.contents() as *const LayoutContents) {
      use LayoutContents::*;
      match layout.contents() {
        Text(_) => {}
        Choice(first, second) => {
          self.visit_node(first);
          self.visit_node(second);
        }
        Stack(top, bottom) => {
          self.visit_node(top);
          self.visit_node(bottom);
        }
        Juxtapose(_left, right) => {
          self.visit_node(right);
        }
      }
    }
  }

  fn get_count(&self) -> usize {
    self.seen.len()
  }
}

#[cfg(test)]
mod test {
  use super::Layout;

  #[test]
  fn test_simple_set() {
    let foo = Layout::text("foo");
    let pair = Layout::juxtapose(&[&foo, &foo]);
    assert_eq!(pair.layout(10), "foofoo");
  }

  #[test]
  fn test_simple_stack() {
    let foo = Layout::text("foo");
    let pair = Layout::stack(&[&foo, &foo]);
    assert_eq!(pair.layout(10), "foo\nfoo");
  }

  #[test]
  fn test_simple_choice() {
    let foo = Layout::text("foo");
    let pair = Layout::choices(&[
      &Layout::juxtapose(&[&foo, &foo]),
      &Layout::stack(&[&foo, &foo]),
    ]);
    assert_eq!(pair.layout(10), "foofoo");
    assert_eq!(pair.layout(4), "foo\nfoo");
  }

  #[test]
  fn test_wrap() {
    let lorem = &"Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    Nullam suscipit dolor sed dolor facilisis ultrices ut id nisl. Nam
    malesuada malesuada dolor, eget dapibus nibh euismod at. Vestibulum
    aliquam aliquam mi at tincidunt. Sed imperdiet eget purus in egestas.
    Suspendisse id odio in augue cursus tempor. Duis imperdiet imperdiet eros
    et lobortis. Vestibulum vestibulum condimentum dui, sit amet fringilla libero
    commodo at. Sed aliquam mauris vitae egestas convallis. Integer sed est vitae
    nibh pellentesque sodales. Suspendisse sit amet dignissim arcu. Quisque hendrerit
    pellentesque egestas. Nulla at elementum est. Maecenas lectus turpis, placerat
    vitae est sit amet, mattis pharetra orci. Praesent.";
    let words: Vec<_> = lorem.split_whitespace().map(|k| Layout::text(k)).collect();
    let layout = Layout::wrap(words);
    println!("{}", layout.debug_num_nodes());
    assert_eq!(layout.layout(80).chars().filter(|c| c == &'\n').count(), 9);
    assert_eq!(layout.layout(100).chars().filter(|c| c == &'\n').count(), 7);
  }

  #[test]
  fn test_large_stack() {
    let foo = Layout::text("foo");
    let bar = Layout::text("bar");
    let foo_stack = Layout::stack(&[&foo, &bar]);
    let foo_jux = Layout::juxtapose(&[&foo, &bar]);
    let foo_choice = Layout::choices(&[&foo_stack, &foo_jux]);

    let choice = Layout::juxtapose(&vec![&foo_choice; 1000]);

    println!("Done creating layout.");
    println!("Num nodes: {}", choice.debug_num_nodes());

    choice.layout(500);
  }
}
<|endoftext|>


<commit_before>extern crate cocoa;
extern crate metal_sys;
#[macro_use]
extern crate objc;

mod device;
mod command_queue;
mod value_types;

pub mod sys {
    pub use metal_sys::*;
}

pub use device::{Device, DeviceError, DeviceRef};
pub use command_queue::{CommandQueue, CommandQueueError};
pub use value_types::{ClearColor, Origin, Region, ScissorRect, Size, Viewport};
<commit_msg>Export ReadOnlyDevice<commit_after>extern crate cocoa;
extern crate metal_sys;
#[macro_use]
extern crate objc;

mod device;
mod command_queue;
mod value_types;

pub mod sys {
    pub use metal_sys::*;
}

pub use device::{Device, DeviceError, DeviceRef, ReadOnlyDevice};
pub use command_queue::{CommandQueue, CommandQueueError};
pub use value_types::{ClearColor, Origin, Region, ScissorRect, Size, Viewport};
<|endoftext|>


<commit_before>// (c) 2015-2016 Joost Yervante Damad <joost@damad.be>

use std::fmt;
use std::fs::File;
use std::io::Read;

extern crate rustysexp;
use rustysexp::Sexp;
use rustysexp::Atom;

type ERes<T> = Result<T, String>;

fn err<T>(msg: &str) -> ERes<T> {
    Err(String::from(msg))
}

pub struct Effects {
    todo: String
}

impl Effects {
    fn new() -> Effects {
        Effects { todo: String::from("todo") }
    }
}

pub struct At {
    x: f64,
    y: f64,
    rot: f64
}

impl At {
    fn new(x:f64 ,y:f64, rot:f64) -> At {
        At { x:x, y:y, rot:rot }
    }
}

pub struct FpText {
    name: String,
    value: String,
    at: At,
    layer: String,
    effects: Effects,
    hide: bool,
}

impl FpText {
    fn new(name: &String, value: &String) -> FpText {
        FpText {
            name: name.clone(),
            value: value.clone(),
            at: At::new(0.,0.,0.),
            layer: String::from("cow"),
            effects: Effects::new(),
            hide: false
        }
    }
}

pub enum Element {
    Layer(String),
    Descr(String),
    FpText(FpText),
    Pad,
    FpPoly,
    FpLine,
    FpCircle
}

pub struct Module {
    name: String,
    elements: Vec<Element>
}

impl Module {
    fn new(name: &String) -> Module {
        Module { name: name.clone(), elements: vec![] }
    }
    fn append(&mut self, e: Element) {
        self.elements.push(e)
    }
}

impl fmt::Display for Module {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(module {}\n", self.name));
        for e in &self.elements {
            try!(write!(f, "{}\n", e))
        };
        write!(f, ")")
    }
}

impl fmt::Display for Effects {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "(effects)")
    }
}

impl fmt::Display for At {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "(at {} {} {})", self.x, self.y, self.rot)
    }
}

impl fmt::Display for FpText {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "(fp_text {} \"{}\" {} (layer {}) {})", self.name, self.value, self.at, self.layer, self.effects)
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Layer(ref s) => write!(f, "(layer {})", s),
            Element::Descr(ref s) => write!(f, "(descr \"{}\")", s),
            Element::FpText(ref p) => write!(f, "{}", p),
            Element::Pad => write!(f, "(pad)"),
            Element::FpPoly => write!(f, "(fp_poly)"),
            Element::FpLine => write!(f, "(fp_line)"),
            Element::FpCircle => write!(f, "(fp_circle)"),
        }
    }
}

fn parse_layer(v: &Vec<Sexp>) -> ERes<Element> {
    match v[1] {
        Sexp::Atom(Atom::S(ref s)) => {
            Ok(Element::Layer(s.clone()))
        }
        ref x => Err(format!("unexpected element in layer: {}", x))
    }
}

fn parse_descr(v: &Vec<Sexp>) -> ERes<Element> {
    match v[1] {
        Sexp::Atom(Atom::Q(ref s)) => {
            Ok(Element::Descr(s.clone()))
        }
        ref x => Err(format!("unexpected element in descr: {}", x))
    }
}
fn parse_fp_text(v: &Vec<Sexp>) -> ERes<Element> {
    let name = try!(match v[1] {
        Sexp::Atom(Atom::S(ref s)) => Ok(s),
        ref x => err("expecting name for fp_text")
    });
    let value = try!(match v[2] {
        Sexp::Atom(Atom::Q(ref s)) => Ok(s),
        ref x => err("expecting value for fp_text")
    });
    let mut fp = FpText::new(name, value);
    for e in &v[3..] {
    }
    Ok(Element::FpText(fp))
}
fn parse_pad(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::Pad)
}
fn parse_fp_poly(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpPoly)
}
fn parse_fp_line(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpLine)
}
fn parse_fp_circle(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpCircle)
}

fn parse_element_list(v: &Vec<Sexp>) -> ERes<Element> {
    match v[0] {
        Sexp::Atom(Atom::S(ref s)) => {
            match &s[..] {
                "layer" => parse_layer(v),
                "descr" => parse_descr(v),
                "fp_text" => parse_fp_text(v),
                "pad" => parse_pad(v),
                "fp_poly" => parse_fp_poly(v),
                "fp_line" => parse_fp_line(v),
                "fp_circle" => parse_fp_circle(v),
                x => Err(format!("unknown element in module: {}", x))
            }
        }
        _ => err("expecting atom")
    }
}

fn parse_element(s: &Sexp) -> ERes<Element> {
    match *s {
        Sexp::List(ref v) => parse_element_list(&v),
        _ => err("expecting element list in module")
    }
}

fn parse_module_list(v: &Vec<Sexp>) -> ERes<Module> {
    let mut module = (match v[0] {
        Sexp::Atom(Atom::S(ref s)) if s == "module" => {
            match v[1] {
                Sexp::Atom(Atom::S(ref s)) => {
                    Ok(Module::new(s))
                }
                ref x => return Err(format!("expecting module name got {}", x))
            }
        }
        _ => err("expecting module")
    }).unwrap();
    for e in &v[2..] {
        let el = try!(parse_element(e));
        module.append(el)
    }
    Ok(module)
}

fn parse_module(s: Sexp) -> ERes<Module> {
    match s {
        Sexp::List(v) => parse_module_list(&v),
        _ => err("expecting top level list")
    }
}

fn parse(s: &str) -> ERes<Module> {
    match rustysexp::parse_str(s) {
        Ok(s) => parse_module(s),
        Err(x) => Err(format!("IOError: {}", x))
    }
}

fn read_file(name: &str) -> Result<String,std::io::Error> {
    let mut f = try!(File::open(name));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    Ok(s)
}

pub fn parse_str(s: &str) -> Module {
    parse(s).unwrap()
}

pub fn parse_file(name: &str) -> Module {
    let s = read_file(name).unwrap();
    parse(&s[..]).unwrap()
}

<commit_msg>cleanup file structure<commit_after>// (c) 2015-2016 Joost Yervante Damad <joost@damad.be>

use std::fmt;
use std::fs::File;
use std::io::Read;

extern crate rustysexp;
use rustysexp::Sexp;
use rustysexp::Atom;

type ERes<T> = Result<T, String>;

fn err<T>(msg: &str) -> ERes<T> {
    Err(String::from(msg))
}

pub struct Module {
    name: String,
    elements: Vec<Element>
}

impl Module {
    fn new(name: &String) -> Module {
        Module { name: name.clone(), elements: vec![] }
    }
    fn append(&mut self, e: Element) {
        self.elements.push(e)
    }
}

impl fmt::Display for Module {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(module {}\n", self.name));
        for e in &self.elements {
            try!(write!(f, "{}\n", e))
        };
        write!(f, ")")
    }
}

pub enum Element {
    Layer(String),
    Descr(String),
    FpText(FpText),
    Pad,
    FpPoly,
    FpLine,
    FpCircle
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Layer(ref s) => write!(f, "(layer {})", s),
            Element::Descr(ref s) => write!(f, "(descr \"{}\")", s),
            Element::FpText(ref p) => write!(f, "{}", p),
            Element::Pad => write!(f, "(pad)"),
            Element::FpPoly => write!(f, "(fp_poly)"),
            Element::FpLine => write!(f, "(fp_line)"),
            Element::FpCircle => write!(f, "(fp_circle)"),
        }
    }
}

pub struct FpText {
    name: String,
    value: String,
    at: At,
    layer: String,
    effects: Effects,
    hide: bool,
}

impl FpText {
    fn new(name: &String, value: &String) -> FpText {
        FpText {
            name: name.clone(),
            value: value.clone(),
            at: At::new(0.,0.,0.),
            layer: String::from("cow"),
            effects: Effects::new(),
            hide: false
        }
    }
}

impl fmt::Display for FpText {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "(fp_text {} \"{}\" {} (layer {}) {})", self.name, self.value, self.at, self.layer, self.effects)
    }
}

pub struct At {
    x: f64,
    y: f64,
    rot: f64
}

impl At {
    fn new(x:f64 ,y:f64, rot:f64) -> At {
        At { x:x, y:y, rot:rot }
    }
}

impl fmt::Display for At {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "(at {} {} {})", self.x, self.y, self.rot)
    }
}

pub struct Effects {
    todo: String
}

impl Effects {
    fn new() -> Effects {
        Effects { todo: String::from("todo") }
    }
}

impl fmt::Display for Effects {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "(effects)")
    }
}

fn parse_layer(v: &Vec<Sexp>) -> ERes<Element> {
    match v[1] {
        Sexp::Atom(Atom::S(ref s)) => {
            Ok(Element::Layer(s.clone()))
        }
        ref x => Err(format!("unexpected element in layer: {}", x))
    }
}

fn parse_descr(v: &Vec<Sexp>) -> ERes<Element> {
    match v[1] {
        Sexp::Atom(Atom::Q(ref s)) => {
            Ok(Element::Descr(s.clone()))
        }
        ref x => Err(format!("unexpected element in descr: {}", x))
    }
}
fn parse_fp_text(v: &Vec<Sexp>) -> ERes<Element> {
    let name = try!(match v[1] {
        Sexp::Atom(Atom::S(ref s)) => Ok(s),
        ref x => err("expecting name for fp_text")
    });
    let value = try!(match v[2] {
        Sexp::Atom(Atom::Q(ref s)) => Ok(s),
        ref x => err("expecting value for fp_text")
    });
    let mut fp = FpText::new(name, value);
    for e in &v[3..] {
    }
    Ok(Element::FpText(fp))
}
fn parse_pad(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::Pad)
}
fn parse_fp_poly(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpPoly)
}
fn parse_fp_line(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpLine)
}
fn parse_fp_circle(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpCircle)
}

fn parse_element_list(v: &Vec<Sexp>) -> ERes<Element> {
    match v[0] {
        Sexp::Atom(Atom::S(ref s)) => {
            match &s[..] {
                "layer" => parse_layer(v),
                "descr" => parse_descr(v),
                "fp_text" => parse_fp_text(v),
                "pad" => parse_pad(v),
                "fp_poly" => parse_fp_poly(v),
                "fp_line" => parse_fp_line(v),
                "fp_circle" => parse_fp_circle(v),
                x => Err(format!("unknown element in module: {}", x))
            }
        }
        _ => err("expecting atom")
    }
}

fn parse_element(s: &Sexp) -> ERes<Element> {
    match *s {
        Sexp::List(ref v) => parse_element_list(&v),
        _ => err("expecting element list in module")
    }
}

fn parse_module_list(v: &Vec<Sexp>) -> ERes<Module> {
    let mut module = (match v[0] {
        Sexp::Atom(Atom::S(ref s)) if s == "module" => {
            match v[1] {
                Sexp::Atom(Atom::S(ref s)) => {
                    Ok(Module::new(s))
                }
                ref x => return Err(format!("expecting module name got {}", x))
            }
        }
        _ => err("expecting module")
    }).unwrap();
    for e in &v[2..] {
        let el = try!(parse_element(e));
        module.append(el)
    }
    Ok(module)
}

fn parse_module(s: Sexp) -> ERes<Module> {
    match s {
        Sexp::List(v) => parse_module_list(&v),
        _ => err("expecting top level list")
    }
}

fn parse(s: &str) -> ERes<Module> {
    match rustysexp::parse_str(s) {
        Ok(s) => parse_module(s),
        Err(x) => Err(format!("IOError: {}", x))
    }
}

fn read_file(name: &str) -> Result<String,std::io::Error> {
    let mut f = try!(File::open(name));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    Ok(s)
}

pub fn parse_str(s: &str) -> Module {
    parse(s).unwrap()
}

pub fn parse_file(name: &str) -> Module {
    let s = read_file(name).unwrap();
    parse(&s[..]).unwrap()
}

<|endoftext|>