<commit_before>use std::mem::replace;
use std::iter::repeat;
use std::collections::{HashMap, HashSet};

use super::operator::{Operator, DataOperator};
use super::data::Data;
use super::node::{Node, NodeRole, IndexedInlet};

pub const NODE_INDEX_OFFSET: usize = 1;

#[derive(Debug)]
pub enum Inlet {
   Source(String),
   Data(Data),
   None,
}

#[derive(Debug)]
enum NodeDef {
   Operator((String, Box<Operator>, Vec<Inlet>)),
   Data((String, Data)),
   None,
}

impl NodeDef {
   fn key(&self) -> String {
      match self {
         &NodeDef::Operator((ref key, _, _)) => key.clone(),
         &NodeDef::Data((ref key, _)) => key.clone(),

         _ => panic!(""),
      }
   }
}

pub struct NodeBuilder {
   node_defs: Vec<NodeDef>,
   anon_count: usize,
}

impl NodeBuilder {
   pub fn new() -> Self {
      NodeBuilder {
         node_defs: Vec::new(),
         anon_count: 0,
      }
   }

   pub fn operator<T: 'static + Operator>(&mut self, node_id: String, inlets: Vec<Inlet>) {
      let operator = Box::new(T::new());

      self.node_defs.push(
         NodeDef::Operator((node_id, operator, inlets))
      );
   }

   pub fn anonymous<T: 'static + Operator>(&mut self, inlets: Vec<Inlet>) -> String {
      self.anon_count += 1;

      let node_id = format!("__{}__", self.anon_count);

      self.operator::<T>(node_id.clone(), inlets);

      node_id
   }

   pub fn data(&mut self, node_id: String, data: Data) {
      self.node_defs.push(
         NodeDef::Data((String::from(node_id), data))
      );
   }

   pub fn compile(&mut self) -> NodeScene {
      let mut slot_map = HashMap::new();

      // Data::frame number at slot 0
      slot_map.insert(String::from("frame"), 0);

      for (i, node_def) in self.node_defs.iter().enumerate() {
         let slot = i + NODE_INDEX_OFFSET;
         slot_map.insert(node_def.key(), slot);
      }

      let mut state = create_state(self.node_defs.len());

      let mut nodes = Vec::new();

      let mut artboard_slot = 0;

      let mut i = 0;

      for node_def_ref in self.node_defs.iter_mut() {
         let node_def = replace(node_def_ref, NodeDef::None);

         let slot = i + NODE_INDEX_OFFSET;

         i += 1;

         let node = node_from_def(
            slot, node_def, &slot_map, &mut state
         );

         if node.role() == NodeRole::Artboard {
            artboard_slot = node.slot;
         }

         nodes.push(node);
      }

      let nodes = execution_sort(nodes);

      state[artboard_slot].push(Data::None);

      NodeScene::new(nodes, state, artboard_slot)
   }
}

pub struct NodeScene {
   pub nodes: Vec<Node>,
   pub state: Vec<Vec<Data>>,
   pub artboard_slot: usize,
}

impl NodeScene {
   pub fn new(nodes: Vec<Node>, state: Vec<Vec<Data>>, artboard_slot: usize) -> Self {
      NodeScene {
         nodes: nodes,
         state: state,
         artboard_slot: artboard_slot,
      }
   }
}

pub fn create_state(nodes_len: usize) -> Vec<Vec<Data>> {
   let data_len = nodes_len + NODE_INDEX_OFFSET;

   let mut state = Vec::with_capacity(data_len);

   for _ in 0..data_len {
      state.push(Vec::new());
   }

   state
}

pub fn execution_sort(mut nodes: Vec<Node>) -> Vec<Node> {
   let len = nodes.len();

   let ordering = topological_ordering(&nodes);

   let mut positions: Vec<usize> = repeat(0).take(len).collect();

   for (position, order) in ordering.iter().enumerate() {
      positions[*order] = position;
   }

   let mut result = default_node_vec(len);

   for j in 0..len {
      let i = len - j - 1;

      let node = nodes.pop().unwrap();

      result[positions[i]] = node;
   }

   result
}

fn topological_ordering(nodes: &Vec<Node>) -> Vec<usize> {
   let connections = connections_map(&nodes);

   let mut ordering = Vec::new();

   let mut to_visit = Vec::new();

   let mut processed = HashSet::new();

   for root in 0..nodes.len() {
      if !processed.contains(&root) {

         to_visit.push((false, root));
      }

      while let Some((parent, current)) = to_visit.pop() {
         if processed.contains(&current) {
            break;
         }

         if parent {
            ordering.push(current);
            processed.insert(current);
         } else {
            to_visit.push((true, current));

            for child in connections[current].iter() {
               if !processed.contains(child) {
                  to_visit.push((false, *child));
               }
            }
         }
      }
   }

   ordering.reverse();

   ordering
}

fn connections_map(nodes: &Vec<Node>) -> Vec<Vec<usize>> {
   let positions = positions_map(nodes);

   let mut connections: Vec<Vec<usize>> = repeat(Vec::new()).take(nodes.len()).collect();

   for (i, node) in nodes.iter().enumerate() {
      for inlet in &node.inlets {
         if let &IndexedInlet::Slot((in_index, _)) = inlet {
            if let Some(node_index) = positions.get(&in_index) {
               connections[*node_index].push(i);
            }
         }
      }
   }

   connections
}

fn positions_map(nodes: &Vec<Node>) -> HashMap<usize, usize> {
   let mut positions = HashMap::new();

   for (i, node) in nodes.iter().enumerate() {
      positions.insert(node.slot, i);
   }

   positions
}

fn default_node_vec(len: usize) -> Vec<Node> {
   let mut nodes = Vec::with_capacity(len);

   for _ in 0..len {
      nodes.push(Node::default());
   }

   nodes
}

fn node_from_def(
   node_index: usize,
   node_def: NodeDef,
   slot_map: &HashMap<String, usize>,
   state: &mut Vec<Vec<Data>>,
) -> Node {
   match node_def {
      NodeDef::Data((_, data)) => {
         let operator = Box::new(DataOperator::new());

         let indexed_inlets = vec![
            IndexedInlet::Data(data)
         ];

         Node::new(operator, indexed_inlets, node_index)
      },
      NodeDef::Operator((_, operator, inlets)) => {
         let indexed_inlets = node_sources(inlets, slot_map, state);

         Node::new(operator, indexed_inlets, node_index)

      },
      _ => panic!("")
   }
}

fn node_sources(
   mut inlets: Vec<Inlet>,
   slot_map: &HashMap<String, usize>,
   state: &mut Vec<Vec<Data>>,
) -> Vec<IndexedInlet> {

   let mut indexed_inlets = Vec::with_capacity(inlets.len());

   for inlet in inlets.iter_mut() {
      let extracted = replace(inlet, Inlet::None);

      match extracted {
         Inlet::Source(node_id) => {
            let slot = match slot_map.get::<str>(&node_id) {
               Some(slot) => slot,
               _ => {
                  panic!("Unrecognized ID {:?}", node_id);
               }
            };

            let subslot = state[*slot].len();

            state[*slot].push(Data::None);

            indexed_inlets.push(
               IndexedInlet::Slot((*slot, subslot))
            );
         },
         Inlet::Data(data) => {
            indexed_inlets.push(
               IndexedInlet::Data(data)
            );
         },
         Inlet::None => {
            indexed_inlets.push(
               IndexedInlet::Data(Data::None)
            );
         }
      }
   }

   indexed_inlets
}

<commit_msg>Iteration improvement<commit_after>use std::mem::replace;
use std::iter::repeat;
use std::collections::{HashMap, HashSet};

use super::operator::{Operator, DataOperator};
use super::data::Data;
use super::node::{Node, NodeRole, IndexedInlet};

pub const NODE_INDEX_OFFSET: usize = 1;

#[derive(Debug)]
pub enum Inlet {
   Source(String),
   Data(Data),
   None,
}

#[derive(Debug)]
enum NodeDef {
   Operator((String, Box<Operator>, Vec<Inlet>)),
   Data((String, Data)),
   None,
}

impl NodeDef {
   fn key(&self) -> String {
      match self {
         &NodeDef::Operator((ref key, _, _)) => key.clone(),
         &NodeDef::Data((ref key, _)) => key.clone(),

         _ => panic!(""),
      }
   }
}

pub struct NodeBuilder {
   node_defs: Vec<NodeDef>,
   anon_count: usize,
}

impl NodeBuilder {
   pub fn new() -> Self {
      NodeBuilder {
         node_defs: Vec::new(),
         anon_count: 0,
      }
   }

   pub fn operator<T: 'static + Operator>(&mut self, node_id: String, inlets: Vec<Inlet>) {
      let operator = Box::new(T::new());

      self.node_defs.push(
         NodeDef::Operator((node_id, operator, inlets))
      );
   }

   pub fn anonymous<T: 'static + Operator>(&mut self, inlets: Vec<Inlet>) -> String {
      self.anon_count += 1;

      let node_id = format!("__{}__", self.anon_count);

      self.operator::<T>(node_id.clone(), inlets);

      node_id
   }

   pub fn data(&mut self, node_id: String, data: Data) {
      self.node_defs.push(
         NodeDef::Data((String::from(node_id), data))
      );
   }

   pub fn compile(&mut self) -> NodeScene {
      let mut slot_map = HashMap::new();

      // Data::frame number at slot 0
      slot_map.insert(String::from("frame"), 0);

      for (i, node_def) in self.node_defs.iter().enumerate() {
         let slot = i + NODE_INDEX_OFFSET;
         slot_map.insert(node_def.key(), slot);
      }

      let mut state = create_state(self.node_defs.len());

      let mut nodes = Vec::new();

      let mut artboard_slot = 0;

      let mut i = 0;

      for node_def_ref in self.node_defs.iter_mut() {
         let node_def = replace(node_def_ref, NodeDef::None);

         let slot = i + NODE_INDEX_OFFSET;

         i += 1;

         let node = node_from_def(
            slot, node_def, &slot_map, &mut state
         );

         if node.role() == NodeRole::Artboard {
            artboard_slot = node.slot;
         }

         nodes.push(node);
      }

      let nodes = execution_sort(nodes);

      state[artboard_slot].push(Data::None);

      NodeScene::new(nodes, state, artboard_slot)
   }
}

pub struct NodeScene {
   pub nodes: Vec<Node>,
   pub state: Vec<Vec<Data>>,
   pub artboard_slot: usize,
}

impl NodeScene {
   pub fn new(nodes: Vec<Node>, state: Vec<Vec<Data>>, artboard_slot: usize) -> Self {
      NodeScene {
         nodes: nodes,
         state: state,
         artboard_slot: artboard_slot,
      }
   }
}

pub fn create_state(nodes_len: usize) -> Vec<Vec<Data>> {
   let data_len = nodes_len + NODE_INDEX_OFFSET;

   let mut state = Vec::with_capacity(data_len);

   for _ in 0..data_len {
      state.push(Vec::new());
   }

   state
}

pub fn execution_sort(mut nodes: Vec<Node>) -> Vec<Node> {
   let len = nodes.len();

   let ordering = topological_ordering(&nodes);

   let mut positions: Vec<usize> = repeat(0).take(len).collect();

   for (position, order) in ordering.iter().enumerate() {
      positions[*order] = position;
   }

   let mut result = default_node_vec(len);

   for j in 0..len {
      let i = len - j - 1;

      let node = nodes.pop().unwrap();

      result[positions[i]] = node;
   }

   result
}

fn topological_ordering(nodes: &Vec<Node>) -> Vec<usize> {
   let connections = connections_map(&nodes);

   let mut ordering = Vec::new();

   let mut to_visit = Vec::new();

   let mut processed = HashSet::new();

   for root in 0..nodes.len() {
      if !processed.contains(&root) {

         to_visit.push((false, root));
      }

      while let Some((parent, current)) = to_visit.pop() {
         if processed.contains(&current) {
            break;
         }

         if parent {
            ordering.push(current);
            processed.insert(current);
         } else {
            to_visit.push((true, current));

            for child in connections[current].iter() {
               if !processed.contains(child) {
                  to_visit.push((false, *child));
               }
            }
         }
      }
   }

   ordering.reverse();

   ordering
}

fn connections_map(nodes: &Vec<Node>) -> Vec<Vec<usize>> {
   let positions = positions_map(nodes);

   let mut connections: Vec<Vec<usize>> = repeat(Vec::new()).take(nodes.len()).collect();

   for (i, node) in nodes.iter().enumerate() {
      for inlet in &node.inlets {
         if let &IndexedInlet::Slot((in_index, _)) = inlet {
            if let Some(node_index) = positions.get(&in_index) {
               connections[*node_index].push(i);
            }
         }
      }
   }

   connections
}

fn positions_map(nodes: &Vec<Node>) -> HashMap<usize, usize> {
   let mut positions = HashMap::new();

   for (i, node) in nodes.iter().enumerate() {
      positions.insert(node.slot, i);
   }

   positions
}

fn default_node_vec(len: usize) -> Vec<Node> {
   let mut nodes = Vec::with_capacity(len);

   for _ in 0..len {
      nodes.push(Node::default());
   }

   nodes
}

fn node_from_def(
   node_index: usize,
   node_def: NodeDef,
   slot_map: &HashMap<String, usize>,
   state: &mut Vec<Vec<Data>>,
) -> Node {
   match node_def {
      NodeDef::Data((_, data)) => {
         let operator = Box::new(DataOperator::new());

         let indexed_inlets = vec![
            IndexedInlet::Data(data)
         ];

         Node::new(operator, indexed_inlets, node_index)
      },
      NodeDef::Operator((_, operator, inlets)) => {
         let indexed_inlets = node_sources(inlets, slot_map, state);

         Node::new(operator, indexed_inlets, node_index)

      },
      _ => panic!("")
   }
}

fn node_sources(
   inlets: Vec<Inlet>,
   slot_map: &HashMap<String, usize>,
   state: &mut Vec<Vec<Data>>,
) -> Vec<IndexedInlet> {

   let mut indexed_inlets = Vec::with_capacity(inlets.len());

   for inlet in inlets {
      match inlet {
         Inlet::Source(node_id) => {
            let slot = match slot_map.get::<str>(&node_id) {
               Some(slot) => slot,
               _ => {
                  panic!("Unrecognized ID {:?}", node_id);
               }
            };

            let subslot = state[*slot].len();

            state[*slot].push(Data::None);

            indexed_inlets.push(
               IndexedInlet::Slot((*slot, subslot))
            );
         },
         Inlet::Data(data) => {
            indexed_inlets.push(
               IndexedInlet::Data(data)
            );
         },
         Inlet::None => {
            indexed_inlets.push(
               IndexedInlet::Data(Data::None)
            );
         }
      }
   }

   indexed_inlets
}

<|endoftext|>


<commit_before>// Copyright 2013 The noise-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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.

//! An implementation of Ken Perlin's [Improved Noise]
//! (http://mrl.nyu.edu/~perlin/noise/) algorithm.

use std::num::cast;

pub trait Perlin<T> {
    fn perlin(&self, ctx: &PerlinContext) -> T;
}

// impl<T: Clone + Float> Perlin<T> for T {
//     fn perlin(&self, ctx: &PerlinContext) -> T {
//         ctx.gen1(self)
//     }
// }

impl<T: Clone + Float> Perlin<T> for (T,) {
    fn perlin(&self, ctx: &PerlinContext) -> T {
        match *self {
            (ref x,) => ctx.gen1(x)
        }
    }
}

impl<T: Clone + Float> Perlin<T> for (T, T) {
    fn perlin(&self, ctx: &PerlinContext) -> T {
        match *self {
            (ref x, ref y) => ctx.gen2(x, y)
        }
    }
}

impl<T: Clone + Float> Perlin<T> for (T, T, T) {
    fn perlin(&self, ctx: &PerlinContext) -> T {
        match *self {
            (ref x, ref y, ref z) => ctx.gen3(x, y, z)
        }
    }
}

impl<T: Clone + Float> Perlin<T> for [T, ..1] {
    fn perlin(&self, ctx: &PerlinContext) -> T {
        match *self {
            [ref x] => ctx.gen1(x),
        }
    }
}

impl<T: Clone + Float> Perlin<T> for [T, ..2] {
    fn perlin(&self, ctx: &PerlinContext) -> T {
        match *self {
            [ref x, ref y] => ctx.gen2(x, y),
        }
    }
}

impl<T: Clone + Float> Perlin<T> for [T, ..3] {
    fn perlin(&self, ctx: &PerlinContext) -> T {
        match *self {
            [ref x, ref y, ref z] => ctx.gen3(x, y, z),
        }
    }
}

/// A perlin noise generator
pub struct PerlinContext {
    // permutation table
    priv ptable: [uint, ..512],
}

impl PerlinContext {
    pub fn new() -> PerlinContext {
        // TODO: generate random permutation table
        PerlinContext { ptable: P }
    }

    pub fn gen1<T:Clone + Float>(&self, x: &T) -> T {
        self.gen2(x, &cast(0))
    }

    pub fn gen2<T:Clone + Float>(&self, x: &T, y: &T) -> T {
        self.gen3(x, y, &cast(0))
    }

    pub fn gen3<T:Clone + Float>(&self, x: &T, y: &T, z: &T) -> T {
        // Find the unit cube that contains the point
        let X = x.floor().to_uint() & 255;
        let Y = y.floor().to_uint() & 255;
        let Z = z.floor().to_uint() & 255;

        // Find the relative X, Y, Z of point in the cube
        let x_ = *x - x.floor();
        let y_ = *y - y.floor();
        let z_ = *z - z.floor();

        // Compute the fade curves for X, Y, Z
        let u = fade(x_.clone());
        let v = fade(y_.clone());
        let w = fade(z_.clone());

        // Hash coordinates of the 8 cube corners
        let A  = self.ptable[X    ] + Y;
        let AA = self.ptable[A    ] + Z;
        let AB = self.ptable[A + 1] + Z;
        let B  = self.ptable[X + 1] + Y;
        let BA = self.ptable[B    ] + Z;
        let BB = self.ptable[B + 1] + Z;

        // Add the blended results from the 8 corners of the cube
        lerp(w, lerp(v.clone(), lerp(u.clone(), grad(self.ptable[AA    ], x_.clone(), y_.clone(), z_.clone()),
                                                grad(self.ptable[BA    ], x_-cast(1), y_.clone(), z_.clone())),
                                lerp(u.clone(), grad(self.ptable[AB    ], x_.clone(), y_-cast(1), z_.clone()),
                                                grad(self.ptable[BB    ], x_-cast(1), y_-cast(1), z_.clone()))),
                lerp(v.clone(), lerp(u.clone(), grad(self.ptable[AA + 1], x_.clone(), y_.clone(), z_-cast(1)),
                                                grad(self.ptable[BA + 1], x_-cast(1), y_.clone(), z_-cast(1))),
                                lerp(u.clone(), grad(self.ptable[AB + 1], x_.clone(), y_-cast(1), z_-cast(1)),
                                                grad(self.ptable[BB + 1], x_-cast(1), y_-cast(1), z_-cast(1)))))
    }
}

fn fade<T:Num + NumCast>(t: T) -> T {
    t * t * t * (t * (t * cast(6) - cast(15)) + cast(10))
}

fn lerp<T:Num + NumCast>(t: T, a: T, b: T) -> T {
    a + t * (b - a)
}

fn grad<T:Clone + Num + NumCast>(hash: uint, x: T, y: T, z: T) -> T {
    let h = hash & 15;

    let u = match h {
        0..7 => x.clone(),
        _    => y.clone(),
    };
    let v = match h {
        0..3    => y.clone(),
        12 | 14 => x.clone(),
        _       => z.clone(),
    };

    (if (h & 1) == 0 { u } else { -u }) +
    (if (h & 2) == 0 { v } else { -v })
}

/// Permutation table
static P: [uint, ..512] = [
    151, 160, 137,  91,  90,  15, 131,  13, 201,  95,  96,  53, 194, 233,   7, 225,
    140,  36, 103,  30,  69, 142,   8,  99,  37, 240,  21,  10,  23, 190,   6, 148,
    247, 120, 234,  75,   0,  26, 197,  62,  94, 252, 219, 203, 117,  35,  11,  32,
     57, 177,  33,  88, 237, 149,  56,  87, 174,  20, 125, 136, 171, 168,  68, 175,
     74, 165,  71, 134, 139,  48,  27, 166,  77, 146, 158, 231,  83, 111, 229, 122,
     60, 211, 133, 230, 220, 105,  92,  41,  55,  46, 245,  40, 244, 102, 143,  54,
     65,  25,  63, 161,   1, 216,  80,  73, 209,  76, 132, 187, 208,  89,  18, 169,
    200, 196, 135, 130, 116, 188, 159,  86, 164, 100, 109, 198, 173, 186,   3,  64,
     52, 217, 226, 250, 124, 123,   5, 202,  38, 147, 118, 126, 255,  82,  85, 212,
    207, 206,  59, 227,  47,  16,  58,  17, 182, 189,  28,  42, 223, 183, 170, 213,
    119, 248, 152,   2,  44, 154, 163,  70, 221, 153, 101, 155, 167,  43, 172,   9,
    129,  22,  39, 253,  19,  98, 108, 110,  79, 113, 224, 232, 178, 185, 112, 104,
    218, 246,  97, 228, 251,  34, 242, 193, 238, 210, 144,  12, 191, 179, 162, 241,
     81,  51, 145, 235, 249,  14, 239, 107,  49, 192, 214,  31, 181, 199, 106, 157,
    184,  84, 204, 176, 115, 121,  50,  45, 127,   4, 150, 254, 138, 236, 205,  93,
    222, 114,  67,  29,  24,  72, 243, 141, 128, 195,  78,  66, 215,  61, 156, 180,

    151, 160, 137,  91,  90,  15, 131,  13, 201,  95,  96,  53, 194, 233,   7, 225,
    140,  36, 103,  30,  69, 142,   8,  99,  37, 240,  21,  10,  23, 190,   6, 148,
    247, 120, 234,  75,   0,  26, 197,  62,  94, 252, 219, 203, 117,  35,  11,  32,
     57, 177,  33,  88, 237, 149,  56,  87, 174,  20, 125, 136, 171, 168,  68, 175,
     74, 165,  71, 134, 139,  48,  27, 166,  77, 146, 158, 231,  83, 111, 229, 122,
     60, 211, 133, 230, 220, 105,  92,  41,  55,  46, 245,  40, 244, 102, 143,  54,
     65,  25,  63, 161,   1, 216,  80,  73, 209,  76, 132, 187, 208,  89,  18, 169,
    200, 196, 135, 130, 116, 188, 159,  86, 164, 100, 109, 198, 173, 186,   3,  64,
     52, 217, 226, 250, 124, 123,   5, 202,  38, 147, 118, 126, 255,  82,  85, 212,
    207, 206,  59, 227,  47,  16,  58,  17, 182, 189,  28,  42, 223, 183, 170, 213,
    119, 248, 152,   2,  44, 154, 163,  70, 221, 153, 101, 155, 167,  43, 172,   9,
    129,  22,  39, 253,  19,  98, 108, 110,  79, 113, 224, 232, 178, 185, 112, 104,
    218, 246,  97, 228, 251,  34, 242, 193, 238, 210, 144,  12, 191, 179, 162, 241,
     81,  51, 145, 235, 249,  14, 239, 107,  49, 192, 214,  31, 181, 199, 106, 157,
    184,  84, 204, 176, 115, 121,  50,  45, 127,   4, 150, 254, 138, 236, 205,  93,
    222, 114,  67,  29,  24,  72, 243, 141, 128, 195,  78,  66, 215,  61, 156, 180,
];
<commit_msg>Generated permutation table<commit_after>// Copyright 2013 The noise-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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.

//! An implementation of Ken Perlin's [Improved Noise]
//! (http://mrl.nyu.edu/~perlin/noise/) algorithm.

use std::num::cast;
use std::rand;
use std::rand::Rng;

pub trait Perlin<T> {
    fn perlin(&self, ctx: &PerlinContext) -> T;
}

// impl<T: Clone + Float> Perlin<T> for T {
//     fn perlin(&self, ctx: &PerlinContext) -> T {
//         ctx.gen1(self)
//     }
// }

impl<T: Clone + Float> Perlin<T> for (T,) {
    fn perlin(&self, ctx: &PerlinContext) -> T {
        match *self {
            (ref x,) => ctx.gen1(x)
        }
    }
}

impl<T: Clone + Float> Perlin<T> for (T, T) {
    fn perlin(&self, ctx: &PerlinContext) -> T {
        match *self {
            (ref x, ref y) => ctx.gen2(x, y)
        }
    }
}

impl<T: Clone + Float> Perlin<T> for (T, T, T) {
    fn perlin(&self, ctx: &PerlinContext) -> T {
        match *self {
            (ref x, ref y, ref z) => ctx.gen3(x, y, z)
        }
    }
}

impl<T: Clone + Float> Perlin<T> for [T, ..1] {
    fn perlin(&self, ctx: &PerlinContext) -> T {
        match *self {
            [ref x] => ctx.gen1(x),
        }
    }
}

impl<T: Clone + Float> Perlin<T> for [T, ..2] {
    fn perlin(&self, ctx: &PerlinContext) -> T {
        match *self {
            [ref x, ref y] => ctx.gen2(x, y),
        }
    }
}

impl<T: Clone + Float> Perlin<T> for [T, ..3] {
    fn perlin(&self, ctx: &PerlinContext) -> T {
        match *self {
            [ref x, ref y, ref z] => ctx.gen3(x, y, z),
        }
    }
}

/// A perlin noise generator
pub struct PerlinContext {
    // permutation table
    priv ptable: ~[u8]//[uint, ..512],
}

impl PerlinContext {
    pub fn new() -> PerlinContext {
        let mut rng = rand::rng();
        PerlinContext { ptable: rng.gen_vec::<u8>(512) }
    }

    pub fn gen1<T:Clone + Float>(&self, x: &T) -> T {
        self.gen2(x, &cast(0))
    }

    pub fn gen2<T:Clone + Float>(&self, x: &T, y: &T) -> T {
        self.gen3(x, y, &cast(0))
    }

    pub fn gen3<T:Clone + Float>(&self, x: &T, y: &T, z: &T) -> T {
        // Find the unit cube that contains the point
        let X = x.floor().to_uint() as u8;
        let Y = y.floor().to_uint() as u8;
        let Z = z.floor().to_uint() as u8;

        // Find the relative X, Y, Z of point in the cube
        let x_ = *x - x.floor();
        let y_ = *y - y.floor();
        let z_ = *z - z.floor();

        // Compute the fade curves for X, Y, Z
        let u = fade(x_.clone());
        let v = fade(y_.clone());
        let w = fade(z_.clone());

        // Hash coordinates of the 8 cube corners
        let A  = self.ptable[X    ] + Y;
        let AA = self.ptable[A    ] + Z;
        let AB = self.ptable[A + 1] + Z;
        let B  = self.ptable[X + 1] + Y;
        let BA = self.ptable[B    ] + Z;
        let BB = self.ptable[B + 1] + Z;

        // Add the blended results from the 8 corners of the cube
        lerp(w, lerp(v.clone(), lerp(u.clone(), grad(self.ptable[AA    ] as uint, x_.clone(), y_.clone(), z_.clone()),
                                                grad(self.ptable[BA    ] as uint, x_-cast(1), y_.clone(), z_.clone())),
                                lerp(u.clone(), grad(self.ptable[AB    ] as uint, x_.clone(), y_-cast(1), z_.clone()),
                                                grad(self.ptable[BB    ] as uint, x_-cast(1), y_-cast(1), z_.clone()))),
                lerp(v.clone(), lerp(u.clone(), grad(self.ptable[AA + 1] as uint, x_.clone(), y_.clone(), z_-cast(1)),
                                                grad(self.ptable[BA + 1] as uint, x_-cast(1), y_.clone(), z_-cast(1))),
                                lerp(u.clone(), grad(self.ptable[AB + 1] as uint, x_.clone(), y_-cast(1), z_-cast(1)),
                                                grad(self.ptable[BB + 1] as uint, x_-cast(1), y_-cast(1), z_-cast(1)))))
    }
}

fn fade<T:Num + NumCast>(t: T) -> T {
    t * t * t * (t * (t * cast(6) - cast(15)) + cast(10))
}

fn lerp<T:Num + NumCast>(t: T, a: T, b: T) -> T {
    a + t * (b - a)
}

fn grad<T:Clone + Num + NumCast>(hash: uint, x: T, y: T, z: T) -> T {
    let h = hash & 15;

    let u = match h {
        0..7 => x.clone(),
        _    => y.clone(),
    };
    let v = match h {
        0..3    => y.clone(),
        12 | 14 => x.clone(),
        _       => z.clone(),
    };

    (if (h & 1) == 0 { u } else { -u }) +
    (if (h & 2) == 0 { v } else { -v })
}

<|endoftext|>


<commit_before>// Copyright 2018 The Grin 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.

//! Definition of the genesis block. Placeholder for now.

use time;

use core;
use consensus;
use core::target::Difficulty;
use global;

/// Genesis block definition for development networks. The proof of work size
/// is small enough to mine it on the fly, so it does not contain its own
/// proof of work solution. Can also be easily mutated for different tests.
pub fn genesis_dev() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 1997 - 1900,
				tm_mon: 7,
				tm_mday: 4,
				..time::empty_tm()
			},
			nonce: global::get_genesis_nonce(),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// First testnet genesis block, still subject to change (especially the date,
/// will hopefully come before Christmas).
pub fn genesis_testnet1() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2017 - 1900,
				tm_mon: 10,
				tm_mday: 16,
				tm_hour: 20,
				..time::empty_tm()
			},
			nonce: 28205,
			pow: core::Proof::new(vec![
				0x21e, 0x7a2, 0xeae, 0x144e, 0x1b1c, 0x1fbd, 0x203a, 0x214b, 0x293b, 0x2b74,
				0x2bfa, 0x2c26, 0x32bb, 0x346a, 0x34c7, 0x37c5, 0x4164, 0x42cc, 0x4cc3, 0x55af,
				0x5a70, 0x5b14, 0x5e1c, 0x5f76, 0x6061, 0x60f9, 0x61d7, 0x6318, 0x63a1, 0x63fb,
				0x649b, 0x64e5, 0x65a1, 0x6b69, 0x70f8, 0x71c7, 0x71cd, 0x7492, 0x7b11, 0x7db8,
				0x7f29, 0x7ff8,
			]),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// Second testnet genesis block (cuckoo30). TBD and don't start getting excited
/// just because you see this reference here... this is for testing mining
/// at cuckoo 30
pub fn genesis_testnet2() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2018 - 1900,
				tm_mon: 3,
				tm_mday: 26,
				tm_hour: 16,
				..time::empty_tm()
			},
			//TODO: Check this is over-estimated at T2 launch
			total_difficulty: Difficulty::from_num(global::initial_block_difficulty()),
			nonce: 329,
			pow: core::Proof::new(vec![
				0x5108b5, 0x6de3c4, 0xded539, 0x15d0e7a, 0x1b05bad, 0x24503fb, 0x420ee7a,
				0x5d905bb, 0x615571f, 0x631d3de, 0x740f1a2, 0x763f189, 0x778edd0, 0x916b09e,
				0x9679a4a, 0x99a7081, 0xad03e98, 0xd0f168c, 0xd878881, 0xda3166f, 0xe402699,
				0x10cac1ec, 0x11598a22, 0x11ad8968, 0x11b7f61a, 0x11c744f5, 0x129911ae,
				0x12d983c3, 0x14052a3c, 0x14464051, 0x16148155, 0x16f8577d, 0x18385648,
				0x18c25a31, 0x1ad7924c, 0x1b6c5079, 0x1c27837c, 0x1ce15e64, 0x1ecd7f12,
				0x1ef421bd, 0x1f5f0642, 0x1f97d069,
			]),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// Placeholder for mainnet genesis block, will definitely change before
/// release so no use trying to pre-mine it.
pub fn genesis_main() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2018 - 1900,
				tm_mon: 7,
				tm_mday: 14,
				..time::empty_tm()
			},
			total_difficulty: Difficulty::from_num(global::initial_block_difficulty()),
			nonce: global::get_genesis_nonce(),
			pow: core::Proof::zero(consensus::PROOFSIZE),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}
<commit_msg>Hopefully last genesis update...<commit_after>// Copyright 2018 The Grin 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.

//! Definition of the genesis block. Placeholder for now.

use time;

use core;
use consensus;
use core::target::Difficulty;
use global;

/// Genesis block definition for development networks. The proof of work size
/// is small enough to mine it on the fly, so it does not contain its own
/// proof of work solution. Can also be easily mutated for different tests.
pub fn genesis_dev() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 1997 - 1900,
				tm_mon: 7,
				tm_mday: 4,
				..time::empty_tm()
			},
			nonce: global::get_genesis_nonce(),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// First testnet genesis block, still subject to change (especially the date,
/// will hopefully come before Christmas).
pub fn genesis_testnet1() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2017 - 1900,
				tm_mon: 10,
				tm_mday: 16,
				tm_hour: 20,
				..time::empty_tm()
			},
			nonce: 28205,
			pow: core::Proof::new(vec![
				0x21e, 0x7a2, 0xeae, 0x144e, 0x1b1c, 0x1fbd, 0x203a, 0x214b, 0x293b, 0x2b74,
				0x2bfa, 0x2c26, 0x32bb, 0x346a, 0x34c7, 0x37c5, 0x4164, 0x42cc, 0x4cc3, 0x55af,
				0x5a70, 0x5b14, 0x5e1c, 0x5f76, 0x6061, 0x60f9, 0x61d7, 0x6318, 0x63a1, 0x63fb,
				0x649b, 0x64e5, 0x65a1, 0x6b69, 0x70f8, 0x71c7, 0x71cd, 0x7492, 0x7b11, 0x7db8,
				0x7f29, 0x7ff8,
			]),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// Second testnet genesis block (cuckoo30). TBD and don't start getting excited
/// just because you see this reference here... this is for testing mining
/// at cuckoo 30
pub fn genesis_testnet2() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2018 - 1900,
				tm_mon: 2,
				tm_mday: 26,
				tm_hour: 16,
				..time::empty_tm()
			},
			//TODO: Check this is over-estimated at T2 launch
			total_difficulty: Difficulty::from_num(global::initial_block_difficulty()),
			nonce: 1060,
			pow: core::Proof::new(vec![
				0x1940730, 0x333b9d0, 0x4739d6f, 0x4c6cfb1, 0x6e3d6c3, 0x74408a3, 0x7ba2bd2,
				0x83e2024, 0x8ca22b5, 0x9d39ab8, 0xb6646dd, 0xc6698b6, 0xc6f78fe, 0xc99b662,
				0xcf2ae8c, 0xcf41eed, 0xdd073e6, 0xded6af8, 0xf08d1a5, 0x1156a144, 0x11d1160a,
				0x131bb0a5, 0x137ad703, 0x13b0831f, 0x1421683f, 0x147e3c1f, 0x1496fda0,
				0x150ba22b, 0x15cc5bc6, 0x16edf697, 0x17ced40c, 0x17d84f9e, 0x18a515c1,
				0x19320d9c, 0x19da4f6d, 0x1b50bcb1, 0x1b8bc72f, 0x1c7b6964, 0x1d07b3a9,
				0x1d189d4d, 0x1d1f9a15, 0x1dafcd41,
			]),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}

/// Placeholder for mainnet genesis block, will definitely change before
/// release so no use trying to pre-mine it.
pub fn genesis_main() -> core::Block {
	core::Block {
		header: core::BlockHeader {
			height: 0,
			previous: core::hash::Hash([0xff; 32]),
			timestamp: time::Tm {
				tm_year: 2018 - 1900,
				tm_mon: 7,
				tm_mday: 14,
				..time::empty_tm()
			},
			total_difficulty: Difficulty::from_num(global::initial_block_difficulty()),
			nonce: global::get_genesis_nonce(),
			pow: core::Proof::zero(consensus::PROOFSIZE),
			..Default::default()
		},
		inputs: vec![],
		outputs: vec![],
		kernels: vec![],
	}
}
<|endoftext|>


<commit_before>/// The query resolver that operates on the AST and the TOML object

#[cfg(test)]
mod test {
    use toml::from_str as toml_from_str;
    use toml::Value;
    use tokenizer::*;
    use error::*;

    macro_rules! do_resolve {
        ( $toml:ident => $query:expr ) => {
            resolve(&mut $toml, tokenize_with_seperator(&String::from($query), '.').unwrap())
        }
    }

    #[test]
    fn test_resolve_empty_toml_simple_query() {
        let mut toml = toml_from_str("").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_err());
        let result = result.unwrap_err();

        let errkind = result.kind();
        assert!(is_match!(errkind, &ErrorKind::IdentifierNotFoundInDocument { .. }));
    }

    #[test]
    fn test_resolve_present_bool() {
        let mut toml = toml_from_str("example = true").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Boolean(true)));
    }

    #[test]
    fn test_resolve_present_integer() {
        let mut toml = toml_from_str("example = 1").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Integer(1)));
    }

    #[test]
    fn test_resolve_present_float() {
        let mut toml = toml_from_str("example = 1.0").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Float(1.0)));
    }

    #[test]
    fn test_resolve_present_string() {
        let mut toml = toml_from_str("example = 'string'").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::String(_)));
        match result {
            &mut Value::String(ref s) => assert_eq!("string", s),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_present_array_bools() {
        let mut toml = toml_from_str("example = [ true, false ]").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Array(_)));
        match result {
            &mut Value::Array(ref ary) => {
                assert_eq!(ary[0], Value::Boolean(true));
                assert_eq!(ary[1], Value::Boolean(false));
            },
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_present_array_integers() {
        let mut toml = toml_from_str("example = [ 1, 1337 ]").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Array(_)));
        match result {
            &mut Value::Array(ref ary) => {
                assert_eq!(ary[0], Value::Integer(1));
                assert_eq!(ary[1], Value::Integer(1337));
            },
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_present_array_floats() {
        let mut toml = toml_from_str("example = [ 1.0, 133.25 ]").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Array(_)));
        match result {
            &mut Value::Array(ref ary) => {
                assert_eq!(ary[0], Value::Float(1.0));
                assert_eq!(ary[1], Value::Float(133.25));
            },
            _ => panic!("What just happened?"),
        }
    }

}
<commit_msg>Add function stup to get code compiling<commit_after>/// The query resolver that operates on the AST and the TOML object

use toml::Value;
use tokenizer::Token;
use error::*;

fn resolve(toml: &mut Value, tokens: Token) -> Result<&mut Value> {
    unimplemented!()
}

#[cfg(test)]
mod test {
    use toml::from_str as toml_from_str;
    use toml::Value;
    use tokenizer::*;
    use error::*;
    use super::resolve;

    macro_rules! do_resolve {
        ( $toml:ident => $query:expr ) => {
            resolve(&mut $toml, tokenize_with_seperator(&String::from($query), '.').unwrap())
        }
    }

    #[test]
    fn test_resolve_empty_toml_simple_query() {
        let mut toml = toml_from_str("").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_err());
        let result = result.unwrap_err();

        let errkind = result.kind();
        assert!(is_match!(errkind, &ErrorKind::IdentifierNotFoundInDocument { .. }));
    }

    #[test]
    fn test_resolve_present_bool() {
        let mut toml = toml_from_str("example = true").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Boolean(true)));
    }

    #[test]
    fn test_resolve_present_integer() {
        let mut toml = toml_from_str("example = 1").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Integer(1)));
    }

    #[test]
    fn test_resolve_present_float() {
        let mut toml = toml_from_str("example = 1.0").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Float(1.0)));
    }

    #[test]
    fn test_resolve_present_string() {
        let mut toml = toml_from_str("example = 'string'").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::String(_)));
        match result {
            &mut Value::String(ref s) => assert_eq!("string", s),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_present_array_bools() {
        let mut toml = toml_from_str("example = [ true, false ]").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Array(_)));
        match result {
            &mut Value::Array(ref ary) => {
                assert_eq!(ary[0], Value::Boolean(true));
                assert_eq!(ary[1], Value::Boolean(false));
            },
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_present_array_integers() {
        let mut toml = toml_from_str("example = [ 1, 1337 ]").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Array(_)));
        match result {
            &mut Value::Array(ref ary) => {
                assert_eq!(ary[0], Value::Integer(1));
                assert_eq!(ary[1], Value::Integer(1337));
            },
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_resolve_present_array_floats() {
        let mut toml = toml_from_str("example = [ 1.0, 133.25 ]").unwrap();
        let result = do_resolve!(toml => "example");

        assert!(result.is_ok());
        let result = result.unwrap();

        assert!(is_match!(result, &mut Value::Array(_)));
        match result {
            &mut Value::Array(ref ary) => {
                assert_eq!(ary[0], Value::Float(1.0));
                assert_eq!(ary[1], Value::Float(133.25));
            },
            _ => panic!("What just happened?"),
        }
    }

}
<|endoftext|>


<commit_before>use futures::Finished;
use tokio_core::net::TcpStream;
use tk_bufstream::{Flushed, IoBuf};
use minihttp::{self, Status};
use cookie::Cookie;

use std::fmt::Display;
use std::fs;
use std::io::{self, Read, Write};
use std::path::Path;

pub struct ResponseWriter {
    res_writer: minihttp::ResponseWriter<TcpStream>,
}

impl ResponseWriter {
    pub fn new(res: minihttp::ResponseWriter<TcpStream>) -> ResponseWriter {
        ResponseWriter { res_writer: res }
    }

    pub fn status(&mut self, status: Status) {
        self.res_writer.status(status)
    }

    pub fn custom_status(&mut self, code: u16, reason: &str) {
        self.res_writer.custom_status(code, reason)
    }

    // TODO(nokaa): currently if the called function returns an error, we are panicking.
    // We want to return the normal value, but the used Error is not exported from minihttp
    pub fn add_header<V: AsRef<[u8]>>(&mut self, name: &str, value: V) {
        if !self.is_started() {
            self.status(Status::Ok);
        }
        self.res_writer.add_header(name, value).unwrap()
    }

    // TODO(nokaa): currently if the called function returns an error, we are panicking.
    // We want to return the normal value, but the used Error is not exported from minihttp
    pub fn format_header<D: Display>(&mut self, name: &str, value: D) {
        self.res_writer.format_header(name, value).unwrap()
    }

    // TODO(nokaa): currently if the called function returns an error, we are panicking.
    // We want to return the normal value, but the used Error is not exported from minihttp
    pub fn add_length(&mut self, n: u64) {
        self.res_writer.add_length(n).unwrap()
    }

    // TODO(nokaa): currently if the called function returns an error, we are panicking.
    // We want to return the normal value, but the used Error is not exported from minihttp
    pub fn add_chunked(&mut self) {
        self.res_writer.add_chunked().unwrap()
    }

    pub fn is_started(&self) -> bool {
        self.res_writer.is_started()
    }

    // TODO(nokaa): currently if the called function returns an error, we are panicking.
    // We want to return the normal value, but the used Error is not exported from minihttp
    pub fn done_headers(&mut self) -> bool {
        self.res_writer.done_headers().unwrap()
    }

    pub fn write_body(&mut self, data: &[u8]) {
        self.res_writer.write_body(data)
    }

    pub fn is_complete(&self) -> bool {
        self.res_writer.is_complete()
    }

    pub fn done<E>(self) -> Finished<IoBuf<TcpStream>, E> {
        self.res_writer.done()
    }

    pub fn steal_socket(self) -> Flushed<TcpStream> {
        self.res_writer.steal_socket()
    }

    pub fn send_file<P: AsRef<Path>>(&mut self, filename: P) -> io::Result<()> {
        let mut file = fs::File::open(filename)?;
        let mut buf = Vec::new();
        file.read_to_end(&mut buf)?;
        self.write_all(&buf)
    }

    pub fn redirect(&mut self, status: Status, location: &[u8], data: &[u8]) -> io::Result<()> {
        if !self.is_started() {
            self.status(status);
        }
        self.add_header("Location", location);
        self.write_all(data)
    }

    pub fn set_cookie(&mut self, cookie: Cookie) {
        if !self.is_started() {
            self.status(Status::Ok);
        }
        let cookie = cookie.as_bytes();
        self.add_header("Set-Cookie", &cookie);
    }
}

impl Write for ResponseWriter {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let len = buf.len();
        if !self.is_started() {
            self.status(Status::Ok);
        }
        // TODO(nokaa): We want to make sure that the `Content-Type` header
        // has not already been set.
        self.add_header("Content-Type", b"text/html; charset=utf-8");
        self.add_length(len as u64);
        if self.done_headers() {
            self.write_body(buf);
            Ok((buf.len()))
        } else {
            Ok(0)
        }

    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}
<commit_msg>Accept reference to Cookie<commit_after>use futures::Finished;
use tokio_core::net::TcpStream;
use tk_bufstream::{Flushed, IoBuf};
use minihttp::{self, Status};
use cookie::Cookie;

use std::fmt::Display;
use std::fs;
use std::io::{self, Read, Write};
use std::path::Path;

pub struct ResponseWriter {
    res_writer: minihttp::ResponseWriter<TcpStream>,
}

impl ResponseWriter {
    pub fn new(res: minihttp::ResponseWriter<TcpStream>) -> ResponseWriter {
        ResponseWriter { res_writer: res }
    }

    pub fn status(&mut self, status: Status) {
        self.res_writer.status(status)
    }

    pub fn custom_status(&mut self, code: u16, reason: &str) {
        self.res_writer.custom_status(code, reason)
    }

    // TODO(nokaa): currently if the called function returns an error, we are panicking.
    // We want to return the normal value, but the used Error is not exported from minihttp
    pub fn add_header<V: AsRef<[u8]>>(&mut self, name: &str, value: V) {
        if !self.is_started() {
            self.status(Status::Ok);
        }
        self.res_writer.add_header(name, value).unwrap()
    }

    // TODO(nokaa): currently if the called function returns an error, we are panicking.
    // We want to return the normal value, but the used Error is not exported from minihttp
    pub fn format_header<D: Display>(&mut self, name: &str, value: D) {
        self.res_writer.format_header(name, value).unwrap()
    }

    // TODO(nokaa): currently if the called function returns an error, we are panicking.
    // We want to return the normal value, but the used Error is not exported from minihttp
    pub fn add_length(&mut self, n: u64) {
        self.res_writer.add_length(n).unwrap()
    }

    // TODO(nokaa): currently if the called function returns an error, we are panicking.
    // We want to return the normal value, but the used Error is not exported from minihttp
    pub fn add_chunked(&mut self) {
        self.res_writer.add_chunked().unwrap()
    }

    pub fn is_started(&self) -> bool {
        self.res_writer.is_started()
    }

    // TODO(nokaa): currently if the called function returns an error, we are panicking.
    // We want to return the normal value, but the used Error is not exported from minihttp
    pub fn done_headers(&mut self) -> bool {
        self.res_writer.done_headers().unwrap()
    }

    pub fn write_body(&mut self, data: &[u8]) {
        self.res_writer.write_body(data)
    }

    pub fn is_complete(&self) -> bool {
        self.res_writer.is_complete()
    }

    pub fn done<E>(self) -> Finished<IoBuf<TcpStream>, E> {
        self.res_writer.done()
    }

    pub fn steal_socket(self) -> Flushed<TcpStream> {
        self.res_writer.steal_socket()
    }

    pub fn send_file<P: AsRef<Path>>(&mut self, filename: P) -> io::Result<()> {
        let mut file = fs::File::open(filename)?;
        let mut buf = Vec::new();
        file.read_to_end(&mut buf)?;
        self.write_all(&buf)
    }

    pub fn redirect(&mut self, status: Status, location: &[u8], data: &[u8]) -> io::Result<()> {
        if !self.is_started() {
            self.status(status);
        }
        self.add_header("Location", location);
        self.write_all(data)
    }

    pub fn set_cookie(&mut self, cookie: &Cookie) {
        if !self.is_started() {
            self.status(Status::Ok);
        }
        let cookie = cookie.as_bytes();
        self.add_header("Set-Cookie", &cookie);
    }
}

impl Write for ResponseWriter {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let len = buf.len();
        if !self.is_started() {
            self.status(Status::Ok);
        }
        // TODO(nokaa): We want to make sure that the `Content-Type` header
        // has not already been set.
        self.add_header("Content-Type", b"text/html; charset=utf-8");
        self.add_length(len as u64);
        if self.done_headers() {
            self.write_body(buf);
            Ok((buf.len()))
        } else {
            Ok(0)
        }

    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::default::Default;
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};

use config::Settings;
use quire::parse_config;
use quire::validate as V;

#[derive(PartialEq, RustcDecodable)]
struct SecureSettings {
    allowed_dirs: BTreeMap<String, PathBuf>,
    storage_dir: Option<PathBuf>,
    cache_dir: Option<PathBuf>,
    version_check: Option<bool>,
    ubuntu_mirror: Option<String>,
    alpine_mirror: Option<String>,
    site_settings: BTreeMap<PathBuf, SecureSettings>,
}

pub fn secure_settings_validator<'a>(has_children: bool)
    -> Box<V::Validator + 'a>
{
    let mut members = vec!(
        ("allowed_dirs".to_string(), Box::new(V::Mapping {
            key_element: Box::new(V::Scalar {
                .. Default::default()}) as Box<V::Validator>,
            value_element: Box::new(V::Scalar {
                .. Default::default()}) as Box<V::Validator>,
            .. Default::default()}) as Box<V::Validator>),
        ("storage_dir".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator>),
        ("cache_dir".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator>),
        ("version_check".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator>),
        ("ubuntu_mirror".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator>),
        ("alpine_mirror".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator>),
    );
    if has_children {
        members.push(
            ("site_settings".to_string(), Box::new(V::Mapping {
                key_element: Box::new(V::Scalar {
                    .. Default::default()}) as Box<V::Validator>,
                value_element: secure_settings_validator(false),
                .. Default::default()}) as Box<V::Validator>),
        );
    }
    return Box::new(V::Structure {
        members: members, .. Default::default()}) as Box<V::Validator>;
}

#[derive(PartialEq, RustcDecodable)]
struct InsecureSettings {
    version_check: Option<bool>,
    shared_cache: Option<bool>,
    ubuntu_mirror: Option<String>,
    alpine_mirror: Option<String>,
}

pub fn insecure_settings_validator<'a>() -> Box<V::Validator + 'a> {
    return Box::new(V::Structure { members: vec!(
        ("version_check".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator + 'a>),
        ("shared_cache".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator + 'a>),
        ("ubuntu_mirror".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator>),
        ("alpine_mirror".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator>),
    ), .. Default::default()}) as Box<V::Validator>;
}

pub struct MergedSettings {
    pub allowed_dirs: BTreeMap<String, PathBuf>,
    pub allowed_files: BTreeMap<String, PathBuf>,
    pub storage_dir: Option<PathBuf>,
    pub cache_dir: Option<PathBuf>,
    pub shared_cache: bool,
}

pub fn read_settings(project_root: &Path)
    -> Result<(MergedSettings, Settings), String>
{
    let mut ext_settings = MergedSettings {
        allowed_dirs: BTreeMap::new(),
        allowed_files: BTreeMap::new(),
        storage_dir: None,
        cache_dir: None,
        shared_cache: false,
    };
    let mut int_settings = Settings {
        version_check: true,
        uid_map: None,
        ubuntu_mirror: "mirror://mirrors.ubuntu.com/mirrors.txt".to_string(),
        alpine_mirror: None,
    };
    let mut secure_files = vec!();
    if let Ok(home) = env::var("VAGGA_USER_HOME") {
        let home = Path::new(home);
        secure_files.push(home.join(".config/vagga/settings.yaml"));
        secure_files.push(home.join(".vagga/settings.yaml"));
        secure_files.push(home.join(".vagga.yaml"));
    };
    for filename in secure_files.iter() {
        if !filename.exists() {
            continue;
        }
        let cfg: SecureSettings = try!(parse_config(filename,
            &*secure_settings_validator(true), Default::default()));
        for (k, v) in cfg.allowed_dirs.iter() {
            ext_settings.allowed_dirs.insert(k.clone(), v.clone());
        }
        if let Some(dir) = cfg.storage_dir {
            ext_settings.storage_dir = Some(dir);
        }
        if let Some(dir) = cfg.cache_dir {
            ext_settings.cache_dir = Some(dir);
            ext_settings.shared_cache = true;
        }
        if let Some(val) = cfg.version_check {
            int_settings.version_check = val;
        }
        if let Some(ref val) = cfg.ubuntu_mirror {
            int_settings.ubuntu_mirror = val.clone();
        }
        if let Some(ref val) = cfg.alpine_mirror {
            int_settings.alpine_mirror = Some(val.clone());
        }
        if let Some(cfg) = cfg.site_settings.get(project_root) {
            for (k, v) in cfg.allowed_dirs.iter() {
                ext_settings.allowed_dirs.insert(k.clone(), v.clone());
            }
            if let Some(ref dir) = cfg.storage_dir {
                ext_settings.storage_dir = Some(dir.clone());
            }
            if let Some(ref dir) = cfg.cache_dir {
                ext_settings.cache_dir = Some(dir.clone());
                ext_settings.shared_cache = true;
            }
            if let Some(val) = cfg.version_check {
                int_settings.version_check = val;
            }
            if let Some(ref val) = cfg.ubuntu_mirror {
                int_settings.ubuntu_mirror = val.clone();
            }
            if let Some(ref val) = cfg.alpine_mirror {
                int_settings.alpine_mirror = Some(val.clone());
            }
        }
    }
    let mut insecure_files = vec!();
    insecure_files.push(project_root.join(".vagga.settings.yaml"));
    insecure_files.push(project_root.join(".vagga/settings.yaml"));
    for filename in insecure_files.iter() {
        if !filename.exists() {
            continue;
        }
        let cfg: InsecureSettings = try!(parse_config(filename,
            &*insecure_settings_validator(), Default::default()));
        if let Some(val) = cfg.version_check {
            int_settings.version_check = val;
        }
        if let Some(ref val) = cfg.ubuntu_mirror {
            int_settings.ubuntu_mirror = val.clone();
        }
        if let Some(ref val) = cfg.alpine_mirror {
            int_settings.alpine_mirror = Some(val.clone());
        }
        if let Some(val) = cfg.shared_cache {
            ext_settings.shared_cache = val;
        }
    }
    return Ok((ext_settings, int_settings));
}
<commit_msg>Fix wrapper/settings.rs<commit_after>use std::env;
use std::fs::{PathExt};
use std::default::Default;
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};

use config::Settings;
use quire::parse_config;
use quire::validate as V;

#[derive(PartialEq, RustcDecodable)]
struct SecureSettings {
    allowed_dirs: BTreeMap<String, PathBuf>,
    storage_dir: Option<PathBuf>,
    cache_dir: Option<PathBuf>,
    version_check: Option<bool>,
    ubuntu_mirror: Option<String>,
    alpine_mirror: Option<String>,
    site_settings: BTreeMap<PathBuf, SecureSettings>,
}

pub fn secure_settings_validator<'a>(has_children: bool)
    -> Box<V::Validator + 'a>
{
    let mut members = vec!(
        ("allowed_dirs".to_string(), Box::new(V::Mapping {
            key_element: Box::new(V::Scalar {
                .. Default::default()}) as Box<V::Validator>,
            value_element: Box::new(V::Scalar {
                .. Default::default()}) as Box<V::Validator>,
            .. Default::default()}) as Box<V::Validator>),
        ("storage_dir".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator>),
        ("cache_dir".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator>),
        ("version_check".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator>),
        ("ubuntu_mirror".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator>),
        ("alpine_mirror".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator>),
    );
    if has_children {
        members.push(
            ("site_settings".to_string(), Box::new(V::Mapping {
                key_element: Box::new(V::Scalar {
                    .. Default::default()}) as Box<V::Validator>,
                value_element: secure_settings_validator(false),
                .. Default::default()}) as Box<V::Validator>),
        );
    }
    return Box::new(V::Structure {
        members: members, .. Default::default()}) as Box<V::Validator>;
}

#[derive(PartialEq, RustcDecodable)]
struct InsecureSettings {
    version_check: Option<bool>,
    shared_cache: Option<bool>,
    ubuntu_mirror: Option<String>,
    alpine_mirror: Option<String>,
}

pub fn insecure_settings_validator<'a>() -> Box<V::Validator + 'a> {
    return Box::new(V::Structure { members: vec!(
        ("version_check".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator + 'a>),
        ("shared_cache".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator + 'a>),
        ("ubuntu_mirror".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator>),
        ("alpine_mirror".to_string(), Box::new(V::Scalar {
            optional: true,
            .. Default::default()}) as Box<V::Validator>),
    ), .. Default::default()}) as Box<V::Validator>;
}

pub struct MergedSettings {
    pub allowed_dirs: BTreeMap<String, PathBuf>,
    pub allowed_files: BTreeMap<String, PathBuf>,
    pub storage_dir: Option<PathBuf>,
    pub cache_dir: Option<PathBuf>,
    pub shared_cache: bool,
}

pub fn read_settings(project_root: &Path)
    -> Result<(MergedSettings, Settings), String>
{
    let mut ext_settings = MergedSettings {
        allowed_dirs: BTreeMap::new(),
        allowed_files: BTreeMap::new(),
        storage_dir: None,
        cache_dir: None,
        shared_cache: false,
    };
    let mut int_settings = Settings {
        version_check: true,
        uid_map: None,
        ubuntu_mirror: "mirror://mirrors.ubuntu.com/mirrors.txt".to_string(),
        alpine_mirror: None,
    };
    let mut secure_files = vec!();
    if let Ok(home) = env::var("VAGGA_USER_HOME") {
        let home = Path::new(&home);
        secure_files.push(home.join(".config/vagga/settings.yaml"));
        secure_files.push(home.join(".vagga/settings.yaml"));
        secure_files.push(home.join(".vagga.yaml"));
    };
    for filename in secure_files.iter() {
        if !filename.exists() {
            continue;
        }
        let cfg: SecureSettings = try!(parse_config(filename,
            &*secure_settings_validator(true), Default::default()));
        for (k, v) in cfg.allowed_dirs.iter() {
            ext_settings.allowed_dirs.insert(k.clone(), v.clone());
        }
        if let Some(dir) = cfg.storage_dir {
            ext_settings.storage_dir = Some(dir);
        }
        if let Some(dir) = cfg.cache_dir {
            ext_settings.cache_dir = Some(dir);
            ext_settings.shared_cache = true;
        }
        if let Some(val) = cfg.version_check {
            int_settings.version_check = val;
        }
        if let Some(ref val) = cfg.ubuntu_mirror {
            int_settings.ubuntu_mirror = val.clone();
        }
        if let Some(ref val) = cfg.alpine_mirror {
            int_settings.alpine_mirror = Some(val.clone());
        }
        if let Some(cfg) = cfg.site_settings.get(project_root) {
            for (k, v) in cfg.allowed_dirs.iter() {
                ext_settings.allowed_dirs.insert(k.clone(), v.clone());
            }
            if let Some(ref dir) = cfg.storage_dir {
                ext_settings.storage_dir = Some(dir.clone());
            }
            if let Some(ref dir) = cfg.cache_dir {
                ext_settings.cache_dir = Some(dir.clone());
                ext_settings.shared_cache = true;
            }
            if let Some(val) = cfg.version_check {
                int_settings.version_check = val;
            }
            if let Some(ref val) = cfg.ubuntu_mirror {
                int_settings.ubuntu_mirror = val.clone();
            }
            if let Some(ref val) = cfg.alpine_mirror {
                int_settings.alpine_mirror = Some(val.clone());
            }
        }
    }
    let mut insecure_files = vec!();
    insecure_files.push(project_root.join(".vagga.settings.yaml"));
    insecure_files.push(project_root.join(".vagga/settings.yaml"));
    for filename in insecure_files.iter() {
        if !filename.exists() {
            continue;
        }
        let cfg: InsecureSettings = try!(parse_config(filename,
            &*insecure_settings_validator(), Default::default()));
        if let Some(val) = cfg.version_check {
            int_settings.version_check = val;
        }
        if let Some(ref val) = cfg.ubuntu_mirror {
            int_settings.ubuntu_mirror = val.clone();
        }
        if let Some(ref val) = cfg.alpine_mirror {
            int_settings.alpine_mirror = Some(val.clone());
        }
        if let Some(val) = cfg.shared_cache {
            ext_settings.shared_cache = val;
        }
    }
    return Ok((ext_settings, int_settings));
}
<|endoftext|>


<commit_before>//! # Getting started
//!
//! ```rust,no_run
//! use sdl2::pixels::Color;
//! use sdl2::event::Event;
//! use sdl2::keyboard::Keycode;
//! use std::time::Duration;
//!
//! pub fn main() {
//!     let sdl_context = sdl2::init().unwrap();
//!     let video_subsystem = sdl_context.video().unwrap();
//!
//!     let window = video_subsystem.window("rust-sdl2 demo", 800, 600)
//!         .position_centered()
//!         .build()
//!         .unwrap();
//!
//!     let mut canvas = window.into_canvas().build().unwrap();
//!
//!     canvas.set_draw_color(Color::RGB(0, 255, 255));
//!     canvas.clear();
//!     canvas.present();
//!     let mut event_pump = sdl_context.event_pump().unwrap();
//!     let mut i = 0;
//!     'running: loop {
//!         i = (i + 1) % 255;
//!         canvas.set_draw_color(Color::RGB(i, 64, 255 - i));
//!         canvas.clear();
//!         for event in event_pump.poll_iter() {
//!             match event {
//!                 Event::Quit {..} |
//!                 Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
//!                     break 'running
//!                 },
//!                 _ => {}
//!             }
//!         }
//!         // The rest of the game loop goes here...
//!
//!         canvas.present();
//!         ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
//!     }
//! }
//! ```

#![crate_name = "sdl2"]
#![crate_type = "lib"]

#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless, transmute_ptr_to_ref))]

extern crate num;
pub extern crate libc;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate bitflags;
pub extern crate sdl2_sys as sys;

#[cfg(feature = "gfx")]
extern crate c_vec;

pub use sdl::*;

pub mod clipboard;
pub mod cpuinfo;
#[macro_use] pub mod macros;
pub mod event;
pub mod filesystem;
pub mod gesture;
pub mod touch;
pub mod joystick;
pub mod controller;
pub mod haptic;
pub mod keyboard;
pub mod mouse;
pub mod rect;
pub mod surface;
pub mod pixels;
pub mod video;
pub mod timer;
pub mod render;
pub mod rwops;
pub mod log;
mod sdl;
pub mod audio;
pub mod version;
pub mod messagebox;
pub mod hint;

// modules
#[cfg(feature = "ttf")]
pub mod ttf;
#[cfg(feature = "image")]
pub mod image;
#[cfg(feature = "mixer")]
pub mod mixer;
#[cfg(feature = "gfx")]
pub mod gfx;

mod common;
// Export return types and such from the common module.
pub use common::IntegerOrSdlError;
<commit_msg>Make getting-started example copy-paste friendly<commit_after>//! # Getting started
//!
//! ```rust,no_run
//! extern crate sdl2;
//!
//! use sdl2::pixels::Color;
//! use sdl2::event::Event;
//! use sdl2::keyboard::Keycode;
//! use std::time::Duration;
//!
//! pub fn main() {
//!     let sdl_context = sdl2::init().unwrap();
//!     let video_subsystem = sdl_context.video().unwrap();
//!
//!     let window = video_subsystem.window("rust-sdl2 demo", 800, 600)
//!         .position_centered()
//!         .build()
//!         .unwrap();
//!
//!     let mut canvas = window.into_canvas().build().unwrap();
//!
//!     canvas.set_draw_color(Color::RGB(0, 255, 255));
//!     canvas.clear();
//!     canvas.present();
//!     let mut event_pump = sdl_context.event_pump().unwrap();
//!     let mut i = 0;
//!     'running: loop {
//!         i = (i + 1) % 255;
//!         canvas.set_draw_color(Color::RGB(i, 64, 255 - i));
//!         canvas.clear();
//!         for event in event_pump.poll_iter() {
//!             match event {
//!                 Event::Quit {..} |
//!                 Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
//!                     break 'running
//!                 },
//!                 _ => {}
//!             }
//!         }
//!         // The rest of the game loop goes here...
//!
//!         canvas.present();
//!         ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
//!     }
//! }
//! ```

#![crate_name = "sdl2"]
#![crate_type = "lib"]

#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless, transmute_ptr_to_ref))]

extern crate num;
pub extern crate libc;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate bitflags;
pub extern crate sdl2_sys as sys;

#[cfg(feature = "gfx")]
extern crate c_vec;

pub use sdl::*;

pub mod clipboard;
pub mod cpuinfo;
#[macro_use] pub mod macros;
pub mod event;
pub mod filesystem;
pub mod gesture;
pub mod touch;
pub mod joystick;
pub mod controller;
pub mod haptic;
pub mod keyboard;
pub mod mouse;
pub mod rect;
pub mod surface;
pub mod pixels;
pub mod video;
pub mod timer;
pub mod render;
pub mod rwops;
pub mod log;
mod sdl;
pub mod audio;
pub mod version;
pub mod messagebox;
pub mod hint;

// modules
#[cfg(feature = "ttf")]
pub mod ttf;
#[cfg(feature = "image")]
pub mod image;
#[cfg(feature = "mixer")]
pub mod mixer;
#[cfg(feature = "gfx")]
pub mod gfx;

mod common;
// Export return types and such from the common module.
pub use common::IntegerOrSdlError;
<|endoftext|>


<commit_before>//! # Getting started
//!
//! ```rust,no_run
//! extern crate sdl2;
//!
//! use sdl2::pixels::Color;
//! use sdl2::event::Event;
//! use sdl2::keyboard::Keycode;
//! use std::time::Duration;
//!
//! pub fn main() {
//!     let sdl_context = sdl2::init().unwrap();
//!     let video_subsystem = sdl_context.video().unwrap();
//!
//!     let window = video_subsystem.window("rust-sdl2 demo", 800, 600)
//!         .position_centered()
//!         .build()
//!         .unwrap();
//!
//!     let mut canvas = window.into_canvas().build().unwrap();
//!
//!     canvas.set_draw_color(Color::RGB(0, 255, 255));
//!     canvas.clear();
//!     canvas.present();
//!     let mut event_pump = sdl_context.event_pump().unwrap();
//!     let mut i = 0;
//!     'running: loop {
//!         i = (i + 1) % 255;
//!         canvas.set_draw_color(Color::RGB(i, 64, 255 - i));
//!         canvas.clear();
//!         for event in event_pump.poll_iter() {
//!             match event {
//!                 Event::Quit {..} |
//!                 Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
//!                     break 'running
//!                 },
//!                 _ => {}
//!             }
//!         }
//!         // The rest of the game loop goes here...
//!
//!         canvas.present();
//!         ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
//!     }
//! }
//! ```

#![crate_name = "sdl2"]
#![crate_type = "lib"]

#![allow(clippy::cast_lossless, clippy::transmute_ptr_to_ref)]

pub extern crate libc;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate bitflags;
pub extern crate sdl2_sys as sys;

#[cfg(feature = "gfx")]
extern crate c_vec;

pub use crate::sdl::*;

pub mod clipboard;
pub mod cpuinfo;
#[macro_use] pub mod macros;
pub mod event;
pub mod filesystem;
pub mod gesture;
pub mod touch;
pub mod joystick;
pub mod controller;
pub mod haptic;
pub mod keyboard;
pub mod mouse;
pub mod rect;
pub mod surface;
pub mod pixels;
pub mod video;
pub mod timer;
pub mod render;
pub mod rwops;
pub mod log;
mod sdl;
pub mod audio;
pub mod version;
pub mod messagebox;
pub mod hint;

// modules
#[cfg(feature = "ttf")]
pub mod ttf;
#[cfg(feature = "image")]
pub mod image;
#[cfg(feature = "mixer")]
pub mod mixer;
#[cfg(feature = "gfx")]
pub mod gfx;

mod common;
// Export return types and such from the common module.
pub use crate::common::IntegerOrSdlError;

#[cfg(feature = "raw-window-handle")]
pub mod raw_window_handle;
<commit_msg>Make `macros` private, remove `gesture`<commit_after>//! # Getting started
//!
//! ```rust,no_run
//! extern crate sdl2;
//!
//! use sdl2::pixels::Color;
//! use sdl2::event::Event;
//! use sdl2::keyboard::Keycode;
//! use std::time::Duration;
//!
//! pub fn main() {
//!     let sdl_context = sdl2::init().unwrap();
//!     let video_subsystem = sdl_context.video().unwrap();
//!
//!     let window = video_subsystem.window("rust-sdl2 demo", 800, 600)
//!         .position_centered()
//!         .build()
//!         .unwrap();
//!
//!     let mut canvas = window.into_canvas().build().unwrap();
//!
//!     canvas.set_draw_color(Color::RGB(0, 255, 255));
//!     canvas.clear();
//!     canvas.present();
//!     let mut event_pump = sdl_context.event_pump().unwrap();
//!     let mut i = 0;
//!     'running: loop {
//!         i = (i + 1) % 255;
//!         canvas.set_draw_color(Color::RGB(i, 64, 255 - i));
//!         canvas.clear();
//!         for event in event_pump.poll_iter() {
//!             match event {
//!                 Event::Quit {..} |
//!                 Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
//!                     break 'running
//!                 },
//!                 _ => {}
//!             }
//!         }
//!         // The rest of the game loop goes here...
//!
//!         canvas.present();
//!         ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
//!     }
//! }
//! ```

#![crate_name = "sdl2"]
#![crate_type = "lib"]

#![allow(clippy::cast_lossless, clippy::transmute_ptr_to_ref)]

pub extern crate libc;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate bitflags;
pub extern crate sdl2_sys as sys;

#[cfg(feature = "gfx")]
extern crate c_vec;

pub use crate::sdl::*;

pub mod clipboard;
pub mod cpuinfo;
#[macro_use] mod macros;
pub mod event;
pub mod filesystem;
pub mod touch;
pub mod joystick;
pub mod controller;
pub mod haptic;
pub mod keyboard;
pub mod mouse;
pub mod rect;
pub mod surface;
pub mod pixels;
pub mod video;
pub mod timer;
pub mod render;
pub mod rwops;
pub mod log;
mod sdl;
pub mod audio;
pub mod version;
pub mod messagebox;
pub mod hint;

// modules
#[cfg(feature = "ttf")]
pub mod ttf;
#[cfg(feature = "image")]
pub mod image;
#[cfg(feature = "mixer")]
pub mod mixer;
#[cfg(feature = "gfx")]
pub mod gfx;

mod common;
// Export return types and such from the common module.
pub use crate::common::IntegerOrSdlError;

#[cfg(feature = "raw-window-handle")]
pub mod raw_window_handle;
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fs::{File, OpenOptions, remove_file};
use std::io::{Read, Write};

use rustc::ty::layout::Size;

use crate::stacked_borrows::Tag;
use crate::*;

pub struct FileHandle {
    file: File,
    flag: i32,
}

pub struct FileHandler {
    handles: HashMap<i32, FileHandle>,
    low: i32,
}

impl Default for FileHandler {
    fn default() -> Self {
        FileHandler {
            handles: Default::default(),
            // 0, 1 and 2 are reserved for stdin, stdout and stderr
            low: 3,
        }
    }
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn open(
        &mut self,
        path_op: OpTy<'tcx, Tag>,
        flag_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`open` not available when isolation is enabled")
        }

        let flag = this.read_scalar(flag_op)?.to_i32()?;

        let mut options = OpenOptions::new();

        // The first two bits of the flag correspond to the access mode of the file in linux.
        let access_mode = flag & 0b11;

        if access_mode == this.eval_libc_i32("O_RDONLY")? {
            options.read(true);
        } else if access_mode == this.eval_libc_i32("O_WRONLY")? {
            options.write(true);
        } else if access_mode == this.eval_libc_i32("O_RDWR")? {
            options.read(true).write(true);
        } else {
            throw_unsup_format!("Unsupported access mode {:#x}", access_mode);
        }

        if flag & this.eval_libc_i32("O_APPEND")? != 0 {
            options.append(true);
        }
        if flag & this.eval_libc_i32("O_TRUNC")? != 0 {
            options.truncate(true);
        }
        if flag & this.eval_libc_i32("O_CREAT")? != 0 {
            options.create(true);
        }

        let path_bytes = this
            .memory()
            .read_c_str(this.read_scalar(path_op)?.not_undef()?)?;
        let path = std::str::from_utf8(path_bytes)
            .map_err(|_| err_unsup_format!("{:?} is not a valid utf-8 string", path_bytes))?;

        let fd = options.open(path).map(|file| {
            let mut fh = &mut this.machine.file_handler;
            fh.low += 1;
            fh.handles.insert(fh.low, FileHandle { file, flag });
            fh.low
        });

        this.consume_result(fd)
    }

    fn fcntl(
        &mut self,
        fd_op: OpTy<'tcx, Tag>,
        cmd_op: OpTy<'tcx, Tag>,
        arg_op: Option<OpTy<'tcx, Tag>>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`fcntl` not available when isolation is enabled")
        }

        let fd = this.read_scalar(fd_op)?.to_i32()?;
        let cmd = this.read_scalar(cmd_op)?.to_i32()?;

        if cmd == this.eval_libc_i32("F_SETFD")? {
            // This does not affect the file itself. Certain flags might require changing the file
            // or the way it is accessed somehow.
            let flag = this.read_scalar(arg_op.unwrap())?.to_i32()?;
            // The only usage of this in stdlib at the moment is to enable the `FD_CLOEXEC` flag.
            let fd_cloexec = this.eval_libc_i32("FD_CLOEXEC")?;
            if let Some(FileHandle { flag: old_flag, .. }) =
                this.machine.file_handler.handles.get_mut(&fd)
            {
                if flag ^ *old_flag == fd_cloexec {
                    *old_flag = flag;
                } else {
                    throw_unsup_format!("Unsupported arg {:#x} for `F_SETFD`", flag);
                }
            }
            Ok(0)
        } else if cmd == this.eval_libc_i32("F_GETFD")? {
            this.get_handle_and(fd, |handle| Ok(handle.flag))
        } else {
            throw_unsup_format!("Unsupported command {:#x}", cmd);
        }
    }

    fn close(&mut self, fd_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`close` not available when isolation is enabled")
        }

        let fd = this.read_scalar(fd_op)?.to_i32()?;

        this.remove_handle_and(fd, |handle, this| {
            this.consume_result(handle.file.sync_all().map(|_| 0i32))
        })
    }

    fn read(
        &mut self,
        fd_op: OpTy<'tcx, Tag>,
        buf_op: OpTy<'tcx, Tag>,
        count_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i64> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`read` not available when isolation is enabled")
        }

        let tcx = &{ this.tcx.tcx };

        let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;
        // Reading zero bytes should not change `buf`
        if count == 0 {
            return Ok(0);
        }
        let fd = this.read_scalar(fd_op)?.to_i32()?;
        let buf_scalar = this.read_scalar(buf_op)?.not_undef()?;

        // Remove the file handle to avoid borrowing issues
        this.remove_handle_and(fd, |mut handle, this| {
            // Don't use `?` to avoid returning before reinserting the handle
            let bytes = this.force_ptr(buf_scalar).and_then(|buf| {
                this.memory_mut()
                    .get_mut(buf.alloc_id)?
                    .get_bytes_mut(tcx, buf, Size::from_bytes(count))
                    .map(|buffer| handle.file.read(buffer))
            });
            // Reinsert the file handle
            this.machine.file_handler.handles.insert(fd, handle);
            this.consume_result(bytes?.map(|bytes| bytes as i64))
        })
    }

    fn write(
        &mut self,
        fd_op: OpTy<'tcx, Tag>,
        buf_op: OpTy<'tcx, Tag>,
        count_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i64> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`write` not available when isolation is enabled")
        }

        let tcx = &{ this.tcx.tcx };

        let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;
        // Writing zero bytes should not change `buf`
        if count == 0 {
            return Ok(0);
        }
        let fd = this.read_scalar(fd_op)?.to_i32()?;
        let buf = this.force_ptr(this.read_scalar(buf_op)?.not_undef()?)?;

        this.remove_handle_and(fd, |mut handle, this| {
            let bytes = this.memory().get(buf.alloc_id).and_then(|alloc| {
                alloc
                    .get_bytes(tcx, buf, Size::from_bytes(count))
                    .map(|bytes| handle.file.write(bytes).map(|bytes| bytes as i64))
            });
            this.machine.file_handler.handles.insert(fd, handle);
            this.consume_result(bytes?)
        })
    }

    fn unlink( &mut self, path_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`write` not available when isolation is enabled")
        }

        let path_bytes = this
            .memory()
            .read_c_str(this.read_scalar(path_op)?.not_undef()?)?;
        let path = std::str::from_utf8(path_bytes)
            .map_err(|_| err_unsup_format!("{:?} is not a valid utf-8 string", path_bytes))?;

        let result = remove_file(path).map(|_| 0);

        this.consume_result(result)
    }

    /// Helper function that gets a `FileHandle` immutable reference and allows to manipulate it
    /// using the `f` closure.
    ///
    /// If the `fd` file descriptor does not correspond to a file, this functions returns `Ok(-1)`
    /// and sets `Evaluator::last_error` to `libc::EBADF` (invalid file descriptor).
    ///
    /// This function uses `T: From<i32>` instead of `i32` directly because some IO related
    /// functions return different integer types (like `read`, that returns an `i64`)
    fn get_handle_and<F, T: From<i32>>(&mut self, fd: i32, f: F) -> InterpResult<'tcx, T>
    where
        F: Fn(&FileHandle) -> InterpResult<'tcx, T>,
    {
        let this = self.eval_context_mut();
        if let Some(handle) = this.machine.file_handler.handles.get(&fd) {
            f(handle)
        } else {
            let ebadf = this.eval_libc("EBADF")?;
            this.set_last_error(ebadf)?;
            Ok((-1).into())
        }
    }

    /// Helper function that removes a `FileHandle` and allows to manipulate it using the `f`
    /// closure. This function is quite useful when you need to modify a `FileHandle` but you need
    /// to modify `MiriEvalContext` at the same time, so you can modify the handle and reinsert it
    /// using `f`.
    ///
    /// If the `fd` file descriptor does not correspond to a file, this functions returns `Ok(-1)`
    /// and sets `Evaluator::last_error` to `libc::EBADF` (invalid file descriptor).
    ///
    /// This function uses `T: From<i32>` instead of `i32` directly because some IO related
    /// functions return different integer types (like `read`, that returns an `i64`)
    fn remove_handle_and<F, T: From<i32>>(&mut self, fd: i32, mut f: F) -> InterpResult<'tcx, T>
    where
        F: FnMut(FileHandle, &mut MiriEvalContext<'mir, 'tcx>) -> InterpResult<'tcx, T>,
    {
        let this = self.eval_context_mut();
        if let Some(handle) = this.machine.file_handler.handles.remove(&fd) {
            f(handle, this)
        } else {
            let ebadf = this.eval_libc("EBADF")?;
            this.set_last_error(ebadf)?;
            Ok((-1).into())
        }
    }

    /// Helper function that consumes an `std::io::Result<T>` and returns an
    /// `InterpResult<'tcx,T>::Ok` instead. It is expected that the result can be converted to an
    /// OS error using `std::io::Error::raw_os_error`.
    ///
    /// This function uses `T: From<i32>` instead of `i32` directly because some IO related
    /// functions return different integer types (like `read`, that returns an `i64`)
    fn consume_result<T: From<i32>>(
        &mut self,
        result: std::io::Result<T>,
    ) -> InterpResult<'tcx, T> {
        match result {
            Ok(ok) => Ok(ok),
            Err(e) => {
                self.eval_context_mut().consume_io_error(e)?;
                Ok((-1).into())
            }
        }
    }
}
<commit_msg>Add comment for the flag diff check<commit_after>use std::collections::HashMap;
use std::fs::{File, OpenOptions, remove_file};
use std::io::{Read, Write};

use rustc::ty::layout::Size;

use crate::stacked_borrows::Tag;
use crate::*;

pub struct FileHandle {
    file: File,
    flag: i32,
}

pub struct FileHandler {
    handles: HashMap<i32, FileHandle>,
    low: i32,
}

impl Default for FileHandler {
    fn default() -> Self {
        FileHandler {
            handles: Default::default(),
            // 0, 1 and 2 are reserved for stdin, stdout and stderr
            low: 3,
        }
    }
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn open(
        &mut self,
        path_op: OpTy<'tcx, Tag>,
        flag_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`open` not available when isolation is enabled")
        }

        let flag = this.read_scalar(flag_op)?.to_i32()?;

        let mut options = OpenOptions::new();

        // The first two bits of the flag correspond to the access mode of the file in linux.
        let access_mode = flag & 0b11;

        if access_mode == this.eval_libc_i32("O_RDONLY")? {
            options.read(true);
        } else if access_mode == this.eval_libc_i32("O_WRONLY")? {
            options.write(true);
        } else if access_mode == this.eval_libc_i32("O_RDWR")? {
            options.read(true).write(true);
        } else {
            throw_unsup_format!("Unsupported access mode {:#x}", access_mode);
        }

        if flag & this.eval_libc_i32("O_APPEND")? != 0 {
            options.append(true);
        }
        if flag & this.eval_libc_i32("O_TRUNC")? != 0 {
            options.truncate(true);
        }
        if flag & this.eval_libc_i32("O_CREAT")? != 0 {
            options.create(true);
        }

        let path_bytes = this
            .memory()
            .read_c_str(this.read_scalar(path_op)?.not_undef()?)?;
        let path = std::str::from_utf8(path_bytes)
            .map_err(|_| err_unsup_format!("{:?} is not a valid utf-8 string", path_bytes))?;

        let fd = options.open(path).map(|file| {
            let mut fh = &mut this.machine.file_handler;
            fh.low += 1;
            fh.handles.insert(fh.low, FileHandle { file, flag });
            fh.low
        });

        this.consume_result(fd)
    }

    fn fcntl(
        &mut self,
        fd_op: OpTy<'tcx, Tag>,
        cmd_op: OpTy<'tcx, Tag>,
        arg_op: Option<OpTy<'tcx, Tag>>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`fcntl` not available when isolation is enabled")
        }

        let fd = this.read_scalar(fd_op)?.to_i32()?;
        let cmd = this.read_scalar(cmd_op)?.to_i32()?;

        if cmd == this.eval_libc_i32("F_SETFD")? {
            // This does not affect the file itself. Certain flags might require changing the file
            // or the way it is accessed somehow.
            let flag = this.read_scalar(arg_op.unwrap())?.to_i32()?;
            // The only usage of this in stdlib at the moment is to enable the `FD_CLOEXEC` flag.
            let fd_cloexec = this.eval_libc_i32("FD_CLOEXEC")?;
            if let Some(FileHandle { flag: old_flag, .. }) =
                this.machine.file_handler.handles.get_mut(&fd)
            {
                // Check that the only difference between the old flag and the current flag is
                // exactly the `FD_CLOEXEC` value.
                if flag ^ *old_flag == fd_cloexec {
                    *old_flag = flag;
                } else {
                    throw_unsup_format!("Unsupported arg {:#x} for `F_SETFD`", flag);
                }
            }
            Ok(0)
        } else if cmd == this.eval_libc_i32("F_GETFD")? {
            this.get_handle_and(fd, |handle| Ok(handle.flag))
        } else {
            throw_unsup_format!("Unsupported command {:#x}", cmd);
        }
    }

    fn close(&mut self, fd_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`close` not available when isolation is enabled")
        }

        let fd = this.read_scalar(fd_op)?.to_i32()?;

        this.remove_handle_and(fd, |handle, this| {
            this.consume_result(handle.file.sync_all().map(|_| 0i32))
        })
    }

    fn read(
        &mut self,
        fd_op: OpTy<'tcx, Tag>,
        buf_op: OpTy<'tcx, Tag>,
        count_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i64> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`read` not available when isolation is enabled")
        }

        let tcx = &{ this.tcx.tcx };

        let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;
        // Reading zero bytes should not change `buf`
        if count == 0 {
            return Ok(0);
        }
        let fd = this.read_scalar(fd_op)?.to_i32()?;
        let buf_scalar = this.read_scalar(buf_op)?.not_undef()?;

        // Remove the file handle to avoid borrowing issues
        this.remove_handle_and(fd, |mut handle, this| {
            // Don't use `?` to avoid returning before reinserting the handle
            let bytes = this.force_ptr(buf_scalar).and_then(|buf| {
                this.memory_mut()
                    .get_mut(buf.alloc_id)?
                    .get_bytes_mut(tcx, buf, Size::from_bytes(count))
                    .map(|buffer| handle.file.read(buffer))
            });
            // Reinsert the file handle
            this.machine.file_handler.handles.insert(fd, handle);
            this.consume_result(bytes?.map(|bytes| bytes as i64))
        })
    }

    fn write(
        &mut self,
        fd_op: OpTy<'tcx, Tag>,
        buf_op: OpTy<'tcx, Tag>,
        count_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i64> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`write` not available when isolation is enabled")
        }

        let tcx = &{ this.tcx.tcx };

        let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;
        // Writing zero bytes should not change `buf`
        if count == 0 {
            return Ok(0);
        }
        let fd = this.read_scalar(fd_op)?.to_i32()?;
        let buf = this.force_ptr(this.read_scalar(buf_op)?.not_undef()?)?;

        this.remove_handle_and(fd, |mut handle, this| {
            let bytes = this.memory().get(buf.alloc_id).and_then(|alloc| {
                alloc
                    .get_bytes(tcx, buf, Size::from_bytes(count))
                    .map(|bytes| handle.file.write(bytes).map(|bytes| bytes as i64))
            });
            this.machine.file_handler.handles.insert(fd, handle);
            this.consume_result(bytes?)
        })
    }

    fn unlink( &mut self, path_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`write` not available when isolation is enabled")
        }

        let path_bytes = this
            .memory()
            .read_c_str(this.read_scalar(path_op)?.not_undef()?)?;
        let path = std::str::from_utf8(path_bytes)
            .map_err(|_| err_unsup_format!("{:?} is not a valid utf-8 string", path_bytes))?;

        let result = remove_file(path).map(|_| 0);

        this.consume_result(result)
    }

    /// Helper function that gets a `FileHandle` immutable reference and allows to manipulate it
    /// using the `f` closure.
    ///
    /// If the `fd` file descriptor does not correspond to a file, this functions returns `Ok(-1)`
    /// and sets `Evaluator::last_error` to `libc::EBADF` (invalid file descriptor).
    ///
    /// This function uses `T: From<i32>` instead of `i32` directly because some IO related
    /// functions return different integer types (like `read`, that returns an `i64`)
    fn get_handle_and<F, T: From<i32>>(&mut self, fd: i32, f: F) -> InterpResult<'tcx, T>
    where
        F: Fn(&FileHandle) -> InterpResult<'tcx, T>,
    {
        let this = self.eval_context_mut();
        if let Some(handle) = this.machine.file_handler.handles.get(&fd) {
            f(handle)
        } else {
            let ebadf = this.eval_libc("EBADF")?;
            this.set_last_error(ebadf)?;
            Ok((-1).into())
        }
    }

    /// Helper function that removes a `FileHandle` and allows to manipulate it using the `f`
    /// closure. This function is quite useful when you need to modify a `FileHandle` but you need
    /// to modify `MiriEvalContext` at the same time, so you can modify the handle and reinsert it
    /// using `f`.
    ///
    /// If the `fd` file descriptor does not correspond to a file, this functions returns `Ok(-1)`
    /// and sets `Evaluator::last_error` to `libc::EBADF` (invalid file descriptor).
    ///
    /// This function uses `T: From<i32>` instead of `i32` directly because some IO related
    /// functions return different integer types (like `read`, that returns an `i64`)
    fn remove_handle_and<F, T: From<i32>>(&mut self, fd: i32, mut f: F) -> InterpResult<'tcx, T>
    where
        F: FnMut(FileHandle, &mut MiriEvalContext<'mir, 'tcx>) -> InterpResult<'tcx, T>,
    {
        let this = self.eval_context_mut();
        if let Some(handle) = this.machine.file_handler.handles.remove(&fd) {
            f(handle, this)
        } else {
            let ebadf = this.eval_libc("EBADF")?;
            this.set_last_error(ebadf)?;
            Ok((-1).into())
        }
    }

    /// Helper function that consumes an `std::io::Result<T>` and returns an
    /// `InterpResult<'tcx,T>::Ok` instead. It is expected that the result can be converted to an
    /// OS error using `std::io::Error::raw_os_error`.
    ///
    /// This function uses `T: From<i32>` instead of `i32` directly because some IO related
    /// functions return different integer types (like `read`, that returns an `i64`)
    fn consume_result<T: From<i32>>(
        &mut self,
        result: std::io::Result<T>,
    ) -> InterpResult<'tcx, T> {
        match result {
            Ok(ok) => Ok(ok),
            Err(e) => {
                self.eval_context_mut().consume_io_error(e)?;
                Ok((-1).into())
            }
        }
    }
}
<|endoftext|>