<commit_before>//! Used to specify the constraint name for an upsert statement in the form `ON
//! CONFLICT ON CONSTRAINT`. Note that `constraint_name` must be the name of a
//! unique constraint, not the name of an index.

use pg::Pg;
use query_builder::*;
use result::QueryResult;
use upsert::{ConflictTarget, OnConflictTarget};

/// # Example
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../upsert/on_conflict_docs_setup.rs");
/// #
/// # fn main() {
/// #     use users::dsl::*;
/// use diesel::pg::upsert::*;
///
/// #     let conn = establish_connection();
/// #     conn.execute("TRUNCATE TABLE users").unwrap();
/// conn.execute("ALTER TABLE users ADD CONSTRAINT users_name UNIQUE (name)").unwrap();
/// let user = User { id: 1, name: "Sean", };
/// let same_name_different_id = User { id: 2, name: "Sean" };
/// let same_id_different_name = User { id: 1, name: "Pascal" };
///
/// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(&conn));
///
/// let inserted_row_count = diesel::insert_into(users)
///     .values(&same_name_different_id)
///     .on_conflict(on_constraint("users_name"))
///     .do_nothing()
///     .execute(&conn);
/// assert_eq!(Ok(0), inserted_row_count);
///
/// let pk_conflict_result = diesel::insert_into(users)
///     .values(&same_id_different_name)
///     .on_conflict(on_constraint("users_name"))
///     .do_nothing()
///     .execute(&conn);
/// assert!(pk_conflict_result.is_err());
/// # }
/// ```
pub fn on_constraint(constraint_name: &str) -> OnConstraint {
    OnConstraint {
        constraint_name: constraint_name,
    }
}

#[doc(hidden)]
#[derive(Debug, Clone, Copy)]
pub struct OnConstraint<'a> {
    constraint_name: &'a str,
}

impl<'a> QueryFragment<Pg> for ConflictTarget<OnConstraint<'a>> {
    fn walk_ast(&self, mut out: AstPass<Pg>) -> QueryResult<()> {
        out.push_sql(" ON CONSTRAINT ");
        try!(out.push_identifier(self.0.constraint_name));
        Ok(())
    }
}

impl<'a, Table> OnConflictTarget<Table> for ConflictTarget<OnConstraint<'a>> {}
<commit_msg>Fix doc test<commit_after>//! Used to specify the constraint name for an upsert statement in the form `ON
//! CONFLICT ON CONSTRAINT`. Note that `constraint_name` must be the name of a
//! unique constraint, not the name of an index.

use pg::Pg;
use query_builder::*;
use result::QueryResult;
use upsert::{ConflictTarget, OnConflictTarget};

/// # Example
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("../upsert/on_conflict_docs_setup.rs");
/// #
/// # fn main() {
/// #     use users::dsl::*;
/// use diesel::upsert::*;
///
/// #     let conn = establish_connection();
/// #     conn.execute("TRUNCATE TABLE users").unwrap();
/// conn.execute("ALTER TABLE users ADD CONSTRAINT users_name UNIQUE (name)").unwrap();
/// let user = User { id: 1, name: "Sean", };
/// let same_name_different_id = User { id: 2, name: "Sean" };
/// let same_id_different_name = User { id: 1, name: "Pascal" };
///
/// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(&conn));
///
/// let inserted_row_count = diesel::insert_into(users)
///     .values(&same_name_different_id)
///     .on_conflict(on_constraint("users_name"))
///     .do_nothing()
///     .execute(&conn);
/// assert_eq!(Ok(0), inserted_row_count);
///
/// let pk_conflict_result = diesel::insert_into(users)
///     .values(&same_id_different_name)
///     .on_conflict(on_constraint("users_name"))
///     .do_nothing()
///     .execute(&conn);
/// assert!(pk_conflict_result.is_err());
/// # }
/// ```
pub fn on_constraint(constraint_name: &str) -> OnConstraint {
    OnConstraint {
        constraint_name: constraint_name,
    }
}

#[doc(hidden)]
#[derive(Debug, Clone, Copy)]
pub struct OnConstraint<'a> {
    constraint_name: &'a str,
}

impl<'a> QueryFragment<Pg> for ConflictTarget<OnConstraint<'a>> {
    fn walk_ast(&self, mut out: AstPass<Pg>) -> QueryResult<()> {
        out.push_sql(" ON CONSTRAINT ");
        try!(out.push_identifier(self.0.constraint_name));
        Ok(())
    }
}

impl<'a, Table> OnConflictTarget<Table> for ConflictTarget<OnConstraint<'a>> {}
<|endoftext|>


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

//! Rust helpers for Gecko's nsTArray.

use crate::gecko_bindings::bindings;
use crate::gecko_bindings::structs::{nsTArray, nsTArrayHeader};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::slice;

impl<T> Deref for nsTArray<T> {
    type Target = [T];

    fn deref<'a>(&'a self) -> &'a [T] {
        unsafe { slice::from_raw_parts(self.slice_begin(), self.header().mLength as usize) }
    }
}

impl<T> DerefMut for nsTArray<T> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut [T] {
        unsafe { slice::from_raw_parts_mut(self.slice_begin(), self.header().mLength as usize) }
    }
}

impl<T> nsTArray<T> {
    #[inline]
    fn header<'a>(&'a self) -> &'a nsTArrayHeader {
        debug_assert!(!self.mBuffer.is_null());
        unsafe { mem::transmute(self.mBuffer) }
    }

    // unsafe, since header may be in shared static or something
    unsafe fn header_mut<'a>(&'a mut self) -> &'a mut nsTArrayHeader {
        debug_assert!(!self.mBuffer.is_null());

        mem::transmute(self.mBuffer)
    }

    #[inline]
    unsafe fn slice_begin(&self) -> *mut T {
        debug_assert!(!self.mBuffer.is_null());
        (self.mBuffer as *const nsTArrayHeader).offset(1) as *mut _
    }

    /// Ensures the array has enough capacity at least to hold `cap` elements.
    ///
    /// NOTE: This doesn't call the constructor on the values!
    pub fn ensure_capacity(&mut self, cap: usize) {
        if cap >= self.len() {
            unsafe {
                bindings::Gecko_EnsureTArrayCapacity(
                    self as *mut nsTArray<T> as *mut _,
                    cap,
                    mem::size_of::<T>(),
                )
            }
        }
    }

    /// Clears the array storage without calling the destructor on the values.
    #[inline]
    pub unsafe fn clear(&mut self) {
        if self.len() != 0 {
            bindings::Gecko_ClearPODTArray(
                self as *mut nsTArray<T> as *mut _,
                mem::size_of::<T>(),
                mem::align_of::<T>(),
            );
        }
    }

    /// Clears a POD array. This is safe since copy types are memcopyable.
    #[inline]
    pub fn clear_pod(&mut self)
    where
        T: Copy,
    {
        unsafe { self.clear() }
    }

    /// Resize and set the length of the array to `len`.
    ///
    /// unsafe because this may leave the array with uninitialized elements.
    ///
    /// This will not call constructors.  If you need that, either manually add
    /// bindings or run the typed `EnsureCapacity` call on the gecko side.
    pub unsafe fn set_len(&mut self, len: u32) {
        // this can leak
        debug_assert!(len >= self.len() as u32);
        if self.len() == len as usize {
            return;
        }
        self.ensure_capacity(len as usize);
        self.header_mut().mLength = len;
    }

    /// Resizes an array containing only POD elements
    ///
    /// unsafe because this may leave the array with uninitialized elements.
    ///
    /// This will not leak since it only works on POD types (and thus doesn't assert)
    pub unsafe fn set_len_pod(&mut self, len: u32)
    where
        T: Copy,
    {
        if self.len() == len as usize {
            return;
        }
        self.ensure_capacity(len as usize);
        let header = self.header_mut();
        header.mLength = len;
    }

    /// Collects the given iterator into this array.
    ///
    /// Not unsafe because we won't leave uninitialized elements in the array.
    pub fn assign_from_iter_pod<I>(&mut self, iter: I)
    where
        T: Copy,
        I: ExactSizeIterator + Iterator<Item = T>,
    {
        debug_assert!(iter.len() <= 0xFFFFFFFF);
        unsafe {
            self.set_len_pod(iter.len() as u32);
        }
        self.iter_mut().zip(iter).for_each(|(r, v)| *r = v);
    }
}
<commit_msg>style: Improve handling of copying arrays in layout/style/ and servo/.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

//! Rust helpers for Gecko's nsTArray.

use crate::gecko_bindings::bindings;
use crate::gecko_bindings::structs::{nsTArray, nsTArrayHeader, CopyableTArray};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::slice;

impl<T> Deref for nsTArray<T> {
    type Target = [T];

    fn deref<'a>(&'a self) -> &'a [T] {
        unsafe { slice::from_raw_parts(self.slice_begin(), self.header().mLength as usize) }
    }
}

impl<T> DerefMut for nsTArray<T> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut [T] {
        unsafe { slice::from_raw_parts_mut(self.slice_begin(), self.header().mLength as usize) }
    }
}

impl<T> nsTArray<T> {
    #[inline]
    fn header<'a>(&'a self) -> &'a nsTArrayHeader {
        debug_assert!(!self.mBuffer.is_null());
        unsafe { mem::transmute(self.mBuffer) }
    }

    // unsafe, since header may be in shared static or something
    unsafe fn header_mut<'a>(&'a mut self) -> &'a mut nsTArrayHeader {
        debug_assert!(!self.mBuffer.is_null());

        mem::transmute(self.mBuffer)
    }

    #[inline]
    unsafe fn slice_begin(&self) -> *mut T {
        debug_assert!(!self.mBuffer.is_null());
        (self.mBuffer as *const nsTArrayHeader).offset(1) as *mut _
    }

    /// Ensures the array has enough capacity at least to hold `cap` elements.
    ///
    /// NOTE: This doesn't call the constructor on the values!
    pub fn ensure_capacity(&mut self, cap: usize) {
        if cap >= self.len() {
            unsafe {
                bindings::Gecko_EnsureTArrayCapacity(
                    self as *mut nsTArray<T> as *mut _,
                    cap,
                    mem::size_of::<T>(),
                )
            }
        }
    }

    /// Clears the array storage without calling the destructor on the values.
    #[inline]
    pub unsafe fn clear(&mut self) {
        if self.len() != 0 {
            bindings::Gecko_ClearPODTArray(
                self as *mut nsTArray<T> as *mut _,
                mem::size_of::<T>(),
                mem::align_of::<T>(),
            );
        }
    }

    /// Clears a POD array. This is safe since copy types are memcopyable.
    #[inline]
    pub fn clear_pod(&mut self)
    where
        T: Copy,
    {
        unsafe { self.clear() }
    }

    /// Resize and set the length of the array to `len`.
    ///
    /// unsafe because this may leave the array with uninitialized elements.
    ///
    /// This will not call constructors.  If you need that, either manually add
    /// bindings or run the typed `EnsureCapacity` call on the gecko side.
    pub unsafe fn set_len(&mut self, len: u32) {
        // this can leak
        debug_assert!(len >= self.len() as u32);
        if self.len() == len as usize {
            return;
        }
        self.ensure_capacity(len as usize);
        self.header_mut().mLength = len;
    }

    /// Resizes an array containing only POD elements
    ///
    /// unsafe because this may leave the array with uninitialized elements.
    ///
    /// This will not leak since it only works on POD types (and thus doesn't assert)
    pub unsafe fn set_len_pod(&mut self, len: u32)
    where
        T: Copy,
    {
        if self.len() == len as usize {
            return;
        }
        self.ensure_capacity(len as usize);
        let header = self.header_mut();
        header.mLength = len;
    }

    /// Collects the given iterator into this array.
    ///
    /// Not unsafe because we won't leave uninitialized elements in the array.
    pub fn assign_from_iter_pod<I>(&mut self, iter: I)
    where
        T: Copy,
        I: ExactSizeIterator + Iterator<Item = T>,
    {
        debug_assert!(iter.len() <= 0xFFFFFFFF);
        unsafe {
            self.set_len_pod(iter.len() as u32);
        }
        self.iter_mut().zip(iter).for_each(|(r, v)| *r = v);
    }
}

impl<T> Deref for CopyableTArray<T> {
    type Target = nsTArray<T>;
    fn deref(&self) -> &Self::Target {
        &self._base
    }
}

impl<T> DerefMut for CopyableTArray<T> {
    fn deref_mut(&mut self) -> &mut nsTArray<T> {
        &mut self._base
    }
}
<|endoftext|>


<commit_before>//! test type inference issues in parsee compilation
//#![feature(trace_macros)]
#![allow(dead_code)]
#![allow(unused_comparisons)]
#![allow(unused_doc_comment)]
#![allow(unused_variables)]
#![allow(unused_imports)]

#[macro_use]
extern crate nom;

use std::str;
use nom::{alpha, is_digit};

// issue #617
named!(multi<&[u8], () >, fold_many0!( take_while1!( is_digit ), (), |_, _| {}));

// issue #561
#[cfg(feature = "alloc")]
named!(
  value<Vec<Vec<&str>>>,
  do_parse!(
    first_line: map_res!(is_not_s!("\n"), std::str::from_utf8)
      >> rest:
        many_m_n!(
          0,
          1,
          separated_list!(
            tag!("\n\t"),
            map_res!(take_while!(call!(|c| c != b'\n')), std::str::from_utf8)
          )
        ) >> (rest)
  )
);

// issue #534
#[cfg(feature = "alloc")]
fn wrap_suffix(input: &Option<Vec<&[u8]>>) -> Option<String> {
  if input.is_some() {
    ///
    /// I've tried both of the lines below individually and get the same error.
    ///
    Some("hello".to_string())
  //Some(str::from_utf8(u).expect("Found invalid UTF-8").to_string())
  } else {
    None
  }
}

#[cfg(feature = "alloc")]
named!(parse_suffix<&[u8],Option<String>>,do_parse!(
  u: opt!(many1!(alt_complete!(
    tag!("%") | tag!("#")  | tag!("@") | alpha
  ))) >>
  (wrap_suffix(&u))
));
<commit_msg>fix unused doc comment<commit_after>//! test type inference issues in parsee compilation
//#![feature(trace_macros)]
#![allow(dead_code)]
#![allow(unused_comparisons)]
#![allow(unused_doc_comment)]
#![allow(unused_variables)]
#![allow(unused_imports)]

#[macro_use]
extern crate nom;

use std::str;
use nom::{alpha, is_digit};

// issue #617
named!(multi<&[u8], () >, fold_many0!( take_while1!( is_digit ), (), |_, _| {}));

// issue #561
#[cfg(feature = "alloc")]
named!(
  value<Vec<Vec<&str>>>,
  do_parse!(
    first_line: map_res!(is_not_s!("\n"), std::str::from_utf8)
      >> rest:
        many_m_n!(
          0,
          1,
          separated_list!(
            tag!("\n\t"),
            map_res!(take_while!(call!(|c| c != b'\n')), std::str::from_utf8)
          )
        ) >> (rest)
  )
);

// issue #534
#[cfg(feature = "alloc")]
fn wrap_suffix(input: &Option<Vec<&[u8]>>) -> Option<String> {
  if input.is_some() {
    // I've tried both of the lines below individually and get the same error.
    Some("hello".to_string())
  //Some(str::from_utf8(u).expect("Found invalid UTF-8").to_string())
  } else {
    None
  }
}

#[cfg(feature = "alloc")]
named!(parse_suffix<&[u8],Option<String>>,do_parse!(
  u: opt!(many1!(alt_complete!(
    tag!("%") | tag!("#")  | tag!("@") | alpha
  ))) >>
  (wrap_suffix(&u))
));
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::io::{self, Read, Write};
use std::net::Shutdown;

use futures::prelude::*;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::io::shutdown;
use bytes::{Bytes, IntoBuf};
use h2::{self, server as h2s, client as h2c};
use tokio_core::net::TcpStream;

#[async]
pub fn copy_from_h2<
    W: AsyncWrite + 'static,
    B: Stream<Item = Bytes, Error = h2::Error> + 'static,
>(
    src: B,
    mut dst: W,
) -> Result<usize, h2::Error> {
    let mut counter = 0;
    #[async]
    for buf in src {
        let mut buf = buf.into_buf();
        let n = poll!(dst.write_buf(&mut buf))?;
        counter += n;
    }
    await!(shutdown(dst))?;
    Ok(counter)
}

pub trait SendData<B: IntoBuf> {
    fn send_data(&mut self, data: B, end_of_stream: bool) -> Result<(), h2::Error>;
}

impl<B: IntoBuf> SendData<B> for h2c::Stream<B> {
    fn send_data(&mut self, data: B, end_of_stream: bool) -> Result<(), h2::Error> {
        h2c::Stream::send_data(self, data, end_of_stream)
    }
}
impl<B: IntoBuf> SendData<B> for h2s::Stream<B> {
    fn send_data(&mut self, data: B, end_of_stream: bool) -> Result<(), h2::Error> {
        h2s::Stream::send_data(self, data, end_of_stream)
    }
}

#[async]
pub fn copy_to_h2<R: AsyncRead + 'static, H: SendData<Bytes> + 'static>(
    mut src: R,
    mut dst: H,
) -> Result<usize, h2::Error> {
    let mut counter = 0;
    let mut buf = Vec::with_capacity(1024);
    loop {
        let n = poll!(src.read_buf(&mut buf))?;
        if n == 0 {
            dst.send_data(Bytes::from(&buf[..n]), true)?;
            break;
        } else {
            dst.send_data(Bytes::from(&buf[..n]), false)?;
        }
        counter += n;
    }
    Ok(counter)
}

// This is a custom type used to have a custom implementation of the
// `AsyncWrite::shutdown` method which actually calls `TcpStream::shutdown` to
// notify the remote end that we're done writing.
#[derive(Clone)]
pub struct Socket(Rc<TcpStream>);

impl Socket {
    pub fn new(s: TcpStream) -> Socket {
        Socket(Rc::new(s))
    }
}

impl Read for Socket {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        (&*self.0).read(buf)
    }
}

impl Write for Socket {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        (&*self.0).write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl AsyncRead for Socket {}

impl AsyncWrite for Socket {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        try!(self.0.shutdown(Shutdown::Write));
        Ok(().into())
    }
}
<commit_msg>Increase the buffer size to 2048 bytes<commit_after>use std::rc::Rc;
use std::io::{self, Read, Write};
use std::net::Shutdown;

use futures::prelude::*;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::io::shutdown;
use bytes::{Bytes, IntoBuf};
use h2::{self, server as h2s, client as h2c};
use tokio_core::net::TcpStream;

#[async]
pub fn copy_from_h2<
    W: AsyncWrite + 'static,
    B: Stream<Item = Bytes, Error = h2::Error> + 'static,
>(
    src: B,
    mut dst: W,
) -> Result<usize, h2::Error> {
    let mut counter = 0;
    #[async]
    for buf in src {
        let mut buf = buf.into_buf();
        let n = poll!(dst.write_buf(&mut buf))?;
        counter += n;
    }
    await!(shutdown(dst))?;
    Ok(counter)
}

pub trait SendData<B: IntoBuf> {
    fn send_data(&mut self, data: B, end_of_stream: bool) -> Result<(), h2::Error>;
}

impl<B: IntoBuf> SendData<B> for h2c::Stream<B> {
    fn send_data(&mut self, data: B, end_of_stream: bool) -> Result<(), h2::Error> {
        h2c::Stream::send_data(self, data, end_of_stream)
    }
}
impl<B: IntoBuf> SendData<B> for h2s::Stream<B> {
    fn send_data(&mut self, data: B, end_of_stream: bool) -> Result<(), h2::Error> {
        h2s::Stream::send_data(self, data, end_of_stream)
    }
}

#[async]
pub fn copy_to_h2<R: AsyncRead + 'static, H: SendData<Bytes> + 'static>(
    mut src: R,
    mut dst: H,
) -> Result<usize, h2::Error> {
    let mut counter = 0;
    let mut buf = Vec::with_capacity(2048);
    loop {
        let n = poll!(src.read_buf(&mut buf))?;
        if n == 0 {
            dst.send_data(Bytes::from(&buf[..n]), true)?;
            break;
        } else {
            dst.send_data(Bytes::from(&buf[..n]), false)?;
        }
        counter += n;
    }
    Ok(counter)
}

// This is a custom type used to have a custom implementation of the
// `AsyncWrite::shutdown` method which actually calls `TcpStream::shutdown` to
// notify the remote end that we're done writing.
#[derive(Clone)]
pub struct Socket(Rc<TcpStream>);

impl Socket {
    pub fn new(s: TcpStream) -> Socket {
        Socket(Rc::new(s))
    }
}

impl Read for Socket {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        (&*self.0).read(buf)
    }
}

impl Write for Socket {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        (&*self.0).write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl AsyncRead for Socket {}

impl AsyncWrite for Socket {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        try!(self.0.shutdown(Shutdown::Write));
        Ok(().into())
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{self, BufRead, BufReader, Cursor, Read, Seek, SeekFrom};
use std::path::Path;

use crate::dynimage::DynamicImage;
use crate::image::ImageFormat;
use crate::{ImageError, ImageResult};

use super::free_functions;

/// A multi-format image reader.
///
/// Wraps an input reader to facilitate automatic detection of an image's format, appropriate
/// decoding method, and dispatches into the set of supported [`ImageDecoder`] implementations.
///
/// ## Usage
///
/// Opening a file, deducing the format based on the file path automatically, and trying to decode
/// the image contained can be performed by constructing the reader and immediately consuming it.
///
/// ```no_run
/// # use image::ImageError;
/// # use image::io::Reader;
/// # fn main() -> Result<(), ImageError> {
/// let image = Reader::open("path/to/image.png")?
///     .decode()?;
/// # Ok(()) }
/// ```
///
/// It is also possible to make a guess based on the content. This is especially handy if the
/// source is some blob in memory and you have constructed the reader in another way. Here is an
/// example with a `pnm` black-and-white subformat that encodes its pixel matrix with ascii values.
///
#[cfg_attr(feature = "pnm", doc = "```")]
#[cfg_attr(not(feature = "pnm"), doc = "```no_run")]
/// # use image::ImageError;
/// # use image::io::Reader;
/// # fn main() -> Result<(), ImageError> {
/// use std::io::Cursor;
/// use image::ImageFormat;
///
/// let raw_data = b"P1 2 2\n\
///     0 1\n\
///     1 0\n";
///
/// let mut reader = Reader::new(Cursor::new(raw_data))
///     .with_guessed_format()
///     .expect("Cursor io never fails");
/// assert_eq!(reader.format(), Some(ImageFormat::Pnm));
///
/// let image = reader.decode()?;
/// # Ok(()) }
/// ```
///
/// As a final fallback or if only a specific format must be used, the reader always allows manual
/// specification of the supposed image format with [`set_format`].
///
/// [`set_format`]: #method.set_format
/// [`ImageDecoder`]: ../trait.ImageDecoder.html
pub struct Reader<R: Read> {
    /// The reader.
    inner: R,
    /// The format, if one has been set or deduced.
    format: Option<ImageFormat>,
}

impl<R: Read> Reader<R> {
    /// Create a new image reader without a preset format.
    ///
    /// It is possible to guess the format based on the content of the read object with
    /// [`guess_format`], or to set the format directly with [`set_format`].
    ///
    /// [`guess_format`]: #method.guess_format
    /// [`set_format`]: method.set_format
    pub fn new(reader: R) -> Self {
        Reader {
            inner: reader,
            format: None,
        }
    }

    /// Construct a reader with specified format.
    pub fn with_format(reader: R, format: ImageFormat) -> Self {
        Reader {
            inner: reader,
            format: Some(format),
        }
    }

    /// Get the currently determined format.
    pub fn format(&self) -> Option<ImageFormat> {
        self.format
    }

    /// Supply the format as which to interpret the read image.
    pub fn set_format(&mut self, format: ImageFormat) {
        self.format = Some(format);
    }

    /// Remove the current information on the image format.
    ///
    /// Note that many operations require format information to be present and will return e.g. an
    /// `ImageError::UnsupportedError` when the image format has not been set.
    pub fn clear_format(&mut self) {
        self.format = None;
    }

    /// Unwrap the reader.
    pub fn into_inner(self) -> R {
        self.inner
    }
}

impl Reader<BufReader<File>> {
    /// Open a file to read, format will be guessed from path.
    ///
    /// This will not attempt any io operation on the opened file.
    ///
    /// If you want to inspect the content for a better guess on the format, which does not depend
    /// on file extensions, follow this call with a call to [`guess_format`].
    ///
    /// [`guess_format`]: #method.guess_format
    pub fn open<P>(path: P) -> io::Result<Self> where P: AsRef<Path> {
        Self::open_impl(path.as_ref())
    }

    fn open_impl(path: &Path) -> io::Result<Self> {
        let file = File::open(path)?;
        Ok(Reader {
            inner: BufReader::new(file),
            format: ImageFormat::from_path(path).ok(),
        })
    }
}

impl<R: BufRead + Seek> Reader<R> {
    /// Make a format guess based on the content, replacing it on success.
    ///
    /// Returns `Ok` with the guess if no io error occurs. Additionally, replaces the current
    /// format if the guess was successful. If the guess was not unable to determine a format then
    /// the current format of the reader is unchanged.
    ///
    /// Returns an error if the underlying reader fails. The format is unchanged. The error is a
    /// `std::io::Error` and not `ImageError` since the only error case is an error when the
    /// underlying reader seeks.
    ///
    /// When an error occurs, the reader may not have been properly reset and it is potentially
    /// hazardous to continue with more io.
    ///
    /// ## Usage
    ///
    /// This supplements the path based type deduction from [`open`] with content based deduction.
    /// This is more common in Linux and UNIX operating systems and also helpful if the path can
    /// not be directly controlled.
    ///
    /// ```no_run
    /// # use image::ImageError;
    /// # use image::io::Reader;
    /// # fn main() -> Result<(), ImageError> {
    /// let image = Reader::open("image.unknown")?
    ///     .with_guessed_format()?
    ///     .decode()?;
    /// # Ok(()) }
    /// ```
    pub fn with_guessed_format(mut self) -> io::Result<Self> {
        let format = self.guess_format()?;
        // Replace format if found, keep current state if not.
        self.format = format.or(self.format);
        Ok(self)
    }

    fn guess_format(&mut self) -> io::Result<Option<ImageFormat>> {
        let mut start = [0; 16];

        // Save current offset, read start, restore offset.
        let cur = self.inner.seek(SeekFrom::Current(0))?;
        let len = io::copy(
            // Accept shorter files but read at most 16 bytes.
            &mut self.inner.by_ref().take(16),
            &mut Cursor::new(&mut start[..]))?;
        self.inner.seek(SeekFrom::Start(cur))?;

        Ok(free_functions::guess_format_impl(&start[..len as usize]))
    }

    /// Read the image dimensions.
    ///
    /// Uses the current format to construct the correct reader for the format.
    ///
    /// If no format was determined, returns an `ImageError::UnsupportedError`.
    pub fn into_dimensions(mut self) -> ImageResult<(u32, u32)> {
        let format = self.require_format()?;
        free_functions::image_dimensions_with_format_impl(self.inner, format)
    }

    /// Read the image (replaces `load`).
    ///
    /// Uses the current format to construct the correct reader for the format.
    ///
    /// If no format was determined, returns an `ImageError::UnsupportedError`.
    pub fn decode(mut self) -> ImageResult<DynamicImage> {
        let format = self.require_format()?;
        free_functions::load(self.inner, format)
    }

    fn require_format(&mut self) -> ImageResult<ImageFormat> {
        self.format.ok_or_else(||
            ImageError::UnsupportedError("Unable to determine image format".into()))
    }
}
<commit_msg>Fix Reader::open link.<commit_after>use std::fs::File;
use std::io::{self, BufRead, BufReader, Cursor, Read, Seek, SeekFrom};
use std::path::Path;

use crate::dynimage::DynamicImage;
use crate::image::ImageFormat;
use crate::{ImageError, ImageResult};

use super::free_functions;

/// A multi-format image reader.
///
/// Wraps an input reader to facilitate automatic detection of an image's format, appropriate
/// decoding method, and dispatches into the set of supported [`ImageDecoder`] implementations.
///
/// ## Usage
///
/// Opening a file, deducing the format based on the file path automatically, and trying to decode
/// the image contained can be performed by constructing the reader and immediately consuming it.
///
/// ```no_run
/// # use image::ImageError;
/// # use image::io::Reader;
/// # fn main() -> Result<(), ImageError> {
/// let image = Reader::open("path/to/image.png")?
///     .decode()?;
/// # Ok(()) }
/// ```
///
/// It is also possible to make a guess based on the content. This is especially handy if the
/// source is some blob in memory and you have constructed the reader in another way. Here is an
/// example with a `pnm` black-and-white subformat that encodes its pixel matrix with ascii values.
///
#[cfg_attr(feature = "pnm", doc = "```")]
#[cfg_attr(not(feature = "pnm"), doc = "```no_run")]
/// # use image::ImageError;
/// # use image::io::Reader;
/// # fn main() -> Result<(), ImageError> {
/// use std::io::Cursor;
/// use image::ImageFormat;
///
/// let raw_data = b"P1 2 2\n\
///     0 1\n\
///     1 0\n";
///
/// let mut reader = Reader::new(Cursor::new(raw_data))
///     .with_guessed_format()
///     .expect("Cursor io never fails");
/// assert_eq!(reader.format(), Some(ImageFormat::Pnm));
///
/// let image = reader.decode()?;
/// # Ok(()) }
/// ```
///
/// As a final fallback or if only a specific format must be used, the reader always allows manual
/// specification of the supposed image format with [`set_format`].
///
/// [`set_format`]: #method.set_format
/// [`ImageDecoder`]: ../trait.ImageDecoder.html
pub struct Reader<R: Read> {
    /// The reader.
    inner: R,
    /// The format, if one has been set or deduced.
    format: Option<ImageFormat>,
}

impl<R: Read> Reader<R> {
    /// Create a new image reader without a preset format.
    ///
    /// It is possible to guess the format based on the content of the read object with
    /// [`guess_format`], or to set the format directly with [`set_format`].
    ///
    /// [`guess_format`]: #method.guess_format
    /// [`set_format`]: method.set_format
    pub fn new(reader: R) -> Self {
        Reader {
            inner: reader,
            format: None,
        }
    }

    /// Construct a reader with specified format.
    pub fn with_format(reader: R, format: ImageFormat) -> Self {
        Reader {
            inner: reader,
            format: Some(format),
        }
    }

    /// Get the currently determined format.
    pub fn format(&self) -> Option<ImageFormat> {
        self.format
    }

    /// Supply the format as which to interpret the read image.
    pub fn set_format(&mut self, format: ImageFormat) {
        self.format = Some(format);
    }

    /// Remove the current information on the image format.
    ///
    /// Note that many operations require format information to be present and will return e.g. an
    /// `ImageError::UnsupportedError` when the image format has not been set.
    pub fn clear_format(&mut self) {
        self.format = None;
    }

    /// Unwrap the reader.
    pub fn into_inner(self) -> R {
        self.inner
    }
}

impl Reader<BufReader<File>> {
    /// Open a file to read, format will be guessed from path.
    ///
    /// This will not attempt any io operation on the opened file.
    ///
    /// If you want to inspect the content for a better guess on the format, which does not depend
    /// on file extensions, follow this call with a call to [`guess_format`].
    ///
    /// [`guess_format`]: #method.guess_format
    pub fn open<P>(path: P) -> io::Result<Self> where P: AsRef<Path> {
        Self::open_impl(path.as_ref())
    }

    fn open_impl(path: &Path) -> io::Result<Self> {
        let file = File::open(path)?;
        Ok(Reader {
            inner: BufReader::new(file),
            format: ImageFormat::from_path(path).ok(),
        })
    }
}

impl<R: BufRead + Seek> Reader<R> {
    /// Make a format guess based on the content, replacing it on success.
    ///
    /// Returns `Ok` with the guess if no io error occurs. Additionally, replaces the current
    /// format if the guess was successful. If the guess was not unable to determine a format then
    /// the current format of the reader is unchanged.
    ///
    /// Returns an error if the underlying reader fails. The format is unchanged. The error is a
    /// `std::io::Error` and not `ImageError` since the only error case is an error when the
    /// underlying reader seeks.
    ///
    /// When an error occurs, the reader may not have been properly reset and it is potentially
    /// hazardous to continue with more io.
    ///
    /// ## Usage
    ///
    /// This supplements the path based type deduction from [`open`](Reader::open) with content based deduction.
    /// This is more common in Linux and UNIX operating systems and also helpful if the path can
    /// not be directly controlled.
    ///
    /// ```no_run
    /// # use image::ImageError;
    /// # use image::io::Reader;
    /// # fn main() -> Result<(), ImageError> {
    /// let image = Reader::open("image.unknown")?
    ///     .with_guessed_format()?
    ///     .decode()?;
    /// # Ok(()) }
    /// ```
    pub fn with_guessed_format(mut self) -> io::Result<Self> {
        let format = self.guess_format()?;
        // Replace format if found, keep current state if not.
        self.format = format.or(self.format);
        Ok(self)
    }

    fn guess_format(&mut self) -> io::Result<Option<ImageFormat>> {
        let mut start = [0; 16];

        // Save current offset, read start, restore offset.
        let cur = self.inner.seek(SeekFrom::Current(0))?;
        let len = io::copy(
            // Accept shorter files but read at most 16 bytes.
            &mut self.inner.by_ref().take(16),
            &mut Cursor::new(&mut start[..]))?;
        self.inner.seek(SeekFrom::Start(cur))?;

        Ok(free_functions::guess_format_impl(&start[..len as usize]))
    }

    /// Read the image dimensions.
    ///
    /// Uses the current format to construct the correct reader for the format.
    ///
    /// If no format was determined, returns an `ImageError::UnsupportedError`.
    pub fn into_dimensions(mut self) -> ImageResult<(u32, u32)> {
        let format = self.require_format()?;
        free_functions::image_dimensions_with_format_impl(self.inner, format)
    }

    /// Read the image (replaces `load`).
    ///
    /// Uses the current format to construct the correct reader for the format.
    ///
    /// If no format was determined, returns an `ImageError::UnsupportedError`.
    pub fn decode(mut self) -> ImageResult<DynamicImage> {
        let format = self.require_format()?;
        free_functions::load(self.inner, format)
    }

    fn require_format(&mut self) -> ImageResult<ImageFormat> {
        self.format.ok_or_else(||
            ImageError::UnsupportedError("Unable to determine image format".into()))
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;

use term::terminfo::TermInfo;
use unicode_width::UnicodeWidthStr;

use std::sync::mpsc::{Receiver, Sender};
use std::borrow::Cow;
use std::collections::HashMap;
use std::ffi::OsString;

use std::sync::mpsc;
use std::io;
use std::env;
use std::thread;

use bis_c::{TermTrack, TermSize};
use error::StringError;
use search::SearchBase;

// TermControl contains utility funcitons for terminfo
struct TermControl {
    // come on man Vec<u8>? Really? smh
    strings: HashMap<String, OsString>
}

// our user interface instance
pub struct UI {
    // track is a guard, we never touch it manually
    #[allow(dead_code)]
    track: TermTrack,
    size: TermSize,
    query: Sender<String>,
    matches: Receiver<Vec<Cow<'static, str>>>,
    save_cursor: String,
    restore_cursor: String,
    clr_eos: String
}

impl Drop for UI {
    fn drop(&mut self) {
        debug!("Clearing screen on exit");
        let mut output = io::stdout();
        match write!(output, "{}", self.clr_eos) {
            Ok(_) => {
                trace!("Cleared screen successfully");
            },
            Err(e) => {
                error!("Failed to clear screen: {}", e);
            }
        }
        debug!("Flushing output");
        match output.flush() {
            Ok(_) => {
                trace!("Flushed screen successfully");
            },
            Err(e) => {
                error!("Failed to flush screen: {}", e);
            }
        }
    }
}

impl TermControl {
    pub fn create() -> Result<TermControl, StringError> {
        debug!("Getting terminal info");
        let info = match TermInfo::from_env() {
            Ok(info) => info,
            Err(e) => return Err(StringError::new("Failed to get TermInfo", Some(Box::new(e))))
        };

        trace!("Got terminfo: {:?}", info);

        let mut strings = HashMap::default();

        for (name, value) in info.strings.into_iter() {
            strings.insert(name, match OsString::from_bytes(value) {
                Some(s) => s,
                None => return Err(StringError::new("Failed to convert value into an OsString", None))
            });
        }

        // right now all we care about are the strings
        Ok(TermControl {
            strings: strings
        })
    }
}

impl UI {
    pub fn create() -> Result<UI, StringError> {
        debug!("Getting terminfo");
        let mut info = match TermInfo::from_env() {
            Ok(t) => t,
            Err(e) => return Err(StringError::new("Failed to get terminfo",
                                                  Some(Box::new(e))))
        };

        // use terminfo to get control sequences
        debug!("Terminfo: {:?}", info);

        trace!("Getting save_cursor");
        let save_cursor = match info.strings.remove(&format!("sc")) {
            None => return Err(StringError::new("Terminfo did not contain save_cursor", None)),
            Some(item) => match String::from_utf8(item) {
                Err(e) => return Err(StringError::new("save_cursor was not valid utf-8", Some(Box::new(e)))),
                Ok(s) => {
                    trace!("save_cursor: {:?}", s.escape_default());
                    s
                }
            }
        };

        trace!("Getting restore_cursor");
        let restore_cursor = match info.strings.remove(&format!("rc")) {
            None => return Err(StringError::new("Terminfo did not contain restore_cursor", None)),
            Some(item) => match String::from_utf8(item) {
                Err(e) => return Err(StringError::new("restore_cursor was not valid utf-8", Some(Box::new(e)))),
                Ok(s) => {
                    trace!("restore_cursor: {:?}", s.escape_default());
                    s
                }
            }
        };

        trace!("Getting clr_eos");
        let clr_eos = match info.strings.remove(&format!("clr_eos")) {
            None => return Err(StringError::new("Terminfo did not contain clr_eos", None)),
            Some(item) => match String::from_utf8(item) {
                Err(e) => return Err(StringError::new("clr_eos was not valid utf-8", Some(Box::new(e)))),
                Ok(s) => {
                    trace!("restore_cursor: {:?}", s.escape_default());
                    s
                }
            }
        };

        let mut track = TermTrack::default();

        debug!("Getting terminal size");
        let size = match track.get_size() {
            Err(e) => return Err(StringError::new("Failed to get terminal size", Some(Box::new(e)))),
            Ok(s) => {
                trace!("Terminal size: {:?}", s);
                s
            }
        };

        debug!("Preparing terminal");
        match track.prepare() {
            Err(e) => return Err(StringError::new("Failed to prepare terminal", Some(Box::new(e)))),
            Ok(_) => {
                trace!("Terminal prepared successfully");
            }
        }

        debug!("Starting search thread");

        trace!("Creating thread primitives");
        let (query_tx, query_rx) = mpsc::channel();
        let (matches_tx, matches_rx) = mpsc::channel();

        trace!("Starting thread");
        thread::spawn(move|| {
            search_thread(query_rx, matches_tx);
        });

        debug!("Creating UI instance");
        let instance = UI {
            track: track,
            size: size,
            query: query_tx,
            matches: matches_rx,
            save_cursor: save_cursor,
            restore_cursor: restore_cursor,
            clr_eos: clr_eos
        };

        trace!("Instance creation successful");
        Ok(instance)
    }

    pub fn start(&mut self) -> Result<(), StringError> {
        // assume start on a new line
        // get handles for io
        let stdout = io::stdout();
        let stdin = io::stdin();
        let mut output = stdout.lock();
        let input = stdin.lock();

        let mut query = String::new();

        // draw our prompt, move ten lines down and then back up, and save the cursor
        debug!("Drawing prompt");
        match write!(output, "Match: {}", self.save_cursor) {
            Err(e) => return Err(StringError::new("Failed to draw prompt", Some(Box::new(e)))),
            Ok(_) => {
                trace!("Drew prompt successfully");
            }
        }

        // flush the output
        debug!("Flushing output");
        match output.flush() {
            Ok(_) => {
                trace!("Successfully flushed output");
            },
            Err(e) => {
                return Err(StringError::new("Failed to flush output", Some(Box::new(e))));
            }
        }

        // wait for input
        for maybe_chr in input.chars() {
            let chr = match maybe_chr {
                Err(e) => return Err(StringError::new("Failed to read character", Some(Box::new(e)))),
                Ok(c) => c
            };
            trace!("Got character: {:?}", chr);

            // push the character onto the query string
            query.push(chr);

            // draw the character, save the cursor position, clear the screen after us
            match write!(output, "{}{}{}", chr, self.save_cursor, self.clr_eos) {
                Err(e) => return Err(StringError::new("Failed to output character", Some(Box::new(e)))),
                Ok(_) => {
                    trace!("Outputted character successfully");
                }
            }

            // send the search thread our query
            debug!("Sending {} to search thread", &query);
            match self.query.send(query.clone()) {
                Ok(_) => {
                    trace!("Send successful");
                },
                Err(e) => {
                    return Err(StringError::new("Failed to send to search thread", Some(Box::new(e))));
                }
            }

            // wait for matches
            let matches = match self.matches.recv() {
                Ok(m) => m,
                Err(e) => {
                    return Err(StringError::new("Failed to read matches", Some(Box::new(e))));
                }
            };

            debug!("Got matches: {:?}", &matches);

            // draw the matches
            for item in matches.into_iter() {
                if UnicodeWidthStr::width(item.as_ref()) > self.size.cols {
                    let mut owned = item.into_owned();
                    while UnicodeWidthStr::width((&owned as &AsRef<str>).as_ref()) > self.size.cols {
                        // truncate long lines
                        owned.pop();
                    }
                    // draw the truncated item
                    match write!(output, "\n{}", owned) {
                        Err(e) => return Err(StringError::new("Failed to draw match", Some(Box::new(e)))),
                        Ok(_) => {
                            trace!("Drew match successfully");
                        }
                    }
                } else {
                    // draw the match after a newline
                    match write!(output, "\n{}", item) {
                        Err(e) => return Err(StringError::new("Failed to draw match", Some(Box::new(e)))),
                        Ok(_) => {
                            trace!("Drew match successfully");
                        }
                    }
                }
            }

            // restore the cursor
            match write!(output, "{}", self.restore_cursor) {
                Err(e) => return Err(StringError::new("Failed to restore cursor", Some(Box::new(e)))),
                Ok(_) => {
                    trace!("Restored cursor successfully");
                }
            }

            // flush the output
            match output.flush() {
                Ok(_) => {
                    trace!("Successfully flushed output");
                },
                Err(e) => {
                    return Err(StringError::new("Failed to flush output", Some(Box::new(e))));
                }
            }
        }

        // Return success
        Ok(())
    }
}

pub fn search_thread(query: Receiver<String>,
                     matches: Sender<Vec<Cow<'static, str>>>) {
    debug!("Starting query thread");

    debug!("Getting history path");
    let history_path = match env::var("HISTFILE") {
        Ok(p) => {
            trace!("Got history path: {:?}", p);
            p
        },
        Err(e) => panic!("Failed to get bash history file: {}", e)
    };

    let mut base = SearchBase::default();

    // read the history
    info!("Reading history");
    match base.read_history(history_path) {
        Ok(_) => {
            // success
        },
        Err(e) => {
            panic!("Failed to read history: {}", e)
        }
    }

    debug!("Starting query loop");

    loop {
        trace!("Waiting for a query");
        match query.recv() {
            Err(e) => {
                debug!("Search thread exiting: {}", e);
                break;
            },
            Ok(q) => {
                debug!("Got query: {:?}", q);
                let result = base.query(q);
                debug!("Got result: {:?}", result);
                match matches.send(result) {
                    Err(e) => {
                        debug!("Search thread exiting: {}", e);
                        break;
                    },
                    Ok(_) => {
                        trace!("Matches sent successfully");
                    }
                }
            }
        }
    }
}
<commit_msg>Begin implementing TermControl<commit_after>use std::io::prelude::*;

use term::terminfo::TermInfo;
use unicode_width::UnicodeWidthStr;

use std::sync::mpsc::{Receiver, Sender};
use std::borrow::Cow;
use std::collections::HashMap;
use std::ffi::OsString;

use std::sync::mpsc;
use std::io;
use std::env;
use std::thread;

use bis_c::{TermTrack, TermSize};
use error::StringError;
use search::SearchBase;

// TermControl contains utility funcitons for terminfo
struct TermControl {
    strings: HashMap<String, String>,
    globals: HashMap<char, TermStack>
}

#[derive(PartialEq)]
enum TermStack {
    Str(String),
    Int(isize),
    Bool(bool)
}

// our user interface instance
pub struct UI {
    // track is a guard, we never touch it manually
    #[allow(dead_code)]
    track: TermTrack,
    size: TermSize,
    query: Sender<String>,
    matches: Receiver<Vec<Cow<'static, str>>>,
    save_cursor: String,
    restore_cursor: String,
    clr_eos: String
}

impl Drop for UI {
    fn drop(&mut self) {
        debug!("Clearing screen on exit");
        let mut output = io::stdout();
        match write!(output, "{}", self.clr_eos) {
            Ok(_) => {
                trace!("Cleared screen successfully");
            },
            Err(e) => {
                error!("Failed to clear screen: {}", e);
            }
        }
        debug!("Flushing output");
        match output.flush() {
            Ok(_) => {
                trace!("Flushed screen successfully");
            },
            Err(e) => {
                error!("Failed to flush screen: {}", e);
            }
        }
    }
}

impl TermControl {
    pub fn create() -> Result<TermControl, StringError> {
        debug!("Getting terminal info");
        let info = match TermInfo::from_env() {
            Ok(info) => info,
            Err(e) => return Err(StringError::new("Failed to get TermInfo", Some(Box::new(e))))
        };

        trace!("Got terminfo: {:?}", info);

        let mut strings = HashMap::default();

        for (name, value) in info.strings.into_iter() {
            strings.insert(name, match String::from_utf8(value) {
                Ok(s) => s,
                Err(e) => return Err(StringError::new("Failed to convert value into an OsString", Some(Box::new(e))))
            });
        }

        // right now all we care about are the strings
        Ok(TermControl {
            strings: strings,
            globals: HashMap::default()
        })
    }

    pub fn get_string<T: Borrow<String>>(&mut self, name: T, params: Vec<TermStack>) -> Option<String> {
        let sequence = match self.strings.get(name) {
            None => return None,
            Some(s) => {
                trace!("Matched string: {:?}", s);
                s.clone()
            }
        };

        let mut escaped = false;

        let mut escape = String::default();
        let result = String::default();
        let stack: Vec<TermStack> = vec![];
        let mut locals: HashMap<char, TermStack> = HashMap::default();

        for c in sequence.chars() {
            if !escaped {
                if c == '%' {
                    escaped = true;
                } else {
                    result.push(c);
                }
            } else if escape.is_empty() {
                if c == '%' {
                    result.push('%');
                    escaped = false;
                } else if c == 'c' {
                    match stack.pop() {
                        Some(Str(s)) => {
                            if !s.is_empty() {
                                result.push(s[0]);
                            }
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == 's' {
                    match stack.pop() {
                        Some(Str(s)) => {
                            result.push_str(s.as_str())
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == 'l' {
                    let len = 0;
                    let push;
                    match stack.last() {
                        Some(Str(s)) => {
                            len = s.len() as isize;
                            push = true;
                        },
                        _ => {
                            push = false;
                        }
                    }
                    if push {
                        stack.push(Int(len));
                    }

                    escaped = false;
                } else if c == 'i' {
                    match params.get_mut(0) {
                        Some(&mut Int(ref mut i)) => {
                            i += 1;
                        },
                        _ => {}
                    }

                    match params.get_mut(1) {
                        Some(&mut Int(ref mut i)) => {
                            i += 1;
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == '+' {
                    let first = stack.pop();
                    let second = stack.pop();
                    match first {
                        Some(Int(i)) => match second {
                            Some(Int(oi)) => {
                                stack.push(Int(i + oi));
                            },
                            _ => {}
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == '-' {
                    let first = stack.pop();
                    let second = stack.pop();
                    match first {
                        Some(Int(i)) => match second {
                            Some(Int(oi)) => {
                                stack.push(Int(i - oi));
                            },
                            _ => {}
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == '*' {
                    let first = stack.pop();
                    let second = stack.pop();
                    match first {
                        Some(Int(i)) => match second {
                            Some(Int(oi)) => {
                                stack.push(Int(i * oi));
                            },
                            _ => {}
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == '/' {
                    let first = stack.pop();
                    let second = stack.pop();
                    match first {
                        Some(Int(i)) => match second {
                            Some(Int(oi)) => {
                                if oi != 0 {
                                    stack.push(Int(i / oi));
                                }
                            },
                            _ => {}
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == 'm' {
                    let first = stack.pop();
                    let second = stack.pop();
                    match first {
                        Some(Int(i)) => match second {
                            Some(Int(oi)) => {
                                stack.push(Int(i % oi));
                            },
                            _ => {}
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == '&' {
                    let first = stack.pop();
                    let second = stack.pop();
                    match first {
                        Some(Int(i)) => match second {
                            Some(Int(oi)) => {
                                stack.push(Int(i & oi));
                            },
                            _ => {}
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == '|' {
                    let first = stack.pop();
                    let second = stack.pop();
                    match first {
                        Some(Int(i)) => match second {
                            Some(Int(oi)) => {
                                stack.push(Int(i | oi));
                            },
                            _ => {}
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == '^' {
                    let first = stack.pop();
                    let second = stack.pop();
                    match first {
                        Some(Int(i)) => match second {
                            Some(Int(oi)) => {
                                stack.push(Int(i ^ oi));
                            },
                            _ => {}
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == '=' {
                    let first = stack.pop();
                    let second = stack.pop();
                    match first {
                        Some(v) => match second {
                            Some(ov) => {
                                stack.push(Bool(v == ov));
                            },
                            _ => {}
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == '>' {
                    let first = stack.pop();
                    let second = stack.pop();
                    match first {
                        Some(Int(i)) => match second {
                            Some(Int(oi)) => {
                                stack.push(Bool(i > oi));
                            },
                            _ => {}
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == '>' {
                    let first = stack.pop();
                    let second = stack.pop();
                    match first {
                        Some(Int(i)) => match second {
                            Some(Int(oi)) => {
                                stack.push(Bool(i < oi));
                            },
                            _ => {}
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == 'A' {
                    let first = stack.pop();
                    let second = stack.pop();
                    match first {
                        Some(Bool(b)) => match second {
                            Some(Bool(ob)) => {
                                stack.push(Bool(b && ob));
                            },
                            _ => {}
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == 'O' {
                    let first = stack.pop();
                    let second = stack.pop();
                    match first {
                        Some(Bool(b)) => match second {
                            Some(Bool(ob)) => {
                                stack.push(Bool(b || ob));
                            },
                            _ => {}
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == '!' {
                    let item = stack.pop();
                    match item {
                        Some(Bool(b)) => {
                            stack.push(Bool(!b));
                        },
                        _ => {}
                    }

                    escaped = false;
                } else if c == '~' {
                    let item = stack.pop();
                    match item {
                        Some(Int(b)) => {
                            stack.push(Int(!b));
                        },
                        _ => {}
                    }

                    escaped = false;
                }
            }
        }
    }
}

impl UI {
    pub fn create() -> Result<UI, StringError> {
        debug!("Getting terminfo");
        let mut info = match TermInfo::from_env() {
            Ok(t) => t,
            Err(e) => return Err(StringError::new("Failed to get terminfo",
                                                  Some(Box::new(e))))
        };

        // use terminfo to get control sequences
        debug!("Terminfo: {:?}", info);

        trace!("Getting save_cursor");
        let save_cursor = match info.strings.remove(&format!("sc")) {
            None => return Err(StringError::new("Terminfo did not contain save_cursor", None)),
            Some(item) => match String::from_utf8(item) {
                Err(e) => return Err(StringError::new("save_cursor was not valid utf-8", Some(Box::new(e)))),
                Ok(s) => {
                    trace!("save_cursor: {:?}", s.escape_default());
                    s
                }
            }
        };

        trace!("Getting restore_cursor");
        let restore_cursor = match info.strings.remove(&format!("rc")) {
            None => return Err(StringError::new("Terminfo did not contain restore_cursor", None)),
            Some(item) => match String::from_utf8(item) {
                Err(e) => return Err(StringError::new("restore_cursor was not valid utf-8", Some(Box::new(e)))),
                Ok(s) => {
                    trace!("restore_cursor: {:?}", s.escape_default());
                    s
                }
            }
        };

        trace!("Getting clr_eos");
        let clr_eos = match info.strings.remove(&format!("clr_eos")) {
            None => return Err(StringError::new("Terminfo did not contain clr_eos", None)),
            Some(item) => match String::from_utf8(item) {
                Err(e) => return Err(StringError::new("clr_eos was not valid utf-8", Some(Box::new(e)))),
                Ok(s) => {
                    trace!("restore_cursor: {:?}", s.escape_default());
                    s
                }
            }
        };

        let mut track = TermTrack::default();

        debug!("Getting terminal size");
        let size = match track.get_size() {
            Err(e) => return Err(StringError::new("Failed to get terminal size", Some(Box::new(e)))),
            Ok(s) => {
                trace!("Terminal size: {:?}", s);
                s
            }
        };

        debug!("Preparing terminal");
        match track.prepare() {
            Err(e) => return Err(StringError::new("Failed to prepare terminal", Some(Box::new(e)))),
            Ok(_) => {
                trace!("Terminal prepared successfully");
            }
        }

        debug!("Starting search thread");

        trace!("Creating thread primitives");
        let (query_tx, query_rx) = mpsc::channel();
        let (matches_tx, matches_rx) = mpsc::channel();

        trace!("Starting thread");
        thread::spawn(move|| {
            search_thread(query_rx, matches_tx);
        });

        debug!("Creating UI instance");
        let instance = UI {
            track: track,
            size: size,
            query: query_tx,
            matches: matches_rx,
            save_cursor: save_cursor,
            restore_cursor: restore_cursor,
            clr_eos: clr_eos
        };

        trace!("Instance creation successful");
        Ok(instance)
    }

    pub fn start(&mut self) -> Result<(), StringError> {
        // assume start on a new line
        // get handles for io
        let stdout = io::stdout();
        let stdin = io::stdin();
        let mut output = stdout.lock();
        let input = stdin.lock();

        let mut query = String::new();

        // draw our prompt, move ten lines down and then back up, and save the cursor
        debug!("Drawing prompt");
        match write!(output, "Match: {}", self.save_cursor) {
            Err(e) => return Err(StringError::new("Failed to draw prompt", Some(Box::new(e)))),
            Ok(_) => {
                trace!("Drew prompt successfully");
            }
        }

        // flush the output
        debug!("Flushing output");
        match output.flush() {
            Ok(_) => {
                trace!("Successfully flushed output");
            },
            Err(e) => {
                return Err(StringError::new("Failed to flush output", Some(Box::new(e))));
            }
        }

        // wait for input
        for maybe_chr in input.chars() {
            let chr = match maybe_chr {
                Err(e) => return Err(StringError::new("Failed to read character", Some(Box::new(e)))),
                Ok(c) => c
            };
            trace!("Got character: {:?}", chr);

            // push the character onto the query string
            query.push(chr);

            // draw the character, save the cursor position, clear the screen after us
            match write!(output, "{}{}{}", chr, self.save_cursor, self.clr_eos) {
                Err(e) => return Err(StringError::new("Failed to output character", Some(Box::new(e)))),
                Ok(_) => {
                    trace!("Outputted character successfully");
                }
            }

            // send the search thread our query
            debug!("Sending {} to search thread", &query);
            match self.query.send(query.clone()) {
                Ok(_) => {
                    trace!("Send successful");
                },
                Err(e) => {
                    return Err(StringError::new("Failed to send to search thread", Some(Box::new(e))));
                }
            }

            // wait for matches
            let matches = match self.matches.recv() {
                Ok(m) => m,
                Err(e) => {
                    return Err(StringError::new("Failed to read matches", Some(Box::new(e))));
                }
            };

            debug!("Got matches: {:?}", &matches);

            // draw the matches
            for item in matches.into_iter() {
                if UnicodeWidthStr::width(item.as_ref()) > self.size.cols {
                    let mut owned = item.into_owned();
                    while UnicodeWidthStr::width((&owned as &AsRef<str>).as_ref()) > self.size.cols {
                        // truncate long lines
                        owned.pop();
                    }
                    // draw the truncated item
                    match write!(output, "\n{}", owned) {
                        Err(e) => return Err(StringError::new("Failed to draw match", Some(Box::new(e)))),
                        Ok(_) => {
                            trace!("Drew match successfully");
                        }
                    }
                } else {
                    // draw the match after a newline
                    match write!(output, "\n{}", item) {
                        Err(e) => return Err(StringError::new("Failed to draw match", Some(Box::new(e)))),
                        Ok(_) => {
                            trace!("Drew match successfully");
                        }
                    }
                }
            }

            // restore the cursor
            match write!(output, "{}", self.restore_cursor) {
                Err(e) => return Err(StringError::new("Failed to restore cursor", Some(Box::new(e)))),
                Ok(_) => {
                    trace!("Restored cursor successfully");
                }
            }

            // flush the output
            match output.flush() {
                Ok(_) => {
                    trace!("Successfully flushed output");
                },
                Err(e) => {
                    return Err(StringError::new("Failed to flush output", Some(Box::new(e))));
                }
            }
        }

        // Return success
        Ok(())
    }
}

pub fn search_thread(query: Receiver<String>,
                     matches: Sender<Vec<Cow<'static, str>>>) {
    debug!("Starting query thread");

    debug!("Getting history path");
    let history_path = match env::var("HISTFILE") {
        Ok(p) => {
            trace!("Got history path: {:?}", p);
            p
        },
        Err(e) => panic!("Failed to get bash history file: {}", e)
    };

    let mut base = SearchBase::default();

    // read the history
    info!("Reading history");
    match base.read_history(history_path) {
        Ok(_) => {
            // success
        },
        Err(e) => {
            panic!("Failed to read history: {}", e)
        }
    }

    debug!("Starting query loop");

    loop {
        trace!("Waiting for a query");
        match query.recv() {
            Err(e) => {
                debug!("Search thread exiting: {}", e);
                break;
            },
            Ok(q) => {
                debug!("Got query: {:?}", q);
                let result = base.query(q);
                debug!("Got result: {:?}", result);
                match matches.send(result) {
                    Err(e) => {
                        debug!("Search thread exiting: {}", e);
                        break;
                    },
                    Ok(_) => {
                        trace!("Matches sent successfully");
                    }
                }
            }
        }
    }
}
<|endoftext|>


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

//! Volume Groups

use std::io::Result;
use std::io::Error;
use std::io::ErrorKind::Other;
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::str::FromStr;
use std::borrow::Cow;

use uuid::Uuid;
use time::now;
use nix;

use lv::{LV, Segment};
use pv::{PV, Device};
use pvlabel::PvHeader;
use parser::{LvmTextMap, Entry};
use lvmetad::vg_update_lvmetad;
use dm::DM;

/// A Volume Group.
#[derive(Debug, PartialEq, Clone)]
pub struct VG {
    /// Name.
    pub name: String,
    /// Uuid.
    pub id: String,
    /// The generation of metadata this VG represents.
    pub seqno: u64,
    /// Always "LVM2".
    pub format: String,
    /// Status.
    pub status: Vec<String>,
    /// Flags.
    pub flags: Vec<String>,
    /// Size of each extent, in 512-byte sectors.
    pub extent_size: u64,
    /// Maximum number of LVs, 0 means no limit.
    pub max_lv: u64,
    /// Maximum number of PVs, 0 means no limit.
    pub max_pv: u64,
    /// How many metadata copies (?)
    pub metadata_copies: u64,
    /// Physical Volumes within this volume group.
    pub pvs: BTreeMap<String, PV>,
    /// Logical Volumes within this volume group.
    pub lvs: BTreeMap<String, LV>,
}

impl VG {
    /// The total number of extents in use in the volume group.
    pub fn extents_in_use(&self) -> u64 {
        self.lvs
            .values()
            .map(|x| x.used_extents())
            .sum()
    }

    /// The total number of free extents in the volume group.
    pub fn extents_free(&self) -> u64 {
        self.extents() - self.extents_in_use()
    }

    /// The total number of extents in the volume group.
    pub fn extents(&self) -> u64 {
        self.pvs
            .values()
            .map(|x| x.pe_count)
            .sum()
    }

    // Recursively walk DM deps to see if device is present
    fn depends_on(dev: Device, dm_majors: &BTreeSet<u32>, dm: &DM) -> bool {
        if !dm_majors.contains(&dev.major) {
            return false;
        }

        match dm.list_deps(dev) {
            Err(_) => return false,
            Ok(dep_list) => {
                for d in dep_list {
                    if d == dev {
                        return true;
                    } else if Self::depends_on(d, dm_majors, dm) {
                        return true;
                    }
                }
            }
        }

        false
    }

    /// Add a non-affiliated PV to this VG.
    pub fn add_pv(&mut self, pvh: &PvHeader) -> Result<()> {
        // add_pv_to_vg
        // check pv is not on an LV from the vg:
        // 1) is pv's major a devicemapper major?
        // 2) equiv. of dev_manager_device_uses_vg()

        let dm_majors = DM::dm_majors();
        let dev = try!(Device::from_str(&pvh.dev_path.to_string_lossy()));
        let dm = try!(DM::new(&self));
        if Self::depends_on(dev, &dm_majors, &dm) {
            return Err(Error::new(Other, "Dependency loops prohibited"));
        }

        // check pv is not already in the VG or another VG
        // Does it have text metadata??
        if let Ok(metadata) = pvh.read_metadata() {

            // Find the textmap for the vg, among all the other stuff.
            // (It's the only textmap.)
            let mut vg_name = Cow::Borrowed("<unknown>");
            for (key, value) in metadata {
                match value {
                    Entry::TextMap(_) => {
                        vg_name = Cow::Owned(key);
                        break
                    },
                    _ => {}
                }
            }

            return Err(Error::new(Other, format!("PV already in VG {}", vg_name)));
        }

        // figure out how many extents fit in the PV's data area
        // pe_start = da.offset
        // area_size = dev_size - da.offset - maybe(mda1.size)
        // pe_count = area_size / vg.extent_size

        // make a PV and add it to self

        Ok(())
    }

    /// Create a new linear logical volume in the volume group.
    pub fn new_linear_lv(&mut self, name: &str, extent_size: u64) -> Result<()> {
        if self.lvs.contains_key(name) {
            return Err(Error::new(Other, "LV already exists"));
        }

        let mut contig_area = None;
        for (pvname, areas) in self.free_areas() {
            for (start, len) in areas {
                if len >= extent_size {
                    contig_area = Some((pvname, start));
                    break;
                }
            }
        }

        // we don't support multiple segments yet
        let (pv_with_area, area_start) = match contig_area {
            None => return Err(Error::new(Other, "no contiguous area for new LV")),
            Some(x) => x,
        };

        let segment = Segment {
            name: "segment1".to_string(),
            start_extent: 0,
            extent_count: extent_size,
            ty: "striped".to_string(),
            stripes: vec![(pv_with_area, area_start)],
        };

        let mut lv = LV {
            name: name.to_string(),
            id: Uuid::new_v4().to_hyphenated_string(),
            status: vec!["READ".to_string(),
                         "WRITE".to_string(),
                         "VISIBLE".to_string()],
            flags: Vec::new(),
            creation_host: nix::sys::utsname::uname().nodename().to_string(),
            creation_time: now().to_timespec().sec,
            segments: vec![segment],
            device: None,
        };

        // poke dm and tell it about a new device
        {
            let dm = try!(DM::new(self));
            try!(dm.activate_device(&mut lv));
        }

        self.lvs.insert(name.to_string(), lv);

        self.commit()
    }

    /// Destroy a logical volume.
    pub fn lv_remove(&mut self, name: &str) -> Result<()> {
        match self.lvs.remove(name) {
            Some(mut lv) => {
                {
                    let dm = try!(DM::new(self));
                    try!(dm.deactivate_device(&mut lv));
                }

                self.commit()
            },
            None => Err(Error::new(Other, "LV not found in VG")),
        }
    }

    fn commit(&mut self) -> Result<()> {
        let map = self.clone().into();

        // TODO: atomicity of updating pvs, metad, dm
        for pv in self.pvs.values() {
            if let Some(path) = pv.device.path() {
                let mut pvheader = PvHeader::find_in_dev(&path)
                    .expect("could not find pvheader");

                try!(pvheader.write_metadata(&map));
            }
        }

        // tell lvmetad
        vg_update_lvmetad(&map)
    }

    // Returns e.g. {"pv0": {0: 45, 47: 100, 100: 200} }
    // This means extents 0-44 are used, 45 and 46 are not,
    // 47-99 are used, then 100-199 are used.
    //
    // Adjacent used areas are not merged.
    //
    // PVs with no used areas are not in the outer map at all.
    //
    fn used_areas(&self) -> BTreeMap<String, BTreeMap<u64, u64>> {
        let mut used_map = BTreeMap::new();

        for lv in self.lvs.values() {
            for seg in &lv.segments {
                for &(ref pvname, start) in &seg.stripes {
                    used_map.entry(pvname.to_string())
                        .or_insert(BTreeMap::new())
                        .insert(start as u64, seg.extent_count);
                }
            }
        }

        used_map
    }

    // Returns e.g. {"pv0": {45: 47, 200: 1000} }
    // (assuming pv0 has 1000 extents)
    //
    fn free_areas(&self) -> BTreeMap<String, BTreeMap<u64, u64>> {
        let mut free_map = BTreeMap::new();

        for (pvname, mut area_map) in self.used_areas() {

            // Insert an entry to mark the end of the PV so the fold works
            // correctly
            let pv = self.pvs.get(&pvname)
                .expect("area map name refers to nonexistent PV");
            area_map.insert(pv.pe_count, 0);

            area_map.iter()
                .fold(0, |prev_end, (start, len)| {
                    if prev_end < *start {
                        free_map.entry(pvname.clone())
                            .or_insert(BTreeMap::new())
                            .insert(prev_end, start-prev_end);
                    }
                    start + len
                });
        }

        // Also return completely-unused PVs
        for (pvname, pv) in &self.pvs {
            if !free_map.contains_key(pvname) {
                let mut map = BTreeMap::new();
                map.insert(0, pv.pe_count);
                free_map.insert(pvname.clone(), map);
            }
        }

        free_map
    }
}

impl From<VG> for LvmTextMap {
    fn from(vg: VG) -> Self {
        let mut map = LvmTextMap::new();

        map.insert("id".to_string(), Entry::String(vg.id));
        map.insert("seqno".to_string(),
                   Entry::Number(vg.seqno as i64 + 1));
        map.insert("format".to_string(), Entry::String(vg.format));

        map.insert("max_pv".to_string(), Entry::Number(0));
        map.insert("max_lv".to_string(), Entry::Number(0));

        map.insert("status".to_string(),
                   Entry::List(
                       Box::new(
                           vg.status
                               .into_iter()
                               .map(|x| Entry::String(x))
                               .collect())));

        map.insert("flags".to_string(),
                   Entry::List(
                       Box::new(
                           vg.flags
                               .into_iter()
                               .map(|x| Entry::String(x))
                               .collect())));

        map.insert("extent_size".to_string(),
                   Entry::Number(vg.extent_size as i64));
        map.insert("metadata_copies".to_string(),
                   Entry::Number(vg.metadata_copies as i64));
        map.insert("physical_volumes".to_string(),
                   Entry::TextMap(
                       Box::new(
                           vg.pvs
                               .into_iter()
                               .map(|(k, v)|
                                    (k, Entry::TextMap(Box::new(v.into()))))
                               .collect())));

        map.insert("logical_volumes".to_string(),
                   Entry::TextMap(
                       Box::new(
                           vg.lvs
                               .into_iter()
                               .map(|(k, v)|
                                    (k, Entry::TextMap(Box::new(v.into()))))
                               .collect())));

        let mut outer_map = LvmTextMap::new();

        outer_map.insert(vg.name, Entry::TextMap(Box::new(map)));

        outer_map
    }
}
<commit_msg>Limit lifetime of dm in VG::add_pv<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//! Volume Groups

use std::io::Result;
use std::io::Error;
use std::io::ErrorKind::Other;
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::str::FromStr;
use std::borrow::Cow;

use uuid::Uuid;
use time::now;
use nix;

use lv::{LV, Segment};
use pv::{PV, Device};
use pvlabel::PvHeader;
use parser::{LvmTextMap, Entry};
use lvmetad::vg_update_lvmetad;
use dm::DM;

/// A Volume Group.
#[derive(Debug, PartialEq, Clone)]
pub struct VG {
    /// Name.
    pub name: String,
    /// Uuid.
    pub id: String,
    /// The generation of metadata this VG represents.
    pub seqno: u64,
    /// Always "LVM2".
    pub format: String,
    /// Status.
    pub status: Vec<String>,
    /// Flags.
    pub flags: Vec<String>,
    /// Size of each extent, in 512-byte sectors.
    pub extent_size: u64,
    /// Maximum number of LVs, 0 means no limit.
    pub max_lv: u64,
    /// Maximum number of PVs, 0 means no limit.
    pub max_pv: u64,
    /// How many metadata copies (?)
    pub metadata_copies: u64,
    /// Physical Volumes within this volume group.
    pub pvs: BTreeMap<String, PV>,
    /// Logical Volumes within this volume group.
    pub lvs: BTreeMap<String, LV>,
}

impl VG {
    /// The total number of extents in use in the volume group.
    pub fn extents_in_use(&self) -> u64 {
        self.lvs
            .values()
            .map(|x| x.used_extents())
            .sum()
    }

    /// The total number of free extents in the volume group.
    pub fn extents_free(&self) -> u64 {
        self.extents() - self.extents_in_use()
    }

    /// The total number of extents in the volume group.
    pub fn extents(&self) -> u64 {
        self.pvs
            .values()
            .map(|x| x.pe_count)
            .sum()
    }

    // Recursively walk DM deps to see if device is present
    fn depends_on(dev: Device, dm_majors: &BTreeSet<u32>, dm: &DM) -> bool {
        if !dm_majors.contains(&dev.major) {
            return false;
        }

        match dm.list_deps(dev) {
            Err(_) => return false,
            Ok(dep_list) => {
                for d in dep_list {
                    if d == dev {
                        return true;
                    } else if Self::depends_on(d, dm_majors, dm) {
                        return true;
                    }
                }
            }
        }

        false
    }

    /// Add a non-affiliated PV to this VG.
    pub fn add_pv(&mut self, pvh: &PvHeader) -> Result<()> {
        // add_pv_to_vg
        // check pv is not on an LV from the vg:
        // 1) is pv's major a devicemapper major?
        // 2) equiv. of dev_manager_device_uses_vg()

        let dm_majors = DM::dm_majors();
        let dev = try!(Device::from_str(&pvh.dev_path.to_string_lossy()));
        {
            let dm = try!(DM::new(&self));
            if Self::depends_on(dev, &dm_majors, &dm) {
                return Err(Error::new(Other, "Dependency loops prohibited"));
            }
        }

        // check pv is not already in the VG or another VG
        // Does it have text metadata??
        if let Ok(metadata) = pvh.read_metadata() {

            // Find the textmap for the vg, among all the other stuff.
            // (It's the only textmap.)
            let mut vg_name = Cow::Borrowed("<unknown>");
            for (key, value) in metadata {
                match value {
                    Entry::TextMap(_) => {
                        vg_name = Cow::Owned(key);
                        break
                    },
                    _ => {}
                }
            }

            return Err(Error::new(Other, format!("PV already in VG {}", vg_name)));
        }

        // figure out how many extents fit in the PV's data area
        // pe_start = da.offset
        // area_size = dev_size - da.offset - maybe(mda1.size)
        // pe_count = area_size / vg.extent_size

        // make a PV and add it to self

        Ok(())
    }

    /// Create a new linear logical volume in the volume group.
    pub fn new_linear_lv(&mut self, name: &str, extent_size: u64) -> Result<()> {
        if self.lvs.contains_key(name) {
            return Err(Error::new(Other, "LV already exists"));
        }

        let mut contig_area = None;
        for (pvname, areas) in self.free_areas() {
            for (start, len) in areas {
                if len >= extent_size {
                    contig_area = Some((pvname, start));
                    break;
                }
            }
        }

        // we don't support multiple segments yet
        let (pv_with_area, area_start) = match contig_area {
            None => return Err(Error::new(Other, "no contiguous area for new LV")),
            Some(x) => x,
        };

        let segment = Segment {
            name: "segment1".to_string(),
            start_extent: 0,
            extent_count: extent_size,
            ty: "striped".to_string(),
            stripes: vec![(pv_with_area, area_start)],
        };

        let mut lv = LV {
            name: name.to_string(),
            id: Uuid::new_v4().to_hyphenated_string(),
            status: vec!["READ".to_string(),
                         "WRITE".to_string(),
                         "VISIBLE".to_string()],
            flags: Vec::new(),
            creation_host: nix::sys::utsname::uname().nodename().to_string(),
            creation_time: now().to_timespec().sec,
            segments: vec![segment],
            device: None,
        };

        // poke dm and tell it about a new device
        {
            let dm = try!(DM::new(self));
            try!(dm.activate_device(&mut lv));
        }

        self.lvs.insert(name.to_string(), lv);

        self.commit()
    }

    /// Destroy a logical volume.
    pub fn lv_remove(&mut self, name: &str) -> Result<()> {
        match self.lvs.remove(name) {
            Some(mut lv) => {
                {
                    let dm = try!(DM::new(self));
                    try!(dm.deactivate_device(&mut lv));
                }

                self.commit()
            },
            None => Err(Error::new(Other, "LV not found in VG")),
        }
    }

    fn commit(&mut self) -> Result<()> {
        let map = self.clone().into();

        // TODO: atomicity of updating pvs, metad, dm
        for pv in self.pvs.values() {
            if let Some(path) = pv.device.path() {
                let mut pvheader = PvHeader::find_in_dev(&path)
                    .expect("could not find pvheader");

                try!(pvheader.write_metadata(&map));
            }
        }

        // tell lvmetad
        vg_update_lvmetad(&map)
    }

    // Returns e.g. {"pv0": {0: 45, 47: 100, 100: 200} }
    // This means extents 0-44 are used, 45 and 46 are not,
    // 47-99 are used, then 100-199 are used.
    //
    // Adjacent used areas are not merged.
    //
    // PVs with no used areas are not in the outer map at all.
    //
    fn used_areas(&self) -> BTreeMap<String, BTreeMap<u64, u64>> {
        let mut used_map = BTreeMap::new();

        for lv in self.lvs.values() {
            for seg in &lv.segments {
                for &(ref pvname, start) in &seg.stripes {
                    used_map.entry(pvname.to_string())
                        .or_insert(BTreeMap::new())
                        .insert(start as u64, seg.extent_count);
                }
            }
        }

        used_map
    }

    // Returns e.g. {"pv0": {45: 47, 200: 1000} }
    // (assuming pv0 has 1000 extents)
    //
    fn free_areas(&self) -> BTreeMap<String, BTreeMap<u64, u64>> {
        let mut free_map = BTreeMap::new();

        for (pvname, mut area_map) in self.used_areas() {

            // Insert an entry to mark the end of the PV so the fold works
            // correctly
            let pv = self.pvs.get(&pvname)
                .expect("area map name refers to nonexistent PV");
            area_map.insert(pv.pe_count, 0);

            area_map.iter()
                .fold(0, |prev_end, (start, len)| {
                    if prev_end < *start {
                        free_map.entry(pvname.clone())
                            .or_insert(BTreeMap::new())
                            .insert(prev_end, start-prev_end);
                    }
                    start + len
                });
        }

        // Also return completely-unused PVs
        for (pvname, pv) in &self.pvs {
            if !free_map.contains_key(pvname) {
                let mut map = BTreeMap::new();
                map.insert(0, pv.pe_count);
                free_map.insert(pvname.clone(), map);
            }
        }

        free_map
    }
}

impl From<VG> for LvmTextMap {
    fn from(vg: VG) -> Self {
        let mut map = LvmTextMap::new();

        map.insert("id".to_string(), Entry::String(vg.id));
        map.insert("seqno".to_string(),
                   Entry::Number(vg.seqno as i64 + 1));
        map.insert("format".to_string(), Entry::String(vg.format));

        map.insert("max_pv".to_string(), Entry::Number(0));
        map.insert("max_lv".to_string(), Entry::Number(0));

        map.insert("status".to_string(),
                   Entry::List(
                       Box::new(
                           vg.status
                               .into_iter()
                               .map(|x| Entry::String(x))
                               .collect())));

        map.insert("flags".to_string(),
                   Entry::List(
                       Box::new(
                           vg.flags
                               .into_iter()
                               .map(|x| Entry::String(x))
                               .collect())));

        map.insert("extent_size".to_string(),
                   Entry::Number(vg.extent_size as i64));
        map.insert("metadata_copies".to_string(),
                   Entry::Number(vg.metadata_copies as i64));
        map.insert("physical_volumes".to_string(),
                   Entry::TextMap(
                       Box::new(
                           vg.pvs
                               .into_iter()
                               .map(|(k, v)|
                                    (k, Entry::TextMap(Box::new(v.into()))))
                               .collect())));

        map.insert("logical_volumes".to_string(),
                   Entry::TextMap(
                       Box::new(
                           vg.lvs
                               .into_iter()
                               .map(|(k, v)|
                                    (k, Entry::TextMap(Box::new(v.into()))))
                               .collect())));

        let mut outer_map = LvmTextMap::new();

        outer_map.insert(vg.name, Entry::TextMap(Box::new(map)));

        outer_map
    }
}
<|endoftext|>


<commit_before>
fn main() {
    println!("hello");
}
<commit_msg>Add Emulator to vm.<commit_after>
const REGISTERS_COUNT: usize = 256;

struct Emulator {
    registers: [u32; REGISTERS_COUNT],
    eflags: u32,
    eip: u32,
}

impl Emulator {
}

fn main() {
    println!("hello");
}
<|endoftext|>