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

use dynimage::DynamicImage;
use image::ImageFormat;
use {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.
///
/// ```
/// # 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>Run doctest only when pnm is enabled<commit_after>use std::fs::File;
use std::io::{self, BufRead, BufReader, Cursor, Read, Seek, SeekFrom};
use std::path::Path;

use dynimage::DynamicImage;
use image::ImageFormat;
use {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()))
    }
}
<|endoftext|>


<commit_before>use std::cmp;
use std::borrow::Cow;
use std::old_io::{fs, File, FileMode, FileAccess, TempDir};

use buffer::{Buffer, Direction, Mark};
use input::Input;
use uibuf::{UIBuffer, CharColor};
use frontends::Frontend;
use overlay::{Overlay, OverlayType};
use utils;

/// A View is an abstract Window (into a Buffer).
///
/// It draws a portion of a Buffer to a UIBuffer which in turn is drawn to the
/// screen. It maintains the status bar for the current view, the "dirty status"
/// which is whether the buffer has been modified or not and a number of other
/// pieces of information.
pub struct View<'v> {
    pub buffer: Buffer,
    pub overlay: Overlay,

    /// First character of the top line to be displayed
    top_line: Mark,

    /// Index into the top_line - used for horizontal scrolling
    left_col: usize,

    /// The current View's cursor - a reference into the Buffer
    cursor: Mark,

    /// The UIBuffer to which the View is drawn
    uibuf: UIBuffer,

    /// Number of lines from the top/bottom of the View after which vertical
    /// scrolling begins.
    threshold: usize,
}

impl<'v> View<'v> {

    pub fn new(source: Input, width: usize, height: usize) -> View<'v> {
        let mut buffer = match source {
            Input::Filename(path) => {
                match path {
                    Some(s) => Buffer::new_from_file(Path::new(s)),
                    None    => Buffer::new(),
                }
            },
            Input::Stdin(reader) => {
                Buffer::new_from_reader(reader)
            },
        };

        let cursor = Mark::Cursor(0);
        let top_line = Mark::DisplayMark(0);

        buffer.set_mark(cursor, 0);
        buffer.set_mark(top_line, 0);

        View {
            buffer: buffer,
            top_line: top_line,
            left_col: 0,
            cursor: cursor,
            uibuf: UIBuffer::new(width, height),
            overlay: Overlay::None,
            threshold: 5,
        }
    }

    /// Get the height of the View.
    ///
    /// This is the height of the UIBuffer minus the status bar height.
    pub fn get_height(&self) -> usize {
        let status_bar_height = 1;
        let uibuf_height = self.uibuf.get_height();

        uibuf_height - status_bar_height
    }

    /// Get the width of the View.
    pub fn get_width(&self) -> usize {
        self.uibuf.get_width()
    }

    /// Resize the view
    ///
    /// This involves simply changing the size of the associated UIBuffer
    pub fn resize(&mut self, width: usize, height: usize) {
        let uibuf = UIBuffer::new(width, height);
        self.uibuf = uibuf;
    }

    /// Clear the buffer
    ///
    /// Fills every cell in the UIBuffer with the space (' ') char.
    pub fn clear<T: Frontend>(&mut self, frontend: &mut T) {
        self.uibuf.fill(' ');
        self.uibuf.draw_everything(frontend);
    }

    pub fn draw<T: Frontend>(&mut self, frontend: &mut T) {
        for (index,line) in self.buffer
                                .lines_from(self.top_line)
                                .unwrap()
                                .take(self.get_height())
                                .enumerate() {
            draw_line(&mut self.uibuf, &*line, index, self.left_col);
            if index == self.get_height() { break; }
        }

        match self.overlay {
            Overlay::None => self.draw_cursor(frontend),
            _ => {
                self.overlay.draw(frontend, &mut self.uibuf);
                self.overlay.draw_cursor(frontend);
            }
        }
        self.draw_status(frontend);
        self.uibuf.draw_everything(frontend);
    }

    fn draw_status<T: Frontend>(&mut self, frontend: &mut T) {
        let buffer_status = self.buffer.status_text();
        let mut cursor_status = self.buffer.get_mark_coords(self.cursor).unwrap_or((0,0));
        cursor_status = (cursor_status.0 + 1, cursor_status.1 + 1);
        let status_text = format!("{} ({}, {})", buffer_status, cursor_status.0 + 1, cursor_status.1 + 1).into_bytes();
        let status_text_len = status_text.len();
        let width = self.get_width();
        let height = self.get_height() - 1;

        for index in range(0, width) {
            let mut ch: char = ' ';
            if index < status_text_len {
                ch = status_text[index] as char;
            }
            self.uibuf.update_cell(index, height, ch, CharColor::Black, CharColor::Blue);
        }

        self.uibuf.draw_range(frontend, height, height+1);
    }

    fn draw_cursor<T: Frontend>(&mut self, frontend: &mut T) {
        if let Some(top_line) = self.buffer.get_mark_coords(self.top_line) {
            if let Some((x, y)) = self.buffer.get_mark_coords(self.cursor) {
                frontend.draw_cursor((x - self.left_col) as isize, y as isize - top_line.1 as isize);
            }
        }
    }

    pub fn set_overlay(&mut self, overlay_type: OverlayType) {
        match overlay_type {
            OverlayType::Prompt => {
                self.overlay = Overlay::Prompt {
                    cursor_x: 1,
                    prefix: ":",
                    data: String::new(),
                };
            }
            _ => {}
        }
    }

    pub fn move_cursor(&mut self, direction: Direction, amount: usize) {
        self.buffer.shift_mark(self.cursor, direction, amount);
        self.maybe_move_screen();
    }

    pub fn move_cursor_to_line_end(&mut self) {
        self.buffer.shift_mark(self.cursor, Direction::LineEnd, 0);
        self.maybe_move_screen();
    }

    pub fn move_cursor_to_line_start(&mut self) {
        self.buffer.shift_mark(self.cursor, Direction::LineStart, 0);
        self.maybe_move_screen();
    }

    /// Update the top_line mark if necessary to keep the cursor on the screen.
    fn maybe_move_screen(&mut self) {
        if let (Some(cursor), Some((_, top_line))) = (self.buffer.get_mark_coords(self.cursor),
                                                      self.buffer.get_mark_coords(self.top_line)) {

            let width  = (self.get_width()  - self.threshold) as isize;
            let height = (self.get_height() - self.threshold) as isize;

            //left-right shifting
            self.left_col = match cursor.0 as isize - self.left_col as isize {
                x_offset if x_offset < self.threshold as isize => {
                    cmp::max(0, self.left_col as isize - (self.threshold as isize - x_offset)) as usize
                }
                x_offset if x_offset >= width => {
                    self.left_col + (x_offset - width + 1) as usize
                }
                _ => { self.left_col }
            };

            //up-down shifting
            match cursor.1 as isize - top_line as isize {
                y_offset if y_offset < self.threshold as isize && top_line > 0 => {
                    self.buffer.shift_mark(self.top_line,
                                           Direction::Up,
                                           (self.threshold as isize - y_offset) as usize);
                }
                y_offset if y_offset >= height => {
                    self.buffer.shift_mark(self.top_line,
                                           Direction::Down,
                                           (y_offset - height + 1) as usize);
                }
                _ => { }
            }
        }
    }

    pub fn delete_chars(&mut self, direction: Direction, num_chars: usize) {
        let chars = self.buffer.remove_chars(self.cursor, direction, num_chars);
        match (chars, direction) {
            (Some(chars), Direction::Left) => {
                self.move_cursor(Direction::Left, chars.len());
            }
            (Some(chars), Direction::LeftWord(..)) => {
                self.move_cursor(Direction::Left, chars.len());
            }
            _ => {}
        }
    }

    pub fn insert_tab(&mut self) {
        // A tab is just 4 spaces
        for _ in range(0, 4) {
            self.insert_char(' ');
        }
    }

    /// Insert a chacter into the buffer & update cursor position accordingly.
    pub fn insert_char(&mut self, ch: char) {
        self.buffer.insert_char(self.cursor, ch as u8);
        // NOTE: the last param to char_width here may not be correct
        if let Some(ch_width) = utils::char_width(ch, false, 4, 1) {
            self.move_cursor(Direction::Right, ch_width)
        }
    }

    pub fn undo(&mut self) {
        let point = if let Some(transaction) = self.buffer.undo() { transaction.end_point }
                    else { return; };
        self.buffer.set_mark(self.cursor, point);
        self.maybe_move_screen();
    }

    pub fn redo(&mut self) {
        let point = if let Some(transaction) = self.buffer.redo() { transaction.end_point }
                    else { return; };
        self.buffer.set_mark(self.cursor, point);
        self.maybe_move_screen();
    }

    fn save_buffer(&mut self) {
        let path = match self.buffer.file_path {
            Some(ref p) => Cow::Borrowed(p),
            None => {
                // NOTE: this should never happen, as the file path
                // should have been set inside the try_save_buffer method.
                //
                // If this runs, it probably means save_buffer has been called
                // directly, rather than try_save_buffer.
                Cow::Owned(Path::new("untitled"))
            },
        };
        let tmpdir = match TempDir::new_in(&Path::new("."), "iota") {
            Ok(d) => d,
            Err(e) => panic!("file error: {}", e)
        };

        let tmppath = tmpdir.path().join(Path::new("tmpfile"));
        let mut file = match File::open_mode(&tmppath, FileMode::Open, FileAccess::Write) {
            Ok(f) => f,
            Err(e) => panic!("file error: {}", e)
        };

        //TODO (lee): Is iteration still necessary in this format?
        for line in self.buffer.lines() {
            let result = file.write_all(&*line);

            if result.is_err() {
                // TODO(greg): figure out what to do here.
                panic!("Something went wrong while writing the file");
            }
        }

        if let Err(e) = fs::rename(&tmppath, &*path) {
            panic!("file error: {}", e);
        }
    }

    pub fn try_save_buffer(&mut self) {
        match self.buffer.file_path {
            Some(_) => self.save_buffer(),
            None => {
                let prefix = "Enter file name: ";
                self.overlay = Overlay::SavePrompt {
                    cursor_x: prefix.len(),
                    prefix: prefix,
                    data: String::new(),
                };
            },
        };
    }

}

pub fn draw_line(buf: &mut UIBuffer, line: &[u8], idx: usize, left: usize) {
    let width = buf.get_width() - 1;
    let mut wide_chars = 0;
    for line_idx in range(left, left + width) {
        if line_idx < line.len() {
            let special_char = line[line_idx] as char;
            match special_char {
                '\t'   => {
                    let w = 4 - line_idx % 4;
                    for _ in range(0, w) {
                        buf.update_cell_content(line_idx + wide_chars - left, idx, ' ');
                    }
                }
                '\n'   => buf.update_cell_content(line_idx + wide_chars - left, idx, ' '),
                _       => buf.update_cell_content(line_idx + wide_chars - left, idx,
                                                   line[line_idx] as char),
            }
            wide_chars += (line[line_idx] as char).width(false).unwrap_or(1) - 1;
        } else { buf.update_cell_content(line_idx + wide_chars - left, idx, ' '); }
    }
    if line.len() >= width {
        buf.update_cell_content(width + wide_chars, idx, '→');
    }

}

#[cfg(test)]
mod tests {

    use buffer::Direction;
    use view::View;
    use input::Input;

    fn setup_view<'v>(testcase: &'static str) -> View<'v> {
        let mut view = View::new(Input::Filename(None), 50, 50);
        for ch in testcase.chars() {
            view.insert_char(ch);
        }
        view.buffer.set_mark(view.cursor, 0);
        view
    }

    #[test]
    fn test_move_cursor_down() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Down, 1);
        assert_eq!(view.buffer.get_mark_coords(view.cursor).unwrap().1, 1);
        assert_eq!(view.buffer.lines_from(view.cursor).unwrap().next().unwrap(), b"second");
    }

    #[test]
    fn test_move_cursor_up() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Down, 1);
        view.move_cursor(Direction::Up, 1);
        assert_eq!(view.buffer.get_mark_coords(view.cursor).unwrap().1, 0);
        assert_eq!(view.buffer.lines_from(view.cursor).unwrap().next().unwrap(), b"test\n");
    }

    #[test]
    fn test_insert_line() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Right, 1);
        view.insert_char('\n');

        assert_eq!(view.buffer.get_mark_coords(view.cursor).unwrap(), (0, 1))
    }

    #[test]
    fn test_insert_char() {
        let mut view = setup_view("test\nsecond");
        view.insert_char('t');

        assert_eq!(view.buffer.lines().next().unwrap(), b"ttest\n");
    }

    #[test]
    fn test_delete_char_to_right() {
        let mut view = setup_view("test\nsecond");
        view.delete_chars(Direction::Right, 1);

        assert_eq!(view.buffer.lines().next().unwrap(), b"est\n");
    }

    #[test]
    fn test_delete_char_to_left() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Right, 1);
        view.delete_chars(Direction::Left, 1);

        assert_eq!(view.buffer.lines().next().unwrap(), b"est\n");
    }

    #[test]
    fn test_delete_char_at_start_of_line() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Down, 1);
        view.delete_chars(Direction::Left, 1);

        assert_eq!(view.buffer.lines().next().unwrap(), b"testsecond");
    }

    #[test]
    fn test_delete_char_at_end_of_line() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Right, 4);
        view.delete_chars(Direction::Right, 1);

        assert_eq!(view.buffer.lines().next().unwrap(), b"testsecond");
    }

    #[test]
    fn deleting_backward_at_start_of_first_line_does_nothing() {
        let mut view = setup_view("test\nsecond");
        view.delete_chars(Direction::Left, 1);

        let lines: Vec<_> = view.buffer.lines().collect();

        assert_eq!(lines.len(), 2);
        assert_eq!(view.buffer.lines().next().unwrap(), b"test\n");
    }
}
<commit_msg>Remove View::insert_tab<commit_after>use std::cmp;
use std::borrow::Cow;
use std::old_io::{fs, File, FileMode, FileAccess, TempDir};

use buffer::{Buffer, Direction, Mark};
use input::Input;
use uibuf::{UIBuffer, CharColor};
use frontends::Frontend;
use overlay::{Overlay, OverlayType};
use utils;

/// A View is an abstract Window (into a Buffer).
///
/// It draws a portion of a Buffer to a UIBuffer which in turn is drawn to the
/// screen. It maintains the status bar for the current view, the "dirty status"
/// which is whether the buffer has been modified or not and a number of other
/// pieces of information.
pub struct View<'v> {
    pub buffer: Buffer,
    pub overlay: Overlay,

    /// First character of the top line to be displayed
    top_line: Mark,

    /// Index into the top_line - used for horizontal scrolling
    left_col: usize,

    /// The current View's cursor - a reference into the Buffer
    cursor: Mark,

    /// The UIBuffer to which the View is drawn
    uibuf: UIBuffer,

    /// Number of lines from the top/bottom of the View after which vertical
    /// scrolling begins.
    threshold: usize,
}

impl<'v> View<'v> {

    pub fn new(source: Input, width: usize, height: usize) -> View<'v> {
        let mut buffer = match source {
            Input::Filename(path) => {
                match path {
                    Some(s) => Buffer::new_from_file(Path::new(s)),
                    None    => Buffer::new(),
                }
            },
            Input::Stdin(reader) => {
                Buffer::new_from_reader(reader)
            },
        };

        let cursor = Mark::Cursor(0);
        let top_line = Mark::DisplayMark(0);

        buffer.set_mark(cursor, 0);
        buffer.set_mark(top_line, 0);

        View {
            buffer: buffer,
            top_line: top_line,
            left_col: 0,
            cursor: cursor,
            uibuf: UIBuffer::new(width, height),
            overlay: Overlay::None,
            threshold: 5,
        }
    }

    /// Get the height of the View.
    ///
    /// This is the height of the UIBuffer minus the status bar height.
    pub fn get_height(&self) -> usize {
        let status_bar_height = 1;
        let uibuf_height = self.uibuf.get_height();

        uibuf_height - status_bar_height
    }

    /// Get the width of the View.
    pub fn get_width(&self) -> usize {
        self.uibuf.get_width()
    }

    /// Resize the view
    ///
    /// This involves simply changing the size of the associated UIBuffer
    pub fn resize(&mut self, width: usize, height: usize) {
        let uibuf = UIBuffer::new(width, height);
        self.uibuf = uibuf;
    }

    /// Clear the buffer
    ///
    /// Fills every cell in the UIBuffer with the space (' ') char.
    pub fn clear<T: Frontend>(&mut self, frontend: &mut T) {
        self.uibuf.fill(' ');
        self.uibuf.draw_everything(frontend);
    }

    pub fn draw<T: Frontend>(&mut self, frontend: &mut T) {
        for (index,line) in self.buffer
                                .lines_from(self.top_line)
                                .unwrap()
                                .take(self.get_height())
                                .enumerate() {
            draw_line(&mut self.uibuf, &*line, index, self.left_col);
            if index == self.get_height() { break; }
        }

        match self.overlay {
            Overlay::None => self.draw_cursor(frontend),
            _ => {
                self.overlay.draw(frontend, &mut self.uibuf);
                self.overlay.draw_cursor(frontend);
            }
        }
        self.draw_status(frontend);
        self.uibuf.draw_everything(frontend);
    }

    fn draw_status<T: Frontend>(&mut self, frontend: &mut T) {
        let buffer_status = self.buffer.status_text();
        let mut cursor_status = self.buffer.get_mark_coords(self.cursor).unwrap_or((0,0));
        cursor_status = (cursor_status.0 + 1, cursor_status.1 + 1);
        let status_text = format!("{} ({}, {})", buffer_status, cursor_status.0 + 1, cursor_status.1 + 1).into_bytes();
        let status_text_len = status_text.len();
        let width = self.get_width();
        let height = self.get_height() - 1;

        for index in range(0, width) {
            let mut ch: char = ' ';
            if index < status_text_len {
                ch = status_text[index] as char;
            }
            self.uibuf.update_cell(index, height, ch, CharColor::Black, CharColor::Blue);
        }

        self.uibuf.draw_range(frontend, height, height+1);
    }

    fn draw_cursor<T: Frontend>(&mut self, frontend: &mut T) {
        if let Some(top_line) = self.buffer.get_mark_coords(self.top_line) {
            if let Some((x, y)) = self.buffer.get_mark_coords(self.cursor) {
                frontend.draw_cursor((x - self.left_col) as isize, y as isize - top_line.1 as isize);
            }
        }
    }

    pub fn set_overlay(&mut self, overlay_type: OverlayType) {
        match overlay_type {
            OverlayType::Prompt => {
                self.overlay = Overlay::Prompt {
                    cursor_x: 1,
                    prefix: ":",
                    data: String::new(),
                };
            }
            _ => {}
        }
    }

    pub fn move_cursor(&mut self, direction: Direction, amount: usize) {
        self.buffer.shift_mark(self.cursor, direction, amount);
        self.maybe_move_screen();
    }

    pub fn move_cursor_to_line_end(&mut self) {
        self.buffer.shift_mark(self.cursor, Direction::LineEnd, 0);
        self.maybe_move_screen();
    }

    pub fn move_cursor_to_line_start(&mut self) {
        self.buffer.shift_mark(self.cursor, Direction::LineStart, 0);
        self.maybe_move_screen();
    }

    /// Update the top_line mark if necessary to keep the cursor on the screen.
    fn maybe_move_screen(&mut self) {
        if let (Some(cursor), Some((_, top_line))) = (self.buffer.get_mark_coords(self.cursor),
                                                      self.buffer.get_mark_coords(self.top_line)) {

            let width  = (self.get_width()  - self.threshold) as isize;
            let height = (self.get_height() - self.threshold) as isize;

            //left-right shifting
            self.left_col = match cursor.0 as isize - self.left_col as isize {
                x_offset if x_offset < self.threshold as isize => {
                    cmp::max(0, self.left_col as isize - (self.threshold as isize - x_offset)) as usize
                }
                x_offset if x_offset >= width => {
                    self.left_col + (x_offset - width + 1) as usize
                }
                _ => { self.left_col }
            };

            //up-down shifting
            match cursor.1 as isize - top_line as isize {
                y_offset if y_offset < self.threshold as isize && top_line > 0 => {
                    self.buffer.shift_mark(self.top_line,
                                           Direction::Up,
                                           (self.threshold as isize - y_offset) as usize);
                }
                y_offset if y_offset >= height => {
                    self.buffer.shift_mark(self.top_line,
                                           Direction::Down,
                                           (y_offset - height + 1) as usize);
                }
                _ => { }
            }
        }
    }

    pub fn delete_chars(&mut self, direction: Direction, num_chars: usize) {
        let chars = self.buffer.remove_chars(self.cursor, direction, num_chars);
        match (chars, direction) {
            (Some(chars), Direction::Left) => {
                self.move_cursor(Direction::Left, chars.len());
            }
            (Some(chars), Direction::LeftWord(..)) => {
                self.move_cursor(Direction::Left, chars.len());
            }
            _ => {}
        }
    }

    /// Insert a chacter into the buffer & update cursor position accordingly.
    pub fn insert_char(&mut self, ch: char) {
        self.buffer.insert_char(self.cursor, ch as u8);
        // NOTE: the last param to char_width here may not be correct
        if let Some(ch_width) = utils::char_width(ch, false, 4, 1) {
            self.move_cursor(Direction::Right, ch_width)
        }
    }

    pub fn undo(&mut self) {
        let point = if let Some(transaction) = self.buffer.undo() { transaction.end_point }
                    else { return; };
        self.buffer.set_mark(self.cursor, point);
        self.maybe_move_screen();
    }

    pub fn redo(&mut self) {
        let point = if let Some(transaction) = self.buffer.redo() { transaction.end_point }
                    else { return; };
        self.buffer.set_mark(self.cursor, point);
        self.maybe_move_screen();
    }

    fn save_buffer(&mut self) {
        let path = match self.buffer.file_path {
            Some(ref p) => Cow::Borrowed(p),
            None => {
                // NOTE: this should never happen, as the file path
                // should have been set inside the try_save_buffer method.
                //
                // If this runs, it probably means save_buffer has been called
                // directly, rather than try_save_buffer.
                Cow::Owned(Path::new("untitled"))
            },
        };
        let tmpdir = match TempDir::new_in(&Path::new("."), "iota") {
            Ok(d) => d,
            Err(e) => panic!("file error: {}", e)
        };

        let tmppath = tmpdir.path().join(Path::new("tmpfile"));
        let mut file = match File::open_mode(&tmppath, FileMode::Open, FileAccess::Write) {
            Ok(f) => f,
            Err(e) => panic!("file error: {}", e)
        };

        //TODO (lee): Is iteration still necessary in this format?
        for line in self.buffer.lines() {
            let result = file.write_all(&*line);

            if result.is_err() {
                // TODO(greg): figure out what to do here.
                panic!("Something went wrong while writing the file");
            }
        }

        if let Err(e) = fs::rename(&tmppath, &*path) {
            panic!("file error: {}", e);
        }
    }

    pub fn try_save_buffer(&mut self) {
        match self.buffer.file_path {
            Some(_) => self.save_buffer(),
            None => {
                let prefix = "Enter file name: ";
                self.overlay = Overlay::SavePrompt {
                    cursor_x: prefix.len(),
                    prefix: prefix,
                    data: String::new(),
                };
            },
        };
    }

}

pub fn draw_line(buf: &mut UIBuffer, line: &[u8], idx: usize, left: usize) {
    let width = buf.get_width() - 1;
    let mut wide_chars = 0;
    for line_idx in range(left, left + width) {
        if line_idx < line.len() {
            let special_char = line[line_idx] as char;
            match special_char {
                '\t'   => {
                    let w = 4 - line_idx % 4;
                    for _ in range(0, w) {
                        buf.update_cell_content(line_idx + wide_chars - left, idx, ' ');
                    }
                }
                '\n'   => buf.update_cell_content(line_idx + wide_chars - left, idx, ' '),
                _       => buf.update_cell_content(line_idx + wide_chars - left, idx,
                                                   line[line_idx] as char),
            }
            wide_chars += (line[line_idx] as char).width(false).unwrap_or(1) - 1;
        } else { buf.update_cell_content(line_idx + wide_chars - left, idx, ' '); }
    }
    if line.len() >= width {
        buf.update_cell_content(width + wide_chars, idx, '→');
    }

}

#[cfg(test)]
mod tests {

    use buffer::Direction;
    use view::View;
    use input::Input;

    fn setup_view<'v>(testcase: &'static str) -> View<'v> {
        let mut view = View::new(Input::Filename(None), 50, 50);
        for ch in testcase.chars() {
            view.insert_char(ch);
        }
        view.buffer.set_mark(view.cursor, 0);
        view
    }

    #[test]
    fn test_move_cursor_down() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Down, 1);
        assert_eq!(view.buffer.get_mark_coords(view.cursor).unwrap().1, 1);
        assert_eq!(view.buffer.lines_from(view.cursor).unwrap().next().unwrap(), b"second");
    }

    #[test]
    fn test_move_cursor_up() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Down, 1);
        view.move_cursor(Direction::Up, 1);
        assert_eq!(view.buffer.get_mark_coords(view.cursor).unwrap().1, 0);
        assert_eq!(view.buffer.lines_from(view.cursor).unwrap().next().unwrap(), b"test\n");
    }

    #[test]
    fn test_insert_line() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Right, 1);
        view.insert_char('\n');

        assert_eq!(view.buffer.get_mark_coords(view.cursor).unwrap(), (0, 1))
    }

    #[test]
    fn test_insert_char() {
        let mut view = setup_view("test\nsecond");
        view.insert_char('t');

        assert_eq!(view.buffer.lines().next().unwrap(), b"ttest\n");
    }

    #[test]
    fn test_delete_char_to_right() {
        let mut view = setup_view("test\nsecond");
        view.delete_chars(Direction::Right, 1);

        assert_eq!(view.buffer.lines().next().unwrap(), b"est\n");
    }

    #[test]
    fn test_delete_char_to_left() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Right, 1);
        view.delete_chars(Direction::Left, 1);

        assert_eq!(view.buffer.lines().next().unwrap(), b"est\n");
    }

    #[test]
    fn test_delete_char_at_start_of_line() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Down, 1);
        view.delete_chars(Direction::Left, 1);

        assert_eq!(view.buffer.lines().next().unwrap(), b"testsecond");
    }

    #[test]
    fn test_delete_char_at_end_of_line() {
        let mut view = setup_view("test\nsecond");
        view.move_cursor(Direction::Right, 4);
        view.delete_chars(Direction::Right, 1);

        assert_eq!(view.buffer.lines().next().unwrap(), b"testsecond");
    }

    #[test]
    fn deleting_backward_at_start_of_first_line_does_nothing() {
        let mut view = setup_view("test\nsecond");
        view.delete_chars(Direction::Left, 1);

        let lines: Vec<_> = view.buffer.lines().collect();

        assert_eq!(lines.len(), 2);
        assert_eq!(view.buffer.lines().next().unwrap(), b"test\n");
    }
}
<|endoftext|>


<commit_before>use opencl::hl::{Device, Context, CommandQueue};
use opencl::util::create_compute_context;

pub struct CL {
  pub device: Device,
  pub context: Context,
  pub queue: CommandQueue,
}

impl CL {
  pub unsafe fn new() -> CL {
    let (device, context, queue) = create_compute_context().unwrap();
    CL {
      device: device,
      context: context,
      queue: queue,
    }
  }
}
<commit_msg>Smarter and more transparent OpenCL device selection.<commit_after>use opencl::hl;
use opencl::hl::{Device, Context, CommandQueue};

pub struct CL {
  pub device: Device,
  pub context: Context,
  pub queue: CommandQueue,
}

impl CL {
  pub unsafe fn new() -> CL {
    for platform in hl::get_platforms().iter() {
      debug!("Found OpenCL platform: {}", platform.name());
      debug!("Available devices:");
      let devices = platform.get_devices();
      for device in devices.into_iter() {
        debug!("  {}", device.name());
        let context = device.create_context();
        let queue = context.create_command_queue(&device);

        return CL {
          device: device,
          context: context,
          queue: queue,
        };
      }
    }

    panic!("Couldn't find an OpenCL device.");
  }
}
<|endoftext|>


<commit_before>#![crate_name = "foo"]

// ignore-tidy-linelength

// @has foo/fn.bar.html '//*[@class="tooltip compile_fail"]/span' "This example deliberately fails to compile"
// @has foo/fn.bar.html '//*[@class="tooltip ignore"]/span' "This example is not tested"
// @has foo/fn.bar.html '//*[@class="tooltip should_panic"]/span' "This example panics"

/// foo
///
/// ```compile_fail
/// foo();
/// ```
///
/// ```ignore (tidy)
/// goo();
/// ```
///
/// ```should_panic
/// hoo();
/// ```
///
/// ```
/// let x = 0;
/// ```
pub fn bar() -> usize { 2 }
<commit_msg>Removed trailing whitespace<commit_after>#![crate_name = "foo"]

// ignore-tidy-linelength

// @has foo/fn.bar.html '//*[@class="tooltip compile_fail"]/span' "This example deliberately fails to compile"
// @has foo/fn.bar.html '//*[@class="tooltip ignore"]/span' "This example is not tested"
// @has foo/fn.bar.html '//*[@class="tooltip should_panic"]/span' "This example panics"

/// foo
///
/// ```compile_fail
/// foo();
/// ```
///
/// ```ignore (tidy)
/// goo();
/// ```
///
/// ```should_panic
/// hoo();
/// ```
///
/// ```
/// let x = 0;
/// ```
pub fn bar() -> usize { 2 }
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A group of side offsets, which correspond to top/left/bottom/right for borders, padding,
//! and margins in CSS.

use std::num::Zero;

/// A group of side offsets, which correspond to top/left/bottom/right for borders, padding,
/// and margins in CSS.
#[deriving(Eq)]
pub struct SideOffsets2D<T> {
    top: T,
    right: T,
    bottom: T,
    left: T,
}

impl<T> SideOffsets2D<T> {
    pub fn new(top: T, right: T, bottom: T, left: T) -> SideOffsets2D<T> {
        SideOffsets2D {
            top: top,
            right: right,
            bottom: bottom,
            left: left,
        }
    }
}

impl<T:Clone> SideOffsets2D<T> {
    pub fn new_all_same(all: T) -> SideOffsets2D<T> {
        SideOffsets2D::new(all.clone(), all.clone(), all.clone(), all.clone())
    }
}

impl<T:Num> SideOffsets2D<T> {
    pub fn horizontal(&self) -> T {
        self.left + self.right
    }

    pub fn vertical(&self) -> T {
        self.top + self.bottom
    }
}

impl<T:Num> Zero for SideOffsets2D<T> {
    fn zero() -> SideOffsets2D<T> {
        SideOffsets2D {
            top: Zero::zero(),
            right: Zero::zero(),
            bottom: Zero::zero(),
            left: Zero::zero(),
        }
    }

    fn is_zero(&self) -> bool {
        self.top.is_zero() && self.right.is_zero() && self.bottom.is_zero() && self.left.is_zero()
    }
}

<commit_msg>Make SideOffsets2D derive Clone<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A group of side offsets, which correspond to top/left/bottom/right for borders, padding,
//! and margins in CSS.

use std::num::Zero;

/// A group of side offsets, which correspond to top/left/bottom/right for borders, padding,
/// and margins in CSS.
#[deriving(Clone, Eq)]
pub struct SideOffsets2D<T> {
    top: T,
    right: T,
    bottom: T,
    left: T,
}

impl<T> SideOffsets2D<T> {
    pub fn new(top: T, right: T, bottom: T, left: T) -> SideOffsets2D<T> {
        SideOffsets2D {
            top: top,
            right: right,
            bottom: bottom,
            left: left,
        }
    }
}

impl<T:Clone> SideOffsets2D<T> {
    pub fn new_all_same(all: T) -> SideOffsets2D<T> {
        SideOffsets2D::new(all.clone(), all.clone(), all.clone(), all.clone())
    }
}

impl<T:Num> SideOffsets2D<T> {
    pub fn horizontal(&self) -> T {
        self.left + self.right
    }

    pub fn vertical(&self) -> T {
        self.top + self.bottom
    }
}

impl<T:Num> Zero for SideOffsets2D<T> {
    fn zero() -> SideOffsets2D<T> {
        SideOffsets2D {
            top: Zero::zero(),
            right: Zero::zero(),
            bottom: Zero::zero(),
            left: Zero::zero(),
        }
    }

    fn is_zero(&self) -> bool {
        self.top.is_zero() && self.right.is_zero() && self.bottom.is_zero() && self.left.is_zero()
    }
}

<|endoftext|>


<commit_before>use super::definitions::{
    RededicateVector,
    DataVectorDomain};
use vector_types::{
    GenericDataVector,
    RealTimeVector,
    ComplexTimeVector,
    RealFreqVector,
    ComplexFreqVector};
use RealNumber;

macro_rules! add_rededicate_impl {
    ($(struct $name:ident, $is_complex:ident, $domain:expr);*) => {
    $(
        impl<T> RededicateVector<ComplexTimeVector<T>> for $name<T>
            where T: RealNumber {
            fn rededicate(self) -> ComplexTimeVector<T> {
                ComplexTimeVector {
                    delta: self.delta,
                    is_complex: true,
                    valid_len: 0,
                    domain: DataVectorDomain::Time,
                    data: self.data,
                    temp: self.temp,
                    multicore_settings: self.multicore_settings
                }
            }

            fn rededicate_from(other: ComplexTimeVector<T>) -> Self {
                $name {
                    delta: other.delta,
                    is_complex: $is_complex,
                    valid_len: 0,
                    domain: $domain,
                    data: other.data,
                    temp: other.temp,
                    multicore_settings: other.multicore_settings
                }
            }
        }

        impl<T> RededicateVector<ComplexFreqVector<T>> for $name<T>
            where T: RealNumber {
            fn rededicate(self) -> ComplexFreqVector<T> {
                ComplexFreqVector {
                    delta: self.delta,
                    is_complex: true,
                    valid_len: 0,
                    domain: DataVectorDomain::Frequency,
                    data: self.data,
                    temp: self.temp,
                    multicore_settings: self.multicore_settings
                }
            }

            fn rededicate_from(other: ComplexFreqVector<T>) -> Self {
                $name {
                    delta: other.delta,
                    is_complex: $is_complex,
                    valid_len: 0,
                    domain: $domain,
                    data: other.data,
                    temp: other.temp,
                    multicore_settings: other.multicore_settings
                }
            }
        }

        impl<T> RededicateVector<RealTimeVector<T>> for $name<T>
            where T: RealNumber {
            fn rededicate(self) -> RealTimeVector<T> {
                RealTimeVector {
                    delta: self.delta,
                    is_complex: false,
                    valid_len: 0,
                    domain: DataVectorDomain::Time,
                    data: self.data,
                    temp: self.temp,
                    multicore_settings: self.multicore_settings
                }
            }

            fn rededicate_from(other: RealTimeVector<T>) -> Self {
                $name {
                    delta: other.delta,
                    is_complex: $is_complex,
                    valid_len: 0,
                    domain: $domain,
                    data: other.data,
                    temp: other.temp,
                    multicore_settings: other.multicore_settings
                }
            }
        }

        impl<T> RededicateVector<RealFreqVector<T>> for $name<T>
            where T: RealNumber {
            fn rededicate(self) -> RealFreqVector<T> {
                RealFreqVector {
                    delta: self.delta,
                    is_complex: false,
                    valid_len: 0,
                    domain: DataVectorDomain::Frequency,
                    data: self.data,
                    temp: self.temp,
                    multicore_settings: self.multicore_settings
                }
            }

            fn rededicate_from(other: RealFreqVector<T>) -> Self {
                $name {
                    delta: other.delta,
                    is_complex: $is_complex,
                    valid_len: 0,
                    domain: $domain,
                    data: other.data,
                    temp: other.temp,
                    multicore_settings: other.multicore_settings
                }
            }
        }

        impl<T> RededicateVector<GenericDataVector<T>> for $name<T>
            where T: RealNumber {
            fn rededicate(self) -> GenericDataVector<T> {
                GenericDataVector {
                    delta: self.delta,
                    is_complex: self.is_complex,
                    valid_len: self.valid_len,
                    domain: self.domain,
                    data: self.data,
                    temp: self.temp,
                    multicore_settings: self.multicore_settings
                }
            }

            fn rededicate_from(other: GenericDataVector<T>) -> Self {
                let valid_len =
                    if other.is_complex == $is_complex
                        && other.domain == $domain {
                        other.valid_len
                    } else {
                        0
                    };

                $name {
                    delta: other.delta,
                    is_complex: $is_complex,
                    valid_len: valid_len,
                    domain: $domain,
                    data: other.data,
                    temp: other.temp,
                    multicore_settings: other.multicore_settings
                }
            }
        }
      )*
    }
}

add_rededicate_impl!(struct RealTimeVector, false, DataVectorDomain::Time);
add_rededicate_impl!(struct ComplexTimeVector, true, DataVectorDomain::Time);
add_rededicate_impl!(struct RealFreqVector, false, DataVectorDomain::Frequency);
add_rededicate_impl!(struct ComplexFreqVector, true, DataVectorDomain::Frequency);

// Conversions to `GenericDataVector` are always valid therefore `GenericDataVector`
// needs to have a specific `RededicateVector` implementation

impl<T> RededicateVector<ComplexTimeVector<T>> for GenericDataVector<T>
        where T: RealNumber {
    fn rededicate(self) -> ComplexTimeVector<T> {
        let valid_len =
            if self.is_complex == true
                && self.domain == DataVectorDomain::Time {
                self.valid_len
            } else {
                0
            };

        ComplexTimeVector {
            delta: self.delta,
            is_complex: true,
            valid_len: valid_len,
            domain: DataVectorDomain::Time,
            data: self.data,
            temp: self.temp,
            multicore_settings: self.multicore_settings
        }
    }

    fn rededicate_from(other: ComplexTimeVector<T>) -> Self {
        GenericDataVector {
            delta: other.delta,
            is_complex: other.is_complex,
            valid_len: other.valid_len,
            domain: other.domain,
            data: other.data,
            temp: other.temp,
            multicore_settings: other.multicore_settings
        }
    }
}

impl<T> RededicateVector<ComplexFreqVector<T>> for GenericDataVector<T>
    where T: RealNumber {
    fn rededicate(self) -> ComplexFreqVector<T> {
        let valid_len =
            if self.is_complex == true
                && self.domain == DataVectorDomain::Frequency {
                self.valid_len
            } else {
                0
            };

        ComplexFreqVector {
            delta: self.delta,
            is_complex: true,
            valid_len: valid_len,
            domain: DataVectorDomain::Frequency,
            data: self.data,
            temp: self.temp,
            multicore_settings: self.multicore_settings
        }
    }

    fn rededicate_from(other: ComplexFreqVector<T>) -> Self {
        GenericDataVector {
            delta: other.delta,
            is_complex: other.is_complex,
            valid_len: other.valid_len,
            domain: other.domain,
            data: other.data,
            temp: other.temp,
            multicore_settings: other.multicore_settings
        }
    }
}

impl<T> RededicateVector<RealTimeVector<T>> for GenericDataVector<T>
    where T: RealNumber {
    fn rededicate(self) -> RealTimeVector<T> {
        let valid_len =
            if self.is_complex == false
                && self.domain == DataVectorDomain::Time {
                self.valid_len
            } else {
                0
            };

        RealTimeVector {
            delta: self.delta,
            is_complex: false,
            valid_len: valid_len,
            domain: DataVectorDomain::Time,
            data: self.data,
            temp: self.temp,
            multicore_settings: self.multicore_settings
        }
    }

    fn rededicate_from(other: RealTimeVector<T>) -> Self {
        GenericDataVector {
            delta: other.delta,
            is_complex: other.is_complex,
            valid_len: other.valid_len,
            domain: other.domain,
            data: other.data,
            temp: other.temp,
            multicore_settings: other.multicore_settings
        }
    }
}

impl<T> RededicateVector<RealFreqVector<T>> for GenericDataVector<T>
    where T: RealNumber {
    fn rededicate(self) -> RealFreqVector<T> {
        let valid_len =
            if self.is_complex == false
                && self.domain == DataVectorDomain::Frequency {
                self.valid_len
            } else {
                0
            };

        RealFreqVector {
            delta: self.delta,
            is_complex: false,
            valid_len: valid_len,
            domain: DataVectorDomain::Frequency,
            data: self.data,
            temp: self.temp,
            multicore_settings: self.multicore_settings
        }
    }

    fn rededicate_from(other: RealFreqVector<T>) -> Self {
        GenericDataVector {
            delta: other.delta,
            is_complex: other.is_complex,
            valid_len: other.valid_len,
            domain: other.domain,
            data: other.data,
            temp: other.temp,
            multicore_settings: other.multicore_settings
        }
    }
}

impl<T> RededicateVector<GenericDataVector<T>> for GenericDataVector<T>
    where T: RealNumber {
    fn rededicate(self) -> GenericDataVector<T> {
        self
    }

    fn rededicate_from(other: GenericDataVector<T>) -> Self {
        other
    }
}<commit_msg>Removed code duplication in RededicateVector trait<commit_after>use super::definitions::{
    RededicateVector,
    DataVectorDomain};
use vector_types::{
    GenericDataVector,
    RealTimeVector,
    ComplexTimeVector,
    RealFreqVector,
    ComplexFreqVector};
use RealNumber;

macro_rules! add_rededicate_impl {
    ($(struct $name:ident, $is_complex:ident, $domain:expr);*) => {
    $(
        impl<T> RededicateVector<ComplexTimeVector<T>> for $name<T>
            where T: RealNumber {
            fn rededicate(self) -> ComplexTimeVector<T> {
                ComplexTimeVector {
                    delta: self.delta,
                    is_complex: true,
                    valid_len: 0,
                    domain: DataVectorDomain::Time,
                    data: self.data,
                    temp: self.temp,
                    multicore_settings: self.multicore_settings
                }
            }

            fn rededicate_from(other: ComplexTimeVector<T>) -> Self {
                other.rededicate()
            }
        }

        impl<T> RededicateVector<ComplexFreqVector<T>> for $name<T>
            where T: RealNumber {
            fn rededicate(self) -> ComplexFreqVector<T> {
                ComplexFreqVector {
                    delta: self.delta,
                    is_complex: true,
                    valid_len: 0,
                    domain: DataVectorDomain::Frequency,
                    data: self.data,
                    temp: self.temp,
                    multicore_settings: self.multicore_settings
                }
            }

            fn rededicate_from(other: ComplexFreqVector<T>) -> Self {
                other.rededicate()
            }
        }

        impl<T> RededicateVector<RealTimeVector<T>> for $name<T>
            where T: RealNumber {
            fn rededicate(self) -> RealTimeVector<T> {
                RealTimeVector {
                    delta: self.delta,
                    is_complex: false,
                    valid_len: 0,
                    domain: DataVectorDomain::Time,
                    data: self.data,
                    temp: self.temp,
                    multicore_settings: self.multicore_settings
                }
            }

            fn rededicate_from(other: RealTimeVector<T>) -> Self {
                other.rededicate()
            }
        }

        impl<T> RededicateVector<RealFreqVector<T>> for $name<T>
            where T: RealNumber {
            fn rededicate(self) -> RealFreqVector<T> {
                RealFreqVector {
                    delta: self.delta,
                    is_complex: false,
                    valid_len: 0,
                    domain: DataVectorDomain::Frequency,
                    data: self.data,
                    temp: self.temp,
                    multicore_settings: self.multicore_settings
                }
            }

            fn rededicate_from(other: RealFreqVector<T>) -> Self {
                other.rededicate()
            }
        }

        impl<T> RededicateVector<GenericDataVector<T>> for $name<T>
            where T: RealNumber {
            fn rededicate(self) -> GenericDataVector<T> {
                GenericDataVector {
                    delta: self.delta,
                    is_complex: self.is_complex,
                    valid_len: self.valid_len,
                    domain: self.domain,
                    data: self.data,
                    temp: self.temp,
                    multicore_settings: self.multicore_settings
                }
            }

            fn rededicate_from(other: GenericDataVector<T>) -> Self {
                other.rededicate()
            }
        }
      )*
    }
}

add_rededicate_impl!(struct RealTimeVector, false, DataVectorDomain::Time);
add_rededicate_impl!(struct ComplexTimeVector, true, DataVectorDomain::Time);
add_rededicate_impl!(struct RealFreqVector, false, DataVectorDomain::Frequency);
add_rededicate_impl!(struct ComplexFreqVector, true, DataVectorDomain::Frequency);

// Conversions to `GenericDataVector` are always valid therefore `GenericDataVector`
// needs to have a specific `RededicateVector` implementation

impl<T> RededicateVector<ComplexTimeVector<T>> for GenericDataVector<T>
        where T: RealNumber {
    fn rededicate(self) -> ComplexTimeVector<T> {
        let valid_len =
            if self.is_complex == true
                && self.domain == DataVectorDomain::Time {
                self.valid_len
            } else {
                0
            };

        ComplexTimeVector {
            delta: self.delta,
            is_complex: true,
            valid_len: valid_len,
            domain: DataVectorDomain::Time,
            data: self.data,
            temp: self.temp,
            multicore_settings: self.multicore_settings
        }
    }

    fn rededicate_from(other: ComplexTimeVector<T>) -> Self {
        GenericDataVector {
            delta: other.delta,
            is_complex: other.is_complex,
            valid_len: other.valid_len,
            domain: other.domain,
            data: other.data,
            temp: other.temp,
            multicore_settings: other.multicore_settings
        }
    }
}

impl<T> RededicateVector<ComplexFreqVector<T>> for GenericDataVector<T>
    where T: RealNumber {
    fn rededicate(self) -> ComplexFreqVector<T> {
        let valid_len =
            if self.is_complex == true
                && self.domain == DataVectorDomain::Frequency {
                self.valid_len
            } else {
                0
            };

        ComplexFreqVector {
            delta: self.delta,
            is_complex: true,
            valid_len: valid_len,
            domain: DataVectorDomain::Frequency,
            data: self.data,
            temp: self.temp,
            multicore_settings: self.multicore_settings
        }
    }

    fn rededicate_from(other: ComplexFreqVector<T>) -> Self {
        GenericDataVector {
            delta: other.delta,
            is_complex: other.is_complex,
            valid_len: other.valid_len,
            domain: other.domain,
            data: other.data,
            temp: other.temp,
            multicore_settings: other.multicore_settings
        }
    }
}

impl<T> RededicateVector<RealTimeVector<T>> for GenericDataVector<T>
    where T: RealNumber {
    fn rededicate(self) -> RealTimeVector<T> {
        let valid_len =
            if self.is_complex == false
                && self.domain == DataVectorDomain::Time {
                self.valid_len
            } else {
                0
            };

        RealTimeVector {
            delta: self.delta,
            is_complex: false,
            valid_len: valid_len,
            domain: DataVectorDomain::Time,
            data: self.data,
            temp: self.temp,
            multicore_settings: self.multicore_settings
        }
    }

    fn rededicate_from(other: RealTimeVector<T>) -> Self {
        GenericDataVector {
            delta: other.delta,
            is_complex: other.is_complex,
            valid_len: other.valid_len,
            domain: other.domain,
            data: other.data,
            temp: other.temp,
            multicore_settings: other.multicore_settings
        }
    }
}

impl<T> RededicateVector<RealFreqVector<T>> for GenericDataVector<T>
    where T: RealNumber {
    fn rededicate(self) -> RealFreqVector<T> {
        let valid_len =
            if self.is_complex == false
                && self.domain == DataVectorDomain::Frequency {
                self.valid_len
            } else {
                0
            };

        RealFreqVector {
            delta: self.delta,
            is_complex: false,
            valid_len: valid_len,
            domain: DataVectorDomain::Frequency,
            data: self.data,
            temp: self.temp,
            multicore_settings: self.multicore_settings
        }
    }

    fn rededicate_from(other: RealFreqVector<T>) -> Self {
        GenericDataVector {
            delta: other.delta,
            is_complex: other.is_complex,
            valid_len: other.valid_len,
            domain: other.domain,
            data: other.data,
            temp: other.temp,
            multicore_settings: other.multicore_settings
        }
    }
}

impl<T> RededicateVector<GenericDataVector<T>> for GenericDataVector<T>
    where T: RealNumber {
    fn rededicate(self) -> GenericDataVector<T> {
        self
    }

    fn rededicate_from(other: GenericDataVector<T>) -> Self {
        other
    }
}<|endoftext|>


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

use std::str::FromStr;
use app_units::Au;
use euclid::TypedSize2D;

use yaml_rust::Yaml;

use webrender_traits::*;

pub trait YamlHelper {
    fn as_force_f32(&self) -> Option<f32>;
    fn as_vec_f32(&self) -> Option<Vec<f32>>;
    fn as_vec_u32(&self) -> Option<Vec<u32>>;
    fn as_rect(&self) -> Option<LayoutRect>;
    fn as_size(&self) -> Option<LayoutSize>;
    fn as_point(&self) -> Option<LayoutPoint>;
    fn as_matrix4d(&self) -> Option<LayoutTransform>;
    fn as_colorf(&self) -> Option<ColorF>;
    fn as_vec_colorf(&self) -> Option<Vec<ColorF>>;
    fn as_px_to_au(&self) -> Option<Au>;
    fn as_pt_to_au(&self) -> Option<Au>;
    fn as_vec_string(&self) -> Option<Vec<String>>;
    fn as_border_radius(&self) -> Option<BorderRadius>;
}

fn string_to_color(color: &str) -> Option<ColorF> {
    match color {
        "red" => Some(ColorF::new(1.0, 0.0, 0.0, 1.0)),
        "green" => Some(ColorF::new(0.0, 1.0, 0.0, 1.0)),
        "blue" => Some(ColorF::new(0.0, 0.0, 1.0, 1.0)),
        "white" => Some(ColorF::new(1.0, 1.0, 1.0, 1.0)),
        "black" => Some(ColorF::new(0.0, 0.0, 0.0, 1.0)),
        s => {
            let items: Vec<f32> = s.split_whitespace().map(|s| f32::from_str(s).unwrap()).collect();
            if items.len() == 3 {
                Some(ColorF::new(items[0] / 255.0, items[1] / 255.0, items[2] / 255.0, 1.0))
            } else if items.len() == 4 {
                Some(ColorF::new(items[0] / 255.0, items[1] / 255.0, items[2] / 255.0, items[3]))
            } else {
                None
            }
        }
    }
}

impl YamlHelper for Yaml {
    fn as_force_f32(&self) -> Option<f32> {
        match *self {
            Yaml::Integer(iv) => Some(iv as f32),
            Yaml::String(ref sv) | Yaml::Real(ref sv) => match f32::from_str(sv.as_str()) {
                Ok(v) => Some(v),
                Err(_) => None
            },
            _ => None
        }
    }

    fn as_vec_f32(&self) -> Option<Vec<f32>> {
        match *self {
            Yaml::String(ref s) | Yaml::Real(ref s) => {
                s.split_whitespace()
                 .map(|v| f32::from_str(v))
                 .collect::<Result<Vec<_>,_>>()
                 .ok()
            }
            Yaml::Array(ref v) => {
                v.iter().map(|v| {
                    match *v {
                        Yaml::Integer(k) => Ok(k as f32),
                        Yaml::String(ref k) | Yaml::Real(ref k) => {
                            f32::from_str(&k).map_err(|_| false)
                        },
                        _ => Err(false),
                    }
                }).collect::<Result<Vec<_>,_>>().ok()
            }
            Yaml::Integer(k) => {
                Some(vec![k as f32])
            }
            _ => None
        }
    }

    fn as_vec_u32(&self) -> Option<Vec<u32>> {
        if let Some(v) = self.as_vec() {
            Some(v.iter().map(|v| v.as_i64().unwrap() as u32).collect())
        } else {
            None
        }
    }

    fn as_px_to_au(&self) -> Option<Au> {
        match self.as_force_f32() {
            Some(fv) => Some(Au::from_f32_px(fv)),
            None => None
        }
    }

    fn as_pt_to_au(&self) -> Option<Au> {
        match self.as_force_f32() {
            Some(fv) => Some(Au::from_f32_px(fv * 16. / 12.)),
            None => None
        }
    }

    fn as_rect(&self) -> Option<LayoutRect> {
        if self.is_badvalue() {
            return None;
        }

        if let Some(nums) = self.as_vec_f32() {
            if nums.len() == 4 {
                return Some(LayoutRect::new(LayoutPoint::new(nums[0], nums[1]), LayoutSize::new(nums[2], nums[3])));
            }
        }

        None
    }

    fn as_size(&self) -> Option<LayoutSize> {
        if self.is_badvalue() {
            return None;
        }

        let nums = self.as_vec_f32().unwrap();
        if nums.len() != 2 {
            panic!("size expected 2 float values, got {} instead ('{:?}')", nums.len(), self);
        }
        Some(LayoutSize::new(nums[0], nums[1]))
    }

    fn as_point(&self) -> Option<LayoutPoint> {
        if self.is_badvalue() {
            return None;
        }

        let nums = self.as_vec_f32().unwrap();
        if nums.len() != 2 {
            panic!("point expected 2 float values, got {} instead ('{:?}')", nums.len(), self);
        }
        Some(LayoutPoint::new(nums[0], nums[1]))
    }

    fn as_matrix4d(&self) -> Option<LayoutTransform> {
        None
    }

    fn as_colorf(&self) -> Option<ColorF> {
        if let Some(mut nums) = self.as_vec_f32() {
            if nums.len() != 3 && nums.len() != 4 {
                panic!("color expected a color name, or 3-4 floats; got '{:?}'", self);
            }

            if nums.len() == 3 {
                nums.push(1.0);
            }
            return Some(ColorF::new(nums[0] / 255.0, nums[1] / 255.0, nums[2] / 255.0, nums[3]));
        }

        if let Some(s) = self.as_str() {
            string_to_color(s)
        } else {
            None
        }
    }

    fn as_vec_colorf(&self) -> Option<Vec<ColorF>> {
        if let Some(v) = self.as_vec() {
            Some(v.iter().map(|v| v.as_colorf().unwrap()).collect())
        } else {
            if let Some(color) = self.as_colorf() {
                Some(vec![color])
            } else {
                None
            }
        }
    }

    fn as_vec_string(&self) -> Option<Vec<String>> {
        if let Some(v) = self.as_vec() {
            Some(v.iter().map(|v| v.as_str().unwrap().to_owned()).collect())
        } else if let Some(s) = self.as_str() {
            Some(vec![s.to_owned()])
        } else {
            None
        }
    }

    fn as_border_radius(&self) -> Option<BorderRadius> {
        match *self {
            Yaml::BadValue => { None }
            Yaml::String(ref s) | Yaml::Real(ref s) => {
                let fv = f32::from_str(s).unwrap();
                Some(BorderRadius::uniform(fv))
            }
            Yaml::Integer(v) => {
                Some(BorderRadius::uniform(v as f32))
            }
            Yaml::Hash(_) => {
                let top_left = self["top_left"].as_size().unwrap_or(TypedSize2D::zero());
                let top_right = self["top_right"].as_size().unwrap_or(TypedSize2D::zero());
                let bottom_left = self["bottom_left"].as_size().unwrap_or(TypedSize2D::zero());
                let bottom_right = self["bottom_right"].as_size().unwrap_or(TypedSize2D::zero());
                Some(BorderRadius {
                    top_left: top_left,
                    top_right: top_right,
                    bottom_left: bottom_left,
                    bottom_right: bottom_right,
                })
            }
            _ => {
                panic!("Invalid border radius specified: {:?}", self);
            }
        }
    }
}
<commit_msg>Auto merge of #726 - jrmuizel:read-transform, r=glennw<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::str::FromStr;
use app_units::Au;
use euclid::TypedSize2D;

use yaml_rust::Yaml;

use webrender_traits::*;

pub trait YamlHelper {
    fn as_force_f32(&self) -> Option<f32>;
    fn as_vec_f32(&self) -> Option<Vec<f32>>;
    fn as_vec_u32(&self) -> Option<Vec<u32>>;
    fn as_rect(&self) -> Option<LayoutRect>;
    fn as_size(&self) -> Option<LayoutSize>;
    fn as_point(&self) -> Option<LayoutPoint>;
    fn as_matrix4d(&self) -> Option<LayoutTransform>;
    fn as_colorf(&self) -> Option<ColorF>;
    fn as_vec_colorf(&self) -> Option<Vec<ColorF>>;
    fn as_px_to_au(&self) -> Option<Au>;
    fn as_pt_to_au(&self) -> Option<Au>;
    fn as_vec_string(&self) -> Option<Vec<String>>;
    fn as_border_radius(&self) -> Option<BorderRadius>;
}

fn string_to_color(color: &str) -> Option<ColorF> {
    match color {
        "red" => Some(ColorF::new(1.0, 0.0, 0.0, 1.0)),
        "green" => Some(ColorF::new(0.0, 1.0, 0.0, 1.0)),
        "blue" => Some(ColorF::new(0.0, 0.0, 1.0, 1.0)),
        "white" => Some(ColorF::new(1.0, 1.0, 1.0, 1.0)),
        "black" => Some(ColorF::new(0.0, 0.0, 0.0, 1.0)),
        s => {
            let items: Vec<f32> = s.split_whitespace().map(|s| f32::from_str(s).unwrap()).collect();
            if items.len() == 3 {
                Some(ColorF::new(items[0] / 255.0, items[1] / 255.0, items[2] / 255.0, 1.0))
            } else if items.len() == 4 {
                Some(ColorF::new(items[0] / 255.0, items[1] / 255.0, items[2] / 255.0, items[3]))
            } else {
                None
            }
        }
    }
}

impl YamlHelper for Yaml {
    fn as_force_f32(&self) -> Option<f32> {
        match *self {
            Yaml::Integer(iv) => Some(iv as f32),
            Yaml::String(ref sv) | Yaml::Real(ref sv) => match f32::from_str(sv.as_str()) {
                Ok(v) => Some(v),
                Err(_) => None
            },
            _ => None
        }
    }

    fn as_vec_f32(&self) -> Option<Vec<f32>> {
        match *self {
            Yaml::String(ref s) | Yaml::Real(ref s) => {
                s.split_whitespace()
                 .map(|v| f32::from_str(v))
                 .collect::<Result<Vec<_>,_>>()
                 .ok()
            }
            Yaml::Array(ref v) => {
                v.iter().map(|v| {
                    match *v {
                        Yaml::Integer(k) => Ok(k as f32),
                        Yaml::String(ref k) | Yaml::Real(ref k) => {
                            f32::from_str(&k).map_err(|_| false)
                        },
                        _ => Err(false),
                    }
                }).collect::<Result<Vec<_>,_>>().ok()
            }
            Yaml::Integer(k) => {
                Some(vec![k as f32])
            }
            _ => None
        }
    }

    fn as_vec_u32(&self) -> Option<Vec<u32>> {
        if let Some(v) = self.as_vec() {
            Some(v.iter().map(|v| v.as_i64().unwrap() as u32).collect())
        } else {
            None
        }
    }

    fn as_px_to_au(&self) -> Option<Au> {
        match self.as_force_f32() {
            Some(fv) => Some(Au::from_f32_px(fv)),
            None => None
        }
    }

    fn as_pt_to_au(&self) -> Option<Au> {
        match self.as_force_f32() {
            Some(fv) => Some(Au::from_f32_px(fv * 16. / 12.)),
            None => None
        }
    }

    fn as_rect(&self) -> Option<LayoutRect> {
        if self.is_badvalue() {
            return None;
        }

        if let Some(nums) = self.as_vec_f32() {
            if nums.len() == 4 {
                return Some(LayoutRect::new(LayoutPoint::new(nums[0], nums[1]), LayoutSize::new(nums[2], nums[3])));
            }
        }

        None
    }

    fn as_size(&self) -> Option<LayoutSize> {
        if self.is_badvalue() {
            return None;
        }

        let nums = self.as_vec_f32().unwrap();
        if nums.len() != 2 {
            panic!("size expected 2 float values, got {} instead ('{:?}')", nums.len(), self);
        }
        Some(LayoutSize::new(nums[0], nums[1]))
    }

    fn as_point(&self) -> Option<LayoutPoint> {
        if self.is_badvalue() {
            return None;
        }

        let nums = self.as_vec_f32().unwrap();
        if nums.len() != 2 {
            panic!("point expected 2 float values, got {} instead ('{:?}')", nums.len(), self);
        }
        Some(LayoutPoint::new(nums[0], nums[1]))
    }

    fn as_matrix4d(&self) -> Option<LayoutTransform> {
        if let Some(mut nums) = self.as_vec_f32() {
            if nums.len() != 16 {
                panic!("expected 16 floats, got '{:?}'", self);
            }
            return Some(LayoutTransform::row_major(nums[0], nums[1], nums[2], nums[3],
                                                   nums[4], nums[5], nums[6], nums[7],
                                                   nums[8], nums[9], nums[10], nums[11],
                                                   nums[12], nums[13], nums[14], nums[15]))
        }
        None
    }

    fn as_colorf(&self) -> Option<ColorF> {
        if let Some(mut nums) = self.as_vec_f32() {
            if nums.len() != 3 && nums.len() != 4 {
                panic!("color expected a color name, or 3-4 floats; got '{:?}'", self);
            }

            if nums.len() == 3 {
                nums.push(1.0);
            }
            return Some(ColorF::new(nums[0] / 255.0, nums[1] / 255.0, nums[2] / 255.0, nums[3]));
        }

        if let Some(s) = self.as_str() {
            string_to_color(s)
        } else {
            None
        }
    }

    fn as_vec_colorf(&self) -> Option<Vec<ColorF>> {
        if let Some(v) = self.as_vec() {
            Some(v.iter().map(|v| v.as_colorf().unwrap()).collect())
        } else {
            if let Some(color) = self.as_colorf() {
                Some(vec![color])
            } else {
                None
            }
        }
    }

    fn as_vec_string(&self) -> Option<Vec<String>> {
        if let Some(v) = self.as_vec() {
            Some(v.iter().map(|v| v.as_str().unwrap().to_owned()).collect())
        } else if let Some(s) = self.as_str() {
            Some(vec![s.to_owned()])
        } else {
            None
        }
    }

    fn as_border_radius(&self) -> Option<BorderRadius> {
        match *self {
            Yaml::BadValue => { None }
            Yaml::String(ref s) | Yaml::Real(ref s) => {
                let fv = f32::from_str(s).unwrap();
                Some(BorderRadius::uniform(fv))
            }
            Yaml::Integer(v) => {
                Some(BorderRadius::uniform(v as f32))
            }
            Yaml::Hash(_) => {
                let top_left = self["top_left"].as_size().unwrap_or(TypedSize2D::zero());
                let top_right = self["top_right"].as_size().unwrap_or(TypedSize2D::zero());
                let bottom_left = self["bottom_left"].as_size().unwrap_or(TypedSize2D::zero());
                let bottom_right = self["bottom_right"].as_size().unwrap_or(TypedSize2D::zero());
                Some(BorderRadius {
                    top_left: top_left,
                    top_right: top_right,
                    bottom_left: bottom_left,
                    bottom_right: bottom_right,
                })
            }
            _ => {
                panic!("Invalid border radius specified: {:?}", self);
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    loop {
        println!("Please input your guess.");

        let mut guess = String::new();

        io::stdin().read_line(&mut guess)
            .expect("Failed to read line");

        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };

        println!("You guessed: {}", guess);

        match guess.cmp(&secret_number) {
            Ordering::Less    => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal   => {
                println!("You win!");
                break;
            }
        }
    }
}
<commit_msg>adjust format<commit_after>// 用于声明依赖外部库 rand
extern crate rand;

// use 主要适用于命名空间的缩写，类似于c++的using关键字
use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("Guess the number!");

	// let 为 rust 变量赋值的关键字， 默认情况为赋值的变量是 immutable，不能够被修改
    let secret_number = rand::thread_rng().gen_range(1, 101);  // [1, 101)

	// loop 对应于无限循环
    loop {
        println!("Please input your guess.");

		// 定义一个 String 变量，但是该变量是可以是 mutable，值可以被修改
		// 完整类型为： Struct std::string::String
        let mut guess = String::new();

		// 采用 std::io::stdin().read_line() 函数，从用户输入读取变量，并赋值到 guess 变量中。
		// pub fn stdin() -> Stdin (pub struct Stdin { /* fields omitted */ })
		// fn Stdin::read_line(&self, buf: &mut String) -> Result<usize>
		// type Result<T> = Result<T, Error>;
		// std::result::Result
		// pub enum Result<T, E> {
		//		Ok(T),
		//		Err(E),
		//}

		// fn expect(self, msg: &str) -> T
		// Panics if the value is an Err, with a panic message including the passed message, and the content of the Err.

		// &mut guess 中的 &mut 则用于指明，guess是可以修改变量
        io::stdin().read_line(&mut guess)
            .expect("Failed to read line");  // .expect 为 readline 出错后的，panic 打印的信息

        // guess: u32 用于指明 guess变量的类型为u32
        // rust 允许 重新定义 guess 为 u32 类型，用于覆盖前面定义的 String 类型的 guess

        // fn trim(&self) -> &str,  trim 用于删除字符串前后的空格，空格依赖于 White_Space
        // fn str::parse<F>(&self) -> Result<F, F::Err>  Parses this string slice into another type.

        // 使用 match 来处理， result的两个 枚举值， Ok or Err
        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };

        println!("You guessed: {}", guess);

        match guess.cmp(&secret_number) {
            Ordering::Less    => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal   => {
                println!("You win!");
                break;  // 如果guess ok，则退出
            }
        }
    }
}<|endoftext|>


<commit_before>use std::fmt;
use std::ops::Index;
use std::slice::Iter;
use std::vec::Vec;

use itertools::Itertools;

use types::*;

pub type ColumnId = usize;

#[derive(Clone, PartialEq, Debug)]
pub struct Constraint
{
  pub nullable: bool,
  pub unique: bool,
  pub sorted: bool
}

pub struct Identifier
{
  pub name: String,
  pub quoted: bool
}

impl Identifier
{
  pub fn new<T: AsRef<str>>(name: T) -> Identifier
  {
    Identifier {
      name: name.as_ref().to_string(),
      quoted: false
    }
  }

  pub fn new_quoted<T: AsRef<str>>(name: T, quoted: bool) -> Identifier
  {
    Identifier {
      name: name.as_ref().to_string(),
      quoted: quoted
    }
  }
}

#[derive(Clone, PartialEq, Debug)]
pub struct Field
{
  pub name: String,
  pub decl: FieldDecl,
  pub cstr: Option<Constraint>
}

impl Field
{
  pub fn new<T: AsRef<str>>(name: T, decl: FieldDecl) -> Field
  {
    Field {
      name: name.as_ref().to_string(),
      decl: decl,
      cstr: None,
    }
  }

  pub fn scalar<T: AsRef<str>>(name: T, ty: Ty) -> Field
  {
    Field::new(name, FieldDecl::Scalar(ty))
  }

  pub fn array<T: AsRef<str>>(name: T, decl: FieldDecl) -> Field
  {
    Field::new(name, FieldDecl::Array(Box::new(decl)))
  }

  pub fn map<T: AsRef<str>>(name: T, key_ty: FieldDecl, val_ty: FieldDecl) -> Field
  {
    Field::new(name, FieldDecl::Map(Box::new(key_ty), Box::new(val_ty)))
  }

  pub fn record<T: AsRef<str>>(name: T, r: Record) -> Field
  {
    Field::new(name, FieldDecl::Record(r))
  }

  pub fn record_from_vec<T: AsRef<str>>(name: T, fields: Vec<Field>) -> Field
  {
    Field::new(name, FieldDecl::Record(Record::new(fields)))
  }

  #[inline]
  pub fn name(&self) -> &str { &self.name }
}

impl fmt::Display for Field
{
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
  {
    write!(f, "{}", display_field(self))
  }
}

#[inline]
fn display_field(f: &Field) -> String { format!("{} {}", f.name, f.decl) }

#[inline]
fn display_fields(fields: &Vec<Field>) -> String
{
  fields.iter().map(|f| display_field(f)).join(", ")
}

#[derive(Clone, PartialEq, Debug)]
pub enum FieldDecl
{
  Scalar (Ty),
  Record (Record),
  Array  (Box<FieldDecl>),
  Map    (Box<FieldDecl>, Box<FieldDecl>)
}

impl FieldDecl
{
  pub fn scalar(ty: Ty) -> FieldDecl { FieldDecl::Scalar(ty) }

  pub fn record_from_vec(fields: Vec<Field>) -> FieldDecl
  {
    FieldDecl::Record(Record::new(fields))
  }
}

impl fmt::Display for FieldDecl
{
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
  {
    write!(f, "{}", display_field_decl(self))
  }
}

fn display_field_decl(decl: &FieldDecl) -> String
{
  match *decl {
    FieldDecl::Scalar(ref ty)         => ty.name().to_owned(),
    FieldDecl::Record(ref r)          => format!("record ({})", r),
    FieldDecl::Array (ref vt)         => format!("array<{}>", vt),
    FieldDecl::Map   (ref kt, ref vt) => format!("map<{},{}>", kt, vt)
  }
}

#[derive(Clone, PartialEq, Debug)]
pub struct Record { fields: Vec<Field> }

impl Record
{
  pub fn new(fields: Vec<Field>) -> Record { Record {fields: fields} }

  pub fn size(&self) -> usize { self.fields.len() }

  pub fn find_id(&self, name: &str) -> Option<ColumnId>
  {
    self.fields.iter().position(|f| f.name == name)
  }

  pub fn find_by_name(&self, name : &str) -> Option<&Field>
  {
    self.fields.iter().filter(|&f| f.name == name).next()
  }

  pub fn iter(&self) -> Iter<Field>
  {
    self.fields.iter()
  }
}

impl Index<ColumnId> for Record
{
  type Output = Field;
  fn index<'a>(&'a self, id: ColumnId) -> &'a Field
  {
    debug_assert!(id < self.fields.len(), "Field index is out of range");
    &self.fields[id]
  }
}

impl fmt::Display for Record
{
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
  {
    write!(f, "{}", display_fields(&self.fields))
  }
}

#[allow(dead_code)]
fn create_test_schema() -> Record
{
	Record::new(vec![
    Field::scalar("col1", *INT4_TY),
    Field::record_from_vec("col2", vec![
        Field::scalar("col3", *INT4_TY),
        Field::scalar("col4", *INT4_TY)
      ]
    ),
    Field::record_from_vec("col5", vec![
        Field::array("col6", FieldDecl::scalar(*INT8_TY)),
        Field::array("col7", FieldDecl::scalar(*INT8_TY)),
      ]
    ),
    Field::map("col8", FieldDecl::scalar(*INT4_TY), FieldDecl::record_from_vec(
      vec![
        Field::scalar("col9",  *TEXT_TY),
        Field::scalar("col10", *TEXT_TY),
      ])
    )
  ])
}

#[test]
fn test_schema_creation()
{
  let schema = create_test_schema();
  assert_eq!(vec![
    "col1 int4, col2 record (col3 int4, col4 int4), col5 record (col6 array<int8>, ",
    "col7 array<int8>), col8 map<int4,record (col9 text, col10 text)>"
    ].concat(), format!("{}", schema));
}
<commit_msg>Implement Identifier and add it to Field.<commit_after>use std::fmt;
use std::ops::Index;
use std::slice::Iter;
use std::vec::Vec;

use itertools::Itertools;

use types::*;

pub type ColumnId = usize;

#[derive(Clone, PartialEq, Debug)]
pub struct Constraint
{
  pub nullable: bool,
  pub unique: bool,
  pub sorted: bool
}

#[derive(Clone, PartialEq, Debug)]
pub struct Identifier
{
  pub name: String,
  pub quoted: bool
}

impl Identifier
{
  pub fn new<T: AsRef<str>>(name: T) -> Identifier
  {
    Identifier {
      name: name.as_ref().to_string(),
      quoted: false
    }
  }

  pub fn new_quoted<T: AsRef<str>>(name: T, quoted: bool) -> Identifier
  {
    Identifier {
      name: name.as_ref().to_string(),
      quoted: quoted
    }
  }

  pub fn as_str(&self) -> &str { &self.name }
}

#[inline]
pub fn name<T: AsRef<str>>(name: T) -> Identifier { Identifier::new(name.as_ref()) }

impl fmt::Display for Identifier
{
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
  {
    write!(f, "{}", self.name)
  }
}

#[derive(Clone, PartialEq, Debug)]
pub struct Field
{
  pub name: Identifier,
  pub decl: FieldDecl,
  pub cstr: Option<Constraint>
}

impl Field
{
  pub fn new(name: Identifier, decl: FieldDecl) -> Field
  {
    Field {
      name: name,
      decl: decl,
      cstr: None,
    }
  }

  pub fn scalar(name: Identifier, ty: Ty) -> Field
  {
    Field::new(name, FieldDecl::Scalar(ty))
  }

  pub fn array(name: Identifier, decl: FieldDecl) -> Field
  {
    Field::new(name, FieldDecl::Array(Box::new(decl)))
  }

  pub fn map(name: Identifier, key_ty: FieldDecl, val_ty: FieldDecl) -> Field
  {
    Field::new(name, FieldDecl::Map(Box::new(key_ty), Box::new(val_ty)))
  }

  pub fn record(name: Identifier, r: Record) -> Field
  {
    Field::new(name, FieldDecl::Record(r))
  }

  pub fn record_from_vec(name: Identifier, fields: Vec<Field>) -> Field
  {
    Field::new(name, FieldDecl::Record(Record::new(fields)))
  }

  #[inline]
  pub fn name(&self) -> &str { &self.name.as_str() }

  pub fn identifier(&self) -> &Identifier { &self.name }
}

impl fmt::Display for Field
{
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
  {
    write!(f, "{}", display_field(self))
  }
}

#[inline]
fn display_field(f: &Field) -> String { format!("{} {}", f.name, f.decl) }

#[inline]
fn display_fields(fields: &Vec<Field>) -> String
{
  fields.iter().map(|f| display_field(f)).join(", ")
}

#[derive(Clone, PartialEq, Debug)]
pub enum FieldDecl
{
  Scalar (Ty),
  Record (Record),
  Array  (Box<FieldDecl>),
  Map    (Box<FieldDecl>, Box<FieldDecl>)
}

impl FieldDecl
{
  pub fn scalar(ty: Ty) -> FieldDecl { FieldDecl::Scalar(ty) }

  pub fn record_from_vec(fields: Vec<Field>) -> FieldDecl
  {
    FieldDecl::Record(Record::new(fields))
  }
}

impl fmt::Display for FieldDecl
{
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
  {
    write!(f, "{}", display_field_decl(self))
  }
}

fn display_field_decl(decl: &FieldDecl) -> String
{
  match *decl {
    FieldDecl::Scalar(ref ty)         => ty.name().to_owned(),
    FieldDecl::Record(ref r)          => format!("record ({})", r),
    FieldDecl::Array (ref vt)         => format!("array<{}>", vt),
    FieldDecl::Map   (ref kt, ref vt) => format!("map<{},{}>", kt, vt)
  }
}

#[derive(Clone, PartialEq, Debug)]
pub struct Record { fields: Vec<Field> }

impl Record
{
  pub fn new(fields: Vec<Field>) -> Record { Record {fields: fields} }

  pub fn size(&self) -> usize { self.fields.len() }

  pub fn find_id(&self, name: &str) -> Option<ColumnId>
  {
    self.fields.iter().position(|f| f.name() == name)
  }

  pub fn find_by_name(&self, name : &str) -> Option<&Field>
  {
    self.fields.iter().filter(|&f| f.name() == name).next()
  }

  pub fn iter(&self) -> Iter<Field>
  {
    self.fields.iter()
  }
}

impl Index<ColumnId> for Record
{
  type Output = Field;
  fn index<'a>(&'a self, id: ColumnId) -> &'a Field
  {
    debug_assert!(id < self.fields.len(), "Field index is out of range");
    &self.fields[id]
  }
}

impl fmt::Display for Record
{
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
  {
    write!(f, "{}", display_fields(&self.fields))
  }
}

#[allow(dead_code)]
fn create_test_schema() -> Record
{
	Record::new(vec![
    Field::scalar(name("col1"), *INT4_TY),
    Field::record_from_vec(name("col2"), vec![
        Field::scalar(name("col3"), *INT4_TY),
        Field::scalar(name("col4"), *INT4_TY)
      ]
    ),
    Field::record_from_vec(name("col5"), vec![
        Field::array(name("col6"), FieldDecl::scalar(*INT8_TY)),
        Field::array(name("col7"), FieldDecl::scalar(*INT8_TY)),
      ]
    ),
    Field::map(name("col8"), FieldDecl::scalar(*INT4_TY), FieldDecl::record_from_vec(
      vec![
        Field::scalar(name("col9"),  *TEXT_TY),
        Field::scalar(name("col10"), *TEXT_TY),
      ])
    )
  ])
}

#[test]
fn test_schema_creation()
{
  let schema = create_test_schema();
  assert_eq!(vec![
    "col1 int4, col2 record (col3 int4, col4 int4), col5 record (col6 array<int8>, ",
    "col7 array<int8>), col8 map<int4,record (col9 text, col10 text)>"
    ].concat(), format!("{}", schema));
}
<|endoftext|>


<commit_before>extern crate machinelearning;

use machinelearning::vector::Vector;
use machinelearning::linear_regression::LinearRegression;

fn main() {
    let xs = Vector::from_slice(&[1.0,2.0,4.0,0.0]);
    let ys = Vector::from_slice(&[0.5,1.0,2.0,0.0]);
    let mut model = LinearRegression::new(0.1, 1e-6);
    model.fit(&xs, &ys);
    println!("{:?}", model);
}
<commit_msg>Change tolerance level for the example.<commit_after>extern crate machinelearning;

use machinelearning::vector::Vector;
use machinelearning::linear_regression::LinearRegression;

fn main() {
    let xs = Vector::from_slice(&[1.0,2.0,4.0,0.0]);
    let ys = Vector::from_slice(&[0.5,1.0,2.0,0.0]);
    let mut model = LinearRegression::new(0.1, 1e-8);
    model.fit(&xs, &ys);
    println!("{:?}", model);
}
<|endoftext|>