<commit_before>extern crate pwx;
extern crate docopt;
extern crate rustc_serialize;
extern crate uuid;

use pwx::{Pwx, PwxFieldIterator, Field, Value};
use std::io::{Write, stderr};
use std::process::exit;
use std::path::PathBuf;
use docopt::Docopt;
use uuid::Uuid;
use pwx::util::{fuzzy_eq, from_time_t, abspath, get_password_from_user};
use std::str::from_utf8;

// Get pkg version at compile time
const VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_file: String,
    arg_fieldname: String,
    arg_uuid: String,
    arg_filter: Vec<String>,
    flag_url: String,
    flag_group: String,
    flag_username: String,
    flag_title: String,
    flag_quiet: bool,
    cmd_count: bool,
    cmd_list: bool,
    cmd_get: bool,
    cmd_info: bool,
    flag_version: bool,
    flag_pass_interactive: bool,
    flag_no_pinentry: bool,
}

/// Get password
/// 1. If --pass-interactive read from console
/// 2. If PWX_PASSWORD is set use it
/// 3. Otherwise read from console
///
/// This function may panic on encoding issues
fn get_password(args: &Args, description: &str) -> Option<String> {
    let var = std::env::var("PWX_PASSWORD");
    if args.flag_pass_interactive || !var.is_ok() {
        get_password_from_user(description, args.flag_no_pinentry)
    } else {
        Some(var.unwrap())
    }
}

/// A filter to match multiple keywords
///
/// The default state is for the filter to be unmatched.
/// Push content with 'push()', if it matches the keywords
/// the filter will match.
struct KeywordFilter<'a> {
    m_filter: Vec<bool>,
    args: &'a Args,
}

impl<'a> KeywordFilter<'a> {
    fn new(args: &Args) -> KeywordFilter {
        let mut f = KeywordFilter {
            m_filter: Vec::with_capacity(args.arg_filter.len()),
            args: args,
        };
        f.m_filter.resize(args.arg_filter.len(), false);
        f
    }

    /// Attempt to match this filter against a field
    fn push(&mut self, field: &Field) {
        let utf8 = match *field {
            Field::Group(ref v) => from_utf8(v.as_ref()),
            Field::Title(ref v) => from_utf8(v.as_ref()),
            Field::Username(ref v) => from_utf8(v.as_ref()),
            Field::Notes(ref v) => from_utf8(v.as_ref()),
            Field::Password(_) => return,
            Field::Url(ref v) => from_utf8(v.as_ref()),
            _ => return,
        };

        if let Ok(s) = utf8 {
            for (idx, word) in self.args
                                   .arg_filter
                                   .iter()
                                   .enumerate() {
                self.m_filter[idx] = self.m_filter[idx] || fuzzy_eq(&word, s);
            }
        }
    }

    /// Returns true if all the keywords matched
    fn matched(&self) -> bool {
        self.m_filter.iter().all(|v| *v)
    }
}

fn real_main() -> i32 {

    let args: Args = Docopt::new(include_str!(concat!(env!("CARGO_MANIFEST_DIR"),
                                                      "/doc/pwx.docopt")))
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| e.exit());

    if args.flag_version {
        println!("pwx {}", VERSION);
        return 0;
    }

    // The password safe is one of
    // 1. Command line [<file>]
    // 2. PWX_DATABASE env var
    // 3. ~/.pwsafe/psafe.psafe3
    let env_db = std::env::var("PWX_DATABASE").unwrap_or(String::new());

    let mut path = if !args.arg_file.is_empty() {
        PathBuf::from(&args.arg_file)
    } else if !env_db.is_empty() {
        PathBuf::from(&env_db)
    } else {
        std::env::home_dir()
            .expect("Cannot find your HOME path")
            .join(".pwsafe")
            .join("pwsafe.psafe3")
    };

    path = match abspath(&path) {
        Ok(abs) => abs,
        Err(_) => path,
    };

    // FIXME: PathBuf::exists is still Unstable, but we need to verify
    // if the file exists before prompting for password
    match std::fs::File::open(&path) {
        Err(err) => {
            let _ = writeln!(stderr(), "{}: {}", path.to_string_lossy(), err);
            return -1;
        }
        _ => (),
    }

    path = match abspath(&path) {
        Ok(abs) => abs,
        Err(_) => path,
    };

    let description = format!("Opening {}", path.to_string_lossy());
    let mut p = match Pwx::open(&path,
                                get_password(&args, &description)
                                    .expect("Unable to get user password")
                                    .as_bytes()) {
        Err(f) => {
            let _ = writeln!(stderr(), "Error: {} {}", f, path.to_string_lossy());
            exit(-1);
        }
        Ok(p) => p,
    };

    if !p.is_authentic() {
        return -1;
    }

    if args.cmd_list || args.cmd_count {
        let mut count = 0;

        for record in p.iter().unwrap() {
            let mut uuid = String::new();
            let mut title = String::new();
            let mut username = String::new();

            // Field filters
            let mut f_username = args.flag_username.is_empty();
            let mut f_title = args.flag_title.is_empty();
            let mut f_url = args.flag_url.is_empty();
            let mut f_group = args.flag_group.is_empty();

            // Keyword filters
            let mut f_keywords = KeywordFilter::new(&args);

            for field in record {
                f_keywords.push(&field);
                match field {
                    Field::Uuid(_) => uuid = format!("{}", field),
                    Field::Title(_) => {
                        title = format!("{}", field);
                        f_title = f_title || fuzzy_eq(&args.flag_title, &title);
                    }
                    Field::Username(_) => {
                        username = format!("{}", field);
                        f_username = f_username || fuzzy_eq(&args.flag_username, &username);
                    }
                    Field::Url(_) => {
                        let url = format!("{}", field);
                        f_url = f_url || fuzzy_eq(&args.flag_url, &url);
                    }
                    Field::Group(_) => {
                        let group = format!("{}", field);
                        f_group = f_group || fuzzy_eq(&args.flag_group, &group);
                    }
                    _ => (),
                }
            }

            if !f_username || !f_title || !f_url || !f_group {
                // Skip, record filter did not match
                continue;
            }

            if !f_keywords.matched() {
                // Skip, generic keyword filter did not match
                continue;
            }

            if args.cmd_count {
                count += 1;
            } else {
                println!("{} {}[{}]", uuid, title, username);
            }
        }

        if args.cmd_count {
            println!("{}", count);
        }
    } else if args.cmd_info {

        let fields = PwxFieldIterator::new(&mut p).unwrap();
        for (typ, val) in fields {
            match typ {
                0x01 => {
                    print!("{} ",
                           Uuid::from_bytes(val.as_ref())
                               .unwrap_or(Uuid::nil())
                               .hyphenated()
                               .to_string())
                }
                0x04 => {
                    print!("{} ",
                           from_time_t(val.as_ref()).expect("Invalid time_t field contents"))
                }
                0x07 => print!("{} ", String::from_utf8_lossy(val.as_ref())),
                0x08 => println!("@{} ", String::from_utf8_lossy(val.as_ref())),
                0x09 => println!("{} ", String::from_utf8_lossy(val.as_ref())),
                0x0a => println!("\"{}\" ", String::from_utf8_lossy(val.as_ref())),
                0xff => break,
                _ => (),
            }
        }
    } else if args.cmd_get {
        let get_uuid = Field::Uuid(Value::from(Uuid::parse_str(&args.arg_uuid)
                                                   .expect("Invalid UUID")
                                                   .as_bytes()
                                                   .to_vec()));

        for record in p.iter().unwrap() {
            // Find record by UUID
            let mut found = false;
            for field in &record {
                if *field == get_uuid {
                    found = true;
                    break;
                }
            }

            if !found {
                continue;
            }

            // Get field value
            for field in &record {
                if let Some(name) = field.name() {
                    if name == args.arg_fieldname {
                        println!("{}", field);
                        return 0;
                    }
                }
            }
            let _ = writeln!(stderr(), "Unknown field: {}", args.arg_fieldname);
        }

        let _ = writeln!(stderr(), "Unknown record: {}", args.arg_uuid);
        return -1;
    }

    return 0;
}

// We want to make sure we exit only after all the destructors
// are called, wait for real_main() to be done before actually
// calling exit.
fn main() {
    let exit_code = real_main();
    exit(exit_code);
}
<commit_msg>Don't use exit() in inner pwx function<commit_after>extern crate pwx;
extern crate docopt;
extern crate rustc_serialize;
extern crate uuid;

use pwx::{Pwx, PwxFieldIterator, Field, Value};
use std::io::{Write, stderr};
use std::process::exit;
use std::path::PathBuf;
use docopt::Docopt;
use uuid::Uuid;
use pwx::util::{fuzzy_eq, from_time_t, abspath, get_password_from_user};
use std::str::from_utf8;

// Get pkg version at compile time
const VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_file: String,
    arg_fieldname: String,
    arg_uuid: String,
    arg_filter: Vec<String>,
    flag_url: String,
    flag_group: String,
    flag_username: String,
    flag_title: String,
    flag_quiet: bool,
    cmd_count: bool,
    cmd_list: bool,
    cmd_get: bool,
    cmd_info: bool,
    flag_version: bool,
    flag_pass_interactive: bool,
    flag_no_pinentry: bool,
}

/// Get password
/// 1. If --pass-interactive read from console
/// 2. If PWX_PASSWORD is set use it
/// 3. Otherwise read from console
///
/// This function may panic on encoding issues
fn get_password(args: &Args, description: &str) -> Option<String> {
    let var = std::env::var("PWX_PASSWORD");
    if args.flag_pass_interactive || !var.is_ok() {
        get_password_from_user(description, args.flag_no_pinentry)
    } else {
        Some(var.unwrap())
    }
}

/// A filter to match multiple keywords
///
/// The default state is for the filter to be unmatched.
/// Push content with 'push()', if it matches the keywords
/// the filter will match.
struct KeywordFilter<'a> {
    m_filter: Vec<bool>,
    args: &'a Args,
}

impl<'a> KeywordFilter<'a> {
    fn new(args: &Args) -> KeywordFilter {
        let mut f = KeywordFilter {
            m_filter: Vec::with_capacity(args.arg_filter.len()),
            args: args,
        };
        f.m_filter.resize(args.arg_filter.len(), false);
        f
    }

    /// Attempt to match this filter against a field
    fn push(&mut self, field: &Field) {
        let utf8 = match *field {
            Field::Group(ref v) => from_utf8(v.as_ref()),
            Field::Title(ref v) => from_utf8(v.as_ref()),
            Field::Username(ref v) => from_utf8(v.as_ref()),
            Field::Notes(ref v) => from_utf8(v.as_ref()),
            Field::Password(_) => return,
            Field::Url(ref v) => from_utf8(v.as_ref()),
            _ => return,
        };

        if let Ok(s) = utf8 {
            for (idx, word) in self.args
                                   .arg_filter
                                   .iter()
                                   .enumerate() {
                self.m_filter[idx] = self.m_filter[idx] || fuzzy_eq(&word, s);
            }
        }
    }

    /// Returns true if all the keywords matched
    fn matched(&self) -> bool {
        self.m_filter.iter().all(|v| *v)
    }
}

fn real_main() -> i32 {

    let args: Args = Docopt::new(include_str!(concat!(env!("CARGO_MANIFEST_DIR"),
                                                      "/doc/pwx.docopt")))
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| e.exit());

    if args.flag_version {
        println!("pwx {}", VERSION);
        return 0;
    }

    // The password safe is one of
    // 1. Command line [<file>]
    // 2. PWX_DATABASE env var
    // 3. ~/.pwsafe/psafe.psafe3
    let env_db = std::env::var("PWX_DATABASE").unwrap_or(String::new());

    let mut path = if !args.arg_file.is_empty() {
        PathBuf::from(&args.arg_file)
    } else if !env_db.is_empty() {
        PathBuf::from(&env_db)
    } else {
        std::env::home_dir()
            .expect("Cannot find your HOME path")
            .join(".pwsafe")
            .join("pwsafe.psafe3")
    };

    path = match abspath(&path) {
        Ok(abs) => abs,
        Err(_) => path,
    };

    // FIXME: PathBuf::exists is still Unstable, but we need to verify
    // if the file exists before prompting for password
    match std::fs::File::open(&path) {
        Err(err) => {
            let _ = writeln!(stderr(), "{}: {}", path.to_string_lossy(), err);
            return -1;
        }
        _ => (),
    }

    path = match abspath(&path) {
        Ok(abs) => abs,
        Err(_) => path,
    };

    let description = format!("Opening {}", path.to_string_lossy());
    let mut p = match Pwx::open(&path,
                                get_password(&args, &description)
                                    .expect("Unable to get user password")
                                    .as_bytes()) {
        Err(f) => {
            let _ = writeln!(stderr(), "Error: {} {}", f, path.to_string_lossy());
            return -1;
        }
        Ok(p) => p,
    };

    if !p.is_authentic() {
        return -1;
    }

    if args.cmd_list || args.cmd_count {
        let mut count = 0;

        for record in p.iter().unwrap() {
            let mut uuid = String::new();
            let mut title = String::new();
            let mut username = String::new();

            // Field filters
            let mut f_username = args.flag_username.is_empty();
            let mut f_title = args.flag_title.is_empty();
            let mut f_url = args.flag_url.is_empty();
            let mut f_group = args.flag_group.is_empty();

            // Keyword filters
            let mut f_keywords = KeywordFilter::new(&args);

            for field in record {
                f_keywords.push(&field);
                match field {
                    Field::Uuid(_) => uuid = format!("{}", field),
                    Field::Title(_) => {
                        title = format!("{}", field);
                        f_title = f_title || fuzzy_eq(&args.flag_title, &title);
                    }
                    Field::Username(_) => {
                        username = format!("{}", field);
                        f_username = f_username || fuzzy_eq(&args.flag_username, &username);
                    }
                    Field::Url(_) => {
                        let url = format!("{}", field);
                        f_url = f_url || fuzzy_eq(&args.flag_url, &url);
                    }
                    Field::Group(_) => {
                        let group = format!("{}", field);
                        f_group = f_group || fuzzy_eq(&args.flag_group, &group);
                    }
                    _ => (),
                }
            }

            if !f_username || !f_title || !f_url || !f_group {
                // Skip, record filter did not match
                continue;
            }

            if !f_keywords.matched() {
                // Skip, generic keyword filter did not match
                continue;
            }

            if args.cmd_count {
                count += 1;
            } else {
                println!("{} {}[{}]", uuid, title, username);
            }
        }

        if args.cmd_count {
            println!("{}", count);
        }
    } else if args.cmd_info {

        let fields = PwxFieldIterator::new(&mut p).unwrap();
        for (typ, val) in fields {
            match typ {
                0x01 => {
                    print!("{} ",
                           Uuid::from_bytes(val.as_ref())
                               .unwrap_or(Uuid::nil())
                               .hyphenated()
                               .to_string())
                }
                0x04 => {
                    print!("{} ",
                           from_time_t(val.as_ref()).expect("Invalid time_t field contents"))
                }
                0x07 => print!("{} ", String::from_utf8_lossy(val.as_ref())),
                0x08 => println!("@{} ", String::from_utf8_lossy(val.as_ref())),
                0x09 => println!("{} ", String::from_utf8_lossy(val.as_ref())),
                0x0a => println!("\"{}\" ", String::from_utf8_lossy(val.as_ref())),
                0xff => break,
                _ => (),
            }
        }
    } else if args.cmd_get {
        let get_uuid = Field::Uuid(Value::from(Uuid::parse_str(&args.arg_uuid)
                                                   .expect("Invalid UUID")
                                                   .as_bytes()
                                                   .to_vec()));

        for record in p.iter().unwrap() {
            // Find record by UUID
            let mut found = false;
            for field in &record {
                if *field == get_uuid {
                    found = true;
                    break;
                }
            }

            if !found {
                continue;
            }

            // Get field value
            for field in &record {
                if let Some(name) = field.name() {
                    if name == args.arg_fieldname {
                        println!("{}", field);
                        return 0;
                    }
                }
            }
            let _ = writeln!(stderr(), "Unknown field: {}", args.arg_fieldname);
        }

        let _ = writeln!(stderr(), "Unknown record: {}", args.arg_uuid);
        return -1;
    }

    return 0;
}

// We want to make sure we exit only after all the destructors
// are called, wait for real_main() to be done before actually
// calling exit.
fn main() {
    let exit_code = real_main();
    exit(exit_code);
}
<|endoftext|>


<commit_before>//! This module defines [`BVH`] and [`BVHNode`] and functions for building and traversing it.
//!
//! [`BVH`]: struct.BVH.html
//! [`BVHNode`]: struct.BVHNode.html
//!

use EPSILON;
use aabb::{AABB, Bounded};
use bounding_hierarchy::{BoundingHierarchy, BHShape};
use ray::Ray;
use std::f32;
use std::iter::repeat;

/// The BVHNode enum that describes a node in a [`BVH`].
/// It's either a leaf node and references a shape (by holding its index)
/// or a regular node that has two children nodes.
/// The non-leaf node stores the [`AABB`]s of its children.
///
/// [`AABB`]: ../aabb/struct.AABB.html
/// [`BVH`]: struct.BVH.html
///
#[derive(Debug, Copy, Clone)]
pub enum BVHNode {
    /// Leaf node.
    Leaf {
        /// The node's parent.
        parent: usize,

        /// The node's depth.
        depth: u32,

        /// The shape contained in this leaf.
        shape: usize,
    },
    /// Inner node.
    Node {
        /// The node's parent.
        parent: usize,

        /// The node's depth.
        depth: u32,

        /// The convex hull of the shapes' `AABB`s in child_l.
        child_l_aabb: AABB,

        /// Index of the left subtree's root node.
        child_l: usize,

        /// The convex hull of the shapes' `AABB`s in child_r.
        child_r_aabb: AABB,

        /// Index of the right subtree's root node.
        child_r: usize,
    },
}

impl BVHNode {
    fn create_dummy() -> BVHNode {
        BVHNode::Leaf {
            parent: 0,
            depth: 0,
            shape: 0,
        }
    }

    /// Builds a [`BVHNode`] recursively using SAH partitioning.
    /// Returns the index of the node in the nodes vector.
    ///
    /// [`BVHNode`]: enum.BVHNode.html
    ///
    pub fn build<T: BHShape>(shapes: &mut [T],
                             indices: Vec<usize>,
                             nodes: &mut Vec<BVHNode>,
                             parent: usize,
                             depth: u32)
                             -> usize {
        // Helper function to accumulate the AABB joint and the centroids AABB
        fn grow_convex_hull(convex_hull: (AABB, AABB), shape_aabb: &AABB) -> (AABB, AABB) {
            let center = &shape_aabb.center();
            let convex_hull_aabbs = &convex_hull.0;
            let convex_hull_centroids = &convex_hull.1;
            (convex_hull_aabbs.join(shape_aabb), convex_hull_centroids.grow(center))
        }

        let mut convex_hull = Default::default();
        for index in &indices {
            convex_hull = grow_convex_hull(convex_hull, &shapes[*index].aabb());
        }
        let (aabb_bounds, centroid_bounds) = convex_hull;

        // If there is only one element left, don't split anymore
        if indices.len() == 1 {
            let shape_index = indices[0];
            nodes.push(BVHNode::Leaf {
                parent: parent,
                depth: depth,
                shape: shape_index,
            });
            let node_index = nodes.len() - 1;
            // Let the shape know the index of the node that represents it
            shapes[shape_index].set_bh_node_index(node_index);
            return node_index;
        }

        // Find the axis along which the shapes are spread the most
        let split_axis = centroid_bounds.largest_axis();
        let split_axis_size = centroid_bounds.max[split_axis] - centroid_bounds.min[split_axis];

        /// Defines a Bucket utility object.
        #[derive(Copy, Clone)]
        struct Bucket {
            size: usize,
            aabb: AABB,
        }

        impl Bucket {
            /// Returns an empty bucket.
            fn empty() -> Bucket {
                Bucket {
                    size: 0,
                    aabb: AABB::empty(),
                }
            }

            /// Extends this `Bucket` by the given `AABB`.
            fn add_aabb(&mut self, aabb: &AABB) {
                self.size += 1;
                self.aabb = self.aabb.join(aabb);
            }
        }

        /// Joins two `Bucket`s.
        fn join_bucket(a: Bucket, b: &Bucket) -> Bucket {
            Bucket {
                size: a.size + b.size,
                aabb: a.aabb.join(&b.aabb),
            }
        }

        // Create six buckets, and six index assignment vectors
        const NUM_BUCKETS: usize = 6;
        let mut buckets = [Bucket::empty(); NUM_BUCKETS];
        let mut bucket_assignments: [Vec<usize>; NUM_BUCKETS] = Default::default();

        if split_axis_size < EPSILON {
            // Spread the remaining shapes evenly across buckets,
            // instead of using a heuristic
            for (counter, idx) in (&indices).iter().enumerate() {
                let shape = &shapes[*idx];
                let shape_aabb = shape.aabb();

                let bucket_num = counter % NUM_BUCKETS;

                buckets[bucket_num].add_aabb(&shape_aabb);
                bucket_assignments[bucket_num].push(*idx);
            }
        } else {
            // Assign each shape to a bucket
            for idx in &indices {
                let shape = &shapes[*idx];
                let shape_aabb = shape.aabb();
                let shape_center = shape_aabb.center();

                // Get the relative position of the shape centroid [0.0..1.0]
                let bucket_num_relative =
                    (shape_center[split_axis] - centroid_bounds.min[split_axis]) / split_axis_size;

                // Convert that to the actual `Bucket` number
                let bucket_num = (bucket_num_relative * (NUM_BUCKETS as f32 - 0.01)) as usize;

                // Extend the selected `Bucket` and add the index to the actual bucket
                buckets[bucket_num].add_aabb(&shape_aabb);
                bucket_assignments[bucket_num].push(*idx);
            }
        }

        // Compute the costs for each configuration and
        // select the configuration with the minimal costs
        let mut min_bucket = 0;
        let mut min_cost = f32::INFINITY;
        let mut child_l_aabb = AABB::empty();
        let mut child_r_aabb = AABB::empty();
        for i in 0..(NUM_BUCKETS - 1) {
            let child_l = buckets.iter().take(i + 1).fold(Bucket::empty(), join_bucket);
            let child_r = buckets.iter().skip(i + 1).fold(Bucket::empty(), join_bucket);

            let cost = (child_l.size as f32 * child_l.aabb.surface_area() +
                        child_r.size as f32 * child_r.aabb.surface_area()) /
                       aabb_bounds.surface_area();

            if cost < min_cost {
                min_bucket = i;
                min_cost = cost;
                child_l_aabb = child_l.aabb;
                child_r_aabb = child_r.aabb;
            }
        }

        // Join together all index buckets, and proceed recursively
        let mut child_l_indices = Vec::new();
        for mut indices in bucket_assignments.iter_mut().take(min_bucket + 1) {
            child_l_indices.append(&mut indices);
        }
        let mut child_r_indices = Vec::new();
        for mut indices in bucket_assignments.iter_mut().skip(min_bucket + 1) {
            child_r_indices.append(&mut indices);
        }

        let node_index = nodes.len();

        nodes.push(BVHNode::create_dummy());

        let child_l = BVHNode::build(shapes, child_l_indices, nodes, node_index, depth + 1);
        let child_r = BVHNode::build(shapes, child_r_indices, nodes, node_index, depth + 1);

        // Construct the actual data structure
        nodes[node_index] = BVHNode::Node {
            parent: parent,
            depth: depth,
            child_l_aabb: child_l_aabb,
            child_l: child_l,
            child_r_aabb: child_r_aabb,
            child_r: child_r,
        };

        node_index
    }

    /// Traverses the [`BVH`] recursively and returns all shapes whose [`AABB`] is
    /// intersected by the given [`Ray`].
    ///
    /// [`AABB`]: ../aabb/struct.AABB.html
    /// [`BVH`]: struct.BVH.html
    /// [`Ray`]: ../ray/struct.Ray.html
    ///
    pub fn traverse_recursive(nodes: &Vec<BVHNode>, node_index: usize, ray: &Ray, indices: &mut Vec<usize>) {
        let node = &nodes[node_index];
        match *node {
            BVHNode::Node { ref child_l_aabb, child_l, ref child_r_aabb, child_r, .. } => {
                if ray.intersects_aabb(child_l_aabb) {
                    BVHNode::traverse_recursive(nodes, child_l, ray, indices);
                }
                if ray.intersects_aabb(child_r_aabb) {
                    BVHNode::traverse_recursive(nodes, child_r, ray, indices);
                }
            }
            BVHNode::Leaf { shape, .. } => {
                indices.push(shape);
            }
        }
    }
}

/// The [`BVH`] data structure. Contains the list of [`BVHNode`]s.
///
/// [`BVH`]: struct.BVH.html
///
pub struct BVH {
    /// The list of nodes of the [`BVH`].
    ///
    /// [`BVH`]: struct.BVH.html
    ///
    pub nodes: Vec<BVHNode>,
}

impl BVH {
    /// Creates a new [`BVH`] from the `shapes` slice.
    ///
    /// [`BVH`]: struct.BVH.html
    ///
    pub fn build<Shape: BHShape>(shapes: &mut [Shape]) -> BVH {
        let indices = (0..shapes.len()).collect::<Vec<usize>>();
        let mut nodes = Vec::new();
        BVHNode::build(shapes, indices, &mut nodes, 0, 0);
        BVH { nodes: nodes }
    }

    /// Traverses the [`BVH`].
    /// Returns a subset of `shapes`, in which the [`AABB`]s of the elements were hit by `ray`.
    ///
    /// [`BVH`]: struct.BVH.html
    /// [`AABB`]: ../aabb/struct.AABB.html
    ///
    pub fn traverse<'a, Shape: Bounded>(&'a self, ray: &Ray, shapes: &'a [Shape]) -> Vec<&Shape> {
        let mut indices = Vec::new();
        BVHNode::traverse_recursive(&self.nodes, 0, ray, &mut indices);
        let mut hit_shapes = Vec::new();
        for index in &indices {
            let shape = &shapes[*index];
            hit_shapes.push(shape);
        }
        hit_shapes
    }

    /// Prints the [`BVH`] in a tree-like visualization.
    ///
    /// [`BVH`]: struct.BVH.html
    ///
    pub fn pretty_print(&self) {
        let nodes = &self.nodes;
        fn print_node(nodes: &Vec<BVHNode>, node_index: usize) {
            let node = &nodes[node_index];
            match *node {
                BVHNode::Node { child_l, child_r, depth, child_l_aabb, child_r_aabb, .. } => {
                    let padding: String = repeat(" ").take(depth as usize).collect();
                    println!("{}child_l {:?}", padding, child_l_aabb);
                    print_node(nodes, child_l);
                    println!("{}child_r {:?}", padding, child_r_aabb);
                    print_node(nodes, child_r);
                }
                BVHNode::Leaf { shape, depth, .. } => {
                    let padding: String = repeat(" ").take(depth as usize).collect();
                    println!("{}shape\t{:?}", padding, shape);
                }
            }
        }
        print_node(nodes, 0);
    }
}

impl BoundingHierarchy for BVH {
    fn build<Shape: BHShape>(shapes: &mut [Shape]) -> BVH {
        BVH::build(shapes)
    }

    fn traverse<'a, Shape: Bounded>(&'a self, ray: &Ray, shapes: &'a [Shape]) -> Vec<&Shape> {
        self.traverse(ray, shapes)
    }

    fn pretty_print(&self) {
        self.pretty_print();
    }
}

#[cfg(test)]
pub mod tests {
    use bvh::BVH;
    use testbase::{build_some_bh, traverse_some_bh, build_1200_triangles_bh,
                   build_12k_triangles_bh, build_120k_triangles_bh, intersect_1200_triangles_bh,
                   intersect_12k_triangles_bh, intersect_120k_triangles_bh};

    #[test]
    /// Tests whether the building procedure succeeds in not failing.
    fn test_build_bvh() {
        build_some_bh::<BVH>();
    }

    #[test]
    /// Runs some primitive tests for intersections of a ray with a fixed scene given as a BVH.
    fn test_traverse_bvh() {
        traverse_some_bh::<BVH>();
    }

    #[bench]
    /// Benchmark the construction of a `BVH` with 1,200 triangles.
    fn bench_build_1200_triangles_bvh(mut b: &mut ::test::Bencher) {
        build_1200_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark the construction of a `BVH` with 12,000 triangles.
    fn bench_build_12k_triangles_bvh(mut b: &mut ::test::Bencher) {
        build_12k_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark the construction of a `BVH` with 120,000 triangles.
    fn bench_build_120k_triangles_bvh(mut b: &mut ::test::Bencher) {
        build_120k_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark intersecting 1,200 triangles using the recursive `BVH`.
    fn bench_intersect_1200_triangles_bvh(mut b: &mut ::test::Bencher) {
        intersect_1200_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark intersecting 12,000 triangles using the recursive `BVH`.
    fn bench_intersect_12k_triangles_bvh(mut b: &mut ::test::Bencher) {
        intersect_12k_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark intersecting 120,000 triangles using the recursive `BVH`.
    fn bench_intersect_120k_triangles_bvh(mut b: &mut ::test::Bencher) {
        intersect_120k_triangles_bh::<BVH>(&mut b);
    }
}
<commit_msg>Improve doc comment<commit_after>//! This module defines [`BVH`] and [`BVHNode`] and functions for building and traversing it.
//!
//! [`BVH`]: struct.BVH.html
//! [`BVHNode`]: struct.BVHNode.html
//!

use EPSILON;
use aabb::{AABB, Bounded};
use bounding_hierarchy::{BoundingHierarchy, BHShape};
use ray::Ray;
use std::f32;
use std::iter::repeat;

/// The [`BVHNode`] enum that describes a node in a [`BVH`].
/// It's either a leaf node and references a shape (by holding its index)
/// or a regular node that has two child nodes.
/// The non-leaf node stores the [`AABB`]s of its children.
///
/// [`AABB`]: ../aabb/struct.AABB.html
/// [`BVH`]: struct.BVH.html
/// [`BVH`]: struct.BVHNode.html
///
#[derive(Debug, Copy, Clone)]
pub enum BVHNode {
    /// Leaf node.
    Leaf {
        /// The node's parent.
        parent: usize,

        /// The node's depth.
        depth: u32,

        /// The shape contained in this leaf.
        shape: usize,
    },
    /// Inner node.
    Node {
        /// The node's parent.
        parent: usize,

        /// The node's depth.
        depth: u32,

        /// The convex hull of the shapes' `AABB`s in child_l.
        child_l_aabb: AABB,

        /// Index of the left subtree's root node.
        child_l: usize,

        /// The convex hull of the shapes' `AABB`s in child_r.
        child_r_aabb: AABB,

        /// Index of the right subtree's root node.
        child_r: usize,
    },
}

impl BVHNode {
    fn create_dummy() -> BVHNode {
        BVHNode::Leaf {
            parent: 0,
            depth: 0,
            shape: 0,
        }
    }

    /// Builds a [`BVHNode`] recursively using SAH partitioning.
    /// Returns the index of the node in the nodes vector.
    ///
    /// [`BVHNode`]: enum.BVHNode.html
    ///
    pub fn build<T: BHShape>(shapes: &mut [T],
                             indices: Vec<usize>,
                             nodes: &mut Vec<BVHNode>,
                             parent: usize,
                             depth: u32)
                             -> usize {
        // Helper function to accumulate the AABB joint and the centroids AABB
        fn grow_convex_hull(convex_hull: (AABB, AABB), shape_aabb: &AABB) -> (AABB, AABB) {
            let center = &shape_aabb.center();
            let convex_hull_aabbs = &convex_hull.0;
            let convex_hull_centroids = &convex_hull.1;
            (convex_hull_aabbs.join(shape_aabb), convex_hull_centroids.grow(center))
        }

        let mut convex_hull = Default::default();
        for index in &indices {
            convex_hull = grow_convex_hull(convex_hull, &shapes[*index].aabb());
        }
        let (aabb_bounds, centroid_bounds) = convex_hull;

        // If there is only one element left, don't split anymore
        if indices.len() == 1 {
            let shape_index = indices[0];
            nodes.push(BVHNode::Leaf {
                parent: parent,
                depth: depth,
                shape: shape_index,
            });
            let node_index = nodes.len() - 1;
            // Let the shape know the index of the node that represents it
            shapes[shape_index].set_bh_node_index(node_index);
            return node_index;
        }

        // Find the axis along which the shapes are spread the most
        let split_axis = centroid_bounds.largest_axis();
        let split_axis_size = centroid_bounds.max[split_axis] - centroid_bounds.min[split_axis];

        /// Defines a Bucket utility object.
        #[derive(Copy, Clone)]
        struct Bucket {
            size: usize,
            aabb: AABB,
        }

        impl Bucket {
            /// Returns an empty bucket.
            fn empty() -> Bucket {
                Bucket {
                    size: 0,
                    aabb: AABB::empty(),
                }
            }

            /// Extends this `Bucket` by the given `AABB`.
            fn add_aabb(&mut self, aabb: &AABB) {
                self.size += 1;
                self.aabb = self.aabb.join(aabb);
            }
        }

        /// Joins two `Bucket`s.
        fn join_bucket(a: Bucket, b: &Bucket) -> Bucket {
            Bucket {
                size: a.size + b.size,
                aabb: a.aabb.join(&b.aabb),
            }
        }

        // Create six buckets, and six index assignment vectors
        const NUM_BUCKETS: usize = 6;
        let mut buckets = [Bucket::empty(); NUM_BUCKETS];
        let mut bucket_assignments: [Vec<usize>; NUM_BUCKETS] = Default::default();

        if split_axis_size < EPSILON {
            // Spread the remaining shapes evenly across buckets,
            // instead of using a heuristic
            for (counter, idx) in (&indices).iter().enumerate() {
                let shape = &shapes[*idx];
                let shape_aabb = shape.aabb();

                let bucket_num = counter % NUM_BUCKETS;

                buckets[bucket_num].add_aabb(&shape_aabb);
                bucket_assignments[bucket_num].push(*idx);
            }
        } else {
            // Assign each shape to a bucket
            for idx in &indices {
                let shape = &shapes[*idx];
                let shape_aabb = shape.aabb();
                let shape_center = shape_aabb.center();

                // Get the relative position of the shape centroid [0.0..1.0]
                let bucket_num_relative =
                    (shape_center[split_axis] - centroid_bounds.min[split_axis]) / split_axis_size;

                // Convert that to the actual `Bucket` number
                let bucket_num = (bucket_num_relative * (NUM_BUCKETS as f32 - 0.01)) as usize;

                // Extend the selected `Bucket` and add the index to the actual bucket
                buckets[bucket_num].add_aabb(&shape_aabb);
                bucket_assignments[bucket_num].push(*idx);
            }
        }

        // Compute the costs for each configuration and
        // select the configuration with the minimal costs
        let mut min_bucket = 0;
        let mut min_cost = f32::INFINITY;
        let mut child_l_aabb = AABB::empty();
        let mut child_r_aabb = AABB::empty();
        for i in 0..(NUM_BUCKETS - 1) {
            let child_l = buckets.iter().take(i + 1).fold(Bucket::empty(), join_bucket);
            let child_r = buckets.iter().skip(i + 1).fold(Bucket::empty(), join_bucket);

            let cost = (child_l.size as f32 * child_l.aabb.surface_area() +
                        child_r.size as f32 * child_r.aabb.surface_area()) /
                       aabb_bounds.surface_area();

            if cost < min_cost {
                min_bucket = i;
                min_cost = cost;
                child_l_aabb = child_l.aabb;
                child_r_aabb = child_r.aabb;
            }
        }

        // Join together all index buckets, and proceed recursively
        let mut child_l_indices = Vec::new();
        for mut indices in bucket_assignments.iter_mut().take(min_bucket + 1) {
            child_l_indices.append(&mut indices);
        }
        let mut child_r_indices = Vec::new();
        for mut indices in bucket_assignments.iter_mut().skip(min_bucket + 1) {
            child_r_indices.append(&mut indices);
        }

        let node_index = nodes.len();

        nodes.push(BVHNode::create_dummy());

        let child_l = BVHNode::build(shapes, child_l_indices, nodes, node_index, depth + 1);
        let child_r = BVHNode::build(shapes, child_r_indices, nodes, node_index, depth + 1);

        // Construct the actual data structure
        nodes[node_index] = BVHNode::Node {
            parent: parent,
            depth: depth,
            child_l_aabb: child_l_aabb,
            child_l: child_l,
            child_r_aabb: child_r_aabb,
            child_r: child_r,
        };

        node_index
    }

    /// Traverses the [`BVH`] recursively and returns all shapes whose [`AABB`] is
    /// intersected by the given [`Ray`].
    ///
    /// [`AABB`]: ../aabb/struct.AABB.html
    /// [`BVH`]: struct.BVH.html
    /// [`Ray`]: ../ray/struct.Ray.html
    ///
    pub fn traverse_recursive(nodes: &Vec<BVHNode>, node_index: usize, ray: &Ray, indices: &mut Vec<usize>) {
        let node = &nodes[node_index];
        match *node {
            BVHNode::Node { ref child_l_aabb, child_l, ref child_r_aabb, child_r, .. } => {
                if ray.intersects_aabb(child_l_aabb) {
                    BVHNode::traverse_recursive(nodes, child_l, ray, indices);
                }
                if ray.intersects_aabb(child_r_aabb) {
                    BVHNode::traverse_recursive(nodes, child_r, ray, indices);
                }
            }
            BVHNode::Leaf { shape, .. } => {
                indices.push(shape);
            }
        }
    }
}

/// The [`BVH`] data structure. Contains the list of [`BVHNode`]s.
///
/// [`BVH`]: struct.BVH.html
///
pub struct BVH {
    /// The list of nodes of the [`BVH`].
    ///
    /// [`BVH`]: struct.BVH.html
    ///
    pub nodes: Vec<BVHNode>,
}

impl BVH {
    /// Creates a new [`BVH`] from the `shapes` slice.
    ///
    /// [`BVH`]: struct.BVH.html
    ///
    pub fn build<Shape: BHShape>(shapes: &mut [Shape]) -> BVH {
        let indices = (0..shapes.len()).collect::<Vec<usize>>();
        let mut nodes = Vec::new();
        BVHNode::build(shapes, indices, &mut nodes, 0, 0);
        BVH { nodes: nodes }
    }

    /// Traverses the [`BVH`].
    /// Returns a subset of `shapes`, in which the [`AABB`]s of the elements were hit by `ray`.
    ///
    /// [`BVH`]: struct.BVH.html
    /// [`AABB`]: ../aabb/struct.AABB.html
    ///
    pub fn traverse<'a, Shape: Bounded>(&'a self, ray: &Ray, shapes: &'a [Shape]) -> Vec<&Shape> {
        let mut indices = Vec::new();
        BVHNode::traverse_recursive(&self.nodes, 0, ray, &mut indices);
        let mut hit_shapes = Vec::new();
        for index in &indices {
            let shape = &shapes[*index];
            hit_shapes.push(shape);
        }
        hit_shapes
    }

    /// Prints the [`BVH`] in a tree-like visualization.
    ///
    /// [`BVH`]: struct.BVH.html
    ///
    pub fn pretty_print(&self) {
        let nodes = &self.nodes;
        fn print_node(nodes: &Vec<BVHNode>, node_index: usize) {
            let node = &nodes[node_index];
            match *node {
                BVHNode::Node { child_l, child_r, depth, child_l_aabb, child_r_aabb, .. } => {
                    let padding: String = repeat(" ").take(depth as usize).collect();
                    println!("{}child_l {:?}", padding, child_l_aabb);
                    print_node(nodes, child_l);
                    println!("{}child_r {:?}", padding, child_r_aabb);
                    print_node(nodes, child_r);
                }
                BVHNode::Leaf { shape, depth, .. } => {
                    let padding: String = repeat(" ").take(depth as usize).collect();
                    println!("{}shape\t{:?}", padding, shape);
                }
            }
        }
        print_node(nodes, 0);
    }
}

impl BoundingHierarchy for BVH {
    fn build<Shape: BHShape>(shapes: &mut [Shape]) -> BVH {
        BVH::build(shapes)
    }

    fn traverse<'a, Shape: Bounded>(&'a self, ray: &Ray, shapes: &'a [Shape]) -> Vec<&Shape> {
        self.traverse(ray, shapes)
    }

    fn pretty_print(&self) {
        self.pretty_print();
    }
}

#[cfg(test)]
pub mod tests {
    use bvh::BVH;
    use testbase::{build_some_bh, traverse_some_bh, build_1200_triangles_bh,
                   build_12k_triangles_bh, build_120k_triangles_bh, intersect_1200_triangles_bh,
                   intersect_12k_triangles_bh, intersect_120k_triangles_bh};

    #[test]
    /// Tests whether the building procedure succeeds in not failing.
    fn test_build_bvh() {
        build_some_bh::<BVH>();
    }

    #[test]
    /// Runs some primitive tests for intersections of a ray with a fixed scene given as a BVH.
    fn test_traverse_bvh() {
        traverse_some_bh::<BVH>();
    }

    #[bench]
    /// Benchmark the construction of a `BVH` with 1,200 triangles.
    fn bench_build_1200_triangles_bvh(mut b: &mut ::test::Bencher) {
        build_1200_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark the construction of a `BVH` with 12,000 triangles.
    fn bench_build_12k_triangles_bvh(mut b: &mut ::test::Bencher) {
        build_12k_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark the construction of a `BVH` with 120,000 triangles.
    fn bench_build_120k_triangles_bvh(mut b: &mut ::test::Bencher) {
        build_120k_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark intersecting 1,200 triangles using the recursive `BVH`.
    fn bench_intersect_1200_triangles_bvh(mut b: &mut ::test::Bencher) {
        intersect_1200_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark intersecting 12,000 triangles using the recursive `BVH`.
    fn bench_intersect_12k_triangles_bvh(mut b: &mut ::test::Bencher) {
        intersect_12k_triangles_bh::<BVH>(&mut b);
    }

    #[bench]
    /// Benchmark intersecting 120,000 triangles using the recursive `BVH`.
    fn bench_intersect_120k_triangles_bvh(mut b: &mut ::test::Bencher) {
        intersect_120k_triangles_bh::<BVH>(&mut b);
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::io::Write;

use backend::{self, Backend, BinaryRawValue};
use deserialize::{self, FromSql, FromSqlRow, Queryable};
use serialize::{self, IsNull, Output, ToSql};
use sql_types::{self, BigInt, Binary, Bool, Double, Float, Integer, NotNull, SmallInt, Text};

#[allow(dead_code)]
mod foreign_impls {
    use super::*;

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Bool"]
    struct BoolProxy(bool);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[cfg_attr(feature = "mysql", sql_type = "::sql_types::TinyInt")]
    struct I8Proxy(i8);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "SmallInt"]
    struct I16Proxy(i16);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Integer"]
    struct I32Proxy(i32);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "BigInt"]
    struct I64Proxy(i64);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[cfg_attr(
        feature = "mysql",
        sql_type = "::sql_types::Unsigned<::sql_types::TinyInt>"
    )]
    struct U8Proxy(u8);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[cfg_attr(feature = "mysql", sql_type = "::sql_types::Unsigned<SmallInt>")]
    struct U16Proxy(u16);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[cfg_attr(feature = "mysql", sql_type = "::sql_types::Unsigned<Integer>")]
    #[cfg_attr(feature = "postgres", sql_type = "::sql_types::Oid")]
    struct U32Proxy(u32);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[cfg_attr(feature = "mysql", sql_type = "::sql_types::Unsigned<BigInt>")]
    struct U64Proxy(u64);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Float"]
    struct F32Proxy(f32);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Double"]
    struct F64Proxy(f64);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Text"]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Date")]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Time")]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Timestamp")]
    struct StringProxy(String);

    #[derive(AsExpression)]
    #[diesel(foreign_derive, not_sized)]
    #[sql_type = "Text"]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Date")]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Time")]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Timestamp")]
    struct StrProxy(str);

    #[derive(FromSqlRow)]
    #[diesel(foreign_derive)]
    struct VecProxy<T>(Vec<T>);

    #[derive(AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Binary"]
    struct BinaryVecProxy(Vec<u8>);

    #[derive(AsExpression)]
    #[diesel(foreign_derive, not_sized)]
    #[sql_type = "Binary"]
    struct BinarySliceProxy([u8]);
}

impl NotNull for () {}

impl<ST, DB> FromSql<ST, DB> for String
where
    DB: Backend,
    *const str: FromSql<ST, DB>,
{
    fn from_sql(bytes: Option<backend::RawValue<DB>>) -> deserialize::Result<Self> {
        let str_ptr = <*const str as FromSql<ST, DB>>::from_sql(bytes)?;
        // We know that the pointer impl will never return null
        let string = unsafe { &*str_ptr };
        Ok(string.to_owned())
    }
}

/// The returned pointer is *only* valid for the lifetime to the argument of
/// `from_sql`. This impl is intended for uses where you want to write a new
/// impl in terms of `String`, but don't want to allocate. We have to return a
/// raw pointer instead of a reference with a lifetime due to the structure of
/// `FromSql`
impl<DB> FromSql<sql_types::Text, DB> for *const str
where
    DB: Backend + for<'a> BinaryRawValue<'a>,
{
    fn from_sql(value: Option<::backend::RawValue<DB>>) -> deserialize::Result<Self> {
        use std::str;
        let value = not_none!(value);
        let string = str::from_utf8(DB::as_bytes(value))?;
        Ok(string as *const _)
    }
}

impl<DB: Backend> ToSql<sql_types::Text, DB> for str {
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        out.write_all(self.as_bytes())
            .map(|_| IsNull::No)
            .map_err(|e| Box::new(e) as Box<dyn Error + Send + Sync>)
    }
}

impl<DB> ToSql<sql_types::Text, DB> for String
where
    DB: Backend,
    str: ToSql<sql_types::Text, DB>,
{
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        (self as &str).to_sql(out)
    }
}

impl<ST, DB> FromSql<ST, DB> for Vec<u8>
where
    DB: Backend,
    *const [u8]: FromSql<ST, DB>,
{
    fn from_sql(bytes: Option<backend::RawValue<DB>>) -> deserialize::Result<Self> {
        let slice_ptr = <*const [u8] as FromSql<ST, DB>>::from_sql(bytes)?;
        // We know that the pointer impl will never return null
        let bytes = unsafe { &*slice_ptr };
        Ok(bytes.to_owned())
    }
}

/// The returned pointer is *only* valid for the lifetime to the argument of
/// `from_sql`. This impl is intended for uses where you want to write a new
/// impl in terms of `Vec<u8>`, but don't want to allocate. We have to return a
/// raw pointer instead of a reference with a lifetime due to the structure of
/// `FromSql`
impl<DB> FromSql<sql_types::Binary, DB> for *const [u8]
where
    DB: Backend + for<'a> BinaryRawValue<'a>,
{
    fn from_sql(bytes: Option<backend::RawValue<DB>>) -> deserialize::Result<Self> {
        Ok(DB::as_bytes(not_none!(bytes)) as *const _)
    }
}

impl<DB> ToSql<sql_types::Binary, DB> for Vec<u8>
where
    DB: Backend,
    [u8]: ToSql<sql_types::Binary, DB>,
{
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        (self as &[u8]).to_sql(out)
    }
}

impl<DB: Backend> ToSql<sql_types::Binary, DB> for [u8] {
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        out.write_all(self)
            .map(|_| IsNull::No)
            .map_err(|e| Box::new(e) as Box<dyn Error + Send + Sync>)
    }
}

use std::borrow::{Cow, ToOwned};
use std::fmt;
impl<'a, T: ?Sized, ST, DB> ToSql<ST, DB> for Cow<'a, T>
where
    T: 'a + ToOwned + ToSql<ST, DB>,
    DB: Backend,
    Self: fmt::Debug,
{
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        ToSql::<ST, DB>::to_sql(&**self, out)
    }
}

impl<'a, T: ?Sized, ST, DB> FromSql<ST, DB> for Cow<'a, T>
where
    T: 'a + ToOwned,
    DB: Backend,
    T::Owned: FromSql<ST, DB>,
{
    fn from_sql(bytes: Option<backend::RawValue<DB>>) -> deserialize::Result<Self> {
        T::Owned::from_sql(bytes).map(Cow::Owned)
    }
}

impl<'a, T: ?Sized, ST, DB> FromSqlRow<ST, DB> for Cow<'a, T>
where
    T: 'a + ToOwned,
    DB: Backend,
    Cow<'a, T>: FromSql<ST, DB>,
{
    fn build_from_row<R: ::row::Row<DB>>(row: &mut R) -> deserialize::Result<Self> {
        FromSql::<ST, DB>::from_sql(row.take())
    }
}

impl<'a, T: ?Sized, ST, DB> Queryable<ST, DB> for Cow<'a, T>
where
    T: 'a + ToOwned,
    DB: Backend,
    Self: FromSqlRow<ST, DB>,
{
    type Row = Self;

    fn build(row: Self::Row) -> Self {
        row
    }
}

use expression::bound::Bound;
use expression::{AsExpression, Expression};

impl<'a, T: ?Sized, ST> AsExpression<ST> for Cow<'a, T>
where
    T: 'a + ToOwned,
    Bound<ST, Cow<'a, T>>: Expression<SqlType = ST>,
{
    type Expression = Bound<ST, Self>;

    fn as_expression(self) -> Self::Expression {
        Bound::new(self)
    }
}

impl<'a, 'b, T: ?Sized, ST> AsExpression<ST> for &'b Cow<'a, T>
where
    T: 'a + ToOwned,
    Bound<ST, &'b T>: Expression<SqlType = ST>,
{
    type Expression = Bound<ST, &'b T>;

    fn as_expression(self) -> Self::Expression {
        Bound::new(&**self)
    }
}
<commit_msg>Allow to specialize `FromSql<Text>` impl for strings<commit_after>use std::error::Error;
use std::io::Write;

use backend::{self, Backend, BinaryRawValue};
use deserialize::{self, FromSql, FromSqlRow, Queryable};
use serialize::{self, IsNull, Output, ToSql};
use sql_types::{self, BigInt, Binary, Bool, Double, Float, Integer, NotNull, SmallInt, Text};

#[allow(dead_code)]
mod foreign_impls {
    use super::*;

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Bool"]
    struct BoolProxy(bool);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[cfg_attr(feature = "mysql", sql_type = "::sql_types::TinyInt")]
    struct I8Proxy(i8);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "SmallInt"]
    struct I16Proxy(i16);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Integer"]
    struct I32Proxy(i32);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "BigInt"]
    struct I64Proxy(i64);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[cfg_attr(
        feature = "mysql",
        sql_type = "::sql_types::Unsigned<::sql_types::TinyInt>"
    )]
    struct U8Proxy(u8);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[cfg_attr(feature = "mysql", sql_type = "::sql_types::Unsigned<SmallInt>")]
    struct U16Proxy(u16);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[cfg_attr(feature = "mysql", sql_type = "::sql_types::Unsigned<Integer>")]
    #[cfg_attr(feature = "postgres", sql_type = "::sql_types::Oid")]
    struct U32Proxy(u32);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[cfg_attr(feature = "mysql", sql_type = "::sql_types::Unsigned<BigInt>")]
    struct U64Proxy(u64);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Float"]
    struct F32Proxy(f32);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Double"]
    struct F64Proxy(f64);

    #[derive(FromSqlRow, AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Text"]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Date")]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Time")]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Timestamp")]
    struct StringProxy(String);

    #[derive(AsExpression)]
    #[diesel(foreign_derive, not_sized)]
    #[sql_type = "Text"]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Date")]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Time")]
    #[cfg_attr(feature = "sqlite", sql_type = "::sql_types::Timestamp")]
    struct StrProxy(str);

    #[derive(FromSqlRow)]
    #[diesel(foreign_derive)]
    struct VecProxy<T>(Vec<T>);

    #[derive(AsExpression)]
    #[diesel(foreign_derive)]
    #[sql_type = "Binary"]
    struct BinaryVecProxy(Vec<u8>);

    #[derive(AsExpression)]
    #[diesel(foreign_derive, not_sized)]
    #[sql_type = "Binary"]
    struct BinarySliceProxy([u8]);
}

impl NotNull for () {}

impl<ST, DB> FromSql<ST, DB> for String
where
    DB: Backend,
    *const str: FromSql<ST, DB>,
{
    fn from_sql(bytes: Option<backend::RawValue<DB>>) -> deserialize::Result<Self> {
        let str_ptr = <*const str as FromSql<ST, DB>>::from_sql(bytes)?;
        // We know that the pointer impl will never return null
        let string = unsafe { &*str_ptr };
        Ok(string.to_owned())
    }
}

/// The returned pointer is *only* valid for the lifetime to the argument of
/// `from_sql`. This impl is intended for uses where you want to write a new
/// impl in terms of `String`, but don't want to allocate. We have to return a
/// raw pointer instead of a reference with a lifetime due to the structure of
/// `FromSql`
#[cfg(not(feature = "unstable"))]
impl<DB> FromSql<sql_types::Text, DB> for *const str
where
    DB: Backend + for<'a> BinaryRawValue<'a>,
{
    fn from_sql(value: Option<::backend::RawValue<DB>>) -> deserialize::Result<Self> {
        use std::str;
        let value = not_none!(value);
        let string = str::from_utf8(DB::as_bytes(value))?;
        Ok(string as *const _)
    }
}

#[cfg(feature = "unstable")]
impl<DB> FromSql<sql_types::Text, DB> for *const str
where
    DB: Backend + for<'a> BinaryRawValue<'a>,
{
    default fn from_sql(value: Option<::backend::RawValue<DB>>) -> deserialize::Result<Self> {
        use std::str;
        let value = not_none!(value);
        let string = str::from_utf8(DB::as_bytes(value))?;
        Ok(string as *const _)
    }
}

impl<DB: Backend> ToSql<sql_types::Text, DB> for str {
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        out.write_all(self.as_bytes())
            .map(|_| IsNull::No)
            .map_err(|e| Box::new(e) as Box<dyn Error + Send + Sync>)
    }
}

impl<DB> ToSql<sql_types::Text, DB> for String
where
    DB: Backend,
    str: ToSql<sql_types::Text, DB>,
{
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        (self as &str).to_sql(out)
    }
}

impl<ST, DB> FromSql<ST, DB> for Vec<u8>
where
    DB: Backend,
    *const [u8]: FromSql<ST, DB>,
{
    fn from_sql(bytes: Option<backend::RawValue<DB>>) -> deserialize::Result<Self> {
        let slice_ptr = <*const [u8] as FromSql<ST, DB>>::from_sql(bytes)?;
        // We know that the pointer impl will never return null
        let bytes = unsafe { &*slice_ptr };
        Ok(bytes.to_owned())
    }
}

/// The returned pointer is *only* valid for the lifetime to the argument of
/// `from_sql`. This impl is intended for uses where you want to write a new
/// impl in terms of `Vec<u8>`, but don't want to allocate. We have to return a
/// raw pointer instead of a reference with a lifetime due to the structure of
/// `FromSql`
impl<DB> FromSql<sql_types::Binary, DB> for *const [u8]
where
    DB: Backend + for<'a> BinaryRawValue<'a>,
{
    fn from_sql(bytes: Option<backend::RawValue<DB>>) -> deserialize::Result<Self> {
        Ok(DB::as_bytes(not_none!(bytes)) as *const _)
    }
}

impl<DB> ToSql<sql_types::Binary, DB> for Vec<u8>
where
    DB: Backend,
    [u8]: ToSql<sql_types::Binary, DB>,
{
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        (self as &[u8]).to_sql(out)
    }
}

impl<DB: Backend> ToSql<sql_types::Binary, DB> for [u8] {
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        out.write_all(self)
            .map(|_| IsNull::No)
            .map_err(|e| Box::new(e) as Box<dyn Error + Send + Sync>)
    }
}

use std::borrow::{Cow, ToOwned};
use std::fmt;
impl<'a, T: ?Sized, ST, DB> ToSql<ST, DB> for Cow<'a, T>
where
    T: 'a + ToOwned + ToSql<ST, DB>,
    DB: Backend,
    Self: fmt::Debug,
{
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        ToSql::<ST, DB>::to_sql(&**self, out)
    }
}

impl<'a, T: ?Sized, ST, DB> FromSql<ST, DB> for Cow<'a, T>
where
    T: 'a + ToOwned,
    DB: Backend,
    T::Owned: FromSql<ST, DB>,
{
    fn from_sql(bytes: Option<backend::RawValue<DB>>) -> deserialize::Result<Self> {
        T::Owned::from_sql(bytes).map(Cow::Owned)
    }
}

impl<'a, T: ?Sized, ST, DB> FromSqlRow<ST, DB> for Cow<'a, T>
where
    T: 'a + ToOwned,
    DB: Backend,
    Cow<'a, T>: FromSql<ST, DB>,
{
    fn build_from_row<R: ::row::Row<DB>>(row: &mut R) -> deserialize::Result<Self> {
        FromSql::<ST, DB>::from_sql(row.take())
    }
}

impl<'a, T: ?Sized, ST, DB> Queryable<ST, DB> for Cow<'a, T>
where
    T: 'a + ToOwned,
    DB: Backend,
    Self: FromSqlRow<ST, DB>,
{
    type Row = Self;

    fn build(row: Self::Row) -> Self {
        row
    }
}

use expression::bound::Bound;
use expression::{AsExpression, Expression};

impl<'a, T: ?Sized, ST> AsExpression<ST> for Cow<'a, T>
where
    T: 'a + ToOwned,
    Bound<ST, Cow<'a, T>>: Expression<SqlType = ST>,
{
    type Expression = Bound<ST, Self>;

    fn as_expression(self) -> Self::Expression {
        Bound::new(self)
    }
}

impl<'a, 'b, T: ?Sized, ST> AsExpression<ST> for &'b Cow<'a, T>
where
    T: 'a + ToOwned,
    Bound<ST, &'b T>: Expression<SqlType = ST>,
{
    type Expression = Bound<ST, &'b T>;

    fn as_expression(self) -> Self::Expression {
        Bound::new(&**self)
    }
}
<|endoftext|>


<commit_before>extern crate chrono;

use self::chrono::*;
use constants::*;
use std::collections::BTreeSet;
use std::fs;
use std::fs::File;
use std::io::{Read, Write};
use std::path::{Path, PathBuf};
use lib::fs_helper::*;

pub fn initialize() {
    println!("Initialize ...");

    let dir_name    = WORKING_DIR_NAME;
    let path_to_dir = Path::new(dir_name);
    if path_to_dir.exists() && path_to_dir.is_dir() {
        println!("  OK: \"{}\" directory has already exist.", dir_name);
    } else {
        match fs::create_dir(path_to_dir) {
            Ok(_)    => println!("  OK: Created \"{}\" directory.", dir_name),
            Err(why) => panic!("{:?}", why),
        }
    }

    let path_to_config = path_to_dir.clone().join(CONFIG_FILE_NAME);
    create_setting_file(path_to_config, DEFAULT_CONFIG);

    let path_to_ignore = path_to_dir.clone().join(IGNORE_FILE_NAME);
    let ignore_contents = walk_dir(".").iter()
        .fold(String::new(), |c, f| c + &f + "\n");
    create_setting_file(path_to_ignore, ignore_contents);
}

fn create_setting_file<S: AsRef<str>>(path_to_file: PathBuf, contents: S) {
    let file_name = path_to_file.file_name().and_then(|f| f.to_str()).unwrap();
    if path_to_file.exists() && path_to_file.is_file() {
        println!("  OK: \"{}\" file has already exist.", file_name);
    } else {
        match File::create(&path_to_file) {
            Ok(mut f) => {
                println!("  OK: Created \"{}\" file.", file_name);
                match f.write(contents.as_ref().as_bytes()) {
                    Ok(_)    => {},
                    Err(why) => panic!("{:?}", why),
                }
            },
            Err(why) => panic!("{:?}", why),
        }
    }
}

pub fn set_params() {
    println!("set parameters");
}

pub fn sweep() {
    let now           = Local::now();
    let trash_name    = format!("trash_{}", now.format("%Y-%m-%d"));
    let path_to_trash = Path::new(WORKING_DIR_NAME).join(trash_name);
    if !(path_to_trash.exists() && path_to_trash.is_dir()) {
        match fs::create_dir(path_to_trash) {
            Ok(_)    => {},
            Err(why) => panic!("{:?}", why),
        }
    }

    println!("Sweep ...");

    let ignore = read_ignore_file();

    let target_files = walk_dir(".")
        .difference(&ignore)
        .cloned()
        .collect::<Vec<String>>();

    println!("{:?}", target_files);
}

fn read_ignore_file() -> BTreeSet<String> {
    let ignore_file = Path::new(WORKING_DIR_NAME).join(IGNORE_FILE_NAME);
    let mut f       = match File::open(ignore_file) {
        Ok(f)    => f,
        Err(why) => panic!("{:?}", why),
    };
    let mut contents = String::new();
    match f.read_to_string(&mut contents) {
        Ok(_)    => {},
        Err(why) => panic!("{:?}", why),
    }
    contents
        .lines()
        .map(|l| l.trim().to_string())
        .collect::<BTreeSet<String>>()
}

pub fn burn() {
    println!("burn");
}

pub fn register_with_cron() {
    println!("register");
}

pub fn unregister_cron() {
    println!("unregister");
}

pub fn destroy() {
    println!("Destroy ...");

    match fs::remove_dir_all(WORKING_DIR_NAME) {
        Ok(_)    => println!("  OK: Removed \"{}\" directory.", WORKING_DIR_NAME),
        Err(why) => panic!("{:?}", why),
    }
}
<commit_msg>Do not panic if ".kic" not exist<commit_after>extern crate chrono;

use self::chrono::*;
use constants::*;
use std::collections::BTreeSet;
use std::fs;
use std::fs::File;
use std::io::{Read, Write};
use std::path::{Path, PathBuf};
use lib::fs_helper::*;

pub fn initialize() {
    println!("Initialize ...");

    let dir_name    = WORKING_DIR_NAME;
    let path_to_dir = Path::new(dir_name);
    if path_to_dir.exists() && path_to_dir.is_dir() {
        println!("  OK: \"{}\" directory has already exist.", dir_name);
    } else {
        match fs::create_dir(path_to_dir) {
            Ok(_)    => println!("  OK: Created \"{}\" directory.", dir_name),
            Err(why) => panic!("{:?}", why),
        }
    }

    let path_to_config = path_to_dir.clone().join(CONFIG_FILE_NAME);
    create_setting_file(path_to_config, DEFAULT_CONFIG);

    let path_to_ignore = path_to_dir.clone().join(IGNORE_FILE_NAME);
    let ignore_contents = walk_dir(".").iter()
        .fold(String::new(), |c, f| c + &f + "\n");
    create_setting_file(path_to_ignore, ignore_contents);
}

fn create_setting_file<S: AsRef<str>>(path_to_file: PathBuf, contents: S) {
    let file_name = path_to_file.file_name().and_then(|f| f.to_str()).unwrap();
    if path_to_file.exists() && path_to_file.is_file() {
        println!("  OK: \"{}\" file has already exist.", file_name);
    } else {
        match File::create(&path_to_file) {
            Ok(mut f) => {
                println!("  OK: Created \"{}\" file.", file_name);
                match f.write(contents.as_ref().as_bytes()) {
                    Ok(_)    => {},
                    Err(why) => panic!("{:?}", why),
                }
            },
            Err(why) => panic!("{:?}", why),
        }
    }
}

pub fn set_params() {
    println!("set parameters");
}

pub fn sweep() {
    let now           = Local::now();
    let trash_name    = format!("trash_{}", now.format("%Y-%m-%d"));
    let path_to_trash = Path::new(WORKING_DIR_NAME).join(trash_name);
    if !(path_to_trash.exists() && path_to_trash.is_dir()) {
        match fs::create_dir(path_to_trash) {
            Ok(_)    => {},
            Err(why) => panic!("{:?}", why),
        }
    }

    println!("Sweep ...");

    let ignore = read_ignore_file();

    let target_files = walk_dir(".")
        .difference(&ignore)
        .cloned()
        .collect::<Vec<String>>();

    println!("{:?}", target_files);
}

fn read_ignore_file() -> BTreeSet<String> {
    let ignore_file = Path::new(WORKING_DIR_NAME).join(IGNORE_FILE_NAME);
    let mut f       = match File::open(ignore_file) {
        Ok(f)    => f,
        Err(why) => panic!("{:?}", why),
    };
    let mut contents = String::new();
    match f.read_to_string(&mut contents) {
        Ok(_)    => {},
        Err(why) => panic!("{:?}", why),
    }
    contents
        .lines()
        .map(|l| l.trim().to_string())
        .collect::<BTreeSet<String>>()
}

pub fn burn() {
    println!("burn");
}

pub fn register_with_cron() {
    println!("register");
}

pub fn unregister_cron() {
    println!("unregister");
}

pub fn destroy() {
    println!("Destroy ...");

    let path_to_dir = Path::new(WORKING_DIR_NAME).to_path_buf();

    if path_to_dir.exists() {
        match fs::remove_dir_all(WORKING_DIR_NAME) {
            Ok(_)    => println!("  OK: Removed \"{}\" directory.", WORKING_DIR_NAME),
            Err(why) => panic!("{:?}", why),
        }
    } else {
        println!("  OK: \"{}\" does not exist.", WORKING_DIR_NAME);
    }
}
<|endoftext|>


<commit_before>pub struct ServiceOptions(u8);

impl ServiceOptions {
    pub fn new(opts: u8) -> ServiceOptions { ServiceOptions(opts) }

    pub fn emergency(&self) -> bool { self.0 >> 7 == 1 }
    pub fn protected(&self) -> bool { self.0 >> 6 & 1 == 1 }
    pub fn duplex(&self) -> bool { self.0 >> 5 & 1 == 1 }
    pub fn packet_switched(&self) -> bool { self.0 >> 4 & 1 == 1 }
    pub fn prio(&self) -> u8 { self.0 & 0x7 }
}

pub struct Channel(u16);

impl Channel {
    pub fn new(bytes: &[u8]) -> Channel { Channel(slice_u16(bytes)) }

    pub fn band(&self) -> u8 { (self.0 >> 12) as u8 }
    pub fn number(&self) -> u16 { self.0 & 0xFFF }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum TalkGroup {
    Nobody,
    Default,
    Everbody,
    Other(u16),
}

impl TalkGroup {
    pub fn new(bytes: &[u8]) -> TalkGroup {
        Self::from_bits(slice_u16(bytes))
    }

    pub fn from_bits(bits: u16) -> TalkGroup {
        use self::TalkGroup::*;

        match bits {
            0x0000 => Nobody,
            0x0001 => Default,
            0xFFFF => Everbody,
            _ => Other(bits),
        }
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct SystemServices(u8);

impl SystemServices {
    pub fn new(ssc: u8) -> Self { SystemServices(ssc) }

    pub fn is_composite(&self) -> bool { self.0 & 0x01 != 0 }
    pub fn has_updates(&self) -> bool { self.0 & 0x02 != 0 }
    pub fn is_backup(&self) -> bool { self.0 & 0x04 != 0 }
    pub fn has_data(&self) -> bool { self.0 & 0x10 != 0 }
    pub fn has_voice(&self) -> bool { self.0 & 0x20 != 0 }
    pub fn has_registration(&self) -> bool { self.0 & 0x40 != 0 }
    pub fn has_auth(&self) -> bool { self.0 & 0x80 != 0 }
}

pub fn slice_u16(bytes: &[u8]) -> u16 {
    (bytes[0] as u16) << 8 | bytes[1] as u16
}

pub fn slice_u24(bytes: &[u8]) -> u32 {
    (slice_u16(bytes) as u32) << 8 | bytes[2] as u32
}

pub fn slice_u32(bytes: &[u8]) -> u32 {
    (slice_u16(bytes) as u32) << 16 | slice_u16(&bytes[2..]) as u32
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_slice_u16() {
        assert_eq!(slice_u16(&[0xDE, 0xAD]), 0xDEAD);
        assert_eq!(slice_u16(&[0xAB, 0xCD, 0xEF]), 0xABCD);
    }

    #[test]
    fn test_slice_u24() {
        assert_eq!(slice_u24(&[0xDE, 0xAD, 0xBE]), 0xDEADBE);
        assert_eq!(slice_u24(&[0xAB, 0xCD, 0xEF, 0x12]), 0xABCDEF);
    }

    #[test]
    fn test_slice_u32() {
        assert_eq!(slice_u32(&[0xDE, 0xAD, 0xBE, 0xEF]), 0xDEADBEEF);
        assert_eq!(slice_u32(&[0xDE, 0xAD, 0xBE, 0xEF, 0x12]), 0xDEADBEEF);
    }
}
<commit_msg>Add ChannelParams decoder<commit_after>pub struct ServiceOptions(u8);

impl ServiceOptions {
    pub fn new(opts: u8) -> ServiceOptions { ServiceOptions(opts) }

    pub fn emergency(&self) -> bool { self.0 >> 7 == 1 }
    pub fn protected(&self) -> bool { self.0 >> 6 & 1 == 1 }
    pub fn duplex(&self) -> bool { self.0 >> 5 & 1 == 1 }
    pub fn packet_switched(&self) -> bool { self.0 >> 4 & 1 == 1 }
    pub fn prio(&self) -> u8 { self.0 & 0x7 }
}

pub struct Channel(u16);

impl Channel {
    pub fn new(bytes: &[u8]) -> Channel { Channel(slice_u16(bytes)) }

    pub fn band(&self) -> u8 { (self.0 >> 12) as u8 }
    pub fn number(&self) -> u16 { self.0 & 0xFFF }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum TalkGroup {
    Nobody,
    Default,
    Everbody,
    Other(u16),
}

impl TalkGroup {
    pub fn new(bytes: &[u8]) -> TalkGroup {
        Self::from_bits(slice_u16(bytes))
    }

    pub fn from_bits(bits: u16) -> TalkGroup {
        use self::TalkGroup::*;

        match bits {
            0x0000 => Nobody,
            0x0001 => Default,
            0xFFFF => Everbody,
            _ => Other(bits),
        }
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct SystemServices(u8);

impl SystemServices {
    pub fn new(ssc: u8) -> Self { SystemServices(ssc) }

    pub fn is_composite(&self) -> bool { self.0 & 0x01 != 0 }
    pub fn has_updates(&self) -> bool { self.0 & 0x02 != 0 }
    pub fn is_backup(&self) -> bool { self.0 & 0x04 != 0 }
    pub fn has_data(&self) -> bool { self.0 & 0x10 != 0 }
    pub fn has_voice(&self) -> bool { self.0 & 0x20 != 0 }
    pub fn has_registration(&self) -> bool { self.0 & 0x40 != 0 }
    pub fn has_auth(&self) -> bool { self.0 & 0x80 != 0 }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct ChannelParams {
    /// Receive frequency in Hz.
    pub rx_freq: u64,
    /// Transmit frequency in Hz.
    pub tx_freq: u64,
    /// Channel bandwidth in Hz.
    pub bandwidth: u64,
}

impl ChannelParams {
    pub fn new(base: u32, channel: u8, bandwidth: u16, offset: u16, spacing: u16)
        -> ChannelParams
    {
        let rx = base as u64 * 5 + channel as u64 * spacing as u64 * 125;
        let off = (offset as u64 & 0xFF) * 250_000;
        let tx = if offset >> 8 == 0 {
            rx - off
        } else {
            rx + off
        };

        ChannelParams {
            rx_freq: rx,
            tx_freq: tx,
            bandwidth: bandwidth as u64 * 125,
        }
    }
}

pub fn slice_u16(bytes: &[u8]) -> u16 {
    (bytes[0] as u16) << 8 | bytes[1] as u16
}

pub fn slice_u24(bytes: &[u8]) -> u32 {
    (slice_u16(bytes) as u32) << 8 | bytes[2] as u32
}

pub fn slice_u32(bytes: &[u8]) -> u32 {
    (slice_u16(bytes) as u32) << 16 | slice_u16(&bytes[2..]) as u32
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_slice_u16() {
        assert_eq!(slice_u16(&[0xDE, 0xAD]), 0xDEAD);
        assert_eq!(slice_u16(&[0xAB, 0xCD, 0xEF]), 0xABCD);
    }

    #[test]
    fn test_slice_u24() {
        assert_eq!(slice_u24(&[0xDE, 0xAD, 0xBE]), 0xDEADBE);
        assert_eq!(slice_u24(&[0xAB, 0xCD, 0xEF, 0x12]), 0xABCDEF);
    }

    #[test]
    fn test_slice_u32() {
        assert_eq!(slice_u32(&[0xDE, 0xAD, 0xBE, 0xEF]), 0xDEADBEEF);
        assert_eq!(slice_u32(&[0xDE, 0xAD, 0xBE, 0xEF, 0x12]), 0xDEADBEEF);
    }

    #[test]
    fn test_channel_params() {
        let p = ChannelParams::new(170201250, 0, 0x64, 0b010110100, 0x32);
        assert_eq!(p.rx_freq, 851_006_250);
        assert_eq!(p.tx_freq, 806_006_250);
        assert_eq!(p.bandwidth, 12500);
    }
}
<|endoftext|>


<commit_before>pub fn reply(message: &str) -> &str {
    if is_silence(message) { "Fine. Be that way!" }
    else if is_yelling(message) { "Woah, chill out!" }
    else if is_question(message) { "Sure." }
    else { "Whatever." }
}

fn is_silence(message: &str) -> bool {
    message == ""
}

fn is_yelling(message: &str) -> bool {
    message.chars().all(|char| !char.is_lowercase())
}

fn is_question(message: &str) -> bool {
    message.ends_with("?")
}
<commit_msg>Update example.rs<commit_after>pub fn reply(message: &str) -> &str {
    if is_silence(message) { "Fine. Be that way!" }
    else if is_yelling(message) { "Whoa, chill out!" }
    else if is_question(message) { "Sure." }
    else { "Whatever." }
}

fn is_silence(message: &str) -> bool {
    message == ""
}

fn is_yelling(message: &str) -> bool {
    message.chars().all(|char| !char.is_lowercase())
}

fn is_question(message: &str) -> bool {
    message.ends_with("?")
}
<|endoftext|>