<commit_before>use core::cmp::{Eq, Ord};
use iter::BaseIter;

pub trait PersistentMap<K: Copy Eq Ord, V: Copy> {
  pure fn get(k: K) -> Option<V>;
  pure fn put(k: K, v: V) -> self;
  pure fn delete(k: K) -> self;
}

enum RBColor {
  Red,
  Black
}

pub enum RBMap<K: Copy Eq Ord, V: Copy> {
  //   color    left         k  value       right
  Tree(RBColor, @RBMap<K,V>, K, Option<V>, @RBMap<K,V>),
  Leaf
}

pure fn RBMap<K: Copy Eq Ord, V: Copy>(key: K, value: V) -> @RBMap<K, V> {
  @Tree(Red, @Leaf, key, Some(value), @Leaf)
}

priv impl<K: Copy Eq Ord, V: Copy> @RBMap<K, V> {
  pure fn modify(k: K, new_value: Option<V>) -> @RBMap<K, V> {
    match self {
      @Leaf => @Tree(Red, self, k, copy new_value, self),
      @Tree(color, left, key, original_value, right) => {
        if (k.lt(&key)) {
          self.balanceLeft(color, left.modify(k, new_value), key, original_value, right)
        } else if (k == key) {
          @Tree(color, left, k, copy new_value, right)
        } else {
          self.balanceRight(color, left, key, original_value, right.modify(k, new_value))
        }
      }
    }
  }

  pure fn balanceLeft(c: RBColor, l: @RBMap<K,V>, k: K, v: Option<V>, r: @RBMap<K,V>) -> @RBMap<K,V> {
    match (c, l, k, v, r) {
      (Black,@Tree(Red,@Tree(Red,a,xK,xV,b),yK,yV,c),zK,zV,d) =>
        @Tree(Red,@Tree(Black,a,xK,xV,b),yK,yV,@Tree(Black,c,zK,zV,d)),
      (c,a,xK,xV,b) =>
        @Tree(c,a,xK,xV,b)
    }
  }

  pure fn balanceRight(c: RBColor, l: @RBMap<K,V>, k: K, v: Option<V>, r: @RBMap<K,V>) -> @RBMap<K,V> {
    match (c, l, k, v, r) {
      (Black, @Tree(Red, t1, k1, v1, t2), k0, v0, @Tree(Red, t3, k2, v2, t4)) =>
        @Tree(Red, @Tree(Black, t1, k1, v1, t2), k0, v0, @Tree(Black, t3, k2, v2, t4)),
      (c, l, k, v, @Tree(Red, t1, k1, v1, t2)) =>
        @Tree(c, @Tree(Red, l, k, v, t1), k1, v1, t2),
      (c,a,xK,xV,b) =>
        @Tree(c,a,xK,xV,b)
    }
  }
}

/**
 * A purely functional Left-Leaning Red-Black Tree.
 */
impl<K: Copy Eq Ord, V: Copy> @RBMap<K, V> : PersistentMap<K, V> {
  pure fn get(k: K) -> Option<V> {
    match self {
      @Leaf => None,
      @Tree(_, left, key, maybe_value, right) => {
        if (k.lt(&key)) {
          left.get(k)
        } else if (k.gt(&key)) {
          right.get(k)
        } else {
          copy maybe_value
        }
      }
    }
  }

  pure fn put(k: K, new_value: V) -> @RBMap<K, V> {
    self.modify(k, Some(new_value))
  }

  pure fn delete(k: K) -> @RBMap<K, V> {
    self.modify(k, None)
  }
}

impl<K: Copy Eq Ord, V: Copy> RBMap<K, V>: iter::BaseIter<(&K, &V)> {
  pure fn size_hint() -> Option<uint> {
    None
  }

  pure fn each(f: fn(&(&K, &V)) -> bool) {
    match self {
      Leaf => (),
      Tree(_, left, key, maybe_value, right) => {
        left.each(f);
        match maybe_value {
          Some(value) => f(&(&key, &value)),
          None => false,
        };
        right.each(f);
      }
    }
  }
}

#[test]
fn test_rb_tree() {
  let v1 = RBMap("stevej", 150);
  let v2 = v1.put("thatstacy", 187);

  assert(v2.get("stevej") == Some(150));
  assert(v2.get("thatstacy") == Some(187));

  let v3 = v2.delete("stevej");
  assert(v3.get("stevej") == None);
  assert(v3.get("thatstacy") == Some(187));

  let v4 = v2.put("jeremy", 16);

  let v5 = v4.put("ev", 20);
  let v6 = v5.put("zhana", 51573);

  assert(v6.get("jeremy") == Some(16));
  assert(v6.get("stevej") == Some(150));
  assert(v6.get("thatstacy") == Some(187));
  assert(v6.get("ev") == Some(20));
  assert(v6.get("zhana") == Some(51573));
}

#[test]
fn test_base_iter_each() {
  let v1 = RBMap(1, 0);
  let v2 = v1.put(4, 0);
  let v3 = v2.put(3, 0);
  let v4 = v3.put(5, 0);
  let v5 = v4.put(2, 0);

  let n = @mut 1;

  fn t(n: @mut int, kv: &(&int, &int)) -> bool{
    match kv {
      &(k, _) => {
        assert (*n == *k);
        *n += 1;
      }
    }
    false
  }

  v5.each(|z| t(n, z));
}
<commit_msg>using self-types as per 0.5<commit_after>use core::cmp::{Eq, Ord};
use iter::BaseIter;

pub trait PersistentMap<K: Copy Eq Ord, V: Copy> {
  pure fn get(k: K) -> Option<V>;
  pure fn put(k: K, v: V) -> self;
  pure fn delete(k: K) -> self;
}

enum RBColor {
  Red,
  Black
}

pub enum RBMap<K: Copy Eq Ord, V: Copy> {
  //   color    left         k  value       right
  Tree(RBColor, @RBMap<K,V>, K, Option<V>, @RBMap<K,V>),
  Leaf
}

pure fn RBMap<K: Copy Eq Ord, V: Copy>(key: K, value: V) -> @RBMap<K, V> {
  @Tree(Red, @Leaf, key, Some(value), @Leaf)
}

priv impl<K: Copy Eq Ord, V: Copy> @RBMap<K, V> {
  pure fn modify(k: K, new_value: Option<V>) -> @RBMap<K, V> {
    match self {
      @Leaf => @Tree(Red, self, k, copy new_value, self),
      @Tree(color, left, key, original_value, right) => {
        if (k.lt(&key)) {
          self.balanceLeft(color, left.modify(k, new_value), key, original_value, right)
        } else if (k == key) {
          @Tree(color, left, k, copy new_value, right)
        } else {
          self.balanceRight(color, left, key, original_value, right.modify(k, new_value))
        }
      }
    }
  }

  pure fn balanceLeft(c: RBColor, l: @RBMap<K,V>, k: K, v: Option<V>, r: @RBMap<K,V>) -> @RBMap<K,V> {
    match (c, l, k, v, r) {
      (Black,@Tree(Red,@Tree(Red,a,xK,xV,b),yK,yV,c),zK,zV,d) =>
        @Tree(Red,@Tree(Black,a,xK,xV,b),yK,yV,@Tree(Black,c,zK,zV,d)),
      (c,a,xK,xV,b) =>
        @Tree(c,a,xK,xV,b)
    }
  }

  pure fn balanceRight(c: RBColor, l: @RBMap<K,V>, k: K, v: Option<V>, r: @RBMap<K,V>) -> @RBMap<K,V> {
    match (c, l, k, v, r) {
      (Black, @Tree(Red, t1, k1, v1, t2), k0, v0, @Tree(Red, t3, k2, v2, t4)) =>
        @Tree(Red, @Tree(Black, t1, k1, v1, t2), k0, v0, @Tree(Black, t3, k2, v2, t4)),
      (c, l, k, v, @Tree(Red, t1, k1, v1, t2)) =>
        @Tree(c, @Tree(Red, l, k, v, t1), k1, v1, t2),
      (c,a,xK,xV,b) =>
        @Tree(c,a,xK,xV,b)
    }
  }
}

/**
 * A purely functional Left-Leaning Red-Black Tree.
 */
impl<K: Copy Eq Ord, V: Copy> @RBMap<K, V> : PersistentMap<K, V> {
  pure fn get(k: K) -> Option<V> {
    match self {
      @Leaf => None,
      @Tree(_, left, key, maybe_value, right) => {
        if (k.lt(&key)) {
          left.get(k)
        } else if (k.gt(&key)) {
          right.get(k)
        } else {
          copy maybe_value
        }
      }
    }
  }

  pure fn put(k: K, new_value: V) -> @RBMap<K, V> {
    self.modify(k, Some(new_value))
  }

  pure fn delete(k: K) -> @RBMap<K, V> {
    self.modify(k, None)
  }
}

impl<K: Copy Eq Ord, V: Copy> RBMap<K, V>: iter::BaseIter<(&K, &V)> {
  pure fn size_hint(&self) -> Option<uint> {
    None
  }

  pure fn each(&self, f: fn(&(&K, &V)) -> bool) {
    match *self {
      Leaf => (),
      Tree(_, left, key, maybe_value, right) => {
        left.each(f);
        match maybe_value {
          Some(value) => f(&(&key, &value)),
          None => false,
        };
        right.each(f);
      }
    }
  }
}

#[test]
fn test_rb_tree() {
  let v1 = RBMap("stevej", 150);
  let v2 = v1.put("thatstacy", 187);

  assert(v2.get("stevej") == Some(150));
  assert(v2.get("thatstacy") == Some(187));

  let v3 = v2.delete("stevej");
  assert(v3.get("stevej") == None);
  assert(v3.get("thatstacy") == Some(187));

  let v4 = v2.put("jeremy", 16);

  let v5 = v4.put("ev", 20);
  let v6 = v5.put("zhana", 51573);

  assert(v6.get("jeremy") == Some(16));
  assert(v6.get("stevej") == Some(150));
  assert(v6.get("thatstacy") == Some(187));
  assert(v6.get("ev") == Some(20));
  assert(v6.get("zhana") == Some(51573));
}

#[test]
fn test_base_iter_each() {
  let v1 = RBMap(1, 0);
  let v2 = v1.put(4, 0);
  let v3 = v2.put(3, 0);
  let v4 = v3.put(5, 0);
  let v5 = v4.put(2, 0);

  let n = @mut 1;

  fn t(n: @mut int, kv: &(&int, &int)) -> bool{
    match kv {
      &(k, _) => {
        assert (*n == *k);
        *n += 1;
      }
    }
    false
  }

  v5.each(|z| t(n, z));
}
<|endoftext|>


<commit_before>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std;
use std::os::unix::io::RawFd;
use std::sync::Arc;

use crate::bindings;
use crate::config_descriptor::ConfigDescriptor;
use crate::device_handle::DeviceHandle;
use crate::error::{Error, Result};
use crate::libusb_context::LibUsbContextInner;
use crate::types::Speed;

pub type DeviceDescriptor = bindings::libusb_device_descriptor;

/// LibUsbDevice wraps libusb_device.
pub struct LibUsbDevice {
    _context: Arc<LibUsbContextInner>,
    device: *mut bindings::libusb_device,
}

unsafe impl Send for LibUsbDevice {}

impl Drop for LibUsbDevice {
    fn drop(&mut self) {
        // Safe because 'self.device' is a valid pointer and libusb_ref_device is invoked when
        // 'self' is built.
        unsafe {
            bindings::libusb_unref_device(self.device);
        }
    }
}

impl LibUsbDevice {
    /// Create a new LibUsbDevice. 'device' should be a valid pointer to libusb_device.
    pub unsafe fn new(
        ctx: Arc<LibUsbContextInner>,
        device: *mut bindings::libusb_device,
    ) -> LibUsbDevice {
        bindings::libusb_ref_device(device);
        LibUsbDevice {
            _context: ctx,
            device,
        }
    }

    /// Get device descriptor of this device.
    pub fn get_device_descriptor(&self) -> Result<DeviceDescriptor> {
        // Safe because memory is initialized later.
        let mut descriptor: bindings::libusb_device_descriptor =
            unsafe { std::mem::uninitialized() };
        // Safe because 'self.device' is valid and '&mut descriptor' is valid.
        try_libusb!(unsafe {
            bindings::libusb_get_device_descriptor(self.device, &mut descriptor)
        });
        Ok(descriptor)
    }

    /// Get config descriptor at index of idx.
    pub fn get_config_descriptor(&self, idx: u8) -> Result<ConfigDescriptor> {
        let mut descriptor: *mut bindings::libusb_config_descriptor = std::ptr::null_mut();
        // Safe because 'self.device' is valid and '&mut descriptor' is valid.
        try_libusb!(unsafe {
            bindings::libusb_get_config_descriptor(self.device, idx, &mut descriptor)
        });
        // Safe because descriptor is inited with valid pointer.
        Ok(unsafe { ConfigDescriptor::new(descriptor) })
    }

    /// Get active config descriptor of this device.
    pub fn get_active_config_descriptor(&self) -> Result<ConfigDescriptor> {
        let mut descriptor: *mut bindings::libusb_config_descriptor = std::ptr::null_mut();
        // Safe because 'self.device' is valid and '&mut descriptor' is valid.
        try_libusb!(unsafe {
            bindings::libusb_get_active_config_descriptor(self.device, &mut descriptor)
        });
        // Safe becuase descriptor points to valid memory.
        Ok(unsafe { ConfigDescriptor::new(descriptor) })
    }

    /// Get bus number of this device.
    pub fn get_bus_number(&self) -> u8 {
        // Safe because 'self.device' is valid.
        unsafe { bindings::libusb_get_bus_number(self.device) }
    }

    /// Get address of this device.
    pub fn get_address(&self) -> u8 {
        // Safe because 'self.device' is valid.
        unsafe { bindings::libusb_get_device_address(self.device) }
    }

    /// Get speed of this device.
    pub fn get_speed(&self) -> Speed {
        // Safe because 'self.device' is valid.
        let speed = unsafe { bindings::libusb_get_device_speed(self.device) };
        Speed::from(speed as u32)
    }

    /// Get device handle of this device.
    pub fn open(&self) -> Result<DeviceHandle> {
        let mut handle: *mut bindings::libusb_device_handle = std::ptr::null_mut();
        // Safe because 'self.device' is constructed from libusb device list and handle is on stack.
        try_libusb!(unsafe { bindings::libusb_open(self.device, &mut handle) });
        // Safe because handle points to valid memory.
        Ok(unsafe { DeviceHandle::new(self._context.clone(), handle) })
    }

    /// Get device handle of this device. Take an external fd. This function is only safe when fd
    /// is an fd of this usb device.
    #[cfg(feature = "sandboxed-libusb")]
    pub unsafe fn open_fd(&self, fd: RawFd) -> Result<DeviceHandle> {
        let mut handle: *mut bindings::libusb_device_handle = std::ptr::null_mut();
        // Safe when 'self.device' is constructed from libusb device list and handle is on stack.
        try_libusb!(bindings::libusb_open_fd(self.device, fd, &mut handle));
        Ok(DeviceHandle::new(self._context.clone(), handle))
    }
}
<commit_msg>usb_util: silence unused code warning<commit_after>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std;
#[cfg(feature = "sandboxed-libusb")]
use std::os::unix::io::RawFd;
use std::sync::Arc;

use crate::bindings;
use crate::config_descriptor::ConfigDescriptor;
use crate::device_handle::DeviceHandle;
use crate::error::{Error, Result};
use crate::libusb_context::LibUsbContextInner;
use crate::types::Speed;

pub type DeviceDescriptor = bindings::libusb_device_descriptor;

/// LibUsbDevice wraps libusb_device.
pub struct LibUsbDevice {
    _context: Arc<LibUsbContextInner>,
    device: *mut bindings::libusb_device,
}

unsafe impl Send for LibUsbDevice {}

impl Drop for LibUsbDevice {
    fn drop(&mut self) {
        // Safe because 'self.device' is a valid pointer and libusb_ref_device is invoked when
        // 'self' is built.
        unsafe {
            bindings::libusb_unref_device(self.device);
        }
    }
}

impl LibUsbDevice {
    /// Create a new LibUsbDevice. 'device' should be a valid pointer to libusb_device.
    pub unsafe fn new(
        ctx: Arc<LibUsbContextInner>,
        device: *mut bindings::libusb_device,
    ) -> LibUsbDevice {
        bindings::libusb_ref_device(device);
        LibUsbDevice {
            _context: ctx,
            device,
        }
    }

    /// Get device descriptor of this device.
    pub fn get_device_descriptor(&self) -> Result<DeviceDescriptor> {
        // Safe because memory is initialized later.
        let mut descriptor: bindings::libusb_device_descriptor =
            unsafe { std::mem::uninitialized() };
        // Safe because 'self.device' is valid and '&mut descriptor' is valid.
        try_libusb!(unsafe {
            bindings::libusb_get_device_descriptor(self.device, &mut descriptor)
        });
        Ok(descriptor)
    }

    /// Get config descriptor at index of idx.
    pub fn get_config_descriptor(&self, idx: u8) -> Result<ConfigDescriptor> {
        let mut descriptor: *mut bindings::libusb_config_descriptor = std::ptr::null_mut();
        // Safe because 'self.device' is valid and '&mut descriptor' is valid.
        try_libusb!(unsafe {
            bindings::libusb_get_config_descriptor(self.device, idx, &mut descriptor)
        });
        // Safe because descriptor is inited with valid pointer.
        Ok(unsafe { ConfigDescriptor::new(descriptor) })
    }

    /// Get active config descriptor of this device.
    pub fn get_active_config_descriptor(&self) -> Result<ConfigDescriptor> {
        let mut descriptor: *mut bindings::libusb_config_descriptor = std::ptr::null_mut();
        // Safe because 'self.device' is valid and '&mut descriptor' is valid.
        try_libusb!(unsafe {
            bindings::libusb_get_active_config_descriptor(self.device, &mut descriptor)
        });
        // Safe becuase descriptor points to valid memory.
        Ok(unsafe { ConfigDescriptor::new(descriptor) })
    }

    /// Get bus number of this device.
    pub fn get_bus_number(&self) -> u8 {
        // Safe because 'self.device' is valid.
        unsafe { bindings::libusb_get_bus_number(self.device) }
    }

    /// Get address of this device.
    pub fn get_address(&self) -> u8 {
        // Safe because 'self.device' is valid.
        unsafe { bindings::libusb_get_device_address(self.device) }
    }

    /// Get speed of this device.
    pub fn get_speed(&self) -> Speed {
        // Safe because 'self.device' is valid.
        let speed = unsafe { bindings::libusb_get_device_speed(self.device) };
        Speed::from(speed as u32)
    }

    /// Get device handle of this device.
    pub fn open(&self) -> Result<DeviceHandle> {
        let mut handle: *mut bindings::libusb_device_handle = std::ptr::null_mut();
        // Safe because 'self.device' is constructed from libusb device list and handle is on stack.
        try_libusb!(unsafe { bindings::libusb_open(self.device, &mut handle) });
        // Safe because handle points to valid memory.
        Ok(unsafe { DeviceHandle::new(self._context.clone(), handle) })
    }

    /// Get device handle of this device. Take an external fd. This function is only safe when fd
    /// is an fd of this usb device.
    #[cfg(feature = "sandboxed-libusb")]
    pub unsafe fn open_fd(&self, fd: RawFd) -> Result<DeviceHandle> {
        let mut handle: *mut bindings::libusb_device_handle = std::ptr::null_mut();
        // Safe when 'self.device' is constructed from libusb device list and handle is on stack.
        try_libusb!(bindings::libusb_open_fd(self.device, fd, &mut handle));
        Ok(DeviceHandle::new(self._context.clone(), handle))
    }
}
<|endoftext|>


<commit_before>struct Point {
    x: f64,
    y: f64,
}

// 实现的代码块，所有的 `Point` 方法都在这里给出
impl Point {
    // 这是一个静态方法（static method）
    // 静态方法不需要通过实例来调用
    // 这类方法一般用作构造器（constructor）
    fn origin() -> Point {
        Point { x: 0.0, y: 0.0 }
    }

    // 另外一个静态方法，带有两个参数：
    fn new(x: f64, y: f64) -> Point {
        Point { x: x, y: y }
    }
}

struct Rectangle {
    p1: Point,
    p2: Point,
}

impl Rectangle {
    // 这是实例方法（instance method）
    // `&slef` 是 `self: &Self` 的语法糖（sugar），其中 `Self` 是所调用对象
    // 的类型。在这个例子中 `Self` = `Rectangle`
    fn area(&self) -> f64 {
        // `self` 通过点运算符来访问结构体字段
        let Point { x: x1, y: y1 } = self.p1;
        let Point { x: x2, y: y2 } = self.p2;

        // `abs` 是一个 `f64` 类型的方法，返回调用者的绝对值
        ((x1 - x2) * (y1 - y2)).abs()
    }

    fn perimeter(&self) -> f64 {
        let Point { x: x1, y: y1 } = self.p1;
        let Point { x: x2, y: y2 } = self.p2;

        2.0 * ((x1 - x2).abs() + (y1 - y2).abs())
    }

    // 这个方法要求调用者对象是可变的
    // `&mut self` 为 `self: &mut Self` 的语法糖
    fn translate(&mut self, x: f64, y: f64) {
        self.p1.x += x;
        self.p2.x += x;

        self.p1.y += y;
        self.p2.y += y;
    }
}

// `Pair` 含有的资源：两个堆分配的整型
struct Pair(Box<i32>, Box<i32>);

impl Pair {
    // 这个方法“消费”调用者对象的资源
    // `self` 为 `self: Self` 的语法糖
    fn destroy(self) {
        // 解构 `self`
        let Pair(first, second) = self;

        println!("Destroying Pair({}, {})", first, second);

        // `first` 和 `second` 离开作用域后释放
    }
}

fn main() {
    let rectangle = Rectangle {
        // 静态方法使用双重冒号来调用
        p1: Point::origin(),
        p2: Point::new(3.0, 4.0),
    };

    // 实例方法通过点运算符来调用
    // 注意第一个参数 `&self` 是隐式传递的，比如：
    // `rectangle.perimeter()` === `Rectangle::perimeter(&rectangle)`
    println!("Rectangle perimeter: {}", rectangle.perimeter());
    println!("Rectangle area: {}", rectangle.area());

    let mut square = Rectangle {
        p1: Point::origin(),
        p2: Point::new(1.0, 1.0),
    };

    // 报错！ `rectangle` 是不可变的，但这方法需要一个可变对象
    //rectangle.translate(1.0, 0.0);
    // 试一试 ^ 将此行注释去掉

    // 正常运行！可变对象可以调用可变方法
    square.translate(1.0, 1.0);

    let pair = Pair(Box::new(1), Box::new(2));

    pair.destroy();

    // 报错！前面的 `destroy` 调用“消费了” `pair`
    //pair.destroy();
    // 试一试 ^ 将此行注释去掉
}
<commit_msg>Typo fix<commit_after>struct Point {
    x: f64,
    y: f64,
}

// 实现的代码块，所有的 `Point` 方法都在这里给出
impl Point {
    // 这是一个静态方法（static method）
    // 静态方法不需要通过实例来调用
    // 这类方法一般用作构造器（constructor）
    fn origin() -> Point {
        Point { x: 0.0, y: 0.0 }
    }

    // 另外一个静态方法，带有两个参数：
    fn new(x: f64, y: f64) -> Point {
        Point { x: x, y: y }
    }
}

struct Rectangle {
    p1: Point,
    p2: Point,
}

impl Rectangle {
    // 这是实例方法（instance method）
    // `&self` 是 `self: &Self` 的语法糖（sugar），其中 `Self` 是所调用对象
    // 的类型。在这个例子中 `Self` = `Rectangle`
    fn area(&self) -> f64 {
        // `self` 通过点运算符来访问结构体字段
        let Point { x: x1, y: y1 } = self.p1;
        let Point { x: x2, y: y2 } = self.p2;

        // `abs` 是一个 `f64` 类型的方法，返回调用者的绝对值
        ((x1 - x2) * (y1 - y2)).abs()
    }

    fn perimeter(&self) -> f64 {
        let Point { x: x1, y: y1 } = self.p1;
        let Point { x: x2, y: y2 } = self.p2;

        2.0 * ((x1 - x2).abs() + (y1 - y2).abs())
    }

    // 这个方法要求调用者对象是可变的
    // `&mut self` 为 `self: &mut Self` 的语法糖
    fn translate(&mut self, x: f64, y: f64) {
        self.p1.x += x;
        self.p2.x += x;

        self.p1.y += y;
        self.p2.y += y;
    }
}

// `Pair` 含有的资源：两个堆分配的整型
struct Pair(Box<i32>, Box<i32>);

impl Pair {
    // 这个方法“消费”调用者对象的资源
    // `self` 为 `self: Self` 的语法糖
    fn destroy(self) {
        // 解构 `self`
        let Pair(first, second) = self;

        println!("Destroying Pair({}, {})", first, second);

        // `first` 和 `second` 离开作用域后释放
    }
}

fn main() {
    let rectangle = Rectangle {
        // 静态方法使用双重冒号来调用
        p1: Point::origin(),
        p2: Point::new(3.0, 4.0),
    };

    // 实例方法通过点运算符来调用
    // 注意第一个参数 `&self` 是隐式传递的，比如：
    // `rectangle.perimeter()` === `Rectangle::perimeter(&rectangle)`
    println!("Rectangle perimeter: {}", rectangle.perimeter());
    println!("Rectangle area: {}", rectangle.area());

    let mut square = Rectangle {
        p1: Point::origin(),
        p2: Point::new(1.0, 1.0),
    };

    // 报错！ `rectangle` 是不可变的，但这方法需要一个可变对象
    //rectangle.translate(1.0, 0.0);
    // 试一试 ^ 将此行注释去掉

    // 正常运行！可变对象可以调用可变方法
    square.translate(1.0, 1.0);

    let pair = Pair(Box::new(1), Box::new(2));

    pair.destroy();

    // 报错！前面的 `destroy` 调用“消费了” `pair`
    //pair.destroy();
    // 试一试 ^ 将此行注释去掉
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Simple counting bloom filters.

use fnv::FnvHasher;
use std::hash::{Hash, Hasher};

// The top 12 bits of the 32-bit hash value are not used by the bloom filter.
// Consumers may rely on this to pack hashes more efficiently.
pub const BLOOM_HASH_MASK: u32 = 0x00ffffff;
const KEY_SIZE: usize = 12;

const ARRAY_SIZE: usize = 1 << KEY_SIZE;
const KEY_MASK: u32 = (1 << KEY_SIZE) - 1;

/// A counting Bloom filter with 8-bit counters.  For now we assume
/// that having two hash functions is enough, but we may revisit that
/// decision later.
///
/// The filter uses an array with 2**KeySize entries.
///
/// Assuming a well-distributed hash function, a Bloom filter with
/// array size M containing N elements and
/// using k hash function has expected false positive rate exactly
///
/// $  (1 - (1 - 1/M)^{kN})^k  $
///
/// because each array slot has a
///
/// $  (1 - 1/M)^{kN}  $
///
/// chance of being 0, and the expected false positive rate is the
/// probability that all of the k hash functions will hit a nonzero
/// slot.
///
/// For reasonable assumptions (M large, kN large, which should both
/// hold if we're worried about false positives) about M and kN this
/// becomes approximately
///
/// $$  (1 - \exp(-kN/M))^k   $$
///
/// For our special case of k == 2, that's $(1 - \exp(-2N/M))^2$,
/// or in other words
///
/// $$    N/M = -0.5 * \ln(1 - \sqrt(r))   $$
///
/// where r is the false positive rate.  This can be used to compute
/// the desired KeySize for a given load N and false positive rate r.
///
/// If N/M is assumed small, then the false positive rate can
/// further be approximated as 4*N^2/M^2.  So increasing KeySize by
/// 1, which doubles M, reduces the false positive rate by about a
/// factor of 4, and a false positive rate of 1% corresponds to
/// about M/N == 20.
///
/// What this means in practice is that for a few hundred keys using a
/// KeySize of 12 gives false positive rates on the order of 0.25-4%.
///
/// Similarly, using a KeySize of 10 would lead to a 4% false
/// positive rate for N == 100 and to quite bad false positive
/// rates for larger N.
pub struct BloomFilter {
    counters: [u8; ARRAY_SIZE],
}

impl Clone for BloomFilter {
    #[inline]
    fn clone(&self) -> BloomFilter {
        BloomFilter {
            counters: self.counters,
        }
    }
}

impl BloomFilter {
    /// Creates a new bloom filter.
    #[inline]
    pub fn new() -> BloomFilter {
        BloomFilter {
            counters: [0; ARRAY_SIZE],
        }
    }

    #[inline]
    fn first_slot(&self, hash: u32) -> &u8 {
        &self.counters[hash1(hash) as usize]
    }

    #[inline]
    fn first_mut_slot(&mut self, hash: u32) -> &mut u8 {
        &mut self.counters[hash1(hash) as usize]
    }

    #[inline]
    fn second_slot(&self, hash: u32) -> &u8 {
        &self.counters[hash2(hash) as usize]
    }

    #[inline]
    fn second_mut_slot(&mut self, hash: u32) -> &mut u8 {
        &mut self.counters[hash2(hash) as usize]
    }

    #[inline]
    pub fn clear(&mut self) {
        self.counters = [0; ARRAY_SIZE]
    }

    #[inline]
    pub fn insert_hash(&mut self, hash: u32) {
        {
            let slot1 = self.first_mut_slot(hash);
            if !full(slot1) {
                *slot1 += 1
            }
        }
        {
            let slot2 = self.second_mut_slot(hash);
            if !full(slot2) {
                *slot2 += 1
            }
        }
    }

    /// Inserts an item into the bloom filter.
    #[inline]
    pub fn insert<T: Hash>(&mut self, elem: &T) {
        self.insert_hash(hash(elem))
    }

    #[inline]
    pub fn remove_hash(&mut self, hash: u32) {
        {
            let slot1 = self.first_mut_slot(hash);
            if !full(slot1) {
                *slot1 -= 1
            }
        }
        {
            let slot2 = self.second_mut_slot(hash);
            if !full(slot2) {
                *slot2 -= 1
            }
        }
    }

    /// Removes an item from the bloom filter.
    #[inline]
    pub fn remove<T: Hash>(&mut self, elem: &T) {
        self.remove_hash(hash(elem))
    }

    #[inline]
    pub fn might_contain_hash(&self, hash: u32) -> bool {
        *self.first_slot(hash) != 0 && *self.second_slot(hash) != 0
    }

    /// Check whether the filter might contain an item.  This can
    /// sometimes return true even if the item is not in the filter,
    /// but will never return false for items that are actually in the
    /// filter.
    #[inline]
    pub fn might_contain<T: Hash>(&self, elem: &T) -> bool {
        self.might_contain_hash(hash(elem))
    }
}

#[inline]
fn full(slot: &u8) -> bool {
    *slot == 0xff
}

fn hash<T: Hash>(elem: &T) -> u32 {
    let mut hasher = FnvHasher::default();
    elem.hash(&mut hasher);
    let hash: u64 = hasher.finish();
    (hash >> 32) as u32 ^ (hash as u32)
}

#[inline]
fn hash1(hash: u32) -> u32 {
    hash & KEY_MASK
}

#[inline]
fn hash2(hash: u32) -> u32 {
    (hash >> KEY_SIZE) & KEY_MASK
}

#[test]
fn create_and_insert_some_stuff() {
    let mut bf = BloomFilter::new();

    for i in 0_usize .. 1000 {
        bf.insert(&i);
    }

    for i in 0_usize .. 1000 {
        assert!(bf.might_contain(&i));
    }

    let false_positives =
        (1001_usize .. 2000).filter(|i| bf.might_contain(i)).count();

    assert!(false_positives < 150, "{} is not < 150", false_positives); // 15%.

    for i in 0_usize .. 100 {
        bf.remove(&i);
    }

    for i in 100_usize .. 1000 {
        assert!(bf.might_contain(&i));
    }

    let false_positives = (0_usize .. 100).filter(|i| bf.might_contain(i)).count();

    assert!(false_positives < 20, "{} is not < 20", false_positives); // 20%.

    bf.clear();

    for i in 0_usize .. 2000 {
        assert!(!bf.might_contain(&i));
    }
}

#[cfg(feature = "unstable")]
#[cfg(test)]
mod bench {
    extern crate test;

    use std::hash::{Hash, Hasher, SipHasher};
    use super::BloomFilter;

    #[bench]
    fn create_insert_1000_remove_100_lookup_100(b: &mut test::Bencher) {
        b.iter(|| {
            let mut bf = BloomFilter::new();
            for i in 0_usize .. 1000 {
                bf.insert(&i);
            }
            for i in 0_usize .. 100 {
                bf.remove(&i);
            }
            for i in 100_usize .. 200 {
                test::black_box(bf.might_contain(&i));
            }
        });
    }

    #[bench]
    fn might_contain(b: &mut test::Bencher) {
        let mut bf = BloomFilter::new();

        for i in 0_usize .. 1000 {
            bf.insert(&i);
        }

        let mut i = 0_usize;

        b.bench(|b| {
            b.iter(|| {
                test::black_box(bf.might_contain(&i));
                i += 1;
            });
        });
    }

    #[bench]
    fn insert(b: &mut test::Bencher) {
        let mut bf = BloomFilter::new();

        b.bench(|b| {
            let mut i = 0_usize;

            b.iter(|| {
                test::black_box(bf.insert(&i));
                i += 1;
            });
        });
    }

    #[bench]
    fn remove(b: &mut test::Bencher) {
        let mut bf = BloomFilter::new();
        for i in 0_usize .. 1000 {
            bf.insert(&i);
        }

        b.bench(|b| {
            let mut i = 0_usize;

            b.iter(|| {
                bf.remove(&i);
                i += 1;
            });
        });

        test::black_box(bf.might_contain(&0_usize));
    }

    #[bench]
    fn hash_a_uint(b: &mut test::Bencher) {
        let mut i = 0_usize;
        b.iter(|| {
            let mut hasher = SipHasher::default();
            i.hash(&mut hasher);
            test::black_box(hasher.finish());
            i += 1;
        })
    }
}
<commit_msg>Improve bloom microbenchmarks.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Simple counting bloom filters.

use fnv::FnvHasher;
use std::hash::{Hash, Hasher};

// The top 12 bits of the 32-bit hash value are not used by the bloom filter.
// Consumers may rely on this to pack hashes more efficiently.
pub const BLOOM_HASH_MASK: u32 = 0x00ffffff;
const KEY_SIZE: usize = 12;

const ARRAY_SIZE: usize = 1 << KEY_SIZE;
const KEY_MASK: u32 = (1 << KEY_SIZE) - 1;

/// A counting Bloom filter with 8-bit counters.  For now we assume
/// that having two hash functions is enough, but we may revisit that
/// decision later.
///
/// The filter uses an array with 2**KeySize entries.
///
/// Assuming a well-distributed hash function, a Bloom filter with
/// array size M containing N elements and
/// using k hash function has expected false positive rate exactly
///
/// $  (1 - (1 - 1/M)^{kN})^k  $
///
/// because each array slot has a
///
/// $  (1 - 1/M)^{kN}  $
///
/// chance of being 0, and the expected false positive rate is the
/// probability that all of the k hash functions will hit a nonzero
/// slot.
///
/// For reasonable assumptions (M large, kN large, which should both
/// hold if we're worried about false positives) about M and kN this
/// becomes approximately
///
/// $$  (1 - \exp(-kN/M))^k   $$
///
/// For our special case of k == 2, that's $(1 - \exp(-2N/M))^2$,
/// or in other words
///
/// $$    N/M = -0.5 * \ln(1 - \sqrt(r))   $$
///
/// where r is the false positive rate.  This can be used to compute
/// the desired KeySize for a given load N and false positive rate r.
///
/// If N/M is assumed small, then the false positive rate can
/// further be approximated as 4*N^2/M^2.  So increasing KeySize by
/// 1, which doubles M, reduces the false positive rate by about a
/// factor of 4, and a false positive rate of 1% corresponds to
/// about M/N == 20.
///
/// What this means in practice is that for a few hundred keys using a
/// KeySize of 12 gives false positive rates on the order of 0.25-4%.
///
/// Similarly, using a KeySize of 10 would lead to a 4% false
/// positive rate for N == 100 and to quite bad false positive
/// rates for larger N.
pub struct BloomFilter {
    counters: [u8; ARRAY_SIZE],
}

impl Clone for BloomFilter {
    #[inline]
    fn clone(&self) -> BloomFilter {
        BloomFilter {
            counters: self.counters,
        }
    }
}

impl BloomFilter {
    /// Creates a new bloom filter.
    #[inline]
    pub fn new() -> BloomFilter {
        BloomFilter {
            counters: [0; ARRAY_SIZE],
        }
    }

    #[inline]
    fn first_slot(&self, hash: u32) -> &u8 {
        &self.counters[hash1(hash) as usize]
    }

    #[inline]
    fn first_mut_slot(&mut self, hash: u32) -> &mut u8 {
        &mut self.counters[hash1(hash) as usize]
    }

    #[inline]
    fn second_slot(&self, hash: u32) -> &u8 {
        &self.counters[hash2(hash) as usize]
    }

    #[inline]
    fn second_mut_slot(&mut self, hash: u32) -> &mut u8 {
        &mut self.counters[hash2(hash) as usize]
    }

    #[inline]
    pub fn clear(&mut self) {
        self.counters = [0; ARRAY_SIZE]
    }

    #[inline]
    pub fn insert_hash(&mut self, hash: u32) {
        {
            let slot1 = self.first_mut_slot(hash);
            if !full(slot1) {
                *slot1 += 1
            }
        }
        {
            let slot2 = self.second_mut_slot(hash);
            if !full(slot2) {
                *slot2 += 1
            }
        }
    }

    /// Inserts an item into the bloom filter.
    #[inline]
    pub fn insert<T: Hash>(&mut self, elem: &T) {
        self.insert_hash(hash(elem))
    }

    #[inline]
    pub fn remove_hash(&mut self, hash: u32) {
        {
            let slot1 = self.first_mut_slot(hash);
            if !full(slot1) {
                *slot1 -= 1
            }
        }
        {
            let slot2 = self.second_mut_slot(hash);
            if !full(slot2) {
                *slot2 -= 1
            }
        }
    }

    /// Removes an item from the bloom filter.
    #[inline]
    pub fn remove<T: Hash>(&mut self, elem: &T) {
        self.remove_hash(hash(elem))
    }

    #[inline]
    pub fn might_contain_hash(&self, hash: u32) -> bool {
        *self.first_slot(hash) != 0 && *self.second_slot(hash) != 0
    }

    /// Check whether the filter might contain an item.  This can
    /// sometimes return true even if the item is not in the filter,
    /// but will never return false for items that are actually in the
    /// filter.
    #[inline]
    pub fn might_contain<T: Hash>(&self, elem: &T) -> bool {
        self.might_contain_hash(hash(elem))
    }
}

#[inline]
fn full(slot: &u8) -> bool {
    *slot == 0xff
}

fn hash<T: Hash>(elem: &T) -> u32 {
    let mut hasher = FnvHasher::default();
    elem.hash(&mut hasher);
    let hash: u64 = hasher.finish();
    (hash >> 32) as u32 ^ (hash as u32)
}

#[inline]
fn hash1(hash: u32) -> u32 {
    hash & KEY_MASK
}

#[inline]
fn hash2(hash: u32) -> u32 {
    (hash >> KEY_SIZE) & KEY_MASK
}

#[test]
fn create_and_insert_some_stuff() {
    let mut bf = BloomFilter::new();

    for i in 0_usize .. 1000 {
        bf.insert(&i);
    }

    for i in 0_usize .. 1000 {
        assert!(bf.might_contain(&i));
    }

    let false_positives =
        (1001_usize .. 2000).filter(|i| bf.might_contain(i)).count();

    assert!(false_positives < 150, "{} is not < 150", false_positives); // 15%.

    for i in 0_usize .. 100 {
        bf.remove(&i);
    }

    for i in 100_usize .. 1000 {
        assert!(bf.might_contain(&i));
    }

    let false_positives = (0_usize .. 100).filter(|i| bf.might_contain(i)).count();

    assert!(false_positives < 20, "{} is not < 20", false_positives); // 20%.

    bf.clear();

    for i in 0_usize .. 2000 {
        assert!(!bf.might_contain(&i));
    }
}

#[cfg(feature = "unstable")]
#[cfg(test)]
mod bench {
    extern crate test;
    use super::BloomFilter;

    #[derive(Default)]
    struct HashGenerator(u32);

    impl HashGenerator {
        fn next(&mut self) -> u32 {
            // Each hash is split into two twelve-bit segments, which are used
            // as an index into an array. We increment each by 64 so that we
            // hit the next cache line, and then another 1 so that our wrapping
            // behavior leads us to different entries each time.
            //
            // Trying to simulate cold caches is rather difficult with the cargo
            // benchmarking setup, so it may all be moot depending on the number
            // of iterations that end up being run. But we might as well.
            self.0 += (65) + (65 << super::KEY_SIZE);
            self.0
        }
    }

    #[bench]
    fn create_insert_1000_remove_100_lookup_100(b: &mut test::Bencher) {
        b.iter(|| {
            let mut gen1 = HashGenerator::default();
            let mut gen2 = HashGenerator::default();
            let mut bf = BloomFilter::new();
            for _ in 0_usize .. 1000 {
                bf.insert_hash(gen1.next());
            }
            for _ in 0_usize .. 100 {
                bf.remove_hash(gen2.next());
            }
            for _ in 100_usize .. 200 {
                test::black_box(bf.might_contain_hash(gen2.next()));
            }
        });
    }

    #[bench]
    fn might_contain_10(b: &mut test::Bencher) {
        let bf = BloomFilter::new();
        let mut gen = HashGenerator::default();
        b.iter(|| for _ in 0..10 {
            test::black_box(bf.might_contain_hash(gen.next()));
        });
    }

    #[bench]
    fn clear(b: &mut test::Bencher) {
        let mut bf = Box::new(BloomFilter::new());
        b.iter(|| test::black_box(&mut bf).clear());
    }

    #[bench]
    fn insert_10(b: &mut test::Bencher) {
        let mut bf = BloomFilter::new();
        let mut gen = HashGenerator::default();
        b.iter(|| for _ in 0..10 {
            test::black_box(bf.insert_hash(gen.next()));
        });
    }

    #[bench]
    fn remove_10(b: &mut test::Bencher) {
        let mut bf = BloomFilter::new();
        let mut gen = HashGenerator::default();
        // Note: this will underflow, and that's ok.
        b.iter(|| for _ in 0..10 {
            bf.remove_hash(gen.next())
        });
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

use aws_config::meta::region::RegionProviderChain;
use aws_sdk_ecs::{Error, Region};
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
struct Opt {
    /// The AWS Region.
    #[structopt(short, long)]
    region: Option<String>,

    /// The name of the cluster.
    #[structopt(short, long)]
    name: String,

    /// Whether to display additional information.
    #[structopt(short, long)]
    verbose: bool,
}

// Create and delete a cluster.
// snippet-start:[ecs.rust.cluster]
async fn cluster_ops(client: &aws_sdk_ecs::Client, name: &str) -> Result<(), aws_sdk_ecs::Error> {
    let cluster = client.create_cluster().cluster_name(name).send().await?;
    println!("cluster created: {:?}", cluster);

    let cluster_deleted = client.delete_cluster().cluster(name).send().await?;
    println!("cluster deleted: {:?}", cluster_deleted);
    Ok(())
}
// snippet-end:[ecs.rust.cluster]

/// Creates and deletes an Amazon Elastic Container Service cluster in the Region.
/// # Arguments
///
/// * `-n NAME]` - The name of the cluster.
/// * `[-r REGION]` - The Region in which the client is created.
///   If not supplied, uses the value of the **AWS_REGION** environment variable.
///   If the environment variable is not set, defaults to **us-west-2**.
/// * `[-v]` - Whether to display additional information.
#[tokio::main]
async fn main() -> Result<(), Error> {
    let Opt {
        name,
        region,
        verbose,
    } = Opt::from_args();

    if verbose {
        tracing_subscriber::fmt::init();
    }

    let region_provider = RegionProviderChain::first_try(region.map(Region::new))
        .or_default_provider()
        .or_else(Region::new("us-west-2"));

    let shared_config = aws_config::from_env().region(region_provider).load().await;
    let client = aws_sdk_ecs::Client::new(&shared_config);

    cluster_ops(&client, &name).await
}
<commit_msg>Updated ECS code example in Rust to use separate functions for creating and deleting a cluster<commit_after>/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

use aws_config::meta::region::RegionProviderChain;
use aws_sdk_ecs::{Error, Region};
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
struct Opt {
    /// The AWS Region.
    #[structopt(short, long)]
    region: Option<String>,

    /// The name of the cluster.
    #[structopt(short, long)]
    name: String,

    /// Whether to display additional information.
    #[structopt(short, long)]
    verbose: bool,
}

// Create a cluster.
// snippet-start:[ecs.rust.cluster-create]
async fn make_cluster(client: &aws_sdk_ecs::Client, name: &str) -> Result<(), aws_sdk_ecs::Error> {
    let cluster = client.create_cluster().cluster_name(name).send().await?;
    println!("cluster created: {:?}", cluster);

    Ok(())
}
// snippet-end:[ecs.rust.cluster-create]

// Delete a cluster.
// snippet-start:[ecs.rust.cluster-delete]
async fn remove_cluster(
    client: &aws_sdk_ecs::Client,
    name: &str,
) -> Result<(), aws_sdk_ecs::Error> {
    let cluster_deleted = client.delete_cluster().cluster(name).send().await?;
    println!("cluster deleted: {:?}", cluster_deleted);

    Ok(())
}
// snippet-end:[ecs.rust.cluster-delete]

/// Creates and deletes an Amazon Elastic Container Service cluster in the Region.
/// # Arguments
///
/// * `-n NAME]` - The name of the cluster.
/// * `[-r REGION]` - The Region in which the client is created.
///   If not supplied, uses the value of the **AWS_REGION** environment variable.
///   If the environment variable is not set, defaults to **us-west-2**.
/// * `[-v]` - Whether to display additional information.
#[tokio::main]
async fn main() -> Result<(), Error> {
    let Opt {
        name,
        region,
        verbose,
    } = Opt::from_args();

    if verbose {
        tracing_subscriber::fmt::init();
    }

    let region_provider = RegionProviderChain::first_try(region.map(Region::new))
        .or_default_provider()
        .or_else(Region::new("us-west-2"));

    let shared_config = aws_config::from_env().region(region_provider).load().await;
    let client = aws_sdk_ecs::Client::new(&shared_config);

    make_cluster(&client, &name).await?;
    remove_cluster(&client, &name).await
}
<|endoftext|>


<commit_before>extern crate neat;
extern crate rand;
extern crate graph_neighbor_matching;
extern crate graph_io_gml as gml;
extern crate closed01;

use neat::population::{Population, Unrated, Runner};
use neat::network::{NetworkGenome, NetworkGenomeDistance, NodeType, Environment,
                    LinkWeightStrategy};
use neat::fitness::Fitness;
use neat::traits::Mate;
use neat::crossover::ProbabilisticCrossover;
use neat::prob::is_probable;
use graph_neighbor_matching::{SimilarityMatrix, ScoreNorm, NodeColorMatching};
use graph_neighbor_matching::graph::{OwnedGraph, GraphBuilder};
use rand::{Rng, Closed01};
use std::marker::PhantomData;
use neat::mutate::{MutateMethod, MutateMethodWeighting};

fn load_graph(graph_file: &str) -> OwnedGraph<NodeType> {
    use std::fs::File;
    use std::io::Read;

    let graph_s = {
        let mut graph_file = File::open(graph_file).unwrap();
        let mut graph_s = String::new();
        let _ = graph_file.read_to_string(&mut graph_s).unwrap();
        graph_s
    };

    let graph = gml::parse_gml(&graph_s,
                               &|sexp| -> Option<NodeType> {
                                   sexp.and_then(|se| {
                                       se.get_str().map(|s| {
                                           match s {
                                               "input" => NodeType::Input,
                                               "output" => NodeType::Output,
                                               "hidden" => NodeType::Hidden,
                                               _ => panic!("Invalid node type/weight"),
                                           }
                                       })
                                   })
                               },
                               &|_| -> Option<()> { Some(()) })
                    .unwrap();
    OwnedGraph::from_petgraph(&graph)
}

fn genome_to_graph(genome: &NetworkGenome) -> OwnedGraph<NodeType> {
    let mut builder = GraphBuilder::new();

    for (&innov, node) in genome.node_genes.map.iter() {
        // make sure the node exists, even if there are no connection to it.
        let _ = builder.add_node(innov.get(), node.node_type);
    }

    for link in genome.link_genes.map.values() {
        if link.active {
            builder.add_edge_unweighted(link.source_node_gene.get(), link.target_node_gene.get());
        }
    }

    return builder.graph();
}

#[derive(Debug)]
struct FitnessEvaluator {
    target_graph: OwnedGraph<NodeType>,
}

#[derive(Debug)]
struct NodeColors;

impl NodeColorMatching<NodeType> for NodeColors {
    fn node_color_matching(&self,
                           node_i_value: &NodeType,
                           node_j_value: &NodeType)
                           -> closed01::Closed01<f32> {
        if node_i_value == node_j_value {
            closed01::Closed01::one()
        } else {
            closed01::Closed01::zero()
        }
    }
}

impl FitnessEvaluator {
    // A larger fitness means "better"
    fn fitness(&self, genome: &NetworkGenome) -> f32 {
        let graph = genome_to_graph(genome);
        let mut s = SimilarityMatrix::new(&graph, &self.target_graph, NodeColors);
        s.iterate(50, 0.01);
        s.score_optimal_sum_norm(None, ScoreNorm::MaxDegree).get()
    }
}

#[derive(Debug)]
struct LinkWeightS;

impl LinkWeightStrategy for LinkWeightS {}

const POP_SIZE: usize = 100;
const INPUTS: usize = 2;
const OUTPUTS: usize = 3;

struct Mater<'a, T: LinkWeightStrategy + 'a> {
    // probability for crossover. P_mutate = 1.0 - p_crossover
    p_crossover: Closed01<f32>,
    env: &'a mut Environment<T>,
}

impl<'a, T: LinkWeightStrategy> Mate<NetworkGenome> for Mater<'a, T> {
    // Add an argument that descibes whether both genomes are of equal fitness.
    // Pass individual, which includes the fitness.
    fn mate<R: Rng>(&mut self,
                    parent_left: &NetworkGenome,
                    parent_right: &NetworkGenome,
                    rng: &mut R)
                    -> NetworkGenome {
        if is_probable(&self.p_crossover, rng) {
            let x = ProbabilisticCrossover {
                prob_match_left: Closed01(0.5), /* NEAT always selects a random parent for matching genes */
                prob_disjoint_left: Closed01(0.9),
                prob_excess_left: Closed01(0.9),
                prob_disjoint_right: Closed01(0.15),
                prob_excess_right: Closed01(0.15),
            };
            NetworkGenome::crossover(parent_left, parent_right, &x, rng)
        } else {
            // mutate
            let p = MutateMethodWeighting {
                w_modify_weight: 1,
                w_add_node: 1,
                w_add_connection: 1,
            };
            let mutate_method = MutateMethod::random_with(&p, rng);
            self.env.mutate(parent_left, mutate_method, rng).
                or_else(|| self.env.mutate(parent_right, mutate_method, rng)).
                unwrap_or_else(|| parent_left.clone())
        }
    }
}

fn main() {
    let mut rng = rand::thread_rng();

    let fitness_evaluator = FitnessEvaluator { target_graph: load_graph("examples/jeffress.gml") };
    println!("{:?}", fitness_evaluator);

    // start with minimal random topology.
    let mut env: Environment<LinkWeightS> = Environment::new();

    let template_genome = env.generate_genome(INPUTS, OUTPUTS);

    println!("{:#?}", template_genome);

    let mut initial_pop = Population::<_, Unrated>::new();

    for _ in 0..POP_SIZE {
        // Add a single link gene! This is required, otherwise we can't determine
        // correctly an InnovationRange.
        let genome = env.mutate_add_connection(&template_genome, &mut rng).unwrap();

        initial_pop.add_genome(Box::new(genome));
    }
    assert!(initial_pop.len() == POP_SIZE);

    let mut mater = Mater {
        p_crossover: Closed01(0.5),
        env: &mut env,
    };

    let compatibility = NetworkGenomeDistance {
        excess: 1.0,
        disjoint: 1.0,
        weight: 0.0,
    };

    let mut runner = Runner {
        pop_size: POP_SIZE,
        elite_percentage: Closed01(0.05),
        selection_percentage: Closed01(0.2),
        tournament_k: 3,
        compatibility_threshold: 1.0,
        compatibility: &compatibility,
        mate: &mut mater,
        fitness: &|genome| Fitness::new(fitness_evaluator.fitness(genome) as f64),
        _marker: PhantomData,
    };

    let (iter, new_pop) = runner.run(initial_pop,
                                     &|iter, pop| {
                                         iter >= 100 || pop.max_fitness().unwrap().get() > 0.99
                                     },
                                     &mut rng);

    let new_pop = new_pop.sort();

    println!("iter: {}", iter);
    println!("{:#?}", new_pop);
}
<commit_msg>Move probabilities out of method mate()<commit_after>extern crate neat;
extern crate rand;
extern crate graph_neighbor_matching;
extern crate graph_io_gml as gml;
extern crate closed01;

use neat::population::{Population, Unrated, Runner};
use neat::network::{NetworkGenome, NetworkGenomeDistance, NodeType, Environment,
                    LinkWeightStrategy};
use neat::fitness::Fitness;
use neat::traits::Mate;
use neat::crossover::ProbabilisticCrossover;
use neat::prob::is_probable;
use graph_neighbor_matching::{SimilarityMatrix, ScoreNorm, NodeColorMatching};
use graph_neighbor_matching::graph::{OwnedGraph, GraphBuilder};
use rand::{Rng, Closed01};
use std::marker::PhantomData;
use neat::mutate::{MutateMethod, MutateMethodWeighting};

fn load_graph(graph_file: &str) -> OwnedGraph<NodeType> {
    use std::fs::File;
    use std::io::Read;

    let graph_s = {
        let mut graph_file = File::open(graph_file).unwrap();
        let mut graph_s = String::new();
        let _ = graph_file.read_to_string(&mut graph_s).unwrap();
        graph_s
    };

    let graph = gml::parse_gml(&graph_s,
                               &|sexp| -> Option<NodeType> {
                                   sexp.and_then(|se| {
                                       se.get_str().map(|s| {
                                           match s {
                                               "input" => NodeType::Input,
                                               "output" => NodeType::Output,
                                               "hidden" => NodeType::Hidden,
                                               _ => panic!("Invalid node type/weight"),
                                           }
                                       })
                                   })
                               },
                               &|_| -> Option<()> { Some(()) })
                    .unwrap();
    OwnedGraph::from_petgraph(&graph)
}

fn genome_to_graph(genome: &NetworkGenome) -> OwnedGraph<NodeType> {
    let mut builder = GraphBuilder::new();

    for (&innov, node) in genome.node_genes.map.iter() {
        // make sure the node exists, even if there are no connection to it.
        let _ = builder.add_node(innov.get(), node.node_type);
    }

    for link in genome.link_genes.map.values() {
        if link.active {
            builder.add_edge_unweighted(link.source_node_gene.get(), link.target_node_gene.get());
        }
    }

    return builder.graph();
}

#[derive(Debug)]
struct FitnessEvaluator {
    target_graph: OwnedGraph<NodeType>,
}

#[derive(Debug)]
struct NodeColors;

impl NodeColorMatching<NodeType> for NodeColors {
    fn node_color_matching(&self,
                           node_i_value: &NodeType,
                           node_j_value: &NodeType)
                           -> closed01::Closed01<f32> {
        if node_i_value == node_j_value {
            closed01::Closed01::one()
        } else {
            closed01::Closed01::zero()
        }
    }
}

impl FitnessEvaluator {
    // A larger fitness means "better"
    fn fitness(&self, genome: &NetworkGenome) -> f32 {
        let graph = genome_to_graph(genome);
        let mut s = SimilarityMatrix::new(&graph, &self.target_graph, NodeColors);
        s.iterate(50, 0.01);
        s.score_optimal_sum_norm(None, ScoreNorm::MaxDegree).get()
    }
}

#[derive(Debug)]
struct LinkWeightS;

impl LinkWeightStrategy for LinkWeightS {}

const POP_SIZE: usize = 100;
const INPUTS: usize = 2;
const OUTPUTS: usize = 3;

struct Mater<'a, T: LinkWeightStrategy + 'a> {
    // probability for crossover. P_mutate = 1.0 - p_crossover
    p_crossover: Closed01<f32>,
    p_crossover_detail: ProbabilisticCrossover,
    mutate_weights: MutateMethodWeighting,
    env: &'a mut Environment<T>,
}

impl<'a, T: LinkWeightStrategy> Mate<NetworkGenome> for Mater<'a, T> {
    // Add an argument that descibes whether both genomes are of equal fitness.
    // Pass individual, which includes the fitness.
    fn mate<R: Rng>(&mut self,
                    parent_left: &NetworkGenome,
                    parent_right: &NetworkGenome,
                    rng: &mut R)
                    -> NetworkGenome {
        if is_probable(&self.p_crossover, rng) {
            NetworkGenome::crossover(parent_left, parent_right, &self.p_crossover_detail, rng)
        } else {
            // mutate
            let mutate_method = MutateMethod::random_with(&self.mutate_weights, rng);
            self.env.mutate(parent_left, mutate_method, rng).
                or_else(|| self.env.mutate(parent_right, mutate_method, rng)).
                unwrap_or_else(|| parent_left.clone())
        }
    }
}

fn main() {
    let mut rng = rand::thread_rng();

    let fitness_evaluator = FitnessEvaluator { target_graph: load_graph("examples/jeffress.gml") };
    println!("{:?}", fitness_evaluator);

    // start with minimal random topology.
    let mut env: Environment<LinkWeightS> = Environment::new();

    let template_genome = env.generate_genome(INPUTS, OUTPUTS);

    println!("{:#?}", template_genome);

    let mut initial_pop = Population::<_, Unrated>::new();

    for _ in 0..POP_SIZE {
        // Add a single link gene! This is required, otherwise we can't determine
        // correctly an InnovationRange.
        let genome = env.mutate_add_connection(&template_genome, &mut rng).unwrap();

        initial_pop.add_genome(Box::new(genome));
    }
    assert!(initial_pop.len() == POP_SIZE);

    let mut mater = Mater {
        p_crossover: Closed01(0.5),
        p_crossover_detail: ProbabilisticCrossover {
                prob_match_left: Closed01(0.5), /* NEAT always selects a random parent for matching genes */
                prob_disjoint_left: Closed01(0.9),
                prob_excess_left: Closed01(0.9),
                prob_disjoint_right: Closed01(0.15),
                prob_excess_right: Closed01(0.15),
            },
        mutate_weights: MutateMethodWeighting {
            w_modify_weight: 1,
            w_add_node: 1,
            w_add_connection: 1,
        },

        env: &mut env,
    };

    let compatibility = NetworkGenomeDistance {
        excess: 1.0,
        disjoint: 1.0,
        weight: 0.0,
    };

    let mut runner = Runner {
        pop_size: POP_SIZE,
        elite_percentage: Closed01(0.05),
        selection_percentage: Closed01(0.2),
        tournament_k: 3,
        compatibility_threshold: 1.0,
        compatibility: &compatibility,
        mate: &mut mater,
        fitness: &|genome| Fitness::new(fitness_evaluator.fitness(genome) as f64),
        _marker: PhantomData,
    };

    let (iter, new_pop) = runner.run(initial_pop,
                                     &|iter, pop| {
                                         iter >= 100 || pop.max_fitness().unwrap().get() > 0.99
                                     },
                                     &mut rng);

    let new_pop = new_pop.sort();

    println!("iter: {}", iter);
    println!("{:#?}", new_pop);
}
<|endoftext|>


<commit_before>extern crate three;
extern crate mint;
extern crate froggy;

use std::env;
use three::{Geometry, Object};
use mint::Point3;
use froggy::WeakPointer;

fn main() {
    let mut args = env::args();
    let obj_path = concat!(env!("CARGO_MANIFEST_DIR"), "/test_data/sample.stl");
    let path = args.nth(1).unwrap_or(obj_path.into());
    let mut vertices = vec!();

    match stlv::parser::load_file(path.as_str()) {
        Ok(model) => {
            for triangle in (*model).iter() {
                let stl_vertices = triangle.vertices();
                vertices.push(Point3 {
                    x: stl_vertices[0].get_x(),
                    y: stl_vertices[0].get_y(),
                    z: stl_vertices[0].get_z(),
                });
                vertices.push(Point3 {
                    x: stl_vertices[1].get_x(),
                    y: stl_vertices[1].get_y(),
                    z: stl_vertices[1].get_z(),
                });
                vertices.push(Point3 {
                    x: stl_vertices[2].get_x(),
                    y: stl_vertices[2].get_y(),
                    z: stl_vertices[2].get_z(),
                });
            }
        }
        _ => panic!("Failed to parse the STL file {}", path),
    }

    let geometry = Geometry::with_vertices(vertices);

    // Upload the triangle data to the GPU.
    let mut window = three::Window::new("Loading STL...");

    // Create multiple meshes with the same GPU data and material.
    let material = three::material::Wireframe{color: 0xff0000};

    let mesh = window.factory.mesh(geometry, material);
    window.scene.add(&mesh);

    let cam = window.factory.perspective_camera(60.0, 1.0 .. 1000.0);
    let mut controls = three::controls::Orbit::builder(&cam)
        .position([0.0, 2.0, -5.0])
        .target([0.0, 0.0, 0.0])
        .build();

    let dir_light = window.factory.directional_light(0xffffff, 0.9);
    dir_light.look_at([15.0, 35.0, 35.0], [0.0, 0.0, 2.0], None);
    window.scene.add(&dir_light);

    while window.update() && !window.input.hit(three::KEY_ESCAPE) {
        controls.update(&window.input);
        window.render(&cam);
    }
}
<commit_msg>Check for STL file path<commit_after>extern crate three;
extern crate mint;
extern crate froggy;

use std::env;
use three::{Geometry, Object};
use mint::Point3;
use froggy::WeakPointer;

fn main() {
    let mut args = env::args();
    let path = args.nth(1).expect("Please provide STL file path");
    let mut vertices = vec!();

    match stlv::parser::load_file(path.as_str()) {
        Ok(model) => {
            for triangle in (*model).iter() {
                let stl_vertices = triangle.vertices();
                vertices.push(Point3 {
                    x: stl_vertices[0].get_x(),
                    y: stl_vertices[0].get_y(),
                    z: stl_vertices[0].get_z(),
                });
                vertices.push(Point3 {
                    x: stl_vertices[1].get_x(),
                    y: stl_vertices[1].get_y(),
                    z: stl_vertices[1].get_z(),
                });
                vertices.push(Point3 {
                    x: stl_vertices[2].get_x(),
                    y: stl_vertices[2].get_y(),
                    z: stl_vertices[2].get_z(),
                });
            }
        }
        _ => panic!("Failed to parse the STL file {}", path),
    }

    let geometry = Geometry::with_vertices(vertices);

    // Upload the triangle data to the GPU.
    let mut window = three::Window::new("Loading STL...");

    // Create multiple meshes with the same GPU data and material.
    let material = three::material::Wireframe{color: 0xff0000};

    let mesh = window.factory.mesh(geometry, material);
    window.scene.add(&mesh);

    let cam = window.factory.perspective_camera(60.0, 1.0 .. 1000.0);
    let mut controls = three::controls::Orbit::builder(&cam)
        .position([0.0, 2.0, -5.0])
        .target([0.0, 0.0, 0.0])
        .build();

    let dir_light = window.factory.directional_light(0xffffff, 0.9);
    dir_light.look_at([15.0, 35.0, 35.0], [0.0, 0.0, 2.0], None);
    window.scene.add(&dir_light);

    while window.update() && !window.input.hit(three::KEY_ESCAPE) {
        controls.update(&window.input);
        window.render(&cam);
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use types::cef_base_t;

use libc::{self, c_int, c_void, size_t};
use std::mem;
use std::slice;
use std::str;

/// Allows you to downcast a CEF interface to a CEF class instance.
///
/// FIXME(pcwalton): This is currently unsafe. I think the right way to make this safe is to (a)
/// forbid more than one Rust implementation of a given interface (easy to do by manufacturing an
/// impl that will conflict if there is more than one) and then (b) add a dynamic check to make
/// sure the `release` for the object is equal to `servo_release`.
pub trait Downcast<Class> {
    fn downcast(&self) -> &Class;
}

pub fn slice_to_str<F>(s: *const u8, l: usize, f: F) -> c_int where F: FnOnce(&str) -> c_int {
    unsafe {
        let s = slice::from_raw_parts(s, l);
        str::from_utf8(s).map(f).unwrap_or(0)
    }
}

/// Creates a new raw CEF object of the given type and sets up its reference counting machinery.
/// All fields are initialized to zero. It is the caller's responsibility to ensure that the given
/// type is a CEF type with `cef_base_t` as its first member.
pub unsafe fn create_cef_object<Base,Extra>(size: size_t) -> *mut Base {
    let object = libc::calloc(1, (mem::size_of::<Base>() + mem::size_of::<Extra>()) as u64) as
        *mut cef_base_t;
    (*object).size = size;
    (*object).add_ref = Some(servo_add_ref as extern "C" fn(*mut cef_base_t) -> c_int);
    (*object).release = Some(servo_release as extern "C" fn(*mut cef_base_t) -> c_int);
    *ref_count(object) = 1;
    object as *mut Base
}

/// Returns a pointer to the Servo-specific reference count for the given object. This only works
/// on objects that Servo created!
unsafe fn ref_count(object: *mut cef_base_t) -> *mut usize {
    // The reference count should be the first field of the extra data.
    (object as *mut u8).offset((*object).size as isize) as *mut usize
}

/// Increments the reference count on a CEF object. This only works on objects that Servo created!
extern "C" fn servo_add_ref(object: *mut cef_base_t) -> c_int {
    unsafe {
        let count = ref_count(object);
        *count += 1;
        *count as c_int
    }
}

/// Decrements the reference count on a CEF object. If zero, frees it. This only works on objects
/// that Servo created!
extern "C" fn servo_release(object: *mut cef_base_t) -> c_int {
    unsafe {
        let count = ref_count(object);
        *count -= 1;
        let new_count = *count;
        if new_count == 0 {
            servo_free(object);
        }
        (new_count == 0) as c_int
    }
}

unsafe fn servo_free(object: *mut cef_base_t) {
    libc::free(object as *mut c_void);
}

pub unsafe fn add_ref(c_object: *mut cef_base_t) {
    ((*c_object).add_ref.unwrap())(c_object);
}

<commit_msg>add embedding function for checking whether the loaded cef lib is servo<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use types::cef_base_t;

use libc::{self, c_int, c_void, size_t};
use std::mem;
use std::slice;
use std::str;

/// Allows you to downcast a CEF interface to a CEF class instance.
///
/// FIXME(pcwalton): This is currently unsafe. I think the right way to make this safe is to (a)
/// forbid more than one Rust implementation of a given interface (easy to do by manufacturing an
/// impl that will conflict if there is more than one) and then (b) add a dynamic check to make
/// sure the `release` for the object is equal to `servo_release`.
pub trait Downcast<Class> {
    fn downcast(&self) -> &Class;
}

pub fn slice_to_str<F>(s: *const u8, l: usize, f: F) -> c_int where F: FnOnce(&str) -> c_int {
    unsafe {
        let s = slice::from_raw_parts(s, l);
        str::from_utf8(s).map(f).unwrap_or(0)
    }
}

/// Creates a new raw CEF object of the given type and sets up its reference counting machinery.
/// All fields are initialized to zero. It is the caller's responsibility to ensure that the given
/// type is a CEF type with `cef_base_t` as its first member.
pub unsafe fn create_cef_object<Base,Extra>(size: size_t) -> *mut Base {
    let object = libc::calloc(1, (mem::size_of::<Base>() + mem::size_of::<Extra>()) as u64) as
        *mut cef_base_t;
    (*object).size = size;
    (*object).add_ref = Some(servo_add_ref as extern "C" fn(*mut cef_base_t) -> c_int);
    (*object).release = Some(servo_release as extern "C" fn(*mut cef_base_t) -> c_int);
    *ref_count(object) = 1;
    object as *mut Base
}

/// Returns a pointer to the Servo-specific reference count for the given object. This only works
/// on objects that Servo created!
unsafe fn ref_count(object: *mut cef_base_t) -> *mut usize {
    // The reference count should be the first field of the extra data.
    (object as *mut u8).offset((*object).size as isize) as *mut usize
}

/// Increments the reference count on a CEF object. This only works on objects that Servo created!
extern "C" fn servo_add_ref(object: *mut cef_base_t) -> c_int {
    unsafe {
        let count = ref_count(object);
        *count += 1;
        *count as c_int
    }
}

/// Decrements the reference count on a CEF object. If zero, frees it. This only works on objects
/// that Servo created!
extern "C" fn servo_release(object: *mut cef_base_t) -> c_int {
    unsafe {
        let count = ref_count(object);
        *count -= 1;
        let new_count = *count;
        if new_count == 0 {
            servo_free(object);
        }
        (new_count == 0) as c_int
    }
}

unsafe fn servo_free(object: *mut cef_base_t) {
    libc::free(object as *mut c_void);
}

pub unsafe fn add_ref(c_object: *mut cef_base_t) {
    ((*c_object).add_ref.unwrap())(c_object);
}

pub extern "C" fn servo_test() -> c_int {
    1
}
<|endoftext|>


<commit_before>/*
  Copyright (c) 2015, Al Poole <netstar@gmail.com>

  Permission to use, copy, modify, and/or distribute this software for any
  purpose with or without fee is hereby granted, provided that the above
  copyright notice and this permission notice appear in all copies.

  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  PERFORMANCE OF THIS SOFTWARE.
*/

//   This is a HTTPS CONNECT proxy!

use std::string::{String};
use std::net::{SocketAddrV4,Ipv4Addr,TcpListener,TcpStream};
use std::io::{Write, Read};

const REQUEST_LEN: usize = 65535;

fn substr(buf: [u8;REQUEST_LEN], needle: &str, byte: u8) -> String
{
	let mut i = 0;
	let mut x = 0;
	let mut request = String::new();

	let srch = needle.as_bytes();

	if srch.len() == 0 {
		return request;
	}

	while buf[i] as char != '\0'  {
		if buf[i] as char == srch[0] as char {
			while x < srch.len() && buf[i] as char  == srch[x] as char {
				i = i + 1;
				x = x + 1;
			}
			break;
		} else {
			i = i + 1;
		}
	}

	if x == srch.len() {
		let mut end = i;
		while buf[end] as char != byte as char && buf[end] as char != '\n'
		{
			end = end + 1;

		}

		for y in i..end {
			request.push(buf[y] as char);
		}
	}

	return request;
}

const CHUNK: usize = 4096; // PAGESIZEish

fn talk_to_me(mut instream: &TcpStream, mut outstream: &TcpStream, mut headers: &Header) -> bool
{

	let mut buf = [0u8; CHUNK];

	println!("top");
	let bytes = instream.read(&mut buf).unwrap();
	if bytes <= 0 {
		return false;
	}

	println!("recv {}", bytes);

	for i in 0..bytes {
		print!("{}", buf[i] as char);
	}

	let mut chunk = 0;

	while chunk < bytes {
		let sent = outstream.write(&mut buf[0..bytes]).unwrap();
		if sent <= 0 {
			return false;
		}
		println!("sent {}", sent);
		chunk = chunk + sent;
	}
	true
}

struct Header {
	pub hostname: String,
	pub connection: String,
	pub proxy: String,
	pub agent: String,
}

impl Header {

pub fn new() -> Header
{
	let hostname	 = String::new();
	let connection   = String::new();
	let proxy	 = String::new();
	let agent	 = String::new();

	let h = Header
	{
		hostname: hostname,
		connection: connection,
		proxy: proxy,
		agent: agent
	};

	return h;
}

}

fn http_connect_request(instream: TcpStream, headers: Header)
{
	let bogus_fix = &format!("{}", headers.hostname);

	let outstream = TcpStream::connect::<(&str)>(bogus_fix).unwrap();
	let mut disconnected = false;

	let request = format!("HTTP/1.1 200 Connection established\r\nUser-Agent: {}\r\nProxy-Connection: {}\r\nConnection: {}\r\nHost: {}\r\n\r\n",
			headers.agent, headers.proxy, headers.connection, headers.hostname);

	let mut s = &instream;
	s.write(request.as_bytes()).unwrap(); // tell client the connection is made

	while ! disconnected {
		disconnected = talk_to_me(&instream, &outstream, &headers);
	}
}

fn check_headers(buffer: [u8;REQUEST_LEN], headers: &mut Header) -> bool
{
	let mut i = 0;

	while buffer[i] != '\0' as u8
	{
		print!("{}", buffer[i] as char);
		i+=1;
	}
	print!("\n");

	if headers.hostname.is_empty()
	{
		headers.hostname = substr(buffer, "Host: ", '\r' as u8);
	}

	if headers.connection.is_empty()
	{
		headers.connection = substr(buffer, "Connection: ", '\r' as u8);
	}

	if headers.proxy.is_empty()
	{
		headers.proxy = substr(buffer, "Proxy-Connection: ", '\r' as u8);
	}

	if headers.agent.is_empty()
	{
		headers.agent = substr(buffer, "User-Agent: ", '\r' as u8);
	}

	if ! headers.hostname.is_empty() && ! headers.connection.is_empty()
		&& ! headers.proxy.is_empty() && ! headers.agent.is_empty()
	{

		return true;
	}

	return false;
}

fn request_headers(mut instream: &TcpStream, headers: &mut Header)
{
	 loop
	{
		let mut buffer = [0u8; REQUEST_LEN];
		let mut byte = [0u8; 1];
		let mut len = 0;

		while byte[0] as char != '\n'
		{
			let bytes = instream.read(&mut byte).unwrap();
			buffer[len] = byte[0];
			len += bytes;
		}

		buffer[len] = '\0' as u8;

		if check_headers(buffer, headers) && len == 2
		{
			let mut i = 0;

			while i < REQUEST_LEN
			{
				buffer[i] = 0;
				i += 1;
			}
			return;
		}
	}

}

fn request_method(mut instream: &TcpStream) -> String
{
	let mut byte = [0u8;1];

	let mut method: String = String::new();

	// bit better for now it'll do!
	while byte[0] as char != ' '
	{
		instream.read(&mut byte).unwrap();
		if byte[0] as char != ' '
		{
			method.push(byte[0] as char);
		}
	}

	match method.as_ref()
	{
		"CONNECT" =>
		{
			return method;
		}

		"GET" | "POST" | "OPTIONS" | "HEAD" =>
		{
			return "".to_string();
			// all good do not return!!!
		}

		_ =>
		{
			return "".to_string();
		}
	}
}

fn proxy(stream: TcpStream) {
	let method = request_method(&stream);

	match method.as_ref()
	{
		"CONNECT" =>
		{
			let mut headers = Header::new();
			request_headers(&stream, &mut headers);

			http_connect_request(stream, headers);
		}

		_ =>
		{
			println!("REQUEST UNKNOWN");
		}
	}
}

extern crate threadpool;
use threadpool::ThreadPool;

fn proxy_time(port: u16, threads: usize) {
	let ip = Ipv4Addr::new(127, 0, 0, 1);
	let host = SocketAddrV4::new(ip, port);
	let listener = TcpListener::bind(host).unwrap();

	let pool = ThreadPool::new(threads);

	for stream in listener.incoming()
	{
		match stream
		{
			Ok(stream) =>
			{
				pool.execute(move || { proxy(stream); });
			}

			Err(_) =>
			{
				println!("NET error");
				1 << 7;
			}
		}
	}

	drop (listener);
}

fn main () {
	let threads = 128;
	let port: u16 = 9998;

	proxy_time(port, threads);
	println!("Blocking all badness");
}

<commit_msg>blah blah<commit_after>/*
  Copyright (c) 2015, Al Poole <netstar@gmail.com>

  Permission to use, copy, modify, and/or distribute this software for any
  purpose with or without fee is hereby granted, provided that the above
  copyright notice and this permission notice appear in all copies.

  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  PERFORMANCE OF THIS SOFTWARE.
*/

//   This is a HTTPS CONNECT proxy!

use std::string::{String};
use std::net::{SocketAddrV4,Ipv4Addr,TcpListener,TcpStream};
use std::io::{Write, Read};

const REQUEST_LEN: usize = 65535;

fn substr(buf: [u8;REQUEST_LEN], needle: &str, byte: u8) -> String
{
	let mut i = 0;
	let mut x = 0;
	let mut request = String::new();

	let srch = needle.as_bytes();

	if srch.len() == 0 {
		return request;
	}

	while buf[i] as char != '\0'  {
		if buf[i] as char == srch[0] as char {
			while x < srch.len() && buf[i] as char  == srch[x] as char {
				i = i + 1;
				x = x + 1;
			}
			break;
		} else {
			i = i + 1;
		}
	}

	if x == srch.len() {
		let mut end = i;
		while buf[end] as char != byte as char && buf[end] as char != '\n'
		{
			end = end + 1;

		}

		for y in i..end {
			request.push(buf[y] as char);
		}
	}

	return request;
}

const CHUNK: usize = 4096; // PAGESIZEish

fn talk_to_me(mut instream: &TcpStream, mut outstream: &TcpStream, mut headers: &Header) -> bool
{

	let mut buf = [0u8; CHUNK];

	println!("top");
	let bytes = instream.read(&mut buf).unwrap();
	if bytes <= 0 {
		return false;
	}

	println!("recv {}", bytes);

	for i in 0..bytes {
		print!("{}", buf[i] as char);
	}

	let mut chunk = 0;

	while chunk < bytes {
		let sent = outstream.write(&mut buf[0..bytes]).unwrap();
		if sent <= 0 {
			return false;
		}
		println!("sent {}", sent);
		chunk = chunk + sent;
	}
	true
}

struct Header {
	pub hostname: String,
	pub connection: String,
	pub proxy: String,
	pub agent: String,
}

impl Header {

pub fn new() -> Header
{
	let hostname	 = String::new();
	let connection   = String::new();
	let proxy	 = String::new();
	let agent	 = String::new();

	let h = Header
	{
		hostname: hostname,
		connection: connection,
		proxy: proxy,
		agent: agent
	};

	return h;
}

}

fn http_connect_request(instream: TcpStream, headers: Header)
{
	let bogus_fix = &format!("{}", headers.hostname);

	let mut outstream = TcpStream::connect::<(&str)>(bogus_fix).unwrap();
	let mut disconnected = false;

	let request = format!("HTTP/1.1 200 Connection established\r\nUser-Agent: {}\r\nProxy-Connection: {}\r\nConnection: {}\r\nHost: {}\r\n\r\n",
			headers.agent, headers.proxy, headers.connection, headers.hostname);
	println!("sending: \n\n{}", request);
	let mut s = &instream;
	s.write(request.as_bytes()).unwrap(); // tell client the connection is made

	while ! disconnected {
		disconnected = talk_to_me(&instream, &outstream, &headers);
	}

	let response = format!("HTTP/1.1 200 OK\r\n\r\n");
	outstream.write(response.as_bytes()).unwrap();

}

fn check_headers(buffer: [u8;REQUEST_LEN], headers: &mut Header) -> bool
{
	let mut i = 0;

	while buffer[i] != '\0' as u8
	{
		print!("{}", buffer[i] as char);
		i+=1;
	}
	print!("\n");

	if headers.hostname.is_empty()
	{
		headers.hostname = substr(buffer, "Host: ", '\r' as u8);
	}

	if headers.connection.is_empty()
	{
		headers.connection = substr(buffer, "Connection: ", '\r' as u8);
	}

	if headers.proxy.is_empty()
	{
		headers.proxy = substr(buffer, "Proxy-Connection: ", '\r' as u8);
	}

	if headers.agent.is_empty()
	{
		headers.agent = substr(buffer, "User-Agent: ", '\r' as u8);
	}

	if ! headers.hostname.is_empty() && ! headers.connection.is_empty()
		&& ! headers.proxy.is_empty() && ! headers.agent.is_empty()
	{

		return true;
	}

	return false;
}

fn request_headers(mut instream: &TcpStream, headers: &mut Header)
{
	 loop
	{
		let mut buffer = [0u8; REQUEST_LEN];
		let mut byte = [0u8; 1];
		let mut len = 0;

		while byte[0] as char != '\n'
		{
			let bytes = instream.read(&mut byte).unwrap();
			buffer[len] = byte[0];
			len += bytes;
		}

		buffer[len] = '\0' as u8;

		if check_headers(buffer, headers) && len == 2
		{
			let mut i = 0;

			while i < REQUEST_LEN
			{
				buffer[i] = 0;
				i += 1;
			}
			return;
		}
	}

}

fn request_method(mut instream: &TcpStream) -> String
{
	let mut byte = [0u8;1];

	let mut method: String = String::new();

	// bit better for now it'll do!
	while byte[0] as char != ' '
	{
		instream.read(&mut byte).unwrap();
		if byte[0] as char != ' '
		{
			method.push(byte[0] as char);
		}
	}

	match method.as_ref()
	{
		"CONNECT" =>
		{
			return method;
		}

		"GET" | "POST" | "OPTIONS" | "HEAD" =>
		{
			return "".to_string();
			// all good do not return!!!
		}

		_ =>
		{
			return "".to_string();
		}
	}
}

fn proxy(stream: TcpStream) {
	let method = request_method(&stream);

	match method.as_ref()
	{
		"CONNECT" =>
		{
			let mut headers = Header::new();
			request_headers(&stream, &mut headers);

			http_connect_request(stream, headers);
		}

		_ =>
		{
			println!("REQUEST UNKNOWN");
		}
	}
}

extern crate threadpool;
use threadpool::ThreadPool;

fn proxy_time(port: u16, threads: usize) {
	let ip = Ipv4Addr::new(127, 0, 0, 1);
	let host = SocketAddrV4::new(ip, port);
	let listener = TcpListener::bind(host).unwrap();

	let pool = ThreadPool::new(threads);

	for stream in listener.incoming()
	{
		match stream
		{
			Ok(stream) =>
			{
				pool.execute(move || { proxy(stream); });
			}

			Err(_) =>
			{
				println!("NET error");
				1 << 7;
			}
		}
	}

	drop (listener);
}

fn main () {
	let threads = 128;
	let port: u16 = 9998;

	proxy_time(port, threads);
	println!("Blocking all badness");
}

<|endoftext|>


<commit_before>//! Command-line iterface to substudy.

extern crate rustc_serialize;
extern crate docopt;
extern crate env_logger;

extern crate substudy;

use docopt::Docopt;
use std::path::Path;
use std::process::exit;

use substudy::err::Result;
use substudy::srt::SubtitleFile;
use substudy::align::combine_files;
use substudy::video;
use substudy::export;

const USAGE: &'static str = "
Subtitle processing tools for students of foreign languages

Usage: substudy clean <subs>
       substudy combine <foreign-subs> <native-subs>
       substudy export review <video> <foreign-subs> [<native-subs>]
       substudy list tracks <video>
       substudy --help

For now, all subtitles must be in *.srt format. Many common encodings
will be automatically detected, but try converting to UTF-8 if you
have problems.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_clean: bool,
    cmd_combine: bool,
    cmd_tracks: bool,
    cmd_export: bool,
    arg_subs: String,
    arg_foreign_subs: String,
    arg_native_subs: Option<String>,
    arg_video: String,
}

// Choose and run the appropriate command.
fn run(args: &Args) -> Result<()> {
    match *args {
        Args{cmd_clean: true, arg_subs: ref path, ..} =>
            cmd_clean(&Path::new(path)),
        Args{cmd_combine: true, arg_foreign_subs: ref path1,
             arg_native_subs: Some(ref path2), ..} =>
            cmd_combine(&Path::new(path1), &Path::new(path2)),
        Args{cmd_tracks: true, arg_video: ref path, ..} =>
            cmd_tracks(&Path::new(path)),
        Args{cmd_export: true, arg_video: ref video_path,
             arg_foreign_subs: ref foreign_path,
             arg_native_subs: ref native_path, ..} => {
            match native_path {
                &None =>
                    cmd_export(&Path::new(video_path),
                               &Path::new(foreign_path),
                               None),
                &Some(ref native) =>
                    cmd_export(&Path::new(video_path),
                               &Path::new(foreign_path),
                               Some(&Path::new(native))),
            }
        }
        _ => panic!("Unexpected argument combination: {:?}", args)
    }
}

fn cmd_clean(path: &Path) -> Result<()> {
    let file1 = try!(SubtitleFile::cleaned_from_path(path));
    print!("{}", file1.to_string());
    Ok(())
}

fn cmd_combine(path1: &Path, path2: &Path) -> Result<()> {
    let file1 = try!(SubtitleFile::cleaned_from_path(path1));
    let file2 = try!(SubtitleFile::cleaned_from_path(path2));
    print!("{}", combine_files(&file1, &file2).to_string());
    Ok(())
}

fn cmd_tracks(path: &Path) -> Result<()> {
    let v = try!(video::Video::new(path));
    for stream in v.streams() {
        let lang: &str = match stream.tags.get("language") {
            Some(ref code) => code,
            None => "unknown",
        };
        println!("#{} {} {:?}", stream.index, lang, stream.codec_type);
    }
    Ok(())
}

fn cmd_export(video_path: &Path, foreign_sub_path: &Path,
              native_sub_path: Option<&Path>) ->
    Result<()>
{
    // Load our input files.
    let video = try!(video::Video::new(video_path));
    let foreign_subs = try!(SubtitleFile::cleaned_from_path(foreign_sub_path));
    let native_subs = match native_sub_path {
        None => None,
        Some(p) => Some(try!(SubtitleFile::cleaned_from_path(p))),
    };

    let request = export::ExportRequest {
        video: video,
        foreign_subtitles: foreign_subs,
        native_subtitles: native_subs,
    };
    try!(export::export(&request));

    Ok(())
}

fn main() {
    env_logger::init().unwrap();

    // Parse our command-line arguments using docopt (very shiny).
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    // Decide which command to run, and run it.
    if let Err(ref err) = run(&args) {
        // Print any error and exit with an error status.
        println!("{}", err);
        exit(1);
    }
}
<commit_msg>Use stream.language() in `list tracks` output<commit_after>//! Command-line iterface to substudy.

extern crate rustc_serialize;
extern crate docopt;
extern crate env_logger;

extern crate substudy;

use docopt::Docopt;
use std::path::Path;
use std::process::exit;

use substudy::err::Result;
use substudy::srt::SubtitleFile;
use substudy::align::combine_files;
use substudy::video;
use substudy::export;

const USAGE: &'static str = "
Subtitle processing tools for students of foreign languages

Usage: substudy clean <subs>
       substudy combine <foreign-subs> <native-subs>
       substudy export review <video> <foreign-subs> [<native-subs>]
       substudy list tracks <video>
       substudy --help

For now, all subtitles must be in *.srt format. Many common encodings
will be automatically detected, but try converting to UTF-8 if you
have problems.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_clean: bool,
    cmd_combine: bool,
    cmd_tracks: bool,
    cmd_export: bool,
    arg_subs: String,
    arg_foreign_subs: String,
    arg_native_subs: Option<String>,
    arg_video: String,
}

// Choose and run the appropriate command.
fn run(args: &Args) -> Result<()> {
    match *args {
        Args{cmd_clean: true, arg_subs: ref path, ..} =>
            cmd_clean(&Path::new(path)),
        Args{cmd_combine: true, arg_foreign_subs: ref path1,
             arg_native_subs: Some(ref path2), ..} =>
            cmd_combine(&Path::new(path1), &Path::new(path2)),
        Args{cmd_tracks: true, arg_video: ref path, ..} =>
            cmd_tracks(&Path::new(path)),
        Args{cmd_export: true, arg_video: ref video_path,
             arg_foreign_subs: ref foreign_path,
             arg_native_subs: ref native_path, ..} => {
            match native_path {
                &None =>
                    cmd_export(&Path::new(video_path),
                               &Path::new(foreign_path),
                               None),
                &Some(ref native) =>
                    cmd_export(&Path::new(video_path),
                               &Path::new(foreign_path),
                               Some(&Path::new(native))),
            }
        }
        _ => panic!("Unexpected argument combination: {:?}", args)
    }
}

fn cmd_clean(path: &Path) -> Result<()> {
    let file1 = try!(SubtitleFile::cleaned_from_path(path));
    print!("{}", file1.to_string());
    Ok(())
}

fn cmd_combine(path1: &Path, path2: &Path) -> Result<()> {
    let file1 = try!(SubtitleFile::cleaned_from_path(path1));
    let file2 = try!(SubtitleFile::cleaned_from_path(path2));
    print!("{}", combine_files(&file1, &file2).to_string());
    Ok(())
}

fn cmd_tracks(path: &Path) -> Result<()> {
    let v = try!(video::Video::new(path));
    for stream in v.streams() {
        let lang = stream.language();
        let lang_str = lang.map(|l| l.as_str().to_owned())
            .unwrap_or("??".to_owned());
        println!("#{} {} {:?}", stream.index, &lang_str, stream.codec_type);
    }
    Ok(())
}

fn cmd_export(video_path: &Path, foreign_sub_path: &Path,
              native_sub_path: Option<&Path>) ->
    Result<()>
{
    // Load our input files.
    let video = try!(video::Video::new(video_path));
    let foreign_subs = try!(SubtitleFile::cleaned_from_path(foreign_sub_path));
    let native_subs = match native_sub_path {
        None => None,
        Some(p) => Some(try!(SubtitleFile::cleaned_from_path(p))),
    };

    let request = export::ExportRequest {
        video: video,
        foreign_subtitles: foreign_subs,
        native_subtitles: native_subs,
    };
    try!(export::export(&request));

    Ok(())
}

fn main() {
    env_logger::init().unwrap();

    // Parse our command-line arguments using docopt (very shiny).
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    // Decide which command to run, and run it.
    if let Err(ref err) = run(&args) {
        // Print any error and exit with an error status.
        println!("{}", err);
        exit(1);
    }
}
<|endoftext|>


<commit_before>// How many bits in a `u8`
const U8BITS: usize = 8;

/// Lazy iterator over bits of a vector of bytes, starting with the LSB
/// (least-significat bit) of the first element of the vector.
pub struct BitIterator<'a> {
    object: &'a Vec<u8>,
    next_idx: usize,
    end_idx: usize,
}

impl<'a> BitIterator<'a> {
    /// Creates an iterator from a vector of bytes. Each byte becomes eight bits, with the least
    /// significant bits coming first.
    pub fn from_bytes(obj: &'a Vec<u8>) -> BitIterator {
        BitIterator { object: obj, next_idx: 0, end_idx: obj.len() * U8BITS }
    }

    /// Returns the number of ones in the binary representation of the underlying object.
    pub fn count_ones(&self) -> u32 {
        self.object.iter().fold(0, |acc, bv| acc + bv.count_ones())
    }
}

impl<'a> Iterator for BitIterator<'a> {
    type Item = bool;

    fn next(&mut self) -> Option<bool> {
        if self.next_idx != self.end_idx {
            let (byte_idx, bit_idx) = (self.next_idx / U8BITS, self.next_idx % U8BITS);
            let bit = self.object[byte_idx] >> bit_idx & 0x1;
            self.next_idx += 1;
            Some(bit == 0x1)
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.end_idx, Some(self.end_idx))
    }
}

impl<'a> ExactSizeIterator for BitIterator<'a> {}

#[test]
fn test_iterator() {
    let bytes = vec!(0xCA, 0xFE);
    let expected_bits = vec!(0,1,0,1, 0,0,1,1, 0,1,1,1, 1,1,1,1);

    for (i, bit) in BitIterator::from_bytes(&bytes).enumerate() {
        println!("{} == {}", bit, expected_bits[i] == 0x1);
        assert_eq!(bit, expected_bits[i] == 0x1);
    }
}
<commit_msg>Make BitIterator work with slices.<commit_after>// How many bits in a `u8`
const U8BITS: usize = 8;

/// Lazy iterator over bits of a vector of bytes, starting with the LSB
/// (least-significat bit) of the first element of the vector.
pub struct BitIterator<'a> {
    object: &'a [u8],
    next_idx: usize,
    end_idx: usize,
}

impl<'a> BitIterator<'a> {
    /// Creates an iterator from a vector of bytes. Each byte becomes eight bits, with the least
    /// significant bits coming first.
    pub fn from_bytes(obj: &'a [u8]) -> BitIterator {
        BitIterator { object: obj, next_idx: 0, end_idx: obj.len() * U8BITS }
    }

    /// Returns the number of ones in the binary representation of the underlying object.
    pub fn count_ones(&self) -> u32 {
        self.object.iter().fold(0, |acc, bv| acc + bv.count_ones())
    }
}

impl<'a> Iterator for BitIterator<'a> {
    type Item = bool;

    fn next(&mut self) -> Option<bool> {
        if self.next_idx != self.end_idx {
            let (byte_idx, bit_idx) = (self.next_idx / U8BITS, self.next_idx % U8BITS);
            let bit = self.object[byte_idx] >> bit_idx & 0x1;
            self.next_idx += 1;
            Some(bit == 0x1)
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.end_idx, Some(self.end_idx))
    }
}

impl<'a> ExactSizeIterator for BitIterator<'a> {}

#[test]
fn test_iterator() {
    let bytes = vec!(0xCA, 0xFE);
    let expected_bits = vec!(0,1,0,1, 0,0,1,1, 0,1,1,1, 1,1,1,1);

    for (i, bit) in BitIterator::from_bytes(&bytes).enumerate() {
        println!("{} == {}", bit, expected_bits[i] == 0x1);
        assert_eq!(bit, expected_bits[i] == 0x1);
    }
}
<|endoftext|>