<commit_before>use image::{ImageBuffer, RgbImage};
use bitreader::{BitReader};
use itertools::Itertools;
use discrete_transforms::dct_2d::Dct2D;

#[derive(Debug)]
pub struct CoverImage {
    cover_image: RgbImage,
    message: &'static str,
    output_image_path: &'static str,
    message_as_bits: Vec<u8>,
    tiles: Vec<u8>,
    dct_tiles: Vec<f64>,
    quantized_tiles: Vec<i32>,
    modified_pixels: Vec<f64>
}

impl CoverImage {
    pub fn new() -> CoverImage {
        CoverImage {
            cover_image: ImageBuffer::new(0, 0),
            message: "",
            output_image_path: "",
            message_as_bits: vec![],
            tiles: vec![],
            dct_tiles: vec![],
            quantized_tiles: vec![],
            modified_pixels: vec![]
        }
    }

    pub fn set_cover_image(&mut self, input_path: &'static str) -> &mut Self {
        self.cover_image = image::open(input_path).unwrap().as_rgb8().unwrap().clone();

        self
    }

    pub fn set_message(&mut self, message: &'static str) -> &mut Self {
        self.message = message;

        self
    }

    pub fn set_output_image_path(&mut self, output_path: &'static str) -> &mut Self {
        self.output_image_path = output_path;

        self
    }

    pub fn encode(&mut self) {
        self.get_message_as_bits();
        self.tile_image();
        self.encode_message();

        self.cover_image.save(self.output_image_path).unwrap();
    }

    fn get_message_as_bits(&mut self) {
        let mut reader = BitReader::new(&self.message.as_bytes());

        for _ in 0..self.message.len() * 8 {
            self.message_as_bits.push(reader.read_u8(1).unwrap());
        }
    }

    fn tile_image(&mut self) {
        let (width, height) = self.cover_image.dimensions();
        let mut count = 0;

        for row_index in 0..(height / 8) as u32 {
            for col_index in 0..(width / 8) as u32 {
                for channel in 0..3 {
                    if count == self.message_as_bits.len() {
                        break
                    }

                    for row in 0..8 {
                        for column in 0..8 {
                            let pixel = self.cover_image.get_pixel(column + (col_index * 8),
                                                                      row + (row_index * 8));

                            self.tiles.push(pixel.data[channel]);
                        }
                    }

                    count += 1;
                }
            }
        }
    }

    fn encode_message(&mut self) {
        let mut dct = Dct2D::new();

        for chunk in &self.tiles.iter().chunks(64) {
            let input = chunk.map(|x| *x as f64).collect_vec();

            dct.set_input(input);

            self.dct_tiles.extend(&dct.forward());
        }

        self.quantize();
    }

    fn quantize(&mut self) {
        let quantization_table = vec![16, 11, 10, 16,  24,  40,  51,  61,
                                      12, 12, 14, 19,  26,  58,  60,  55,
                                      14, 13, 16, 24,  40,  57,  69,  56,
                                      14, 17, 22, 29,  51,  87,  80,  62,
                                      18, 22, 37, 56,  68, 109, 103,  77,
                                      24, 36, 55, 64,  81, 104, 113,  92,
                                      49, 64, 78, 87, 103, 121, 120, 101,
                                      72, 92, 95, 98, 112, 100, 103,  99];

        for x in 0..self.dct_tiles.len() {
            let quantized_coeff = self.dct_tiles[x] / quantization_table[x % 64] as f64;

            self.quantized_tiles.push(quantized_coeff as i32);
        }
    }
}

#[test]
fn get_message_as_bits_test() {
    let test_bits = vec![0, 1, 1, 0, 1, 0, 0, 0];
    let mut cover_image = CoverImage::new();

    cover_image.set_message("h");
    cover_image.get_message_as_bits();

    assert_eq!(cover_image.message_as_bits, test_bits);
}

#[test]
fn tile_image_length_test() {
    let mut cover_image = CoverImage::new();

    cover_image.set_message("h");
    cover_image.set_cover_image("src/testing.jpg");

    // 64 = length of 1 tile, message.len() * 8 = number of tiles needed; 1 tile per bit
    let length = 64 * cover_image.message.len() * 8;

    cover_image.get_message_as_bits();
    cover_image.tile_image();

    let tile_vec_length = cover_image.tiles.len();

    assert_eq!(length, tile_vec_length);
}

#[test]
fn test_random_pixel_in_tile() {
    let mut cover_image = CoverImage::new();

    cover_image.set_message("h");
    cover_image.set_cover_image("src/testing.jpg");
    cover_image.get_message_as_bits();
    cover_image.tile_image();

    let pixel = cover_image.cover_image.get_pixel(8, 8);

    let r_pixel = pixel.data[0];
    let g_pixel = pixel.data[1];
    let b_pixel = pixel.data[2];

    let r_pixel_from_tile = cover_image.tiles[63];
    let g_pixel_from_tile = cover_image.tiles[127];
    let b_pixel_from_tile = cover_image.tiles[191];

    assert_eq!(r_pixel, r_pixel_from_tile);
    assert_eq!(g_pixel, g_pixel_from_tile);
    assert_eq!(b_pixel, b_pixel_from_tile);
}

#[test]
fn delete() {
    let mut cover_image = CoverImage::new();

    cover_image.set_message("h");
    cover_image.set_cover_image("src/testing.jpg");
    cover_image.set_output_image_path("output.jpg");
    cover_image.encode();
}<commit_msg>This can now definitely encode at least 1 letter, haven't tested full sentences yet<commit_after>use image::{ImageBuffer, RgbImage};
use bitreader::{BitReader};
use itertools::Itertools;
use discrete_transforms::dct_2d::Dct2D;

const QUANTIZATION_TABLE: [i32; 64] = [16, 11, 10, 16,  24,  40,  51,  61,
                                       12, 12, 14, 19,  26,  58,  60,  55,
                                       14, 13, 16, 24,  40,  57,  69,  56,
                                       14, 17, 22, 29,  51,  87,  80,  62,
                                       18, 22, 37, 56,  68, 109, 103,  77,
                                       24, 36, 55, 64,  81, 104, 113,  92,
                                       49, 64, 78, 87, 103, 121, 120, 101,
                                       72, 92, 95, 98, 112, 100, 103,  99];

#[derive(Debug)]
pub struct CoverImage {
    cover_image: RgbImage,
    message: &'static str,
    output_image_path: &'static str,
    message_as_bits: Vec<u8>,
    tiles: Vec<u8>,
    dct_tiles: Vec<f64>,
    quantized_tiles: Vec<i32>,
    dequantized_tiles: Vec<i32>,
    idct_tiles: Vec<f64>,
}

impl CoverImage {
    pub fn new() -> CoverImage {
        CoverImage {
            cover_image: ImageBuffer::new(0, 0),
            message: "",
            output_image_path: "",
            message_as_bits: vec![],
            tiles: vec![],
            dct_tiles: vec![],
            quantized_tiles: vec![],
            dequantized_tiles: vec![],
            idct_tiles: vec![]
        }
    }

    pub fn set_cover_image(&mut self, input_path: &'static str) -> &mut Self {
        self.cover_image = image::open(input_path).unwrap().as_rgb8().unwrap().clone();

        self
    }

    pub fn set_message(&mut self, message: &'static str) -> &mut Self {
        self.message = message;

        self
    }

    pub fn set_output_image_path(&mut self, output_path: &'static str) -> &mut Self {
        self.output_image_path = output_path;

        self
    }

    pub fn encode(&mut self) {
        self.get_message_as_bits();
        self.tile_image();
        self.encode_message();
        self.save_image();
    }

    fn get_message_as_bits(&mut self) {
        let mut reader = BitReader::new(&self.message.as_bytes());

        for _ in 0..self.message.len() * 8 {
            self.message_as_bits.push(reader.read_u8(1).unwrap());
        }
    }

    fn tile_image(&mut self) {
        let (width, height) = self.cover_image.dimensions();
        let mut count = 0;

        for row_index in 0..(height / 8) as u32 {
            for col_index in 0..(width / 8) as u32 {
                for channel in 0..3 {
                    if count == self.message_as_bits.len() {
                        break
                    }

                    for row in 0..8 {
                        for column in 0..8 {
                            let pixel = self.cover_image.get_pixel(column + (col_index * 8),
                                                                      row + (row_index * 8));

                            self.tiles.push(pixel.data[channel]);
                        }
                    }

                    count += 1;
                }
            }
        }
    }

    fn encode_message(&mut self) {
        let mut dct = Dct2D::new();

        for chunk in &self.tiles.iter().chunks(64) {
            let input = chunk.map(|x| *x as f64).collect_vec();

            dct.set_input(input);

            self.dct_tiles.extend(&dct.forward());
        }

        self.quantize();

        for (count, bit) in self.message_as_bits.iter().enumerate() {
            if *bit == 1 as u8 {
                self.quantized_tiles[count * 64] |= 1;
            }
            else {
                self.quantized_tiles[count * 64] &= 0b1111_1110
            }
        }

        self.dequantize();

        for chunk in &self.dequantized_tiles.iter().chunks(64) {
            let input = chunk.map(|x| *x as f64).collect_vec();

            dct.set_input(input);

            self.idct_tiles.extend(&dct.inverse());
        }

        self.idct_tiles = self.idct_tiles.iter()
                                         .map(|x| (x * 1000.0).round() / 1000.0)
                                         .collect_vec();
    }

    fn quantize(&mut self) {
        for x in 0..self.dct_tiles.len() {
            let quantized_coeff = self.dct_tiles[x] / QUANTIZATION_TABLE[x % 64] as f64;

            self.quantized_tiles.push(quantized_coeff.round() as i32);
        }
    }

    fn dequantize(&mut self) {
        for x in 0..self.quantized_tiles.len() {
            let dequantized_coeff = self.quantized_tiles[x] * QUANTIZATION_TABLE[x % 64];

            self.dequantized_tiles.push(dequantized_coeff);
        }
    }

    fn save_image(&mut self) {
        let (width, height) = self.cover_image.dimensions();
        let mut count = 0;
        let mut pixel_count = 0;

        for row_index in 0..(height / 8) as u32 {
            for col_index in 0..(width / 8) as u32 {
                for channel in 0..3 {
                    if count == self.message_as_bits.len() {
                        break
                    }

                    for row in 0..8 {
                        for column in 0..8 {
                            let pixel = self.cover_image.get_pixel_mut(column + (col_index * 8),
                                                                          row + (row_index * 8));

                            pixel.data[channel] = self.idct_tiles[pixel_count] as u8;

                            pixel_count += 1;
                        }
                    }

                    count += 1;
                }
            }
        }

        self.cover_image.save(self.output_image_path).unwrap();
    }
}

#[test]
fn get_message_as_bits_test() {
    let test_bits = vec![0, 1, 1, 0, 1, 0, 0, 0];
    let mut cover_image = CoverImage::new();

    cover_image.set_message("h");
    cover_image.get_message_as_bits();

    assert_eq!(cover_image.message_as_bits, test_bits);
}

#[test]
fn tile_image_length_test() {
    let mut cover_image = CoverImage::new();

    cover_image.set_message("h");
    cover_image.set_cover_image("src/testing.jpg");

    // 64 = length of 1 tile, message.len() * 8 = number of tiles needed; 1 tile per bit
    let length = 64 * cover_image.message.len() * 8;

    cover_image.get_message_as_bits();
    cover_image.tile_image();

    let tile_vec_length = cover_image.tiles.len();

    assert_eq!(length, tile_vec_length);
}

#[test]
fn test_random_pixel_in_tile() {
    let mut cover_image = CoverImage::new();

    cover_image.set_message("h");
    cover_image.set_cover_image("src/testing.jpg");
    cover_image.get_message_as_bits();
    cover_image.tile_image();

    let pixel = cover_image.cover_image.get_pixel(8, 8);

    let r_pixel = pixel.data[0];
    let g_pixel = pixel.data[1];
    let b_pixel = pixel.data[2];

    let r_pixel_from_tile = cover_image.tiles[63];
    let g_pixel_from_tile = cover_image.tiles[127];
    let b_pixel_from_tile = cover_image.tiles[191];

    assert_eq!(r_pixel, r_pixel_from_tile);
    assert_eq!(g_pixel, g_pixel_from_tile);
    assert_eq!(b_pixel, b_pixel_from_tile);
}<|endoftext|>


<commit_before>use super::plumbing::*;
use super::*;

use std::fmt::{self, Debug};

/// The `split` function takes arbitrary data and a closure that knows how to
/// split it, and turns this into a `ParallelIterator`.
///
/// # Examples
///
/// As a simple example, Rayon can recursively split ranges of indices
///
/// ```
/// use rayon::iter;
/// use rayon::prelude::*;
/// use std::ops::Range;
///
///
/// // We define a range of indices as follows
/// type Range1D = Range<usize>;
///
/// // Splitting it in two can be done like this
/// fn split_range1(r: Range1D) -> (Range1D, Option<Range1D>) {
///     // We are mathematically unable to split the range if there is only
///     // one point inside of it, but we could stop splitting before that.
///     if r.end - r.start <= 1 { return (r, None); }
///
///     // Here, our range is considered large enough to be splittable
///     let midpoint = r.start + (r.end - r.start) / 2;
///     let out1 = Range1D {
///         start: r.start,
///         end: midpoint,
///     };
///     let out2 = Range1D {
///         start: midpoint,
///         end: r.end,
///     };
///     (out1, Some(out2))
/// }
///
/// // By using iter::split, Rayon will split the range until it has enough work
/// // to feed the CPU cores, then give us the resulting sub-ranges
/// iter::split(0..4096, split_range1).for_each(|sub_range| {
///     // As our initial range had a power-of-two size, the final sub-ranges
///     // should have power-of-two sizes too
///     assert!((sub_range.end - sub_range.start).is_power_of_two());
/// });
/// ```
///
/// This recursive splitting can be extended to two or three dimensions,
/// to reproduce a classic "block-wise" parallelization scheme of graphics and
/// numerical simulations:
///
/// ```
/// # type Range1D = Range<usize>;
/// # fn split_range1(r: Range1D) -> (Range1D, Option<Range1D>) {
/// #     if r.end - r.start <= 1 { return (r, None); }
/// #     let midpoint = r.start + (r.end - r.start) / 2;
/// #     let out1 = Range1D {
/// #         start: r.start,
/// #         end: midpoint,
/// #     };
/// #     let out2 = Range1D {
/// #         start: midpoint,
/// #         end: r.end,
/// #     };
/// #     (out1, Some(out2))
/// # }
/// #
/// // A two-dimensional range of indices can be built out of two 1D ones
/// struct Range2D {
///     // Range of horizontal indices
///     pub rx: Range1D,
///
///     // Range of vertical indices
///     pub ry: Range1D,
/// }
///
/// // We want to recursively split them by the largest dimension until we have
/// // enough sub-ranges to feed our mighty multi-core CPU. This function
/// // carries out one such split.
/// fn split_range2(r2: Range2D) -> (Range2D, Option<Range2D>) {
///     // Decide on which axis (horizontal/vertical) the range should be split
///     let width = r2.rx.end - r2.rx.start;
///     let height = r2.ry.end - r2.ry.start;
///     if width >= height {
///         // This is a wide rectangle, split it on the horizontal axis
///         let (split_rx, ry) = (split_range1(r2.rx), r2.ry);
///         let out1 = Range2D {
///             rx: split_rx.0,
///             ry: ry.clone(),
///         };
///         let out2 = split_rx.1.map(|rx| Range2D { rx, ry });
///         (out1, out2)
///     } else {
///         // This is a tall rectangle, split it on the vertical axis
///         let (rx, split_ry) = (r2.rx, split_range1(r2.ry));
///         let out1 = Range2D {
///             rx: rx.clone(),
///             ry: split_ry.0,
///         };
///         let out2 = split_ry.1.map(|ry| Range2D { rx, ry, });
///         (out1, out2)
///     }
/// }
///
/// // Again, rayon can handle the recursive splitting for us
/// let range = Range2D { rx: 0..800, ry: 0..600 };
/// iter::split(range, split_range2).for_each(|sub_range| {
///     // If the sub-ranges were indeed split by the largest dimension, then
///     // if no dimension was twice larger than the other initially, this
///     // property will remain true in the final sub-ranges.
///     let width = sub_range.rx.end - sub_range.rx.start;
///     let height = sub_range.ry.end - sub_range.ry.start;
///     assert!((width < 2 * height) && (height < 2 * width));
/// });
/// ```
///
pub fn split<D, S>(data: D, splitter: S) -> Split<D, S>
    where D: Send,
          S: Fn(D) -> (D, Option<D>) + Sync
{
    Split {
        data: data,
        splitter: splitter,
    }
}

/// `Split` is a parallel iterator using arbitrary data and a splitting function.
/// This struct is created by the [`split()`] function.
///
/// [`split()`]: fn.split.html
#[derive(Clone)]
pub struct Split<D, S> {
    data: D,
    splitter: S,
}

impl<D: Debug, S> Debug for Split<D, S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Split")
            .field("data", &self.data)
            .finish()
    }
}

impl<D, S> ParallelIterator for Split<D, S>
    where D: Send,
          S: Fn(D) -> (D, Option<D>) + Sync + Send
{
    type Item = D;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        let producer = SplitProducer {
            data: self.data,
            splitter: &self.splitter,
        };
        bridge_unindexed(producer, consumer)
    }
}

struct SplitProducer<'a, D, S: 'a> {
    data: D,
    splitter: &'a S,
}

impl<'a, D, S> UnindexedProducer for SplitProducer<'a, D, S>
    where D: Send,
          S: Fn(D) -> (D, Option<D>) + Sync
{
    type Item = D;

    fn split(mut self) -> (Self, Option<Self>) {
        let splitter = self.splitter;
        let (left, right) = splitter(self.data);
        self.data = left;
        (self,
         right.map(|data| {
                       SplitProducer {
                           data: data,
                           splitter: splitter,
                       }
                   }))
    }

    fn fold_with<F>(self, folder: F) -> F
        where F: Folder<Self::Item>
    {
        folder.consume(self.data)
    }
}
<commit_msg>Copy use clauses too...<commit_after>use super::plumbing::*;
use super::*;

use std::fmt::{self, Debug};

/// The `split` function takes arbitrary data and a closure that knows how to
/// split it, and turns this into a `ParallelIterator`.
///
/// # Examples
///
/// As a simple example, Rayon can recursively split ranges of indices
///
/// ```
/// use rayon::iter;
/// use rayon::prelude::*;
/// use std::ops::Range;
///
///
/// // We define a range of indices as follows
/// type Range1D = Range<usize>;
///
/// // Splitting it in two can be done like this
/// fn split_range1(r: Range1D) -> (Range1D, Option<Range1D>) {
///     // We are mathematically unable to split the range if there is only
///     // one point inside of it, but we could stop splitting before that.
///     if r.end - r.start <= 1 { return (r, None); }
///
///     // Here, our range is considered large enough to be splittable
///     let midpoint = r.start + (r.end - r.start) / 2;
///     let out1 = Range1D {
///         start: r.start,
///         end: midpoint,
///     };
///     let out2 = Range1D {
///         start: midpoint,
///         end: r.end,
///     };
///     (out1, Some(out2))
/// }
///
/// // By using iter::split, Rayon will split the range until it has enough work
/// // to feed the CPU cores, then give us the resulting sub-ranges
/// iter::split(0..4096, split_range1).for_each(|sub_range| {
///     // As our initial range had a power-of-two size, the final sub-ranges
///     // should have power-of-two sizes too
///     assert!((sub_range.end - sub_range.start).is_power_of_two());
/// });
/// ```
///
/// This recursive splitting can be extended to two or three dimensions,
/// to reproduce a classic "block-wise" parallelization scheme of graphics and
/// numerical simulations:
///
/// ```
/// # use rayon::iter;
/// # use rayon::prelude::*;
/// # use std::ops::Range;
/// # type Range1D = Range<usize>;
/// # fn split_range1(r: Range1D) -> (Range1D, Option<Range1D>) {
/// #     if r.end - r.start <= 1 { return (r, None); }
/// #     let midpoint = r.start + (r.end - r.start) / 2;
/// #     let out1 = Range1D {
/// #         start: r.start,
/// #         end: midpoint,
/// #     };
/// #     let out2 = Range1D {
/// #         start: midpoint,
/// #         end: r.end,
/// #     };
/// #     (out1, Some(out2))
/// # }
/// #
/// // A two-dimensional range of indices can be built out of two 1D ones
/// struct Range2D {
///     // Range of horizontal indices
///     pub rx: Range1D,
///
///     // Range of vertical indices
///     pub ry: Range1D,
/// }
///
/// // We want to recursively split them by the largest dimension until we have
/// // enough sub-ranges to feed our mighty multi-core CPU. This function
/// // carries out one such split.
/// fn split_range2(r2: Range2D) -> (Range2D, Option<Range2D>) {
///     // Decide on which axis (horizontal/vertical) the range should be split
///     let width = r2.rx.end - r2.rx.start;
///     let height = r2.ry.end - r2.ry.start;
///     if width >= height {
///         // This is a wide rectangle, split it on the horizontal axis
///         let (split_rx, ry) = (split_range1(r2.rx), r2.ry);
///         let out1 = Range2D {
///             rx: split_rx.0,
///             ry: ry.clone(),
///         };
///         let out2 = split_rx.1.map(|rx| Range2D { rx, ry });
///         (out1, out2)
///     } else {
///         // This is a tall rectangle, split it on the vertical axis
///         let (rx, split_ry) = (r2.rx, split_range1(r2.ry));
///         let out1 = Range2D {
///             rx: rx.clone(),
///             ry: split_ry.0,
///         };
///         let out2 = split_ry.1.map(|ry| Range2D { rx, ry, });
///         (out1, out2)
///     }
/// }
///
/// // Again, rayon can handle the recursive splitting for us
/// let range = Range2D { rx: 0..800, ry: 0..600 };
/// iter::split(range, split_range2).for_each(|sub_range| {
///     // If the sub-ranges were indeed split by the largest dimension, then
///     // if no dimension was twice larger than the other initially, this
///     // property will remain true in the final sub-ranges.
///     let width = sub_range.rx.end - sub_range.rx.start;
///     let height = sub_range.ry.end - sub_range.ry.start;
///     assert!((width < 2 * height) && (height < 2 * width));
/// });
/// ```
///
pub fn split<D, S>(data: D, splitter: S) -> Split<D, S>
    where D: Send,
          S: Fn(D) -> (D, Option<D>) + Sync
{
    Split {
        data: data,
        splitter: splitter,
    }
}

/// `Split` is a parallel iterator using arbitrary data and a splitting function.
/// This struct is created by the [`split()`] function.
///
/// [`split()`]: fn.split.html
#[derive(Clone)]
pub struct Split<D, S> {
    data: D,
    splitter: S,
}

impl<D: Debug, S> Debug for Split<D, S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Split")
            .field("data", &self.data)
            .finish()
    }
}

impl<D, S> ParallelIterator for Split<D, S>
    where D: Send,
          S: Fn(D) -> (D, Option<D>) + Sync + Send
{
    type Item = D;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        let producer = SplitProducer {
            data: self.data,
            splitter: &self.splitter,
        };
        bridge_unindexed(producer, consumer)
    }
}

struct SplitProducer<'a, D, S: 'a> {
    data: D,
    splitter: &'a S,
}

impl<'a, D, S> UnindexedProducer for SplitProducer<'a, D, S>
    where D: Send,
          S: Fn(D) -> (D, Option<D>) + Sync
{
    type Item = D;

    fn split(mut self) -> (Self, Option<Self>) {
        let splitter = self.splitter;
        let (left, right) = splitter(self.data);
        self.data = left;
        (self,
         right.map(|data| {
                       SplitProducer {
                           data: data,
                           splitter: splitter,
                       }
                   }))
    }

    fn fold_with<F>(self, folder: F) -> F
        where F: Folder<Self::Item>
    {
        folder.consume(self.data)
    }
}
<|endoftext|>


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

//! Readers and Writers for in-memory buffers
//!
//! # XXX
//!
//! * Should probably have something like this for strings.
//! * Should they implement Closable? Would take extra state.
use cmp::max;
use cmp::min;
use prelude::*;
use super::*;
use vec;

/// Writes to an owned, growable byte vector
pub struct MemWriter {
    priv buf: ~[u8],
    priv pos: uint,
}

impl MemWriter {
    pub fn new() -> MemWriter {
        MemWriter { buf: vec::with_capacity(128), pos: 0 }
    }
}

impl Writer for MemWriter {
    fn write(&mut self, buf: &[u8]) {
        // Make sure the internal buffer is as least as big as where we
        // currently are
        let difference = self.pos as i64 - self.buf.len() as i64;
        if difference > 0 {
            self.buf.grow(difference as uint, &0);
        }

        // Figure out what bytes will be used to overwrite what's currently
        // there (left), and what will be appended on the end (right)
        let cap = self.buf.len() - self.pos;
        let (left, right) = if cap <= buf.len() {
            (buf.slice_to(cap), buf.slice_from(cap))
        } else {
            (buf, &[])
        };

        // Do the necessary writes
        if left.len() > 0 {
            vec::bytes::copy_memory(self.buf.mut_slice_from(self.pos),
                                    left, left.len());
        }
        if right.len() > 0 {
            self.buf.push_all(right);
        }

        // Bump us forward
        self.pos += buf.len();
    }
}

// FIXME(#10432)
impl Seek for MemWriter {
    fn tell(&self) -> u64 { self.pos as u64 }

    fn seek(&mut self, pos: i64, style: SeekStyle) {
        // compute offset as signed and clamp to prevent overflow
        let offset = match style {
            SeekSet => { 0 }
            SeekEnd => { self.buf.len() }
            SeekCur => { self.pos }
        } as i64;

        self.pos = max(0, offset+pos) as uint;
    }
}

impl Decorator<~[u8]> for MemWriter {
    fn inner(self) -> ~[u8] { self.buf }
    fn inner_ref<'a>(&'a self) -> &'a ~[u8] { &self.buf }
    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] { &mut self.buf }
}

/// Reads from an owned byte vector
pub struct MemReader {
    priv buf: ~[u8],
    priv pos: uint
}

impl MemReader {
    pub fn new(buf: ~[u8]) -> MemReader {
        MemReader {
            buf: buf,
            pos: 0
        }
    }
}

impl Reader for MemReader {
    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
        { if self.eof() { return None; } }

        let write_len = min(buf.len(), self.buf.len() - self.pos);
        {
            let input = self.buf.slice(self.pos, self.pos + write_len);
            let output = buf.mut_slice(0, write_len);
            assert_eq!(input.len(), output.len());
            vec::bytes::copy_memory(output, input, write_len);
        }
        self.pos += write_len;
        assert!(self.pos <= self.buf.len());

        return Some(write_len);
    }

    fn eof(&mut self) -> bool { self.pos == self.buf.len() }
}

impl Seek for MemReader {
    fn tell(&self) -> u64 { self.pos as u64 }
    fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
}

impl Buffer for MemReader {
    fn fill<'a>(&'a mut self) -> &'a [u8] { self.buf.slice_from(self.pos) }
    fn consume(&mut self, amt: uint) { self.pos += amt; }
}

impl Decorator<~[u8]> for MemReader {
    fn inner(self) -> ~[u8] { self.buf }
    fn inner_ref<'a>(&'a self) -> &'a ~[u8] { &self.buf }
    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] { &mut self.buf }
}

/// Writes to a fixed-size byte slice
///
/// If a write will not fit in the buffer, it raises the `io_error`
/// condition and does not write any data.
pub struct BufWriter<'self> {
    priv buf: &'self mut [u8],
    priv pos: uint
}

impl<'self> BufWriter<'self> {
    pub fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> {
        BufWriter {
            buf: buf,
            pos: 0
        }
    }
}

impl<'self> Writer for BufWriter<'self> {
    fn write(&mut self, buf: &[u8]) {
        // raises a condition if the entire write does not fit in the buffer
        let max_size = self.buf.len();
        if self.pos >= max_size || (self.pos + buf.len()) > max_size {
            io_error::cond.raise(IoError {
                kind: OtherIoError,
                desc: "Trying to write past end of buffer",
                detail: None
            });
            return;
        }

        vec::bytes::copy_memory(self.buf.mut_slice_from(self.pos),
                                buf, buf.len());
        self.pos += buf.len();
    }
}

// FIXME(#10432)
impl<'self> Seek for BufWriter<'self> {
    fn tell(&self) -> u64 { self.pos as u64 }

    fn seek(&mut self, pos: i64, style: SeekStyle) {
        // compute offset as signed and clamp to prevent overflow
        let offset = match style {
            SeekSet => { 0 }
            SeekEnd => { self.buf.len() }
            SeekCur => { self.pos }
        } as i64;

        self.pos = max(0, offset+pos) as uint;
    }
}

/// Reads from a fixed-size byte slice
pub struct BufReader<'self> {
    priv buf: &'self [u8],
    priv pos: uint
}

impl<'self> BufReader<'self> {
    pub fn new<'a>(buf: &'a [u8]) -> BufReader<'a> {
        BufReader {
            buf: buf,
            pos: 0
        }
    }
}

impl<'self> Reader for BufReader<'self> {
    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
        { if self.eof() { return None; } }

        let write_len = min(buf.len(), self.buf.len() - self.pos);
        {
            let input = self.buf.slice(self.pos, self.pos + write_len);
            let output = buf.mut_slice(0, write_len);
            assert_eq!(input.len(), output.len());
            vec::bytes::copy_memory(output, input, write_len);
        }
        self.pos += write_len;
        assert!(self.pos <= self.buf.len());

        return Some(write_len);
     }

    fn eof(&mut self) -> bool { self.pos == self.buf.len() }
}

impl<'self> Seek for BufReader<'self> {
    fn tell(&self) -> u64 { self.pos as u64 }

    fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
}

impl<'self> Buffer for BufReader<'self> {
    fn fill<'a>(&'a mut self) -> &'a [u8] { self.buf.slice_from(self.pos) }
    fn consume(&mut self, amt: uint) { self.pos += amt; }
}

///Calls a function with a MemWriter and returns
///the writer's stored vector.
pub fn with_mem_writer(writeFn: |&mut MemWriter|) -> ~[u8] {
    let mut writer = MemWriter::new();
    writeFn(&mut writer);
    writer.inner()
}

#[cfg(test)]
mod test {
    use prelude::*;
    use super::*;
    use io::*;

    #[test]
    fn test_mem_writer() {
        let mut writer = MemWriter::new();
        assert_eq!(writer.tell(), 0);
        writer.write([0]);
        assert_eq!(writer.tell(), 1);
        writer.write([1, 2, 3]);
        writer.write([4, 5, 6, 7]);
        assert_eq!(writer.tell(), 8);
        assert_eq!(*writer.inner_ref(), ~[0, 1, 2, 3, 4, 5, 6, 7]);

        writer.seek(0, SeekSet);
        assert_eq!(writer.tell(), 0);
        writer.write([3, 4]);
        assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 3, 4, 5, 6, 7]);

        writer.seek(1, SeekCur);
        writer.write([0, 1]);
        assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 0, 1, 5, 6, 7]);

        writer.seek(-1, SeekEnd);
        writer.write([1, 2]);
        assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 0, 1, 5, 6, 1, 2]);

        writer.seek(1, SeekEnd);
        writer.write([1]);
        assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]);
    }

    #[test]
    fn test_buf_writer() {
        let mut buf = [0 as u8, ..8];
        {
            let mut writer = BufWriter::new(buf);
            assert_eq!(writer.tell(), 0);
            writer.write([0]);
            assert_eq!(writer.tell(), 1);
            writer.write([1, 2, 3]);
            writer.write([4, 5, 6, 7]);
            assert_eq!(writer.tell(), 8);
        }
        assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7]);
    }

    #[test]
    fn test_buf_writer_seek() {
        let mut buf = [0 as u8, ..8];
        {
            let mut writer = BufWriter::new(buf);
            assert_eq!(writer.tell(), 0);
            writer.write([1]);
            assert_eq!(writer.tell(), 1);

            writer.seek(2, SeekSet);
            assert_eq!(writer.tell(), 2);
            writer.write([2]);
            assert_eq!(writer.tell(), 3);

            writer.seek(-2, SeekCur);
            assert_eq!(writer.tell(), 1);
            writer.write([3]);
            assert_eq!(writer.tell(), 2);

            writer.seek(-1, SeekEnd);
            assert_eq!(writer.tell(), 7);
            writer.write([4]);
            assert_eq!(writer.tell(), 8);

        }
        assert_eq!(buf, [1, 3, 2, 0, 0, 0, 0, 4]);
    }

    #[test]
    fn test_buf_writer_error() {
        let mut buf = [0 as u8, ..2];
        let mut writer = BufWriter::new(buf);
        writer.write([0]);

        let mut called = false;
        io_error::cond.trap(|err| {
            assert_eq!(err.kind, OtherIoError);
            called = true;
        }).inside(|| {
            writer.write([0, 0]);
        });
        assert!(called);
    }

    #[test]
    fn test_mem_reader() {
        let mut reader = MemReader::new(~[0, 1, 2, 3, 4, 5, 6, 7]);
        let mut buf = [];
        assert_eq!(reader.read(buf), Some(0));
        assert_eq!(reader.tell(), 0);
        let mut buf = [0];
        assert_eq!(reader.read(buf), Some(1));
        assert_eq!(reader.tell(), 1);
        assert_eq!(buf, [0]);
        let mut buf = [0, ..4];
        assert_eq!(reader.read(buf), Some(4));
        assert_eq!(reader.tell(), 5);
        assert_eq!(buf, [1, 2, 3, 4]);
        assert_eq!(reader.read(buf), Some(3));
        assert_eq!(buf.slice(0, 3), [5, 6, 7]);
        assert!(reader.eof());
        assert_eq!(reader.read(buf), None);
        assert!(reader.eof());
    }

    #[test]
    fn test_buf_reader() {
        let in_buf = ~[0, 1, 2, 3, 4, 5, 6, 7];
        let mut reader = BufReader::new(in_buf);
        let mut buf = [];
        assert_eq!(reader.read(buf), Some(0));
        assert_eq!(reader.tell(), 0);
        let mut buf = [0];
        assert_eq!(reader.read(buf), Some(1));
        assert_eq!(reader.tell(), 1);
        assert_eq!(buf, [0]);
        let mut buf = [0, ..4];
        assert_eq!(reader.read(buf), Some(4));
        assert_eq!(reader.tell(), 5);
        assert_eq!(buf, [1, 2, 3, 4]);
        assert_eq!(reader.read(buf), Some(3));
        assert_eq!(buf.slice(0, 3), [5, 6, 7]);
        assert!(reader.eof());
        assert_eq!(reader.read(buf), None);
        assert!(reader.eof());
    }

    #[test]
    fn test_with_mem_writer() {
        let buf = with_mem_writer(|wr| wr.write([1,2,3,4,5,6,7]));
        assert_eq!(buf, ~[1,2,3,4,5,6,7]);
    }

    #[test]
    fn test_read_char() {
        let mut r = BufReader::new(bytes!("Việt"));
        assert_eq!(r.read_char(), Some('V'));
        assert_eq!(r.read_char(), Some('i'));
        assert_eq!(r.read_char(), Some('ệ'));
        assert_eq!(r.read_char(), Some('t'));
        assert_eq!(r.read_char(), None);
    }

    #[test]
    fn test_read_bad_char() {
        let mut r = BufReader::new(bytes!(0x80));
        assert_eq!(r.read_char(), None);
    }
}
<commit_msg>std::io::mem: add a with_capacity constructor to MemWriter.<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Readers and Writers for in-memory buffers
//!
//! # XXX
//!
//! * Should probably have something like this for strings.
//! * Should they implement Closable? Would take extra state.
use cmp::max;
use cmp::min;
use prelude::*;
use super::*;
use vec;

/// Writes to an owned, growable byte vector
pub struct MemWriter {
    priv buf: ~[u8],
    priv pos: uint,
}

impl MemWriter {
    /// Create a new `MemWriter`.
    pub fn new() -> MemWriter {
        MemWriter::with_capacity(128)
    }
    /// Create a new `MemWriter`, allocating at least `n` bytes for
    /// the internal buffer.
    pub fn with_capacity(n: uint) -> MemWriter {
        MemWriter { buf: vec::with_capacity(n), pos: 0 }
    }
}

impl Writer for MemWriter {
    fn write(&mut self, buf: &[u8]) {
        // Make sure the internal buffer is as least as big as where we
        // currently are
        let difference = self.pos as i64 - self.buf.len() as i64;
        if difference > 0 {
            self.buf.grow(difference as uint, &0);
        }

        // Figure out what bytes will be used to overwrite what's currently
        // there (left), and what will be appended on the end (right)
        let cap = self.buf.len() - self.pos;
        let (left, right) = if cap <= buf.len() {
            (buf.slice_to(cap), buf.slice_from(cap))
        } else {
            (buf, &[])
        };

        // Do the necessary writes
        if left.len() > 0 {
            vec::bytes::copy_memory(self.buf.mut_slice_from(self.pos),
                                    left, left.len());
        }
        if right.len() > 0 {
            self.buf.push_all(right);
        }

        // Bump us forward
        self.pos += buf.len();
    }
}

// FIXME(#10432)
impl Seek for MemWriter {
    fn tell(&self) -> u64 { self.pos as u64 }

    fn seek(&mut self, pos: i64, style: SeekStyle) {
        // compute offset as signed and clamp to prevent overflow
        let offset = match style {
            SeekSet => { 0 }
            SeekEnd => { self.buf.len() }
            SeekCur => { self.pos }
        } as i64;

        self.pos = max(0, offset+pos) as uint;
    }
}

impl Decorator<~[u8]> for MemWriter {
    fn inner(self) -> ~[u8] { self.buf }
    fn inner_ref<'a>(&'a self) -> &'a ~[u8] { &self.buf }
    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] { &mut self.buf }
}

/// Reads from an owned byte vector
pub struct MemReader {
    priv buf: ~[u8],
    priv pos: uint
}

impl MemReader {
    pub fn new(buf: ~[u8]) -> MemReader {
        MemReader {
            buf: buf,
            pos: 0
        }
    }
}

impl Reader for MemReader {
    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
        { if self.eof() { return None; } }

        let write_len = min(buf.len(), self.buf.len() - self.pos);
        {
            let input = self.buf.slice(self.pos, self.pos + write_len);
            let output = buf.mut_slice(0, write_len);
            assert_eq!(input.len(), output.len());
            vec::bytes::copy_memory(output, input, write_len);
        }
        self.pos += write_len;
        assert!(self.pos <= self.buf.len());

        return Some(write_len);
    }

    fn eof(&mut self) -> bool { self.pos == self.buf.len() }
}

impl Seek for MemReader {
    fn tell(&self) -> u64 { self.pos as u64 }
    fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
}

impl Buffer for MemReader {
    fn fill<'a>(&'a mut self) -> &'a [u8] { self.buf.slice_from(self.pos) }
    fn consume(&mut self, amt: uint) { self.pos += amt; }
}

impl Decorator<~[u8]> for MemReader {
    fn inner(self) -> ~[u8] { self.buf }
    fn inner_ref<'a>(&'a self) -> &'a ~[u8] { &self.buf }
    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] { &mut self.buf }
}

/// Writes to a fixed-size byte slice
///
/// If a write will not fit in the buffer, it raises the `io_error`
/// condition and does not write any data.
pub struct BufWriter<'self> {
    priv buf: &'self mut [u8],
    priv pos: uint
}

impl<'self> BufWriter<'self> {
    pub fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> {
        BufWriter {
            buf: buf,
            pos: 0
        }
    }
}

impl<'self> Writer for BufWriter<'self> {
    fn write(&mut self, buf: &[u8]) {
        // raises a condition if the entire write does not fit in the buffer
        let max_size = self.buf.len();
        if self.pos >= max_size || (self.pos + buf.len()) > max_size {
            io_error::cond.raise(IoError {
                kind: OtherIoError,
                desc: "Trying to write past end of buffer",
                detail: None
            });
            return;
        }

        vec::bytes::copy_memory(self.buf.mut_slice_from(self.pos),
                                buf, buf.len());
        self.pos += buf.len();
    }
}

// FIXME(#10432)
impl<'self> Seek for BufWriter<'self> {
    fn tell(&self) -> u64 { self.pos as u64 }

    fn seek(&mut self, pos: i64, style: SeekStyle) {
        // compute offset as signed and clamp to prevent overflow
        let offset = match style {
            SeekSet => { 0 }
            SeekEnd => { self.buf.len() }
            SeekCur => { self.pos }
        } as i64;

        self.pos = max(0, offset+pos) as uint;
    }
}

/// Reads from a fixed-size byte slice
pub struct BufReader<'self> {
    priv buf: &'self [u8],
    priv pos: uint
}

impl<'self> BufReader<'self> {
    pub fn new<'a>(buf: &'a [u8]) -> BufReader<'a> {
        BufReader {
            buf: buf,
            pos: 0
        }
    }
}

impl<'self> Reader for BufReader<'self> {
    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
        { if self.eof() { return None; } }

        let write_len = min(buf.len(), self.buf.len() - self.pos);
        {
            let input = self.buf.slice(self.pos, self.pos + write_len);
            let output = buf.mut_slice(0, write_len);
            assert_eq!(input.len(), output.len());
            vec::bytes::copy_memory(output, input, write_len);
        }
        self.pos += write_len;
        assert!(self.pos <= self.buf.len());

        return Some(write_len);
     }

    fn eof(&mut self) -> bool { self.pos == self.buf.len() }
}

impl<'self> Seek for BufReader<'self> {
    fn tell(&self) -> u64 { self.pos as u64 }

    fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
}

impl<'self> Buffer for BufReader<'self> {
    fn fill<'a>(&'a mut self) -> &'a [u8] { self.buf.slice_from(self.pos) }
    fn consume(&mut self, amt: uint) { self.pos += amt; }
}

///Calls a function with a MemWriter and returns
///the writer's stored vector.
pub fn with_mem_writer(writeFn: |&mut MemWriter|) -> ~[u8] {
    let mut writer = MemWriter::new();
    writeFn(&mut writer);
    writer.inner()
}

#[cfg(test)]
mod test {
    use prelude::*;
    use super::*;
    use io::*;

    #[test]
    fn test_mem_writer() {
        let mut writer = MemWriter::new();
        assert_eq!(writer.tell(), 0);
        writer.write([0]);
        assert_eq!(writer.tell(), 1);
        writer.write([1, 2, 3]);
        writer.write([4, 5, 6, 7]);
        assert_eq!(writer.tell(), 8);
        assert_eq!(*writer.inner_ref(), ~[0, 1, 2, 3, 4, 5, 6, 7]);

        writer.seek(0, SeekSet);
        assert_eq!(writer.tell(), 0);
        writer.write([3, 4]);
        assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 3, 4, 5, 6, 7]);

        writer.seek(1, SeekCur);
        writer.write([0, 1]);
        assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 0, 1, 5, 6, 7]);

        writer.seek(-1, SeekEnd);
        writer.write([1, 2]);
        assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 0, 1, 5, 6, 1, 2]);

        writer.seek(1, SeekEnd);
        writer.write([1]);
        assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]);
    }

    #[test]
    fn test_buf_writer() {
        let mut buf = [0 as u8, ..8];
        {
            let mut writer = BufWriter::new(buf);
            assert_eq!(writer.tell(), 0);
            writer.write([0]);
            assert_eq!(writer.tell(), 1);
            writer.write([1, 2, 3]);
            writer.write([4, 5, 6, 7]);
            assert_eq!(writer.tell(), 8);
        }
        assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7]);
    }

    #[test]
    fn test_buf_writer_seek() {
        let mut buf = [0 as u8, ..8];
        {
            let mut writer = BufWriter::new(buf);
            assert_eq!(writer.tell(), 0);
            writer.write([1]);
            assert_eq!(writer.tell(), 1);

            writer.seek(2, SeekSet);
            assert_eq!(writer.tell(), 2);
            writer.write([2]);
            assert_eq!(writer.tell(), 3);

            writer.seek(-2, SeekCur);
            assert_eq!(writer.tell(), 1);
            writer.write([3]);
            assert_eq!(writer.tell(), 2);

            writer.seek(-1, SeekEnd);
            assert_eq!(writer.tell(), 7);
            writer.write([4]);
            assert_eq!(writer.tell(), 8);

        }
        assert_eq!(buf, [1, 3, 2, 0, 0, 0, 0, 4]);
    }

    #[test]
    fn test_buf_writer_error() {
        let mut buf = [0 as u8, ..2];
        let mut writer = BufWriter::new(buf);
        writer.write([0]);

        let mut called = false;
        io_error::cond.trap(|err| {
            assert_eq!(err.kind, OtherIoError);
            called = true;
        }).inside(|| {
            writer.write([0, 0]);
        });
        assert!(called);
    }

    #[test]
    fn test_mem_reader() {
        let mut reader = MemReader::new(~[0, 1, 2, 3, 4, 5, 6, 7]);
        let mut buf = [];
        assert_eq!(reader.read(buf), Some(0));
        assert_eq!(reader.tell(), 0);
        let mut buf = [0];
        assert_eq!(reader.read(buf), Some(1));
        assert_eq!(reader.tell(), 1);
        assert_eq!(buf, [0]);
        let mut buf = [0, ..4];
        assert_eq!(reader.read(buf), Some(4));
        assert_eq!(reader.tell(), 5);
        assert_eq!(buf, [1, 2, 3, 4]);
        assert_eq!(reader.read(buf), Some(3));
        assert_eq!(buf.slice(0, 3), [5, 6, 7]);
        assert!(reader.eof());
        assert_eq!(reader.read(buf), None);
        assert!(reader.eof());
    }

    #[test]
    fn test_buf_reader() {
        let in_buf = ~[0, 1, 2, 3, 4, 5, 6, 7];
        let mut reader = BufReader::new(in_buf);
        let mut buf = [];
        assert_eq!(reader.read(buf), Some(0));
        assert_eq!(reader.tell(), 0);
        let mut buf = [0];
        assert_eq!(reader.read(buf), Some(1));
        assert_eq!(reader.tell(), 1);
        assert_eq!(buf, [0]);
        let mut buf = [0, ..4];
        assert_eq!(reader.read(buf), Some(4));
        assert_eq!(reader.tell(), 5);
        assert_eq!(buf, [1, 2, 3, 4]);
        assert_eq!(reader.read(buf), Some(3));
        assert_eq!(buf.slice(0, 3), [5, 6, 7]);
        assert!(reader.eof());
        assert_eq!(reader.read(buf), None);
        assert!(reader.eof());
    }

    #[test]
    fn test_with_mem_writer() {
        let buf = with_mem_writer(|wr| wr.write([1,2,3,4,5,6,7]));
        assert_eq!(buf, ~[1,2,3,4,5,6,7]);
    }

    #[test]
    fn test_read_char() {
        let mut r = BufReader::new(bytes!("Việt"));
        assert_eq!(r.read_char(), Some('V'));
        assert_eq!(r.read_char(), Some('i'));
        assert_eq!(r.read_char(), Some('ệ'));
        assert_eq!(r.read_char(), Some('t'));
        assert_eq!(r.read_char(), None);
    }

    #[test]
    fn test_read_bad_char() {
        let mut r = BufReader::new(bytes!(0x80));
        assert_eq!(r.read_char(), None);
    }
}
<|endoftext|>


<commit_before>pub use smithay::{
    backend::input::KeyState,
    desktop::{LayerSurface, PopupKind, Window},
    input::{
        keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
        pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerTarget},
        Seat,
    },
    reexports::wayland_server::{backend::ObjectId, protocol::wl_surface::WlSurface, Resource},
    utils::{IsAlive, Serial},
    wayland::seat::WaylandFocus,
};

use crate::state::AnvilState;

#[derive(Debug, Clone, PartialEq)]
pub enum FocusTarget {
    Window(Window),
    LayerSurface(LayerSurface),
    Popup(PopupKind),
}

impl IsAlive for FocusTarget {
    fn alive(&self) -> bool {
        match self {
            FocusTarget::Window(w) => w.alive(),
            FocusTarget::LayerSurface(l) => l.alive(),
            FocusTarget::Popup(p) => p.alive(),
        }
    }
}

impl From<FocusTarget> for WlSurface {
    fn from(target: FocusTarget) -> Self {
        target.wl_surface().unwrap()
    }
}

impl<Backend> PointerTarget<AnvilState<Backend>> for FocusTarget {
    fn enter(&self, seat: &Seat<AnvilState<Backend>>, data: &mut AnvilState<Backend>, event: &MotionEvent) {
        match self {
            FocusTarget::Window(w) => PointerTarget::enter(w, seat, data, event),
            FocusTarget::LayerSurface(l) => PointerTarget::enter(l.wl_surface(), seat, data, event),
            FocusTarget::Popup(p) => PointerTarget::enter(p.wl_surface(), seat, data, event),
        }
    }
    fn motion(&self, seat: &Seat<AnvilState<Backend>>, data: &mut AnvilState<Backend>, event: &MotionEvent) {
        match self {
            FocusTarget::Window(w) => PointerTarget::motion(w, seat, data, event),
            FocusTarget::LayerSurface(l) => PointerTarget::motion(l.wl_surface(), seat, data, event),
            FocusTarget::Popup(p) => PointerTarget::motion(p.wl_surface(), seat, data, event),
        }
    }
    fn button(&self, seat: &Seat<AnvilState<Backend>>, data: &mut AnvilState<Backend>, event: &ButtonEvent) {
        match self {
            FocusTarget::Window(w) => PointerTarget::button(w, seat, data, event),
            FocusTarget::LayerSurface(l) => PointerTarget::button(l.wl_surface(), seat, data, event),
            FocusTarget::Popup(p) => PointerTarget::button(p.wl_surface(), seat, data, event),
        }
    }
    fn axis(&self, seat: &Seat<AnvilState<Backend>>, data: &mut AnvilState<Backend>, frame: AxisFrame) {
        match self {
            FocusTarget::Window(w) => PointerTarget::axis(w, seat, data, frame),
            FocusTarget::LayerSurface(l) => PointerTarget::axis(l.wl_surface(), seat, data, frame),
            FocusTarget::Popup(p) => PointerTarget::axis(p.wl_surface(), seat, data, frame),
        }
    }
    fn leave(
        &self,
        seat: &Seat<AnvilState<Backend>>,
        data: &mut AnvilState<Backend>,
        serial: Serial,
        time: u32,
    ) {
        match self {
            FocusTarget::Window(w) => PointerTarget::leave(w, seat, data, serial, time),
            FocusTarget::LayerSurface(l) => PointerTarget::leave(l.wl_surface(), seat, data, serial, time),
            FocusTarget::Popup(p) => PointerTarget::leave(p.wl_surface(), seat, data, serial, time),
        }
    }
}

impl<Backend> KeyboardTarget<AnvilState<Backend>> for FocusTarget {
    fn enter(
        &self,
        seat: &Seat<AnvilState<Backend>>,
        data: &mut AnvilState<Backend>,
        keys: Vec<KeysymHandle<'_>>,
        serial: Serial,
    ) {
        match self {
            FocusTarget::Window(w) => KeyboardTarget::enter(w, seat, data, keys, serial),
            FocusTarget::LayerSurface(l) => KeyboardTarget::enter(l.wl_surface(), seat, data, keys, serial),
            FocusTarget::Popup(p) => KeyboardTarget::enter(p.wl_surface(), seat, data, keys, serial),
        }
    }
    fn leave(&self, seat: &Seat<AnvilState<Backend>>, data: &mut AnvilState<Backend>, serial: Serial) {
        match self {
            FocusTarget::Window(w) => KeyboardTarget::leave(w, seat, data, serial),
            FocusTarget::LayerSurface(l) => KeyboardTarget::leave(l.wl_surface(), seat, data, serial),
            FocusTarget::Popup(p) => KeyboardTarget::leave(p.wl_surface(), seat, data, serial),
        }
    }
    fn key(
        &self,
        seat: &Seat<AnvilState<Backend>>,
        data: &mut AnvilState<Backend>,
        key: KeysymHandle<'_>,
        state: KeyState,
        serial: Serial,
        time: u32,
    ) {
        match self {
            FocusTarget::Window(w) => KeyboardTarget::key(w, seat, data, key, state, serial, time),
            FocusTarget::LayerSurface(l) => {
                KeyboardTarget::key(l.wl_surface(), seat, data, key, state, serial, time)
            }
            FocusTarget::Popup(p) => {
                KeyboardTarget::key(p.wl_surface(), seat, data, key, state, serial, time)
            }
        }
    }
    fn modifiers(
        &self,
        seat: &Seat<AnvilState<Backend>>,
        data: &mut AnvilState<Backend>,
        modifiers: ModifiersState,
        serial: Serial,
    ) {
        match self {
            FocusTarget::Window(w) => KeyboardTarget::modifiers(w, seat, data, modifiers, serial),
            FocusTarget::LayerSurface(l) => {
                KeyboardTarget::modifiers(l.wl_surface(), seat, data, modifiers, serial)
            }
            FocusTarget::Popup(p) => KeyboardTarget::modifiers(p.wl_surface(), seat, data, modifiers, serial),
        }
    }
}

impl WaylandFocus for FocusTarget {
    fn wl_surface(&self) -> Option<WlSurface> {
        Some(match self {
            FocusTarget::Window(w) => w.toplevel().wl_surface().clone(),
            FocusTarget::LayerSurface(l) => l.wl_surface().clone(),
            FocusTarget::Popup(p) => p.wl_surface().clone(),
        })
    }
    fn same_client_as(&self, object_id: &ObjectId) -> bool {
        match self {
            FocusTarget::Window(w) => w.toplevel().wl_surface().id().same_client_as(object_id),
            FocusTarget::LayerSurface(l) => l.wl_surface().id().same_client_as(object_id),
            FocusTarget::Popup(p) => p.wl_surface().id().same_client_as(object_id),
        }
    }
}

impl From<Window> for FocusTarget {
    fn from(w: Window) -> Self {
        FocusTarget::Window(w)
    }
}

impl From<LayerSurface> for FocusTarget {
    fn from(l: LayerSurface) -> Self {
        FocusTarget::LayerSurface(l)
    }
}

impl From<PopupKind> for FocusTarget {
    fn from(p: PopupKind) -> Self {
        FocusTarget::Popup(p)
    }
}
<commit_msg>anvil: Dispatch input events into layer surfacetree<commit_after>pub use smithay::{
    backend::input::KeyState,
    desktop::{LayerSurface, PopupKind, Window},
    input::{
        keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
        pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerTarget},
        Seat,
    },
    reexports::wayland_server::{backend::ObjectId, protocol::wl_surface::WlSurface, Resource},
    utils::{IsAlive, Serial},
    wayland::seat::WaylandFocus,
};

use crate::state::AnvilState;

#[derive(Debug, Clone, PartialEq)]
pub enum FocusTarget {
    Window(Window),
    LayerSurface(LayerSurface),
    Popup(PopupKind),
}

impl IsAlive for FocusTarget {
    fn alive(&self) -> bool {
        match self {
            FocusTarget::Window(w) => w.alive(),
            FocusTarget::LayerSurface(l) => l.alive(),
            FocusTarget::Popup(p) => p.alive(),
        }
    }
}

impl From<FocusTarget> for WlSurface {
    fn from(target: FocusTarget) -> Self {
        target.wl_surface().unwrap()
    }
}

impl<Backend> PointerTarget<AnvilState<Backend>> for FocusTarget {
    fn enter(&self, seat: &Seat<AnvilState<Backend>>, data: &mut AnvilState<Backend>, event: &MotionEvent) {
        match self {
            FocusTarget::Window(w) => PointerTarget::enter(w, seat, data, event),
            FocusTarget::LayerSurface(l) => PointerTarget::enter(l, seat, data, event),
            FocusTarget::Popup(p) => PointerTarget::enter(p.wl_surface(), seat, data, event),
        }
    }
    fn motion(&self, seat: &Seat<AnvilState<Backend>>, data: &mut AnvilState<Backend>, event: &MotionEvent) {
        match self {
            FocusTarget::Window(w) => PointerTarget::motion(w, seat, data, event),
            FocusTarget::LayerSurface(l) => PointerTarget::motion(l, seat, data, event),
            FocusTarget::Popup(p) => PointerTarget::motion(p.wl_surface(), seat, data, event),
        }
    }
    fn button(&self, seat: &Seat<AnvilState<Backend>>, data: &mut AnvilState<Backend>, event: &ButtonEvent) {
        match self {
            FocusTarget::Window(w) => PointerTarget::button(w, seat, data, event),
            FocusTarget::LayerSurface(l) => PointerTarget::button(l, seat, data, event),
            FocusTarget::Popup(p) => PointerTarget::button(p.wl_surface(), seat, data, event),
        }
    }
    fn axis(&self, seat: &Seat<AnvilState<Backend>>, data: &mut AnvilState<Backend>, frame: AxisFrame) {
        match self {
            FocusTarget::Window(w) => PointerTarget::axis(w, seat, data, frame),
            FocusTarget::LayerSurface(l) => PointerTarget::axis(l, seat, data, frame),
            FocusTarget::Popup(p) => PointerTarget::axis(p.wl_surface(), seat, data, frame),
        }
    }
    fn leave(
        &self,
        seat: &Seat<AnvilState<Backend>>,
        data: &mut AnvilState<Backend>,
        serial: Serial,
        time: u32,
    ) {
        match self {
            FocusTarget::Window(w) => PointerTarget::leave(w, seat, data, serial, time),
            FocusTarget::LayerSurface(l) => PointerTarget::leave(l, seat, data, serial, time),
            FocusTarget::Popup(p) => PointerTarget::leave(p.wl_surface(), seat, data, serial, time),
        }
    }
}

impl<Backend> KeyboardTarget<AnvilState<Backend>> for FocusTarget {
    fn enter(
        &self,
        seat: &Seat<AnvilState<Backend>>,
        data: &mut AnvilState<Backend>,
        keys: Vec<KeysymHandle<'_>>,
        serial: Serial,
    ) {
        match self {
            FocusTarget::Window(w) => KeyboardTarget::enter(w, seat, data, keys, serial),
            FocusTarget::LayerSurface(l) => KeyboardTarget::enter(l, seat, data, keys, serial),
            FocusTarget::Popup(p) => KeyboardTarget::enter(p.wl_surface(), seat, data, keys, serial),
        }
    }
    fn leave(&self, seat: &Seat<AnvilState<Backend>>, data: &mut AnvilState<Backend>, serial: Serial) {
        match self {
            FocusTarget::Window(w) => KeyboardTarget::leave(w, seat, data, serial),
            FocusTarget::LayerSurface(l) => KeyboardTarget::leave(l, seat, data, serial),
            FocusTarget::Popup(p) => KeyboardTarget::leave(p.wl_surface(), seat, data, serial),
        }
    }
    fn key(
        &self,
        seat: &Seat<AnvilState<Backend>>,
        data: &mut AnvilState<Backend>,
        key: KeysymHandle<'_>,
        state: KeyState,
        serial: Serial,
        time: u32,
    ) {
        match self {
            FocusTarget::Window(w) => KeyboardTarget::key(w, seat, data, key, state, serial, time),
            FocusTarget::LayerSurface(l) => KeyboardTarget::key(l, seat, data, key, state, serial, time),
            FocusTarget::Popup(p) => {
                KeyboardTarget::key(p.wl_surface(), seat, data, key, state, serial, time)
            }
        }
    }
    fn modifiers(
        &self,
        seat: &Seat<AnvilState<Backend>>,
        data: &mut AnvilState<Backend>,
        modifiers: ModifiersState,
        serial: Serial,
    ) {
        match self {
            FocusTarget::Window(w) => KeyboardTarget::modifiers(w, seat, data, modifiers, serial),
            FocusTarget::LayerSurface(l) => KeyboardTarget::modifiers(l, seat, data, modifiers, serial),
            FocusTarget::Popup(p) => KeyboardTarget::modifiers(p.wl_surface(), seat, data, modifiers, serial),
        }
    }
}

impl WaylandFocus for FocusTarget {
    fn wl_surface(&self) -> Option<WlSurface> {
        Some(match self {
            FocusTarget::Window(w) => w.toplevel().wl_surface().clone(),
            FocusTarget::LayerSurface(l) => l.wl_surface().clone(),
            FocusTarget::Popup(p) => p.wl_surface().clone(),
        })
    }
    fn same_client_as(&self, object_id: &ObjectId) -> bool {
        match self {
            FocusTarget::Window(w) => w.toplevel().wl_surface().id().same_client_as(object_id),
            FocusTarget::LayerSurface(l) => l.wl_surface().id().same_client_as(object_id),
            FocusTarget::Popup(p) => p.wl_surface().id().same_client_as(object_id),
        }
    }
}

impl From<Window> for FocusTarget {
    fn from(w: Window) -> Self {
        FocusTarget::Window(w)
    }
}

impl From<LayerSurface> for FocusTarget {
    fn from(l: LayerSurface) -> Self {
        FocusTarget::LayerSurface(l)
    }
}

impl From<PopupKind> for FocusTarget {
    fn from(p: PopupKind) -> Self {
        FocusTarget::Popup(p)
    }
}
<|endoftext|>


<commit_before>use rna_transcription as dna;

#[test]
fn test_valid_dna_input() {
    assert!(dna::DNA::new("GCTA").is_ok());
}

#[test]
#[ignore]
fn test_valid_rna_input() {
    assert!(dna::RNA::new("CGAU").is_ok());
}

#[test]
#[ignore]
fn test_invalid_dna_input() {
    // Invalid character
    assert_eq!(dna::DNA::new("X").err(), Some(0));
    // Valid nucleotide, but invalid in context
    assert_eq!(dna::DNA::new("U").err(), Some(0));
    // Longer string with contained errors
    assert_eq!(dna::DNA::new("ACGTUXXCTTAA").err(), Some(4));
}

#[test]
#[ignore]
fn test_invalid_rna_input() {
    // Invalid character
    assert!(dna::RNA::new("X").is_err());
    // Valid nucleotide, but invalid in context
    assert!(dna::RNA::new("T").is_err());
    // Longer string with contained errors
    assert!(dna::RNA::new("ACGUTTXCUUAA").is_err());
}

#[test]
#[ignore]
fn test_acid_equals_acid() {
    assert_eq!(dna::DNA::new("CGA").unwrap(), dna::DNA::new("CGA").unwrap());
    assert_ne!(dna::DNA::new("CGA").unwrap(), dna::DNA::new("AGC").unwrap());
    assert_eq!(dna::RNA::new("CGA").unwrap(), dna::RNA::new("CGA").unwrap());
    assert_ne!(dna::RNA::new("CGA").unwrap(), dna::RNA::new("AGC").unwrap());
}

#[test]
#[ignore]
fn test_transcribes_cytosine_guanine() {
    assert_eq!(
        dna::RNA::new("G").unwrap(),
        dna::DNA::new("C").unwrap().into_rna()
    );
}

#[test]
#[ignore]
fn test_transcribes_guanine_cytosine() {
    assert_eq!(
        dna::RNA::new("C").unwrap(),
        dna::DNA::new("G").unwrap().into_rna()
    );
}

#[test]
#[ignore]
fn test_transcribes_adenine_uracil() {
    assert_eq!(
        dna::RNA::new("U").unwrap(),
        dna::DNA::new("A").unwrap().into_rna()
    );
}

#[test]
#[ignore]
fn test_transcribes_thymine_to_adenine() {
    assert_eq!(
        dna::RNA::new("A").unwrap(),
        dna::DNA::new("T").unwrap().into_rna()
    );
}

#[test]
#[ignore]
fn test_transcribes_all_dna_to_rna() {
    assert_eq!(
        dna::RNA::new("UGCACCAGAAUU").unwrap(),
        dna::DNA::new("ACGTGGTCTTAA").unwrap().into_rna()
    )
}
<commit_msg>rna-transcription: avoid using assert!(something().is_err()) (#972)<commit_after>use rna_transcription as dna;

#[test]
fn test_valid_dna_input() {
    assert!(dna::DNA::new("GCTA").is_ok());
}

#[test]
#[ignore]
fn test_valid_rna_input() {
    assert!(dna::RNA::new("CGAU").is_ok());
}

#[test]
#[ignore]
fn test_invalid_dna_input() {
    // Invalid character
    assert_eq!(dna::DNA::new("X").err(), Some(0));
    // Valid nucleotide, but invalid in context
    assert_eq!(dna::DNA::new("U").err(), Some(0));
    // Longer string with contained errors
    assert_eq!(dna::DNA::new("ACGTUXXCTTAA").err(), Some(4));
}

#[test]
#[ignore]
fn test_invalid_rna_input() {
    // Invalid character
    assert_eq!(dna::RNA::new("X").unwrap_err(), 0);
    // Valid nucleotide, but invalid in context
    assert_eq!(dna::RNA::new("T").unwrap_err(), 0);
    // Longer string with contained errors
    assert_eq!(dna::RNA::new("ACGUTTXCUUAA").unwrap_err(), 4);
}

#[test]
#[ignore]
fn test_acid_equals_acid() {
    assert_eq!(dna::DNA::new("CGA").unwrap(), dna::DNA::new("CGA").unwrap());
    assert_ne!(dna::DNA::new("CGA").unwrap(), dna::DNA::new("AGC").unwrap());
    assert_eq!(dna::RNA::new("CGA").unwrap(), dna::RNA::new("CGA").unwrap());
    assert_ne!(dna::RNA::new("CGA").unwrap(), dna::RNA::new("AGC").unwrap());
}

#[test]
#[ignore]
fn test_transcribes_cytosine_guanine() {
    assert_eq!(
        dna::RNA::new("G").unwrap(),
        dna::DNA::new("C").unwrap().into_rna()
    );
}

#[test]
#[ignore]
fn test_transcribes_guanine_cytosine() {
    assert_eq!(
        dna::RNA::new("C").unwrap(),
        dna::DNA::new("G").unwrap().into_rna()
    );
}

#[test]
#[ignore]
fn test_transcribes_adenine_uracil() {
    assert_eq!(
        dna::RNA::new("U").unwrap(),
        dna::DNA::new("A").unwrap().into_rna()
    );
}

#[test]
#[ignore]
fn test_transcribes_thymine_to_adenine() {
    assert_eq!(
        dna::RNA::new("A").unwrap(),
        dna::DNA::new("T").unwrap().into_rna()
    );
}

#[test]
#[ignore]
fn test_transcribes_all_dna_to_rna() {
    assert_eq!(
        dna::RNA::new("UGCACCAGAAUU").unwrap(),
        dna::DNA::new("ACGTGGTCTTAA").unwrap().into_rna()
    )
}
<|endoftext|>


<commit_before>use std::hash;
use std::collections::HashMap;
use std::ops::Deref;
use image::{self, GenericImage};
use euclid::{Point2D, Rect, Size2D};
use vitral;
use calx_resource::{Loadable, Resource, ResourceStore};
use calx_color::Rgba;
use calx_color::color::*;

// XXX: This module is a bit awkward fit to the world crate, which we generally want to keep
// rendering method agnostic. However, world-level types with a visual representation hold on to a
// Brush Resource to represent it, so they need to be exposed to the brush type.

#[derive(Clone)]
struct DynamicImageShim(image::DynamicImage);

impl Loadable for DynamicImageShim {
    fn load(key: &String) -> Option<Self>
        where Self: Sized
    {
        image::open(key).ok().map(|x| DynamicImageShim(x))
    }
}

impl_store!(DYNAMIC_IMAGE, String, DynamicImageShim);

pub type Color = [f32; 4];

pub type ImageRef = usize;

#[derive(Copy, Clone, Debug)]
pub struct Splat {
    pub image: ImageRef,
    pub offset: Point2D<f32>,
    pub color: Color,
}

pub type Frame = Vec<Splat>;

#[derive(Clone)]
pub struct Brush(pub Vec<Frame>);

impl Deref for Brush {
    type Target = Vec<Frame>;

    #[inline(always)]
    fn deref(&self) -> &Vec<Frame> {
        &self.0
    }
}

// Brush implements Loadable so we can have a cache for it, but there's no actual implicit load
// method, brushes must be inserted manually in code.
//
// (We *could* make a load method later and have it read configuration files or something that
// specify te brush.)
impl Loadable for Brush {}

impl_store!(BRUSH, String, Brush);

type SplatImage = image::ImageBuffer<image::Rgba<u8>, Vec<u8>>;

#[derive(Clone, PartialEq, Eq, Debug)]
struct SubImageSpec {
    image: Resource<DynamicImageShim>,
    bounds: Rect<u32>,
}

impl SubImageSpec {
    pub fn new(path: String, bounds: Rect<u32>) -> Option<SubImageSpec> {
        if let Some(image) = Resource::new(path) {
            Some(SubImageSpec {
                image: image,
                bounds: bounds,
            })
        } else {
            None
        }
    }
}

impl Loadable<SubImageSpec> for SplatImage {
    fn load(spec: &SubImageSpec) -> Option<Self>
        where Self: Sized
    {
        // XXX: Using sub_image on spec.image would be neater, but can't use it here
        // because current image::SubImage must get a mutable access to the parent image and the
        // resource handle is immutable.
        Some(image::ImageBuffer::from_fn(spec.bounds.size.width, spec.bounds.size.height, |x, y| {
            spec.image.0.get_pixel(spec.bounds.origin.x + x, spec.bounds.origin.y + y)
        }))
    }
}

impl hash::Hash for SubImageSpec {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.image.hash(state);
        self.bounds.origin.hash(state);
        self.bounds.size.hash(state);
    }
}

impl_store!(SPLAT_IMAGE, SubImageSpec, SplatImage);

pub struct BrushBuilder<'a, V: 'a> {
    builder: &'a mut vitral::Builder<V>,
    image_file: Option<String>,
    brush: Vec<Frame>,
    splat_images: HashMap<SubImageSpec, usize>,
    color: Rgba,
}

impl<'a, V: Copy + Eq + 'a> BrushBuilder<'a, V> {
    pub fn new(builder: &'a mut vitral::Builder<V>) -> BrushBuilder<'a, V> {
        BrushBuilder {
            builder: builder,
            image_file: None,
            brush: Vec::new(),
            splat_images: HashMap::new(),
            color: WHITE,
        }
    }

    pub fn file(mut self, name: &str) -> Self {
        self.image_file = Some(name.to_string());
        self
    }

    fn get_splat(&mut self, key: &SubImageSpec) -> usize {
        // XXX: Crashy-crash unwrapping if you feed it bad data.
        if let Some(ret) = self.splat_images.get(key) {
            return *ret;
        }

        let image: Resource<SplatImage, SubImageSpec> = Resource::new(key.clone()).unwrap();
        let ret = self.builder.add_image(&*image);

        self.splat_images.insert(key.clone(), ret);

        ret
    }

    /// Add a new splat with the given bounding rectangle to the current frame.
    pub fn splat(mut self, x: u32, y: u32, w: u32, h: u32) -> Self {
        if self.brush.is_empty() {
            self.brush.push(Vec::new());
        }
        let filename = self.image_file.clone().expect("Image file not set");
        let spec = SubImageSpec::new(filename, Rect::new(Point2D::new(x, y), Size2D::new(w, h)))
                       .unwrap();

        let image = self.get_splat(&spec);

        let idx = self.brush.len() - 1;
        self.brush[idx].push(Splat {
            image: image,
            offset: Point2D::new(0.0, 0.0),
            color: [self.color.r, self.color.g, self.color.b, self.color.a],
        });

        self
    }

    /// Set the color for the next splats.
    pub fn color<C: Into<Rgba>>(mut self, c: C) -> Self {
        self.color = c.into();
        self
    }

    /// Set the offset of the last splat.
    pub fn offset(mut self, x: i32, y: i32) -> Self {
        assert!(!self.brush.is_empty());
        let i = self.brush.len() - 1;
        assert!(!self.brush[i].is_empty());
        let j = self.brush[i].len() - 1;

        // Internally offset is floats because all screen geometry stuff is, but on the data spec
        // level we're pretty much operating on per-pixel level.
        self.brush[i][j].offset = Point2D::new(x as f32, y as f32);

        self
    }

    /// Helper for regular tiles.
    pub fn tile(self, x: u32, y: u32) -> Self {
        self.splat(x, y, 32, 32).offset(16, 16)
    }

    /// Helper for blob chunks.
    ///
    /// Blobs are built from three 96x32 strips. First one contains the vertical edges, the second
    /// contains the rear blob and the third contains the blob front. The vertical and rear
    /// frames are nondescript and will probably be reused extensively.
    ///
    /// Blob shaping is somewhat complicated and requires a large number of frames.
    pub fn blob(self, vert_x: u32, vert_y: u32, rear_x: u32, rear_y: u32, x: u32, y: u32) -> Self {
        self.splat(vert_x, vert_y, 16, 32).offset(16, 16)               // 0: Top left
            .frame().splat(vert_x + 16, vert_y, 16, 32).offset(0, 16)   // 1: Top right
            .frame().splat(vert_x + 32, vert_y, 16, 32).offset(16, 16)  // 2: Middle left
            .frame().splat(vert_x + 48, vert_y, 16, 32).offset(0, 16)   // 3: Middle right
            .frame().splat(vert_x + 64, vert_y, 16, 32).offset(16, 16)  // 4: Bottom left
            .frame().splat(vert_x + 80, vert_y, 16, 32).offset(0, 16)   // 5: Bottom right

            .frame().splat(rear_x, rear_y, 10, 32).offset(16, 16)       // 6: Left half

            .frame().splat(rear_x + 10, rear_y, 6, 32).offset(6, 16)    // 7: Front
            .frame().splat(rear_x + 16, rear_y, 6, 32).offset(0, 16)    // 8

            .frame().splat(rear_x + 22, rear_y, 10, 32).offset(-6, 16)  // 9: Right half

            .frame().splat(rear_x + 32, rear_y, 10, 32).offset(16, 16)  // 10: Y-axis slope
            .frame().splat(rear_x + 42, rear_y, 6, 32).offset(6, 16)    // 11
            .frame().splat(rear_x + 48, rear_y, 6, 32).offset(0, 16)    // 12
            .frame().splat(rear_x + 54, rear_y, 10, 32).offset(-6, 16)  // 13

            .frame().splat(rear_x + 64, rear_y, 10, 32).offset(16, 16)  // 14: X-axis slope
            .frame().splat(rear_x + 74, rear_y, 6, 32).offset(6, 16)    // 15
            .frame().splat(rear_x + 80, rear_y, 6, 32).offset(0, 16)    // 16
            .frame().splat(rear_x + 86, rear_y, 10, 32).offset(-6, 16)  // 17

            .frame().splat(x, y, 10, 32).offset(16, 16)                 // 18 Left half

            .frame().splat(x + 10, y, 6, 32).offset(6, 16)              // 19: Front
            .frame().splat(x + 16, y, 6, 32).offset(0, 16)              // 20

            .frame().splat(x + 22, y, 10, 32).offset(-6, 16)            // 21: Right half

            .frame().splat(x + 32, y, 10, 32).offset(16, 16)            // 22: Y-axis slope
            .frame().splat(x + 42, y, 6, 32).offset(6, 16)              // 23
            .frame().splat(x + 48, y, 6, 32).offset(0, 16)              // 24
            .frame().splat(x + 54, y, 10, 32).offset(-6, 16)            // 25

            .frame().splat(x + 64, y, 10, 32).offset(16, 16)            // 26: X-axis slope
            .frame().splat(x + 74, y, 6, 32).offset(6, 16)              // 27
            .frame().splat(x + 80, y, 6, 32).offset(0, 16)              // 28
            .frame().splat(x + 86, y, 10, 32).offset(-6, 16)            // 29
    }

    /// Helper for wall tiles
    ///
    /// Wall tiles are chopped up from two 32x32 images. One contains the center pillar wallform
    /// and the other contains the two long sides wallform.
    pub fn wall(self, center_x: u32, center_y: u32, sides_x: u32, sides_y: u32) -> Self {
        self.splat(center_x, center_y, 16, 32).offset(16, 16)
            .frame().splat(center_x + 16, center_y, 16, 32).offset(0, 16)
            .frame().splat(sides_x, sides_y, 16, 32).offset(16, 16)
            .frame().splat(sides_x + 16, sides_y, 16, 32).offset(0, 16)
    }

    /// Start a new frame in the current brush.
    pub fn frame(mut self) -> Self {
        self.brush.push(Vec::new());
        self
    }

    /// Finish and name the current brush and start a new one.
    pub fn brush(mut self, name: &str) -> Self {
        use std::mem;

        let name = name.to_string();
        // Must be an original name.
        assert!(Brush::get_resource(&name).is_none());

        // Zero cached brush and copy the old value here so we can insert it.
        let mut brush = Vec::new();
        mem::swap(&mut brush, &mut self.brush);
        assert!(!brush.is_empty());

        Brush::insert_resource(name, Brush(brush));

        // Reset color
        self.color = WHITE;

        self
    }
}
<commit_msg>Blob brush annotation<commit_after>use std::hash;
use std::collections::HashMap;
use std::ops::Deref;
use image::{self, GenericImage};
use euclid::{Point2D, Rect, Size2D};
use vitral;
use calx_resource::{Loadable, Resource, ResourceStore};
use calx_color::Rgba;
use calx_color::color::*;

// XXX: This module is a bit awkward fit to the world crate, which we generally want to keep
// rendering method agnostic. However, world-level types with a visual representation hold on to a
// Brush Resource to represent it, so they need to be exposed to the brush type.

#[derive(Clone)]
struct DynamicImageShim(image::DynamicImage);

impl Loadable for DynamicImageShim {
    fn load(key: &String) -> Option<Self>
        where Self: Sized
    {
        image::open(key).ok().map(|x| DynamicImageShim(x))
    }
}

impl_store!(DYNAMIC_IMAGE, String, DynamicImageShim);

pub type Color = [f32; 4];

pub type ImageRef = usize;

#[derive(Copy, Clone, Debug)]
pub struct Splat {
    pub image: ImageRef,
    pub offset: Point2D<f32>,
    pub color: Color,
}

pub type Frame = Vec<Splat>;

#[derive(Clone)]
pub struct Brush(pub Vec<Frame>);

impl Deref for Brush {
    type Target = Vec<Frame>;

    #[inline(always)]
    fn deref(&self) -> &Vec<Frame> {
        &self.0
    }
}

// Brush implements Loadable so we can have a cache for it, but there's no actual implicit load
// method, brushes must be inserted manually in code.
//
// (We *could* make a load method later and have it read configuration files or something that
// specify te brush.)
impl Loadable for Brush {}

impl_store!(BRUSH, String, Brush);

type SplatImage = image::ImageBuffer<image::Rgba<u8>, Vec<u8>>;

#[derive(Clone, PartialEq, Eq, Debug)]
struct SubImageSpec {
    image: Resource<DynamicImageShim>,
    bounds: Rect<u32>,
}

impl SubImageSpec {
    pub fn new(path: String, bounds: Rect<u32>) -> Option<SubImageSpec> {
        if let Some(image) = Resource::new(path) {
            Some(SubImageSpec {
                image: image,
                bounds: bounds,
            })
        } else {
            None
        }
    }
}

impl Loadable<SubImageSpec> for SplatImage {
    fn load(spec: &SubImageSpec) -> Option<Self>
        where Self: Sized
    {
        // XXX: Using sub_image on spec.image would be neater, but can't use it here
        // because current image::SubImage must get a mutable access to the parent image and the
        // resource handle is immutable.
        Some(image::ImageBuffer::from_fn(spec.bounds.size.width, spec.bounds.size.height, |x, y| {
            spec.image.0.get_pixel(spec.bounds.origin.x + x, spec.bounds.origin.y + y)
        }))
    }
}

impl hash::Hash for SubImageSpec {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.image.hash(state);
        self.bounds.origin.hash(state);
        self.bounds.size.hash(state);
    }
}

impl_store!(SPLAT_IMAGE, SubImageSpec, SplatImage);

pub struct BrushBuilder<'a, V: 'a> {
    builder: &'a mut vitral::Builder<V>,
    image_file: Option<String>,
    brush: Vec<Frame>,
    splat_images: HashMap<SubImageSpec, usize>,
    color: Rgba,
}

impl<'a, V: Copy + Eq + 'a> BrushBuilder<'a, V> {
    pub fn new(builder: &'a mut vitral::Builder<V>) -> BrushBuilder<'a, V> {
        BrushBuilder {
            builder: builder,
            image_file: None,
            brush: Vec::new(),
            splat_images: HashMap::new(),
            color: WHITE,
        }
    }

    pub fn file(mut self, name: &str) -> Self {
        self.image_file = Some(name.to_string());
        self
    }

    fn get_splat(&mut self, key: &SubImageSpec) -> usize {
        // XXX: Crashy-crash unwrapping if you feed it bad data.
        if let Some(ret) = self.splat_images.get(key) {
            return *ret;
        }

        let image: Resource<SplatImage, SubImageSpec> = Resource::new(key.clone()).unwrap();
        let ret = self.builder.add_image(&*image);

        self.splat_images.insert(key.clone(), ret);

        ret
    }

    /// Add a new splat with the given bounding rectangle to the current frame.
    pub fn splat(mut self, x: u32, y: u32, w: u32, h: u32) -> Self {
        if self.brush.is_empty() {
            self.brush.push(Vec::new());
        }
        let filename = self.image_file.clone().expect("Image file not set");
        let spec = SubImageSpec::new(filename, Rect::new(Point2D::new(x, y), Size2D::new(w, h)))
                       .unwrap();

        let image = self.get_splat(&spec);

        let idx = self.brush.len() - 1;
        self.brush[idx].push(Splat {
            image: image,
            offset: Point2D::new(0.0, 0.0),
            color: [self.color.r, self.color.g, self.color.b, self.color.a],
        });

        self
    }

    /// Set the color for the next splats.
    pub fn color<C: Into<Rgba>>(mut self, c: C) -> Self {
        self.color = c.into();
        self
    }

    /// Set the offset of the last splat.
    pub fn offset(mut self, x: i32, y: i32) -> Self {
        assert!(!self.brush.is_empty());
        let i = self.brush.len() - 1;
        assert!(!self.brush[i].is_empty());
        let j = self.brush[i].len() - 1;

        // Internally offset is floats because all screen geometry stuff is, but on the data spec
        // level we're pretty much operating on per-pixel level.
        self.brush[i][j].offset = Point2D::new(x as f32, y as f32);

        self
    }

    /// Helper for regular tiles.
    pub fn tile(self, x: u32, y: u32) -> Self {
        self.splat(x, y, 32, 32).offset(16, 16)
    }

    /// Helper for blob chunks.
    ///
    /// Blobs are built from three 96x32 strips. First one contains the vertical edges, the second
    /// contains the rear blob and the third contains the blob front. The vertical and rear
    /// frames are nondescript and will probably be reused extensively.
    ///
    /// Blob shaping is somewhat complicated and requires a large number of frames.
    pub fn blob(self, vert_x: u32, vert_y: u32, rear_x: u32, rear_y: u32, x: u32, y: u32) -> Self {
        self.splat(vert_x, vert_y, 16, 32).offset(16, 16)               // 0: Top left    VERTICAL SIDES
            .frame().splat(vert_x + 16, vert_y, 16, 32).offset(0, 16)   // 1: Top right
            .frame().splat(vert_x + 32, vert_y, 16, 32).offset(16, 16)  // 2: Middle left
            .frame().splat(vert_x + 48, vert_y, 16, 32).offset(0, 16)   // 3: Middle right
            .frame().splat(vert_x + 64, vert_y, 16, 32).offset(16, 16)  // 4: Bottom left
            .frame().splat(vert_x + 80, vert_y, 16, 32).offset(0, 16)   // 5: Bottom right

            .frame().splat(rear_x, rear_y, 10, 32).offset(16, 16)       // 6: Left half       REAR PARTS

            .frame().splat(rear_x + 10, rear_y, 6, 32).offset(6, 16)    // 7: Front
            .frame().splat(rear_x + 16, rear_y, 6, 32).offset(0, 16)    // 8

            .frame().splat(rear_x + 22, rear_y, 10, 32).offset(-6, 16)  // 9: Right half

            .frame().splat(rear_x + 32, rear_y, 10, 32).offset(16, 16)  // 10: Y-axis slope
            .frame().splat(rear_x + 42, rear_y, 6, 32).offset(6, 16)    // 11
            .frame().splat(rear_x + 48, rear_y, 6, 32).offset(0, 16)    // 12
            .frame().splat(rear_x + 54, rear_y, 10, 32).offset(-6, 16)  // 13

            .frame().splat(rear_x + 64, rear_y, 10, 32).offset(16, 16)  // 14: X-axis slope
            .frame().splat(rear_x + 74, rear_y, 6, 32).offset(6, 16)    // 15
            .frame().splat(rear_x + 80, rear_y, 6, 32).offset(0, 16)    // 16
            .frame().splat(rear_x + 86, rear_y, 10, 32).offset(-6, 16)  // 17

            .frame().splat(x, y, 10, 32).offset(16, 16)                 // 18 Left half      FRONT PARTS

            .frame().splat(x + 10, y, 6, 32).offset(6, 16)              // 19: Front
            .frame().splat(x + 16, y, 6, 32).offset(0, 16)              // 20

            .frame().splat(x + 22, y, 10, 32).offset(-6, 16)            // 21: Right half

            .frame().splat(x + 32, y, 10, 32).offset(16, 16)            // 22: Y-axis slope
            .frame().splat(x + 42, y, 6, 32).offset(6, 16)              // 23
            .frame().splat(x + 48, y, 6, 32).offset(0, 16)              // 24
            .frame().splat(x + 54, y, 10, 32).offset(-6, 16)            // 25

            .frame().splat(x + 64, y, 10, 32).offset(16, 16)            // 26: X-axis slope
            .frame().splat(x + 74, y, 6, 32).offset(6, 16)              // 27
            .frame().splat(x + 80, y, 6, 32).offset(0, 16)              // 28
            .frame().splat(x + 86, y, 10, 32).offset(-6, 16)            // 29
    }

    /// Helper for wall tiles
    ///
    /// Wall tiles are chopped up from two 32x32 images. One contains the center pillar wallform
    /// and the other contains the two long sides wallform.
    pub fn wall(self, center_x: u32, center_y: u32, sides_x: u32, sides_y: u32) -> Self {
        self.splat(center_x, center_y, 16, 32).offset(16, 16)
            .frame().splat(center_x + 16, center_y, 16, 32).offset(0, 16)
            .frame().splat(sides_x, sides_y, 16, 32).offset(16, 16)
            .frame().splat(sides_x + 16, sides_y, 16, 32).offset(0, 16)
    }

    /// Start a new frame in the current brush.
    pub fn frame(mut self) -> Self {
        self.brush.push(Vec::new());
        self
    }

    /// Finish and name the current brush and start a new one.
    pub fn brush(mut self, name: &str) -> Self {
        use std::mem;

        let name = name.to_string();
        // Must be an original name.
        assert!(Brush::get_resource(&name).is_none());

        // Zero cached brush and copy the old value here so we can insert it.
        let mut brush = Vec::new();
        mem::swap(&mut brush, &mut self.brush);
        assert!(!brush.is_empty());

        Brush::insert_resource(name, Brush(brush));

        // Reset color
        self.color = WHITE;

        self
    }
}
<|endoftext|>