<commit_before>use futures::{Poll, Future, Async, BoxFuture};
use tokio_service::Service;
use store::Store;
use {LogPos, Error};
use std::net::SocketAddr;
use std::io;
use std::mem;
use replica::{ReplicaRequest, ReplicaResponse, LogEntry};

enum ReplicatorState<S: Store, D>
    where D: DownstreamService
{
    Idle,
    Fetching(S::FetchFut),
    Forwarding(D::Future),
}

pub trait DownstreamService {
    type Future: Future<Item = ReplicaResponse, Error = io::Error>;
}

impl<D> DownstreamService for D
    where D: Service<Request = (SocketAddr, ReplicaRequest),
                     Response = ReplicaResponse,
                     Error = io::Error,
                     Future = BoxFuture<ReplicaResponse, io::Error>>
{
    type Future = D::Future;
}

pub struct Replicator<S: Store, D: DownstreamService> {
    store: S,
    downstream: D,
    last_seen_seq: LogPos,
    downstream_addr: Option<SocketAddr>,
    state: ReplicatorState<S, D>,
}

impl<S: Store, D: DownstreamService> Replicator<S, D> {
    pub fn new(store: S, downstream: D) -> Self {
        Replicator {
            store: store,
            downstream: downstream,
            last_seen_seq: LogPos::zero(),
            downstream_addr: None,
            state: ReplicatorState::Idle,
        }
    }
}

impl<S: Store, D: DownstreamService> Drop for Replicator<S, D> {
    fn drop(&mut self) {
        debug!("Drop Replicator");
    }
}

impl<S: Store, D> Future for Replicator<S, D>
    where S: Store,
          D: Service<Request = (SocketAddr, ReplicaRequest),
                     Response = ReplicaResponse,
                     Error = io::Error,
                     Future = BoxFuture<ReplicaResponse, io::Error>>
{
    type Item = ();
    type Error = Error;
    fn poll(&mut self) -> Poll<(), Error> {
        debug!("Replicator#poll");
        loop {
            match mem::replace(&mut self.state, ReplicatorState::Idle) {
                ReplicatorState::Idle => {
                    debug!("Idle, fetching after: {:?}", self.last_seen_seq);
                    let fetch_f = self.store.fetch_next(self.last_seen_seq);
                    self.state = ReplicatorState::Fetching(fetch_f);
                }
                // Now, what have we learnt from this, children? Surely it's
                // that because we're forwarding LogEntries at least, we
                // should make it easy to get a LogEntry into/out of the
                // store, rather than having to futz around with serialisation
                // rubbish.
                ReplicatorState::Fetching(mut fetch_f) => {
                    debug!("Fetching");
                    match try!(fetch_f.poll()) {
                        Async::NotReady => {
                            self.state = ReplicatorState::Fetching(fetch_f);
                            return Ok(Async::NotReady);
                        }
                        Async::Ready((off, val)) => {
                            debug!("Fetched: {:?}", (&off, &val));
                            if let &LogEntry::Config(ref conf) = &val {
                                debug!("logged Config message: {:?}", conf);
                                // FIXME: Well, this is blatantly wrong.
                                self.downstream_addr = Some(conf.head);
                            };

                            if let Some(addr) = self.downstream_addr {
                                debug!("Forward {:?} to: {:?}", off, addr);
                                // XXX: Symmetry with ReplClient?
                                let req = ReplicaRequest::AppendLogEntry {
                                    assumed_offset: self.last_seen_seq,
                                    entry_offset: off,
                                    datum: val,
                                };
                                let f = self.downstream.call((addr, req));
                                self.state = ReplicatorState::Forwarding(f);
                            } else {
                                debug!("No downstream at {:?}", off);
                            }
                            self.last_seen_seq = off;
                        }
                    }
                }
                ReplicatorState::Forwarding(mut f) => {
                    match try!(f.poll()) {
                        Async::NotReady => {
                            self.state = ReplicatorState::Forwarding(f);
                            return Ok(Async::NotReady);
                        }
                        Async::Ready(ReplicaResponse::Done(pos)) => {
                            debug!("woo! {:?}", pos);
                        }
                        Async::Ready(ReplicaResponse::BadSequence(pos)) => {
                            panic!("ARGH! {:?}", pos);
                        }
                    }
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    use futures::{self, Future, BoxFuture, Async};
    use futures::stream::Stream;
    use service::Service;
    use tokio::channel;
    use replica::LogPos;
    use store::{RamStore, Store};
    use replica::{ReplicaRequest, ReplicaResponse, LogEntry, HostConfig};
    use std::net::SocketAddr;
    use super::*;
    use tokio::reactor::Core;
    use std::time::Duration;
    use std::io;
    use tokio_timer;
    use env_logger;

    struct MyMagicalDownstream {
        send: channel::Sender<((SocketAddr, ReplicaRequest), futures::Complete<ReplicaResponse>)>,
    }

    impl Service for MyMagicalDownstream {
        type Request = (SocketAddr, ReplicaRequest);
        type Response = ReplicaResponse;
        type Error = io::Error;
        type Future = BoxFuture<ReplicaResponse, io::Error>;
        fn poll_ready(&self) -> Async<()> {
            Async::Ready(())
        }
        fn call(&self, req: Self::Request) -> Self::Future {
            let (c, p) = futures::oneshot();
            match self.send.send((req, c)) {
                Ok(()) => (),
                Err(e) => return futures::failed(e).boxed(),
            };
            p.map_err(|_| io::Error::new(io::ErrorKind::BrokenPipe, "broken pipe"))
                .boxed()
        }
    }

    #[test]
    fn should_start_replicating_to_downstream_on_committed_config_message() {
        env_logger::init().unwrap_or(());
        let store = RamStore::new();
        let timer = tokio_timer::wheel().tick_duration(Duration::from_millis(1)).build();

        let mut core = Core::new().expect("core::new");
        let (tx, rx) = channel::channel(&core.handle()).expect("channel");

        let downstream = MyMagicalDownstream { send: tx };

        let replica = Replicator::new(store.clone(), downstream);

        core.handle().spawn(replica.map_err(|e| panic!("Replicator failed!: {:?}", e)));
        debug!("Spawned replica task");

        let off = LogPos::zero();

        let head_addr = "1.2.3.4:5".parse().expect("parse");

        let config: HostConfig<::std::net::SocketAddr> = HostConfig {
            head: head_addr,
            tail: "1.2.3.6:7".parse().expect("parse"),
        };

        debug!("append config message");
        core.run(store.append_entry(off, off.next(), LogEntry::Config(config.clone())))
            .expect("append");

        let f = timer.timeout(rx.into_future().map_err(|(e, _)| e),
                              Duration::from_millis(1000));
        debug!("wait for stub message");
        let (data, _rx) = core.run(f).expect("receive downstream");
        let ((addr, msg), _completer) = data.expect("Some message");
        println!("Some: {:?}", (&addr, &msg));
        let (_assumed, _off, entry) = match msg {
            ReplicaRequest::AppendLogEntry { assumed_offset, entry_offset, datum } => {
                (assumed_offset, entry_offset, datum)
            }
        };
        assert_eq!((addr, entry), (head_addr, LogEntry::Config(config)));
    }

    #[test]
    fn should_send_next_log_entry_on_okay_from_downstream() {
        env_logger::init().unwrap_or(());
        let store = RamStore::new();
        let timer = tokio_timer::wheel().tick_duration(Duration::from_millis(1)).build();

        let mut core = Core::new().expect("core::new");
        let (tx, rx) = channel::channel(&core.handle()).expect("channel");

        let downstream = MyMagicalDownstream { send: tx };

        let replica = Replicator::new(store.clone(), downstream);

        core.handle().spawn(replica.map_err(|e| panic!("Replicator failed!: {:?}", e)));
        debug!("Spawned replica task");

        let head_addr = "1.2.3.4:5".parse().expect("parse");

        let config: HostConfig<::std::net::SocketAddr> = HostConfig {
            head: head_addr,
            tail: "1.2.3.6:7".parse().expect("parse"),
        };

        {
            let off = LogPos::zero();
            let next = off.next();
            debug!("append config message {:?} -> {:?}", off, next);
            core.run(store.append_entry(off, next, LogEntry::Config(config.clone())))
                .expect("append");

            let off = next;
            let next = off.next();
            debug!("append data message {:?} -> {:?}", off, next);
            core.run(store.append_entry(off, next, LogEntry::Data(b"Hello world!".to_vec())))
                .expect("append");
        }

        let f = timer.timeout(rx.into_future().map_err(|(e, _)| e),
                              Duration::from_millis(1000));
        debug!("wait for stub message");
        let (data, rx) = core.run(f).expect("receive downstream");
        let ((addr, msg), completer) = data.expect("Some message");
        println!("Some: {:?}", (&addr, &msg));
        // Expect that the target at `head_addr` receives a set of replication messages.
        let (_assumed0, off0, _entry0) = match msg {
            ReplicaRequest::AppendLogEntry { assumed_offset, entry_offset, datum } => {
                (assumed_offset, entry_offset, datum)
            }
        };

        completer.complete(ReplicaResponse::Done(off0));

        let f = timer.timeout(rx.into_future().map_err(|(e, _)| e),
                              Duration::from_millis(1000));
        debug!("wait for stub message");
        let (data, _rx) = core.run(f).expect("receive downstream");
        let ((addr, msg), _completer) = data.expect("Some message");
        println!("Some: {:?}", (&addr, &msg));
        // Expect that the target at `head_addr` receives a set of replication messages.
        let (assumed1, off1, entry1) = match msg {
            ReplicaRequest::AppendLogEntry { assumed_offset, entry_offset, datum } => {
                (assumed_offset, entry_offset, datum)
            }
        };

        assert_eq!((addr, assumed1, entry1),
                   (head_addr, off0, LogEntry::Data(b"Hello world!".to_vec())));
        assert!(off1 > assumed1);
    }

    #[test]
    #[ignore]
    fn should_restart_replication_on_badsequence_from_downstream() {}

}
<commit_msg>Restart replicator after a bad-sequence message.<commit_after>use futures::{Poll, Future, Async, BoxFuture};
use tokio_service::Service;
use store::Store;
use {LogPos, Error};
use std::net::SocketAddr;
use std::io;
use std::mem;
use replica::{ReplicaRequest, ReplicaResponse, LogEntry};

enum ReplicatorState<S: Store, D>
    where D: DownstreamService
{
    Idle,
    Fetching(S::FetchFut),
    Forwarding(D::Future),
}

pub trait DownstreamService {
    type Future: Future<Item = ReplicaResponse, Error = io::Error>;
}

impl<D> DownstreamService for D
    where D: Service<Request = (SocketAddr, ReplicaRequest),
                     Response = ReplicaResponse,
                     Error = io::Error,
                     Future = BoxFuture<ReplicaResponse, io::Error>>
{
    type Future = D::Future;
}

pub struct Replicator<S: Store, D: DownstreamService> {
    store: S,
    downstream: D,
    last_seen_seq: LogPos,
    downstream_addr: Option<SocketAddr>,
    state: ReplicatorState<S, D>,
}

impl<S: Store, D: DownstreamService> Replicator<S, D> {
    pub fn new(store: S, downstream: D) -> Self {
        Replicator {
            store: store,
            downstream: downstream,
            last_seen_seq: LogPos::zero(),
            downstream_addr: None,
            state: ReplicatorState::Idle,
        }
    }
}

impl<S: Store, D: DownstreamService> Drop for Replicator<S, D> {
    fn drop(&mut self) {
        debug!("Drop Replicator");
    }
}

impl<S: Store, D> Future for Replicator<S, D>
    where S: Store,
          D: Service<Request = (SocketAddr, ReplicaRequest),
                     Response = ReplicaResponse,
                     Error = io::Error,
                     Future = BoxFuture<ReplicaResponse, io::Error>>
{
    type Item = ();
    type Error = Error;
    fn poll(&mut self) -> Poll<(), Error> {
        debug!("Replicator#poll");
        loop {
            match mem::replace(&mut self.state, ReplicatorState::Idle) {
                ReplicatorState::Idle => {
                    debug!("Idle, fetching after: {:?}", self.last_seen_seq);
                    let fetch_f = self.store.fetch_next(self.last_seen_seq);
                    self.state = ReplicatorState::Fetching(fetch_f);
                }
                // Now, what have we learnt from this, children? Surely it's
                // that because we're forwarding LogEntries at least, we
                // should make it easy to get a LogEntry into/out of the
                // store, rather than having to futz around with serialisation
                // rubbish.
                ReplicatorState::Fetching(mut fetch_f) => {
                    debug!("Fetching");
                    match try!(fetch_f.poll()) {
                        Async::NotReady => {
                            self.state = ReplicatorState::Fetching(fetch_f);
                            return Ok(Async::NotReady);
                        }
                        Async::Ready((off, val)) => {
                            debug!("Fetched: {:?}", (&off, &val));
                            if let &LogEntry::Config(ref conf) = &val {
                                debug!("logged Config message: {:?}", conf);
                                // FIXME: Well, this is blatantly wrong.
                                self.downstream_addr = Some(conf.head);
                            };

                            if let Some(addr) = self.downstream_addr {
                                debug!("Forward {:?} to: {:?}", off, addr);
                                // XXX: Symmetry with ReplClient?
                                let req = ReplicaRequest::AppendLogEntry {
                                    assumed_offset: self.last_seen_seq,
                                    entry_offset: off,
                                    datum: val,
                                };
                                let f = self.downstream.call((addr, req));
                                self.state = ReplicatorState::Forwarding(f);
                            } else {
                                debug!("No downstream at {:?}", off);
                            }
                            self.last_seen_seq = off;
                        }
                    }
                }
                ReplicatorState::Forwarding(mut f) => {
                    match try!(f.poll()) {
                        Async::NotReady => {
                            self.state = ReplicatorState::Forwarding(f);
                            return Ok(Async::NotReady);
                        }
                        Async::Ready(ReplicaResponse::Done(pos)) => {
                            debug!("woo! {:?}", pos);
                        }
                        Async::Ready(ReplicaResponse::BadSequence(pos)) => {
                            debug!("Bad sequence: resetting to {:?}", pos);
                            self.last_seen_seq = pos;
                        }
                    }
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    use futures::{self, Future, BoxFuture, Async};
    use futures::stream::Stream;
    use service::Service;
    use tokio::channel;
    use replica::LogPos;
    use store::{RamStore, Store};
    use replica::{ReplicaRequest, ReplicaResponse, LogEntry, HostConfig};
    use std::net::SocketAddr;
    use super::*;
    use tokio::reactor::Core;
    use std::time::Duration;
    use std::io;
    use tokio_timer;
    use env_logger;

    struct MyMagicalDownstream {
        send: channel::Sender<((SocketAddr, ReplicaRequest), futures::Complete<ReplicaResponse>)>,
    }

    impl Service for MyMagicalDownstream {
        type Request = (SocketAddr, ReplicaRequest);
        type Response = ReplicaResponse;
        type Error = io::Error;
        type Future = BoxFuture<ReplicaResponse, io::Error>;
        fn poll_ready(&self) -> Async<()> {
            Async::Ready(())
        }
        fn call(&self, req: Self::Request) -> Self::Future {
            let (c, p) = futures::oneshot();
            match self.send.send((req, c)) {
                Ok(()) => (),
                Err(e) => return futures::failed(e).boxed(),
            };
            p.map_err(|_| io::Error::new(io::ErrorKind::BrokenPipe, "broken pipe"))
                .boxed()
        }
    }

    #[test]
    fn should_start_replicating_to_downstream_on_committed_config_message() {
        env_logger::init().unwrap_or(());
        let store = RamStore::new();
        let timer = tokio_timer::wheel().tick_duration(Duration::from_millis(1)).build();

        let mut core = Core::new().expect("core::new");
        let (tx, rx) = channel::channel(&core.handle()).expect("channel");

        let downstream = MyMagicalDownstream { send: tx };

        let replica = Replicator::new(store.clone(), downstream);

        core.handle().spawn(replica.map_err(|e| panic!("Replicator failed!: {:?}", e)));
        debug!("Spawned replica task");

        let off = LogPos::zero();

        let head_addr = "1.2.3.4:5".parse().expect("parse");

        let config: HostConfig<::std::net::SocketAddr> = HostConfig {
            head: head_addr,
            tail: "1.2.3.6:7".parse().expect("parse"),
        };

        debug!("append config message");
        core.run(store.append_entry(off, off.next(), LogEntry::Config(config.clone())))
            .expect("append");

        let f = timer.timeout(rx.into_future().map_err(|(e, _)| e),
                              Duration::from_millis(1000));
        debug!("wait for stub message");
        let (data, _rx) = core.run(f).expect("receive downstream");
        let ((addr, msg), _completer) = data.expect("Some message");
        println!("Some: {:?}", (&addr, &msg));
        let (_assumed, _off, entry) = match msg {
            ReplicaRequest::AppendLogEntry { assumed_offset, entry_offset, datum } => {
                (assumed_offset, entry_offset, datum)
            }
        };
        assert_eq!((addr, entry), (head_addr, LogEntry::Config(config)));
    }

    #[test]
    fn should_send_next_log_entry_on_okay_from_downstream() {
        env_logger::init().unwrap_or(());
        let store = RamStore::new();
        let timer = tokio_timer::wheel().tick_duration(Duration::from_millis(1)).build();

        let mut core = Core::new().expect("core::new");
        let (tx, rx) = channel::channel(&core.handle()).expect("channel");

        let downstream = MyMagicalDownstream { send: tx };

        let replica = Replicator::new(store.clone(), downstream);

        core.handle().spawn(replica.map_err(|e| panic!("Replicator failed!: {:?}", e)));
        debug!("Spawned replica task");

        let head_addr = "1.2.3.4:5".parse().expect("parse");

        let config: HostConfig<::std::net::SocketAddr> = HostConfig {
            head: head_addr,
            tail: "1.2.3.6:7".parse().expect("parse"),
        };

        {
            let off = LogPos::zero();
            let next = off.next();
            debug!("append config message {:?} -> {:?}", off, next);
            core.run(store.append_entry(off, next, LogEntry::Config(config.clone())))
                .expect("append");

            let off = next;
            let next = off.next();
            debug!("append data message {:?} -> {:?}", off, next);
            core.run(store.append_entry(off, next, LogEntry::Data(b"Hello world!".to_vec())))
                .expect("append");
        }

        let f = timer.timeout(rx.into_future().map_err(|(e, _)| e),
                              Duration::from_millis(1000));
        debug!("wait for stub message");
        let (data, rx) = core.run(f).expect("receive downstream");
        let ((addr, msg), completer) = data.expect("Some message");
        println!("Some: {:?}", (&addr, &msg));
        // Expect that the target at `head_addr` receives a set of replication messages.
        let (_assumed0, off0, _entry0) = match msg {
            ReplicaRequest::AppendLogEntry { assumed_offset, entry_offset, datum } => {
                (assumed_offset, entry_offset, datum)
            }
        };

        completer.complete(ReplicaResponse::Done(off0));

        let f = timer.timeout(rx.into_future().map_err(|(e, _)| e),
                              Duration::from_millis(1000));
        debug!("wait for stub message");
        let (data, _rx) = core.run(f).expect("receive downstream");
        let ((addr, msg), _completer) = data.expect("Some message");
        println!("Some: {:?}", (&addr, &msg));
        // Expect that the target at `head_addr` receives a set of replication messages.
        let (assumed1, off1, entry1) = match msg {
            ReplicaRequest::AppendLogEntry { assumed_offset, entry_offset, datum } => {
                (assumed_offset, entry_offset, datum)
            }
        };

        assert_eq!((addr, assumed1, entry1),
                   (head_addr, off0, LogEntry::Data(b"Hello world!".to_vec())));
        assert!(off1 > assumed1);
    }

    #[test]
    fn should_restart_replication_on_badsequence_from_downstream() {
        env_logger::init().unwrap_or(());
        let store = RamStore::new();
        let timer = tokio_timer::wheel().tick_duration(Duration::from_millis(1)).build();

        let mut core = Core::new().expect("core::new");
        let (tx, rx) = channel::channel(&core.handle()).expect("channel");

        let downstream = MyMagicalDownstream { send: tx };

        let replica = Replicator::new(store.clone(), downstream);

        core.handle().spawn(replica.map_err(|e| panic!("Replicator failed!: {:?}", e)));
        debug!("Spawned replica task");

        let head_addr = "1.2.3.4:5".parse().expect("parse");

        let config: HostConfig<::std::net::SocketAddr> = HostConfig {
            head: head_addr,
            tail: "1.2.3.6:7".parse().expect("parse"),
        };

        let off = LogPos::zero();
        let next = off.next();
        debug!("append config message {:?} -> {:?}", off, next);
        core.run(store.append_entry(off, next, LogEntry::Config(config.clone())))
            .expect("append");

        let off = next;
        let next = off.next();
        debug!("append data message {:?} -> {:?}", off, next);
        core.run(store.append_entry(off, next, LogEntry::Data(b"Hello".to_vec())))
            .expect("append");

        let off = next;
        let next = off.next();
        debug!("append data message {:?} -> {:?}", off, next);
        core.run(store.append_entry(off, next, LogEntry::Data(b"world!".to_vec())))
            .expect("append");

        let f = timer.timeout(rx.into_future().map_err(|(e, _)| e),
                              Duration::from_millis(1000));
        debug!("wait for stub message");
        let (data, rx) = core.run(f).expect("receive downstream");
        let ((addr, msg), completer) = data.expect("Some message");
        println!("Some: {:?}", (&addr, &msg));
        // Expect that the target at `head_addr` receives a set of replication messages.
        let (_assumed0, _off0, _entry0) = match msg {
            ReplicaRequest::AppendLogEntry { assumed_offset, entry_offset, datum } => {
                (assumed_offset, entry_offset, datum)
            }
        };

        // So we expect the delivery of "world!"
        let resp = ReplicaResponse::BadSequence(off);
        println!("Respond with: {:?}", resp);
        completer.complete(resp);

        let f = timer.timeout(rx.into_future().map_err(|(e, _)| e),
                              Duration::from_millis(1000));
        debug!("wait for stub message");
        let (data, _rx) = core.run(f).expect("receive downstream");
        let ((addr, msg), _completer) = data.expect("Some message");
        println!("Some: {:?}", (&addr, &msg));
        // Expect that the target at `head_addr` receives a set of replication messages.
        let (assumed1, off1, entry1) = match msg {
            ReplicaRequest::AppendLogEntry { assumed_offset, entry_offset, datum } => {
                (assumed_offset, entry_offset, datum)
            }
        };

        assert_eq!((addr, assumed1, off1, entry1),
                   (head_addr, off, next, LogEntry::Data(b"world!".to_vec())));
        assert!(off1 > assumed1);
    }
}
<|endoftext|>


<commit_before>static side: i8 = 8;
static queens: i8 = 8;

fn place(mut board: [i8,..side*side], ix:i8) -> Option<[i8,..side*side]> {
    if board[ix] == 0 {
        return None
    };
    board[ix] = -1;
    let i1 = ix/side;
    let j1 = ix % side;
    for k in range(1,side) {
        let mut loc :i8 = i1 * side + k;
        board[loc] = 0;
        loc = k * side + j1;
        board[loc] = 0;
        loc = (i1-k) * side + (j1-k);
        if loc / side == i1 -k && loc % side == j1 - k && loc != ix && loc >= 0 { board[loc] = 0 };
        loc = loc + 2 * k;
        if loc / side == i1 - k && loc % side == j1 + k && loc != ix && loc >= 0 { board[loc] = 0};
        loc = loc + 2 * side * k;
        if loc / side == i1 + k && loc % side == j1 + k && loc != ix && loc < side*side { board[loc] = 0};
        loc = loc - 2 * k;
        if loc / side == i1 + k && loc % side == j1 - k && loc != ix && loc < side*side { board[loc] = 0};
    }
    Some(board)
}

fn tryplace(b : [i8,..side*side],ix:i8, nq: i8, mut score: u32) -> u32 {
    if nq == queens { return score + 1 }
    for ind in range(ix, side*side) {
        score = match place(b, ind) {
            Some(b2) => tryplace(b2, ind+1, nq+1, score),
            None() => score
        };
    }
    return score
}

fn main() {
    let b : [i8, ..side*side] = [1,..side*side];
    let score = tryplace(b, 0, 0, 0);
    println!("{}", score)
}
<commit_msg>N_Queens fix.<commit_after>static side: i8 = 8;
static queens: i8 = 8;

fn place(mut board: [i8,..side*side], ix:i8) -> Option<[i8,..side*side]> {
    if board[ix] == 0 {
        return None
    };
    board[ix] = -1;
    let i1 = ix/side;
    let j1 = ix % side;
    for k in range(1,side) {
        let mut loc :i8 = i1 * side + k;
        board[loc] = 0;
        loc = k * side + j1;
        board[loc] = 0;
        loc = (i1-k) * side + (j1-k);
        if loc / side == i1 -k && loc % side == j1 - k && loc != ix && loc >= 0 { board[loc] = 0 };
        loc = loc + 2 * k;
        if loc / side == i1 - k && loc % side == j1 + k && loc != ix && loc >= 0 { board[loc] = 0};
        loc = loc + 2 * side * k;
        if loc / side == i1 + k && loc % side == j1 + k && loc != ix && loc < side*side { board[loc] = 0};
        loc = loc - 2 * k;
        if loc / side == i1 + k && loc % side == j1 - k && loc != ix && loc < side*side { board[loc] = 0};
    }
    Some(board)
}

fn tryplace(b : [i8,..side*side],ix:i8, nq: i8, mut score: u32) -> u32 {
    if nq == queens { return score + 1 }
    for ind in range(ix, side*side) {
        score = match place(b, ind) {
            Some(b2) => tryplace(b2, ind+1, nq+1, score),
            None => score
        };
    }
    return score
}

fn main() {
    let b : [i8, ..side*side] = [1,..side*side];
    let score = tryplace(b, 0, 0, 0);
    println!("{}", score)
}
<|endoftext|>


<commit_before>use libc;
use std;
use std::ptr;
use std::rc::Rc;
use std::str;

use handle::{self, RsvgHandle};
use load::rsvg_load_new_node;
use node::{node_new, Node, NodeType};
use property_bag::PropertyBag;
use structure::NodeSvg;
use text::NodeChars;
use tree::{RsvgTree, Tree};
use util::utf8_cstr;

/// A trait for processing a certain kind of XML subtree
///
/// In the "normal" state of processing, an `XmlHandler` may create an RsvgNode
/// for each SVG element it finds, and create NodeChars inside those nodes when it
/// encounters character data.
///
/// There may be other, special contexts for different subtrees, for example,
/// for the `<style>` element.
trait XmlHandler {
    /// Called when the XML parser sees the beginning of an element
    fn start_element(
        &self,
        parent: Option<&Rc<Node>>,
        handle: *mut RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) -> Box<XmlHandler>;

    /// Called when the XML parser sees the end of an element.
    fn end_element(&self, handle: *mut RsvgHandle, name: &str) -> Rc<Node>;

    /// Called when the XML parser sees character data or CDATA
    fn characters(&self, text: &str);

    fn get_node(&self) -> Rc<Node>;
}

struct NodeCreationContext {
    node: Option<Rc<Node>>,
}

impl XmlHandler for NodeCreationContext {
    fn start_element(
        &self,
        parent: Option<&Rc<Node>>,
        handle: *mut RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) -> Box<XmlHandler> {
        let mut defs = handle::get_defs(handle);
        let mut is_svg = false;

        let new_node = rsvg_load_new_node(name, parent, pbag, &mut defs, &mut is_svg);

        if let Some(parent) = parent {
            parent.add_child(&new_node);
        }

        new_node.set_atts(&new_node, handle, pbag);

        // The "svg" node is special; it will parse its style attributes
        // until the end, in standard_element_end().
        if new_node.get_type() != NodeType::Svg {
            new_node.parse_style_attributes(handle, name, pbag);
        }

        new_node.set_overridden_properties();

        Box::new(NodeCreationContext {
            node: Some(new_node),
        })
    }

    fn end_element(&self, handle: *mut RsvgHandle, _name: &str) -> Rc<Node> {
        let node = self.node.as_ref().unwrap().clone();

        // The "svg" node is special; it parses its style attributes
        // here, not during element creation.
        if node.get_type() == NodeType::Svg {
            node.with_impl(|svg: &NodeSvg| {
                svg.parse_style_attributes(&node, handle);
            });
        }

        node
    }

    fn characters(&self, text: &str) {
        let node = self.node.as_ref().unwrap();

        if text.len() == 0 {
            return;
        }

        if node.accept_chars() {
            let chars_node = if let Some(child) = node.find_last_chars_child() {
                child
            } else {
                let child = node_new(
                    NodeType::Chars,
                    Some(&node),
                    None,
                    None,
                    Box::new(NodeChars::new()),
                );
                node.add_child(&child);
                child
            };

            chars_node.with_impl(|chars: &NodeChars| {
                chars.append(text);
            });
        }
    }

    fn get_node(&self) -> Rc<Node> {
        self.node.as_ref().unwrap().clone()
    }
}

/// A concrete parsing context for a surrounding `element_name` and its XML event handlers
struct Context {
    element_name: String,
    handler: Box<XmlHandler>,
}

// A *const RsvgXmlState is just the type that we export to C
pub enum RsvgXmlState {}

/// Holds the state used for XML processing
///
/// These methods are called when an XML event is parsed out of the XML stream: `start_element`,
/// `end_element`, `characters`.
///
/// When an element starts, we push a corresponding `Context` into the `context_stack`.  Within
/// that context, all XML events will be forwarded to it, and processed in one of the `XmlHandler`
/// trait objects. Normally the context refers to a `NodeCreationContext` implementation which is
/// what creates normal graphical elements.
///
/// When we get to a `<style>` element, we push a `StyleContext`, which processes its contents
/// specially.
struct XmlState {
    tree: Option<Box<Tree>>,

    context_stack: Vec<Context>,
}

impl XmlState {
    fn new() -> XmlState {
        XmlState {
            tree: None,
            context_stack: Vec::new(),
        }
    }

    pub fn set_root(&mut self, root: &Rc<Node>) {
        if self.tree.is_some() {
            panic!("The tree root has already been set");
        }

        self.tree = Some(Box::new(Tree::new(root)));
    }

    pub fn steal_tree(&mut self) -> Option<Box<Tree>> {
        self.tree.take()
    }

    pub fn start_element(&mut self, handle: *mut RsvgHandle, name: &str, pbag: &PropertyBag) {
        let next_context = if let Some(top) = self.context_stack.last() {
            top.handler
                .start_element(Some(&top.handler.get_node()), handle, name, pbag)
        } else {
            let default_context = NodeCreationContext { node: None };

            default_context.start_element(None, handle, name, pbag)
        };

        let context = Context {
            element_name: name.to_string(),
            handler: next_context,
        };

        self.context_stack.push(context);
    }

    pub fn end_element(&mut self, handle: *mut RsvgHandle, name: &str) {
        if let Some(top) = self.context_stack.pop() {
            assert!(name == top.element_name);

            let node = top.handler.end_element(handle, name);

            if self.context_stack.is_empty() {
                self.set_root(&node);
            }
        } else {
            panic!("end_element: XML handler stack is empty!?");
        }
    }

    pub fn characters(&mut self, text: &str) {
        if let Some(top) = self.context_stack.last() {
            top.handler.characters(text);
        } else {
            panic!("characters: XML handler stack is empty!?");
        }
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_new() -> *mut RsvgXmlState {
    Box::into_raw(Box::new(XmlState::new())) as *mut RsvgXmlState
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_free(xml: *mut RsvgXmlState) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };
    unsafe {
        Box::from_raw(xml);
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_steal_tree(xml: *mut RsvgXmlState) -> *mut RsvgTree {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    if let Some(tree) = xml.steal_tree() {
        Box::into_raw(tree) as *mut RsvgTree
    } else {
        ptr::null_mut()
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_start_element(
    xml: *mut RsvgXmlState,
    handle: *mut RsvgHandle,
    name: *const libc::c_char,
    pbag: *const PropertyBag,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());
    let name = unsafe { utf8_cstr(name) };

    assert!(!pbag.is_null());
    let pbag = unsafe { &*pbag };

    xml.start_element(handle, name, pbag);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_end_element(
    xml: *mut RsvgXmlState,
    handle: *mut RsvgHandle,
    name: *const libc::c_char,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());
    let name = unsafe { utf8_cstr(name) };

    xml.end_element(handle, name);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_characters(
    xml: *mut RsvgXmlState,
    unterminated_text: *const libc::c_char,
    len: usize,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!unterminated_text.is_null());

    // libxml2 already validated the incoming string as UTF-8.  Note that
    // it is *not* nul-terminated; this is why we create a byte slice first.
    let bytes = unsafe { std::slice::from_raw_parts(unterminated_text as *const u8, len) };
    let utf8 = unsafe { str::from_utf8_unchecked(bytes) };

    xml.characters(utf8);
}
<commit_msg>NodeCreationContext: move the actual node creation to its own function<commit_after>use libc;
use std;
use std::ptr;
use std::rc::Rc;
use std::str;

use handle::{self, RsvgHandle};
use load::rsvg_load_new_node;
use node::{node_new, Node, NodeType};
use property_bag::PropertyBag;
use structure::NodeSvg;
use text::NodeChars;
use tree::{RsvgTree, Tree};
use util::utf8_cstr;

/// A trait for processing a certain kind of XML subtree
///
/// In the "normal" state of processing, an `XmlHandler` may create an RsvgNode
/// for each SVG element it finds, and create NodeChars inside those nodes when it
/// encounters character data.
///
/// There may be other, special contexts for different subtrees, for example,
/// for the `<style>` element.
trait XmlHandler {
    /// Called when the XML parser sees the beginning of an element
    fn start_element(
        &self,
        parent: Option<&Rc<Node>>,
        handle: *mut RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) -> Box<XmlHandler>;

    /// Called when the XML parser sees the end of an element.
    fn end_element(&self, handle: *mut RsvgHandle, name: &str) -> Rc<Node>;

    /// Called when the XML parser sees character data or CDATA
    fn characters(&self, text: &str);

    fn get_node(&self) -> Rc<Node>;
}

struct NodeCreationContext {
    node: Option<Rc<Node>>,
}

impl XmlHandler for NodeCreationContext {
    fn start_element(
        &self,
        parent: Option<&Rc<Node>>,
        handle: *mut RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) -> Box<XmlHandler> {
        let node = self.create_node(parent, handle, name, pbag);

        Box::new(NodeCreationContext { node: Some(node) })
    }

    fn end_element(&self, handle: *mut RsvgHandle, _name: &str) -> Rc<Node> {
        let node = self.node.as_ref().unwrap().clone();

        // The "svg" node is special; it parses its style attributes
        // here, not during element creation.
        if node.get_type() == NodeType::Svg {
            node.with_impl(|svg: &NodeSvg| {
                svg.parse_style_attributes(&node, handle);
            });
        }

        node
    }

    fn characters(&self, text: &str) {
        let node = self.node.as_ref().unwrap();

        if text.len() == 0 {
            return;
        }

        if node.accept_chars() {
            let chars_node = if let Some(child) = node.find_last_chars_child() {
                child
            } else {
                let child = node_new(
                    NodeType::Chars,
                    Some(&node),
                    None,
                    None,
                    Box::new(NodeChars::new()),
                );
                node.add_child(&child);
                child
            };

            chars_node.with_impl(|chars: &NodeChars| {
                chars.append(text);
            });
        }
    }

    fn get_node(&self) -> Rc<Node> {
        self.node.as_ref().unwrap().clone()
    }
}

impl NodeCreationContext {
    fn create_node(
        &self,
        parent: Option<&Rc<Node>>,
        handle: *const RsvgHandle,
        name: &str,
        pbag: &PropertyBag,
    ) -> Rc<Node> {
        let mut defs = handle::get_defs(handle);

        let new_node = rsvg_load_new_node(name, parent, pbag, &mut defs);

        if let Some(parent) = parent {
            parent.add_child(&new_node);
        }

        new_node.set_atts(&new_node, handle, pbag);

        // The "svg" node is special; it will parse its style attributes
        // until the end, in standard_element_end().
        if new_node.get_type() != NodeType::Svg {
            new_node.parse_style_attributes(handle, name, pbag);
        }

        new_node.set_overridden_properties();

        new_node
    }
}

/// A concrete parsing context for a surrounding `element_name` and its XML event handlers
struct Context {
    element_name: String,
    handler: Box<XmlHandler>,
}

// A *const RsvgXmlState is just the type that we export to C
pub enum RsvgXmlState {}

/// Holds the state used for XML processing
///
/// These methods are called when an XML event is parsed out of the XML stream: `start_element`,
/// `end_element`, `characters`.
///
/// When an element starts, we push a corresponding `Context` into the `context_stack`.  Within
/// that context, all XML events will be forwarded to it, and processed in one of the `XmlHandler`
/// trait objects. Normally the context refers to a `NodeCreationContext` implementation which is
/// what creates normal graphical elements.
///
/// When we get to a `<style>` element, we push a `StyleContext`, which processes its contents
/// specially.
struct XmlState {
    tree: Option<Box<Tree>>,

    context_stack: Vec<Context>,
}

impl XmlState {
    fn new() -> XmlState {
        XmlState {
            tree: None,
            context_stack: Vec::new(),
        }
    }

    pub fn set_root(&mut self, root: &Rc<Node>) {
        if self.tree.is_some() {
            panic!("The tree root has already been set");
        }

        self.tree = Some(Box::new(Tree::new(root)));
    }

    pub fn steal_tree(&mut self) -> Option<Box<Tree>> {
        self.tree.take()
    }

    pub fn start_element(&mut self, handle: *mut RsvgHandle, name: &str, pbag: &PropertyBag) {
        let next_context = if let Some(top) = self.context_stack.last() {
            top.handler
                .start_element(Some(&top.handler.get_node()), handle, name, pbag)
        } else {
            let default_context = NodeCreationContext { node: None };

            default_context.start_element(None, handle, name, pbag)
        };

        let context = Context {
            element_name: name.to_string(),
            handler: next_context,
        };

        self.context_stack.push(context);
    }

    pub fn end_element(&mut self, handle: *mut RsvgHandle, name: &str) {
        if let Some(top) = self.context_stack.pop() {
            assert!(name == top.element_name);

            let node = top.handler.end_element(handle, name);

            if self.context_stack.is_empty() {
                self.set_root(&node);
            }
        } else {
            panic!("end_element: XML handler stack is empty!?");
        }
    }

    pub fn characters(&mut self, text: &str) {
        if let Some(top) = self.context_stack.last() {
            top.handler.characters(text);
        } else {
            panic!("characters: XML handler stack is empty!?");
        }
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_new() -> *mut RsvgXmlState {
    Box::into_raw(Box::new(XmlState::new())) as *mut RsvgXmlState
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_free(xml: *mut RsvgXmlState) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };
    unsafe {
        Box::from_raw(xml);
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_steal_tree(xml: *mut RsvgXmlState) -> *mut RsvgTree {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    if let Some(tree) = xml.steal_tree() {
        Box::into_raw(tree) as *mut RsvgTree
    } else {
        ptr::null_mut()
    }
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_start_element(
    xml: *mut RsvgXmlState,
    handle: *mut RsvgHandle,
    name: *const libc::c_char,
    pbag: *const PropertyBag,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());
    let name = unsafe { utf8_cstr(name) };

    assert!(!pbag.is_null());
    let pbag = unsafe { &*pbag };

    xml.start_element(handle, name, pbag);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_end_element(
    xml: *mut RsvgXmlState,
    handle: *mut RsvgHandle,
    name: *const libc::c_char,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!name.is_null());
    let name = unsafe { utf8_cstr(name) };

    xml.end_element(handle, name);
}

#[no_mangle]
pub extern "C" fn rsvg_xml_state_characters(
    xml: *mut RsvgXmlState,
    unterminated_text: *const libc::c_char,
    len: usize,
) {
    assert!(!xml.is_null());
    let xml = unsafe { &mut *(xml as *mut XmlState) };

    assert!(!unterminated_text.is_null());

    // libxml2 already validated the incoming string as UTF-8.  Note that
    // it is *not* nul-terminated; this is why we create a byte slice first.
    let bytes = unsafe { std::slice::from_raw_parts(unterminated_text as *const u8, len) };
    let utf8 = unsafe { str::from_utf8_unchecked(bytes) };

    xml.characters(utf8);
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. 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.

//! A container for all the tabs being edited. Also functions as main dispatch for RPC.

use std::collections::BTreeMap;
use std::io::{self, Read, Write};
use std::path::{PathBuf, Path};
use std::fs::File;
use std::sync::{Arc, Mutex};
use serde_json::value::Value;

use xi_rope::rope::Rope;
use editor::Editor;
use rpc::{CoreCommand, EditCommand};
use styles::{Style, StyleMap};
use MainPeer;

/// ViewIdentifiers are the primary means of routing messages between xi-core and a client view.
pub type ViewIdentifier = String;

/// BufferIdentifiers uniquely identify open buffers.
type BufferIdentifier = String;

// TODO: proposed new name: something like "Core" or "CoreState" or "EditorState"? "Documents?"
pub struct Tabs<W: Write> {
    /// maps file names to buffer identifiers. If a client asks to open a file that is already
    /// open, we treat it as a request for a new view.
    open_files: BTreeMap<PathBuf, BufferIdentifier>,
    /// maps buffer identifiers (filenames) to editor instances
    buffers: BTreeMap<BufferIdentifier, Arc<Mutex<Editor<W>>>>,
    /// maps view identifiers to editor instances. All actions originate in a view; this lets us
    /// route messages correctly when multiple views share a buffer.
    views: BTreeMap<ViewIdentifier, BufferIdentifier>,
    id_counter: usize,
    kill_ring: Arc<Mutex<Rope>>,
    style_map: Arc<Mutex<StyleMap>>,
}

#[derive(Clone)]
pub struct TabCtx<W: Write> {
    kill_ring: Arc<Mutex<Rope>>,
    rpc_peer: MainPeer<W>,
    style_map: Arc<Mutex<StyleMap>>,
}

impl<W: Write + Send + 'static> Tabs<W> {
    pub fn new() -> Tabs<W> {
        Tabs {
            open_files: BTreeMap::new(),
            buffers: BTreeMap::new(),
            views: BTreeMap::new(),
            id_counter: 0,
            kill_ring: Arc::new(Mutex::new(Rope::from(""))),
            style_map: Arc::new(Mutex::new(StyleMap::new())),
        }
    }

    fn new_tab_ctx(&self, peer: &MainPeer<W>) -> TabCtx<W> {
        TabCtx {
            kill_ring: self.kill_ring.clone(),
            rpc_peer: peer.clone(),
            style_map: self.style_map.clone(),
        }
    }

    fn next_view_id(&mut self) -> ViewIdentifier {
        self.id_counter += 1;
        format!("view-id-{}", self.id_counter)
    }

    fn next_buffer_id(&mut self) -> BufferIdentifier {
        self.id_counter += 1;
        format!("buffer-id-{}", self.id_counter)
    }

    pub fn do_rpc(&mut self, cmd: CoreCommand, rpc_peer: &MainPeer<W>) -> Option<Value> {
        use rpc::CoreCommand::*;

        match cmd {
            CloseView { view_id } => {
                self.do_close_view(view_id); self.
                None
            },

            NewView { file_path } => Some(Value::String(self.do_new_view(rpc_peer, file_path))),
            Save { view_id, file_path } => self.do_save(view_id, file_path),
            Edit { view_id, edit_command } => self.do_edit(view_id, edit_command),
        }
    }

    /// Creates a new view and associates it with a buffer.
    ///
    /// This function always creates a new view and associates it with a buffer (which we access
    ///through an `Editor` instance). This buffer may be existing, or it may be created.
    ///
    ///A `new_view` request is handled differently depending on the `file_path` argument, and on
    ///application state. If `file_path` is given and a buffer associated with that file is already
    ///open, we create a new view into the existing buffer. If `file_path` is given and that file
    ///_isn't_ open, we load that file into a new buffer. If `file_path` is not given, we create a
    ///new empty buffer.
    fn do_new_view(&mut self, rpc_peer: &MainPeer<W>, file_path: Option<&str>) -> ViewIdentifier {
        // three code paths: new buffer, open file, and new view into existing buffer
        let view_id = self.next_view_id();
        if let Some(file_path) = file_path.map(PathBuf::from) {
            // TODO: here, we should eventually be adding views to the existing editor.
            // for the time being, we just create a new empty view.
            if self.open_files.contains_key(&file_path) {
                let buffer_id = self.next_buffer_id();
                self.new_empty_view(rpc_peer, &view_id, buffer_id);
                // let buffer_id = self.open_files.get(&file_path).unwrap().to_owned();
                //self.add_view(&view_id, buffer_id);
            } else {
                // not open: create new buffer_id and open file
                let buffer_id = self.next_buffer_id();
                self.open_files.insert(file_path.to_owned(), buffer_id.clone());
                self.new_view_with_file(rpc_peer, &view_id, buffer_id.clone(), &file_path);
                // above fn has two branches: set path after
                self.buffers.get(&buffer_id).unwrap().lock().unwrap().set_path(&file_path);
            }
        } else {
            // file_path was nil: create a new empty buffer.
            let buffer_id = self.next_buffer_id();
            self.new_empty_view(rpc_peer, &view_id, buffer_id);
        }
        view_id
    }

    fn do_close_view(&mut self, view_id: &str) {
        self.close_view(view_id);
    }

    fn new_empty_view(&mut self, rpc_peer: &MainPeer<W>,
                      view_id: &str, buffer_id: BufferIdentifier) {
        let editor = Editor::new(self.new_tab_ctx(rpc_peer), view_id);
        self.finalize_new_view(view_id, buffer_id, editor);
    }

    fn new_view_with_file(&mut self, rpc_peer: &MainPeer<W>, view_id: &str, buffer_id: BufferIdentifier, path: &Path) {
        match self.read_file(&path) {
            Ok(contents) => {
                let editor = Editor::with_text(self.new_tab_ctx(rpc_peer), view_id, contents);
                self.finalize_new_view(view_id, buffer_id, editor)
            }
            Err(err) => {
                // TODO: we should be reporting errors to the client
                // (if this is even an error? we treat opening a non-existent file as a new buffer,
                // but set the editor's path)
                print_err!("unable to read file: {}, error: {:?}", buffer_id, err);
               self.new_empty_view(rpc_peer, view_id, buffer_id);
            }
        }
    }

    /// Adds a new view to an existing editor instance.
    #[allow(unreachable_code, unused_variables, dead_code)]
    fn add_view(&mut self, view_id: &str, buffer_id: BufferIdentifier) {
        panic!("add_view should not currently be accessible");
        let editor = self.buffers.get(&buffer_id).expect("missing editor_id for view_id");
        self.views.insert(view_id.to_owned(), buffer_id);
        editor.lock().unwrap().add_view(view_id);
    }

    fn finalize_new_view(&mut self, view_id: &str, buffer_id: String, editor: Arc<Mutex<Editor<W>>>) {
        self.views.insert(view_id.to_owned(), buffer_id.clone());
        self.buffers.insert(buffer_id, editor.clone());
    }

    fn read_file<P: AsRef<Path>>(&self, path: P) -> io::Result<String> {
        let mut f = File::open(path)?;
        let mut s = String::new();
        f.read_to_string(&mut s)?;
        Ok(s)
    }

    fn close_view(&mut self, view_id: &str) {
        let buf_id = self.views.remove(view_id).expect("missing buffer id when closing view");
        let has_views = {
            let editor = self.buffers.get(&buf_id).expect("missing editor when closing view");
            editor.lock().unwrap().remove_view(view_id);
            editor.lock().unwrap().has_views()
        };

        if !has_views {
            self.buffers.remove(&buf_id);
        }
    }

    fn do_save(&mut self, view_id: &str, file_path: &str) -> Option<Value> {
        let buffer_id = self.views.get(view_id)
            .expect(&format!("missing buffer id for view {}", view_id));
        let editor = self.buffers.get(buffer_id)
            .expect(&format!("missing editor for buffer {}", buffer_id));
        let file_path = PathBuf::from(file_path);

        // if this is a new path for an existing file, we have a bit of housekeeping to do:
        if let Some(prev_path) = editor.lock().unwrap().get_path() {
            if prev_path != file_path {
                self.open_files.remove(prev_path);
            }
        }
        editor.lock().unwrap().do_save(&file_path);
        self.open_files.insert(file_path, buffer_id.to_owned());
        None
    }

    fn do_edit(&mut self, view_id: &str, cmd: EditCommand) -> Option<Value> {
        let buffer_id = self.views.get(view_id)
            .expect(&format!("missing buffer id for view {}", view_id));
        if let Some(editor) = self.buffers.get(buffer_id) {
            Editor::do_rpc(editor, view_id, cmd)
        } else {
            print_err!("buffer not found: {}, for view {}", buffer_id, view_id);
            None
        }
    }

    pub fn handle_idle(&self) {
        for editor in self.buffers.values() {
            editor.lock().unwrap().render();
        }
    }
}

impl<W: Write> TabCtx<W> {
    pub fn update_view(&self, view_id: &str, update: &Value) {
        self.rpc_peer.send_rpc_notification("update",
            &json!({
                "view_id": view_id,
                "update": update,
            }));
    }

    pub fn scroll_to(&self, view_id: &str, line: usize, col: usize) {
        self.rpc_peer.send_rpc_notification("scroll_to",
            &json!({
                "view_id": view_id,
                "line": line,
                "col": col,
            }));
    }

    pub fn get_kill_ring(&self) -> Rope {
        self.kill_ring.lock().unwrap().clone()
    }

    pub fn set_kill_ring(&self, val: Rope) {
        let mut kill_ring = self.kill_ring.lock().unwrap();
        *kill_ring = val;
    }

    pub fn alert(&self, msg: &str) {
        self.rpc_peer.send_rpc_notification("alert",
            &json!({
                "msg": msg,
            }));
    }

    // Get the index for a given style. If the style is not in the existing
    // style map, then issues a def_style request to the front end. Intended
    // to be reasonably efficient, but ideally callers would do their own
    // indexing.
    pub fn get_style_id(&self, style: &Style) -> usize {
        let mut style_map = self.style_map.lock().unwrap();
        if let Some(ix) = style_map.lookup(style) {
            return ix;
        }
        let ix = style_map.add(style);
        self.rpc_peer.send_rpc_notification("def_style", &style.to_json(ix));
        ix
    }
}
<commit_msg>Human error<commit_after>// Copyright 2016 Google Inc. 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.

//! A container for all the tabs being edited. Also functions as main dispatch for RPC.

use std::collections::BTreeMap;
use std::io::{self, Read, Write};
use std::path::{PathBuf, Path};
use std::fs::File;
use std::sync::{Arc, Mutex};
use serde_json::value::Value;

use xi_rope::rope::Rope;
use editor::Editor;
use rpc::{CoreCommand, EditCommand};
use styles::{Style, StyleMap};
use MainPeer;

/// ViewIdentifiers are the primary means of routing messages between xi-core and a client view.
pub type ViewIdentifier = String;

/// BufferIdentifiers uniquely identify open buffers.
type BufferIdentifier = String;

// TODO: proposed new name: something like "Core" or "CoreState" or "EditorState"? "Documents?"
pub struct Tabs<W: Write> {
    /// maps file names to buffer identifiers. If a client asks to open a file that is already
    /// open, we treat it as a request for a new view.
    open_files: BTreeMap<PathBuf, BufferIdentifier>,
    /// maps buffer identifiers (filenames) to editor instances
    buffers: BTreeMap<BufferIdentifier, Arc<Mutex<Editor<W>>>>,
    /// maps view identifiers to editor instances. All actions originate in a view; this lets us
    /// route messages correctly when multiple views share a buffer.
    views: BTreeMap<ViewIdentifier, BufferIdentifier>,
    id_counter: usize,
    kill_ring: Arc<Mutex<Rope>>,
    style_map: Arc<Mutex<StyleMap>>,
}

#[derive(Clone)]
pub struct TabCtx<W: Write> {
    kill_ring: Arc<Mutex<Rope>>,
    rpc_peer: MainPeer<W>,
    style_map: Arc<Mutex<StyleMap>>,
}

impl<W: Write + Send + 'static> Tabs<W> {
    pub fn new() -> Tabs<W> {
        Tabs {
            open_files: BTreeMap::new(),
            buffers: BTreeMap::new(),
            views: BTreeMap::new(),
            id_counter: 0,
            kill_ring: Arc::new(Mutex::new(Rope::from(""))),
            style_map: Arc::new(Mutex::new(StyleMap::new())),
        }
    }

    fn new_tab_ctx(&self, peer: &MainPeer<W>) -> TabCtx<W> {
        TabCtx {
            kill_ring: self.kill_ring.clone(),
            rpc_peer: peer.clone(),
            style_map: self.style_map.clone(),
        }
    }

    fn next_view_id(&mut self) -> ViewIdentifier {
        self.id_counter += 1;
        format!("view-id-{}", self.id_counter)
    }

    fn next_buffer_id(&mut self) -> BufferIdentifier {
        self.id_counter += 1;
        format!("buffer-id-{}", self.id_counter)
    }

    pub fn do_rpc(&mut self, cmd: CoreCommand, rpc_peer: &MainPeer<W>) -> Option<Value> {
        use rpc::CoreCommand::*;

        match cmd {
            CloseView { view_id } => {
                self.do_close_view(view_id);
                None
            },

            NewView { file_path } => Some(Value::String(self.do_new_view(rpc_peer, file_path))),
            Save { view_id, file_path } => self.do_save(view_id, file_path),
            Edit { view_id, edit_command } => self.do_edit(view_id, edit_command),
        }
    }

    /// Creates a new view and associates it with a buffer.
    ///
    /// This function always creates a new view and associates it with a buffer (which we access
    ///through an `Editor` instance). This buffer may be existing, or it may be created.
    ///
    ///A `new_view` request is handled differently depending on the `file_path` argument, and on
    ///application state. If `file_path` is given and a buffer associated with that file is already
    ///open, we create a new view into the existing buffer. If `file_path` is given and that file
    ///_isn't_ open, we load that file into a new buffer. If `file_path` is not given, we create a
    ///new empty buffer.
    fn do_new_view(&mut self, rpc_peer: &MainPeer<W>, file_path: Option<&str>) -> ViewIdentifier {
        // three code paths: new buffer, open file, and new view into existing buffer
        let view_id = self.next_view_id();
        if let Some(file_path) = file_path.map(PathBuf::from) {
            // TODO: here, we should eventually be adding views to the existing editor.
            // for the time being, we just create a new empty view.
            if self.open_files.contains_key(&file_path) {
                let buffer_id = self.next_buffer_id();
                self.new_empty_view(rpc_peer, &view_id, buffer_id);
                // let buffer_id = self.open_files.get(&file_path).unwrap().to_owned();
                //self.add_view(&view_id, buffer_id);
            } else {
                // not open: create new buffer_id and open file
                let buffer_id = self.next_buffer_id();
                self.open_files.insert(file_path.to_owned(), buffer_id.clone());
                self.new_view_with_file(rpc_peer, &view_id, buffer_id.clone(), &file_path);
                // above fn has two branches: set path after
                self.buffers.get(&buffer_id).unwrap().lock().unwrap().set_path(&file_path);
            }
        } else {
            // file_path was nil: create a new empty buffer.
            let buffer_id = self.next_buffer_id();
            self.new_empty_view(rpc_peer, &view_id, buffer_id);
        }
        view_id
    }

    fn do_close_view(&mut self, view_id: &str) {
        self.close_view(view_id);
    }

    fn new_empty_view(&mut self, rpc_peer: &MainPeer<W>,
                      view_id: &str, buffer_id: BufferIdentifier) {
        let editor = Editor::new(self.new_tab_ctx(rpc_peer), view_id);
        self.finalize_new_view(view_id, buffer_id, editor);
    }

    fn new_view_with_file(&mut self, rpc_peer: &MainPeer<W>, view_id: &str, buffer_id: BufferIdentifier, path: &Path) {
        match self.read_file(&path) {
            Ok(contents) => {
                let editor = Editor::with_text(self.new_tab_ctx(rpc_peer), view_id, contents);
                self.finalize_new_view(view_id, buffer_id, editor)
            }
            Err(err) => {
                // TODO: we should be reporting errors to the client
                // (if this is even an error? we treat opening a non-existent file as a new buffer,
                // but set the editor's path)
                print_err!("unable to read file: {}, error: {:?}", buffer_id, err);
               self.new_empty_view(rpc_peer, view_id, buffer_id);
            }
        }
    }

    /// Adds a new view to an existing editor instance.
    #[allow(unreachable_code, unused_variables, dead_code)]
    fn add_view(&mut self, view_id: &str, buffer_id: BufferIdentifier) {
        panic!("add_view should not currently be accessible");
        let editor = self.buffers.get(&buffer_id).expect("missing editor_id for view_id");
        self.views.insert(view_id.to_owned(), buffer_id);
        editor.lock().unwrap().add_view(view_id);
    }

    fn finalize_new_view(&mut self, view_id: &str, buffer_id: String, editor: Arc<Mutex<Editor<W>>>) {
        self.views.insert(view_id.to_owned(), buffer_id.clone());
        self.buffers.insert(buffer_id, editor.clone());
    }

    fn read_file<P: AsRef<Path>>(&self, path: P) -> io::Result<String> {
        let mut f = File::open(path)?;
        let mut s = String::new();
        f.read_to_string(&mut s)?;
        Ok(s)
    }

    fn close_view(&mut self, view_id: &str) {
        let buf_id = self.views.remove(view_id).expect("missing buffer id when closing view");
        let has_views = {
            let editor = self.buffers.get(&buf_id).expect("missing editor when closing view");
            editor.lock().unwrap().remove_view(view_id);
            editor.lock().unwrap().has_views()
        };

        if !has_views {
            self.buffers.remove(&buf_id);
        }
    }

    fn do_save(&mut self, view_id: &str, file_path: &str) -> Option<Value> {
        let buffer_id = self.views.get(view_id)
            .expect(&format!("missing buffer id for view {}", view_id));
        let editor = self.buffers.get(buffer_id)
            .expect(&format!("missing editor for buffer {}", buffer_id));
        let file_path = PathBuf::from(file_path);

        // if this is a new path for an existing file, we have a bit of housekeeping to do:
        if let Some(prev_path) = editor.lock().unwrap().get_path() {
            if prev_path != file_path {
                self.open_files.remove(prev_path);
            }
        }
        editor.lock().unwrap().do_save(&file_path);
        self.open_files.insert(file_path, buffer_id.to_owned());
        None
    }

    fn do_edit(&mut self, view_id: &str, cmd: EditCommand) -> Option<Value> {
        let buffer_id = self.views.get(view_id)
            .expect(&format!("missing buffer id for view {}", view_id));
        if let Some(editor) = self.buffers.get(buffer_id) {
            Editor::do_rpc(editor, view_id, cmd)
        } else {
            print_err!("buffer not found: {}, for view {}", buffer_id, view_id);
            None
        }
    }

    pub fn handle_idle(&self) {
        for editor in self.buffers.values() {
            editor.lock().unwrap().render();
        }
    }
}

impl<W: Write> TabCtx<W> {
    pub fn update_view(&self, view_id: &str, update: &Value) {
        self.rpc_peer.send_rpc_notification("update",
            &json!({
                "view_id": view_id,
                "update": update,
            }));
    }

    pub fn scroll_to(&self, view_id: &str, line: usize, col: usize) {
        self.rpc_peer.send_rpc_notification("scroll_to",
            &json!({
                "view_id": view_id,
                "line": line,
                "col": col,
            }));
    }

    pub fn get_kill_ring(&self) -> Rope {
        self.kill_ring.lock().unwrap().clone()
    }

    pub fn set_kill_ring(&self, val: Rope) {
        let mut kill_ring = self.kill_ring.lock().unwrap();
        *kill_ring = val;
    }

    pub fn alert(&self, msg: &str) {
        self.rpc_peer.send_rpc_notification("alert",
            &json!({
                "msg": msg,
            }));
    }

    // Get the index for a given style. If the style is not in the existing
    // style map, then issues a def_style request to the front end. Intended
    // to be reasonably efficient, but ideally callers would do their own
    // indexing.
    pub fn get_style_id(&self, style: &Style) -> usize {
        let mut style_map = self.style_map.lock().unwrap();
        if let Some(ix) = style_map.lookup(style) {
            return ix;
        }
        let ix = style_map.add(style);
        self.rpc_peer.send_rpc_notification("def_style", &style.to_json(ix));
        ix
    }
}
<|endoftext|>


<commit_before>use hyper::header::StrictTransportSecurity;
use iron::middleware::AfterMiddleware;
use iron::modifiers;
use iron::{IronError, IronResult, Request, Response, Set};

header! { (ContentSecurityPolicy, "Content-Security-Policy") => [String] }
header! { (XContentSecurityPolicy, "X-Content-Security-Policy") => [String] }
header! { (XContentTypeOptions, "X-Content-Type-Options") => [String] }
header! { (XXSSProtection, "X-XSS-Protection") => [String] }
header! { (XFrameOptions, "X-Frame-Options") => [String] }

/// Middleware that sets common headers.
pub struct SecurityHeaders;
impl SecurityHeaders {
    fn set_headers(&self, res: &mut Response) {
        // Specify a tight content security policy. We need to be able to POST
        // redirect anywhere, and run our own inline scripts.
        let csp = vec![
            "sandbox allow-scripts allow-forms",
            "default-src 'none'",
            "script-src 'self'",
            "style-src 'self'",
            "form-action *",
        ].join("; ");
        res.set_mut((modifiers::Header(StrictTransportSecurity::excluding_subdomains(31536000u64)),
                     modifiers::Header(ContentSecurityPolicy(csp.clone())),
                     modifiers::Header(XContentSecurityPolicy(csp)),
                     modifiers::Header(XContentTypeOptions("nosniff".to_string())),
                     modifiers::Header(XXSSProtection("1; mode=block".to_string())),
                     modifiers::Header(XFrameOptions("DENY".to_string()))));
    }
}
impl AfterMiddleware for SecurityHeaders {
    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
        self.set_headers(&mut res);
        Ok(res)
    }
    fn catch(&self, _: &mut Request, mut err: IronError) -> IronResult<Response> {
        self.set_headers(&mut err.response);
        Err(err)
    }
}
<commit_msg>Refactor middleware::SecurityHeaders::set_headers<commit_after>use hyper::header::StrictTransportSecurity;
use iron::middleware::AfterMiddleware;
use iron::modifiers;
use iron::{IronError, IronResult, Request, Response, Set};

header! { (ContentSecurityPolicy, "Content-Security-Policy") => [String] }
header! { (XContentSecurityPolicy, "X-Content-Security-Policy") => [String] }
header! { (XContentTypeOptions, "X-Content-Type-Options") => [String] }
header! { (XXSSProtection, "X-XSS-Protection") => [String] }
header! { (XFrameOptions, "X-Frame-Options") => [String] }

/// Middleware that enforces common security headers on all outgoing responses.
pub struct SecurityHeaders;

impl AfterMiddleware for SecurityHeaders {
    fn after(&self, _: &mut Request, mut res: Response) -> IronResult<Response> {
        set_headers(&mut res);
        Ok(res)
    }

    fn catch(&self, _: &mut Request, mut err: IronError) -> IronResult<Response> {
        set_headers(&mut err.response);
        Err(err)
    }
}

/// Mutate an `iron::Response` to set common security headers.
fn set_headers(res: &mut Response) {
    // Specify a tight content security policy. We need to be able to POST
    // redirect anywhere, and run our own inline scripts.
    let csp = vec![
        "sandbox allow-scripts allow-forms",
        "default-src 'none'",
        "script-src 'self'",
        "style-src 'self'",
        "form-action *",
    ].join("; ");

    res.set_mut((modifiers::Header(StrictTransportSecurity::excluding_subdomains(31536000u64)),
                 modifiers::Header(ContentSecurityPolicy(csp.clone())),
                 modifiers::Header(XContentSecurityPolicy(csp)),
                 modifiers::Header(XContentTypeOptions("nosniff".to_string())),
                 modifiers::Header(XXSSProtection("1; mode=block".to_string())),
                 modifiers::Header(XFrameOptions("DENY".to_string()))));
}

#[cfg(test)]
mod tests {
    use iron::Response;
    use super::set_headers;

    #[test]
    fn sets_expected_headers() {
        let mut res = Response::new();
        set_headers(&mut res);

        assert!(res.headers.get_raw("Strict-Transport-Security").is_some());
        assert!(res.headers.get_raw("Content-Security-Policy").is_some());
        assert!(res.headers.get_raw("X-Content-Security-Policy").is_some());
        assert!(res.headers.get_raw("X-Content-Type-Options").is_some());
        assert!(res.headers.get_raw("X-XSS-Protection").is_some());
        assert!(res.headers.get_raw("X-Frame-Options").is_some());
    }
}
<|endoftext|>


<commit_before>#![allow(non_snake_case)]

/// This file contains various traits/functions for interacting with Cocoa/objc classes which
/// are not available in the cocoa/objc crates. They should probably be migrated to them soon.

use cocoa::base::{class, id, BOOL};
use cocoa::foundation::NSUInteger;
use std::any::Any;

pub trait NSArray {
    unsafe fn arrayWithArray(array: id) -> Self where Self: Sized + Any {
        msg_send![class("NSArray"), arrayWithArray:array]
    }
    unsafe fn arrayWithObject(object: id) -> Self where Self: Sized + Any {
        msg_send![class("NSArray"), arrayWithObject:object]
    }
    unsafe fn arrayWithObjects_count(objects: *mut id, count: NSUInteger) -> Self where Self: Sized + Any {
        msg_send![class("NSArray"), arrayWithObjects:objects count:count]
    }

    unsafe fn containsObject(self, anObject: id) -> BOOL;
    unsafe fn count(self) -> NSUInteger;
    unsafe fn firstObject(self) -> id;
    unsafe fn lastObject(self) -> id;
    unsafe fn objectAtIndex(self, index: NSUInteger) -> id;
    unsafe fn indexOfObject(self, anObject: id) -> NSUInteger;
    unsafe fn indexOfObjectIdenticalTo(self, anObject: id) -> NSUInteger;
}

impl NSArray for id {
    unsafe fn containsObject(self, anObject: id) -> BOOL {
        msg_send![self, containsObject:anObject]
    }

    unsafe fn count(self) -> NSUInteger {
        msg_send![self, count]
    }

    unsafe fn firstObject(self) -> id {
        msg_send![self, firstObject]
    }

    unsafe fn lastObject(self) -> id {
        msg_send![self, lastObject]
    }

    unsafe fn objectAtIndex(self, index: NSUInteger) -> id {
        msg_send![self, objectAtIndex:index]
    }

    unsafe fn indexOfObject(self, anObject: id) -> NSUInteger {
        msg_send![self, indexOfObject:anObject]
    }

    unsafe fn indexOfObjectIdenticalTo(self, anObject: id) -> NSUInteger {
        msg_send![self, indexOfObjectIdenticalTo:anObject]
    }
}

pub trait NSDictionary {

}
<commit_msg>Allow(dead_code) because objc macros are generating dead code :-(<commit_after>#![allow(dead_code, non_snake_case)]

/// This file contains various traits/functions for interacting with Cocoa/objc classes which
/// are not available in the cocoa/objc crates. They should probably be migrated to them soon.

use cocoa::base::{class, id, BOOL};
use cocoa::foundation::NSUInteger;
use std::any::Any;

pub trait NSArray {
    unsafe fn arrayWithArray(array: id) -> Self where Self: Sized + Any {
        msg_send![class("NSArray"), arrayWithArray:array]
    }
    unsafe fn arrayWithObject(object: id) -> Self where Self: Sized + Any {
        msg_send![class("NSArray"), arrayWithObject:object]
    }
    unsafe fn arrayWithObjects_count(objects: *mut id, count: NSUInteger) -> Self where Self: Sized + Any {
        msg_send![class("NSArray"), arrayWithObjects:objects count:count]
    }

    unsafe fn containsObject(self, anObject: id) -> BOOL;
    unsafe fn count(self) -> NSUInteger;
    unsafe fn firstObject(self) -> id;
    unsafe fn lastObject(self) -> id;
    unsafe fn objectAtIndex(self, index: NSUInteger) -> id;
    unsafe fn indexOfObject(self, anObject: id) -> NSUInteger;
    unsafe fn indexOfObjectIdenticalTo(self, anObject: id) -> NSUInteger;
}

impl NSArray for id {
    unsafe fn containsObject(self, anObject: id) -> BOOL {
        msg_send![self, containsObject:anObject]
    }

    unsafe fn count(self) -> NSUInteger {
        msg_send![self, count]
    }

    unsafe fn firstObject(self) -> id {
        msg_send![self, firstObject]
    }

    unsafe fn lastObject(self) -> id {
        msg_send![self, lastObject]
    }

    unsafe fn objectAtIndex(self, index: NSUInteger) -> id {
        msg_send![self, objectAtIndex:index]
    }

    unsafe fn indexOfObject(self, anObject: id) -> NSUInteger {
        msg_send![self, indexOfObject:anObject]
    }

    unsafe fn indexOfObjectIdenticalTo(self, anObject: id) -> NSUInteger {
        msg_send![self, indexOfObjectIdenticalTo:anObject]
    }
}

pub trait NSDictionary {

}
<|endoftext|>


<commit_before>/// Breadth First Search
pub mod bfs {

    use hex2d::Coordinate;
    use hex2d;

    use std::hash;
    use std::collections::VecDeque;
    use std::collections::HashMap;
    use std::collections::hash_map::Entry::{Occupied,Vacant};

    struct Visited<I = i32>
        where I : hex2d::Integer
        {
            prev : Coordinate<I>,
            dist : u32,
        }

    /// Breadth First Search
    ///
    /// Use BFS to find closest (in walk steps) Coordinates that satisfy `is_dest` and can be
    /// reached with a walk through coordinates for which `can_pass` returns true.
    pub struct Traverser<FCanPass, FIsDest, I = i32> where
        I : hex2d::Integer,
        I : hash::Hash,
        FCanPass : Fn(Coordinate<I>) -> bool,
        FIsDest : Fn(Coordinate<I>) -> bool
    {
        visited : HashMap<Coordinate<I>, Visited<I>>,
        to_traverse : VecDeque<Coordinate<I>>,
        can_pass : FCanPass,
        is_dest : FIsDest,
        start : Coordinate<I>,
    }

    impl<FCanPass, FIsDest, I> Traverser<FCanPass, FIsDest, I> where
        I : hex2d::Integer,
        I : hash::Hash,
        FCanPass : Fn(Coordinate<I>) -> bool,
        FIsDest : Fn(Coordinate<I>) -> bool
    {

        /// Create a Traverser instance with initial conditions
        pub fn new(can_pass : FCanPass, is_dest : FIsDest, start: Coordinate<I>) -> Traverser<FCanPass, FIsDest, I> {
            let mut to_traverse = VecDeque::new();
            to_traverse.push_back(start);

            let mut visited = HashMap::new();
            visited.insert(start, Visited{prev: start, dist: 0});

            Traverser {
                visited: visited,
                to_traverse: to_traverse,
                can_pass: can_pass,
                is_dest: is_dest,
                start: start,
            }
        }

        /// Find next closest coordinate.
        ///
        /// Can be called multiple times, each time returning next coordinate
        pub fn find(&mut self) -> Option<Coordinate<I>> {

            loop {
                let pos = match self.to_traverse.pop_front() {
                    None => return None,
                    Some(coord) => coord,
                };

                // Traverse before returning, so `find` can be call subsequently
                // for more than just first answer
                if (self.can_pass)(pos) {

                    let &Visited{dist, ..} = self.visited.get(&pos).expect("BFS: Should have been visited already");

                    let dist = dist + 1;

                    for &npos in pos.neighbors().iter() {
                        match self.visited.entry(npos) {
                            Occupied(_) => { /* already visited */ }
                            Vacant(entry) => {
                                entry.insert(Visited{prev: pos, dist: dist});
                                self.to_traverse.push_back(npos);
                            }
                        }
                    }
                }

                if (self.is_dest)(pos) {
                    return Some(pos);
                }
            }
        }

        /// Return neighbor Coordinate to `pos` that is one step closer to
        /// `start` from initial conditions.
        ///
        /// Useful for finding whole path to a Coordinate returned by `find`.
        ///
        /// Returns `None` for Coordinates that were not yet visited.
        /// Returns `start` for `start` (from initial conditions)
        pub fn backtrace(&self, pos : Coordinate<I>) -> Option<Coordinate<I>> {
            self.visited.get(&pos).map(|entry| entry.prev)
        }

        /// Perform a recursive `backtrace` walk to find a neighbor of `start` that leads to the
        /// Coordinate returned by `find()`.
        ///
        /// Returns `None` for Coordinates that were not yet visited.
        /// Returns `start` for `start` (from initial conditions)
        pub fn backtrace_last(&self, mut pos : Coordinate<I>) -> Option<Coordinate<I>> {
            loop {
                pos = match self.visited.get(&pos) {
                    None => return None,
                    Some(entry) => {
                        if entry.prev == self.start {
                            return Some(pos);
                        } else {
                            entry.prev
                        }
                    }
                }
            }
        }
    }
}

/// Very tricky, but (hopefully) good enough, recursive LoS algorithm
pub mod los {
    use hex2d;
    use hex2d::Angle::{Left,Right};

    use hex2d::Direction;
    use hex2d::Coordinate;

    fn los_rec<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        pos : Coordinate<I>,
        start_dir : Direction,
        main_dir : Direction,
        dir : Option<Direction>,
        pdir : Option<Direction>,
    ) where
        I : hex2d::Integer,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {

            let mut light = light;
            let opaq = opaqueness(pos);

            if opaq >= light {
                return;
            } else {
                light = light - opaq;
            }

            visible(pos, light);

            let neighbors = match (dir, pdir) {
                (Some(dir), Some(pdir)) => {
                    if dir == pdir {
                        vec!(dir)
                    } else {
                        vec!(dir, pdir)
                    }
                },
                (Some(dir), None) => {
                    if main_dir == dir {
                        vec!(dir, dir + Left, dir + Right)
                    } else {
                        vec!(dir, main_dir)
                    }
                },
                _ => {
                    vec!(main_dir, main_dir + Left, main_dir + Right)
                }
            };

            for &d in neighbors.iter() {
                let npos = pos + d;
                match dir {
                    Some(_) => los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, npos, start_dir, d, Some(d), dir),
                    None => los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, npos, start_dir, main_dir, Some(d), dir),
                }
            }
        }

    /// Starting from `pos` in direction `dir`, call `visible` for each visible Coordinate.
    ///
    /// Use `light` as starting range of the LoS. For each visible Coordinate, the value returned
    /// by `opaqueness` will be subtracted from `light` to check if the LoS should finish due to
    /// "lack of visibility". `opaqueness` should typically return 1 for fully transparent
    /// Coordinates, and anything bigger than initial `light` for fully opaque Coordinates.
    pub fn los<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        pos : Coordinate<I>,
        dirs : &[Direction],
    ) where
        I : hex2d::Integer,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {
            for dir in dirs.iter() {
                los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, pos, *dir, *dir, None, None);
            }
        }
}

/// Combination of tricky Los with straight line checking
pub mod los2 {
    use hex2d;
    use hex2d::Angle::{Left, Right, Forward};
    use hex2d::Direction;
    use hex2d::Coordinate;
    use num::{FromPrimitive};
    use std::collections::HashSet;
    use std::hash;
    use std::ops::{Add};

    fn los_rec<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        start : Coordinate<I>,
        pos : Coordinate<I>,
        dir : Direction,
        visited : &mut HashSet<Coordinate<I>>,
    ) where
        I : hex2d::Integer,
        I : hash::Hash+Eq,
        for <'a> &'a I: Add<&'a I, Output = I>,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {
            if visited.contains(&pos) {
                return;
            } else {
                visited.insert(pos);
            }

            let mut opaq_sum1 : I = FromPrimitive::from_i8(0).unwrap();
            let mut last1 = start;

            let mut opaq_sum2 : I = FromPrimitive::from_i8(0).unwrap();
            let mut last2 = start;

            for &(c1, c2) in start.line_to_with_edge_detection(pos).iter() {
                if opaq_sum1 < light {
                    let opaq1 = opaqueness(c1);
                    opaq_sum1 = opaq_sum1 + opaq1;
                    last1 = c1;
                }

                if opaq_sum2 < light {
                    let opaq2 = opaqueness(c2);
                    opaq_sum2 = opaq_sum2 + opaq2;
                    last2 = c2;
                }
            };

            if last1 == pos || last2 == pos {
                visible(pos, light - light);
            } else {
                return;
            }

            let neighbors = vec!(Forward, Left, Right);

            for &a in neighbors.iter() {
                let npos = pos + (dir + a);
                los_rec::<FOpaqueness, FVisible, I>(
                    opaqueness, visible, light, start, npos, dir, visited
                    );
            }
        }

    /// Starting from `pos` in direction `dir`, call `visible` for each visible Coordinate.
    ///
    /// Use `light` as starting range of the LoS. For each visible Coordinate, the value returned
    /// by `opaqueness` will be subtracted from `light` to check if the LoS should finish due to
    /// "lack of visibility". `opaqueness` should typically return 1 for fully transparent
    /// Coordinates, and anything bigger than initial `light` for fully opaque Coordinates.
    pub fn los<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        pos : Coordinate<I>,
        dirs : &[Direction],
    ) where
        I : hex2d::Integer,
        I : hash::Hash,
        for <'a> &'a I: Add<&'a I, Output = I>,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {
            for dir in dirs.iter() {
                let mut visited = HashSet::new();
                los_rec::<FOpaqueness, FVisible, I>(
                    opaqueness, visible, light, pos, pos, *dir, &mut visited
                    );
            }
        }
}
<commit_msg>Better LoS.<commit_after>/// Breadth First Search
pub mod bfs {

    use hex2d::Coordinate;
    use hex2d;

    use std::hash;
    use std::collections::VecDeque;
    use std::collections::HashMap;
    use std::collections::hash_map::Entry::{Occupied,Vacant};

    struct Visited<I = i32>
        where I : hex2d::Integer
        {
            prev : Coordinate<I>,
            dist : u32,
        }

    /// Breadth First Search
    ///
    /// Use BFS to find closest (in walk steps) Coordinates that satisfy `is_dest` and can be
    /// reached with a walk through coordinates for which `can_pass` returns true.
    pub struct Traverser<FCanPass, FIsDest, I = i32> where
        I : hex2d::Integer,
        I : hash::Hash,
        FCanPass : Fn(Coordinate<I>) -> bool,
        FIsDest : Fn(Coordinate<I>) -> bool
    {
        visited : HashMap<Coordinate<I>, Visited<I>>,
        to_traverse : VecDeque<Coordinate<I>>,
        can_pass : FCanPass,
        is_dest : FIsDest,
        start : Coordinate<I>,
    }

    impl<FCanPass, FIsDest, I> Traverser<FCanPass, FIsDest, I> where
        I : hex2d::Integer,
        I : hash::Hash,
        FCanPass : Fn(Coordinate<I>) -> bool,
        FIsDest : Fn(Coordinate<I>) -> bool
    {

        /// Create a Traverser instance with initial conditions
        pub fn new(can_pass : FCanPass, is_dest : FIsDest, start: Coordinate<I>) -> Traverser<FCanPass, FIsDest, I> {
            let mut to_traverse = VecDeque::new();
            to_traverse.push_back(start);

            let mut visited = HashMap::new();
            visited.insert(start, Visited{prev: start, dist: 0});

            Traverser {
                visited: visited,
                to_traverse: to_traverse,
                can_pass: can_pass,
                is_dest: is_dest,
                start: start,
            }
        }

        /// Find next closest coordinate.
        ///
        /// Can be called multiple times, each time returning next coordinate
        pub fn find(&mut self) -> Option<Coordinate<I>> {

            loop {
                let pos = match self.to_traverse.pop_front() {
                    None => return None,
                    Some(coord) => coord,
                };

                // Traverse before returning, so `find` can be call subsequently
                // for more than just first answer
                if (self.can_pass)(pos) {

                    let &Visited{dist, ..} = self.visited.get(&pos).expect("BFS: Should have been visited already");

                    let dist = dist + 1;

                    for &npos in pos.neighbors().iter() {
                        match self.visited.entry(npos) {
                            Occupied(_) => { /* already visited */ }
                            Vacant(entry) => {
                                entry.insert(Visited{prev: pos, dist: dist});
                                self.to_traverse.push_back(npos);
                            }
                        }
                    }
                }

                if (self.is_dest)(pos) {
                    return Some(pos);
                }
            }
        }

        /// Return neighbor Coordinate to `pos` that is one step closer to
        /// `start` from initial conditions.
        ///
        /// Useful for finding whole path to a Coordinate returned by `find`.
        ///
        /// Returns `None` for Coordinates that were not yet visited.
        /// Returns `start` for `start` (from initial conditions)
        pub fn backtrace(&self, pos : Coordinate<I>) -> Option<Coordinate<I>> {
            self.visited.get(&pos).map(|entry| entry.prev)
        }

        /// Perform a recursive `backtrace` walk to find a neighbor of `start` that leads to the
        /// Coordinate returned by `find()`.
        ///
        /// Returns `None` for Coordinates that were not yet visited.
        /// Returns `start` for `start` (from initial conditions)
        pub fn backtrace_last(&self, mut pos : Coordinate<I>) -> Option<Coordinate<I>> {
            loop {
                pos = match self.visited.get(&pos) {
                    None => return None,
                    Some(entry) => {
                        if entry.prev == self.start {
                            return Some(pos);
                        } else {
                            entry.prev
                        }
                    }
                }
            }
        }
    }
}

/// Very tricky, but (hopefully) good enough, recursive LoS algorithm
pub mod los {
    use hex2d;
    use hex2d::Angle::{Left,Right};

    use hex2d::Direction;
    use hex2d::Coordinate;

    fn los_rec<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        pos : Coordinate<I>,
        start_dir : Direction,
        main_dir : Direction,
        dir : Option<Direction>,
        pdir : Option<Direction>,
    ) where
        I : hex2d::Integer,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {

            let mut light = light;
            let opaq = opaqueness(pos);

            if opaq >= light {
                return;
            } else {
                light = light - opaq;
            }

            visible(pos, light);

            let neighbors = match (dir, pdir) {
                (Some(dir), Some(pdir)) => {
                    if dir == pdir {
                        vec!(dir)
                    } else {
                        vec!(dir, pdir)
                    }
                },
                (Some(dir), None) => {
                    if main_dir == dir {
                        vec!(dir, dir + Left, dir + Right)
                    } else {
                        vec!(dir, main_dir)
                    }
                },
                _ => {
                    vec!(main_dir, main_dir + Left, main_dir + Right)
                }
            };

            for &d in neighbors.iter() {
                let npos = pos + d;
                match dir {
                    Some(_) => los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, npos, start_dir, d, Some(d), dir),
                    None => los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, npos, start_dir, main_dir, Some(d), dir),
                }
            }
        }

    /// Starting from `pos` in direction `dir`, call `visible` for each visible Coordinate.
    ///
    /// Use `light` as starting range of the LoS. For each visible Coordinate, the value returned
    /// by `opaqueness` will be subtracted from `light` to check if the LoS should finish due to
    /// "lack of visibility". `opaqueness` should typically return 1 for fully transparent
    /// Coordinates, and anything bigger than initial `light` for fully opaque Coordinates.
    pub fn los<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        pos : Coordinate<I>,
        dirs : &[Direction],
    ) where
        I : hex2d::Integer,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {
            for dir in dirs.iter() {
                los_rec::<FOpaqueness, FVisible, I>(opaqueness, visible, light, pos, *dir, *dir, None, None);
            }
        }
}

/// Combination of tricky Los with straight line checking
pub mod los2 {
    use hex2d;
    use hex2d::Angle::{Left, Right, Forward};
    use hex2d::Direction;
    use hex2d::Coordinate;
    use num::{FromPrimitive};
    use std::collections::HashSet;
    use std::hash;
    use std::ops::{Add};

    fn los_rec<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        start : Coordinate<I>,
        pos : Coordinate<I>,
        dir : Direction,
        visited : &mut HashSet<Coordinate<I>>,
    ) where
        I : hex2d::Integer,
        I : hash::Hash+Eq,
        for <'a> &'a I: Add<&'a I, Output = I>,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {
            if visited.contains(&pos) {
                return;
            } else {
                visited.insert(pos);
            }

            let mut opaq_sum1 : I = FromPrimitive::from_i8(0).unwrap();
            let mut last1 = start;

            let mut opaq_sum2 : I = FromPrimitive::from_i8(0).unwrap();
            let mut last2 = start;

            let mut directly_visible = false;
            for &(c1, c2) in start.line_to_with_edge_detection(pos).iter() {
                if opaq_sum1 < light {
                    let opaq1 = opaqueness(c1);
                    opaq_sum1 = opaq_sum1 + opaq1;
                    last1 = c1;
                }

                if opaq_sum2 < light {
                    let opaq2 = opaqueness(c2);
                    opaq_sum2 = opaq_sum2 + opaq2;
                    last2 = c2;
                }
            };

            if last1 == pos {
                visible(pos, light - opaq_sum1);
                directly_visible = true;
            } else if  last2 == pos {
                visible(pos, light - opaq_sum2);
                directly_visible = true;
            }

            if !directly_visible {

                let dir_to = start.direction_to_cw(pos).unwrap_or(dir);
                let neighbors = vec!(Left, Right);
                for npos in neighbors.iter()
                    .map(|&rd| dir_to + rd)
                        .map(|dir| pos + dir) {

                            let mut opaq_sum1 : I = FromPrimitive::from_i8(0).unwrap();
                            let mut last1 = start;

                            let mut opaq_sum2 : I = FromPrimitive::from_i8(0).unwrap();
                            let mut last2 = start;

                            for &(c1, c2) in start.line_to_with_edge_detection(npos).iter() {
                                if opaq_sum1 < light {
                                    let opaq1 = opaqueness(c1);
                                    opaq_sum1 = opaq_sum1 + opaq1;
                                    last1 = c1;
                                }

                                if opaq_sum2 < light {
                                    let opaq2 = opaqueness(c2);
                                    opaq_sum2 = opaq_sum2 + opaq2;
                                    last2 = c2;
                                }
                            };

                            if last1 == npos {
                                visible(pos, light - opaq_sum1);
                            } else if last2 == npos {
                                visible(pos, light - opaq_sum2);
                            }
                        }
                return;
            }

            let neighbors = vec!(Forward, Left, Right);

            for &a in neighbors.iter() {
                let npos = pos + (dir + a);
                los_rec::<FOpaqueness, FVisible, I>(
                    opaqueness, visible, light, start, npos, dir, visited
                    );
            }
        }

    /// Starting from `pos` in direction `dir`, call `visible` for each visible Coordinate.
    ///
    /// Use `light` as starting range of the LoS. For each visible Coordinate, the value returned
    /// by `opaqueness` will be subtracted from `light` to check if the LoS should finish due to
    /// "lack of visibility". `opaqueness` should typically return 1 for fully transparent
    /// Coordinates, and anything bigger than initial `light` for fully opaque Coordinates.
    pub fn los<FOpaqueness, FVisible, I=i32>(
        opaqueness : &FOpaqueness,
        visible : &mut FVisible,
        light: I,
        pos : Coordinate<I>,
        dirs : &[Direction],
    ) where
        I : hex2d::Integer,
        I : hash::Hash,
        for <'a> &'a I: Add<&'a I, Output = I>,
        FOpaqueness : Fn(Coordinate<I>) -> I,
        FVisible : FnMut(Coordinate<I>, I)
        {
            for dir in dirs.iter() {
                let mut visited = HashSet::new();
                los_rec::<FOpaqueness, FVisible, I>(
                    opaqueness, visible, light, pos, pos, *dir, &mut visited
                    );
            }
        }
}
<|endoftext|>