<commit_before>use dbus::Connection as DBusConnection;
use dbus::{BusType, Path, ConnPath, Message};
use dbus::arg::{Variant, Iter, Array, Get, RefArg};
use dbus::stdintf::OrgFreedesktopDBusProperties;
use dbus::Error;

pub const DEFAULT_TIMEOUT: u64 = 10;
pub const RETRIES_ALLOWED: usize = 10;

pub struct DBusApi {
    connection: DBusConnection,
    method_timeout: u64,
    base: &'static str,
    method_retry_error_names: &'static [&'static str],
}

impl DBusApi {
    pub fn new(base: &'static str, method_retry_error_names: &'static [&'static str]) -> Self {
        let connection = DBusConnection::get_private(BusType::System).unwrap();

        DBusApi {
            connection: connection,
            method_timeout: DEFAULT_TIMEOUT,
            base: base,
            method_retry_error_names: method_retry_error_names,
        }
    }

    pub fn method_timeout(&self) -> u64 {
        self.method_timeout
    }

    pub fn set_method_timeout(&mut self, timeout: u64) {
        self.method_timeout = timeout;
    }

    pub fn call(&self, path: &str, interface: &str, method: &str) -> Result<Message, String> {
        self.call_with_args(path, interface, method, &[])
    }

    pub fn call_with_args(&self,
                          path: &str,
                          interface: &str,
                          method: &str,
                          args: &[&RefArg])
                          -> Result<Message, String> {
        self.call_with_args_retry(path, interface, method, args)
            .map_err(|error| {
                         format!("D-Bus '{}'::'{}' method call failed on '{}': {}",
                                 interface,
                                 method,
                                 path,
                                 error)
                     })
    }

    fn call_with_args_retry(&self,
                            path: &str,
                            interface: &str,
                            method: &str,
                            args: &[&RefArg])
                            -> Result<Message, String> {
        let mut retries = 0;

        loop {
            if let Some(result) = self.create_and_send_message(path, interface, method, args) {
                return result;
            }

            retries += 1;

            if retries == RETRIES_ALLOWED {
                return Err(format!("method failed after {} retries", RETRIES_ALLOWED));
            }

            ::std::thread::sleep(::std::time::Duration::from_secs(1));
        }
    }

    fn create_and_send_message(&self,
                               path: &str,
                               interface: &str,
                               method: &str,
                               args: &[&RefArg])
                               -> Option<Result<Message, String>> {
        match Message::new_method_call(self.base, path, interface, method) {
            Ok(mut message) => {
                if args.len() > 0 {
                    message = message.append_ref(args);
                }

                self.send_message_checked(message)
            }
            Err(details) => Some(Err(details)),
        }
    }

    fn send_message_checked(&self, message: Message) -> Option<Result<Message, String>> {
        match self.connection
                  .send_with_reply_and_block(message, self.method_timeout as i32 * 1000) {
            Ok(response) => Some(Ok(response)),
            Err(err) => {
                let message = get_error_message(&err).to_string();

                let name = err.name();
                for error_name in self.method_retry_error_names {
                    if name == Some(error_name) {
                        return None;
                    }
                }

                Some(Err(message))
            }
        }
    }

    pub fn property<T>(&self, path: &str, interface: &str, name: &str) -> Result<T, String>
        where DBusApi: VariantTo<T>
    {
        let property_error = |details: &str| {
            Err(format!("D-Bus get '{}'::'{}' property failed on '{}': {}",
                        interface,
                        name,
                        path,
                        details))
        };

        let path = self.with_path(path);

        match path.get(interface, name) {
            Ok(variant) => {
                match DBusApi::variant_to(variant) {
                    Some(data) => Ok(data),
                    None => property_error("wrong property type"),
                }
            }
            Err(err) => {
                match err.message() {
                    Some(details) => property_error(details),
                    None => property_error("no details"),
                }
            }
        }
    }

    pub fn extract<'a, T>(&self, response: &'a Message) -> Result<T, String>
        where T: Get<'a>
    {
        response
            .get1()
            .ok_or("D-Bus wrong response type".to_string())
    }

    pub fn extract_two<'a, T1, T2>(&self, response: &'a Message) -> Result<(T1, T2), String>
        where T1: Get<'a>,
              T2: Get<'a>
    {
        let (first, second) = response.get2();

        if let Some(first) = first {
            if let Some(second) = second {
                return Ok((first, second));
            }
        }

        Err("D-Bus wrong response type".to_string())
    }

    fn with_path<'a, P: Into<Path<'a>>>(&'a self, path: P) -> ConnPath<'a, &'a DBusConnection> {
        self.connection
            .with_path(self.base, path, self.method_timeout as i32 * 1000)
    }
}

pub trait VariantTo<T> {
    fn variant_to(value: Variant<Box<RefArg>>) -> Option<T>;
}

impl VariantTo<String> for DBusApi {
    fn variant_to(value: Variant<Box<RefArg>>) -> Option<String> {
        variant_to_string(value)
    }
}

impl VariantTo<i64> for DBusApi {
    fn variant_to(value: Variant<Box<RefArg>>) -> Option<i64> {
        variant_to_i64(value)
    }
}

impl VariantTo<u32> for DBusApi {
    fn variant_to(value: Variant<Box<RefArg>>) -> Option<u32> {
        variant_to_u32(value)
    }
}

impl VariantTo<bool> for DBusApi {
    fn variant_to(value: Variant<Box<RefArg>>) -> Option<bool> {
        variant_to_bool(value)
    }
}

impl VariantTo<Vec<String>> for DBusApi {
    fn variant_to(value: Variant<Box<RefArg>>) -> Option<Vec<String>> {
        variant_to_string_vec(value)
    }
}

impl VariantTo<Vec<u8>> for DBusApi {
    fn variant_to(value: Variant<Box<RefArg>>) -> Option<Vec<u8>> {
        variant_to_u8_vec(value)
    }
}

fn variant_to_string_vec(value: Variant<Box<RefArg>>) -> Option<Vec<String>> {
    let mut result = Vec::new();

    if let Some(list) = value.0.as_iter() {
        for element in list {
            if let Some(string) = element.as_str() {
                result.push(string.to_string());
            } else {
                return None;
            }
        }

        Some(result)
    } else {
        None
    }
}

fn variant_to_u8_vec(value: Variant<Box<RefArg>>) -> Option<Vec<u8>> {
    let mut result = Vec::new();

    if let Some(list) = value.0.as_iter() {
        for element in list {
            if let Some(value) = element.as_i64() {
                result.push(value as u8);
            } else {
                return None;
            }
        }

        Some(result)
    } else {
        None
    }
}

fn variant_to_string(value: Variant<Box<RefArg>>) -> Option<String> {
    value.0.as_str().and_then(|v| Some(v.to_string()))
}

fn variant_to_i64(value: Variant<Box<RefArg>>) -> Option<i64> {
    value.0.as_i64()
}

fn variant_to_u32(value: Variant<Box<RefArg>>) -> Option<u32> {
    value.0.as_i64().and_then(|v| Some(v as u32))
}

fn variant_to_bool(value: Variant<Box<RefArg>>) -> Option<bool> {
    value.0.as_i64().and_then(|v| Some(v == 0))
}

pub fn extract<'a, T>(var: &'a Variant<Iter>) -> Result<T, String>
    where T: Get<'a>
{
    var.0
        .clone()
        .get::<T>()
        .ok_or(format!("D-Bus variant type does not match: {:?}", var))
}

pub fn utf8_vec_u8_to_string(var: Vec<u8>) -> Result<String, String> {
    String::from_utf8(var).or(Err(format!("D-Bus variant not a UTF-8 string")))
}

pub fn utf8_variant_to_string(var: &Variant<Iter>) -> Result<String, String> {
    let array_option = &var.0.clone().get::<Array<u8, _>>();

    if let Some(array) = *array_option {
        utf8_vec_u8_to_string(array.collect())
    } else {
        Err(format!("D-Bus variant not an array: {:?}", var))
    }
}

pub fn string_to_utf8_vec_u8(var: &String) -> Vec<u8> {
    var.as_bytes().to_vec()
}

pub fn path_to_string(path: &Path) -> Result<String, String> {
    if let Ok(slice) = path.as_cstr().to_str() {
        Ok(slice.to_string())
    } else {
        Err(format!("Path not a UTF-8 string: {:?}", path))
    }
}

fn get_error_message(err: &Error) -> &str {
    match err.message() {
        Some(details) => details,
        None => "Undefined error message",
    }
}
<commit_msg>Consts in dbus_api do not have to be public<commit_after>use dbus::Connection as DBusConnection;
use dbus::{BusType, Path, ConnPath, Message};
use dbus::arg::{Variant, Iter, Array, Get, RefArg};
use dbus::stdintf::OrgFreedesktopDBusProperties;
use dbus::Error;

const DEFAULT_TIMEOUT: u64 = 10;
const RETRIES_ALLOWED: usize = 10;

pub struct DBusApi {
    connection: DBusConnection,
    method_timeout: u64,
    base: &'static str,
    method_retry_error_names: &'static [&'static str],
}

impl DBusApi {
    pub fn new(base: &'static str, method_retry_error_names: &'static [&'static str]) -> Self {
        let connection = DBusConnection::get_private(BusType::System).unwrap();

        DBusApi {
            connection: connection,
            method_timeout: DEFAULT_TIMEOUT,
            base: base,
            method_retry_error_names: method_retry_error_names,
        }
    }

    pub fn method_timeout(&self) -> u64 {
        self.method_timeout
    }

    pub fn set_method_timeout(&mut self, timeout: u64) {
        self.method_timeout = timeout;
    }

    pub fn call(&self, path: &str, interface: &str, method: &str) -> Result<Message, String> {
        self.call_with_args(path, interface, method, &[])
    }

    pub fn call_with_args(&self,
                          path: &str,
                          interface: &str,
                          method: &str,
                          args: &[&RefArg])
                          -> Result<Message, String> {
        self.call_with_args_retry(path, interface, method, args)
            .map_err(|error| {
                         format!("D-Bus '{}'::'{}' method call failed on '{}': {}",
                                 interface,
                                 method,
                                 path,
                                 error)
                     })
    }

    fn call_with_args_retry(&self,
                            path: &str,
                            interface: &str,
                            method: &str,
                            args: &[&RefArg])
                            -> Result<Message, String> {
        let mut retries = 0;

        loop {
            if let Some(result) = self.create_and_send_message(path, interface, method, args) {
                return result;
            }

            retries += 1;

            if retries == RETRIES_ALLOWED {
                return Err(format!("method failed after {} retries", RETRIES_ALLOWED));
            }

            ::std::thread::sleep(::std::time::Duration::from_secs(1));
        }
    }

    fn create_and_send_message(&self,
                               path: &str,
                               interface: &str,
                               method: &str,
                               args: &[&RefArg])
                               -> Option<Result<Message, String>> {
        match Message::new_method_call(self.base, path, interface, method) {
            Ok(mut message) => {
                if args.len() > 0 {
                    message = message.append_ref(args);
                }

                self.send_message_checked(message)
            }
            Err(details) => Some(Err(details)),
        }
    }

    fn send_message_checked(&self, message: Message) -> Option<Result<Message, String>> {
        match self.connection
                  .send_with_reply_and_block(message, self.method_timeout as i32 * 1000) {
            Ok(response) => Some(Ok(response)),
            Err(err) => {
                let message = get_error_message(&err).to_string();

                let name = err.name();
                for error_name in self.method_retry_error_names {
                    if name == Some(error_name) {
                        return None;
                    }
                }

                Some(Err(message))
            }
        }
    }

    pub fn property<T>(&self, path: &str, interface: &str, name: &str) -> Result<T, String>
        where DBusApi: VariantTo<T>
    {
        let property_error = |details: &str| {
            Err(format!("D-Bus get '{}'::'{}' property failed on '{}': {}",
                        interface,
                        name,
                        path,
                        details))
        };

        let path = self.with_path(path);

        match path.get(interface, name) {
            Ok(variant) => {
                match DBusApi::variant_to(variant) {
                    Some(data) => Ok(data),
                    None => property_error("wrong property type"),
                }
            }
            Err(err) => {
                match err.message() {
                    Some(details) => property_error(details),
                    None => property_error("no details"),
                }
            }
        }
    }

    pub fn extract<'a, T>(&self, response: &'a Message) -> Result<T, String>
        where T: Get<'a>
    {
        response
            .get1()
            .ok_or("D-Bus wrong response type".to_string())
    }

    pub fn extract_two<'a, T1, T2>(&self, response: &'a Message) -> Result<(T1, T2), String>
        where T1: Get<'a>,
              T2: Get<'a>
    {
        let (first, second) = response.get2();

        if let Some(first) = first {
            if let Some(second) = second {
                return Ok((first, second));
            }
        }

        Err("D-Bus wrong response type".to_string())
    }

    fn with_path<'a, P: Into<Path<'a>>>(&'a self, path: P) -> ConnPath<'a, &'a DBusConnection> {
        self.connection
            .with_path(self.base, path, self.method_timeout as i32 * 1000)
    }
}

pub trait VariantTo<T> {
    fn variant_to(value: Variant<Box<RefArg>>) -> Option<T>;
}

impl VariantTo<String> for DBusApi {
    fn variant_to(value: Variant<Box<RefArg>>) -> Option<String> {
        variant_to_string(value)
    }
}

impl VariantTo<i64> for DBusApi {
    fn variant_to(value: Variant<Box<RefArg>>) -> Option<i64> {
        variant_to_i64(value)
    }
}

impl VariantTo<u32> for DBusApi {
    fn variant_to(value: Variant<Box<RefArg>>) -> Option<u32> {
        variant_to_u32(value)
    }
}

impl VariantTo<bool> for DBusApi {
    fn variant_to(value: Variant<Box<RefArg>>) -> Option<bool> {
        variant_to_bool(value)
    }
}

impl VariantTo<Vec<String>> for DBusApi {
    fn variant_to(value: Variant<Box<RefArg>>) -> Option<Vec<String>> {
        variant_to_string_vec(value)
    }
}

impl VariantTo<Vec<u8>> for DBusApi {
    fn variant_to(value: Variant<Box<RefArg>>) -> Option<Vec<u8>> {
        variant_to_u8_vec(value)
    }
}

fn variant_to_string_vec(value: Variant<Box<RefArg>>) -> Option<Vec<String>> {
    let mut result = Vec::new();

    if let Some(list) = value.0.as_iter() {
        for element in list {
            if let Some(string) = element.as_str() {
                result.push(string.to_string());
            } else {
                return None;
            }
        }

        Some(result)
    } else {
        None
    }
}

fn variant_to_u8_vec(value: Variant<Box<RefArg>>) -> Option<Vec<u8>> {
    let mut result = Vec::new();

    if let Some(list) = value.0.as_iter() {
        for element in list {
            if let Some(value) = element.as_i64() {
                result.push(value as u8);
            } else {
                return None;
            }
        }

        Some(result)
    } else {
        None
    }
}

fn variant_to_string(value: Variant<Box<RefArg>>) -> Option<String> {
    value.0.as_str().and_then(|v| Some(v.to_string()))
}

fn variant_to_i64(value: Variant<Box<RefArg>>) -> Option<i64> {
    value.0.as_i64()
}

fn variant_to_u32(value: Variant<Box<RefArg>>) -> Option<u32> {
    value.0.as_i64().and_then(|v| Some(v as u32))
}

fn variant_to_bool(value: Variant<Box<RefArg>>) -> Option<bool> {
    value.0.as_i64().and_then(|v| Some(v == 0))
}

pub fn extract<'a, T>(var: &'a Variant<Iter>) -> Result<T, String>
    where T: Get<'a>
{
    var.0
        .clone()
        .get::<T>()
        .ok_or(format!("D-Bus variant type does not match: {:?}", var))
}

pub fn utf8_vec_u8_to_string(var: Vec<u8>) -> Result<String, String> {
    String::from_utf8(var).or(Err(format!("D-Bus variant not a UTF-8 string")))
}

pub fn utf8_variant_to_string(var: &Variant<Iter>) -> Result<String, String> {
    let array_option = &var.0.clone().get::<Array<u8, _>>();

    if let Some(array) = *array_option {
        utf8_vec_u8_to_string(array.collect())
    } else {
        Err(format!("D-Bus variant not an array: {:?}", var))
    }
}

pub fn string_to_utf8_vec_u8(var: &String) -> Vec<u8> {
    var.as_bytes().to_vec()
}

pub fn path_to_string(path: &Path) -> Result<String, String> {
    if let Ok(slice) = path.as_cstr().to_str() {
        Ok(slice.to_string())
    } else {
        Err(format!("Path not a UTF-8 string: {:?}", path))
    }
}

fn get_error_message(err: &Error) -> &str {
    match err.message() {
        Some(details) => details,
        None => "Undefined error message",
    }
}
<|endoftext|>


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

/*!
# ears

__ears__ is a simple library for play Audio in Rust.

__ears__ is build on the top of OpenAL and libsndfile.

* Provide an acces to the OpenAL spatialization functionnality in a simple way.
* Accept a lot of audio format thanks to libsndfile.

# A simple example

```Rust
extern mod ears;
use ears::Sound;

fn main() -> {
	// Create a new Sound.
	let snd = Sound::new(~"path/to/my/sound.ogg").unwrap();

	// Play the Sound
	snd.play();

	// Wait until the end of the sound
	while snd.is_playing() {}
}
```

# Functionnality

__ears__ provide two way for play audio files.

* The Sound class, which represent light sounds who can share a buffer of samples with another Sound.
* The Music class, which is a bigger sound and who can't share sample buffer.

# Use ears

As said before, __ears__ require OpenAL and libsndfile, you need to install these two libraries in your system.

__ears__ compile against the last Rust compiler, so if it doesn't work on your computer you may need to update your compiler.

__ears__ work fully with `rustpkg`, so just install __ears__ in your project workspace like this :

```Shell
> rustpkg install github.com/JeremyLetang/ears
```

then import stuff from __ears__ in your project, you can import all the stuff :

```Rust
extern mod ears;

use ears::*;
```

or a specific :

```Rust
extern mod ears;

use ears::Music;
```

# Compile examples

Like __ears__ you can build the examples with `rustpkg`, just do :

```Shell
> rustpkg install examples/an_example
```
*/

#[feature(globs, macro_rules)];

#[link(name = "src/ears",
       vers = "0.0.1",
       package_id = "github.com/JeremyLetang/ears",
       author = "letang.jeremy@gmail.com",
       uuid = "D0271EC6-5F27-4C72-BBEA-1341DC665F34",
       url = "https://github.com/JeremyLetang/ears")];

#[desc = "Easy Api in Rust for Sounds"];
#[license = "MIT"];
#[crate_type = "lib"];

extern mod extra;

// Reexport public API
pub use music::Music;
pub use sound::Sound;
pub use states::{State, Initial, Playing, Paused, Stopped};
pub use sound_data::SoundData;
pub use audio_controller::AudioController;
pub use audio_tags::{AudioTags, Tags};

// Hidden internal bindings
#[doc(hidden)]
pub mod internal;
#[doc(hidden)]
mod openal;
#[doc(hidden)]
mod sndfile;

// The public ears API
pub mod init;
pub mod listener;
pub mod sound;
pub mod music;
pub mod sound_data;
pub mod states;
pub mod audio_controller;
pub mod audio_tags;
pub mod recorder;
<commit_msg>rustpkg test again...<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/*!
# ears

__ears__ is a simple library for play Audio in Rust.

__ears__ is build on the top of OpenAL and libsndfile.

* Provide an acces to the OpenAL spatialization functionnality in a simple way.
* Accept a lot of audio format thanks to libsndfile.

# A simple example

```Rust
extern mod ears;
use ears::Sound;

fn main() -> {
	// Create a new Sound.
	let snd = Sound::new(~"path/to/my/sound.ogg").unwrap();

	// Play the Sound
	snd.play();

	// Wait until the end of the sound
	while snd.is_playing() {}
}
```

# Functionnality

__ears__ provide two way for play audio files.

* The Sound class, which represent light sounds who can share a buffer of samples with another Sound.
* The Music class, which is a bigger sound and who can't share sample buffer.

# Use ears

As said before, __ears__ require OpenAL and libsndfile, you need to install these two libraries in your system.

__ears__ compile against the last Rust compiler, so if it doesn't work on your computer you may need to update your compiler.

__ears__ work fully with `rustpkg`, so just install __ears__ in your project workspace like this :

```Shell
> rustpkg install github.com/JeremyLetang/ears
```

then import stuff from __ears__ in your project, you can import all the stuff :

```Rust
extern mod ears;

use ears::*;
```

or a specific :

```Rust
extern mod ears;

use ears::Music;
```

# Compile examples

Like __ears__ you can build the examples with `rustpkg`, just do :

```Shell
> rustpkg install examples/an_example
```
*/

#[feature(globs, macro_rules)];

#[link(name = "ears",
       vers = "0.1",
       package_id = "github.com/JeremyLetang/ears",
       author = "letang.jeremy@gmail.com",
       uuid = "D0271EC6-5F27-4C72-BBEA-1341DC665F34",
       url = "https://github.com/JeremyLetang/ears")];

#[desc = "Easy Api in Rust for Sounds"];
#[license = "MIT"];
#[crate_type = "lib"];

extern mod extra;

// Reexport public API
pub use music::Music;
pub use sound::Sound;
pub use states::{State, Initial, Playing, Paused, Stopped};
pub use sound_data::SoundData;
pub use audio_controller::AudioController;
pub use audio_tags::{AudioTags, Tags};

// Hidden internal bindings
#[doc(hidden)]
pub mod internal;
#[doc(hidden)]
mod openal;
#[doc(hidden)]
mod sndfile;

// The public ears API
pub mod init;
pub mod listener;
pub mod sound;
pub mod music;
pub mod sound_data;
pub mod states;
pub mod audio_controller;
pub mod audio_tags;
pub mod recorder;
<|endoftext|>


<commit_before>// Copyright 2013-2014 The rust-url developers.
//
// 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.

//! Abstraction that conditionally compiles either to rust-encoding,
//! or to only support UTF-8.

#[cfg(feature = "query_encoding")] extern crate encoding;

use std::borrow::Cow;

#[cfg(feature = "query_encoding")] use self::encoding::types::{DecoderTrap, EncoderTrap};
#[cfg(feature = "query_encoding")] use self::encoding::label::encoding_from_whatwg_label;
#[cfg(feature = "query_encoding")] pub use self::encoding::types::EncodingRef;

#[cfg(feature = "query_encoding")]
#[derive(Copy, Clone)]
pub struct EncodingOverride {
    /// `None` means UTF-8.
    encoding: Option<EncodingRef>
}

#[cfg(feature = "query_encoding")]
impl EncodingOverride {
    pub fn from_opt_encoding(encoding: Option<EncodingRef>) -> Self {
        encoding.map(Self::from_encoding).unwrap_or_else(Self::utf8)
    }

    pub fn from_encoding(encoding: EncodingRef) -> Self {
        EncodingOverride {
            encoding: if encoding.name() == "utf-8" { None } else { Some(encoding) }
        }
    }

    #[inline]
    pub fn utf8() -> Self {
        EncodingOverride { encoding: None }
    }

    pub fn lookup(label: &[u8]) -> Option<Self> {
        // Don't use String::from_utf8_lossy since no encoding label contains U+FFFD
        // https://encoding.spec.whatwg.org/#names-and-labels
        ::std::str::from_utf8(label)
        .ok()
        .and_then(encoding_from_whatwg_label)
        .map(Self::from_encoding)
    }

    /// https://encoding.spec.whatwg.org/#get-an-output-encoding
    pub fn to_output_encoding(self) -> Self {
        if let Some(encoding) = self.encoding {
            if matches!(encoding.name(), "utf-16le" | "utf-16be") {
                return Self::utf8()
            }
        }
        self
    }

    pub fn is_utf8(&self) -> bool {
        self.encoding.is_none()
    }

    pub fn name(&self) -> &'static str {
        match self.encoding {
            Some(encoding) => encoding.name(),
            None => "utf-8",
        }
    }

    pub fn decode<'a>(&self, input: Cow<'a, [u8]>) -> Cow<'a, str> {
        match self.encoding {
            // `encoding.decode` never returns `Err` when called with `DecoderTrap::Replace`
            Some(encoding) => encoding.decode(&input, DecoderTrap::Replace).unwrap().into(),
            None => decode_utf8_lossy(input),
        }
    }

    pub fn encode<'a>(&self, input: Cow<'a, str>) -> Cow<'a, [u8]> {
        match self.encoding {
            // `encoding.encode` never returns `Err` when called with `EncoderTrap::NcrEscape`
            Some(encoding) => Cow::Owned(encoding.encode(&input, EncoderTrap::NcrEscape).unwrap()),
            None => encode_utf8(input)
        }
    }
}

#[cfg(feature = "query_encoding")]
impl Debug for EncodingOverride {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "EncodingOverride {{ encoding: ")?;
        match self.encoding {
            Some(_) => write!(f, "Some(EncodingOverride) }}"),
            None => write!(f, "None }}")
        }
    }
}

#[cfg(not(feature = "query_encoding"))]
#[derive(Copy, Clone, Debug)]
pub struct EncodingOverride;

#[cfg(not(feature = "query_encoding"))]
impl EncodingOverride {
    #[inline]
    pub fn utf8() -> Self {
        EncodingOverride
    }

    pub fn decode<'a>(&self, input: Cow<'a, [u8]>) -> Cow<'a, str> {
        decode_utf8_lossy(input)
    }

    pub fn encode<'a>(&self, input: Cow<'a, str>) -> Cow<'a, [u8]> {
        encode_utf8(input)
    }
}

pub fn decode_utf8_lossy(input: Cow<[u8]>) -> Cow<str> {
    match input {
        Cow::Borrowed(bytes) => String::from_utf8_lossy(bytes),
        Cow::Owned(bytes) => {
            let raw_utf8: *const [u8];
            match String::from_utf8_lossy(&bytes) {
                Cow::Borrowed(utf8) => raw_utf8 = utf8.as_bytes(),
                Cow::Owned(s) => return s.into(),
            }
            // from_utf8_lossy returned a borrow of `bytes` unchanged.
            debug_assert!(raw_utf8 == &*bytes as *const [u8]);
            // Reuse the existing `Vec` allocation.
            unsafe { String::from_utf8_unchecked(bytes) }.into()
        }
    }
}

pub fn encode_utf8(input: Cow<str>) -> Cow<[u8]> {
    match input {
        Cow::Borrowed(s) => Cow::Borrowed(s.as_bytes()),
        Cow::Owned(s) => Cow::Owned(s.into_bytes())
    }
}
<commit_msg>Add missing 'use' declarations<commit_after>// Copyright 2013-2014 The rust-url developers.
//
// 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.

//! Abstraction that conditionally compiles either to rust-encoding,
//! or to only support UTF-8.

#[cfg(feature = "query_encoding")] extern crate encoding;

use std::borrow::Cow;
#[cfg(feature = "query_encoding")] use std::fmt::{self, Write, Debug, Formatter};

#[cfg(feature = "query_encoding")] use self::encoding::types::{DecoderTrap, EncoderTrap};
#[cfg(feature = "query_encoding")] use self::encoding::label::encoding_from_whatwg_label;
#[cfg(feature = "query_encoding")] pub use self::encoding::types::EncodingRef;

#[cfg(feature = "query_encoding")]
#[derive(Copy, Clone)]
pub struct EncodingOverride {
    /// `None` means UTF-8.
    encoding: Option<EncodingRef>
}

#[cfg(feature = "query_encoding")]
impl EncodingOverride {
    pub fn from_opt_encoding(encoding: Option<EncodingRef>) -> Self {
        encoding.map(Self::from_encoding).unwrap_or_else(Self::utf8)
    }

    pub fn from_encoding(encoding: EncodingRef) -> Self {
        EncodingOverride {
            encoding: if encoding.name() == "utf-8" { None } else { Some(encoding) }
        }
    }

    #[inline]
    pub fn utf8() -> Self {
        EncodingOverride { encoding: None }
    }

    pub fn lookup(label: &[u8]) -> Option<Self> {
        // Don't use String::from_utf8_lossy since no encoding label contains U+FFFD
        // https://encoding.spec.whatwg.org/#names-and-labels
        ::std::str::from_utf8(label)
        .ok()
        .and_then(encoding_from_whatwg_label)
        .map(Self::from_encoding)
    }

    /// https://encoding.spec.whatwg.org/#get-an-output-encoding
    pub fn to_output_encoding(self) -> Self {
        if let Some(encoding) = self.encoding {
            if matches!(encoding.name(), "utf-16le" | "utf-16be") {
                return Self::utf8()
            }
        }
        self
    }

    pub fn is_utf8(&self) -> bool {
        self.encoding.is_none()
    }

    pub fn name(&self) -> &'static str {
        match self.encoding {
            Some(encoding) => encoding.name(),
            None => "utf-8",
        }
    }

    pub fn decode<'a>(&self, input: Cow<'a, [u8]>) -> Cow<'a, str> {
        match self.encoding {
            // `encoding.decode` never returns `Err` when called with `DecoderTrap::Replace`
            Some(encoding) => encoding.decode(&input, DecoderTrap::Replace).unwrap().into(),
            None => decode_utf8_lossy(input),
        }
    }

    pub fn encode<'a>(&self, input: Cow<'a, str>) -> Cow<'a, [u8]> {
        match self.encoding {
            // `encoding.encode` never returns `Err` when called with `EncoderTrap::NcrEscape`
            Some(encoding) => Cow::Owned(encoding.encode(&input, EncoderTrap::NcrEscape).unwrap()),
            None => encode_utf8(input)
        }
    }
}

#[cfg(feature = "query_encoding")]
impl Debug for EncodingOverride {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "EncodingOverride {{ encoding: ")?;
        match self.encoding {
            Some(_) => write!(f, "Some(EncodingOverride) }}"),
            None => write!(f, "None }}")
        }
    }
}

#[cfg(not(feature = "query_encoding"))]
#[derive(Copy, Clone, Debug)]
pub struct EncodingOverride;

#[cfg(not(feature = "query_encoding"))]
impl EncodingOverride {
    #[inline]
    pub fn utf8() -> Self {
        EncodingOverride
    }

    pub fn decode<'a>(&self, input: Cow<'a, [u8]>) -> Cow<'a, str> {
        decode_utf8_lossy(input)
    }

    pub fn encode<'a>(&self, input: Cow<'a, str>) -> Cow<'a, [u8]> {
        encode_utf8(input)
    }
}

pub fn decode_utf8_lossy(input: Cow<[u8]>) -> Cow<str> {
    match input {
        Cow::Borrowed(bytes) => String::from_utf8_lossy(bytes),
        Cow::Owned(bytes) => {
            let raw_utf8: *const [u8];
            match String::from_utf8_lossy(&bytes) {
                Cow::Borrowed(utf8) => raw_utf8 = utf8.as_bytes(),
                Cow::Owned(s) => return s.into(),
            }
            // from_utf8_lossy returned a borrow of `bytes` unchanged.
            debug_assert!(raw_utf8 == &*bytes as *const [u8]);
            // Reuse the existing `Vec` allocation.
            unsafe { String::from_utf8_unchecked(bytes) }.into()
        }
    }
}

pub fn encode_utf8(input: Cow<str>) -> Cow<[u8]> {
    match input {
        Cow::Borrowed(s) => Cow::Borrowed(s.as_bytes()),
        Cow::Owned(s) => Cow::Owned(s.into_bytes())
    }
}
<|endoftext|>


<commit_before>// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

//! The Resolver is responsible for performing recursive queries to lookup domain names.
//!
//! This is a 100% in process DNS resolver. It *does not* use the Host OS' resolver. If what is desired is to use the Host OS' resolver, generally in the system's libc, then the `std::net::ToSocketAddrs` variant over `&str` is what should be used. As of the initial release, `trust-dns-resolver` it does not currently support search paths or ndot recursive lookups. It only supports FQDN, where the name must be specified with the final dot, e.g. `www.example.com.`. This limitation will be removed in future releases.
//!
//! Unlike the `trust-dns` client, this tries to provide a simpler interface to perform DNS queries. For update options, i.e. Dynamic DNS, the `trust-dns` crate must be used directly.
//!
//! There are two types for performing DNS queries, `Resolver` and `ResolverFuture`. `Resolver` is the easiest to work with, it is a wrapper around `ResolverFuture`. `ResolverFuture` is a `Tokio` based async resolver, and can be used inside any `Tokio` based system.
//!
//! *Notes on current limitations*: DNSSec is not yet supported in the Resolver, use the `trust-dns` Client if DNSSec validation is needed. Many standard system options and configurations are not yet supported. The host system `/etc/resolv.conf` is not yet being used. Recursion is not yet built, i.e. CNAME chains will not be fully resolved if an address is not returned. IPv6 lookups are not included in queries. Due to many of these limitations, you may not yet want to use this library.
//!
//! This as best as possible attempts to abide by the the DNS RFCs, please file issues at https://github.com/bluejekyll/trust-dns .
//!
//! # Usage
//!
//! ## Declare dependency
//!
//! ```toml
//! [dependency]
//! trust-dns-resolver = "^0.1"
//! ```
//!
//! ## Extern the crate for usage in the library
//!
//! ```rust
//! extern crate trust_dns_resolver;
//! ```
//!
//! ## Using the Synchronous Resolver
//!
//! This uses the default configuration. Currently this sets the google resolvers as the upstream resolvers.
//!
//! ```rust
//! use std::net::*;
//! use trust_dns_resolver::Resolver;
//! use trust_dns_resolver::config::*;
//!
//! // Construct a new Resolver with default configuration options
//! let mut resolver = Resolver::new(ResolverConfig::default(), ResolverOpts::default()).unwrap();
//!
//! // Lookup the IP addresses associated with a name.
//! // NOTE: do not forget the final dot, as the resolver does not yet support search paths.
//! let mut response = resolver.lookup_ip("www.example.com.").unwrap();
//!
//! // There can be many addresses associated with the name,
//! //  this can return IPv4 and/or IPv6 addresses
//! let address = response.next().expect("no addresses returned!");
//! if address.is_ipv4() {
//!     assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
//! } else {
//!     assert_eq!(address, IpAddr::V6(Ipv6Addr::new(0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946)));
//! }
//! ```
//!
//! ## Using the Tokio/Async Resolver
//!
//! For more advanced asynchronous usage, the ResolverFuture is integrated with Tokio. In fact, the ResolverFuture is used by the synchronous Resolver for all lookups.
//!
//! ```rust
//! # extern crate futures;
//! # extern crate tokio_core;
//! # extern crate trust_dns_resolver;
//! # fn main() {
//! use std::net::*;
//! use tokio_core::reactor::Core;
//! use trust_dns_resolver::ResolverFuture;
//! use trust_dns_resolver::config::*;
//!
//! // We need a Tokio reactor::Core to run the resolver
//! //  this is responsible for running all Future tasks and registering interest in IO channels
//! let mut io_loop = Core::new().unwrap();
//!
//! // Construct a new Resolver with default configuration options
//! let mut resolver = ResolverFuture::new(ResolverConfig::default(), ResolverOpts::default(), io_loop.handle());
//!
//! // Lookup the IP addresses associated with a name.
//! // NOTE: do not forget the final dot, as the resolver does not yet support search paths.
//! // This returns a future that will lookup the IP addresses, it must be run in the Core to
//! //  to get the actual result.
//! let lookup_future = resolver.lookup_ip("www.example.com.");
//!
//! // Run the lookup until it resolves or errors
//! let mut response = io_loop.run(lookup_future).unwrap();
//!
//! // There can be many addresses associated with the name,
//! //  this can return IPv4 and/or IPv6 addresses
//! let address = response.next().expect("no addresses returned!");
//! if address.is_ipv4() {
//!     assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
//! } else {
//!     assert_eq!(address, IpAddr::V6(Ipv6Addr::new(0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946)));
//! }
//! # }
//! ```
//!
//! Generaally after a lookup in an asynchornous context, there would probably be a connection made to a server, for example:
//!
//! ```c
//! let result = io_loop.run(lookup_future.and_then(|ips| {
//!                              let ip = ips.next().unwrap();
//!                              TcpStream::connect()
//!                          }).and_then(|conn| /* do something with the connection... */)
//! ).unwrap();
//! ```
//!
//! It's beyond the scope of these examples to show how to deal with connection failures and looping etc. But if you wanted to say try a different address from the result set after a connection failure, it will be necessary to create a type that implements the `Future` trait. Inside the `Future::poll` method would be the place to implement a loop over the different IP addresses.

#![deny(missing_docs)]

extern crate futures;
#[macro_use]
extern crate log;
extern crate tokio_core;
extern crate trust_dns;

pub mod config;
pub mod lookup_ip;
mod name_server_pool;
mod resolver;
mod resolver_future;

pub use resolver::Resolver;
pub use resolver_future::ResolverFuture;

/// returns a version as specified in Cargo.toml
pub fn version() -> &'static str {
    env!("CARGO_PKG_VERSION")
}
<commit_msg>fix some documentation<commit_after>// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

//! The Resolver is responsible for performing recursive queries to lookup domain names.
//!
//! This is a 100% in process DNS resolver. It *does not* use the Host OS' resolver. If what is desired is to use the Host OS' resolver, generally in the system's libc, then the `std::net::ToSocketAddrs` variant over `&str` is what should be used. As of the initial release, `trust-dns-resolver` it does not currently support search paths or ndot recursive lookups. It only supports FQDN, where the name must be specified with the final dot, e.g. `www.example.com.`. This limitation will be removed in future releases.
//!
//! Unlike the `trust-dns` client, this tries to provide a simpler interface to perform DNS queries. For update options, i.e. Dynamic DNS, the `trust-dns` crate must be used directly.
//!
//! There are two types for performing DNS queries, `Resolver` and `ResolverFuture`. `Resolver` is the easiest to work with, it is a wrapper around `ResolverFuture`. `ResolverFuture` is a `Tokio` based async resolver, and can be used inside any `Tokio` based system.
//!
//! *Notes on current limitations*: DNSSec is not yet supported in the Resolver, use the `trust-dns` Client if DNSSec validation is needed. Many standard system options and configurations are not yet supported. The host system `/etc/resolv.conf` is not yet being used. Recursion is not yet built, i.e. CNAME chains will not be fully resolved if an address is not returned, though many upstream resolvers will perform this making it a none blocking issue.
//!
//! This as best as possible attempts to abide by the the DNS RFCs, please file issues at https://github.com/bluejekyll/trust-dns .
//!
//! # Usage
//!
//! ## Declare dependency
//!
//! ```toml
//! [dependency]
//! trust-dns-resolver = "^0.1"
//! ```
//!
//! ## Extern the crate for usage in the library
//!
//! ```rust
//! extern crate trust_dns_resolver;
//! ```
//!
//! ## Using the Synchronous Resolver
//!
//! This uses the default configuration. Currently this sets the google resolvers as the upstream resolvers.
//!
//! ```rust
//! use std::net::*;
//! use trust_dns_resolver::Resolver;
//! use trust_dns_resolver::config::*;
//!
//! // Construct a new Resolver with default configuration options
//! let mut resolver = Resolver::new(ResolverConfig::default(), ResolverOpts::default()).unwrap();
//!
//! // Lookup the IP addresses associated with a name.
//! // NOTE: do not forget the final dot, as the resolver does not yet support search paths.
//! let mut response = resolver.lookup_ip("www.example.com.").unwrap();
//!
//! // There can be many addresses associated with the name,
//! //  this can return IPv4 and/or IPv6 addresses
//! let address = response.next().expect("no addresses returned!");
//! if address.is_ipv4() {
//!     assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
//! } else {
//!     assert_eq!(address, IpAddr::V6(Ipv6Addr::new(0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946)));
//! }
//! ```
//!
//! ## Using the Tokio/Async Resolver
//!
//! For more advanced asynchronous usage, the ResolverFuture is integrated with Tokio. In fact, the ResolverFuture is used by the synchronous Resolver for all lookups.
//!
//! ```rust
//! # extern crate futures;
//! # extern crate tokio_core;
//! # extern crate trust_dns_resolver;
//! # fn main() {
//! use std::net::*;
//! use tokio_core::reactor::Core;
//! use trust_dns_resolver::ResolverFuture;
//! use trust_dns_resolver::config::*;
//!
//! // We need a Tokio reactor::Core to run the resolver
//! //  this is responsible for running all Future tasks and registering interest in IO channels
//! let mut io_loop = Core::new().unwrap();
//!
//! // Construct a new Resolver with default configuration options
//! let mut resolver = ResolverFuture::new(ResolverConfig::default(), ResolverOpts::default(), io_loop.handle());
//!
//! // Lookup the IP addresses associated with a name.
//! // NOTE: do not forget the final dot, as the resolver does not yet support search paths.
//! // This returns a future that will lookup the IP addresses, it must be run in the Core to
//! //  to get the actual result.
//! let lookup_future = resolver.lookup_ip("www.example.com.");
//!
//! // Run the lookup until it resolves or errors
//! let mut response = io_loop.run(lookup_future).unwrap();
//!
//! // There can be many addresses associated with the name,
//! //  this can return IPv4 and/or IPv6 addresses
//! let address = response.next().expect("no addresses returned!");
//! if address.is_ipv4() {
//!     assert_eq!(address, IpAddr::V4(Ipv4Addr::new(93, 184, 216, 34)));
//! } else {
//!     assert_eq!(address, IpAddr::V6(Ipv6Addr::new(0x2606, 0x2800, 0x220, 0x1, 0x248, 0x1893, 0x25c8, 0x1946)));
//! }
//! # }
//! ```
//!
//! Generaally after a lookup in an asynchornous context, there would probably be a connection made to a server, for example:
//!
//! ```c
//! let result = io_loop.run(lookup_future.and_then(|ips| {
//!                              let ip = ips.next().unwrap();
//!                              TcpStream::connect()
//!                          }).and_then(|conn| /* do something with the connection... */)
//! ).unwrap();
//! ```
//!
//! It's beyond the scope of these examples to show how to deal with connection failures and looping etc. But if you wanted to say try a different address from the result set after a connection failure, it will be necessary to create a type that implements the `Future` trait. Inside the `Future::poll` method would be the place to implement a loop over the different IP addresses.

#![deny(missing_docs)]

extern crate futures;
#[macro_use]
extern crate log;
extern crate tokio_core;
extern crate trust_dns;

pub mod config;
pub mod lookup_ip;
mod name_server_pool;
mod resolver;
mod resolver_future;

pub use resolver::Resolver;
pub use resolver_future::ResolverFuture;

/// returns a version as specified in Cargo.toml
pub fn version() -> &'static str {
    env!("CARGO_PKG_VERSION")
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::types::{Namespace, TypeName};
use proc_macro2::TokenStream;
use std::{
    collections::{HashMap, HashSet},
    fmt::Display,
};
use syn::{ForeignItem, Ident, ImplItem, Item, ItemConst, ItemType};

use super::codegen_cpp::AdditionalNeed;

#[derive(Debug)]
pub enum ConvertError {
    NoContent,
    UnsafePODType(String),
    UnexpectedForeignItem,
    UnexpectedOuterItem,
    UnexpectedItemInMod,
    ComplexTypedefTarget(String),
    UnexpectedThisType(Namespace, String),
    UnsupportedBuiltInType(TypeName),
    VirtualThisType(Namespace, String),
    ConflictingTemplatedArgsWithTypedef(TypeName),
    UnacceptableParam(String),
    NotOneInputReference(String),
}

impl Display for ConvertError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ConvertError::NoContent => write!(f, "The initial run of 'bindgen' did not generate any content. This might be because none of the requested items for generation could be converted.")?,
            ConvertError::UnsafePODType(err) => write!(f, "An item was requested using 'generate_pod' which was not safe to hold by value in Rust. {}", err)?,
            ConvertError::UnexpectedForeignItem => write!(f, "Bindgen generated some unexpected code in a foreign mod section. You may have specified something in a 'generate' directive which is not currently compatible with autocxx.")?,
            ConvertError::UnexpectedOuterItem => write!(f, "Bindgen generated some unexpected code in its outermost mod section. You may have specified something in a 'generate' directive which is not currently compatible with autocxx.")?,
            ConvertError::UnexpectedItemInMod => write!(f, "Bindgen generated some unexpected code in an inner namespace mod. You may have specified something in a 'generate' directive which is not currently compatible with autocxx.")?,
            ConvertError::ComplexTypedefTarget(ty) => write!(f, "autocxx was unable to produce a typdef pointing to the complex type {}.", ty)?,
            ConvertError::UnexpectedThisType(ns, fn_name) => write!(f, "Unexpected type for 'this' in the function {}{}.", fn_name, ns.to_display_suffix())?,
            ConvertError::UnsupportedBuiltInType(ty) => write!(f, "autocxx does not yet know how to support the built-in C++ type {} - please raise an issue on github", ty.to_cpp_name())?,
            ConvertError::VirtualThisType(ns, fn_name) => write!(f, "Member function encountered where the 'this' type is 'void*', but we were unable to recognize which type that corresponds to. Function {}{}.", fn_name, ns.to_display_suffix())?,
            ConvertError::ConflictingTemplatedArgsWithTypedef(tn) => write!(f, "Type {} has templated arguments and so does the typedef to which it points", tn)?,
            ConvertError::UnacceptableParam(fn_name) => write!(f, "Function {} has a parameter or return type which is either on the blocklist or a forward declaration", fn_name)?,
            ConvertError::NotOneInputReference(fn_name) => write!(f, "Function {} has a return reference parameter, but 0 or >1 input reference parameters, so the lifetime of the output reference cannot be deduced.", fn_name)?,
        }
        Ok(())
    }
}

impl ConvertError {
    /// Whether we should ignore this error and simply skip over such items.
    /// In the future we need to use this to provide diagnostics or logging to the user,
    /// which ideally we'd somehow winkle into the generated bindings
    /// in a way that causes them a compile-time problem only if they try to
    /// _use_ the affects functions. I don't know a way to do that. Otherwise,
    /// we should output these things as warnings during the codegen phase. TODO.
    pub(crate) fn is_ignorable(&self) -> bool {
        match self {
            ConvertError::VirtualThisType(..)
            | ConvertError::UnsupportedBuiltInType(..)
            | ConvertError::UnacceptableParam(..)
            | ConvertError::NotOneInputReference(..) => true,
            _ => false,
        }
    }
}

#[derive(Copy, Clone, Eq, PartialEq)]
pub(crate) enum TypeKind {
    POD,                // trivial. Can be moved and copied in Rust.
    NonPOD, // has destructor or non-trivial move constructors. Can only hold by UniquePtr
    ForwardDeclaration, // no full C++ declaration available - can't even generate UniquePtr
}

/// Whether and how this type should be exposed in the mods constructed
/// for actual end-user use.
pub(crate) enum Use {
    Unused,
    Used,
    UsedWithAlias(Ident),
}

/// Common details for types of API which are a type and will require
/// us to generate an ExternType.
pub(crate) struct TypeApiDetails {
    pub(crate) fulltypath: Vec<Ident>,
    pub(crate) final_ident: Ident,
    pub(crate) tynamestring: String,
}

pub(crate) struct ImplBlockDetails {
    pub(crate) item: ImplItem,
    pub(crate) ty: Ident,
}

/// Different types of API we might encounter.
pub(crate) enum ApiDetail {
    ConcreteType(TypeApiDetails),
    StringConstructor,
    Function {
        // TODO move this to be much higher level
        extern_c_mod_item: ForeignItem,
        impl_entry: Option<Box<ImplBlockDetails>>,
    },
    Const {
        const_item: ItemConst,
    },
    Typedef {
        type_item: ItemType,
    },
    Type {
        ty_details: TypeApiDetails,
        for_extern_c_ts: TokenStream,
        type_kind: TypeKind,
        bindgen_mod_item: Option<Item>,
    },
    CType {
        id: Ident,
    },
}

/// Any API we encounter in the input bindgen rs which we might want to pass
/// onto the output Rust or C++. This is not exactly a high level representation
/// of the APIs we encounter - instead, we're mostly storing snippets of Rust
/// syntax which we encountered in the bindgen mod and want to pass onto the
/// resulting Rust mods. It may be that eventually this type turns into
/// a higher level description of the APIs we find, possibly even an enum.
/// That's the approach taken by both cxx and bindgen. This gives a cleaner
/// separation between the parser and the codegen phases. However our case is
/// a bit less normal because the code we generate actually includes most of
/// the code we parse.
pub(crate) struct Api {
    pub(crate) ns: Namespace,
    pub(crate) id: Ident,
    pub(crate) use_stmt: Use,
    pub(crate) deps: HashSet<TypeName>,
    pub(crate) id_for_allowlist: Option<Ident>,
    pub(crate) additional_cpp: Option<AdditionalNeed>,
    pub(crate) detail: ApiDetail,
}

impl Api {
    pub(crate) fn typename(&self) -> TypeName {
        TypeName::new(&self.ns, &self.id.to_string())
    }

    pub(crate) fn typename_for_allowlist(&self) -> TypeName {
        let id_for_allowlist = match &self.id_for_allowlist {
            None => match &self.use_stmt {
                Use::UsedWithAlias(alias) => alias,
                _ => &self.id,
            },
            Some(id) => &id,
        };
        TypeName::new(&self.ns, &id_for_allowlist.to_string())
    }
}

/// Results of parsing the bindgen mod. This is what is passed from
/// the parser to the code generation phase.
pub(crate) struct ParseResults {
    pub(crate) apis: Vec<Api>,
    pub(crate) use_stmts_by_mod: HashMap<Namespace, Vec<Item>>,
}
<commit_msg>Marking a TODO done.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::types::{Namespace, TypeName};
use proc_macro2::TokenStream;
use std::{
    collections::{HashMap, HashSet},
    fmt::Display,
};
use syn::{ForeignItem, Ident, ImplItem, Item, ItemConst, ItemType};

use super::codegen_cpp::AdditionalNeed;

#[derive(Debug)]
pub enum ConvertError {
    NoContent,
    UnsafePODType(String),
    UnexpectedForeignItem,
    UnexpectedOuterItem,
    UnexpectedItemInMod,
    ComplexTypedefTarget(String),
    UnexpectedThisType(Namespace, String),
    UnsupportedBuiltInType(TypeName),
    VirtualThisType(Namespace, String),
    ConflictingTemplatedArgsWithTypedef(TypeName),
    UnacceptableParam(String),
    NotOneInputReference(String),
}

impl Display for ConvertError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ConvertError::NoContent => write!(f, "The initial run of 'bindgen' did not generate any content. This might be because none of the requested items for generation could be converted.")?,
            ConvertError::UnsafePODType(err) => write!(f, "An item was requested using 'generate_pod' which was not safe to hold by value in Rust. {}", err)?,
            ConvertError::UnexpectedForeignItem => write!(f, "Bindgen generated some unexpected code in a foreign mod section. You may have specified something in a 'generate' directive which is not currently compatible with autocxx.")?,
            ConvertError::UnexpectedOuterItem => write!(f, "Bindgen generated some unexpected code in its outermost mod section. You may have specified something in a 'generate' directive which is not currently compatible with autocxx.")?,
            ConvertError::UnexpectedItemInMod => write!(f, "Bindgen generated some unexpected code in an inner namespace mod. You may have specified something in a 'generate' directive which is not currently compatible with autocxx.")?,
            ConvertError::ComplexTypedefTarget(ty) => write!(f, "autocxx was unable to produce a typdef pointing to the complex type {}.", ty)?,
            ConvertError::UnexpectedThisType(ns, fn_name) => write!(f, "Unexpected type for 'this' in the function {}{}.", fn_name, ns.to_display_suffix())?,
            ConvertError::UnsupportedBuiltInType(ty) => write!(f, "autocxx does not yet know how to support the built-in C++ type {} - please raise an issue on github", ty.to_cpp_name())?,
            ConvertError::VirtualThisType(ns, fn_name) => write!(f, "Member function encountered where the 'this' type is 'void*', but we were unable to recognize which type that corresponds to. Function {}{}.", fn_name, ns.to_display_suffix())?,
            ConvertError::ConflictingTemplatedArgsWithTypedef(tn) => write!(f, "Type {} has templated arguments and so does the typedef to which it points", tn)?,
            ConvertError::UnacceptableParam(fn_name) => write!(f, "Function {} has a parameter or return type which is either on the blocklist or a forward declaration", fn_name)?,
            ConvertError::NotOneInputReference(fn_name) => write!(f, "Function {} has a return reference parameter, but 0 or >1 input reference parameters, so the lifetime of the output reference cannot be deduced.", fn_name)?,
        }
        Ok(())
    }
}

impl ConvertError {
    /// Whether we should ignore this error and simply skip over such items.
    /// In the future we need to use this to provide diagnostics or logging to the user,
    /// which ideally we'd somehow winkle into the generated bindings
    /// in a way that causes them a compile-time problem only if they try to
    /// _use_ the affects functions. I don't know a way to do that. Meanwhile,
    /// we should output these things as warnings during the codegen phase.
    pub(crate) fn is_ignorable(&self) -> bool {
        match self {
            ConvertError::VirtualThisType(..)
            | ConvertError::UnsupportedBuiltInType(..)
            | ConvertError::UnacceptableParam(..)
            | ConvertError::NotOneInputReference(..) => true,
            _ => false,
        }
    }
}

#[derive(Copy, Clone, Eq, PartialEq)]
pub(crate) enum TypeKind {
    POD,                // trivial. Can be moved and copied in Rust.
    NonPOD, // has destructor or non-trivial move constructors. Can only hold by UniquePtr
    ForwardDeclaration, // no full C++ declaration available - can't even generate UniquePtr
}

/// Whether and how this type should be exposed in the mods constructed
/// for actual end-user use.
pub(crate) enum Use {
    Unused,
    Used,
    UsedWithAlias(Ident),
}

/// Common details for types of API which are a type and will require
/// us to generate an ExternType.
pub(crate) struct TypeApiDetails {
    pub(crate) fulltypath: Vec<Ident>,
    pub(crate) final_ident: Ident,
    pub(crate) tynamestring: String,
}

pub(crate) struct ImplBlockDetails {
    pub(crate) item: ImplItem,
    pub(crate) ty: Ident,
}

/// Different types of API we might encounter.
pub(crate) enum ApiDetail {
    ConcreteType(TypeApiDetails),
    StringConstructor,
    Function {
        // TODO move this to be much higher level
        extern_c_mod_item: ForeignItem,
        impl_entry: Option<Box<ImplBlockDetails>>,
    },
    Const {
        const_item: ItemConst,
    },
    Typedef {
        type_item: ItemType,
    },
    Type {
        ty_details: TypeApiDetails,
        for_extern_c_ts: TokenStream,
        type_kind: TypeKind,
        bindgen_mod_item: Option<Item>,
    },
    CType {
        id: Ident,
    },
}

/// Any API we encounter in the input bindgen rs which we might want to pass
/// onto the output Rust or C++. This is not exactly a high level representation
/// of the APIs we encounter - instead, we're mostly storing snippets of Rust
/// syntax which we encountered in the bindgen mod and want to pass onto the
/// resulting Rust mods. It may be that eventually this type turns into
/// a higher level description of the APIs we find, possibly even an enum.
/// That's the approach taken by both cxx and bindgen. This gives a cleaner
/// separation between the parser and the codegen phases. However our case is
/// a bit less normal because the code we generate actually includes most of
/// the code we parse.
pub(crate) struct Api {
    pub(crate) ns: Namespace,
    pub(crate) id: Ident,
    pub(crate) use_stmt: Use,
    pub(crate) deps: HashSet<TypeName>,
    pub(crate) id_for_allowlist: Option<Ident>,
    pub(crate) additional_cpp: Option<AdditionalNeed>,
    pub(crate) detail: ApiDetail,
}

impl Api {
    pub(crate) fn typename(&self) -> TypeName {
        TypeName::new(&self.ns, &self.id.to_string())
    }

    pub(crate) fn typename_for_allowlist(&self) -> TypeName {
        let id_for_allowlist = match &self.id_for_allowlist {
            None => match &self.use_stmt {
                Use::UsedWithAlias(alias) => alias,
                _ => &self.id,
            },
            Some(id) => &id,
        };
        TypeName::new(&self.ns, &id_for_allowlist.to_string())
    }
}

/// Results of parsing the bindgen mod. This is what is passed from
/// the parser to the code generation phase.
pub(crate) struct ParseResults {
    pub(crate) apis: Vec<Api>,
    pub(crate) use_stmts_by_mod: HashMap<Namespace, Vec<Item>>,
}
<|endoftext|>


<commit_before>/// Solve least square problem `|b - Ax|` with multi-column `b`
use approx::AbsDiffEq;
use ndarray::*;
use ndarray_linalg::*;

/// A is square. `x = A^{-1} b`, `|b - Ax| = 0`
fn test_exact<T: Scalar + Lapack>(a: Array2<T>, b: Array2<T>) {
    assert_eq!(a.layout().unwrap().size(), (3, 3));
    assert_eq!(b.layout().unwrap().size(), (3, 2));

    let result = a.least_squares(&b).unwrap();
    // unpack result
    let x: Array2<T> = result.solution;
    let residual_l2_square: Array1<T::Real> = result.residual_sum_of_squares.unwrap();

    // must be full-rank
    assert_eq!(result.rank, 3);

    // |b - Ax| == 0
    for &residual in &residual_l2_square {
        assert!(residual < T::real(1.0e-4));
    }

    // b == Ax
    let ax = a.dot(&x);
    assert_close_l2!(&b, &ax, T::real(1.0e-4));
}

macro_rules! impl_exact {
    ($scalar:ty) => {
        paste::item! {
            #[test]
            fn [<least_squares_ $scalar _exact_ac_bc>]() {
                let a: Array2<f64> = random((3, 3));
                let b: Array2<f64> = random((3, 2));
                test_exact(a, b)
            }

            #[test]
            fn [<least_squares_ $scalar _exact_ac_bf>]() {
                let a: Array2<f64> = random((3, 3));
                let b: Array2<f64> = random((3, 2).f());
                test_exact(a, b)
            }

            #[test]
            fn [<least_squares_ $scalar _exact_af_bc>]() {
                let a: Array2<f64> = random((3, 3).f());
                let b: Array2<f64> = random((3, 2));
                test_exact(a, b)
            }

            #[test]
            fn [<least_squares_ $scalar _exact_af_bf>]() {
                let a: Array2<f64> = random((3, 3).f());
                let b: Array2<f64> = random((3, 2).f());
                test_exact(a, b)
            }
        }
    };
}

impl_exact!(f32);
impl_exact!(f64);
impl_exact!(c32);
impl_exact!(c64);

/// #column < #row case.
/// Linear problem is overdetermined, `|b - Ax| > 0`.
fn test_overdetermined<T: Scalar + Lapack>(a: Array2<T>, bs: Array2<T>)
where
    T::Real: AbsDiffEq<Epsilon = T::Real>,
{
    assert_eq!(a.layout().unwrap().size(), (4, 3));
    assert_eq!(bs.layout().unwrap().size(), (4, 2));

    let result = a.least_squares(&bs).unwrap();
    // unpack result
    let xs = result.solution;
    let residual_l2_square = result.residual_sum_of_squares.unwrap();

    // Must be full-rank
    assert_eq!(result.rank, 3);

    for j in 0..2 {
        let b = bs.index_axis(Axis(1), j);
        let x = xs.index_axis(Axis(1), j);
        let residual = &b - &a.dot(&x);
        let residual_l2_sq = residual_l2_square[j];
        assert!(residual_l2_sq.abs_diff_eq(&residual.norm_l2().powi(2), T::real(1.0e-4)));

        // `|residual| < |b|`
        assert!(residual.norm_l2() < b.norm_l2());
    }
}

macro_rules! impl_overdetermined {
    ($scalar:ty) => {
        paste::item! {
            #[test]
            fn [<least_squares_ $scalar _overdetermined_ac_bc>]() {
                let a: Array2<f64> = random((4, 3));
                let b: Array2<f64> = random((4, 2));
                test_overdetermined(a, b)
            }

            #[test]
            fn [<least_squares_ $scalar _overdetermined_af_bc>]() {
                let a: Array2<f64> = random((4, 3).f());
                let b: Array2<f64> = random((4, 2));
                test_overdetermined(a, b)
            }

            #[test]
            fn [<least_squares_ $scalar _overdetermined_ac_bf>]() {
                let a: Array2<f64> = random((4, 3));
                let b: Array2<f64> = random((4, 2).f());
                test_overdetermined(a, b)
            }

            #[test]
            fn [<least_squares_ $scalar _overdetermined_af_bf>]() {
                let a: Array2<f64> = random((4, 3).f());
                let b: Array2<f64> = random((4, 2).f());
                test_overdetermined(a, b)
            }
        }
    };
}

impl_overdetermined!(f32);
impl_overdetermined!(f64);
impl_overdetermined!(c32);
impl_overdetermined!(c64);

/// #column > #row case.
/// Linear problem is underdetermined, `|b - Ax| = 0` and `x` is not unique
fn test_underdetermined<T: Scalar + Lapack>(a: Array2<T>, b: Array2<T>) {
    assert_eq!(a.layout().unwrap().size(), (3, 4));
    assert_eq!(b.layout().unwrap().size(), (3, 2));

    let result = a.least_squares(&b).unwrap();
    assert_eq!(result.rank, 3);
    assert!(result.residual_sum_of_squares.is_none());

    // b == Ax
    let x = result.solution;
    let ax = a.dot(&x);
    assert_close_l2!(&b, &ax, T::real(1.0e-4));
}

macro_rules! impl_underdetermined {
    ($scalar:ty) => {
        paste::item! {
            #[test]
            fn [<least_squares_ $scalar _underdetermined_ac_bc>]() {
                let a: Array2<f64> = random((3, 4));
                let b: Array2<f64> = random((3, 2));
                test_underdetermined(a, b)
            }

            #[test]
            fn [<least_squares_ $scalar _underdetermined_af_bc>]() {
                let a: Array2<f64> = random((3, 4).f());
                let b: Array2<f64> = random((3, 2));
                test_underdetermined(a, b)
            }

            #[test]
            fn [<least_squares_ $scalar _underdetermined_ac_bf>]() {
                let a: Array2<f64> = random((3, 4));
                let b: Array2<f64> = random((3, 2).f());
                test_underdetermined(a, b)
            }

            #[test]
            fn [<least_squares_ $scalar _underdetermined_af_bf>]() {
                let a: Array2<f64> = random((3, 4).f());
                let b: Array2<f64> = random((3, 2).f());
                test_underdetermined(a, b)
            }
        }
    };
}

impl_underdetermined!(f32);
impl_underdetermined!(f64);
impl_underdetermined!(c32);
impl_underdetermined!(c64);
<commit_msg>Comment out Unsupported C/F-mixed cases<commit_after>/// Solve least square problem `|b - Ax|` with multi-column `b`
use approx::AbsDiffEq;
use ndarray::*;
use ndarray_linalg::*;

/// A is square. `x = A^{-1} b`, `|b - Ax| = 0`
fn test_exact<T: Scalar + Lapack>(a: Array2<T>, b: Array2<T>) {
    assert_eq!(a.layout().unwrap().size(), (3, 3));
    assert_eq!(b.layout().unwrap().size(), (3, 2));

    let result = a.least_squares(&b).unwrap();
    // unpack result
    let x: Array2<T> = result.solution;
    let residual_l2_square: Array1<T::Real> = result.residual_sum_of_squares.unwrap();

    // must be full-rank
    assert_eq!(result.rank, 3);

    // |b - Ax| == 0
    for &residual in &residual_l2_square {
        assert!(residual < T::real(1.0e-4));
    }

    // b == Ax
    let ax = a.dot(&x);
    assert_close_l2!(&b, &ax, T::real(1.0e-4));
}

macro_rules! impl_exact {
    ($scalar:ty) => {
        paste::item! {
            #[test]
            fn [<least_squares_ $scalar _exact_ac_bc>]() {
                let a: Array2<f64> = random((3, 3));
                let b: Array2<f64> = random((3, 2));
                test_exact(a, b)
            }

            /* Unsupported currently. See https://github.com/rust-ndarray/ndarray-linalg/issues/234

            #[test]
            fn [<least_squares_ $scalar _exact_ac_bf>]() {
                let a: Array2<f64> = random((3, 3));
                let b: Array2<f64> = random((3, 2).f());
                test_exact(a, b)
            }

            #[test]
            fn [<least_squares_ $scalar _exact_af_bc>]() {
                let a: Array2<f64> = random((3, 3).f());
                let b: Array2<f64> = random((3, 2));
                test_exact(a, b)
            }

            */

            #[test]
            fn [<least_squares_ $scalar _exact_af_bf>]() {
                let a: Array2<f64> = random((3, 3).f());
                let b: Array2<f64> = random((3, 2).f());
                test_exact(a, b)
            }
        }
    };
}

impl_exact!(f32);
impl_exact!(f64);
impl_exact!(c32);
impl_exact!(c64);

/// #column < #row case.
/// Linear problem is overdetermined, `|b - Ax| > 0`.
fn test_overdetermined<T: Scalar + Lapack>(a: Array2<T>, bs: Array2<T>)
where
    T::Real: AbsDiffEq<Epsilon = T::Real>,
{
    assert_eq!(a.layout().unwrap().size(), (4, 3));
    assert_eq!(bs.layout().unwrap().size(), (4, 2));

    let result = a.least_squares(&bs).unwrap();
    // unpack result
    let xs = result.solution;
    let residual_l2_square = result.residual_sum_of_squares.unwrap();

    // Must be full-rank
    assert_eq!(result.rank, 3);

    for j in 0..2 {
        let b = bs.index_axis(Axis(1), j);
        let x = xs.index_axis(Axis(1), j);
        let residual = &b - &a.dot(&x);
        let residual_l2_sq = residual_l2_square[j];
        assert!(residual_l2_sq.abs_diff_eq(&residual.norm_l2().powi(2), T::real(1.0e-4)));

        // `|residual| < |b|`
        assert!(residual.norm_l2() < b.norm_l2());
    }
}

macro_rules! impl_overdetermined {
    ($scalar:ty) => {
        paste::item! {
            #[test]
            fn [<least_squares_ $scalar _overdetermined_ac_bc>]() {
                let a: Array2<f64> = random((4, 3));
                let b: Array2<f64> = random((4, 2));
                test_overdetermined(a, b)
            }

            /* Unsupported currently. See https://github.com/rust-ndarray/ndarray-linalg/issues/234

            #[test]
            fn [<least_squares_ $scalar _overdetermined_af_bc>]() {
                let a: Array2<f64> = random((4, 3).f());
                let b: Array2<f64> = random((4, 2));
                test_overdetermined(a, b)
            }

            #[test]
            fn [<least_squares_ $scalar _overdetermined_ac_bf>]() {
                let a: Array2<f64> = random((4, 3));
                let b: Array2<f64> = random((4, 2).f());
                test_overdetermined(a, b)
            }

            */

            #[test]
            fn [<least_squares_ $scalar _overdetermined_af_bf>]() {
                let a: Array2<f64> = random((4, 3).f());
                let b: Array2<f64> = random((4, 2).f());
                test_overdetermined(a, b)
            }
        }
    };
}

impl_overdetermined!(f32);
impl_overdetermined!(f64);
impl_overdetermined!(c32);
impl_overdetermined!(c64);

/// #column > #row case.
/// Linear problem is underdetermined, `|b - Ax| = 0` and `x` is not unique
fn test_underdetermined<T: Scalar + Lapack>(a: Array2<T>, b: Array2<T>) {
    assert_eq!(a.layout().unwrap().size(), (3, 4));
    assert_eq!(b.layout().unwrap().size(), (3, 2));

    let result = a.least_squares(&b).unwrap();
    assert_eq!(result.rank, 3);
    assert!(result.residual_sum_of_squares.is_none());

    // b == Ax
    let x = result.solution;
    let ax = a.dot(&x);
    assert_close_l2!(&b, &ax, T::real(1.0e-4));
}

macro_rules! impl_underdetermined {
    ($scalar:ty) => {
        paste::item! {
            #[test]
            fn [<least_squares_ $scalar _underdetermined_ac_bc>]() {
                let a: Array2<f64> = random((3, 4));
                let b: Array2<f64> = random((3, 2));
                test_underdetermined(a, b)
            }

            /* Unsupported currently. See https://github.com/rust-ndarray/ndarray-linalg/issues/234

            #[test]
            fn [<least_squares_ $scalar _underdetermined_af_bc>]() {
                let a: Array2<f64> = random((3, 4).f());
                let b: Array2<f64> = random((3, 2));
                test_underdetermined(a, b)
            }

            #[test]
            fn [<least_squares_ $scalar _underdetermined_ac_bf>]() {
                let a: Array2<f64> = random((3, 4));
                let b: Array2<f64> = random((3, 2).f());
                test_underdetermined(a, b)
            }

            */

            #[test]
            fn [<least_squares_ $scalar _underdetermined_af_bf>]() {
                let a: Array2<f64> = random((3, 4).f());
                let b: Array2<f64> = random((3, 2).f());
                test_underdetermined(a, b)
            }
        }
    };
}

impl_underdetermined!(f32);
impl_underdetermined!(f64);
impl_underdetermined!(c32);
impl_underdetermined!(c64);
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Alex Lyon <arcterus@mail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (ToDO) delim

use clap::{crate_version, App, AppSettings, Arg};
use std::fs::File;
use std::io::{stdin, BufRead, BufReader, Read};
use std::path::Path;
use uucore::error::{FromIo, UResult};

static ABOUT: &str = "Write lines consisting of the sequentially corresponding lines from each
FILE, separated by TABs, to standard output.";

mod options {
    pub const DELIMITER: &str = "delimiters";
    pub const SERIAL: &str = "serial";
    pub const FILE: &str = "file";
}

// Wraps BufReader and stdin
fn read_line<R: Read>(
    reader: Option<&mut BufReader<R>>,
    buf: &mut String,
) -> std::io::Result<usize> {
    match reader {
        Some(reader) => reader.read_line(buf),
        None => stdin().read_line(buf),
    }
}

#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    let matches = uu_app().get_matches_from(args);

    let serial = matches.is_present(options::SERIAL);
    let delimiters = matches.value_of(options::DELIMITER).unwrap();
    let files = matches
        .values_of(options::FILE)
        .unwrap()
        .map(|s| s.to_owned())
        .collect();
    paste(files, serial, delimiters)
}

pub fn uu_app<'a>() -> App<'a> {
    App::new(uucore::util_name())
        .version(crate_version!())
        .about(ABOUT)
        .setting(AppSettings::InferLongArgs)
        .arg(
            Arg::new(options::SERIAL)
                .long(options::SERIAL)
                .short('s')
                .help("paste one file at a time instead of in parallel"),
        )
        .arg(
            Arg::new(options::DELIMITER)
                .long(options::DELIMITER)
                .short('d')
                .help("reuse characters from LIST instead of TABs")
                .value_name("LIST")
                .default_value("\t")
                .hide_default_value(true),
        )
        .arg(
            Arg::new(options::FILE)
                .value_name("FILE")
                .multiple_occurrences(true)
                .default_value("-"),
        )
}

fn paste(filenames: Vec<String>, serial: bool, delimiters: &str) -> UResult<()> {
    let mut files = vec![];
    for name in filenames {
        let file = if name == "-" {
            None
        } else {
            let path = Path::new(&name);
            let r = File::open(path).map_err_context(String::new)?;
            Some(BufReader::new(r))
        };
        files.push(file);
    }

    let delimiters: Vec<char> = unescape(delimiters).chars().collect();
    let mut delim_count = 0;

    if serial {
        for file in &mut files {
            let mut output = String::new();
            loop {
                let mut line = String::new();
                match read_line(file.as_mut(), &mut line) {
                    Ok(0) => break,
                    Ok(_) => {
                        output.push_str(line.trim_end());
                        output.push(delimiters[delim_count % delimiters.len()]);
                    }
                    Err(e) => return Err(e.map_err_context(String::new)),
                }
                delim_count += 1;
            }
            output.pop();
            println!("{}", output);
        }
    } else {
        let mut eof = vec![false; files.len()];
        loop {
            let mut output = String::new();
            let mut eof_count = 0;
            for (i, file) in files.iter_mut().enumerate() {
                if eof[i] {
                    eof_count += 1;
                } else {
                    let mut line = String::new();
                    match read_line(file.as_mut(), &mut line) {
                        Ok(0) => {
                            eof[i] = true;
                            eof_count += 1;
                        }
                        Ok(_) => output.push_str(line.trim_end()),
                        Err(e) => return Err(e.map_err_context(String::new)),
                    }
                }
                output.push(delimiters[delim_count % delimiters.len()]);
                delim_count += 1;
            }
            if files.len() == eof_count {
                break;
            }
            // Remove final delimiter
            output.pop();
            println!("{}", output);
            delim_count = 0;
        }
    }
    Ok(())
}

// Unescape all special characters
// TODO: this will need work to conform to GNU implementation
fn unescape(s: &str) -> String {
    s.replace("\\n", "\n")
        .replace("\\t", "\t")
        .replace("\\\\", "\\")
        .replace('\\', "")
}
<commit_msg>paste: Write to a locked stdout<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Alex Lyon <arcterus@mail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (ToDO) delim

use clap::{crate_version, App, AppSettings, Arg};
use std::fs::File;
use std::io::{stdin, BufRead, BufReader, Read, stdout, Write};
use std::path::Path;
use uucore::error::{FromIo, UResult};

static ABOUT: &str = "Write lines consisting of the sequentially corresponding lines from each
FILE, separated by TABs, to standard output.";

mod options {
    pub const DELIMITER: &str = "delimiters";
    pub const SERIAL: &str = "serial";
    pub const FILE: &str = "file";
}

// Wraps BufReader and stdin
fn read_line<R: Read>(
    reader: Option<&mut BufReader<R>>,
    buf: &mut String,
) -> std::io::Result<usize> {
    match reader {
        Some(reader) => reader.read_line(buf),
        None => stdin().read_line(buf),
    }
}

#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
    let matches = uu_app().get_matches_from(args);

    let serial = matches.is_present(options::SERIAL);
    let delimiters = matches.value_of(options::DELIMITER).unwrap();
    let files = matches
        .values_of(options::FILE)
        .unwrap()
        .map(|s| s.to_owned())
        .collect();
    paste(files, serial, delimiters)
}

pub fn uu_app<'a>() -> App<'a> {
    App::new(uucore::util_name())
        .version(crate_version!())
        .about(ABOUT)
        .setting(AppSettings::InferLongArgs)
        .arg(
            Arg::new(options::SERIAL)
                .long(options::SERIAL)
                .short('s')
                .help("paste one file at a time instead of in parallel"),
        )
        .arg(
            Arg::new(options::DELIMITER)
                .long(options::DELIMITER)
                .short('d')
                .help("reuse characters from LIST instead of TABs")
                .value_name("LIST")
                .default_value("\t")
                .hide_default_value(true),
        )
        .arg(
            Arg::new(options::FILE)
                .value_name("FILE")
                .multiple_occurrences(true)
                .default_value("-"),
        )
}

fn paste(filenames: Vec<String>, serial: bool, delimiters: &str) -> UResult<()> {
    let mut files = vec![];
    for name in filenames {
        let file = if name == "-" {
            None
        } else {
            let path = Path::new(&name);
            let r = File::open(path).map_err_context(String::new)?;
            Some(BufReader::new(r))
        };
        files.push(file);
    }

    let delimiters: Vec<char> = unescape(delimiters).chars().collect();
    let mut delim_count = 0;
    let stdout = stdout();
    let mut stdout = stdout.lock();

    let mut line = String::new();
    if serial {
        for file in &mut files {
            let mut output = String::new();
            loop {
                line.clear();
                match read_line(file.as_mut(), &mut line) {
                    Ok(0) => break,
                    Ok(_) => {
                        output.push_str(line.trim_end());
                        output.push(delimiters[delim_count % delimiters.len()]);
                    }
                    Err(e) => return Err(e.map_err_context(String::new)),
                }
                delim_count += 1;
            }
            output.pop();
            writeln!(stdout, "{}", output)?;
        }
    } else {
        let mut eof = vec![false; files.len()];
        loop {
            let mut output = String::new();
            let mut eof_count = 0;
            for (i, file) in files.iter_mut().enumerate() {
                if eof[i] {
                    eof_count += 1;
                } else {
                    line.clear();
                    match read_line(file.as_mut(), &mut line) {
                        Ok(0) => {
                            eof[i] = true;
                            eof_count += 1;
                        }
                        Ok(_) => output.push_str(line.trim_end()),
                        Err(e) => return Err(e.map_err_context(String::new)),
                    }
                }
                output.push(delimiters[delim_count % delimiters.len()]);
                delim_count += 1;
            }
            if files.len() == eof_count {
                break;
            }
            // Remove final delimiter
            output.pop();
            writeln!(stdout, "{}", output)?;
            delim_count = 0;
        }
    }
    Ok(())
}

// Unescape all special characters
// TODO: this will need work to conform to GNU implementation
fn unescape(s: &str) -> String {
    s.replace("\\n", "\n")
        .replace("\\t", "\t")
        .replace("\\\\", "\\")
        .replace('\\', "")
}
<|endoftext|>


<commit_before>//! Extended attribute support for darwin
extern crate libc;

use std::ffi::CString;
use std::ptr;
use std::mem;
use std::old_io as io;
use self::libc::{c_int, size_t, ssize_t, c_char, c_void, uint32_t};

/// Don't follow symbolic links
const XATTR_NOFOLLOW: c_int = 0x0001;
/// Expose HFS Compression extended attributes
const XATTR_SHOWCOMPRESSION: c_int = 0x0020;

extern "C" {
    fn listxattr(path: *const c_char, namebuf: *mut c_char,
                 size: size_t, options: c_int) -> ssize_t;
    fn getxattr(path: *const c_char, name: *const c_char,
                value: *mut c_void, size: size_t, position: uint32_t,
                options: c_int) -> ssize_t;
}

/// Attributes which can be passed to `Attribute::list_with_flags`
#[derive(Copy)]
pub enum ListFlags {
    /// Don't follow symbolic links
    NoFollow = XATTR_NOFOLLOW as isize,
    /// Expose HFS Compression extended attributes
    ShowCompression = XATTR_SHOWCOMPRESSION as isize
}

/// Extended attribute
#[derive(Debug, Clone)]
pub struct Attribute {
    name: String,
    size: usize,
}

impl Attribute {
    /// Lists the extended attribute of `path`.
    /// Does follow symlinks by default.
    pub fn list(path: &Path, flags: &[ListFlags]) -> io::IoResult<Vec<Attribute>> {
        let mut c_flags: c_int = 0;
        for &flag in flags.iter() {
            c_flags |= flag as c_int
        }
        let c_path = try!(CString::new(path.as_vec()));
        let bufsize = unsafe { listxattr(
            c_path.as_ptr(),
            ptr::null_mut(),
            0, c_flags
        )} as isize;
        if bufsize > 0 {
            let mut buf = vec![0u8; bufsize as usize];
            let err = unsafe { listxattr(
                c_path.as_ptr(),
                buf.as_mut_ptr() as *mut c_char,
                bufsize as size_t, c_flags
            )};
            if err > 0 {
                // End indicies of the attribute names
                // the buffer contains 0-terminates c-strings
                let idx = buf.iter().enumerate().filter_map(|(i, v)|
                    if *v == 0 { Some(i) } else { None }
                );
                let mut names = Vec::new();
                let mut start = 0;
                for end in idx {
                    let size = unsafe {
                        getxattr(
                            c_path.as_ptr(),
                            buf[start..end+1].as_ptr() as *const c_char,
                            ptr::null_mut(), 0, 0, c_flags
                        )
                    };
                    if size > 0 {
                        names.push(Attribute {
                            name: unsafe {
                                // buf is guaranteed to contain valid utf8 strings
                                // see man listxattr
                                mem::transmute::<&[u8], &str>(&buf[start..end]).to_string()
                            },
                            size: size as usize
                        });
                    }
                    start = end + 1;
                }
                Ok(names)
            } else {
                // Ignore error for now
                Ok(Vec::new())
            }
        } else {
            // Ignore error for now
            Ok(Vec::new())
        }
    }

    /// Getter for name
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Getter for size
    pub fn size(&self) -> usize {
        self.size
    }
}

/// Lists the extended attributes.
/// Follows symlinks like `stat`
pub fn list(path: &Path) -> io::IoResult<Vec<Attribute>> {
    Attribute::list(path, &[])
}
/// Lists the extended attributes.
/// Does not follow symlinks like `lstat`
pub fn llist(path: &Path) -> io::IoResult<Vec<Attribute>> {
    Attribute::list(path, &[ListFlags::NoFollow])
}

/// Returns true if the extended attribute feature is implemented on this platform.
#[inline(always)]
pub fn feature_implemented() -> bool { true }<commit_msg>Better error handling<commit_after>//! Extended attribute support for darwin
extern crate libc;

use std::ffi::CString;
use std::ptr;
use std::mem;
use std::old_io as io;
use self::libc::{c_int, size_t, ssize_t, c_char, c_void, uint32_t};

/// Don't follow symbolic links
const XATTR_NOFOLLOW: c_int = 0x0001;
/// Expose HFS Compression extended attributes
const XATTR_SHOWCOMPRESSION: c_int = 0x0020;

extern "C" {
    fn listxattr(path: *const c_char, namebuf: *mut c_char,
                 size: size_t, options: c_int) -> ssize_t;
    fn getxattr(path: *const c_char, name: *const c_char,
                value: *mut c_void, size: size_t, position: uint32_t,
                options: c_int) -> ssize_t;
}

/// Attributes which can be passed to `Attribute::list_with_flags`
#[derive(Copy)]
pub enum ListFlags {
    /// Don't follow symbolic links
    NoFollow = XATTR_NOFOLLOW as isize,
    /// Expose HFS Compression extended attributes
    ShowCompression = XATTR_SHOWCOMPRESSION as isize
}

/// Extended attribute
#[derive(Debug, Clone)]
pub struct Attribute {
    name: String,
    size: usize,
}

impl Attribute {
    /// Lists the extended attribute of `path`.
    /// Does follow symlinks by default.
    pub fn list(path: &Path, flags: &[ListFlags]) -> io::IoResult<Vec<Attribute>> {
        let mut c_flags: c_int = 0;
        for &flag in flags.iter() {
            c_flags |= flag as c_int
        }
        let c_path = try!(CString::new(path.as_vec()));
        let bufsize = unsafe { listxattr(
            c_path.as_ptr(),
            ptr::null_mut(),
            0, c_flags
        )} as isize;
        if bufsize > 0 {
            let mut buf = vec![0u8; bufsize as usize];
            let err = unsafe { listxattr(
                c_path.as_ptr(),
                buf.as_mut_ptr() as *mut c_char,
                bufsize as size_t, c_flags
            )};
            if err > 0 {
                // End indicies of the attribute names
                // the buffer contains 0-terminates c-strings
                let idx = buf.iter().enumerate().filter_map(|(i, v)|
                    if *v == 0 { Some(i) } else { None }
                );
                let mut names = Vec::new();
                let mut start = 0;
                for end in idx {
                    let size = unsafe {
                        getxattr(
                            c_path.as_ptr(),
                            buf[start..end+1].as_ptr() as *const c_char,
                            ptr::null_mut(), 0, 0, c_flags
                        )
                    };
                    if size > 0 {
                        names.push(Attribute {
                            name: unsafe {
                                // buf is guaranteed to contain valid utf8 strings
                                // see man listxattr
                                mem::transmute::<&[u8], &str>(&buf[start..end]).to_string()
                            },
                            size: size as usize
                        });
                    }
                    start = end + 1;
                }
                Ok(names)
            } else {
                Err(io::IoError {
                    kind: io::OtherIoError,
                    desc: "could not read extended attributes",
                    detail: None
                })
            }
        } else {
            Err(io::IoError {
                kind: io::OtherIoError,
                desc: "could not read extended attributes",
                detail: None
            })
        }
    }

    /// Getter for name
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Getter for size
    pub fn size(&self) -> usize {
        self.size
    }
}

/// Lists the extended attributes.
/// Follows symlinks like `stat`
pub fn list(path: &Path) -> io::IoResult<Vec<Attribute>> {
    Attribute::list(path, &[])
}
/// Lists the extended attributes.
/// Does not follow symlinks like `lstat`
pub fn llist(path: &Path) -> io::IoResult<Vec<Attribute>> {
    Attribute::list(path, &[ListFlags::NoFollow])
}

/// Returns true if the extended attribute feature is implemented on this platform.
#[inline(always)]
pub fn feature_implemented() -> bool { true }<|endoftext|>