<commit_before>use std::ffi::CString;
use std::ptr;

use class::TypeParams;
use ctxt::{Fct, FctId, FctParent, FctSrc, SemContext};
use ty::{BuiltinType, MachineMode};

use dora_parser::ast::*;

use llvm;
use llvm::core::*;
// use llvm::execution_engine::*;
// use llvm::target::*;

pub fn generate<'ast>(
    ctxt: &SemContext<'ast>,
    id: FctId,
    cls_type_params: &TypeParams,
    fct_type_params: &TypeParams,
) -> Result<*const u8, ()> {
    let fct = ctxt.fcts[id].borrow();
    let src = fct.src();
    let mut src = src.borrow_mut();

    generate_fct(ctxt, &fct, &mut src, cls_type_params, fct_type_params)
}

pub fn generate_fct<'ast>(
    ctxt: &SemContext<'ast>,
    fct: &Fct<'ast>,
    src: &mut FctSrc,
    cls_type_params: &TypeParams,
    fct_type_params: &TypeParams,
) -> Result<*const u8, ()> {
    let name = fct.full_name(ctxt);

    let mut cg = CodeGen {
        ctxt: ctxt,
        fct: fct,
        ast: fct.ast,
        src: src,
        cls_type_params,
        fct_type_params,

        fct_name: CString::new(name).unwrap(),

        context: ptr::null_mut(),
        module: ptr::null_mut(),
        builder: ptr::null_mut(),
        function: ptr::null_mut(),
    };

    cg.generate()
}

struct CodeGen<'a, 'ast: 'a> {
    ctxt: &'a SemContext<'ast>,
    fct: &'a Fct<'ast>,
    ast: &'ast Function,
    src: &'a mut FctSrc,
    cls_type_params: &'a TypeParams,
    fct_type_params: &'a TypeParams,

    fct_name: CString,

    context: *mut llvm::LLVMContext,
    module: *mut llvm::LLVMModule,
    builder: *mut llvm::LLVMBuilder,
    function: *mut llvm::LLVMValue,
}

impl<'a, 'ast> CodeGen<'a, 'ast>
where
    'ast: 'a,
{
    fn generate(&mut self) -> Result<*const u8, ()> {
        self.init();
        self.create_function()?;

        Err(())
    }

    fn init(&mut self) {
        unsafe {
            self.context = LLVMContextCreate();
            self.module = LLVMModuleCreateWithNameInContext(
                self.fct_name.as_ptr(),
                self.context,
            );
            self.builder = LLVMCreateBuilderInContext(self.context);
        }
    }

    fn create_function(&mut self) -> Result<(), ()> {
        let mut params = Vec::with_capacity(self.ast.params.len());

        for param in &self.ast.params {
            let ty = self.ty(param.id);
            params.push(self.llvm_ty(ty));
        }

        let return_type = self.specialize_type(self.fct.return_type);
        let llvm_return_type = self.llvm_ty(return_type);

        unsafe {
            let function_type = LLVMFunctionType(
                llvm_return_type,
                params.as_mut_ptr(),
                params.len() as u32,
                0);

            self.function = LLVMAddFunction(self.module, self.fct_name.as_ptr(), function_type);
        }

        Err(())
    }

    fn ty(&self, id: NodeId) -> BuiltinType {
        let ty = self.src.ty(id);
        self.specialize_type(ty)
    }

    fn specialize_type(&self, ty: BuiltinType) -> BuiltinType {
        match ty {
            BuiltinType::ClassTypeParam(cls_id, id) => {
                assert!(self.fct.parent == FctParent::Class(cls_id));
                self.cls_type_params[id.idx()]
            }

            BuiltinType::FctTypeParam(fct_id, id) => {
                assert!(self.fct.id == fct_id);
                self.fct_type_params[id.idx()]
            }

            BuiltinType::Class(cls_id, list_id) => {
                let params = self.ctxt.lists.borrow().get(list_id);

                let params: Vec<_> = params.iter().map(|t| self.specialize_type(t)).collect();

                let list_id = self.ctxt.lists.borrow_mut().insert(params.into());

                BuiltinType::Class(cls_id, list_id)
            }

            BuiltinType::Lambda(_) => unimplemented!(),

            _ => ty,
        }
    }

    fn llvm_ty(&self, ty: BuiltinType) -> *mut llvm::LLVMType {
        let mode = ty.mode();

        unsafe {
            match mode {
                MachineMode::Int64 => LLVMInt64TypeInContext(self.context),
                MachineMode::Int32 => LLVMInt32TypeInContext(self.context),
                MachineMode::Int8 => LLVMInt8TypeInContext(self.context),
                MachineMode::Float32 => LLVMFloatTypeInContext(self.context),
                MachineMode::Float64 => LLVMDoubleTypeInContext(self.context),
                MachineMode::Ptr => unimplemented!(),
            }
        }
    }
}
<commit_msg>boots: return llvm pointer type for refernces<commit_after>use std::ffi::CString;
use std::ptr;

use class::TypeParams;
use ctxt::{Fct, FctId, FctParent, FctSrc, SemContext};
use ty::{BuiltinType, MachineMode};

use dora_parser::ast::*;

use llvm;
use llvm::core::*;
// use llvm::execution_engine::*;
// use llvm::target::*;

pub fn generate<'ast>(
    ctxt: &SemContext<'ast>,
    id: FctId,
    cls_type_params: &TypeParams,
    fct_type_params: &TypeParams,
) -> Result<*const u8, ()> {
    let fct = ctxt.fcts[id].borrow();
    let src = fct.src();
    let mut src = src.borrow_mut();

    generate_fct(ctxt, &fct, &mut src, cls_type_params, fct_type_params)
}

pub fn generate_fct<'ast>(
    ctxt: &SemContext<'ast>,
    fct: &Fct<'ast>,
    src: &mut FctSrc,
    cls_type_params: &TypeParams,
    fct_type_params: &TypeParams,
) -> Result<*const u8, ()> {
    let name = fct.full_name(ctxt);

    let mut cg = CodeGen {
        ctxt: ctxt,
        fct: fct,
        ast: fct.ast,
        src: src,
        cls_type_params,
        fct_type_params,

        fct_name: CString::new(name).unwrap(),

        context: ptr::null_mut(),
        module: ptr::null_mut(),
        builder: ptr::null_mut(),
        function: ptr::null_mut(),
    };

    cg.generate()
}

struct CodeGen<'a, 'ast: 'a> {
    ctxt: &'a SemContext<'ast>,
    fct: &'a Fct<'ast>,
    ast: &'ast Function,
    src: &'a mut FctSrc,
    cls_type_params: &'a TypeParams,
    fct_type_params: &'a TypeParams,

    fct_name: CString,

    context: *mut llvm::LLVMContext,
    module: *mut llvm::LLVMModule,
    builder: *mut llvm::LLVMBuilder,
    function: *mut llvm::LLVMValue,
}

impl<'a, 'ast> CodeGen<'a, 'ast>
where
    'ast: 'a,
{
    fn generate(&mut self) -> Result<*const u8, ()> {
        self.init();
        self.create_function()?;

        Err(())
    }

    fn init(&mut self) {
        unsafe {
            self.context = LLVMContextCreate();
            self.module = LLVMModuleCreateWithNameInContext(
                self.fct_name.as_ptr(),
                self.context,
            );
            self.builder = LLVMCreateBuilderInContext(self.context);
        }
    }

    fn create_function(&mut self) -> Result<(), ()> {
        let mut params = Vec::with_capacity(self.ast.params.len());

        for param in &self.ast.params {
            let ty = self.ty(param.id);
            params.push(self.llvm_ty(ty));
        }

        let return_type = self.specialize_type(self.fct.return_type);
        let llvm_return_type = self.llvm_ty(return_type);

        unsafe {
            let function_type = LLVMFunctionType(
                llvm_return_type,
                params.as_mut_ptr(),
                params.len() as u32,
                0);

            self.function = LLVMAddFunction(self.module, self.fct_name.as_ptr(), function_type);
        }

        Err(())
    }

    fn ty(&self, id: NodeId) -> BuiltinType {
        let ty = self.src.ty(id);
        self.specialize_type(ty)
    }

    fn specialize_type(&self, ty: BuiltinType) -> BuiltinType {
        match ty {
            BuiltinType::ClassTypeParam(cls_id, id) => {
                assert!(self.fct.parent == FctParent::Class(cls_id));
                self.cls_type_params[id.idx()]
            }

            BuiltinType::FctTypeParam(fct_id, id) => {
                assert!(self.fct.id == fct_id);
                self.fct_type_params[id.idx()]
            }

            BuiltinType::Class(cls_id, list_id) => {
                let params = self.ctxt.lists.borrow().get(list_id);

                let params: Vec<_> = params.iter().map(|t| self.specialize_type(t)).collect();

                let list_id = self.ctxt.lists.borrow_mut().insert(params.into());

                BuiltinType::Class(cls_id, list_id)
            }

            BuiltinType::Lambda(_) => unimplemented!(),

            _ => ty,
        }
    }

    fn llvm_ty(&self, ty: BuiltinType) -> *mut llvm::LLVMType {
        let mode = ty.mode();

        unsafe {
            match mode {
                MachineMode::Int64 => LLVMInt64TypeInContext(self.context),
                MachineMode::Int32 => LLVMInt32TypeInContext(self.context),
                MachineMode::Int8 => LLVMInt8TypeInContext(self.context),
                MachineMode::Float32 => LLVMFloatTypeInContext(self.context),
                MachineMode::Float64 => LLVMDoubleTypeInContext(self.context),
                MachineMode::Ptr => {
                    let int8 = LLVMInt8TypeInContext(self.context);
                    LLVMPointerType(int8, 1)
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use prelude::*;
use super::{CheckpointFormat};
use rw::{ReadBuffer, WriteBuffer};

use csv::{Writer as CsvWriter};
use densearray::{Reshape, ReshapeMut};

use rand::{Rng, thread_rng};
use rustc_serialize::{Encodable};
use std::cmp::{max, min};
use std::fmt::{Debug};
use std::fs::{File, create_dir_all};
use std::io::{Write};
use std::path::{Path, PathBuf};
use std::thread::{sleep};
use std::time::{Duration, Instant};

//pub mod adagrad;
pub mod adagrad_new;
//pub mod adam;
pub mod adam_new;
//pub mod rmsprop;
//pub mod sgd;
pub mod sgd_new;
//pub mod shared_sgd;
pub mod shared_sgd_new;

#[derive(Clone, Debug)]
pub struct CheckpointConfig {
  pub prefix:   PathBuf,
  pub trace:    bool,
}

pub struct CheckpointState {
  pub cfg:          CheckpointConfig,
  pub config_file:  Option<File>,
  pub train_file:   Option<CsvWriter<File>>,
  pub valid_file:   Option<CsvWriter<File>>,
  start_time:   Instant,
  lap_time:     Instant,
  elapsed_s:    f64,
}

impl CheckpointState {
  pub fn new(cfg: CheckpointConfig) -> CheckpointState {
    Self::with_fields(cfg, "iter,loss,accuracy,elapsed")
  }

  pub fn with_fields(cfg: CheckpointConfig, fields: &str) -> CheckpointState {
    let delay_ns = thread_rng().gen_range(100_000_000, 500_000_000);
    sleep(Duration::new(0, delay_ns));
    create_dir_all(&cfg.prefix).ok();
    loop {
      let mut lo_idx = Some(0);
      let mut hi_idx = None;
      let mut idx = 0;
      while lo_idx != hi_idx {
        match (lo_idx, hi_idx) {
          (Some(lo), None) => {
            idx = lo;
          }
          (Some(lo), Some(hi)) => {
            idx = (lo + hi) / 2;
          }
          _ => unreachable!(),
        }
        let mut config_path = PathBuf::from(&cfg.prefix);
        let mut config_filename = format!("config.{}", idx);
        config_path.push(&config_filename);
        if config_path.exists() {
          match (lo_idx, hi_idx) {
            (Some(lo), None) => {
              lo_idx = Some(lo + max(1, lo));
            }
            (Some(lo), Some(hi)) => {
              lo_idx = Some(min(hi, max(lo + 1, idx)));
            }
            _ => unreachable!(),
          }
        } else {
          match (lo_idx, hi_idx) {
            (Some(_), None) => {
              lo_idx = Some(idx / 2);
              hi_idx = Some(idx);
            }
            (Some(_), Some(_)) => {
              hi_idx = Some(idx);
            }
            _ => unreachable!(),
          }
        }
      }
      idx = hi_idx.unwrap();
      let mut cfg_f = None;
      let mut trace_f = None;
      let mut valid_f = None;
      let mut config_path = PathBuf::from(&cfg.prefix);
      let mut config_filename = format!("config.{}", idx);
      config_path.push(&config_filename);
      if config_path.exists() {
        continue;
      }
      match File::create(&config_path) {
        Err(_) => {
          continue;
        }
        Ok(f) => {
          cfg_f = Some(f);
        }
      }
      if cfg.trace {
        let mut train_path = PathBuf::from(&cfg.prefix);
        let mut train_filename = format!("train.log.{}", idx);
        train_path.push(&train_filename);
        assert!(!train_path.exists());
        let mut f = File::create(&train_path).unwrap();
        writeln!(&mut f, "{}", fields).unwrap();
        trace_f = Some(f);

        let mut valid_path = PathBuf::from(&cfg.prefix);
        let mut valid_filename = format!("valid.log.{}", idx);
        valid_path.push(&valid_filename);
        assert!(!valid_path.exists());
        let mut f = File::create(&valid_path).unwrap();
        writeln!(&mut f, "{}", fields).unwrap();
        valid_f = Some(f);
      }
      let init_time = Instant::now();
      return CheckpointState{
        cfg:          cfg,
        config_file:  cfg_f,
        train_file:   trace_f.map(|f| CsvWriter::from_writer(f)),
        valid_file:   valid_f.map(|f| CsvWriter::from_writer(f)),
        start_time:   init_time,
        lap_time:     init_time,
        elapsed_s:    0.0,
      };
    }
  }

  pub fn start_timing(&mut self) {
    self.start_time = Instant::now();
  }

  pub fn stop_timing(&mut self) {
    self.lap_time = Instant::now();
    let duration = self.lap_time - self.start_time;
    self.elapsed_s = duration.as_secs() as f64 + 1.0e-9 * duration.subsec_nanos() as f64;
  }

  pub fn elapsed(&self) -> f64 {
    self.elapsed_s
  }

  pub fn append_config_info<U>(&mut self, info: &U) where U: Debug {
    if let Some(ref mut config_file) = self.config_file {
      writeln!(config_file, "{:?}", info).unwrap();
    }
  }

  pub fn append_class_stats_train(&mut self, stats: &ClassLossStats) {
    let elapsed = self.elapsed_s;
    self.append_train_info(&stats.to_record(elapsed));
  }

  pub fn append_train_info<Rec>(&mut self, rec: &Rec) where Rec: Encodable {
    if let Some(ref mut train_file) = self.train_file {
      train_file.encode(rec).unwrap();
      //train_file.flush().unwrap();
    }
  }

  pub fn append_class_stats_valid(&mut self, stats: &ClassLossStats) {
    let elapsed = self.elapsed_s;
    self.append_valid_info(&stats.to_record(elapsed));
  }

  pub fn append_valid_info<Rec>(&mut self, rec: &Rec) where Rec: Encodable {
    if let Some(ref mut valid_file) = self.valid_file {
      valid_file.encode(rec).unwrap();
      valid_file.flush().unwrap();
    }
  }
}

pub trait TraceRecord {
  fn loss(&self) -> f32;
  fn other(&self) -> f32;
}

#[derive(Clone, Debug)]
pub enum StepSize {
  Constant(f32),
  Custom{init_step: f32, steps: Vec<(usize, f32)>},
  Decay{init_step: f32, step_decay: f32, decay_iters: usize},
  Adaptive{init_step: f32, test_iters: usize, epoch_iters: usize, sched: AdaptiveStepSizeSchedule},
  BacktrackingLineSearch{decay: f32, c: f32},
  //WeakWolfeLineSearch,
}

#[derive(Clone, Copy, Debug)]
pub enum AdaptiveStepSizeSchedule {
  Pow10,
  Decimal,
}

pub fn adaptive_pow10_step_size_factor(t: usize) -> f32 {
  const F1: [f32; 2] = [0.3,    0.1];
  const F2: [f32; 2] = [0.03,   0.01];
  const F3: [f32; 2] = [0.003,  0.001];
  const F4: [f32; 2] = [0.0003, 0.0001];
  if t == 0 {
    1.0
  } else if t > 0 && t <= 2 {
    F1[t-1]
  } else if t > 2 && t <= 4 {
    F2[t-2-1]
  } else if t > 4 && t <= 6 {
    F3[t-4-1]
  } else if t > 6 && t <= 8 {
    F4[t-6-1]
  } else {
    unimplemented!();
  }
}

pub fn adaptive_decimal_step_size_factor(t: usize) -> f32 {
  const F1: [f32; 9] = [0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1];
  const F2: [f32; 9] = [0.09, 0.08, 0.07, 0.06, 0.05, 0.04, 0.03, 0.02, 0.01];
  const F3: [f32; 9] = [0.009, 0.008, 0.007, 0.006, 0.005, 0.004, 0.003, 0.002, 0.001];
  if t == 0 {
    1.0
  } else if t > 0 && t <= 9 {
    F1[t-1]
  } else if t > 9 && t <= 18 {
    F2[t-9-1]
  } else if t > 18 && t <= 27 {
    F3[t-18-1]
  } else {
    unimplemented!();
  }
}

#[derive(Clone, Copy, Debug)]
pub enum GradientMomentum {
  HeavyBall(f32),
  Nesterov(f32),
}

#[derive(Clone, Copy, Debug)]
pub enum NesterovParamState {
  Orig,
  PlusMomentum,
}

#[derive(Clone, Copy, Debug)]
pub struct StepStats {
  pub elapsed:  Option<f64>,
}

pub trait OptWorker<T, S> {
  type Rng: Rng;

  //fn init_param(&mut self, rng: &mut Xorshiftplus128Rng);
  fn init_param(&mut self, rng: &mut Self::Rng);
  /*fn load_local_param(&mut self, param_reader: &mut ReadBuffer<T>);
  fn store_local_param(&mut self, param_writer: &mut WriteBuffer<T>);
  fn store_global_param(&mut self, param_writer: &mut WriteBuffer<T>);*/

  fn step(&mut self, samples: &mut Iterator<Item=S>) /* -> StepStats*/;
  fn eval(&mut self, epoch_size: usize, samples: &mut Iterator<Item=S>);
}

pub trait OptCheckpoint<Format> where Format: CheckpointFormat {
  fn save_checkpoint(&mut self, path: &Path) -> Result<(), ()>;
  fn restore_checkpoint(&mut self, path: &Path) -> Result<(), ()>;
}

pub trait OptStats<Stats> {
  fn reset_opt_stats(&mut self);
  fn get_opt_stats(&self) -> &Stats;
}

pub trait OptUpdateStats<Stats> {
  fn update_stats(&mut self, stats: &mut Stats);
}

#[derive(Clone, Default, Debug)]
pub struct ClassOptStats {
  pub iter_count:       usize,
  pub sample_count:     usize,
  pub correct_count:    usize,
  pub avg_loss:         f32,
}

impl ClassOptStats {
  pub fn reset(&mut self) {
    self.iter_count = 0;
    self.sample_count = 0;
    self.correct_count = 0;
    self.avg_loss = 0.0;
  }

  pub fn accuracy(&self) -> f32 {
    self.correct_count as f32 / self.sample_count as f32
  }
}

#[derive(Clone, Default, Debug)]
pub struct RegressOptStats {
  pub avg_loss:         f32,
}
<commit_msg>Add a delay in seconds.<commit_after>use prelude::*;
use super::{CheckpointFormat};
use rw::{ReadBuffer, WriteBuffer};

use csv::{Writer as CsvWriter};
use densearray::{Reshape, ReshapeMut};

use rand::{Rng, thread_rng};
use rustc_serialize::{Encodable};
use std::cmp::{max, min};
use std::fmt::{Debug};
use std::fs::{File, create_dir_all};
use std::io::{Write};
use std::path::{Path, PathBuf};
use std::thread::{sleep};
use std::time::{Duration, Instant};

//pub mod adagrad;
pub mod adagrad_new;
//pub mod adam;
pub mod adam_new;
//pub mod rmsprop;
//pub mod sgd;
pub mod sgd_new;
//pub mod shared_sgd;
pub mod shared_sgd_new;

#[derive(Clone, Debug)]
pub struct CheckpointConfig {
  pub prefix:   PathBuf,
  pub trace:    bool,
}

pub struct CheckpointState {
  pub cfg:          CheckpointConfig,
  pub config_file:  Option<File>,
  pub train_file:   Option<CsvWriter<File>>,
  pub valid_file:   Option<CsvWriter<File>>,
  start_time:   Instant,
  lap_time:     Instant,
  elapsed_s:    f64,
}

impl CheckpointState {
  pub fn new(cfg: CheckpointConfig) -> CheckpointState {
    Self::with_fields(cfg, "iter,loss,accuracy,elapsed")
  }

  pub fn with_fields(cfg: CheckpointConfig, fields: &str) -> CheckpointState {
    let delay_s = thread_rng().gen_range(0, 4);
    let delay_ns = thread_rng().gen_range(100_000_000, 500_000_000);
    sleep(Duration::new(delay_s, delay_ns));
    create_dir_all(&cfg.prefix).ok();
    loop {
      let mut lo_idx = Some(0);
      let mut hi_idx = None;
      let mut idx = 0;
      while lo_idx != hi_idx {
        match (lo_idx, hi_idx) {
          (Some(lo), None) => {
            idx = lo;
          }
          (Some(lo), Some(hi)) => {
            idx = (lo + hi) / 2;
          }
          _ => unreachable!(),
        }
        let mut config_path = PathBuf::from(&cfg.prefix);
        let mut config_filename = format!("config.{}", idx);
        config_path.push(&config_filename);
        if config_path.exists() {
          match (lo_idx, hi_idx) {
            (Some(lo), None) => {
              lo_idx = Some(lo + max(1, lo));
            }
            (Some(lo), Some(hi)) => {
              lo_idx = Some(min(hi, max(lo + 1, idx)));
            }
            _ => unreachable!(),
          }
        } else {
          match (lo_idx, hi_idx) {
            (Some(_), None) => {
              lo_idx = Some(idx / 2);
              hi_idx = Some(idx);
            }
            (Some(_), Some(_)) => {
              hi_idx = Some(idx);
            }
            _ => unreachable!(),
          }
        }
      }
      idx = hi_idx.unwrap();
      let mut cfg_f = None;
      let mut trace_f = None;
      let mut valid_f = None;
      let mut config_path = PathBuf::from(&cfg.prefix);
      let mut config_filename = format!("config.{}", idx);
      config_path.push(&config_filename);
      if config_path.exists() {
        continue;
      }
      match File::create(&config_path) {
        Err(_) => {
          continue;
        }
        Ok(f) => {
          cfg_f = Some(f);
        }
      }
      if cfg.trace {
        let mut train_path = PathBuf::from(&cfg.prefix);
        let mut train_filename = format!("train.log.{}", idx);
        train_path.push(&train_filename);
        assert!(!train_path.exists());
        let mut f = File::create(&train_path).unwrap();
        writeln!(&mut f, "{}", fields).unwrap();
        trace_f = Some(f);

        let mut valid_path = PathBuf::from(&cfg.prefix);
        let mut valid_filename = format!("valid.log.{}", idx);
        valid_path.push(&valid_filename);
        assert!(!valid_path.exists());
        let mut f = File::create(&valid_path).unwrap();
        writeln!(&mut f, "{}", fields).unwrap();
        valid_f = Some(f);
      }
      let init_time = Instant::now();
      return CheckpointState{
        cfg:          cfg,
        config_file:  cfg_f,
        train_file:   trace_f.map(|f| CsvWriter::from_writer(f)),
        valid_file:   valid_f.map(|f| CsvWriter::from_writer(f)),
        start_time:   init_time,
        lap_time:     init_time,
        elapsed_s:    0.0,
      };
    }
  }

  pub fn start_timing(&mut self) {
    self.start_time = Instant::now();
  }

  pub fn stop_timing(&mut self) {
    self.lap_time = Instant::now();
    let duration = self.lap_time - self.start_time;
    self.elapsed_s = duration.as_secs() as f64 + 1.0e-9 * duration.subsec_nanos() as f64;
  }

  pub fn elapsed(&self) -> f64 {
    self.elapsed_s
  }

  pub fn append_config_info<U>(&mut self, info: &U) where U: Debug {
    if let Some(ref mut config_file) = self.config_file {
      writeln!(config_file, "{:?}", info).unwrap();
    }
  }

  pub fn append_class_stats_train(&mut self, stats: &ClassLossStats) {
    let elapsed = self.elapsed_s;
    self.append_train_info(&stats.to_record(elapsed));
  }

  pub fn append_train_info<Rec>(&mut self, rec: &Rec) where Rec: Encodable {
    if let Some(ref mut train_file) = self.train_file {
      train_file.encode(rec).unwrap();
      //train_file.flush().unwrap();
    }
  }

  pub fn append_class_stats_valid(&mut self, stats: &ClassLossStats) {
    let elapsed = self.elapsed_s;
    self.append_valid_info(&stats.to_record(elapsed));
  }

  pub fn append_valid_info<Rec>(&mut self, rec: &Rec) where Rec: Encodable {
    if let Some(ref mut valid_file) = self.valid_file {
      valid_file.encode(rec).unwrap();
      valid_file.flush().unwrap();
    }
  }
}

pub trait TraceRecord {
  fn loss(&self) -> f32;
  fn other(&self) -> f32;
}

#[derive(Clone, Debug)]
pub enum StepSize {
  Constant(f32),
  Custom{init_step: f32, steps: Vec<(usize, f32)>},
  Decay{init_step: f32, step_decay: f32, decay_iters: usize},
  Adaptive{init_step: f32, test_iters: usize, epoch_iters: usize, sched: AdaptiveStepSizeSchedule},
  BacktrackingLineSearch{decay: f32, c: f32},
  //WeakWolfeLineSearch,
}

#[derive(Clone, Copy, Debug)]
pub enum AdaptiveStepSizeSchedule {
  Pow10,
  Decimal,
}

pub fn adaptive_pow10_step_size_factor(t: usize) -> f32 {
  const F1: [f32; 2] = [0.3,    0.1];
  const F2: [f32; 2] = [0.03,   0.01];
  const F3: [f32; 2] = [0.003,  0.001];
  const F4: [f32; 2] = [0.0003, 0.0001];
  if t == 0 {
    1.0
  } else if t > 0 && t <= 2 {
    F1[t-1]
  } else if t > 2 && t <= 4 {
    F2[t-2-1]
  } else if t > 4 && t <= 6 {
    F3[t-4-1]
  } else if t > 6 && t <= 8 {
    F4[t-6-1]
  } else {
    unimplemented!();
  }
}

pub fn adaptive_decimal_step_size_factor(t: usize) -> f32 {
  const F1: [f32; 9] = [0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1];
  const F2: [f32; 9] = [0.09, 0.08, 0.07, 0.06, 0.05, 0.04, 0.03, 0.02, 0.01];
  const F3: [f32; 9] = [0.009, 0.008, 0.007, 0.006, 0.005, 0.004, 0.003, 0.002, 0.001];
  if t == 0 {
    1.0
  } else if t > 0 && t <= 9 {
    F1[t-1]
  } else if t > 9 && t <= 18 {
    F2[t-9-1]
  } else if t > 18 && t <= 27 {
    F3[t-18-1]
  } else {
    unimplemented!();
  }
}

#[derive(Clone, Copy, Debug)]
pub enum GradientMomentum {
  HeavyBall(f32),
  Nesterov(f32),
}

#[derive(Clone, Copy, Debug)]
pub enum NesterovParamState {
  Orig,
  PlusMomentum,
}

#[derive(Clone, Copy, Debug)]
pub struct StepStats {
  pub elapsed:  Option<f64>,
}

pub trait OptWorker<T, S> {
  type Rng: Rng;

  //fn init_param(&mut self, rng: &mut Xorshiftplus128Rng);
  fn init_param(&mut self, rng: &mut Self::Rng);
  /*fn load_local_param(&mut self, param_reader: &mut ReadBuffer<T>);
  fn store_local_param(&mut self, param_writer: &mut WriteBuffer<T>);
  fn store_global_param(&mut self, param_writer: &mut WriteBuffer<T>);*/

  fn step(&mut self, samples: &mut Iterator<Item=S>) /* -> StepStats*/;
  fn eval(&mut self, epoch_size: usize, samples: &mut Iterator<Item=S>);
}

pub trait OptCheckpoint<Format> where Format: CheckpointFormat {
  fn save_checkpoint(&mut self, path: &Path) -> Result<(), ()>;
  fn restore_checkpoint(&mut self, path: &Path) -> Result<(), ()>;
}

pub trait OptStats<Stats> {
  fn reset_opt_stats(&mut self);
  fn get_opt_stats(&self) -> &Stats;
}

pub trait OptUpdateStats<Stats> {
  fn update_stats(&mut self, stats: &mut Stats);
}

#[derive(Clone, Default, Debug)]
pub struct ClassOptStats {
  pub iter_count:       usize,
  pub sample_count:     usize,
  pub correct_count:    usize,
  pub avg_loss:         f32,
}

impl ClassOptStats {
  pub fn reset(&mut self) {
    self.iter_count = 0;
    self.sample_count = 0;
    self.correct_count = 0;
    self.avg_loss = 0.0;
  }

  pub fn accuracy(&self) -> f32 {
    self.correct_count as f32 / self.sample_count as f32
  }
}

#[derive(Clone, Default, Debug)]
pub struct RegressOptStats {
  pub avg_loss:         f32,
}
<|endoftext|>


<commit_before>#[derive(Debug, Clone, Copy, PartialEq)]
pub enum OutputStyle {
    Nested,
    Expanded,
    Compact,
    Compressed,
}

/// The user facing Options struct, where they can select the libsass
/// options
#[derive(Debug, PartialEq, Clone)]
pub struct Options {
    /// The output format of the final CSS style.
    pub output_style: OutputStyle,
    /// How many digits after the decimal will be allowed.
    pub precision: usize,
    /// `true` values enable Sass Indented Syntax for parsing the data string or file.
    pub indented_syntax: bool,
    /// An array of paths that LibSass can look in to attempt to resolve your @import declarations.
    pub include_paths: Vec<String>,
}

impl Default for Options {
    fn default() -> Self {
        Options {
            output_style: OutputStyle::Nested,
            precision: 5,
            indented_syntax: false,
            include_paths: vec![],
        }
    }
}
<commit_msg>Document OutputStyle with ref to official doc<commit_after>#[derive(Debug, Clone, Copy, PartialEq)]
/// See the [Sass docs](https://sass-lang.com/documentation/file.SASS_REFERENCE.html#output_style)
/// for examples of how each style looks.
pub enum OutputStyle {
    Nested,
    Expanded,
    Compact,
    Compressed,
}

/// The user facing Options struct, where they can select the libsass
/// options
#[derive(Debug, PartialEq, Clone)]
pub struct Options {
    /// The output format of the final CSS style.
    pub output_style: OutputStyle,
    /// How many digits after the decimal will be allowed.
    pub precision: usize,
    /// `true` values enable Sass Indented Syntax for parsing the data string or file.
    pub indented_syntax: bool,
    /// An array of paths that LibSass can look in to attempt to resolve your @import declarations.
    pub include_paths: Vec<String>,
}

impl Default for Options {
    fn default() -> Self {
        Options {
            output_style: OutputStyle::Nested,
            precision: 5,
            indented_syntax: false,
            include_paths: vec![],
        }
    }
}
<|endoftext|>


<commit_before>//!
//! A session runs a filesystem implementation while it is being mounted
//! to a specific mount point. A session begins by mounting the filesystem
//! and ends by unmounting it. While the filesystem is mounted, the session
//! loop receives, dispatches and replies to kernel requests for filesystem
//! operations under its mount point.
//!

use std::task::TaskBuilder;
use libc::{EAGAIN, EINTR, ENODEV, ENOENT};
use native;
use channel;
use channel::Channel;
use Filesystem;
use request::{request, dispatch};

/// The max size of write requests from the kernel. The absolute minimum is 4k,
/// FUSE recommends at least 128k, max 16M. The FUSE default is 16M on OS X
/// and 128k on other systems.
pub static MAX_WRITE_SIZE: uint = 16*1024*1024;

/// Size of the buffer for reading a request from the kernel. Since the kernel may send
/// up to MAX_WRITE_SIZE bytes in a write request, we use that value plus some extra space.
static BUFFER_SIZE: uint = MAX_WRITE_SIZE + 4096;

/// The session data structure
pub struct Session<FS> {
	/// Filesystem operation implementations
	pub filesystem: FS,
	/// Path of the mounted filesystem
	pub mountpoint: Path,
	/// Communication channel to the kernel driver
	ch: Channel,
	/// FUSE protocol major version
	pub proto_major: uint,
	/// FUSE protocol minor version
	pub proto_minor: uint,
	/// True if the filesystem is initialized (init operation done)
	pub initialized: bool,
	/// True if the filesystem was destroyed (destroy operation done)
	pub destroyed: bool,
}

impl<FS: Filesystem+Send> Session<FS> {
	/// Create a new session by mounting the given filesystem to the given mountpoint
	pub fn new (filesystem: FS, mountpoint: &Path, options: &[&[u8]]) -> Session<FS> {
		info!("Mounting {}", mountpoint.display());
		let ch = match Channel::new(mountpoint, options) {
			Ok(ch) => ch,
			Err(err) => fail!("Unable to mount filesystem. Error {:i}", err),
		};
		Session {
			filesystem: filesystem,
			mountpoint: mountpoint.clone(),
			ch: ch,
			proto_major: 0,
			proto_minor: 0,
			initialized: false,
			destroyed: false,
		}
	}

	/// Run the session loop that receives kernel requests and dispatches them to method
	/// calls into the filesystem. This read-dispatch-loop is non-concurrent to prevent
	/// having multiple buffers (which take up much memory), but the filesystem methods
	/// may run concurrent by spawning tasks.
	/// Make sure to run this on a new single threaded scheduler since native I/O in the
	/// session loop can block.
	pub fn run (&mut self) {
		// Buffer for receiving requests from the kernel. Only one is allocated and
		// it is reused immediately after dispatching to conserve memory and allocations.
		let mut buffer = Vec::from_elem(BUFFER_SIZE, 0u8);
		loop {
			// Read the next request from the given channel to kernel driver
			// The kernel driver makes sure that we get exactly one request per read
			match self.ch.receive(buffer.as_mut_slice()) {
				Err(ENOENT) => continue,				// Operation interrupted. Accordingly to FUSE, this is safe to retry
				Err(EINTR) => continue,					// Interrupted system call, retry
				Err(EAGAIN) => continue,				// Explicitly try again
				Err(ENODEV) => break,					// Filesystem was unmounted, quit the loop
				Err(err) => fail!("Lost connection to FUSE device. Error {:i}", err),
				Ok(len) => match request(self.ch.sender(), buffer.slice_to(len)) {
					None => break,						// Illegal request, quit the loop
					Some(req) => dispatch(&req, self),
				},
			}
		}
	}

	/// Run the session loop in a background task
	pub fn spawn (self) -> BackgroundSession {
		BackgroundSession::new(self)
	}
}

#[unsafe_destructor]
impl<FS: Filesystem+Send> Drop for Session<FS> {
	fn drop (&mut self) {
		info!("Unmounted {}", self.mountpoint.display());
		// The actual unmounting takes place because self.ch is dropped here
	}
}

/// The background session data structure
pub struct BackgroundSession {
	/// Path of the mounted filesystem
	pub mountpoint: Path,
}

impl BackgroundSession {
	/// Create a new background session for the given session by running its
	/// session loop in a background task. If the returned handle is dropped,
	/// the filesystem is unmounted and the given session ends.
	pub fn new<FS: Filesystem+Send> (se: Session<FS>) -> BackgroundSession {
		let mountpoint = se.mountpoint.clone();
		// The background task is started using a a new native thread
		// since native I/O in the session loop can block
		let task = TaskBuilder::new().named(format!("FUSE {}", mountpoint.display()));
		native::task::spawn_opts(task.opts, proc() {
			let mut se = se;
			se.run();
		});
		BackgroundSession { mountpoint: mountpoint }
	}
}

impl Drop for BackgroundSession {
	fn drop (&mut self) {
		info!("Unmounting {}", self.mountpoint.display());
		// Unmounting the filesystem will eventually end the session loop,
		// drop the session and hence end the background task.
		channel::unmount(&self.mountpoint);
	}
}
<commit_msg>Use TaskBuilder::spawn()<commit_after>//!
//! A session runs a filesystem implementation while it is being mounted
//! to a specific mount point. A session begins by mounting the filesystem
//! and ends by unmounting it. While the filesystem is mounted, the session
//! loop receives, dispatches and replies to kernel requests for filesystem
//! operations under its mount point.
//!

use std::task::TaskBuilder;
use libc::{EAGAIN, EINTR, ENODEV, ENOENT};
use channel;
use channel::Channel;
use Filesystem;
use request::{request, dispatch};

/// The max size of write requests from the kernel. The absolute minimum is 4k,
/// FUSE recommends at least 128k, max 16M. The FUSE default is 16M on OS X
/// and 128k on other systems.
pub static MAX_WRITE_SIZE: uint = 16*1024*1024;

/// Size of the buffer for reading a request from the kernel. Since the kernel may send
/// up to MAX_WRITE_SIZE bytes in a write request, we use that value plus some extra space.
static BUFFER_SIZE: uint = MAX_WRITE_SIZE + 4096;

/// The session data structure
pub struct Session<FS> {
	/// Filesystem operation implementations
	pub filesystem: FS,
	/// Path of the mounted filesystem
	pub mountpoint: Path,
	/// Communication channel to the kernel driver
	ch: Channel,
	/// FUSE protocol major version
	pub proto_major: uint,
	/// FUSE protocol minor version
	pub proto_minor: uint,
	/// True if the filesystem is initialized (init operation done)
	pub initialized: bool,
	/// True if the filesystem was destroyed (destroy operation done)
	pub destroyed: bool,
}

impl<FS: Filesystem+Send> Session<FS> {
	/// Create a new session by mounting the given filesystem to the given mountpoint
	pub fn new (filesystem: FS, mountpoint: &Path, options: &[&[u8]]) -> Session<FS> {
		info!("Mounting {}", mountpoint.display());
		let ch = match Channel::new(mountpoint, options) {
			Ok(ch) => ch,
			Err(err) => fail!("Unable to mount filesystem. Error {:i}", err),
		};
		Session {
			filesystem: filesystem,
			mountpoint: mountpoint.clone(),
			ch: ch,
			proto_major: 0,
			proto_minor: 0,
			initialized: false,
			destroyed: false,
		}
	}

	/// Run the session loop that receives kernel requests and dispatches them to method
	/// calls into the filesystem. This read-dispatch-loop is non-concurrent to prevent
	/// having multiple buffers (which take up much memory), but the filesystem methods
	/// may run concurrent by spawning tasks.
	/// Make sure to run this on a new single threaded scheduler since native I/O in the
	/// session loop can block.
	pub fn run (&mut self) {
		// Buffer for receiving requests from the kernel. Only one is allocated and
		// it is reused immediately after dispatching to conserve memory and allocations.
		let mut buffer = Vec::from_elem(BUFFER_SIZE, 0u8);
		loop {
			// Read the next request from the given channel to kernel driver
			// The kernel driver makes sure that we get exactly one request per read
			match self.ch.receive(buffer.as_mut_slice()) {
				Err(ENOENT) => continue,				// Operation interrupted. Accordingly to FUSE, this is safe to retry
				Err(EINTR) => continue,					// Interrupted system call, retry
				Err(EAGAIN) => continue,				// Explicitly try again
				Err(ENODEV) => break,					// Filesystem was unmounted, quit the loop
				Err(err) => fail!("Lost connection to FUSE device. Error {:i}", err),
				Ok(len) => match request(self.ch.sender(), buffer.slice_to(len)) {
					None => break,						// Illegal request, quit the loop
					Some(req) => dispatch(&req, self),
				},
			}
		}
	}

	/// Run the session loop in a background task
	pub fn spawn (self) -> BackgroundSession {
		BackgroundSession::new(self)
	}
}

#[unsafe_destructor]
impl<FS: Filesystem+Send> Drop for Session<FS> {
	fn drop (&mut self) {
		info!("Unmounted {}", self.mountpoint.display());
		// The actual unmounting takes place because self.ch is dropped here
	}
}

/// The background session data structure
pub struct BackgroundSession {
	/// Path of the mounted filesystem
	pub mountpoint: Path,
}

impl BackgroundSession {
	/// Create a new background session for the given session by running its
	/// session loop in a background task. If the returned handle is dropped,
	/// the filesystem is unmounted and the given session ends.
	pub fn new<FS: Filesystem+Send> (se: Session<FS>) -> BackgroundSession {
		let mountpoint = se.mountpoint.clone();
		// The background task is started using a a new native thread
		// since native I/O in the session loop can block
		let task = TaskBuilder::new().named(format!("FUSE {}", mountpoint.display()));
		task.spawn(proc() {
			let mut se = se;
			se.run();
		});
		BackgroundSession { mountpoint: mountpoint }
	}
}

impl Drop for BackgroundSession {
	fn drop (&mut self) {
		info!("Unmounting {}", self.mountpoint.display());
		// Unmounting the filesystem will eventually end the session loop,
		// drop the session and hence end the background task.
		channel::unmount(&self.mountpoint);
	}
}
<|endoftext|>


<commit_before>use std::ops::Range;
use std::cmp::min;
use super::{Fractional, Shaper, CharMapper};

static MAX_UTF8_LEN: usize = 4;

pub struct BasicShaper;
impl Shaper for BasicShaper {
	type CharMapper = BasicCharMapper;
	fn shape<T, F: FnMut(char) -> Option<T>>(&self, text: &str, lookup: &mut F) -> Option<(Vec<T>, BasicCharMapper)> {
		let (mut chars, mut clusters) = (Vec::with_capacity(text.len()/MAX_UTF8_LEN), Vec::with_capacity(text.len()/MAX_UTF8_LEN));
		for (i, c) in text.char_indices() {
			chars.push(try_opt!(lookup(c)));
			let last_cluster = clusters.last().cloned().unwrap_or((0, 0));
			let char_size = c.len_utf8();
			if char_size > 1 {
				clusters.push((chars.len(), i+char_size));
			}
		}
		let num_chars = chars.len();
		Some((chars, BasicCharMapper(num_chars, clusters)))
	}
}

/// Simple cluster mapping (cluster = 0.. ASCII chars (len=1) + 0..1 non-ASCII)
/// Tuples are cluster boundaries as (char idx, string offset), a first (0, 0) and the last (num chars, str len) are implied
/// Rationale: compared to cluster=1char, this saves memory for text containing ASCII (no heap alloc for pure ASCII) while being cheap to compute
#[derive(Debug)]
pub struct BasicCharMapper(usize, Vec<(usize, usize)>);
impl CharMapper for BasicCharMapper {
	fn map_cursor(&self, text: &str, character: usize, pos: Fractional) -> usize {unimplemented!()}
	fn map_range(&self, range: Range<usize>) -> Vec<Range<usize>> {
		let translate = |pos:usize| {
			let (cluster_offset, cluster_start, cluster_end) = match self.1.binary_search_by(|&(_, cstart)| cstart.cmp(&pos)) {
				Err(0) => (0, 0, self.1.first().map_or(self.0, |&(x, _)| x)),
				Ok(x) => (self.1[x].1, self.1[x].0, self.1.get(x+1).map_or(self.0, |&(_, x)| x)),
				Err(x) => (self.1[x-1].1, self.1[x-1].0, self.1.get(x).map_or(self.0, |&(_, x)| x))
			};
			min(pos-cluster_offset, cluster_end-cluster_start) + cluster_start
		};
		vec![translate(range.start)..translate(range.end)]
	}
}

#[test]
fn test_basic_shaper() {
	let data = &[
		"",
		"Abc",
		"Test123",
		"Übung",	// multibyte char at the beginning
		"Weiß"	// multibyte char at the end
	];
	for case in data {
		let (chars, mapper) = BasicShaper.shape(case, &mut|x:char| Some(x)).unwrap();
		assert_eq!(chars, case.chars().collect::<Vec<char>>());
		for (cidx, (i, c)) in case.char_indices().enumerate() {
			assert_eq!(&mapper.map_range(i..case.len()), &[cidx..chars.len()]);
		}
		for (cidx, (i, c)) in case.char_indices().rev().enumerate() {
			assert_eq!(&mapper.map_range(0..i), &[0..chars.len()-1-cidx]);
		}
	}
}
<commit_msg>remove dead code<commit_after>use std::ops::Range;
use std::cmp::min;
use super::{Fractional, Shaper, CharMapper};

static MAX_UTF8_LEN: usize = 4;

pub struct BasicShaper;
impl Shaper for BasicShaper {
	type CharMapper = BasicCharMapper;
	fn shape<T, F: FnMut(char) -> Option<T>>(&self, text: &str, lookup: &mut F) -> Option<(Vec<T>, BasicCharMapper)> {
		let (mut chars, mut clusters) = (Vec::with_capacity(text.len()/MAX_UTF8_LEN), Vec::with_capacity(text.len()/MAX_UTF8_LEN));
		for (i, c) in text.char_indices() {
			chars.push(try_opt!(lookup(c)));
			let char_size = c.len_utf8();
			if char_size > 1 {
				clusters.push((chars.len(), i+char_size));
			}
		}
		let num_chars = chars.len();
		Some((chars, BasicCharMapper(num_chars, clusters)))
	}
}

/// Simple cluster mapping (cluster = 0.. ASCII chars (len=1) + 0..1 non-ASCII)
/// Tuples are cluster boundaries as (char idx, string offset), a first (0, 0) and the last (num chars, str len) are implied
/// Rationale: compared to cluster=1char, this saves memory for text containing ASCII (no heap alloc for pure ASCII) while being cheap to compute
#[derive(Debug)]
pub struct BasicCharMapper(usize, Vec<(usize, usize)>);
impl CharMapper for BasicCharMapper {
	fn map_cursor(&self, text: &str, character: usize, pos: Fractional) -> usize {unimplemented!()}
	fn map_range(&self, range: Range<usize>) -> Vec<Range<usize>> {
		let translate = |pos:usize| {
			let (cluster_offset, cluster_start, cluster_end) = match self.1.binary_search_by(|&(_, cstart)| cstart.cmp(&pos)) {
				Err(0) => (0, 0, self.1.first().map_or(self.0, |&(x, _)| x)),
				Ok(x) => (self.1[x].1, self.1[x].0, self.1.get(x+1).map_or(self.0, |&(_, x)| x)),
				Err(x) => (self.1[x-1].1, self.1[x-1].0, self.1.get(x).map_or(self.0, |&(_, x)| x))
			};
			min(pos-cluster_offset, cluster_end-cluster_start) + cluster_start
		};
		vec![translate(range.start)..translate(range.end)]
	}
}

#[test]
fn test_basic_shaper() {
	let data = &[
		"",
		"Abc",
		"Test123",
		"Übung",	// multibyte char at the beginning
		"Weiß"	// multibyte char at the end
	];
	for case in data {
		let (chars, mapper) = BasicShaper.shape(case, &mut|x:char| Some(x)).unwrap();
		assert_eq!(chars, case.chars().collect::<Vec<char>>());
		for (cidx, (i, c)) in case.char_indices().enumerate() {
			assert_eq!(&mapper.map_range(i..case.len()), &[cidx..chars.len()]);
		}
		for (cidx, (i, c)) in case.char_indices().rev().enumerate() {
			assert_eq!(&mapper.map_range(0..i), &[0..chars.len()-1-cidx]);
		}
	}
}
<|endoftext|>


<commit_before>//! Area (base unit square meter, m2).

quantity! {
    /// Area (base unit square meter, m2).
    quantity: Area; "area";
    /// Area dimension, m2.
    dimension: ISQ<
        P2,     // length
        Z0,     // mass
        Z0,     // time
        Z0,     // electric current
        Z0,     // thermodynamic temperature
        Z0,     // amount of substance
        Z0>;    // luminous intensity
    units {
        @square_yottameter: prefix!(yotta) * prefix!(yotta);
            "Ym²", "square yottameter", "square yottameters";
        @square_zettameter: prefix!(zetta) * prefix!(zetta);
            "Zm²", "square zettameter", "square zettameters";
        @square_exameter: prefix!(exa) * prefix!(exa);
            "Em²", "square exameter", "square exameters";
        @square_petameter: prefix!(peta) * prefix!(peta);
            "Pm²", "square petameter", "square petameters";
        @square_terameter: prefix!(tera) * prefix!(tera);
            "Tm²", "square terameter", "square terameters";
        @square_gigameter: prefix!(giga) * prefix!(giga);
            "Gm²", "square gigameter", "square gigameters";
        @square_megameter: prefix!(mega) * prefix!(mega);
            "Mm²", "square megameter", "square megameters";
        @square_kilometer: prefix!(kilo) * prefix!(kilo);
            "km²", "square kilometer", "square kilometers";
        @square_hectometer: prefix!(hecto) * prefix!(hecto);
            "hm²", "square hectometer", "square hectometers";
        @square_decameter: prefix!(deca) * prefix!(deca);
            "dam²", "square decameter", "square decameters";
        @square_meter: prefix!(none);
            "m²", "square meter", "square meters";
        @square_decimeter: prefix!(deci) * prefix!(deci);
            "dm²", "square decimeter", "square decimeters";
        @square_centimeter: prefix!(centi) * prefix!(centi);
            "cm²", "square centimeter", "square centimeters";
        @square_millimeter: prefix!(milli) * prefix!(milli);
            "mm²", "square millimeter", "square millimeters";
        @square_micrometer: prefix!(micro) * prefix!(micro);
            "µm²", "square micrometer", "square micrometers";
        @square_nanometer: prefix!(nano) * prefix!(nano);
            "nm²", "square nanometer", "square nanometers";
        @square_picometer: prefix!(pico) * prefix!(pico);
            "pm²", "square picometer", "square picometers";
        @square_femtometer: prefix!(femto) * prefix!(femto);
            "fm²", "square femtometer", "square femtometers";
        @square_attometer: prefix!(atto) * prefix!(atto);
            "am²", "square attometer", "square attometers";
        @square_zeptometer: prefix!(zepto) * prefix!(zepto);
            "zm²", "square zeptometer", "square zeptometers";
        @square_yoctometer: prefix!(yocto) * prefix!(yocto);
            "ym²", "square yoctometer", "square yoctometers";
    }
}

#[cfg(test)]
mod tests {
    storage_types! {
        use lib::any::TypeId;
        use num::One;
        use si::quantities::*;
        use si::area as a;
        use si::length as l;
        use tests::Test;

        #[test]
        fn check_dimension() {
            let _: Area<V> = Length::new::<l::meter>(V::one()) * Length::new::<l::meter>(V::one());
        }

        #[test]
        fn check_units() {
            // Values too large for f32.
            if TypeId::of::<f64>() == TypeId::of::<V>() {
                test::<l::yottameter, a::square_yottameter>();
                test::<l::zettameter, a::square_zettameter>();
            }

            test::<l::exameter, a::square_exameter>();
            test::<l::petameter, a::square_petameter>();
            test::<l::terameter, a::square_terameter>();
            test::<l::gigameter, a::square_gigameter>();
            test::<l::megameter, a::square_megameter>();
            test::<l::kilometer, a::square_kilometer>();
            test::<l::hectometer, a::square_hectometer>();
            test::<l::decameter, a::square_decameter>();
            test::<l::meter, a::square_meter>();
            test::<l::decimeter, a::square_decimeter>();
            test::<l::centimeter, a::square_centimeter>();
            test::<l::millimeter, a::square_millimeter>();
            test::<l::micrometer, a::square_micrometer>();
            test::<l::nanometer, a::square_nanometer>();
            test::<l::picometer, a::square_picometer>();
            test::<l::femtometer, a::square_femtometer>();
            test::<l::attometer, a::square_attometer>();
            test::<l::zeptometer, a::square_zeptometer>();

            // Values too small for f32.
            if TypeId::of::<f64>() == TypeId::of::<V>() {
                test::<l::yoctometer, a::square_yoctometer>();
            }

            fn test<L: l::Conversion<V>, A: a::Conversion<V>>() {
                Test::assert_eq(&Area::new::(V::one()),
                    &(Length::new::<L>(V::one()) * Length::new::<L>(V::one())));
            }
        }
    }
}
<commit_msg>Add additional area units.<commit_after>//! Area (base unit square meter, m2).

quantity! {
    /// Area (base unit square meter, m2).
    quantity: Area; "area";
    /// Area dimension, m2.
    dimension: ISQ<
        P2,     // length
        Z0,     // mass
        Z0,     // time
        Z0,     // electric current
        Z0,     // thermodynamic temperature
        Z0,     // amount of substance
        Z0>;    // luminous intensity
    units {
        @square_yottameter: prefix!(yotta) * prefix!(yotta);
            "Ym²", "square yottameter", "square yottameters";
        @square_zettameter: prefix!(zetta) * prefix!(zetta);
            "Zm²", "square zettameter", "square zettameters";
        @square_exameter: prefix!(exa) * prefix!(exa);
            "Em²", "square exameter", "square exameters";
        @square_petameter: prefix!(peta) * prefix!(peta);
            "Pm²", "square petameter", "square petameters";
        @square_terameter: prefix!(tera) * prefix!(tera);
            "Tm²", "square terameter", "square terameters";
        @square_gigameter: prefix!(giga) * prefix!(giga);
            "Gm²", "square gigameter", "square gigameters";
        @square_megameter: prefix!(mega) * prefix!(mega);
            "Mm²", "square megameter", "square megameters";
        @square_kilometer: prefix!(kilo) * prefix!(kilo);
            "km²", "square kilometer", "square kilometers";
        @square_hectometer: prefix!(hecto) * prefix!(hecto);
            "hm²", "square hectometer", "square hectometers";
        @square_decameter: prefix!(deca) * prefix!(deca);
            "dam²", "square decameter", "square decameters";
        @square_meter: prefix!(none);
            "m²", "square meter", "square meters";
        @square_decimeter: prefix!(deci) * prefix!(deci);
            "dm²", "square decimeter", "square decimeters";
        @square_centimeter: prefix!(centi) * prefix!(centi);
            "cm²", "square centimeter", "square centimeters";
        @square_millimeter: prefix!(milli) * prefix!(milli);
            "mm²", "square millimeter", "square millimeters";
        @square_micrometer: prefix!(micro) * prefix!(micro);
            "µm²", "square micrometer", "square micrometers";
        @square_nanometer: prefix!(nano) * prefix!(nano);
            "nm²", "square nanometer", "square nanometers";
        @square_picometer: prefix!(pico) * prefix!(pico);
            "pm²", "square picometer", "square picometers";
        @square_femtometer: prefix!(femto) * prefix!(femto);
            "fm²", "square femtometer", "square femtometers";
        @square_attometer: prefix!(atto) * prefix!(atto);
            "am²", "square attometer", "square attometers";
        @square_zeptometer: prefix!(zepto) * prefix!(zepto);
            "zm²", "square zeptometer", "square zeptometers";
        @square_yoctometer: prefix!(yocto) * prefix!(yocto);
            "ym²", "square yoctometer", "square yoctometers";

        @acre: 4.046_873_E3; "ac", "acre", "acres";
        @are: 1.0_E2; "a", "are", "ares";
        @barn: 1.0_E-28; "b", "barn", "barns";
        @circular_mil: 5.067_075_E-10; "cmil", "circular mil", "circular mils";
        @hectare: 1.0_E4; "ha", "hectare", "hectares";
        @square_foot: 9.290_304_E-2; "ft²", "square foot", "square feet";
        @square_inch: 6.451_6_E-4; "in²", "square inch", "square inches";
        @square_mile: 2.589_988_E6; "mi²", "square mile", "square miles";
        @square_yard: 8.361_274_E-1; "yd²", "square yard", "square yards";
    }
}

#[cfg(test)]
mod tests {
    storage_types! {
        use lib::any::TypeId;
        use num::One;
        use si::quantities::*;
        use si::area as a;
        use si::length as l;
        use tests::Test;

        #[test]
        fn check_dimension() {
            let _: Area<V> = Length::new::<l::meter>(V::one()) * Length::new::<l::meter>(V::one());
        }

        #[test]
        fn check_units() {
            // Values too large for f32.
            if TypeId::of::<f64>() == TypeId::of::<V>() {
                test::<l::yottameter, a::square_yottameter>();
                test::<l::zettameter, a::square_zettameter>();
            }

            test::<l::exameter, a::square_exameter>();
            test::<l::petameter, a::square_petameter>();
            test::<l::terameter, a::square_terameter>();
            test::<l::gigameter, a::square_gigameter>();
            test::<l::megameter, a::square_megameter>();
            test::<l::kilometer, a::square_kilometer>();
            test::<l::hectometer, a::square_hectometer>();
            test::<l::decameter, a::square_decameter>();
            test::<l::meter, a::square_meter>();
            test::<l::decimeter, a::square_decimeter>();
            test::<l::centimeter, a::square_centimeter>();
            test::<l::millimeter, a::square_millimeter>();
            test::<l::micrometer, a::square_micrometer>();
            test::<l::nanometer, a::square_nanometer>();
            test::<l::picometer, a::square_picometer>();
            test::<l::femtometer, a::square_femtometer>();
            test::<l::attometer, a::square_attometer>();
            test::<l::zeptometer, a::square_zeptometer>();

            // Values too small for f32.
            if TypeId::of::<f64>() == TypeId::of::<V>() {
                test::<l::yoctometer, a::square_yoctometer>();
            }

            fn test<L: l::Conversion<V>, A: a::Conversion<V>>() {
                Test::assert_eq(&Area::new::(V::one()),
                    &(Length::new::<L>(V::one()) * Length::new::<L>(V::one())));
            }
        }
    }
}
<|endoftext|>


<commit_before>#![allow(unmounted_route)]

use rocket::Route;

use rocket::Response;
use rocket::http::Status;

use rocket_contrib::JSON;

use std::str::FromStr;

use std::collections::HashMap;

use std::time::Duration;

use comm;

#[derive(Debug)]
struct SpinnerError;

pub enum OutgoingMessage {
    SetState(u64, ChannelCommand),
    GetState(u64),
    SetPlan(u64, Vec<PlanLeg>),
    GetPlan(u64),
}

impl From<OutgoingMessage> for String {
    fn from(msg: OutgoingMessage) -> String {
        match msg {
            OutgoingMessage::SetState(channel_id, ref cmd) => {
                format!("SET_SPIN_STATE,{},{}",
                        channel_id,
                        match *cmd {
                            ChannelCommand::Start => "START",
                            ChannelCommand::Stop => "STOP",
                        })
            }
            OutgoingMessage::GetState(channel_id) => format!("GET_SPIN_STATE,{}", channel_id),
            OutgoingMessage::SetPlan(channel_id, ref plan) => {
                let mut msg = format!("SET_PLAN,{}", channel_id);
                for leg in plan {
                    msg = format!("{},{},{}", msg, leg.target_val_pct, leg.duration_msecs);
                }

                msg
            }
            OutgoingMessage::GetPlan(channel_id) => format!("GET_PLAN,{}", channel_id),
        }
    }
}

enum IncomingMessage {
    Plan(u64, Vec<PlanLeg>),
    State(u64, ChannelState),
    RetVal(i64),
}

impl FromStr for IncomingMessage {
    type Err = SpinnerError;

    fn from_str(s: &str) -> Result<IncomingMessage, Self::Err> {
        let mut tokens = s.split(',');
        if let Some(msg_type) = tokens.next() {
            match msg_type {
                "SPIN_PLAN_REPLY" => {
                    let ch_num =
                        tokens.next().ok_or(SpinnerError)?.parse().map_err(|_| SpinnerError)?;

                    let mut plan_legs = Vec::new();

                    let mut plan_tokens = tokens.peekable();

                    while plan_tokens.peek().is_some() {
                        let duration_msecs = plan_tokens.next()
                            .ok_or(SpinnerError)?
                            .parse()
                            .map_err(|_| SpinnerError)?;
                        let target_val_pct = plan_tokens.next()
                            .ok_or(SpinnerError)?
                            .parse()
                            .map_err(|_| SpinnerError)?;

                        plan_legs.push(PlanLeg {
                            target_val_pct: target_val_pct,
                            duration_msecs: duration_msecs,
                        });
                    }

                    Ok(IncomingMessage::Plan(ch_num, plan_legs))
                }
                "SPIN_STATE_REPLY" => {
                    let ch_num =
                        tokens.next().ok_or(SpinnerError)?.parse().map_err(|_| SpinnerError)?;

                    let state_str = tokens.next().ok_or(SpinnerError)?;

                    let pos_in_plan_msecs =
                        tokens.next().ok_or(SpinnerError)?.parse().map_err(|_| SpinnerError)?;
                    let output_val_pct =
                        tokens.next().ok_or(SpinnerError)?.parse().map_err(|_| SpinnerError)?;

                    match state_str {
                        "RUNNING" => {
                            Ok(IncomingMessage::State(ch_num,
                                                      ChannelState::Running {
                                                          output_val_pct: output_val_pct,
                                                          pos_in_plan_msecs: pos_in_plan_msecs,
                                                      }))
                        }
                        "STOPPED" => Ok(IncomingMessage::State(ch_num, ChannelState::Stopped)),
                        _ => Err(SpinnerError),
                    }
                }
                "RET_VAL" => {
                    let ret_val =
                        tokens.next().ok_or(SpinnerError)?.parse().map_err(|_| SpinnerError)?;
                    Ok(IncomingMessage::RetVal(ret_val))
                }
                _ => Err(SpinnerError),
            }
        } else {
            Err(SpinnerError)
        }
    }
}

#[derive(Serialize, Clone)]
pub enum ChannelState {
    Running {
        output_val_pct: f64,
        pos_in_plan_msecs: u64,
    },
    Stopped,
}

#[derive(Deserialize)]
pub enum ChannelCommand {
    Start,
    Stop,
}

#[derive(Serialize, Deserialize, Clone)]
pub struct PlanLeg {
    target_val_pct: f64,
    duration_msecs: u64,
}

const NUM_CHANNELS: u64 = 1;

fn send_msg(msg_str: String, comm: &comm::CommChannelTx) -> Result<String, SpinnerError> {
    debug!("Sending: {}", msg_str);

    let response_channel = comm.send(msg_str)
        .map_err(|e| {
            warn!("{}", e);
            SpinnerError
        })?;

    let raw_response_msg = response_channel.recv_timeout(Duration::from_secs(3))
        .map_err(|e| {
            warn!("{}", e);
            SpinnerError
        })?;

    debug!("Response: {}", raw_response_msg);

    Ok(raw_response_msg)
}

fn send_channel_state_query_msg(id: u64,
                                comm: &comm::CommChannelTx)
                                -> Result<ChannelState, SpinnerError> {

    let response_str = send_msg(OutgoingMessage::GetPlan(id).into(), comm)?;

    match response_str.parse()? {
        IncomingMessage::State(ret_id, ref state) if ret_id == id => Ok(state.clone()),
        _ => Err(SpinnerError),
    }
}

fn send_channel_plan_query_msg(id: u64,
                               comm: &comm::CommChannelTx)
                               -> Result<Vec<PlanLeg>, SpinnerError> {

    let response_str = send_msg(OutgoingMessage::GetState(id).into(), comm)?;

    match response_str.parse()? {
        IncomingMessage::Plan(ret_id, ref plan) if ret_id == id => Ok(plan.clone()),
        _ => Err(SpinnerError),
    }
}

#[get("/channels")]
fn query_channels(comm: comm::CommChannelTx)
                  -> Result<JSON<HashMap<u64, (ChannelState, Vec<PlanLeg>)>>, SpinnerError> {
    let mut map = HashMap::new();

    for ch_num in 0..NUM_CHANNELS {
        map.insert(ch_num,
                   (send_channel_state_query_msg(ch_num, &comm)?,
                    send_channel_plan_query_msg(ch_num, &comm)?));
    }

    Ok(JSON(map))
}

#[get("/channels/<id>")]
fn query_channel(id: u64,
                 comm: comm::CommChannelTx)
                 -> Result<Option<JSON<(ChannelState, Vec<PlanLeg>)>>, SpinnerError> {

    Ok(Some(JSON((send_channel_state_query_msg(id, &comm)?,
                  send_channel_plan_query_msg(id, &comm)?))))
}

#[get("/channels/<id>/state")]
fn query_channel_state(id: u64,
                       comm: comm::CommChannelTx)
                       -> Result<Option<JSON<ChannelState>>, SpinnerError> {

    match send_channel_state_query_msg(id, &comm) {
        Ok(state) => Ok(Some(JSON(state))),
        Err(_) => Err(SpinnerError),
    }
}

#[post("/channels/<id>/state", format = "application/json", data = "<new_state>")]
fn set_channel_state<'a>(id: u64,
                         new_state: JSON<ChannelCommand>,
                         comm: comm::CommChannelTx)
                         -> Result<Response<'a>, SpinnerError> {

    let response_str = send_msg(OutgoingMessage::SetState(id, new_state.into_inner()).into(),
                                &comm)?;

    match response_str.parse() {
        Ok(IncomingMessage::RetVal(ret_val)) => {
            if ret_val == 0 {
                Ok(Response::build().status(Status::Accepted).finalize())
            } else {
                Ok(Response::build().status(Status::Conflict).finalize())
            }
        }
        _ => Err(SpinnerError),
    }
}

#[get("/channels/<id>/plan")]
fn query_plan(id: u64,
              comm: comm::CommChannelTx)
              -> Result<Option<JSON<Vec<PlanLeg>>>, SpinnerError> {

    match send_channel_plan_query_msg(id, &comm) {
        Ok(plan) => Ok(Some(JSON(plan))),
        Err(_) => Err(SpinnerError),
    }
}

#[put("/channels/<id>/plan", format = "application/json", data = "<new_plan>")]
fn set_plan<'a>(id: u64,
                new_plan: JSON<Vec<PlanLeg>>,
                comm: comm::CommChannelTx)
                -> Result<Response<'a>, SpinnerError> {

    let response_str = send_msg(OutgoingMessage::SetPlan(id, new_plan.into_inner()).into(),
                                &comm)?;

    match response_str.parse() {
        Ok(IncomingMessage::RetVal(ret_val)) => {
            if ret_val == 0 {
                Ok(Response::build().status(Status::Accepted).finalize())
            } else {
                Ok(Response::build().status(Status::Conflict).finalize())
            }
        }
        _ => Err(SpinnerError),
    }
}

pub fn get_routes() -> Vec<Route> {

                 routes![query_channels,
                         query_channel,
                         query_channel_state,
                         set_channel_state,
                         query_plan,
                         set_plan]
}
<commit_msg>Aligned message data types with ratfist-stm32<commit_after>#![allow(unmounted_route)]

use rocket::Route;

use rocket::Response;
use rocket::http::Status;

use rocket_contrib::JSON;

use std::str::FromStr;

use std::collections::HashMap;

use std::time::Duration;

use comm;

#[derive(Debug)]
struct SpinnerError;

pub enum OutgoingMessage {
    SetState(u8, ChannelCommand),
    GetState(u8),
    SetPlan(u8, Vec<PlanLeg>),
    GetPlan(u8),
}

impl From<OutgoingMessage> for String {
    fn from(msg: OutgoingMessage) -> String {
        match msg {
            OutgoingMessage::SetState(channel_id, ref cmd) => {
                format!("SET_SPIN_STATE,{},{}",
                        channel_id,
                        match *cmd {
                            ChannelCommand::Start => "START",
                            ChannelCommand::Stop => "STOP",
                        })
            }
            OutgoingMessage::GetState(channel_id) => format!("GET_SPIN_STATE,{}", channel_id),
            OutgoingMessage::SetPlan(channel_id, ref plan) => {
                let mut msg = format!("SET_PLAN,{}", channel_id);
                for leg in plan {
                    msg = format!("{},{},{}", msg, leg.target_val_pct, leg.duration_msecs);
                }

                msg
            }
            OutgoingMessage::GetPlan(channel_id) => format!("GET_PLAN,{}", channel_id),
        }
    }
}

enum IncomingMessage {
    Plan(u8, Vec<PlanLeg>),
    State(u8, ChannelState),
    RetVal(i32),
}

impl FromStr for IncomingMessage {
    type Err = SpinnerError;

    fn from_str(s: &str) -> Result<IncomingMessage, Self::Err> {
        let mut tokens = s.split(',');
        if let Some(msg_type) = tokens.next() {
            match msg_type {
                "SPIN_PLAN_REPLY" => {
                    let ch_num =
                        tokens.next().ok_or(SpinnerError)?.parse().map_err(|_| SpinnerError)?;

                    let mut plan_legs = Vec::new();

                    let mut plan_tokens = tokens.peekable();

                    while plan_tokens.peek().is_some() {
                        let duration_msecs = plan_tokens.next()
                            .ok_or(SpinnerError)?
                            .parse()
                            .map_err(|_| SpinnerError)?;
                        let target_val_pct = plan_tokens.next()
                            .ok_or(SpinnerError)?
                            .parse()
                            .map_err(|_| SpinnerError)?;

                        plan_legs.push(PlanLeg {
                            target_val_pct: target_val_pct,
                            duration_msecs: duration_msecs,
                        });
                    }

                    Ok(IncomingMessage::Plan(ch_num, plan_legs))
                }
                "SPIN_STATE_REPLY" => {
                    let ch_num =
                        tokens.next().ok_or(SpinnerError)?.parse().map_err(|_| SpinnerError)?;

                    let state_str = tokens.next().ok_or(SpinnerError)?;

                    let pos_in_plan_msecs =
                        tokens.next().ok_or(SpinnerError)?.parse().map_err(|_| SpinnerError)?;
                    let output_val_pct =
                        tokens.next().ok_or(SpinnerError)?.parse().map_err(|_| SpinnerError)?;

                    match state_str {
                        "RUNNING" => {
                            Ok(IncomingMessage::State(ch_num,
                                                      ChannelState::Running {
                                                          output_val_pct: output_val_pct,
                                                          pos_in_plan_msecs: pos_in_plan_msecs,
                                                      }))
                        }
                        "STOPPED" => Ok(IncomingMessage::State(ch_num, ChannelState::Stopped)),
                        _ => Err(SpinnerError),
                    }
                }
                "RET_VAL" => {
                    let ret_val =
                        tokens.next().ok_or(SpinnerError)?.parse().map_err(|_| SpinnerError)?;
                    Ok(IncomingMessage::RetVal(ret_val))
                }
                _ => Err(SpinnerError),
            }
        } else {
            Err(SpinnerError)
        }
    }
}

#[derive(Serialize, Clone)]
pub enum ChannelState {
    Running {
        output_val_pct: f64,
        pos_in_plan_msecs: u64,
    },
    Stopped,
}

#[derive(Deserialize)]
pub enum ChannelCommand {
    Start,
    Stop,
}

#[derive(Serialize, Deserialize, Clone)]
pub struct PlanLeg {
    target_val_pct: f64,
    duration_msecs: u64,
}

const NUM_CHANNELS: u8 = 1;

fn send_msg(msg_str: String, comm: &comm::CommChannelTx) -> Result<String, SpinnerError> {
    debug!("Sending: {}", msg_str);

    let response_channel = comm.send(msg_str)
        .map_err(|e| {
            warn!("{}", e);
            SpinnerError
        })?;

    let raw_response_msg = response_channel.recv_timeout(Duration::from_secs(3))
        .map_err(|e| {
            warn!("{}", e);
            SpinnerError
        })?;

    debug!("Response: {}", raw_response_msg);

    Ok(raw_response_msg)
}

fn send_channel_state_query_msg(id: u8,
                                comm: &comm::CommChannelTx)
                                -> Result<ChannelState, SpinnerError> {

    let response_str = send_msg(OutgoingMessage::GetPlan(id).into(), comm)?;

    match response_str.parse()? {
        IncomingMessage::State(ret_id, ref state) if ret_id == id => Ok(state.clone()),
        _ => Err(SpinnerError),
    }
}

fn send_channel_plan_query_msg(id: u8,
                               comm: &comm::CommChannelTx)
                               -> Result<Vec<PlanLeg>, SpinnerError> {

    let response_str = send_msg(OutgoingMessage::GetState(id).into(), comm)?;

    match response_str.parse()? {
        IncomingMessage::Plan(ret_id, ref plan) if ret_id == id => Ok(plan.clone()),
        _ => Err(SpinnerError),
    }
}

#[get("/channels")]
fn query_channels(comm: comm::CommChannelTx)
                  -> Result<JSON<HashMap<u8, (ChannelState, Vec<PlanLeg>)>>, SpinnerError> {
    let mut map = HashMap::new();

    for ch_num in 0..NUM_CHANNELS {
        map.insert(ch_num,
                   (send_channel_state_query_msg(ch_num, &comm)?,
                    send_channel_plan_query_msg(ch_num, &comm)?));
    }

    Ok(JSON(map))
}

#[get("/channels/<id>")]
fn query_channel(id: u8,
                 comm: comm::CommChannelTx)
                 -> Result<Option<JSON<(ChannelState, Vec<PlanLeg>)>>, SpinnerError> {

    Ok(Some(JSON((send_channel_state_query_msg(id, &comm)?,
                  send_channel_plan_query_msg(id, &comm)?))))
}

#[get("/channels/<id>/state")]
fn query_channel_state(id: u8,
                       comm: comm::CommChannelTx)
                       -> Result<Option<JSON<ChannelState>>, SpinnerError> {

    match send_channel_state_query_msg(id, &comm) {
        Ok(state) => Ok(Some(JSON(state))),
        Err(_) => Err(SpinnerError),
    }
}

#[post("/channels/<id>/state", format = "application/json", data = "<new_state>")]
fn set_channel_state<'a>(id: u8,
                         new_state: JSON<ChannelCommand>,
                         comm: comm::CommChannelTx)
                         -> Result<Response<'a>, SpinnerError> {

    let response_str = send_msg(OutgoingMessage::SetState(id, new_state.into_inner()).into(),
                                &comm)?;

    match response_str.parse() {
        Ok(IncomingMessage::RetVal(ret_val)) => {
            if ret_val == 0 {
                Ok(Response::build().status(Status::Accepted).finalize())
            } else {
                Ok(Response::build().status(Status::Conflict).finalize())
            }
        }
        _ => Err(SpinnerError),
    }
}

#[get("/channels/<id>/plan")]
fn query_plan(id: u8,
              comm: comm::CommChannelTx)
              -> Result<Option<JSON<Vec<PlanLeg>>>, SpinnerError> {

    match send_channel_plan_query_msg(id, &comm) {
        Ok(plan) => Ok(Some(JSON(plan))),
        Err(_) => Err(SpinnerError),
    }
}

#[put("/channels/<id>/plan", format = "application/json", data = "<new_plan>")]
fn set_plan<'a>(id: u8,
                new_plan: JSON<Vec<PlanLeg>>,
                comm: comm::CommChannelTx)
                -> Result<Response<'a>, SpinnerError> {

    let response_str = send_msg(OutgoingMessage::SetPlan(id, new_plan.into_inner()).into(),
                                &comm)?;

    match response_str.parse() {
        Ok(IncomingMessage::RetVal(ret_val)) => {
            if ret_val == 0 {
                Ok(Response::build().status(Status::Accepted).finalize())
            } else {
                Ok(Response::build().status(Status::Conflict).finalize())
            }
        }
        _ => Err(SpinnerError),
    }
}

pub fn get_routes() -> Vec<Route> {

                 routes![query_channels,
                         query_channel,
                         query_channel_state,
                         set_channel_state,
                         query_plan,
                         set_plan]
}
<|endoftext|>


<commit_before>//! Low-level push primitives

use std::sync::{Arc, RwLock, Weak};
use std::collections::RingBuf;

pub enum ListenerError {
    Disappeared,
    Poisoned,
}

pub type ListenerResult = Result<(), ListenerError>;

pub trait Listener<A>: Send + Sync {
    fn accept(&mut self, a: A) -> ListenerResult;
}

pub struct ListenerWrapper<L> {
    weak: Weak<RwLock<L>>
}

impl<L> ListenerWrapper<L> {
    pub fn boxed<A>(strong: &Arc<RwLock<L>>) -> Box<Listener<A> + 'static>
        where L: Listener<A>, A: Send + Sync,
    {
        Box::new(ListenerWrapper { weak: strong.downgrade() })
    }
}

impl<A, L> Listener<A> for ListenerWrapper<L>
    where L: Listener<A> + Send + Sync, A: Send + Sync
{
    fn accept(&mut self, a: A) -> ListenerResult {
        match self.weak.upgrade() {
            Some(listener) => match listener.write() {
                Ok(mut listener) => listener.accept(a),
                Err(_) => Err(ListenerError::Poisoned),
            },
            None => Err(ListenerError::Disappeared),
        }
    }
}

pub trait WrapListener<L> {
    fn wrap<A>(&self) -> Box<Listener<A> + 'static>
        where L: Listener<A>, A: Send + Sync;
}

impl<L> WrapListener<L> for Arc<RwLock<L>> {
    fn wrap<A>(&self) -> Box<Listener<A> + 'static>
        where L: Listener<A>, A: Send + Sync
    {
        ListenerWrapper::boxed(self)
    }
}

pub trait Subject<A>: Send + Sync {
    fn listen(&mut self, listener: Box<Listener<A> + 'static>);
}

pub struct Source<A> {
    listeners: Vec<Box<Listener<A> + 'static>>,
}

impl<A> Source<A> {
    pub fn new() -> Source<A> {
        Source { listeners: Vec::new() }
    }
}

impl<A: Send + Sync + Clone> Source<A> {
    pub fn send(&mut self, a: A) {
        let mut idx_to_remove = vec!();
        for (k, listener) in self.listeners.iter_mut().enumerate() {
            if listener.accept(a.clone()).is_err() {
                idx_to_remove.push(k);
            }
        }
        for k in idx_to_remove.into_iter() {
            self.listeners.remove(k);
        }
    }
}

impl<A: Send + Sync + Clone> Listener<A> for Source<A> {
    fn accept(&mut self, a: A) -> ListenerResult {
        self.send(a);
        Ok(())
    }
}

impl<A: Send + Sync> Subject<A> for Source<A> {
    fn listen(&mut self, listener: Box<Listener<A> + 'static>) {
        self.listeners.push(listener);
    }
}

pub struct Mapper<A, B, F: Fn(A) -> B> {
    func: F,
    subject: Source<B>,
}

impl<A, B, F: Fn(A) -> B> Mapper<A, B, F> {
    pub fn new(func: F) -> Mapper<A, B, F> {
        Mapper { func: func, subject: Source::new() }
    }
}

impl<A, B, F> Subject<B> for Mapper<A, B, F>
    where A: Send + Sync + Clone,
          B: Send + Sync + Clone,
          F: Fn(A) -> B + Send + Sync,
{
    fn listen(&mut self, listener: Box<Listener<B> + 'static>) {
        self.subject.listen(listener);
    }
}

impl<A, B, F> Listener<A> for Mapper<A, B, F>
    where B: Send + Sync + Clone,
          F: Fn(A) -> B + Send + Sync,
{
    fn accept(&mut self, a: A) -> ListenerResult {
        self.subject.accept((self.func)(a))
    }
}

pub struct Filter<A, F> {
    func: F,
    source: Source<A>,
}

impl<A, F> Filter<A, F> {
    pub fn new(f: F) -> Filter<A, F> {
        Filter { source: Source::new(), func: f }
    }
}

impl<A: Send + Sync, F: Send + Sync> Subject<A> for Filter<A, F> {
    fn listen(&mut self, listener: Box<Listener<A> + 'static>) {
        self.source.listen(listener);
    }
}

impl<A, F> Listener<A> for Filter<A, F>
    where A: Send + Sync + Clone,
          F: Fn(&A) -> bool + Send + Sync,
{
    fn accept(&mut self, a: A) -> ListenerResult {
        if (self.func)(&a) {
            self.source.accept(a)
        } else {
            Ok(())
        }
    }
}

pub struct Holder<A> {
    current: A,
    source: Source<A>,
}

impl<A> Holder<A> {
    pub fn new(initial: A) -> Holder<A> {
        Holder { current: initial, source: Source::new() }
    }
}

impl<A: Clone> Holder<A> {
    pub fn current(&self) -> A { self.current.clone() }
}

impl<A: Send + Sync> Subject<A> for Holder<A> {
    fn listen(&mut self, listener: Box<Listener<A> + 'static>) {
        self.source.listen(listener);
    }
}

impl<A: Send + Sync + Clone> Listener<A> for Holder<A> {
    fn accept(&mut self, a: A) -> ListenerResult {
        self.current = a.clone();
        self.source.accept(a)
    }
}

pub struct Receiver<A> {
    buffer: RingBuf<A>,
}

impl<A> Receiver<A> {
    pub fn new() -> Receiver<A> {
        Receiver { buffer: RingBuf::new() }
    }
}

impl<A> Iterator for Receiver<A> {
    type Item = A;
    fn next(&mut self) -> Option<A> {
        self.buffer.pop_front()
    }
}

impl<A: Send + Sync> Subject<()> for Receiver<A> {
    fn listen(&mut self, _: Box<Listener<()> + 'static>) {}
}

impl<A: Send + Sync> Listener<A> for Receiver<A> {
    fn accept(&mut self, a: A) -> ListenerResult {
        self.buffer.push_back(a);
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use std::sync::{Arc, RwLock};
    use super::*;

    #[test]
    fn src_recv() {
        let mut src = Source::new();
        let recv = Arc::new(RwLock::new(Receiver::new()));
        src.listen(recv.wrap());
        src.send(3);
        assert_eq!(recv.write().unwrap().next(), Some(3));
    }

    #[test]
    fn map() {
        let mut src = Source::new();
        let map = Arc::new(RwLock::new(Mapper::new(|x: i32| x + 3)));
        src.listen(map.wrap());
        let recv = Arc::new(RwLock::new(Receiver::new()));
        map.write().unwrap().listen(recv.wrap());
        src.send(3);
        assert_eq!(recv.write().unwrap().next(), Some(6));
    }

    #[test]
    fn fork() {
        let mut src = Source::new();
        let map = Arc::new(RwLock::new(Mapper::new(|x: i32| x + 3)));
        src.listen(map.wrap());
        let r1 = Arc::new(RwLock::new(Receiver::new()));
        map.write().unwrap().listen(r1.wrap());
        let r2 = Arc::new(RwLock::new(Receiver::new()));
        src.listen(r2.wrap());
        src.send(4);
        assert_eq!(r1.write().unwrap().next(), Some(7));
        assert_eq!(r2.write().unwrap().next(), Some(4));
    }

    #[test]
    fn filter() {
        let mut src = Source::new();
        let filter = Arc::new(RwLock::new(Filter::new(|&:x: &i32| *x > 2)));
        src.listen(filter.wrap());
        let recv = Arc::new(RwLock::new(Receiver::new()));
        filter.write().unwrap().listen(recv.wrap());
        src.send(1);
        src.send(3);
        assert_eq!(recv.write().unwrap().next(), Some(3));
    }

    #[test]
    fn holder() {
        let mut src = Source::new();
        let holder = Arc::new(RwLock::new(Holder::new(1)));
        src.listen(holder.wrap());
        assert_eq!(holder.write().unwrap().current(), 1);
        src.send(3);
        assert_eq!(holder.write().unwrap().current(), 3);
    }
}
<commit_msg>Implement snapper push-primitive<commit_after>//! Low-level push primitives

use std::sync::{Arc, RwLock, Weak};
use std::collections::RingBuf;

pub enum ListenerError {
    Disappeared,
    Poisoned,
}

pub type ListenerResult = Result<(), ListenerError>;

pub trait Listener<A>: Send + Sync {
    fn accept(&mut self, a: A) -> ListenerResult;
}

pub struct ListenerWrapper<L> {
    weak: Weak<RwLock<L>>
}

impl<L> ListenerWrapper<L> {
    pub fn boxed<A>(strong: &Arc<RwLock<L>>) -> Box<Listener<A> + 'static>
        where L: Listener<A>, A: Send + Sync,
    {
        Box::new(ListenerWrapper { weak: strong.downgrade() })
    }
}

impl<A, L> Listener<A> for ListenerWrapper<L>
    where L: Listener<A> + Send + Sync, A: Send + Sync
{
    fn accept(&mut self, a: A) -> ListenerResult {
        match self.weak.upgrade() {
            Some(listener) => match listener.write() {
                Ok(mut listener) => listener.accept(a),
                Err(_) => Err(ListenerError::Poisoned),
            },
            None => Err(ListenerError::Disappeared),
        }
    }
}

pub trait WrapListener<L> {
    fn wrap<A>(&self) -> Box<Listener<A> + 'static>
        where L: Listener<A>, A: Send + Sync;
}

impl<L> WrapListener<L> for Arc<RwLock<L>> {
    fn wrap<A>(&self) -> Box<Listener<A> + 'static>
        where L: Listener<A>, A: Send + Sync
    {
        ListenerWrapper::boxed(self)
    }
}

pub trait Subject<A>: Send + Sync {
    fn listen(&mut self, listener: Box<Listener<A> + 'static>);
}

pub struct Source<A> {
    listeners: Vec<Box<Listener<A> + 'static>>,
}

impl<A> Source<A> {
    pub fn new() -> Source<A> {
        Source { listeners: Vec::new() }
    }
}

impl<A: Send + Sync + Clone> Source<A> {
    pub fn send(&mut self, a: A) {
        let mut idx_to_remove = vec!();
        for (k, listener) in self.listeners.iter_mut().enumerate() {
            if listener.accept(a.clone()).is_err() {
                idx_to_remove.push(k);
            }
        }
        for k in idx_to_remove.into_iter() {
            self.listeners.remove(k);
        }
    }
}

impl<A: Send + Sync + Clone> Listener<A> for Source<A> {
    fn accept(&mut self, a: A) -> ListenerResult {
        self.send(a);
        Ok(())
    }
}

impl<A: Send + Sync> Subject<A> for Source<A> {
    fn listen(&mut self, listener: Box<Listener<A> + 'static>) {
        self.listeners.push(listener);
    }
}

pub struct Mapper<A, B, F: Fn(A) -> B> {
    func: F,
    subject: Source<B>,
}

impl<A, B, F: Fn(A) -> B> Mapper<A, B, F> {
    pub fn new(func: F) -> Mapper<A, B, F> {
        Mapper { func: func, subject: Source::new() }
    }
}

impl<A, B, F> Subject<B> for Mapper<A, B, F>
    where A: Send + Sync + Clone,
          B: Send + Sync + Clone,
          F: Fn(A) -> B + Send + Sync,
{
    fn listen(&mut self, listener: Box<Listener<B> + 'static>) {
        self.subject.listen(listener);
    }
}

impl<A, B, F> Listener<A> for Mapper<A, B, F>
    where B: Send + Sync + Clone,
          F: Fn(A) -> B + Send + Sync,
{
    fn accept(&mut self, a: A) -> ListenerResult {
        self.subject.accept((self.func)(a))
    }
}

pub struct Filter<A, F> {
    func: F,
    source: Source<A>,
}

impl<A, F> Filter<A, F> {
    pub fn new(f: F) -> Filter<A, F> {
        Filter { source: Source::new(), func: f }
    }
}

impl<A: Send + Sync, F: Send + Sync> Subject<A> for Filter<A, F> {
    fn listen(&mut self, listener: Box<Listener<A> + 'static>) {
        self.source.listen(listener);
    }
}

impl<A, F> Listener<A> for Filter<A, F>
    where A: Send + Sync + Clone,
          F: Fn(&A) -> bool + Send + Sync,
{
    fn accept(&mut self, a: A) -> ListenerResult {
        if (self.func)(&a) {
            self.source.accept(a)
        } else {
            Ok(())
        }
    }
}

pub struct Holder<A> {
    current: A,
    source: Source<A>,
}

impl<A> Holder<A> {
    pub fn new(initial: A) -> Holder<A> {
        Holder { current: initial, source: Source::new() }
    }
}

impl<A: Clone> Holder<A> {
    pub fn current(&self) -> A { self.current.clone() }
}

impl<A: Send + Sync> Subject<A> for Holder<A> {
    fn listen(&mut self, listener: Box<Listener<A> + 'static>) {
        self.source.listen(listener);
    }
}

impl<A: Send + Sync + Clone> Listener<A> for Holder<A> {
    fn accept(&mut self, a: A) -> ListenerResult {
        self.current = a.clone();
        self.source.accept(a)
    }
}

pub struct Snapper<A, B> {
    current: A,
    source: Source<(A, B)>,
}

impl<A, B> Snapper<A, B> {
    pub fn new(initial: A) -> Snapper<A, B> {
        Snapper { current: initial, source: Source::new() }
    }
}

pub struct SnapperWrapper<A, B> {
    weak: Weak<RwLock<Snapper<A, B>>>,
}

impl<A: Send + Sync, B: Send + Sync> SnapperWrapper<A, B> {
    pub fn boxed(strong: &Arc<RwLock<Snapper<A, B>>>) -> Box<Listener<A> + 'static> {
        Box::new(SnapperWrapper { weak: strong.downgrade() })
    }
}

impl<A: Send + Sync, B: Send + Sync> Listener<A> for SnapperWrapper<A, B> {
    fn accept(&mut self, a: A) -> ListenerResult {
        match self.weak.upgrade() {
            Some(arc) => match arc.write() {
                Ok(mut snapper) => { snapper.current = a; Ok(()) },
                Err(_) => Err(ListenerError::Poisoned),
            },
            None => Err(ListenerError::Disappeared),
        }
    }
}

impl<A: Send + Sync + Clone, B: Send + Sync + Clone> Listener<B> for Snapper<A, B> {
    fn accept(&mut self, b: B) -> ListenerResult {
        self.source.accept((self.current.clone(), b))
    }
}

impl<A: Send + Sync, B: Send + Sync> Subject<(A, B)> for Snapper<A, B> {
    fn listen(&mut self, listener: Box<Listener<(A, B)> + 'static>) {
        self.source.listen(listener);
    }
}

pub struct Receiver<A> {
    buffer: RingBuf<A>,
}

impl<A> Receiver<A> {
    pub fn new() -> Receiver<A> {
        Receiver { buffer: RingBuf::new() }
    }
}

impl<A> Iterator for Receiver<A> {
    type Item = A;
    fn next(&mut self) -> Option<A> {
        self.buffer.pop_front()
    }
}

impl<A: Send + Sync> Subject<()> for Receiver<A> {
    fn listen(&mut self, _: Box<Listener<()> + 'static>) {}
}

impl<A: Send + Sync> Listener<A> for Receiver<A> {
    fn accept(&mut self, a: A) -> ListenerResult {
        self.buffer.push_back(a);
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use std::sync::{Arc, RwLock};
    use super::*;

    #[test]
    fn src_recv() {
        let mut src = Source::new();
        let recv = Arc::new(RwLock::new(Receiver::new()));
        src.listen(recv.wrap());
        src.send(3);
        assert_eq!(recv.write().unwrap().next(), Some(3));
    }

    #[test]
    fn map() {
        let mut src = Source::new();
        let map = Arc::new(RwLock::new(Mapper::new(|x: i32| x + 3)));
        src.listen(map.wrap());
        let recv = Arc::new(RwLock::new(Receiver::new()));
        map.write().unwrap().listen(recv.wrap());
        src.send(3);
        assert_eq!(recv.write().unwrap().next(), Some(6));
    }

    #[test]
    fn fork() {
        let mut src = Source::new();
        let map = Arc::new(RwLock::new(Mapper::new(|x: i32| x + 3)));
        src.listen(map.wrap());
        let r1 = Arc::new(RwLock::new(Receiver::new()));
        map.write().unwrap().listen(r1.wrap());
        let r2 = Arc::new(RwLock::new(Receiver::new()));
        src.listen(r2.wrap());
        src.send(4);
        assert_eq!(r1.write().unwrap().next(), Some(7));
        assert_eq!(r2.write().unwrap().next(), Some(4));
    }

    #[test]
    fn filter() {
        let mut src = Source::new();
        let filter = Arc::new(RwLock::new(Filter::new(|&:x: &i32| *x > 2)));
        src.listen(filter.wrap());
        let recv = Arc::new(RwLock::new(Receiver::new()));
        filter.write().unwrap().listen(recv.wrap());
        src.send(1);
        src.send(3);
        assert_eq!(recv.write().unwrap().next(), Some(3));
    }

    #[test]
    fn holder() {
        let mut src = Source::new();
        let holder = Arc::new(RwLock::new(Holder::new(1)));
        src.listen(holder.wrap());
        assert_eq!(holder.write().unwrap().current(), 1);
        src.send(3);
        assert_eq!(holder.write().unwrap().current(), 3);
    }

    #[test]
    fn snapper() {
        let mut src1 = Source::new();
        let mut src2 = Source::new();
        let snapper = Arc::new(RwLock::new(Snapper::new(3)));
        src1.listen(SnapperWrapper::boxed(&snapper));
        src2.listen(snapper.wrap());
        let recv = Arc::new(RwLock::new(Receiver::new()));
        snapper.write().unwrap().listen(recv.wrap());
        src2.send(6);
        assert_eq!(recv.write().unwrap().next(), Some((3, 6)));
        src1.send(5);
        assert_eq!(recv.write().unwrap().next(), None);
        src2.send(-4);
        assert_eq!(recv.write().unwrap().next(), Some((5, -4)));
    }
}
<|endoftext|>


<commit_before>//! Mostly platform-specific functionality
#[cfg(any(
    target_os = "dragonfly",
    target_os = "freebsd",
    target_os = "ios",
    all(target_os = "linux", not(target_env = "uclibc")),
    target_os = "macos",
    target_os = "netbsd"
))]
feature! {
    #![feature = "aio"]
    pub mod aio;
}

feature! {
    #![feature = "event"]

    #[cfg(any(target_os = "android", target_os = "linux"))]
    #[allow(missing_docs)]
    pub mod epoll;

    #[cfg(any(target_os = "dragonfly",
              target_os = "freebsd",
              target_os = "ios",
              target_os = "macos",
              target_os = "netbsd",
              target_os = "openbsd"))]
    #[allow(missing_docs)]
    pub mod event;

    #[cfg(any(target_os = "android", target_os = "linux"))]
    #[allow(missing_docs)]
    pub mod eventfd;
}

#[cfg(any(
    target_os = "android",
    target_os = "dragonfly",
    target_os = "freebsd",
    target_os = "ios",
    target_os = "linux",
    target_os = "redox",
    target_os = "macos",
    target_os = "netbsd",
    target_os = "illumos",
    target_os = "openbsd"
))]
#[cfg(feature = "ioctl")]
#[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
#[macro_use]
pub mod ioctl;

#[cfg(any(target_is = "android", target_os = "linux"))]
feature! {
    #![feature = "fs"]
    pub mod memfd;
}

#[cfg(not(target_os = "redox"))]
feature! {
    #![feature = "mman"]
    pub mod mman;
}

#[cfg(target_os = "linux")]
feature! {
    #![feature = "personality"]
    pub mod personality;
}

feature! {
    #![feature = "pthread"]
    pub mod pthread;
}

#[cfg(any(
    target_os = "android",
    target_os = "dragonfly",
    target_os = "freebsd",
    target_os = "linux",
    target_os = "macos",
    target_os = "netbsd",
    target_os = "openbsd"
))]
feature! {
    #![feature = "ptrace"]
    #[allow(missing_docs)]
    pub mod ptrace;
}

#[cfg(target_os = "linux")]
feature! {
    #![feature = "quota"]
    pub mod quota;
}

#[cfg(target_os = "linux")]
feature! {
    #![feature = "reboot"]
    pub mod reboot;
}

#[cfg(not(any(
    target_os = "redox",
    target_os = "fuchsia",
    target_os = "illumos",
    target_os = "haiku"
)))]
feature! {
    #![feature = "resource"]
    pub mod resource;
}

#[cfg(not(target_os = "redox"))]
feature! {
    #![feature = "poll"]
    pub mod select;
}

#[cfg(any(
    target_os = "android",
    target_os = "dragonfly",
    target_os = "freebsd",
    target_os = "ios",
    target_os = "linux",
    target_os = "macos"
))]
feature! {
    #![feature = "zerocopy"]
    pub mod sendfile;
}

pub mod signal;

#[cfg(any(target_os = "android", target_os = "linux"))]
feature! {
    #![feature = "signal"]
    #[allow(missing_docs)]
    pub mod signalfd;
}

#[cfg(not(target_os = "redox"))]
feature! {
    #![feature = "socket"]
    #[allow(missing_docs)]
    pub mod socket;
}

feature! {
    #![feature = "fs"]
    #[allow(missing_docs)]
    pub mod stat;
}

#[cfg(any(
    target_os = "android",
    target_os = "dragonfly",
    target_os = "freebsd",
    target_os = "ios",
    target_os = "linux",
    target_os = "macos",
    target_os = "openbsd"
))]
feature! {
    #![feature = "fs"]
    pub mod statfs;
}

feature! {
    #![feature = "fs"]
    pub mod statvfs;
}

#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
#[allow(missing_docs)]
pub mod sysinfo;

feature! {
    #![feature = "term"]
    #[allow(missing_docs)]
    pub mod termios;
}

#[allow(missing_docs)]
pub mod time;

feature! {
    #![feature = "uio"]
    pub mod uio;
}

feature! {
    #![feature = "feature"]
    pub mod utsname;
}

feature! {
    #![feature = "process"]
    pub mod wait;
}

#[cfg(any(target_os = "android", target_os = "linux"))]
feature! {
    #![feature = "inotify"]
    pub mod inotify;
}

#[cfg(any(target_os = "android", target_os = "linux"))]
feature! {
    #![feature = "time"]
    pub mod timerfd;
}

#[cfg(all(
    any(
        target_os = "freebsd",
        target_os = "illumos",
        target_os = "linux",
        target_os = "netbsd"
    ),
    feature = "time",
    feature = "signal"
))]
feature! {
    #![feature = "time"]
    pub mod timer;
}
<commit_msg>Fix typo guarding memfd export on android.<commit_after>//! Mostly platform-specific functionality
#[cfg(any(
    target_os = "dragonfly",
    target_os = "freebsd",
    target_os = "ios",
    all(target_os = "linux", not(target_env = "uclibc")),
    target_os = "macos",
    target_os = "netbsd"
))]
feature! {
    #![feature = "aio"]
    pub mod aio;
}

feature! {
    #![feature = "event"]

    #[cfg(any(target_os = "android", target_os = "linux"))]
    #[allow(missing_docs)]
    pub mod epoll;

    #[cfg(any(target_os = "dragonfly",
              target_os = "freebsd",
              target_os = "ios",
              target_os = "macos",
              target_os = "netbsd",
              target_os = "openbsd"))]
    #[allow(missing_docs)]
    pub mod event;

    #[cfg(any(target_os = "android", target_os = "linux"))]
    #[allow(missing_docs)]
    pub mod eventfd;
}

#[cfg(any(
    target_os = "android",
    target_os = "dragonfly",
    target_os = "freebsd",
    target_os = "ios",
    target_os = "linux",
    target_os = "redox",
    target_os = "macos",
    target_os = "netbsd",
    target_os = "illumos",
    target_os = "openbsd"
))]
#[cfg(feature = "ioctl")]
#[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
#[macro_use]
pub mod ioctl;

#[cfg(any(target_os = "android", target_os = "linux"))]
feature! {
    #![feature = "fs"]
    pub mod memfd;
}

#[cfg(not(target_os = "redox"))]
feature! {
    #![feature = "mman"]
    pub mod mman;
}

#[cfg(target_os = "linux")]
feature! {
    #![feature = "personality"]
    pub mod personality;
}

feature! {
    #![feature = "pthread"]
    pub mod pthread;
}

#[cfg(any(
    target_os = "android",
    target_os = "dragonfly",
    target_os = "freebsd",
    target_os = "linux",
    target_os = "macos",
    target_os = "netbsd",
    target_os = "openbsd"
))]
feature! {
    #![feature = "ptrace"]
    #[allow(missing_docs)]
    pub mod ptrace;
}

#[cfg(target_os = "linux")]
feature! {
    #![feature = "quota"]
    pub mod quota;
}

#[cfg(target_os = "linux")]
feature! {
    #![feature = "reboot"]
    pub mod reboot;
}

#[cfg(not(any(
    target_os = "redox",
    target_os = "fuchsia",
    target_os = "illumos",
    target_os = "haiku"
)))]
feature! {
    #![feature = "resource"]
    pub mod resource;
}

#[cfg(not(target_os = "redox"))]
feature! {
    #![feature = "poll"]
    pub mod select;
}

#[cfg(any(
    target_os = "android",
    target_os = "dragonfly",
    target_os = "freebsd",
    target_os = "ios",
    target_os = "linux",
    target_os = "macos"
))]
feature! {
    #![feature = "zerocopy"]
    pub mod sendfile;
}

pub mod signal;

#[cfg(any(target_os = "android", target_os = "linux"))]
feature! {
    #![feature = "signal"]
    #[allow(missing_docs)]
    pub mod signalfd;
}

#[cfg(not(target_os = "redox"))]
feature! {
    #![feature = "socket"]
    #[allow(missing_docs)]
    pub mod socket;
}

feature! {
    #![feature = "fs"]
    #[allow(missing_docs)]
    pub mod stat;
}

#[cfg(any(
    target_os = "android",
    target_os = "dragonfly",
    target_os = "freebsd",
    target_os = "ios",
    target_os = "linux",
    target_os = "macos",
    target_os = "openbsd"
))]
feature! {
    #![feature = "fs"]
    pub mod statfs;
}

feature! {
    #![feature = "fs"]
    pub mod statvfs;
}

#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
#[allow(missing_docs)]
pub mod sysinfo;

feature! {
    #![feature = "term"]
    #[allow(missing_docs)]
    pub mod termios;
}

#[allow(missing_docs)]
pub mod time;

feature! {
    #![feature = "uio"]
    pub mod uio;
}

feature! {
    #![feature = "feature"]
    pub mod utsname;
}

feature! {
    #![feature = "process"]
    pub mod wait;
}

#[cfg(any(target_os = "android", target_os = "linux"))]
feature! {
    #![feature = "inotify"]
    pub mod inotify;
}

#[cfg(any(target_os = "android", target_os = "linux"))]
feature! {
    #![feature = "time"]
    pub mod timerfd;
}

#[cfg(all(
    any(
        target_os = "freebsd",
        target_os = "illumos",
        target_os = "linux",
        target_os = "netbsd"
    ),
    feature = "time",
    feature = "signal"
))]
feature! {
    #![feature = "time"]
    pub mod timer;
}
<|endoftext|>