<commit_before>use std::cmp::{max, min};
use std::fmt::{self, Debug, Formatter};
use std::rc::Rc;

use piston;
use piston::input::*;
use piston::window::{AdvancedWindow, Window};
use piston_window::{Context, G2d};

use {GameState, Resources, StateTransition};
use sprites::{Sprite, SpriteSheet};
use utils::one_rest_split_iter;
use vecmath::*;
use world::{Entity, EntityLogic, EntityPhysics, MapFactory, Spawnable, World, WorldView};

mod pausemenu;

const CAMERA_MARGIN_X: f64 = 5.0;
const CAMERA_MARGIN_Y: f64 = 5.0;

struct Character {
    player: usize,
    dir: f64,
    jump: bool,
    sprite_sheet: Rc<SpriteSheet>,
}

impl fmt::Debug for Character {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Character for player={:?}", self.player)
    }
}

impl Character {
    fn new(player: usize, resources: &mut Resources) -> Character {
        Character {
            player: player,
            dir: 0.0,
            jump: false,
            sprite_sheet: resources.load_spritesheet(
                "alien/green__0000_idle_1.png"),
        }
    }
}

const CHAR_W: f64 = 0.63;
const CHAR_H: f64 = 1.29;
const MARGIN: f64 = 0.05;

impl EntityLogic for Character {
    fn update(&mut self, entity: &mut EntityPhysics, dt: f64,
              world: &mut WorldView, resources: &Resources, sprite: &mut Option<Sprite>) -> bool {
        // Characters should be in focus
        world.focus(&entity.pos);

        // Read input
        if let Some(i) = resources.input_manager.player_input(0) {
            self.dir = i.x();
            self.jump = i.jump();
        };

        // Movements
        let mut on_ground = false;
        if entity.speed.y() <= 0.05 {
            if let Some(tile) = world.map.tilef(entity.pos.x(),
                                                entity.pos.y() - CHAR_H / 2. - MARGIN) {
                if tile.collide {
                    on_ground = true;
                    entity.speed[1] = 0.0;
                    entity.pos[1] = (entity.pos.y() - CHAR_H / 2. - MARGIN).floor() +
                                    1. + CHAR_H / 2.;
                }
            }
        }
        if on_ground {
            entity.speed[0] = self.dir * 5.0;
            if self.jump {
                entity.speed[1] = 5.0;
            }
        } else {
            if entity.speed.x() * self.dir.signum() < self.dir.abs() * 5.0 {
                entity.speed[0] += self.dir * 20.0 * dt;
            }
            entity.speed[1] += -10.0 * dt;
        }

        let dir = entity.speed.x().signum();
        for height in [-1.0f64, 1.0].iter() {
            if let Some(tile) = world.map.tilef(entity.pos.x() + (CHAR_W / 2. + MARGIN) * dir,
                                                entity.pos.y() - (CHAR_H / 2. - MARGIN) * height) {
                if tile.collide {
                    entity.pos[0] = (entity.pos.x() + (CHAR_W / 2. + MARGIN) * dir).floor() +
                        -dir * (CHAR_W / 2. + 0.5) + 0.5;
                    entity.speed[0] = 0.0;
                    break;
                }
            }
        }

        entity.pos = vec2_add(entity.pos, vec2_scale(entity.speed, dt));

        // Set sprite
        // TODO: Animation
        *sprite = Some(Sprite {
            sheet: self.sprite_sheet.clone(),
            coords: [0., 0., 213., 428.],
            size: [CHAR_W, CHAR_H],
        });

        true
    }
}

struct SimpleSpawn {
    entity_logic: Option<Box<EntityLogic>>,
}

impl SimpleSpawn {
    fn new(entity_logic: Box<EntityLogic>) -> SimpleSpawn {
        SimpleSpawn {
            entity_logic: Some(entity_logic),
        }
    }
}

impl fmt::Debug for SimpleSpawn {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(entity_logic) = self.entity_logic.as_ref() {
            write!(f, "SimpleSpawn({:?})", entity_logic)
        } else {
            write!(f, "SimpleSpawn(empty)")
        }
    }
}

impl Spawnable for SimpleSpawn {
    fn spawn(&mut self, pos: &Vector2) -> (bool, Option<Entity>) {
        (false, self.entity_logic.take().map(|entity_logic| {
            Some(Entity {
                physics: EntityPhysics {
                    pos: pos.clone(),
                    speed: [0.0, 0.0],
                },
                logic: entity_logic,
                sprite: None,
            })
        }).unwrap_or(None))
    }
}

struct Camera {
    aspect_ratio: f64,
    pos: Vector2,
    size: f64,
    update_rate: f64,
}

pub struct Game {
    pub world: World,
    camera: Camera,
}

impl Game {
    pub fn new(map_factory: MapFactory, resources: &mut Resources) -> Game {
        info!("Creating game...");

        if map_factory.nb_players < 1 {
            panic!("Can't play on map meant for 0 players");
        }

        info!("Creating map");
        let mut world = map_factory.create(resources, 42);

        info!("Creating {} characters", 1);
        let character = Character::new(0, resources);
        world.spawnables.push(Box::new(SimpleSpawn::new(Box::new(character))));

        let window_size = resources.window.size();
        let mut game = Game {
            world: world,
            camera: Camera {
                aspect_ratio: window_size.height as f64 / window_size.width as f64,
                pos: [0.0, 0.0],
                size: 10.0,
                update_rate: 1.0,
            }
        };

        // Initial update: spawns characters, set camera, ...
        game.update(0.0, resources);

        game.camera.update_rate = 0.1;
        info!("Camera: aspect_ratio = {:?}", game.camera.aspect_ratio);
        info!("Camera: Initial position: {:?}, {:?}", game.camera.pos, game.camera.size);

        game
    }
}

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

impl GameState for Game {
    fn handle_event(&mut self, event: &piston::input::Event,
                    resources: &mut Resources) -> StateTransition
    {
        if let Some(Button::Keyboard(key)) = event.press_args() {
            if key == Key::Escape {
                return StateTransition::Push(Box::new(pausemenu::PauseMenu::new(resources)));
            }
        }

        resources.input_manager.handle_event(event);

        StateTransition::Continue
    }

    fn update(&mut self, dt: f64, resources: &mut Resources) -> StateTransition {
        resources.input_manager.update(dt);

        let map = &mut self.world.map;
        let spawnables = &mut self.world.spawnables;
        let mut focus = None;
        one_rest_split_iter(&mut self.world.entities, |mut entity, other_entities| {
            let mut world_view = WorldView {
                map: map,
                entities: other_entities,
                spawnables: spawnables,
                focus: &mut focus,
            };
            entity.logic.update(&mut entity.physics, dt,
                                &mut world_view, resources, &mut entity.sprite);
        });
        if let Some((a, b)) = focus {
            let a = [a.x() - CAMERA_MARGIN_X, a.y() - CAMERA_MARGIN_Y];
            let b = [b.x() + CAMERA_MARGIN_X, b.y() + CAMERA_MARGIN_Y];

            let mut camera = &mut self.camera;

            // Compute desired camera position
            let ratio = camera.aspect_ratio;
            let size = (b.x() - a.x()).max((b.y() - a.y())/ratio);
            let pos = [(a.x() + b.x() - size)/2.0,
                       (a.y() + b.y() - size * ratio)/2.0];

            // Update current camera position according to update rate
            camera.pos = vec2_add(vec2_scale(camera.pos, 1.0 - camera.update_rate),
                                  vec2_scale(pos, camera.update_rate));
            camera.size = camera.size * (1.0 - camera.update_rate) + size * camera.update_rate;
        }

        StateTransition::Continue
    }

    fn draw(&mut self, c: Context, g: &mut G2d) {
        use graphics::*;

        let (width, height) = if let Some(v) = c.viewport {
            (v.rect[2], v.rect[3])
        } else {
            warn!("Got Context with no attached Viewport");
            return;
        };

        // Clear the screen.
        clear([0.0, 0.0, 0.5, 1.0], g);

        // Compute transformation from camera
        let zoom = width as f64 / self.camera.size as f64;
        let transform = c.transform
            .trans(0.0, height as f64)
            .scale(1.0, -1.0)
            .scale(zoom, zoom)
            .trans(-self.camera.pos.x(), -self.camera.pos.y());

        let x1 = max(self.camera.pos.x() as i32 - 1, 0);
        let y1 = max(self.camera.pos.y() as i32 - 1, 0);
        let x2 = min((self.camera.pos.x() + self.camera.size + 1.0) as i32,
                     self.world.map.width as i32);
        let y2 = min((self.camera.pos.y() + self.camera.size * self.camera.aspect_ratio + 1.0) as i32,
                            self.world.map.height as i32);

        // Draw map
        for y in y1..y2 {
            for x in x1..x2 {
                if let Some(ref sprite) = self.world.map.tile(x, y).unwrap().sprite {
                    let image = Image::new()
                        .src_rect(sprite.coords)
                        .rect([(x as f64 + 0.5 - sprite.size[0] / 2.0),
                               (y as f64 + 0.5 + sprite.size[1] / 2.0),
                               sprite.size[0] as f64,
                               -sprite.size[1] as f64]);
                    image.draw(&sprite.sheet.texture, &DrawState::default(),
                               transform, g);
                }
            }
        }

        // Debug: draw grid
        for x in x1..x2 {
            rectangle([1.0, 1.0, 1.0, 1.0],
                      rectangle::centered([x as f64, (y1 + y2) as f64 * 0.5,
                                           0.5 / zoom as f64, (y2 - y1) as f64 * 0.5]),
                      transform, g);
        }
        for y in y1..y2 {
            rectangle([1.0, 1.0, 1.0, 1.0],
                      rectangle::centered([(x1 + x2) as f64 * 0.5, y as f64,
                                           (x2 - x1) as f64 * 0.5, 0.5 / zoom as f64]),
                      transform, g);
        }

        // Draw entities
        for entity in self.world.entities.iter() {
            if let Some(ref sprite) = entity.sprite {
                let image = Image::new()
                    .src_rect(sprite.coords)
                    .rect([(entity.physics.pos.x() - sprite.size[0] / 2.0),
                           (entity.physics.pos.y() + sprite.size[1] / 2.0),
                           sprite.size[0],
                           -sprite.size[1]]);
                image.draw(&sprite.sheet.texture, &DrawState::default(),
                           transform, g);
            } else {
                // Debug: circle invisible entities
                let circle = CircleArc::new(
                    [1.0, 0.0, 0.0, 1.0],
                    0.05, 0.0, 2.0 * ::std::f64::consts::PI);
                circle.draw(
                    rectangle::centered([entity.physics.pos.x(), entity.physics.pos.y(), 0.5, 0.5]),
                    &DrawState::default(), transform, g);
            }
        }
    }

    fn pause(&mut self, resources: &mut Resources) {
        resources.window.set_capture_cursor(false);
    }

    fn resume(&mut self, resources: &mut Resources) {
        resources.window.set_capture_cursor(true);
    }
}
<commit_msg>Fix warning<commit_after>use std::cmp::{max, min};
use std::fmt::{self, Debug, Formatter};
use std::rc::Rc;

use piston;
use piston::input::*;
use piston::window::{AdvancedWindow, Window};
use piston_window::{Context, G2d};

use {GameState, Resources, StateTransition};
use sprites::{Sprite, SpriteSheet};
use utils::one_rest_split_iter;
use vecmath::*;
use world::{Entity, EntityLogic, EntityPhysics, MapFactory, Spawnable, World, WorldView};

mod pausemenu;

const CAMERA_MARGIN_X: f64 = 5.0;
const CAMERA_MARGIN_Y: f64 = 5.0;

struct Character {
    player: usize,
    dir: f64,
    jump: bool,
    sprite_sheet: Rc<SpriteSheet>,
}

impl fmt::Debug for Character {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Character for player={:?}", self.player)
    }
}

impl Character {
    fn new(player: usize, resources: &mut Resources) -> Character {
        Character {
            player: player,
            dir: 0.0,
            jump: false,
            sprite_sheet: resources.load_spritesheet(
                "alien/green__0000_idle_1.png"),
        }
    }
}

const CHAR_W: f64 = 0.63;
const CHAR_H: f64 = 1.29;
const MARGIN: f64 = 0.05;

impl EntityLogic for Character {
    fn update(&mut self, entity: &mut EntityPhysics, dt: f64,
              world: &mut WorldView, resources: &Resources, sprite: &mut Option<Sprite>) -> bool {
        // Characters should be in focus
        world.focus(&entity.pos);

        // Read input
        if let Some(i) = resources.input_manager.player_input(0) {
            self.dir = i.x();
            self.jump = i.jump();
        };

        // Movements
        let mut on_ground = false;
        if entity.speed.y() <= 0.05 {
            if let Some(tile) = world.map.tilef(entity.pos.x(),
                                                entity.pos.y() - CHAR_H / 2. - MARGIN) {
                if tile.collide {
                    on_ground = true;
                    entity.speed[1] = 0.0;
                    entity.pos[1] = (entity.pos.y() - CHAR_H / 2. - MARGIN).floor() +
                                    1. + CHAR_H / 2.;
                }
            }
        }
        if on_ground {
            entity.speed[0] = self.dir * 5.0;
            if self.jump {
                entity.speed[1] = 5.0;
            }
        } else {
            if entity.speed.x() * self.dir.signum() < self.dir.abs() * 5.0 {
                entity.speed[0] += self.dir * 20.0 * dt;
            }
            entity.speed[1] += -10.0 * dt;
        }

        let dir = entity.speed.x().signum();
        for height in [-1.0f64, 1.0].iter() {
            if let Some(tile) = world.map.tilef(entity.pos.x() + (CHAR_W / 2. + MARGIN) * dir,
                                                entity.pos.y() - (CHAR_H / 2. - MARGIN) * height) {
                if tile.collide {
                    entity.pos[0] = (entity.pos.x() + (CHAR_W / 2. + MARGIN) * dir).floor() +
                        -dir * (CHAR_W / 2. + 0.5) + 0.5;
                    entity.speed[0] = 0.0;
                    break;
                }
            }
        }

        entity.pos = vec2_add(entity.pos, vec2_scale(entity.speed, dt));

        // Set sprite
        // TODO: Animation
        *sprite = Some(Sprite {
            sheet: self.sprite_sheet.clone(),
            coords: [0., 0., 213., 428.],
            size: [CHAR_W, CHAR_H],
        });

        true
    }
}

struct SimpleSpawn {
    entity_logic: Option<Box<EntityLogic>>,
}

impl SimpleSpawn {
    fn new(entity_logic: Box<EntityLogic>) -> SimpleSpawn {
        SimpleSpawn {
            entity_logic: Some(entity_logic),
        }
    }
}

impl fmt::Debug for SimpleSpawn {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(entity_logic) = self.entity_logic.as_ref() {
            write!(f, "SimpleSpawn({:?})", entity_logic)
        } else {
            write!(f, "SimpleSpawn(empty)")
        }
    }
}

impl Spawnable for SimpleSpawn {
    fn spawn(&mut self, pos: &Vector2) -> (bool, Option<Entity>) {
        (false, self.entity_logic.take().map(|entity_logic| {
            Some(Entity {
                physics: EntityPhysics {
                    pos: pos.clone(),
                    speed: [0.0, 0.0],
                },
                logic: entity_logic,
                sprite: None,
            })
        }).unwrap_or(None))
    }
}

struct Camera {
    aspect_ratio: f64,
    pos: Vector2,
    size: f64,
    update_rate: f64,
}

pub struct Game {
    pub world: World,
    camera: Camera,
}

impl Game {
    pub fn new(map_factory: MapFactory, resources: &mut Resources) -> Game {
        info!("Creating game...");

        if map_factory.nb_players < 1 {
            panic!("Can't play on map meant for 0 players");
        }

        info!("Creating map");
        let mut world = map_factory.create(resources, 42);

        info!("Creating {} characters", 1);
        let character = Character::new(0, resources);
        world.spawnables.push(Box::new(SimpleSpawn::new(Box::new(character))));

        let window_size = resources.window.size();
        let mut game = Game {
            world: world,
            camera: Camera {
                aspect_ratio: window_size.height as f64 / window_size.width as f64,
                pos: [0.0, 0.0],
                size: 10.0,
                update_rate: 1.0,
            }
        };

        // Initial update: spawns characters, set camera, ...
        game.update(0.0, resources);

        game.camera.update_rate = 0.1;
        info!("Camera: aspect_ratio = {:?}", game.camera.aspect_ratio);
        info!("Camera: Initial position: {:?}, {:?}", game.camera.pos, game.camera.size);

        game
    }
}

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

impl GameState for Game {
    fn handle_event(&mut self, event: &piston::input::Event,
                    resources: &mut Resources) -> StateTransition
    {
        if let Some(Button::Keyboard(key)) = event.press_args() {
            if key == Key::Escape {
                return StateTransition::Push(Box::new(pausemenu::PauseMenu::new(resources)));
            }
        }

        resources.input_manager.handle_event(event);

        StateTransition::Continue
    }

    fn update(&mut self, dt: f64, resources: &mut Resources) -> StateTransition {
        resources.input_manager.update(dt);

        let map = &mut self.world.map;
        let spawnables = &mut self.world.spawnables;
        let mut focus = None;
        one_rest_split_iter(&mut self.world.entities, |entity, other_entities| {
            let mut world_view = WorldView {
                map: map,
                entities: other_entities,
                spawnables: spawnables,
                focus: &mut focus,
            };
            entity.logic.update(&mut entity.physics, dt,
                                &mut world_view, resources, &mut entity.sprite);
        });
        if let Some((a, b)) = focus {
            let a = [a.x() - CAMERA_MARGIN_X, a.y() - CAMERA_MARGIN_Y];
            let b = [b.x() + CAMERA_MARGIN_X, b.y() + CAMERA_MARGIN_Y];

            let mut camera = &mut self.camera;

            // Compute desired camera position
            let ratio = camera.aspect_ratio;
            let size = (b.x() - a.x()).max((b.y() - a.y())/ratio);
            let pos = [(a.x() + b.x() - size)/2.0,
                       (a.y() + b.y() - size * ratio)/2.0];

            // Update current camera position according to update rate
            camera.pos = vec2_add(vec2_scale(camera.pos, 1.0 - camera.update_rate),
                                  vec2_scale(pos, camera.update_rate));
            camera.size = camera.size * (1.0 - camera.update_rate) + size * camera.update_rate;
        }

        StateTransition::Continue
    }

    fn draw(&mut self, c: Context, g: &mut G2d) {
        use graphics::*;

        let (width, height) = if let Some(v) = c.viewport {
            (v.rect[2], v.rect[3])
        } else {
            warn!("Got Context with no attached Viewport");
            return;
        };

        // Clear the screen.
        clear([0.0, 0.0, 0.5, 1.0], g);

        // Compute transformation from camera
        let zoom = width as f64 / self.camera.size as f64;
        let transform = c.transform
            .trans(0.0, height as f64)
            .scale(1.0, -1.0)
            .scale(zoom, zoom)
            .trans(-self.camera.pos.x(), -self.camera.pos.y());

        let x1 = max(self.camera.pos.x() as i32 - 1, 0);
        let y1 = max(self.camera.pos.y() as i32 - 1, 0);
        let x2 = min((self.camera.pos.x() + self.camera.size + 1.0) as i32,
                     self.world.map.width as i32);
        let y2 = min((self.camera.pos.y() + self.camera.size * self.camera.aspect_ratio + 1.0) as i32,
                            self.world.map.height as i32);

        // Draw map
        for y in y1..y2 {
            for x in x1..x2 {
                if let Some(ref sprite) = self.world.map.tile(x, y).unwrap().sprite {
                    let image = Image::new()
                        .src_rect(sprite.coords)
                        .rect([(x as f64 + 0.5 - sprite.size[0] / 2.0),
                               (y as f64 + 0.5 + sprite.size[1] / 2.0),
                               sprite.size[0] as f64,
                               -sprite.size[1] as f64]);
                    image.draw(&sprite.sheet.texture, &DrawState::default(),
                               transform, g);
                }
            }
        }

        // Debug: draw grid
        for x in x1..x2 {
            rectangle([1.0, 1.0, 1.0, 1.0],
                      rectangle::centered([x as f64, (y1 + y2) as f64 * 0.5,
                                           0.5 / zoom as f64, (y2 - y1) as f64 * 0.5]),
                      transform, g);
        }
        for y in y1..y2 {
            rectangle([1.0, 1.0, 1.0, 1.0],
                      rectangle::centered([(x1 + x2) as f64 * 0.5, y as f64,
                                           (x2 - x1) as f64 * 0.5, 0.5 / zoom as f64]),
                      transform, g);
        }

        // Draw entities
        for entity in self.world.entities.iter() {
            if let Some(ref sprite) = entity.sprite {
                let image = Image::new()
                    .src_rect(sprite.coords)
                    .rect([(entity.physics.pos.x() - sprite.size[0] / 2.0),
                           (entity.physics.pos.y() + sprite.size[1] / 2.0),
                           sprite.size[0],
                           -sprite.size[1]]);
                image.draw(&sprite.sheet.texture, &DrawState::default(),
                           transform, g);
            } else {
                // Debug: circle invisible entities
                let circle = CircleArc::new(
                    [1.0, 0.0, 0.0, 1.0],
                    0.05, 0.0, 2.0 * ::std::f64::consts::PI);
                circle.draw(
                    rectangle::centered([entity.physics.pos.x(), entity.physics.pos.y(), 0.5, 0.5]),
                    &DrawState::default(), transform, g);
            }
        }
    }

    fn pause(&mut self, resources: &mut Resources) {
        resources.window.set_capture_cursor(false);
    }

    fn resume(&mut self, resources: &mut Resources) {
        resources.window.set_capture_cursor(true);
    }
}
<|endoftext|>


<commit_before>//! OpenGL arrays of verticies, all shaded with the same program.
use gl;
use gl::types::*;
use std::mem;
use std::ptr;
use std::raw;
use libc::types::common::c95;
use vertex;

/// Gets the id number for a given input of the shader program.
#[allow(non_snake_case_functions)]
unsafe fn glGetAttribLocation(shader_program: GLuint, name: &str) -> GLint {
  name.with_c_str(|ptr| gl::GetAttribLocation(shader_program, ptr))
}

unsafe fn aligned_slice_to_ptr<T>(vs: &[T], alignment: uint) -> *const c95::c_void {
  let vs_as_slice : raw::Slice<T> = mem::transmute(vs);
  assert_eq!(vs_as_slice.data as uint & (alignment - 1), 0);
  vs_as_slice.data as *const c95::c_void
}

/// A fixed-capacity array of GLfloat-based structures passed to OpenGL.
pub struct GLBuffer<T> {
  vertex_array: u32,
  vertex_buffer: u32,
  length: uint,
  capacity: uint,
}

impl<T: Clone> GLBuffer<T> {
  #[inline]
  /// An empty `GLBuffer`.
  pub unsafe fn null() -> GLBuffer<T> {
    GLBuffer {
      vertex_array: -1 as u32,
      vertex_buffer: -1 as u32,
      length: 0,
      capacity: 0,
    }
  }

  #[inline]
  /// Creates a new array of objects on the GPU.
  pub unsafe fn new(shader_program: GLuint, attribs: &[vertex::AttribData], capacity: uint) -> GLBuffer<T> {
    let mut vertex_array = 0;
    let mut vertex_buffer = 0;
    gl::GenVertexArrays(1, &mut vertex_array);
    gl::GenBuffers(1, &mut vertex_buffer);

    gl::BindVertexArray(vertex_array);
    gl::BindBuffer(gl::ARRAY_BUFFER, vertex_buffer);

    let mut offset = 0;
    for attrib in attribs.iter() {
      let shader_attrib = glGetAttribLocation(shader_program, attrib.name) as GLuint;
      assert!(shader_attrib != -1, "shader attribute \"{}\" not found", attrib.name);

      gl::EnableVertexAttribArray(shader_attrib);
      gl::VertexAttribPointer(
          shader_attrib,
          attrib.size as i32,
          gl::FLOAT,
          gl::FALSE as GLboolean,
          mem::size_of::<T>() as i32,
          ptr::null().offset(offset),
      );
      offset += (attrib.size * mem::size_of::<GLfloat>()) as int;
    }

    // Check that the attribs are sized correctly.
    assert_eq!(offset, mem::size_of::<T>() as int);

    gl::BufferData(
      gl::ARRAY_BUFFER,
      (capacity * mem::size_of::<T>()) as GLsizeiptr,
      ptr::null(),
      gl::DYNAMIC_DRAW,
    );

    GLBuffer {
      vertex_array: vertex_array,
      vertex_buffer: vertex_buffer,
      length: 0,
      capacity: capacity,
    }
  }

  /// Analog of vec::Vector::swap_remove`, but for GLBuffer data.
  pub unsafe fn swap_remove(&mut self, span: uint, i: uint) {
    gl::BindVertexArray(self.vertex_array);
    gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer);

    self.length -= span;
    let size = mem::size_of::<T>();
    let copy_size = (size * span) as uint;
    let mut bytes: Vec<T> = Vec::with_capacity(span);
    bytes.set_len(span);
    gl::GetBufferSubData(
      gl::ARRAY_BUFFER,
      (self.length * size) as i64,
      copy_size as i64,
      mem::transmute(&bytes.as_mut_slice()[0]),
    );
    gl::BufferSubData(
      gl::ARRAY_BUFFER,
      (i * copy_size) as i64,
      copy_size as i64,
      aligned_slice_to_ptr(bytes.slice(0, span), 16),
    );
  }

  #[inline]
  /// Add a set of triangles to the set of triangles to render.
  pub unsafe fn push(&mut self, vs: &[T]) {
    assert!(
      self.length + vs.len() <= self.capacity,
      "GLBuffer::push: {} into a {}/{} full GLbuffer", vs.len(), self.length, self.capacity);

    gl::BindVertexArray(self.vertex_array);
    gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer);

    let size = mem::size_of::<T>() as i64;
    gl::BufferSubData(
      gl::ARRAY_BUFFER,
      size * self.length as i64,
      size * vs.len() as i64,
      aligned_slice_to_ptr(vs, 4)
    );

    self.length += vs.len();
  }

  #[inline]
  /// Draws all the queued triangles to the screen.
  pub fn draw(&self, mode: GLenum) {
    self.draw_slice(mode, 0, self.length);
  }

  /// Draw some subset of the triangle array.
  pub fn draw_slice(&self, mode: GLenum, start: uint, len: uint) {
    gl::BindVertexArray(self.vertex_array);
    gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer);

    gl::DrawArrays(mode, start as i32, len as i32);
  }
}

#[unsafe_destructor]
impl<T> Drop for GLBuffer<T> {
  #[inline]
  fn drop(&mut self) {
    unsafe {
      gl::DeleteBuffers(1, &self.vertex_buffer);
      gl::DeleteVertexArrays(1, &self.vertex_array);
    }
  }
}
<commit_msg>GLBuffer::swap_remove uses gl::CopyBufferSubData<commit_after>//! OpenGL arrays of verticies, all shaded with the same program.
use gl;
use gl::types::*;
use std::mem;
use std::ptr;
use std::raw;
use libc::types::common::c95;
use vertex;

/// Gets the id number for a given input of the shader program.
#[allow(non_snake_case_functions)]
unsafe fn glGetAttribLocation(shader_program: GLuint, name: &str) -> GLint {
  name.with_c_str(|ptr| gl::GetAttribLocation(shader_program, ptr))
}

unsafe fn aligned_slice_to_ptr<T>(vs: &[T], alignment: uint) -> *const c95::c_void {
  let vs_as_slice : raw::Slice<T> = mem::transmute(vs);
  assert_eq!(vs_as_slice.data as uint & (alignment - 1), 0);
  vs_as_slice.data as *const c95::c_void
}

/// A fixed-capacity array of GLfloat-based structures passed to OpenGL.
pub struct GLBuffer<T> {
  vertex_array: u32,
  vertex_buffer: u32,
  length: uint,
  capacity: uint,
}

impl<T: Clone> GLBuffer<T> {
  #[inline]
  /// An empty `GLBuffer`.
  pub unsafe fn null() -> GLBuffer<T> {
    GLBuffer {
      vertex_array: -1 as u32,
      vertex_buffer: -1 as u32,
      length: 0,
      capacity: 0,
    }
  }

  #[inline]
  /// Creates a new array of objects on the GPU.
  pub unsafe fn new(shader_program: GLuint, attribs: &[vertex::AttribData], capacity: uint) -> GLBuffer<T> {
    let mut vertex_array = 0;
    let mut vertex_buffer = 0;
    gl::GenVertexArrays(1, &mut vertex_array);
    gl::GenBuffers(1, &mut vertex_buffer);

    gl::BindVertexArray(vertex_array);
    gl::BindBuffer(gl::ARRAY_BUFFER, vertex_buffer);

    let mut offset = 0;
    for attrib in attribs.iter() {
      let shader_attrib = glGetAttribLocation(shader_program, attrib.name) as GLuint;
      assert!(shader_attrib != -1, "shader attribute \"{}\" not found", attrib.name);

      gl::EnableVertexAttribArray(shader_attrib);
      gl::VertexAttribPointer(
          shader_attrib,
          attrib.size as i32,
          gl::FLOAT,
          gl::FALSE as GLboolean,
          mem::size_of::<T>() as i32,
          ptr::null().offset(offset),
      );
      offset += (attrib.size * mem::size_of::<GLfloat>()) as int;
    }

    // Check that the attribs are sized correctly.
    assert_eq!(offset, mem::size_of::<T>() as int);

    gl::BufferData(
      gl::ARRAY_BUFFER,
      (capacity * mem::size_of::<T>()) as GLsizeiptr,
      ptr::null(),
      gl::DYNAMIC_DRAW,
    );

    GLBuffer {
      vertex_array: vertex_array,
      vertex_buffer: vertex_buffer,
      length: 0,
      capacity: capacity,
    }
  }

  /// Analog of vec::Vector::swap_remove`, but for GLBuffer data.
  pub unsafe fn swap_remove(&mut self, span: uint, i: uint) {
    let i = i * span;
    assert!(i < self.length);
    self.length -= span;
    if i == self.length {
      // just remove, no swap.
      return;
    }

    gl::BindVertexArray(self.vertex_array);
    gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer);

    let byte_size = mem::size_of::<T>() as i64;
    gl::CopyBufferSubData(
      gl::ARRAY_BUFFER,
      gl::ARRAY_BUFFER,
      self.length as i64 * byte_size,
      i as i64 * byte_size,
      span as i64 * byte_size
    );
  }

  #[inline]
  /// Add a set of triangles to the set of triangles to render.
  pub unsafe fn push(&mut self, vs: &[T]) {
    assert!(
      self.length + vs.len() <= self.capacity,
      "GLBuffer::push: {} into a {}/{} full GLbuffer", vs.len(), self.length, self.capacity);

    gl::BindVertexArray(self.vertex_array);
    gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer);

    let size = mem::size_of::<T>() as i64;
    gl::BufferSubData(
      gl::ARRAY_BUFFER,
      size * self.length as i64,
      size * vs.len() as i64,
      aligned_slice_to_ptr(vs, 4)
    );

    self.length += vs.len();
  }

  #[inline]
  /// Draws all the queued triangles to the screen.
  pub fn draw(&self, mode: GLenum) {
    self.draw_slice(mode, 0, self.length);
  }

  /// Draw some subset of the triangle array.
  pub fn draw_slice(&self, mode: GLenum, start: uint, len: uint) {
    gl::BindVertexArray(self.vertex_array);
    gl::BindBuffer(gl::ARRAY_BUFFER, self.vertex_buffer);

    gl::DrawArrays(mode, start as i32, len as i32);
  }
}

#[unsafe_destructor]
impl<T> Drop for GLBuffer<T> {
  #[inline]
  fn drop(&mut self) {
    unsafe {
      gl::DeleteBuffers(1, &self.vertex_buffer);
      gl::DeleteVertexArrays(1, &self.vertex_array);
    }
  }
}
<|endoftext|>


<commit_before>// Copyright 2014 Google Inc. All rights reserved.
//
// 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.

#![crate_type="bin"]

#![allow(dead_code)]

#![warn(non_upper_case_globals)]
#![warn(non_camel_case_types)]
#![warn(unused_qualifications)]

// Unstable APIs:
#![feature(test)]

#![feature(custom_attribute)]
#![feature(custom_derive)]
#![feature(plugin)]

#![feature(fnbox)]

// Standard Rust imports
extern crate rand;
extern crate test;
extern crate time;

// Rust bindings
extern crate sodiumoxide;
extern crate sqlite3;

extern crate rustc_serialize;
extern crate threadpool;

// Argument parsing
#[macro_use]
extern crate clap;

// Testing
#[cfg(test)]
extern crate quickcheck;

use std::convert::From;
use std::path::PathBuf;
use std::borrow::ToOwned;

use clap::{App, SubCommand};

mod cumulative_counter;
mod ordered_collection;
mod periodic_timer;
mod unique_priority_queue;

mod hat;
mod listdir;
mod process;

mod hash_index;
mod hash_tree;

mod blob_index;
mod blob_store;

mod key_index;
mod key_store;

mod gc;
mod gc_noop;
mod gc_rc;
mod tags;

mod snapshot_index;

static MAX_BLOB_SIZE: usize = 4 * 1024 * 1024;

fn blob_dir() -> PathBuf { PathBuf::from("blobs") }

#[cfg(not(test))]
fn license() {
  println!(include_str!("../../LICENSE"));
  println!("clap (Command Line Argument Parser) License:");
  println!(include_str!("../../LICENSE-CLAP"));
}

#[cfg(not(test))]
fn main() {
    // Because "snapshot" and "checkout" use the exact same type of arguments, we can make a template
    // This template defines two positional arguments, both are required
    let arg_template = "<NAME> 'Name of the snapshot'
                        <PATH> 'The path of the snapshot'";

    // Create valid arguments
    let matches = App::new("hat")
                        // get version from Cargo.toml
                        .version(&format!("v{}", crate_version!())[..])
                        .about("Create backup snapshots")
                        .arg_from_usage("--license 'Display the license'")
                        .subcommand(SubCommand::with_name("snapshot")
                            .about("Create a snapshot")
                            .args_from_usage(arg_template))
                        .subcommand(SubCommand::with_name("checkout")
                            .about("Checkout a snapshot")
                            .args_from_usage(arg_template))
                        .subcommand(SubCommand::with_name("commit")
                            .about("Commit a snapshot")
                            .arg_from_usage("<NAME> 'Name of the snapshot'"))
                        .subcommand(SubCommand::with_name("delete")
                            .about("Delete a snapshot")
                            .args_from_usage("<NAME> 'Name of the snapshot family'
                                              <ID> 'The snapshot id to delete'"))
                        .subcommand(SubCommand::with_name("gc")
                            .args_from_usage("-p --pretend 'Do not modify any data'")
                            .about("Garbage collect: identify and remove unused data blocks."))
                        .get_matches();

    // Check for license flag
    if matches.is_present("license") { license(); std::process::exit(0); }

    // Initialize sodium (must only be called once)
    sodiumoxide::init();

    match matches.subcommand() {
        ("snapshot", Some(matches)) => {
            let name = matches.value_of("NAME").unwrap().to_owned();
            let path = matches.value_of("PATH").unwrap();

            let backend = blob_store::FileBackend::new(blob_dir());
            let hat = hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);

            let family_opt = hat.open_family(name.clone());
            let family = family_opt.expect(&format!("Could not open family '{}'", name));

            family.snapshot_dir(PathBuf::from(path));
            family.flush();

            println!("Waiting for final flush...");
        },
        ("checkout", Some(matches)) => {
            let name = matches.value_of("NAME").unwrap().to_owned();
            let path = matches.value_of("PATH").unwrap();

            let backend = blob_store::FileBackend::new(blob_dir());
            let hat = hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);

            hat.checkout_in_dir(name.clone(), PathBuf::from(path));
        },
        ("commit", Some(matches)) => {
            let name = matches.value_of("NAME").unwrap().to_owned();

            let backend = blob_store::FileBackend::new(blob_dir());
            let mut hat = hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);

            hat.commit(name, None);
        },
        ("delete", Some(matches)) => {
            let name = matches.value_of("NAME").unwrap().to_owned();
            let id = matches.value_of("ID").unwrap().to_owned();

            let backend = blob_store::FileBackend::new(blob_dir());
            let mut hat = hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);

            hat.deregister(name, id.parse::<i64>().unwrap());
        },
        ("gc", Some(_matches)) => {
            let backend = blob_store::FileBackend::new(blob_dir());
            let mut hat = hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);
            hat.gc();
        },
        _ => {
            println!("No subcommand specified\n{}\nFor more information re-run with --help", matches.usage());
            std::process::exit(1);
        }
    }
}
<commit_msg>Add subcommand 'resume' that just triggers resume.<commit_after>// Copyright 2014 Google Inc. All rights reserved.
//
// 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.

#![crate_type="bin"]

#![allow(dead_code)]

#![warn(non_upper_case_globals)]
#![warn(non_camel_case_types)]
#![warn(unused_qualifications)]

// Unstable APIs:
#![feature(test)]

#![feature(custom_attribute)]
#![feature(custom_derive)]
#![feature(plugin)]

#![feature(fnbox)]

// Standard Rust imports
extern crate rand;
extern crate test;
extern crate time;

// Rust bindings
extern crate sodiumoxide;
extern crate sqlite3;

extern crate rustc_serialize;
extern crate threadpool;

// Argument parsing
#[macro_use]
extern crate clap;

// Testing
#[cfg(test)]
extern crate quickcheck;

use std::convert::From;
use std::path::PathBuf;
use std::borrow::ToOwned;

use clap::{App, SubCommand};

mod cumulative_counter;
mod ordered_collection;
mod periodic_timer;
mod unique_priority_queue;

mod hat;
mod listdir;
mod process;

mod hash_index;
mod hash_tree;

mod blob_index;
mod blob_store;

mod key_index;
mod key_store;

mod gc;
mod gc_noop;
mod gc_rc;
mod tags;

mod snapshot_index;

static MAX_BLOB_SIZE: usize = 4 * 1024 * 1024;

fn blob_dir() -> PathBuf { PathBuf::from("blobs") }

#[cfg(not(test))]
fn license() {
  println!(include_str!("../../LICENSE"));
  println!("clap (Command Line Argument Parser) License:");
  println!(include_str!("../../LICENSE-CLAP"));
}

#[cfg(not(test))]
fn main() {
    // Because "snapshot" and "checkout" use the exact same type of arguments, we can make a template
    // This template defines two positional arguments, both are required
    let arg_template = "<NAME> 'Name of the snapshot'
                        <PATH> 'The path of the snapshot'";

    // Create valid arguments
    let matches = App::new("hat")
                        // get version from Cargo.toml
                        .version(&format!("v{}", crate_version!())[..])
                        .about("Create backup snapshots")
                        .arg_from_usage("--license 'Display the license'")
                        .subcommand(SubCommand::with_name("snapshot")
                            .about("Create a snapshot")
                            .args_from_usage(arg_template))
                        .subcommand(SubCommand::with_name("checkout")
                            .about("Checkout a snapshot")
                            .args_from_usage(arg_template))
                        .subcommand(SubCommand::with_name("commit")
                            .about("Commit a snapshot")
                            .arg_from_usage("<NAME> 'Name of the snapshot'"))
                        .subcommand(SubCommand::with_name("delete")
                            .about("Delete a snapshot")
                            .args_from_usage("<NAME> 'Name of the snapshot family'
                                              <ID> 'The snapshot id to delete'"))
                        .subcommand(SubCommand::with_name("gc")
                            .about("Garbage collect: identify and remove unused data blocks.")
                            .args_from_usage("-p --pretend 'Do not modify any data'"))
                        .subcommand(SubCommand::with_name("resume")
                            .about("Resume previous failed command."))
                        .get_matches();

    // Check for license flag
    if matches.is_present("license") { license(); std::process::exit(0); }

    // Initialize sodium (must only be called once)
    sodiumoxide::init();

    match matches.subcommand() {
        ("resume", Some(_matches)) => {
            // Setting up the repository triggers automatic resume.
            let backend = blob_store::FileBackend::new(blob_dir());
            hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);
        },
        ("snapshot", Some(matches)) => {
            let name = matches.value_of("NAME").unwrap().to_owned();
            let path = matches.value_of("PATH").unwrap();

            let backend = blob_store::FileBackend::new(blob_dir());
            let hat = hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);

            let family_opt = hat.open_family(name.clone());
            let family = family_opt.expect(&format!("Could not open family '{}'", name));

            family.snapshot_dir(PathBuf::from(path));
            family.flush();

            println!("Waiting for final flush...");
        },
        ("checkout", Some(matches)) => {
            let name = matches.value_of("NAME").unwrap().to_owned();
            let path = matches.value_of("PATH").unwrap();

            let backend = blob_store::FileBackend::new(blob_dir());
            let hat = hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);

            hat.checkout_in_dir(name.clone(), PathBuf::from(path));
        },
        ("commit", Some(matches)) => {
            let name = matches.value_of("NAME").unwrap().to_owned();

            let backend = blob_store::FileBackend::new(blob_dir());
            let mut hat = hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);

            hat.commit(name, None);
        },
        ("delete", Some(matches)) => {
            let name = matches.value_of("NAME").unwrap().to_owned();
            let id = matches.value_of("ID").unwrap().to_owned();

            let backend = blob_store::FileBackend::new(blob_dir());
            let mut hat = hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);

            hat.deregister(name, id.parse::<i64>().unwrap());
        },
        ("gc", Some(_matches)) => {
            let backend = blob_store::FileBackend::new(blob_dir());
            let mut hat = hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);
            hat.gc();
        },
        _ => {
            println!("No subcommand specified\n{}\nFor more information re-run with --help", matches.usage());
            std::process::exit(1);
        }
    }
}
<|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::image::manifest::Manifest;
use crate::image::manifest_def::ManifestDef;
use crate::util::parse_int::ParseInt;
use anyhow::{ensure, Result};
use std::convert::TryInto;
use std::fs::File;
use std::io::{Read, Write};
use std::mem::size_of;
use std::path::{Path, PathBuf};
use thiserror::Error;

use zerocopy::LayoutVerified;

#[derive(Debug, Error)]
pub enum ImageError {
    #[error("Incomplete read: expected to read {0} bytes but read {1} bytes")]
    IncompleteRead(usize, usize),
    #[error("Failed to parse image manifest.")]
    Parse,
}

#[repr(C)]
#[derive(Debug)]
pub struct Image {
    bytes: Vec<u8>,
}

#[derive(Debug)]
pub enum ImageChunk {
    Concat(PathBuf),
    Offset(PathBuf, usize),
}

#[derive(Debug, Default)]
pub struct ImageAssembler {
    pub size: usize,
    pub mirrored: bool,
    pub chunks: Vec<ImageChunk>,
}

impl Image {
    /// Creates an `Image` from a given input binary.
    pub fn read_from_file(path: &Path) -> Result<Image> {
        let file_len = path.metadata()?.len() as usize;
        // Create a buffer with the same alignment as Manifest that's as least as long as the input
        // file.
        let mut aligned: Vec<Manifest> =
            Vec::with_capacity((0..file_len).step_by(size_of::<Manifest>()).len());

        // Convert the aligned buffer to a Vec<u8> with the same capacity, but length equal to the
        // size of the input file.
        let vec_ptr = aligned.as_mut_ptr() as *mut u8;
        let vec_cap = aligned.capacity() * size_of::<Manifest>();

        // Forget `aligned` so we don't double free.
        std::mem::forget(aligned);

        // Convert our `aligned` Vec<Manifest> to a Vec<u8> with the same capacity and len equal to
        // the size of the input image. This should mean that the new Vec<u8> has the same
        // alignment as Manifest so we can successfully use LayoutVerified later to reinterpret the
        // head of the image as a Manifest.
        let mut buf: Vec<u8> = unsafe { Vec::from_raw_parts(vec_ptr, file_len, vec_cap) };

        // Read the image into our buffer.
        let mut file = File::open(path)?;
        file.read(&mut *buf)?;

        Ok(Image { bytes: buf })
    }

    /// Write out the `Image` to a file at the given `path`.
    pub fn write_to_file(self, path: &Path) -> Result<()> {
        let mut file = File::create(path)?;
        file.write(self.bytes.as_slice())?;
        Ok(())
    }

    /// Overwrites all fields in the image's manifest that are defined in `other`.
    pub fn overwrite_manifest(&mut self, other: ManifestDef) -> Result<()> {
        let (manifest_slice, _) = self.bytes.split_at_mut(size_of::<Manifest>());
        let manifest_layout: LayoutVerified<&mut [u8], Manifest> =
            LayoutVerified::new(&mut *manifest_slice).ok_or(ImageError::Parse)?;
        let manifest: &mut Manifest = manifest_layout.into_mut();
        let mut manifest_def: ManifestDef = (&*manifest).try_into()?;
        manifest_def.overwrite_fields(other);
        *manifest = manifest_def.try_into()?;
        Ok(())
    }
}

impl ImageAssembler {
    /// Creates an `ImageAssembler` with a given `size` and mirroring parameters.
    pub fn with_params(size: usize, mirrored: bool) -> Self {
        ImageAssembler {
            size,
            mirrored,
            ..Default::default()
        }
    }

    /// Creates an `ImageAssembler` with default parameters for OpenTitan: a 1MiB image which is mirrored.
    pub fn new() -> Self {
        Self::with_params(0x100000, true)
    }

    /// Parse a list of strings into chunks to be assembled.
    /// Each string may be a filename or a filename@offset describing where in the assembled image the contents of the file should appear.
    /// The offset is an integer expressed in any of the bases accepted by [`ParseInt`].
    pub fn parse(&mut self, chunks: &[impl AsRef<str>]) -> Result<()> {
        for chunk in chunks {
            if let Some((file, offset)) = chunk.as_ref().split_once('@') {
                self.chunks.push(ImageChunk::Offset(
                    PathBuf::from(file),
                    usize::from_str(offset)?,
                ));
            } else {
                self.chunks
                    .push(ImageChunk::Concat(PathBuf::from(chunk.as_ref())));
            }
        }
        Ok(())
    }

    // Read a file into a buffer.  Ensure the entire file is read.
    fn read(path: &Path, buf: &mut [u8]) -> Result<usize> {
        let mut file = File::open(path)?;
        let len = file.metadata()?.len() as usize;
        let n = file.read(buf)?;
        ensure!(len == n, ImageError::IncompleteRead(len, n));
        Ok(n)
    }

    /// Assemble the image according to the parameters and parsed chunk specifications.
    pub fn assemble(&self) -> Result<Vec<u8>> {
        let size = if self.mirrored {
            self.size / 2
        } else {
            self.size
        };
        let mut image = vec![0xff; size];
        let mut pos = 0;
        for chunk in &self.chunks {
            match chunk {
                ImageChunk::Concat(path) => {
                    let n = Self::read(path, &mut image[pos..])?;
                    pos += n;
                }
                ImageChunk::Offset(path, offset) => {
                    let n = Self::read(path, &mut image[*offset..])?;
                    pos = offset + n;
                }
            }
        }
        if self.mirrored {
            image.extend_from_within(..size);
        }
        Ok(image)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::testdata;

    #[test]
    fn test_assemble_concat() -> Result<()> {
        // Test image assembly by concatenation.
        let mut image = ImageAssembler::with_params(16, false);
        image.parse(&[
            testdata!("hello.txt").to_str().unwrap(),
            testdata!("world.txt").to_str().unwrap(),
        ])?;
        let data = image.assemble()?;
        assert_eq!(data, b"HelloWorld\xff\xff\xff\xff\xff\xff");
        Ok(())
    }

    #[test]
    fn test_assemble_offset() -> Result<()> {
        // Test image assembly by explicit offsets.
        let mut image = ImageAssembler::with_params(16, false);
        image.parse(&[
            testdata!("hello.txt@0").to_str().unwrap(),
            testdata!("world.txt@0x8").to_str().unwrap(),
        ])?;
        let data = image.assemble()?;
        assert_eq!(data, b"Hello\xff\xff\xffWorld\xff\xff\xff");
        Ok(())
    }

    #[test]
    fn test_assemble_mirrored() -> Result<()> {
        // Test image assembly with mirroring.
        let mut image = ImageAssembler::with_params(20, true);
        image.parse(&[
            testdata!("hello.txt").to_str().unwrap(),
            testdata!("world.txt").to_str().unwrap(),
        ])?;
        let data = image.assemble()?;
        assert_eq!(data, b"HelloWorldHelloWorld");
        Ok(())
    }

    #[test]
    fn test_assemble_mirrored_offset_error() -> Result<()> {
        // Test image assembly where one of the source files isn't read completely.
        let mut image = ImageAssembler::with_params(16, true);
        image.parse(&[
            testdata!("hello.txt@0").to_str().unwrap(),
            testdata!("world.txt@0x5").to_str().unwrap(),
        ])?;
        let err = image.assemble().unwrap_err();
        assert_eq!(
            err.to_string(),
            "Incomplete read: expected to read 5 bytes but read 3 bytes"
        );
        Ok(())
    }

    #[test]
    fn test_load_image() {
        // Read and write back image.
        let image = Image::read_from_file(&testdata!("test_image.bin")).unwrap();
        image
            .write_to_file(&testdata!("test_image_out.bin"))
            .unwrap();

        // Ensure the result is identical to the original.
        let (mut orig_bytes, mut res_bytes) = (Vec::<u8>::new(), Vec::<u8>::new());
        File::open(&testdata!("test_image.bin"))
            .unwrap()
            .read_to_end(&mut orig_bytes)
            .unwrap();
        File::open(&testdata!("test_image_out.bin"))
            .unwrap()
            .read_to_end(&mut res_bytes)
            .unwrap();
        assert_eq!(orig_bytes, res_bytes);
    }
}
<commit_msg>[opentitanlib] Alternate to unsafe code for alignment<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::image::manifest::Manifest;
use crate::image::manifest_def::ManifestDef;
use crate::util::parse_int::ParseInt;
use anyhow::{ensure, Result};
use std::convert::TryInto;
use std::fs::File;
use std::io::{Read, Write};
use std::mem::size_of;
use std::path::{Path, PathBuf};
use thiserror::Error;

use zerocopy::LayoutVerified;

#[derive(Debug, Error)]
pub enum ImageError {
    #[error("Incomplete read: expected to read {0} bytes but read {1} bytes")]
    IncompleteRead(usize, usize),
    #[error("Failed to parse image manifest.")]
    Parse,
}

#[repr(C)]
#[derive(Debug)]
pub struct ImageData {
    pub bytes: [u8; Image::MAX_SIZE],
    _align: [Manifest; 0],
}

impl Default for ImageData {
    fn default() -> Self {
        ImageData {
            bytes: [0xFF; Image::MAX_SIZE],
            _align: [],
        }
    }
}

#[derive(Debug, Default)]
pub struct Image {
    data: Box<ImageData>,
    size: usize,
}

#[derive(Debug)]
pub enum ImageChunk {
    Concat(PathBuf),
    Offset(PathBuf, usize),
}

#[derive(Debug, Default)]
pub struct ImageAssembler {
    pub size: usize,
    pub mirrored: bool,
    pub chunks: Vec<ImageChunk>,
}

impl Image {
    const MAX_SIZE: usize = 512 * 1024;
    /// Creates an `Image` from a given input binary.
    pub fn from_reader(mut r: impl Read) -> Result<Self> {
        let mut image = Image::default();
        image.size = r.read(&mut image.data.bytes)?;
        Ok(image)
    }

    pub fn to_writer(&self, w: &mut impl Write) -> Result<()> {
        w.write_all(&self.data.bytes[..self.size])?;
        Ok(())
    }

    pub fn read_from_file(path: &Path) -> Result<Image> {
        let file = File::open(path)?;
        Self::from_reader(file)
    }

    /// Write out the `Image` to a file at the given `path`.
    pub fn write_to_file(self, path: &Path) -> Result<()> {
        let mut file = File::create(path)?;
        self.to_writer(&mut file)
    }

    /// Overwrites all fields in the image's manifest that are defined in `other`.
    pub fn overwrite_manifest(&mut self, other: ManifestDef) -> Result<()> {
        let manifest_slice = &mut self.data.bytes[0..size_of::<Manifest>()];
        let manifest_layout: LayoutVerified<&mut [u8], Manifest> =
            LayoutVerified::new(&mut *manifest_slice).ok_or(ImageError::Parse)?;
        let manifest: &mut Manifest = manifest_layout.into_mut();
        let mut manifest_def: ManifestDef = (&*manifest).try_into()?;
        manifest_def.overwrite_fields(other);
        *manifest = manifest_def.try_into()?;
        Ok(())
    }
}

impl ImageAssembler {
    /// Creates an `ImageAssembler` with a given `size` and mirroring parameters.
    pub fn with_params(size: usize, mirrored: bool) -> Self {
        ImageAssembler {
            size,
            mirrored,
            ..Default::default()
        }
    }

    /// Creates an `ImageAssembler` with default parameters for OpenTitan: a 1MiB image which is mirrored.
    pub fn new() -> Self {
        Self::with_params(0x100000, true)
    }

    /// Parse a list of strings into chunks to be assembled.
    /// Each string may be a filename or a filename@offset describing where in the assembled image the contents of the file should appear.
    /// The offset is an integer expressed in any of the bases accepted by [`ParseInt`].
    pub fn parse(&mut self, chunks: &[impl AsRef<str>]) -> Result<()> {
        for chunk in chunks {
            if let Some((file, offset)) = chunk.as_ref().split_once('@') {
                self.chunks.push(ImageChunk::Offset(
                    PathBuf::from(file),
                    usize::from_str(offset)?,
                ));
            } else {
                self.chunks
                    .push(ImageChunk::Concat(PathBuf::from(chunk.as_ref())));
            }
        }
        Ok(())
    }

    // Read a file into a buffer.  Ensure the entire file is read.
    fn read(path: &Path, buf: &mut [u8]) -> Result<usize> {
        let mut file = File::open(path)?;
        let len = file.metadata()?.len() as usize;
        let n = file.read(buf)?;
        ensure!(len == n, ImageError::IncompleteRead(len, n));
        Ok(n)
    }

    /// Assemble the image according to the parameters and parsed chunk specifications.
    pub fn assemble(&self) -> Result<Vec<u8>> {
        let size = if self.mirrored {
            self.size / 2
        } else {
            self.size
        };
        let mut image = vec![0xff; size];
        let mut pos = 0;
        for chunk in &self.chunks {
            match chunk {
                ImageChunk::Concat(path) => {
                    let n = Self::read(path, &mut image[pos..])?;
                    pos += n;
                }
                ImageChunk::Offset(path, offset) => {
                    let n = Self::read(path, &mut image[*offset..])?;
                    pos = offset + n;
                }
            }
        }
        if self.mirrored {
            image.extend_from_within(..size);
        }
        Ok(image)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::testdata;

    #[test]
    fn test_assemble_concat() -> Result<()> {
        // Test image assembly by concatenation.
        let mut image = ImageAssembler::with_params(16, false);
        image.parse(&[
            testdata!("hello.txt").to_str().unwrap(),
            testdata!("world.txt").to_str().unwrap(),
        ])?;
        let data = image.assemble()?;
        assert_eq!(data, b"HelloWorld\xff\xff\xff\xff\xff\xff");
        Ok(())
    }

    #[test]
    fn test_assemble_offset() -> Result<()> {
        // Test image assembly by explicit offsets.
        let mut image = ImageAssembler::with_params(16, false);
        image.parse(&[
            testdata!("hello.txt@0").to_str().unwrap(),
            testdata!("world.txt@0x8").to_str().unwrap(),
        ])?;
        let data = image.assemble()?;
        assert_eq!(data, b"Hello\xff\xff\xffWorld\xff\xff\xff");
        Ok(())
    }

    #[test]
    fn test_assemble_mirrored() -> Result<()> {
        // Test image assembly with mirroring.
        let mut image = ImageAssembler::with_params(20, true);
        image.parse(&[
            testdata!("hello.txt").to_str().unwrap(),
            testdata!("world.txt").to_str().unwrap(),
        ])?;
        let data = image.assemble()?;
        assert_eq!(data, b"HelloWorldHelloWorld");
        Ok(())
    }

    #[test]
    fn test_assemble_mirrored_offset_error() -> Result<()> {
        // Test image assembly where one of the source files isn't read completely.
        let mut image = ImageAssembler::with_params(16, true);
        image.parse(&[
            testdata!("hello.txt@0").to_str().unwrap(),
            testdata!("world.txt@0x5").to_str().unwrap(),
        ])?;
        let err = image.assemble().unwrap_err();
        assert_eq!(
            err.to_string(),
            "Incomplete read: expected to read 5 bytes but read 3 bytes"
        );
        Ok(())
    }

    #[test]
    fn test_load_image() {
        // Read and write back image.
        let image = Image::read_from_file(&testdata!("test_image.bin")).unwrap();
        image
            .write_to_file(&testdata!("test_image_out.bin"))
            .unwrap();

        // Ensure the result is identical to the original.
        let (mut orig_bytes, mut res_bytes) = (Vec::<u8>::new(), Vec::<u8>::new());
        File::open(&testdata!("test_image.bin"))
            .unwrap()
            .read_to_end(&mut orig_bytes)
            .unwrap();
        File::open(&testdata!("test_image_out.bin"))
            .unwrap()
            .read_to_end(&mut res_bytes)
            .unwrap();
        assert_eq!(orig_bytes, res_bytes);
    }
}
<|endoftext|>


<commit_before>extern crate bytes;

use super::{
    Encodable,
    SszStream
};
use super::ethereum_types::{ H256, U256 };
use self::bytes::{ BytesMut, BufMut };

/*
 * Note: there is a "to_bytes" function for integers
 * in Rust nightly. When it is in stable, we should
 * use it instead.
 */
macro_rules! impl_encodable_for_uint {
    ($type: ident, $bit_size: expr) => {
        impl Encodable for $type {
            fn ssz_append(&self, s: &mut SszStream)
            {
                // Ensure bit size is valid
                assert!((0 < $bit_size) &&
                        ($bit_size % 8 == 0) &&
                        (2_u128.pow($bit_size) > *self as u128));

                // Serialize to bytes
                let mut buf = BytesMut::with_capacity($bit_size/8);

                // Match bit size with encoding
                match $bit_size {
                    8 => buf.put_u8(*self as u8),
                    16 => buf.put_u16_be(*self as u16),
                    32 => buf.put_u32_be(*self as u32),
                    64 => buf.put_u64_be(*self as u64),
                    _ => { ; }
                }

                // Append bytes to the SszStream
                s.append_encoded_raw(&mut buf.to_vec());
            }
        }
    }
}

impl_encodable_for_uint!(u8, 8);
impl_encodable_for_uint!(u16, 16);
impl_encodable_for_uint!(u32, 32);
impl_encodable_for_uint!(u64, 64);
impl_encodable_for_uint!(usize, 64);

impl Encodable for H256 {
    fn ssz_append(&self, s: &mut SszStream) {
        s.append_encoded_val(&self.to_vec());
    }
}

impl Encodable for U256 {
    fn ssz_append(&self, s: &mut SszStream) {
        let mut a = [0; 32];
        self.to_big_endian(&mut a);
        s.append_encoded_val(&a.to_vec());
    }
}

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

    #[test]
    fn test_ssz_encode_u8() {
        let x: u8 = 0;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0]);

        let x: u8 = 1;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![1]);

        let x: u8 = 100;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![100]);

        let x: u8 = 255;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![255]);
    }

    #[test]
    fn test_ssz_encode_u16() {
        let x: u16 = 1;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 1]);

        let x: u16 = 100;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 100]);

        let x: u16 = 1 << 8;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![1, 0]);

        let x: u16 = 65535;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![255, 255]);
    }

    #[test]
    fn test_ssz_encode_u32() {
        let x: u32 = 1;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 0, 0, 1]);

        let x: u32 = 100;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 0, 0, 100]);

        let x: u32 = 1 << 16;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 1, 0, 0]);

        let x: u32 = 1 << 24;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![1, 0, 0, 0]);

        let x: u32 = !0;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![255, 255, 255, 255]);
    }

    #[test]
    fn test_ssz_encode_u64() {
        let x: u64 = 1;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 0, 0, 0, 1]);

        let x: u64 = 100;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 0, 0, 0, 100]);

        let x: u64 = 1 << 32;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 0, 0, 1, 0, 0, 0, 0]);

        let x: u64 = !0;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![255, 255, 255, 255, 255, 255, 255, 255]);
    }

    #[test]
    fn test_ssz_encode_usize() {
        let x: usize = 1;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 0, 0, 0, 1]);

        let x: usize = 100;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 0, 0, 0, 100]);

        let x: usize = 1 << 32;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 0, 0, 1, 0, 0, 0, 0]);

        let x: usize = !0;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![255, 255, 255, 255, 255, 255, 255, 255]);
    }
}
<commit_msg>Fix H256 encoding, remove U256 encoding<commit_after>extern crate bytes;

use super::{
    Encodable,
    SszStream
};
use super::ethereum_types::H256;
use self::bytes::{ BytesMut, BufMut };

/*
 * Note: there is a "to_bytes" function for integers
 * in Rust nightly. When it is in stable, we should
 * use it instead.
 */
macro_rules! impl_encodable_for_uint {
    ($type: ident, $bit_size: expr) => {
        impl Encodable for $type {
            fn ssz_append(&self, s: &mut SszStream)
            {
                // Ensure bit size is valid
                assert!((0 < $bit_size) &&
                        ($bit_size % 8 == 0) &&
                        (2_u128.pow($bit_size) > *self as u128));

                // Serialize to bytes
                let mut buf = BytesMut::with_capacity($bit_size/8);

                // Match bit size with encoding
                match $bit_size {
                    8 => buf.put_u8(*self as u8),
                    16 => buf.put_u16_be(*self as u16),
                    32 => buf.put_u32_be(*self as u32),
                    64 => buf.put_u64_be(*self as u64),
                    _ => { ; }
                }

                // Append bytes to the SszStream
                s.append_encoded_raw(&mut buf.to_vec());
            }
        }
    }
}

impl_encodable_for_uint!(u8, 8);
impl_encodable_for_uint!(u16, 16);
impl_encodable_for_uint!(u32, 32);
impl_encodable_for_uint!(u64, 64);
impl_encodable_for_uint!(usize, 64);

impl Encodable for H256 {
    fn ssz_append(&self, s: &mut SszStream) {
        s.append_encoded_raw(&self.to_vec());
    }
}

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

    #[test]
    fn test_ssz_encode_h256() {
        let h = H256::zero();
        let mut ssz = SszStream::new();
        ssz.append(&h);
        assert_eq!(ssz.drain(), vec![0; 32]);
    }

    #[test]
    fn test_ssz_encode_u8() {
        let x: u8 = 0;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0]);

        let x: u8 = 1;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![1]);

        let x: u8 = 100;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![100]);

        let x: u8 = 255;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![255]);
    }

    #[test]
    fn test_ssz_encode_u16() {
        let x: u16 = 1;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 1]);

        let x: u16 = 100;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 100]);

        let x: u16 = 1 << 8;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![1, 0]);

        let x: u16 = 65535;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![255, 255]);
    }

    #[test]
    fn test_ssz_encode_u32() {
        let x: u32 = 1;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 0, 0, 1]);

        let x: u32 = 100;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 0, 0, 100]);

        let x: u32 = 1 << 16;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 1, 0, 0]);

        let x: u32 = 1 << 24;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![1, 0, 0, 0]);

        let x: u32 = !0;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![255, 255, 255, 255]);
    }

    #[test]
    fn test_ssz_encode_u64() {
        let x: u64 = 1;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 0, 0, 0, 1]);

        let x: u64 = 100;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 0, 0, 0, 100]);

        let x: u64 = 1 << 32;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 0, 0, 1, 0, 0, 0, 0]);

        let x: u64 = !0;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![255, 255, 255, 255, 255, 255, 255, 255]);
    }

    #[test]
    fn test_ssz_encode_usize() {
        let x: usize = 1;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 0, 0, 0, 1]);

        let x: usize = 100;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 0, 0, 0, 100]);

        let x: usize = 1 << 32;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![0, 0, 0, 1, 0, 0, 0, 0]);

        let x: usize = !0;
        let mut ssz = SszStream::new();
        ssz.append(&x);
        assert_eq!(ssz.drain(), vec![255, 255, 255, 255, 255, 255, 255, 255]);
    }
}
<|endoftext|>


<commit_before>use std::iter::FromIterator;
use std::slice;
use std::vec;

#[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash, Debug))]
#[cfg_attr(feature = "clone-impls", derive(Clone))]
pub struct Delimited<T, D> {
    inner: Vec<(T, Option<D>)>
}

impl<T, D> Delimited<T, D> {
    pub fn new() -> Delimited<T, D> {
        Delimited {
            inner: Vec::new(),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.inner.len() == 0
    }

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

    pub fn get(&self, idx: usize) -> Element<&T, &D> {
        let (ref t, ref d) = self.inner[idx];
        match *d {
            Some(ref d) => Element::Delimited(t, d),
            None => Element::End(t),
        }
    }

    pub fn get_mut(&mut self, idx: usize) -> Element<&mut T, &mut D> {
        let (ref mut t, ref mut d) = self.inner[idx];
        match *d {
            Some(ref mut d) => Element::Delimited(t, d),
            None => Element::End(t),
        }
    }

    pub fn iter(&self) -> Iter<T, D> {
        Iter { inner: self.inner.iter() }
    }

    pub fn iter_mut(&mut self) -> IterMut<T, D> {
        IterMut { inner: self.inner.iter_mut() }
    }

    pub fn items(&self) -> Items<T, D> {
        Items { inner: self.inner.iter() }
    }

    pub fn push(&mut self, token: Element<T, D>) {
        assert!(self.is_empty() || self.trailing_delim());
        match token {
            Element::Delimited(t, d) => self.inner.push((t, Some(d))),
            Element::End(t) => self.inner.push((t, None)),
        }
    }

    pub fn push_first(&mut self, token: T) {
        assert!(self.is_empty());
        self.inner.push((token, None));
    }

    pub fn push_next(&mut self, token: T, delimiter: D) {
        self.push_trailing(delimiter);
        self.inner.push((token, None));
    }

    pub fn push_trailing(&mut self, delimiter: D) {
        let len = self.len();
        assert!(self.inner[len - 1].1.is_none());
        self.inner[len - 1].1 = Some(delimiter);
    }

    pub fn push_default(&mut self, token: T) where D: Default {
        if self.is_empty() || self.trailing_delim() {
            self.inner.push((token, None));
        } else {
            self.push_next(token, D::default());
        }
    }

    pub fn pop(&mut self) -> Option<Element<T, D>> {
        self.inner.pop().map(|e| {
            match e {
                (t, Some(d)) => Element::Delimited(t, d),
                (t, None) => Element::End(t),
            }
        })
    }

    pub fn into_vec(self) -> Vec<T> {
        self.inner.into_iter().map(|t| t.0).collect()
    }

    pub fn trailing_delim(&self) -> bool {
        self.inner[self.inner.len() - 1].1.is_some()
    }
}

impl<T, D> From<Vec<(T, Option<D>)>> for Delimited<T, D> {
    fn from(v: Vec<(T, Option<D>)>) -> Self {
        Delimited {
            inner: v,
        }
    }
}

impl<T, D> From<Vec<T>> for Delimited<T, D>
    where D: Default,
{
    fn from(v: Vec<T>) -> Self {
        let len = v.len();
        Delimited {
            inner: v.into_iter().enumerate().map(|(i, item)| {
                (item, if i + 1 == len {None} else {Some(D::default())})
            }).collect(),
        }
    }
}

impl<T, D> FromIterator<Element<T, D>> for Delimited<T, D> {
    fn from_iter<I: IntoIterator<Item = Element<T, D>>>(i: I) -> Self {
        let mut ret = Delimited::new();
        for element in i {
            match element {
                Element::Delimited(a, b) => ret.inner.push((a, Some(b))),
                Element::End(a) => ret.inner.push((a, None)),
            }
        }
        ret
    }
}

impl<T, D> FromIterator<T> for Delimited<T, D>
    where D: Default,
{
    fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
        let mut ret = Delimited::new();
        for element in i {
            ret.push_default(element);
        }
        ret
    }
}

impl<'a, T, D> IntoIterator for &'a Delimited<T, D> {
    type Item = Element<&'a T, &'a D>;
    type IntoIter = Iter<'a, T, D>;

    fn into_iter(self) -> Iter<'a, T, D> {
        <Delimited<T, D>>::iter(self)
    }
}

impl<T, D> IntoIterator for Delimited<T, D> {
    type Item = Element<T, D>;
    type IntoIter = IntoIter<T, D>;

    fn into_iter(self) -> IntoIter<T, D> {
        IntoIter { inner: self.inner.into_iter() }
    }
}

impl<T, D> Default for Delimited<T, D> {
    fn default() -> Self {
        Delimited::new()
    }
}

pub struct Iter<'a, T: 'a, D: 'a> {
    inner: slice::Iter<'a, (T, Option<D>)>,
}

impl<'a, T, D> Iterator for Iter<'a, T, D> {
    type Item = Element<&'a T, &'a D>;

    fn next(&mut self) -> Option<Element<&'a T, &'a D>> {
        self.inner.next().map(|pair| {
            match pair.1 {
                Some(ref delimited) => Element::Delimited(&pair.0, delimited),
                None => Element::End(&pair.0),
            }
        })
    }
}

pub struct IterMut<'a, T: 'a, D: 'a> {
    inner: slice::IterMut<'a, (T, Option<D>)>,
}

impl<'a, T, D> Iterator for IterMut<'a, T, D> {
    type Item = Element<&'a mut T, &'a mut D>;

    fn next(&mut self) -> Option<Element<&'a mut T, &'a mut D>> {
        self.inner.next().map(|pair| {
            match pair.1 {
                Some(ref mut delimited) => Element::Delimited(&mut pair.0, delimited),
                None => Element::End(&mut pair.0),
            }
        })
    }
}

pub struct Items<'a, T: 'a, D: 'a> {
    inner: slice::Iter<'a, (T, Option<D>)>,
}

impl<'a, T, D> Iterator for Items<'a, T, D> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        self.inner.next().map(|pair| &pair.0)
    }
}

pub struct IntoIter<T, D> {
    inner: vec::IntoIter<(T, Option<D>)>,
}

impl<T, D> Iterator for IntoIter<T, D> {
    type Item = Element<T, D>;

    fn next(&mut self) -> Option<Element<T, D>> {
        self.inner.next().map(|pair| {
            match pair.1 {
                Some(v) => Element::Delimited(pair.0, v),
                None => Element::End(pair.0)
            }
        })
    }
}

pub enum Element<T, D> {
    Delimited(T, D),
    End(T),
}

impl<T, D> Element<T, D> {
    pub fn into_item(self) -> T {
        match self {
            Element::Delimited(t, _) |
            Element::End(t) => t,
        }
    }

    pub fn item(&self) -> &T {
        match *self {
            Element::Delimited(ref t, _) |
            Element::End(ref t) => t,
        }
    }

    pub fn item_mut(&mut self) -> &mut T {
        match *self {
            Element::Delimited(ref mut t, _) |
            Element::End(ref mut t) => t,
        }
    }

    pub fn delimiter(&self) -> Option<&D> {
        match *self {
            Element::Delimited(_, ref d) => Some(d),
            Element::End(_) => None,
        }
    }
}

#[cfg(feature = "parsing")]
mod parsing {
    use super::Delimited;
    use {PResult, Cursor, Synom, parse_error};

    impl<T, D> Delimited<T, D>
        where T: Synom,
              D: Synom,
    {
        pub fn parse_separated(input: Cursor) -> PResult<Self>
        {
            Self::parse(input, T::parse, false)
        }

        pub fn parse_separated_nonempty(input: Cursor) -> PResult<Self>
        {
            Self::parse_separated_nonempty_with(input, T::parse)
        }

        pub fn parse_terminated(input: Cursor) -> PResult<Self>
        {
            Self::parse_terminated_with(input, T::parse)
        }
    }

    impl<T, D> Delimited<T, D>
        where D: Synom,
    {
        pub fn parse_separated_nonempty_with(
                input: Cursor,
                parse: fn(Cursor) -> PResult<T>)
            -> PResult<Self>
        {
            match Self::parse(input, parse, false) {
                Ok((_, ref b)) if b.is_empty() => parse_error(),
                other => other,
            }
        }

        pub fn parse_terminated_with(
                input: Cursor,
                parse: fn(Cursor) -> PResult<T>)
            -> PResult<Self>
        {
            Self::parse(input, parse, true)
        }

        fn parse(mut input: Cursor,
                 parse: fn(Cursor) -> PResult<T>,
                 terminated: bool)
            -> PResult<Self>
        {
            let mut res = Delimited::new();

            // get the first element
            match parse(input) {
                Err(_) => Ok((input, res)),
                Ok((i, o)) => {
                    if i == input {
                        return parse_error();
                    }
                    input = i;
                    res.push_first(o);

                    // get the separator first
                    while let Ok((i2, s)) = D::parse(input) {
                        if i2 == input {
                            break;
                        }

                        // get the element next
                        if let Ok((i3, o3)) = parse(i2) {
                            if i3 == i2 {
                                break;
                            }
                            res.push_next(o3, s);
                            input = i3;
                        } else {
                            break;
                        }
                    }
                    if terminated {
                        if let Ok((after, sep)) = D::parse(input) {
                            res.push_trailing(sep);
                            input = after;
                        }
                    }
                    Ok((input, res))
                }
            }
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{Tokens, ToTokens};

    impl<T, D> ToTokens for Delimited<T, D>
        where T: ToTokens,
              D: ToTokens,
    {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append_all(self.iter())
        }
    }

    impl<T, D> ToTokens for Element<T, D>
        where T: ToTokens,
              D: ToTokens,
    {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                Element::Delimited(ref a, ref b) => {
                    a.to_tokens(tokens);
                    b.to_tokens(tokens);
                }
                Element::End(ref a) => a.to_tokens(tokens),
            }
        }
    }
}
<commit_msg>Add {first,last}{,_mut} to Delimited<commit_after>use std::iter::FromIterator;
use std::slice;
use std::vec;

#[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash, Debug))]
#[cfg_attr(feature = "clone-impls", derive(Clone))]
pub struct Delimited<T, D> {
    inner: Vec<(T, Option<D>)>
}

impl<T, D> Delimited<T, D> {
    pub fn new() -> Delimited<T, D> {
        Delimited {
            inner: Vec::new(),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.inner.len() == 0
    }

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

    pub fn get(&self, idx: usize) -> Element<&T, &D> {
        let (ref t, ref d) = self.inner[idx];
        match *d {
            Some(ref d) => Element::Delimited(t, d),
            None => Element::End(t),
        }
    }

    pub fn get_mut(&mut self, idx: usize) -> Element<&mut T, &mut D> {
        let (ref mut t, ref mut d) = self.inner[idx];
        match *d {
            Some(ref mut d) => Element::Delimited(t, d),
            None => Element::End(t),
        }
    }

    pub fn first(&self) -> Option<Element<&T, &D>> {
        self.inner.first().map(|&(ref t, ref d)| {
            match *d {
                Some(ref d) => Element::Delimited(t, d),
                None => Element::End(t),
            }
        })
    }

    pub fn first_mut(&mut self) -> Option<Element<&mut T, &mut D>> {
        self.inner.first_mut().map(|&mut (ref mut t, ref mut d)| {
            match *d {
                Some(ref mut d) => Element::Delimited(t, d),
                None => Element::End(t),
            }
        })
    }

    pub fn last(&self) -> Option<Element<&T, &D>> {
        self.inner.last().map(|&(ref t, ref d)| {
            match *d {
                Some(ref d) => Element::Delimited(t, d),
                None => Element::End(t),
            }
        })
    }

    pub fn last_mut(&mut self) -> Option<Element<&mut T, &mut D>> {
        self.inner.last_mut().map(|&mut (ref mut t, ref mut d)| {
            match *d {
                Some(ref mut d) => Element::Delimited(t, d),
                None => Element::End(t),
            }
        })
    }

    pub fn iter(&self) -> Iter<T, D> {
        Iter { inner: self.inner.iter() }
    }

    pub fn iter_mut(&mut self) -> IterMut<T, D> {
        IterMut { inner: self.inner.iter_mut() }
    }

    pub fn items(&self) -> Items<T, D> {
        Items { inner: self.inner.iter() }
    }

    pub fn push(&mut self, token: Element<T, D>) {
        assert!(self.is_empty() || self.trailing_delim());
        match token {
            Element::Delimited(t, d) => self.inner.push((t, Some(d))),
            Element::End(t) => self.inner.push((t, None)),
        }
    }

    pub fn push_first(&mut self, token: T) {
        assert!(self.is_empty());
        self.inner.push((token, None));
    }

    pub fn push_next(&mut self, token: T, delimiter: D) {
        self.push_trailing(delimiter);
        self.inner.push((token, None));
    }

    pub fn push_trailing(&mut self, delimiter: D) {
        let len = self.len();
        assert!(self.inner[len - 1].1.is_none());
        self.inner[len - 1].1 = Some(delimiter);
    }

    pub fn push_default(&mut self, token: T) where D: Default {
        if self.is_empty() || self.trailing_delim() {
            self.inner.push((token, None));
        } else {
            self.push_next(token, D::default());
        }
    }

    pub fn pop(&mut self) -> Option<Element<T, D>> {
        self.inner.pop().map(|e| {
            match e {
                (t, Some(d)) => Element::Delimited(t, d),
                (t, None) => Element::End(t),
            }
        })
    }

    pub fn into_vec(self) -> Vec<T> {
        self.inner.into_iter().map(|t| t.0).collect()
    }

    pub fn trailing_delim(&self) -> bool {
        self.inner[self.inner.len() - 1].1.is_some()
    }
}

impl<T, D> From<Vec<(T, Option<D>)>> for Delimited<T, D> {
    fn from(v: Vec<(T, Option<D>)>) -> Self {
        Delimited {
            inner: v,
        }
    }
}

impl<T, D> From<Vec<T>> for Delimited<T, D>
    where D: Default,
{
    fn from(v: Vec<T>) -> Self {
        let len = v.len();
        Delimited {
            inner: v.into_iter().enumerate().map(|(i, item)| {
                (item, if i + 1 == len {None} else {Some(D::default())})
            }).collect(),
        }
    }
}

impl<T, D> FromIterator<Element<T, D>> for Delimited<T, D> {
    fn from_iter<I: IntoIterator<Item = Element<T, D>>>(i: I) -> Self {
        let mut ret = Delimited::new();
        for element in i {
            match element {
                Element::Delimited(a, b) => ret.inner.push((a, Some(b))),
                Element::End(a) => ret.inner.push((a, None)),
            }
        }
        ret
    }
}

impl<T, D> FromIterator<T> for Delimited<T, D>
    where D: Default,
{
    fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
        let mut ret = Delimited::new();
        for element in i {
            ret.push_default(element);
        }
        ret
    }
}

impl<'a, T, D> IntoIterator for &'a Delimited<T, D> {
    type Item = Element<&'a T, &'a D>;
    type IntoIter = Iter<'a, T, D>;

    fn into_iter(self) -> Iter<'a, T, D> {
        <Delimited<T, D>>::iter(self)
    }
}

impl<T, D> IntoIterator for Delimited<T, D> {
    type Item = Element<T, D>;
    type IntoIter = IntoIter<T, D>;

    fn into_iter(self) -> IntoIter<T, D> {
        IntoIter { inner: self.inner.into_iter() }
    }
}

impl<T, D> Default for Delimited<T, D> {
    fn default() -> Self {
        Delimited::new()
    }
}

pub struct Iter<'a, T: 'a, D: 'a> {
    inner: slice::Iter<'a, (T, Option<D>)>,
}

impl<'a, T, D> Iterator for Iter<'a, T, D> {
    type Item = Element<&'a T, &'a D>;

    fn next(&mut self) -> Option<Element<&'a T, &'a D>> {
        self.inner.next().map(|pair| {
            match pair.1 {
                Some(ref delimited) => Element::Delimited(&pair.0, delimited),
                None => Element::End(&pair.0),
            }
        })
    }
}

pub struct IterMut<'a, T: 'a, D: 'a> {
    inner: slice::IterMut<'a, (T, Option<D>)>,
}

impl<'a, T, D> Iterator for IterMut<'a, T, D> {
    type Item = Element<&'a mut T, &'a mut D>;

    fn next(&mut self) -> Option<Element<&'a mut T, &'a mut D>> {
        self.inner.next().map(|pair| {
            match pair.1 {
                Some(ref mut delimited) => Element::Delimited(&mut pair.0, delimited),
                None => Element::End(&mut pair.0),
            }
        })
    }
}

pub struct Items<'a, T: 'a, D: 'a> {
    inner: slice::Iter<'a, (T, Option<D>)>,
}

impl<'a, T, D> Iterator for Items<'a, T, D> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        self.inner.next().map(|pair| &pair.0)
    }
}

pub struct IntoIter<T, D> {
    inner: vec::IntoIter<(T, Option<D>)>,
}

impl<T, D> Iterator for IntoIter<T, D> {
    type Item = Element<T, D>;

    fn next(&mut self) -> Option<Element<T, D>> {
        self.inner.next().map(|pair| {
            match pair.1 {
                Some(v) => Element::Delimited(pair.0, v),
                None => Element::End(pair.0)
            }
        })
    }
}

pub enum Element<T, D> {
    Delimited(T, D),
    End(T),
}

impl<T, D> Element<T, D> {
    pub fn into_item(self) -> T {
        match self {
            Element::Delimited(t, _) |
            Element::End(t) => t,
        }
    }

    pub fn item(&self) -> &T {
        match *self {
            Element::Delimited(ref t, _) |
            Element::End(ref t) => t,
        }
    }

    pub fn item_mut(&mut self) -> &mut T {
        match *self {
            Element::Delimited(ref mut t, _) |
            Element::End(ref mut t) => t,
        }
    }

    pub fn delimiter(&self) -> Option<&D> {
        match *self {
            Element::Delimited(_, ref d) => Some(d),
            Element::End(_) => None,
        }
    }
}

#[cfg(feature = "parsing")]
mod parsing {
    use super::Delimited;
    use {PResult, Cursor, Synom, parse_error};

    impl<T, D> Delimited<T, D>
        where T: Synom,
              D: Synom,
    {
        pub fn parse_separated(input: Cursor) -> PResult<Self>
        {
            Self::parse(input, T::parse, false)
        }

        pub fn parse_separated_nonempty(input: Cursor) -> PResult<Self>
        {
            Self::parse_separated_nonempty_with(input, T::parse)
        }

        pub fn parse_terminated(input: Cursor) -> PResult<Self>
        {
            Self::parse_terminated_with(input, T::parse)
        }
    }

    impl<T, D> Delimited<T, D>
        where D: Synom,
    {
        pub fn parse_separated_nonempty_with(
                input: Cursor,
                parse: fn(Cursor) -> PResult<T>)
            -> PResult<Self>
        {
            match Self::parse(input, parse, false) {
                Ok((_, ref b)) if b.is_empty() => parse_error(),
                other => other,
            }
        }

        pub fn parse_terminated_with(
                input: Cursor,
                parse: fn(Cursor) -> PResult<T>)
            -> PResult<Self>
        {
            Self::parse(input, parse, true)
        }

        fn parse(mut input: Cursor,
                 parse: fn(Cursor) -> PResult<T>,
                 terminated: bool)
            -> PResult<Self>
        {
            let mut res = Delimited::new();

            // get the first element
            match parse(input) {
                Err(_) => Ok((input, res)),
                Ok((i, o)) => {
                    if i == input {
                        return parse_error();
                    }
                    input = i;
                    res.push_first(o);

                    // get the separator first
                    while let Ok((i2, s)) = D::parse(input) {
                        if i2 == input {
                            break;
                        }

                        // get the element next
                        if let Ok((i3, o3)) = parse(i2) {
                            if i3 == i2 {
                                break;
                            }
                            res.push_next(o3, s);
                            input = i3;
                        } else {
                            break;
                        }
                    }
                    if terminated {
                        if let Ok((after, sep)) = D::parse(input) {
                            res.push_trailing(sep);
                            input = after;
                        }
                    }
                    Ok((input, res))
                }
            }
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{Tokens, ToTokens};

    impl<T, D> ToTokens for Delimited<T, D>
        where T: ToTokens,
              D: ToTokens,
    {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append_all(self.iter())
        }
    }

    impl<T, D> ToTokens for Element<T, D>
        where T: ToTokens,
              D: ToTokens,
    {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                Element::Delimited(ref a, ref b) => {
                    a.to_tokens(tokens);
                    b.to_tokens(tokens);
                }
                Element::End(ref a) => a.to_tokens(tokens),
            }
        }
    }
}
<|endoftext|>