<commit_before>use iced::{
  canvas, executor, mouse, Application, Canvas, Color, Command, Element, Length, Point, Rectangle, Settings, Vector,
};
use oppai_field::field::{self, Field, Pos};
use oppai_field::player::Player;
use oppai_field::zobrist::Zobrist;
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;

const FIELD_WIDTH: u32 = 39;
const FIELD_HEIGHT: u32 = 32;

pub fn main() -> iced::Result {
  Game::run(Settings {
    antialiasing: true,
    ..Settings::default()
  })
}

struct Game {
  player: Player,
  field: Field,
  captures: Vec<(Vec<Pos>, Player)>,
}

#[derive(Debug, Clone, Copy)]
enum Message {
  PutPoint(Pos),
}

impl Application for Game {
  type Executor = executor::Default;
  type Message = Message;
  type Flags = ();

  fn new(_flags: ()) -> (Self, Command<Self::Message>) {
    let mut rng = XorShiftRng::from_entropy();
    let zobrist = Zobrist::new(field::length(FIELD_WIDTH, FIELD_HEIGHT) * 2, &mut rng);
    let field = Field::new(FIELD_WIDTH, FIELD_HEIGHT, std::sync::Arc::new(zobrist));
    (
      Game {
        player: Player::Red,
        field,
        captures: Vec::new(),
      },
      Command::none(),
    )
  }

  fn title(&self) -> String {
    "OpPAI".into()
  }

  fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
    let Message::PutPoint(pos) = message;
    if self.field.put_point(pos, self.player) {
      let last_chain = self.field.get_last_chain();
      if let Some(&pos) = last_chain.first() {
        let player = self.field.cell(pos).get_player();
        self.captures.push((last_chain, player));
      }

      let n = self.field.n(pos);
      let s = self.field.s(pos);
      let w = self.field.w(pos);
      let e = self.field.e(pos);
      let nw = self.field.nw(pos);
      let ne = self.field.ne(pos);
      let sw = self.field.sw(pos);
      let se = self.field.se(pos);

      let mut check = |pos1: Pos, pos2: Pos| {
        if self.field.cell(pos1).get_players_point() == Some(self.player)
          && self.field.cell(pos2).get_players_point() == Some(self.player)
        {
          self.captures.push((vec![pos, pos1, pos2], self.player));
          true
        } else {
          false
        }
      };

      let _ = !check(s, e) && (check(s, se) || check(e, se));
      let _ = !check(e, n) && (check(e, ne) || check(n, ne));
      let _ = !check(n, w) && (check(n, nw) || check(w, nw));
      let _ = !check(w, s) && (check(w, sw) || check(s, sw));

      self.player = self.player.next();
    }

    Command::none()
  }

  fn view(&mut self) -> iced::Element<'_, Self::Message> {
    let canvas = Canvas::new(self).height(Length::Fill).width(Length::Fill);
    Element::<Pos>::from(canvas).map(Message::PutPoint)
  }
}

impl canvas::Program<Pos> for Game {
  fn update(&mut self, event: canvas::Event, bounds: Rectangle, cursor: canvas::Cursor) -> (canvas::event::Status, Option<Pos>) {
    let cursor_position = if let Some(position) = cursor.position_in(&bounds) {
      position
    } else {
      return (canvas::event::Status::Ignored, None);
    };
    match event {
      canvas::Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => {
        let field_width = self.field.width();
        let field_height = self.field.height();
        let width = bounds
          .width
          .min(bounds.height / field_height as f32 * field_width as f32);
        let height = bounds
          .height
          .min(bounds.width / field_width as f32 * field_height as f32);
        let step_x = width / field_width as f32;
        let step_y = height / field_height as f32;
        let shift = Vector::new(
          ((bounds.width - width) / 2.0).round(),
          ((bounds.height - height) / 2.0).round(),
        );
        let cursor_shift = Vector::new(step_x / 2.0, step_y / 2.0);

        let point = cursor_position - shift;
        if point.x >= 0.0 && point.x <= width && point.y >= 0.0 && point.y <= height {
          let point = point - cursor_shift;
          let x = (point.x / step_x).round() as u32;
          let y = (point.y / step_y).round() as u32;
          (canvas::event::Status::Captured, Some(self.field.to_pos(x, y)))
        } else {
          (canvas::event::Status::Captured, None)
        }
      }
      _ => (canvas::event::Status::Ignored, None),
    }
  }

  fn draw(&self, bounds: Rectangle, cursor: canvas::Cursor) -> Vec<canvas::Geometry> {
    let mut frame = canvas::Frame::new(bounds.size());

    let field_width = self.field.width();
    let field_height = self.field.height();
    let width = frame
      .width()
      .min(frame.height() / field_height as f32 * field_width as f32);
    let height = frame
      .height()
      .min(frame.width() / field_width as f32 * field_height as f32);
    let step_x = width / field_width as f32;
    let step_y = height / field_height as f32;
    let shift = Vector::new(
      ((frame.width() - width) / 2.0).round(),
      ((frame.height() - height) / 2.0).round(),
    );
    let cursor_shift = Vector::new(step_x / 2.0, step_y / 2.0);

    let grid = canvas::Path::new(|path| {
      for x in 0..field_width {
        let offset = (step_x * x as f32 + step_x / 2.0).round() + 0.5;
        path.move_to(Point::new(offset, 0.0) + shift);
        path.line_to(Point::new(offset, height) + shift);
      }
      for y in 0..field_height {
        let offset = (step_y * y as f32 + step_y / 2.0).round() + 0.5;
        path.move_to(Point::new(0.0, offset) + shift);
        path.line_to(Point::new(width, offset) + shift);
      }
    });

    frame.stroke(
      &grid,
      canvas::Stroke {
        width: 1.0,
        color: Color::BLACK,
        ..canvas::Stroke::default()
      },
    );

    fn color(player: Player) -> Color {
      match player {
        Player::Red => Color::from_rgb8(0xFF, 0x00, 0x00),
        Player::Black => Color::BLACK,
      }
    }

    let xy_to_point = |x: u32, y: u32| {
      let offset_x = (step_x * x as f32 + step_x / 2.0).round() + 0.5;
      let offset_y = (step_y * y as f32 + step_y / 2.0).round() + 0.5;
      Point::new(offset_x, offset_y) + shift
    };
    let pos_to_point = |pos: Pos| {
      let x = self.field.to_x(pos);
      let y = self.field.to_y(pos);
      xy_to_point(x, y)
    };

    for &player in &[Player::Red, Player::Black] {
      let points = canvas::Path::new(|path| {
        for &pos in self
          .field
          .points_seq()
          .iter()
          .filter(|&&pos| self.field.cell(pos).is_players_point(player))
        {
          path.circle(pos_to_point(pos), 5.0)
        }
      });

      frame.fill(&points, color(player));
    }

    for (chain, player) in &self.captures {
      let path = canvas::Path::new(|path| {
        path.move_to(pos_to_point(chain[0]));
        for &pos in chain.iter().skip(1) {
          path.line_to(pos_to_point(pos));
        }
      });

      let mut color = color(*player);
      color.a = 0.5;

      frame.fill(&path, color);
    }

    if let Some(&pos) = self.field.points_seq().last() {
      let last_point = canvas::Path::new(|path| path.circle(pos_to_point(pos), 8.0));

      let color = color(self.field.cell(pos).get_player());

      frame.stroke(
        &last_point,
        canvas::Stroke {
          width: 2.0,
          color,
          ..canvas::Stroke::default()
        },
      );
    }

    if let Some(point) = cursor.position().and_then(|cursor_position| {
      let point = cursor_position - shift;
      if point.x >= 0.0 && point.x <= width && point.y >= 0.0 && point.y <= height {
        let point = point - cursor_shift;
        let x = (point.x / step_x).round() as u32;
        let y = (point.y / step_y).round() as u32;
        let pos = self.field.to_pos(x, y);
        if self.field.is_putting_allowed(pos) {
          Some(xy_to_point(x, y))
        } else {
          None
        }
      } else {
        None
      }
    }) {
      let cursor_point = canvas::Path::new(|path| path.circle(point, 5.0));

      let mut color = color(self.player);
      color.a = 0.5;

      frame.fill(&cursor_point, color);
    }

    vec![frame.into_geometry()]
  }
}
<commit_msg>Cache field.<commit_after>use iced::{
  canvas, executor, mouse, Application, Canvas, Color, Command, Element, Length, Point, Rectangle, Settings, Vector,
};
use oppai_field::field::{self, Field, Pos};
use oppai_field::player::Player;
use oppai_field::zobrist::Zobrist;
use rand::SeedableRng;
use rand_xorshift::XorShiftRng;

const FIELD_WIDTH: u32 = 39;
const FIELD_HEIGHT: u32 = 32;

pub fn main() -> iced::Result {
  Game::run(Settings {
    antialiasing: true,
    ..Settings::default()
  })
}

struct Game {
  player: Player,
  field: Field,
  captures: Vec<(Vec<Pos>, Player)>,
  field_cache: canvas::Cache,
}

#[derive(Debug, Clone, Copy)]
enum Message {
  PutPoint(Pos),
}

impl Application for Game {
  type Executor = executor::Default;
  type Message = Message;
  type Flags = ();

  fn new(_flags: ()) -> (Self, Command<Self::Message>) {
    let mut rng = XorShiftRng::from_entropy();
    let zobrist = Zobrist::new(field::length(FIELD_WIDTH, FIELD_HEIGHT) * 2, &mut rng);
    let field = Field::new(FIELD_WIDTH, FIELD_HEIGHT, std::sync::Arc::new(zobrist));
    (
      Game {
        player: Player::Red,
        field,
        captures: Vec::new(),
        field_cache: Default::default(),
      },
      Command::none(),
    )
  }

  fn title(&self) -> String {
    "OpPAI".into()
  }

  fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
    let Message::PutPoint(pos) = message;
    if self.field.put_point(pos, self.player) {
      let last_chain = self.field.get_last_chain();
      if let Some(&pos) = last_chain.first() {
        let player = self.field.cell(pos).get_player();
        self.captures.push((last_chain, player));
      }

      let n = self.field.n(pos);
      let s = self.field.s(pos);
      let w = self.field.w(pos);
      let e = self.field.e(pos);
      let nw = self.field.nw(pos);
      let ne = self.field.ne(pos);
      let sw = self.field.sw(pos);
      let se = self.field.se(pos);

      let mut check = |pos1: Pos, pos2: Pos| {
        if self.field.cell(pos1).get_players_point() == Some(self.player)
          && self.field.cell(pos2).get_players_point() == Some(self.player)
        {
          self.captures.push((vec![pos, pos1, pos2], self.player));
          true
        } else {
          false
        }
      };

      let _ = !check(s, e) && (check(s, se) || check(e, se));
      let _ = !check(e, n) && (check(e, ne) || check(n, ne));
      let _ = !check(n, w) && (check(n, nw) || check(w, nw));
      let _ = !check(w, s) && (check(w, sw) || check(s, sw));

      self.player = self.player.next();

      self.field_cache.clear();
    }

    Command::none()
  }

  fn view(&mut self) -> iced::Element<'_, Self::Message> {
    let canvas = Canvas::new(self).height(Length::Fill).width(Length::Fill);
    Element::<Pos>::from(canvas).map(Message::PutPoint)
  }
}

impl canvas::Program<Pos> for Game {
  fn update(
    &mut self,
    event: canvas::Event,
    bounds: Rectangle,
    cursor: canvas::Cursor,
  ) -> (canvas::event::Status, Option<Pos>) {
    let cursor_position = if let Some(position) = cursor.position_in(&bounds) {
      position
    } else {
      return (canvas::event::Status::Ignored, None);
    };
    match event {
      canvas::Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => {
        let field_width = self.field.width();
        let field_height = self.field.height();
        let width = bounds
          .width
          .min(bounds.height / field_height as f32 * field_width as f32);
        let height = bounds
          .height
          .min(bounds.width / field_width as f32 * field_height as f32);
        let step_x = width / field_width as f32;
        let step_y = height / field_height as f32;
        let shift = Vector::new(
          ((bounds.width - width) / 2.0).round(),
          ((bounds.height - height) / 2.0).round(),
        );
        let cursor_shift = Vector::new(step_x / 2.0, step_y / 2.0);

        let point = cursor_position - shift;
        if point.x >= 0.0 && point.x <= width && point.y >= 0.0 && point.y <= height {
          let point = point - cursor_shift;
          let x = (point.x / step_x).round() as u32;
          let y = (point.y / step_y).round() as u32;
          (canvas::event::Status::Captured, Some(self.field.to_pos(x, y)))
        } else {
          (canvas::event::Status::Captured, None)
        }
      }
      _ => (canvas::event::Status::Ignored, None),
    }
  }

  fn draw(&self, bounds: Rectangle, cursor: canvas::Cursor) -> Vec<canvas::Geometry> {
    fn color(player: Player) -> Color {
      match player {
        Player::Red => Color::from_rgb8(0xFF, 0x00, 0x00),
        Player::Black => Color::BLACK,
      }
    }

    let field_width = self.field.width();
    let field_height = self.field.height();
    let width = bounds
      .width
      .min(bounds.height / field_height as f32 * field_width as f32);
    let height = bounds
      .height
      .min(bounds.width / field_width as f32 * field_height as f32);
    let step_x = width / field_width as f32;
    let step_y = height / field_height as f32;
    let shift = Vector::new(
      ((bounds.width - width) / 2.0).round(),
      ((bounds.height - height) / 2.0).round(),
    );
    let cursor_shift = Vector::new(step_x / 2.0, step_y / 2.0);

    let xy_to_point = |x: u32, y: u32| {
      let offset_x = (step_x * x as f32 + step_x / 2.0).round() + 0.5;
      let offset_y = (step_y * y as f32 + step_y / 2.0).round() + 0.5;
      Point::new(offset_x, offset_y) + shift
    };
    let pos_to_point = |pos: Pos| {
      let x = self.field.to_x(pos);
      let y = self.field.to_y(pos);
      xy_to_point(x, y)
    };

    let field = self.field_cache.draw(bounds.size(), |frame| {
      let grid = canvas::Path::new(|path| {
        for x in 0..field_width {
          let offset = (step_x * x as f32 + step_x / 2.0).round() + 0.5;
          path.move_to(Point::new(offset, 0.0) + shift);
          path.line_to(Point::new(offset, height) + shift);
        }
        for y in 0..field_height {
          let offset = (step_y * y as f32 + step_y / 2.0).round() + 0.5;
          path.move_to(Point::new(0.0, offset) + shift);
          path.line_to(Point::new(width, offset) + shift);
        }
      });

      frame.stroke(
        &grid,
        canvas::Stroke {
          width: 1.0,
          color: Color::BLACK,
          ..canvas::Stroke::default()
        },
      );

      for &player in &[Player::Red, Player::Black] {
        let points = canvas::Path::new(|path| {
          for &pos in self
            .field
            .points_seq()
            .iter()
            .filter(|&&pos| self.field.cell(pos).is_players_point(player))
          {
            path.circle(pos_to_point(pos), 5.0)
          }
        });

        frame.fill(&points, color(player));
      }

      for (chain, player) in &self.captures {
        let path = canvas::Path::new(|path| {
          path.move_to(pos_to_point(chain[0]));
          for &pos in chain.iter().skip(1) {
            path.line_to(pos_to_point(pos));
          }
        });

        let mut color = color(*player);
        color.a = 0.5;

        frame.fill(&path, color);
      }

      if let Some(&pos) = self.field.points_seq().last() {
        let last_point = canvas::Path::new(|path| path.circle(pos_to_point(pos), 8.0));

        let color = color(self.field.cell(pos).get_player());

        frame.stroke(
          &last_point,
          canvas::Stroke {
            width: 2.0,
            color,
            ..canvas::Stroke::default()
          },
        );
      }
    });

    let mut frame = canvas::Frame::new(bounds.size());

    if let Some(point) = cursor.position().and_then(|cursor_position| {
      let point = cursor_position - shift;
      if point.x >= 0.0 && point.x <= width && point.y >= 0.0 && point.y <= height {
        let point = point - cursor_shift;
        let x = (point.x / step_x).round() as u32;
        let y = (point.y / step_y).round() as u32;
        let pos = self.field.to_pos(x, y);
        if self.field.is_putting_allowed(pos) {
          Some(xy_to_point(x, y))
        } else {
          None
        }
      } else {
        None
      }
    }) {
      let cursor_point = canvas::Path::new(|path| path.circle(point, 5.0));

      let mut color = color(self.player);
      color.a = 0.5;

      frame.fill(&cursor_point, color);
    }

    vec![field, frame.into_geometry()]
  }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::io;
use std::rc::{Rc, Weak};
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};

use super::client::Client;
use super::connection::{self, Connection};
use super::datagram_buffer::DatagramBuffer;
use super::ipv4_packet::{IPv4Packet, MAX_PACKET_LENGTH};
use super::packetizer::Packetizer;
use super::route::RouteKey;

pub struct UDPConnection {
    client: Weak<RefCell<Client>>,
    route_key: RouteKey,
    socket: UdpSocket,
    client_to_network: DatagramBuffer,
    network_to_client: Packetizer,
}

impl UDPConnection {
    pub fn new(client: Weak<RefCell<Client>>, route_key: RouteKey, reference_packet: &IPv4Packet) -> io::Result<Rc<RefCell<Self>>> {
        let socket = UDPConnection::create_socket(&route_key)?;
        let raw: &[u8] = reference_packet.raw();
        let ipv4_header = reference_packet.ipv4_header().clone();
        let transport_header = reference_packet.transport_header().as_ref().unwrap().clone();
        let rc = Rc::new(RefCell::new(Self {
            client: client,
            route_key: route_key,
            socket: socket,
            client_to_network: DatagramBuffer::new(4 * MAX_PACKET_LENGTH),
            network_to_client: Packetizer::new(raw, ipv4_header, transport_header),
        }));
        Ok(rc)
    }

    fn create_socket(route_key: &RouteKey) -> io::Result<UdpSocket> {
        let autobind_addr = SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 0);
        let udp_socket = UdpSocket::bind(autobind_addr)?;
        let rewritten_destination = connection::rewritten_destination(route_key.destination_ip(), route_key.destination_port());
        udp_socket.connect(rewritten_destination)?;
        Ok(udp_socket)
    }
}

impl Connection for UDPConnection {
    fn send_to_network(&mut self, ipv4_packet: &IPv4Packet) {
        // TODO
    }

    fn disconnect(&mut self) {
        // TODO
    }

    fn is_expired(&self) -> bool {
        // TODO
        false
    }
}
<commit_msg>Implement UDPConnection::new()<commit_after>use std::cell::RefCell;
use std::io;
use std::rc::{Rc, Weak};
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
use mio::{Event, PollOpt, Ready};

use super::client::Client;
use super::connection::{self, Connection};
use super::datagram_buffer::DatagramBuffer;
use super::ipv4_packet::{IPv4Packet, MAX_PACKET_LENGTH};
use super::packetizer::Packetizer;
use super::route::RouteKey;
use super::selector::Selector;

pub struct UDPConnection {
    client: Weak<RefCell<Client>>,
    route_key: RouteKey,
    socket: UdpSocket,
    client_to_network: DatagramBuffer,
    network_to_client: Packetizer,
}

impl UDPConnection {
    pub fn new(client: Weak<RefCell<Client>>, route_key: RouteKey, reference_packet: &IPv4Packet) -> io::Result<Rc<RefCell<Self>>> {
        let socket = UDPConnection::create_socket(&route_key)?;
        let raw: &[u8] = reference_packet.raw();
        let ipv4_header = reference_packet.ipv4_header().clone();
        let transport_header = reference_packet.transport_header().as_ref().unwrap().clone();
        let rc = Rc::new(RefCell::new(Self {
            client: client,
            route_key: route_key,
            socket: socket,
            client_to_network: DatagramBuffer::new(4 * MAX_PACKET_LENGTH),
            network_to_client: Packetizer::new(raw, ipv4_header, transport_header),
        }));

        {
            let rc_clone = rc.clone();
            let handler = move |selector: &mut Selector, ready| {
                let mut self_ref = rc_clone.borrow_mut();
                self_ref.on_ready(selector, ready);
            };
            let mut self_ref = rc.borrow_mut();
            //let token = selector.register(&self_ref.socket, handler, Ready::readable(), PollOpt::level())?;
        }
        Ok(rc)
    }

    fn create_socket(route_key: &RouteKey) -> io::Result<UdpSocket> {
        let autobind_addr = SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 0);
        let udp_socket = UdpSocket::bind(autobind_addr)?;
        let rewritten_destination = connection::rewritten_destination(route_key.destination_ip(), route_key.destination_port());
        udp_socket.connect(rewritten_destination)?;
        Ok(udp_socket)
    }

    fn on_ready(&mut self, selector: &mut Selector, event: Event) {

    }
}

impl Connection for UDPConnection {
    fn send_to_network(&mut self, ipv4_packet: &IPv4Packet) {
        // TODO
    }

    fn disconnect(&mut self) {
        // TODO
    }

    fn is_expired(&self) -> bool {
        // TODO
        false
    }
}
<|endoftext|>


<commit_before>use base::world::{Chunk, HexPillar, PropType};
use base::math::*;
use glium::{self, DrawParameters, IndexBuffer, Program, VertexBuffer};
use glium::draw_parameters::{BackfaceCullingMode, DepthTest};
use glium::backend::Facade;
use glium::texture::DepthTexture2d;
use glium::uniforms::SamplerWrapFunction;
use glium::uniforms::MinifySamplerFilter;
use Camera;
use util::ToArr;
use view::{PlantRenderer, PlantView};
use world::ChunkRenderer;
use world::HexagonOutline;
use std::rc::Rc;
use base::world::ground::GroundMaterial;

/// Graphical representation of the `base::Chunk`.
pub struct ChunkView {
    renderer: Rc<ChunkRenderer>,
    pillars: Vec<PillarView>,
    /// Instance data buffer.
    pillar_buf: VertexBuffer<Instance>,
}

impl ChunkView {
    /// Creates the graphical representation of given chunk at the given chunk
    /// offset
    pub fn from_chunk<F: Facade>(chunk: &Chunk,
                                 offset: AxialPoint,
                                 chunk_renderer: Rc<ChunkRenderer>,
                                 plant_renderer: Rc<PlantRenderer>,
                                 facade: &F)
                                 -> Self {

        let mut sections = Vec::new();
        let mut pillars = Vec::new();

        for (axial, pillar) in chunk.pillars() {
            let pos = offset.to_real() + axial.to_real();
            pillars.push(PillarView::from_pillar(pos, pillar, plant_renderer.clone(), facade));
            for section in pillar.sections() {
                let g = match section.ground {
                    GroundMaterial::Grass => 1,
                    GroundMaterial::Sand => 2,
                    GroundMaterial::Snow => 3,
                    GroundMaterial::Dirt => 4,
                    GroundMaterial::Stone => 5,
                    GroundMaterial::JungleGrass => 1,
                    GroundMaterial::Mulch => 7,
                    GroundMaterial::Debug => 8,
                };
                sections.push(Instance {
                    material_color: section.ground.get_color(),
                    ground: g,
                    offset: [pos.x, pos.y, section.bottom.to_real()],
                    height: (section.top.units() - section.bottom.units()) as f32,
                });
            }
        }

        ChunkView {
            renderer: chunk_renderer,
            pillars: pillars,
            pillar_buf: VertexBuffer::dynamic(facade, &sections).unwrap(),
        }
    }

    pub fn get_outline(&self) -> &HexagonOutline {
        &self.renderer.outline
    }

    pub fn draw_shadow<S: glium::Surface>(&self, surface: &mut S, camera: &Camera) {
        let uniforms = uniform! {
            proj_matrix: camera.proj_matrix().to_arr(),
            view_matrix: camera.view_matrix().to_arr(),
        };

        let params = DrawParameters {
            depth: glium::Depth {
                write: true,
                test: DepthTest::IfLess,
                ..Default::default()
            },
            backface_culling: BackfaceCullingMode::CullClockwise,
            ..Default::default()
        };

        surface.draw((self.renderer.pillar_vertices(), self.pillar_buf.per_instance().unwrap()),
                  self.renderer.pillar_indices(),
                  self.renderer.shadow_program(),
                  &uniforms,
                  &params)
            .unwrap();

        for pillar in &self.pillars {
            for plant in &pillar.plants {
                plant.draw_shadow(surface, camera);
            }
        }
    }

    pub fn draw<S: glium::Surface>(&self,
                                   surface: &mut S,
                                   camera: &Camera,
                                   shadow_map: &DepthTexture2d,
                                   depth_view_proj: &Matrix4<f32>,
                                   sun_dir: Vector3f) {
        let uniforms = uniform! {
            proj_matrix: camera.proj_matrix().to_arr(),
            view_matrix: camera.view_matrix().to_arr(),
            shadow_map: shadow_map.sampled().wrap_function(SamplerWrapFunction::Clamp),
            depth_view_proj: depth_view_proj.to_arr(),
            sun_dir: sun_dir.to_arr(),

            sand_texture:  self.renderer.noise_sand.sampled()
                .minify_filter(MinifySamplerFilter::NearestMipmapLinear)
                .wrap_function(SamplerWrapFunction::Repeat),
            snow_texture:  self.renderer.noise_snow.sampled()
                .minify_filter(MinifySamplerFilter::NearestMipmapLinear)
                .wrap_function(SamplerWrapFunction::Repeat),
            grass_texture: self.renderer.noise_grass.sampled()
                .minify_filter(MinifySamplerFilter::NearestMipmapLinear)
                .wrap_function(SamplerWrapFunction::Repeat),
            stone_texture: self.renderer.noise_stone.sampled()
                .minify_filter(MinifySamplerFilter::NearestMipmapLinear)
                .wrap_function(SamplerWrapFunction::Repeat),
            dirt_texture: self.renderer.noise_dirt.sampled()
                .minify_filter(MinifySamplerFilter::NearestMipmapLinear)
                .wrap_function(SamplerWrapFunction::Repeat),
            mulch_texture: self.renderer.noise_mulch.sampled()
                .minify_filter(MinifySamplerFilter::NearestMipmapLinear)
                .wrap_function(SamplerWrapFunction::Repeat),

            normal_sand: &self.renderer.normal_sand,
            normal_snow: &self.renderer.normal_snow,
            normal_grass: &self.renderer.normal_grass,
            normal_stone: &self.renderer.normal_stone,
            normal_dirt: &self.renderer.normal_dirt,
            normal_mulch: &self.renderer.normal_mulch,
        };
        let params = DrawParameters {
            depth: glium::Depth {
                write: true,
                test: DepthTest::IfLess,
                ..Default::default()
            },
            backface_culling: BackfaceCullingMode::CullCounterClockwise,
            ..Default::default()
        };

        // Draw hexagons
        surface.draw((self.renderer.pillar_vertices(), self.pillar_buf.per_instance().unwrap()),
                  self.renderer.pillar_indices(),
                  self.renderer.program(),
                  &uniforms,
                  &params)
            .unwrap();

        for pillar in &self.pillars {
            for plant in &pillar.plants {
                plant.draw(surface, camera);
            }
        }
    }
}

/// Vertex type used to render chunks (or hex pillars).
#[derive(Debug, Copy, Clone)]
pub struct Vertex {
    pub position: [f32; 3],
    pub normal: [f32; 3],
    pub radius: f32,
    pub tex_coords: [f32; 2],
}

implement_vertex!(Vertex, position, normal, radius, tex_coords);

/// Instance data for each pillar section.
#[derive(Debug, Copy, Clone)]
pub struct Instance {
    ground: i32,
    /// Material color.
    material_color: [f32; 3],
    /// Offset in world coordinates.
    offset: [f32; 3],
    /// Pillar height.
    height: f32,
}

implement_vertex!(Instance, material_color, offset, ground, height);

pub struct PillarView {
    plants: Vec<PlantView>,

}

impl PillarView {
    fn from_pillar<F: Facade>(pos: Point2f,
                              pillar: &HexPillar,
                              plant_renderer: Rc<PlantRenderer>,
                              facade: &F)
                              -> PillarView {
        PillarView {
            plants: pillar.props()
                .iter()
                .map(|prop| {
                    match prop.prop {
                        PropType::Plant(ref plant) => {
                            let pos = Point3f::new(pos.x, pos.y, prop.baseline.to_real());
                            PlantView::from_plant(pos, plant, plant_renderer.clone(), facade)
                        }
                    }
                })
                .collect(),
        }
    }
}
<commit_msg>Implement Outlined Hexagon<commit_after>use base::world::{Chunk, HexPillar, PropType};
use base::math::*;
use glium::{self, DrawParameters, IndexBuffer, Program, VertexBuffer};
use glium::draw_parameters::{BackfaceCullingMode, DepthTest};
use glium::backend::Facade;
use glium::texture::DepthTexture2d;
use glium::uniforms::SamplerWrapFunction;
use glium::uniforms::MinifySamplerFilter;
use Camera;
use util::ToArr;
use view::{PlantRenderer, PlantView};
use world::ChunkRenderer;
use world::HexagonOutline;
use std::rc::Rc;
use base::world::ground::GroundMaterial;

/// Graphical representation of the `base::Chunk`.
pub struct ChunkView {
    renderer: Rc<ChunkRenderer>,
    pillars: Vec<PillarView>,
    /// Instance data buffer.
    pillar_buf: VertexBuffer<Instance>,
}

impl ChunkView {
    /// Creates the graphical representation of given chunk at the given chunk
    /// offset
    pub fn from_chunk<F: Facade>(chunk: &Chunk,
                                 offset: AxialPoint,
                                 chunk_renderer: Rc<ChunkRenderer>,
                                 plant_renderer: Rc<PlantRenderer>,
                                 facade: &F)
                                 -> Self {

        let mut sections = Vec::new();
        let mut pillars = Vec::new();

        for (axial, pillar) in chunk.pillars() {
            let pos = offset.to_real() + axial.to_real();
            pillars.push(PillarView::from_pillar(pos, pillar, plant_renderer.clone(), facade));
            for section in pillar.sections() {
                let g = match section.ground {
                    GroundMaterial::Grass => 1,
                    GroundMaterial::Sand => 2,
                    GroundMaterial::Snow => 3,
                    GroundMaterial::Dirt => 4,
                    GroundMaterial::Stone => 5,
                    GroundMaterial::JungleGrass => 1,
                    GroundMaterial::Mulch => 7,
                    GroundMaterial::Debug => 8,
                };
                sections.push(Instance {
                    material_color: section.ground.get_color(),
                    ground: g,
                    offset: [pos.x, pos.y, section.bottom.to_real()],
                    height: (section.top.units() - section.bottom.units()) as f32,
                });
            }
        }

        ChunkView {
            renderer: chunk_renderer,
            pillars: pillars,
            pillar_buf: VertexBuffer::dynamic(facade, &sections).unwrap(),
        }
    }

    pub fn get_outline(&self) -> &HexagonOutline {
        &self.renderer.outline
    }

    pub fn draw_shadow<S: glium::Surface>(&self, surface: &mut S, camera: &Camera) {

        let uniforms = uniform! {
            proj_matrix: camera.proj_matrix().to_arr(),
            view_matrix: camera.view_matrix().to_arr(),
        };

        let params = DrawParameters {
            depth: glium::Depth {
                write: true,
                test: DepthTest::IfLess,
                ..Default::default()
            },
            backface_culling: BackfaceCullingMode::CullClockwise,
            ..Default::default()
        };

        surface.draw((self.renderer.pillar_vertices(), self.pillar_buf.per_instance().unwrap()),
                  self.renderer.pillar_indices(),
                  self.renderer.shadow_program(),
                  &uniforms,
                  &params)
            .unwrap();

        for pillar in &self.pillars {
            for plant in &pillar.plants {
                plant.draw_shadow(surface, camera);
            }
        }
    }

    pub fn draw<S: glium::Surface>(&self,
                                   surface: &mut S,
                                   camera: &Camera,
                                   shadow_map: &DepthTexture2d,
                                   depth_view_proj: &Matrix4<f32>,
                                   sun_dir: Vector3f) {
        let uniforms = uniform! {
            proj_matrix: camera.proj_matrix().to_arr(),
            view_matrix: camera.view_matrix().to_arr(),
            shadow_map: shadow_map.sampled().wrap_function(SamplerWrapFunction::Clamp),
            depth_view_proj: depth_view_proj.to_arr(),
            sun_dir: sun_dir.to_arr(),

            sand_texture:  self.renderer.noise_sand.sampled()
                .minify_filter(MinifySamplerFilter::NearestMipmapLinear)
                .wrap_function(SamplerWrapFunction::Repeat),
            snow_texture:  self.renderer.noise_snow.sampled()
                .minify_filter(MinifySamplerFilter::NearestMipmapLinear)
                .wrap_function(SamplerWrapFunction::Repeat),
            grass_texture: self.renderer.noise_grass.sampled()
                .minify_filter(MinifySamplerFilter::NearestMipmapLinear)
                .wrap_function(SamplerWrapFunction::Repeat),
            stone_texture: self.renderer.noise_stone.sampled()
                .minify_filter(MinifySamplerFilter::NearestMipmapLinear)
                .wrap_function(SamplerWrapFunction::Repeat),
            dirt_texture: self.renderer.noise_dirt.sampled()
                .minify_filter(MinifySamplerFilter::NearestMipmapLinear)
                .wrap_function(SamplerWrapFunction::Repeat),
            mulch_texture: self.renderer.noise_mulch.sampled()
                .minify_filter(MinifySamplerFilter::NearestMipmapLinear)
                .wrap_function(SamplerWrapFunction::Repeat),

            normal_sand: &self.renderer.normal_sand,
            normal_snow: &self.renderer.normal_snow,
            normal_grass: &self.renderer.normal_grass,
            normal_stone: &self.renderer.normal_stone,
            normal_dirt: &self.renderer.normal_dirt,
            normal_mulch: &self.renderer.normal_mulch,
        };
        let params = DrawParameters {
            depth: glium::Depth {
                write: true,
                test: DepthTest::IfLess,
                ..Default::default()
            },
            backface_culling: BackfaceCullingMode::CullCounterClockwise,
            ..Default::default()
        };

        // Draw hexagons
        surface.draw((self.renderer.pillar_vertices(), self.pillar_buf.per_instance().unwrap()),
                  self.renderer.pillar_indices(),
                  self.renderer.program(),
                  &uniforms,
                  &params)
            .unwrap();

        // Draw outline
        let outline_params = DrawParameters {
            depth: glium::Depth {
                write: true,
                test: DepthTest::IfLess,
                ..Default::default()
            },
            ..Default::default()
        };

        let outline_uniforms = uniform! {
            outline_pos: self.renderer.outline.position().to_arr(),
            proj_matrix: camera.proj_matrix().to_arr(),
            view_matrix: camera.view_matrix().to_arr(),
            transformation: [
                [1.5, 0.0, 0.0, 0.0],
                [0.0, 1.5, 0.0, 0.0],
                [0.0, 0.0, 1.5, 0.0],
                [0.0, 0.0, 0.0, 1.0f32]
            ],
        };

        surface.draw(self.renderer.outline.vertices(),
                  self.renderer.outline.indices(),
                  self.renderer.outline.program(),
                  &outline_uniforms,
                  &outline_params)
            .unwrap();

        for pillar in &self.pillars {
            for plant in &pillar.plants {
                plant.draw(surface, camera);
            }
        }
    }
}

/// Vertex type used to render chunks (or hex pillars).
#[derive(Debug, Copy, Clone)]
pub struct Vertex {
    pub position: [f32; 3],
    pub normal: [f32; 3],
    pub radius: f32,
    pub tex_coords: [f32; 2],
}

implement_vertex!(Vertex, position, normal, radius, tex_coords);

/// Instance data for each pillar section.
#[derive(Debug, Copy, Clone)]
pub struct Instance {
    ground: i32,
    /// Material color.
    material_color: [f32; 3],
    /// Offset in world coordinates.
    offset: [f32; 3],
    /// Pillar height.
    height: f32,
}

implement_vertex!(Instance, material_color, offset, ground, height);

pub struct PillarView {
    plants: Vec<PlantView>,

}

impl PillarView {
    fn from_pillar<F: Facade>(pos: Point2f,
                              pillar: &HexPillar,
                              plant_renderer: Rc<PlantRenderer>,
                              facade: &F)
                              -> PillarView {
        PillarView {
            plants: pillar.props()
                .iter()
                .map(|prop| {
                    match prop.prop {
                        PropType::Plant(ref plant) => {
                            let pos = Point3f::new(pos.x, pos.y, prop.baseline.to_real());
                            PlantView::from_plant(pos, plant, plant_renderer.clone(), facade)
                        }
                    }
                })
                .collect(),
        }
    }
}
<|endoftext|>


<commit_before>#![feature(try_trait_v2)]
#![feature(let_chains)]

mod builtin_functions;
mod compiler;
mod database;
mod discover;
mod incremental;
mod input;
mod language_server;
mod vm;

use crate::{
    compiler::{
        ast_to_hir::AstToHir, cst_to_ast::CstToAst, hir, hir_to_lir::HirToLir,
        rcst_to_cst::RcstToCst, string_to_rcst::StringToRcst,
    },
    database::{Database, PROJECT_DIRECTORY},
    input::Input,
    vm::{Status, Vm},
};
use compiler::lir::Lir;
use itertools::Itertools;
use language_server::CandyLanguageServer;
use log::{debug, error, info, LevelFilter};
use lspower::{LspService, Server};
use notify::{watcher, RecursiveMode, Watcher};
use std::{
    env::current_dir,
    fs,
    path::PathBuf,
    sync::{mpsc::channel, Arc},
    time::Duration,
};
use structopt::StructOpt;

#[derive(StructOpt, Debug)]
#[structopt(name = "candy", about = "The 🍭 Candy CLI.")]
enum CandyOptions {
    Build(CandyBuildOptions),
    Run(CandyRunOptions),
    Lsp,
}

#[derive(StructOpt, Debug)]
struct CandyBuildOptions {
    #[structopt(long)]
    debug: bool,

    #[structopt(long)]
    watch: bool,

    #[structopt(parse(from_os_str))]
    file: PathBuf,
}

#[derive(StructOpt, Debug)]
struct CandyRunOptions {
    #[structopt(parse(from_os_str))]
    file: PathBuf,
}

#[tokio::main]
async fn main() {
    init_logger();
    match CandyOptions::from_args() {
        CandyOptions::Build(options) => build(options),
        CandyOptions::Run(options) => run(options),
        CandyOptions::Lsp => lsp().await,
    }
}

fn build(options: CandyBuildOptions) {
    *PROJECT_DIRECTORY.lock().unwrap() = Some(current_dir().unwrap());

    raw_build(&options.file, options.debug);

    if options.watch {
        let (tx, rx) = channel();
        let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap();
        watcher
            .watch(&options.file, RecursiveMode::Recursive)
            .unwrap();
        loop {
            match rx.recv() {
                Ok(_) => {
                    raw_build(&options.file, options.debug);
                }
                Err(e) => error!("watch error: {:#?}", e),
            }
        }
    }
}
fn raw_build(file: &PathBuf, debug: bool) -> Option<Arc<Lir>> {
    let path_string = file.to_string_lossy();
    debug!("Building `{}`.", path_string);

    let input: Input = file.clone().into();
    let db = Database::default();

    info!("Parsing string to RCST…");
    let rcst = db
        .rcst(input.clone())
        .unwrap_or_else(|| panic!("File `{}` not found.", path_string));
    if debug {
        let hir_file = file.clone_with_extension("candy.rcst");
        fs::write(hir_file, format!("{:#?}\n", rcst.clone())).unwrap();
    }

    info!("Parsing RCST to CST…");
    let cst = db
        .cst(input.clone())
        .unwrap_or_else(|| panic!("File `{}` not found.", path_string));
    if debug {
        let cst_file = file.clone_with_extension("candy.cst");
        fs::write(cst_file, format!("{:#?}\n", cst.clone())).unwrap();
    }

    info!("Lowering CST to AST…");
    let (asts, ast_cst_id_map) = db
        .ast(input.clone())
        .unwrap_or_else(|| panic!("File `{}` not found.", path_string));
    if debug {
        let ast_file = file.clone_with_extension("candy.ast");
        fs::write(
            ast_file,
            format!("{}\n", asts.iter().map(|ast| format!("{}", ast)).join("\n")),
        )
        .unwrap();

        let ast_to_cst_ids_file = file.clone_with_extension("candy.ast_to_cst_ids");
        fs::write(
            ast_to_cst_ids_file,
            ast_cst_id_map
                .keys()
                .into_iter()
                .sorted_by_key(|it| it.local)
                .map(|key| format!("{} -> {}\n", key, ast_cst_id_map[key].0))
                .join(""),
        )
        .unwrap();
    }

    info!("Compiling AST to HIR…");
    let (hir, hir_ast_id_map) = db
        .hir(input.clone())
        .unwrap_or_else(|| panic!("File `{}` not found.", path_string));
    if debug {
        let hir_file = file.clone_with_extension("candy.hir");
        fs::write(hir_file, format!("{}", hir.clone())).unwrap();

        let hir_ast_id_file = file.clone_with_extension("candy.hir_to_ast_ids");
        fs::write(
            hir_ast_id_file,
            hir_ast_id_map
                .keys()
                .into_iter()
                .map(|key| format!("{} -> {}\n", key, hir_ast_id_map[key]))
                .join(""),
        )
        .unwrap();
    }

    info!("Compiling HIR to LIR…");
    let lir = db
        .lir(input.clone())
        .unwrap_or_else(|| panic!("File `{}` not found.", path_string));
    if debug {
        let lir_file = file.clone_with_extension("candy.lir");
        fs::write(lir_file, format!("{}", lir)).unwrap();
    }

    Some(lir)
}

fn run(options: CandyRunOptions) {
    *PROJECT_DIRECTORY.lock().unwrap() = Some(current_dir().unwrap());

    debug!("Running `{}`.\n", options.file.display());

    let _input: Input = options.file.clone().into();
    let _db = Database::default();

    let lir = match raw_build(&options.file, false) {
        Some(lir) => lir,
        None => {
            println!("Build failed.");
            return;
        }
    };

    let path_string = options.file.to_string_lossy();
    debug!("Running `{}`.", path_string);

    let mut vm = Vm::new(lir.chunks.clone());
    vm.run(1000);
    match vm.status() {
        Status::Running => info!("VM is still running."),
        Status::Done(value) => info!("VM is done: {:#?}", value),
        Status::Panicked(value) => {
            error!("VM panicked: {:#?}", value);
        }
    }
}

async fn lsp() {
    info!("Starting language server…");
    let (service, messages) = LspService::new(|client| CandyLanguageServer::from_client(client));
    Server::new(tokio::io::stdin(), tokio::io::stdout())
        .interleave(messages)
        .serve(service)
        .await;
}

fn init_logger() {
    fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{} [{:>5}] {} {}",
                chrono::Local::now().format("%H:%M:%S"),
                record.level(),
                record.target(),
                message
            ))
        })
        .level_for("salsa", LevelFilter::Error)
        .level_for("tokio_util", LevelFilter::Error)
        .level_for("lspower::transport", LevelFilter::Error)
        .level_for("candy::compiler::string_to_rcst", LevelFilter::Debug)
        .chain(std::io::stderr())
        .apply()
        .unwrap();
}

trait CloneWithExtension {
    fn clone_with_extension(&self, extension: &'static str) -> Self;
}
impl CloneWithExtension for PathBuf {
    fn clone_with_extension(&self, extension: &'static str) -> Self {
        let mut path = self.clone();
        assert!(path.set_extension(extension));
        path
    }
}
<commit_msg>Display a stack trace on panic<commit_after>#![feature(try_trait_v2)]
#![feature(let_chains)]

mod builtin_functions;
mod compiler;
mod database;
mod discover;
mod incremental;
mod input;
mod language_server;
mod vm;

use crate::{
    compiler::{
        ast_to_hir::AstToHir, cst::CstDb, cst_to_ast::CstToAst, hir, hir_to_lir::HirToLir,
        rcst_to_cst::RcstToCst, string_to_rcst::StringToRcst,
    },
    database::{Database, PROJECT_DIRECTORY},
    input::Input,
    language_server::utils::LspPositionConversion,
    vm::{Status, Vm},
};
use compiler::lir::Lir;
use itertools::Itertools;
use language_server::CandyLanguageServer;
use log::{debug, error, info, LevelFilter};
use lspower::{LspService, Server};
use notify::{watcher, RecursiveMode, Watcher};
use std::{
    env::current_dir,
    fs,
    path::PathBuf,
    sync::{mpsc::channel, Arc},
    time::Duration,
};
use structopt::StructOpt;

#[derive(StructOpt, Debug)]
#[structopt(name = "candy", about = "The 🍭 Candy CLI.")]
enum CandyOptions {
    Build(CandyBuildOptions),
    Run(CandyRunOptions),
    Lsp,
}

#[derive(StructOpt, Debug)]
struct CandyBuildOptions {
    #[structopt(long)]
    debug: bool,

    #[structopt(long)]
    watch: bool,

    #[structopt(parse(from_os_str))]
    file: PathBuf,
}

#[derive(StructOpt, Debug)]
struct CandyRunOptions {
    #[structopt(parse(from_os_str))]
    file: PathBuf,
}

#[tokio::main]
async fn main() {
    init_logger();
    match CandyOptions::from_args() {
        CandyOptions::Build(options) => build(options),
        CandyOptions::Run(options) => run(options),
        CandyOptions::Lsp => lsp().await,
    }
}

fn build(options: CandyBuildOptions) {
    *PROJECT_DIRECTORY.lock().unwrap() = Some(current_dir().unwrap());

    raw_build(&options.file, options.debug);

    if options.watch {
        let (tx, rx) = channel();
        let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap();
        watcher
            .watch(&options.file, RecursiveMode::Recursive)
            .unwrap();
        loop {
            match rx.recv() {
                Ok(_) => {
                    raw_build(&options.file, options.debug);
                }
                Err(e) => error!("watch error: {:#?}", e),
            }
        }
    }
}
fn raw_build(file: &PathBuf, debug: bool) -> Option<Arc<Lir>> {
    let path_string = file.to_string_lossy();
    debug!("Building `{}`.", path_string);

    let input: Input = file.clone().into();
    let db = Database::default();

    info!("Parsing string to RCST…");
    let rcst = db
        .rcst(input.clone())
        .unwrap_or_else(|| panic!("File `{}` not found.", path_string));
    if debug {
        let hir_file = file.clone_with_extension("candy.rcst");
        fs::write(hir_file, format!("{:#?}\n", rcst.clone())).unwrap();
    }

    info!("Parsing RCST to CST…");
    let cst = db
        .cst(input.clone())
        .unwrap_or_else(|| panic!("File `{}` not found.", path_string));
    if debug {
        let cst_file = file.clone_with_extension("candy.cst");
        fs::write(cst_file, format!("{:#?}\n", cst.clone())).unwrap();
    }

    info!("Lowering CST to AST…");
    let (asts, ast_cst_id_map) = db
        .ast(input.clone())
        .unwrap_or_else(|| panic!("File `{}` not found.", path_string));
    if debug {
        let ast_file = file.clone_with_extension("candy.ast");
        fs::write(
            ast_file,
            format!("{}\n", asts.iter().map(|ast| format!("{}", ast)).join("\n")),
        )
        .unwrap();

        let ast_to_cst_ids_file = file.clone_with_extension("candy.ast_to_cst_ids");
        fs::write(
            ast_to_cst_ids_file,
            ast_cst_id_map
                .keys()
                .into_iter()
                .sorted_by_key(|it| it.local)
                .map(|key| format!("{} -> {}\n", key, ast_cst_id_map[key].0))
                .join(""),
        )
        .unwrap();
    }

    info!("Compiling AST to HIR…");
    let (hir, hir_ast_id_map) = db
        .hir(input.clone())
        .unwrap_or_else(|| panic!("File `{}` not found.", path_string));
    if debug {
        let hir_file = file.clone_with_extension("candy.hir");
        fs::write(hir_file, format!("{}", hir.clone())).unwrap();

        let hir_ast_id_file = file.clone_with_extension("candy.hir_to_ast_ids");
        fs::write(
            hir_ast_id_file,
            hir_ast_id_map
                .keys()
                .into_iter()
                .map(|key| format!("{} -> {}\n", key, hir_ast_id_map[key]))
                .join(""),
        )
        .unwrap();
    }

    info!("Compiling HIR to LIR…");
    let lir = db
        .lir(input.clone())
        .unwrap_or_else(|| panic!("File `{}` not found.", path_string));
    if debug {
        let lir_file = file.clone_with_extension("candy.lir");
        fs::write(lir_file, format!("{}", lir)).unwrap();
    }

    Some(lir)
}

fn run(options: CandyRunOptions) {
    *PROJECT_DIRECTORY.lock().unwrap() = Some(current_dir().unwrap());

    debug!("Running `{}`.\n", options.file.display());

    let input: Input = options.file.clone().into();
    let db = Database::default();

    let lir = match raw_build(&options.file, false) {
        Some(lir) => lir,
        None => {
            println!("Build failed.");
            return;
        }
    };

    let path_string = options.file.to_string_lossy();
    debug!("Running `{}`.", path_string);

    let mut vm = Vm::new(lir.chunks.clone());
    vm.run(1000);
    match vm.status() {
        Status::Running => info!("VM is still running."),
        Status::Done(value) => info!("VM is done: {:#?}", value),
        Status::Panicked(value) => {
            error!("VM panicked: {:#?}", value);

            error!("Stack trace:");
            let (_, hir_to_ast_ids) = db.hir(input.clone()).unwrap();
            let (_, ast_to_cst_ids) = db.ast(input.clone()).unwrap();
            for hir_id in vm.current_stack_trace().into_iter().rev() {
                let ast_id = hir_to_ast_ids[&hir_id].clone();
                let cst_id = ast_to_cst_ids[&ast_id];
                let cst = db.find_cst(input.clone(), cst_id);
                let start = db.offset_to_lsp(input.clone(), cst.span.start);
                let end = db.offset_to_lsp(input.clone(), cst.span.end);
                error!(
                    "{}, {}, {:?}, {}:{} – {}:{}",
                    hir_id, ast_id, cst_id, start.0, start.1, end.0, end.1
                );
            }
        }
    }
}

async fn lsp() {
    info!("Starting language server…");
    let (service, messages) = LspService::new(|client| CandyLanguageServer::from_client(client));
    Server::new(tokio::io::stdin(), tokio::io::stdout())
        .interleave(messages)
        .serve(service)
        .await;
}

fn init_logger() {
    fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{} [{:>5}] {} {}",
                chrono::Local::now().format("%H:%M:%S"),
                record.level(),
                record.target(),
                message
            ))
        })
        .level_for("salsa", LevelFilter::Error)
        .level_for("tokio_util", LevelFilter::Error)
        .level_for("lspower::transport", LevelFilter::Error)
        .level_for("candy::compiler::string_to_rcst", LevelFilter::Debug)
        .chain(std::io::stderr())
        .apply()
        .unwrap();
}

trait CloneWithExtension {
    fn clone_with_extension(&self, extension: &'static str) -> Self;
}
impl CloneWithExtension for PathBuf {
    fn clone_with_extension(&self, extension: &'static str) -> Self {
        let mut path = self.clone();
        assert!(path.set_extension(extension));
        path
    }
}
<|endoftext|>


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

use std::collections::HashSet;
use std::{ffi, fmt, mem, str};
use gl;
use gfx_core::Capabilities;

/// A version number for a specific component of an OpenGL implementation
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct Version {
    pub major: u32,
    pub minor: u32,
    pub revision: Option<u32>,
    pub vendor_info: &'static str,
}

impl Version {
    /// Create a new OpenGL version number
    pub fn new(major: u32, minor: u32, revision: Option<u32>,
               vendor_info: &'static str) -> Version {
        Version {
            major: major,
            minor: minor,
            revision: revision,
            vendor_info: vendor_info,
        }
    }

    /// According to the OpenGL specification, the version information is
    /// expected to follow the following syntax:
    ///
    /// ~~~bnf
    /// <major>       ::= <number>
    /// <minor>       ::= <number>
    /// <revision>    ::= <number>
    /// <vendor-info> ::= <string>
    /// <release>     ::= <major> "." <minor> ["." <release>]
    /// <version>     ::= <release> [" " <vendor-info>]
    /// ~~~
    ///
    /// Note that this function is intentionally lenient in regards to parsing,
    /// and will try to recover at least the first two version numbers without
    /// resulting in an `Err`.
    pub fn parse(src: &'static str) -> Result<Version, &'static str> {
        let (version, vendor_info) = match src.find(' ') {
            Some(i) => (&src[..i], &src[(i + 1)..]),
            None => (src, ""),
        };

        // TODO: make this even more lenient so that we can also accept
        // `<major> "." <minor> [<???>]`
        let mut it = version.split('.');
        let major = it.next().and_then(|s| s.parse().ok());
        let minor = it.next().and_then(|s| s.parse().ok());
        let revision = it.next().and_then(|s| s.parse().ok());

        match (major, minor, revision) {
            (Some(major), Some(minor), revision) => Ok(Version {
                major: major,
                minor: minor,
                revision: revision,
                vendor_info: vendor_info,
            }),
            (_, _, _) => Err(src),
        }
    }
}

impl fmt::Debug for Version {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match (self.major, self.minor, self.revision, self.vendor_info) {
            (major, minor, Some(revision), "") =>
                write!(f, "{}.{}.{}", major, minor, revision),
            (major, minor, None, "") =>
                write!(f, "{}.{}", major, minor),
            (major, minor, Some(revision), vendor_info) =>
                write!(f, "{}.{}.{}, {}", major, minor, revision, vendor_info),
            (major, minor, None, vendor_info) =>
                write!(f, "{}.{}, {}", major, minor, vendor_info),
        }
    }
}

const EMPTY_STRING: &'static str = "";

/// Get a statically allocated string from the implementation using
/// `glGetString`. Fails if it `GLenum` cannot be handled by the
/// implementation's `gl.GetString` function.
fn get_string(gl: &gl::Gl, name: gl::types::GLenum) -> &'static str {
    let ptr = unsafe { gl.GetString(name) } as *const i8;
    if !ptr.is_null() {
        // This should be safe to mark as statically allocated because
        // GlGetString only returns static strings.
        unsafe { c_str_as_static_str(ptr) }
    } else {
        error!("Invalid GLenum passed to `get_string`: {:x}", name);
        EMPTY_STRING
    }
}

fn get_usize(gl: &gl::Gl, name: gl::types::GLenum) -> usize {
    let mut value = 0 as gl::types::GLint;
    unsafe { gl.GetIntegerv(name, &mut value) };
    value as usize
}

unsafe fn c_str_as_static_str(c_str: *const i8) -> &'static str {
    mem::transmute(str::from_utf8(ffi::CStr::from_ptr(c_str as *const _).to_bytes()).unwrap())
}

/// A unique platform identifier that does not change between releases
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct PlatformName {
    /// The company responsible for the OpenGL implementation
    pub vendor: &'static str,
    /// The name of the renderer
    pub renderer: &'static str,
}

impl PlatformName {
    fn get(gl: &gl::Gl) -> PlatformName {
        PlatformName {
            vendor: get_string(gl, gl::VENDOR),
            renderer: get_string(gl, gl::RENDERER),
        }
    }
}

/// Private capabilities that don't need to be exposed.
#[derive(Debug)]
pub struct PrivateCaps {
    pub array_buffer_supported: bool,
    pub frame_buffer_supported: bool,
    pub immutable_storage_supported: bool,
    pub sampler_objects_supported: bool,
    pub program_interface_supported: bool,
}

/// OpenGL implementation information
#[derive(Debug)]
pub struct Info {
    /// The platform identifier
    pub platform_name: PlatformName,
    /// The OpenGL API vesion number
    pub version: Version,
    /// The GLSL vesion number
    pub shading_language: Version,
    /// The extensions supported by the implementation
    pub extensions: HashSet<&'static str>,
}

impl Info {
    fn get(gl: &gl::Gl) -> Info {
        let platform_name = PlatformName::get(gl);
        let version = Version::parse(get_string(gl, gl::VERSION)).unwrap();
        let shading_language = Version::parse(get_string(gl, gl::SHADING_LANGUAGE_VERSION)).unwrap();
        let extensions = if version >= Version::new(3, 0, None, "") {
            let num_exts = get_usize(gl, gl::NUM_EXTENSIONS) as gl::types::GLuint;
            (0..num_exts)
                .map(|i| unsafe { c_str_as_static_str(gl.GetStringi(gl::EXTENSIONS, i) as *const i8) })
                .collect()
        } else {
            // Fallback
            get_string(gl, gl::EXTENSIONS).split(' ').collect()
        };
        Info {
            platform_name: platform_name,
            version: version,
            shading_language: shading_language,
            extensions: extensions,
        }
    }

    pub fn is_version_supported(&self, major: u32, minor: u32) -> bool {
        self.version >= Version::new(major, minor, None, "")
    }

    /// Returns `true` if the implementation supports the extension
    pub fn is_extension_supported(&self, s: &'static str) -> bool {
        self.extensions.contains(&s)
    }

    pub fn is_version_or_extension_supported(&self, major: u32, minor: u32, ext: &'static str) -> bool {
        self.is_version_supported(major, minor) || self.is_extension_supported(ext)
    }
}

/// Load the information pertaining to the driver and the corresponding device
/// capabilities.
pub fn get(gl: &gl::Gl) -> (Info, Capabilities, PrivateCaps) {
    let info = Info::get(gl);
    let caps = Capabilities {
        max_vertex_count: get_usize(gl, gl::MAX_ELEMENTS_VERTICES),
        max_index_count:  get_usize(gl, gl::MAX_ELEMENTS_INDICES),
        max_texture_size: get_usize(gl, gl::MAX_TEXTURE_SIZE),

        instance_base_supported:           info.is_version_or_extension_supported(4, 2, "GL_ARB_base_instance"),
        instance_call_supported:           info.is_version_or_extension_supported(3, 1, "GL_ARB_draw_instanced"),
        instance_rate_supported:           info.is_version_or_extension_supported(3, 3, "GL_ARB_instanced_arrays"),
        vertex_base_supported:             info.is_version_or_extension_supported(3, 2, "GL_ARB_draw_elements_base_vertex"),
        srgb_color_supported:              info.is_version_or_extension_supported(3, 2, "GL_ARB_framebuffer_sRGB"),
        constant_buffer_supported:         info.is_version_or_extension_supported(3, 1, "GL_ARB_uniform_buffer_object"),
        unordered_access_view_supported:   info.is_version_or_extension_supported(4, 0, "XXX"), //TODO
        separate_blending_slots_supported: info.is_version_or_extension_supported(4, 0, "GL_ARB_draw_buffers_blend"),
    };
    let private = PrivateCaps {
        array_buffer_supported:            info.is_version_or_extension_supported(3, 0, "GL_ARB_vertex_array_object"),
        frame_buffer_supported:            info.is_version_or_extension_supported(3, 0, "GL_ARB_framebuffer_object"),
        immutable_storage_supported:       info.is_version_or_extension_supported(4, 2, "GL_ARB_texture_storage"),
        sampler_objects_supported:         info.is_version_or_extension_supported(3, 3, "GL_ARB_sampler_objects"),
        program_interface_supported:       info.is_version_or_extension_supported(4, 3, "GL_ARB_program_interface_query"),
    };
    (info, caps, private)
}

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

    #[test]
    fn test_version_parse() {
        assert_eq!(Version::parse("1"), Err("1"));
        assert_eq!(Version::parse("1."), Err("1."));
        assert_eq!(Version::parse("1 h3l1o. W0rld"), Err("1 h3l1o. W0rld"));
        assert_eq!(Version::parse("1. h3l1o. W0rld"), Err("1. h3l1o. W0rld"));
        assert_eq!(Version::parse("1.2.3"), Ok(Version::new(1, 2, Some(3), "")));
        assert_eq!(Version::parse("1.2"), Ok(Version::new(1, 2, None, "")));
        assert_eq!(Version::parse("1.2 h3l1o. W0rld"), Ok(Version::new(1, 2, None, "h3l1o. W0rld")));
        assert_eq!(Version::parse("1.2.h3l1o. W0rld"), Ok(Version::new(1, 2, None, "W0rld")));
        assert_eq!(Version::parse("1.2. h3l1o. W0rld"), Ok(Version::new(1, 2, None, "h3l1o. W0rld")));
        assert_eq!(Version::parse("1.2.3.h3l1o. W0rld"), Ok(Version::new(1, 2, Some(3), "W0rld")));
        assert_eq!(Version::parse("1.2.3 h3l1o. W0rld"), Ok(Version::new(1, 2, Some(3), "h3l1o. W0rld")));
    }
}
<commit_msg>[gl] basic GLES version check<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashSet;
use std::{ffi, fmt, mem, str};
use gl;
use gfx_core::Capabilities;

/// A version number for a specific component of an OpenGL implementation
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct Version {
    pub is_embedded: bool,
    pub major: u32,
    pub minor: u32,
    pub revision: Option<u32>,
    pub vendor_info: &'static str,
}

impl Version {
    /// Create a new OpenGL version number
    pub fn new(major: u32, minor: u32, revision: Option<u32>,
               vendor_info: &'static str) -> Version {
        Version {
            is_embedded: false,
            major: major,
            minor: minor,
            revision: revision,
            vendor_info: vendor_info,
        }
    }

    /// According to the OpenGL specification, the version information is
    /// expected to follow the following syntax:
    ///
    /// ~~~bnf
    /// <major>       ::= <number>
    /// <minor>       ::= <number>
    /// <revision>    ::= <number>
    /// <vendor-info> ::= <string>
    /// <release>     ::= <major> "." <minor> ["." <release>]
    /// <version>     ::= <release> [" " <vendor-info>]
    /// ~~~
    ///
    /// Note that this function is intentionally lenient in regards to parsing,
    /// and will try to recover at least the first two version numbers without
    /// resulting in an `Err`.
    pub fn parse(mut src: &'static str) -> Result<Version, &'static str> {
        let es_signature = "OpenGL ES ";
        let is_es = src.starts_with(es_signature);
        if is_es {
            src = &src[es_signature.len()..];
        }
        let (version, vendor_info) = match src.find(' ') {
            Some(i) => src.split_at(i),
            None => (src, ""),
        };

        // TODO: make this even more lenient so that we can also accept
        // `<major> "." <minor> [<???>]`
        let mut it = version.split('.');
        let major = it.next().and_then(|s| s.parse().ok());
        let minor = it.next().and_then(|s| s.parse().ok());
        let revision = it.next().and_then(|s| s.parse().ok());

        match (major, minor, revision) {
            (Some(major), Some(minor), revision) => Ok(Version {
                is_embedded: is_es,
                major: major,
                minor: minor,
                revision: revision,
                vendor_info: vendor_info,
            }),
            (_, _, _) => Err(src),
        }
    }
}

impl fmt::Debug for Version {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match (self.major, self.minor, self.revision, self.vendor_info) {
            (major, minor, Some(revision), "") =>
                write!(f, "{}.{}.{}", major, minor, revision),
            (major, minor, None, "") =>
                write!(f, "{}.{}", major, minor),
            (major, minor, Some(revision), vendor_info) =>
                write!(f, "{}.{}.{}, {}", major, minor, revision, vendor_info),
            (major, minor, None, vendor_info) =>
                write!(f, "{}.{}, {}", major, minor, vendor_info),
        }
    }
}

const EMPTY_STRING: &'static str = "";

/// Get a statically allocated string from the implementation using
/// `glGetString`. Fails if it `GLenum` cannot be handled by the
/// implementation's `gl.GetString` function.
fn get_string(gl: &gl::Gl, name: gl::types::GLenum) -> &'static str {
    let ptr = unsafe { gl.GetString(name) } as *const i8;
    if !ptr.is_null() {
        // This should be safe to mark as statically allocated because
        // GlGetString only returns static strings.
        unsafe { c_str_as_static_str(ptr) }
    } else {
        error!("Invalid GLenum passed to `get_string`: {:x}", name);
        EMPTY_STRING
    }
}

fn get_usize(gl: &gl::Gl, name: gl::types::GLenum) -> usize {
    let mut value = 0 as gl::types::GLint;
    unsafe { gl.GetIntegerv(name, &mut value) };
    value as usize
}

unsafe fn c_str_as_static_str(c_str: *const i8) -> &'static str {
    mem::transmute(str::from_utf8(ffi::CStr::from_ptr(c_str as *const _).to_bytes()).unwrap())
}

/// A unique platform identifier that does not change between releases
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct PlatformName {
    /// The company responsible for the OpenGL implementation
    pub vendor: &'static str,
    /// The name of the renderer
    pub renderer: &'static str,
}

impl PlatformName {
    fn get(gl: &gl::Gl) -> PlatformName {
        PlatformName {
            vendor: get_string(gl, gl::VENDOR),
            renderer: get_string(gl, gl::RENDERER),
        }
    }
}

/// Private capabilities that don't need to be exposed.
#[derive(Debug)]
pub struct PrivateCaps {
    pub array_buffer_supported: bool,
    pub frame_buffer_supported: bool,
    pub immutable_storage_supported: bool,
    pub sampler_objects_supported: bool,
    pub program_interface_supported: bool,
}

/// OpenGL implementation information
#[derive(Debug)]
pub struct Info {
    /// The platform identifier
    pub platform_name: PlatformName,
    /// The OpenGL API vesion number
    pub version: Version,
    /// The GLSL vesion number
    pub shading_language: Version,
    /// The extensions supported by the implementation
    pub extensions: HashSet<&'static str>,
}

impl Info {
    fn get(gl: &gl::Gl) -> Info {
        let platform_name = PlatformName::get(gl);
        let version = Version::parse(get_string(gl, gl::VERSION)).unwrap();
        let shading_language = Version::parse(get_string(gl, gl::SHADING_LANGUAGE_VERSION)).unwrap();
        let extensions = if version >= Version::new(3, 0, None, "") {
            let num_exts = get_usize(gl, gl::NUM_EXTENSIONS) as gl::types::GLuint;
            (0..num_exts)
                .map(|i| unsafe { c_str_as_static_str(gl.GetStringi(gl::EXTENSIONS, i) as *const i8) })
                .collect()
        } else {
            // Fallback
            get_string(gl, gl::EXTENSIONS).split(' ').collect()
        };
        Info {
            platform_name: platform_name,
            version: version,
            shading_language: shading_language,
            extensions: extensions,
        }
    }

    pub fn is_version_supported(&self, major: u32, minor: u32) -> bool {
        self.version >= Version::new(major, minor, None, "")
    }

    /// Returns `true` if the implementation supports the extension
    pub fn is_extension_supported(&self, s: &'static str) -> bool {
        self.extensions.contains(&s)
    }

    pub fn is_version_or_extension_supported(&self, major: u32, minor: u32, ext: &'static str) -> bool {
        self.is_version_supported(major, minor) || self.is_extension_supported(ext)
    }
}

/// Load the information pertaining to the driver and the corresponding device
/// capabilities.
pub fn get(gl: &gl::Gl) -> (Info, Capabilities, PrivateCaps) {
    let info = Info::get(gl);
    let caps = Capabilities {
        max_vertex_count: get_usize(gl, gl::MAX_ELEMENTS_VERTICES),
        max_index_count:  get_usize(gl, gl::MAX_ELEMENTS_INDICES),
        max_texture_size: get_usize(gl, gl::MAX_TEXTURE_SIZE),

        instance_base_supported:           info.is_version_or_extension_supported(4, 2, "GL_ARB_base_instance"),
        instance_call_supported:           info.is_version_or_extension_supported(3, 1, "GL_ARB_draw_instanced"),
        instance_rate_supported:           info.is_version_or_extension_supported(3, 3, "GL_ARB_instanced_arrays"),
        vertex_base_supported:             info.is_version_or_extension_supported(3, 2, "GL_ARB_draw_elements_base_vertex"),
        srgb_color_supported:              info.is_version_or_extension_supported(3, 2, "GL_ARB_framebuffer_sRGB"),
        constant_buffer_supported:         info.is_version_or_extension_supported(3, 1, "GL_ARB_uniform_buffer_object"),
        unordered_access_view_supported:   info.is_version_or_extension_supported(4, 0, "XXX"), //TODO
        separate_blending_slots_supported: info.is_version_or_extension_supported(4, 0, "GL_ARB_draw_buffers_blend"),
    };
    let private = PrivateCaps {
        array_buffer_supported:            info.is_version_or_extension_supported(3, 0, "GL_ARB_vertex_array_object"),
        frame_buffer_supported:            info.is_version_or_extension_supported(3, 0, "GL_ARB_framebuffer_object"),
        immutable_storage_supported:       info.is_version_or_extension_supported(4, 2, "GL_ARB_texture_storage"),
        sampler_objects_supported:         info.is_version_or_extension_supported(3, 3, "GL_ARB_sampler_objects"),
        program_interface_supported:       info.is_version_or_extension_supported(4, 3, "GL_ARB_program_interface_query"),
    };
    (info, caps, private)
}

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

    #[test]
    fn test_version_parse() {
        assert_eq!(Version::parse("1"), Err("1"));
        assert_eq!(Version::parse("1."), Err("1."));
        assert_eq!(Version::parse("1 h3l1o. W0rld"), Err("1 h3l1o. W0rld"));
        assert_eq!(Version::parse("1. h3l1o. W0rld"), Err("1. h3l1o. W0rld"));
        assert_eq!(Version::parse("1.2.3"), Ok(Version::new(1, 2, Some(3), "")));
        assert_eq!(Version::parse("1.2"), Ok(Version::new(1, 2, None, "")));
        assert_eq!(Version::parse("1.2 h3l1o. W0rld"), Ok(Version::new(1, 2, None, "h3l1o. W0rld")));
        assert_eq!(Version::parse("1.2.h3l1o. W0rld"), Ok(Version::new(1, 2, None, "W0rld")));
        assert_eq!(Version::parse("1.2. h3l1o. W0rld"), Ok(Version::new(1, 2, None, "h3l1o. W0rld")));
        assert_eq!(Version::parse("1.2.3.h3l1o. W0rld"), Ok(Version::new(1, 2, Some(3), "W0rld")));
        assert_eq!(Version::parse("1.2.3 h3l1o. W0rld"), Ok(Version::new(1, 2, Some(3), "h3l1o. W0rld")));
    }
}
<|endoftext|>


<commit_before>// Transfer all crates from one user to another.
//
// Usage:
//      cargo run --bin transfer-crates from-user to-user

#![deny(warnings)]

extern crate cargo_registry;
extern crate postgres;
extern crate time;
extern crate semver;

use std::env;
use std::io;
use std::io::prelude::*;

use cargo_registry::{Crate, User};
use cargo_registry::owner::OwnerKind;
use cargo_registry::Model;

#[allow(dead_code)]
fn main() {
    let conn = cargo_registry::db::connect_now();
    {
        let tx = conn.transaction().unwrap();
        transfer(&tx);
        tx.set_commit();
        tx.finish().unwrap();
    }
}

fn transfer(tx: &postgres::transaction::Transaction) {
    let from = match env::args().nth(1) {
        None => {
            println!("needs a from-user argument");
            return;
        }
        Some(s) => s,
    };
    let to = match env::args().nth(2) {
        None => {
            println!("needs a to-user argument");
            return;
        }
        Some(s) => s,
    };

    let from = User::find_by_login(tx, &from).unwrap();
    let to = User::find_by_login(tx, &to).unwrap();

    if from.gh_avatar != to.gh_avatar {
        println!("====================================================");
        println!("WARNING");
        println!("");
        println!("this may not be the same github user, different github IDs");
        println!("");
        println!("from: {:?}", from.gh_id);
        println!("to:   {:?}", to.gh_id);

        get_confirm("continue?");
    }

    println!(
        "Are you sure you want to transfer crates from {} to {}",
        from.gh_login,
        to.gh_login
    );
    get_confirm("continue");

    let stmt = tx.prepare(
        "SELECT * FROM crate_owners
                                   WHERE owner_id = $1
                                     AND owner_kind = $2",
    ).unwrap();
    let rows = stmt.query(&[&from.id, &(OwnerKind::User as i32)]).unwrap();
    for row in rows.iter() {
        let owner_id: i32 = row.get("owner_id");
        let krate = Crate::find(tx, row.get("crate_id")).unwrap();
        println!("transferring {}", krate.name);
        let owners = krate.owners_old(tx).unwrap();
        if owners.len() != 1 {
            println!("warning: not exactly one owner for {}", krate.name);
        }
        let n = tx.execute(
            "UPDATE crate_owners SET owner_id = $1
                             WHERE owner_id = $2",
            &[&to.id, &owner_id],
        ).unwrap();
        assert_eq!(n, 1);
    }

    get_confirm("commit?");
}

fn get_confirm(msg: &str) {
    print!("{} [y/N]: ", msg);
    io::stdout().flush().unwrap();
    let mut line = String::new();
    io::stdin().read_line(&mut line).unwrap();
    if !line.starts_with("y") {
        std::process::exit(0);
    }
}
<commit_msg>Changed to gh_id<commit_after>// Transfer all crates from one user to another.
//
// Usage:
//      cargo run --bin transfer-crates from-user to-user

#![deny(warnings)]

extern crate cargo_registry;
extern crate postgres;
extern crate time;
extern crate semver;

use std::env;
use std::io;
use std::io::prelude::*;

use cargo_registry::{Crate, User};
use cargo_registry::owner::OwnerKind;
use cargo_registry::Model;

#[allow(dead_code)]
fn main() {
    let conn = cargo_registry::db::connect_now();
    {
        let tx = conn.transaction().unwrap();
        transfer(&tx);
        tx.set_commit();
        tx.finish().unwrap();
    }
}

fn transfer(tx: &postgres::transaction::Transaction) {
    let from = match env::args().nth(1) {
        None => {
            println!("needs a from-user argument");
            return;
        }
        Some(s) => s,
    };
    let to = match env::args().nth(2) {
        None => {
            println!("needs a to-user argument");
            return;
        }
        Some(s) => s,
    };

    let from = User::find_by_login(tx, &from).unwrap();
    let to = User::find_by_login(tx, &to).unwrap();

    if from.gh_id != to.gh_id {
        println!("====================================================");
        println!("WARNING");
        println!("");
        println!("this may not be the same github user, different github IDs");
        println!("");
        println!("from: {:?}", from.gh_id);
        println!("to:   {:?}", to.gh_id);

        get_confirm("continue?");
    }

    println!(
        "Are you sure you want to transfer crates from {} to {}",
        from.gh_login,
        to.gh_login
    );
    get_confirm("continue");

    let stmt = tx.prepare(
        "SELECT * FROM crate_owners
                                   WHERE owner_id = $1
                                     AND owner_kind = $2",
    ).unwrap();
    let rows = stmt.query(&[&from.id, &(OwnerKind::User as i32)]).unwrap();
    for row in rows.iter() {
        let owner_id: i32 = row.get("owner_id");
        let krate = Crate::find(tx, row.get("crate_id")).unwrap();
        println!("transferring {}", krate.name);
        let owners = krate.owners_old(tx).unwrap();
        if owners.len() != 1 {
            println!("warning: not exactly one owner for {}", krate.name);
        }
        let n = tx.execute(
            "UPDATE crate_owners SET owner_id = $1
                             WHERE owner_id = $2",
            &[&to.id, &owner_id],
        ).unwrap();
        assert_eq!(n, 1);
    }

    get_confirm("commit?");
}

fn get_confirm(msg: &str) {
    print!("{} [y/N]: ", msg);
    io::stdout().flush().unwrap();
    let mut line = String::new();
    io::stdin().read_line(&mut line).unwrap();
    if !line.starts_with("y") {
        std::process::exit(0);
    }
}
<|endoftext|>


<commit_before>//! Shim which is passed to Cargo as "rustc" when running the bootstrap.
//!
//! This shim will take care of some various tasks that our build process
//! requires that Cargo can't quite do through normal configuration:
//!
//! 1. When compiling build scripts and build dependencies, we need a guaranteed
//!    full standard library available. The only compiler which actually has
//!    this is the snapshot, so we detect this situation and always compile with
//!    the snapshot compiler.
//! 2. We pass a bunch of `--cfg` and other flags based on what we're compiling
//!    (and this slightly differs based on a whether we're using a snapshot or
//!    not), so we do that all here.
//!
//! This may one day be replaced by RUSTFLAGS, but the dynamic nature of
//! switching compilers for the bootstrap and for build scripts will probably
//! never get replaced.

use std::env;
use std::io;
use std::path::PathBuf;
use std::process::Command;
use std::str::FromStr;
use std::time::Instant;

fn main() {
    let args = env::args_os().skip(1).collect::<Vec<_>>();

    // Detect whether or not we're a build script depending on whether --target
    // is passed (a bit janky...)
    let target = args.windows(2)
        .find(|w| &*w[0] == "--target")
        .and_then(|w| w[1].to_str());
    let version = args.iter().find(|w| &**w == "-vV");

    let verbose = match env::var("RUSTC_VERBOSE") {
        Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
        Err(_) => 0,
    };

    // Use a different compiler for build scripts, since there may not yet be a
    // libstd for the real compiler to use. However, if Cargo is attempting to
    // determine the version of the compiler, the real compiler needs to be
    // used. Currently, these two states are differentiated based on whether
    // --target and -vV is/isn't passed.
    let (rustc, libdir) = if target.is_none() && version.is_none() {
        ("RUSTC_SNAPSHOT", "RUSTC_SNAPSHOT_LIBDIR")
    } else {
        ("RUSTC_REAL", "RUSTC_LIBDIR")
    };
    let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
    let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
    let on_fail = env::var_os("RUSTC_ON_FAIL").map(|of| Command::new(of));

    let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
    let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
    let mut dylib_path = bootstrap::util::dylib_path();
    dylib_path.insert(0, PathBuf::from(&libdir));

    let mut cmd = Command::new(rustc);
    cmd.args(&args)
        .env(bootstrap::util::dylib_path_var(),
             env::join_paths(&dylib_path).unwrap());

    // Get the name of the crate we're compiling, if any.
    let crate_name = args.windows(2)
        .find(|args| args[0] == "--crate-name")
        .and_then(|args| args[1].to_str());

    if let Some(crate_name) = crate_name {
        if let Some(target) = env::var_os("RUSTC_TIME") {
            if target == "all" ||
                target.into_string().unwrap().split(",").any(|c| c.trim() == crate_name)
            {
                cmd.arg("-Ztime");
            }
        }
    }

    // Print backtrace in case of ICE
    if env::var("RUSTC_BACKTRACE_ON_ICE").is_ok() && env::var("RUST_BACKTRACE").is_err() {
        cmd.env("RUST_BACKTRACE", "1");
    }

    if target.is_some() {
        // The stage0 compiler has a special sysroot distinct from what we
        // actually downloaded, so we just always pass the `--sysroot` option,
        // unless one is already set.
        if !args.iter().any(|arg| arg == "--sysroot") {
            cmd.arg("--sysroot").arg(&sysroot);
        }

        // If we're compiling specifically the `panic_abort` crate then we pass
        // the `-C panic=abort` option. Note that we do not do this for any
        // other crate intentionally as this is the only crate for now that we
        // ship with panic=abort.
        //
        // This... is a bit of a hack how we detect this. Ideally this
        // information should be encoded in the crate I guess? Would likely
        // require an RFC amendment to RFC 1513, however.
        //
        // `compiler_builtins` are unconditionally compiled with panic=abort to
        // workaround undefined references to `rust_eh_unwind_resume` generated
        // otherwise, see issue https://github.com/rust-lang/rust/issues/43095.
        if crate_name == Some("panic_abort") ||
           crate_name == Some("compiler_builtins") && stage != "0" {
            cmd.arg("-C").arg("panic=abort");
        }

        // Set various options from config.toml to configure how we're building
        // code.
        let debug_assertions = match env::var("RUSTC_DEBUG_ASSERTIONS") {
            Ok(s) => if s == "true" { "y" } else { "n" },
            Err(..) => "n",
        };

        // The compiler builtins are pretty sensitive to symbols referenced in
        // libcore and such, so we never compile them with debug assertions.
        if crate_name == Some("compiler_builtins") {
            cmd.arg("-C").arg("debug-assertions=no");
        } else {
            cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions));
        }
    } else {
        // Override linker if necessary.
        if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") {
            cmd.arg(format!("-Clinker={}", host_linker));
        }

        if let Ok(s) = env::var("RUSTC_HOST_CRT_STATIC") {
            if s == "true" {
                cmd.arg("-C").arg("target-feature=+crt-static");
            }
            if s == "false" {
                cmd.arg("-C").arg("target-feature=-crt-static");
            }
        }
    }

    if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") {
        cmd.arg("--remap-path-prefix").arg(&map);
    }

    // Force all crates compiled by this compiler to (a) be unstable and (b)
    // allow the `rustc_private` feature to link to other unstable crates
    // also in the sysroot. We also do this for host crates, since those
    // may be proc macros, in which case we might ship them.
    if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() && (stage != "0" || target.is_some()) {
        cmd.arg("-Z").arg("force-unstable-if-unmarked");
    }

    if verbose > 1 {
        eprintln!(
            "rustc command: {:?}={:?} {:?}",
            bootstrap::util::dylib_path_var(),
            env::join_paths(&dylib_path).unwrap(),
            cmd,
        );
        eprintln!("sysroot: {:?}", sysroot);
        eprintln!("libdir: {:?}", libdir);
    }

    if let Some(mut on_fail) = on_fail {
        let e = match cmd.status() {
            Ok(s) if s.success() => std::process::exit(0),
            e => e,
        };
        println!("\nDid not run successfully: {:?}\n{:?}\n-------------", e, cmd);
        exec_cmd(&mut on_fail).expect("could not run the backup command");
        std::process::exit(1);
    }

    if env::var_os("RUSTC_PRINT_STEP_TIMINGS").is_some() {
        if let Some(crate_name) = crate_name {
            let start = Instant::now();
            let status = cmd
                .status()
                .unwrap_or_else(|_| panic!("\n\n failed to run {:?}", cmd));
            let dur = start.elapsed();

            let is_test = args.iter().any(|a| a == "--test");
            eprintln!("[RUSTC-TIMING] {} test:{} {}.{:03}",
                      crate_name,
                      is_test,
                      dur.as_secs(),
                      dur.subsec_nanos() / 1_000_000);

            match status.code() {
                Some(i) => std::process::exit(i),
                None => {
                    eprintln!("rustc exited with {}", status);
                    std::process::exit(0xfe);
                }
            }
        }
    }

    let code = exec_cmd(&mut cmd).unwrap_or_else(|_| panic!("\n\n failed to run {:?}", cmd));
    std::process::exit(code);
}

#[cfg(unix)]
fn exec_cmd(cmd: &mut Command) -> io::Result<i32> {
    use std::os::unix::process::CommandExt;
    Err(cmd.exec())
}

#[cfg(not(unix))]
fn exec_cmd(cmd: &mut Command) -> io::Result<i32> {
    cmd.status().map(|status| status.code().unwrap())
}
<commit_msg>Add some FIXME for future Cargo issues<commit_after>//! Shim which is passed to Cargo as "rustc" when running the bootstrap.
//!
//! This shim will take care of some various tasks that our build process
//! requires that Cargo can't quite do through normal configuration:
//!
//! 1. When compiling build scripts and build dependencies, we need a guaranteed
//!    full standard library available. The only compiler which actually has
//!    this is the snapshot, so we detect this situation and always compile with
//!    the snapshot compiler.
//! 2. We pass a bunch of `--cfg` and other flags based on what we're compiling
//!    (and this slightly differs based on a whether we're using a snapshot or
//!    not), so we do that all here.
//!
//! This may one day be replaced by RUSTFLAGS, but the dynamic nature of
//! switching compilers for the bootstrap and for build scripts will probably
//! never get replaced.

use std::env;
use std::io;
use std::path::PathBuf;
use std::process::Command;
use std::str::FromStr;
use std::time::Instant;

fn main() {
    let args = env::args_os().skip(1).collect::<Vec<_>>();

    // Detect whether or not we're a build script depending on whether --target
    // is passed (a bit janky...)
    let target = args.windows(2)
        .find(|w| &*w[0] == "--target")
        .and_then(|w| w[1].to_str());
    let version = args.iter().find(|w| &**w == "-vV");

    let verbose = match env::var("RUSTC_VERBOSE") {
        Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
        Err(_) => 0,
    };

    // Use a different compiler for build scripts, since there may not yet be a
    // libstd for the real compiler to use. However, if Cargo is attempting to
    // determine the version of the compiler, the real compiler needs to be
    // used. Currently, these two states are differentiated based on whether
    // --target and -vV is/isn't passed.
    let (rustc, libdir) = if target.is_none() && version.is_none() {
        ("RUSTC_SNAPSHOT", "RUSTC_SNAPSHOT_LIBDIR")
    } else {
        ("RUSTC_REAL", "RUSTC_LIBDIR")
    };
    let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
    let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
    let on_fail = env::var_os("RUSTC_ON_FAIL").map(|of| Command::new(of));

    let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
    let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
    let mut dylib_path = bootstrap::util::dylib_path();
    dylib_path.insert(0, PathBuf::from(&libdir));

    let mut cmd = Command::new(rustc);
    cmd.args(&args)
        .env(bootstrap::util::dylib_path_var(),
             env::join_paths(&dylib_path).unwrap());

    // Get the name of the crate we're compiling, if any.
    let crate_name = args.windows(2)
        .find(|args| args[0] == "--crate-name")
        .and_then(|args| args[1].to_str());

    if let Some(crate_name) = crate_name {
        if let Some(target) = env::var_os("RUSTC_TIME") {
            if target == "all" ||
                target.into_string().unwrap().split(",").any(|c| c.trim() == crate_name)
            {
                cmd.arg("-Ztime");
            }
        }
    }

    // Print backtrace in case of ICE
    if env::var("RUSTC_BACKTRACE_ON_ICE").is_ok() && env::var("RUST_BACKTRACE").is_err() {
        cmd.env("RUST_BACKTRACE", "1");
    }

    if target.is_some() {
        // The stage0 compiler has a special sysroot distinct from what we
        // actually downloaded, so we just always pass the `--sysroot` option,
        // unless one is already set.
        if !args.iter().any(|arg| arg == "--sysroot") {
            cmd.arg("--sysroot").arg(&sysroot);
        }

        // If we're compiling specifically the `panic_abort` crate then we pass
        // the `-C panic=abort` option. Note that we do not do this for any
        // other crate intentionally as this is the only crate for now that we
        // ship with panic=abort.
        //
        // This... is a bit of a hack how we detect this. Ideally this
        // information should be encoded in the crate I guess? Would likely
        // require an RFC amendment to RFC 1513, however.
        //
        // `compiler_builtins` are unconditionally compiled with panic=abort to
        // workaround undefined references to `rust_eh_unwind_resume` generated
        // otherwise, see issue https://github.com/rust-lang/rust/issues/43095.
        if crate_name == Some("panic_abort") ||
           crate_name == Some("compiler_builtins") && stage != "0" {
            cmd.arg("-C").arg("panic=abort");
        }

        // Set various options from config.toml to configure how we're building
        // code.
        let debug_assertions = match env::var("RUSTC_DEBUG_ASSERTIONS") {
            Ok(s) => if s == "true" { "y" } else { "n" },
            Err(..) => "n",
        };

        // The compiler builtins are pretty sensitive to symbols referenced in
        // libcore and such, so we never compile them with debug assertions.
        //
        // FIXME(rust-lang/cargo#7253) we should be doing this in `builder.rs`
        // with env vars instead of doing it here in this script.
        if crate_name == Some("compiler_builtins") {
            cmd.arg("-C").arg("debug-assertions=no");
        } else {
            cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions));
        }
    } else {
        // FIXME(rust-lang/cargo#5754) we shouldn't be using special env vars
        // here, but rather Cargo should know what flags to pass rustc itself.

        // Override linker if necessary.
        if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") {
            cmd.arg(format!("-Clinker={}", host_linker));
        }

        if let Ok(s) = env::var("RUSTC_HOST_CRT_STATIC") {
            if s == "true" {
                cmd.arg("-C").arg("target-feature=+crt-static");
            }
            if s == "false" {
                cmd.arg("-C").arg("target-feature=-crt-static");
            }
        }
    }

    if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") {
        cmd.arg("--remap-path-prefix").arg(&map);
    }

    // Force all crates compiled by this compiler to (a) be unstable and (b)
    // allow the `rustc_private` feature to link to other unstable crates
    // also in the sysroot. We also do this for host crates, since those
    // may be proc macros, in which case we might ship them.
    if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() && (stage != "0" || target.is_some()) {
        cmd.arg("-Z").arg("force-unstable-if-unmarked");
    }

    if verbose > 1 {
        eprintln!(
            "rustc command: {:?}={:?} {:?}",
            bootstrap::util::dylib_path_var(),
            env::join_paths(&dylib_path).unwrap(),
            cmd,
        );
        eprintln!("sysroot: {:?}", sysroot);
        eprintln!("libdir: {:?}", libdir);
    }

    if let Some(mut on_fail) = on_fail {
        let e = match cmd.status() {
            Ok(s) if s.success() => std::process::exit(0),
            e => e,
        };
        println!("\nDid not run successfully: {:?}\n{:?}\n-------------", e, cmd);
        exec_cmd(&mut on_fail).expect("could not run the backup command");
        std::process::exit(1);
    }

    if env::var_os("RUSTC_PRINT_STEP_TIMINGS").is_some() {
        if let Some(crate_name) = crate_name {
            let start = Instant::now();
            let status = cmd
                .status()
                .unwrap_or_else(|_| panic!("\n\n failed to run {:?}", cmd));
            let dur = start.elapsed();

            let is_test = args.iter().any(|a| a == "--test");
            eprintln!("[RUSTC-TIMING] {} test:{} {}.{:03}",
                      crate_name,
                      is_test,
                      dur.as_secs(),
                      dur.subsec_nanos() / 1_000_000);

            match status.code() {
                Some(i) => std::process::exit(i),
                None => {
                    eprintln!("rustc exited with {}", status);
                    std::process::exit(0xfe);
                }
            }
        }
    }

    let code = exec_cmd(&mut cmd).unwrap_or_else(|_| panic!("\n\n failed to run {:?}", cmd));
    std::process::exit(code);
}

#[cfg(unix)]
fn exec_cmd(cmd: &mut Command) -> io::Result<i32> {
    use std::os::unix::process::CommandExt;
    Err(cmd.exec())
}

#[cfg(not(unix))]
fn exec_cmd(cmd: &mut Command) -> io::Result<i32> {
    cmd.status().map(|status| status.code().unwrap())
}
<|endoftext|>