<commit_before>use bluetooth_device::BluetoothDevice;
use bluetooth_utils;
use dbus::MessageItem;
use rustc_serialize::hex::FromHex;
use std::error::Error;

static ADAPTER_INTERFACE: &'static str = "org.bluez.Adapter1";

#[derive(Clone, Debug)]
pub struct BluetoothAdapter {
    object_path: String,
}

impl BluetoothAdapter {
    fn new(object_path: String) -> BluetoothAdapter {
        BluetoothAdapter {
            object_path: object_path,
        }
    }

    pub fn init() -> Result<BluetoothAdapter, Box<Error>> {
        let adapters = try!(bluetooth_utils::get_adapters());

        if adapters.is_empty() {
            return Err(Box::from("Bluetooth adapter not found"))
        }

        Ok(BluetoothAdapter::new(adapters[0].clone()))
    }

    pub fn get_object_path(&self) -> String {
        self.object_path.clone()
    }

    pub fn get_first_device(&self) -> Result<BluetoothDevice, Box<Error>> {
        let devices = try!(bluetooth_utils::list_devices(&self.object_path));

        if devices.is_empty() {
            return Err(Box::from("No device found."))
        }
        Ok(BluetoothDevice::create_device(devices[0].clone()))
    }

    pub fn get_device_list(&self) -> Result<Vec<String>, Box<Error>> {
        bluetooth_utils::list_devices(&self.object_path)
    }

    fn get_property(&self, prop: &str) -> Result<MessageItem, Box<Error>> {
        bluetooth_utils::get_property(ADAPTER_INTERFACE, &self.object_path, prop)
    }

    fn set_property<T>(&self, prop: &str, value: T) -> Result<(), Box<Error>>
    where T: Into<MessageItem> {
        bluetooth_utils::set_property(ADAPTER_INTERFACE, &self.object_path, prop, value)
    }

    fn call_method(&self, method: &str, param: Option<[MessageItem; 1]>) -> Result<(), Box<Error>> {
        bluetooth_utils::call_method(ADAPTER_INTERFACE, &self.object_path, method, param)
    }

/*
 * Properties
 */

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n108
    pub fn get_address(&self) -> Result<String, Box<Error>> {
        let address = try!(self.get_property("Address"));
        Ok(String::from(address.inner::<&str>().unwrap()))
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n112
    pub fn get_name(&self) -> Result<String, Box<Error>> {
        let name = try!(self.get_property("Name"));
        Ok(String::from(name.inner::<&str>().unwrap()))
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n120
    pub fn get_alias(&self) -> Result<String, Box<Error>> {
        let alias = try!(self.get_property("Alias"));
        Ok(String::from(alias.inner::<&str>().unwrap()))
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n120
    pub fn set_alias(&self, value: String) -> Result<(), Box<Error>> {
        self.set_property("Alias", value)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n139
    pub fn get_class(&self) -> Result<u32, Box<Error>> {
        let class = try!(self.get_property("Class"));
        Ok(class.inner::<u32>().unwrap())
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n147
    pub fn is_powered(&self) -> Result<bool, Box<Error>> {
        let powered = try!(self.get_property("Powered"));
        Ok(powered.inner::<bool>().unwrap())
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n147
    pub fn set_powered(&self, value: bool) -> Result<(),Box<Error>> {
        self.set_property("Powered", value)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n156
    pub fn is_discoverable(&self) -> Result<bool, Box<Error>> {
        let discoverable = try!(self.get_property("Discoverable"));
        Ok(discoverable.inner::<bool>().unwrap())
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n156
    pub fn set_discoverable(&self, value: bool) -> Result<(), Box<Error>> {
        self.set_property("Discoverable", value)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n176
    pub fn is_pairable(&self) -> Result<bool, Box<Error>> {
        let pairable = try!(self.get_property("Pairable"));
        Ok(pairable.inner::<bool>().unwrap())
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n176
    pub fn set_pairable(&self, value: bool) -> Result<(), Box<Error>> {
        self.set_property("Pairable", value)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n187
    pub fn get_pairable_timeout(&self) -> Result<u32, Box<Error>> {
        let pairable_timeout = try!(self.get_property("PairableTimeout"));
        Ok(pairable_timeout.inner::<u32>().unwrap())
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n187
    pub fn set_pairable_timeout(&self, value: u32) -> Result<(), Box<Error>> {
        self.set_property("PairableTimeout", value)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n196
    pub fn get_discoverable_timeout(&self) -> Result<u32, Box<Error>> {
        let discoverable_timeout = try!(self.get_property("DiscoverableTimeout"));
        Ok(discoverable_timeout.inner::<u32>().unwrap())
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n196
    pub fn set_discoverable_timeout(&self, value: u32) -> Result<(), Box<Error>> {
        self.set_property("DiscoverableTimeout", value)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n205
    pub fn is_discovering(&self) -> Result<bool, Box<Error>> {
        let discovering = try!(self.get_property("Discovering"));
        Ok(discovering.inner::<bool>().unwrap())
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n209
    pub fn get_uuids(&self) -> Result<Vec<String>, Box<Error>> {
        let uuids = try!(self.get_property("UUIDs"));
        let z: &[MessageItem] = uuids.inner().unwrap();
        let mut v: Vec<String> = Vec::new();
        for y in z {
            v.push(String::from(y.inner::<&str>().unwrap()));
        }
        Ok(v)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n215
    pub fn get_modalias(&self) ->  Result<(String, u32, u32, u32), Box<Error>> {
        let modalias = try!(self.get_property("Modalias"));
        let m = modalias.inner::<&str>().unwrap();
        let ids: Vec<&str> = m.split(":").collect();

        let source = String::from(ids[0]);
        let vendor = ids[1][1..5].from_hex().unwrap();
        let product = ids[1][6..10].from_hex().unwrap();
        let device = ids[1][11..15].from_hex().unwrap();

        Ok((source,
        (vendor[0] as u32) * 16 * 16 + (vendor[1] as u32),
        (product[0] as u32) * 16 * 16 + (product[1] as u32),
        (device[0] as u32) * 16 * 16 + (device[1] as u32)))
    }

    pub fn get_vendor_id_source(&self) -> Result<String, Box<Error>> {
        let (vendor_id_source,_,_,_) = try!(self.get_modalias());
        Ok(vendor_id_source)
    }

    pub fn get_vendor_id(&self) -> Result<u32, Box<Error>> {
        let (_,vendor_id,_,_) = try!(self.get_modalias());
        Ok(vendor_id)
    }

    pub fn get_product_id(&self) -> Result<u32, Box<Error>> {
        let (_,_,product_id,_) = try!(self.get_modalias());
        Ok(product_id)
    }

    pub fn get_device_id(&self) -> Result<u32, Box<Error>> {
        let (_,_,_,device_id) = try!(self.get_modalias());
        Ok(device_id)
    }

/*
 * Methods
 */

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n12
    pub fn start_discovery(&self) -> Result<(), Box<Error>> {
        self.call_method("StartDiscovery", None)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n27
    pub fn stop_discovery(&self) -> Result<(), Box<Error>> {
        self.call_method("StopDiscovery", None)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n40
    pub fn remove_device(&self, device: String) -> Result<(), Box<Error>> {
        self.call_method("RemoveDevice", Some([device.into()]))
    }
}
<commit_msg>Add create adapter method<commit_after>use bluetooth_device::BluetoothDevice;
use bluetooth_utils;
use dbus::MessageItem;
use rustc_serialize::hex::FromHex;
use std::error::Error;

static ADAPTER_INTERFACE: &'static str = "org.bluez.Adapter1";

#[derive(Clone, Debug)]
pub struct BluetoothAdapter {
    object_path: String,
}

impl BluetoothAdapter {
    fn new(object_path: String) -> BluetoothAdapter {
        BluetoothAdapter {
            object_path: object_path,
        }
    }

    pub fn init() -> Result<BluetoothAdapter, Box<Error>> {
        let adapters = try!(bluetooth_utils::get_adapters());

        if adapters.is_empty() {
            return Err(Box::from("Bluetooth adapter not found"))
        }

        Ok(BluetoothAdapter::new(adapters[0].clone()))
    }

    pub fn create_adapter(object_path: String) -> Result<BluetoothAdapter, Box<Error>> {
        let adapters = try!(bluetooth_utils::get_adapters());

        for adapter in adapters {
            if adapter == object_path {
                return Ok(BluetoothAdapter::new(adapter.clone()));
            }
        }
        Err(Box::from("Bluetooth adapter not found"))
    }

    pub fn get_object_path(&self) -> String {
        self.object_path.clone()
    }

    pub fn get_first_device(&self) -> Result<BluetoothDevice, Box<Error>> {
        let devices = try!(bluetooth_utils::list_devices(&self.object_path));

        if devices.is_empty() {
            return Err(Box::from("No device found."))
        }
        Ok(BluetoothDevice::create_device(devices[0].clone()))
    }

    pub fn get_device_list(&self) -> Result<Vec<String>, Box<Error>> {
        bluetooth_utils::list_devices(&self.object_path)
    }

    fn get_property(&self, prop: &str) -> Result<MessageItem, Box<Error>> {
        bluetooth_utils::get_property(ADAPTER_INTERFACE, &self.object_path, prop)
    }

    fn set_property<T>(&self, prop: &str, value: T) -> Result<(), Box<Error>>
    where T: Into<MessageItem> {
        bluetooth_utils::set_property(ADAPTER_INTERFACE, &self.object_path, prop, value)
    }

    fn call_method(&self, method: &str, param: Option<[MessageItem; 1]>) -> Result<(), Box<Error>> {
        bluetooth_utils::call_method(ADAPTER_INTERFACE, &self.object_path, method, param)
    }

/*
 * Properties
 */

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n108
    pub fn get_address(&self) -> Result<String, Box<Error>> {
        let address = try!(self.get_property("Address"));
        Ok(String::from(address.inner::<&str>().unwrap()))
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n112
    pub fn get_name(&self) -> Result<String, Box<Error>> {
        let name = try!(self.get_property("Name"));
        Ok(String::from(name.inner::<&str>().unwrap()))
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n120
    pub fn get_alias(&self) -> Result<String, Box<Error>> {
        let alias = try!(self.get_property("Alias"));
        Ok(String::from(alias.inner::<&str>().unwrap()))
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n120
    pub fn set_alias(&self, value: String) -> Result<(), Box<Error>> {
        self.set_property("Alias", value)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n139
    pub fn get_class(&self) -> Result<u32, Box<Error>> {
        let class = try!(self.get_property("Class"));
        Ok(class.inner::<u32>().unwrap())
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n147
    pub fn is_powered(&self) -> Result<bool, Box<Error>> {
        let powered = try!(self.get_property("Powered"));
        Ok(powered.inner::<bool>().unwrap())
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n147
    pub fn set_powered(&self, value: bool) -> Result<(),Box<Error>> {
        self.set_property("Powered", value)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n156
    pub fn is_discoverable(&self) -> Result<bool, Box<Error>> {
        let discoverable = try!(self.get_property("Discoverable"));
        Ok(discoverable.inner::<bool>().unwrap())
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n156
    pub fn set_discoverable(&self, value: bool) -> Result<(), Box<Error>> {
        self.set_property("Discoverable", value)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n176
    pub fn is_pairable(&self) -> Result<bool, Box<Error>> {
        let pairable = try!(self.get_property("Pairable"));
        Ok(pairable.inner::<bool>().unwrap())
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n176
    pub fn set_pairable(&self, value: bool) -> Result<(), Box<Error>> {
        self.set_property("Pairable", value)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n187
    pub fn get_pairable_timeout(&self) -> Result<u32, Box<Error>> {
        let pairable_timeout = try!(self.get_property("PairableTimeout"));
        Ok(pairable_timeout.inner::<u32>().unwrap())
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n187
    pub fn set_pairable_timeout(&self, value: u32) -> Result<(), Box<Error>> {
        self.set_property("PairableTimeout", value)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n196
    pub fn get_discoverable_timeout(&self) -> Result<u32, Box<Error>> {
        let discoverable_timeout = try!(self.get_property("DiscoverableTimeout"));
        Ok(discoverable_timeout.inner::<u32>().unwrap())
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n196
    pub fn set_discoverable_timeout(&self, value: u32) -> Result<(), Box<Error>> {
        self.set_property("DiscoverableTimeout", value)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n205
    pub fn is_discovering(&self) -> Result<bool, Box<Error>> {
        let discovering = try!(self.get_property("Discovering"));
        Ok(discovering.inner::<bool>().unwrap())
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n209
    pub fn get_uuids(&self) -> Result<Vec<String>, Box<Error>> {
        let uuids = try!(self.get_property("UUIDs"));
        let z: &[MessageItem] = uuids.inner().unwrap();
        let mut v: Vec<String> = Vec::new();
        for y in z {
            v.push(String::from(y.inner::<&str>().unwrap()));
        }
        Ok(v)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n215
    pub fn get_modalias(&self) ->  Result<(String, u32, u32, u32), Box<Error>> {
        let modalias = try!(self.get_property("Modalias"));
        let m = modalias.inner::<&str>().unwrap();
        let ids: Vec<&str> = m.split(":").collect();

        let source = String::from(ids[0]);
        let vendor = ids[1][1..5].from_hex().unwrap();
        let product = ids[1][6..10].from_hex().unwrap();
        let device = ids[1][11..15].from_hex().unwrap();

        Ok((source,
        (vendor[0] as u32) * 16 * 16 + (vendor[1] as u32),
        (product[0] as u32) * 16 * 16 + (product[1] as u32),
        (device[0] as u32) * 16 * 16 + (device[1] as u32)))
    }

    pub fn get_vendor_id_source(&self) -> Result<String, Box<Error>> {
        let (vendor_id_source,_,_,_) = try!(self.get_modalias());
        Ok(vendor_id_source)
    }

    pub fn get_vendor_id(&self) -> Result<u32, Box<Error>> {
        let (_,vendor_id,_,_) = try!(self.get_modalias());
        Ok(vendor_id)
    }

    pub fn get_product_id(&self) -> Result<u32, Box<Error>> {
        let (_,_,product_id,_) = try!(self.get_modalias());
        Ok(product_id)
    }

    pub fn get_device_id(&self) -> Result<u32, Box<Error>> {
        let (_,_,_,device_id) = try!(self.get_modalias());
        Ok(device_id)
    }

/*
 * Methods
 */

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n12
    pub fn start_discovery(&self) -> Result<(), Box<Error>> {
        self.call_method("StartDiscovery", None)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n27
    pub fn stop_discovery(&self) -> Result<(), Box<Error>> {
        self.call_method("StopDiscovery", None)
    }

    // http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/adapter-api.txt#n40
    pub fn remove_device(&self, device: String) -> Result<(), Box<Error>> {
        self.call_method("RemoveDevice", Some([device.into()]))
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Build configuration for Rust's release channels.
//!
//! Implements the stable/beta/nightly channel distinctions by setting various
//! flags like the `unstable_features`, calculating variables like `release` and
//! `package_vers`, and otherwise indicating to the compiler what it should
//! print out as part of its version information.

use std::path::Path;
use std::process::Command;

use build_helper::output;

use Build;
use config::Config;

// The version number
pub const CFG_RELEASE_NUM: &str = "1.23.0";

// An optional number to put after the label, e.g. '.2' -> '-beta.2'
// Be sure to make this starts with a dot to conform to semver pre-release
// versions (section 9)
pub const CFG_PRERELEASE_VERSION: &str = ".1";

pub struct GitInfo {
    inner: Option<Info>,
}

struct Info {
    commit_date: String,
    sha: String,
    short_sha: String,
}

impl GitInfo {
    pub fn new(config: &Config, dir: &Path) -> GitInfo {
        // See if this even begins to look like a git dir
        if config.ignore_git || !dir.join(".git").exists() {
            return GitInfo { inner: None }
        }

        // Make sure git commands work
        let out = Command::new("git")
                          .arg("rev-parse")
                          .current_dir(dir)
                          .output()
                          .expect("failed to spawn git");
        if !out.status.success() {
            return GitInfo { inner: None }
        }

        // Ok, let's scrape some info
        let ver_date = output(Command::new("git").current_dir(dir)
                                      .arg("log").arg("-1")
                                      .arg("--date=short")
                                      .arg("--pretty=format:%cd"));
        let ver_hash = output(Command::new("git").current_dir(dir)
                                      .arg("rev-parse").arg("HEAD"));
        let short_ver_hash = output(Command::new("git")
                                            .current_dir(dir)
                                            .arg("rev-parse")
                                            .arg("--short=9")
                                            .arg("HEAD"));
        GitInfo {
            inner: Some(Info {
                commit_date: ver_date.trim().to_string(),
                sha: ver_hash.trim().to_string(),
                short_sha: short_ver_hash.trim().to_string(),
            }),
        }
    }

    pub fn sha(&self) -> Option<&str> {
        self.inner.as_ref().map(|s| &s.sha[..])
    }

    pub fn sha_short(&self) -> Option<&str> {
        self.inner.as_ref().map(|s| &s.short_sha[..])
    }

    pub fn commit_date(&self) -> Option<&str> {
        self.inner.as_ref().map(|s| &s.commit_date[..])
    }

    pub fn version(&self, build: &Build, num: &str) -> String {
        let mut version = build.release(num);
        if let Some(ref inner) = self.inner {
            version.push_str(" (");
            version.push_str(&inner.short_sha);
            version.push_str(" ");
            version.push_str(&inner.commit_date);
            version.push_str(")");
        }
        version
    }

    pub fn is_git(&self) -> bool {
        self.inner.is_some()
    }
}
<commit_msg>Auto merge of #46286 - SimonSapin:patch-6, r=alexcrichton<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Build configuration for Rust's release channels.
//!
//! Implements the stable/beta/nightly channel distinctions by setting various
//! flags like the `unstable_features`, calculating variables like `release` and
//! `package_vers`, and otherwise indicating to the compiler what it should
//! print out as part of its version information.

use std::path::Path;
use std::process::Command;

use build_helper::output;

use Build;
use config::Config;

// The version number
pub const CFG_RELEASE_NUM: &str = "1.24.0";

// An optional number to put after the label, e.g. '.2' -> '-beta.2'
// Be sure to make this starts with a dot to conform to semver pre-release
// versions (section 9)
pub const CFG_PRERELEASE_VERSION: &str = ".1";

pub struct GitInfo {
    inner: Option<Info>,
}

struct Info {
    commit_date: String,
    sha: String,
    short_sha: String,
}

impl GitInfo {
    pub fn new(config: &Config, dir: &Path) -> GitInfo {
        // See if this even begins to look like a git dir
        if config.ignore_git || !dir.join(".git").exists() {
            return GitInfo { inner: None }
        }

        // Make sure git commands work
        let out = Command::new("git")
                          .arg("rev-parse")
                          .current_dir(dir)
                          .output()
                          .expect("failed to spawn git");
        if !out.status.success() {
            return GitInfo { inner: None }
        }

        // Ok, let's scrape some info
        let ver_date = output(Command::new("git").current_dir(dir)
                                      .arg("log").arg("-1")
                                      .arg("--date=short")
                                      .arg("--pretty=format:%cd"));
        let ver_hash = output(Command::new("git").current_dir(dir)
                                      .arg("rev-parse").arg("HEAD"));
        let short_ver_hash = output(Command::new("git")
                                            .current_dir(dir)
                                            .arg("rev-parse")
                                            .arg("--short=9")
                                            .arg("HEAD"));
        GitInfo {
            inner: Some(Info {
                commit_date: ver_date.trim().to_string(),
                sha: ver_hash.trim().to_string(),
                short_sha: short_ver_hash.trim().to_string(),
            }),
        }
    }

    pub fn sha(&self) -> Option<&str> {
        self.inner.as_ref().map(|s| &s.sha[..])
    }

    pub fn sha_short(&self) -> Option<&str> {
        self.inner.as_ref().map(|s| &s.short_sha[..])
    }

    pub fn commit_date(&self) -> Option<&str> {
        self.inner.as_ref().map(|s| &s.commit_date[..])
    }

    pub fn version(&self, build: &Build, num: &str) -> String {
        let mut version = build.release(num);
        if let Some(ref inner) = self.inner {
            version.push_str(" (");
            version.push_str(&inner.short_sha);
            version.push_str(" ");
            version.push_str(&inner.commit_date);
            version.push_str(")");
        }
        version
    }

    pub fn is_git(&self) -> bool {
        self.inner.is_some()
    }
}
<|endoftext|>


<commit_before>#[derive(Copy, Clone)]
pub struct SubscribeError {
    pub driver_number: usize,
    pub subscribe_number: usize,
    pub return_code: isize,
}

#[derive(Copy, Clone)]
pub struct CommandError {
    pub driver_number: usize,
    pub command_number: usize,
    pub arg1: usize,
    pub arg2: usize,
    pub return_code: isize,
}

#[derive(Copy, Clone)]
pub struct AllowError {
    pub driver_number: usize,
    pub allow_number: usize,
    pub return_code: isize,
}

pub const SUCCESS: isize = 0;
pub const FAIL: isize = -1;
pub const EBUSY: isize = -2;
pub const EALREADY: isize = -3;
pub const EINVAL: isize = -6;
pub const ESIZE: isize = -7;
pub const ENOMEM: isize = -9;
<commit_msg>Update result.rs<commit_after>#[derive(Copy, Clone)]
pub struct SubscribeError {
    pub driver_number: usize,
    pub subscribe_number: usize,
    pub return_code: isize,
}

#[derive(Copy, Clone)]
pub struct CommandError {
    pub driver_number: usize,
    pub command_number: usize,
    pub arg1: usize,
    pub arg2: usize,
    pub return_code: isize,
}

#[derive(Copy, Clone)]
pub struct AllowError {
    pub driver_number: usize,
    pub allow_number: usize,
    pub return_code: isize,
}

pub const SUCCESS: isize = 0;
pub const FAIL: isize = -1;
pub const EBUSY: isize = -2;
pub const EALREADY: isize = -3;
pub const EOFF: isize = -4;
pub const ERESERVE: isize = -5;
pub const EINVAL: isize = -6;
pub const ESIZE: isize = -7;
pub const ECANCEL: isize = -8;
pub const ENOMEM: isize = -9;
pub const ENOSUPPORT: isize = -10;
pub const ENODEVICE: isize = -11;
pub const EUNINSTALLED: isize = -12;
pub const ENOACK: isize = -13;

<|endoftext|>


<commit_before>use rustc_parse::{self, DirectoryOwnership, new_sub_parser_from_file, parser::Parser};
use syntax::ast;
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::symbol::Symbol;
use syntax::token;
use syntax::tokenstream::TokenStream;
use syntax::early_buffered_lints::BufferedEarlyLintId;
use syntax_expand::panictry;
use syntax_expand::base::{self, *};

use smallvec::SmallVec;
use syntax_pos::{self, Pos, Span};

use rustc_data_structures::sync::Lrc;

// These macros all relate to the file system; they either return
// the column/row/filename of the expression, or they include
// a given file into the current one.

/// line!(): expands to the current line number
pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                   -> Box<dyn base::MacResult+'static> {
    base::check_zero_tts(cx, sp, tts, "line!");

    let topmost = cx.expansion_cause().unwrap_or(sp);
    let loc = cx.source_map().lookup_char_pos(topmost.lo());

    base::MacEager::expr(cx.expr_u32(topmost, loc.line as u32))
}

/* column!(): expands to the current column number */
pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                  -> Box<dyn base::MacResult+'static> {
    base::check_zero_tts(cx, sp, tts, "column!");

    let topmost = cx.expansion_cause().unwrap_or(sp);
    let loc = cx.source_map().lookup_char_pos(topmost.lo());

    base::MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1))
}

/// file!(): expands to the current filename */
/// The source_file (`loc.file`) contains a bunch more information we could spit
/// out if we wanted.
pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                   -> Box<dyn base::MacResult+'static> {
    base::check_zero_tts(cx, sp, tts, "file!");

    let topmost = cx.expansion_cause().unwrap_or(sp);
    let loc = cx.source_map().lookup_char_pos(topmost.lo());
    base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&loc.file.name.to_string())))
}

pub fn expand_stringify(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                        -> Box<dyn base::MacResult+'static> {
    let s = pprust::tts_to_string(tts);
    base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&s)))
}

pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                  -> Box<dyn base::MacResult+'static> {
    base::check_zero_tts(cx, sp, tts, "module_path!");
    let mod_path = &cx.current_expansion.module.mod_path;
    let string = mod_path.iter().map(|x| x.to_string()).collect::<Vec<String>>().join("::");

    base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&string)))
}

/// include! : parse the given file as an expr
/// This is generally a bad idea because it's going to behave
/// unhygienically.
pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                           -> Box<dyn base::MacResult+'cx> {
    let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
        Some(f) => f,
        None => return DummyResult::any(sp),
    };
    // The file will be added to the code map by the parser
    let file = match cx.resolve_path(file, sp) {
        Ok(f) => f,
        Err(mut err) => {
            err.emit();
            return DummyResult::any(sp);
        },
    };
    let directory_ownership = DirectoryOwnership::Owned { relative: None };
    let p = new_sub_parser_from_file(cx.parse_sess(), &file, directory_ownership, None, sp);

    struct ExpandResult<'a> {
        p: Parser<'a>,
    }
    impl<'a> base::MacResult for ExpandResult<'a> {
        fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
            let r = panictry!(self.p.parse_expr());
            if self.p.token != token::Eof {
                self.p.sess.buffer_lint(
                    BufferedEarlyLintId::IncompleteInclude,
                    self.p.token.span,
                    ast::CRATE_NODE_ID,
                    "include macro expected single expression in source",
                );
            }
            Some(r)
        }

        fn make_items(mut self: Box<ExpandResult<'a>>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
            let mut ret = SmallVec::new();
            while self.p.token != token::Eof {
                match panictry!(self.p.parse_item()) {
                    Some(item) => ret.push(item),
                    None => self.p.sess.span_diagnostic.span_fatal(self.p.token.span,
                                                           &format!("expected item, found `{}`",
                                                                    self.p.this_token_to_string()))
                                               .raise()
                }
            }
            Some(ret)
        }
    }

    Box::new(ExpandResult { p })
}

// include_str! : read the given file, insert it as a literal string expr
pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                          -> Box<dyn base::MacResult+'static> {
    let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
        Some(f) => f,
        None => return DummyResult::any(sp)
    };
    let file = match cx.resolve_path(file, sp) {
        Ok(f) => f,
        Err(mut err) => {
            err.emit();
            return DummyResult::any(sp);
        },
    };
    match cx.source_map().load_binary_file(&file) {
        Ok(bytes) => match std::str::from_utf8(&bytes) {
            Ok(src) => {
                let interned_src = Symbol::intern(&src);
                base::MacEager::expr(cx.expr_str(sp, interned_src))
            }
            Err(_) => {
                cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display()));
                DummyResult::any(sp)
            }
        },
        Err(e) => {
            cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
            DummyResult::any(sp)
        }
    }
}

pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                            -> Box<dyn base::MacResult+'static> {
    let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") {
        Some(f) => f,
        None => return DummyResult::any(sp)
    };
    let file = match cx.resolve_path(file, sp) {
        Ok(f) => f,
        Err(mut err) => {
            err.emit();
            return DummyResult::any(sp);
        },
    };
    match cx.source_map().load_binary_file(&file) {
        Ok(bytes) => {
            base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::new(bytes))))
        },
        Err(e) => {
            cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
            DummyResult::any(sp)
        }
    }
}
<commit_msg>Rollup merge of #66349 - euclio:def-site-builtins, r=petrochenkov<commit_after>use rustc_parse::{self, DirectoryOwnership, new_sub_parser_from_file, parser::Parser};
use syntax::ast;
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::symbol::Symbol;
use syntax::token;
use syntax::tokenstream::TokenStream;
use syntax::early_buffered_lints::BufferedEarlyLintId;
use syntax_expand::panictry;
use syntax_expand::base::{self, *};

use smallvec::SmallVec;
use syntax_pos::{self, Pos, Span};

use rustc_data_structures::sync::Lrc;

// These macros all relate to the file system; they either return
// the column/row/filename of the expression, or they include
// a given file into the current one.

/// line!(): expands to the current line number
pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                   -> Box<dyn base::MacResult+'static> {
    let sp = cx.with_def_site_ctxt(sp);
    base::check_zero_tts(cx, sp, tts, "line!");

    let topmost = cx.expansion_cause().unwrap_or(sp);
    let loc = cx.source_map().lookup_char_pos(topmost.lo());

    base::MacEager::expr(cx.expr_u32(topmost, loc.line as u32))
}

/* column!(): expands to the current column number */
pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                  -> Box<dyn base::MacResult+'static> {
    let sp = cx.with_def_site_ctxt(sp);
    base::check_zero_tts(cx, sp, tts, "column!");

    let topmost = cx.expansion_cause().unwrap_or(sp);
    let loc = cx.source_map().lookup_char_pos(topmost.lo());

    base::MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1))
}

/// file!(): expands to the current filename */
/// The source_file (`loc.file`) contains a bunch more information we could spit
/// out if we wanted.
pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                   -> Box<dyn base::MacResult+'static> {
    let sp = cx.with_def_site_ctxt(sp);
    base::check_zero_tts(cx, sp, tts, "file!");

    let topmost = cx.expansion_cause().unwrap_or(sp);
    let loc = cx.source_map().lookup_char_pos(topmost.lo());
    base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&loc.file.name.to_string())))
}

pub fn expand_stringify(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                        -> Box<dyn base::MacResult+'static> {
    let sp = cx.with_def_site_ctxt(sp);
    let s = pprust::tts_to_string(tts);
    base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&s)))
}

pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                  -> Box<dyn base::MacResult+'static> {
    let sp = cx.with_def_site_ctxt(sp);
    base::check_zero_tts(cx, sp, tts, "module_path!");
    let mod_path = &cx.current_expansion.module.mod_path;
    let string = mod_path.iter().map(|x| x.to_string()).collect::<Vec<String>>().join("::");

    base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&string)))
}

/// include! : parse the given file as an expr
/// This is generally a bad idea because it's going to behave
/// unhygienically.
pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                           -> Box<dyn base::MacResult+'cx> {
    let sp = cx.with_def_site_ctxt(sp);
    let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
        Some(f) => f,
        None => return DummyResult::any(sp),
    };
    // The file will be added to the code map by the parser
    let file = match cx.resolve_path(file, sp) {
        Ok(f) => f,
        Err(mut err) => {
            err.emit();
            return DummyResult::any(sp);
        },
    };
    let directory_ownership = DirectoryOwnership::Owned { relative: None };
    let p = new_sub_parser_from_file(cx.parse_sess(), &file, directory_ownership, None, sp);

    struct ExpandResult<'a> {
        p: Parser<'a>,
    }
    impl<'a> base::MacResult for ExpandResult<'a> {
        fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
            let r = panictry!(self.p.parse_expr());
            if self.p.token != token::Eof {
                self.p.sess.buffer_lint(
                    BufferedEarlyLintId::IncompleteInclude,
                    self.p.token.span,
                    ast::CRATE_NODE_ID,
                    "include macro expected single expression in source",
                );
            }
            Some(r)
        }

        fn make_items(mut self: Box<ExpandResult<'a>>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
            let mut ret = SmallVec::new();
            while self.p.token != token::Eof {
                match panictry!(self.p.parse_item()) {
                    Some(item) => ret.push(item),
                    None => self.p.sess.span_diagnostic.span_fatal(self.p.token.span,
                                                           &format!("expected item, found `{}`",
                                                                    self.p.this_token_to_string()))
                                               .raise()
                }
            }
            Some(ret)
        }
    }

    Box::new(ExpandResult { p })
}

// include_str! : read the given file, insert it as a literal string expr
pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                          -> Box<dyn base::MacResult+'static> {
    let sp = cx.with_def_site_ctxt(sp);
    let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
        Some(f) => f,
        None => return DummyResult::any(sp)
    };
    let file = match cx.resolve_path(file, sp) {
        Ok(f) => f,
        Err(mut err) => {
            err.emit();
            return DummyResult::any(sp);
        },
    };
    match cx.source_map().load_binary_file(&file) {
        Ok(bytes) => match std::str::from_utf8(&bytes) {
            Ok(src) => {
                let interned_src = Symbol::intern(&src);
                base::MacEager::expr(cx.expr_str(sp, interned_src))
            }
            Err(_) => {
                cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display()));
                DummyResult::any(sp)
            }
        },
        Err(e) => {
            cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
            DummyResult::any(sp)
        }
    }
}

pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
                            -> Box<dyn base::MacResult+'static> {
    let sp = cx.with_def_site_ctxt(sp);
    let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") {
        Some(f) => f,
        None => return DummyResult::any(sp)
    };
    let file = match cx.resolve_path(file, sp) {
        Ok(f) => f,
        Err(mut err) => {
            err.emit();
            return DummyResult::any(sp);
        },
    };
    match cx.source_map().load_binary_file(&file) {
        Ok(bytes) => {
            base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::new(bytes))))
        },
        Err(e) => {
            cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
            DummyResult::any(sp)
        }
    }
}
<|endoftext|>


<commit_before>use super::Position;
use super::Range;
use std::str::from_utf8;

/// A UTF-8 string buffer designed to minimize reallocations,
/// maintaining performance amid frequent modifications.
pub struct GapBuffer {
    data: Vec<u8>,
    gap_start: usize,
    gap_length: usize,
}

/// Initializes a gap buffer with the specified data as its contents.
///
/// # Examples
///
/// ```
/// let buffer = scribe::buffer::gap_buffer::new("scribe".to_string());
/// assert_eq!(buffer.to_string(), "scribe");
/// ```
pub fn new(mut data: String) -> GapBuffer {
    let mut bytes = data.into_bytes();
    let capacity = bytes.capacity();
    let gap_start = bytes.len();
    let gap_length = capacity - gap_start;
    unsafe {
        bytes.set_len(capacity);
    }
    GapBuffer{ data: bytes, gap_start: gap_start, gap_length: gap_length }
}

impl GapBuffer {
    /// Inserts the specified data into the buffer at the specified position.
    /// The buffer will reallocate if there is insufficient space. If the
    /// position is out of bounds, the buffer contents will remain unchanged.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::gap_buffer::new("my buffer data".to_string());
    /// buffer.insert(" changed", &scribe::buffer::Position{ line: 0, offset: 2});
    /// assert_eq!("my changed buffer data", buffer.to_string());
    /// ```
    pub fn insert(&mut self, data: &str, position: &Position) {
        // Ensure we have the capacity to insert this data.
        if data.len() > self.gap_length {
            // TODO: Move gap to the end before resizing buffer.
            self.data.reserve(data.len());
            let capacity = self.data.capacity();
            self.gap_length = capacity - self.gap_start;
            unsafe {
                self.data.set_len(capacity);
            }
        }

        let offset = match self.find_offset(position) {
            Some(o) => o,
            None => return,
        };

        self.move_gap(offset);
        self.write_to_gap(data);
    }

    /// Returns a string representation of the buffer data (without gap).
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::gap_buffer::new("my data".to_string());
    /// assert_eq!(buffer.to_string(), "my data");
    /// ```
    pub fn to_string(&self) -> String {
        from_utf8(&self.data[..self.gap_start]).unwrap().to_string() + from_utf8(&self.data[self.gap_start+self.gap_length..]).unwrap()
    }

    /// Removes the specified range of data from the buffer.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::gap_buffer::new("my data".to_string());
    /// let range = scribe::buffer::Range{ start: scribe::buffer::Position{ line: 0, offset: 0 },
    ///   end: scribe::buffer::Position{ line: 0, offset: 3} };
    /// buffer.remove(&range);
    /// assert_eq!(buffer.to_string(), "data");
    /// ```
    pub fn remove(&mut self, range: &Range) {
        let start_offset = match self.find_offset(&range.start) {
            Some(o) => o,
            None => return,
        };
        self.move_gap(start_offset);

        let end_offset = match self.find_offset(&range.end) {
            Some(o) => o,
            None => return,
        };
        self.gap_length=end_offset-start_offset;
    }

    /// Checks whether or not the specified position is in bounds of the buffer data.
    ///
    /// # Examples
    ///
    /// ```
    /// let buffer = scribe::buffer::gap_buffer::new("scribe".to_string());
    /// let in_bounds = scribe::buffer::Position{ line: 0, offset: 0 };
    /// let out_of_bounds = scribe::buffer::Position{ line: 1, offset: 3 };
    ///
    /// assert_eq!(buffer.in_bounds(&in_bounds), true);
    /// assert_eq!(buffer.in_bounds(&out_of_bounds), false);
    /// ```
    pub fn in_bounds(&self, position: &Position) -> bool {
        self.find_offset(position) != None
    }

    // Maps a position to its offset equivalent in the data.
    fn find_offset(&self, position: &Position) -> Option<usize> {
        let first_half = from_utf8(&self.data[..self.gap_start]).unwrap();
        let mut line = 0;
        let mut line_offset = 0;

        for char_index in first_half.char_indices() {
            let (offset, character) = char_index;

            // Check to see if we've found the position yet.
            if line == position.line && line_offset == position.offset {
                return Some(offset);
            }

            // Advance the line and offset characters.
            if character == '\n' {
                line+=1;
                line_offset = 0;
            } else {
                line_offset+=1;
            }
        }

        // We didn't find the position *within* the first half, but it could
        // be right after it, which means it's right at the start of the gap.
        if line == position.line && line_offset == position.offset {
            return Some(self.gap_start);
        }

        // We haven't reached the position yet, so we'll move on to the other half.
        let second_half = from_utf8(&self.data[self.gap_start+self.gap_length..]).unwrap();
        for char_index in second_half.char_indices() {
            let (offset, character) = char_index;

            // Check to see if we've found the position yet.
            if line == position.line && line_offset == position.offset {
                return Some(self.gap_start + self.gap_length + offset);
            }

            // Advance the line and offset characters.
            if character == '\n' {
                line+=1;
                line_offset = 0;
            } else {
                line_offset+=1;
            }
        }

        // We didn't find the position *within* the second half, but it could
        // be right after it, which means it's at the end of the buffer.
        if line == position.line && line_offset == position.offset {
            return Some(self.data.len());
        }

        None
    }

    fn move_gap(&mut self, offset: usize) {
        // We don't need to move any data if the buffer is at capacity.
        if self.gap_length == 0 {
            self.gap_start = offset;
            return;
        }

        if offset < self.gap_start {
            // Shift the gap to the left one byte at a time.
            for index in (offset..self.gap_start).rev() {
                self.data[index + self.gap_length] = self.data[index];
                self.data[index] = 0;
            }

            self.gap_start = offset;
        } else if offset > self.gap_start {
            // Shift the gap to the right one byte at a time.
            for index in (self.gap_start+self.gap_length..offset) {
                self.data[index-self.gap_length] = self.data[index];
                self.data[index] = 0;
            }

            // Because the offset was after the gap, its value included the
            // gap length. We must remove it to determine the starting point.
            self.gap_start = offset - self.gap_length;
        }
    }

    fn write_to_gap(&mut self, data: &str) {
        for byte in data.bytes() {
            self.data[self.gap_start] = byte;
            self.gap_start+=1;
            self.gap_length-=1;
        }
    }
}

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

    #[test]
    fn move_gap_works() {
        let mut gb = new("This is a test.".to_string());
        gb.move_gap(0);
        assert_eq!(gb.to_string(), "This is a test.");
    }

    #[test]
    fn inserting_at_the_start_works() {
        let mut gb = new("This is a test.".to_string());
        gb.insert("Hi. ", &Position { line: 0, offset: 0 });
        assert_eq!(gb.to_string(), "Hi. This is a test.");
    }

    #[test]
    fn inserting_in_the_middle_works() {
        let mut gb = new("This is a test.\nPlease be gentle.".to_string());
        gb.insert(" very", &Position { line: 1, offset: 9 });
        assert_eq!(gb.to_string(), "This is a test.\nPlease be very gentle.");
    }

    #[test]
    fn inserting_at_the_end_works() {
        let mut gb = new("This is a test.".to_string());
        gb.insert(" Seriously.", &Position { line: 0, offset: 15 });
        assert_eq!(gb.to_string(), "This is a test. Seriously.");
    }

    #[test]
    fn inserting_in_different_spots_twice_works() {
        let mut gb = new("This is a test.".to_string());
        gb.insert("Hi. ", &Position { line: 0, offset: 0 });
        gb.insert(" Thank you.", &Position { line: 0, offset: 19 });
        assert_eq!(gb.to_string(), "Hi. This is a test. Thank you.");
    }

    #[test]
    fn inserting_at_an_invalid_position_does_nothing() {
        let mut gb = new("This is a test.".to_string());
        gb.insert(" Seriously.", &Position { line: 0, offset: 35 });
        assert_eq!(gb.to_string(), "This is a test.");
    }

    #[test]
    fn removing_works() {
        let mut gb = new("This is a test.\nSee what happens.".to_string());
        let start = Position{ line: 0, offset: 8 };
        let end = Position{ line: 1, offset: 4 };
        gb.remove(&Range{ start: start, end: end });
        assert_eq!(gb.to_string(), "This is what happens.");
    }

    #[test]
    fn inserting_then_removing_at_the_start_works() {
        let mut gb = new(String::new());
        gb.insert("This is a test.", &Position{ line: 0, offset: 0});
        let start = Position{ line: 0, offset: 0 };
        let end = Position{ line: 0, offset: 1 };
        gb.remove(&Range{ start: start, end: end });
        assert_eq!(gb.to_string(), "his is a test.");
    }
}
<commit_msg>Rename gap buffer remove to delete.<commit_after>use super::Position;
use super::Range;
use std::str::from_utf8;

/// A UTF-8 string buffer designed to minimize reallocations,
/// maintaining performance amid frequent modifications.
pub struct GapBuffer {
    data: Vec<u8>,
    gap_start: usize,
    gap_length: usize,
}

/// Initializes a gap buffer with the specified data as its contents.
///
/// # Examples
///
/// ```
/// let buffer = scribe::buffer::gap_buffer::new("scribe".to_string());
/// assert_eq!(buffer.to_string(), "scribe");
/// ```
pub fn new(mut data: String) -> GapBuffer {
    let mut bytes = data.into_bytes();
    let capacity = bytes.capacity();
    let gap_start = bytes.len();
    let gap_length = capacity - gap_start;
    unsafe {
        bytes.set_len(capacity);
    }
    GapBuffer{ data: bytes, gap_start: gap_start, gap_length: gap_length }
}

impl GapBuffer {
    /// Inserts the specified data into the buffer at the specified position.
    /// The buffer will reallocate if there is insufficient space. If the
    /// position is out of bounds, the buffer contents will remain unchanged.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::gap_buffer::new("my buffer data".to_string());
    /// buffer.insert(" changed", &scribe::buffer::Position{ line: 0, offset: 2});
    /// assert_eq!("my changed buffer data", buffer.to_string());
    /// ```
    pub fn insert(&mut self, data: &str, position: &Position) {
        // Ensure we have the capacity to insert this data.
        if data.len() > self.gap_length {
            // TODO: Move gap to the end before resizing buffer.
            self.data.reserve(data.len());
            let capacity = self.data.capacity();
            self.gap_length = capacity - self.gap_start;
            unsafe {
                self.data.set_len(capacity);
            }
        }

        let offset = match self.find_offset(position) {
            Some(o) => o,
            None => return,
        };

        self.move_gap(offset);
        self.write_to_gap(data);
    }

    /// Returns a string representation of the buffer data (without gap).
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::gap_buffer::new("my data".to_string());
    /// assert_eq!(buffer.to_string(), "my data");
    /// ```
    pub fn to_string(&self) -> String {
        from_utf8(&self.data[..self.gap_start]).unwrap().to_string() + from_utf8(&self.data[self.gap_start+self.gap_length..]).unwrap()
    }

    /// Removes the specified range of data from the buffer.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::gap_buffer::new("my data".to_string());
    /// let range = scribe::buffer::Range{ start: scribe::buffer::Position{ line: 0, offset: 0 },
    ///   end: scribe::buffer::Position{ line: 0, offset: 3} };
    /// buffer.delete(&range);
    /// assert_eq!(buffer.to_string(), "data");
    /// ```
    pub fn delete(&mut self, range: &Range) {
        let start_offset = match self.find_offset(&range.start) {
            Some(o) => o,
            None => return,
        };
        self.move_gap(start_offset);

        let end_offset = match self.find_offset(&range.end) {
            Some(o) => o,
            None => return,
        };
        self.gap_length=end_offset-start_offset;
    }

    /// Checks whether or not the specified position is in bounds of the buffer data.
    ///
    /// # Examples
    ///
    /// ```
    /// let buffer = scribe::buffer::gap_buffer::new("scribe".to_string());
    /// let in_bounds = scribe::buffer::Position{ line: 0, offset: 0 };
    /// let out_of_bounds = scribe::buffer::Position{ line: 1, offset: 3 };
    ///
    /// assert_eq!(buffer.in_bounds(&in_bounds), true);
    /// assert_eq!(buffer.in_bounds(&out_of_bounds), false);
    /// ```
    pub fn in_bounds(&self, position: &Position) -> bool {
        self.find_offset(position) != None
    }

    // Maps a position to its offset equivalent in the data.
    fn find_offset(&self, position: &Position) -> Option<usize> {
        let first_half = from_utf8(&self.data[..self.gap_start]).unwrap();
        let mut line = 0;
        let mut line_offset = 0;

        for char_index in first_half.char_indices() {
            let (offset, character) = char_index;

            // Check to see if we've found the position yet.
            if line == position.line && line_offset == position.offset {
                return Some(offset);
            }

            // Advance the line and offset characters.
            if character == '\n' {
                line+=1;
                line_offset = 0;
            } else {
                line_offset+=1;
            }
        }

        // We didn't find the position *within* the first half, but it could
        // be right after it, which means it's right at the start of the gap.
        if line == position.line && line_offset == position.offset {
            return Some(self.gap_start);
        }

        // We haven't reached the position yet, so we'll move on to the other half.
        let second_half = from_utf8(&self.data[self.gap_start+self.gap_length..]).unwrap();
        for char_index in second_half.char_indices() {
            let (offset, character) = char_index;

            // Check to see if we've found the position yet.
            if line == position.line && line_offset == position.offset {
                return Some(self.gap_start + self.gap_length + offset);
            }

            // Advance the line and offset characters.
            if character == '\n' {
                line+=1;
                line_offset = 0;
            } else {
                line_offset+=1;
            }
        }

        // We didn't find the position *within* the second half, but it could
        // be right after it, which means it's at the end of the buffer.
        if line == position.line && line_offset == position.offset {
            return Some(self.data.len());
        }

        None
    }

    fn move_gap(&mut self, offset: usize) {
        // We don't need to move any data if the buffer is at capacity.
        if self.gap_length == 0 {
            self.gap_start = offset;
            return;
        }

        if offset < self.gap_start {
            // Shift the gap to the left one byte at a time.
            for index in (offset..self.gap_start).rev() {
                self.data[index + self.gap_length] = self.data[index];
                self.data[index] = 0;
            }

            self.gap_start = offset;
        } else if offset > self.gap_start {
            // Shift the gap to the right one byte at a time.
            for index in (self.gap_start+self.gap_length..offset) {
                self.data[index-self.gap_length] = self.data[index];
                self.data[index] = 0;
            }

            // Because the offset was after the gap, its value included the
            // gap length. We must remove it to determine the starting point.
            self.gap_start = offset - self.gap_length;
        }
    }

    fn write_to_gap(&mut self, data: &str) {
        for byte in data.bytes() {
            self.data[self.gap_start] = byte;
            self.gap_start+=1;
            self.gap_length-=1;
        }
    }
}

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

    #[test]
    fn move_gap_works() {
        let mut gb = new("This is a test.".to_string());
        gb.move_gap(0);
        assert_eq!(gb.to_string(), "This is a test.");
    }

    #[test]
    fn inserting_at_the_start_works() {
        let mut gb = new("This is a test.".to_string());
        gb.insert("Hi. ", &Position { line: 0, offset: 0 });
        assert_eq!(gb.to_string(), "Hi. This is a test.");
    }

    #[test]
    fn inserting_in_the_middle_works() {
        let mut gb = new("This is a test.\nPlease be gentle.".to_string());
        gb.insert(" very", &Position { line: 1, offset: 9 });
        assert_eq!(gb.to_string(), "This is a test.\nPlease be very gentle.");
    }

    #[test]
    fn inserting_at_the_end_works() {
        let mut gb = new("This is a test.".to_string());
        gb.insert(" Seriously.", &Position { line: 0, offset: 15 });
        assert_eq!(gb.to_string(), "This is a test. Seriously.");
    }

    #[test]
    fn inserting_in_different_spots_twice_works() {
        let mut gb = new("This is a test.".to_string());
        gb.insert("Hi. ", &Position { line: 0, offset: 0 });
        gb.insert(" Thank you.", &Position { line: 0, offset: 19 });
        assert_eq!(gb.to_string(), "Hi. This is a test. Thank you.");
    }

    #[test]
    fn inserting_at_an_invalid_position_does_nothing() {
        let mut gb = new("This is a test.".to_string());
        gb.insert(" Seriously.", &Position { line: 0, offset: 35 });
        assert_eq!(gb.to_string(), "This is a test.");
    }

    #[test]
    fn deleting_works() {
        let mut gb = new("This is a test.\nSee what happens.".to_string());
        let start = Position{ line: 0, offset: 8 };
        let end = Position{ line: 1, offset: 4 };
        gb.delete(&Range{ start: start, end: end });
        assert_eq!(gb.to_string(), "This is what happens.");
    }

    #[test]
    fn inserting_then_deleting_at_the_start_works() {
        let mut gb = new(String::new());
        gb.insert("This is a test.", &Position{ line: 0, offset: 0});
        let start = Position{ line: 0, offset: 0 };
        let end = Position{ line: 0, offset: 1 };
        gb.delete(&Range{ start: start, end: end });
        assert_eq!(gb.to_string(), "his is a test.");
    }
}
<|endoftext|>


<commit_before>use sdl2::rect::Rect as SdlRect;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Rectangle {
    pub x: f64,
    pub y: f64,
    pub w: f64,
    pub h: f64,
}

impl Rectangle {
    /// Generates an SDL-compatible Rect equivalent to `self`.
    /// Panics if it could not be created, for example if a
    /// coordinate of a corner overflows an `i32`.
    pub fn to_sdl(self) -> Option<SdlRect> {
        // Reject negative width and height
        assert!(self.w >= 0.0 && self.h >= 0.0);

        // SdlRect::new : `(i32, i32, u32, u32) -> Result<Option<SdlRect>>`
        SdlRect::new(self.x as i32, self.y as i32, self.w as u32, self.h as u32)
            .unwrap()
    }

    /// Returns a (perhaps moved) rectangle which is contained by a `parent`
    /// rectangle. If it can indeed be moved to fit, return `Some(result)`;
    /// otherwise, return `None`.
    pub fn move_inside(self, parent: Rectangle) -> Option<Rectangle> {
        // It must be smaller than the parent rectangle to fit in it.
        if self.w > parent.w || self.h > parent.h {
            return None;
        }

        Some(Rectangle {
            w: self.w,
            h: self.h,
            x: if self.x < parent.x { parent.x }
               else if self.x + self.w >= parent.x + parent.w { parent.x + parent.w - self.w }
               else { self.x },
           y: if self.y < parent.y { parent.y }
               else if self.y + self.h >= parent.y + parent.h { parent.y + parent.h - self.h }
               else { self.y }
        })
    }

    pub fn contains(&self, other: Rectangle) -> bool {
        let x_min = other.x;
        let x_max = other.x + other.w;
        let y_min = other.y;
        let y_max = other.y + other.h;

        x_min >= self.x && x_min <= self.x + self.w &&
        x_max >= self.x && x_max <= self.x + self.w &&
        y_min >= self.y && y_min <= self.y + self.h &&
        y_max >= self.y && y_max <= self.y + self.h
    }

    pub fn overlaps(&self, other: Rectangle) -> bool {
        self.x < other.x + other.w &&
        other.x < self.x + self.w &&
        self.y < other.y + other.h &&
        other.y < self.y + self.h
    }
}
<commit_msg>Added Rectangle testing<commit_after>use sdl2::rect::Rect as SdlRect;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Rectangle {
    pub x: f64,
    pub y: f64,
    pub w: f64,
    pub h: f64,
}

impl Rectangle {
    /// Generates an SDL-compatible Rect equivalent to `self`.
    /// Panics if it could not be created, for example if a
    /// coordinate of a corner overflows an `i32`.
    pub fn to_sdl(self) -> Option<SdlRect> {
        // Reject negative width and height
        assert!(self.w >= 0.0 && self.h >= 0.0);

        // SdlRect::new : `(i32, i32, u32, u32) -> Result<Option<SdlRect>>`
        SdlRect::new(self.x as i32, self.y as i32, self.w as u32, self.h as u32)
            .unwrap()
    }

    /// Returns a (perhaps moved) rectangle which is contained by a `parent`
    /// rectangle. If it can indeed be moved to fit, return `Some(result)`;
    /// otherwise, return `None`.
    pub fn move_inside(self, parent: Rectangle) -> Option<Rectangle> {
        // It must be smaller than the parent rectangle to fit in it.
        if self.w > parent.w || self.h > parent.h {
            return None;
        }

        Some(Rectangle {
            w: self.w,
            h: self.h,
            x: if self.x < parent.x { parent.x }
               else if self.x + self.w >= parent.x + parent.w { parent.x + parent.w - self.w }
               else { self.x },
           y: if self.y < parent.y { parent.y }
               else if self.y + self.h >= parent.y + parent.h { parent.y + parent.h - self.h }
               else { self.y }
        })
    }

    pub fn contains(&self, other: Rectangle) -> bool {
        let x_min = other.x;
        let x_max = other.x + other.w;
        let y_min = other.y;
        let y_max = other.y + other.h;

        x_min >= self.x && x_min <= self.x + self.w &&
        x_max >= self.x && x_max <= self.x + self.w &&
        y_min >= self.y && y_min <= self.y + self.h &&
        y_max >= self.y && y_max <= self.y + self.h
    }

    pub fn overlaps(&self, other: Rectangle) -> bool {
        self.x < other.x + other.w &&
        other.x < self.x + self.w &&
        self.y < other.y + other.h &&
        other.y < self.y + self.h
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn rect_basics() {
        use phi::data::Rectangle;

        let bounding_rect = Rectangle {
            x: 1.0,
            y: 1.0,
            w: 1.0,
            h: 1.0
        };

        // Outside rectangles
        let outside_rect = Rectangle { x: 0.0, .. bounding_rect };
        assert!(!bounding_rect.contains(outside_rect));
        assert!(!bounding_rect.overlaps(outside_rect));

        let outside_rect = Rectangle { y: 0.0, .. bounding_rect };
        assert!(!bounding_rect.contains(outside_rect));
        assert!(!bounding_rect.overlaps(outside_rect));

        let outside_rect = Rectangle { x: 2.0, .. bounding_rect };
        assert!(!bounding_rect.contains(outside_rect));
        assert!(!bounding_rect.overlaps(outside_rect));

        let outside_rect = Rectangle { y: 2.0, .. bounding_rect };
        assert!(!bounding_rect.contains(outside_rect));
        assert!(!bounding_rect.overlaps(outside_rect));

        // Overlapping rectangles
        let overlap_rect = Rectangle { x: 0.5, y: 0.5, .. bounding_rect };
        assert!(!bounding_rect.contains(overlap_rect));
        assert!(bounding_rect.overlaps(overlap_rect));

        let overlap_rect = Rectangle { x: 1.5, y: 0.5, .. bounding_rect };
        assert!(!bounding_rect.contains(overlap_rect));
        assert!(bounding_rect.overlaps(overlap_rect));

        let overlap_rect = Rectangle { x: 0.5, y: 1.5, .. bounding_rect };
        assert!(!bounding_rect.contains(overlap_rect));
        assert!(bounding_rect.overlaps(overlap_rect));

        let overlap_rect = Rectangle { x: 1.5, y: 1.5, .. bounding_rect };
        assert!(!bounding_rect.contains(overlap_rect));
        assert!(bounding_rect.overlaps(overlap_rect));

        // Inside rectangles

        let inside_rect = Rectangle { x: 1.5, y: 1.5, w: 0.5, h: 0.5 };
        assert!(bounding_rect.contains(inside_rect));
        assert!(bounding_rect.overlaps(inside_rect));
    }
}
<|endoftext|>


<commit_before>use std::ffi::OsStr;
use std::fs;
use std::path;

use cobalt_config::DateTime;
use failure::ResultExt;
use liquid;
use log::debug;
use serde::{Deserialize, Serialize};
use serde_json;
use serde_yaml;
use toml;

use super::files;

#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields, default)]
pub struct Site {
    pub title: Option<kstring::KString>,
    pub description: Option<kstring::KString>,
    pub base_url: Option<kstring::KString>,
    pub sitemap: Option<cobalt_config::RelPath>,
    pub data: Option<liquid::Object>,
    pub data_dir: &'static str,
    /// The time at which the `cobalt` binary built the site
    pub time: DateTime,
}

impl Site {
    pub fn from_config(config: cobalt_config::Site) -> Self {
        let cobalt_config::Site {
            title,
            description,
            base_url,
            sitemap,
            data,
            data_dir,
        } = config;

        let base_url = base_url.map(|mut l| {
            if l.ends_with('/') {
                let mut other = String::from(l.as_str());
                other.pop();
                l = kstring::KString::from_string(other);
            }
            l
        });

        Self {
            title,
            description,
            base_url,
            sitemap,
            data,
            data_dir,
            time: DateTime::now(),
        }
    }

    pub fn load(&self, source: &std::path::Path) -> Result<liquid::Object> {
        let mut attributes = liquid::Object::new();
        if let Some(title) = self.title.as_ref() {
            attributes.insert(
                "title".into(),
                liquid::model::Value::scalar(kstring::KString::from_ref(title)),
            );
        }
        if let Some(description) = self.description.as_ref() {
            attributes.insert(
                "description".into(),
                liquid::model::Value::scalar(kstring::KString::from_ref(description)),
            );
        }
        if let Some(base_url) = self.base_url.as_ref() {
            attributes.insert(
                "base_url".into(),
                liquid::model::Value::scalar(kstring::KString::from_ref(base_url)),
            );
        }
        attributes.insert("time".into(), liquid::model::Value::scalar(self.time));

        let mut data = self.data.clone().unwrap_or_default();
        let data_path = source.join(&self.data_dir);
        insert_data_dir(&mut data, &data_path)?;
        if !data.is_empty() {
            attributes.insert("data".into(), liquid::model::Value::Object(data));
        }

        Ok(attributes)
    }
}

fn deep_insert(
    data_map: &mut liquid::Object,
    file_path: &path::Path,
    target_key: String,
    data: liquid::model::Value,
) -> Result<()> {
    // now find the nested map it is supposed to be in
    let target_map = if let Some(path) = file_path.parent() {
        let mut map = data_map;
        for part in path.iter() {
            let key = part.to_str().ok_or_else(|| {
                failure::format_err!(
                    "The data from {:?} can't be loaded as it contains non utf-8 characters",
                    path
                )
            })?;
            let cur_map = map;
            let key = kstring::KString::from_ref(key);
            map = cur_map
                .entry(key)
                .or_insert_with(|| liquid::model::Value::Object(liquid::Object::new()))
                .as_object_mut()
                .ok_or_else(|| {
                    failure::format_err!(
                        "Aborting: Duplicate in data tree. Would overwrite {:?} ",
                        path
                    )
                })?;
        }
        map
    } else {
        data_map
    };

    match target_map.insert(target_key.into(), data) {
        None => Ok(()),
        _ => Err(failure::format_err!(
            "The data from {:?} can't be loaded: the key already exists",
            file_path
        )),
    }
}

fn load_data(data_path: &path::Path) -> Result<liquid::model::Value> {
    let ext = data_path.extension().unwrap_or_else(|| OsStr::new(""));

    let data: liquid::model::Value;

    if ext == OsStr::new("yml") || ext == OsStr::new("yaml") {
        let reader = fs::File::open(data_path)?;
        data = serde_yaml::from_reader(reader)?;
    } else if ext == OsStr::new("json") {
        let reader = fs::File::open(data_path)?;
        data = serde_json::from_reader(reader)?;
    } else if ext == OsStr::new("toml") {
        let text = files::read_file(data_path)?;
        data = toml::from_str(&text)?;
    } else {
        failure::bail!(
            "Failed to load of data {:?}: unknown file type '{:?}'.\n\
             Supported data files extensions are: yml, yaml, json and toml.",
            data_path,
            ext
        );
    }

    Ok(data)
}

fn insert_data_dir(data: &mut liquid::Object, data_root: &path::Path) -> Result<()> {
    debug!("Loading data from {:?}", data_root);

    let data_files_builder = files::FilesBuilder::new(data_root)?;
    let data_files = data_files_builder.build()?;
    for full_path in data_files.files() {
        let rel_path = full_path
            .strip_prefix(data_root)
            .expect("file was found under the root");

        let file_stem = full_path
            .file_stem()
            .expect("Files will always return with a stem");
        let file_stem = String::from(file_stem.to_str().unwrap());
        let data_fragment = load_data(&full_path)
            .with_context(|_| format!("Loading data from {:?} failed", full_path))?;

        deep_insert(data, rel_path, file_stem, data_fragment)
            .with_context(|_| format!("Merging data into {:?} failed", rel_path))?;
    }

    Ok(())
}
<commit_msg>fix: merge arised issue<commit_after>use std::ffi::OsStr;
use std::fs;
use std::path;

use cobalt_config::DateTime;
use failure::ResultExt;
use liquid;
use log::debug;
use serde::{Deserialize, Serialize};
use serde_json;
use serde_yaml;
use toml;

use crate::error::*;

use super::files;

#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields, default)]
pub struct Site {
    pub title: Option<kstring::KString>,
    pub description: Option<kstring::KString>,
    pub base_url: Option<kstring::KString>,
    pub sitemap: Option<cobalt_config::RelPath>,
    pub data: Option<liquid::Object>,
    pub data_dir: &'static str,
    /// The time at which the `cobalt` binary built the site
    pub time: DateTime,
}

impl Site {
    pub fn from_config(config: cobalt_config::Site) -> Self {
        let cobalt_config::Site {
            title,
            description,
            base_url,
            sitemap,
            data,
            data_dir,
        } = config;

        let base_url = base_url.map(|mut l| {
            if l.ends_with('/') {
                let mut other = String::from(l.as_str());
                other.pop();
                l = kstring::KString::from_string(other);
            }
            l
        });

        Self {
            title,
            description,
            base_url,
            sitemap,
            data,
            data_dir,
            time: DateTime::now(),
        }
    }

    pub fn load(&self, source: &std::path::Path) -> Result<liquid::Object> {
        let mut attributes = liquid::Object::new();
        if let Some(title) = self.title.as_ref() {
            attributes.insert(
                "title".into(),
                liquid::model::Value::scalar(kstring::KString::from_ref(title)),
            );
        }
        if let Some(description) = self.description.as_ref() {
            attributes.insert(
                "description".into(),
                liquid::model::Value::scalar(kstring::KString::from_ref(description)),
            );
        }
        if let Some(base_url) = self.base_url.as_ref() {
            attributes.insert(
                "base_url".into(),
                liquid::model::Value::scalar(kstring::KString::from_ref(base_url)),
            );
        }
        attributes.insert("time".into(), liquid::model::Value::scalar(self.time));

        let mut data = self.data.clone().unwrap_or_default();
        let data_path = source.join(&self.data_dir);
        insert_data_dir(&mut data, &data_path)?;
        if !data.is_empty() {
            attributes.insert("data".into(), liquid::model::Value::Object(data));
        }

        Ok(attributes)
    }
}

fn deep_insert(
    data_map: &mut liquid::Object,
    file_path: &path::Path,
    target_key: String,
    data: liquid::model::Value,
) -> Result<()> {
    // now find the nested map it is supposed to be in
    let target_map = if let Some(path) = file_path.parent() {
        let mut map = data_map;
        for part in path.iter() {
            let key = part.to_str().ok_or_else(|| {
                failure::format_err!(
                    "The data from {:?} can't be loaded as it contains non utf-8 characters",
                    path
                )
            })?;
            let cur_map = map;
            let key = kstring::KString::from_ref(key);
            map = cur_map
                .entry(key)
                .or_insert_with(|| liquid::model::Value::Object(liquid::Object::new()))
                .as_object_mut()
                .ok_or_else(|| {
                    failure::format_err!(
                        "Aborting: Duplicate in data tree. Would overwrite {:?} ",
                        path
                    )
                })?;
        }
        map
    } else {
        data_map
    };

    match target_map.insert(target_key.into(), data) {
        None => Ok(()),
        _ => Err(failure::format_err!(
            "The data from {:?} can't be loaded: the key already exists",
            file_path
        )),
    }
}

fn load_data(data_path: &path::Path) -> Result<liquid::model::Value> {
    let ext = data_path.extension().unwrap_or_else(|| OsStr::new(""));

    let data: liquid::model::Value;

    if ext == OsStr::new("yml") || ext == OsStr::new("yaml") {
        let reader = fs::File::open(data_path)?;
        data = serde_yaml::from_reader(reader)?;
    } else if ext == OsStr::new("json") {
        let reader = fs::File::open(data_path)?;
        data = serde_json::from_reader(reader)?;
    } else if ext == OsStr::new("toml") {
        let text = files::read_file(data_path)?;
        data = toml::from_str(&text)?;
    } else {
        failure::bail!(
            "Failed to load of data {:?}: unknown file type '{:?}'.\n\
             Supported data files extensions are: yml, yaml, json and toml.",
            data_path,
            ext
        );
    }

    Ok(data)
}

fn insert_data_dir(data: &mut liquid::Object, data_root: &path::Path) -> Result<()> {
    debug!("Loading data from {:?}", data_root);

    let data_files_builder = files::FilesBuilder::new(data_root)?;
    let data_files = data_files_builder.build()?;
    for full_path in data_files.files() {
        let rel_path = full_path
            .strip_prefix(data_root)
            .expect("file was found under the root");

        let file_stem = full_path
            .file_stem()
            .expect("Files will always return with a stem");
        let file_stem = String::from(file_stem.to_str().unwrap());
        let data_fragment = load_data(&full_path)
            .with_context(|_| format!("Loading data from {:?} failed", full_path))?;

        deep_insert(data, rel_path, file_stem, data_fragment)
            .with_context(|_| format!("Merging data into {:?} failed", rel_path))?;
    }

    Ok(())
}
<|endoftext|>


<commit_before>use super::NoticeTrace;
use crate::backtrace::Backtrace;
use std::error::Error;
use std::panic::PanicInfo;

#[derive(Default, Clone)]
pub struct NoticeErrorBuilder {
    pub name: String,
    pub message: Option<String>,
    pub backtrace: Option<NoticeTrace>,
}

impl NoticeErrorBuilder {
    pub fn new(name: &str) -> NoticeErrorBuilder {
        NoticeErrorBuilder {
            name: name.to_string(),
            message: None,
            backtrace: None,
        }
    }

    pub fn message(&mut self, message: &str) -> &mut NoticeErrorBuilder {
        self.message = Some(message.to_string());
        self
    }

    // TODO: Maybe this should be renamed to `trace` and the `raw_backtrace` renamed to `backetrace`?
    pub fn backtrace(&mut self, backtrace: NoticeTrace) -> &mut NoticeErrorBuilder {
        self.backtrace = Some(backtrace);
        self
    }

    pub fn raw_backtrace(&mut self, backtrace: &Backtrace) -> &mut NoticeErrorBuilder {
        self.backtrace = Some(NoticeTrace::from(backtrace));
        self
    }

    pub fn build(&self) -> NoticeError {
        NoticeError::new(&self.name, self.message.clone(), self.backtrace.clone())
    }
}

#[derive(Debug, Clone, Serialize)]
pub struct NoticeError {
    #[serde(rename = "type")]
    pub name: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub message: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub backtrace: Option<NoticeTrace>,
}

impl NoticeError {
    pub fn new(name: &str, message: Option<String>, backtrace: Option<NoticeTrace>) -> NoticeError {
        NoticeError {
            name: name.to_string(),
            message,
            backtrace,
        }
    }

    pub fn builder(name: &str) -> NoticeErrorBuilder {
        NoticeErrorBuilder::new(name)
    }

    pub fn from_panic_backtrace(panic_info: &PanicInfo, backtrace: &Backtrace) -> NoticeError {
        // TODO: PanicInfo has a `message()` on nightly which might be easier to work with
        // here, but for now we'll just deal with `payload()`
        let message: String = panic_info
            .payload()
            .downcast_ref::<String>()
            .map(|s| s.to_string())
            .or_else(|| Some("None".to_string()))
            .unwrap();
        NoticeError::builder("panic")
            .message(&message)
            .raw_backtrace(&backtrace)
            .build()
    }
}

impl<'a, E: Error> From<E> for NoticeError {
    fn from(error: E) -> NoticeError {
        let name = format!("{:?}", error)
            .split_whitespace()
            .next()
            .unwrap()
            .to_string();
        let message = Some(format!("{}", error));
        let backtrace = None;

        NoticeError::new(&name, message, backtrace)
    }
}
<commit_msg>Removed default message in errors from PanicInfo<commit_after>use super::NoticeTrace;
use crate::backtrace::Backtrace;
use std::error::Error;
use std::panic::PanicInfo;

#[derive(Default, Clone)]
pub struct NoticeErrorBuilder {
    pub name: String,
    pub message: Option<String>,
    pub backtrace: Option<NoticeTrace>,
}

impl NoticeErrorBuilder {
    pub fn new(name: &str) -> NoticeErrorBuilder {
        NoticeErrorBuilder {
            name: name.to_string(),
            message: None,
            backtrace: None,
        }
    }

    pub fn message(&mut self, message: &str) -> &mut NoticeErrorBuilder {
        self.message = Some(message.to_string());
        self
    }

    // TODO: Maybe this should be renamed to `trace` and the `raw_backtrace` renamed to `backetrace`?
    pub fn backtrace(&mut self, backtrace: NoticeTrace) -> &mut NoticeErrorBuilder {
        self.backtrace = Some(backtrace);
        self
    }

    pub fn raw_backtrace(&mut self, backtrace: &Backtrace) -> &mut NoticeErrorBuilder {
        self.backtrace = Some(NoticeTrace::from(backtrace));
        self
    }

    pub fn build(&self) -> NoticeError {
        NoticeError::new(&self.name, self.message.clone(), self.backtrace.clone())
    }
}

#[derive(Debug, Clone, Serialize)]
pub struct NoticeError {
    #[serde(rename = "type")]
    pub name: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub message: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub backtrace: Option<NoticeTrace>,
}

impl NoticeError {
    pub fn new(name: &str, message: Option<String>, backtrace: Option<NoticeTrace>) -> NoticeError {
        NoticeError {
            name: name.to_string(),
            message,
            backtrace,
        }
    }

    pub fn builder(name: &str) -> NoticeErrorBuilder {
        NoticeErrorBuilder::new(name)
    }

    pub fn from_panic_backtrace(panic_info: &PanicInfo, backtrace: &Backtrace) -> NoticeError {
        // TODO: PanicInfo has a `message()` on nightly which might be easier to work with
        // here, but for now we'll just deal with `payload()`
        let message: Option<&str> = panic_info.payload().downcast_ref::<&str>().map(|s| *s);
        let mut builder = NoticeError::builder("panic");
        builder.raw_backtrace(&backtrace);
        if message.is_some() {
            builder.message(message.unwrap());
        }
        builder.build()
    }
}

impl<'a, E: Error> From<E> for NoticeError {
    fn from(error: E) -> NoticeError {
        let name = format!("{:?}", error)
            .split_whitespace()
            .next()
            .unwrap()
            .to_string();
        let message = Some(format!("{}", error));
        let backtrace = None;

        NoticeError::new(&name, message, backtrace)
    }
}
<|endoftext|>


<commit_before>#[crate_type = "rlib"];

extern mod extra;

use std::util;
use extra::bigint::BigUint;

pub static EXPECTED_ANSWER: &'static str = "153";

// a[0] = 1 + 1/2
// a[1] = 1 + 1/(2 + 1/2)
//      = 1 + 1/(1 + a[0]) =
// a[2] = 1 + 1/(2 + 1/(2 + 1/2))
//      = 1 + 1/(1 + a[1])
// a[i+1] = n[i+1] / d[i+1]
//        = 1 + 1 / (1 + n[i]/d[i])
//        = 1 + d[i] / (d[i] + n[i])
//        = (2d[i] + n[i]) / (d[i] + n[i])
//  n[0] = 3, d[0] = 2
//  n[i+1] = 2d[i] + n[i]
//  d[i+1] = d[i] + n[i]
struct Frac { nd: (BigUint, BigUint) }

impl Frac {
    fn new() -> Frac {
        Frac { nd: (FromPrimitive::from_uint(3).unwrap(), FromPrimitive::from_uint(2).unwrap()) }
    }
}

impl Iterator<(BigUint, BigUint)> for Frac {
    #[inline]
    fn next(&mut self) -> Option<(BigUint, BigUint)> {
        let next = {
            let (ref n, ref d) = self.nd;
            (((*d) << 1) + (*n), (*n) + (*d))
        };
        Some(util::replace(&mut self.nd, next))
    }
}

pub fn solve() -> ~str {
    Frac::new().take(1000)
        .map(|(n, d)| (n.to_str().len(), d.to_str().len()))
        .count(|(n_len, d_len)| n_len > d_len)
        .to_str()
}
<commit_msg>ユニットテストを追加<commit_after>#[crate_type = "rlib"];

extern mod extra;

use std::util;
use extra::bigint::BigUint;

pub static EXPECTED_ANSWER: &'static str = "153";

// a[0] = 1 + 1/2
// a[1] = 1 + 1/(2 + 1/2)
//      = 1 + 1/(1 + a[0]) =
// a[2] = 1 + 1/(2 + 1/(2 + 1/2))
//      = 1 + 1/(1 + a[1])
// a[i+1] = n[i+1] / d[i+1]
//        = 1 + 1 / (1 + n[i]/d[i])
//        = 1 + d[i] / (d[i] + n[i])
//        = (2d[i] + n[i]) / (d[i] + n[i])
//  n[0] = 3, d[0] = 2
//  n[i+1] = 2d[i] + n[i]
//  d[i+1] = d[i] + n[i]
struct Frac { nd: (BigUint, BigUint) }

impl Frac {
    fn new() -> Frac {
        Frac { nd: (FromPrimitive::from_uint(3).unwrap(), FromPrimitive::from_uint(2).unwrap()) }
    }
}

impl Iterator<(BigUint, BigUint)> for Frac {
    #[inline]
    fn next(&mut self) -> Option<(BigUint, BigUint)> {
        let next = {
            let (ref n, ref d) = self.nd;
            (((*d) << 1) + (*n), (*n) + (*d))
        };
        Some(util::replace(&mut self.nd, next))
    }
}

pub fn solve() -> ~str {
    Frac::new()
        .take(1000)
        .count(|(n, d)| n.to_str().len() > d.to_str().len())
        .to_str()
}

#[cfg(test)]
mod test {
    use extra::bigint::BigUint;
    use super::Frac;

    #[test]
    fn frac() {
        fn gen(n: uint, d: uint) -> (BigUint, BigUint) {
            (FromPrimitive::from_uint(n).unwrap(),
             FromPrimitive::from_uint(d).unwrap())
        }
        let mut it = Frac::new();
        assert_eq!(Some(gen(3, 2)), it.next());
        assert_eq!(Some(gen(7, 5)), it.next());
        assert_eq!(Some(gen(17, 12)), it.next());
        assert_eq!(Some(gen(41, 29)), it.next());
        assert_eq!(Some(gen(99, 70)), it.next());
        assert_eq!(Some(gen(239, 169)), it.next());
        assert_eq!(Some(gen(577, 408)), it.next());
        assert_eq!(Some(gen(1393, 985)), it.next());
    }
}
<|endoftext|>