<commit_before>use std::sync::Arc;
use std::default::Default;
use graphics::{self, DrawState, ImageSize, Graphics};
use glium::{Display, Surface, Texture2d, Texture, Program, VertexBuffer,
            DrawParameters, BlendingFunction, LinearBlendingFactor};
use glium::index::{NoIndices, PrimitiveType};
use shader_version::Shaders;
use shader_version::glsl::GLSL;

use shader;
use OpenGL;

#[derive(Clone)]
pub struct DrawTexture {
    texture: Arc<Texture2d>,
}

impl DrawTexture {
    pub fn new(texture: Texture2d) -> DrawTexture {
        DrawTexture { texture: Arc::new(texture) }
    }
}

impl ImageSize for DrawTexture {
    fn get_size(&self) -> (u32, u32) {
        let ref tex = self.texture;
        (tex.get_width(), tex.get_height().unwrap())
    }
}

#[derive(Copy, Clone)]
struct PlainVertex {
    position: [f32; 2],
}

implement_vertex!(PlainVertex, position);

#[derive(Copy, Clone)]
struct TexturedVertex {
    position: [f32; 2],
    texcoord: [f32; 2],
}

implement_vertex!(TexturedVertex, position, texcoord);

pub struct Glium2d {
    next_plain_buffer: u32,
    plain_buffer1: VertexBuffer<PlainVertex>,
    plain_buffer2: VertexBuffer<PlainVertex>,
    next_textured_buffer: u32,
    textured_buffer1: VertexBuffer<TexturedVertex>,
    textured_buffer2: VertexBuffer<TexturedVertex>,
    shader_texture: Program,
    shader_color: Program,
}

impl Glium2d {
    pub fn new(opengl: OpenGL, display: &Display) -> Glium2d {
        // FIXME: create empty buffers when glium supports them
        let plain_data = ::std::iter::repeat(PlainVertex { position: [0.0, 0.0] })
                                .take(graphics::BACK_END_MAX_VERTEX_COUNT).collect::<Vec<_>>();
        let textured_data = ::std::iter::repeat(TexturedVertex { position: [0.0, 0.0], texcoord: [0.0, 0.0] })
                                .take(graphics::BACK_END_MAX_VERTEX_COUNT).collect::<Vec<_>>();

        Glium2d {
            next_plain_buffer: 0,
            plain_buffer1: VertexBuffer::new(display, plain_data.clone()),
            plain_buffer2: VertexBuffer::new(display, plain_data),
            next_textured_buffer: 0,
            textured_buffer1: VertexBuffer::new(display, textured_data.clone()),
            textured_buffer2: VertexBuffer::new(display, textured_data),
            shader_texture:
                Program::from_source(display,
                                     Shaders::new().set(GLSL::_1_20, shader::VS_TEXTURED_120)
                                                   .set(GLSL::_1_50, shader::VS_TEXTURED_150)
                                                   .get(opengl.to_GLSL()).unwrap(),
                                     Shaders::new().set(GLSL::_1_20, shader::FS_TEXTURED_120)
                                                   .set(GLSL::_1_50, shader::FS_TEXTURED_150)
                                                   .get(opengl.to_GLSL()).unwrap(),
                                     None).ok().expect("failed to initialize textured shader"),
            shader_color:
                Program::from_source(&display,
                                     Shaders::new().set(GLSL::_1_20, shader::VS_COLORED_120)
                                                   .set(GLSL::_1_50, shader::VS_COLORED_150)
                                                   .get(opengl.to_GLSL()).unwrap(),
                                     Shaders::new().set(GLSL::_1_20, shader::FS_COLORED_120)
                                                   .set(GLSL::_1_50, shader::FS_COLORED_150)
                                                   .get(opengl.to_GLSL()).unwrap(),
                                     None).ok().expect("failed to initialize colored shader"),
        }
    }
}

pub struct GliumGraphics<'d, 's, S: 's> {
    system: &'d mut Glium2d,
    surface: &'s mut S,
}

impl<'d, 's, S> GliumGraphics<'d, 's, S> {
    pub fn new(system: &'d mut Glium2d, surface: &'s mut S)
               -> GliumGraphics<'d, 's, S> {
        GliumGraphics {
            system: system,
            surface: surface,
        }
    }
}

/// Implemented by all graphics back-ends.
impl<'d, 's, S: Surface> Graphics for GliumGraphics<'d, 's, S> {
    type Texture = DrawTexture;

    /// Clears background with a color.
    fn clear(&mut self, color: [f32; 4]) {
        let [r, g, b, a] = color;
        self.surface.clear_color(r, g, b, a);
    }

    /// Renders list of 2d triangles.
    fn tri_list<F>(
        &mut self,
        _draw_state: &DrawState,
        color: &[f32; 4],
        mut f: F
    )
        where F: FnMut(&mut FnMut(&[f32]))
    {
        f(&mut |vertices: &[f32]| {
            let slice = match self.system.next_plain_buffer {
                0 => {
                    self.system.next_plain_buffer = 1;
                    self.system.plain_buffer1.slice(0, vertices.len() / 2).unwrap()
                },
                1 => {
                    self.system.next_plain_buffer = 0;
                    self.system.plain_buffer2.slice(0, vertices.len() / 2).unwrap()
                },
                _ => unreachable!()
            };

            slice.write({
                (0..vertices.len() / 2)
                    .map(|i| PlainVertex {
                        position: [vertices[2 * i], vertices[2 * i + 1]],
                    })
                    .collect()
            });

            self.surface.draw(
                slice,
                &NoIndices(PrimitiveType::TrianglesList),
                &self.system.shader_color,
                &uniform! { color: *color },
                &DrawParameters {
                    blending_function: Some(BlendingFunction::Addition {
                        source: LinearBlendingFactor::SourceAlpha,
                        destination: LinearBlendingFactor::OneMinusSourceAlpha,
                    }),
                    .. Default::default()
                },
            )
            .ok()
            .expect("failed to draw triangle list");
        })
    }

    /// Renders list of 2d triangles.
    ///
    /// A texture coordinate is assigned per vertex.
    /// The texture coordinates refers to the current texture.
    fn tri_list_uv<F>(
        &mut self,
        _draw_state: &DrawState,
        color: &[f32; 4],
        texture: &DrawTexture,
        mut f: F
    )
        where F: FnMut(&mut FnMut(&[f32], &[f32]))
    {
        use std::cmp::min;

        f(&mut |vertices: &[f32], texture_coords: &[f32]| {
            let len = min(vertices.len(), texture_coords.len()) / 2;

            let slice = match self.system.next_textured_buffer {
                0 => {
                    self.system.next_textured_buffer = 1;
                    self.system.textured_buffer1.slice(0, len).unwrap()
                },
                1 => {
                    self.system.next_textured_buffer = 0;
                    self.system.textured_buffer2.slice(0, len).unwrap()
                },
                _ => unreachable!()
            };

            slice.write({
                (0..len)
                    .map(|i| TexturedVertex {
                        position: [vertices[2 * i], vertices[2 * i + 1]],
                        // FIXME: The `1.0 - ...` is because of a wrong convention
                        texcoord: [texture_coords[2 * i], 1.0 - texture_coords[2 * i + 1]],
                    })
                    .collect()
            });

            let texture = &*(texture.texture);
            self.surface.draw(
                slice,
                &NoIndices(PrimitiveType::TrianglesList),
                &self.system.shader_texture,
                &uniform! {
                    color: *color,
                    s_texture: texture
                },
                &DrawParameters {
                    blending_function: Some(BlendingFunction::Addition {
                        source: LinearBlendingFactor::SourceAlpha,
                        destination: LinearBlendingFactor::OneMinusSourceAlpha,
                    }),
                    .. Default::default()
                },
            )
            .ok()
            .expect("failed to draw triangle list");
        })
    }
}
<commit_msg>Update to latest glium<commit_after>use std::sync::Arc;
use std::default::Default;
use graphics::{self, DrawState, ImageSize, Graphics};
use glium::{Display, Surface, Texture2d, Texture, Program, VertexBuffer,
            DrawParameters, BlendingFunction, LinearBlendingFactor};
use glium::index::{NoIndices, PrimitiveType};
use shader_version::Shaders;
use shader_version::glsl::GLSL;

use shader;
use OpenGL;

#[derive(Clone)]
pub struct DrawTexture {
    texture: Arc<Texture2d>,
}

impl DrawTexture {
    pub fn new(texture: Texture2d) -> DrawTexture {
        DrawTexture { texture: Arc::new(texture) }
    }
}

impl ImageSize for DrawTexture {
    fn get_size(&self) -> (u32, u32) {
        let ref tex = self.texture;
        (tex.get_width(), tex.get_height().unwrap())
    }
}

#[derive(Copy, Clone)]
struct PlainVertex {
    position: [f32; 2],
}

implement_vertex!(PlainVertex, position);

#[derive(Copy, Clone)]
struct TexturedVertex {
    position: [f32; 2],
    texcoord: [f32; 2],
}

implement_vertex!(TexturedVertex, position, texcoord);

pub struct Glium2d {
    next_plain_buffer: u32,
    plain_buffer1: VertexBuffer<PlainVertex>,
    plain_buffer2: VertexBuffer<PlainVertex>,
    next_textured_buffer: u32,
    textured_buffer1: VertexBuffer<TexturedVertex>,
    textured_buffer2: VertexBuffer<TexturedVertex>,
    shader_texture: Program,
    shader_color: Program,
}

impl Glium2d {
    pub fn new(opengl: OpenGL, display: &Display) -> Glium2d {
        // FIXME: create empty buffers when glium supports them
        let plain_data = ::std::iter::repeat(PlainVertex { position: [0.0, 0.0] })
                                .take(graphics::BACK_END_MAX_VERTEX_COUNT).collect::<Vec<_>>();
        let textured_data = ::std::iter::repeat(TexturedVertex { position: [0.0, 0.0], texcoord: [0.0, 0.0] })
                                .take(graphics::BACK_END_MAX_VERTEX_COUNT).collect::<Vec<_>>();

        Glium2d {
            next_plain_buffer: 0,
            plain_buffer1: VertexBuffer::new(display, plain_data.clone()),
            plain_buffer2: VertexBuffer::new(display, plain_data),
            next_textured_buffer: 0,
            textured_buffer1: VertexBuffer::new(display, textured_data.clone()),
            textured_buffer2: VertexBuffer::new(display, textured_data),
            shader_texture:
                Program::from_source(display,
                                     Shaders::new().set(GLSL::_1_20, shader::VS_TEXTURED_120)
                                                   .set(GLSL::_1_50, shader::VS_TEXTURED_150)
                                                   .get(opengl.to_GLSL()).unwrap(),
                                     Shaders::new().set(GLSL::_1_20, shader::FS_TEXTURED_120)
                                                   .set(GLSL::_1_50, shader::FS_TEXTURED_150)
                                                   .get(opengl.to_GLSL()).unwrap(),
                                     None).ok().expect("failed to initialize textured shader"),
            shader_color:
                Program::from_source(display,
                                     Shaders::new().set(GLSL::_1_20, shader::VS_COLORED_120)
                                                   .set(GLSL::_1_50, shader::VS_COLORED_150)
                                                   .get(opengl.to_GLSL()).unwrap(),
                                     Shaders::new().set(GLSL::_1_20, shader::FS_COLORED_120)
                                                   .set(GLSL::_1_50, shader::FS_COLORED_150)
                                                   .get(opengl.to_GLSL()).unwrap(),
                                     None).ok().expect("failed to initialize colored shader"),
        }
    }
}

pub struct GliumGraphics<'d, 's, S: 's> {
    system: &'d mut Glium2d,
    surface: &'s mut S,
}

impl<'d, 's, S> GliumGraphics<'d, 's, S> {
    pub fn new(system: &'d mut Glium2d, surface: &'s mut S)
               -> GliumGraphics<'d, 's, S> {
        GliumGraphics {
            system: system,
            surface: surface,
        }
    }
}

/// Implemented by all graphics back-ends.
impl<'d, 's, S: Surface> Graphics for GliumGraphics<'d, 's, S> {
    type Texture = DrawTexture;

    /// Clears background with a color.
    fn clear(&mut self, color: [f32; 4]) {
        let [r, g, b, a] = color;
        self.surface.clear_color(r, g, b, a);
    }

    /// Renders list of 2d triangles.
    fn tri_list<F>(
        &mut self,
        _draw_state: &DrawState,
        color: &[f32; 4],
        mut f: F
    )
        where F: FnMut(&mut FnMut(&[f32]))
    {
        f(&mut |vertices: &[f32]| {
            let slice = match self.system.next_plain_buffer {
                0 => {
                    self.system.next_plain_buffer = 1;
                    self.system.plain_buffer1.slice(0, vertices.len() / 2).unwrap()
                },
                1 => {
                    self.system.next_plain_buffer = 0;
                    self.system.plain_buffer2.slice(0, vertices.len() / 2).unwrap()
                },
                _ => unreachable!()
            };

            slice.write({
                (0..vertices.len() / 2)
                    .map(|i| PlainVertex {
                        position: [vertices[2 * i], vertices[2 * i + 1]],
                    })
                    .collect()
            });

            self.surface.draw(
                slice,
                &NoIndices(PrimitiveType::TrianglesList),
                &self.system.shader_color,
                &uniform! { color: *color },
                &DrawParameters {
                    blending_function: Some(BlendingFunction::Addition {
                        source: LinearBlendingFactor::SourceAlpha,
                        destination: LinearBlendingFactor::OneMinusSourceAlpha,
                    }),
                    .. Default::default()
                },
            )
            .ok()
            .expect("failed to draw triangle list");
        })
    }

    /// Renders list of 2d triangles.
    ///
    /// A texture coordinate is assigned per vertex.
    /// The texture coordinates refers to the current texture.
    fn tri_list_uv<F>(
        &mut self,
        _draw_state: &DrawState,
        color: &[f32; 4],
        texture: &DrawTexture,
        mut f: F
    )
        where F: FnMut(&mut FnMut(&[f32], &[f32]))
    {
        use std::cmp::min;

        f(&mut |vertices: &[f32], texture_coords: &[f32]| {
            let len = min(vertices.len(), texture_coords.len()) / 2;

            let slice = match self.system.next_textured_buffer {
                0 => {
                    self.system.next_textured_buffer = 1;
                    self.system.textured_buffer1.slice(0, len).unwrap()
                },
                1 => {
                    self.system.next_textured_buffer = 0;
                    self.system.textured_buffer2.slice(0, len).unwrap()
                },
                _ => unreachable!()
            };

            slice.write({
                (0..len)
                    .map(|i| TexturedVertex {
                        position: [vertices[2 * i], vertices[2 * i + 1]],
                        // FIXME: The `1.0 - ...` is because of a wrong convention
                        texcoord: [texture_coords[2 * i], 1.0 - texture_coords[2 * i + 1]],
                    })
                    .collect()
            });

            let texture = &*(texture.texture);
            self.surface.draw(
                slice,
                &NoIndices(PrimitiveType::TrianglesList),
                &self.system.shader_texture,
                &uniform! {
                    color: *color,
                    s_texture: texture
                },
                &DrawParameters {
                    blending_function: Some(BlendingFunction::Addition {
                        source: LinearBlendingFactor::SourceAlpha,
                        destination: LinearBlendingFactor::OneMinusSourceAlpha,
                    }),
                    .. Default::default()
                },
            )
            .ok()
            .expect("failed to draw triangle list");
        })
    }
}
<|endoftext|>


<commit_before>use rust_utils::*;
use std::fs;

/*----------------------------------------------------------------------------*/

pub fn main() {
    let data = fs::read_to_string("data/p6.txt")
        .expect("Something went wrong reading the file")
        .replace("\n", "");
    let decoded = to_bytes::from_b64(&data);

    let decrypted = decrypt_xor::multi_char_xor(&decoded, 2, 40);
    let plaintext = from_bytes::to_utf8(&decrypted);

    println!("{:?}", plaintext);
}
<commit_msg>print display instead of debug<commit_after>use rust_utils::*;
use std::fs;

/*----------------------------------------------------------------------------*/

pub fn main() {
    let data = fs::read_to_string("data/p6.txt")
        .expect("Something went wrong reading the file")
        .replace("\n", "");
    let decoded = to_bytes::from_b64(&data);

    let decrypted = decrypt_xor::multi_char_xor(&decoded, 2, 40);
    let plaintext = from_bytes::to_utf8(&decrypted);

    println!("{}", plaintext);
}
<|endoftext|>


<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use crate::io::spi::{Target, Transfer};
use crate::spiflash::sfdp::{BlockEraseSize, Sfdp, SupportedAddressModes};
use anyhow::{ensure, Result};
use std::convert::TryFrom;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum Error {
    #[error("address out of bounds: {0} >= {1}")]
    AddressOutOfBounds(u32, u32),
    #[error("erase at address {0} not aligned on {1}-byte boundary")]
    BadEraseAddress(u32, u32),
    #[error("erase length {0} not a multiple of {1} bytes")]
    BadEraseLength(u32, u32),
}

#[derive(Debug, PartialEq, Eq)]
pub enum AddressMode {
    Mode3b,
    Mode4b,
}

impl From<SupportedAddressModes> for AddressMode {
    fn from(mode: SupportedAddressModes) -> Self {
        match mode {
            SupportedAddressModes::Mode4b => AddressMode::Mode4b,
            _ => AddressMode::Mode3b,
        }
    }
}

impl Default for AddressMode {
    fn default() -> Self {
        AddressMode::Mode3b
    }
}

pub struct SpiFlash {
    pub size: u32,
    pub erase_size: u32,
    pub erase_opcode: u8,
    pub program_size: u32,
    pub address_mode: AddressMode,
    pub sfdp: Option<Sfdp>,
}

impl Default for SpiFlash {
    fn default() -> Self {
        SpiFlash {
            size: 16 * 1024 * 1024,
            erase_size: 4 * 1024,
            erase_opcode: 0x20,
            program_size: SpiFlash::LEGACY_PAGE_SIZE,
            address_mode: AddressMode::default(),
            sfdp: None,
        }
    }
}

impl SpiFlash {
    // Well known SPI Flash opcodes.
    pub const READ: u8 = 0x03;
    pub const PAGE_PROGRAM: u8 = 0x02;
    pub const SECTOR_ERASE: u8 = 0x20;
    pub const CHIP_ERASE: u8 = 0x60;
    pub const WRITE_ENABLE: u8 = 0x06;
    pub const WRITE_DISABLE: u8 = 0x04;
    pub const READ_STATUS: u8 = 0x05;
    pub const READ_ID: u8 = 0x9f;
    pub const ENTER_4B: u8 = 0xb7;
    pub const EXIT_4B: u8 = 0xe9;
    pub const READ_SFDP: u8 = 0x5a;
    pub const NOP: u8 = 0x00;
    pub const RESET_ENABLE: u8 = 0x66;
    pub const RESET: u8 = 0x99;

    /// The legacy JEDEC page size for programming operations is 256 bytes.
    pub const LEGACY_PAGE_SIZE: u32 = 256;

    /// Status register bits:
    /// The `WIP` bit indicates a write in progress (sometimes called the busy bit).
    pub const STATUS_WIP: u8 = 0x01;
    /// The `WEL` bit is the write enable latch.
    pub const STATUS_WEL: u8 = 0x02;

    /// Prepare an opcode and address buffer according to the address_mode.
    fn opcode_with_address(&self, opcode: u8, address: u32) -> Result<Vec<u8>> {
        ensure!(
            address < self.size,
            Error::AddressOutOfBounds(address, self.size)
        );
        let mut buf = vec![opcode];
        if self.address_mode == AddressMode::Mode4b {
            buf.push((address >> 24) as u8);
        }
        buf.push((address >> 16) as u8);
        buf.push((address >> 8) as u8);
        buf.push(address as u8);
        Ok(buf)
    }

    /// Read `length` bytes of the JEDEC ID from the `spi` target.
    pub fn read_jedec_id(spi: &dyn Target, length: usize) -> Result<Vec<u8>> {
        let mut buf = vec![0u8; length];
        spi.run_transaction(&mut [
            Transfer::Write(&[SpiFlash::READ_ID]),
            Transfer::Read(&mut buf),
        ])?;
        Ok(buf)
    }

    /// Read status register from the `spi` target.
    pub fn read_status(spi: &dyn Target) -> Result<u8> {
        let mut buf = [0u8; 1];
        spi.run_transaction(&mut [
            Transfer::Write(&[SpiFlash::READ_STATUS]),
            Transfer::Read(&mut buf),
        ])?;
        Ok(buf[0])
    }

    /// Poll the status register waiting for the busy bit to clear.
    pub fn wait_for_busy_clear(spi: &dyn Target) -> Result<()> {
        while SpiFlash::read_status(spi)? & SpiFlash::STATUS_WIP != 0 {
            // Do nothing.
        }
        Ok(())
    }

    /// Send the WRITE_ENABLE opcode to the `spi` target.
    pub fn set_write_enable(spi: &dyn Target) -> Result<()> {
        let wren = [SpiFlash::WRITE_ENABLE];
        spi.run_transaction(&mut [Transfer::Write(&wren)])?;
        Ok(())
    }

    /// Read and parse the SFDP table from the `spi` target.
    pub fn read_sfdp(spi: &dyn Target) -> Result<Sfdp> {
        let mut buf = vec![0u8; 256];
        let mut tries = 0;
        loop {
            spi.run_transaction(&mut [
                // READ_SFDP always takes a 3-byte address followed by a dummy
                // byte regardless of address mode.  To simplify, we always
                // read from address zero.
                Transfer::Write(&[SpiFlash::READ_SFDP, 0, 0, 0, 0]),
                Transfer::Read(&mut buf),
            ])?;

            // We only want to give SFDP parsing one extra chance for length
            // extension. If parsing fails a second time, just return the error.
            let result = Sfdp::try_from(&buf[..]);
            if result.is_ok() || tries > 0 {
                return result;
            }
            buf.resize(Sfdp::length_required(&buf)?, 0);
            tries += 1;
        }
    }

    /// Create a new `SpiFlash` instance from an SFDP table.
    pub fn from_sfdp(sfdp: Sfdp) -> Self {
        let (erase_sz, erase_op) = match sfdp.jedec.block_erase_size {
            BlockEraseSize::Block4KiB => (4096, sfdp.jedec.erase_opcode_4kib),
            _ => (sfdp.jedec.sector[0].size, sfdp.jedec.sector[0].erase_opcode),
        };
        SpiFlash {
            size: sfdp.jedec.density,
            erase_size: erase_sz,
            erase_opcode: erase_op,
            program_size: SpiFlash::LEGACY_PAGE_SIZE,
            address_mode: AddressMode::from(sfdp.jedec.address_modes),
            sfdp: Some(sfdp),
        }
    }

    /// Create a new `SpiFlash` instance by reading an SFDP table from the `spi` Target.
    pub fn from_spi(spi: &dyn Target) -> Result<Self> {
        let sfdp = SpiFlash::read_sfdp(spi)?;
        Ok(SpiFlash::from_sfdp(sfdp))
    }

    /// Set the SPI flash addressing mode to either 3b or 4b mode.
    pub fn set_address_mode(&mut self, spi: &dyn Target, mode: AddressMode) -> Result<()> {
        let opcode = [match mode {
            AddressMode::Mode3b => SpiFlash::EXIT_4B,
            AddressMode::Mode4b => SpiFlash::ENTER_4B,
        }];
        spi.run_transaction(&mut [Transfer::Write(&opcode)])?;
        self.address_mode = mode;
        Ok(())
    }

    /// Automatically set the addressing mode based on the size of the SPI flash.
    pub fn set_address_mode_auto(&mut self, spi: &dyn Target) -> Result<()> {
        self.set_address_mode(
            spi,
            if self.size <= 16 * 1024 * 1024 {
                AddressMode::Mode3b
            } else {
                AddressMode::Mode4b
            },
        )
    }

    /// Read into `buffer` from the SPI flash starting at `address`.
    pub fn read(&self, spi: &dyn Target, address: u32, buffer: &mut [u8]) -> Result<()> {
        self.read_with_progress(spi, address, buffer, |_, _| {})
    }

    /// Read into `buffer` from the SPI flash starting at `address`.
    /// The `progress` callback will be invoked after each chunk of the read operation.
    pub fn read_with_progress(
        &self,
        spi: &dyn Target,
        mut address: u32,
        buffer: &mut [u8],
        progress: impl Fn(u32, u32),
    ) -> Result<()> {
        // Break the read up according to the maximum chunksize the backend can handle.
        for chunk in buffer.chunks_mut(spi.max_chunk_size()?) {
            let op_addr = self.opcode_with_address(SpiFlash::READ, address)?;
            spi.run_transaction(&mut [Transfer::Write(&op_addr), Transfer::Read(chunk)])?;
            address += chunk.len() as u32;
            progress(address, chunk.len() as u32);
        }
        Ok(())
    }

    /// Erase the entire EEPROM via the CHIP_ERASE opcode.
    pub fn chip_erase(&self, spi: &dyn Target) -> Result<()> {
        Self::set_write_enable(spi)?;
        spi.run_transaction(&mut [Transfer::Write(&[Self::CHIP_ERASE])])?;
        Self::wait_for_busy_clear(spi)?;
        Ok(())
    }

    /// Erase a segment of the SPI flash starting at `address` for `length` bytes.
    /// The address and length must be sector aligned.
    pub fn erase(&self, spi: &dyn Target, address: u32, length: u32) -> Result<()> {
        self.erase_with_progress(spi, address, length, |_, _| {})
    }

    /// Erase a segment of the SPI flash starting at `address` for `length` bytes.
    /// The address and length must be sector aligned.
    /// The `progress` callback will be invoked after each chunk of the erase operation.
    pub fn erase_with_progress(
        &self,
        spi: &dyn Target,
        address: u32,
        length: u32,
        progress: impl Fn(u32, u32),
    ) -> Result<()> {
        if address % self.erase_size != 0 {
            return Err(Error::BadEraseAddress(address, self.erase_size).into());
        }
        if length % self.erase_size != 0 {
            return Err(Error::BadEraseLength(length, self.erase_size).into());
        }
        let end = address + length;
        for addr in (address..end).step_by(self.erase_size as usize) {
            // Issue the write enable first as a separate transaction.
            SpiFlash::set_write_enable(spi)?;
            // Then issue the erase transaction.
            let op_addr = self.opcode_with_address(SpiFlash::SECTOR_ERASE, addr)?;
            spi.run_transaction(&mut [Transfer::Write(&op_addr)])?;
            SpiFlash::wait_for_busy_clear(spi)?;
            progress(addr, self.erase_size);
        }
        Ok(())
    }

    /// Program a segment of the SPI flash starting at `address` with the contents of `buffer`.
    /// The address and buffer length may be arbitrary.  This function will not
    /// erase the segment first.
    pub fn program(&self, spi: &dyn Target, address: u32, buffer: &[u8]) -> Result<()> {
        self.program_with_progress(spi, address, buffer, |_, _| {})
    }

    /// Program a segment of the SPI flash starting at `address` with the contents of `buffer`.
    /// The address and buffer length may be arbitrary.  This function will not
    /// erase the segment first.
    /// The `progress` callback will be invoked after each chunk of the program operation.
    pub fn program_with_progress(
        &self,
        spi: &dyn Target,
        mut address: u32,
        buffer: &[u8],
        progress: impl Fn(u32, u32),
    ) -> Result<()> {
        let mut remain = buffer.len();
        let mut chunkstart = 0usize;
        while remain != 0 {
            // If the address isn't program-page-size aligned, adjust the first
            // chunk so that subsequent writes will be so-aligned.
            // This is necessary because the SPI eeprom will wrap within the
            // programming page and the resultant data in the eeprom will not
            // be what you intended.
            let chunk = (self.program_size - (address % self.program_size)) as usize;
            let chunk = std::cmp::min(chunk, remain);
            let chunkend = chunkstart + chunk;
            let op_addr = self.opcode_with_address(SpiFlash::PAGE_PROGRAM, address)?;
            // Issue the write enable first as a separate transaction.
            SpiFlash::set_write_enable(spi)?;
            // Then issue the program operation.
            spi.run_transaction(&mut [
                Transfer::Write(&op_addr),
                Transfer::Write(&buffer[chunkstart..chunkend]),
            ])?;
            SpiFlash::wait_for_busy_clear(spi)?;
            address += chunk as u32;
            chunkstart += chunk;
            remain -= chunk;
            progress(address, chunk as u32);
        }
        Ok(())
    }

    /// Send the software reset sequence to the `spi` target.
    pub fn chip_reset(spi: &dyn Target) -> Result<()> {
        spi.run_transaction(&mut [Transfer::Write(&[Self::RESET_ENABLE])])?;
        spi.run_transaction(&mut [Transfer::Write(&[Self::RESET])])?;
        Ok(())
    }
}
<commit_msg>[opentitanlib] Change CHIP_ERASE opcode to 0xc7<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use crate::io::spi::{Target, Transfer};
use crate::spiflash::sfdp::{BlockEraseSize, Sfdp, SupportedAddressModes};
use anyhow::{ensure, Result};
use std::convert::TryFrom;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum Error {
    #[error("address out of bounds: {0} >= {1}")]
    AddressOutOfBounds(u32, u32),
    #[error("erase at address {0} not aligned on {1}-byte boundary")]
    BadEraseAddress(u32, u32),
    #[error("erase length {0} not a multiple of {1} bytes")]
    BadEraseLength(u32, u32),
}

#[derive(Debug, PartialEq, Eq)]
pub enum AddressMode {
    Mode3b,
    Mode4b,
}

impl From<SupportedAddressModes> for AddressMode {
    fn from(mode: SupportedAddressModes) -> Self {
        match mode {
            SupportedAddressModes::Mode4b => AddressMode::Mode4b,
            _ => AddressMode::Mode3b,
        }
    }
}

impl Default for AddressMode {
    fn default() -> Self {
        AddressMode::Mode3b
    }
}

pub struct SpiFlash {
    pub size: u32,
    pub erase_size: u32,
    pub erase_opcode: u8,
    pub program_size: u32,
    pub address_mode: AddressMode,
    pub sfdp: Option<Sfdp>,
}

impl Default for SpiFlash {
    fn default() -> Self {
        SpiFlash {
            size: 16 * 1024 * 1024,
            erase_size: 4 * 1024,
            erase_opcode: 0x20,
            program_size: SpiFlash::LEGACY_PAGE_SIZE,
            address_mode: AddressMode::default(),
            sfdp: None,
        }
    }
}

impl SpiFlash {
    // Well known SPI Flash opcodes.
    pub const READ: u8 = 0x03;
    pub const PAGE_PROGRAM: u8 = 0x02;
    pub const SECTOR_ERASE: u8 = 0x20;
    pub const CHIP_ERASE: u8 = 0xc7;
    pub const WRITE_ENABLE: u8 = 0x06;
    pub const WRITE_DISABLE: u8 = 0x04;
    pub const READ_STATUS: u8 = 0x05;
    pub const READ_ID: u8 = 0x9f;
    pub const ENTER_4B: u8 = 0xb7;
    pub const EXIT_4B: u8 = 0xe9;
    pub const READ_SFDP: u8 = 0x5a;
    pub const NOP: u8 = 0x00;
    pub const RESET_ENABLE: u8 = 0x66;
    pub const RESET: u8 = 0x99;

    /// The legacy JEDEC page size for programming operations is 256 bytes.
    pub const LEGACY_PAGE_SIZE: u32 = 256;

    /// Status register bits:
    /// The `WIP` bit indicates a write in progress (sometimes called the busy bit).
    pub const STATUS_WIP: u8 = 0x01;
    /// The `WEL` bit is the write enable latch.
    pub const STATUS_WEL: u8 = 0x02;

    /// Prepare an opcode and address buffer according to the address_mode.
    fn opcode_with_address(&self, opcode: u8, address: u32) -> Result<Vec<u8>> {
        ensure!(
            address < self.size,
            Error::AddressOutOfBounds(address, self.size)
        );
        let mut buf = vec![opcode];
        if self.address_mode == AddressMode::Mode4b {
            buf.push((address >> 24) as u8);
        }
        buf.push((address >> 16) as u8);
        buf.push((address >> 8) as u8);
        buf.push(address as u8);
        Ok(buf)
    }

    /// Read `length` bytes of the JEDEC ID from the `spi` target.
    pub fn read_jedec_id(spi: &dyn Target, length: usize) -> Result<Vec<u8>> {
        let mut buf = vec![0u8; length];
        spi.run_transaction(&mut [
            Transfer::Write(&[SpiFlash::READ_ID]),
            Transfer::Read(&mut buf),
        ])?;
        Ok(buf)
    }

    /// Read status register from the `spi` target.
    pub fn read_status(spi: &dyn Target) -> Result<u8> {
        let mut buf = [0u8; 1];
        spi.run_transaction(&mut [
            Transfer::Write(&[SpiFlash::READ_STATUS]),
            Transfer::Read(&mut buf),
        ])?;
        Ok(buf[0])
    }

    /// Poll the status register waiting for the busy bit to clear.
    pub fn wait_for_busy_clear(spi: &dyn Target) -> Result<()> {
        while SpiFlash::read_status(spi)? & SpiFlash::STATUS_WIP != 0 {
            // Do nothing.
        }
        Ok(())
    }

    /// Send the WRITE_ENABLE opcode to the `spi` target.
    pub fn set_write_enable(spi: &dyn Target) -> Result<()> {
        let wren = [SpiFlash::WRITE_ENABLE];
        spi.run_transaction(&mut [Transfer::Write(&wren)])?;
        Ok(())
    }

    /// Read and parse the SFDP table from the `spi` target.
    pub fn read_sfdp(spi: &dyn Target) -> Result<Sfdp> {
        let mut buf = vec![0u8; 256];
        let mut tries = 0;
        loop {
            spi.run_transaction(&mut [
                // READ_SFDP always takes a 3-byte address followed by a dummy
                // byte regardless of address mode.  To simplify, we always
                // read from address zero.
                Transfer::Write(&[SpiFlash::READ_SFDP, 0, 0, 0, 0]),
                Transfer::Read(&mut buf),
            ])?;

            // We only want to give SFDP parsing one extra chance for length
            // extension. If parsing fails a second time, just return the error.
            let result = Sfdp::try_from(&buf[..]);
            if result.is_ok() || tries > 0 {
                return result;
            }
            buf.resize(Sfdp::length_required(&buf)?, 0);
            tries += 1;
        }
    }

    /// Create a new `SpiFlash` instance from an SFDP table.
    pub fn from_sfdp(sfdp: Sfdp) -> Self {
        let (erase_sz, erase_op) = match sfdp.jedec.block_erase_size {
            BlockEraseSize::Block4KiB => (4096, sfdp.jedec.erase_opcode_4kib),
            _ => (sfdp.jedec.sector[0].size, sfdp.jedec.sector[0].erase_opcode),
        };
        SpiFlash {
            size: sfdp.jedec.density,
            erase_size: erase_sz,
            erase_opcode: erase_op,
            program_size: SpiFlash::LEGACY_PAGE_SIZE,
            address_mode: AddressMode::from(sfdp.jedec.address_modes),
            sfdp: Some(sfdp),
        }
    }

    /// Create a new `SpiFlash` instance by reading an SFDP table from the `spi` Target.
    pub fn from_spi(spi: &dyn Target) -> Result<Self> {
        let sfdp = SpiFlash::read_sfdp(spi)?;
        Ok(SpiFlash::from_sfdp(sfdp))
    }

    /// Set the SPI flash addressing mode to either 3b or 4b mode.
    pub fn set_address_mode(&mut self, spi: &dyn Target, mode: AddressMode) -> Result<()> {
        let opcode = [match mode {
            AddressMode::Mode3b => SpiFlash::EXIT_4B,
            AddressMode::Mode4b => SpiFlash::ENTER_4B,
        }];
        spi.run_transaction(&mut [Transfer::Write(&opcode)])?;
        self.address_mode = mode;
        Ok(())
    }

    /// Automatically set the addressing mode based on the size of the SPI flash.
    pub fn set_address_mode_auto(&mut self, spi: &dyn Target) -> Result<()> {
        self.set_address_mode(
            spi,
            if self.size <= 16 * 1024 * 1024 {
                AddressMode::Mode3b
            } else {
                AddressMode::Mode4b
            },
        )
    }

    /// Read into `buffer` from the SPI flash starting at `address`.
    pub fn read(&self, spi: &dyn Target, address: u32, buffer: &mut [u8]) -> Result<()> {
        self.read_with_progress(spi, address, buffer, |_, _| {})
    }

    /// Read into `buffer` from the SPI flash starting at `address`.
    /// The `progress` callback will be invoked after each chunk of the read operation.
    pub fn read_with_progress(
        &self,
        spi: &dyn Target,
        mut address: u32,
        buffer: &mut [u8],
        progress: impl Fn(u32, u32),
    ) -> Result<()> {
        // Break the read up according to the maximum chunksize the backend can handle.
        for chunk in buffer.chunks_mut(spi.max_chunk_size()?) {
            let op_addr = self.opcode_with_address(SpiFlash::READ, address)?;
            spi.run_transaction(&mut [Transfer::Write(&op_addr), Transfer::Read(chunk)])?;
            address += chunk.len() as u32;
            progress(address, chunk.len() as u32);
        }
        Ok(())
    }

    /// Erase the entire EEPROM via the CHIP_ERASE opcode.
    pub fn chip_erase(&self, spi: &dyn Target) -> Result<()> {
        Self::set_write_enable(spi)?;
        spi.run_transaction(&mut [Transfer::Write(&[Self::CHIP_ERASE])])?;
        Self::wait_for_busy_clear(spi)?;
        Ok(())
    }

    /// Erase a segment of the SPI flash starting at `address` for `length` bytes.
    /// The address and length must be sector aligned.
    pub fn erase(&self, spi: &dyn Target, address: u32, length: u32) -> Result<()> {
        self.erase_with_progress(spi, address, length, |_, _| {})
    }

    /// Erase a segment of the SPI flash starting at `address` for `length` bytes.
    /// The address and length must be sector aligned.
    /// The `progress` callback will be invoked after each chunk of the erase operation.
    pub fn erase_with_progress(
        &self,
        spi: &dyn Target,
        address: u32,
        length: u32,
        progress: impl Fn(u32, u32),
    ) -> Result<()> {
        if address % self.erase_size != 0 {
            return Err(Error::BadEraseAddress(address, self.erase_size).into());
        }
        if length % self.erase_size != 0 {
            return Err(Error::BadEraseLength(length, self.erase_size).into());
        }
        let end = address + length;
        for addr in (address..end).step_by(self.erase_size as usize) {
            // Issue the write enable first as a separate transaction.
            SpiFlash::set_write_enable(spi)?;
            // Then issue the erase transaction.
            let op_addr = self.opcode_with_address(SpiFlash::SECTOR_ERASE, addr)?;
            spi.run_transaction(&mut [Transfer::Write(&op_addr)])?;
            SpiFlash::wait_for_busy_clear(spi)?;
            progress(addr, self.erase_size);
        }
        Ok(())
    }

    /// Program a segment of the SPI flash starting at `address` with the contents of `buffer`.
    /// The address and buffer length may be arbitrary.  This function will not
    /// erase the segment first.
    pub fn program(&self, spi: &dyn Target, address: u32, buffer: &[u8]) -> Result<()> {
        self.program_with_progress(spi, address, buffer, |_, _| {})
    }

    /// Program a segment of the SPI flash starting at `address` with the contents of `buffer`.
    /// The address and buffer length may be arbitrary.  This function will not
    /// erase the segment first.
    /// The `progress` callback will be invoked after each chunk of the program operation.
    pub fn program_with_progress(
        &self,
        spi: &dyn Target,
        mut address: u32,
        buffer: &[u8],
        progress: impl Fn(u32, u32),
    ) -> Result<()> {
        let mut remain = buffer.len();
        let mut chunkstart = 0usize;
        while remain != 0 {
            // If the address isn't program-page-size aligned, adjust the first
            // chunk so that subsequent writes will be so-aligned.
            // This is necessary because the SPI eeprom will wrap within the
            // programming page and the resultant data in the eeprom will not
            // be what you intended.
            let chunk = (self.program_size - (address % self.program_size)) as usize;
            let chunk = std::cmp::min(chunk, remain);
            let chunkend = chunkstart + chunk;
            let op_addr = self.opcode_with_address(SpiFlash::PAGE_PROGRAM, address)?;
            // Issue the write enable first as a separate transaction.
            SpiFlash::set_write_enable(spi)?;
            // Then issue the program operation.
            spi.run_transaction(&mut [
                Transfer::Write(&op_addr),
                Transfer::Write(&buffer[chunkstart..chunkend]),
            ])?;
            SpiFlash::wait_for_busy_clear(spi)?;
            address += chunk as u32;
            chunkstart += chunk;
            remain -= chunk;
            progress(address, chunk as u32);
        }
        Ok(())
    }

    /// Send the software reset sequence to the `spi` target.
    pub fn chip_reset(spi: &dyn Target) -> Result<()> {
        spi.run_transaction(&mut [Transfer::Write(&[Self::RESET_ENABLE])])?;
        spi.run_transaction(&mut [Transfer::Write(&[Self::RESET])])?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>use {Message, Body};
use super::{multiplex, RequestId, Transport, Multiplex, MultiplexMessage};
use tokio_service::Service;
use futures::{Future, Poll, Async};
use futures::stream::Stream;
use std::io;

/// A server `Task` that dispatches `Transport` messages to a `Service` using
/// protocol multiplexing.
pub struct Server<S, T, B>
    where T: Transport,
          S: Service<Request = Message<T::Out, Body<T::BodyOut, T::Error>>,
                    Response = Message<T::In, B>,
                       Error = T::Error> + 'static,
          B: Stream<Item = T::BodyIn, Error = T::Error> + 'static,
{
    inner: Multiplex<Dispatch<S, T>>,
}

struct Dispatch<S, T> where S: Service {
    // The service handling the connection
    service: S,
    transport: T,
    in_flight: Vec<(RequestId, InFlight<S::Future>)>,
}

enum InFlight<F: Future> {
    Active(F),
    Done(Result<F::Item, F::Error>),
}

/// The total number of requests that can be in flight at once.
const MAX_IN_FLIGHT_REQUESTS: usize = 32;

/*
 *
 * ===== Server =====
 *
 */

impl<S, T, B> Server<S, T, B>
    where T: Transport,
          S: Service<Request = Message<T::Out, Body<T::BodyOut, T::Error>>,
                    Response = Message<T::In, B>,
                       Error = T::Error> + 'static,
          B: Stream<Item = T::BodyIn, Error = T::Error>,
{
    /// Create a new pipeline `Server` dispatcher with the given service and
    /// transport
    pub fn new(service: S, transport: T) -> Server<S, T, B> {
        let dispatch = Dispatch {
            service: service,
            transport: transport,
            in_flight: vec![],
        };

        // Create the multiplexer
        let multiplex = Multiplex::new(dispatch);

        // Return the server task
        Server { inner: multiplex }
    }
}

impl<S, T, B> multiplex::Dispatch for Dispatch<S, T>
    where T: Transport,
          S: Service<Request = Message<T::Out, Body<T::BodyOut, T::Error>>,
                    Response = Message<T::In, B>,
                       Error = T::Error> + 'static,
          B: Stream<Item = T::BodyIn, Error = T::Error> + 'static,
{

    type In = T::In;
    type BodyIn = T::BodyIn;
    type Out = T::Out;
    type BodyOut = T::BodyOut;
    type Error = T::Error;
    type Stream = B;
    type Transport = T;

    fn transport(&mut self) -> &mut T {
        &mut self.transport
    }

    fn poll(&mut self) -> Poll<Option<MultiplexMessage<Self::In, B, Self::Error>>, io::Error> {
        trace!("Dispatch::poll");

        let mut idx = None;

        for (i, &mut (request_id, ref mut slot)) in self.in_flight.iter_mut().enumerate() {
            trace!("   --> poll; request_id={:?}", request_id);
            if slot.poll() && idx.is_none() {
                idx = Some(i);
            }
        }

        if let Some(idx) = idx {
            // let (request_id, message) = self.in_flight.remove(idx);
            let (request_id, message) = self.in_flight.remove(idx);
            let message = MultiplexMessage {
                id: request_id,
                message: message.unwrap_done(),
                solo: false,
            };

            Ok(Async::Ready(Some(message)))
        } else {
            Ok(Async::NotReady)
        }
    }

    fn dispatch(&mut self, message: MultiplexMessage<Self::Out, Body<Self::BodyOut, Self::Error>, Self::Error>) -> io::Result<()> {
        assert!(self.poll_ready().is_ready());

        let MultiplexMessage { id, message, solo } = message;

        assert!(!solo);

        if let Ok(request) = message {
            let response = self.service.call(request);
            self.in_flight.push((id, InFlight::Active(response)));
        }

        // TODO: Should the error be handled differently?

        Ok(())
    }

    fn poll_ready(&self) -> Async<()> {
        if self.in_flight.len() < MAX_IN_FLIGHT_REQUESTS {
            Async::Ready(())
        } else {
            Async::NotReady
        }
    }

    fn cancel(&mut self, _request_id: RequestId) -> io::Result<()> {
        // TODO: implement
        Ok(())
    }
}

impl<S, T, B> Future for Server<S, T, B>
    where T: Transport,
          S: Service<Request = Message<T::Out, Body<T::BodyOut, T::Error>>,
                    Response = Message<T::In, B>,
                       Error = T::Error> + 'static,
          B: Stream<Item = T::BodyIn, Error = T::Error>,
{
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<(), io::Error> {
        self.inner.poll()
    }
}

/*
 *
 * ===== InFlight =====
 *
 */

impl<F> InFlight<F>
    where F: Future,
{
    // Returns true if done
    fn poll(&mut self) -> bool {
        let res = match *self {
            InFlight::Active(ref mut f) => {
                trace!("   --> polling future");
                match f.poll() {
                    Ok(Async::Ready(e)) => Ok(e),
                    Err(e) => Err(e),
                    Ok(Async::NotReady) => return false,
                }
            }
            _ => return true,
        };

        *self = InFlight::Done(res);
        true
    }

    fn unwrap_done(self) -> Result<F::Item, F::Error> {
        match self {
            InFlight::Done(res) => res,
            _ => panic!("future is not ready"),
        }
    }
}
<commit_msg>multiplex::Server future error is ()<commit_after>use {Message, Body};
use super::{multiplex, RequestId, Transport, Multiplex, MultiplexMessage};
use tokio_service::Service;
use futures::{Future, Poll, Async};
use futures::stream::Stream;
use std::io;

/// A server `Task` that dispatches `Transport` messages to a `Service` using
/// protocol multiplexing.
pub struct Server<S, T, B>
    where T: Transport,
          S: Service<Request = Message<T::Out, Body<T::BodyOut, T::Error>>,
                    Response = Message<T::In, B>,
                       Error = T::Error> + 'static,
          B: Stream<Item = T::BodyIn, Error = T::Error> + 'static,
{
    inner: Multiplex<Dispatch<S, T>>,
}

struct Dispatch<S, T> where S: Service {
    // The service handling the connection
    service: S,
    transport: T,
    in_flight: Vec<(RequestId, InFlight<S::Future>)>,
}

enum InFlight<F: Future> {
    Active(F),
    Done(Result<F::Item, F::Error>),
}

/// The total number of requests that can be in flight at once.
const MAX_IN_FLIGHT_REQUESTS: usize = 32;

/*
 *
 * ===== Server =====
 *
 */

impl<S, T, B> Server<S, T, B>
    where T: Transport,
          S: Service<Request = Message<T::Out, Body<T::BodyOut, T::Error>>,
                    Response = Message<T::In, B>,
                       Error = T::Error> + 'static,
          B: Stream<Item = T::BodyIn, Error = T::Error>,
{
    /// Create a new pipeline `Server` dispatcher with the given service and
    /// transport
    pub fn new(service: S, transport: T) -> Server<S, T, B> {
        let dispatch = Dispatch {
            service: service,
            transport: transport,
            in_flight: vec![],
        };

        // Create the multiplexer
        let multiplex = Multiplex::new(dispatch);

        // Return the server task
        Server { inner: multiplex }
    }
}

impl<S, T, B> multiplex::Dispatch for Dispatch<S, T>
    where T: Transport,
          S: Service<Request = Message<T::Out, Body<T::BodyOut, T::Error>>,
                    Response = Message<T::In, B>,
                       Error = T::Error> + 'static,
          B: Stream<Item = T::BodyIn, Error = T::Error> + 'static,
{

    type In = T::In;
    type BodyIn = T::BodyIn;
    type Out = T::Out;
    type BodyOut = T::BodyOut;
    type Error = T::Error;
    type Stream = B;
    type Transport = T;

    fn transport(&mut self) -> &mut T {
        &mut self.transport
    }

    fn poll(&mut self) -> Poll<Option<MultiplexMessage<Self::In, B, Self::Error>>, io::Error> {
        trace!("Dispatch::poll");

        let mut idx = None;

        for (i, &mut (request_id, ref mut slot)) in self.in_flight.iter_mut().enumerate() {
            trace!("   --> poll; request_id={:?}", request_id);
            if slot.poll() && idx.is_none() {
                idx = Some(i);
            }
        }

        if let Some(idx) = idx {
            // let (request_id, message) = self.in_flight.remove(idx);
            let (request_id, message) = self.in_flight.remove(idx);
            let message = MultiplexMessage {
                id: request_id,
                message: message.unwrap_done(),
                solo: false,
            };

            Ok(Async::Ready(Some(message)))
        } else {
            Ok(Async::NotReady)
        }
    }

    fn dispatch(&mut self, message: MultiplexMessage<Self::Out, Body<Self::BodyOut, Self::Error>, Self::Error>) -> io::Result<()> {
        assert!(self.poll_ready().is_ready());

        let MultiplexMessage { id, message, solo } = message;

        assert!(!solo);

        if let Ok(request) = message {
            let response = self.service.call(request);
            self.in_flight.push((id, InFlight::Active(response)));
        }

        // TODO: Should the error be handled differently?

        Ok(())
    }

    fn poll_ready(&self) -> Async<()> {
        if self.in_flight.len() < MAX_IN_FLIGHT_REQUESTS {
            Async::Ready(())
        } else {
            Async::NotReady
        }
    }

    fn cancel(&mut self, _request_id: RequestId) -> io::Result<()> {
        // TODO: implement
        Ok(())
    }
}

impl<S, T, B> Future for Server<S, T, B>
    where T: Transport,
          S: Service<Request = Message<T::Out, Body<T::BodyOut, T::Error>>,
                    Response = Message<T::In, B>,
                       Error = T::Error> + 'static,
          B: Stream<Item = T::BodyIn, Error = T::Error>,
{
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        self.inner.poll()
            .map_err(|e| {
                debug!("multiplex server connection hit error; {:?}", e);
                ()
            })
    }
}

/*
 *
 * ===== InFlight =====
 *
 */

impl<F> InFlight<F>
    where F: Future,
{
    // Returns true if done
    fn poll(&mut self) -> bool {
        let res = match *self {
            InFlight::Active(ref mut f) => {
                trace!("   --> polling future");
                match f.poll() {
                    Ok(Async::Ready(e)) => Ok(e),
                    Err(e) => Err(e),
                    Ok(Async::NotReady) => return false,
                }
            }
            _ => return true,
        };

        *self = InFlight::Done(res);
        true
    }

    fn unwrap_done(self) -> Result<F::Item, F::Error> {
        match self {
            InFlight::Done(res) => res,
            _ => panic!("future is not ready"),
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::{HashMap, HashSet};

use render::Renderer;
use resman::AudioBuffer;
use routing::{Edge, GraphWatcher, NodeData, NodeHandle};
use routing::effect::{PrimitiveEffect, EffectData};
use util::unpack_f32;

type NodeMap = HashMap<NodeHandle, Node>;

#[derive(Default, Debug)]
pub struct RefRenderer {
    nodes: NodeMap,
}

#[derive(Debug)]
struct Node {
    data: MyNodeData,
    inbound: HashSet<Edge>
}

#[derive(Debug)]
enum MyNodeData {
    /// This node is a non-primitive effect.
    UserNode(NodeMap),
    /// Primitive effect (delay, constant, etc).
    Primitive(PrimitiveEffect),
    /// External audio.
    Buffer(AudioBuffer),
    /// This node is a DAG definition. i.e. it holds the output edges of a DAG.
    DagIO,
}

impl Renderer for RefRenderer {
    fn get_sample(&mut self, time: u64, slot: u32) -> f32 {
        // Try to find the edge that goes to -> (Null, slot==slot)
        let root_handle = NodeHandle::toplevel();
        // empty graph is 0 = silence
        self.nodes.get(&root_handle).map_or(0f32, |node| {
            // find all edges to ([Null], slot=slot)
            self.sum_input_to_slot(&self.nodes, node, time, slot, &Vec::new()) as f32
        })
    }
}
impl RefRenderer {
    /// Get the value on an edge at a particular time
    /// When backtracking from the output, we push each Node onto the context if we enter inside of
    ///   it (i.e. if it's a nested DAG) & pop when exiting.
    fn get_value(&self, nodes: &NodeMap, edge: &Edge, time: u64, context: &Vec<(&NodeMap, NodeHandle)>) -> f64 {
        let from = edge.from_full();
        if *from.node_handle() == None {
            // Reading from one of the inputs to the top of `context`
            // TODO: we can avoid cloning by reversing the pop after recursing.
            let mut new_context = context.clone();
            let (new_nodes, head) = new_context.pop().unwrap();
            // Sum the inputs to the matching slot
            self.sum_input_to_slot(new_nodes, &new_nodes[&head], time, edge.from_slot(), &new_context)
        } else {
            // Reading from another node within the DAG
            let node = &nodes[&from];
            match node.data {
                MyNodeData::UserNode(ref new_nodes) => {
                    let mut new_context = context.clone();
                    new_context.push((nodes, from));
                    // Now find the *output* of the sub dag (or 0 if the sub dag has no outputs)
                    new_nodes.get(&NodeHandle::toplevel()).map_or(0f64, |root_node| {
                        self.sum_input_to_slot(new_nodes, root_node, time, edge.from_slot(), &new_context)
                    })
                },
                MyNodeData::Primitive(prim) => match prim {
                    // Output = sum of all inputs to slot 0.
                    PrimitiveEffect::Delay => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from Delay slot != 0");
                            0f64
                        } else {
                            let delay_frames = self.sum_input_to_slot(nodes, node, time, 1, context);
                            // Clamp delay value to [0, u64::max]
                            let delay_int = if delay_frames < 0f64 {
                                0u64
                            } else if delay_frames > u64::max_value() as f64 {
                                // TODO: u64::max isn't precisely representable in f64;
                                // will this cause issues?
                                u64::max_value()
                            } else {
                                // Note: this conversion is flooring.
                                delay_frames as u64
                            };
                            // t<0 -> value is 0.
                            time.checked_sub(delay_int).map_or(0f64, |origin_time| {
                                self.sum_input_to_slot(nodes, node, origin_time, 0, context)
                            })
                        }
                    },
                    PrimitiveEffect::F32Constant => {
                        // Float value is encoded via the slot.
                        let value = edge.from_slot();
                        unpack_f32(value) as f64
                    },
                    PrimitiveEffect::Multiply => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from Multiply slot != 0");
                            0f64
                        } else {
                            // Sum all inputs from slot=0 and slot=2 into two separate
                            // variables, then multiply them.
                            let val_a = self.sum_input_to_slot(nodes, node, time, 0, context);
                            let val_b = self.sum_input_to_slot(nodes, node, time, 1, context);
                            val_a * val_b
                        }
                    },
                    PrimitiveEffect::Divide => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from MultInv slot != 0");
                            0f64
                        } else {
                            // Sum all inputs
                            let dividend = self.sum_input_to_slot(nodes, node, time, 0, context);
                            let divisor = self.sum_input_to_slot(nodes, node, time, 1, context);
                            dividend / divisor
                        }
                    },
                    PrimitiveEffect::Minimum => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from Modulo slot != 0");
                            0f64
                        } else {
                            let input_a = self.sum_input_to_slot(nodes, node, time, 0, context);
                            let input_b = self.sum_input_to_slot(nodes, node, time, 1, context);
                            input_a.min(input_b)
                        }
                    }
                    PrimitiveEffect::Modulo => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from Modulo slot != 0");
                            0f64
                        } else {
                            // Sum all dividends
                            let dividend = self.sum_input_to_slot(nodes, node, time, 0, context);
                            // Sum all divisors
                            let divisor = self.sum_input_to_slot(nodes, node, time, 1, context);
                            let rem = dividend % divisor;
                            if rem < 0f64 {
                                // TODO: We may be losing precision here, if rem is small.
                                // We should find a way to do true modulus.
                                rem + divisor
                            } else {
                                rem
                            }
                        }
                    },
                },
                MyNodeData::Buffer(ref buf) => buf.get(time, edge.from_slot()) as f64,
                // TODO: refactor to remove illegal enums
                _ => panic!("Internal RefRenderer error: illegal node type"),
            }
        }
    }
    /// Return the sum of all inputs into a specific slot of the given
    /// node at the given time.
    fn sum_input_to_slot(&self, nodes: &NodeMap, node: &Node, time: u64, slot: u32, context: &Vec<(&NodeMap, NodeHandle)>) -> f64 {
        let edges_in = node.inbound.iter().filter(|in_edge| {
            in_edge.to_slot() == slot
        });
        edges_in.map(|edge| self.get_value(nodes, edge, time, context)).sum()
    }

    fn make_node(&self, effect: &NodeData) -> MyNodeData {
        match *effect.data() {
            EffectData::Primitive(e) => MyNodeData::Primitive(e),
            EffectData::Buffer(ref buff) => MyNodeData::Buffer(buff.clone()),
            EffectData::RouteGraph(ref graph) => {
                let mut nodes = HashMap::new();
                for (node, data) in graph.iter_nodes() {
                    nodes.insert(*node, Node::new(self.make_node(data)));
                }
                for edge in graph.iter_edges() {
                    nodes.entry(edge.to_full()).or_insert_with(|| {
                        Node::new(MyNodeData::DagIO)
                    }).inbound.insert(edge.clone());
                }
                MyNodeData::UserNode(nodes)
            }
        }
    }
}

impl GraphWatcher for RefRenderer {
    fn on_add_node(&mut self, handle: &NodeHandle, data: &NodeData) {
        let my_node_data = self.make_node(data);
        self.nodes.insert(*handle, Node::new(my_node_data));
        // If the node is part of a new DAG, allocate data so that future edges
        // to null within the DAG can be held.
        self.nodes.entry(NodeHandle::toplevel()).or_insert_with(|| {
            Node::new(MyNodeData::DagIO)
        });
    }
    fn on_del_node(&mut self, handle: &NodeHandle) {
        self.nodes.remove(handle);
    }
    fn on_add_edge(&mut self, edge: &Edge) {
        self.nodes.get_mut(&edge.to_full()).unwrap().inbound.insert(edge.clone());
    }
    fn on_del_edge(&mut self, edge: &Edge) {
        self.nodes.get_mut(&edge.to_full()).unwrap().inbound.remove(edge);
    }
}

impl Node {
    fn new(data: MyNodeData) -> Self {
        Node {
            data: data,
            inbound: HashSet::new(),
        }
    }
}
<commit_msg>Remove MyNodeData::DagIO enum variant.<commit_after>use std::collections::{HashMap, HashSet};

use render::Renderer;
use resman::AudioBuffer;
use routing::{Edge, GraphWatcher, NodeData, NodeHandle};
use routing::effect::{PrimitiveEffect, EffectData};
use util::unpack_f32;

type NodeMap = HashMap<NodeHandle, Node>;

#[derive(Default, Debug)]
pub struct RefRenderer {
    nodes: NodeMap,
}

#[derive(Default, Debug)]
struct Node {
    data: Option<MyNodeData>,
    inbound: HashSet<Edge>
}

#[derive(Debug)]
enum MyNodeData {
    /// This node is a non-primitive effect.
    UserNode(NodeMap),
    /// Primitive effect (delay, constant, etc).
    Primitive(PrimitiveEffect),
    /// External audio.
    Buffer(AudioBuffer),
}

impl Renderer for RefRenderer {
    fn get_sample(&mut self, time: u64, slot: u32) -> f32 {
        // Try to find the edge that goes to -> (Null, slot==slot)
        let root_handle = NodeHandle::toplevel();
        // empty graph is 0 = silence
        self.nodes.get(&root_handle).map_or(0f32, |node| {
            // find all edges to ([Null], slot=slot)
            self.sum_input_to_slot(&self.nodes, node, time, slot, &Vec::new()) as f32
        })
    }
}
impl RefRenderer {
    /// Get the value on an edge at a particular time
    /// When backtracking from the output, we push each Node onto the context if we enter inside of
    ///   it (i.e. if it's a nested DAG) & pop when exiting.
    fn get_value(&self, nodes: &NodeMap, edge: &Edge, time: u64, context: &Vec<(&NodeMap, NodeHandle)>) -> f64 {
        let from = edge.from_full();
        if *from.node_handle() == None {
            // Reading from one of the inputs to the top of `context`
            // TODO: we can avoid cloning by reversing the pop after recursing.
            let mut new_context = context.clone();
            let (new_nodes, head) = new_context.pop().unwrap();
            // Sum the inputs to the matching slot
            self.sum_input_to_slot(new_nodes, &new_nodes[&head], time, edge.from_slot(), &new_context)
        } else {
            // Reading from another node within the DAG
            let node = &nodes[&from];
            match *node.data.as_ref().expect("Expected node to have associated data") {
                MyNodeData::UserNode(ref new_nodes) => {
                    let mut new_context = context.clone();
                    new_context.push((nodes, from));
                    // Now find the *output* of the sub dag (or 0 if the sub dag has no outputs)
                    new_nodes.get(&NodeHandle::toplevel()).map_or(0f64, |root_node| {
                        self.sum_input_to_slot(new_nodes, root_node, time, edge.from_slot(), &new_context)
                    })
                },
                MyNodeData::Primitive(prim) => match prim {
                    // Output = sum of all inputs to slot 0.
                    PrimitiveEffect::Delay => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from Delay slot != 0");
                            0f64
                        } else {
                            let delay_frames = self.sum_input_to_slot(nodes, node, time, 1, context);
                            // Clamp delay value to [0, u64::max]
                            let delay_int = if delay_frames < 0f64 {
                                0u64
                            } else if delay_frames > u64::max_value() as f64 {
                                // TODO: u64::max isn't precisely representable in f64;
                                // will this cause issues?
                                u64::max_value()
                            } else {
                                // Note: this conversion is flooring.
                                delay_frames as u64
                            };
                            // t<0 -> value is 0.
                            time.checked_sub(delay_int).map_or(0f64, |origin_time| {
                                self.sum_input_to_slot(nodes, node, origin_time, 0, context)
                            })
                        }
                    },
                    PrimitiveEffect::F32Constant => {
                        // Float value is encoded via the slot.
                        let value = edge.from_slot();
                        unpack_f32(value) as f64
                    },
                    PrimitiveEffect::Multiply => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from Multiply slot != 0");
                            0f64
                        } else {
                            // Sum all inputs from slot=0 and slot=2 into two separate
                            // variables, then multiply them.
                            let val_a = self.sum_input_to_slot(nodes, node, time, 0, context);
                            let val_b = self.sum_input_to_slot(nodes, node, time, 1, context);
                            val_a * val_b
                        }
                    },
                    PrimitiveEffect::Divide => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from MultInv slot != 0");
                            0f64
                        } else {
                            // Sum all inputs
                            let dividend = self.sum_input_to_slot(nodes, node, time, 0, context);
                            let divisor = self.sum_input_to_slot(nodes, node, time, 1, context);
                            dividend / divisor
                        }
                    },
                    PrimitiveEffect::Minimum => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from Modulo slot != 0");
                            0f64
                        } else {
                            let input_a = self.sum_input_to_slot(nodes, node, time, 0, context);
                            let input_b = self.sum_input_to_slot(nodes, node, time, 1, context);
                            input_a.min(input_b)
                        }
                    }
                    PrimitiveEffect::Modulo => {
                        // The only nonzero output is slot=0.
                        if edge.from_slot() != 0 {
                            warn!("Attempt to read from Modulo slot != 0");
                            0f64
                        } else {
                            // Sum all dividends
                            let dividend = self.sum_input_to_slot(nodes, node, time, 0, context);
                            // Sum all divisors
                            let divisor = self.sum_input_to_slot(nodes, node, time, 1, context);
                            let rem = dividend % divisor;
                            if rem < 0f64 {
                                // TODO: We may be losing precision here, if rem is small.
                                // We should find a way to do true modulus.
                                rem + divisor
                            } else {
                                rem
                            }
                        }
                    },
                },
                MyNodeData::Buffer(ref buf) => buf.get(time, edge.from_slot()) as f64,
            }
        }
    }
    /// Return the sum of all inputs into a specific slot of the given
    /// node at the given time.
    fn sum_input_to_slot(&self, nodes: &NodeMap, node: &Node, time: u64, slot: u32, context: &Vec<(&NodeMap, NodeHandle)>) -> f64 {
        let edges_in = node.inbound.iter().filter(|in_edge| {
            in_edge.to_slot() == slot
        });
        edges_in.map(|edge| self.get_value(nodes, edge, time, context)).sum()
    }

    fn make_node(&self, effect: &NodeData) -> MyNodeData {
        match *effect.data() {
            EffectData::Primitive(e) => MyNodeData::Primitive(e),
            EffectData::Buffer(ref buff) => MyNodeData::Buffer(buff.clone()),
            EffectData::RouteGraph(ref graph) => {
                let mut nodes = HashMap::new();
                for (node, data) in graph.iter_nodes() {
                    nodes.insert(*node, Node::new(Some(self.make_node(data))));
                }
                for edge in graph.iter_edges() {
                    nodes.entry(edge.to_full()).or_insert_with(Default::default)
                        .inbound.insert(edge.clone());
                }
                MyNodeData::UserNode(nodes)
            }
        }
    }
}

impl GraphWatcher for RefRenderer {
    fn on_add_node(&mut self, handle: &NodeHandle, data: &NodeData) {
        let my_node_data = self.make_node(data);
        self.nodes.insert(*handle, Node::new(Some(my_node_data)));
        // If the node is part of a new DAG, allocate data so that future edges
        // to null within the DAG can be held.
        self.nodes.entry(NodeHandle::toplevel()).or_insert_with(Default::default);
    }
    fn on_del_node(&mut self, handle: &NodeHandle) {
        self.nodes.remove(handle);
    }
    fn on_add_edge(&mut self, edge: &Edge) {
        self.nodes.get_mut(&edge.to_full()).unwrap().inbound.insert(edge.clone());
    }
    fn on_del_edge(&mut self, edge: &Edge) {
        self.nodes.get_mut(&edge.to_full()).unwrap().inbound.remove(edge);
    }
}

impl Node {
    fn new(data: Option<MyNodeData>) -> Self {
        Node {
            data: data,
            inbound: HashSet::new(),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Slices
//!
//! See `Slice`-structure documentation for more information on this module.

use core::{handle, buffer};
use core::{Primitive, Resources, VertexCount};
use core::command::InstanceParams;
use core::factory::Factory;
use core::memory::Bind;
use format::Format;
use pso;

/// A `Slice` dictates in which and in what order vertices get processed. It is required for
/// processing a PSO.
///
/// # Overview
/// A `Slice` object in essence dictates in what order the vertices in a `VertexBuffer` get
/// processed. To do this, it contains an internal index-buffer. This `Buffer` is a list of
/// indices into this `VertexBuffer` (vertex-index). A vertex-index of 0 represents the first
/// vertex in the `VertexBuffer`, a vertex-index of 1 represents the second, 2 represents the
/// third, and so on. The vertex-indices in the index-buffer are read in order; every vertex-index
/// tells the pipeline which vertex to process next.
///
/// Because the same index can re-appear multiple times, duplicate-vertices can be avoided. For
/// instance, if you want to draw a square, you need two triangles, and thus six vertices. Because
/// the same index can reappear multiple times, this means we can instead use 4 vertices, and 6
/// vertex-indices.
///
/// This index-buffer has a few variants. See the `IndexBuffer` documentation for a detailed
/// description.
///
/// The `start` and `end` fields say where in the index-buffer to start and stop reading.
/// Setting `start` to 0, and `end` to the length of the index-buffer, will cause the entire
/// index-buffer to be processed. The `base_vertex` dictates the index of the first vertex
/// in the `VertexBuffer`. This essentially moves the the start of the `VertexBuffer`, to the
/// vertex with this index.
///
/// # Constuction & Handling
/// The `Slice` structure can be constructed automatically when using a `Factory` to create a
/// vertex buffer. If needed, it can also be created manually.
///
/// A `Slice` is required to process a PSO, as it contains the needed information on in what order
/// to draw which vertices. As such, every `draw` call on an `Encoder` requires a `Slice`.
#[derive(Clone, Debug, PartialEq)]
pub struct Slice<R: Resources> {
    /// The start index of the index-buffer. Processing will start at this location in the
    /// index-buffer.
    pub start: VertexCount,
    /// The end index in the index-buffer. Processing will stop at this location (exclusive) in
    /// the index buffer.
    pub end: VertexCount,
    /// This is the index of the first vertex in the `VertexBuffer`. This value will be added to
    /// every index in the index-buffer, effectively moving the start of the `VertexBuffer` to this
    /// base-vertex.
    pub base_vertex: VertexCount,
    /// Instancing configuration.
    pub instances: Option<InstanceParams>,
    /// Represents the type of index-buffer used.
    pub buffer: IndexBuffer<R>,
}

impl<R: Resources> Slice<R> {
    /// Creates a new `Slice` to match the supplied vertex buffer, from start to end, in order.
    pub fn new_match_vertex_buffer<V>(vbuf: &handle::Buffer<R, V>) -> Self
                                      where V: pso::buffer::Structure<Format> {
        Slice {
            start: 0,
            end: vbuf.len() as u32,
            base_vertex: 0,
            instances: None,
            buffer: IndexBuffer::Auto,
        }
    }

    /// Calculates the number of primitives of the specified type in this `Slice`.
    pub fn get_prim_count(&self, prim: Primitive) -> u32 {
        use core::Primitive as p;
        let nv = (self.end - self.start) as u32;
        match prim {
            p::PointList => nv,
            p::LineList => nv / 2,
            p::LineStrip => (nv-1),
            p::TriangleList => nv / 3,
            p::TriangleStrip => (nv-2) / 3,
            p::PatchList(num) => nv / (num as u32),
        }
    }
}

/// Type of index-buffer used in a Slice.
///
/// The `Auto` variant represents a hypothetical index-buffer from 0 to infinity. In other words,
/// all vertices get processed in order. Do note that the `Slice`' `start` and `end` restrictions
/// still apply for this variant. To render every vertex in the `VertexBuffer`, you would set
/// `start` to 0, and `end` to the `VertexBuffer`'s length.
///
/// The `Index*` variants represent an actual `Buffer` with a list of vertex-indices. The numeric
/// suffix specifies the amount of bits to use per index. Each of these also contains a
/// base-vertex. This is the index of the first vertex in the `VertexBuffer`. This value will be
/// added to every index in the index-buffer, effectively moving the start of the `VertexBuffer` to
/// this base-vertex.
///
/// # Construction & Handling
/// A `IndexBuffer` can be constructed using the `IntoIndexBuffer` trait, from either a slice or a
/// `Buffer` of integers, using a factory.
///
/// An `IndexBuffer` is exclusively used to create `Slice`s.
#[derive(Clone, Debug, PartialEq)]
pub enum IndexBuffer<R: Resources> {
    /// Represents a hypothetical index-buffer from 0 to infinity. In other words, all vertices
    /// get processed in order.
    Auto,
    /// An index-buffer with unsigned 16 bit indices.
    Index16(handle::Buffer<R, u16>),
    /// An index-buffer with unsigned 32 bit indices.
    Index32(handle::Buffer<R, u32>),
}

impl<R: Resources> Default for IndexBuffer<R> {
    fn default() -> Self {
        IndexBuffer::Auto
    }
}
/// A helper trait to create `IndexBuffers` from different kinds of data.
pub trait IntoIndexBuffer<R: Resources> {
    /// Turns self into an `IndexBuffer`.
    fn into_index_buffer<F: Factory<R> + ?Sized>(self, factory: &mut F) -> IndexBuffer<R>;
}

impl<R: Resources> IntoIndexBuffer<R> for IndexBuffer<R> {
    fn into_index_buffer<F: Factory<R> + ?Sized>(self, _: &mut F) -> IndexBuffer<R> {
        self
    }
}

impl<R: Resources> IntoIndexBuffer<R> for () {
    fn into_index_buffer<F: Factory<R> + ?Sized>(self, _: &mut F) -> IndexBuffer<R> {
        IndexBuffer::Auto
    }
}

macro_rules! impl_index_buffer {
    ($prim_ty:ty, $buf_ty:ident) => (
        impl<R: Resources> IntoIndexBuffer<R> for handle::Buffer<R, $prim_ty> {
            fn into_index_buffer<F: Factory<R> + ?Sized>(self, _: &mut F) -> IndexBuffer<R> {
                IndexBuffer::$buf_ty(self)
            }
        }

        impl<'s, R: Resources> IntoIndexBuffer<R> for &'s [$prim_ty] {
            fn into_index_buffer<F: Factory<R> + ?Sized>(self, factory: &mut F) -> IndexBuffer<R> {
                factory.create_buffer_immutable(self, buffer::Role::Index, Bind::empty())
                       .unwrap()
                       .into_index_buffer(factory)
            }
        }
    )
}

impl_index_buffer!(u16, Index16);
impl_index_buffer!(u32, Index32);
<commit_msg>Add a gfx::Slice::split_at method.<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Slices
//!
//! See `Slice`-structure documentation for more information on this module.

use core::{handle, buffer};
use core::{Primitive, Resources, VertexCount};
use core::command::InstanceParams;
use core::factory::Factory;
use core::memory::Bind;
use format::Format;
use pso;

/// A `Slice` dictates in which and in what order vertices get processed. It is required for
/// processing a PSO.
///
/// # Overview
/// A `Slice` object in essence dictates in what order the vertices in a `VertexBuffer` get
/// processed. To do this, it contains an internal index-buffer. This `Buffer` is a list of
/// indices into this `VertexBuffer` (vertex-index). A vertex-index of 0 represents the first
/// vertex in the `VertexBuffer`, a vertex-index of 1 represents the second, 2 represents the
/// third, and so on. The vertex-indices in the index-buffer are read in order; every vertex-index
/// tells the pipeline which vertex to process next.
///
/// Because the same index can re-appear multiple times, duplicate-vertices can be avoided. For
/// instance, if you want to draw a square, you need two triangles, and thus six vertices. Because
/// the same index can reappear multiple times, this means we can instead use 4 vertices, and 6
/// vertex-indices.
///
/// This index-buffer has a few variants. See the `IndexBuffer` documentation for a detailed
/// description.
///
/// The `start` and `end` fields say where in the index-buffer to start and stop reading.
/// Setting `start` to 0, and `end` to the length of the index-buffer, will cause the entire
/// index-buffer to be processed. The `base_vertex` dictates the index of the first vertex
/// in the `VertexBuffer`. This essentially moves the the start of the `VertexBuffer`, to the
/// vertex with this index.
///
/// # Constuction & Handling
/// The `Slice` structure can be constructed automatically when using a `Factory` to create a
/// vertex buffer. If needed, it can also be created manually.
///
/// A `Slice` is required to process a PSO, as it contains the needed information on in what order
/// to draw which vertices. As such, every `draw` call on an `Encoder` requires a `Slice`.
#[derive(Clone, Debug, PartialEq)]
pub struct Slice<R: Resources> {
    /// The start index of the index-buffer. Processing will start at this location in the
    /// index-buffer.
    pub start: VertexCount,
    /// The end index in the index-buffer. Processing will stop at this location (exclusive) in
    /// the index buffer.
    pub end: VertexCount,
    /// This is the index of the first vertex in the `VertexBuffer`. This value will be added to
    /// every index in the index-buffer, effectively moving the start of the `VertexBuffer` to this
    /// base-vertex.
    pub base_vertex: VertexCount,
    /// Instancing configuration.
    pub instances: Option<InstanceParams>,
    /// Represents the type of index-buffer used.
    pub buffer: IndexBuffer<R>,
}

impl<R: Resources> Slice<R> {
    /// Creates a new `Slice` to match the supplied vertex buffer, from start to end, in order.
    pub fn new_match_vertex_buffer<V>(vbuf: &handle::Buffer<R, V>) -> Self
                                      where V: pso::buffer::Structure<Format> {
        Slice {
            start: 0,
            end: vbuf.len() as u32,
            base_vertex: 0,
            instances: None,
            buffer: IndexBuffer::Auto,
        }
    }

    /// Calculates the number of primitives of the specified type in this `Slice`.
    pub fn get_prim_count(&self, prim: Primitive) -> u32 {
        use core::Primitive as p;
        let nv = (self.end - self.start) as u32;
        match prim {
            p::PointList => nv,
            p::LineList => nv / 2,
            p::LineStrip => (nv-1),
            p::TriangleList => nv / 3,
            p::TriangleStrip => (nv-2) / 3,
            p::PatchList(num) => nv / (num as u32),
        }
    }

    /// Divides one slice into two at an index.
    ///
    /// The first will contain the range in the index-buffer [self.start, mid) (excluding the index mid itself) and the
    /// second will contain the range [mid, self.end).
    pub fn split_at(&self, mid: VertexCount) -> (Self, Self) {
        let mut first = self.clone();
        let mut second = self.clone();
        first.end = mid;
        second.start = mid;

        (first, second)
    }
}

/// Type of index-buffer used in a Slice.
///
/// The `Auto` variant represents a hypothetical index-buffer from 0 to infinity. In other words,
/// all vertices get processed in order. Do note that the `Slice`' `start` and `end` restrictions
/// still apply for this variant. To render every vertex in the `VertexBuffer`, you would set
/// `start` to 0, and `end` to the `VertexBuffer`'s length.
///
/// The `Index*` variants represent an actual `Buffer` with a list of vertex-indices. The numeric
/// suffix specifies the amount of bits to use per index. Each of these also contains a
/// base-vertex. This is the index of the first vertex in the `VertexBuffer`. This value will be
/// added to every index in the index-buffer, effectively moving the start of the `VertexBuffer` to
/// this base-vertex.
///
/// # Construction & Handling
/// A `IndexBuffer` can be constructed using the `IntoIndexBuffer` trait, from either a slice or a
/// `Buffer` of integers, using a factory.
///
/// An `IndexBuffer` is exclusively used to create `Slice`s.
#[derive(Clone, Debug, PartialEq)]
pub enum IndexBuffer<R: Resources> {
    /// Represents a hypothetical index-buffer from 0 to infinity. In other words, all vertices
    /// get processed in order.
    Auto,
    /// An index-buffer with unsigned 16 bit indices.
    Index16(handle::Buffer<R, u16>),
    /// An index-buffer with unsigned 32 bit indices.
    Index32(handle::Buffer<R, u32>),
}

impl<R: Resources> Default for IndexBuffer<R> {
    fn default() -> Self {
        IndexBuffer::Auto
    }
}
/// A helper trait to create `IndexBuffers` from different kinds of data.
pub trait IntoIndexBuffer<R: Resources> {
    /// Turns self into an `IndexBuffer`.
    fn into_index_buffer<F: Factory<R> + ?Sized>(self, factory: &mut F) -> IndexBuffer<R>;
}

impl<R: Resources> IntoIndexBuffer<R> for IndexBuffer<R> {
    fn into_index_buffer<F: Factory<R> + ?Sized>(self, _: &mut F) -> IndexBuffer<R> {
        self
    }
}

impl<R: Resources> IntoIndexBuffer<R> for () {
    fn into_index_buffer<F: Factory<R> + ?Sized>(self, _: &mut F) -> IndexBuffer<R> {
        IndexBuffer::Auto
    }
}

macro_rules! impl_index_buffer {
    ($prim_ty:ty, $buf_ty:ident) => (
        impl<R: Resources> IntoIndexBuffer<R> for handle::Buffer<R, $prim_ty> {
            fn into_index_buffer<F: Factory<R> + ?Sized>(self, _: &mut F) -> IndexBuffer<R> {
                IndexBuffer::$buf_ty(self)
            }
        }

        impl<'s, R: Resources> IntoIndexBuffer<R> for &'s [$prim_ty] {
            fn into_index_buffer<F: Factory<R> + ?Sized>(self, factory: &mut F) -> IndexBuffer<R> {
                factory.create_buffer_immutable(self, buffer::Role::Index, Bind::empty())
                       .unwrap()
                       .into_index_buffer(factory)
            }
        }
    )
}

impl_index_buffer!(u16, Index16);
impl_index_buffer!(u32, Index32);
<|endoftext|>


<commit_before>use std::string::String;
use std::slice::Iter;

pub struct MessageList {
    messages: Vec<Message>,
}

pub enum MessageType {
    Info,
    Error,
}

pub struct Message {
    text: String,
    ty: MessageType,
}

impl Message {
    pub fn text(&self) -> &str {
        &self.text
    }
}

impl MessageList {

    pub fn new() -> MessageList {
        MessageList { messages: vec![] }
    }

    pub fn info(&mut self, text: &str) {
        self.messages.push(Message { text: String::from_str(text), ty: MessageType::Info });
    }

    pub fn error(&mut self, text: &str) {
        self.messages.push(Message { text: String::from_str(text), ty: MessageType::Error });
    }

    pub fn items(&self) -> Iter<Message> {
        self.messages.iter()
    }

}
<commit_msg>Allow fetching the MessageType of a message<commit_after>use std::string::String;
use std::slice::Iter;

pub struct MessageList {
    messages: Vec<Message>,
}

pub enum MessageType {
    Info,
    Error,
}

pub struct Message {
    text: String,
    ty: MessageType,
}

impl Message {
    pub fn text(&self) -> &str {
        &self.text
    }

    pub fn ty(&self) -> &MessageType {
        &self.ty
    }
}

impl MessageList {

    pub fn new() -> MessageList {
        MessageList { messages: vec![] }
    }

    pub fn info(&mut self, text: &str) {
        self.messages.push(Message { text: String::from_str(text), ty: MessageType::Info });
    }

    pub fn error(&mut self, text: &str) {
        self.messages.push(Message { text: String::from_str(text), ty: MessageType::Error });
    }

    pub fn items(&self) -> Iter<Message> {
        self.messages.iter()
    }

}
<|endoftext|>