<commit_before>// TODO: get num cols of terminal dynamically

use super::{Report, ReportKind, Remark, RemarkKind};
use code::{FileMap, LineIdx};
use term_painter::{ToStyle, Color, Attr};
use term_painter::Color::*;

/// Options for printing
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct PrintOptions {
    /// Use of unicode allowed?
    pub unicode: bool,
    /// Use of colors allowed?
    pub color: bool,
    /// Is line wrapping allowed?
    pub line_wrap: bool,
}

pub fn print(rep: &Report, src: &FileMap, _: PrintOptions) {
    // print header
    let title = match rep.kind {
        ReportKind::Error => White.bold().bg(Red).paint("ERROR"),
        ReportKind::Warning => Attr::Bold.bg(Yellow).paint("WARNING"),
    };

    let start = src.get_loc(rep.span.lo);
    let end = src.get_loc(rep.span.hi);
    let line = if start.line != end.line {
        format!("{}-{}", start.line.0, end.line.0)
    } else {
        start.line.0.to_string()
    };

    println!("+---- {} in {} : {} ----+",
        title,
        src.filename(),
        Blue.paint(line)
    );

    for rem in &rep.remarks {
        // print message
        let (title, title_len) = match rem.kind {
            RemarkKind::Error => (Red.paint("error:"), 6),
            RemarkKind::Warning => (Yellow.paint("warning:"), 8),
            RemarkKind::Note => (Green.paint("note:"), 5),
        };

        print!("      =====>  {} ", title);
        // spaces + big arrow + spaces + title + space
        let indent = 6 + 6 + 2 + title_len + 1;
        let block_width = 80 - indent;

        let mut col = 0;
        for word in rem.desc.split_whitespace() {
            let word_len = word.chars().count();
            if col + word_len >= block_width && col != 0 {
                println!("");
                print!("           >  {0:>1$} ", " ", title_len);
                col = 0;
            }
            print!("{} ", White.paint(word));
            col += word_len + 1;
        }
        println!("");

        // print code snippet
        if let Some(span) = rem.span {
            let start = src.get_loc(span.lo);
            let end = src.get_loc(span.hi);

            if start.line == end.line {
                if let Some(line) = src.get_line(start.line) {
                    println!("{:>#4} {} {}",
                        Magenta.bold().paint(start.line),
                        Magenta.bold().paint("|"),
                        line
                    );

                    Yellow.with(|| {
                        println!("       {: <2$}{:-<3$}",
                            " ", "^",
                            start.col.0 as usize,
                            (end.col.0 - start.col.0) as usize
                        );
                    });
                }
            } else {
                for line_idx in start.line.0..end.line.0 + 1 {
                    let line_idx = LineIdx(line_idx);
                    if let Some(line) = src.get_line(line_idx) {
                        println!("{:>#4} {} {}",
                            Magenta.bold().paint(line_idx),
                            Magenta.bold().paint("|"),
                            line
                        );
                    }
                }
            }
            println!("");
        }

    }
    println!("");
}
<commit_msg>Add `Default` impl for `PrintOptions`<commit_after>// TODO: get num cols of terminal dynamically

use super::{Report, ReportKind, RemarkKind};
use code::{FileMap, LineIdx};
use term_painter::{ToStyle, Attr};
use term_painter::Color::*;
use std::default::Default;

/// Options for printing
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct PrintOptions {
    /// Use of unicode allowed?
    pub unicode: bool,
    /// Use of colors allowed?
    pub color: bool,
    /// Is line wrapping allowed?
    pub line_wrap: bool,
}

impl Default for PrintOptions {
    fn default() -> Self {
        PrintOptions {
            unicode: true,
            color: true,
            line_wrap: true,
        }
    }
}

pub fn print(rep: &Report, src: &FileMap, _: PrintOptions) {
    // print header
    let title = match rep.kind {
        ReportKind::Error => White.bold().bg(Red).paint("ERROR"),
        ReportKind::Warning => Attr::Bold.bg(Yellow).paint("WARNING"),
    };

    let start = src.get_loc(rep.span.lo);
    let end = src.get_loc(rep.span.hi);
    let line = if start.line != end.line {
        format!("{}-{}", start.line.0, end.line.0)
    } else {
        start.line.0.to_string()
    };

    println!("+---- {} in {} : {} ----+",
        title,
        src.filename(),
        Blue.paint(line)
    );

    for rem in &rep.remarks {
        // print message
        let (title, title_len) = match rem.kind {
            RemarkKind::Error => (Red.paint("error:"), 6),
            RemarkKind::Warning => (Yellow.paint("warning:"), 8),
            RemarkKind::Note => (Green.paint("note:"), 5),
        };

        print!("      =====>  {} ", title);
        // spaces + big arrow + spaces + title + space
        let indent = 6 + 6 + 2 + title_len + 1;
        let block_width = 80 - indent;

        let mut col = 0;
        for word in rem.desc.split_whitespace() {
            let word_len = word.chars().count();
            if col + word_len >= block_width && col != 0 {
                println!("");
                print!("           >  {0:>1$} ", " ", title_len);
                col = 0;
            }
            print!("{} ", White.paint(word));
            col += word_len + 1;
        }
        println!("");

        // print code snippet
        if let Some(span) = rem.span {
            let start = src.get_loc(span.lo);
            let end = src.get_loc(span.hi);

            if start.line == end.line {
                if let Some(line) = src.get_line(start.line) {
                    println!("{:>#4} {} {}",
                        Magenta.bold().paint(start.line),
                        Magenta.bold().paint("|"),
                        line
                    );

                    Yellow.with(|| {
                        println!("       {: <2$}{:-<3$}",
                            " ", "^",
                            start.col.0 as usize,
                            (end.col.0 - start.col.0) as usize
                        );
                    });
                }
            } else {
                for line_idx in start.line.0..end.line.0 + 1 {
                    let line_idx = LineIdx(line_idx);
                    if let Some(line) = src.get_line(line_idx) {
                        println!("{:>#4} {} {}",
                            Magenta.bold().paint(line_idx),
                            Magenta.bold().paint("|"),
                            line
                        );
                    }
                }
            }
            println!("");
        }

    }
    println!("");
}
<|endoftext|>


<commit_before>//! Initialization logic for a generic instance of the `Allocate` channel allocation trait.

use std::thread;
#[cfg(feature = "arg_parse")]
use std::io::BufRead;
#[cfg(feature = "arg_parse")]
use getopts;
use std::sync::Arc;

use std::any::Any;

use allocator::{Thread, Process, Generic, GenericBuilder};
// use allocator::process_binary::ProcessBinaryBuilder;
// use networking::initialize_networking;
use allocator::zero_copy::allocator_process::ProcessBuilder;
use allocator::zero_copy::initialize::initialize_networking;

/// Possible configurations for the communication infrastructure.
pub enum Configuration {
    /// Use one thread.
    Thread,
    /// Use one process with an indicated number of threads.
    Process(usize),
    /// Expect multiple processes indicated by `(threads, process, host_list, report)`.
    Cluster(usize, usize, Vec<String>, bool)
}

#[cfg(feature = "arg_parse")]
impl Configuration {

    /// Constructs a new configuration by parsing supplied text arguments.
    ///
    /// Most commonly, this uses `std::env::Args()` as the supplied iterator.
    pub fn from_args<I: Iterator<Item=String>>(args: I) -> Result<Configuration,String> {

        let mut opts = getopts::Options::new();
        opts.optopt("w", "threads", "number of per-process worker threads", "NUM");
        opts.optopt("p", "process", "identity of this process", "IDX");
        opts.optopt("n", "processes", "number of processes", "NUM");
        opts.optopt("h", "hostfile", "text file whose lines are process addresses", "FILE");
        opts.optflag("r", "report", "reports connection progress");

        opts.parse(args)
            .map_err(|e| format!("{:?}", e))
            .map(|matches| {

            // let mut config = Configuration::new(1, 0, Vec::new());
            let threads = matches.opt_str("w").map(|x| x.parse().unwrap_or(1)).unwrap_or(1);
            let process = matches.opt_str("p").map(|x| x.parse().unwrap_or(0)).unwrap_or(0);
            let processes = matches.opt_str("n").map(|x| x.parse().unwrap_or(1)).unwrap_or(1);
            let report = matches.opt_present("report");

            assert!(process < processes);

            if processes > 1 {
                let mut addresses = Vec::new();
                if let Some(hosts) = matches.opt_str("h") {
                    let reader = ::std::io::BufReader::new(::std::fs::File::open(hosts.clone()).unwrap());
                    for x in reader.lines().take(processes) {
                        addresses.push(x.unwrap());
                    }
                    if addresses.len() < processes {
                        panic!("could only read {} addresses from {}, but -n: {}", addresses.len(), hosts, processes);
                    }
                }
                else {
                    for index in 0..processes {
                        addresses.push(format!("localhost:{}", 2101 + index));
                    }
                }

                assert!(processes == addresses.len());
                Configuration::Cluster(threads, process, addresses, report)
            }
            else if threads > 1 { Configuration::Process(threads) }
            else { Configuration::Thread }
        })
    }
}

type LogBuilder = Arc<Fn(::logging::CommsSetup)->::logging::CommsLogger+Send+Sync>;

fn create_allocators(config: Configuration, logger: LogBuilder) -> Result<(Vec<GenericBuilder>, Box<Any>),String> {
    match config {
        Configuration::Thread => {
            Ok((vec![GenericBuilder::Thread(Thread)], Box::new(())))
            // Ok(ProcessBinaryBuilder::new_vector(1).into_iter().map(|x| GenericBuilder::ProcessBinary(x)).collect())
        },
        Configuration::Process(threads) => {
            // Ok((Process::new_vector(threads).into_iter().map(|x| GenericBuilder::Process(x)).collect(), Box::new(())))
            Ok((ProcessBuilder::new_vector(threads).into_iter().map(|x| GenericBuilder::ProcessBinary(x)).collect(), Box::new(())))
        },
        Configuration::Cluster(threads, process, addresses, report) => {
            if let Ok((stuff, guard)) = initialize_networking(addresses, process, threads, report, logger) {
                Ok((stuff.into_iter().map(|x| GenericBuilder::ZeroCopy(x)).collect(), Box::new(guard)))
            }
            else {
                Err("failed to initialize networking".to_owned())
            }
        },
    }
}

/// Initializes communication and executes a distributed computation.
///
/// This method allocates an `allocator::Generic` for each thread, spawns local worker threads,
/// and invokes the supplied function with the allocator.
/// The method returns a `WorkerGuards<T>` which can be `join`ed to retrieve the return values
/// (or errors) of the workers.
///
///
/// #Examples
/// ```
/// // configure for two threads, just one process.
/// let config = timely_communication::Configuration::Process(2);
///
/// // create a source of inactive loggers.
/// let logger = ::std::sync::Arc::new(|_| timely_communication::logging::BufferingLogger::new_inactive());
///
/// // initializes communication, spawns workers
/// let guards = timely_communication::initialize(config, logger, |mut allocator| {
///     println!("worker {} started", allocator.index());
///
///     // allocates pair of senders list and one receiver.
///     let (mut senders, mut receiver, _) = allocator.allocate();
///
///     // send typed data along each channel
///     use timely_communication::allocator::Message;
///     senders[0].send(Message::from_typed(format!("hello, {}", 0)));
///     senders[1].send(Message::from_typed(format!("hello, {}", 1)));
///
///     // no support for termination notification,
///     // we have to count down ourselves.
///     let mut expecting = 2;
///     while expecting > 0 {
///         allocator.pre_work();
///         if let Some(message) = receiver.recv() {
///             use std::ops::Deref;
///             println!("worker {}: received: <{}>", allocator.index(), message.deref());
///             expecting -= 1;
///         }
///         allocator.post_work();
///     }
///
///     // optionally, return something
///     allocator.index()
/// });
///
/// // computation runs until guards are joined or dropped.
/// if let Ok(guards) = guards {
///     for guard in guards.join() {
///         println!("result: {:?}", guard);
///     }
/// }
/// else { println!("error in computation"); }
/// ```
///
/// The should produce output like:
///
/// ```ignore
/// worker 0 started
/// worker 1 started
/// worker 0: received: <hello, 0>
/// worker 1: received: <hello, 1>
/// worker 0: received: <hello, 0>
/// worker 1: received: <hello, 1>
/// result: Ok(0)
/// result: Ok(1)
/// ```
pub fn initialize<T:Send+'static, F: Fn(Generic)->T+Send+Sync+'static>(
    config: Configuration,
    log_sender: LogBuilder,
    func: F,
) -> Result<WorkerGuards<T>,String> {

    let (allocators, others) = try!(create_allocators(config, log_sender));
    let logic = Arc::new(func);

    let mut guards = Vec::new();
    for (index, builder) in allocators.into_iter().enumerate() {
        let clone = logic.clone();
        guards.push(try!(thread::Builder::new()
                            .name(format!("worker thread {}", index))
                            .spawn(move || {
                                let communicator = builder.build();
                                (*clone)(communicator)
                            })
                            .map_err(|e| format!("{:?}", e))));
    }

    Ok(WorkerGuards { guards, others })
}

/// Maintains `JoinHandle`s for worker threads.
pub struct WorkerGuards<T:Send+'static> {
    guards: Vec<::std::thread::JoinHandle<T>>,
    others: Box<Any>,
}

impl<T:Send+'static> WorkerGuards<T> {
    /// Waits on the worker threads and returns the results they produce.
    pub fn join(mut self) -> Vec<Result<T,String>> {
        self.guards.drain(..)
                   .map(|guard| guard.join().map_err(|e| format!("{:?}", e)))
                   .collect()
    }
}

impl<T:Send+'static> Drop for WorkerGuards<T> {
    fn drop(&mut self) {
        for guard in self.guards.drain(..) {
            guard.join().expect("Worker panic");
        }
        // println!("WORKER THREADS JOINED");
    }
}
<commit_msg>use prior default process allocator<commit_after>//! Initialization logic for a generic instance of the `Allocate` channel allocation trait.

use std::thread;
#[cfg(feature = "arg_parse")]
use std::io::BufRead;
#[cfg(feature = "arg_parse")]
use getopts;
use std::sync::Arc;

use std::any::Any;

use allocator::{Thread, Process, Generic, GenericBuilder};
// use allocator::process_binary::ProcessBinaryBuilder;
// use networking::initialize_networking;
use allocator::zero_copy::allocator_process::ProcessBuilder;
use allocator::zero_copy::initialize::initialize_networking;

/// Possible configurations for the communication infrastructure.
pub enum Configuration {
    /// Use one thread.
    Thread,
    /// Use one process with an indicated number of threads.
    Process(usize),
    /// Expect multiple processes indicated by `(threads, process, host_list, report)`.
    Cluster(usize, usize, Vec<String>, bool)
}

#[cfg(feature = "arg_parse")]
impl Configuration {

    /// Constructs a new configuration by parsing supplied text arguments.
    ///
    /// Most commonly, this uses `std::env::Args()` as the supplied iterator.
    pub fn from_args<I: Iterator<Item=String>>(args: I) -> Result<Configuration,String> {

        let mut opts = getopts::Options::new();
        opts.optopt("w", "threads", "number of per-process worker threads", "NUM");
        opts.optopt("p", "process", "identity of this process", "IDX");
        opts.optopt("n", "processes", "number of processes", "NUM");
        opts.optopt("h", "hostfile", "text file whose lines are process addresses", "FILE");
        opts.optflag("r", "report", "reports connection progress");

        opts.parse(args)
            .map_err(|e| format!("{:?}", e))
            .map(|matches| {

            // let mut config = Configuration::new(1, 0, Vec::new());
            let threads = matches.opt_str("w").map(|x| x.parse().unwrap_or(1)).unwrap_or(1);
            let process = matches.opt_str("p").map(|x| x.parse().unwrap_or(0)).unwrap_or(0);
            let processes = matches.opt_str("n").map(|x| x.parse().unwrap_or(1)).unwrap_or(1);
            let report = matches.opt_present("report");

            assert!(process < processes);

            if processes > 1 {
                let mut addresses = Vec::new();
                if let Some(hosts) = matches.opt_str("h") {
                    let reader = ::std::io::BufReader::new(::std::fs::File::open(hosts.clone()).unwrap());
                    for x in reader.lines().take(processes) {
                        addresses.push(x.unwrap());
                    }
                    if addresses.len() < processes {
                        panic!("could only read {} addresses from {}, but -n: {}", addresses.len(), hosts, processes);
                    }
                }
                else {
                    for index in 0..processes {
                        addresses.push(format!("localhost:{}", 2101 + index));
                    }
                }

                assert!(processes == addresses.len());
                Configuration::Cluster(threads, process, addresses, report)
            }
            else if threads > 1 { Configuration::Process(threads) }
            else { Configuration::Thread }
        })
    }
}

type LogBuilder = Arc<Fn(::logging::CommsSetup)->::logging::CommsLogger+Send+Sync>;

fn create_allocators(config: Configuration, logger: LogBuilder) -> Result<(Vec<GenericBuilder>, Box<Any>),String> {
    match config {
        Configuration::Thread => {
            Ok((vec![GenericBuilder::Thread(Thread)], Box::new(())))
            // Ok(ProcessBinaryBuilder::new_vector(1).into_iter().map(|x| GenericBuilder::ProcessBinary(x)).collect())
        },
        Configuration::Process(threads) => {
            Ok((Process::new_vector(threads).into_iter().map(|x| GenericBuilder::Process(x)).collect(), Box::new(())))
            // Ok((ProcessBuilder::new_vector(threads).into_iter().map(|x| GenericBuilder::ProcessBinary(x)).collect(), Box::new(())))
        },
        Configuration::Cluster(threads, process, addresses, report) => {
            if let Ok((stuff, guard)) = initialize_networking(addresses, process, threads, report, logger) {
                Ok((stuff.into_iter().map(|x| GenericBuilder::ZeroCopy(x)).collect(), Box::new(guard)))
            }
            else {
                Err("failed to initialize networking".to_owned())
            }
        },
    }
}

/// Initializes communication and executes a distributed computation.
///
/// This method allocates an `allocator::Generic` for each thread, spawns local worker threads,
/// and invokes the supplied function with the allocator.
/// The method returns a `WorkerGuards<T>` which can be `join`ed to retrieve the return values
/// (or errors) of the workers.
///
///
/// #Examples
/// ```
/// // configure for two threads, just one process.
/// let config = timely_communication::Configuration::Process(2);
///
/// // create a source of inactive loggers.
/// let logger = ::std::sync::Arc::new(|_| timely_communication::logging::BufferingLogger::new_inactive());
///
/// // initializes communication, spawns workers
/// let guards = timely_communication::initialize(config, logger, |mut allocator| {
///     println!("worker {} started", allocator.index());
///
///     // allocates pair of senders list and one receiver.
///     let (mut senders, mut receiver, _) = allocator.allocate();
///
///     // send typed data along each channel
///     use timely_communication::allocator::Message;
///     senders[0].send(Message::from_typed(format!("hello, {}", 0)));
///     senders[1].send(Message::from_typed(format!("hello, {}", 1)));
///
///     // no support for termination notification,
///     // we have to count down ourselves.
///     let mut expecting = 2;
///     while expecting > 0 {
///         allocator.pre_work();
///         if let Some(message) = receiver.recv() {
///             use std::ops::Deref;
///             println!("worker {}: received: <{}>", allocator.index(), message.deref());
///             expecting -= 1;
///         }
///         allocator.post_work();
///     }
///
///     // optionally, return something
///     allocator.index()
/// });
///
/// // computation runs until guards are joined or dropped.
/// if let Ok(guards) = guards {
///     for guard in guards.join() {
///         println!("result: {:?}", guard);
///     }
/// }
/// else { println!("error in computation"); }
/// ```
///
/// The should produce output like:
///
/// ```ignore
/// worker 0 started
/// worker 1 started
/// worker 0: received: <hello, 0>
/// worker 1: received: <hello, 1>
/// worker 0: received: <hello, 0>
/// worker 1: received: <hello, 1>
/// result: Ok(0)
/// result: Ok(1)
/// ```
pub fn initialize<T:Send+'static, F: Fn(Generic)->T+Send+Sync+'static>(
    config: Configuration,
    log_sender: LogBuilder,
    func: F,
) -> Result<WorkerGuards<T>,String> {

    let (allocators, others) = try!(create_allocators(config, log_sender));
    let logic = Arc::new(func);

    let mut guards = Vec::new();
    for (index, builder) in allocators.into_iter().enumerate() {
        let clone = logic.clone();
        guards.push(try!(thread::Builder::new()
                            .name(format!("worker thread {}", index))
                            .spawn(move || {
                                let communicator = builder.build();
                                (*clone)(communicator)
                            })
                            .map_err(|e| format!("{:?}", e))));
    }

    Ok(WorkerGuards { guards, others })
}

/// Maintains `JoinHandle`s for worker threads.
pub struct WorkerGuards<T:Send+'static> {
    guards: Vec<::std::thread::JoinHandle<T>>,
    others: Box<Any>,
}

impl<T:Send+'static> WorkerGuards<T> {
    /// Waits on the worker threads and returns the results they produce.
    pub fn join(mut self) -> Vec<Result<T,String>> {
        self.guards.drain(..)
                   .map(|guard| guard.join().map_err(|e| format!("{:?}", e)))
                   .collect()
    }
}

impl<T:Send+'static> Drop for WorkerGuards<T> {
    fn drop(&mut self) {
        for guard in self.guards.drain(..) {
            guard.join().expect("Worker panic");
        }
        // println!("WORKER THREADS JOINED");
    }
}
<|endoftext|>


<commit_before>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use decoders::ljpeg::*;
use decoders::cfa::*;
use std::f32::NAN;
use std::cmp;

#[derive(Debug, Clone)]
pub struct DngDecoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> DngDecoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> DngDecoder<'a> {
    DngDecoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for DngDecoder<'a> {
  fn image(&self) -> Result<Image,String> {
    let ifds = self.tiff.find_ifds_with_tag(Tag::Compression).into_iter().filter(|ifd| {
      let compression = (**ifd).find_entry(Tag::Compression).unwrap().get_u32(0);
      let subsampled = match (**ifd).find_entry(Tag::NewSubFileType) {
        Some(e) => e.get_u32(0) & 1 != 0,
        None => false,
      };
      !subsampled && (compression == 7 || compression == 1 || compression == 0x884c)
    }).collect::<Vec<&TiffIFD>>();
    let raw = ifds[0];
    let width = fetch_tag!(raw, Tag::ImageWidth).get_usize(0);
    let height = fetch_tag!(raw, Tag::ImageLength).get_usize(0);

    let image = match fetch_tag!(raw, Tag::Compression).get_u32(0) {
      1 => try!(self.decode_uncompressed(raw, width, height)),
      7 => try!(self.decode_compressed(raw, width, height)),
      c => return Err(format!("Don't know how to read DNGs with compression {}", c).to_string()),
    };

    let (make, model, clean_make, clean_model) = {
      match self.rawloader.check_supported(&self.tiff) {
        Ok(cam) => {
          (cam.make.clone(), cam.model.clone(),
           cam.clean_make.clone(),cam.clean_model.clone())
        },
        Err(_) => {
          let make = fetch_tag!(self.tiff, Tag::Make).get_str();
          let model = fetch_tag!(self.tiff, Tag::Model).get_str();
          (make.to_string(), model.to_string(), make.to_string(), model.to_string())
        },
      }
    };

    Ok(Image {
      make: make,
      model: model,
      clean_make: clean_make,
      clean_model: clean_model,
      width: width,
      height: height,
      wb_coeffs: try!(self.get_wb()),
      data: image.into_boxed_slice(),
      blacklevels: try!(self.get_blacklevels(raw)),
      whitelevels: try!(self.get_whitelevels(raw)),
      xyz_to_cam: try!(self.get_color_matrix()),
      cfa: try!(self.get_cfa(raw)),
      crops: try!(self.get_crops(raw, width, height)),
    })
  }
}

impl<'a> DngDecoder<'a> {
  fn get_wb(&self) -> Result<[f32;4], String> {
    let levels = fetch_tag!(self.tiff, Tag::AsShotNeutral);
    Ok([1.0/levels.get_f32(0),1.0/levels.get_f32(1),1.0/levels.get_f32(2),NAN])
  }

  fn get_blacklevels(&self, raw: &TiffIFD) -> Result<[u16;4], String> {
    if let Some(levels) = raw.find_entry(Tag::BlackLevels) {
      if levels.count() < 4 {
        let black = levels.get_f32(0) as u16;
        Ok([black, black, black, black])
      } else {
        Ok([levels.get_f32(0) as u16,levels.get_f32(1) as u16,
            levels.get_f32(2) as u16,levels.get_f32(3) as u16])
      }
    } else {
      Ok([0,0,0,0])
    }
  }

  fn get_whitelevels(&self, raw: &TiffIFD) -> Result<[u16;4], String> {
    let level = fetch_tag!(raw, Tag::WhiteLevel).get_u32(0) as u16;
    Ok([level,level,level,level])
  }

  fn get_cfa(&self, raw: &TiffIFD) -> Result<CFA,String> {
    let pattern = fetch_tag!(raw, Tag::CFAPattern);
    Ok(CFA::new_from_tag(pattern))
  }

  fn get_crops(&self, raw: &TiffIFD, width: usize, height: usize) -> Result<[usize;4],String> {
    if let Some(crops) = raw.find_entry(Tag::ActiveArea) {
      Ok([crops.get_usize(0), width - crops.get_usize(3),
          height - crops.get_usize(2), crops.get_usize(1)])
    } else {
      // Ignore missing crops, at least some pentax DNGs don't have it
      Ok([0,0,0,0])
    }
  }

  fn get_color_matrix(&self) -> Result<[[f32;3];4],String> {
    let mut matrix: [[f32;3];4] = [[0.0;3];4];
    let cmatrix = {
      if let Some(c) = self.tiff.find_entry(Tag::ColorMatrix2) {
        c
      } else {
        fetch_tag!(self.tiff, Tag::ColorMatrix1)
      }
    };
    if cmatrix.count() > 12 {
      Err(format!("color matrix supposedly has {} components",cmatrix.count()).to_string())
    } else {
      for i in 0..cmatrix.count() {
        matrix[i/3][i%3] = cmatrix.get_f32(i);
      }
      Ok(matrix)
    }
  }

  pub fn decode_uncompressed(&self, raw: &TiffIFD, width: usize, height: usize) -> Result<Vec<u16>,String> {
    let offset = fetch_tag!(raw, Tag::StripOffsets).get_usize(0);
    let src = &self.buffer[offset..];

    match fetch_tag!(raw, Tag::BitsPerSample).get_u32(0) {
      16  => Ok(decode_16le(src, width, height)),
      12  => Ok(decode_12be(src, width, height)),
      10  => Ok(decode_10le(src, width, height)),
      8   => {
        // It's 8 bit so there will be linearization involved surely!
        let linearization = fetch_tag!(self.tiff, Tag::Linearization);
        let curve = {
          let mut points = vec![0 as u16; 256];
          for i in 0..256 {
            points[i] = linearization.get_u32(i) as u16;
          }
          LookupTable::new(&points)
        };
        Ok(decode_8bit_wtable(src, &curve, width, height))
      },
      bps => Err(format!("DNG: Don't know about {} bps images", bps).to_string()),
    }
  }

  pub fn decode_compressed(&self, raw: &TiffIFD, width: usize, height: usize) -> Result<Vec<u16>,String> {
    if let Some(offsets) = raw.find_entry(Tag::StripOffsets) { // We're in a normal offset situation
      if offsets.count() != 1 {
        return Err("DNG: files with more than one slice not supported yet".to_string())
      }
      let offset = offsets.get_usize(0);
      let src = &self.buffer[offset..];
      let mut out = vec![0 as u16; width*height];
      let decompressor = try!(LjpegDecompressor::new(src, true));
      try!(decompressor.decode(&mut out, 0, width, width, height));
      Ok(out)
    } else if let Some(offsets) = raw.find_entry(Tag::TileOffsets) {
      // They've gone with tiling
      let twidth = fetch_tag!(raw, Tag::TileWidth).get_usize(0);
      let tlength = fetch_tag!(raw, Tag::TileLength).get_usize(0);
      let coltiles = (width-1)/twidth + 1;
      let rowtiles = (height-1)/tlength + 1;
      if coltiles*rowtiles != offsets.count() {
        return Err(format!("DNG: trying to decode {} tiles from {} offsets",
                           coltiles*rowtiles, offsets.count()).to_string())
      }

      Ok(decode_threaded_multiline(width, height, tlength, &(|strip: &mut [u16], row| {
        let row = row / tlength;
        for col in 0..coltiles {
          let offset = offsets.get_usize(row*coltiles+col);
          let src = &self.buffer[offset..];
          // We don't use bigtable here as the tiles are two small to amortize the setup cost
          let decompressor = LjpegDecompressor::new(src, false).unwrap();
          let bwidth = cmp::min(width, (col+1)*twidth) - col*twidth;
          let blength = cmp::min(height, (row+1)*tlength) - row*tlength;
          // FIXME: instead of unwrap() we need to propagate the error
          decompressor.decode(strip, col*twidth, width, bwidth, blength).unwrap();
        }
      })))
    } else {
      Err("DNG: didn't find tiles or strips".to_string())
    }
  }
}
<commit_msg>DNG: use bigtable always as it seems worthwhile<commit_after>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use decoders::ljpeg::*;
use decoders::cfa::*;
use std::f32::NAN;
use std::cmp;

#[derive(Debug, Clone)]
pub struct DngDecoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> DngDecoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> DngDecoder<'a> {
    DngDecoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for DngDecoder<'a> {
  fn image(&self) -> Result<Image,String> {
    let ifds = self.tiff.find_ifds_with_tag(Tag::Compression).into_iter().filter(|ifd| {
      let compression = (**ifd).find_entry(Tag::Compression).unwrap().get_u32(0);
      let subsampled = match (**ifd).find_entry(Tag::NewSubFileType) {
        Some(e) => e.get_u32(0) & 1 != 0,
        None => false,
      };
      !subsampled && (compression == 7 || compression == 1 || compression == 0x884c)
    }).collect::<Vec<&TiffIFD>>();
    let raw = ifds[0];
    let width = fetch_tag!(raw, Tag::ImageWidth).get_usize(0);
    let height = fetch_tag!(raw, Tag::ImageLength).get_usize(0);

    let image = match fetch_tag!(raw, Tag::Compression).get_u32(0) {
      1 => try!(self.decode_uncompressed(raw, width, height)),
      7 => try!(self.decode_compressed(raw, width, height)),
      c => return Err(format!("Don't know how to read DNGs with compression {}", c).to_string()),
    };

    let (make, model, clean_make, clean_model) = {
      match self.rawloader.check_supported(&self.tiff) {
        Ok(cam) => {
          (cam.make.clone(), cam.model.clone(),
           cam.clean_make.clone(),cam.clean_model.clone())
        },
        Err(_) => {
          let make = fetch_tag!(self.tiff, Tag::Make).get_str();
          let model = fetch_tag!(self.tiff, Tag::Model).get_str();
          (make.to_string(), model.to_string(), make.to_string(), model.to_string())
        },
      }
    };

    Ok(Image {
      make: make,
      model: model,
      clean_make: clean_make,
      clean_model: clean_model,
      width: width,
      height: height,
      wb_coeffs: try!(self.get_wb()),
      data: image.into_boxed_slice(),
      blacklevels: try!(self.get_blacklevels(raw)),
      whitelevels: try!(self.get_whitelevels(raw)),
      xyz_to_cam: try!(self.get_color_matrix()),
      cfa: try!(self.get_cfa(raw)),
      crops: try!(self.get_crops(raw, width, height)),
    })
  }
}

impl<'a> DngDecoder<'a> {
  fn get_wb(&self) -> Result<[f32;4], String> {
    let levels = fetch_tag!(self.tiff, Tag::AsShotNeutral);
    Ok([1.0/levels.get_f32(0),1.0/levels.get_f32(1),1.0/levels.get_f32(2),NAN])
  }

  fn get_blacklevels(&self, raw: &TiffIFD) -> Result<[u16;4], String> {
    if let Some(levels) = raw.find_entry(Tag::BlackLevels) {
      if levels.count() < 4 {
        let black = levels.get_f32(0) as u16;
        Ok([black, black, black, black])
      } else {
        Ok([levels.get_f32(0) as u16,levels.get_f32(1) as u16,
            levels.get_f32(2) as u16,levels.get_f32(3) as u16])
      }
    } else {
      Ok([0,0,0,0])
    }
  }

  fn get_whitelevels(&self, raw: &TiffIFD) -> Result<[u16;4], String> {
    let level = fetch_tag!(raw, Tag::WhiteLevel).get_u32(0) as u16;
    Ok([level,level,level,level])
  }

  fn get_cfa(&self, raw: &TiffIFD) -> Result<CFA,String> {
    let pattern = fetch_tag!(raw, Tag::CFAPattern);
    Ok(CFA::new_from_tag(pattern))
  }

  fn get_crops(&self, raw: &TiffIFD, width: usize, height: usize) -> Result<[usize;4],String> {
    if let Some(crops) = raw.find_entry(Tag::ActiveArea) {
      Ok([crops.get_usize(0), width - crops.get_usize(3),
          height - crops.get_usize(2), crops.get_usize(1)])
    } else {
      // Ignore missing crops, at least some pentax DNGs don't have it
      Ok([0,0,0,0])
    }
  }

  fn get_color_matrix(&self) -> Result<[[f32;3];4],String> {
    let mut matrix: [[f32;3];4] = [[0.0;3];4];
    let cmatrix = {
      if let Some(c) = self.tiff.find_entry(Tag::ColorMatrix2) {
        c
      } else {
        fetch_tag!(self.tiff, Tag::ColorMatrix1)
      }
    };
    if cmatrix.count() > 12 {
      Err(format!("color matrix supposedly has {} components",cmatrix.count()).to_string())
    } else {
      for i in 0..cmatrix.count() {
        matrix[i/3][i%3] = cmatrix.get_f32(i);
      }
      Ok(matrix)
    }
  }

  pub fn decode_uncompressed(&self, raw: &TiffIFD, width: usize, height: usize) -> Result<Vec<u16>,String> {
    let offset = fetch_tag!(raw, Tag::StripOffsets).get_usize(0);
    let src = &self.buffer[offset..];

    match fetch_tag!(raw, Tag::BitsPerSample).get_u32(0) {
      16  => Ok(decode_16le(src, width, height)),
      12  => Ok(decode_12be(src, width, height)),
      10  => Ok(decode_10le(src, width, height)),
      8   => {
        // It's 8 bit so there will be linearization involved surely!
        let linearization = fetch_tag!(self.tiff, Tag::Linearization);
        let curve = {
          let mut points = vec![0 as u16; 256];
          for i in 0..256 {
            points[i] = linearization.get_u32(i) as u16;
          }
          LookupTable::new(&points)
        };
        Ok(decode_8bit_wtable(src, &curve, width, height))
      },
      bps => Err(format!("DNG: Don't know about {} bps images", bps).to_string()),
    }
  }

  pub fn decode_compressed(&self, raw: &TiffIFD, width: usize, height: usize) -> Result<Vec<u16>,String> {
    if let Some(offsets) = raw.find_entry(Tag::StripOffsets) { // We're in a normal offset situation
      if offsets.count() != 1 {
        return Err("DNG: files with more than one slice not supported yet".to_string())
      }
      let offset = offsets.get_usize(0);
      let src = &self.buffer[offset..];
      let mut out = vec![0 as u16; width*height];
      let decompressor = try!(LjpegDecompressor::new(src, true));
      try!(decompressor.decode(&mut out, 0, width, width, height));
      Ok(out)
    } else if let Some(offsets) = raw.find_entry(Tag::TileOffsets) {
      // They've gone with tiling
      let twidth = fetch_tag!(raw, Tag::TileWidth).get_usize(0);
      let tlength = fetch_tag!(raw, Tag::TileLength).get_usize(0);
      let coltiles = (width-1)/twidth + 1;
      let rowtiles = (height-1)/tlength + 1;
      if coltiles*rowtiles != offsets.count() {
        return Err(format!("DNG: trying to decode {} tiles from {} offsets",
                           coltiles*rowtiles, offsets.count()).to_string())
      }

      Ok(decode_threaded_multiline(width, height, tlength, &(|strip: &mut [u16], row| {
        let row = row / tlength;
        for col in 0..coltiles {
          let offset = offsets.get_usize(row*coltiles+col);
          let src = &self.buffer[offset..];
          let decompressor = LjpegDecompressor::new(src, true).unwrap();
          let bwidth = cmp::min(width, (col+1)*twidth) - col*twidth;
          let blength = cmp::min(height, (row+1)*tlength) - row*tlength;
          // FIXME: instead of unwrap() we need to propagate the error
          decompressor.decode(strip, col*twidth, width, bwidth, blength).unwrap();
        }
      })))
    } else {
      Err("DNG: didn't find tiles or strips".to_string())
    }
  }
}
<|endoftext|>


<commit_before>#![feature(core)]
#![feature(no_std)]
#![no_std]

//! Transmit "Hello, world!" via USART1 (PA8)

extern crate core;
extern crate cortex;
extern crate stm32;

const CLOCK: u32 = 8_000_000;
const BAUD_RATE: u32 = 115_200;

#[no_mangle]
pub fn main() {
    let gpioa = stm32::peripheral::gpioa();
    let nvic = cortex::peripheral::nvic();
    let rcc = stm32::peripheral::rcc();
    let usart1 = stm32::peripheral::usart1();

    // Enable GPIOA and USART1
    rcc.apb2enr.update(|apb2enr| {
        use stm32::rcc::apb2enr::prelude::*;

        apb2enr | IOPAEN | USART1EN
    });

    // Configure PA8 as USART1 TX
    gpioa.crh.update(|crh| {
        use stm32::gpio::crh::prelude::*;

        crh.configure(Pin::_9, Mode::Output(Alternate, PushPull, _2MHz))
    });

    // Enable USART, transmitter and transmission complete interrupt
    usart1.cr1.set({
        use stm32::usart::cr1::prelude::*;

        TE | TCIE | UE
    });

    // Set baud rate
    usart1.brr.set({
        (CLOCK / BAUD_RATE) as u16
    });

    // Enable USART1 interrupt
    nvic.iser1.set({
        use cortex::nvic::iser1::prelude::*;

        _37  // USART1
    });

    let message = b"Hello, world!\n\r";

    for &byte in message {
        // enqueue byte in the transmit register
        usart1.dr.set(byte);

        // wait for interrupt
        cortex::asm::wfi();
    }
}

#[no_mangle]
pub fn usart1() {
    let usart1 = stm32::peripheral::usart1();

    // Clear transmission complete flag
    usart1.sr.update(|sr| {
        use stm32::usart::sr::prelude::*;

        sr & !TC
    });
}
<commit_msg>refactor(usart_tx): use &str instead of &[u8; _]<commit_after>#![feature(core)]
#![feature(no_std)]
#![no_std]

//! Transmit "Hello, world!" via USART1 (PA8)

extern crate core;
extern crate cortex;
extern crate stm32;

use core::prelude::*;

const CLOCK: u32 = 8_000_000;
const BAUD_RATE: u32 = 115_200;

#[no_mangle]
pub fn main() {
    let gpioa = stm32::peripheral::gpioa();
    let nvic = cortex::peripheral::nvic();
    let rcc = stm32::peripheral::rcc();
    let usart1 = stm32::peripheral::usart1();

    // Enable GPIOA and USART1
    rcc.apb2enr.update(|apb2enr| {
        use stm32::rcc::apb2enr::prelude::*;

        apb2enr | IOPAEN | USART1EN
    });

    // Configure PA8 as USART1 TX
    gpioa.crh.update(|crh| {
        use stm32::gpio::crh::prelude::*;

        crh.configure(Pin::_9, Mode::Output(Alternate, PushPull, _2MHz))
    });

    // Enable USART, transmitter and transmission complete interrupt
    usart1.cr1.set({
        use stm32::usart::cr1::prelude::*;

        TE | TCIE | UE
    });

    // Set baud rate
    usart1.brr.set({
        (CLOCK / BAUD_RATE) as u16
    });

    // Enable USART1 interrupt
    nvic.iser1.set({
        use cortex::nvic::iser1::prelude::*;

        _37  // USART1
    });

    let message = "Hello, world!\n\r";

    for byte in message.bytes() {
        // enqueue byte in the transmit register
        usart1.dr.set(byte);

        // wait for interrupt
        cortex::asm::wfi();
    }
}

#[no_mangle]
pub fn usart1() {
    let usart1 = stm32::peripheral::usart1();

    // Clear transmission complete flag
    usart1.sr.update(|sr| {
        use stm32::usart::sr::prelude::*;

        sr & !TC
    });
}
<|endoftext|>


<commit_before>/// Asserts that types are equal in alignment.
///
/// This is useful when ensuring that pointer arithmetic is done correctly, or
/// when [FFI] requires a type to have the same alignment as some foreign type.
///
/// # Examples
///
/// A `usize` has the same alignment as any pointer type:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_eq!(usize, *const u8, *mut u8);
/// ```
///
/// The following passes because `[i32; 4]` has the same alignment as `i32`:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_eq!([i32; 4], i32);
/// ```
///
/// The following example fails to compile because `i32x4` explicitly has 4
/// times the alignment as `[i32; 4]`:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// # #[allow(non_camel_case_types)]
/// #[repr(align(16))]
/// struct i32x4([i32; 4]);
///
/// assert_align_eq!(i32x4, [i32; 4]);
/// ```
///
/// [FFI]: https://en.wikipedia.org/wiki/Foreign_function_interface
#[macro_export(local_inner_macros)]
macro_rules! assert_align_eq {
    ($x:ty, $($y:ty),+ $(,)?) => {
        const _: fn() = || {
            use $crate::_core::mem::align_of;
            const_assert_eq_usize!(align_of::<$x>() $(, align_of::<$y>())+);
        };
    };
}

/// Asserts that types are equal in alignment.
///
/// This macro has been deprecated in favor of
/// [`assert_align_eq!`](macro.assert_align_eq.html).
#[deprecated(
    since = "1.2.0",
    note = "Please use the 'assert_align_eq' macro instead",
)]
#[macro_export(local_inner_macros)]
macro_rules! assert_eq_align {
    ($($t:tt)*) => {
        assert_align_eq!($($t)*);
    };
}
<commit_msg>Create `assert_align_{ne,lt,le,gt,ge}!` macros<commit_after>/// Asserts that the types' alignments are equal.
///
/// This is useful when ensuring that pointer arithmetic is done correctly, or
/// when [FFI] requires a type to have the same alignment as some foreign type.
///
/// # Examples
///
/// A `usize` has the same alignment as any pointer type:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_eq!(usize, *const u8, *mut u8);
/// ```
///
/// The following passes because `[i32; 4]` has the same alignment as `i32`:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_eq!([i32; 4], i32);
/// ```
///
/// The following example fails to compile because `i32x4` explicitly has 4
/// times the alignment as `[i32; 4]`:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// # #[allow(non_camel_case_types)]
/// #[repr(align(16))]
/// struct i32x4([i32; 4]);
///
/// assert_align_eq!(i32x4, [i32; 4]);
/// ```
///
/// [FFI]: https://en.wikipedia.org/wiki/Foreign_function_interface
#[macro_export(local_inner_macros)]
macro_rules! assert_align_eq {
    ($x:ty, $($y:ty),+ $(,)?) => {
        const _: fn() = || {
            use $crate::_core::mem::align_of;
            const_assert_eq_usize!(align_of::<$x>() $(, align_of::<$y>())+);
        };
    };
}

/// Asserts that the types' alignments are equal.
///
/// This macro has been deprecated in favor of
/// [`assert_align_eq!`](macro.assert_align_eq.html).
#[deprecated(
    since = "1.2.0",
    note = "Please use the 'assert_align_eq' macro instead",
)]
#[macro_export(local_inner_macros)]
macro_rules! assert_eq_align {
    ($($t:tt)*) => {
        assert_align_eq!($($t)*);
    };
}

/// Asserts that the types' alignments are **not** equal.
///
/// # Examples
///
/// A `u8` does not have the same alignment as a pointer:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_ne!(u8, *const u8);
/// ```
///
/// The following example fails to compile because a `usize` has the same
/// alignment as a pointer:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_ne!(*const u8, usize);
/// ```
#[macro_export(local_inner_macros)]
macro_rules! assert_align_ne {
    ($x:ty, $($y:ty),+ $(,)?) => {
        const _: fn() = || {
            use $crate::_core::mem::align_of;
            const_assert_ne!(align_of::<$x>() $(, align_of::<$y>())+);
        };
    };
}

/// Asserts that the types' alignments are less than each other.
///
/// # Examples
///
/// A `u8` has smaller alignment than `u16`, which has smaller alignment than
/// a pointer:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_lt!(u8, u16, *const u8);
/// ```
///
/// The following example fails to compile because a `usize` has the same
/// alignment as a pointer:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_lt!(*const u8, usize);
/// ```
#[macro_export(local_inner_macros)]
macro_rules! assert_align_lt {
    ($x:ty, $($y:ty),+ $(,)?) => {
        const _: fn() = || {
            use $crate::_core::mem::align_of;
            const_assert_lt!(align_of::<$x>() $(, align_of::<$y>())+);
        };
    };
}

/// Asserts that the types' alignments are less than or equal to each other.
///
/// # Examples
///
/// A `u8` and `i8` have smaller alignment than any pointer type:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_le!(u8, i8, *const u8);
/// ```
///
/// The following example fails to compile because a `usize` has greater
/// alignment than `u8`:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_le!(usize, u8);
/// ```
#[macro_export(local_inner_macros)]
macro_rules! assert_align_le {
    ($x:ty, $($y:ty),+ $(,)?) => {
        const _: fn() = || {
            use $crate::_core::mem::align_of;
            const_assert_le!(align_of::<$x>() $(, align_of::<$y>())+);
        };
    };
}

/// Asserts that the types' alignments are greater than each other.
///
/// # Examples
///
/// A pointer has greater alignment than `u16`, which has greater alignment than
/// `u8`:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_gt!(*const u8, u16, u8);
/// ```
///
/// The following example fails to compile because a `usize` has the same
/// alignment as a pointer:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_gt!(*const u8, usize);
/// ```
#[macro_export(local_inner_macros)]
macro_rules! assert_align_gt {
    ($x:ty, $($y:ty),+ $(,)?) => {
        const _: fn() = || {
            use $crate::_core::mem::align_of;
            const_assert_gt!(align_of::<$x>() $(, align_of::<$y>())+);
        };
    };
}

/// Asserts that the types' alignments are greater than or equal to each other.
///
/// # Examples
///
/// A pointer has greater alignment than `u8` and `i8`:
///
/// ```
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_ge!(*const u8, u8, i8);
/// ```
///
/// The following example fails to compile because a `u8` has smaller alignment
/// than `usize`:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions; fn main() {}
/// assert_align_ge!(u8, usize);
/// ```
#[macro_export(local_inner_macros)]
macro_rules! assert_align_ge {
    ($x:ty, $($y:ty),+ $(,)?) => {
        const _: fn() = || {
            use $crate::_core::mem::align_of;
            const_assert_ge!(align_of::<$x>() $(, align_of::<$y>())+);
        };
    };
}
<|endoftext|>


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

use ffiasync;
use libc::{c_char, c_int, c_void};
use std::ffi::{CStr, CString};
use std::mem;
use std::slice;
use std::sync::{Barrier, Arc, Mutex, Condvar};

use super::Message;
use super::options::{PersistenceType, Qos, AsyncConnectOptions, AsyncDisconnectOptions};
use super::error::{MqttError, CommandError, ConnectError, ConnectErrReturnCode, DisconnectError, DisconnectErrReturnCode, CallbackError};
use super::iterator::AsyncClientIntoIterator;

pub struct AsyncClient {
    inner: Box<ImmovableClient>
}

impl AsyncClient {
    pub fn new(address: &str, clientid: &str, persistence: PersistenceType) -> Result<Self, MqttError> {
        let mut ac = AsyncClient {
            inner: Box::new(ImmovableClient::new(address, clientid, persistence))
        };
        try!(ac.inner.create());
        Ok(ac)
    }
    pub fn connect(&mut self, options: &AsyncConnectOptions) -> Result<(), MqttError> {
        self.inner.connect(options)
    }
    pub fn disconnect(&mut self, options: &AsyncDisconnectOptions) -> Result<(), MqttError> {
        self.inner.disconnect(options)
    }
    pub fn is_connected(&self) -> bool {
        self.inner.is_connected()
    }
    pub fn send(&mut self, data: &[u8], topic: &str, qos: Qos) -> Result<(), MqttError> {
        self.inner.send(data, topic, qos)
    }
    pub fn subscribe(&mut self, topic: &str, qos: Qos) -> Result<(), MqttError> {
        self.inner.subscribe(topic, qos)
    }
    pub fn messages(&mut self, timeout_ms: Option<u32>) -> AsyncClientIntoIterator {
        AsyncClientIntoIterator::new(self.inner.messages.clone(), timeout_ms)
    }
}

struct ImmovableClient {
    c_url               : CString,
    c_clientid          : CString,
    handle              : ffiasync::MQTTAsync,
    persistence_context : c_void,
    persistence         : PersistenceType,

    barrier       : Barrier,
    action_result : Option<Result<(), CallbackError>>,
    pub messages  : Arc<(Mutex<Vec<Message>>, Condvar)>,
}
impl ImmovableClient {
    fn context(&mut self) -> *mut c_void {
        self as *mut _ as *mut c_void
    }

    pub fn new(address: &str, clientid: &str, persistence: PersistenceType) -> Self {
        ImmovableClient {
                    c_url               : CString::new(address).unwrap(),
                    c_clientid          : CString::new(clientid).unwrap(),
                    handle              : unsafe{mem::zeroed()},
                    persistence_context : unsafe{mem::zeroed()},
                    persistence         : persistence,

                    barrier         : Barrier::new(2),
                    action_result   : None,
                    messages        : Arc::new((Mutex::new(Vec::new()), Condvar::new())),
        }
    }

    pub fn create(&mut self) -> Result<(), MqttError> {
        let array_url      = self.c_url.as_bytes_with_nul();
        let array_clientid = self.c_clientid.as_bytes_with_nul();
        let error = unsafe {
            ffiasync::MQTTAsync_create(&mut self.handle,
                                       mem::transmute::<&u8, *const c_char>(&array_url[0]),
                                       mem::transmute::<&u8, *const c_char>(&array_clientid[0]),
                                       self.persistence as i32,
                                       &mut self.persistence_context)
        };
        match error {
            0   => { Ok(())},
            err => Err(MqttError::Create(err))
        }
    }

    pub fn connect(&mut self, options: &AsyncConnectOptions) -> Result<(), MqttError> {
        debug!("connect..");
        unsafe {
            ffiasync::MQTTAsync_setCallbacks(self.handle,
                                             self.context(),
                                             Some(Self::disconnected),
                                             Some(Self::received),
                                             None);
        }

        let mut async_opts = ffiasync::MQTTAsync_connectOptions::new();

        // fill in FFI private struct
        async_opts.keepAliveInterval = options.keep_alive_interval;
        async_opts.cleansession      = options.cleansession;
        async_opts.maxInflight       = options.max_in_flight;
        async_opts.connectTimeout    = options.connect_timeout;
        async_opts.retryInterval     = options.retry_interval;

        // register callbacks
        async_opts.context   = self.context();
        async_opts.onSuccess = Some(Self::action_succeeded);
        async_opts.onFailure = Some(Self::action_failed);

        self.action_result = None;
        let error = unsafe {
            ffiasync::MQTTAsync_connect(self.handle, &async_opts)
        };
        if error == 0 {
            self.barrier.wait();
            match (self.is_connected(), &self.action_result) {
                (true,  _                                     ) => Ok(()),
                (false, &None                                 ) => unreachable!(),  // barrier should ensure we have something
                (false, &Some(Ok(()))                         ) => unreachable!(),  // callback and is_connected() don't agree?
                (false, &Some(Err(CallbackError::Response(r)))) => Err(MqttError::Connect(ConnectError::CallbackResponse(r))),
                (false, &Some(Err(CallbackError::NullPtr))    ) => Err(MqttError::Connect(ConnectError::CallbackNullPtr)),
            }
        } else { Err(MqttError::Connect(ConnectError::ReturnCode(ConnectErrReturnCode::from_int(error)))) }
    }

    pub fn disconnect(&mut self, options: &AsyncDisconnectOptions) -> Result<(), MqttError> {
        debug!("disconnect..");
        // client must be already conneced to do disconnect
        if !self.is_connected() {
            Ok(())
        }
        else {
            let mut async_opts = ffiasync::MQTTAsync_disconnectOptions::new();

            // fill in FFI private struct
            async_opts.timeout = options.timeout;

            // register callbacks
            async_opts.context   = self.context();
            async_opts.onSuccess = Some(Self::action_succeeded);
            async_opts.onFailure = Some(Self::action_failed);

            self.action_result = None;
            let error = unsafe {
                ffiasync::MQTTAsync_disconnect(self.handle, &async_opts)
            };
            if error == 0 {
                self.barrier.wait();
                match (self.is_connected(), &self.action_result) {
                    (false, _                                     ) => Ok(()),
                    (_,     &None                                 ) => unreachable!(),  // barrier should ensure we have something
                    (_,     &Some(Ok(()))                         ) => unreachable!(),  // callback and is_connected() don't agree?
                    (_,     &Some(Err(CallbackError::Response(r)))) => Err(MqttError::Disconnect(DisconnectError::CallbackResponse(r))),
                    (_,     &Some(Err(CallbackError::NullPtr))    ) => Err(MqttError::Disconnect(DisconnectError::CallbackNullPtr)),
                }
            } else { Err(MqttError::Disconnect(DisconnectError::ReturnCode(DisconnectErrReturnCode::from_int(error)))) }
        }
    }

    #[allow(unused_variables)]
    extern "C" fn disconnected(context: *mut c_void, cause: *mut c_char) -> () {
        warn!("disconnected");
        assert!(!context.is_null());
    }

    pub fn is_connected(&self) -> bool {
        let ret = unsafe {
            ffiasync::MQTTAsync_isConnected(self.handle)
        };

        match ret {
            1 => true,
            _ => false,
        }
    }

    pub fn send(&mut self, data: &[u8], topic: &str, qos: Qos) -> Result<(), MqttError> {
        debug!("send..");
        let mut responseoption = ffiasync::MQTTAsync_responseOptions {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'R' as i8],
            struct_version  : 0,
            onSuccess       : Some(Self::action_succeeded),
            onFailure       : Some(Self::action_failed),
            context         : self.context(),
            token           : 0,
        };

        let mut message = ffiasync::MQTTAsync_message {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'M' as i8],
            struct_version  : 0,
            payloadlen      : data.len() as i32,
            payload         : unsafe {mem::transmute::<&u8, *mut c_void>(&data[0])},
            qos             : qos as c_int,
            retained        : 0,
            dup             : 0,
            msgid           : 0,
        };

        let c_topic        = CString::new(topic).unwrap();
        let array_topic    = c_topic.as_bytes_with_nul();
        self.action_result = None;

        let error = unsafe {
            ffiasync::MQTTAsync_sendMessage(self.handle,
                                            mem::transmute::<&u8, *const c_char>(&array_topic[0]),
                                            &mut message,
                                            &mut responseoption)
        };
        if error == 0 {
            self.barrier.wait();
            match (self.is_connected(), &self.action_result) {
                (true,  _                                     ) => Ok(()),
                (false, &None                                 ) => unreachable!(),  // barrier should ensure we have something
                (false, &Some(Ok(()))                         ) => unreachable!(),  // callback and is_connected() don't agree?
                (false, &Some(Err(CallbackError::Response(r)))) => Err(MqttError::Send(CommandError::CallbackResponse(r))),
                (false, &Some(Err(CallbackError::NullPtr))    ) => Err(MqttError::Send(CommandError::CallbackNullPtr)),
            }
        } else { Err(MqttError::Send(CommandError::ReturnCode(error))) }
    }

    pub fn subscribe(&mut self, topic: &str, qos: Qos) -> Result<(), MqttError> {
        debug!("subscribe..");
        let mut responseoption = ffiasync::MQTTAsync_responseOptions {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'R' as i8],
            struct_version  : 0,
            onSuccess       : Some(Self::action_succeeded),
            onFailure       : Some(Self::action_failed),
            context         : self.context(),
            token           : 0,
        };

        let c_topic     = CString::new(topic).unwrap();
        let array_topic = c_topic.as_bytes_with_nul();

        let c_qos: i32 = match qos {
            Qos::FireAndForget  => 0,
            Qos::AtLeastOnce    => 1,
            Qos::OnceAndOneOnly => 2,
        };
        self.action_result = None;

        let error = unsafe {
            ffiasync::MQTTAsync_subscribe(self.handle,
                                          mem::transmute::<&u8, *const c_char>(&array_topic[0]),
                                          c_qos,
                                          &mut responseoption)
        };

        if error == 0 {
            self.barrier.wait();
            match (self.is_connected(), &self.action_result) {
                (true,  _                                     ) => Ok(()),
                (false, &None                                 ) => unreachable!(),  // barrier should ensure we have something
                (false, &Some(Ok(()))                         ) => unreachable!(),  // callback and is_connected() don't agree?
                (false, &Some(Err(CallbackError::Response(r)))) => Err(MqttError::Subscribe(CommandError::CallbackResponse(r))),
                (false, &Some(Err(CallbackError::NullPtr))    ) => Err(MqttError::Subscribe(CommandError::CallbackNullPtr)),
            }
        } else { Err(MqttError::Subscribe(CommandError::ReturnCode(error))) }
    }

    #[allow(unused_variables)]
    extern "C" fn action_succeeded(context: *mut ::libc::c_void, response: *mut ffiasync::MQTTAsync_successData) -> () {
        debug!("success callback");
        assert!(!context.is_null());
        let selfclient: &mut ImmovableClient = unsafe {mem::transmute(context)};
        selfclient.action_result = Some(Ok(()));
        selfclient.barrier.wait();
    }

    extern "C" fn action_failed(context: *mut ::libc::c_void, response: *mut ffiasync::MQTTAsync_failureData) -> () {
        debug!("failure callback");
        assert!(!context.is_null());
        let selfclient : &mut ImmovableClient = unsafe {mem::transmute(context)};
        if response.is_null() {
            selfclient.action_result = Some(Err(CallbackError::NullPtr));
        } else {
            let resp : &mut ffiasync::MQTTAsync_failureData = unsafe {mem::transmute(response)};
            selfclient.action_result = Some(Err(CallbackError::Response(resp.code)));
        }
        selfclient.barrier.wait();
    }

    extern "C" fn received(context: *mut ::libc::c_void, topic_name: *mut ::libc::c_char, topic_len: ::libc::c_int, amessage: *mut ffiasync::MQTTAsync_message) -> i32 {
        let c_topic = unsafe {CStr::from_ptr(topic_name).to_bytes()};
        let topic   = String::from_utf8(c_topic.to_vec()).unwrap();
        assert_eq!(topic.len(), topic_len as usize);

        assert!(!amessage.is_null());
        let transmessage: &mut ffiasync::MQTTAsync_message = unsafe {mem::transmute(amessage)};

        let payload = match transmessage.payloadlen {
            0  => None,
            _ => {
                let payload_slice: &[u8] = unsafe {
                        slice::from_raw_parts(transmessage.payload as *mut u8, transmessage.payloadlen as usize)
                };
                Some(payload_slice.to_vec())
            }
        };

        assert!(!context.is_null());
        let selfclient : &mut ImmovableClient = unsafe {mem::transmute(context)};

        let qos = Qos::from_int(transmessage.qos);

        let retained: bool = match transmessage.retained {
            0 => false,
            1 => true,
            _ => unreachable!(),
        };

        let duplicate: bool = match transmessage.dup {
            0 => false,
            1 => true,
            _ => unreachable!(),
        };

        let msg = Message {
            topic     : topic,
            payload   : payload,
            qos       : qos,
            retained  : retained,
            duplicate : duplicate,
        };

        let &(ref msglock, ref cvar) = &*selfclient.messages;
        let mut messages = msglock.lock().unwrap();
        messages.push(msg);
        cvar.notify_one();

        let mut msg = amessage;
        unsafe{ffiasync::MQTTAsync_freeMessage(&mut msg)};
        unsafe{ffiasync::MQTTAsync_free(mem::transmute(topic_name))};
        1
    }

}
impl Drop for ImmovableClient {
    fn drop(&mut self) {
        unsafe{ffiasync::MQTTAsync_destroy(&mut self.handle)};
    }
}
<commit_msg>now it is possible to get received messages also via mpsc::channel<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Andres Vahter (andres.vahter@gmail.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

use ffiasync;
use libc::{c_char, c_int, c_void};
use std::ffi::{CStr, CString};
use std::mem;
use std::slice;
use std::sync::{Barrier, Arc, Mutex, Condvar};

use super::Message;
use super::options::{PersistenceType, Qos, AsyncConnectOptions, AsyncDisconnectOptions};
use super::error::{MqttError, CommandError, ConnectError, ConnectErrReturnCode, DisconnectError, DisconnectErrReturnCode, CallbackError};
use super::iterator::AsyncClientIntoIterator;

use std::sync::mpsc;

pub struct AsyncClient {
    inner: Box<ImmovableClient>
}

impl AsyncClient {
    pub fn new(address: &str, clientid: &str, persistence: PersistenceType, message_channel: Option<mpsc::Sender<Message>>) -> Result<Self, MqttError> {
        let mut ac = AsyncClient {
            inner: Box::new(ImmovableClient::new(address, clientid, persistence, message_channel))
        };
        try!(ac.inner.create());
        Ok(ac)
    }
    pub fn connect(&mut self, options: &AsyncConnectOptions) -> Result<(), MqttError> {
        self.inner.connect(options)
    }
    pub fn disconnect(&mut self, options: &AsyncDisconnectOptions) -> Result<(), MqttError> {
        self.inner.disconnect(options)
    }
    pub fn is_connected(&self) -> bool {
        self.inner.is_connected()
    }
    pub fn send(&mut self, data: &[u8], topic: &str, qos: Qos) -> Result<(), MqttError> {
        self.inner.send(data, topic, qos)
    }
    pub fn subscribe(&mut self, topic: &str, qos: Qos) -> Result<(), MqttError> {
        self.inner.subscribe(topic, qos)
    }
    pub fn messages(&mut self, timeout_ms: Option<u32>) -> AsyncClientIntoIterator {
        AsyncClientIntoIterator::new(self.inner.messages.clone(), timeout_ms)
    }
}

struct ImmovableClient {
    c_url               : CString,
    c_clientid          : CString,
    handle              : ffiasync::MQTTAsync,
    persistence_context : c_void,
    persistence         : PersistenceType,

    barrier       : Barrier,
    action_result : Option<Result<(), CallbackError>>,
    pub messages  : Arc<(Mutex<Vec<Message>>, Condvar)>,
    channel       : Option<mpsc::Sender<Message>>,
}
impl ImmovableClient {
    fn context(&mut self) -> *mut c_void {
        self as *mut _ as *mut c_void
    }

    pub fn new(address: &str, clientid: &str, persistence: PersistenceType, message_channel: Option<mpsc::Sender<Message>>) -> Self {
        ImmovableClient {
                    c_url               : CString::new(address).unwrap(),
                    c_clientid          : CString::new(clientid).unwrap(),
                    handle              : unsafe{mem::zeroed()},
                    persistence_context : unsafe{mem::zeroed()},
                    persistence         : persistence,

                    barrier         : Barrier::new(2),
                    action_result   : None,
                    messages        : Arc::new((Mutex::new(Vec::new()), Condvar::new())),
                    channel         : message_channel
        }
    }

    pub fn create(&mut self) -> Result<(), MqttError> {
        let array_url      = self.c_url.as_bytes_with_nul();
        let array_clientid = self.c_clientid.as_bytes_with_nul();
        let error = unsafe {
            ffiasync::MQTTAsync_create(&mut self.handle,
                                       mem::transmute::<&u8, *const c_char>(&array_url[0]),
                                       mem::transmute::<&u8, *const c_char>(&array_clientid[0]),
                                       self.persistence as i32,
                                       &mut self.persistence_context)
        };
        match error {
            0   => { Ok(())},
            err => Err(MqttError::Create(err))
        }
    }

    pub fn connect(&mut self, options: &AsyncConnectOptions) -> Result<(), MqttError> {
        debug!("connect..");
        unsafe {
            ffiasync::MQTTAsync_setCallbacks(self.handle,
                                             self.context(),
                                             Some(Self::disconnected),
                                             Some(Self::received),
                                             None);
        }

        let mut async_opts = ffiasync::MQTTAsync_connectOptions::new();

        // fill in FFI private struct
        async_opts.keepAliveInterval = options.keep_alive_interval;
        async_opts.cleansession      = options.cleansession;
        async_opts.maxInflight       = options.max_in_flight;
        async_opts.connectTimeout    = options.connect_timeout;
        async_opts.retryInterval     = options.retry_interval;

        // register callbacks
        async_opts.context   = self.context();
        async_opts.onSuccess = Some(Self::action_succeeded);
        async_opts.onFailure = Some(Self::action_failed);

        self.action_result = None;
        let error = unsafe {
            ffiasync::MQTTAsync_connect(self.handle, &async_opts)
        };
        if error == 0 {
            self.barrier.wait();
            match (self.is_connected(), &self.action_result) {
                (true,  _                                     ) => Ok(()),
                (false, &None                                 ) => unreachable!(),  // barrier should ensure we have something
                (false, &Some(Ok(()))                         ) => unreachable!(),  // callback and is_connected() don't agree?
                (false, &Some(Err(CallbackError::Response(r)))) => Err(MqttError::Connect(ConnectError::CallbackResponse(r))),
                (false, &Some(Err(CallbackError::NullPtr))    ) => Err(MqttError::Connect(ConnectError::CallbackNullPtr)),
            }
        } else { Err(MqttError::Connect(ConnectError::ReturnCode(ConnectErrReturnCode::from_int(error)))) }
    }

    pub fn disconnect(&mut self, options: &AsyncDisconnectOptions) -> Result<(), MqttError> {
        debug!("disconnect..");
        // client must be already conneced to do disconnect
        if !self.is_connected() {
            Ok(())
        }
        else {
            let mut async_opts = ffiasync::MQTTAsync_disconnectOptions::new();

            // fill in FFI private struct
            async_opts.timeout = options.timeout;

            // register callbacks
            async_opts.context   = self.context();
            async_opts.onSuccess = Some(Self::action_succeeded);
            async_opts.onFailure = Some(Self::action_failed);

            self.action_result = None;
            let error = unsafe {
                ffiasync::MQTTAsync_disconnect(self.handle, &async_opts)
            };
            if error == 0 {
                self.barrier.wait();
                match (self.is_connected(), &self.action_result) {
                    (false, _                                     ) => Ok(()),
                    (_,     &None                                 ) => unreachable!(),  // barrier should ensure we have something
                    (_,     &Some(Ok(()))                         ) => unreachable!(),  // callback and is_connected() don't agree?
                    (_,     &Some(Err(CallbackError::Response(r)))) => Err(MqttError::Disconnect(DisconnectError::CallbackResponse(r))),
                    (_,     &Some(Err(CallbackError::NullPtr))    ) => Err(MqttError::Disconnect(DisconnectError::CallbackNullPtr)),
                }
            } else { Err(MqttError::Disconnect(DisconnectError::ReturnCode(DisconnectErrReturnCode::from_int(error)))) }
        }
    }

    #[allow(unused_variables)]
    extern "C" fn disconnected(context: *mut c_void, cause: *mut c_char) -> () {
        warn!("disconnected");
        assert!(!context.is_null());
    }

    pub fn is_connected(&self) -> bool {
        let ret = unsafe {
            ffiasync::MQTTAsync_isConnected(self.handle)
        };

        match ret {
            1 => true,
            _ => false,
        }
    }

    pub fn send(&mut self, data: &[u8], topic: &str, qos: Qos) -> Result<(), MqttError> {
        debug!("send..");
        let mut responseoption = ffiasync::MQTTAsync_responseOptions {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'R' as i8],
            struct_version  : 0,
            onSuccess       : Some(Self::action_succeeded),
            onFailure       : Some(Self::action_failed),
            context         : self.context(),
            token           : 0,
        };

        let mut message = ffiasync::MQTTAsync_message {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'M' as i8],
            struct_version  : 0,
            payloadlen      : data.len() as i32,
            payload         : unsafe {mem::transmute::<&u8, *mut c_void>(&data[0])},
            qos             : qos as c_int,
            retained        : 0,
            dup             : 0,
            msgid           : 0,
        };

        let c_topic        = CString::new(topic).unwrap();
        let array_topic    = c_topic.as_bytes_with_nul();
        self.action_result = None;

        let error = unsafe {
            ffiasync::MQTTAsync_sendMessage(self.handle,
                                            mem::transmute::<&u8, *const c_char>(&array_topic[0]),
                                            &mut message,
                                            &mut responseoption)
        };
        if error == 0 {
            self.barrier.wait();
            match (self.is_connected(), &self.action_result) {
                (true,  _                                     ) => Ok(()),
                (false, &None                                 ) => unreachable!(),  // barrier should ensure we have something
                (false, &Some(Ok(()))                         ) => unreachable!(),  // callback and is_connected() don't agree?
                (false, &Some(Err(CallbackError::Response(r)))) => Err(MqttError::Send(CommandError::CallbackResponse(r))),
                (false, &Some(Err(CallbackError::NullPtr))    ) => Err(MqttError::Send(CommandError::CallbackNullPtr)),
            }
        } else { Err(MqttError::Send(CommandError::ReturnCode(error))) }
    }

    pub fn subscribe(&mut self, topic: &str, qos: Qos) -> Result<(), MqttError> {
        debug!("subscribe..");
        let mut responseoption = ffiasync::MQTTAsync_responseOptions {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'R' as i8],
            struct_version  : 0,
            onSuccess       : Some(Self::action_succeeded),
            onFailure       : Some(Self::action_failed),
            context         : self.context(),
            token           : 0,
        };

        let c_topic     = CString::new(topic).unwrap();
        let array_topic = c_topic.as_bytes_with_nul();

        let c_qos: i32 = match qos {
            Qos::FireAndForget  => 0,
            Qos::AtLeastOnce    => 1,
            Qos::OnceAndOneOnly => 2,
        };
        self.action_result = None;

        let error = unsafe {
            ffiasync::MQTTAsync_subscribe(self.handle,
                                          mem::transmute::<&u8, *const c_char>(&array_topic[0]),
                                          c_qos,
                                          &mut responseoption)
        };

        if error == 0 {
            self.barrier.wait();
            match (self.is_connected(), &self.action_result) {
                (true,  _                                     ) => Ok(()),
                (false, &None                                 ) => unreachable!(),  // barrier should ensure we have something
                (false, &Some(Ok(()))                         ) => unreachable!(),  // callback and is_connected() don't agree?
                (false, &Some(Err(CallbackError::Response(r)))) => Err(MqttError::Subscribe(CommandError::CallbackResponse(r))),
                (false, &Some(Err(CallbackError::NullPtr))    ) => Err(MqttError::Subscribe(CommandError::CallbackNullPtr)),
            }
        } else { Err(MqttError::Subscribe(CommandError::ReturnCode(error))) }
    }

    #[allow(unused_variables)]
    extern "C" fn action_succeeded(context: *mut ::libc::c_void, response: *mut ffiasync::MQTTAsync_successData) -> () {
        debug!("success callback");
        assert!(!context.is_null());
        let selfclient: &mut ImmovableClient = unsafe {mem::transmute(context)};
        selfclient.action_result = Some(Ok(()));
        selfclient.barrier.wait();
    }

    extern "C" fn action_failed(context: *mut ::libc::c_void, response: *mut ffiasync::MQTTAsync_failureData) -> () {
        debug!("failure callback");
        assert!(!context.is_null());
        let selfclient : &mut ImmovableClient = unsafe {mem::transmute(context)};
        if response.is_null() {
            selfclient.action_result = Some(Err(CallbackError::NullPtr));
        } else {
            let resp : &mut ffiasync::MQTTAsync_failureData = unsafe {mem::transmute(response)};
            selfclient.action_result = Some(Err(CallbackError::Response(resp.code)));
        }
        selfclient.barrier.wait();
    }

    extern "C" fn received(context: *mut ::libc::c_void, topic_name: *mut ::libc::c_char, topic_len: ::libc::c_int, amessage: *mut ffiasync::MQTTAsync_message) -> i32 {
        let c_topic = unsafe {CStr::from_ptr(topic_name).to_bytes()};
        let topic   = String::from_utf8(c_topic.to_vec()).unwrap();
        assert_eq!(topic.len(), topic_len as usize);

        assert!(!amessage.is_null());
        let transmessage: &mut ffiasync::MQTTAsync_message = unsafe {mem::transmute(amessage)};

        let payload = match transmessage.payloadlen {
            0  => None,
            _ => {
                let payload_slice: &[u8] = unsafe {
                        slice::from_raw_parts(transmessage.payload as *mut u8, transmessage.payloadlen as usize)
                };
                Some(payload_slice.to_vec())
            }
        };

        assert!(!context.is_null());
        let selfclient : &mut ImmovableClient = unsafe {mem::transmute(context)};

        let qos = Qos::from_int(transmessage.qos);

        let retained: bool = match transmessage.retained {
            0 => false,
            1 => true,
            _ => unreachable!(),
        };

        let duplicate: bool = match transmessage.dup {
            0 => false,
            1 => true,
            _ => unreachable!(),
        };

        let msg = Message {
            topic     : topic,
            payload   : payload,
            qos       : qos,
            retained  : retained,
            duplicate : duplicate,
        };

        // send message to channel or to iterator
        match selfclient.channel {
            Some(ref channel) => {
                channel.send(msg);
            }
            None => {
                let &(ref msglock, ref cvar) = &*selfclient.messages;
                let mut messages = msglock.lock().unwrap();
                messages.push(msg);
                cvar.notify_one();
            }
        }

        let mut msg = amessage;
        unsafe{ffiasync::MQTTAsync_freeMessage(&mut msg)};
        unsafe{ffiasync::MQTTAsync_free(mem::transmute(topic_name))};
        1
    }

}
impl Drop for ImmovableClient {
    fn drop(&mut self) {
        unsafe{ffiasync::MQTTAsync_destroy(&mut self.handle)};
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Revolution Solid & Contributors.
// author(s): sysnett
// rust-monster is licensed under a MIT License.

//! GA Test Utilities
//! Reusable classes for testing

use super::ga_core::*;
use super::ga_population::*;

#[cfg(test)]
extern crate env_logger;
pub const GA_TEST_FITNESS_VAL: f32 = 3.14159;

/// GA Test Setup
/// Utility function to setup useful test systems (like logging)
pub fn ga_test_setup(test_name: &str)
{
    ga_test_setup_internal(test_name);
}

#[cfg(not(test))]
fn ga_test_setup_internal(_: &str)
{
    //This only exists to avoid bringing env_logger in non_test builds
}

#[cfg(test)]
fn ga_test_setup_internal(test_name: &str)
{
    let _ = env_logger::init();
    debug!("{:?}", test_name);
}

/// GA Test Teardown
/// Utlity function to teardown used test systems
pub fn ga_test_teardown(){}

/// GATestSolution
/// Implements the GASolution Trait with a only no-ops
pub struct GATestSolution
{
    fitness: f32
}
impl GASolution for GATestSolution
{
    fn new(f:f32) -> GATestSolution
    {
        GATestSolution{ fitness: f}
    }

    fn clone(&self) -> Self { GATestSolution::new(self.fitness) }
    fn evaluate(&mut self) -> f32 { self.fitness }
#[allow(unused_variables)]
    fn crossover(&self, other : &Self) -> Self { GATestSolution::new(self.fitness) }
#[allow(unused_variables)]
    fn mutate(&mut self, pm : f32) {}
    fn fitness(&self) -> f32 { (1.0 / self.fitness) }
    fn score(&self) -> f32 { self.fitness }
}

#[allow(dead_code)]
pub struct GATestFactory
{
    starting_fitness: f32
}
impl GATestFactory
{
    pub fn new(starting_fitness: f32) -> GATestFactory
    {
        GATestFactory {starting_fitness: starting_fitness}
    }
}
impl GAFactory<GATestSolution> for GATestFactory
{
    fn initial_population(&mut self) -> GAPopulation<GATestSolution>
    {
        GAPopulation::new(vec![GATestSolution { fitness: self.starting_fitness }], GAPopulationSortOrder::HighIsBest)
    }
}
<commit_msg>Silence compiler error temporarily.<commit_after>// Copyright 2016 Revolution Solid & Contributors.
// author(s): sysnett
// rust-monster is licensed under a MIT License.

//! GA Test Utilities
//! Reusable classes for testing

use super::ga_core::*;
use super::ga_population::*;

#[cfg(test)]
extern crate env_logger;
pub const GA_TEST_FITNESS_VAL: f32 = 3.14159;

/// GA Test Setup
/// Utility function to setup useful test systems (like logging)
pub fn ga_test_setup(test_name: &str)
{
    ga_test_setup_internal(test_name);
}

#[cfg(not(test))]
fn ga_test_setup_internal(_: &str)
{
    //This only exists to avoid bringing env_logger in non_test builds
}

#[cfg(test)]
fn ga_test_setup_internal(test_name: &str)
{
    let _ = env_logger::init();
    debug!("{:?}", test_name);
}

/// GA Test Teardown
/// Utlity function to teardown used test systems
pub fn ga_test_teardown(){}

/// GATestSolution
/// Implements the GASolution Trait with a only no-ops
pub struct GATestSolution
{
    fitness: f32
}
impl GASolution for GATestSolution
{
    fn new(f:f32) -> GATestSolution
    {
        GATestSolution{ fitness: f}
    }

    //fn clone(&self) -> Self { GATestSolution::new(self.fitness) }
    fn evaluate(&mut self) -> f32 { self.fitness }
#[allow(unused_variables)]
    fn crossover(&self, other : &Self) -> Self { GATestSolution::new(self.fitness) }
#[allow(unused_variables)]
    fn mutate(&mut self, pm : f32) {}
    fn fitness(&self) -> f32 { (1.0 / self.fitness) }
    fn score(&self) -> f32 { self.fitness }
}

#[allow(dead_code)]
pub struct GATestFactory
{
    starting_fitness: f32
}
impl GATestFactory
{
    pub fn new(starting_fitness: f32) -> GATestFactory
    {
        GATestFactory {starting_fitness: starting_fitness}
    }
}
impl GAFactory<GATestSolution> for GATestFactory
{
    fn initial_population(&mut self) -> GAPopulation<GATestSolution>
    {
        GAPopulation::new(vec![GATestSolution { fitness: self.starting_fitness }], GAPopulationSortOrder::HighIsBest)
    }
}
<|endoftext|>


<commit_before>//! The geometry module defines the Geometry trait implemented by
//! the various geometry in the ray tracer and provides some standard
//! geometry for rendering

use linalg;

pub use self::differential_geometry::DifferentialGeometry;
pub use self::intersection::Intersection;
pub use self::instance::Instance;
pub use self::sphere::Sphere;
pub use self::plane::Plane;
pub use self::bbox::BBox;
pub use self::bvh::BVH;
pub use self::mesh::Mesh;

pub mod differential_geometry;
pub mod intersection;
pub mod instance;
pub mod sphere;
pub mod plane;
pub mod bbox;
pub mod bvh;
pub mod mesh;

/// Trait implemented by geometric primitives
pub trait Geometry {
    /// Test a ray for intersection with the geometry.
    /// The ray should have been previously transformed into the geometry's
    /// object space otherwise the test will be incorrect.
    /// Returns the differential geometry containing the hit information if the
    /// ray hit the object and set's the ray's `max_t` member accordingly
    fn intersect(&self, ray: &mut linalg::Ray) -> Option<DifferentialGeometry>;
}

/// Trait implemented by scene objects that can report an AABB describing their bounds
pub trait Boundable {
    /// Get an AABB reporting the object's bounds in space
    fn bounds(&self) -> BBox;
}

/// TODO: This is a workaround for lack of support for bounding on user defined traits
/// Eg. at the time of writing it's not possible to do something like:
/// Box<Geometry + Boundable + Send + Sync> so we use this combo trait
pub trait BoundableGeom: Geometry + Boundable {}
impl<T: ?Sized> BoundableGeom for T where T: Geometry + Boundable {}

<commit_msg>vtable issues are why ThingA + ThingB is not a valid trait object<commit_after>//! The geometry module defines the Geometry trait implemented by
//! the various geometry in the ray tracer and provides some standard
//! geometry for rendering

use linalg;

pub use self::differential_geometry::DifferentialGeometry;
pub use self::intersection::Intersection;
pub use self::instance::Instance;
pub use self::sphere::Sphere;
pub use self::plane::Plane;
pub use self::bbox::BBox;
pub use self::bvh::BVH;
pub use self::mesh::Mesh;

pub mod differential_geometry;
pub mod intersection;
pub mod instance;
pub mod sphere;
pub mod plane;
pub mod bbox;
pub mod bvh;
pub mod mesh;

/// Trait implemented by geometric primitives
pub trait Geometry {
    /// Test a ray for intersection with the geometry.
    /// The ray should have been previously transformed into the geometry's
    /// object space otherwise the test will be incorrect.
    /// Returns the differential geometry containing the hit information if the
    /// ray hit the object and set's the ray's `max_t` member accordingly
    fn intersect(&self, ray: &mut linalg::Ray) -> Option<DifferentialGeometry>;
}

/// Trait implemented by scene objects that can report an AABB describing their bounds
pub trait Boundable {
    /// Get an AABB reporting the object's bounds in space
    fn bounds(&self) -> BBox;
}

pub trait BoundableGeom: Geometry + Boundable {}
impl<T: ?Sized> BoundableGeom for T where T: Geometry + Boundable {}

<|endoftext|>