<commit_before>use std::iter::repeat;
use std::collections::VecDeque;
use std::collections::BinaryHeap;
use std::cmp::Ordering;

fn max(a: u32, b: u32) -> u32 { if a > b { a } else { b } }

#[derive(Clone)]
struct Edge {
    vertex: u32,
    weight: f32,
}

impl Edge {
    pub fn new(vertex_: u32, weight_: f32) -> Edge {
        Edge{vertex: vertex_, weight: weight_,}
    }
}

impl Ord for Edge {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

impl Eq for Edge {}

impl PartialOrd for Edge {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        (self.weight, self.vertex).partial_cmp(&(other.weight, other.vertex))
    }
}

impl PartialEq for Edge {
    fn eq(&self, other: &Self) -> bool {
        (self.weight, &self.vertex) == (other.weight, &other.vertex)
    }
}

struct Graph {
    nodes: Vec<Vec<Edge>>,
}

impl Graph {
    pub fn new() -> Graph { Graph{nodes: Vec::new(),} }

    pub fn add_edge(&mut self, src: u32, dst: u32, weight: f32) {
        let len = self.nodes.len();

        if (max(src, dst)) > len as u32 {
            let new_len = (max(src, dst) + 1) as usize;
            self.nodes.extend(repeat(Vec::new()).take(new_len - len))
        }
        self.nodes[src as usize].push(Edge::new(dst, weight));
    }
    pub fn bfs(&self, src: u32) {
        let mut queue: VecDeque<u32> = VecDeque::new();
        let len = self.nodes.len();
        let mut visited = vec!(false ; len);

        queue.push_front(src);

        while let Some(current) = queue.pop_back() {
            if !visited[current as usize] {
                println!("current: {}" , current);
                visited[current as usize] = true;
            } else { continue ; }

            for n in &self.nodes[current as usize] {
                let neighbor: u32 = n.vertex;
                queue.push_front(neighbor);
            }
        }
    }

    pub fn dfs(&self, src: u32) {
        let mut stack: Vec<u32> = Vec::new();
        let len = self.nodes.len() as usize;
        let mut visited = vec!(false ; len);

        stack.push(src);

        while let Some(current) = stack.pop() {
            if !visited[current as usize] {
                println!("current: {}" , current);
                visited[current as usize] = true;
            } else { continue ; }

            for n in &self.nodes[current as usize] {
                let neighbor: u32 = n.vertex;
                stack.push(neighbor);
            }
        }
    }

    pub fn dijkstra(&self, src: u32, dst: u32) {
      let mut dist: Vec<f32> = Vec::new();
      let mut prev: Vec<u32> = Vec::new();
      let mut q = BinaryHeap::new();
      const MAX_WEIGHT: f32 = std::f32::MAX;

      // init dist, prev table
      for _ in 0..self.nodes.len() {
        dist.push(MAX_WEIGHT);
        prev.push(0);
      }

      // We're at `start`, with a zero cost
      dist[src as usize] = 0.0;
      q.push(Edge::new(src, dist[src as usize]));

      while let Some(u) = q.pop() {
        // loop for all edges connected to
        for v in self.nodes[u.vertex as usize].iter() {

          let alt: f32 = dist[u.vertex as usize] + v.weight; // accumulate shortest dist from source

          // The variable alt is the length of the path from the root node to the neighbor node v
          // if it were to go through u. If this path is shorter than the current shortest path
          // recorded for v, that current path is replaced with this alt path.
          if alt < dist[v.vertex as usize] {
            dist[v.vertex as usize] = alt; // keep the shortest dist from src to v
            prev[v.vertex as usize] = u.vertex;

            q.push(Edge::new(v.vertex, dist[v.vertex as usize])); // Add unvisited v into the Q to be processed
          }
        }
      }

      let mut shortest_path: Vec<u32> = Vec::new();
      let mut curr: u32 = dst;

      shortest_path.push(curr);

      while curr != src {
        curr = prev[curr as usize];
        shortest_path.push(curr);
      }

      shortest_path.reverse();

      for v in shortest_path.iter() {
        println!("{}", v);
      }
    }
}

fn main() {
    let mut g1 = Graph::new();
    g1.add_edge(0, 1, 1.0);
    g1.add_edge(0, 2, 4.0);
    g1.add_edge(1, 0, 1.0);
    g1.add_edge(1, 2, 2.0);
    g1.add_edge(1, 3, 6.0);
    g1.add_edge(2, 0, 4.0);
    g1.add_edge(2, 1, 2.0);
    g1.add_edge(2, 3, 3.0);
    g1.add_edge(3, 1, 6.0);
    g1.add_edge(3, 2, 3.0);

    g1.bfs(3);

    println!("");

    g1.dfs(3);

    println!("");

    g1.dijkstra(0, 3);
}<commit_msg>formatted code<commit_after>use std::iter::repeat;
use std::collections::VecDeque;
use std::collections::BinaryHeap;
use std::cmp::Ordering;

fn max(a: u32, b: u32) -> u32 { if a > b { a } else { b } }

#[derive(Clone)]
struct Edge {
    vertex: u32,
    weight: f32,
}

impl Edge {
    pub fn new(vertex_: u32, weight_: f32) -> Edge {
        Edge{vertex: vertex_, weight: weight_,}
    }
}

impl Ord for Edge {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

impl Eq for Edge {}

impl PartialOrd for Edge {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        (self.weight, self.vertex).partial_cmp(&(other.weight, other.vertex))
    }
}

impl PartialEq for Edge {
    fn eq(&self, other: &Self) -> bool {
        (self.weight, &self.vertex) == (other.weight, &other.vertex)
    }
}

struct Graph {
    nodes: Vec<Vec<Edge>>,
}

impl Graph {
    pub fn new() -> Graph { Graph{nodes: Vec::new(),} }

    pub fn add_edge(&mut self, src: u32, dst: u32, weight: f32) {
        let len = self.nodes.len();

        if (max(src, dst)) > len as u32 {
            let new_len = (max(src, dst) + 1) as usize;
            self.nodes.extend(repeat(Vec::new()).take(new_len - len))
        }
        self.nodes[src as usize].push(Edge::new(dst, weight));
    }

    pub fn bfs(&self, src: u32) {
        let mut queue: VecDeque<u32> = VecDeque::new();
        let len = self.nodes.len();
        let mut visited = vec!(false ; len);

        queue.push_front(src);

        while let Some(current) = queue.pop_back() {
            if !visited[current as usize] {
                println!("current: {}" , current);
                visited[current as usize] = true;
            } else { continue ; }

            for n in &self.nodes[current as usize] {
                let neighbor: u32 = n.vertex;
                queue.push_front(neighbor);
            }
        }
    }

    pub fn dfs(&self, src: u32) {
        let mut stack: Vec<u32> = Vec::new();
        let len = self.nodes.len() as usize;
        let mut visited = vec!(false ; len);

        stack.push(src);

        while let Some(current) = stack.pop() {
            if !visited[current as usize] {
                println!("current: {}" , current);
                visited[current as usize] = true;
            } else { continue ; }

            for n in &self.nodes[current as usize] {
                let neighbor: u32 = n.vertex;
                stack.push(neighbor);
            }
        }
    }

    pub fn dijkstra(&self, src: u32, dst: u32) {
      let mut dist: Vec<f32> = Vec::new();
      let mut prev: Vec<u32> = Vec::new();
      let mut q = BinaryHeap::new();
      const MAX_WEIGHT: f32 = std::f32::MAX;

      // init dist, prev table
      for _ in 0..self.nodes.len() {
        dist.push(MAX_WEIGHT);
        prev.push(0);
      }

      // We're at `start`, with a zero cost
      dist[src as usize] = 0.0;
      q.push(Edge::new(src, dist[src as usize]));

      while let Some(u) = q.pop() {
        // loop for all edges connected to
        for v in self.nodes[u.vertex as usize].iter() {

          let alt: f32 = dist[u.vertex as usize] + v.weight; // accumulate shortest dist from source

          // The variable alt is the length of the path from the root node to the neighbor node v
          // if it were to go through u. If this path is shorter than the current shortest path
          // recorded for v, that current path is replaced with this alt path.
          if alt < dist[v.vertex as usize] {
            dist[v.vertex as usize] = alt; // keep the shortest dist from src to v
            prev[v.vertex as usize] = u.vertex;

            q.push(Edge::new(v.vertex, dist[v.vertex as usize])); // Add unvisited v into the Q to be processed
          }
        }
      }

      let mut shortest_path: Vec<u32> = Vec::new();
      let mut curr: u32 = dst;

      shortest_path.push(curr);

      while curr != src {
        curr = prev[curr as usize];
        shortest_path.push(curr);
      }

      shortest_path.reverse();

      for v in shortest_path.iter() {
        println!("{}", v);
      }
    }
}

fn main() {
    let mut g1 = Graph::new();
    g1.add_edge(0, 1, 1.0);
    g1.add_edge(0, 2, 4.0);
    g1.add_edge(1, 0, 1.0);
    g1.add_edge(1, 2, 2.0);
    g1.add_edge(1, 3, 6.0);
    g1.add_edge(2, 0, 4.0);
    g1.add_edge(2, 1, 2.0);
    g1.add_edge(2, 3, 3.0);
    g1.add_edge(3, 1, 6.0);
    g1.add_edge(3, 2, 3.0);

    g1.bfs(3);

    println!("");

    g1.dfs(3);

    println!("");

    g1.dijkstra(0, 3);
}<|endoftext|>


<commit_before>//! **UnionFind\<K\>** is a disjoint-set data structure.

use std::num;

/// **UnionFind\<K\>** is a disjoint-set data structure. It tracks set membership of *n* elements
/// indexed from *0* to *n - 1*. The scalar type is **K** which must be an unsigned integer type.
///
/// http://en.wikipedia.org/wiki/Disjoint-set_data_structure
///
/// Too awesome not to quote:
///
/// “The amortized time per operation is **O(α(n))** where **α(n)** is the
/// inverse of **f(x) = A(x, x)** with **A** being the extremely fast-growing Ackermann function.”
#[derive(Show, Clone)]
pub struct UnionFind<K> where K: num::UnsignedInt
{
    // For element at index *i*, store the index of its parent; the representative itself
    // stores its own index. This forms equivalence classes which are the disjoint sets, each
    // with a unique representative.
    parent: Vec<K>,
    // It is a balancing tree structure,
    // so the ranks are logarithmic in the size of the container -- a byte is more than enough.
    //
    // Rank is separated out both to save space and to save cache in when searching in the parent
    // vector.
    rank: Vec<u8>,
}

#[inline]
fn to_uint<K: num::UnsignedInt>(x: K) -> usize { x.to_uint().unwrap() }

#[inline]
unsafe fn get_unchecked<K>(xs: &[K], index: usize) -> &K
{
    debug_assert!(index < xs.len());
    xs.get_unchecked(index)
}

impl<K> UnionFind<K> where K: num::UnsignedInt
{
    /// Create a new **UnionFind** of **n** disjoint sets.
    pub fn new(n: usize) -> Self
    {
        let mut parent = Vec::with_capacity(n);
        let mut rank = Vec::with_capacity(n);

        for _ in range(0, n) {
            rank.push(0)
        }

        // unroll the first iteration to avoid wraparound in i for K=u8, n=256.
        let mut i: K = num::Int::zero();
        if n > 0 {
            parent.push(i);
        }
        for _ in range(1, n) {
            i = i + num::Int::one();
            parent.push(i);
        }
        UnionFind{parent: parent, rank: rank}
    }

    /// Return the representative for **x**.
    ///
    /// **Panics** if **x** is out of bounds.
    pub fn find(&self, x: K) -> K
    {
        assert!(to_uint(x) < self.parent.len());
        unsafe {
            let mut x = x;
            loop {
                // Use unchecked indexing because we can trust the internal set ids.
                let xparent = *get_unchecked(&*self.parent, to_uint(x));
                if xparent == x {
                    break
                }
                x = xparent;
            }
            x
        }
    }

    /// Return the representative for **x**.
    ///
    /// Write back the found representative, flattening the internal
    /// datastructure in the process and quicken future lookups.
    ///
    /// **Panics** if **x** is out of bounds.
    pub fn find_mut(&mut self, x: K) -> K
    {
        assert!(to_uint(x) < self.parent.len());
        unsafe {
            self.find_mut_recursive(x)
        }
    }

    unsafe fn find_mut_recursive(&mut self, x: K) -> K
    {
        let xparent = *get_unchecked(&*self.parent, to_uint(x));
        if xparent != x {
            let xrep = self.find_mut_recursive(xparent);
            let xparent = self.parent.get_unchecked_mut(to_uint(x));
            *xparent = xrep;
            *xparent
        } else {
            xparent
        }
    }

    /// Unify the two sets containing **x** and **y**.
    ///
    /// Return **false** if the sets were already the same, **true** if they were unified.
    ///
    /// **Panics** if **x** or **y** is out of bounds.
    pub fn union(&mut self, x: K, y: K) -> bool
    {
        if x == y {
            return false
        }
        let xrep = self.find_mut(x);
        let yrep = self.find_mut(y);

        if xrep == yrep {
            return false
        }

        let xrepu = to_uint(xrep);
        let yrepu = to_uint(yrep);
        let xrank = self.rank[xrepu];
        let yrank = self.rank[yrepu];

        // The rank corresponds roughly to the depth of the treeset, so put the
        // smaller set below the larger
        if xrank < yrank {
            self.parent[xrepu] = yrep;
        } else if xrank > yrank {
            self.parent[yrepu] = xrep;
        } else {
            // put y below x when equal.
            self.parent[yrepu] = xrep;
            self.rank[xrepu] += 1;
        }
        true
    }

    /// Return a vector mapping each element to its representative.
    pub fn into_labeling(mut self) -> Vec<K> where
        K: num::NumCast,
    {
        // write in the labeling of each element
        unsafe {
            for ix in (0..self.parent.len()) {
                self.find_mut_recursive(num::cast(ix).unwrap());
            }
        }
        self.parent
    }
}
<commit_msg>UnionFind: simplify into_labeling<commit_after>//! **UnionFind\<K\>** is a disjoint-set data structure.

use std::num;

/// **UnionFind\<K\>** is a disjoint-set data structure. It tracks set membership of *n* elements
/// indexed from *0* to *n - 1*. The scalar type is **K** which must be an unsigned integer type.
///
/// http://en.wikipedia.org/wiki/Disjoint-set_data_structure
///
/// Too awesome not to quote:
///
/// “The amortized time per operation is **O(α(n))** where **α(n)** is the
/// inverse of **f(x) = A(x, x)** with **A** being the extremely fast-growing Ackermann function.”
#[derive(Show, Clone)]
pub struct UnionFind<K> where K: num::UnsignedInt
{
    // For element at index *i*, store the index of its parent; the representative itself
    // stores its own index. This forms equivalence classes which are the disjoint sets, each
    // with a unique representative.
    parent: Vec<K>,
    // It is a balancing tree structure,
    // so the ranks are logarithmic in the size of the container -- a byte is more than enough.
    //
    // Rank is separated out both to save space and to save cache in when searching in the parent
    // vector.
    rank: Vec<u8>,
}

#[inline]
fn to_uint<K: num::UnsignedInt>(x: K) -> usize { x.to_uint().unwrap() }

#[inline]
unsafe fn get_unchecked<K>(xs: &[K], index: usize) -> &K
{
    debug_assert!(index < xs.len());
    xs.get_unchecked(index)
}

impl<K> UnionFind<K> where K: num::UnsignedInt
{
    /// Create a new **UnionFind** of **n** disjoint sets.
    pub fn new(n: usize) -> Self
    {
        let mut parent = Vec::with_capacity(n);
        let mut rank = Vec::with_capacity(n);

        for _ in range(0, n) {
            rank.push(0)
        }

        // unroll the first iteration to avoid wraparound in i for K=u8, n=256.
        let mut i: K = num::Int::zero();
        if n > 0 {
            parent.push(i);
        }
        for _ in range(1, n) {
            i = i + num::Int::one();
            parent.push(i);
        }
        UnionFind{parent: parent, rank: rank}
    }

    /// Return the representative for **x**.
    ///
    /// **Panics** if **x** is out of bounds.
    pub fn find(&self, x: K) -> K
    {
        assert!(to_uint(x) < self.parent.len());
        unsafe {
            let mut x = x;
            loop {
                // Use unchecked indexing because we can trust the internal set ids.
                let xparent = *get_unchecked(&*self.parent, to_uint(x));
                if xparent == x {
                    break
                }
                x = xparent;
            }
            x
        }
    }

    /// Return the representative for **x**.
    ///
    /// Write back the found representative, flattening the internal
    /// datastructure in the process and quicken future lookups.
    ///
    /// **Panics** if **x** is out of bounds.
    pub fn find_mut(&mut self, x: K) -> K
    {
        assert!(to_uint(x) < self.parent.len());
        unsafe {
            self.find_mut_recursive(x)
        }
    }

    unsafe fn find_mut_recursive(&mut self, x: K) -> K
    {
        let xparent = *get_unchecked(&*self.parent, to_uint(x));
        if xparent != x {
            let xrep = self.find_mut_recursive(xparent);
            let xparent = self.parent.get_unchecked_mut(to_uint(x));
            *xparent = xrep;
            *xparent
        } else {
            xparent
        }
    }

    /// Unify the two sets containing **x** and **y**.
    ///
    /// Return **false** if the sets were already the same, **true** if they were unified.
    ///
    /// **Panics** if **x** or **y** is out of bounds.
    pub fn union(&mut self, x: K, y: K) -> bool
    {
        if x == y {
            return false
        }
        let xrep = self.find_mut(x);
        let yrep = self.find_mut(y);

        if xrep == yrep {
            return false
        }

        let xrepu = to_uint(xrep);
        let yrepu = to_uint(yrep);
        let xrank = self.rank[xrepu];
        let yrank = self.rank[yrepu];

        // The rank corresponds roughly to the depth of the treeset, so put the
        // smaller set below the larger
        if xrank < yrank {
            self.parent[xrepu] = yrep;
        } else if xrank > yrank {
            self.parent[yrepu] = xrep;
        } else {
            // put y below x when equal.
            self.parent[yrepu] = xrep;
            self.rank[xrepu] += 1;
        }
        true
    }

    /// Return a vector mapping each element to its representative.
    pub fn into_labeling(mut self) -> Vec<K>
    {
        // write in the labeling of each element
        unsafe {
            for ix in (0..self.parent.len()) {
                let k = *get_unchecked(&self.parent[], ix);
                let xrep = self.find_mut_recursive(k);
                *self.parent.get_unchecked_mut(ix) = xrep;
            }
        }
        self.parent
    }
}
<|endoftext|>


<commit_before>use conduit::Request;
use krate::Crate;
use util::{CargoResult, internal, ChainError};
use util::{LimitErrorReader, HashingReader, read_le_u32};
use s3;
use semver;
use app::{App, RequestApp};
use std::sync::Arc;
use std::fs::{self, File};
use std::env;
use std::io;

#[derive(Clone, Debug)]
pub enum Uploader {
    /// For production usage, uploads and redirects to s3.
    /// For test usage with a proxy.
    S3 {
        bucket: s3::Bucket,
        proxy: Option<String>,
    },

    /// For development usage only: "uploads" crate files to `dist` and serves them
    /// from there as well to enable local publishing and download
    Local,

    /// For one-off scripts where creating a Config is needed, but uploading is not.
    NoOp,
}

impl Uploader {
    pub fn proxy(&self) -> Option<&str> {
        match *self {
            Uploader::S3 { ref proxy, .. } => proxy.as_ref().map(String::as_str),
            Uploader::Local | Uploader::NoOp => None,
        }
    }

    pub fn crate_location(&self, crate_name: &str, version: &str) -> Option<String> {
        match *self {
            Uploader::S3 { ref bucket, .. } => {
                Some(format!(
                    "https://{}/{}",
                    bucket.host(),
                    Uploader::crate_path(crate_name, version)
                ))
            }
            Uploader::Local => {
                Some(format!(
                    "/local_uploads/{}",
                    Uploader::crate_path(crate_name, version)
                ))
            }
            Uploader::NoOp => None,
        }
    }

    pub fn readme_location(&self, crate_name: &str, version: &str) -> Option<String> {
        match *self {
            Uploader::S3 { ref bucket, .. } => {
                Some(format!(
                    "https://{}/{}",
                    bucket.host(),
                    Uploader::readme_path(crate_name, version)
                ))
            }
            Uploader::Local => {
                Some(format!(
                    "/local_uploads/{}",
                    Uploader::readme_path(crate_name, version)
                ))
            }
            Uploader::NoOp => None,
        }
    }

    fn crate_path(name: &str, version: &str) -> String {
        // No slash in front so we can use join
        format!("crates/{}/{}-{}.crate", name, name, version)
    }

    fn readme_path(name: &str, version: &str) -> String {
        format!("readmes/{}/{}-{}.html", name, name, version)
    }

    /// Uploads a file using the configured uploader (either S3, Local or NoOp).
    /// It returns a a tuple containing the path of the uploaded file
    /// and its checksum.
    pub fn upload(
        &self,
        app: Arc<App>,
        path: &str,
        body: &mut io::Read,
        content_type: &str,
        content_length: u64,
    ) -> CargoResult<(Option<String>, Vec<u8>)> {
        match *self {
            Uploader::S3 { ref bucket, .. } => {
                let mut handle = app.handle();
                let (response, cksum) = {
                    let mut body = HashingReader::new(body);
                    let mut response = Vec::new();
                    {
                        let mut s3req =
                            bucket.put(&mut handle, &path, &mut body, content_type, content_length);
                        s3req
                            .write_function(|data| {
                                response.extend(data);
                                Ok(data.len())
                            })
                            .unwrap();
                        s3req.perform().chain_error(|| {
                            internal(&format_args!("failed to upload to S3: `{}`", path))
                        })?;
                    }
                    (response, body.finalize())
                };
                if handle.response_code().unwrap() != 200 {
                    let response = String::from_utf8_lossy(&response);
                    return Err(internal(&format_args!(
                        "failed to get a 200 response from S3: {}",
                        response
                    )));
                }
                Ok((Some(String::from(path)), cksum))
            }
            Uploader::Local => {
                let filename = env::current_dir()
                    .unwrap()
                    .join("dist")
                    .join("local_uploads")
                    .join(path);
                let dir = filename.parent().unwrap();
                fs::create_dir_all(dir)?;
                let mut file = File::create(&filename)?;
                let mut body = HashingReader::new(body);
                io::copy(&mut body, &mut file)?;
                Ok((filename.to_str().map(String::from), body.finalize()))
            }
            Uploader::NoOp => Ok((None, vec![])),
        }
    }

    /// Uploads a crate and its readme. Returns the checksum of the uploaded crate
    /// file, and bombs for the uploaded crate and the uploaded readme.
    pub fn upload_crate(
        &self,
        req: &mut Request,
        krate: &Crate,
        readme: Option<String>,
        max: u64,
        vers: &semver::Version,
    ) -> CargoResult<(Vec<u8>, Bomb, Bomb)> {
        let app = req.app().clone();
        let (crate_path, checksum) = {
            let path = format!("/{}", Uploader::crate_path(&krate.name, &vers.to_string()));
            let length = read_le_u32(req.body())?;
            let mut body = LimitErrorReader::new(req.body(), max);
            self.upload(
                app.clone(),
                &path,
                &mut body,
                "application/x-tar",
                length as u64,
            )?
        };
        let crate_bomb = Bomb {
            app: app.clone(),
            path: crate_path,
        };
        let (readme_path, _) = if let Some(rendered) = readme {
            let path = format!("/{}", Uploader::readme_path(&krate.name, &vers.to_string()));
            let length = rendered.len();
            let mut body = io::Cursor::new(rendered.into_bytes());
            self.upload(
                app.clone(),
                &path,
                &mut body,
                "text/html",
                length as u64,
            )?
        } else {
            (None, vec![])
        };
        Ok((
            checksum,
            crate_bomb,
            Bomb {
                app: app.clone(),
                path: readme_path,
            },
        ))
    }

    fn delete(&self, app: Arc<App>, path: &str) -> CargoResult<()> {
        match *self {
            Uploader::S3 { ref bucket, .. } => {
                let mut handle = app.handle();
                bucket.delete(&mut handle, path).perform()?;
                Ok(())
            }
            Uploader::Local => {
                fs::remove_file(path)?;
                Ok(())
            }
            Uploader::NoOp => Ok(()),
        }
    }
}

pub struct Bomb {
    app: Arc<App>,
    pub path: Option<String>,
}

impl Drop for Bomb {
    fn drop(&mut self) {
        if let Some(ref path) = self.path {
            if let Err(e) = self.app.config.uploader.delete(self.app.clone(), path) {
                println!("unable to delete {}, {:?}", path, e);
            }
        }
    }
}
<commit_msg>Remove needless borrow<commit_after>use conduit::Request;
use krate::Crate;
use util::{CargoResult, internal, ChainError};
use util::{LimitErrorReader, HashingReader, read_le_u32};
use s3;
use semver;
use app::{App, RequestApp};
use std::sync::Arc;
use std::fs::{self, File};
use std::env;
use std::io;

#[derive(Clone, Debug)]
pub enum Uploader {
    /// For production usage, uploads and redirects to s3.
    /// For test usage with a proxy.
    S3 {
        bucket: s3::Bucket,
        proxy: Option<String>,
    },

    /// For development usage only: "uploads" crate files to `dist` and serves them
    /// from there as well to enable local publishing and download
    Local,

    /// For one-off scripts where creating a Config is needed, but uploading is not.
    NoOp,
}

impl Uploader {
    pub fn proxy(&self) -> Option<&str> {
        match *self {
            Uploader::S3 { ref proxy, .. } => proxy.as_ref().map(String::as_str),
            Uploader::Local | Uploader::NoOp => None,
        }
    }

    pub fn crate_location(&self, crate_name: &str, version: &str) -> Option<String> {
        match *self {
            Uploader::S3 { ref bucket, .. } => {
                Some(format!(
                    "https://{}/{}",
                    bucket.host(),
                    Uploader::crate_path(crate_name, version)
                ))
            }
            Uploader::Local => {
                Some(format!(
                    "/local_uploads/{}",
                    Uploader::crate_path(crate_name, version)
                ))
            }
            Uploader::NoOp => None,
        }
    }

    pub fn readme_location(&self, crate_name: &str, version: &str) -> Option<String> {
        match *self {
            Uploader::S3 { ref bucket, .. } => {
                Some(format!(
                    "https://{}/{}",
                    bucket.host(),
                    Uploader::readme_path(crate_name, version)
                ))
            }
            Uploader::Local => {
                Some(format!(
                    "/local_uploads/{}",
                    Uploader::readme_path(crate_name, version)
                ))
            }
            Uploader::NoOp => None,
        }
    }

    fn crate_path(name: &str, version: &str) -> String {
        // No slash in front so we can use join
        format!("crates/{}/{}-{}.crate", name, name, version)
    }

    fn readme_path(name: &str, version: &str) -> String {
        format!("readmes/{}/{}-{}.html", name, name, version)
    }

    /// Uploads a file using the configured uploader (either S3, Local or NoOp).
    /// It returns a a tuple containing the path of the uploaded file
    /// and its checksum.
    pub fn upload(
        &self,
        app: Arc<App>,
        path: &str,
        body: &mut io::Read,
        content_type: &str,
        content_length: u64,
    ) -> CargoResult<(Option<String>, Vec<u8>)> {
        match *self {
            Uploader::S3 { ref bucket, .. } => {
                let mut handle = app.handle();
                let (response, cksum) = {
                    let mut body = HashingReader::new(body);
                    let mut response = Vec::new();
                    {
                        let mut s3req =
                            bucket.put(&mut handle, path, &mut body, content_type, content_length);
                        s3req
                            .write_function(|data| {
                                response.extend(data);
                                Ok(data.len())
                            })
                            .unwrap();
                        s3req.perform().chain_error(|| {
                            internal(&format_args!("failed to upload to S3: `{}`", path))
                        })?;
                    }
                    (response, body.finalize())
                };
                if handle.response_code().unwrap() != 200 {
                    let response = String::from_utf8_lossy(&response);
                    return Err(internal(&format_args!(
                        "failed to get a 200 response from S3: {}",
                        response
                    )));
                }
                Ok((Some(String::from(path)), cksum))
            }
            Uploader::Local => {
                let filename = env::current_dir()
                    .unwrap()
                    .join("dist")
                    .join("local_uploads")
                    .join(path);
                let dir = filename.parent().unwrap();
                fs::create_dir_all(dir)?;
                let mut file = File::create(&filename)?;
                let mut body = HashingReader::new(body);
                io::copy(&mut body, &mut file)?;
                Ok((filename.to_str().map(String::from), body.finalize()))
            }
            Uploader::NoOp => Ok((None, vec![])),
        }
    }

    /// Uploads a crate and its readme. Returns the checksum of the uploaded crate
    /// file, and bombs for the uploaded crate and the uploaded readme.
    pub fn upload_crate(
        &self,
        req: &mut Request,
        krate: &Crate,
        readme: Option<String>,
        max: u64,
        vers: &semver::Version,
    ) -> CargoResult<(Vec<u8>, Bomb, Bomb)> {
        let app = req.app().clone();
        let (crate_path, checksum) = {
            let path = format!("/{}", Uploader::crate_path(&krate.name, &vers.to_string()));
            let length = read_le_u32(req.body())?;
            let mut body = LimitErrorReader::new(req.body(), max);
            self.upload(
                app.clone(),
                &path,
                &mut body,
                "application/x-tar",
                length as u64,
            )?
        };
        let crate_bomb = Bomb {
            app: app.clone(),
            path: crate_path,
        };
        let (readme_path, _) = if let Some(rendered) = readme {
            let path = format!("/{}", Uploader::readme_path(&krate.name, &vers.to_string()));
            let length = rendered.len();
            let mut body = io::Cursor::new(rendered.into_bytes());
            self.upload(
                app.clone(),
                &path,
                &mut body,
                "text/html",
                length as u64,
            )?
        } else {
            (None, vec![])
        };
        Ok((
            checksum,
            crate_bomb,
            Bomb {
                app: app.clone(),
                path: readme_path,
            },
        ))
    }

    fn delete(&self, app: Arc<App>, path: &str) -> CargoResult<()> {
        match *self {
            Uploader::S3 { ref bucket, .. } => {
                let mut handle = app.handle();
                bucket.delete(&mut handle, path).perform()?;
                Ok(())
            }
            Uploader::Local => {
                fs::remove_file(path)?;
                Ok(())
            }
            Uploader::NoOp => Ok(()),
        }
    }
}

pub struct Bomb {
    app: Arc<App>,
    pub path: Option<String>,
}

impl Drop for Bomb {
    fn drop(&mut self) {
        if let Some(ref path) = self.path {
            if let Err(e) = self.app.config.uploader.delete(self.app.clone(), path) {
                println!("unable to delete {}, {:?}", path, e);
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::io::{stdout, Write};

use super::peg::{Pipeline, Job};
use super::input_editor::readln;
use super::status::{SUCCESS, FAILURE};

pub struct Variables {
    variables: BTreeMap<String, String>,
}

impl Variables {
    pub fn new() -> Variables {
        Variables { variables: BTreeMap::new() }
    }

    pub fn read<I: IntoIterator>(&mut self, args: I) -> i32
        where I::Item: AsRef<str>
    {
        let mut out = stdout();
        for arg in args.into_iter().skip(1) {
            print!("{}=", arg.as_ref().trim());
            if let Err(message) = out.flush() {
                println!("{}: Failed to flush stdout", message);
                return FAILURE;
            }
            if let Some(value) = readln() {
                self.set_var(arg.as_ref(), value.trim());
            }
        }
        SUCCESS
    }

    pub fn let_<I: IntoIterator>(&mut self, args: I) -> i32
        where I::Item: AsRef<str>
    {
        let args = args.into_iter();
        let string: String = args.skip(1).fold(String::new(), |string, x| string + x.as_ref());
        let mut split = string.split('=');
        match (split.next().and_then(|x| if x == "" { None } else { Some(x) }), split.next()) {
            (Some(key), Some(value)) => {
                self.variables.insert(key.to_string(), value.to_string());
            },
            (Some(key), None) => {
                self.variables.remove(key);
            },
            _ => {
                for (key, value) in self.variables.iter() {
                    println!("{}={}", key, value);
                }
            }
        }
        SUCCESS
    }

    pub fn set_var(&mut self, name: &str, value: &str) {
        if !name.is_empty() {
            if value.is_empty() {
                self.variables.remove(&name.to_string());
            } else {
                self.variables.insert(name.to_string(), value.to_string());
            }
        }
    }

    pub fn expand_pipeline(&self, pipeline: &Pipeline) -> Pipeline {
        // TODO don't copy everything
        Pipeline::new(pipeline.jobs.iter().map(|job| {self.expand_job(job)}).collect())
    }

    pub fn expand_job(&self, job: &Job) -> Job {
        // TODO don't copy everything
        Job::from_vec_string(job.args
                                .iter()
                                .map(|original: &String| self.expand_string(&original).to_string())
                                .collect(),
                             job.background)
    }

    fn replace_substring(string: &mut String, start: usize, end: usize, replacement: &str) {
        let string_start = string.chars().take(start).collect::<String>();
        let string_end = string.chars().skip(end+1).collect::<String>();
        *string = string_start + replacement + &string_end;
    }

    #[inline]
    pub fn expand_string<'a>(&'a self, original: &'a str) -> String {
        let mut new = original.to_owned();
        let mut replacements: Vec<(usize, usize, String)> = vec![];
        for (n, _) in original.match_indices("$") {
            if n > 0 {
                if let Some(c) = original.chars().nth(n-1) {
                    if c == '\\' {
                        continue;
                    }
                }
            }
            let mut var_name = "".to_owned();
            for (i, c) in original.char_indices().skip(n+1) { // skip the dollar sign
                if c.is_alphanumeric() || c == '_' {
                    var_name.push(c);
                    if i == original.len() - 1 {
                        replacements.push((n, i, var_name.clone()));
                        break;
                    }
                } else {
                    replacements.push((n, i-1, var_name.clone()));
                    break;
                }
            }
        }

        for &(start, end, ref var_name) in replacements.iter().rev() {
            let value: &str = match self.variables.get(var_name) {
                Some(v) => &v,
                None => ""
            };
            Variables::replace_substring(&mut new, start, end, value);
        }
        new.clone()
    }
}

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

    #[test]
    fn undefined_variable_expands_to_empty_string() {
        let variables = Variables::new();
        let expanded = variables.expand_string("$FOO");
        assert_eq!("", &expanded);
    }

    #[test]
    fn let_and_expand_a_variable() {
        let mut variables = Variables::new();
        variables.let_(vec!["let", "FOO", "=", "BAR"]);
        let expanded = variables.expand_string("$FOO");
        assert_eq!("BAR", &expanded);
    }

    #[test]
    fn set_var_and_expand_a_variable() {
        let mut variables = Variables::new();
        variables.set_var("FOO", "BAR");
        let expanded = variables.expand_string("$FOO");
        assert_eq!("BAR", &expanded);
    }

    #[test]
    fn remove_a_variable_with_let() {
        let mut variables = Variables::new();
        variables.let_(vec!["let", "FOO", "=", "BAR"]);
        variables.let_(vec!["let", "FOO"]);
        let expanded = variables.expand_string("$FOO");
        assert_eq!("", &expanded);
    }

    #[test]
    fn expand_several_variables() {
        let mut variables = Variables::new();
        variables.let_(vec!["let", "FOO", "=", "BAR"]);
        variables.let_(vec!["let", "X", "=", "Y"]);
        let expanded = variables.expand_string("variables: $FOO $X");
        assert_eq!("variables: BAR Y", &expanded);
    }

    #[test]
    fn replace_substring() {
        let mut string = "variable: $FOO".to_owned();
        Variables::replace_substring(&mut string, 10, 13, "BAR");
        assert_eq!("variable: BAR", string);
    }

    #[test]
    fn escape_with_backslash() {
        let mut variables = Variables::new();
        let expanded = variables.expand_string("\\$FOO");
        assert_eq!("\\$FOO", &expanded);
    }
}
<commit_msg>Fix #125<commit_after>use std::collections::BTreeMap;
use std::io::{stdout, Write};

use super::peg::{Pipeline, Job};
use super::input_editor::readln;
use super::status::{SUCCESS, FAILURE};

pub struct Variables {
    variables: BTreeMap<String, String>,
}

impl Variables {
    pub fn new() -> Variables {
        Variables { variables: BTreeMap::new() }
    }

    pub fn read<I: IntoIterator>(&mut self, args: I) -> i32
        where I::Item: AsRef<str>
    {
        let mut out = stdout();
        for arg in args.into_iter().skip(1) {
            print!("{}=", arg.as_ref().trim());
            if let Err(message) = out.flush() {
                println!("{}: Failed to flush stdout", message);
                return FAILURE;
            }
            if let Some(value) = readln() {
                self.set_var(arg.as_ref(), value.trim());
            }
        }
        SUCCESS
    }

    pub fn let_<I: IntoIterator>(&mut self, args: I) -> i32
        where I::Item: AsRef<str>
    {
        let args = args.into_iter();
        let string: String = args.skip(1).fold(String::new(), |string, x| string + x.as_ref());
        let mut split = string.split('=');
        match (split.next().and_then(|x| if x == "" { None } else { Some(x) }), split.next()) {
            (Some(key), Some(value)) => {
                self.variables.insert(key.to_string(), value.to_string());
            },
            (Some(key), None) => {
                self.variables.remove(key);
            },
            _ => {
                for (key, value) in self.variables.iter() {
                    println!("{}={}", key, value);
                }
            }
        }
        SUCCESS
    }

    pub fn set_var(&mut self, name: &str, value: &str) {
        if !name.is_empty() {
            if value.is_empty() {
                self.variables.remove(&name.to_string());
            } else {
                self.variables.insert(name.to_string(), value.to_string());
            }
        }
    }

    pub fn expand_pipeline(&self, pipeline: &Pipeline) -> Pipeline {
        // TODO don't copy everything
        Pipeline::new(pipeline.jobs.iter().map(|job| {self.expand_job(job)}).collect())
    }

    pub fn expand_job(&self, job: &Job) -> Job {
        // TODO don't copy everything
        Job::from_vec_string(job.args
                                .iter()
                                .map(|original: &String| self.expand_string(&original).to_string())
                                .collect(),
                             job.background)
    }

    fn replace_substring(string: &mut String, start: usize, end: usize, replacement: &str) {
        let string_start = string.chars().take(start).collect::<String>();
        let string_end = string.chars().skip(end+1).collect::<String>();
        *string = string_start + replacement + &string_end;
    }

    #[inline]
    pub fn expand_string<'a>(&'a self, original: &'a str) -> String {
        let mut new = original.to_owned();
        let mut replacements: Vec<(usize, usize, String)> = vec![];
        for (n, _) in original.match_indices("$") {
            if n > 0 {
                if let Some(c) = original.chars().nth(n-1) {
                    if c == '\\' {
                        continue;
                    }
                }
            }
            let mut var_name = "".to_owned();
            for (i, c) in original.char_indices().skip(n+1) { // skip the dollar sign
                if !c.is_whitespace() {
                    var_name.push(c);
                    if i == original.len() - 1 {
                        replacements.push((n, i, var_name.clone()));
                        break;
                    }
                } else {
                    replacements.push((n, i-1, var_name.clone()));
                    break;
                }
            }
        }

        for &(start, end, ref var_name) in replacements.iter().rev() {
            let value: &str = match self.variables.get(var_name) {
                Some(v) => &v,
                None => ""
            };
            Variables::replace_substring(&mut new, start, end, value);
        }
        new.clone()
    }
}

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

    #[test]
    fn undefined_variable_expands_to_empty_string() {
        let variables = Variables::new();
        let expanded = variables.expand_string("$FOO");
        assert_eq!("", &expanded);
    }

    #[test]
    fn let_and_expand_a_variable() {
        let mut variables = Variables::new();
        variables.let_(vec!["let", "FOO", "=", "BAR"]);
        let expanded = variables.expand_string("$FOO");
        assert_eq!("BAR", &expanded);
    }

    #[test]
    fn set_var_and_expand_a_variable() {
        let mut variables = Variables::new();
        variables.set_var("FOO", "BAR");
        let expanded = variables.expand_string("$FOO");
        assert_eq!("BAR", &expanded);
    }

    #[test]
    fn remove_a_variable_with_let() {
        let mut variables = Variables::new();
        variables.let_(vec!["let", "FOO", "=", "BAR"]);
        variables.let_(vec!["let", "FOO"]);
        let expanded = variables.expand_string("$FOO");
        assert_eq!("", &expanded);
    }

    #[test]
    fn expand_several_variables() {
        let mut variables = Variables::new();
        variables.let_(vec!["let", "FOO", "=", "BAR"]);
        variables.let_(vec!["let", "X", "=", "Y"]);
        let expanded = variables.expand_string("variables: $FOO $X");
        assert_eq!("variables: BAR Y", &expanded);
    }

    #[test]
    fn replace_substring() {
        let mut string = "variable: $FOO".to_owned();
        Variables::replace_substring(&mut string, 10, 13, "BAR");
        assert_eq!("variable: BAR", string);
    }

    #[test]
    fn escape_with_backslash() {
        let mut variables = Variables::new();
        let expanded = variables.expand_string("\\$FOO");
        assert_eq!("\\$FOO", &expanded);
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate cell_gc;
extern crate lisp;
extern crate test;

use lisp::parse;

macro_rules! bench {
    ( $filename:ident ) => {
        #[bench]
        fn $filename(b: &mut test::Bencher) {
            run_benchmark(
                b,
                include_str!(
                    concat!(env!("CARGO_MANIFEST_DIR"),
                            "/benches/",
                            stringify!($filename),
                            ".scm")
                ),
            );
        }
    }
}

fn run_benchmark(b: &mut test::Bencher, code: &str) {
    b.iter(|| {
        let mut heap = cell_gc::GcHeap::new();
        heap.enter(|hs| {
            let env = lisp::toplevel::default_env(hs);
            let exprs = parse::parse(hs, code).expect("should parse source OK");
            for expr in exprs {
                lisp::toplevel::eval(hs, &env, expr).expect("should eval OK");
            }
        });
    });
}

bench!(allocate_no_garbage);
bench!(allocate_all_garbage);
bench!(nboyer);
<commit_msg>Disable the nboyer bench, since it takes too long for #[bench]<commit_after>#![feature(test)]

extern crate cell_gc;
extern crate lisp;
extern crate test;

use lisp::parse;

macro_rules! bench {
    ( $filename:ident ) => {
        #[bench]
        fn $filename(b: &mut test::Bencher) {
            run_benchmark(
                b,
                include_str!(
                    concat!(env!("CARGO_MANIFEST_DIR"),
                            "/benches/",
                            stringify!($filename),
                            ".scm")
                ),
            );
        }
    }
}

fn run_benchmark(b: &mut test::Bencher, code: &str) {
    b.iter(|| {
        let mut heap = cell_gc::GcHeap::new();
        heap.enter(|hs| {
            let env = lisp::toplevel::default_env(hs);
            let exprs = parse::parse(hs, code).expect("should parse source OK");
            for expr in exprs {
                lisp::toplevel::eval(hs, &env, expr).expect("should eval OK");
            }
        });
    });
}

bench!(allocate_no_garbage);
bench!(allocate_all_garbage);

// This takes too long for a #[bench]
// bench!(nboyer);
<|endoftext|>


<commit_before>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;

use piston::window::WindowSettings;
use piston::event_loop::*;
use piston::input::*;
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{ GlGraphics, OpenGL };

type Triangle = [[f64; 2]; 3];

struct App {
    gl: GlGraphics,
    triangles: Vec<Triangle>,
    index: usize,
}

impl App {
    fn render(&mut self, args: &RenderArgs) {
        use graphics::*;

        const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
        const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

        let i = self.index;
        let triangle = self.triangles[i];

        self.gl.draw(args.viewport(), |c, gl| {
            if i == 0 {
                clear(WHITE, gl);
            }

            let transform = c.transform.trans(0.0, 0.0);

            polygon(BLACK, &triangle, transform, gl);
        });
    }

    fn update(&mut self, args: &UpdateArgs) {
        if (self.index as i32) + 1 >= self.triangles.len() as i32 {
            self.index = 0
        } else {
            self.index += 1;
        }
    }
}

fn sub_triangles(v: &Triangle) -> [Triangle; 4] {
    let (a, b, c) = (v[0], v[1], v[2]); // Vector destructuring is not yet stable in Rust 1.3.0.
    let (sax, say, sbx, sby, scx, scy) = (
            a[0] + ((b[0] - a[0]) / 2.0),
            a[1],
            b[0] - ((b[0] - c[0]) / 2.0),
            b[1] - ((b[1] - c[1]) / 2.0),
            a[0] + ((c[0] - a[0]) / 2.0),
            a[1] - ((a[1] - c[1]) / 2.0));

    [[[sax, say], [sbx, sby], [scx, scy]],
     [[a[0], a[1]], [sax, say], [scx, scy]],
     [[sax, say], [b[0], b[1]], [sbx, sby]],
     [[scx, scy], [sbx, sby], [c[0], c[1]]]]
}

fn sierpinski(depth: i32, vertices: Triangle) -> Vec<Triangle> {
    let mut triangles = vec![];

    match depth {
        0 => triangles,
        d => {
            let sub_tris = sub_triangles(&vertices);

            triangles.push(sub_tris[0]);

            for sub_tri in &sub_tris[1..] {
                for t in sierpinski(d - 1, *sub_tri) {
                    triangles.push(t);
                }
            }

            triangles
        },
    }
}

fn main() {
    const FPS: u64 = 60;
    let opengl = OpenGL::V3_2;
    let window: Window = WindowSettings::new(
        "Sierpinski-Triangle",
        [1000, 800])
        .opengl(opengl)
        .exit_on_esc(true)
        .build()
        .unwrap();

    let triangles = sierpinski(8, [[50.0, 750.0], [950.0, 750.0], [500.0, 50.0]]);
    let mut app = App{gl: GlGraphics::new(opengl), triangles: triangles, index: 0};

    for e in window.events().max_fps(FPS).ups(FPS) {
        if let Some(r) = e.render_args() {
            app.render(&r);
        }

        if let Some(u) = e.update_args() {
            app.update(&u);
        }

    }
}
<commit_msg>Remove warning<commit_after>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;

use piston::window::WindowSettings;
use piston::event_loop::*;
use piston::input::*;
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{ GlGraphics, OpenGL };

type Triangle = [[f64; 2]; 3];

struct App {
    gl: GlGraphics,
    triangles: Vec<Triangle>,
    index: usize,
}

impl App {
    fn render(&mut self, args: &RenderArgs) {
        use graphics::*;

        const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
        const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

        let i = self.index;
        let triangle = self.triangles[i];

        self.gl.draw(args.viewport(), |c, gl| {
            if i == 0 {
                clear(WHITE, gl);
            }

            let transform = c.transform.trans(0.0, 0.0);

            polygon(BLACK, &triangle, transform, gl);
        });
    }

    fn update(&mut self, _args: &UpdateArgs) {
        if (self.index as i32) + 1 >= self.triangles.len() as i32 {
            self.index = 0
        } else {
            self.index += 1;
        }
    }
}

fn sub_triangles(v: &Triangle) -> [Triangle; 4] {
    let (a, b, c) = (v[0], v[1], v[2]); // Vector destructuring is not yet stable in Rust 1.3.0.
    let (sax, say, sbx, sby, scx, scy) = (
            a[0] + ((b[0] - a[0]) / 2.0),
            a[1],
            b[0] - ((b[0] - c[0]) / 2.0),
            b[1] - ((b[1] - c[1]) / 2.0),
            a[0] + ((c[0] - a[0]) / 2.0),
            a[1] - ((a[1] - c[1]) / 2.0));

    [[[sax, say], [sbx, sby], [scx, scy]],
     [[a[0], a[1]], [sax, say], [scx, scy]],
     [[sax, say], [b[0], b[1]], [sbx, sby]],
     [[scx, scy], [sbx, sby], [c[0], c[1]]]]
}

fn sierpinski(depth: i32, vertices: Triangle) -> Vec<Triangle> {
    let mut triangles = vec![];

    match depth {
        0 => triangles,
        d => {
            let sub_tris = sub_triangles(&vertices);

            triangles.push(sub_tris[0]);

            for sub_tri in &sub_tris[1..] {
                for t in sierpinski(d - 1, *sub_tri) {
                    triangles.push(t);
                }
            }

            triangles
        },
    }
}

fn main() {
    const FPS: u64 = 60;
    let opengl = OpenGL::V3_2;
    let window: Window = WindowSettings::new(
        "Sierpinski-Triangle",
        [1000, 800])
        .opengl(opengl)
        .exit_on_esc(true)
        .build()
        .unwrap();

    let triangles = sierpinski(8, [[50.0, 750.0], [950.0, 750.0], [500.0, 50.0]]);
    let mut app = App{gl: GlGraphics::new(opengl), triangles: triangles, index: 0};

    for e in window.events().max_fps(FPS).ups(FPS) {
        if let Some(r) = e.render_args() {
            app.render(&r);
        }

        if let Some(u) = e.update_args() {
            app.update(&u);
        }

    }
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]
extern crate string_telephone;

use string_telephone::{ConnectionConfig, ClientConnectionConfig, Client, Packet};

use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::io::net::udp::UdpSocket;
use std::time::duration::Duration;

fn deserializer(message: &Vec<u8>) -> Option<Vec<u8>> {
    Some(message.clone())
}

fn serializer(packet: &Vec<u8>) -> Vec<u8> {
    packet.clone()
}

fn generate_settings(port: u16, protocol_id: u32) -> (SocketAddr, SocketAddr, ConnectionConfig<Vec<u8>>, ClientConnectionConfig) {
    let my_addr = SocketAddr{ ip: Ipv4Addr(0, 0, 0, 0), port: 0 };
    let target_addr = SocketAddr{ ip: Ipv4Addr(127, 0, 0, 1), port: port };
    let settings = ConnectionConfig::new(protocol_id, 10, deserializer, serializer);
    let client_settings = ClientConnectionConfig::new(1, Duration::seconds(1));
    (my_addr, target_addr, settings, client_settings)
}

fn get_message(socket: &mut UdpSocket) -> (Vec<u8>, SocketAddr) {
    let mut buf = [0, ..255];
    match socket.recv_from(buf) {
        Ok((amt, src)) => (buf.slice_to(amt).to_owned(), src),
        Err(e) => fail!("Socket didn't get a message")
    }
}

macro_rules! with_bound_socket(
    ($socket:ident, ($variable:ident)$code:block) => (
        spawn(proc() {
            match UdpSocket::bind($socket) {
                Ok(mut $variable) => $code,
                Err(e) => fail!(e)
            }
        });
    )
)

/**
 * Test when there isn't a backend to connect to
 * Connect should return an IOResult stating we can't get there
 */
#[test]
fn connection_ignored() {
    let port = 65000;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(_) => fail!("Reported connected when there is no server!"),
        Err(e) => {
            assert!(e.desc == "Failed to connect")
        }
    };
}

/**
 * Test a normal connection where the backend replies with an accept
 */
#[test]
fn standard_connection() {

    let port = 65001;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(1000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(client) => {
            //Success!
        },
        Err(e) => fail!(e)
    };
}

/**
 * If the server gives us back a different protocol id, we shouldn't accept it
 */
#[test]
fn connection_different_protocol_id() {
    let port = 65002;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(1000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(122).serialize().unwrap()[], src);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(_) => fail!("Connected to a server with a different protocol ID!"),
        Err(e) => {
            assert!(e.desc == "Failed to connect")
        }
    };
}

/**
 * If the server specifically rejects us, we should give up
 */
#[test]
fn connection_rejected() {
    let port = 65003;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(1000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::reject(121).serialize().unwrap()[], src);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(_) => fail!("Connected to a server that rejected us!"),
        Err(e) => {
            assert!(e.desc == "Failed to connect")
        }
    };
}

/**
 * We should be able to specify how many retries we want
 */
#[test]
fn different_retry_count() {
    let port = 65004;
    let (my_addr, target_addr, settings, mut client_settings) = generate_settings(port, 121);
    client_settings.max_connect_retries = 3;

    let (tx, rx) = channel();
    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(10000));
        let mut attempts = 0u8;
        while attempts < 3 {
            get_message(&mut socket);
            attempts += 1;
        }

        tx.send(attempts);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(_) => (),
        Err(e) => ()
    };

    assert!(rx.recv() == 3);
}

//TODO: Find a sensible way of testing timeout lengths

#[test]
fn empty_polling() {
    unimplemented!();
}

#[test]
fn single_item_polling() {
    unimplemented!();
}

#[test]
fn multiple_item_polling() {
    unimplemented!();
}

#[test]
fn disconnection() {
    unimplemented!();
}

#[test]
fn timeout() {
    unimplemented!();
}

#[test]
fn send_correct_handshake() {
    unimplemented!();
}

#[test]
fn send_data() {
    unimplemented!();
}
<commit_msg>Test for empty polling<commit_after>#![feature(macro_rules)]
extern crate string_telephone;

use string_telephone::{ConnectionConfig, ClientConnectionConfig, Client, Packet, PollEmpty};

use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::io::net::udp::UdpSocket;
use std::time::duration::Duration;

fn deserializer(message: &Vec<u8>) -> Option<Vec<u8>> {
    Some(message.clone())
}

fn serializer(packet: &Vec<u8>) -> Vec<u8> {
    packet.clone()
}

fn generate_settings(port: u16, protocol_id: u32) -> (SocketAddr, SocketAddr, ConnectionConfig<Vec<u8>>, ClientConnectionConfig) {
    let my_addr = SocketAddr{ ip: Ipv4Addr(0, 0, 0, 0), port: 0 };
    let target_addr = SocketAddr{ ip: Ipv4Addr(127, 0, 0, 1), port: port };
    let settings = ConnectionConfig::new(protocol_id, 10, deserializer, serializer);
    let client_settings = ClientConnectionConfig::new(1, Duration::seconds(1));
    (my_addr, target_addr, settings, client_settings)
}

fn get_message(socket: &mut UdpSocket) -> (Vec<u8>, SocketAddr) {
    let mut buf = [0, ..255];
    match socket.recv_from(buf) {
        Ok((amt, src)) => (buf.slice_to(amt).to_owned(), src),
        Err(e) => fail!("Socket didn't get a message")
    }
}

macro_rules! with_bound_socket(
    ($socket:ident, ($variable:ident)$code:block) => (
        spawn(proc() {
            match UdpSocket::bind($socket) {
                Ok(mut $variable) => $code,
                Err(e) => fail!(e)
            }
        });
    )
)

/**
 * Test when there isn't a backend to connect to
 * Connect should return an IOResult stating we can't get there
 */
#[test]
fn connection_ignored() {
    let port = 65000;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(_) => fail!("Reported connected when there is no server!"),
        Err(e) => {
            assert!(e.desc == "Failed to connect")
        }
    };
}

/**
 * Test a normal connection where the backend replies with an accept
 */
#[test]
fn standard_connection() {

    let port = 65001;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(1000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(client) => {
            //Success!
        },
        Err(e) => fail!(e)
    };
}

/**
 * If the server gives us back a different protocol id, we shouldn't accept it
 */
#[test]
fn connection_different_protocol_id() {
    let port = 65002;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(1000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(122).serialize().unwrap()[], src);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(_) => fail!("Connected to a server with a different protocol ID!"),
        Err(e) => {
            assert!(e.desc == "Failed to connect")
        }
    };
}

/**
 * If the server specifically rejects us, we should give up
 */
#[test]
fn connection_rejected() {
    let port = 65003;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(1000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::reject(121).serialize().unwrap()[], src);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(_) => fail!("Connected to a server that rejected us!"),
        Err(e) => {
            assert!(e.desc == "Failed to connect")
        }
    };
}

/**
 * We should be able to specify how many retries we want
 */
#[test]
fn different_retry_count() {
    let port = 65004;
    let (my_addr, target_addr, settings, mut client_settings) = generate_settings(port, 121);
    client_settings.max_connect_retries = 3;

    let (tx, rx) = channel();
    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(10000));
        let mut attempts = 0u8;
        while attempts < 3 {
            get_message(&mut socket);
            attempts += 1;
        }

        tx.send(attempts);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(_) => (),
        Err(e) => ()
    };

    assert!(rx.recv() == 3);
}

//TODO: Find a sensible way of testing timeout lengths

/**
 * We should instantly return when polling and there's no data available
 */
#[test]
fn empty_polling() {
    let port = 65005;
    let (my_addr, target_addr, settings, mut client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(1000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(mut client) => {
            assert!(match(client.poll()) { Err(PollEmpty) => true, _ => false});
        },
        Err(e) => fail!(e)
    };
}

#[test]
fn single_item_polling() {
    unimplemented!();
}

#[test]
fn multiple_item_polling() {
    unimplemented!();
}

#[test]
fn disconnection() {
    unimplemented!();
}

#[test]
fn timeout() {
    unimplemented!();
}

#[test]
fn send_correct_handshake() {
    unimplemented!();
}

#[test]
fn send_data() {
    unimplemented!();
}
<|endoftext|>


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

fn copy_rect_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.copy_rect_to_canvas",
        name: "copy_rect",
        inbound_edges: EdgesIn::OneInputOneCanvas,
        description: "Copy Rect",
        fn_estimate: Some(NodeDefHelpers::copy_frame_est_from_first_canvas),
        fn_execute: Some({

            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {

                if let s::Node::CopyRectToCanvas { from_x, from_y, width, height, x, y } =
                       ctx.get_json_params(ix).unwrap() {
                    let input: *mut ::ffi::BitmapBgra =
                        ctx.first_parent_result_frame(ix, EdgeKind::Input).unwrap();
                    let canvas: *mut ::ffi::BitmapBgra =
                        ctx.first_parent_result_frame(ix, EdgeKind::Canvas).unwrap();

                    unsafe {
                        if (*input).fmt != (*canvas).fmt {
                            panic!("Can't copy between bitmaps with different pixel formats")
                        }
                        if input == canvas{
                            panic!("Canvas and input must be different bitmaps for CopyRect to work!")
                        }

                        // TODO: Implement faster path for common (full clone) path
                        //    if (info->x == 0 && info->from_x == 0 && info->from_y == 0 && info->y == 0 && info->width == input->w
                        //        && info->width == canvas->w && info->height == input->h && info->height == canvas->h
                        //        && canvas->stride == input->stride) {
                        //        memcpy(canvas->pixels, input->pixels, input->stride * input->h);
                        //        canvas->alpha_meaningful = input->alpha_meaningful;

                        if (*input).w <= from_x || (*input).h <= from_y ||
                           (*input).w < from_x + width ||
                           (*input).h < from_y + height ||
                           (*canvas).w < x + width ||
                           (*canvas).h < y + height {
                            println!("canvas {}x{}, input {}x{}, command {:?}",
                                     (*canvas).w,
                                     (*canvas).h,
                                     (*input).w,
                                     (*input).h,
                                     ctx.get_json_params(ix).unwrap());
                            panic!("Out of bounds")
                        }

                        let bytes_pp = match (*input).fmt {
                            PixelFormat::Gray8 => 1,
                            PixelFormat::Bgra32 => 4,
                            PixelFormat::Bgr24 => 3,
                        };
                        for row in 0..height {
                            let from_offset = (*input).stride * (from_y + row) + bytes_pp * from_x;
                            let from_ptr = (*input).pixels.offset(from_offset as isize);
                            let to_offset = (*canvas).stride * (y + row) + bytes_pp * x;
                            let to_ptr = (*canvas).pixels.offset(to_offset as isize);
                            ptr::copy_nonoverlapping(from_ptr, to_ptr, (width * bytes_pp) as usize);
                        }

                        ctx.weight_mut(ix).result = NodeResult::Frame(canvas);
                    }

                } else {
                    panic!("Missing params")
                }
            }
            f
        }),
        ..Default::default()
    }
}

fn fill_rect_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.fill_rect_mutate",
        name: "fill_rect",
        inbound_edges: EdgesIn::OneInput,
        fn_estimate: Some(NodeDefHelpers::copy_frame_est_from_first_input),
        fn_execute: Some({

            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {

                if let s::Node::FillRect { x1, x2, y1, y2, color } = ctx.get_json_params(ix)
                    .unwrap() {

                    let input = ctx.first_parent_result_frame(ix, EdgeKind::Input).unwrap();
                    unsafe {

                        if !ffi::flow_bitmap_bgra_fill_rect(ctx.c.flow_c(),
                                                            input,
                                                            x1,
                                                            y1,
                                                            x2,
                                                            y2,
                                                            color.to_u32_bgra().unwrap()) {
                            panic!("failed to fill rect. epic.");
                        }

                        ctx.weight_mut(ix).result = NodeResult::Frame(input);
                    }

                } else {
                    panic!("Missing params")
                }
            }
            f
        }),
        ..Default::default()
    }
}

fn clone_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.clone",
        name: "Clone",
        description: "Clone",
        fn_estimate: Some(NodeDefHelpers::copy_frame_est_from_first_input),
        fn_flatten_pre_optimize: Some({
            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {
                match ctx.first_parent_input_weight(ix).unwrap().frame_est {
                    FrameEstimate::Some(FrameInfo { w, h, fmt, alpha_meaningful }) => {
                        let canvas_params = s::Node::CreateCanvas {
                            w: w as usize,
                            h: h as usize,
                            format: s::PixelFormat::from(fmt),
                            color: s::Color::Transparent,
                        };
                        let copy_params = s::Node::CopyRectToCanvas {
                            from_x: 0,
                            from_y: 0,
                            x: 0,
                            y: 0,
                            width: w as u32,
                            height: h as u32,
                        };
                        let canvas = ctx.graph
                            .add_node(Node::new(&CREATE_CANVAS, NodeParams::Json(canvas_params)));
                        let copy = ctx.graph
                            .add_node(Node::new(&COPY_RECT, NodeParams::Json(copy_params)));
                        ctx.graph.add_edge(canvas, copy, EdgeKind::Canvas).unwrap();
                        ctx.replace_node_with_existing(ix, copy);
                    }
                    _ => panic!(""),
                }

            }
            f
        }),
        ..Default::default()
    }
}
fn expand_canvas_size(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {

    let input_info = ctx.first_parent_frame_info_some(ix).unwrap();

    let weight = &mut ctx.weight_mut(ix);
    match weight.params {
        NodeParams::Json(s::Node::ExpandCanvas { ref left,
                                                 ref top,
                                                 ref bottom,
                                                 ref right,
                                                 ref color }) => {
            weight.frame_est = FrameEstimate::Some(FrameInfo {
                w: input_info.w + *left as i32 + *right as i32,
                h: input_info.h + *top as i32 + *bottom as i32,
                fmt: ffi::PixelFormat::from(input_info.fmt),
                alpha_meaningful: input_info.alpha_meaningful,
            }); //TODO: May change if color has alpha
        }
        _ => {
            panic!("Node params missing");
        }
    }
}

fn expand_canvas_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.expand_canvas",
        name: "expand canvas",
        inbound_edges: EdgesIn::OneInput,
        description: "Expand Canvas",
        fn_estimate: Some(expand_canvas_size),
        fn_flatten_pre_optimize: Some({
            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {
                match ctx.first_parent_input_weight(ix).unwrap().frame_est {
                    FrameEstimate::Some(FrameInfo { w, h, fmt, alpha_meaningful }) => {
                        if let s::Node::ExpandCanvas { left, top, right, bottom, color } =
                               ctx.get_json_params(ix).unwrap() {
                            let new_w = w as usize + left as usize + right as usize;
                            let new_h = h as usize + top as usize + bottom as usize;
                            let canvas_params = s::Node::CreateCanvas {
                                w: new_w as usize,
                                h: new_h as usize,
                                format: s::PixelFormat::from(fmt),
                                color: color,
                            };
                            let copy_params = s::Node::CopyRectToCanvas {
                                from_x: 0,
                                from_y: 0,
                                x: left,
                                y: top,
                                width: w as u32,
                                height: h as u32,
                            };
                            let canvas = ctx.graph
                                .add_node(Node::new(&CREATE_CANVAS,
                                                    NodeParams::Json(canvas_params)));
                            let copy = ctx.graph
                                .add_node(Node::new(&COPY_RECT, NodeParams::Json(copy_params)));
                            ctx.graph.add_edge(canvas, copy, EdgeKind::Canvas).unwrap();
                            ctx.replace_node_with_existing(ix, copy);
                        }
                    }
                    _ => panic!(""),
                }
            }
            f
        }),
        ..Default::default()
    }
}

fn crop_size(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {

    let input_info = ctx.first_parent_frame_info_some(ix).unwrap_or_else(|| {
        println!("{:?}", ctx.graph_to_str());
        panic!("");
    });

    let weight = &mut ctx.weight_mut(ix);
    match weight.params {
        NodeParams::Json(s::Node::Crop { ref x1, ref y1, ref x2, ref y2 }) => {
            weight.frame_est = FrameEstimate::Some(FrameInfo {
                w: *x2 as i32 - *x1 as i32,
                h: *y2 as i32 - *y1 as i32,
                fmt: ffi::PixelFormat::from(input_info.fmt),
                alpha_meaningful: input_info.alpha_meaningful,
            });
        }
        _ => {
            panic!("Node params missing");
        }
    }
}
fn crop_mutate_def() -> NodeDefinition {
    NodeDefinition {
        // TODO: As a mutating node, shouldn't this verify no siblings exist? 'Consumed' might be non-deterministic
        fqn: "imazen.crop_mutate",
        name: "crop_mutate",
        inbound_edges: EdgesIn::OneInput,
        fn_estimate: Some(crop_size),
        fn_execute: Some({

            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {

                if let s::Node::Crop { x1, x2, y1, y2 } = ctx.get_json_params(ix).unwrap() {

                    let input = ctx.first_parent_result_frame(ix, EdgeKind::Input).unwrap();
                    unsafe {
                        // println!("Cropping {}x{} to ({},{}) ({},{})", (*input).w, (*input).h, x1, y1, x2, y2);

                        let bytes_pp = match (*input).fmt {
                            PixelFormat::Gray8 => 1,
                            PixelFormat::Bgra32 => 4,
                            PixelFormat::Bgr24 => 3,
                        };
                        let offset = (*input).stride as isize * y1 as isize +
                                     bytes_pp * x1 as isize;
                        (*input).pixels = (*input).pixels.offset(offset);
                        (*input).w = x2 - x1;
                        (*input).h = y2 - y1;
                        // println!("Changing pointer by {}, w{}, h{}", offset, (*input).w, (*input).h);

                        ctx.weight_mut(ix).result = NodeResult::Frame(input);
                        ctx.first_parent_input_weight_mut(ix).unwrap().result =
                            NodeResult::Consumed;
                    }

                } else {
                    panic!("Missing params")
                }
            }
            f
        }),
        ..Default::default()
    }
}

fn crop_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.crop",
        name: "crop",
        inbound_edges: EdgesIn::OneInput,
        fn_estimate: Some(crop_size),
        fn_flatten_pre_optimize: Some({
            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {
                let mut new_nodes = Vec::with_capacity(2);
                if ctx.has_other_children(ctx.first_parent_input(ix).unwrap(), ix) {
                    new_nodes.push(Node::new(&CLONE, NodeParams::None));
                }
                new_nodes.push(Node::new(&CROP_MUTATE,
                                         NodeParams::Json(ctx.get_json_params(ix).unwrap())));
                ctx.replace_node(ix, new_nodes);
            }
            f
        }),
        ..Default::default()
    }
}

fn crop_whitespace_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.crop_whitespace",
        name: "crop_whitespace",
        inbound_edges: EdgesIn::OneInput,
        fn_estimate: Some({
            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {
                ctx.weight_mut(ix).frame_est = FrameEstimate::Impossible;
            }
            f
        }),
        fn_flatten_pre_optimize: Some({
            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {

                // detect bounds, increase, and replace with crop
                if let s::Node::CropWhitespace {threshold, percent_padding} = ctx.get_json_params(ix).unwrap() {
                    let (x1, y1, x2, y2) = match ctx.first_parent_input_weight(ix).unwrap().result {
                        NodeResult::Frame(b) => {
                            unsafe {
                                let rect = ::ffi::detect_content(ctx.c.flow_c(), b, threshold);
                                let padding = (percent_padding * (rect.x2 - rect.x1 + rect.y2 - rect.y1) as f32 / 2f32).ceil() as i32;
                                (cmp::max(0, rect.x1 - padding) as u32, cmp::max(0, rect.y1 - padding) as u32,
                                 cmp::min((*b).w as i32, rect.x2 + padding) as u32, cmp::min((*b).h as i32, rect.y2 + padding) as u32)
                            }
                        },
                        _ => { panic!("") }
                    };

                    ctx.replace_node(ix, vec![
                        Node::new(&CROP,
                                  NodeParams::Json(s::Node::Crop{ x1: x1, y1: y1, x2: x2, y2: y2 }))
                    ]);
                }
            }
            f
        }),
        ..Default::default()
    }
}
lazy_static! {
    pub static ref CLONE: NodeDefinition = clone_def();
    pub static ref CROP_MUTATE: NodeDefinition = crop_mutate_def();
    pub static ref CROP: NodeDefinition = crop_def();
    pub static ref CROP_WHITESPACE: NodeDefinition = crop_whitespace_def();
    pub static ref EXPAND_CANVAS: NodeDefinition = expand_canvas_def();

    pub static ref COPY_RECT: NodeDefinition = copy_rect_def();
    pub static ref FILL_RECT: NodeDefinition = fill_rect_def();
}
<commit_msg>Optimize copy_rect<commit_after>use super::internal_prelude::*;

fn copy_rect_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.copy_rect_to_canvas",
        name: "copy_rect",
        inbound_edges: EdgesIn::OneInputOneCanvas,
        description: "Copy Rect",
        fn_estimate: Some(NodeDefHelpers::copy_frame_est_from_first_canvas),
        fn_execute: Some({

            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {

                if let s::Node::CopyRectToCanvas { from_x, from_y, width, height, x, y } =
                       ctx.get_json_params(ix).unwrap() {
                    let input: *mut ::ffi::BitmapBgra =
                        ctx.first_parent_result_frame(ix, EdgeKind::Input).unwrap();
                    let canvas: *mut ::ffi::BitmapBgra =
                        ctx.first_parent_result_frame(ix, EdgeKind::Canvas).unwrap();

                    unsafe {
                        if (*input).fmt != (*canvas).fmt {
                            panic!("Can't copy between bitmaps with different pixel formats")
                        }
                        if input == canvas{
                            panic!("Canvas and input must be different bitmaps for CopyRect to work!")
                        }

                        // TODO: Implement faster path for common (full clone) path
                        //    if (info->x == 0 && info->from_x == 0 && info->from_y == 0 && info->y == 0 && info->width == input->w
                        //        && info->width == canvas->w && info->height == input->h && info->height == canvas->h
                        //        && canvas->stride == input->stride) {
                        //        memcpy(canvas->pixels, input->pixels, input->stride * input->h);
                        //        canvas->alpha_meaningful = input->alpha_meaningful;

                        if (*input).w <= from_x || (*input).h <= from_y ||
                           (*input).w < from_x + width ||
                           (*input).h < from_y + height ||
                           (*canvas).w < x + width ||
                           (*canvas).h < y + height {
                            println!("canvas {}x{}, input {}x{}, command {:?}",
                                     (*canvas).w,
                                     (*canvas).h,
                                     (*input).w,
                                     (*input).h,
                                     ctx.get_json_params(ix).unwrap());
                            panic!("Out of bounds")
                        }

                        let bytes_pp = match (*input).fmt {
                            PixelFormat::Gray8 => 1,
                            PixelFormat::Bgra32 => 4,
                            PixelFormat::Bgr24 => 3,
                        };
                        if from_x == 0 && x == 0 && width == (*input).w && width == (*canvas).w  &&
                            (*input).stride == (*canvas).stride && !(*canvas).borrowed_pixels {
                            //This optimization has the side effect of copying irrelevant data, so we don't want to do it if windowed, only
                            // if padded or permanently cropped.
                            let from_offset = (*input).stride * from_y;
                            let from_ptr = (*input).pixels.offset(from_offset as isize);
                            let to_offset = (*canvas).stride * y;
                            let to_ptr = (*canvas).pixels.offset(to_offset as isize);
                            ptr::copy_nonoverlapping(from_ptr, to_ptr, ((*input).stride * height) as usize);
                        }else {
                            for row in 0..height {
                                let from_offset = (*input).stride * (from_y + row) + bytes_pp * from_x;
                                let from_ptr = (*input).pixels.offset(from_offset as isize);
                                let to_offset = (*canvas).stride * (y + row) + bytes_pp * x;
                                let to_ptr = (*canvas).pixels.offset(to_offset as isize);
                                ptr::copy_nonoverlapping(from_ptr, to_ptr, (width * bytes_pp) as usize);
                            }
                        }

                        ctx.weight_mut(ix).result = NodeResult::Frame(canvas);
                    }

                } else {
                    panic!("Missing params")
                }
            }
            f
        }),
        ..Default::default()
    }
}

fn fill_rect_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.fill_rect_mutate",
        name: "fill_rect",
        inbound_edges: EdgesIn::OneInput,
        fn_estimate: Some(NodeDefHelpers::copy_frame_est_from_first_input),
        fn_execute: Some({

            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {

                if let s::Node::FillRect { x1, x2, y1, y2, color } = ctx.get_json_params(ix)
                    .unwrap() {

                    let input = ctx.first_parent_result_frame(ix, EdgeKind::Input).unwrap();
                    unsafe {

                        if !ffi::flow_bitmap_bgra_fill_rect(ctx.c.flow_c(),
                                                            input,
                                                            x1,
                                                            y1,
                                                            x2,
                                                            y2,
                                                            color.to_u32_bgra().unwrap()) {
                            panic!("failed to fill rect. epic.");
                        }

                        ctx.weight_mut(ix).result = NodeResult::Frame(input);
                    }

                } else {
                    panic!("Missing params")
                }
            }
            f
        }),
        ..Default::default()
    }
}

fn clone_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.clone",
        name: "Clone",
        description: "Clone",
        fn_estimate: Some(NodeDefHelpers::copy_frame_est_from_first_input),
        fn_flatten_pre_optimize: Some({
            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {
                match ctx.first_parent_input_weight(ix).unwrap().frame_est {
                    FrameEstimate::Some(FrameInfo { w, h, fmt, alpha_meaningful }) => {
                        let canvas_params = s::Node::CreateCanvas {
                            w: w as usize,
                            h: h as usize,
                            format: s::PixelFormat::from(fmt),
                            color: s::Color::Transparent,
                        };
                        let copy_params = s::Node::CopyRectToCanvas {
                            from_x: 0,
                            from_y: 0,
                            x: 0,
                            y: 0,
                            width: w as u32,
                            height: h as u32,
                        };
                        let canvas = ctx.graph
                            .add_node(Node::new(&CREATE_CANVAS, NodeParams::Json(canvas_params)));
                        let copy = ctx.graph
                            .add_node(Node::new(&COPY_RECT, NodeParams::Json(copy_params)));
                        ctx.graph.add_edge(canvas, copy, EdgeKind::Canvas).unwrap();
                        ctx.replace_node_with_existing(ix, copy);
                    }
                    _ => panic!(""),
                }

            }
            f
        }),
        ..Default::default()
    }
}
fn expand_canvas_size(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {

    let input_info = ctx.first_parent_frame_info_some(ix).unwrap();

    let weight = &mut ctx.weight_mut(ix);
    match weight.params {
        NodeParams::Json(s::Node::ExpandCanvas { ref left,
                                                 ref top,
                                                 ref bottom,
                                                 ref right,
                                                 ref color }) => {
            weight.frame_est = FrameEstimate::Some(FrameInfo {
                w: input_info.w + *left as i32 + *right as i32,
                h: input_info.h + *top as i32 + *bottom as i32,
                fmt: ffi::PixelFormat::from(input_info.fmt),
                alpha_meaningful: input_info.alpha_meaningful,
            }); //TODO: May change if color has alpha
        }
        _ => {
            panic!("Node params missing");
        }
    }
}

fn expand_canvas_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.expand_canvas",
        name: "expand canvas",
        inbound_edges: EdgesIn::OneInput,
        description: "Expand Canvas",
        fn_estimate: Some(expand_canvas_size),
        fn_flatten_pre_optimize: Some({
            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {
                match ctx.first_parent_input_weight(ix).unwrap().frame_est {
                    FrameEstimate::Some(FrameInfo { w, h, fmt, alpha_meaningful }) => {
                        if let s::Node::ExpandCanvas { left, top, right, bottom, color } =
                               ctx.get_json_params(ix).unwrap() {
                            let new_w = w as usize + left as usize + right as usize;
                            let new_h = h as usize + top as usize + bottom as usize;
                            let canvas_params = s::Node::CreateCanvas {
                                w: new_w as usize,
                                h: new_h as usize,
                                format: s::PixelFormat::from(fmt),
                                color: color,
                            };
                            let copy_params = s::Node::CopyRectToCanvas {
                                from_x: 0,
                                from_y: 0,
                                x: left,
                                y: top,
                                width: w as u32,
                                height: h as u32,
                            };
                            let canvas = ctx.graph
                                .add_node(Node::new(&CREATE_CANVAS,
                                                    NodeParams::Json(canvas_params)));
                            let copy = ctx.graph
                                .add_node(Node::new(&COPY_RECT, NodeParams::Json(copy_params)));
                            ctx.graph.add_edge(canvas, copy, EdgeKind::Canvas).unwrap();
                            ctx.replace_node_with_existing(ix, copy);
                        }
                    }
                    _ => panic!(""),
                }
            }
            f
        }),
        ..Default::default()
    }
}

fn crop_size(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {

    let input_info = ctx.first_parent_frame_info_some(ix).unwrap_or_else(|| {
        println!("{:?}", ctx.graph_to_str());
        panic!("");
    });

    let weight = &mut ctx.weight_mut(ix);
    match weight.params {
        NodeParams::Json(s::Node::Crop { ref x1, ref y1, ref x2, ref y2 }) => {
            weight.frame_est = FrameEstimate::Some(FrameInfo {
                w: *x2 as i32 - *x1 as i32,
                h: *y2 as i32 - *y1 as i32,
                fmt: ffi::PixelFormat::from(input_info.fmt),
                alpha_meaningful: input_info.alpha_meaningful,
            });
        }
        _ => {
            panic!("Node params missing");
        }
    }
}
fn crop_mutate_def() -> NodeDefinition {
    NodeDefinition {
        // TODO: As a mutating node, shouldn't this verify no siblings exist? 'Consumed' might be non-deterministic
        fqn: "imazen.crop_mutate",
        name: "crop_mutate",
        inbound_edges: EdgesIn::OneInput,
        fn_estimate: Some(crop_size),
        fn_execute: Some({

            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {

                if let s::Node::Crop { x1, x2, y1, y2 } = ctx.get_json_params(ix).unwrap() {

                    let input = ctx.first_parent_result_frame(ix, EdgeKind::Input).unwrap();
                    unsafe {
                        // println!("Cropping {}x{} to ({},{}) ({},{})", (*input).w, (*input).h, x1, y1, x2, y2);

                        let bytes_pp = match (*input).fmt {
                            PixelFormat::Gray8 => 1,
                            PixelFormat::Bgra32 => 4,
                            PixelFormat::Bgr24 => 3,
                        };
                        let offset = (*input).stride as isize * y1 as isize +
                                     bytes_pp * x1 as isize;
                        (*input).pixels = (*input).pixels.offset(offset);
                        (*input).w = x2 - x1;
                        (*input).h = y2 - y1;
                        // println!("Changing pointer by {}, w{}, h{}", offset, (*input).w, (*input).h);

                        ctx.weight_mut(ix).result = NodeResult::Frame(input);
                        ctx.first_parent_input_weight_mut(ix).unwrap().result =
                            NodeResult::Consumed;
                    }

                } else {
                    panic!("Missing params")
                }
            }
            f
        }),
        ..Default::default()
    }
}

fn crop_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.crop",
        name: "crop",
        inbound_edges: EdgesIn::OneInput,
        fn_estimate: Some(crop_size),
        fn_flatten_pre_optimize: Some({
            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {
                let mut new_nodes = Vec::with_capacity(2);
                if ctx.has_other_children(ctx.first_parent_input(ix).unwrap(), ix) {
                    new_nodes.push(Node::new(&CLONE, NodeParams::None));
                }
                new_nodes.push(Node::new(&CROP_MUTATE,
                                         NodeParams::Json(ctx.get_json_params(ix).unwrap())));
                ctx.replace_node(ix, new_nodes);
            }
            f
        }),
        ..Default::default()
    }
}

fn crop_whitespace_def() -> NodeDefinition {
    NodeDefinition {
        fqn: "imazen.crop_whitespace",
        name: "crop_whitespace",
        inbound_edges: EdgesIn::OneInput,
        fn_estimate: Some({
            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {
                ctx.weight_mut(ix).frame_est = FrameEstimate::Impossible;
            }
            f
        }),
        fn_flatten_pre_optimize: Some({
            fn f(ctx: &mut OpCtxMut, ix: NodeIndex<u32>) {

                // detect bounds, increase, and replace with crop
                if let s::Node::CropWhitespace {threshold, percent_padding} = ctx.get_json_params(ix).unwrap() {
                    let (x1, y1, x2, y2) = match ctx.first_parent_input_weight(ix).unwrap().result {
                        NodeResult::Frame(b) => {
                            unsafe {
                                let rect = ::ffi::detect_content(ctx.c.flow_c(), b, threshold);
                                let padding = (percent_padding * (rect.x2 - rect.x1 + rect.y2 - rect.y1) as f32 / 2f32).ceil() as i32;
                                (cmp::max(0, rect.x1 - padding) as u32, cmp::max(0, rect.y1 - padding) as u32,
                                 cmp::min((*b).w as i32, rect.x2 + padding) as u32, cmp::min((*b).h as i32, rect.y2 + padding) as u32)
                            }
                        },
                        _ => { panic!("") }
                    };

                    ctx.replace_node(ix, vec![
                        Node::new(&CROP,
                                  NodeParams::Json(s::Node::Crop{ x1: x1, y1: y1, x2: x2, y2: y2 }))
                    ]);
                }
            }
            f
        }),
        ..Default::default()
    }
}
lazy_static! {
    pub static ref CLONE: NodeDefinition = clone_def();
    pub static ref CROP_MUTATE: NodeDefinition = crop_mutate_def();
    pub static ref CROP: NodeDefinition = crop_def();
    pub static ref CROP_WHITESPACE: NodeDefinition = crop_whitespace_def();
    pub static ref EXPAND_CANVAS: NodeDefinition = expand_canvas_def();

    pub static ref COPY_RECT: NodeDefinition = copy_rect_def();
    pub static ref FILL_RECT: NodeDefinition = fill_rect_def();
}
<|endoftext|>