<commit_before>#![feature(test)]
// PLAYGROUND FOR PERFORMANCE TESTS
//
extern crate libc;
extern crate test;
use test::Bencher;

use libc::c_char;
use std::ffi::{CStr,CString};
use std::str;

#[bench]
fn rust_to_ruby_c_char_convenient(b: &mut Bencher){
  let s: String = "hello".to_string();

  // (185ns)
  b.iter(|| {
    let s = s.clone(); //To imitate .into()
    let s_slice: &str = &s[..];
    CString::new(s_slice).unwrap().into_raw()
  })
}

// SANCTIONED USAGE
#[bench]
fn rust_to_ruby_to_c_char(b: &mut Bencher){
  let s: String = "hello".to_string();
  let s = s.as_str();

  // USE THIS METHOD!!! (153ns)
  b.iter(|| {
    CString::new(s).unwrap().into_raw()
  })
}

#[bench]
fn ruby_to_rust_string_convenient(b: &mut Bencher){
  let s: *const c_char = CString::new("hello").unwrap().into_raw();

  // (46ns)
  b.iter(|| {
    let c_str = unsafe {
      assert!(!s.is_null());
      CStr::from_ptr(s)
    };
    (*str::from_utf8(c_str.to_bytes()).unwrap_or("")).to_string()
  })
}

// SANCTIONED USAGE
#[bench]
fn ruby_to_rust_from_c_char(b: &mut Bencher){
  let s: *const c_char = CString::new("hello").unwrap().into_raw();

  // USE THIS METHOD!!! (19ns)
  b.iter(|| {
    let c_str = unsafe {
      assert!(!s.is_null());
      CStr::from_ptr(s)
    };
    str::from_utf8(c_str.to_bytes()).unwrap_or("")
  })
}
<commit_msg>typo in method name [ci skip]<commit_after>#![feature(test)]
// PLAYGROUND FOR PERFORMANCE TESTS
//
extern crate libc;
extern crate test;
use test::Bencher;

use libc::c_char;
use std::ffi::{CStr,CString};
use std::str;

#[bench]
fn rust_to_ruby_c_char_convenient(b: &mut Bencher){
  let s: String = "hello".to_string();

  // (185ns)
  b.iter(|| {
    let s = s.clone(); //To imitate .into()
    let s_slice: &str = &s[..];
    CString::new(s_slice).unwrap().into_raw()
  })
}

// SANCTIONED USAGE
#[bench]
fn rust_to_ruby_c_char(b: &mut Bencher){
  let s: String = "hello".to_string();
  let s = s.as_str();

  // USE THIS METHOD!!! (153ns)
  b.iter(|| {
    CString::new(s).unwrap().into_raw()
  })
}

#[bench]
fn ruby_to_rust_string_convenient(b: &mut Bencher){
  let s: *const c_char = CString::new("hello").unwrap().into_raw();

  // (46ns)
  b.iter(|| {
    let c_str = unsafe {
      assert!(!s.is_null());
      CStr::from_ptr(s)
    };
    (*str::from_utf8(c_str.to_bytes()).unwrap_or("")).to_string()
  })
}

// SANCTIONED USAGE
#[bench]
fn ruby_to_rust_from_c_char(b: &mut Bencher){
  let s: *const c_char = CString::new("hello").unwrap().into_raw();

  // USE THIS METHOD!!! (19ns)
  b.iter(|| {
    let c_str = unsafe {
      assert!(!s.is_null());
      CStr::from_ptr(s)
    };
    str::from_utf8(c_str.to_bytes()).unwrap_or("")
  })
}
<|endoftext|>


<commit_before>// Copyright 2022 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::env;
use std::path::PathBuf;

fn main() {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

    let output_file = PathBuf::from(env::var("CARGO_TARGET_DIR").unwrap())
        .join("crosvm_control.h")
        .display()
        .to_string();

    cbindgen::Builder::new()
        .with_crate(crate_dir)
        .generate()
        .expect("Unable to generate bindings")
        .write_to_file(&output_file);
}
<commit_msg>crosvm: crosvm_control: use OUT_DIR instead of CARGO_TARGET_DIR in build script<commit_after>// Copyright 2022 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::env;
use std::path::PathBuf;

fn main() {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

    let output_file = PathBuf::from(env::var("OUT_DIR").unwrap())
        .join("crosvm_control.h")
        .display()
        .to_string();

    cbindgen::Builder::new()
        .with_crate(crate_dir)
        .generate()
        .expect("Unable to generate bindings")
        .write_to_file(&output_file);
}
<|endoftext|>


<commit_before>use crate::ty::SourceType;
use crate::utils::GrowableVec;
use crate::vm::{FileId, TypeParam};
use dora_parser::ast::{AnnotationParam, Modifier};
use dora_parser::interner::Name;
use dora_parser::Position;
use parking_lot::RwLock;
use std::sync::Arc;

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct AnnotationId(usize);

impl AnnotationId {
    pub fn max() -> AnnotationId {
        AnnotationId(usize::max_value())
    }
}

impl From<AnnotationId> for usize {
    fn from(data: AnnotationId) -> usize {
        data.0
    }
}

impl From<usize> for AnnotationId {
    fn from(data: usize) -> AnnotationId {
        AnnotationId(data)
    }
}

impl GrowableVec<RwLock<Annotation>> {
    pub fn idx(&self, index: AnnotationId) -> Arc<RwLock<Annotation>> {
        self.idx_usize(index.0)
    }
}

#[derive(Debug)]
pub struct Annotation {
    pub id: AnnotationId,
    pub file_id: FileId,
    pub pos: Position,
    pub name: Name,
    pub ty: SourceType,
    pub internal: Option<Modifier>,

    pub type_params: Option<Vec<TypeParam>>,
    pub term_params: Option<Vec<AnnotationParam>>,
}
<commit_msg>add namespace_id to Annotation<commit_after>use crate::ty::SourceType;
use crate::utils::GrowableVec;
use crate::vm::{FileId, NamespaceId, TypeParam};
use dora_parser::ast::{AnnotationParam, Modifier};
use dora_parser::interner::Name;
use dora_parser::Position;
use parking_lot::RwLock;
use std::sync::Arc;

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct AnnotationId(usize);

impl AnnotationId {
    pub fn max() -> AnnotationId {
        AnnotationId(usize::max_value())
    }
}

impl From<AnnotationId> for usize {
    fn from(data: AnnotationId) -> usize {
        data.0
    }
}

impl From<usize> for AnnotationId {
    fn from(data: usize) -> AnnotationId {
        AnnotationId(data)
    }
}

impl GrowableVec<RwLock<Annotation>> {
    pub fn idx(&self, index: AnnotationId) -> Arc<RwLock<Annotation>> {
        self.idx_usize(index.0)
    }
}

#[derive(Debug)]
pub struct Annotation {
    pub id: AnnotationId,
    pub file_id: FileId,
    pub pos: Position,
    pub name: Name,
    pub namespace_id: NamespaceId,
    pub ty: SourceType,
    pub internal: Option<Modifier>,

    pub type_params: Option<Vec<TypeParam>>,
    pub term_params: Option<Vec<AnnotationParam>>,
}
<|endoftext|>


<commit_before>use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
use std::io::Cursor;
use std::mem;
use super::ipv4_header::IPv4Header;

#[derive(Copy, Clone)]
pub struct TCPHeader {
    source_port: u16,
    destination_port: u16,
    sequence_number: u32,
    acknowledgement_number: u32,
    header_length: u8,
    flags: u16,
    window: u16,
}

pub const TCP_FLAG_FIN: u16 = 1 << 0;
pub const TCP_FLAG_SYN: u16 = 1 << 1;
pub const TCP_FLAG_RST: u16 = 1 << 2;
pub const TCP_FLAG_PSH: u16 = 1 << 3;
pub const TCP_FLAG_ACK: u16 = 1 << 4;
pub const TCP_FLAG_URG: u16 = 1 << 5;

impl TCPHeader {
    pub fn parse(raw: &[u8]) -> Self {
        let data_offset_and_flags = BigEndian::read_u16(&raw[12..14]);
        Self {
            source_port: BigEndian::read_u16(&raw[0..2]),
            destination_port: BigEndian::read_u16(&raw[2..4]),
            sequence_number: BigEndian::read_u32(&raw[4..8]),
            acknowledgement_number: BigEndian::read_u32(&raw[8..12]),
            header_length: ((data_offset_and_flags & 0xF000) >> 10) as u8,
            flags: data_offset_and_flags & 0x1FF,
            window: BigEndian::read_u16(&raw[14..16]),
        }
    }

    pub fn header_length(&self) -> u8 {
        self.header_length
    }

    pub fn source_port(&self) -> u16 {
        self.source_port
    }

    pub fn destination_port(&self) -> u16 {
        self.destination_port
    }

    pub fn sequence_number(&self) -> u32 {
        self.sequence_number
    }

    pub fn acknowledgement_number(&self) -> u32 {
        self.acknowledgement_number
    }

    pub fn flags(&self) -> u16 {
        self.flags
    }

    pub fn set_source_port(&mut self, raw: &mut [u8], source_port: u16) {
        self.source_port = source_port;
        BigEndian::write_u16(&mut raw[0..2], source_port);
    }

    pub fn set_destination_port(&mut self, raw: &mut [u8], destination_port: u16) {
        self.destination_port = destination_port;
        BigEndian::write_u16(&mut raw[2..4], destination_port);
    }

    pub fn swap_source_and_destination(&mut self, raw: &mut [u8]) {
        mem::swap(&mut self.source_port, &mut self.destination_port);
        for i in 0..2 {
            raw.swap(i, i + 2);
        }
    }

    pub fn set_sequence_number(&mut self, raw: &mut [u8], sequence_number: u32) {
        self.sequence_number = sequence_number;
        BigEndian::write_u32(&mut raw[4..8], sequence_number);
    }

    pub fn set_acknowledgement_number(&mut self, raw: &mut [u8], acknowledgement_number: u32) {
        self.acknowledgement_number = acknowledgement_number;
        BigEndian::write_u32(&mut raw[8..12], acknowledgement_number);
    }

    pub fn set_flags(&mut self, raw: &mut [u8], flags: u16) {
        self.flags = flags;
        let mut data_offset_and_flags = BigEndian::read_u16(&mut raw[12..14]);
        data_offset_and_flags = data_offset_and_flags & 0xFE00 | flags & 0x1FF;
        BigEndian::write_u16(&mut raw[12..14], data_offset_and_flags);
    }

    pub fn shrink_options(&mut self, raw: &mut [u8]) {
        self.set_data_offset(raw, 5);
    }

    fn set_data_offset(&mut self, raw: &mut [u8], data_offset: u8) {
        let mut data_offset_and_flags = BigEndian::read_u16(&mut raw[12..14]);
        data_offset_and_flags = data_offset_and_flags & 0x0FFF | ((data_offset as u16) << 12);
        BigEndian::write_u16(&mut raw[12..14], data_offset_and_flags);
        self.header_length = data_offset << 2;
    }

    pub fn compute_checksum(&mut self, raw: &mut [u8], ipv4_header: &IPv4Header) {
        // pseudo-header checksum (cf rfc793 section 3.1)
        let source = ipv4_header.source();
        let destination = ipv4_header.destination();
        let length = ipv4_header.total_length() - ipv4_header.header_length() as u16;
        assert_eq!(raw.len(), ipv4_header.total_length() as usize - ipv4_header.header_length() as usize);

        let mut sum = 6u32; // protocol TCP = 6
        sum += source >> 16;
        sum += source & 0xFFFF;
        sum += destination >> 16;
        sum += destination & 0xFFFF;
        sum += length as u32;

        // reset checksum field
        self.set_checksum(raw, 0);

        {
            let mut cursor = Cursor::new(&raw);
            while length - cursor.position() as u16 > 1 {
                sum += cursor.read_u16::<BigEndian>().unwrap() as u32;
            }
            // if payload length is odd, pad last short with 0
            if cursor.position() as u16 != length {
                sum += (cursor.read_u8().unwrap() as u32) << 8;
            }
        }

        while (sum & !0xFFFF) != 0 {
            sum = (sum & 0xFFFF) + (sum >> 16);
        }
        sum = !sum;

        self.set_checksum(raw, sum as u16);
    }

    fn checksum(&self, raw: &[u8]) -> u16 {
        BigEndian::read_u16(&raw[16..18])
    }

    pub fn set_checksum(&mut self, raw: &mut [u8], checksum: u16) {
        BigEndian::write_u16(&mut raw[16..18], checksum);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use byteorder::{BigEndian, WriteBytesExt};
    use relay::ipv4_packet::IPv4Packet;
    use relay::transport_header::TransportHeader;

    fn create_packet() -> Vec<u8> {
        let mut raw = Vec::new();
        raw.reserve(44);

        raw.write_u8(4u8 << 4 | 5).unwrap(); // version_and_ihl
        raw.write_u8(0).unwrap(); //ToS
        raw.write_u16::<BigEndian>(44).unwrap(); // total length
        raw.write_u32::<BigEndian>(0).unwrap(); // id_flags_fragment_offset
        raw.write_u8(0).unwrap(); // TTL
        raw.write_u8(6).unwrap(); // protocol (TCP)
        raw.write_u16::<BigEndian>(0).unwrap(); // checksum
        raw.write_u32::<BigEndian>(0x12345678).unwrap(); // source address
        raw.write_u32::<BigEndian>(0xA2A24242).unwrap(); // destination address

        raw.write_u16::<BigEndian>(0x1234).unwrap(); // source port
        raw.write_u16::<BigEndian>(0x5678).unwrap(); // destination port
        raw.write_u32::<BigEndian>(0x111).unwrap(); // sequence number
        raw.write_u32::<BigEndian>(0x222).unwrap(); // acknowledgement number
        raw.write_u16::<BigEndian>(5 << 12).unwrap(); // data offset + flags(0)
        raw.write_u16::<BigEndian>(0).unwrap(); // window (don't care for these tests)
        raw.write_u16::<BigEndian>(0).unwrap(); // checksum
        raw.write_u16::<BigEndian>(0).unwrap(); // urgent pointer

        raw.write_u32::<BigEndian>(0x11223344).unwrap(); // payload

        raw
    }

    fn create_odd_packet() -> Vec<u8> {
        let mut raw = Vec::new();
        raw.reserve(45);

        raw.write_u8(4u8 << 4 | 5).unwrap(); // version_and_ihl
        raw.write_u8(0).unwrap(); //ToS
        raw.write_u16::<BigEndian>(45).unwrap(); // total length
        raw.write_u32::<BigEndian>(0).unwrap(); // id_flags_fragment_offset
        raw.write_u8(0).unwrap(); // TTL
        raw.write_u8(6).unwrap(); // protocol (TCP)
        raw.write_u16::<BigEndian>(0).unwrap(); // checksum
        raw.write_u32::<BigEndian>(0x12345678).unwrap(); // source address
        raw.write_u32::<BigEndian>(0xA2A24242).unwrap(); // destination address

        raw.write_u16::<BigEndian>(0x1234).unwrap(); // source port
        raw.write_u16::<BigEndian>(0x5678).unwrap(); // destination port
        raw.write_u32::<BigEndian>(0x111).unwrap(); // sequence number
        raw.write_u32::<BigEndian>(0x222).unwrap(); // acknowledgement number
        raw.write_u16::<BigEndian>(5 << 12).unwrap(); // data offset + flags(0)
        raw.write_u16::<BigEndian>(0).unwrap(); // window (don't care for these tests)
        raw.write_u16::<BigEndian>(0).unwrap(); // checksum
        raw.write_u16::<BigEndian>(0).unwrap(); // urgent pointer

        // payload
        raw.write_u32::<BigEndian>(0x11223344).unwrap();
        raw.write_u8(0x55).unwrap();

        raw
    }

    fn create_tcp_header() -> Vec<u8> {
        let mut raw = Vec::new();
        raw.reserve(20);

        raw.write_u16::<BigEndian>(0x1234).unwrap(); // source port
        raw.write_u16::<BigEndian>(0x5678).unwrap(); // destination port
        raw.write_u32::<BigEndian>(0x111).unwrap(); // sequence number
        raw.write_u32::<BigEndian>(0x222).unwrap(); // acknowledgement number
        raw.write_u16::<BigEndian>(5 << 12).unwrap(); // data offset + flags(0)
        raw.write_u16::<BigEndian>(0).unwrap(); // window (don't care for these tests)
        raw.write_u16::<BigEndian>(0).unwrap(); // checksum
        raw.write_u16::<BigEndian>(0).unwrap(); // urgent pointer

        raw
    }

    #[test]
    fn edit_header() {
        let raw = &mut create_tcp_header()[..];
        let mut header = TCPHeader::parse(raw);

        header.set_source_port(raw, 1111);
        header.set_destination_port(raw, 2222);
        header.set_sequence_number(raw, 300);
        header.set_acknowledgement_number(raw, 101);
        header.set_flags(raw, TCP_FLAG_FIN | TCP_FLAG_ACK);

        assert_eq!(1111, header.source_port());
        assert_eq!(2222, header.destination_port());
        assert_eq!(300, header.sequence_number());
        assert_eq!(101, header.acknowledgement_number());
        assert_eq!(TCP_FLAG_FIN | TCP_FLAG_ACK, header.flags());

        // assert that the buffer has been modified
        let raw_source_port = BigEndian::read_u16(&raw[0..2]);
        let raw_destination_port = BigEndian::read_u16(&raw[2..4]);
        let raw_sequence_number = BigEndian::read_u32(&raw[4..8]);
        let raw_acknowledgement_number = BigEndian::read_u32(&raw[8..12]);
        let raw_data_offset_and_flags = BigEndian::read_u16(&raw[12..14]);

        assert_eq!(1111, raw_source_port);
        assert_eq!(2222, raw_destination_port);
        assert_eq!(300, raw_sequence_number);
        assert_eq!(101, raw_acknowledgement_number);
        assert_eq!(0x5011, raw_data_offset_and_flags);
    }

    #[test]
    fn compute_checksum() {
        let raw = &mut create_packet()[..];
        let mut ipv4_packet = IPv4Packet::parse(raw);
        if let Some(TransportHeader::TCP(mut tcp_header)) = *ipv4_packet.transport_header() {
            // set a fake checksum value to assert that it is correctly computed
            BigEndian::write_u16(&mut ipv4_packet.raw_mut()[36..38], 0x79);

            {
                let (raw, ipv4_header, _) = ipv4_packet.destructure_mut();
                let transport_raw = &mut raw[ipv4_header.header_length() as usize..];
                tcp_header.compute_checksum(transport_raw, ipv4_header);
            }

            let expected_checksum = {
                // pseudo-header
                let mut sum: u32 = 0x1234 + 0x5678 + 0xA2A2 + 0x4242 + 0x0006 + 0x0018;

                // header
                sum += 0x1234 + 0x5678 + 0x0000 + 0x0111 + 0x0000 +
                       0x0222 + 0x5000 + 0x0000 + 0x0000 + 0x0000;

                // payload
                sum += 0x1122 + 0x3344;

                while (sum & !0xFFFF) != 0 {
                    sum = (sum & 0xFFFF) + (sum >> 16);
                }
                !sum as u16
            };

            {
                let (raw, ipv4_header, _) = ipv4_packet.destructure();
                let transport_header_raw = &raw[ipv4_header.header_length() as usize..];
                let actual_checksum = tcp_header.checksum(transport_header_raw);

                assert_eq!(expected_checksum, actual_checksum);
            }

        } else {
            panic!("Packet is not TCP");
        }
    }
}
<commit_msg>Add TCP checksum test for odd-length payloads<commit_after>use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
use std::io::Cursor;
use std::mem;
use super::ipv4_header::IPv4Header;

#[derive(Copy, Clone)]
pub struct TCPHeader {
    source_port: u16,
    destination_port: u16,
    sequence_number: u32,
    acknowledgement_number: u32,
    header_length: u8,
    flags: u16,
    window: u16,
}

pub const TCP_FLAG_FIN: u16 = 1 << 0;
pub const TCP_FLAG_SYN: u16 = 1 << 1;
pub const TCP_FLAG_RST: u16 = 1 << 2;
pub const TCP_FLAG_PSH: u16 = 1 << 3;
pub const TCP_FLAG_ACK: u16 = 1 << 4;
pub const TCP_FLAG_URG: u16 = 1 << 5;

impl TCPHeader {
    pub fn parse(raw: &[u8]) -> Self {
        let data_offset_and_flags = BigEndian::read_u16(&raw[12..14]);
        Self {
            source_port: BigEndian::read_u16(&raw[0..2]),
            destination_port: BigEndian::read_u16(&raw[2..4]),
            sequence_number: BigEndian::read_u32(&raw[4..8]),
            acknowledgement_number: BigEndian::read_u32(&raw[8..12]),
            header_length: ((data_offset_and_flags & 0xF000) >> 10) as u8,
            flags: data_offset_and_flags & 0x1FF,
            window: BigEndian::read_u16(&raw[14..16]),
        }
    }

    pub fn header_length(&self) -> u8 {
        self.header_length
    }

    pub fn source_port(&self) -> u16 {
        self.source_port
    }

    pub fn destination_port(&self) -> u16 {
        self.destination_port
    }

    pub fn sequence_number(&self) -> u32 {
        self.sequence_number
    }

    pub fn acknowledgement_number(&self) -> u32 {
        self.acknowledgement_number
    }

    pub fn flags(&self) -> u16 {
        self.flags
    }

    pub fn set_source_port(&mut self, raw: &mut [u8], source_port: u16) {
        self.source_port = source_port;
        BigEndian::write_u16(&mut raw[0..2], source_port);
    }

    pub fn set_destination_port(&mut self, raw: &mut [u8], destination_port: u16) {
        self.destination_port = destination_port;
        BigEndian::write_u16(&mut raw[2..4], destination_port);
    }

    pub fn swap_source_and_destination(&mut self, raw: &mut [u8]) {
        mem::swap(&mut self.source_port, &mut self.destination_port);
        for i in 0..2 {
            raw.swap(i, i + 2);
        }
    }

    pub fn set_sequence_number(&mut self, raw: &mut [u8], sequence_number: u32) {
        self.sequence_number = sequence_number;
        BigEndian::write_u32(&mut raw[4..8], sequence_number);
    }

    pub fn set_acknowledgement_number(&mut self, raw: &mut [u8], acknowledgement_number: u32) {
        self.acknowledgement_number = acknowledgement_number;
        BigEndian::write_u32(&mut raw[8..12], acknowledgement_number);
    }

    pub fn set_flags(&mut self, raw: &mut [u8], flags: u16) {
        self.flags = flags;
        let mut data_offset_and_flags = BigEndian::read_u16(&mut raw[12..14]);
        data_offset_and_flags = data_offset_and_flags & 0xFE00 | flags & 0x1FF;
        BigEndian::write_u16(&mut raw[12..14], data_offset_and_flags);
    }

    pub fn shrink_options(&mut self, raw: &mut [u8]) {
        self.set_data_offset(raw, 5);
    }

    fn set_data_offset(&mut self, raw: &mut [u8], data_offset: u8) {
        let mut data_offset_and_flags = BigEndian::read_u16(&mut raw[12..14]);
        data_offset_and_flags = data_offset_and_flags & 0x0FFF | ((data_offset as u16) << 12);
        BigEndian::write_u16(&mut raw[12..14], data_offset_and_flags);
        self.header_length = data_offset << 2;
    }

    pub fn compute_checksum(&mut self, raw: &mut [u8], ipv4_header: &IPv4Header) {
        // pseudo-header checksum (cf rfc793 section 3.1)
        let source = ipv4_header.source();
        let destination = ipv4_header.destination();
        let length = ipv4_header.total_length() - ipv4_header.header_length() as u16;
        assert_eq!(raw.len(), ipv4_header.total_length() as usize - ipv4_header.header_length() as usize);

        let mut sum = 6u32; // protocol TCP = 6
        sum += source >> 16;
        sum += source & 0xFFFF;
        sum += destination >> 16;
        sum += destination & 0xFFFF;
        sum += length as u32;

        // reset checksum field
        self.set_checksum(raw, 0);

        {
            let mut cursor = Cursor::new(&raw);
            while length - cursor.position() as u16 > 1 {
                sum += cursor.read_u16::<BigEndian>().unwrap() as u32;
            }
            // if payload length is odd, pad last short with 0
            if cursor.position() as u16 != length {
                sum += (cursor.read_u8().unwrap() as u32) << 8;
            }
        }

        while (sum & !0xFFFF) != 0 {
            sum = (sum & 0xFFFF) + (sum >> 16);
        }
        sum = !sum;

        self.set_checksum(raw, sum as u16);
    }

    fn checksum(&self, raw: &[u8]) -> u16 {
        BigEndian::read_u16(&raw[16..18])
    }

    pub fn set_checksum(&mut self, raw: &mut [u8], checksum: u16) {
        BigEndian::write_u16(&mut raw[16..18], checksum);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use byteorder::{BigEndian, WriteBytesExt};
    use relay::ipv4_packet::IPv4Packet;
    use relay::transport_header::TransportHeader;

    fn create_packet() -> Vec<u8> {
        let mut raw = Vec::new();
        raw.reserve(44);

        raw.write_u8(4u8 << 4 | 5).unwrap(); // version_and_ihl
        raw.write_u8(0).unwrap(); //ToS
        raw.write_u16::<BigEndian>(44).unwrap(); // total length
        raw.write_u32::<BigEndian>(0).unwrap(); // id_flags_fragment_offset
        raw.write_u8(0).unwrap(); // TTL
        raw.write_u8(6).unwrap(); // protocol (TCP)
        raw.write_u16::<BigEndian>(0).unwrap(); // checksum
        raw.write_u32::<BigEndian>(0x12345678).unwrap(); // source address
        raw.write_u32::<BigEndian>(0xA2A24242).unwrap(); // destination address

        raw.write_u16::<BigEndian>(0x1234).unwrap(); // source port
        raw.write_u16::<BigEndian>(0x5678).unwrap(); // destination port
        raw.write_u32::<BigEndian>(0x111).unwrap(); // sequence number
        raw.write_u32::<BigEndian>(0x222).unwrap(); // acknowledgement number
        raw.write_u16::<BigEndian>(5 << 12).unwrap(); // data offset + flags(0)
        raw.write_u16::<BigEndian>(0).unwrap(); // window (don't care for these tests)
        raw.write_u16::<BigEndian>(0).unwrap(); // checksum
        raw.write_u16::<BigEndian>(0).unwrap(); // urgent pointer

        raw.write_u32::<BigEndian>(0x11223344).unwrap(); // payload

        raw
    }

    fn create_odd_packet() -> Vec<u8> {
        let mut raw = Vec::new();
        raw.reserve(45);

        raw.write_u8(4u8 << 4 | 5).unwrap(); // version_and_ihl
        raw.write_u8(0).unwrap(); //ToS
        raw.write_u16::<BigEndian>(45).unwrap(); // total length
        raw.write_u32::<BigEndian>(0).unwrap(); // id_flags_fragment_offset
        raw.write_u8(0).unwrap(); // TTL
        raw.write_u8(6).unwrap(); // protocol (TCP)
        raw.write_u16::<BigEndian>(0).unwrap(); // checksum
        raw.write_u32::<BigEndian>(0x12345678).unwrap(); // source address
        raw.write_u32::<BigEndian>(0xA2A24242).unwrap(); // destination address

        raw.write_u16::<BigEndian>(0x1234).unwrap(); // source port
        raw.write_u16::<BigEndian>(0x5678).unwrap(); // destination port
        raw.write_u32::<BigEndian>(0x111).unwrap(); // sequence number
        raw.write_u32::<BigEndian>(0x222).unwrap(); // acknowledgement number
        raw.write_u16::<BigEndian>(5 << 12).unwrap(); // data offset + flags(0)
        raw.write_u16::<BigEndian>(0).unwrap(); // window (don't care for these tests)
        raw.write_u16::<BigEndian>(0).unwrap(); // checksum
        raw.write_u16::<BigEndian>(0).unwrap(); // urgent pointer

        // payload
        raw.write_u32::<BigEndian>(0x11223344).unwrap();
        raw.write_u8(0x55).unwrap();

        raw
    }

    fn create_tcp_header() -> Vec<u8> {
        let mut raw = Vec::new();
        raw.reserve(20);

        raw.write_u16::<BigEndian>(0x1234).unwrap(); // source port
        raw.write_u16::<BigEndian>(0x5678).unwrap(); // destination port
        raw.write_u32::<BigEndian>(0x111).unwrap(); // sequence number
        raw.write_u32::<BigEndian>(0x222).unwrap(); // acknowledgement number
        raw.write_u16::<BigEndian>(5 << 12).unwrap(); // data offset + flags(0)
        raw.write_u16::<BigEndian>(0).unwrap(); // window (don't care for these tests)
        raw.write_u16::<BigEndian>(0).unwrap(); // checksum
        raw.write_u16::<BigEndian>(0).unwrap(); // urgent pointer

        raw
    }

    #[test]
    fn edit_header() {
        let raw = &mut create_tcp_header()[..];
        let mut header = TCPHeader::parse(raw);

        header.set_source_port(raw, 1111);
        header.set_destination_port(raw, 2222);
        header.set_sequence_number(raw, 300);
        header.set_acknowledgement_number(raw, 101);
        header.set_flags(raw, TCP_FLAG_FIN | TCP_FLAG_ACK);

        assert_eq!(1111, header.source_port());
        assert_eq!(2222, header.destination_port());
        assert_eq!(300, header.sequence_number());
        assert_eq!(101, header.acknowledgement_number());
        assert_eq!(TCP_FLAG_FIN | TCP_FLAG_ACK, header.flags());

        // assert that the buffer has been modified
        let raw_source_port = BigEndian::read_u16(&raw[0..2]);
        let raw_destination_port = BigEndian::read_u16(&raw[2..4]);
        let raw_sequence_number = BigEndian::read_u32(&raw[4..8]);
        let raw_acknowledgement_number = BigEndian::read_u32(&raw[8..12]);
        let raw_data_offset_and_flags = BigEndian::read_u16(&raw[12..14]);

        assert_eq!(1111, raw_source_port);
        assert_eq!(2222, raw_destination_port);
        assert_eq!(300, raw_sequence_number);
        assert_eq!(101, raw_acknowledgement_number);
        assert_eq!(0x5011, raw_data_offset_and_flags);
    }

    #[test]
    fn compute_checksum() {
        let raw = &mut create_packet()[..];
        let mut ipv4_packet = IPv4Packet::parse(raw);
        if let Some(TransportHeader::TCP(mut tcp_header)) = *ipv4_packet.transport_header() {
            // set a fake checksum value to assert that it is correctly computed
            BigEndian::write_u16(&mut ipv4_packet.raw_mut()[36..38], 0x79);

            {
                let (raw, ipv4_header, _) = ipv4_packet.destructure_mut();
                let transport_raw = &mut raw[ipv4_header.header_length() as usize..];
                tcp_header.compute_checksum(transport_raw, ipv4_header);
            }

            let expected_checksum = {
                // pseudo-header
                let mut sum: u32 = 0x1234 + 0x5678 + 0xA2A2 + 0x4242 + 0x0006 + 0x0018;

                // header
                sum += 0x1234 + 0x5678 + 0x0000 + 0x0111 + 0x0000 +
                       0x0222 + 0x5000 + 0x0000 + 0x0000 + 0x0000;

                // payload
                sum += 0x1122 + 0x3344;

                while (sum & !0xFFFF) != 0 {
                    sum = (sum & 0xFFFF) + (sum >> 16);
                }
                !sum as u16
            };

            {
                let (raw, ipv4_header, _) = ipv4_packet.destructure();
                let transport_header_raw = &raw[ipv4_header.header_length() as usize..];
                let actual_checksum = tcp_header.checksum(transport_header_raw);

                assert_eq!(expected_checksum, actual_checksum);
            }

        } else {
            panic!("Packet is not TCP");
        }
    }

    #[test]
    fn compute_checksum_odd() {
        let raw = &mut create_odd_packet()[..];
        let mut ipv4_packet = IPv4Packet::parse(raw);
        if let Some(TransportHeader::TCP(mut tcp_header)) = *ipv4_packet.transport_header() {
            // set a fake checksum value to assert that it is correctly computed
            BigEndian::write_u16(&mut ipv4_packet.raw_mut()[36..38], 0x79);

            {
                let (raw, ipv4_header, _) = ipv4_packet.destructure_mut();
                let transport_raw = &mut raw[ipv4_header.header_length() as usize..];
                tcp_header.compute_checksum(transport_raw, ipv4_header);
            }

            let expected_checksum = {
                // pseudo-header
                let mut sum: u32 = 0x1234 + 0x5678 + 0xA2A2 + 0x4242 + 0x0006 + 0x0019;

                // header
                sum += 0x1234 + 0x5678 + 0x0000 + 0x0111 + 0x0000 +
                       0x0222 + 0x5000 + 0x0000 + 0x0000 + 0x0000;

                // payload
                sum += 0x1122 + 0x3344 + 0x5500;

                while (sum & !0xFFFF) != 0 {
                    sum = (sum & 0xFFFF) + (sum >> 16);
                }
                !sum as u16
            };

            {
                let (raw, ipv4_header, _) = ipv4_packet.destructure();
                let transport_header_raw = &raw[ipv4_header.header_length() as usize..];
                let actual_checksum = tcp_header.checksum(transport_header_raw);

                assert_eq!(expected_checksum, actual_checksum);
            }

        } else {
            panic!("Packet is not TCP");
        }
    }
}
<|endoftext|>


<commit_before>// Rust source (c) 2016 by the Rayon developers. This is ported from
// [JavaScript sources][1] developed by Intel as part of the Parallel
// JS project. The copyright for the original source is reproduced
// below.
//
// Copyright (c) 2011, Intel Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// - Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//
// [1]: https://github.com/IntelLabs/RiverTrail/blob/master/examples/nbody-webgl/NBody.js

use cgmath::{InnerSpace, Point3, Vector3, Zero};
use rayon::prelude::*;
use rand::{Rand, Rng};
use std::f64::consts::PI;

const INITIAL_VELOCITY: f64 = 8.0; // set to 0.0 to turn off.

pub struct NBodyBenchmark {
    time: usize,
    bodies: (Vec<Body>, Vec<Body>),
}

#[derive(Copy, Clone, Debug)]
pub struct Body {
    pub position: Point3<f64>,
    pub velocity: Vector3<f64>,
    pub velocity2: Vector3<f64>,
}

impl NBodyBenchmark {
    pub fn new<R: Rng>(num_bodies: usize, rng: &mut R) -> NBodyBenchmark {
        let bodies0: Vec<_> =
            (0..num_bodies)
            .map(|_| {
                let position = Point3 {
                    x: f64::rand(rng).floor() * 40_000.0,
                    y: f64::rand(rng).floor() * 20_000.0,
                    z: (f64::rand(rng).floor() - 0.25) * 50_000.0,
                };

                let velocity = Vector3 {
                    x: (f64::rand(rng) - 0.5) * INITIAL_VELOCITY,
                    y: (f64::rand(rng) - 0.5) * INITIAL_VELOCITY,
                    z: f64::rand(rng) * INITIAL_VELOCITY + 10.0,
                };

                let velocity2 = Vector3 {
                    x: (f64::rand(rng) - 0.5) * INITIAL_VELOCITY,
                    y: (f64::rand(rng) - 0.5) * INITIAL_VELOCITY,
                    z: f64::rand(rng) * INITIAL_VELOCITY,
                };

                Body { position: position, velocity: velocity, velocity2: velocity2 }
            })
            .collect();

        let bodies1 = bodies0.clone();

        NBodyBenchmark {
            time: 0,
            bodies: (bodies0, bodies1),
        }
    }

    pub fn tick_par(&mut self) -> &[Body] {
        let (in_bodies, out_bodies) = if (self.time & 1) == 0 {
            (&self.bodies.0, &mut self.bodies.1)
        } else {
            (&self.bodies.1, &mut self.bodies.0)
        };

        let time = self.time;
        out_bodies.par_iter_mut()
                  .weight(200.0)
                  .zip(&in_bodies[..])
                  .for_each(|(out, prev)| {
                      let (vel, vel2) = next_velocity(time, prev, in_bodies);
                      out.velocity = vel;
                      out.velocity2 = vel2;

                      let next_velocity = vel - vel2;
                      out.position = prev.position + next_velocity;
                  });

        self.time += 1;

        out_bodies
    }

    pub fn tick_par_reduce(&mut self) -> &[Body] {
        let (in_bodies, out_bodies) = if (self.time & 1) == 0 {
            (&self.bodies.0, &mut self.bodies.1)
        } else {
            (&self.bodies.1, &mut self.bodies.0)
        };

        let time = self.time;
        out_bodies.par_iter_mut()
                  .weight(200.0)
                  .zip(&in_bodies[..])
                  .for_each(|(out, prev)| {
                      let (vel, vel2) = next_velocity_par(time, prev, in_bodies);
                      out.velocity = vel;
                      out.velocity2 = vel2;

                      let next_velocity = vel - vel2;
                      out.position = prev.position + next_velocity;
                  });

        self.time += 1;

        out_bodies
    }

    pub fn tick_seq(&mut self) -> &[Body] {
        let (in_bodies, out_bodies) = if (self.time & 1) == 0 {
            (&self.bodies.0, &mut self.bodies.1)
        } else {
            (&self.bodies.1, &mut self.bodies.0)
        };

        let time = self.time;
        for (out, prev) in out_bodies.iter_mut().zip(&in_bodies[..]) {
            let (vel, vel2) = next_velocity(time, prev, in_bodies);
            out.velocity = vel;
            out.velocity2 = vel2;

            let next_velocity = vel - vel2;
            out.position = prev.position + next_velocity;
        }

        self.time += 1;

        out_bodies
    }
}

/// Compute next velocity of `prev`
fn next_velocity(time: usize, prev: &Body, bodies: &[Body]) -> (Vector3<f64>, Vector3<f64>) {
    let time = time as f64;
    let center = Point3 {
        x: (time / 22.0).cos() * -4200.0,
        y: (time / 14.0).sin() * 9200.0,
        z: (time / 27.0).sin() * 6000.0,
    };

    // pull to center
    let max_distance = 3400.0;
    let pull_strength = 0.042;

    // zones
    let zone = 400.0;
    let repel = 100.0;
    let align = 300.0;
    let attract = 100.0;

    let (speed_limit, attract_power);
    if time < 500.0 {
        speed_limit = 2000.0;
        attract_power = 100.9;
    } else {
        speed_limit = 0.2;
        attract_power = 20.9;
    }

    let zone_sqrd = 3.0 * (zone * zone);

    let mut acc = Vector3::zero();
    let mut acc2 = Vector3::zero();

    let dir_to_center = center - prev.position;
    let dist_to_center = dir_to_center.magnitude();

    // orient to center
    if dist_to_center > max_distance {
        let velc = if time < 200.0 {
            0.2
        } else {
            (dist_to_center - max_distance) * pull_strength
        };

        let diff = (dir_to_center / dist_to_center) * velc;
        acc += diff;
    }

    // TODO -- parallelize this loop too? would be easy enough, it's just a reduction
    // Just have to factor things so that `tick_seq` doesn't do it in parallel.
    let zero: Vector3<f64> = Vector3::zero();
    let (diff, diff2) = bodies
        .iter()
        .fold(
            (zero, zero),
            |(mut diff, mut diff2), body| {
                let r = body.position - prev.position;

                // make sure we are not testing the particle against its own position
                let are_same = r == Vector3::zero();

                let dist_sqrd = r.magnitude2();

                if dist_sqrd < zone_sqrd && !are_same {
                    let length = dist_sqrd.sqrt();
                    let percent = dist_sqrd / zone_sqrd;

                    if dist_sqrd < repel {
                        let f = (repel / percent - 1.0) * 0.025;
                        let normal = (r / length) * f;
                        diff += normal;
                        diff2 += normal;
                    } else if dist_sqrd < align {
                        let thresh_delta = align - repel;
                        let adjusted_percent = (percent - repel) / thresh_delta;
                        let q = (0.5 - (adjusted_percent * PI * 2.0).cos() * 0.5 + 0.5) * 100.9;

                        // normalize vel2 and multiply by factor
                        let vel2_length = body.velocity2.magnitude();
                        let vel2 = (body.velocity2 / vel2_length) * q;

                        // normalize own velocity
                        let vel_length = prev.velocity.magnitude();
                        let vel = (prev.velocity / vel_length) * q;

                        diff += vel2;
                        diff2 += vel;
                    }

                    if dist_sqrd > attract { // attract
                        let thresh_delta2 = 1.0 - attract;
                        let adjusted_percent2 = (percent - attract) / thresh_delta2;
                        let c = (1.0 - ((adjusted_percent2 * PI * 2.0).cos() * 0.5 + 0.5)) * attract_power;

                        // normalize the distance vector
                        let d = (r / length) * c;

                        diff += d;
                        diff2 -= d;
                    }
                }

                (diff, diff2)
            });

    acc += diff;
    acc2 += diff2;

    // Speed limits
    if time > 500.0 {
        let acc_squared = acc.magnitude2();
        if acc_squared > speed_limit {
            acc *= 0.015;
        }

        let acc_squared2 = acc2.magnitude2();
        if acc_squared2 > speed_limit {
            acc2 *= 0.015;
        }
    }

    let mut new = prev.velocity + acc;
    let mut new2 = prev.velocity2 + acc2;

    if time < 500.0 {
        let acs = new2.magnitude2();
        if acs > speed_limit {
            new2 *= 0.15;
        }

        let acs2 = new.magnitude2();
        if acs2 > speed_limit {
            new *= 0.15;
        }
    }

    (new, new2)
}

/// Compute next velocity of `prev`
fn next_velocity_par(time: usize, prev: &Body, bodies: &[Body])
                     -> (Vector3<f64>, Vector3<f64>) {
    let time = time as f64;
    let center = Point3 {
        x: (time / 22.0).cos() * -4200.0,
        y: (time / 14.0).sin() * 9200.0,
        z: (time / 27.0).sin() * 6000.0,
    };

    // pull to center
    let max_distance = 3400.0;
    let pull_strength = 0.042;

    // zones
    let zone = 400.0;
    let repel = 100.0;
    let align = 300.0;
    let attract = 100.0;

    let (speed_limit, attract_power);
    if time < 500.0 {
        speed_limit = 2000.0;
        attract_power = 100.9;
    } else {
        speed_limit = 0.2;
        attract_power = 20.9;
    }

    let zone_sqrd = 3.0 * (zone * zone);

    let mut acc = Vector3::zero();
    let mut acc2 = Vector3::zero();

    let dir_to_center = center - prev.position;
    let dist_to_center = dir_to_center.magnitude();

    // orient to center
    if dist_to_center > max_distance {
        let velc = if time < 200.0 {
            0.2
        } else {
            (dist_to_center - max_distance) * pull_strength
        };

        let diff = (dir_to_center / dist_to_center) * velc;
        acc += diff;
    }

    let zero: Vector3<f64> = Vector3::zero();
    let (diff, diff2) = bodies
        .par_iter()
        .fold(
            (zero, zero),
            |(mut diff, mut diff2), body| {
                let r = body.position - prev.position;

                // make sure we are not testing the particle against its own position
                let are_same = r == Vector3::zero();

                let dist_sqrd = r.magnitude2();

                if dist_sqrd < zone_sqrd && !are_same {
                    let length = dist_sqrd.sqrt();
                    let percent = dist_sqrd / zone_sqrd;

                    if dist_sqrd < repel {
                        let f = (repel / percent - 1.0) * 0.025;
                        let normal = (r / length) * f;
                        diff += normal;
                        diff2 += normal;
                    } else if dist_sqrd < align {
                        let thresh_delta = align - repel;
                        let adjusted_percent = (percent - repel) / thresh_delta;
                        let q = (0.5 - (adjusted_percent * PI * 2.0).cos() * 0.5 + 0.5) * 100.9;

                        // normalize vel2 and multiply by factor
                        let vel2_length = body.velocity2.magnitude();
                        let vel2 = (body.velocity2 / vel2_length) * q;

                        // normalize own velocity
                        let vel_length = prev.velocity.magnitude();
                        let vel = (prev.velocity / vel_length) * q;

                        diff += vel2;
                        diff2 += vel;
                    }

                    if dist_sqrd > attract { // attract
                        let thresh_delta2 = 1.0 - attract;
                        let adjusted_percent2 = (percent - attract) / thresh_delta2;
                        let c = (1.0 - ((adjusted_percent2 * PI * 2.0).cos() * 0.5 + 0.5)) * attract_power;

                        // normalize the distance vector
                        let d = (r / length) * c;

                        diff += d;
                        diff2 -= d;
                    }
                }

                (diff, diff2)
            },
            |(diffa, diff2a), (diffb, diff2b)| (diffa + diffb, diff2a + diff2b));

    acc += diff;
    acc2 += diff2;

    // Speed limits
    if time > 500.0 {
        let acc_squared = acc.magnitude2();
        if acc_squared > speed_limit {
            acc *= 0.015;
        }

        let acc_squared2 = acc2.magnitude2();
        if acc_squared2 > speed_limit {
            acc2 *= 0.015;
        }
    }

    let mut new = prev.velocity + acc;
    let mut new2 = prev.velocity2 + acc2;

    if time < 500.0 {
        let acs = new2.magnitude2();
        if acs > speed_limit {
            new2 *= 0.15;
        }

        let acs2 = new.magnitude2();
        if acs2 > speed_limit {
            new *= 0.15;
        }
    }

    (new, new2)
}
<commit_msg>nbody: remove weights so they run adaptively<commit_after>// Rust source (c) 2016 by the Rayon developers. This is ported from
// [JavaScript sources][1] developed by Intel as part of the Parallel
// JS project. The copyright for the original source is reproduced
// below.
//
// Copyright (c) 2011, Intel Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// - Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//
// [1]: https://github.com/IntelLabs/RiverTrail/blob/master/examples/nbody-webgl/NBody.js

use cgmath::{InnerSpace, Point3, Vector3, Zero};
use rayon::prelude::*;
use rand::{Rand, Rng};
use std::f64::consts::PI;

const INITIAL_VELOCITY: f64 = 8.0; // set to 0.0 to turn off.

pub struct NBodyBenchmark {
    time: usize,
    bodies: (Vec<Body>, Vec<Body>),
}

#[derive(Copy, Clone, Debug)]
pub struct Body {
    pub position: Point3<f64>,
    pub velocity: Vector3<f64>,
    pub velocity2: Vector3<f64>,
}

impl NBodyBenchmark {
    pub fn new<R: Rng>(num_bodies: usize, rng: &mut R) -> NBodyBenchmark {
        let bodies0: Vec<_> =
            (0..num_bodies)
            .map(|_| {
                let position = Point3 {
                    x: f64::rand(rng).floor() * 40_000.0,
                    y: f64::rand(rng).floor() * 20_000.0,
                    z: (f64::rand(rng).floor() - 0.25) * 50_000.0,
                };

                let velocity = Vector3 {
                    x: (f64::rand(rng) - 0.5) * INITIAL_VELOCITY,
                    y: (f64::rand(rng) - 0.5) * INITIAL_VELOCITY,
                    z: f64::rand(rng) * INITIAL_VELOCITY + 10.0,
                };

                let velocity2 = Vector3 {
                    x: (f64::rand(rng) - 0.5) * INITIAL_VELOCITY,
                    y: (f64::rand(rng) - 0.5) * INITIAL_VELOCITY,
                    z: f64::rand(rng) * INITIAL_VELOCITY,
                };

                Body { position: position, velocity: velocity, velocity2: velocity2 }
            })
            .collect();

        let bodies1 = bodies0.clone();

        NBodyBenchmark {
            time: 0,
            bodies: (bodies0, bodies1),
        }
    }

    pub fn tick_par(&mut self) -> &[Body] {
        let (in_bodies, out_bodies) = if (self.time & 1) == 0 {
            (&self.bodies.0, &mut self.bodies.1)
        } else {
            (&self.bodies.1, &mut self.bodies.0)
        };

        let time = self.time;
        out_bodies.par_iter_mut()
                  .zip(&in_bodies[..])
                  .for_each(|(out, prev)| {
                      let (vel, vel2) = next_velocity(time, prev, in_bodies);
                      out.velocity = vel;
                      out.velocity2 = vel2;

                      let next_velocity = vel - vel2;
                      out.position = prev.position + next_velocity;
                  });

        self.time += 1;

        out_bodies
    }

    pub fn tick_par_reduce(&mut self) -> &[Body] {
        let (in_bodies, out_bodies) = if (self.time & 1) == 0 {
            (&self.bodies.0, &mut self.bodies.1)
        } else {
            (&self.bodies.1, &mut self.bodies.0)
        };

        let time = self.time;
        out_bodies.par_iter_mut()
                  .zip(&in_bodies[..])
                  .for_each(|(out, prev)| {
                      let (vel, vel2) = next_velocity_par(time, prev, in_bodies);
                      out.velocity = vel;
                      out.velocity2 = vel2;

                      let next_velocity = vel - vel2;
                      out.position = prev.position + next_velocity;
                  });

        self.time += 1;

        out_bodies
    }

    pub fn tick_seq(&mut self) -> &[Body] {
        let (in_bodies, out_bodies) = if (self.time & 1) == 0 {
            (&self.bodies.0, &mut self.bodies.1)
        } else {
            (&self.bodies.1, &mut self.bodies.0)
        };

        let time = self.time;
        for (out, prev) in out_bodies.iter_mut().zip(&in_bodies[..]) {
            let (vel, vel2) = next_velocity(time, prev, in_bodies);
            out.velocity = vel;
            out.velocity2 = vel2;

            let next_velocity = vel - vel2;
            out.position = prev.position + next_velocity;
        }

        self.time += 1;

        out_bodies
    }
}

/// Compute next velocity of `prev`
fn next_velocity(time: usize, prev: &Body, bodies: &[Body]) -> (Vector3<f64>, Vector3<f64>) {
    let time = time as f64;
    let center = Point3 {
        x: (time / 22.0).cos() * -4200.0,
        y: (time / 14.0).sin() * 9200.0,
        z: (time / 27.0).sin() * 6000.0,
    };

    // pull to center
    let max_distance = 3400.0;
    let pull_strength = 0.042;

    // zones
    let zone = 400.0;
    let repel = 100.0;
    let align = 300.0;
    let attract = 100.0;

    let (speed_limit, attract_power);
    if time < 500.0 {
        speed_limit = 2000.0;
        attract_power = 100.9;
    } else {
        speed_limit = 0.2;
        attract_power = 20.9;
    }

    let zone_sqrd = 3.0 * (zone * zone);

    let mut acc = Vector3::zero();
    let mut acc2 = Vector3::zero();

    let dir_to_center = center - prev.position;
    let dist_to_center = dir_to_center.magnitude();

    // orient to center
    if dist_to_center > max_distance {
        let velc = if time < 200.0 {
            0.2
        } else {
            (dist_to_center - max_distance) * pull_strength
        };

        let diff = (dir_to_center / dist_to_center) * velc;
        acc += diff;
    }

    // TODO -- parallelize this loop too? would be easy enough, it's just a reduction
    // Just have to factor things so that `tick_seq` doesn't do it in parallel.
    let zero: Vector3<f64> = Vector3::zero();
    let (diff, diff2) = bodies
        .iter()
        .fold(
            (zero, zero),
            |(mut diff, mut diff2), body| {
                let r = body.position - prev.position;

                // make sure we are not testing the particle against its own position
                let are_same = r == Vector3::zero();

                let dist_sqrd = r.magnitude2();

                if dist_sqrd < zone_sqrd && !are_same {
                    let length = dist_sqrd.sqrt();
                    let percent = dist_sqrd / zone_sqrd;

                    if dist_sqrd < repel {
                        let f = (repel / percent - 1.0) * 0.025;
                        let normal = (r / length) * f;
                        diff += normal;
                        diff2 += normal;
                    } else if dist_sqrd < align {
                        let thresh_delta = align - repel;
                        let adjusted_percent = (percent - repel) / thresh_delta;
                        let q = (0.5 - (adjusted_percent * PI * 2.0).cos() * 0.5 + 0.5) * 100.9;

                        // normalize vel2 and multiply by factor
                        let vel2_length = body.velocity2.magnitude();
                        let vel2 = (body.velocity2 / vel2_length) * q;

                        // normalize own velocity
                        let vel_length = prev.velocity.magnitude();
                        let vel = (prev.velocity / vel_length) * q;

                        diff += vel2;
                        diff2 += vel;
                    }

                    if dist_sqrd > attract { // attract
                        let thresh_delta2 = 1.0 - attract;
                        let adjusted_percent2 = (percent - attract) / thresh_delta2;
                        let c = (1.0 - ((adjusted_percent2 * PI * 2.0).cos() * 0.5 + 0.5)) * attract_power;

                        // normalize the distance vector
                        let d = (r / length) * c;

                        diff += d;
                        diff2 -= d;
                    }
                }

                (diff, diff2)
            });

    acc += diff;
    acc2 += diff2;

    // Speed limits
    if time > 500.0 {
        let acc_squared = acc.magnitude2();
        if acc_squared > speed_limit {
            acc *= 0.015;
        }

        let acc_squared2 = acc2.magnitude2();
        if acc_squared2 > speed_limit {
            acc2 *= 0.015;
        }
    }

    let mut new = prev.velocity + acc;
    let mut new2 = prev.velocity2 + acc2;

    if time < 500.0 {
        let acs = new2.magnitude2();
        if acs > speed_limit {
            new2 *= 0.15;
        }

        let acs2 = new.magnitude2();
        if acs2 > speed_limit {
            new *= 0.15;
        }
    }

    (new, new2)
}

/// Compute next velocity of `prev`
fn next_velocity_par(time: usize, prev: &Body, bodies: &[Body])
                     -> (Vector3<f64>, Vector3<f64>) {
    let time = time as f64;
    let center = Point3 {
        x: (time / 22.0).cos() * -4200.0,
        y: (time / 14.0).sin() * 9200.0,
        z: (time / 27.0).sin() * 6000.0,
    };

    // pull to center
    let max_distance = 3400.0;
    let pull_strength = 0.042;

    // zones
    let zone = 400.0;
    let repel = 100.0;
    let align = 300.0;
    let attract = 100.0;

    let (speed_limit, attract_power);
    if time < 500.0 {
        speed_limit = 2000.0;
        attract_power = 100.9;
    } else {
        speed_limit = 0.2;
        attract_power = 20.9;
    }

    let zone_sqrd = 3.0 * (zone * zone);

    let mut acc = Vector3::zero();
    let mut acc2 = Vector3::zero();

    let dir_to_center = center - prev.position;
    let dist_to_center = dir_to_center.magnitude();

    // orient to center
    if dist_to_center > max_distance {
        let velc = if time < 200.0 {
            0.2
        } else {
            (dist_to_center - max_distance) * pull_strength
        };

        let diff = (dir_to_center / dist_to_center) * velc;
        acc += diff;
    }

    let zero: Vector3<f64> = Vector3::zero();
    let (diff, diff2) = bodies
        .par_iter()
        .fold(
            (zero, zero),
            |(mut diff, mut diff2), body| {
                let r = body.position - prev.position;

                // make sure we are not testing the particle against its own position
                let are_same = r == Vector3::zero();

                let dist_sqrd = r.magnitude2();

                if dist_sqrd < zone_sqrd && !are_same {
                    let length = dist_sqrd.sqrt();
                    let percent = dist_sqrd / zone_sqrd;

                    if dist_sqrd < repel {
                        let f = (repel / percent - 1.0) * 0.025;
                        let normal = (r / length) * f;
                        diff += normal;
                        diff2 += normal;
                    } else if dist_sqrd < align {
                        let thresh_delta = align - repel;
                        let adjusted_percent = (percent - repel) / thresh_delta;
                        let q = (0.5 - (adjusted_percent * PI * 2.0).cos() * 0.5 + 0.5) * 100.9;

                        // normalize vel2 and multiply by factor
                        let vel2_length = body.velocity2.magnitude();
                        let vel2 = (body.velocity2 / vel2_length) * q;

                        // normalize own velocity
                        let vel_length = prev.velocity.magnitude();
                        let vel = (prev.velocity / vel_length) * q;

                        diff += vel2;
                        diff2 += vel;
                    }

                    if dist_sqrd > attract { // attract
                        let thresh_delta2 = 1.0 - attract;
                        let adjusted_percent2 = (percent - attract) / thresh_delta2;
                        let c = (1.0 - ((adjusted_percent2 * PI * 2.0).cos() * 0.5 + 0.5)) * attract_power;

                        // normalize the distance vector
                        let d = (r / length) * c;

                        diff += d;
                        diff2 -= d;
                    }
                }

                (diff, diff2)
            },
            |(diffa, diff2a), (diffb, diff2b)| (diffa + diffb, diff2a + diff2b));

    acc += diff;
    acc2 += diff2;

    // Speed limits
    if time > 500.0 {
        let acc_squared = acc.magnitude2();
        if acc_squared > speed_limit {
            acc *= 0.015;
        }

        let acc_squared2 = acc2.magnitude2();
        if acc_squared2 > speed_limit {
            acc2 *= 0.015;
        }
    }

    let mut new = prev.velocity + acc;
    let mut new2 = prev.velocity2 + acc2;

    if time < 500.0 {
        let acs = new2.magnitude2();
        if acs > speed_limit {
            new2 *= 0.15;
        }

        let acs2 = new.magnitude2();
        if acs2 > speed_limit {
            new *= 0.15;
        }
    }

    (new, new2)
}
<|endoftext|>


<commit_before>/// Macro for constructing sets of named sprites
///
/// Currently hardcoded to use CYAN / #00FFFF as the transparent color key.
#[macro_export]
macro_rules! brush {
    {
        $enumname:ident {
            // Image file to load brushes from.
            $([$filename:expr,
              // Named brushes
              $([$brushname:ident,
                  // Frames for the named brush as rectangles in the current
                  // image file.
                  $($xcenter:expr, $ycenter:expr, $xdim:expr, $ydim:expr, $x:expr, $y:expr),+
              ])+
            ])+
        }
    } =>
    {
#[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
        pub enum $enumname {
            $(
                $($brushname,)*
            )*
        }

        cache_key!($enumname);

        impl $enumname {
            /// Get the sprite image.
            pub fn get(self, idx: usize) -> Image {
                BRUSH_CACHE.with(|c| c.borrow().get(self).expect("Brush not initialized")[idx])
            }

            /// Build the actual sprites in a canvas for the enum set.
            pub fn init(builder: &mut CanvasBuilder) {
                BRUSH_CACHE.with(|c| { *c.borrow_mut() = build_brushes(builder); });
            }
        }

        thread_local!(static BRUSH_CACHE: RefCell<$crate::IndexCache<Brush, Vec<Image>>> = RefCell::new(IndexCache::new()));

        // TODO: Builder as generic ImageStore
        fn build_brushes(builder: &mut $crate::backend::CanvasBuilder) -> $crate::IndexCache<Brush, Vec<Image>> {
            use image;
            use $crate::{V2, color_key, color};

            let mut ret = $crate::IndexCache::new();

            fn load(data: &'static [u8]) -> image::ImageBuffer<image::Rgba<u8>, Vec<u8>> {
                // XXX: Shouldn't hardcode the color::CYAN part, factor out
                // the loader?
                color_key(&image::load_from_memory(data).unwrap(), color::CYAN)
            }

            $({
                let mut sheet = load(include_bytes!($filename));

                $({
                    let mut frames = Vec::new();

                    $({
                        // Offset vector is the negative of the center
                        // position. Center position is nicer for humans doing
                        // data entry.
                        frames.push(builder.add_image(
                                V2(-$xcenter, -$ycenter),
                                &image::SubImage::new(&mut sheet, $x, $y, $xdim, $ydim)));
                    })*

                    ret.insert($enumname::$brushname, frames);
                })*

            })*

            ret
        }
    }
}
<commit_msg>Bring brush macro up to date<commit_after>/// Macro for constructing sets of named sprites
///
/// Currently hardcoded to use CYAN / #00FFFF as the transparent color key.
#[macro_export]
macro_rules! brush {
    {
        $enumname:ident {
            // Image file to load brushes from.
            $([$filename:expr,
              // Named brushes
              $([$brushname:ident,
                  // Frames for the named brush as rectangles in the current
                  // image file.
                  $($xcenter:expr, $ycenter:expr, $xdim:expr, $ydim:expr, $x:expr, $y:expr),+
              ])+
            ])+
        }
    } =>
    {
#[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
        pub enum $enumname {
            $(
                $($brushname,)*
            )*
        }

        cache_key!($enumname);

        impl $enumname {
            /// Get the sprite image.
            pub fn get(self, idx: usize) -> usize {
                BRUSH_CACHE.with(|c| c.borrow().get(self).expect("Brush not initialized")[idx])
            }

            /// Build the actual sprites in a canvas for the enum set.
            pub fn init<S>(builder: &mut S)
                where S: $crate::ImageStore
            {
                BRUSH_CACHE.with(|c| { *c.borrow_mut() = build_brushes(builder); });
            }
        }

        thread_local!(static BRUSH_CACHE: RefCell<$crate::IndexCache<Brush, Vec<usize>>> = RefCell::new(IndexCache::new()));

        // TODO: Builder as generic ImageStore
        fn build_brushes<S>(builder: &mut S) -> $crate::IndexCache<Brush, Vec<usize>>
            where S: $crate::ImageStore
        {
            use image;
            use $crate::color_key;

            let mut ret = $crate::IndexCache::new();

            fn load(data: &'static [u8]) -> image::ImageBuffer<image::Rgba<u8>, Vec<u8>> {
                // Don't force the macro user have calx_color imported, use
                // the convert from u32 interface for colors.
                let cyan = 0x00FFFFFF;
                color_key(&image::load_from_memory(data).unwrap(), cyan)
            }

            $({
                let mut sheet = load(include_bytes!($filename));

                $({
                    let mut frames = Vec::new();

                    $({
                        frames.push(builder.add_image(
                                [$xcenter, $ycenter],
                                &image::SubImage::new(&mut sheet, $x, $y, $xdim, $ydim)));
                    })*

                    ret.insert($enumname::$brushname, frames);
                })*

            })*

            ret
        }
    }
}
<|endoftext|>


<commit_before>use serde;
use serde_derive::{Deserialize, Serialize};
use std::mem;
use std::ops::Deref;

/// An object that can be incrementally updated with events.
pub trait Incremental: Sized {
    type Seed;
    type Event;

    /// Initialize the starting state from a seed value.
    fn from_seed(s: &Self::Seed) -> Self;

    /// Try to update the object with an event.
    fn update(self, e: &Self::Event) -> Self;
}

/// Handle that stores an `Incremental` object and the event sequence used to build it.
///
/// The full `IncrementalState` serializes itself normally with a full snapshot of the state, but
/// you can make a possibly much smaller serialization by just saving the History and then creating
/// a new state with `IncrmentalState::from(history)`. This will involve replaying the entire
/// history so it might be much slower than just deserializing the snapshot.
///
/// # Examples
///
/// ```
/// use calx::{Incremental, IncrementalState};
///
/// #[derive(Default)]
/// struct State(u32);
///
/// impl Incremental for State {
///     type Seed = u32;
///     type Event = u32;
///
///     fn update(self, e: &Self::Event) -> State { State(self.0 + *e) }
///     fn from_seed(s: &Self::Seed) -> Self { State(*s) }
/// }
///
/// let mut handle: IncrementalState<State> = Default::default();
/// assert_eq!(handle.0, 0);
///
/// for x in &[1, 2, 3, 4] { handle.update(*x); }
/// assert_eq!(handle.0, 10);
///
/// // Save the history.
/// let history_copy = handle.history().clone();
///
/// handle.undo();               // Magical time travel!
/// assert_eq!(handle.0, 6);
///
/// // Create a new state just from the saved history.
/// let handle2: IncrementalState<State> = history_copy.into();
/// assert_eq!(handle2.0, 10);
/// ```
#[derive(Serialize, Deserialize)]
// Need to add extra boilerplate or serde will get confused by the dependenent types.
#[serde(bound(
    serialize = "T: serde::Serialize, T::Seed: serde::Serialize, T::Event: serde::Serialize",
    deserialize = "T: serde::Deserialize<'de>, T::Seed: serde::Deserialize<'de>, T::Event: serde::Deserialize<'de>",
))]
pub struct IncrementalState<T: Incremental> {
    state: T,
    history: History<T::Seed, T::Event>,
}

#[derive(Clone, Serialize, Deserialize)]
pub struct History<U, E> {
    pub seed: U,
    pub events: Vec<E>,
}

// Implemented manually instead of derived so that T::Event doesn't need to implement Default.
impl<T: Incremental<Seed = U>, U: Default> Default for IncrementalState<T> {
    fn default() -> Self { IncrementalState::new(T::Seed::default()) }
}

impl<T: Incremental> IncrementalState<T> {
    pub fn new(seed: T::Seed) -> Self {
        let state = T::from_seed(&seed);
        IncrementalState {
            state,
            history: History {
                seed,
                events: Vec::new(),
            },
        }
    }

    pub fn history(&self) -> &History<T::Seed, T::Event> { &self.history }

    pub fn update(&mut self, e: T::Event) {
        // XXX: Need to get state away from borrow checker for updating, is there a better way than
        // ugly unsafe tricks?
        let state = mem::replace(&mut self.state, unsafe { mem::uninitialized() }).update(&e);
        self.state = state;
        self.history.events.push(e);
    }

    /// Do arbitrary modification on event history, then replay state to match new history.
    ///
    /// Use this if you want to undo multiple steps, replaying can be very expensive.
    pub fn edit_history<F: FnOnce(&mut History<T::Seed, T::Event>) -> U, U>(&mut self, f: F) -> U {
        let ret = f(&mut self.history);
        self.replay();
        ret
    }

    /// Cancel the last event and rewind state to the position before it.
    pub fn undo(&mut self) -> Option<T::Event> { self.edit_history(|h| h.events.pop()) }

    fn replay(&mut self) {
        let mut state = T::from_seed(&self.history.seed);

        for e in &self.history.events {
            state = state.update(e);
        }

        self.state = state;
    }
}

impl<T: Incremental> From<History<T::Seed, T::Event>> for IncrementalState<T> {
    fn from(history: History<T::Seed, T::Event>) -> Self {
        let state = T::from_seed(&history.seed);
        let mut ret = IncrementalState { state, history };
        ret.replay();
        ret
    }
}

impl<T: Incremental> Deref for IncrementalState<T> {
    type Target = T;

    fn deref(&self) -> &T { &self.state }
}
<commit_msg>refactor: Just use `mut &self` in Incremental<commit_after>use serde;
use serde_derive::{Deserialize, Serialize};
use std::ops::Deref;

/// An object that can be incrementally updated with events.
pub trait Incremental: Sized {
    type Seed;
    type Event;

    /// Initialize the starting state from a seed value.
    fn from_seed(s: &Self::Seed) -> Self;

    /// Try to update the object with an event.
    fn update(&mut self, e: &Self::Event);
}

/// Handle that stores an `Incremental` object and the event sequence used to build it.
///
/// The full `IncrementalState` serializes itself normally with a full snapshot of the state, but
/// you can make a possibly much smaller serialization by just saving the `History` and then
/// creating a new state with `IncrmentalState::from(history)`. This will involve replaying the
/// entire history so it might be much slower than just deserializing the snapshot.
///
/// # Examples
///
/// ```
/// use calx::{Incremental, IncrementalState};
///
/// #[derive(Default)]
/// struct State(u32);
///
/// impl Incremental for State {
///     type Seed = u32;
///     type Event = u32;
///
///     fn update(&mut self, e: &Self::Event) { self.0 += *e }
///     fn from_seed(s: &Self::Seed) -> Self { State(*s) }
/// }
///
/// let mut handle: IncrementalState<State> = Default::default();
/// assert_eq!(handle.0, 0);
///
/// for x in &[1, 2, 3, 4] { handle.update(*x); }
/// assert_eq!(handle.0, 10);
///
/// // Save the history.
/// let history_copy = handle.history().clone();
///
/// handle.undo();               // Magical time travel!
/// assert_eq!(handle.0, 6);
///
/// // Create a new state just from the saved history.
/// let handle2: IncrementalState<State> = history_copy.into();
/// assert_eq!(handle2.0, 10);
/// ```
#[derive(Serialize, Deserialize)]
// Need to add extra boilerplate or serde will get confused by the dependenent types.
#[serde(bound(
    serialize = "T: serde::Serialize, T::Seed: serde::Serialize, T::Event: serde::Serialize",
    deserialize = "T: serde::Deserialize<'de>, T::Seed: serde::Deserialize<'de>, T::Event: serde::Deserialize<'de>",
))]
pub struct IncrementalState<T: Incremental> {
    state: T,
    history: History<T::Seed, T::Event>,
}

#[derive(Clone, Serialize, Deserialize)]
pub struct History<U, E> {
    pub seed: U,
    pub events: Vec<E>,
}

// Implemented manually instead of derived so that T::Event doesn't need to implement Default.
impl<T: Incremental<Seed = U>, U: Default> Default for IncrementalState<T> {
    fn default() -> Self { IncrementalState::new(T::Seed::default()) }
}

impl<T: Incremental> IncrementalState<T> {
    pub fn new(seed: T::Seed) -> Self {
        let state = T::from_seed(&seed);
        IncrementalState {
            state,
            history: History {
                seed,
                events: Vec::new(),
            },
        }
    }

    pub fn history(&self) -> &History<T::Seed, T::Event> { &self.history }

    pub fn update(&mut self, e: T::Event) {
        self.state.update(&e);
        self.history.events.push(e);
    }

    /// Do arbitrary modification on event history, then replay state to match new history.
    ///
    /// Use this if you want to undo multiple steps, replaying can be very expensive.
    pub fn edit_history<F: FnOnce(&mut History<T::Seed, T::Event>) -> U, U>(&mut self, f: F) -> U {
        let ret = f(&mut self.history);
        self.replay();
        ret
    }

    /// Cancel the last event and rewind state to the position before it.
    pub fn undo(&mut self) -> Option<T::Event> { self.edit_history(|h| h.events.pop()) }

    fn replay(&mut self) {
        let mut state = T::from_seed(&self.history.seed);

        for e in &self.history.events {
            state.update(e);
        }

        self.state = state;
    }
}

impl<T: Incremental> From<History<T::Seed, T::Event>> for IncrementalState<T> {
    fn from(history: History<T::Seed, T::Event>) -> Self {
        let state = T::from_seed(&history.seed);
        let mut ret = IncrementalState { state, history };
        ret.replay();
        ret
    }
}

impl<T: Incremental> Deref for IncrementalState<T> {
    type Target = T;

    fn deref(&self) -> &T { &self.state }
}
<|endoftext|>


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

#![allow(unused_imports)]

extern crate ceph_rust;
extern crate lsio;
extern crate libc;

use std::iter::FromIterator;
use std::ptr;
use std::str;
use std::slice;
use std::ffi::{CStr, CString};

use libc::*;
use ceph_rust::rados as ceph;
use ceph_rust::helpers as ceph_helpers;

macro_rules! zeroed_c_char_buf {
	($n:expr) => {
		repeat(0).take($n).collect::<Vec<c_char>>();
	}
}

#[cfg(not(target_os = "linux"))]
fn main(){}

#[cfg(target_os = "linux")]
fn main() {
  let mut major: i32 = 0;
  let mut minor: i32 = 0;
  let mut extra: i32 = 0;

  let config_file = CString::new("/etc/ceph/ceph.conf").unwrap();
  let mut cluster: ceph::rados_t = std::ptr::null_mut();
  let mut ret_code: i32;

  unsafe {
    ceph::rados_version(&mut major, &mut minor, &mut extra);
    ret_code = ceph::rados_create(&mut cluster, std::ptr::null());
    println!("Return code: {} - {:?}", ret_code, cluster);

    ret_code = ceph::rados_conf_read_file(cluster, config_file.as_ptr());
    println!("Return code: {} - {:?}", ret_code, cluster);

    ret_code = ceph::rados_connect(cluster);
    println!("Return code: {} - {:?}", ret_code, cluster);

    let pools_list = ceph_helpers::rados_pools(cluster).unwrap();
    println!("{:?}", pools_list);

    ceph::rados_shutdown(cluster);
  }

  println!("v{}.{}.{}", major, minor, extra);

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

#![allow(unused_imports)]

extern crate ceph_rust;
extern crate lsio;
extern crate libc;

use std::iter::FromIterator;
use std::ptr;
use std::str;
use std::slice;
use std::ffi::{CStr, CString};

use libc::*;
#[cfg(target_os = "linux")]
use ceph_rust::rados as ceph;
#[cfg(target_os = "linux")]
use ceph_rust::helpers as ceph_helpers;

macro_rules! zeroed_c_char_buf {
	($n:expr) => {
		repeat(0).take($n).collect::<Vec<c_char>>();
	}
}

#[cfg(not(target_os = "linux"))]
fn main(){}

#[cfg(target_os = "linux")]
fn main() {
  let mut major: i32 = 0;
  let mut minor: i32 = 0;
  let mut extra: i32 = 0;

  let config_file = CString::new("/etc/ceph/ceph.conf").unwrap();
  let mut cluster: ceph::rados_t = std::ptr::null_mut();
  let mut ret_code: i32;

  unsafe {
    ceph::rados_version(&mut major, &mut minor, &mut extra);
    ret_code = ceph::rados_create(&mut cluster, std::ptr::null());
    println!("Return code: {} - {:?}", ret_code, cluster);

    ret_code = ceph::rados_conf_read_file(cluster, config_file.as_ptr());
    println!("Return code: {} - {:?}", ret_code, cluster);

    ret_code = ceph::rados_connect(cluster);
    println!("Return code: {} - {:?}", ret_code, cluster);

    let pools_list = ceph_helpers::rados_pools(cluster).unwrap();
    println!("{:?}", pools_list);

    ceph::rados_shutdown(cluster);
  }

  println!("v{}.{}.{}", major, minor, extra);

}
<|endoftext|>


<commit_before>use std::fmt;
use std::io;
use std::iter;

mod errors;

type Numbers = Vec<i64>;

const PHASES: usize = 100;
const ANSWER_LENGTH: usize = 8;

fn main() -> io::Result<()> {
    let input: Numbers = {
        let mut input = String::new();
        io::stdin().read_line(&mut input)?;
        input
            .trim()
            .chars()
            .map(|c| {
                c.to_digit(10)
                    .map(|d| d as i64)
                    .ok_or(errors::io(&format!("Invalid digit: {}", c)))
            })
            .collect::<io::Result<Numbers>>()
    }?;
    let length = input.len();

    let patterns: Vec<Numbers> = (1..=length)
        .map(|i| {
            iter::repeat(0)
                .take(i)
                .chain(iter::repeat(1).take(i))
                .chain(iter::repeat(0).take(i))
                .chain(iter::repeat(-1).take(i))
                .cycle()
                .skip(1)
                .take(length)
                .collect()
        })
        .collect();

    let result = &iter::successors(Some(input), |input| Some(phase(&input, &patterns)))
        .nth(PHASES)
        .unwrap();
    let answer = {
        let mut answer = join_vec(&result);
        answer.truncate(ANSWER_LENGTH);
        answer
    };
    println!("{}", answer);

    Ok(())
}

fn phase(input: &Numbers, patterns: &Vec<Numbers>) -> Numbers {
    patterns
        .iter()
        .map(|pattern| {
            (pattern
                .iter()
                .zip(input.iter())
                .map(|(pattern_value, input_value)| pattern_value * input_value)
                .sum::<i64>()
                % 10)
                .abs()
        })
        .collect()
}

fn join_vec<T>(vector: &Vec<T>) -> String
where
    T: fmt::Display,
{
    vector
        .iter()
        .map(|value| format!("{}", value))
        .collect::<Vec<String>>()
        .join("")
}
<commit_msg>2019: Day 16, part 1: compute patterns on the fly.<commit_after>use std::fmt;
use std::io;
use std::iter;

mod errors;

type Numbers = Vec<i64>;

const PHASES: usize = 100;
const ANSWER_LENGTH: usize = 8;

fn main() -> io::Result<()> {
    let input: Numbers = {
        let mut input = String::new();
        io::stdin().read_line(&mut input)?;
        input
            .trim()
            .chars()
            .map(|c| {
                c.to_digit(10)
                    .map(|d| d as i64)
                    .ok_or(errors::io(&format!("Invalid digit: {}", c)))
            })
            .collect::<io::Result<Numbers>>()
    }?;

    let result = &iter::successors(Some(input), |input| Some(phase(&input)))
        .nth(PHASES)
        .unwrap();
    let answer = {
        let mut answer = join_vec(&result);
        answer.truncate(ANSWER_LENGTH);
        answer
    };
    println!("{}", answer);

    Ok(())
}

fn phase(input: &Numbers) -> Numbers {
    (1..=input.len())
        .map(|y_offset| {
            (input
                .iter()
                .enumerate()
                .map(|(x_offset, input_value)| input_value * pattern_at(y_offset, x_offset))
                .sum::<i64>()
                % 10)
                .abs()
        })
        .collect()
}

fn pattern_at(y_offset: usize, x_offset: usize) -> i64 {
    let x = x_offset % (y_offset * 4);
    if x < y_offset - 1 {
        0
    } else if x < y_offset * 2 - 1 {
        1
    } else if x < y_offset * 3 - 1 {
        0
    } else if x < y_offset * 4 - 1 {
        -1
    } else {
        0
    }
}

fn join_vec<T>(vector: &Vec<T>) -> String
where
    T: fmt::Display,
{
    vector
        .iter()
        .map(|value| format!("{}", value))
        .collect::<Vec<String>>()
        .join("")
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Single-threaded TCP echo server with a bounded buffer pool. Allocates N buffers upon
//! initialization and uses them to serve up to N clients concurrently. When all buffers are in use,
//! the server waits until the next buffer becomes available before accepting the next client
//! connection.

extern crate gj;
extern crate gjio;

use gj::{EventLoop, Promise, PromiseFulfiller, TaskReaper, TaskSet};
use gjio::{AsyncRead, AsyncWrite, Slice};
use std::cell::RefCell;
use std::rc::Rc;

/// Container for buffers that are not currently being used on a connection.
struct BufferPool {
    buffers: Vec<Vec<u8>>,
    waiting: Option<PromiseFulfiller<Buffer, ()>>,
}

struct Buffer {
    buf: Vec<u8>,
    pool: Rc<RefCell<BufferPool>>,
}

impl Buffer {
    fn new(buf: Vec<u8>, pool: Rc<RefCell<BufferPool>>) -> Buffer {
        Buffer { buf: buf, pool: pool }
    }
}

impl AsRef<[u8]> for Buffer {
    fn as_ref<'a>(&'a self) -> &'a [u8] {
        &self.buf[..]
    }
}

impl AsMut<[u8]> for Buffer {
    fn as_mut<'a>(&'a mut self) -> &'a mut [u8] {
        &mut self.buf[..]
    }
}

impl Drop for Buffer {
    fn drop(&mut self) {
        let vec = ::std::mem::replace(&mut self.buf, Vec::with_capacity(0));
        let waiting = self.pool.borrow_mut().waiting.take();
        match waiting {
            Some(fulfiller) => fulfiller.fulfill(Buffer::new(vec, self.pool.clone())),
            None => self.pool.borrow_mut().buffers.push(vec),
        }
    }
}

impl BufferPool {
    pub fn new(buf_size: usize, num_buffers: usize) -> BufferPool {
        BufferPool { buffers: vec![vec![0; buf_size]; num_buffers], waiting: None }
    }

    /// Retrieves a buffer from the pool, waiting until one is available if there are none
    /// already available. Fails if another task is already waiting for a buffer.
    pub fn pop(pool: &Rc<RefCell<BufferPool>>) -> Promise<Buffer, ()> {
        let maybe_buf = pool.borrow_mut().buffers.pop();
        match maybe_buf {
            Some(buf) => Promise::ok(Buffer::new(buf, pool.clone())),
            None => {
                if pool.borrow().waiting.is_some() {
                    Promise::err(())
                } else {
                    let (promise, fulfiller) = Promise::and_fulfiller();
                    pool.borrow_mut().waiting = Some(fulfiller);
                    promise
                }
            }
        }
    }
}

/// Reads `buf`-sized chunks of bytes from a stream until end-of-file, immediately writing each
/// chunk back to the same stream. Note that this function is recursive. In a naive implementation
/// of promises, such a function could potentially create an unbounded chain of promises. However,
/// GJ implements a tail-call optimization that shortens promise chains when possible, and therefore
/// this loop can run indefinitely, consuming only a small, bounded amount of memory.
fn echo(mut stream: gjio::SocketStream, buf: Buffer) -> Promise<(), ::std::io::Error> {
    stream.try_read(buf, 1).then(move |(buf, n)| {
        if n == 0 { // EOF
            Promise::ok(())
        } else {
            stream.write(Slice::new(buf, n)).then(move |slice| {
                echo(stream, slice.buf)
            })
        }
    })
}

struct Reaper;

impl TaskReaper<(), ::std::io::Error> for Reaper {
    fn task_failed(&mut self, error: ::std::io::Error) {
        println!("Task failed: {}", error);
    }
}

/// Waits for a buffer from the pool, accepts a connection, then spawns an echo() task on that
/// connection with that buffer.
fn accept_loop(mut listener: gjio::SocketListener,
               mut task_set: TaskSet<(), ::std::io::Error>,
               buffer_pool: Rc<RefCell<BufferPool>>)
               -> Promise<(), ::std::io::Error>
{
    let buf_promise = BufferPool::pop(&buffer_pool).map_err(|()| unreachable!());
    buf_promise.then(move |buf| {
        listener.accept().then(move |stream| {
            task_set.add(echo(stream, buf));
            accept_loop(listener, task_set, buffer_pool)
        })
    })
}

pub fn main() {
    let args: Vec<String> = ::std::env::args().collect();
    if args.len() != 2 {
        println!("usage: {} HOST:PORT", args[0]);
        return;
    }
    let buffer_pool = Rc::new(RefCell::new(BufferPool::new(1024, 64)));

    EventLoop::top_level(move |wait_scope| -> Result<(), ::std::io::Error> {
        use std::net::ToSocketAddrs;
        let mut event_port = try!(gjio::EventPort::new());
        let network = event_port.get_network();
        let addr = try!(args[1].to_socket_addrs()).next().expect("could not parse address");
        let mut address = network.get_tcp_address(addr);
        let listener = try!(address.listen());
        let reaper = Box::new(Reaper);
        accept_loop(listener, TaskSet::new(reaper), buffer_pool).lift().wait(wait_scope, &mut event_port)
    }).expect("top level");
}
<commit_msg>cleaning up the echo example<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Single-threaded TCP echo server with a bounded buffer pool. Allocates N buffers upon
//! initialization and uses them to serve up to N clients concurrently. When all buffers are in use,
//! the server waits until the next buffer becomes available before accepting the next client
//! connection.

extern crate gj;
extern crate gjio;

use gj::{EventLoop, Promise, PromiseFulfiller, TaskReaper, TaskSet};
use gjio::{AsyncRead, AsyncWrite, Slice};
use std::cell::RefCell;
use std::rc::Rc;

/// Container for buffers that are not currently being used on a connection.
struct BufferPool {
    buffers: Vec<Vec<u8>>,
    waiting: Option<PromiseFulfiller<Buffer, ::std::io::Error>>,
}

struct Buffer {
    buf: Vec<u8>,
    pool: Rc<RefCell<BufferPool>>,
}

impl AsRef<[u8]> for Buffer {
    fn as_ref<'a>(&'a self) -> &'a [u8] {
        &self.buf[..]
    }
}

impl AsMut<[u8]> for Buffer {
    fn as_mut<'a>(&'a mut self) -> &'a mut [u8] {
        &mut self.buf[..]
    }
}

impl Drop for Buffer {
    fn drop(&mut self) {
        let vec = ::std::mem::replace(&mut self.buf, Vec::with_capacity(0));
        let waiting = self.pool.borrow_mut().waiting.take();
        match waiting {
            Some(fulfiller) => fulfiller.fulfill(Buffer { buf: vec, pool: self.pool.clone() }),
            None => self.pool.borrow_mut().buffers.push(vec),
        }
    }
}

impl BufferPool {
    pub fn new(buf_size: usize, num_buffers: usize) -> BufferPool {
        BufferPool { buffers: vec![vec![0; buf_size]; num_buffers], waiting: None }
    }

    /// Retrieves a buffer from the pool, waiting until one is available if there are none
    /// already available. Fails if another task is already waiting for a buffer.
    pub fn pop(pool: &Rc<RefCell<BufferPool>>) -> Promise<Buffer, ::std::io::Error> {
        let &mut BufferPool { ref mut buffers, ref mut waiting } = &mut *pool.borrow_mut();
        match buffers.pop() {
            Some(buf) => Promise::ok(Buffer { buf: buf, pool: pool.clone() }),
            None => {
                if waiting.is_some() {
                    Promise::err(::std::io::Error::new(::std::io::ErrorKind::Other,
                                                       "another client is already waiting"))
                } else {
                    let (promise, fulfiller) = Promise::and_fulfiller();
                    *waiting = Some(fulfiller);
                    promise
                }
            }
        }
    }
}

/// Reads `buf`-sized chunks of bytes from a stream until end-of-file, immediately writing each
/// chunk back to the same stream. Note that this function is recursive. In a naive implementation
/// of promises, such a function could potentially create an unbounded chain of promises. However,
/// GJ implements a tail-call optimization that shortens promise chains when possible, and therefore
/// this loop can run indefinitely, consuming only a small, bounded amount of memory.
fn echo(mut stream: gjio::SocketStream, buf: Buffer) -> Promise<(), ::std::io::Error> {
    stream.try_read(buf, 1).then(move |(buf, n)| {
        if n == 0 { // EOF
            Promise::ok(())
        } else {
            stream.write(Slice::new(buf, n)).then(move |slice| {
                echo(stream, slice.buf)
            })
        }
    })
}

struct Reaper;

impl TaskReaper<(), ::std::io::Error> for Reaper {
    fn task_failed(&mut self, error: ::std::io::Error) {
        println!("Task failed: {}", error);
    }
}

/// Waits for a buffer from the pool, accepts a connection, then spawns an echo() task on that
/// connection with that buffer.
fn accept_loop(mut listener: gjio::SocketListener,
               mut task_set: TaskSet<(), ::std::io::Error>,
               buffer_pool: Rc<RefCell<BufferPool>>)
               -> Promise<(), ::std::io::Error>
{
    BufferPool::pop(&buffer_pool).then(move |buf| {
        listener.accept().then(move |stream| {
            task_set.add(echo(stream, buf));
            accept_loop(listener, task_set, buffer_pool)
        })
    })
}

pub fn main() {
    let args: Vec<String> = ::std::env::args().collect();
    if args.len() != 2 {
        println!("usage: {} HOST:PORT", args[0]);
        return;
    }
    let buffer_pool = Rc::new(RefCell::new(BufferPool::new(1024, 64)));

    EventLoop::top_level(move |wait_scope| -> Result<(), ::std::io::Error> {
        use std::net::ToSocketAddrs;
        let mut event_port = try!(gjio::EventPort::new());
        let network = event_port.get_network();
        let addr = try!(args[1].to_socket_addrs()).next().expect("could not parse address");
        let mut address = network.get_tcp_address(addr);
        let listener = try!(address.listen());
        let reaper = Box::new(Reaper);
        accept_loop(listener, TaskSet::new(reaper), buffer_pool).lift().wait(wait_scope, &mut event_port)
    }).expect("top level");
}
<|endoftext|>


<commit_before>fn main() {
    let length = 50;
    let width = 30;

    println!(
        "Area of rectangle with length: {} and width: {} is equal to: {}",
        length, width, area(length, width)
    );

    let rect = (length, width);

    println!(
        "Area of rectangle with length: {} and width: {} is equal to: {}",
        rect.0, rect.1, area_with_tuple(rect)
    );

    let rect_struct = Rectangle{
        length,
        width
    };

    println!(
        "Area of rectangle {:?} is equal to: {}",
        rect_struct, rect_struct.area()
    );
}

fn area(length: u32, width: u32) -> u32 {
    length * width
}

fn area_with_tuple(dimensions: (u32, u32)) -> u32 {
    dimensions.0 * dimensions.1
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.length * self.width
    }
}

#[derive(Debug)]
struct Rectangle {
    length: u32,
    width: u32
}
<commit_msg>Implement can_hold method on Rectangle struct<commit_after>fn main() {
    let length = 50;
    let width = 30;

    println!(
        "Area of rectangle with length: {} and width: {} is equal to: {}",
        length, width, area(length, width)
    );

    let rect = (length, width);

    println!(
        "Area of rectangle with length: {} and width: {} is equal to: {}",
        rect.0, rect.1, area_with_tuple(rect)
    );

    let rect_struct = Rectangle{
        length,
        width
    };

    println!(
        "Area of rectangle {:?} is equal to: {}",
        rect_struct, rect_struct.area()
    );

    let other_rect_struct = Rectangle {
        length: 20,
        width: 20
    };

    println!(
        "Does {:?} can hold {:?}: {}",
        rect_struct, other_rect_struct,
        rect_struct.can_hold(&other_rect_struct))
}

fn area(length: u32, width: u32) -> u32 {
    length * width
}

fn area_with_tuple(dimensions: (u32, u32)) -> u32 {
    dimensions.0 * dimensions.1
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.length * self.width
    }

    fn can_hold(&self, other: &Rectangle) -> bool {
        self.length > other.length && self.width > other.width
    }
}

#[derive(Debug)]
struct Rectangle {
    length: u32,
    width: u32
}
<|endoftext|>