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

use ::window::WindowConfig;

/*===============================================================================================*/
/*------WINDOW MANAGER STRUCT--------------------------------------------------------------------*/
/*===============================================================================================*/

/// Handles the creation and destruction of windows.
#[derive (Copy, Clone)]
pub struct WindowManager {

    // Private
    _window_config: WindowConfig,
}

/*===============================================================================================*/
/*------WINDOW MANAGER PUBLIC STATIC METHODS-----------------------------------------------------*/
/*===============================================================================================*/

impl WindowManager {

    /// Returns a new instance of the Window Manager.
    pub fn new () -> WindowManager {
        WindowManager {_window_config: WindowConfig::default ()}
    }
}

/*-----------------------------------------------------------------------------------------------*/

impl Default for WindowManager {

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

use ::engine::App;
use ::window::WindowConfig;

/*===============================================================================================*/
/*------WINDOW MANAGER STRUCT--------------------------------------------------------------------*/
/*===============================================================================================*/

/// Handles the creation and destruction of windows.
pub struct WindowManager {

    // Private
    _window_config: WindowConfig,
}

/*===============================================================================================*/
/*------WINDOW MANAGER PUBLIC METHODS------------------------------------------------------------*/
/*===============================================================================================*/

impl WindowManager {

    /// Initializes the window manager
    pub fn init (&mut self) {

        info! ("Initializing the Window Manager.");

        // Get a reference to the resource manager and load the window config
        let resource_mgr  = App::get_resource_manager ().unwrap ();
        let config_result = resource_mgr.borrow ().load_config::<WindowConfig> ("window");

        if let Ok (config) = config_result {
            self._window_config = config;
        }

        else {

            match resource_mgr.borrow ().new_config::<WindowConfig> ("window") {
                Ok (_) | Err (_) => {}
            }
        }
    }

/*===============================================================================================*/
/*------WINDOW MANAGER PUBLIC STATIC METHODS-----------------------------------------------------*/
/*===============================================================================================*/

    /// Returns a new instance of the Window Manager.
    pub fn new () -> WindowManager {
        WindowManager {_window_config: WindowConfig::default ()}
    }
}

/*-----------------------------------------------------------------------------------------------*/

impl Default for WindowManager {

    fn default () -> WindowManager {
        WindowManager::new ()
    }
}
<|endoftext|>


<commit_before>use wire::handler::{PeerId, PeerAction, ServerHandler};
use metainfo::MetaInfo;
use metainfo::SHA1Hash20b;
use file::PartialFile;
use std::collections::HashMap;
use wire::data::PeerMsg;
use std::time::SystemTime;

pub struct PeerState {
    has_handshake: bool,
    disconnected: bool,
    peer_choking: bool,
    peer_interested: bool,
    am_choking: bool,
    am_interested: bool,
    last_keepalive: SystemTime
}

impl PeerState {
    pub fn new() -> PeerState {
        PeerState {
            has_handshake: false,
            disconnected: false,
            peer_choking: true,
            peer_interested: false,
            am_choking: true,
            am_interested: false,
            last_keepalive: SystemTime::now()
        }
    }
}

pub struct PeerServer {
    peers: HashMap<PeerId, PeerState>,
    hash: SHA1Hash20b,
    our_peer_id: String,
    partial_file: PartialFile
}

const PROTOCOL_ID: &'static str = "rustorrent-beta";

impl ServerHandler for PeerServer {
    fn new(metainfo: MetaInfo, hash: SHA1Hash20b, our_peer_id: &str) -> Self {
        let partial_file = PartialFile::new(&metainfo.info);

        PeerServer{
            peers: HashMap::new(),
            hash: hash,
            our_peer_id: our_peer_id.to_string(),
            partial_file: partial_file
        }
    }

    fn on_peer_connect(&mut self, id: PeerId) -> PeerAction {
        let handshake = PeerMsg::handshake(PROTOCOL_ID.to_string(), self.our_peer_id.to_string(), &self.hash);
        PeerAction::SendMessages(vec![handshake])
    }

    fn on_message_receive(&mut self, id: PeerId, msg: PeerMsg) -> PeerAction {
        let peer = match self.peers.get_mut(&id) {
            Some(peer) => peer,
            None => return PeerAction::Nothing
        };

        if peer.disconnected {
            return PeerAction::Nothing;
        }

        if !peer.has_handshake {
            match msg {
                PeerMsg::HandShake(_, ref their_hash, _) => {
                    if their_hash == &self.hash {
                        peer.has_handshake = true;
                    } else {
                        peer.disconnected = false;
                    }
                    return PeerAction::Nothing;
                },
                _ => peer.disconnected = true
            }
        }

        let mut outgoing_msgs = Vec::new();

        match msg {
            PeerMsg::HandShake(..) => {},
            PeerMsg::KeepAlive => {},
            PeerMsg::Choke => peer.peer_choking = true,
            PeerMsg::Unchoke=> peer.peer_choking = false,
            PeerMsg::Interested => peer.peer_interested = true,
            PeerMsg::NotInterested => peer.peer_interested = false,
            PeerMsg::Have(_) => {},
            PeerMsg::Bitfield(_) => {},
            PeerMsg::Request(index, begin, offset) => {
               if self.partial_file.has_piece(index as usize) {
                   let piece = self.partial_file.get_piece_mut(index as usize);
                   match piece.get_offset(begin as usize, offset as usize) {
                       Some(piece_data) => {
                            let msg = PeerMsg::Piece(begin, offset, Vec::from(piece_data));
                            outgoing_msgs.push(msg);
                       },
                       _ => ()
                   }
               }
            },
            PeerMsg::Piece(..) => {},
            PeerMsg::Cancel(..) => {},
            PeerMsg::Port(_) => {}
        }

        if outgoing_msgs.len() > 0 {
            PeerAction::SendMessages(outgoing_msgs)
        } else {
            PeerAction::Nothing
        }
    }

    fn on_peer_disconnect(&mut self, id: PeerId) -> PeerAction {
        unimplemented!();
    }

    fn on_loop(&mut self) -> PeerAction {
        unimplemented!();
    }
}
<commit_msg>Implement handling of Request message<commit_after>use wire::handler::{PeerId, PeerAction, ServerHandler};
use metainfo::MetaInfo;
use metainfo::SHA1Hash20b;
use file::PartialFile;
use std::collections::HashMap;
use wire::data::PeerMsg;
use std::time::SystemTime;

pub struct PeerState {
    has_handshake: bool,
    disconnected: bool,
    peer_choking: bool,
    peer_interested: bool,
    am_choking: bool,
    am_interested: bool,
    last_keepalive: SystemTime
}

impl PeerState {
    pub fn new() -> PeerState {
        PeerState {
            has_handshake: false,
            disconnected: false,
            peer_choking: true,
            peer_interested: false,
            am_choking: true,
            am_interested: false,
            last_keepalive: SystemTime::now()
        }
    }
}

pub struct PeerServer {
    peers: HashMap<PeerId, PeerState>,
    hash: SHA1Hash20b,
    our_peer_id: String,
    partial_file: PartialFile
}

const PROTOCOL_ID: &'static str = "rustorrent-beta";

impl ServerHandler for PeerServer {
    fn new(metainfo: MetaInfo, hash: SHA1Hash20b, our_peer_id: &str) -> Self {
        let partial_file = PartialFile::new(&metainfo.info);

        PeerServer{
            peers: HashMap::new(),
            hash: hash,
            our_peer_id: our_peer_id.to_string(),
            partial_file: partial_file
        }
    }

    fn on_peer_connect(&mut self, id: PeerId) -> PeerAction {
        let handshake = PeerMsg::handshake(PROTOCOL_ID.to_string(), self.our_peer_id.to_string(), &self.hash);
        PeerAction::SendMessages(vec![handshake])
    }

    fn on_message_receive(&mut self, id: PeerId, msg: PeerMsg) -> PeerAction {
        {
            let peer = match self.peers.get_mut(&id) {
                Some(peer) => peer,
                None => return PeerAction::Nothing
            };

            if peer.disconnected {
                return PeerAction::Nothing;
            }

            if !peer.has_handshake {
                match msg {
                    PeerMsg::HandShake(_, ref their_hash, _) => {
                        if their_hash == &self.hash {
                            peer.has_handshake = true;
                        } else {
                            peer.disconnected = false;
                        }
                        return PeerAction::Nothing;
                    },
                    _ => peer.disconnected = true
                }
            }
        }

        let mut outgoing_msgs = Vec::new();

        match msg {
            PeerMsg::HandShake(..) => {},
            PeerMsg::KeepAlive => {},
            PeerMsg::Choke => {
                self.peers.get_mut(&id).map(|p| p.peer_choking = true);
            },
            PeerMsg::Unchoke=> {
                self.peers.get_mut(&id).map(|p| p.peer_choking = false);
            },
            PeerMsg::Interested => {
                self.peers.get_mut(&id).map(|p| p.peer_interested = true);
            },
            PeerMsg::NotInterested => {
                self.peers.get_mut(&id).map(|p| p.peer_interested = false);
            },
            PeerMsg::Have(_) => {},
            PeerMsg::Bitfield(_) => {},
            PeerMsg::Request(index, begin, offset) => {
              let response = self._get_piece_from_req(index as usize, begin, offset);
              if response.is_some() {
                  outgoing_msgs.push(response.unwrap());
              }
            },
            PeerMsg::Piece(..) => {},
            PeerMsg::Cancel(..) => {},
            PeerMsg::Port(_) => {}
        }

        if outgoing_msgs.len() > 0 {
            PeerAction::SendMessages(outgoing_msgs)
        } else {
            PeerAction::Nothing
        }
    }

    fn on_peer_disconnect(&mut self, id: PeerId) -> PeerAction {
        unimplemented!();
    }

    fn on_loop(&mut self) -> PeerAction {
        unimplemented!();
    }
}

impl PeerServer {
    fn _get_piece_from_req(&mut self, index: usize, begin: u32, offset: u32) -> Option<PeerMsg> {
        if self.partial_file.has_piece(index as usize) {
                   let piece = self.partial_file.get_piece_mut(index as usize);
                   return match piece.get_offset(begin as usize, offset as usize) {
                       Some(piece_data) => {
                            let msg = PeerMsg::Piece(begin, offset, Vec::from(piece_data));
                            Some(msg)
                       },
                       _ => None
                   };
               }
        None
    }
}

<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// compile-flags:-g

#![feature(asm)]

use std::old_io::stderr;
use std::env;

#[path = "backtrace-debuginfo-aux.rs"] mod aux;

macro_rules! pos {
    () => ((file!(), line!()))
}

// we can't use a function as it will alter the backtrace
macro_rules! check {
    ($counter:expr; $($pos:expr),*) => ({
        if *$counter == 0 {
            // XXX we cannot include the current position because
            // the macro span takes over the last frame's file/line.
            dump_filelines(&[$($pos),*]);
            panic!();
        } else {
            *$counter -= 1;
        }
    })
}

type Pos = (&'static str, u32);

// this goes to stdout and each line has to be occurred
// in the following backtrace to stderr with a correct order.
fn dump_filelines(filelines: &[Pos]) {
    for &(file, line) in filelines.iter().rev() {
        // extract a basename
        let basename = file.split(&['/', '\\'][..]).last().unwrap();
        println!("{}:{}", basename, line);
    }
}

#[inline(never)]
fn inner(counter: &mut u32, main_pos: Pos, outer_pos: Pos) {
    check!(counter; main_pos, outer_pos);
    check!(counter; main_pos, outer_pos);
    let inner_pos = pos!(); aux::callback(|aux_pos| {
        check!(counter; main_pos, outer_pos, inner_pos, aux_pos);
    });
    let inner_pos = pos!(); aux::callback_inlined(|aux_pos| {
        check!(counter; main_pos, outer_pos, inner_pos, aux_pos);
    });
}

#[inline(always)]
fn inner_inlined(counter: &mut u32, main_pos: Pos, outer_pos: Pos) {
    check!(counter; main_pos, outer_pos);
    check!(counter; main_pos, outer_pos);

    #[inline(always)]
    fn inner_further_inlined(counter: &mut u32, main_pos: Pos, outer_pos: Pos, inner_pos: Pos) {
        check!(counter; main_pos, outer_pos, inner_pos);
    }
    inner_further_inlined(counter, main_pos, outer_pos, pos!());

    let inner_pos = pos!(); aux::callback(|aux_pos| {
        check!(counter; main_pos, outer_pos, inner_pos, aux_pos);
    });
    let inner_pos = pos!(); aux::callback_inlined(|aux_pos| {
        check!(counter; main_pos, outer_pos, inner_pos, aux_pos);
    });

    // this tests a distinction between two independent calls to the inlined function.
    // (un)fortunately, LLVM somehow merges two consecutive such calls into one node.
    inner_further_inlined(counter, main_pos, outer_pos, pos!());
}

#[inline(never)]
fn outer(mut counter: u32, main_pos: Pos) {
    inner(&mut counter, main_pos, pos!());
    inner_inlined(&mut counter, main_pos, pos!());
}

fn check_trace(output: &str, error: &str) {
    // reverse the position list so we can start with the last item (which was the first line)
    let mut remaining: Vec<&str> = output.lines().map(|s| s.trim()).rev().collect();

    assert!(error.contains("stack backtrace"), "no backtrace in the error: {}", error);
    for line in error.lines() {
        if !remaining.is_empty() && line.contains(remaining.last().unwrap()) {
            remaining.pop();
        }
    }
    assert!(remaining.is_empty(),
            "trace does not match position list: {}\n---\n{}", error, output);
}

fn run_test(me: &str) {
    use std::str;
    use std::old_io::process::Command;

    let mut template = Command::new(me);
    template.env("RUST_BACKTRACE", "1");

    let mut i = 0;
    loop {
        let p = template.clone().arg(i.to_string()).spawn().unwrap();
        let out = p.wait_with_output().unwrap();
        let output = str::from_utf8(&out.output).unwrap();
        let error = str::from_utf8(&out.error).unwrap();
        if out.status.success() {
            assert!(output.contains("done."), "bad output for successful run: {}", output);
            break;
        } else {
            check_trace(output, error);
        }
        i += 1;
    }
}

#[inline(never)]
fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() >= 2 {
        let case = args[1].parse().unwrap();
        writeln!(&mut stderr(), "test case {}", case).unwrap();
        outer(case, pos!());
        println!("done.");
    } else {
        run_test(&args[0]);
    }
}

<commit_msg>Removed an excess feature flag from the backtrace test.<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// compile-flags:-g

use std::old_io::stderr;
use std::env;

#[path = "backtrace-debuginfo-aux.rs"] mod aux;

macro_rules! pos {
    () => ((file!(), line!()))
}

// we can't use a function as it will alter the backtrace
macro_rules! check {
    ($counter:expr; $($pos:expr),*) => ({
        if *$counter == 0 {
            // XXX we cannot include the current position because
            // the macro span takes over the last frame's file/line.
            dump_filelines(&[$($pos),*]);
            panic!();
        } else {
            *$counter -= 1;
        }
    })
}

type Pos = (&'static str, u32);

// this goes to stdout and each line has to be occurred
// in the following backtrace to stderr with a correct order.
fn dump_filelines(filelines: &[Pos]) {
    for &(file, line) in filelines.iter().rev() {
        // extract a basename
        let basename = file.split(&['/', '\\'][..]).last().unwrap();
        println!("{}:{}", basename, line);
    }
}

#[inline(never)]
fn inner(counter: &mut u32, main_pos: Pos, outer_pos: Pos) {
    check!(counter; main_pos, outer_pos);
    check!(counter; main_pos, outer_pos);
    let inner_pos = pos!(); aux::callback(|aux_pos| {
        check!(counter; main_pos, outer_pos, inner_pos, aux_pos);
    });
    let inner_pos = pos!(); aux::callback_inlined(|aux_pos| {
        check!(counter; main_pos, outer_pos, inner_pos, aux_pos);
    });
}

#[inline(always)]
fn inner_inlined(counter: &mut u32, main_pos: Pos, outer_pos: Pos) {
    check!(counter; main_pos, outer_pos);
    check!(counter; main_pos, outer_pos);

    #[inline(always)]
    fn inner_further_inlined(counter: &mut u32, main_pos: Pos, outer_pos: Pos, inner_pos: Pos) {
        check!(counter; main_pos, outer_pos, inner_pos);
    }
    inner_further_inlined(counter, main_pos, outer_pos, pos!());

    let inner_pos = pos!(); aux::callback(|aux_pos| {
        check!(counter; main_pos, outer_pos, inner_pos, aux_pos);
    });
    let inner_pos = pos!(); aux::callback_inlined(|aux_pos| {
        check!(counter; main_pos, outer_pos, inner_pos, aux_pos);
    });

    // this tests a distinction between two independent calls to the inlined function.
    // (un)fortunately, LLVM somehow merges two consecutive such calls into one node.
    inner_further_inlined(counter, main_pos, outer_pos, pos!());
}

#[inline(never)]
fn outer(mut counter: u32, main_pos: Pos) {
    inner(&mut counter, main_pos, pos!());
    inner_inlined(&mut counter, main_pos, pos!());
}

fn check_trace(output: &str, error: &str) {
    // reverse the position list so we can start with the last item (which was the first line)
    let mut remaining: Vec<&str> = output.lines().map(|s| s.trim()).rev().collect();

    assert!(error.contains("stack backtrace"), "no backtrace in the error: {}", error);
    for line in error.lines() {
        if !remaining.is_empty() && line.contains(remaining.last().unwrap()) {
            remaining.pop();
        }
    }
    assert!(remaining.is_empty(),
            "trace does not match position list: {}\n---\n{}", error, output);
}

fn run_test(me: &str) {
    use std::str;
    use std::old_io::process::Command;

    let mut template = Command::new(me);
    template.env("RUST_BACKTRACE", "1");

    let mut i = 0;
    loop {
        let p = template.clone().arg(i.to_string()).spawn().unwrap();
        let out = p.wait_with_output().unwrap();
        let output = str::from_utf8(&out.output).unwrap();
        let error = str::from_utf8(&out.error).unwrap();
        if out.status.success() {
            assert!(output.contains("done."), "bad output for successful run: {}", output);
            break;
        } else {
            check_trace(output, error);
        }
        i += 1;
    }
}

#[inline(never)]
fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() >= 2 {
        let case = args[1].parse().unwrap();
        writeln!(&mut stderr(), "test case {}", case).unwrap();
        outer(case, pos!());
        println!("done.");
    } else {
        run_test(&args[0]);
    }
}

<|endoftext|>


<commit_before>// xfail-fast

// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// An example to make sure the protocol parsing syntax extension works.

use core::option;

proto! pingpong (
    ping:send {
        ping -> pong
    }

    pong:recv {
        pong -> ping
    }
)

mod test {
    use core::pipes::recv;
    use pingpong::{ping, pong};

    pub fn client(-chan: pingpong::client::ping) {
        use pingpong::client;

        let chan = client::ping(move chan);
        log(error, ~"Sent ping");
        let pong(_chan) = recv(move chan);
        log(error, ~"Received pong");
    }

    pub fn server(-chan: pingpong::server::ping) {
        use pingpong::server;

        let ping(chan) = recv(move chan);
        log(error, ~"Received ping");
        let _chan = server::pong(move chan);
        log(error, ~"Sent pong");
    }
}

fn main() {
    let (client_, server_) = pingpong::init();
    let client_ = ~mut Some(move client_);
    let server_ = ~mut Some(move server_);

    do task::spawn |move client_| {
        let mut client__ = None;
        *client_ <-> client__;
        test::client(option::unwrap(move client__));
    };
    do task::spawn |move server_| {
        let mut server_ˊ = None;
        *server_ <-> server_ˊ;
        test::server(option::unwrap(move server_ˊ));
    };
}
<commit_msg>test: Fix test/run-pass/pipe-pingpong-proto. rs=bustage<commit_after>// xfail-fast

// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// An example to make sure the protocol parsing syntax extension works.

use core::option;

proto! pingpong (
    ping:send {
        ping -> pong
    }

    pong:recv {
        pong -> ping
    }
)

mod test {
    use core::pipes::recv;
    use pingpong::{ping, pong};

    pub fn client(-chan: ::pingpong::client::ping) {
        use pingpong::client;

        let chan = client::ping(move chan);
        log(error, ~"Sent ping");
        let pong(_chan) = recv(move chan);
        log(error, ~"Received pong");
    }

    pub fn server(-chan: ::pingpong::server::ping) {
        use pingpong::server;

        let ping(chan) = recv(move chan);
        log(error, ~"Received ping");
        let _chan = server::pong(move chan);
        log(error, ~"Sent pong");
    }
}

fn main() {
    let (client_, server_) = pingpong::init();
    let client_ = ~mut Some(move client_);
    let server_ = ~mut Some(move server_);

    do task::spawn |move client_| {
        let mut client__ = None;
        *client_ <-> client__;
        test::client(option::unwrap(move client__));
    };
    do task::spawn |move server_| {
        let mut server_ˊ = None;
        *server_ <-> server_ˊ;
        test::server(option::unwrap(move server_ˊ));
    };
}
<|endoftext|>


<commit_before>//! These are the unrolled butterflies for specific FFT lengths. They are mostly
//! translations of the butterfly functions from KissFFT, copyright Mark Borgerding.

use num::{Complex, Zero};

pub fn butterfly_2(data: &mut [Complex<f32>], stride: usize,
                   twiddles: &[Complex<f32>], num_ffts: usize) {
    let mut idx_1 = 0usize;
    let mut idx_2 = num_ffts;
    let mut twiddle_idx = 0usize;
    // TODO speed: use pointers instead of pointer offsets?
    for _ in 0..num_ffts {
        unsafe {
            let twiddle = twiddles.get_unchecked(twiddle_idx);
            let temp = data.get_unchecked(idx_2) * twiddle;
            *data.get_unchecked_mut(idx_2) = data.get_unchecked(idx_1) - temp;
            *data.get_unchecked_mut(idx_1) = data.get_unchecked(idx_1) + temp;
        }
        twiddle_idx += stride;
        idx_1 += 1;
        idx_2 += 1;
    }
}

pub fn butterfly_3(data: &mut [Complex<f32>], stride: usize,
                   twiddles: &[Complex<f32>], num_ffts: usize) {
    let mut idx = 0usize;
    let mut tw_idx_1 = 0usize;
    let mut tw_idx_2 = 0usize;
    let mut scratch: [Complex<f32>; 5] = [Zero::zero(); 5];
    for _ in 0..num_ffts {
        unsafe {
            scratch[1] = data.get_unchecked(idx + 1 * num_ffts) * twiddles[tw_idx_1];
            scratch[2] = data.get_unchecked(idx + 2 * num_ffts) * twiddles[tw_idx_2];
            scratch[3] = scratch[1] + scratch[2];
            scratch[0] = scratch[1] - scratch[2];

            data.get_unchecked_mut(idx + num_ffts).re = data.get_unchecked(idx).re
                                                        - scratch[3].re / 2.0;
            data.get_unchecked_mut(idx + num_ffts).im = data.get_unchecked(idx).im
                                                        - scratch[3].im / 2.0;

            scratch[0].re = scratch[0].re * twiddles[stride * num_ffts].im;
            scratch[0].im = scratch[0].im * twiddles[stride * num_ffts].im;

            *data.get_unchecked_mut(idx) = data.get_unchecked(idx) + scratch[3];
            data.get_unchecked_mut(idx + 2 * num_ffts).re = data.get_unchecked(idx + num_ffts).re
                                                            + scratch[0].im;
            data.get_unchecked_mut(idx + 2 * num_ffts).im = data.get_unchecked(idx + num_ffts).im
                                                            - scratch[0].re;
            data.get_unchecked_mut(idx + num_ffts).re = data.get_unchecked(idx + num_ffts).re
                                                        - scratch[0].im;
            data.get_unchecked_mut(idx + num_ffts).im = data.get_unchecked(idx + num_ffts).im
                                                        + scratch[0].re;

            tw_idx_1 += 1 * stride;
            tw_idx_2 += 2 * stride;
            idx += 1;
        }
    }
}

pub fn butterfly_4(data: &mut [Complex<f32>], stride: usize,
                   twiddles: &[Complex<f32>], num_ffts: usize) {
    let mut idx = 0usize;
    let mut tw_idx_1 = 0usize;
    let mut tw_idx_2 = 0usize;
    let mut tw_idx_3 = 0usize;
    let mut scratch: [Complex<f32>; 6] = [Zero::zero(); 6];
    //TODO does using get_unchecked on scratch help with speed?
    for _ in 0..num_ffts {
        unsafe {
            scratch[0] = data.get_unchecked(idx + 1 * num_ffts) * twiddles[tw_idx_1];
            scratch[1] = data.get_unchecked(idx + 2 * num_ffts) * twiddles[tw_idx_2];
            scratch[2] = data.get_unchecked(idx + 3 * num_ffts) * twiddles[tw_idx_3];
            scratch[5] = data.get_unchecked(idx) - scratch[1];
            *data.get_unchecked_mut(idx) = data.get_unchecked(idx) + scratch[1];
            scratch[3] = scratch[0] + scratch[2];
            scratch[4] = scratch[0] - scratch[2];
            *data.get_unchecked_mut(idx + 2 * num_ffts) = data.get_unchecked(idx) - scratch[3];
            *data.get_unchecked_mut(idx) = data.get_unchecked(idx) + scratch[3];
            data.get_unchecked_mut(idx + num_ffts).re = scratch[5].re + scratch[4].im;
            data.get_unchecked_mut(idx + num_ffts).im = scratch[5].im - scratch[4].re;
            data.get_unchecked_mut(idx + 3 * num_ffts).re = scratch[5].re - scratch[4].im;
            data.get_unchecked_mut(idx + 3 * num_ffts).im = scratch[5].im + scratch[4].re;

            tw_idx_1 += 1 * stride;
            tw_idx_2 += 2 * stride;
            tw_idx_3 += 3 * stride;
            idx += 1;
        }
    }
}

pub fn butterfly_5(data: &mut [Complex<f32>], stride: usize,
                   twiddles: &[Complex<f32>], num_ffts: usize) {
    let mut idx_0 = 0 * num_ffts;
    let mut idx_1 = 1 * num_ffts;
    let mut idx_2 = 2 * num_ffts;
    let mut idx_3 = 3 * num_ffts;
    let mut idx_4 = 4 * num_ffts;
    let mut scratch: [Complex<f32>; 13] = [Zero::zero(); 13];
    let ya = twiddles[stride * num_ffts];
    let yb = twiddles[stride * 2 * num_ffts];
    for i in 0..num_ffts {
        unsafe {
            scratch[0] = *data.get_unchecked(idx_0);
            scratch[1] = data.get_unchecked(idx_1) * twiddles[1 * i * stride];
            scratch[2] = data.get_unchecked(idx_2) * twiddles[2 * i * stride];
            scratch[3] = data.get_unchecked(idx_3) * twiddles[3 * i * stride];
            scratch[4] = data.get_unchecked(idx_4) * twiddles[4 * i * stride];

            scratch[7] = scratch[1] + scratch[4];
            scratch[10] = scratch[1] - scratch[4];
            scratch[8] = scratch[2] + scratch[3];
            scratch[9] = scratch[2] - scratch[3];

            data.get_unchecked_mut(idx_0).re += scratch[7].re + scratch[8].re;
            data.get_unchecked_mut(idx_0).im += scratch[7].im + scratch[8].im;

            scratch[5].re = scratch[0].re + scratch[7].re * ya.re + scratch[8].re * yb.re;
            scratch[5].im = scratch[0].im + scratch[7].im * ya.re + scratch[8].im * yb.re;

            scratch[6].re = scratch[10].im * ya.im + scratch[9].im * yb.im;
            scratch[6].im = -1.0 * scratch[10].re * ya.im - scratch[9].re * yb.im;

            *data.get_unchecked_mut(idx_1) = scratch[5] - scratch[6];
            *data.get_unchecked_mut(idx_4) = scratch[5] + scratch[6];

            scratch[11].re = scratch[0].re + scratch[7].re * yb.re + scratch[8].re * ya.re;
            scratch[11].im = scratch[0].im + scratch[7].im * yb.re + scratch[8].im * ya.re;
            scratch[12].re = -1.0 * scratch[10].im * yb.im + scratch[9].im * ya.im;
            scratch[12].im = scratch[10].re * yb.im - scratch[9].re * ya.im;

            *data.get_unchecked_mut(idx_2) = scratch[11] + scratch[12];
            *data.get_unchecked_mut(idx_3) = scratch[11] - scratch[12];

            idx_0 += 1;
            idx_1 += 1;
            idx_2 += 1;
            idx_3 += 1;
            idx_4 += 1;
        }
    }
}

#[cfg(test)]
mod benches {
    extern crate test;

    use std::f32;
    use std::iter::repeat;
    use self::test::Bencher;
    use num::{Complex, Zero};
    use super::{butterfly_2, butterfly_3, butterfly_4, butterfly_5};

    fn set_up_bench(butterfly_len: usize, stride: usize, num_ffts: usize) -> (Vec<Complex<f32>>, Vec<Complex<f32>>) {
        let len = butterfly_len * stride * num_ffts;
        let twiddles: Vec<Complex<f32>> = (0..len)
            .map(|i| -1. * (i as f32) * f32::consts::PI_2 / (len as f32))
            .map(|phase| Complex::from_polar(&1., &phase))
            .collect();

        let data: Vec<Complex<f32>> = repeat(Zero::zero()).take(len).collect();
        (data, twiddles)
    }

    #[bench]
    fn bench_butterfly_2(b: &mut Bencher) {
        let stride = 4usize;
        let num_ffts = 1000usize;
        let (mut data, twiddles) = set_up_bench(2, stride, num_ffts);

        b.iter(|| butterfly_2(&mut data, stride, &twiddles, num_ffts));
    }

    #[bench]
    fn bench_butterfly_3(b: &mut Bencher) {
        let stride = 4usize;
        let num_ffts = 1000usize;
        let (mut data, twiddles) = set_up_bench(3, stride, num_ffts);

        b.iter(|| butterfly_3(&mut data, stride, &twiddles, num_ffts));
    }

    #[bench]
    fn bench_butterfly_4(b: &mut Bencher) {
        let stride = 4usize;
        let num_ffts = 1000usize;
        let (mut data, twiddles) = set_up_bench(4, stride, num_ffts);

        b.iter(|| butterfly_4(&mut data, stride, &twiddles, num_ffts));
    }

    #[bench]
    fn bench_butterfly_5(b: &mut Bencher) {
        let stride = 4usize;
        let num_ffts = 1000usize;
        let (mut data, twiddles) = set_up_bench(5, stride, num_ffts);

        b.iter(|| butterfly_5(&mut data, stride, &twiddles, num_ffts));
    }
}
<commit_msg>Don't build the benchmarks when testing.<commit_after>//! These are the unrolled butterflies for specific FFT lengths. They are mostly
//! translations of the butterfly functions from KissFFT, copyright Mark Borgerding.

use num::{Complex, Zero};

pub fn butterfly_2(data: &mut [Complex<f32>], stride: usize,
                   twiddles: &[Complex<f32>], num_ffts: usize) {
    let mut idx_1 = 0usize;
    let mut idx_2 = num_ffts;
    let mut twiddle_idx = 0usize;
    // TODO speed: use pointers instead of pointer offsets?
    for _ in 0..num_ffts {
        unsafe {
            let twiddle = twiddles.get_unchecked(twiddle_idx);
            let temp = data.get_unchecked(idx_2) * twiddle;
            *data.get_unchecked_mut(idx_2) = data.get_unchecked(idx_1) - temp;
            *data.get_unchecked_mut(idx_1) = data.get_unchecked(idx_1) + temp;
        }
        twiddle_idx += stride;
        idx_1 += 1;
        idx_2 += 1;
    }
}

pub fn butterfly_3(data: &mut [Complex<f32>], stride: usize,
                   twiddles: &[Complex<f32>], num_ffts: usize) {
    let mut idx = 0usize;
    let mut tw_idx_1 = 0usize;
    let mut tw_idx_2 = 0usize;
    let mut scratch: [Complex<f32>; 5] = [Zero::zero(); 5];
    for _ in 0..num_ffts {
        unsafe {
            scratch[1] = data.get_unchecked(idx + 1 * num_ffts) * twiddles[tw_idx_1];
            scratch[2] = data.get_unchecked(idx + 2 * num_ffts) * twiddles[tw_idx_2];
            scratch[3] = scratch[1] + scratch[2];
            scratch[0] = scratch[1] - scratch[2];

            data.get_unchecked_mut(idx + num_ffts).re = data.get_unchecked(idx).re
                                                        - scratch[3].re / 2.0;
            data.get_unchecked_mut(idx + num_ffts).im = data.get_unchecked(idx).im
                                                        - scratch[3].im / 2.0;

            scratch[0].re = scratch[0].re * twiddles[stride * num_ffts].im;
            scratch[0].im = scratch[0].im * twiddles[stride * num_ffts].im;

            *data.get_unchecked_mut(idx) = data.get_unchecked(idx) + scratch[3];
            data.get_unchecked_mut(idx + 2 * num_ffts).re = data.get_unchecked(idx + num_ffts).re
                                                            + scratch[0].im;
            data.get_unchecked_mut(idx + 2 * num_ffts).im = data.get_unchecked(idx + num_ffts).im
                                                            - scratch[0].re;
            data.get_unchecked_mut(idx + num_ffts).re = data.get_unchecked(idx + num_ffts).re
                                                        - scratch[0].im;
            data.get_unchecked_mut(idx + num_ffts).im = data.get_unchecked(idx + num_ffts).im
                                                        + scratch[0].re;

            tw_idx_1 += 1 * stride;
            tw_idx_2 += 2 * stride;
            idx += 1;
        }
    }
}

pub fn butterfly_4(data: &mut [Complex<f32>], stride: usize,
                   twiddles: &[Complex<f32>], num_ffts: usize) {
    let mut idx = 0usize;
    let mut tw_idx_1 = 0usize;
    let mut tw_idx_2 = 0usize;
    let mut tw_idx_3 = 0usize;
    let mut scratch: [Complex<f32>; 6] = [Zero::zero(); 6];
    //TODO does using get_unchecked on scratch help with speed?
    for _ in 0..num_ffts {
        unsafe {
            scratch[0] = data.get_unchecked(idx + 1 * num_ffts) * twiddles[tw_idx_1];
            scratch[1] = data.get_unchecked(idx + 2 * num_ffts) * twiddles[tw_idx_2];
            scratch[2] = data.get_unchecked(idx + 3 * num_ffts) * twiddles[tw_idx_3];
            scratch[5] = data.get_unchecked(idx) - scratch[1];
            *data.get_unchecked_mut(idx) = data.get_unchecked(idx) + scratch[1];
            scratch[3] = scratch[0] + scratch[2];
            scratch[4] = scratch[0] - scratch[2];
            *data.get_unchecked_mut(idx + 2 * num_ffts) = data.get_unchecked(idx) - scratch[3];
            *data.get_unchecked_mut(idx) = data.get_unchecked(idx) + scratch[3];
            data.get_unchecked_mut(idx + num_ffts).re = scratch[5].re + scratch[4].im;
            data.get_unchecked_mut(idx + num_ffts).im = scratch[5].im - scratch[4].re;
            data.get_unchecked_mut(idx + 3 * num_ffts).re = scratch[5].re - scratch[4].im;
            data.get_unchecked_mut(idx + 3 * num_ffts).im = scratch[5].im + scratch[4].re;

            tw_idx_1 += 1 * stride;
            tw_idx_2 += 2 * stride;
            tw_idx_3 += 3 * stride;
            idx += 1;
        }
    }
}

pub fn butterfly_5(data: &mut [Complex<f32>], stride: usize,
                   twiddles: &[Complex<f32>], num_ffts: usize) {
    let mut idx_0 = 0 * num_ffts;
    let mut idx_1 = 1 * num_ffts;
    let mut idx_2 = 2 * num_ffts;
    let mut idx_3 = 3 * num_ffts;
    let mut idx_4 = 4 * num_ffts;
    let mut scratch: [Complex<f32>; 13] = [Zero::zero(); 13];
    let ya = twiddles[stride * num_ffts];
    let yb = twiddles[stride * 2 * num_ffts];
    for i in 0..num_ffts {
        unsafe {
            scratch[0] = *data.get_unchecked(idx_0);
            scratch[1] = data.get_unchecked(idx_1) * twiddles[1 * i * stride];
            scratch[2] = data.get_unchecked(idx_2) * twiddles[2 * i * stride];
            scratch[3] = data.get_unchecked(idx_3) * twiddles[3 * i * stride];
            scratch[4] = data.get_unchecked(idx_4) * twiddles[4 * i * stride];

            scratch[7] = scratch[1] + scratch[4];
            scratch[10] = scratch[1] - scratch[4];
            scratch[8] = scratch[2] + scratch[3];
            scratch[9] = scratch[2] - scratch[3];

            data.get_unchecked_mut(idx_0).re += scratch[7].re + scratch[8].re;
            data.get_unchecked_mut(idx_0).im += scratch[7].im + scratch[8].im;

            scratch[5].re = scratch[0].re + scratch[7].re * ya.re + scratch[8].re * yb.re;
            scratch[5].im = scratch[0].im + scratch[7].im * ya.re + scratch[8].im * yb.re;

            scratch[6].re = scratch[10].im * ya.im + scratch[9].im * yb.im;
            scratch[6].im = -1.0 * scratch[10].re * ya.im - scratch[9].re * yb.im;

            *data.get_unchecked_mut(idx_1) = scratch[5] - scratch[6];
            *data.get_unchecked_mut(idx_4) = scratch[5] + scratch[6];

            scratch[11].re = scratch[0].re + scratch[7].re * yb.re + scratch[8].re * ya.re;
            scratch[11].im = scratch[0].im + scratch[7].im * yb.re + scratch[8].im * ya.re;
            scratch[12].re = -1.0 * scratch[10].im * yb.im + scratch[9].im * ya.im;
            scratch[12].im = scratch[10].re * yb.im - scratch[9].re * ya.im;

            *data.get_unchecked_mut(idx_2) = scratch[11] + scratch[12];
            *data.get_unchecked_mut(idx_3) = scratch[11] - scratch[12];

            idx_0 += 1;
            idx_1 += 1;
            idx_2 += 1;
            idx_3 += 1;
            idx_4 += 1;
        }
    }
}

#[cfg(bench)]
mod benches {
    extern crate test;

    use std::f32;
    use std::iter::repeat;
    use self::test::Bencher;
    use num::{Complex, Zero};
    use super::{butterfly_2, butterfly_3, butterfly_4, butterfly_5};

    fn set_up_bench(butterfly_len: usize, stride: usize, num_ffts: usize) -> (Vec<Complex<f32>>, Vec<Complex<f32>>) {
        let len = butterfly_len * stride * num_ffts;
        let twiddles: Vec<Complex<f32>> = (0..len)
            .map(|i| -1. * (i as f32) * f32::consts::PI_2 / (len as f32))
            .map(|phase| Complex::from_polar(&1., &phase))
            .collect();

        let data: Vec<Complex<f32>> = repeat(Zero::zero()).take(len).collect();
        (data, twiddles)
    }

    #[bench]
    fn bench_butterfly_2(b: &mut Bencher) {
        let stride = 4usize;
        let num_ffts = 1000usize;
        let (mut data, twiddles) = set_up_bench(2, stride, num_ffts);

        b.iter(|| butterfly_2(&mut data, stride, &twiddles, num_ffts));
    }

    #[bench]
    fn bench_butterfly_3(b: &mut Bencher) {
        let stride = 4usize;
        let num_ffts = 1000usize;
        let (mut data, twiddles) = set_up_bench(3, stride, num_ffts);

        b.iter(|| butterfly_3(&mut data, stride, &twiddles, num_ffts));
    }

    #[bench]
    fn bench_butterfly_4(b: &mut Bencher) {
        let stride = 4usize;
        let num_ffts = 1000usize;
        let (mut data, twiddles) = set_up_bench(4, stride, num_ffts);

        b.iter(|| butterfly_4(&mut data, stride, &twiddles, num_ffts));
    }

    #[bench]
    fn bench_butterfly_5(b: &mut Bencher) {
        let stride = 4usize;
        let num_ffts = 1000usize;
        let (mut data, twiddles) = set_up_bench(5, stride, num_ffts);

        b.iter(|| butterfly_5(&mut data, stride, &twiddles, num_ffts));
    }
}
<|endoftext|>


<commit_before>extern crate wobj = "wavefront-obj";

use piston::AssetStore;
use std::io;

use vertex::Vertex;

#[deriving(PartialEq, Eq, FromPrimitive, Show)]
pub enum Type {
    Slab = 0,
}

static TYPE_LEN: uint = 1;

impl Type {
    pub fn get_obj_file(&self) -> Option<&'static str> {
        match *self {
            Slab => Some("slab.obj"),
        }
    }

    pub fn to_uint(&self) -> uint {
        *self as uint
    }
}

pub struct TypeIterator {
    ty: uint,
}

impl TypeIterator {
    pub fn new() -> TypeIterator {
        TypeIterator {
            ty: 0
        }
    }
}

impl Iterator<Type> for TypeIterator {
    fn next(&mut self) -> Option<Type> {
        match self.ty {
            x if x < TYPE_LEN => {
                self.ty += 1;
                FromPrimitive::from_uint(x)
            },
            _ => None
        }
    }
}

pub struct Data {
    pub obj_data: Vec<Option<wobj::obj::ObjSet>>,
    pub vertices: Vec<Vertex>,
    pub indices: Vec<u32>,
    pub index_ranges: Vec<IndexRange>,
    pub objs: Vec<ObjectRange>,
    pub obj_sets: Vec<ObjSetRange>
}

impl Data {
    pub fn from_asset_store(asset_store: &AssetStore) -> Data {
        let obj_data = read_obj_data(asset_store);
        let mut vertices = Vec::new();
        let mut indices = Vec::new();
        let mut index_ranges = Vec::new();
        let mut objs = Vec::new();
        let mut obj_sets = Vec::new();
        for obj_set in obj_data.iter() {
            match *obj_set {
                Some(ref obj_set) => {
                    obj_sets.push(
                        ObjSetRange::add_obj_set(
                            obj_set,
                            &mut vertices,
                            &mut indices,
                            &mut index_ranges,
                            &mut objs
                        )
                    );
                },
                None => {}
            }
        }
        Data {
            obj_data: obj_data,
            vertices: vertices,
            indices: indices,
            index_ranges: index_ranges,
            objs: objs,
            obj_sets: obj_sets
        }
    }
}

pub fn read_obj_data(asset_store: &AssetStore) -> Vec<Option<wobj::obj::ObjSet>> {
    let mut vec = Vec::new();
    for it in TypeIterator::new() {
        match it.get_obj_file() {
            None => vec.push(None),
            Some(file) => vec.push(Some({
                    let txt = io::File::open(&asset_store.path(file).unwrap()).read_to_string().unwrap();
                    wobj::obj::parse(txt).unwrap()
                }))
        }
    }
    vec
}

/// Stores [start, end) ranges to vertices.
pub struct VertexRange(uint, uint);

impl VertexRange {
    /// Extracts the coordinates of the corners and stores it in a list.
    ///
    /// Returns the range where the object is stored in the list.
    pub fn add_vertices(
        obj: &wobj::obj::Object,
        vertices: &mut Vec<Vertex>
    ) -> VertexRange {
        let start = vertices.len();
        for v in obj.vertices.iter() {
            vertices.push(Vertex::new([v.x as f32, v.y as f32, v.z as f32]));
        }
        VertexRange(start, vertices.len())
    }
}

/// Stores [start, end) ranges to indices.
pub struct IndexRange(uint, uint);

impl IndexRange {
    /// Extracts the indices from the triangles and stores it in a list.
    ///
    /// Returns the range where the geometry is stored in the list.
    pub fn add_indices(
        geom: &wobj::obj::Geometry,
        VertexRange(offset, _): VertexRange,
        indices: &mut Vec<u32>
    ) -> IndexRange {
        let start = indices.len();
        for shape in geom.shapes.iter() {
            match *shape {
                // Extract triangles and offset them relative to the
                // position in the vertex mesh.
                wobj::obj::Triangle((a, _), (b, _), (c, _)) => {
                    indices.push((a + offset) as u32);
                    indices.push((b + offset) as u32);
                    indices.push((c + offset) as u32);
                },
                _ => {}
            }
        }
        IndexRange(start, indices.len())
    }
}

/// Stores [start, end) ranges for objects.
///
/// This points to a range of index ranges.
pub struct ObjectRange(uint, uint);

impl ObjectRange {
    pub fn add_object(
        obj: &wobj::obj::Object,
        vertices: &mut Vec<Vertex>,
        indices: &mut Vec<u32>,
        index_ranges: &mut Vec<IndexRange>
    ) -> ObjectRange {
        let vertex_range = VertexRange::add_vertices(obj, vertices);
        let start = index_ranges.len();
        for geom in obj.geometry.iter() {
            index_ranges.push(IndexRange::add_indices(geom, vertex_range, indices))
        }
        ObjectRange(start, index_ranges.len())
    }
}

/// Stores [start, end) for object sets (one OBJ file).
///
/// This points to a range of object ranges.
pub struct ObjSetRange(uint, uint);

impl ObjSetRange {
    pub fn add_obj_set(
        obj_set: &wobj::obj::ObjSet,
        vertices: &mut Vec<Vertex>,
        indices: &mut Vec<u32>,
        index_ranges: &mut Vec<IndexRange>,
        objs: &mut Vec<ObjectRange>
    ) -> ObjSetRange {
        let start = objs.len();
        for obj in obj_set.objects.iter() {
            objs.push(
                ObjectRange::add_object(
                    obj,
                    vertices,
                    indices,
                    index_ranges
                )
            );
        }
        ObjSetRange(start, objs.len())
    }
}

<commit_msg>Added method for iterating through index ranges<commit_after>extern crate wobj = "wavefront-obj";

use piston::AssetStore;
use std::io;

use vertex::Vertex;

#[deriving(PartialEq, Eq, FromPrimitive, Show)]
pub enum Type {
    Slab = 0,
}

static TYPE_LEN: uint = 1;

impl Type {
    pub fn get_obj_file(&self) -> Option<&'static str> {
        match *self {
            Slab => Some("slab.obj"),
        }
    }

    pub fn to_uint(&self) -> uint {
        *self as uint
    }
}

pub struct TypeIterator {
    ty: uint,
}

impl TypeIterator {
    pub fn new() -> TypeIterator {
        TypeIterator {
            ty: 0
        }
    }
}

impl Iterator<Type> for TypeIterator {
    fn next(&mut self) -> Option<Type> {
        match self.ty {
            x if x < TYPE_LEN => {
                self.ty += 1;
                FromPrimitive::from_uint(x)
            },
            _ => None
        }
    }
}

pub struct Data {
    pub obj_data: Vec<Option<wobj::obj::ObjSet>>,
    pub vertices: Vec<Vertex>,
    pub indices: Vec<u32>,
    pub index_ranges: Vec<IndexRange>,
    pub objs: Vec<ObjectRange>,
    pub obj_sets: Vec<ObjSetRange>
}

impl Data {
    pub fn from_asset_store(asset_store: &AssetStore) -> Data {
        let obj_data = read_obj_data(asset_store);
        let mut vertices = Vec::new();
        let mut indices = Vec::new();
        let mut index_ranges = Vec::new();
        let mut objs = Vec::new();
        let mut obj_sets = Vec::new();
        for obj_set in obj_data.iter() {
            match *obj_set {
                Some(ref obj_set) => {
                    obj_sets.push(
                        ObjSetRange::add_obj_set(
                            obj_set,
                            &mut vertices,
                            &mut indices,
                            &mut index_ranges,
                            &mut objs
                        )
                    );
                },
                None => {}
            }
        }
        Data {
            obj_data: obj_data,
            vertices: vertices,
            indices: indices,
            index_ranges: index_ranges,
            objs: objs,
            obj_sets: obj_sets
        }
    }

    pub fn with_type_index_ranges(&self, ty: Type, f: |uint, uint|) {
        let ObjSetRange(start, end) = self.obj_sets[ty.to_uint()];
        for i in range(start, end) {
            let ObjectRange(start, end) = self.objs[i];
            for i in range(start, end) {
                let IndexRange(start, end) = self.index_ranges[i];
                f(start, end);
            }
        }
    }
}

pub fn read_obj_data(asset_store: &AssetStore) -> Vec<Option<wobj::obj::ObjSet>> {
    let mut vec = Vec::new();
    for it in TypeIterator::new() {
        match it.get_obj_file() {
            None => vec.push(None),
            Some(file) => vec.push(Some({
                    let txt = io::File::open(&asset_store.path(file).unwrap()).read_to_string().unwrap();
                    wobj::obj::parse(txt).unwrap()
                }))
        }
    }
    vec
}

/// Stores [start, end) ranges to vertices.
pub struct VertexRange(uint, uint);

impl VertexRange {
    /// Extracts the coordinates of the corners and stores it in a list.
    ///
    /// Returns the range where the object is stored in the list.
    pub fn add_vertices(
        obj: &wobj::obj::Object,
        vertices: &mut Vec<Vertex>
    ) -> VertexRange {
        let start = vertices.len();
        for v in obj.vertices.iter() {
            vertices.push(Vertex::new([v.x as f32, v.y as f32, v.z as f32]));
        }
        VertexRange(start, vertices.len())
    }
}

/// Stores [start, end) ranges to indices.
pub struct IndexRange(uint, uint);

impl IndexRange {
    /// Extracts the indices from the triangles and stores it in a list.
    ///
    /// Returns the range where the geometry is stored in the list.
    pub fn add_indices(
        geom: &wobj::obj::Geometry,
        VertexRange(offset, _): VertexRange,
        indices: &mut Vec<u32>
    ) -> IndexRange {
        let start = indices.len();
        for shape in geom.shapes.iter() {
            match *shape {
                // Extract triangles and offset them relative to the
                // position in the vertex mesh.
                wobj::obj::Triangle((a, _), (b, _), (c, _)) => {
                    indices.push((a + offset) as u32);
                    indices.push((b + offset) as u32);
                    indices.push((c + offset) as u32);
                },
                _ => {}
            }
        }
        IndexRange(start, indices.len())
    }
}

/// Stores [start, end) ranges for objects.
///
/// This points to a range of index ranges.
pub struct ObjectRange(uint, uint);

impl ObjectRange {
    pub fn add_object(
        obj: &wobj::obj::Object,
        vertices: &mut Vec<Vertex>,
        indices: &mut Vec<u32>,
        index_ranges: &mut Vec<IndexRange>
    ) -> ObjectRange {
        let vertex_range = VertexRange::add_vertices(obj, vertices);
        let start = index_ranges.len();
        for geom in obj.geometry.iter() {
            index_ranges.push(IndexRange::add_indices(geom, vertex_range, indices))
        }
        ObjectRange(start, index_ranges.len())
    }
}

/// Stores [start, end) for object sets (one OBJ file).
///
/// This points to a range of object ranges.
pub struct ObjSetRange(uint, uint);

impl ObjSetRange {
    pub fn add_obj_set(
        obj_set: &wobj::obj::ObjSet,
        vertices: &mut Vec<Vertex>,
        indices: &mut Vec<u32>,
        index_ranges: &mut Vec<IndexRange>,
        objs: &mut Vec<ObjectRange>
    ) -> ObjSetRange {
        let start = objs.len();
        for obj in obj_set.objects.iter() {
            objs.push(
                ObjectRange::add_object(
                    obj,
                    vertices,
                    indices,
                    index_ranges
                )
            );
        }
        ObjSetRange(start, objs.len())
    }
}

<|endoftext|>


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

use log::info;
use oak::{
    grpc,
    io::{Sender, SenderExt},
};
use proto::{
    command::Command::{JoinRoom, SendMessage},
    Chat, ChatDispatcher, Command, CreateRoomRequest, DestroyRoomRequest, SendMessageRequest,
    SubscribeRequest,
};
use std::collections::{hash_map::Entry, HashMap};

mod backend;
mod proto {
    include!(concat!(env!("OUT_DIR"), "/oak.examples.chat.rs"));
}

type RoomId = Vec<u8>;
type AdminToken = Vec<u8>;

#[derive(Default)]
struct Node {
    rooms: HashMap<RoomId, Room>,
}

oak::entrypoint!(oak_main => |in_channel| {
    oak::logger::init_default();
    let dispatcher = ChatDispatcher::new(Node::default());
    oak::run_event_loop(dispatcher, oak::io::Receiver::<grpc::Invocation>::new(in_channel));
});

oak::entrypoint!(grpc_oak_main => |_in_channel| {
    oak::logger::init_default();
    let dispatcher = ChatDispatcher::new(Node::default());
    let grpc_channel =
        oak::grpc::server::init("[::]:8080").expect("could not create gRPC server pseudo-Node");
    oak::run_event_loop(dispatcher, grpc_channel);
});

struct Room {
    sender: oak::io::Sender<Command>,
    admin_token: AdminToken,
}

impl Room {
    fn new(admin_token: AdminToken) -> Self {
        let (wh, rh) = oak::channel_create().unwrap();
        oak::node_create(&oak::node_config::wasm("app", "backend_oak_main"), rh)
            .expect("could not create node");
        oak::channel_close(rh.handle).expect("could not close channel");
        Room {
            sender: oak::io::Sender::new(wh),
            admin_token,
        }
    }
}

fn room_id_not_found_err<T>() -> grpc::Result<T> {
    Err(grpc::build_status(grpc::Code::NotFound, "room not found"))
}

fn room_id_duplicate_err<T>() -> grpc::Result<T> {
    Err(grpc::build_status(
        grpc::Code::AlreadyExists,
        "room already exists",
    ))
}

impl Chat for Node {
    fn create_room(&mut self, req: CreateRoomRequest) -> grpc::Result<()> {
        info!("creating room");
        if self.rooms.contains_key(&req.room_id) {
            return room_id_duplicate_err();
        }

        // Create a new Node for this room, and keep the write handle and admin token in the `rooms`
        // map.
        self.rooms.insert(req.room_id, Room::new(req.admin_token));

        Ok(())
    }

    fn destroy_room(&mut self, req: DestroyRoomRequest) -> grpc::Result<()> {
        info!("destroying room");
        match self.rooms.entry(req.room_id) {
            Entry::Occupied(e) => {
                if e.get().admin_token == req.admin_token {
                    // Close the only input channel that reaches the per-room Node, which
                    // will trigger it to terminate.
                    e.get().sender.close().expect("could not close channel");
                    e.remove();
                    Ok(())
                } else {
                    Err(grpc::build_status(
                        grpc::Code::PermissionDenied,
                        "invalid admin token",
                    ))
                }
            }
            Entry::Vacant(_) => room_id_not_found_err(),
        }
    }

    fn subscribe(&mut self, req: SubscribeRequest, writer: grpc::ChannelResponseWriter) {
        info!("subscribing to room");
        match self.rooms.get(&req.room_id) {
            None => {
                writer
                    .close(room_id_not_found_err())
                    .expect("could not close channel");
            }
            Some(room) => {
                info!("new subscription to room {:?}", req.room_id);
                let command = Command {
                    command: Some(JoinRoom(Sender::new(writer.handle()))),
                };
                room.sender
                    .send(&command)
                    .expect("could not send command to room Node");
            }
        };
    }

    fn send_message(&mut self, req: SendMessageRequest) -> grpc::Result<()> {
        info!("sending message to room");
        match self.rooms.get(&req.room_id) {
            None => room_id_not_found_err(),
            Some(room) => {
                info!("new message to room {:?}", req.room_id);
                let command = Command {
                    command: req.message.map(SendMessage),
                };
                room.sender
                    .send(&command)
                    .expect("could not send command to room Node");
                Ok(())
            }
        }
    }
}
<commit_msg>examples: remove now-unused entrypoint<commit_after>//
// Copyright 2019 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

use log::info;
use oak::{
    grpc,
    io::{Sender, SenderExt},
};
use proto::{
    command::Command::{JoinRoom, SendMessage},
    Chat, ChatDispatcher, Command, CreateRoomRequest, DestroyRoomRequest, SendMessageRequest,
    SubscribeRequest,
};
use std::collections::{hash_map::Entry, HashMap};

mod backend;
mod proto {
    include!(concat!(env!("OUT_DIR"), "/oak.examples.chat.rs"));
}

type RoomId = Vec<u8>;
type AdminToken = Vec<u8>;

#[derive(Default)]
struct Node {
    rooms: HashMap<RoomId, Room>,
}

oak::entrypoint!(grpc_oak_main => |_in_channel| {
    oak::logger::init_default();
    let dispatcher = ChatDispatcher::new(Node::default());
    let grpc_channel =
        oak::grpc::server::init("[::]:8080").expect("could not create gRPC server pseudo-Node");
    oak::run_event_loop(dispatcher, grpc_channel);
});

struct Room {
    sender: oak::io::Sender<Command>,
    admin_token: AdminToken,
}

impl Room {
    fn new(admin_token: AdminToken) -> Self {
        let (wh, rh) = oak::channel_create().unwrap();
        oak::node_create(&oak::node_config::wasm("app", "backend_oak_main"), rh)
            .expect("could not create node");
        oak::channel_close(rh.handle).expect("could not close channel");
        Room {
            sender: oak::io::Sender::new(wh),
            admin_token,
        }
    }
}

fn room_id_not_found_err<T>() -> grpc::Result<T> {
    Err(grpc::build_status(grpc::Code::NotFound, "room not found"))
}

fn room_id_duplicate_err<T>() -> grpc::Result<T> {
    Err(grpc::build_status(
        grpc::Code::AlreadyExists,
        "room already exists",
    ))
}

impl Chat for Node {
    fn create_room(&mut self, req: CreateRoomRequest) -> grpc::Result<()> {
        info!("creating room");
        if self.rooms.contains_key(&req.room_id) {
            return room_id_duplicate_err();
        }

        // Create a new Node for this room, and keep the write handle and admin token in the `rooms`
        // map.
        self.rooms.insert(req.room_id, Room::new(req.admin_token));

        Ok(())
    }

    fn destroy_room(&mut self, req: DestroyRoomRequest) -> grpc::Result<()> {
        info!("destroying room");
        match self.rooms.entry(req.room_id) {
            Entry::Occupied(e) => {
                if e.get().admin_token == req.admin_token {
                    // Close the only input channel that reaches the per-room Node, which
                    // will trigger it to terminate.
                    e.get().sender.close().expect("could not close channel");
                    e.remove();
                    Ok(())
                } else {
                    Err(grpc::build_status(
                        grpc::Code::PermissionDenied,
                        "invalid admin token",
                    ))
                }
            }
            Entry::Vacant(_) => room_id_not_found_err(),
        }
    }

    fn subscribe(&mut self, req: SubscribeRequest, writer: grpc::ChannelResponseWriter) {
        info!("subscribing to room");
        match self.rooms.get(&req.room_id) {
            None => {
                writer
                    .close(room_id_not_found_err())
                    .expect("could not close channel");
            }
            Some(room) => {
                info!("new subscription to room {:?}", req.room_id);
                let command = Command {
                    command: Some(JoinRoom(Sender::new(writer.handle()))),
                };
                room.sender
                    .send(&command)
                    .expect("could not send command to room Node");
            }
        };
    }

    fn send_message(&mut self, req: SendMessageRequest) -> grpc::Result<()> {
        info!("sending message to room");
        match self.rooms.get(&req.room_id) {
            None => room_id_not_found_err(),
            Some(room) => {
                info!("new message to room {:?}", req.room_id);
                let command = Command {
                    command: req.message.map(SendMessage),
                };
                room.sender
                    .send(&command)
                    .expect("could not send command to room Node");
                Ok(())
            }
        }
    }
}
<|endoftext|>


<commit_before>use fall_tree::{NodeType, INode, Text, TextRange, tu};
use lex_engine::Token;
use syn_engine::Event;

pub(crate) fn convert(
    text: Text,
    tokens: &[Token],
    events: &[Event],
    is_whitespace: &Fn(NodeType) -> bool,
    whitespace_binder: &Fn(NodeType, &[(NodeType, Text)], bool) -> usize,
) -> INode {
    let events = reshuffle_events(events);
    let (first, rest) = (events[0], &events[1..]);

    let mut len = tu(0);
    let tokens = tokens.iter().map(|&t| {
        let token_text = text.slice(TextRange::from_len(len, t.len));
        len += t.len;
        (t, token_text)
    }).collect::<Vec<_>>();

    let conv = Convertor { is_whitespace, whitespace_binder };
    match first {
        Event::Start { ty, forward_parent: _ } => {
            let conversion = conv.go(ty, &tokens, rest);
            assert_eq!(conversion.right_edge, tokens.len());
            assert_eq!(conversion.n_events, rest.len());
            conversion.inode
        }
        _ => unreachable!()
    }
}

fn reshuffle_events(events: &[Event]) -> Vec<Event> {
    let mut result = Vec::with_capacity(events.len());
    let mut holes = Vec::new();
    let mut forward_parents = Vec::new();

    for (i, &e) in events.iter().enumerate() {
        if holes.last() == Some(&i) {
            holes.pop();
            continue
        }
        match e {
            Event::Start { forward_parent: Some(_), .. } => {
                forward_parents.clear();
                let mut idx = i;
                loop {
                    let (ty, fwd) = match events[idx] {
                        Event::Start { ty, forward_parent } => (ty, forward_parent),
                        _ => unreachable!(),
                    };
                    forward_parents.push((idx, ty));
                    if let Some(fwd) = fwd {
                        idx += fwd as usize;
                    } else {
                        break;
                    }
                }
                for &(idx, ty) in forward_parents.iter().into_iter().rev() {
                    result.push(Event::Start { ty, forward_parent: None });
                    holes.push(idx);
                }
                holes.pop();
            }
            _ => result.push(e)
        }
    }
    result
}

struct Convertor<'a> {
    is_whitespace: &'a Fn(NodeType) -> bool,
    whitespace_binder: &'a Fn(NodeType, &[(NodeType, Text)], bool) -> usize,
}

#[derive(Debug)]
struct Conversion {
    right_edge: usize,
    n_events: usize,
    inode: INode,
}

impl<'a> Convertor<'a> {
    fn go(
        &self,
        ty: NodeType,
        tokens: &[(Token, Text)],
        events: &[Event],
    ) -> Conversion {
        let mut inode = INode::new(ty);
        let (n_tokens, n_events) = self.fill(&mut inode, tokens, events);
        let tokens = &tokens[n_tokens..];

        let trailing_ws = self.collect_tokens_for_binder(tokens);
        let right_ws = (self.whitespace_binder)(ty, &trailing_ws, false);
        for &(t, _) in &tokens[..right_ws] {
            inode.push_child(INode::new_leaf(t.ty, t.len))
        }

        let right_edge = n_tokens + right_ws;
        return Conversion {
            right_edge,
            n_events,
            inode,
        };
    }

    fn collect_tokens_for_binder<'t>(&self, tokens: &[(Token, Text<'t>)]) -> Vec<(NodeType, Text<'t>)> {
        tokens.iter()
            .take_while(|&&(t, _)| (self.is_whitespace)(t.ty))
            .map(|&(t, text)| (t.ty, text))
            .collect()
    }

    fn fill(
        &self,
        inode: &mut INode,
        tokens: &[(Token, Text)],
        events: &[Event],
    ) -> (usize, usize) {
        let mut tokens = tokens;
        let mut n_tokens = 0;
        let mut events = events;
        let mut n_events = 0;
        loop {
            let (first, rest) = (events[0], &events[1..]);
            n_events += 1;
            events = rest;
            match first {
                Event::Start { ty, forward_parent: _ } => {
                    let leading_ws = self.collect_tokens_for_binder(tokens);
                    let left_wd = leading_ws.len() - (self.whitespace_binder)(ty, &leading_ws, true);
                    for i in 0..left_wd {
                        let t = tokens[i].0;
                        inode.push_child(INode::new_leaf(t.ty, t.len))
                    }
                    tokens = &tokens[left_wd..];
                    n_tokens += left_wd;

                    let Conversion { right_edge, n_events: child_events, inode: child } =
                        self.go(ty, tokens, events);
                    inode.push_child(child);
                    tokens = &tokens[right_edge..];
                    n_tokens += right_edge;
                    events = &events[child_events..];
                    n_events += child_events;
                }

                Event::End => return (n_tokens, n_events),

                Event::Token { ty, n_raw_tokens } => {
                    let non_white = tokens.iter().take_while(|&&(t, _)| (self.is_whitespace)(t.ty)).count();
                    for i in 0..non_white {
                        let t = tokens[i].0;
                        inode.push_child(INode::new_leaf(t.ty, t.len))
                    }
                    tokens = &tokens[non_white..];
                    n_tokens += non_white;

                    let n_raw_tokens = n_raw_tokens as usize;
                    let mut token = INode::new(ty);
                    for &(t, _) in &tokens[..n_raw_tokens] {
                        n_tokens += 1;
                        token.push_token_part(t.len)
                    }
                    inode.push_child(token);
                    tokens = &tokens[n_raw_tokens..];
                }

                Event::Cached { .. } => {}
            }
        }
    }
}
<commit_msg>Abstract over builder<commit_after>use fall_tree::{NodeType, INode, Text, TextRange, tu, TextUnit};
use lex_engine::Token;
use syn_engine::Event;

trait TB {
    fn start_internal(&mut self, ty: NodeType);
    fn leaf(&mut self, ty: NodeType, len: TextUnit);
    fn finish_internal(&mut self);
}

struct INodeBuilder {
    nodes: Vec<INode>,
    result: Option<INode>,
}

impl INodeBuilder {
    fn new() -> INodeBuilder {
        INodeBuilder {
            nodes: Vec::new(),
            result: None,
        }
    }
}

impl TB for INodeBuilder {
    fn start_internal(&mut self, ty: NodeType) {
        self.nodes.push(INode::new(ty))
    }

    fn leaf(&mut self, ty: NodeType, len: TextUnit) {
        let mut inode = INode::new(ty);
        inode.push_token_part(len);
        self.nodes.last_mut().unwrap().push_child(inode);
    }

    fn finish_internal(&mut self) {
        let node = self.nodes.pop().unwrap();
        if let Some(parent) = self.nodes.last_mut() {
            parent.push_child(node)
        } else {
            self.result = Some(node)
        }
    }
}

pub(crate) fn convert(
    text: Text,
    tokens: &[Token],
    events: &[Event],
    is_whitespace: &Fn(NodeType) -> bool,
    whitespace_binder: &Fn(NodeType, &[(NodeType, Text)], bool) -> usize,
) -> INode {
    let events = reshuffle_events(events);
    let (first, rest) = (events[0], &events[1..]);

    let mut len = tu(0);
    let tokens = tokens.iter().map(|&t| {
        let token_text = text.slice(TextRange::from_len(len, t.len));
        len += t.len;
        (t, token_text)
    }).collect::<Vec<_>>();

    let conv = Convertor { is_whitespace, whitespace_binder };
    let mut bulider = INodeBuilder::new();
    match first {
        Event::Start { ty, forward_parent: _ } => {
            conv.go(ty, &tokens, rest, &mut bulider);
            bulider.result.unwrap()
        }
        _ => unreachable!()
    }
}

fn reshuffle_events(events: &[Event]) -> Vec<Event> {
    let mut result = Vec::with_capacity(events.len());
    let mut holes = Vec::new();
    let mut forward_parents = Vec::new();

    for (i, &e) in events.iter().enumerate() {
        if holes.last() == Some(&i) {
            holes.pop();
            continue
        }
        match e {
            Event::Start { forward_parent: Some(_), .. } => {
                forward_parents.clear();
                let mut idx = i;
                loop {
                    let (ty, fwd) = match events[idx] {
                        Event::Start { ty, forward_parent } => (ty, forward_parent),
                        _ => unreachable!(),
                    };
                    forward_parents.push((idx, ty));
                    if let Some(fwd) = fwd {
                        idx += fwd as usize;
                    } else {
                        break;
                    }
                }
                for &(idx, ty) in forward_parents.iter().into_iter().rev() {
                    result.push(Event::Start { ty, forward_parent: None });
                    holes.push(idx);
                }
                holes.pop();
            }
            _ => result.push(e)
        }
    }
    result
}

struct Convertor<'a> {
    is_whitespace: &'a Fn(NodeType) -> bool,
    whitespace_binder: &'a Fn(NodeType, &[(NodeType, Text)], bool) -> usize,
}

#[derive(Debug)]
struct Conversion {
    right_edge: usize,
    n_events: usize,
}

impl<'a> Convertor<'a> {
    fn go(
        &self,
        ty: NodeType,
        tokens: &[(Token, Text)],
        events: &[Event],
        builder: &mut TB,
    ) -> Conversion {
        builder.start_internal(ty);
        let (n_tokens, n_events) = self.fill(tokens, events, builder);
        let tokens = &tokens[n_tokens..];

        let trailing_ws = self.collect_tokens_for_binder(tokens);
        let right_ws = (self.whitespace_binder)(ty, &trailing_ws, false);
        for &(t, _) in &tokens[..right_ws] {
            builder.leaf(t.ty, t.len);
        }
        builder.finish_internal();

        let right_edge = n_tokens + right_ws;
        return Conversion {
            right_edge,
            n_events,
        };
    }

    fn collect_tokens_for_binder<'t>(&self, tokens: &[(Token, Text<'t>)]) -> Vec<(NodeType, Text<'t>)> {
        tokens.iter()
            .take_while(|&&(t, _)| (self.is_whitespace)(t.ty))
            .map(|&(t, text)| (t.ty, text))
            .collect()
    }

    fn fill(
        &self,
        tokens: &[(Token, Text)],
        events: &[Event],
        builder: &mut TB,
    ) -> (usize, usize) {
        let mut tokens = tokens;
        let mut n_tokens = 0;
        let mut events = events;
        let mut n_events = 0;
        loop {
            let (first, rest) = (events[0], &events[1..]);
            n_events += 1;
            events = rest;
            match first {
                Event::Start { ty, forward_parent: _ } => {
                    let leading_ws = self.collect_tokens_for_binder(tokens);
                    let left_wd = leading_ws.len() - (self.whitespace_binder)(ty, &leading_ws, true);
                    for i in 0..left_wd {
                        let t = tokens[i].0;
                        builder.leaf(t.ty, t.len);
                    }
                    tokens = &tokens[left_wd..];
                    n_tokens += left_wd;

                    let Conversion { right_edge, n_events: child_events } =
                        self.go(ty, tokens, events, builder);
                    tokens = &tokens[right_edge..];
                    n_tokens += right_edge;
                    events = &events[child_events..];
                    n_events += child_events;
                }

                Event::End => return (n_tokens, n_events),

                Event::Token { ty, n_raw_tokens } => {
                    let non_white = tokens.iter().take_while(|&&(t, _)| (self.is_whitespace)(t.ty)).count();
                    for i in 0..non_white {
                        let t = tokens[i].0;
                        builder.leaf(t.ty, t.len);
                    }
                    tokens = &tokens[non_white..];
                    n_tokens += non_white;

                    let n_raw_tokens = n_raw_tokens as usize;
                    let mut len = tu(0);
                    for &(t, _) in &tokens[..n_raw_tokens] {
                        n_tokens += 1;
                        len += t.len;
                    }
                    builder.leaf(ty, len);
                    tokens = &tokens[n_raw_tokens..];
                }

                Event::Cached { .. } => {}
            }
        }
    }
}
<|endoftext|>