<commit_before>#![allow(dead_code)]
extern crate mio;
extern crate threadpool;

use self::threadpool::ThreadPool;
use std::error::Error;
use network::Connection;
use network::tcp::TcpNetwork;
use std::collections::BTreeMap;
use self::mio::channel::{Sender, Receiver, channel};
use self::mio::{Poll, Ready, PollOpt, Events};
use network::{NetworkConfig, RECEIVER_CHANNEL_TOKEN, LOOP_EVENTS_COUNT, SocketType};
use network::tcp::{TcpWriterCommand, TcpWriterCMD};
use helper::{Log, NetHelper};
use std::process;
use node::Event;
use std::sync::Arc;

pub type ConnectionsMap = BTreeMap<String, Connection>;

pub enum NetworkCMD {
    NONE,
    HandleEvent,
    CloseConnection
}

pub struct NetworkCommand {
    pub cmd: NetworkCMD,
    pub token: Vec<String>,
    pub event: Vec<Event>
}

pub struct Network {
    // value for current Node which will help to send handshake information first
    // All depends on this unique value
    node_value: u64,

    // main collection for connections
    connections: ConnectionsMap,

    // channels for handling Networking command transfer
    sender_chan: Sender<NetworkCommand>,
    receiver_chan: Receiver<NetworkCommand>,

    // poll service for handling events
    poll: Poll,

    // TCP networking
    tcp_net: TcpNetwork,

    // keeping thread pool here
    thread_pool: ThreadPool
}

impl Network {
    pub fn new(value: u64, token: String, config: &NetworkConfig) -> Network {
        let (s, r) = channel::<NetworkCommand>();
        let poll = match Poll::new() {
            Ok(p) => p,
            Err(e) => {
                Log::error("Unable to create POLL service for Networking",
                           e.description());
                process::exit(1);
            }
        };

        // generating handshake information
        let handshake = Network::generate_handshake(value, token.clone(), config.api_version);
        let thread_pool = ThreadPool::new(config.concurrency);
        Network {
            node_value: value,
            connections: ConnectionsMap::new(),
            tcp_net: TcpNetwork::new(config.server_address.as_str(), config.concurrency, s.clone(), handshake, thread_pool.clone()),
            sender_chan: s,
            receiver_chan: r,
            poll: poll,
            thread_pool: thread_pool
        }
    }

    pub fn start(&mut self) {
        match self.poll.register(&self.receiver_chan,
                                 RECEIVER_CHANNEL_TOKEN,
                                 Ready::readable(),
                                 PollOpt::edge()) {
            Ok(_) => {}
            Err(e) => {
                Log::error("Unable to bind Networking receiver channel to POLL I/O service",
                           e.description());
                process::exit(1);
            }
        }

        // registering TCP network server
        self.tcp_net.register(&mut self.poll);

        // making events for handling 5K events at once
        let mut events: Events = Events::with_capacity(LOOP_EVENTS_COUNT);
        loop {
            let event_count = self.poll.poll(&mut events, None).unwrap();
            if event_count == 0 {
                continue;
            }

            for event in events.iter() {
                let (token, kind) = (event.token(), event.kind());
                if token == RECEIVER_CHANNEL_TOKEN {
                    // trying to get commands while there is available data
                    loop {
                        match self.receiver_chan.try_recv() {
                            Ok(cmd) => {
                                let mut c = cmd;
                                self.notify(&mut c);
                            }
                            // if we got error, then data is unavailable
                            // and breaking receive loop
                            Err(e) => {
                                Log::warn("Networking receiver channel data is not available",
                                          e.description());
                                break;
                            }
                        }
                    }
                    continue;
                }

                // passing event to TCP networking
                if self.tcp_net.ready(token, kind, &mut self.poll, &mut self.connections) {
                    // if token found in TCP actions moving on
                    continue;
                }
            }
        }
    }

    #[inline(always)]
    fn notify(&mut self, command: &mut NetworkCommand) {
        match command.cmd {
            _ => {}
        }
    }

    /// Generating Handshake information for sending it with every connection
    #[inline(always)]
    fn generate_handshake(value: u64, token: String, api_version: u32) -> Vec<u8> {
        let (mut offset, text_len) = (0, token.len());
        // making buffer
        // [4 bytes API Number] + [4 bytes text length number] + [text length numbers] + [8 bytes for prime number version]
        let mut buffer: Vec<u8> = vec![0; (4 + 4 + text_len + 8)];
        let text_bytes = token.into_bytes();

        // writing API version
        let mut tmp_offset = NetHelper::u32_to_bytes(api_version, &mut buffer, offset);
        if tmp_offset == 0 {
            Log::error("Unable to write API Version BigEndian number during generating handshake", "returned 0");
            return vec![];
        }
        offset += tmp_offset;

        // Writing text length with more 8 bytes for value
        tmp_offset = NetHelper::u32_to_bytes((text_len + 8) as u32, &mut buffer, offset);
        if tmp_offset == 0 {
            Log::error("Unable to write Token Length BigEndian number during generating handshake", "returned 0");
            return vec![];
        }
        offset += tmp_offset;

        // Adding text bytes
        for i in 0..text_len {
            buffer[offset + i] = text_bytes[i];
        }
        offset += text_len;

        // Writing Prime Value
        tmp_offset = NetHelper::u64_to_bytes(value, &mut buffer, offset);
        if tmp_offset == 0 {
            Log::error("Unable to write Prime Value BigEndian number during generating handshake", "returned 0");
            return vec![];
        }

        buffer
    }

    pub fn emit(&mut self, event: Event) {
        let mut tcp_writer_tokens: Vec<Vec<String>> = vec![Vec::new(); self.tcp_net.writer_channels.len()];
        let mut ev = event;
        let mut have_content = false;
        for (token, conn) in &mut self.connections {
            // checking if we have connection inside path
            if !ev.path.dividable(conn.value) {
                continue;
            }

            match conn.get_identity() {
                Some(ref identity) => {
                    match identity.socket_type {
                        SocketType::TCP => {
                            tcp_writer_tokens[identity.writer_index].push(token.clone());
                            have_content = true;
                        }
                        SocketType::NONE => {}
                    }
                },

                /// TODO: we need to close connection if we don't have an identity in it
                None => {}
            };
        }

        if !have_content {
            return;
        }

        let tcp_writer_channels = self.tcp_net.writer_channels.clone();

        // if we got here then we have something inside our writer tokens, so we need
        // to parse Event into raw data and send it over writer channels
        self.thread_pool.execute(move || {

            let data = match ev.to_raw() {
                Some(d) => Arc::new(d),
                None => return
            };

            // Sending tcp data
            for i in 0..tcp_writer_tokens.len() {
                if tcp_writer_tokens[i].len() == 0 {
                    continue;
                }

                let mut cmd = TcpWriterCommand::default();
                cmd.cmd = TcpWriterCMD::WriteData;
                cmd.data.push(data.clone());
                cmd.conn_token = tcp_writer_tokens.remove(i);
                let _ = tcp_writer_channels[i].send(cmd);
            }
        });
    }
}

impl NetworkCommand {
    pub fn default() -> NetworkCommand {
        NetworkCommand {
            cmd: NetworkCMD::NONE,
            token: vec![],
            event: vec![]
        }
    }
}<commit_msg>api event emit implemented<commit_after>#![allow(dead_code)]
extern crate mio;
extern crate threadpool;

use self::threadpool::ThreadPool;
use std::error::Error;
use network::Connection;
use network::tcp::TcpNetwork;
use std::collections::BTreeMap;
use self::mio::channel::{Sender, Receiver, channel};
use self::mio::{Poll, Ready, PollOpt, Events};
use network::{NetworkConfig, RECEIVER_CHANNEL_TOKEN, LOOP_EVENTS_COUNT, SocketType};
use network::tcp::{TcpWriterCommand, TcpWriterCMD};
use helper::{Log, NetHelper};
use std::process;
use node::Event;
use std::sync::Arc;

pub type ConnectionsMap = BTreeMap<String, Connection>;

pub enum NetworkCMD {
    NONE,
    HandleEvent,
    CloseConnection
}

pub struct NetworkCommand {
    pub cmd: NetworkCMD,
    pub token: Vec<String>,
    pub event: Vec<Event>
}

pub struct Network {
    // value for current Node which will help to send handshake information first
    // All depends on this unique value
    node_value: u64,

    // main collection for connections
    connections: ConnectionsMap,

    // channels for handling Networking command transfer
    sender_chan: Sender<NetworkCommand>,
    receiver_chan: Receiver<NetworkCommand>,

    // poll service for handling events
    poll: Poll,

    // TCP networking
    tcp_net: TcpNetwork,

    // keeping thread pool here
    thread_pool: ThreadPool
}

impl Network {
    pub fn new(value: u64, token: String, config: &NetworkConfig) -> Network {
        let (s, r) = channel::<NetworkCommand>();
        let poll = match Poll::new() {
            Ok(p) => p,
            Err(e) => {
                Log::error("Unable to create POLL service for Networking",
                           e.description());
                process::exit(1);
            }
        };

        // generating handshake information
        let handshake = Network::generate_handshake(value, token.clone(), config.api_version);
        let thread_pool = ThreadPool::new(config.concurrency);
        Network {
            node_value: value,
            connections: ConnectionsMap::new(),
            tcp_net: TcpNetwork::new(config.server_address.as_str(), config.concurrency, s.clone(), handshake, thread_pool.clone()),
            sender_chan: s,
            receiver_chan: r,
            poll: poll,
            thread_pool: thread_pool
        }
    }

    pub fn start(&mut self) {
        match self.poll.register(&self.receiver_chan,
                                 RECEIVER_CHANNEL_TOKEN,
                                 Ready::readable(),
                                 PollOpt::edge()) {
            Ok(_) => {}
            Err(e) => {
                Log::error("Unable to bind Networking receiver channel to POLL I/O service",
                           e.description());
                process::exit(1);
            }
        }

        // registering TCP network server
        self.tcp_net.register(&mut self.poll);

        // making events for handling 5K events at once
        let mut events: Events = Events::with_capacity(LOOP_EVENTS_COUNT);
        loop {
            let event_count = self.poll.poll(&mut events, None).unwrap();
            if event_count == 0 {
                continue;
            }

            for event in events.iter() {
                let (token, kind) = (event.token(), event.kind());
                if token == RECEIVER_CHANNEL_TOKEN {
                    // trying to get commands while there is available data
                    loop {
                        match self.receiver_chan.try_recv() {
                            Ok(cmd) => {
                                let mut c = cmd;
                                self.notify(&mut c);
                            }
                            // if we got error, then data is unavailable
                            // and breaking receive loop
                            Err(e) => {
                                Log::warn("Networking receiver channel data is not available",
                                          e.description());
                                break;
                            }
                        }
                    }
                    continue;
                }

                // passing event to TCP networking
                if self.tcp_net.ready(token, kind, &mut self.poll, &mut self.connections) {
                    // if token found in TCP actions moving on
                    continue;
                }
            }
        }
    }

    #[inline(always)]
    fn notify(&mut self, command: &mut NetworkCommand) {
        match command.cmd {
            _ => {}
        }
    }

    /// Generating Handshake information for sending it with every connection
    #[inline(always)]
    fn generate_handshake(value: u64, token: String, api_version: u32) -> Vec<u8> {
        let (mut offset, text_len) = (0, token.len());
        // making buffer
        // [4 bytes API Number] + [4 bytes text length number] + [text length numbers] + [8 bytes for prime number version]
        let mut buffer: Vec<u8> = vec![0; (4 + 4 + text_len + 8)];
        let text_bytes = token.into_bytes();

        // writing API version
        let mut tmp_offset = NetHelper::u32_to_bytes(api_version, &mut buffer, offset);
        if tmp_offset == 0 {
            Log::error("Unable to write API Version BigEndian number during generating handshake", "returned 0");
            return vec![];
        }
        offset += tmp_offset;

        // Writing text length with more 8 bytes for value
        tmp_offset = NetHelper::u32_to_bytes((text_len + 8) as u32, &mut buffer, offset);
        if tmp_offset == 0 {
            Log::error("Unable to write Token Length BigEndian number during generating handshake", "returned 0");
            return vec![];
        }
        offset += tmp_offset;

        // Adding text bytes
        for i in 0..text_len {
            buffer[offset + i] = text_bytes[i];
        }
        offset += text_len;

        // Writing Prime Value
        tmp_offset = NetHelper::u64_to_bytes(value, &mut buffer, offset);
        if tmp_offset == 0 {
            Log::error("Unable to write Prime Value BigEndian number during generating handshake", "returned 0");
            return vec![];
        }

        buffer
    }

    /// Send event based on Event Path
    #[inline(always)]
    pub fn emit(&mut self, event: Event) {
        let mut tcp_writer_tokens: Vec<Vec<String>> = vec![Vec::new(); self.tcp_net.writer_channels.len()];
        let mut ev = event;
        let mut have_content = false;
        for (token, conn) in &mut self.connections {
            // checking if we have connection inside path
            if !ev.path.dividable(conn.value) {
                continue;
            }

            match conn.get_identity() {
                Some(ref identity) => {
                    match identity.socket_type {
                        SocketType::TCP => {
                            tcp_writer_tokens[identity.writer_index].push(token.clone());
                            have_content = true;
                        }
                        SocketType::NONE => {}
                    }
                },

                /// TODO: we need to close connection if we don't have an identity in it
                None => {}
            };
        }

        if !have_content {
            return;
        }

        self.write_event_pool(tcp_writer_tokens, ev);
    }

    pub fn emit_api(&mut self, api_tokens: Vec<String>, event: Event) {
        let mut tcp_writer_tokens: Vec<Vec<String>> = vec![Vec::new(); self.tcp_net.writer_channels.len()];
        let mut have_content = false;
        for (token, conn) in &mut self.connections {
            for api_token in &api_tokens {
                let str = token.clone();
                let str2 = api_token.clone();
                if str == str2 {
                    match conn.get_identity() {
                        Some(ref identity) => {
                            match identity.socket_type {
                                SocketType::TCP => {
                                    tcp_writer_tokens[identity.writer_index].push(str);
                                    have_content = true;
                                }
                                SocketType::NONE => {}
                            }
                        },

                        /// TODO: we need to close connection if we don't have an identity in it
                        None => {}
                    };
                }
            }
        }

        if !have_content {
            return;
        }

        self.write_event_pool(tcp_writer_tokens, event);
    }

    #[inline(always)]
    fn write_event_pool(&mut self, tokens: Vec<Vec<String>>, ev: Event) {
        let tcp_writer_channels = self.tcp_net.writer_channels.clone();
        let mut tcp_writer_tokens = tokens;
        // if we got here then we have something inside our writer tokens, so we need
        // to parse Event into raw data and send it over writer channels
        self.thread_pool.execute(move || {

            let data = match ev.to_raw() {
                Some(d) => Arc::new(d),
                None => return
            };

            // Sending tcp data
            for i in 0..tcp_writer_tokens.len() {
                if tcp_writer_tokens[i].len() == 0 {
                    continue;
                }

                let mut cmd = TcpWriterCommand::default();
                cmd.cmd = TcpWriterCMD::WriteData;
                cmd.data.push(data.clone());
                cmd.conn_token = tcp_writer_tokens.remove(i);
                let _ = tcp_writer_channels[i].send(cmd);
            }
        });
    }
}

impl NetworkCommand {
    pub fn default() -> NetworkCommand {
        NetworkCommand {
            cmd: NetworkCMD::NONE,
            token: vec![],
            event: vec![]
        }
    }
}<|endoftext|>


<commit_before>use prelude::*;
use data::{SampleWeight};
use opt::{StepSize, GradientMomentum, NesterovParamState, ClassOptStats};
use rw::{ReadBuffer, WriteBuffer, AccumulateBuffer};

use densearray::{Reshape, ReshapeMut};

use rand::{Rng};
use std::cmp::{min};
use std::marker::{PhantomData};

#[derive(Clone, Copy, Debug)]
pub struct RmspropConfig {
  pub batch_sz:     usize,
  pub minibatch_sz: usize,
  pub step_size:    StepSize,
  pub momentum:     Option<GradientMomentum>,
  pub gamma:        f32,
  pub epsilon:      f32,
  pub l2_reg:       Option<f32>,
}

pub struct RmspropWorker<T, S, R, Op> where R: Rng, Op: DiffOperatorInput<T, S> {
  cfg:          RmspropConfig,
  iter_counter: usize,
  operator:     Op,
  cache:        Vec<S>,
  grad_sz:      usize,
  nondiff_sz:   usize,
  param_state:  NesterovParamState,
  param_saved:  Vec<T>,
  grad:         Vec<T>,
  sq_grad_acc:  Vec<T>,
  nrm_update:   Vec<T>,
  tmp_buf:      Vec<T>,
  stats_it:     usize,
  stats:        ClassOptStats,
  _marker:      PhantomData<R>,
}

impl<S, R, Op> RmspropWorker<f32, S, R, Op> where R: Rng, Op: DiffOperatorInput<f32, S, Rng=R> {
  pub fn new(cfg: RmspropConfig, operator: Op) -> RmspropWorker<f32, S, R, Op> {
    let grad_sz = operator.param_len();
    //let grad_sz = operator.diff_param_sz();
    let mut param_saved = Vec::with_capacity(grad_sz);
    for _ in 0 .. grad_sz {
      param_saved.push(0.0);
    }
    let mut grad = Vec::with_capacity(grad_sz);
    for _ in 0 .. grad_sz {
      grad.push(0.0);
    }
    let mut sq_grad_acc = Vec::with_capacity(grad_sz);
    for _ in 0 .. grad_sz {
      sq_grad_acc.push(0.0);
    }
    let mut nrm_update = Vec::with_capacity(grad_sz);
    for _ in 0 .. grad_sz {
      nrm_update.push(0.0);
    }
    let mut tmp_buf = Vec::with_capacity(grad_sz);
    for _ in 0 .. grad_sz {
      tmp_buf.push(0.0);
    }
    RmspropWorker{
      cfg:          cfg,
      iter_counter: 0,
      operator:     operator,
      cache:        Vec::with_capacity(cfg.batch_sz),
      grad_sz:      grad_sz,
      nondiff_sz:   0, // FIXME(20161001): count nondiff params too (e.g. batchnorm).
      param_state:  NesterovParamState::Orig,
      param_saved:  param_saved,
      grad:         grad,
      sq_grad_acc:  sq_grad_acc,
      nrm_update:   nrm_update,
      tmp_buf:      tmp_buf,
      stats_it:     0,
      stats:        Default::default(),
      _marker:      PhantomData,
    }
  }
}

impl<S, R, Op> OptWorker<f32, S> for RmspropWorker<f32, S, R, Op> where S: SampleWeight, R: Rng, Op: DiffOperatorInput<f32, S, Rng=R> {
  type Rng = R;

  fn init_param(&mut self, rng: &mut Op::Rng) {
    self.operator.init_param(rng);
    self.operator.store_param(&mut self.param_saved, 0);
  }

  fn load_local_param(&mut self, param_reader: &mut ReadBuffer<f32>) {
  }

  fn store_local_param(&mut self, param_writer: &mut WriteBuffer<f32>) {
  }

  fn store_global_param(&mut self, param_writer: &mut WriteBuffer<f32>) {
  }

  fn step(&mut self, samples: &mut Iterator<Item=S>) {
    let num_batches = (self.cfg.minibatch_sz + self.cfg.batch_sz - 1) / self.cfg.batch_sz;

    /*match self.param_state {
      NesterovParamState::Orig => {
        //self.operator.load_param(..., 0);
        self.param_state = NesterovParamState::PlusMomentum;
      }
      NesterovParamState::PlusMomentum => {}
    }*/
    self.operator.save_rng_state();
    self.operator.reset_loss();
    self.operator.reset_grad();
    for batch in 0 .. num_batches {
      let actual_batch_sz = min((batch+1) * self.cfg.batch_sz, self.cfg.minibatch_sz) - batch * self.cfg.batch_sz;
      self.cache.clear();
      for mut sample in samples.take(actual_batch_sz) {
        sample.mix_weight(1.0 / self.cfg.minibatch_sz as f32);
        self.cache.push(sample);
      }
      self.operator.load_data(&self.cache);
      self.operator.forward(OpPhase::Learning);
      if let Some(lambda) = self.cfg.l2_reg {
        //self.operator.fwd_reg(Regularization::L2(lambda));
      }
      self.operator.backward();
      if let Some(lambda) = self.cfg.l2_reg {
        //self.operator.bwd_reg(Regularization::L2(lambda));
      }
    }
    if let Some(lambda) = self.cfg.l2_reg {
      self.operator.apply_grad_reg(Regularization::L2(lambda));
    }
    self.operator.store_grad(&mut self.grad, 0);

    let step_size = match self.cfg.step_size {
      StepSize::Constant(alpha) => {
        alpha
      }
      StepSize::Decay{init_step, step_decay, decay_iters} => {
        let num_decays = self.iter_counter / decay_iters;
        init_step * step_decay.powi(num_decays as i32)
      }
      _ => unimplemented!(),
    };

    self.tmp_buf.copy_from_slice(&self.grad);
    self.tmp_buf.reshape_mut(self.grad_sz).vector_square();
    self.sq_grad_acc.reshape_mut(self.grad_sz).vector_scale(1.0 - self.cfg.gamma);
    self.sq_grad_acc.reshape_mut(self.grad_sz).vector_add(self.cfg.gamma, self.tmp_buf.reshape(self.grad_sz));

    self.tmp_buf.copy_from_slice(&self.sq_grad_acc);
    self.tmp_buf.reshape_mut(self.grad_sz).vector_add_scalar(self.cfg.epsilon);
    self.tmp_buf.reshape_mut(self.grad_sz).vector_sqrt();
    self.nrm_update.copy_from_slice(&self.tmp_buf);
    self.nrm_update.reshape_mut(self.grad_sz).vector_recip();
    self.nrm_update.reshape_mut(self.grad_sz).vector_elem_mult(1.0, self.grad.reshape(self.grad_sz));

    self.operator.update_param(-step_size, 1.0, &mut self.nrm_update, 0);
    self.operator.store_param(&mut self.param_saved, 0);

    self.stats_it += 1;
    self.stats.sample_count += self.cfg.minibatch_sz;
    self.stats.avg_loss += 1.0 / (self.stats_it as f32) * (self.operator.store_loss() - self.stats.avg_loss);

    self.iter_counter += 1;
  }

  fn eval(&mut self, epoch_sz: usize, samples: &mut Iterator<Item=S>) {
    /*match self.param_state {
      NesterovParamState::Orig => {}
      NesterovParamState::PlusMomentum => {
        //self.operator.load_param(..., 0);
        self.param_state = NesterovParamState::Orig;
      }
    }*/
    self.cache.clear();
    self.operator.reset_loss();
    for mut sample in samples.take(epoch_sz) {
      sample.mix_weight(1.0 / epoch_sz as f32);
      self.cache.push(sample);
      if self.cache.len() == self.cfg.batch_sz {
        self.operator.load_data(&self.cache);
        self.operator.forward(OpPhase::Inference);
        self.cache.clear();
      }
    }
    if self.cache.len() > 0 {
      self.operator.load_data(&self.cache);
      self.operator.forward(OpPhase::Inference);
    }
    self.stats_it += 1;
    self.stats.sample_count += epoch_sz;
    self.stats.avg_loss += 1.0 / (self.stats_it as f32) * (self.operator.store_loss() - self.stats.avg_loss);
  }
}

impl<S, R, Op> OptStats<ClassOptStats> for RmspropWorker<f32, S, R, Op> where S: SampleWeight, R: Rng, Op: DiffOperatorInput<f32, S> {
  fn reset_opt_stats(&mut self) {
    self.stats_it = 0;
    self.stats.sample_count = 0;
    self.stats.correct_count = 0;
    self.stats.avg_loss = 0.0;
  }

  fn get_opt_stats(&self) -> &ClassOptStats {
    &self.stats
  }
}
<commit_msg>Add optional variance centering to rmsprop.<commit_after>use prelude::*;
use data::{SampleWeight};
use opt::{StepSize, GradientMomentum, NesterovParamState, ClassOptStats};
use rw::{ReadBuffer, WriteBuffer, AccumulateBuffer};

use densearray::{Reshape, ReshapeMut};

use rand::{Rng};
use std::cmp::{min};
use std::marker::{PhantomData};

#[derive(Clone, Copy, Debug)]
pub struct RmspropConfig {
  pub batch_sz:     usize,
  pub minibatch_sz: usize,
  pub step_size:    StepSize,
  //pub momentum:     Option<GradientMomentum>,
  pub momentum:     f32,
  pub gamma:        f32,
  /// `centered_var`: When enabled, this stores the 1st moment of the gradients
  /// and uses it to center the variance; c.f. [Graves 2013, arXiv:1308.0850].
  pub centered_var: bool,
  pub epsilon:      f32,
  pub l2_reg:       Option<f32>,
}

pub struct RmspropWorker<T, S, R, Op> where R: Rng, Op: DiffOperatorInput<T, S> {
  cfg:          RmspropConfig,
  iter_counter: usize,
  operator:     Op,
  cache:        Vec<S>,
  grad_sz:      usize,
  nondiff_sz:   usize,
  //param_state:  NesterovParamState,
  param_saved:  Vec<T>,
  grad:         Vec<T>,
  grad_acc:     Option<Vec<T>>,
  sq_grad_acc:  Vec<T>,
  nrm_update:   Vec<T>,
  tmp_buf:      Vec<T>,
  stats_it:     usize,
  stats:        ClassOptStats,
  _marker:      PhantomData<R>,
}

impl<S, R, Op> RmspropWorker<f32, S, R, Op> where R: Rng, Op: DiffOperatorInput<f32, S, Rng=R> {
  pub fn new(cfg: RmspropConfig, operator: Op) -> RmspropWorker<f32, S, R, Op> {
    let grad_sz = operator.param_len();
    //let grad_sz = operator.diff_param_sz();
    let mut param_saved = Vec::with_capacity(grad_sz);
    for _ in 0 .. grad_sz {
      param_saved.push(0.0);
    }
    let mut grad = Vec::with_capacity(grad_sz);
    for _ in 0 .. grad_sz {
      grad.push(0.0);
    }
    let grad_acc = if cfg.centered_var {
    let mut grad_acc = Vec::with_capacity(grad_sz);
      for _ in 0 .. grad_sz {
        grad_acc.push(0.0);
      }
      Some(grad_acc)
    } else {
      None
    };
    let mut sq_grad_acc = Vec::with_capacity(grad_sz);
    for _ in 0 .. grad_sz {
      sq_grad_acc.push(0.0);
    }
    let mut nrm_update = Vec::with_capacity(grad_sz);
    for _ in 0 .. grad_sz {
      nrm_update.push(0.0);
    }
    let mut tmp_buf = Vec::with_capacity(grad_sz);
    for _ in 0 .. grad_sz {
      tmp_buf.push(0.0);
    }
    RmspropWorker{
      cfg:          cfg,
      iter_counter: 0,
      operator:     operator,
      cache:        Vec::with_capacity(cfg.batch_sz),
      grad_sz:      grad_sz,
      nondiff_sz:   0, // FIXME(20161001): count nondiff params too (e.g. batchnorm).
      //param_state:  NesterovParamState::Orig,
      param_saved:  param_saved,
      grad:         grad,
      grad_acc:     grad_acc,
      sq_grad_acc:  sq_grad_acc,
      nrm_update:   nrm_update,
      tmp_buf:      tmp_buf,
      stats_it:     0,
      stats:        Default::default(),
      _marker:      PhantomData,
    }
  }
}

impl<S, R, Op> OptWorker<f32, S> for RmspropWorker<f32, S, R, Op> where S: SampleWeight, R: Rng, Op: DiffOperatorInput<f32, S, Rng=R> {
  type Rng = R;

  fn init_param(&mut self, rng: &mut Op::Rng) {
    self.operator.init_param(rng);
    self.operator.store_param(&mut self.param_saved, 0);
  }

  fn load_local_param(&mut self, param_reader: &mut ReadBuffer<f32>) {
  }

  fn store_local_param(&mut self, param_writer: &mut WriteBuffer<f32>) {
  }

  fn store_global_param(&mut self, param_writer: &mut WriteBuffer<f32>) {
  }

  fn step(&mut self, samples: &mut Iterator<Item=S>) {
    let num_batches = (self.cfg.minibatch_sz + self.cfg.batch_sz - 1) / self.cfg.batch_sz;

    self.operator.save_rng_state();
    self.operator.reset_loss();
    self.operator.reset_grad();
    for batch in 0 .. num_batches {
      let actual_batch_sz = min((batch+1) * self.cfg.batch_sz, self.cfg.minibatch_sz) - batch * self.cfg.batch_sz;
      self.cache.clear();
      for mut sample in samples.take(actual_batch_sz) {
        sample.mix_weight(1.0 / self.cfg.minibatch_sz as f32);
        self.cache.push(sample);
      }
      self.operator.load_data(&self.cache);
      self.operator.forward(OpPhase::Learning);
      if let Some(lambda) = self.cfg.l2_reg {
        //self.operator.fwd_reg(Regularization::L2(lambda));
      }
      self.operator.backward();
      if let Some(lambda) = self.cfg.l2_reg {
        //self.operator.bwd_reg(Regularization::L2(lambda));
      }
    }
    if let Some(lambda) = self.cfg.l2_reg {
      self.operator.apply_grad_reg(Regularization::L2(lambda));
    }
    self.operator.store_grad(&mut self.grad, 0);

    let step_size = match self.cfg.step_size {
      StepSize::Constant(alpha) => {
        alpha
      }
      StepSize::Decay{init_step, step_decay, decay_iters} => {
        let num_decays = self.iter_counter / decay_iters;
        init_step * step_decay.powi(num_decays as i32)
      }
      _ => unimplemented!(),
    };

    if let Some(ref mut grad_acc) = self.grad_acc {
      if self.iter_counter == 0 {
        grad_acc.copy_from_slice(&self.grad);
      } else {
        grad_acc.reshape_mut(self.grad_sz).vector_scale(1.0 - self.cfg.gamma);
        grad_acc.reshape_mut(self.grad_sz).vector_add(self.cfg.gamma, self.grad.reshape(self.grad_sz));
      }
    }
    self.tmp_buf.copy_from_slice(&self.grad);
    self.tmp_buf.reshape_mut(self.grad_sz).vector_square();
    if self.iter_counter == 0 {
      self.sq_grad_acc.copy_from_slice(&self.tmp_buf);
    } else {
      self.sq_grad_acc.reshape_mut(self.grad_sz).vector_scale(1.0 - self.cfg.gamma);
      self.sq_grad_acc.reshape_mut(self.grad_sz).vector_add(self.cfg.gamma, self.tmp_buf.reshape(self.grad_sz));
    }

    self.nrm_update.copy_from_slice(&self.sq_grad_acc);
    if let Some(ref grad_acc) = self.grad_acc {
      self.tmp_buf.copy_from_slice(grad_acc);
      self.tmp_buf.reshape_mut(self.grad_sz).vector_square();
      self.nrm_update.reshape_mut(self.grad_sz).vector_add(-1.0, self.tmp_buf.reshape(self.grad_sz));
    }
    self.nrm_update.reshape_mut(self.grad_sz).vector_add_scalar(self.cfg.epsilon);
    self.nrm_update.reshape_mut(self.grad_sz).vector_sqrt();
    self.nrm_update.reshape_mut(self.grad_sz).vector_recip();
    self.nrm_update.reshape_mut(self.grad_sz).vector_elem_mult(1.0, self.grad.reshape(self.grad_sz));

    self.operator.update_param(-step_size, 1.0, &mut self.nrm_update, 0);
    self.operator.store_param(&mut self.param_saved, 0);

    self.stats_it += 1;
    self.stats.sample_count += self.cfg.minibatch_sz;
    self.stats.avg_loss += 1.0 / (self.stats_it as f32) * (self.operator.store_loss() - self.stats.avg_loss);

    self.iter_counter += 1;
  }

  fn eval(&mut self, epoch_sz: usize, samples: &mut Iterator<Item=S>) {
    /*match self.param_state {
      NesterovParamState::Orig => {}
      NesterovParamState::PlusMomentum => {
        //self.operator.load_param(..., 0);
        self.param_state = NesterovParamState::Orig;
      }
    }*/
    self.cache.clear();
    self.operator.reset_loss();
    for mut sample in samples.take(epoch_sz) {
      sample.mix_weight(1.0 / epoch_sz as f32);
      self.cache.push(sample);
      if self.cache.len() == self.cfg.batch_sz {
        self.operator.load_data(&self.cache);
        self.operator.forward(OpPhase::Inference);
        self.cache.clear();
      }
    }
    if self.cache.len() > 0 {
      self.operator.load_data(&self.cache);
      self.operator.forward(OpPhase::Inference);
    }
    self.stats_it += 1;
    self.stats.sample_count += epoch_sz;
    self.stats.avg_loss += 1.0 / (self.stats_it as f32) * (self.operator.store_loss() - self.stats.avg_loss);
  }
}

impl<S, R, Op> OptStats<ClassOptStats> for RmspropWorker<f32, S, R, Op> where S: SampleWeight, R: Rng, Op: DiffOperatorInput<f32, S> {
  fn reset_opt_stats(&mut self) {
    self.stats_it = 0;
    self.stats.sample_count = 0;
    self.stats.correct_count = 0;
    self.stats.avg_loss = 0.0;
  }

  fn get_opt_stats(&self) -> &ClassOptStats {
    &self.stats
  }
}
<|endoftext|>


<commit_before>use parser::combinators::{Parser, ParseTo, Consumer, token, tokens};
use parser::lexer::{Token};
use parser::lexer::Token::{Identifier};
use ast::{Typ, Var};
use ast::Typ::{F32, F64, I32, I64};

#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
pub enum ParseError {
    ExpectingTyp(String),
    ExpectingId(String),
}

pub trait ParserConsumer<T,D> where D: Consumer<Result<T,ParseError>> {
    fn accept<P>(self, parser: P) where P: for<'a> ParseTo<&'a[Token<'a>],D>;
}

fn is_identifier<'a>(tok: Token<'a>) -> bool {
    match tok {
        Identifier(_) => true,
        _             => false,
    }
}

fn is_param<'a>(tok: Token<'a>) -> bool {
    match tok {
        Identifier("param") => true,
        _                   => false,
    }
}

fn mk_typ<'a>(tok: Token<'a>) -> Result<Typ,ParseError> {
    match tok {
        Identifier("f32") => Ok(F32),
        Identifier("f64") => Ok(F64),
        Identifier("i32") => Ok(I32),
        Identifier("i64") => Ok(I64),
        _                 => Err(ParseError::ExpectingTyp(String::from(tok))),
    }
}

fn mk_id<'a>(tok: Token<'a>) -> Result<String,ParseError> {
    match tok {
        Identifier(x) => Ok(String::from(x)),
        _             => Err(ParseError::ExpectingId(String::from(tok))),
    }
}

fn mk_var<'a>(children: (Result<String,ParseError>, Result<Typ,ParseError>))-> Result<Var,ParseError> {
    Ok(Var { name: try!(children.0), typ: try!(children.1) })
}

pub fn var_parser<C,D>(consumer: C) where C: ParserConsumer<Var,D>, D: Consumer<Result<Var,ParseError>> {
    let typ = token(is_identifier).map(mk_typ);
    let id = token(is_identifier).map(mk_id);
    let param = token(is_param).ignore().and_then(id).zip(typ).map(mk_var);
    consumer.accept(param);
}

#[test]
fn test_var() {
    use parser::combinators::MatchResult::{Matched,Failed};
    use parser::lexer::Token::{LParen};
    struct TestConsumer;
    impl ParserConsumer<Var,Vec<Result<Var,ParseError>>> for TestConsumer {
        fn accept<P>(self, mut parser: P) where P: for<'a> ParseTo<&'a[Token<'a>],Vec<Result<Var,ParseError>>> {
            let mut results = Vec::new();
            assert_eq!(parser.done_to(&mut results), false);
            assert_eq!(results, []);
            results.clear();
            assert_eq!(parser.push_to(&[Identifier("param"),Identifier("$x"),Identifier("f32")], &mut results), Matched(None));
            assert_eq!(parser.done_to(&mut results), true);
            assert_eq!(results, [Ok(Var{ name: String::from("$x"), typ: F32 })]);
            results.clear();
            assert_eq!(parser.push_to(&[LParen], &mut results), Failed(Some(&[LParen][..])));
            assert_eq!(parser.done_to(&mut results), false);
            assert_eq!(results, []);
            results.clear();
            assert_eq!(parser.push_to(&[Identifier("param"),Identifier("$x"),Identifier("foo")], &mut results), Matched(None));
            assert_eq!(parser.done_to(&mut results), true);
            assert_eq!(results, [Err(ParseError::ExpectingTyp(String::from("foo")))]);
            results.clear();
        }
    }
    var_parser(TestConsumer);
}
<commit_msg>Started on top-down parser.<commit_after>use parser::combinators::{Parser, ParseTo, Consumer, token, tokens};
use parser::lexer::{Token};
use parser::lexer::Token::{Identifier, LParen, RParen};
use ast::{Module, Typ, Var};
use ast::Typ::{F32, F64, I32, I64};

#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
pub enum ParseError {
    ExpectingTyp(String),
    ExpectingId(String),
}

pub trait ParserConsumer<T,D> where D: Consumer<Result<T,ParseError>> {
    fn accept<P>(self, parser: P) where P: for<'a> ParseTo<&'a[Token<'a>],D>;
}

fn is_identifier<'a>(tok: Token<'a>) -> bool {
    match tok {
        Identifier(_) => true,
        _             => false,
    }
}

fn is_lparen<'a>(tok: Token<'a>) -> bool { tok == LParen }
fn is_rparen<'a>(tok: Token<'a>) -> bool { tok == RParen }
fn is_module<'a>(tok: Token<'a>) -> bool { tok == Identifier("module") }
fn is_param<'a>(tok: Token<'a>) -> bool { tok == Identifier("param") }

fn mk_typ<'a>(tok: Token<'a>) -> Result<Typ,ParseError> {
    match tok {
        Identifier("f32") => Ok(F32),
        Identifier("f64") => Ok(F64),
        Identifier("i32") => Ok(I32),
        Identifier("i64") => Ok(I64),
        _                 => Err(ParseError::ExpectingTyp(String::from(tok))),
    }
}

fn mk_id<'a>(tok: Token<'a>) -> Result<String,ParseError> {
    match tok {
        Identifier(x) => Ok(String::from(x)),
        _             => Err(ParseError::ExpectingId(String::from(tok))),
    }
}

fn mk_var(children: (Result<String,ParseError>, Result<Typ,ParseError>))-> Result<Var,ParseError> {
    Ok(Var{ name: try!(children.0), typ: try!(children.1) })
}

fn mk_module(children: ()) -> Result<Module,ParseError> {
    Ok(Module{ memory: None, imports: vec![], exports: vec![], functions: vec![] })
}

pub fn parser<C,D>(consumer: C) where C: ParserConsumer<Module,D>, D: Consumer<Result<Module,ParseError>> {
    let typ = token(is_identifier).map(mk_typ);
    let id = token(is_identifier).map(mk_id);
    let param = token(is_param).ignore().and_then(id).zip(typ).map(mk_var);
    let module = token(is_module).ignore().map(mk_module);
    let top_level = token(is_lparen).ignore().and_then(module).and_then(token(is_rparen).ignore());
    consumer.accept(top_level);
}

#[test]
fn test_parser() {
    use parser::combinators::MatchResult::{Matched,Failed};
    use parser::lexer::Token::{LParen};
    struct TestConsumer;
    impl ParserConsumer<Module,Vec<Result<Module,ParseError>>> for TestConsumer {
        fn accept<P>(self, mut parser: P) where P: for<'a> ParseTo<&'a[Token<'a>],Vec<Result<Module,ParseError>>> {
            let mut results = Vec::new();
            let tokens = [
                LParen, Identifier("module"),
                RParen,
            ];
            assert_eq!(parser.done_to(&mut results), false);
            assert_eq!(results, []);
            results.clear();
            assert_eq!(parser.push_to(&tokens, &mut results), Matched(None));
            assert_eq!(parser.done_to(&mut results), true);
            assert_eq!(results, []);
            results.clear();
        }
    }
    parser(TestConsumer);
}
<|endoftext|>


<commit_before>//pub const FINGERPRINT_SIZE: usize = 1;
pub const BUCKET_SIZE: usize = 4;

// Fingerprint Size is 1 byte so lets remove the Vec
#[derive(PartialEq, Copy, Clone)]
pub struct Fingerprint (pub u8);

pub struct Bucket (pub Vec<Fingerprint>);

impl Bucket {

    pub fn new() -> Bucket {
        Bucket(vec![])
    }

    pub fn insert(&mut self, fp: Fingerprint) -> bool {
        if self.0.len() < BUCKET_SIZE {
            self.0.push(fp);
            true
        } else {
            false
        }
    }

    pub fn delete(&mut self, fp: Fingerprint) -> bool {
        for i in 0..self.0.len() {
            if self.0[i] == fp {
                self.0.remove(i);
                return true;
            }
        }
        false
    }

    pub fn get_fingerprint_index(&mut self, fp: Fingerprint) -> usize {
        for i in 0..self.0.len() {
            if self.0[i] == fp {
                return i;
            }
        }
        BUCKET_SIZE + 1
    }
}
<commit_msg>cleanup: Bucket `delete` and `new`<commit_after>//pub const FINGERPRINT_SIZE: usize = 1;
pub const BUCKET_SIZE: usize = 4;

// Fingerprint Size is 1 byte so lets remove the Vec
#[derive(PartialEq, Copy, Clone)]
pub struct Fingerprint (pub u8);

pub struct Bucket (pub Vec<Fingerprint>);

impl Bucket {

    pub fn new() -> Bucket {
        Bucket(Vec::with_capacity(BUCKET_SIZE))
    }

    pub fn insert(&mut self, fp: Fingerprint) -> bool {
        if self.0.len() < BUCKET_SIZE {
            self.0.push(fp);
            true
        } else {
            false
        }
    }

    /// Deletes the given fingerprint from the bucket. Since the order inside
    /// the bucket doesn't matter, we can use `swap_remove` to keep the runtime
    /// in O(1).
    pub fn delete(&mut self, fp: Fingerprint) -> bool {
        let pos = self.0.iter().position(|e| *e == fp);
        match pos {
            Some(index) => { self.0.swap_remove(index); true }
            None => false
        }
    }

    pub fn get_fingerprint_index(&mut self, fp: Fingerprint) -> usize {
        for i in 0..self.0.len() {
            if self.0[i] == fp {
                return i;
            }
        }
        BUCKET_SIZE + 1
    }
}
<|endoftext|>


<commit_before>
use gl;
use gl::types::{GLenum,GLsizeiptr,GLvoid};

use std::mem::size_of;

use super::Bind;
use super::util::check_error;

pub struct VertexBuffer;
pub struct IndexBuffer;

struct BufferLifetime {
    pub id: u32
}

impl BufferLifetime {
    fn new() -> BufferLifetime {
        let mut id: u32 = 0;
        unsafe {
            gl::GenBuffers(1, &mut id);
            check_error();
        }
        BufferLifetime { id: id }
    }
}

impl Drop for BufferLifetime {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteBuffers(1, &self.id);
            check_error();
        }
        println!("Buffer::drop");
    }
}

pub struct BufferObject<T> {
    lifetime: BufferLifetime,
    target: GLenum
}

impl<T> BufferObject<T> {
    fn new(target: GLenum) -> BufferObject<T> {
        BufferObject { lifetime: BufferLifetime::new(), target: target }
    }

    pub fn data<D>(&self, data: &[D]) {
        let data_size = (size_of::<D>() * data.len()) as GLsizeiptr;
        unsafe {
            gl::BufferData(self.target, data_size, data.as_ptr() as *const GLvoid, gl::STATIC_DRAW);
            check_error();
        }
    }

    pub fn sub_data<D>(&self, data: &[D], offset: uint) {
        let data_size = (size_of::<D>() * data.len()) as GLsizeiptr;
        unsafe {
            gl::BufferSubData(self.target, data_size, offset as GLsizeiptr, data.as_ptr() as *const GLvoid);
            check_error();
        }
    }
}

impl<T> PartialEq for BufferObject<T> {
    fn eq(&self, other: &BufferObject<T>) -> bool {
        self.lifetime.id == other.lifetime.id
    }
}

impl<T> Bind for BufferObject<T> {
    fn bind(&self) {
        gl::BindBuffer(self.target, self.lifetime.id);
    }

    fn get_id(&self) -> u32 {
        self.lifetime.id
    }
}

pub fn new_vertex_buffer() -> BufferObject<VertexBuffer> {
    BufferObject::new(gl::ARRAY_BUFFER)
}

pub fn new_index_buffer() -> BufferObject<IndexBuffer> {
    BufferObject::new(gl::ELEMENT_ARRAY_BUFFER)
}<commit_msg>Remove debug println.<commit_after>
use gl;
use gl::types::{GLenum,GLsizeiptr,GLvoid};

use std::mem::size_of;

use super::Bind;
use super::util::check_error;

pub struct VertexBuffer;
pub struct IndexBuffer;

struct BufferLifetime {
    pub id: u32
}

impl BufferLifetime {
    fn new() -> BufferLifetime {
        let mut id: u32 = 0;
        unsafe {
            gl::GenBuffers(1, &mut id);
            check_error();
        }
        BufferLifetime { id: id }
    }
}

impl Drop for BufferLifetime {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteBuffers(1, &self.id);
            check_error();
        }
    }
}

pub struct BufferObject<T> {
    lifetime: BufferLifetime,
    target: GLenum
}

impl<T> BufferObject<T> {
    fn new(target: GLenum) -> BufferObject<T> {
        BufferObject { lifetime: BufferLifetime::new(), target: target }
    }

    pub fn data<D>(&self, data: &[D]) {
        let data_size = (size_of::<D>() * data.len()) as GLsizeiptr;
        unsafe {
            gl::BufferData(self.target, data_size, data.as_ptr() as *const GLvoid, gl::STATIC_DRAW);
            check_error();
        }
    }

    pub fn sub_data<D>(&self, data: &[D], offset: uint) {
        let data_size = (size_of::<D>() * data.len()) as GLsizeiptr;
        unsafe {
            gl::BufferSubData(self.target, data_size, offset as GLsizeiptr, data.as_ptr() as *const GLvoid);
            check_error();
        }
    }
}

impl<T> PartialEq for BufferObject<T> {
    fn eq(&self, other: &BufferObject<T>) -> bool {
        self.lifetime.id == other.lifetime.id
    }
}

impl<T> Bind for BufferObject<T> {
    fn bind(&self) {
        gl::BindBuffer(self.target, self.lifetime.id);
    }

    fn get_id(&self) -> u32 {
        self.lifetime.id
    }
}

pub fn new_vertex_buffer() -> BufferObject<VertexBuffer> {
    BufferObject::new(gl::ARRAY_BUFFER)
}

pub fn new_index_buffer() -> BufferObject<IndexBuffer> {
    BufferObject::new(gl::ELEMENT_ARRAY_BUFFER)
}<|endoftext|>


<commit_before>use std::fs;
use std::io;
use std::io::{Read, Write};
use std::collections::HashMap;
use mode::Command;
use std::cmp;
use std::cmp::Ordering;
use std;

use geometry;
use errors::{CrbError, CrbResult};

/// A reference to a position.
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub struct Anchor {
    id: i64,
}

#[derive(PartialEq, Eq)]
pub struct Wrap {
    style: WrapStyle,
    width: i32,
    /// Whether the cursor moves between visual lines or buffer lines.
    vismove: bool,
}

#[derive(PartialEq, Eq)]
#[allow(dead_code)]
pub enum WrapStyle {
    Truncate,
    Hard,
    Word,
}

impl Wrap {
    pub fn default(width: i32) -> Wrap {
        Wrap {
            style: WrapStyle::Truncate,
            width: width,
            vismove: false,
        }
    }
}

/// Private structure containing position data.
#[derive(Clone, PartialOrd)]
struct Position {
    line: i32,
    /// Offset from the beginning of the line.
    /// 0 is before the first character.
    /// len(line) is after the last character.
    offset: i32,
    /// The offset that this will snap back to when moving to a longer line.
    wishful_offset: Option<i32>,
}
impl Position {
    fn new(line: i32, offset: i32) -> Position {
        Position {
            line: line,
            offset: offset,
            wishful_offset: None,
        }
    }
}
impl PartialEq for Position {
    fn eq(&self, other: &Self) -> bool {
        (self.line, self.offset) == (other.line, other.offset)
    }
}

impl Eq for Position {}

impl Ord for Position {
    fn cmp(&self, other: &Self) -> Ordering {
        (self.line, self.offset).cmp(&(other.line, other.offset))
    }
}

struct Line {
    text: String,
}

#[derive(Debug)]
pub struct Display {
    pub x: i32,
    pub y: i32,
    pub symbol: Symbol,
}

#[derive(Debug)]
pub enum Symbol {
    Char(char),
    Anchor(Anchor),
    Void,
}

pub struct Buffer {
    // Invariant: contents.len() > 0
    contents: Vec<Line>,
    pub file_path: Option<String>,
    pub unsaved: bool,
    pub newfile: bool,

    // Map from anchor id to position.
    anchors: HashMap<i64, Position>,
    next_anchor_id: i64,
}

impl Buffer {
    /** Creators **/

    pub fn load_from_file(path: &str) -> Result<Buffer, io::Error> {
        let s = try!(read_file(path));
        let mut contents: Vec<Line> = s.split("\n")
            .map(|x| Line { text: x.to_string() })
            .collect();
        if contents.len() == 0 {
            contents.push(Line { text: "".to_string() });
        }
        let mut buf = Buffer::empty();
        buf.contents = contents;
        buf.file_path = Some(path.to_string());
        buf.newfile = false;
        Ok(buf)
    }

    pub fn new_file(path: &str) -> Buffer {
        let mut buf = Buffer::empty();
        buf.file_path = Some(path.to_string());
        buf
    }

    pub fn empty() -> Buffer {
        Buffer {
            contents: vec![Line { text: "".to_string() }],
            file_path: None,
            unsaved: false,
            newfile: true,
            anchors: HashMap::new(),
            next_anchor_id: 0,
        }
    }

    /** Mutators **/

    pub fn save(&mut self) -> CrbResult<()> {
        // TODO keep track of whether changed
        if let Some(ref file_path) = self.file_path {
            let f = try!(fs::File::create(file_path)
                .map_err(|e| CrbError::new(&format!("error while opening to save {}", e))));
            let mut w = io::BufWriter::new(f);
            for line in &self.contents {
                try!(w.write_all(line.text.as_bytes())
                    .map_err(|e| CrbError::new(&format!("error while saving {}", e))));
                try!(w.write_all(b"\n")
                    .map_err(|e| CrbError::new(&format!("error while saving {}", e))));
            }
            Ok(())
        } else {
            return Err(CrbError::new("cannot save with no file path"));
        }
    }

    pub fn new_anchor(&mut self) -> Anchor {
        let a = Anchor { id: self.new_anchor_id() };
        let p = Position {
            line: 0,
            offset: 0,
            wishful_offset: None,
        };
        self.anchors.insert(a.id, p);
        a
    }

    pub fn move_anchor(&mut self, anchor: &Anchor, m: &Command) -> Result<(), CrbError> {
        let err = CrbError::new("no such anchor");
        let mut p2: Position = try!(self.anchors.get(&anchor.id).ok_or(err)).clone();
        let m = canonicalize_move(m);
        let p3: Position = match m {
            Command::MoveRight(n) => {
                let len = self.line(p2.line).unwrap_or("").chars().count() as i32;
                p2.offset = cmp::min(cmp::max(0, p2.offset + n), len);
                p2.wishful_offset = None;
                p2
            }
            Command::MoveDown(n) => {
                p2.line = cmp::min(cmp::max(0, p2.line + n), self.count_lines());
                let len = self.line(p2.line).unwrap_or("").chars().count() as i32;
                let wish = match p2.wishful_offset {
                    None => p2.offset,
                    Some(x) => x,
                };
                p2.offset = cmp::min(wish, len);
                p2.wishful_offset = match p2.offset < wish {
                    true => Some(wish),
                    false => None,
                };
                p2
            }
            _ => return Err(CrbError::new("unsupported move command")),
        };
        self.anchors.insert(anchor.id, p3);
        Ok(())
    }

    fn new_anchor_id(&mut self) -> i64 {
        self.next_anchor_id += 1;
        self.next_anchor_id - 1
    }

    pub fn insert_text_before(&mut self, anchor: &Anchor, text: char) -> Result<(), CrbError> {
        let err = CrbError::new("no such anchor");
        let pos: Position = try!(self.anchors.get(&anchor.id).ok_or(err)).clone();
        let cur_line = self.contents[pos.line as usize].text.clone();
        let (before, after) = cur_line.split_at(pos.offset as usize);
        if text == '\n' {
            self.contents[pos.line as usize] = Line { text: before.to_string() };
            self.contents.insert((pos.line + 1) as usize, Line { text: after.to_string() });
            self.anchors.insert(anchor.id, Position::new(pos.line + 1, 0));
            Ok(())
        } else {
            self.contents[pos.line as usize] =
                Line { text: before.to_string() + &text.to_string() + &after };
            // TODO move anchors on this line
            self.move_anchor(anchor, &Command::MoveRight(1))
        }
    }

    pub fn delete_at(&mut self, anchor: &Anchor) -> Result<(), CrbError> {
        let err = CrbError::new("no such anchor");
        let mut pos: Position = try!(self.anchors.get(&anchor.id).ok_or(err)).clone();
        let cur_line = self.contents[pos.line as usize].text.clone();
        if pos.offset == 0 && pos.line == 0 {
            Ok(())
        } else if pos.offset == 0 {
            let old_text = self.contents[(pos.line - 1) as usize].text.clone();
            self.contents[(pos.line - 1) as usize] = Line { text: old_text.clone() + &cur_line };
            self.anchors.insert(anchor.id,
                                Position::new(pos.line - 1, old_text.chars().count() as i32));
            self.contents.remove(pos.line as usize);
            Ok(())
        } else {
            let (before, after) = cur_line.split_at(pos.offset as usize);
            let before_argh: String = before.chars().take(before.len() - 1).collect();
            self.contents[pos.line as usize] = Line { text: before_argh.to_string() + after };
            pos.offset -= 1;
            // TODO move anchors on this line
            self.anchors.insert(anchor.id, pos);
            Ok(())
        }
    }

    pub fn clear(&mut self) -> CrbResult<()> {
        self.contents.clear();
        self.contents.push(Line { text: "".to_string() });
        self.anchors = self.anchors
            .iter()
            .map(|(&a, _)| {
                (a,
                 Position {
                    line: 0,
                    offset: 0,
                    wishful_offset: None,
                })
            })
            .collect::<HashMap<_, _>>();
        Ok(())
    }

    /** Observers **/

    pub fn line(&self, i: i32) -> Option<&str> {
        self.contents.get(i as usize).map(|l| l.text.as_str())
    }

    pub fn count_lines(&self) -> i32 {
        self.contents.len() as i32
    }

    /// Calls the closure in scan order on the rectangular area.
    pub fn display<F>(&self, start_line: i32, size: geometry::Size, wrap: Wrap, mut f: F)
        where F: FnMut(&Display)
    {
        if wrap != Wrap::default(wrap.width) {
            panic!("TODO unsupported wrap");
        }

        // TODO horizontal scrolling
        // TODO multi-width characters

        let mut buf_y = start_line as usize;
        let mut buf_x = 0 as usize;
        let mut lines = self.contents.iter().skip(buf_y);
        let mut line_chars = to_chars(lines.next()).peekable();
        let anchors_all = self.all_anchors();
        let mut anchors_iter = anchors_all.iter().peekable();

        for view_y in 0..size.height {
            let mut view_x = 0;
            // Draw line numbers
            if buf_y <= self.contents.len() {
                let col_size = self.contents.len().to_string().chars().count();
                let line_num_str = (buf_y + 1).to_string();
                let mut line_num_chars = line_num_str.chars();
                let offset = col_size - line_num_chars.clone().count();
                if offset < 0 {
                    panic!("Negative line number offset");
                }
                for i in 0..col_size {
                    if offset <= i {
                        let d = Display {
                            x: view_x,
                            y: view_y,
                            symbol: Symbol::Char(line_num_chars.next().unwrap()),
                        };
                        f(&d);
                    }
                    view_x += 1;
                }
            }

            for view_x in (view_x + 1)..size.width {
                let mut did_anchor = false;
                if let Some(tpl) = anchors_iter.peek() {
                    let tpl: &(&i64, &Position) = tpl;
                    let anchor_id: &i64 = tpl.0;
                    let pos: &Position = tpl.1;
                    if (pos.line as usize == buf_y) && (pos.offset as usize == buf_x) {
                        let a = Anchor { id: anchor_id + 0 };
                        let d = Display {
                            x: view_x,
                            y: view_y,
                            symbol: Symbol::Anchor(a),
                        };
                        f(&d);
                        did_anchor = true;
                    }
                }
                if did_anchor {
                    anchors_iter.next();
                }

                let s = match line_chars.next() {
                    Some(c) => Symbol::Char(c),
                    None => Symbol::Void,
                };
                let d = Display {
                    x: view_x,
                    y: view_y,
                    symbol: s,
                };
                f(&d);
                buf_x += 1;
            }
            if line_chars.peek().is_none() {
                // Next buf line
                buf_y += 1;
                buf_x = 0;
                line_chars = to_chars(lines.next()).peekable();
            }
        }
    }

    fn all_anchors(&self) -> Vec<(&i64, &Position)> {
        let mut ans: Vec<(&i64, &Position)> = self.anchors.iter().collect();
        ans.sort_by_key(|x| x.1);
        ans
    }
}

fn to_chars(oli: Option<&Line>) -> std::str::Chars {
    match oli {
        Some(y) => y.text.chars(),
        None => "".chars(),
    }
}

fn read_file(path: &str) -> Result<String, io::Error> {
    let mut f = try!(fs::File::open(path));
    let mut contents = String::new();
    try!(f.read_to_string(&mut contents));
    Ok(contents)
}

fn canonicalize_move(mov: &Command) -> Command {
    match mov.clone() {
        Command::MoveLeft(n) => Command::MoveRight(-n),
        Command::MoveUp(n) => Command::MoveDown(-n),
        m @ _ => m,
    }
}
<commit_msg>delete warning thing (it's rust-checked)<commit_after>use std::fs;
use std::io;
use std::io::{Read, Write};
use std::collections::HashMap;
use mode::Command;
use std::cmp;
use std::cmp::Ordering;
use std;

use geometry;
use errors::{CrbError, CrbResult};

/// A reference to a position.
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub struct Anchor {
    id: i64,
}

#[derive(PartialEq, Eq)]
pub struct Wrap {
    style: WrapStyle,
    width: i32,
    /// Whether the cursor moves between visual lines or buffer lines.
    vismove: bool,
}

#[derive(PartialEq, Eq)]
#[allow(dead_code)]
pub enum WrapStyle {
    Truncate,
    Hard,
    Word,
}

impl Wrap {
    pub fn default(width: i32) -> Wrap {
        Wrap {
            style: WrapStyle::Truncate,
            width: width,
            vismove: false,
        }
    }
}

/// Private structure containing position data.
#[derive(Clone, PartialOrd)]
struct Position {
    line: i32,
    /// Offset from the beginning of the line.
    /// 0 is before the first character.
    /// len(line) is after the last character.
    offset: i32,
    /// The offset that this will snap back to when moving to a longer line.
    wishful_offset: Option<i32>,
}
impl Position {
    fn new(line: i32, offset: i32) -> Position {
        Position {
            line: line,
            offset: offset,
            wishful_offset: None,
        }
    }
}
impl PartialEq for Position {
    fn eq(&self, other: &Self) -> bool {
        (self.line, self.offset) == (other.line, other.offset)
    }
}

impl Eq for Position {}

impl Ord for Position {
    fn cmp(&self, other: &Self) -> Ordering {
        (self.line, self.offset).cmp(&(other.line, other.offset))
    }
}

struct Line {
    text: String,
}

#[derive(Debug)]
pub struct Display {
    pub x: i32,
    pub y: i32,
    pub symbol: Symbol,
}

#[derive(Debug)]
pub enum Symbol {
    Char(char),
    Anchor(Anchor),
    Void,
}

pub struct Buffer {
    // Invariant: contents.len() > 0
    contents: Vec<Line>,
    pub file_path: Option<String>,
    pub unsaved: bool,
    pub newfile: bool,

    // Map from anchor id to position.
    anchors: HashMap<i64, Position>,
    next_anchor_id: i64,
}

impl Buffer {
    /** Creators **/

    pub fn load_from_file(path: &str) -> Result<Buffer, io::Error> {
        let s = try!(read_file(path));
        let mut contents: Vec<Line> = s.split("\n")
            .map(|x| Line { text: x.to_string() })
            .collect();
        if contents.len() == 0 {
            contents.push(Line { text: "".to_string() });
        }
        let mut buf = Buffer::empty();
        buf.contents = contents;
        buf.file_path = Some(path.to_string());
        buf.newfile = false;
        Ok(buf)
    }

    pub fn new_file(path: &str) -> Buffer {
        let mut buf = Buffer::empty();
        buf.file_path = Some(path.to_string());
        buf
    }

    pub fn empty() -> Buffer {
        Buffer {
            contents: vec![Line { text: "".to_string() }],
            file_path: None,
            unsaved: false,
            newfile: true,
            anchors: HashMap::new(),
            next_anchor_id: 0,
        }
    }

    /** Mutators **/

    pub fn save(&mut self) -> CrbResult<()> {
        // TODO keep track of whether changed
        if let Some(ref file_path) = self.file_path {
            let f = try!(fs::File::create(file_path)
                .map_err(|e| CrbError::new(&format!("error while opening to save {}", e))));
            let mut w = io::BufWriter::new(f);
            for line in &self.contents {
                try!(w.write_all(line.text.as_bytes())
                    .map_err(|e| CrbError::new(&format!("error while saving {}", e))));
                try!(w.write_all(b"\n")
                    .map_err(|e| CrbError::new(&format!("error while saving {}", e))));
            }
            Ok(())
        } else {
            return Err(CrbError::new("cannot save with no file path"));
        }
    }

    pub fn new_anchor(&mut self) -> Anchor {
        let a = Anchor { id: self.new_anchor_id() };
        let p = Position {
            line: 0,
            offset: 0,
            wishful_offset: None,
        };
        self.anchors.insert(a.id, p);
        a
    }

    pub fn move_anchor(&mut self, anchor: &Anchor, m: &Command) -> Result<(), CrbError> {
        let err = CrbError::new("no such anchor");
        let mut p2: Position = try!(self.anchors.get(&anchor.id).ok_or(err)).clone();
        let m = canonicalize_move(m);
        let p3: Position = match m {
            Command::MoveRight(n) => {
                let len = self.line(p2.line).unwrap_or("").chars().count() as i32;
                p2.offset = cmp::min(cmp::max(0, p2.offset + n), len);
                p2.wishful_offset = None;
                p2
            }
            Command::MoveDown(n) => {
                p2.line = cmp::min(cmp::max(0, p2.line + n), self.count_lines());
                let len = self.line(p2.line).unwrap_or("").chars().count() as i32;
                let wish = match p2.wishful_offset {
                    None => p2.offset,
                    Some(x) => x,
                };
                p2.offset = cmp::min(wish, len);
                p2.wishful_offset = match p2.offset < wish {
                    true => Some(wish),
                    false => None,
                };
                p2
            }
            _ => return Err(CrbError::new("unsupported move command")),
        };
        self.anchors.insert(anchor.id, p3);
        Ok(())
    }

    fn new_anchor_id(&mut self) -> i64 {
        self.next_anchor_id += 1;
        self.next_anchor_id - 1
    }

    pub fn insert_text_before(&mut self, anchor: &Anchor, text: char) -> Result<(), CrbError> {
        let err = CrbError::new("no such anchor");
        let pos: Position = try!(self.anchors.get(&anchor.id).ok_or(err)).clone();
        let cur_line = self.contents[pos.line as usize].text.clone();
        let (before, after) = cur_line.split_at(pos.offset as usize);
        if text == '\n' {
            self.contents[pos.line as usize] = Line { text: before.to_string() };
            self.contents.insert((pos.line + 1) as usize, Line { text: after.to_string() });
            self.anchors.insert(anchor.id, Position::new(pos.line + 1, 0));
            Ok(())
        } else {
            self.contents[pos.line as usize] =
                Line { text: before.to_string() + &text.to_string() + &after };
            // TODO move anchors on this line
            self.move_anchor(anchor, &Command::MoveRight(1))
        }
    }

    pub fn delete_at(&mut self, anchor: &Anchor) -> Result<(), CrbError> {
        let err = CrbError::new("no such anchor");
        let mut pos: Position = try!(self.anchors.get(&anchor.id).ok_or(err)).clone();
        let cur_line = self.contents[pos.line as usize].text.clone();
        if pos.offset == 0 && pos.line == 0 {
            Ok(())
        } else if pos.offset == 0 {
            let old_text = self.contents[(pos.line - 1) as usize].text.clone();
            self.contents[(pos.line - 1) as usize] = Line { text: old_text.clone() + &cur_line };
            self.anchors.insert(anchor.id,
                                Position::new(pos.line - 1, old_text.chars().count() as i32));
            self.contents.remove(pos.line as usize);
            Ok(())
        } else {
            let (before, after) = cur_line.split_at(pos.offset as usize);
            let before_argh: String = before.chars().take(before.len() - 1).collect();
            self.contents[pos.line as usize] = Line { text: before_argh.to_string() + after };
            pos.offset -= 1;
            // TODO move anchors on this line
            self.anchors.insert(anchor.id, pos);
            Ok(())
        }
    }

    pub fn clear(&mut self) -> CrbResult<()> {
        self.contents.clear();
        self.contents.push(Line { text: "".to_string() });
        self.anchors = self.anchors
            .iter()
            .map(|(&a, _)| {
                (a,
                 Position {
                    line: 0,
                    offset: 0,
                    wishful_offset: None,
                })
            })
            .collect::<HashMap<_, _>>();
        Ok(())
    }

    /** Observers **/

    pub fn line(&self, i: i32) -> Option<&str> {
        self.contents.get(i as usize).map(|l| l.text.as_str())
    }

    pub fn count_lines(&self) -> i32 {
        self.contents.len() as i32
    }

    /// Calls the closure in scan order on the rectangular area.
    pub fn display<F>(&self, start_line: i32, size: geometry::Size, wrap: Wrap, mut f: F)
        where F: FnMut(&Display)
    {
        if wrap != Wrap::default(wrap.width) {
            panic!("TODO unsupported wrap");
        }

        // TODO horizontal scrolling
        // TODO multi-width characters

        let mut buf_y = start_line as usize;
        let mut buf_x = 0 as usize;
        let mut lines = self.contents.iter().skip(buf_y);
        let mut line_chars = to_chars(lines.next()).peekable();
        let anchors_all = self.all_anchors();
        let mut anchors_iter = anchors_all.iter().peekable();

        for view_y in 0..size.height {
            let mut view_x = 0;
            // Draw line numbers
            if buf_y <= self.contents.len() {
                let col_size = self.contents.len().to_string().chars().count();
                let line_num_str = (buf_y + 1).to_string();
                let mut line_num_chars = line_num_str.chars();
                let offset = col_size - line_num_chars.clone().count();
                for i in 0..col_size {
                    if offset <= i {
                        let d = Display {
                            x: view_x,
                            y: view_y,
                            symbol: Symbol::Char(line_num_chars.next().unwrap()),
                        };
                        f(&d);
                    }
                    view_x += 1;
                }
            }

            for view_x in (view_x + 1)..size.width {
                let mut did_anchor = false;
                if let Some(tpl) = anchors_iter.peek() {
                    let tpl: &(&i64, &Position) = tpl;
                    let anchor_id: &i64 = tpl.0;
                    let pos: &Position = tpl.1;
                    if (pos.line as usize == buf_y) && (pos.offset as usize == buf_x) {
                        let a = Anchor { id: anchor_id + 0 };
                        let d = Display {
                            x: view_x,
                            y: view_y,
                            symbol: Symbol::Anchor(a),
                        };
                        f(&d);
                        did_anchor = true;
                    }
                }
                if did_anchor {
                    anchors_iter.next();
                }

                let s = match line_chars.next() {
                    Some(c) => Symbol::Char(c),
                    None => Symbol::Void,
                };
                let d = Display {
                    x: view_x,
                    y: view_y,
                    symbol: s,
                };
                f(&d);
                buf_x += 1;
            }
            if line_chars.peek().is_none() {
                // Next buf line
                buf_y += 1;
                buf_x = 0;
                line_chars = to_chars(lines.next()).peekable();
            }
        }
    }

    fn all_anchors(&self) -> Vec<(&i64, &Position)> {
        let mut ans: Vec<(&i64, &Position)> = self.anchors.iter().collect();
        ans.sort_by_key(|x| x.1);
        ans
    }
}

fn to_chars(oli: Option<&Line>) -> std::str::Chars {
    match oli {
        Some(y) => y.text.chars(),
        None => "".chars(),
    }
}

fn read_file(path: &str) -> Result<String, io::Error> {
    let mut f = try!(fs::File::open(path));
    let mut contents = String::new();
    try!(f.read_to_string(&mut contents));
    Ok(contents)
}

fn canonicalize_move(mov: &Command) -> Command {
    match mov.clone() {
        Command::MoveLeft(n) => Command::MoveRight(-n),
        Command::MoveUp(n) => Command::MoveDown(-n),
        m @ _ => m,
    }
}
<|endoftext|>


<commit_before>use files::dump;

pub struct Token<'a>
{
    pub name: &'a str,
    pub range: (usize, usize),
    pub value: String,
}

impl <'a> Token<'a>
{
    pub fn clone(&self) -> Token<'a>
    {
        Token
        {
            name: self.name.clone(),
            range: self.range.clone(),
            value: self.value.clone(),
        }
    }
}

pub trait Printable
{
    fn print_to(&self, file_path: &str, console_out: bool);

    fn format_for_print(&self, console_out: bool) -> String;
}

impl <'a> Printable for Vec<Token<'a>>
{
    fn print_to(&self, file_path: &str, console_out: bool)
    {
        let lexed_token_string = self.format_for_print(console_out);
        if file_path.len() > 0 { dump(file_path, lexed_token_string); }
    }

    fn format_for_print(&self, console_out: bool) -> String
    {
        let mut lexed_token_string: String = String::new();

        for token in self.iter()
        {
            lexed_token_string.push_str(token.name);
            lexed_token_string.push_str("\t");
            lexed_token_string.push_str(&*token.value);
            lexed_token_string.push_str("\n");

            if console_out { println!("\t{}\t{:?}\t{}", token.name, token.range, token.value); }
        }

        lexed_token_string
    }
}
<commit_msg>Suppress irrelevant warning<commit_after>use files::dump;

pub struct Token<'a>
{
    pub name: &'a str,
    pub range: (usize, usize),
    pub value: String,
}

impl <'a> Token<'a>
{
    #[allow(dead_code)]
    pub fn clone(&self) -> Token<'a>
    {
        Token
        {
            name: self.name.clone(),
            range: self.range.clone(),
            value: self.value.clone(),
        }
    }
}

pub trait Printable
{
    fn print_to(&self, file_path: &str, console_out: bool);

    fn format_for_print(&self, console_out: bool) -> String;
}

impl <'a> Printable for Vec<Token<'a>>
{
    fn print_to(&self, file_path: &str, console_out: bool)
    {
        let lexed_token_string = self.format_for_print(console_out);
        if file_path.len() > 0 { dump(file_path, lexed_token_string); }
    }

    fn format_for_print(&self, console_out: bool) -> String
    {
        let mut lexed_token_string: String = String::new();

        for token in self.iter()
        {
            lexed_token_string.push_str(token.name);
            lexed_token_string.push_str("\t");
            lexed_token_string.push_str(&*token.value);
            lexed_token_string.push_str("\n");

            if console_out { println!("\t{}\t{:?}\t{}", token.name, token.range, token.value); }
        }

        lexed_token_string
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove empty scene.rs<commit_after><|endoftext|>


<commit_before>pub use self::{
	browse::*,
	connection::*,
	enumerate_domains::*,
	query_record::*,
	records::Record,
	register::*,
	resolve::*,
	resolve_host::*,
};

mod browse;
mod connection;
mod enumerate_domains;
mod query_record;
mod records;
mod register;
mod resolve;
mod resolve_host;

use crate::dns_consts::{
	Class,
	Type,
};

/// Purge record from cache
///
/// See [`DNSServiceReconfirmRecord`](https://developer.apple.com/documentation/dnssd/1804726-dnsservicereconfirmrecord).
pub fn reconfirm_record(
	interface: crate::interface::Interface,
	fullname: &str,
	rr_type: Type,
	rr_class: Class,
	rdata: &[u8],
) -> ::std::io::Result<()> {
	crate::init();

	let fullname = crate::cstr::CStr::from(&fullname)?;
	crate::inner::reconfirm_record(
		0, // no flags
		interface.into_raw(),
		&fullname,
		rr_type,
		rr_class,
		rdata,
	);

	Ok(())
}

/// Full name consiting of (up to) three parts
pub struct FullName<'a> {
	/// (unescaped) service name (becomes single label in full name)
	pub service: Option<&'a str>,
	/// registration type (valid names don't need escaping)
	pub reg_type: &'a str,
	/// (escaped) domain name (most names don't need escaping)
	pub domain: &'a str,
}

impl<'a> FullName<'a> {
	/// Escape and concatenate all three parts to a full name
	///
	/// See [`DNSServiceConstructFullName`](https://developer.apple.com/documentation/dnssd/1804753-dnsserviceconstructfullname)
	pub fn construct(&self) -> ::std::io::Result<String> {
		use std::io;

		let service = crate::cstr::NullableCStr::from(&self.service)?;
		let reg_type = crate::cstr::CStr::from(&self.reg_type)?;
		let domain = crate::cstr::CStr::from(&self.domain)?;

		const SIZE: usize = crate::ffi::MAX_DOMAIN_NAME + 200;
		let mut buf: Vec<u8> = Vec::new();
		buf.reserve(SIZE);
		let len = unsafe {
			crate::ffi::DNSServiceConstructFullName(
				buf.as_mut_ptr() as *mut i8,
				service.as_ptr(),
				reg_type.as_ptr(),
				domain.as_ptr(),
			)
		};

		if len < 0 {
			return Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid input"));
		}

		unsafe {
			buf.set_len(len as usize);
		}

		String::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
	}
}
<commit_msg>use c_char for casting buffer pointer (fixes #15)<commit_after>pub use self::{
	browse::*,
	connection::*,
	enumerate_domains::*,
	query_record::*,
	records::Record,
	register::*,
	resolve::*,
	resolve_host::*,
};

mod browse;
mod connection;
mod enumerate_domains;
mod query_record;
mod records;
mod register;
mod resolve;
mod resolve_host;

use crate::dns_consts::{
	Class,
	Type,
};
use std::os::raw::c_char;

/// Purge record from cache
///
/// See [`DNSServiceReconfirmRecord`](https://developer.apple.com/documentation/dnssd/1804726-dnsservicereconfirmrecord).
pub fn reconfirm_record(
	interface: crate::interface::Interface,
	fullname: &str,
	rr_type: Type,
	rr_class: Class,
	rdata: &[u8],
) -> ::std::io::Result<()> {
	crate::init();

	let fullname = crate::cstr::CStr::from(&fullname)?;
	crate::inner::reconfirm_record(
		0, // no flags
		interface.into_raw(),
		&fullname,
		rr_type,
		rr_class,
		rdata,
	);

	Ok(())
}

/// Full name consiting of (up to) three parts
pub struct FullName<'a> {
	/// (unescaped) service name (becomes single label in full name)
	pub service: Option<&'a str>,
	/// registration type (valid names don't need escaping)
	pub reg_type: &'a str,
	/// (escaped) domain name (most names don't need escaping)
	pub domain: &'a str,
}

impl<'a> FullName<'a> {
	/// Escape and concatenate all three parts to a full name
	///
	/// See [`DNSServiceConstructFullName`](https://developer.apple.com/documentation/dnssd/1804753-dnsserviceconstructfullname)
	pub fn construct(&self) -> ::std::io::Result<String> {
		use std::io;

		let service = crate::cstr::NullableCStr::from(&self.service)?;
		let reg_type = crate::cstr::CStr::from(&self.reg_type)?;
		let domain = crate::cstr::CStr::from(&self.domain)?;

		const SIZE: usize = crate::ffi::MAX_DOMAIN_NAME + 200;
		let mut buf: Vec<u8> = Vec::new();
		buf.reserve(SIZE);
		let len = unsafe {
			crate::ffi::DNSServiceConstructFullName(
				buf.as_mut_ptr() as *mut c_char,
				service.as_ptr(),
				reg_type.as_ptr(),
				domain.as_ptr(),
			)
		};

		if len < 0 {
			return Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid input"));
		}

		unsafe {
			buf.set_len(len as usize);
		}

		String::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
	}
}
<|endoftext|>


<commit_before>// Queries.
use crate::bounding_volume::{BoundingSphere, AABB};
use crate::math::{Isometry, Vector};
use na::{self, RealField, Unit};
use crate::query::{PointQuery, RayCast};
use crate::shape::{CompositeShape, ConvexPolyhedron, DeformableShape, FeatureId, SupportMap};
use std::ops::Deref;
use std::sync::Arc;
use downcast_rs::Downcast;

pub trait ShapeClone<N: RealField> {
    fn clone_box(&self) -> Box<Shape<N>> {
        unimplemented!()
    }
}

impl<N: RealField, T: 'static + Shape<N> + Clone> ShapeClone<N> for T {
    fn clone_box(&self) -> Box<Shape<N>> {
        Box::new(self.clone())
    }
}

/// Trait implemented by all shapes supported by ncollide.
///
/// This allows dynamic inspection of the shape capabilities.
pub trait Shape<N: RealField>: Send + Sync + Downcast + ShapeClone<N> {
    /// The AABB of `self` transformed by `m`.
    #[inline]
    fn aabb(&self, m: &Isometry<N>) -> AABB<N>;

    /// The AABB of `self`.
    #[inline]
    fn local_aabb(&self) -> AABB<N> {
        self.aabb(&Isometry::identity())
    }

    /// The bounding sphere of `self` transformed by `m`.
    #[inline]
    fn bounding_sphere(&self, m: &Isometry<N>) -> BoundingSphere<N> {
        let aabb = self.aabb(m);
        BoundingSphere::new(aabb.center(), aabb.half_extents().norm())
    }

    /// The bounding sphere of `self`.
    #[inline]
    fn local_bounding_sphere(&self) -> BoundingSphere<N> {
        let aabb = self.local_aabb();
        BoundingSphere::new(aabb.center(), aabb.half_extents().norm())
    }

    /// Check if if the feature `_feature` of the `i-th` subshape of `self` transformed by `m` has a tangent
    /// cone that contains `dir` at the point `pt`.
    // NOTE: for the moment, we assume the tangent cone is the same for the whole feature.
    #[inline]
    fn tangent_cone_contains_dir(
        &self,
        _feature: FeatureId,
        _m: &Isometry<N>,
        _deformations: Option<&[N]>,
        _dir: &Unit<Vector<N>>,
    ) -> bool;

    /// Returns the id of the subshape containing the specified feature.
    ///
    /// If several subshape contains the same feature, any one is returned.
    fn subshape_containing_feature(&self, _i: FeatureId) -> usize {
        0
    }

    /// The `RayCast` implementation of `self`.
    #[inline]
    fn as_ray_cast(&self) -> Option<&RayCast<N>> {
        None
    }

    /// The `PointQuery` implementation of `self`.
    #[inline]
    fn as_point_query(&self) -> Option<&PointQuery<N>> {
        None
    }

    /// The convex polyhedron representation of `self` if applicable.
    #[inline]
    fn as_convex_polyhedron(&self) -> Option<&ConvexPolyhedron<N>> {
        None
    }

    /// The support mapping of `self` if applicable.
    #[inline]
    fn as_support_map(&self) -> Option<&SupportMap<N>> {
        None
    }

    /// The composite shape representation of `self` if applicable.
    #[inline]
    fn as_composite_shape(&self) -> Option<&CompositeShape<N>> {
        None
    }

    /// The deformable shape representation of `self` if applicable.
    #[inline]
    fn as_deformable_shape(&self) -> Option<&DeformableShape<N>> {
        None
    }

    /// The mutable deformable shape representation of `self` if applicable.
    #[inline]
    fn as_deformable_shape_mut(&mut self) -> Option<&mut DeformableShape<N>> {
        None
    }

    /// Whether `self` uses a convex polyhedron representation.
    #[inline]
    fn is_convex_polyhedron(&self) -> bool {
        self.as_convex_polyhedron().is_some()
    }

    /// Whether `self` uses a support-mapping based representation.
    #[inline]
    fn is_support_map(&self) -> bool {
        self.as_support_map().is_some()
    }

    /// Whether `self` uses a composite shape-based representation.
    #[inline]
    fn is_composite_shape(&self) -> bool {
        self.as_composite_shape().is_some()
    }

    /// Whether `self` uses a composite shape-based representation.
    #[inline]
    fn is_deformable_shape(&self) -> bool {
        self.as_deformable_shape().is_some()
    }
}

impl_downcast!(Shape<N> where N: RealField);

/// Trait for casting shapes to its exact represetation.
impl<N: RealField> Shape<N> {
    /// Tests if this shape has a specific type `T`.
    #[inline]
    pub fn is_shape<T: Shape<N>>(&self) -> bool {
        self.is::<T>()
    }

    /// Performs the cast.
    #[inline]
    pub fn as_shape<T: Shape<N>>(&self) -> Option<&T> {
        self.downcast_ref()
    }
}

impl<N: RealField> Clone for Box<Shape<N>> {
    fn clone(&self) -> Box<Shape<N>> {
        self.clone_box()
    }
}

/// A shared handle to an abstract shape.
///
/// This can be mutated using COW.
#[derive(Clone)]
pub struct ShapeHandle<N: RealField>(Arc<Box<Shape<N>>>);

impl<N: RealField> ShapeHandle<N> {
    /// Creates a sharable shape handle from a shape.
    #[inline]
    pub fn new<S: Shape<N> + Clone>(shape: S) -> ShapeHandle<N> {
        ShapeHandle(Arc::new(Box::new(shape)))
    }

    pub(crate) fn make_mut(&mut self) -> &mut Shape<N> {
        &mut **Arc::make_mut(&mut self.0)
    }
}

impl<N: RealField> AsRef<Shape<N>> for ShapeHandle<N> {
    #[inline]
    fn as_ref(&self) -> &Shape<N> {
        &*self.deref()
    }
}

impl<N: RealField> Deref for ShapeHandle<N> {
    type Target = Shape<N>;

    #[inline]
    fn deref(&self) -> &Shape<N> {
        &**self.0.deref()
    }
}<commit_msg>Remove extraneous Clone bound on ShapeHandle::new()<commit_after>// Queries.
use crate::bounding_volume::{BoundingSphere, AABB};
use crate::math::{Isometry, Vector};
use na::{self, RealField, Unit};
use crate::query::{PointQuery, RayCast};
use crate::shape::{CompositeShape, ConvexPolyhedron, DeformableShape, FeatureId, SupportMap};
use std::ops::Deref;
use std::sync::Arc;
use downcast_rs::Downcast;

pub trait ShapeClone<N: RealField> {
    fn clone_box(&self) -> Box<Shape<N>> {
        unimplemented!()
    }
}

impl<N: RealField, T: 'static + Shape<N> + Clone> ShapeClone<N> for T {
    fn clone_box(&self) -> Box<Shape<N>> {
        Box::new(self.clone())
    }
}

/// Trait implemented by all shapes supported by ncollide.
///
/// This allows dynamic inspection of the shape capabilities.
pub trait Shape<N: RealField>: Send + Sync + Downcast + ShapeClone<N> {
    /// The AABB of `self` transformed by `m`.
    #[inline]
    fn aabb(&self, m: &Isometry<N>) -> AABB<N>;

    /// The AABB of `self`.
    #[inline]
    fn local_aabb(&self) -> AABB<N> {
        self.aabb(&Isometry::identity())
    }

    /// The bounding sphere of `self` transformed by `m`.
    #[inline]
    fn bounding_sphere(&self, m: &Isometry<N>) -> BoundingSphere<N> {
        let aabb = self.aabb(m);
        BoundingSphere::new(aabb.center(), aabb.half_extents().norm())
    }

    /// The bounding sphere of `self`.
    #[inline]
    fn local_bounding_sphere(&self) -> BoundingSphere<N> {
        let aabb = self.local_aabb();
        BoundingSphere::new(aabb.center(), aabb.half_extents().norm())
    }

    /// Check if if the feature `_feature` of the `i-th` subshape of `self` transformed by `m` has a tangent
    /// cone that contains `dir` at the point `pt`.
    // NOTE: for the moment, we assume the tangent cone is the same for the whole feature.
    #[inline]
    fn tangent_cone_contains_dir(
        &self,
        _feature: FeatureId,
        _m: &Isometry<N>,
        _deformations: Option<&[N]>,
        _dir: &Unit<Vector<N>>,
    ) -> bool;

    /// Returns the id of the subshape containing the specified feature.
    ///
    /// If several subshape contains the same feature, any one is returned.
    fn subshape_containing_feature(&self, _i: FeatureId) -> usize {
        0
    }

    /// The `RayCast` implementation of `self`.
    #[inline]
    fn as_ray_cast(&self) -> Option<&RayCast<N>> {
        None
    }

    /// The `PointQuery` implementation of `self`.
    #[inline]
    fn as_point_query(&self) -> Option<&PointQuery<N>> {
        None
    }

    /// The convex polyhedron representation of `self` if applicable.
    #[inline]
    fn as_convex_polyhedron(&self) -> Option<&ConvexPolyhedron<N>> {
        None
    }

    /// The support mapping of `self` if applicable.
    #[inline]
    fn as_support_map(&self) -> Option<&SupportMap<N>> {
        None
    }

    /// The composite shape representation of `self` if applicable.
    #[inline]
    fn as_composite_shape(&self) -> Option<&CompositeShape<N>> {
        None
    }

    /// The deformable shape representation of `self` if applicable.
    #[inline]
    fn as_deformable_shape(&self) -> Option<&DeformableShape<N>> {
        None
    }

    /// The mutable deformable shape representation of `self` if applicable.
    #[inline]
    fn as_deformable_shape_mut(&mut self) -> Option<&mut DeformableShape<N>> {
        None
    }

    /// Whether `self` uses a convex polyhedron representation.
    #[inline]
    fn is_convex_polyhedron(&self) -> bool {
        self.as_convex_polyhedron().is_some()
    }

    /// Whether `self` uses a support-mapping based representation.
    #[inline]
    fn is_support_map(&self) -> bool {
        self.as_support_map().is_some()
    }

    /// Whether `self` uses a composite shape-based representation.
    #[inline]
    fn is_composite_shape(&self) -> bool {
        self.as_composite_shape().is_some()
    }

    /// Whether `self` uses a composite shape-based representation.
    #[inline]
    fn is_deformable_shape(&self) -> bool {
        self.as_deformable_shape().is_some()
    }
}

impl_downcast!(Shape<N> where N: RealField);

/// Trait for casting shapes to its exact represetation.
impl<N: RealField> Shape<N> {
    /// Tests if this shape has a specific type `T`.
    #[inline]
    pub fn is_shape<T: Shape<N>>(&self) -> bool {
        self.is::<T>()
    }

    /// Performs the cast.
    #[inline]
    pub fn as_shape<T: Shape<N>>(&self) -> Option<&T> {
        self.downcast_ref()
    }
}

impl<N: RealField> Clone for Box<Shape<N>> {
    fn clone(&self) -> Box<Shape<N>> {
        self.clone_box()
    }
}

/// A shared handle to an abstract shape.
///
/// This can be mutated using COW.
#[derive(Clone)]
pub struct ShapeHandle<N: RealField>(Arc<Box<Shape<N>>>);

impl<N: RealField> ShapeHandle<N> {
    /// Creates a sharable shape handle from a shape.
    #[inline]
    pub fn new<S: Shape<N>>(shape: S) -> ShapeHandle<N> {
        ShapeHandle(Arc::new(Box::new(shape)))
    }

    pub(crate) fn make_mut(&mut self) -> &mut Shape<N> {
        &mut **Arc::make_mut(&mut self.0)
    }
}

impl<N: RealField> AsRef<Shape<N>> for ShapeHandle<N> {
    #[inline]
    fn as_ref(&self) -> &Shape<N> {
        &*self.deref()
    }
}

impl<N: RealField> Deref for ShapeHandle<N> {
    type Target = Shape<N>;

    #[inline]
    fn deref(&self) -> &Shape<N> {
        &**self.0.deref()
    }
}<|endoftext|>


<commit_before>use error::Result;
use evaluator::Evaluator;
use event::Event;
use top_level_event::TopLevelEvent;
use sass::rule::SassRule;
use sass::variable::SassVariable;
use sass::number_value::NumberValue;
use sass::value_part::ValuePart;
use std::collections::HashMap;
use std::borrow::Cow;

pub struct Substituter<'vm, I> {
    tokenizer: I,
    variables: HashMap<String, ValuePart<'vm>>,
}

impl<'vm, I> Substituter<'vm, I> {
    pub fn new(tokenizer: I) -> Substituter<'vm, I> {
        Substituter {
            tokenizer: tokenizer,
            variables: HashMap::new(),
        }
    }
}

impl<'a, I> Iterator for Substituter<'a, I>
    where I: Iterator<Item = Result<TopLevelEvent<'a>>>
{
    type Item = Result<TopLevelEvent<'a>>;

    fn next(&mut self) -> Option<Result<TopLevelEvent<'a>>> {
        match self.tokenizer.next() {
            Some(Ok(TopLevelEvent::Variable(SassVariable { name, value }))) => {
                let val = match owned_evaluated_value(value, &self.variables) {
                    Ok(v) => v,
                    Err(e) => return Some(Err(e)),
                };
                self.variables.insert((*name).to_string(), val);
                self.next()
            },
            Some(Ok(TopLevelEvent::Rule(sass_rule))) => {
                let replaced = match replace_children_in_scope(
                    sass_rule.children, self.variables.clone()
                ) {
                    Ok(children) => children,
                    Err(e) => return Some(Err(e)),
                };

                Some(Ok(TopLevelEvent::Rule(SassRule {
                    children: replaced, ..sass_rule
                })))
            },
            other => other,
        }
    }
}

fn replace_children_in_scope<'b>(children: Vec<Event<'b>>, mut local_variables: HashMap<String, ValuePart<'b>>) -> Result<Vec<Event<'b>>> {
    children.into_iter().filter_map(|c|
        match c {
            Event::Variable(SassVariable { name, value }) => {
                let val = match owned_evaluated_value(value, &local_variables) {
                    Ok(v) => v,
                    Err(e) => return Some(Err(e)),
                };
                local_variables.insert((*name).to_string(), val);
                None
            },
            Event::UnevaluatedProperty(name, value) => {
                let mut ev = Evaluator::new_from_string(&value);
                let ev_res = match ev.evaluate(&local_variables) {
                    Ok(s)  => s.into_owned(),
                    Err(e) => return Some(Err(e)),
                };

                Some(Ok(Event::Property(
                    name,
                    ev_res,
                )))
            },
            Event::ChildRule(rule) => {
                let res = match replace_children_in_scope(
                    rule.children, local_variables.clone()
                ) {
                    Ok(children) => children,
                    Err(e) => return Some(Err(e)),
                };
                Some(Ok(Event::ChildRule(SassRule {
                    children: res, ..rule
                })))
            },
            other => Some(Ok(other))
        }
    ).collect()
}

fn owned_evaluated_value<'a>(
    value: Cow<'a, str>,
    variables: &HashMap<String, ValuePart<'a>>) -> Result<ValuePart<'a>> {

    let value_part = match value {
        Cow::Borrowed(v) => {
            try!(Evaluator::new_from_string(&v).evaluate(variables))
        },
        Cow::Owned(v) => {
            try!(Evaluator::new_from_string(&v).evaluate(variables)).into_owned()
        },
    };
    Ok(match value_part {
        ValuePart::Number(nv) => ValuePart::Number(NumberValue { computed: true, ..nv }),
        other => other,
    })
}
<commit_msg>Keep track of mixin definitions we've seen<commit_after>use error::Result;
use evaluator::Evaluator;
use event::Event;
use top_level_event::TopLevelEvent;
use sass::rule::SassRule;
use sass::variable::SassVariable;
use sass::number_value::NumberValue;
use sass::value_part::ValuePart;
use sass::mixin::{SassMixin, SassMixinCall};

use std::collections::HashMap;
use std::borrow::Cow;

pub struct Substituter<'vm, I> {
    tokenizer: I,
    variables: HashMap<String, ValuePart<'vm>>,
    mixins:    HashMap<String, SassMixin<'vm>>,
}

impl<'vm, I> Substituter<'vm, I> {
    pub fn new(tokenizer: I) -> Substituter<'vm, I> {
        Substituter {
            tokenizer: tokenizer,
            variables: HashMap::new(),
            mixins:    HashMap::new(),
        }
    }
}

impl<'a, I> Iterator for Substituter<'a, I>
    where I: Iterator<Item = Result<TopLevelEvent<'a>>>
{
    type Item = Result<TopLevelEvent<'a>>;

    fn next(&mut self) -> Option<Result<TopLevelEvent<'a>>> {
        match self.tokenizer.next() {
            Some(Ok(TopLevelEvent::Variable(SassVariable { name, value }))) => {
                let val = match owned_evaluated_value(value, &self.variables) {
                    Ok(v) => v,
                    Err(e) => return Some(Err(e)),
                };
                self.variables.insert((*name).to_string(), val);
                self.next()
            },
            Some(Ok(TopLevelEvent::Mixin(mixin))) => {
                self.mixins.insert((mixin.name).to_string(), mixin);
                self.next()
            },
            Some(Ok(TopLevelEvent::Rule(sass_rule))) => {
                let replaced = match replace_children_in_scope(
                    sass_rule.children, self.variables.clone()
                ) {
                    Ok(children) => children,
                    Err(e) => return Some(Err(e)),
                };

                Some(Ok(TopLevelEvent::Rule(SassRule {
                    children: replaced, ..sass_rule
                })))
            },
            Some(Ok(TopLevelEvent::MixinCall(mixin_call))) => unimplemented!(),
            other => other,
        }
    }
}

fn replace_children_in_scope<'b>(children: Vec<Event<'b>>, mut local_variables: HashMap<String, ValuePart<'b>>) -> Result<Vec<Event<'b>>> {
    children.into_iter().filter_map(|c|
        match c {
            Event::Variable(SassVariable { name, value }) => {
                let val = match owned_evaluated_value(value, &local_variables) {
                    Ok(v) => v,
                    Err(e) => return Some(Err(e)),
                };
                local_variables.insert((*name).to_string(), val);
                None
            },
            Event::UnevaluatedProperty(name, value) => {
                let mut ev = Evaluator::new_from_string(&value);
                let ev_res = match ev.evaluate(&local_variables) {
                    Ok(s)  => s.into_owned(),
                    Err(e) => return Some(Err(e)),
                };

                Some(Ok(Event::Property(
                    name,
                    ev_res,
                )))
            },
            Event::ChildRule(rule) => {
                let res = match replace_children_in_scope(
                    rule.children, local_variables.clone()
                ) {
                    Ok(children) => children,
                    Err(e) => return Some(Err(e)),
                };
                Some(Ok(Event::ChildRule(SassRule {
                    children: res, ..rule
                })))
            },
            other => Some(Ok(other))
        }
    ).collect()
}

fn owned_evaluated_value<'a>(
    value: Cow<'a, str>,
    variables: &HashMap<String, ValuePart<'a>>) -> Result<ValuePart<'a>> {

    let value_part = match value {
        Cow::Borrowed(v) => {
            try!(Evaluator::new_from_string(&v).evaluate(variables))
        },
        Cow::Owned(v) => {
            try!(Evaluator::new_from_string(&v).evaluate(variables)).into_owned()
        },
    };
    Ok(match value_part {
        ValuePart::Number(nv) => ValuePart::Number(NumberValue { computed: true, ..nv }),
        other => other,
    })
}
<|endoftext|>