<commit_before>#[derive(Clone)]
pub struct VecMap<K, V> {
    vec: Vec<(K, V)>,
}

impl<K: PartialEq, V> VecMap<K, V> {
    #[inline]
    pub fn with_capacity(cap: usize) -> VecMap<K, V> {
        VecMap {
            vec: Vec::with_capacity(cap)
        }
    }

    #[inline]
    pub fn insert(&mut self, key: K, value: V) {
        match self.find(&key) {
            Some(pos) => self.vec[pos] = (key, value),
            None => self.vec.push((key, value))
        }
    }

    #[inline]
    pub fn append(&mut self, key: K, value: V) {
        self.vec.push((key, value));
    }

    #[inline]
    pub fn entry(&mut self, key: K) -> Entry<K, V> {
        match self.find(&key) {
            Some(pos) => Entry::Occupied(OccupiedEntry {
                vec: self,
                pos: pos,
            }),
            None => Entry::Vacant(VacantEntry {
                vec: self,
                key: key,
            })
        }
    }

    #[inline]
    pub fn get<K2: PartialEq<K> + ?Sized>(&self, key: &K2) -> Option<&V> {
        self.find(key).map(move |pos| &self.vec[pos].1)
    }

    #[inline]
    pub fn get_mut<K2: PartialEq<K> + ?Sized>(&mut self, key: &K2) -> Option<&mut V> {
        self.find(key).map(move |pos| &mut self.vec[pos].1)
    }

    #[inline]
    pub fn contains_key<K2: PartialEq<K> + ?Sized>(&self, key: &K2) -> bool {
        self.find(key).is_some()
    }

    #[inline]
    pub fn len(&self) -> usize { self.vec.len() }

    #[inline]
    pub fn iter(&self) -> ::std::slice::Iter<(K, V)> {
        self.vec.iter()
    }

    #[inline]
    pub fn remove<K2: PartialEq<K> + ?Sized>(&mut self, key: &K2) -> Option<V> {
        self.find(key).map(|pos| self.vec.remove(pos)).map(|(_, v)| v)
    }

    #[inline]
    pub fn remove_all<K2: PartialEq<K> + ?Sized>(&mut self, key: &K2) {
        let len = self.vec.len();
        for i in (0..len).rev() {
            if key == &self.vec[i].0 {
                self.vec.remove(i);
            }
        }
    }

    #[inline]
    pub fn clear(&mut self) {
        self.vec.clear();
    }

    #[inline]
    fn find<K2: PartialEq<K> + ?Sized>(&self, key: &K2) -> Option<usize> {
        self.vec.iter().position(|entry| key == &entry.0)
    }
}

pub enum Entry<'a, K: 'a, V: 'a> {
    Vacant(VacantEntry<'a, K, V>),
    Occupied(OccupiedEntry<'a, K, V>)
}

pub struct VacantEntry<'a, K: 'a, V: 'a> {
    vec: &'a mut VecMap<K, V>,
    key: K,
}

impl<'a, K, V> VacantEntry<'a, K, V> {
    pub fn insert(self, val: V) -> &'a mut V {
        let mut vec = self.vec;
        vec.vec.push((self.key, val));
        let pos = vec.vec.len() - 1;
        &mut vec.vec[pos].1
    }
}

pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
    vec: &'a mut VecMap<K, V>,
    pos: usize,
}

impl<'a, K, V> OccupiedEntry<'a, K, V> {
    pub fn into_mut(self) -> &'a mut V {
        &mut self.vec.vec[self.pos].1
    }
}
<commit_msg>perf(header): speed up VecMap insert and get<commit_after>#[derive(Clone)]
pub struct VecMap<K, V> {
    vec: Vec<(K, V)>,
}

impl<K: PartialEq, V> VecMap<K, V> {
    #[inline]
    pub fn with_capacity(cap: usize) -> VecMap<K, V> {
        VecMap {
            vec: Vec::with_capacity(cap)
        }
    }

    #[inline]
    pub fn insert(&mut self, key: K, value: V) {
        // not using entry or find_mut because of borrowck
        for entry in &mut self.vec {
            if key == entry.0 {
                *entry = (key, value);
                return;
            }
        }
        self.vec.push((key, value));
    }

    #[inline]
    pub fn append(&mut self, key: K, value: V) {
        self.vec.push((key, value));
    }

    #[inline]
    pub fn entry(&mut self, key: K) -> Entry<K, V> {
        match self.pos(&key) {
            Some(pos) => Entry::Occupied(OccupiedEntry {
                vec: &mut self.vec,
                pos: pos,
            }),
            None => Entry::Vacant(VacantEntry {
                vec: &mut self.vec,
                key: key,
            })
        }
    }

    #[inline]
    pub fn get<K2: PartialEq<K> + ?Sized>(&self, key: &K2) -> Option<&V> {
        self.find(key).map(|entry| &entry.1)
    }

    #[inline]
    pub fn get_mut<K2: PartialEq<K> + ?Sized>(&mut self, key: &K2) -> Option<&mut V> {
        self.find_mut(key).map(|entry| &mut entry.1)
    }

    #[inline]
    pub fn contains_key<K2: PartialEq<K> + ?Sized>(&self, key: &K2) -> bool {
        self.find(key).is_some()
    }

    #[inline]
    pub fn len(&self) -> usize { self.vec.len() }

    #[inline]
    pub fn iter(&self) -> ::std::slice::Iter<(K, V)> {
        self.vec.iter()
    }

    #[inline]
    pub fn remove<K2: PartialEq<K> + ?Sized>(&mut self, key: &K2) -> Option<V> {
        self.pos(key).map(|pos| self.vec.remove(pos)).map(|(_, v)| v)
    }

    #[inline]
    pub fn remove_all<K2: PartialEq<K> + ?Sized>(&mut self, key: &K2) {
        let len = self.vec.len();
        for i in (0..len).rev() {
            if key == &self.vec[i].0 {
                self.vec.remove(i);
            }
        }
    }

    #[inline]
    pub fn clear(&mut self) {
        self.vec.clear();
    }

    #[inline]
    fn find<K2: PartialEq<K> + ?Sized>(&self, key: &K2) -> Option<&(K, V)> {
        for entry in &self.vec {
            if key == &entry.0 {
                return Some(entry);
            }
        }
        None
    }

    #[inline]
    fn find_mut<K2: PartialEq<K> + ?Sized>(&mut self, key: &K2) -> Option<&mut (K, V)> {
        for entry in &mut self.vec {
            if key == &entry.0 {
                return Some(entry);
            }
        }
        None
    }

    #[inline]
    fn pos<K2: PartialEq<K> + ?Sized>(&self, key: &K2) -> Option<usize> {
        self.vec.iter().position(|entry| key == &entry.0)
    }
}

pub enum Entry<'a, K: 'a, V: 'a> {
    Vacant(VacantEntry<'a, K, V>),
    Occupied(OccupiedEntry<'a, K, V>)
}

pub struct VacantEntry<'a, K: 'a, V: 'a> {
    vec: &'a mut Vec<(K, V)>,
    key: K,
}

impl<'a, K, V> VacantEntry<'a, K, V> {
    pub fn insert(self, val: V) -> &'a mut V {
        self.vec.push((self.key, val));
        let pos = self.vec.len() - 1;
        &mut self.vec[pos].1
    }
}

pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
    vec: &'a mut Vec<(K, V)>,
    pos: usize,
}

impl<'a, K, V> OccupiedEntry<'a, K, V> {
    pub fn into_mut(self) -> &'a mut V {
        &mut self.vec[self.pos].1
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2020 Google LLC All Rights Reserved.
 *
 * 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
 *
 *     http://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 std::io;
use std::marker::PhantomData;
use std::net::SocketAddr;

use base64_serde::base64_serde_type;
use serde::{Deserialize, Serialize};
use uuid::Uuid;

mod builder;
mod endpoints;
mod error;
mod metadata;

pub use crate::config::endpoints::{
    EmptyListError, Endpoints, UpstreamEndpoints, UpstreamEndpointsIter,
};
pub(crate) use crate::config::error::ValueInvalidArgs;
pub use builder::Builder;
pub use error::ValidationError;
pub(crate) use metadata::{extract_endpoint_tokens, parse_endpoint_metadata_from_yaml};

base64_serde_type!(Base64Standard, base64::STANDARD);

#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum Version {
    #[serde(rename = "v1alpha1")]
    V1Alpha1,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Proxy {
    #[serde(default = "default_proxy_id")]
    pub id: String,
    #[serde(default = "default_proxy_port")]
    pub port: u16,
}

fn default_proxy_id() -> String {
    Uuid::new_v4().to_hyphenated().to_string()
}

fn default_proxy_port() -> u16 {
    7000
}

impl Default for Proxy {
    fn default() -> Self {
        Proxy {
            id: default_proxy_id(),
            port: default_proxy_port(),
        }
    }
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AdminAddress {
    port: u16,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Admin {
    address: Option<AdminAddress>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct ManagementServer {
    pub address: String,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum Source {
    #[serde(rename = "static")]
    Static {
        #[serde(default)]
        filters: Vec<Filter>,

        endpoints: Vec<EndPoint>,
    },
    #[serde(rename = "dynamic")]
    Dynamic {
        management_servers: Vec<ManagementServer>,
    },
}

/// Config is the configuration for either a Client or Server proxy
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Config {
    pub version: Version,

    #[serde(default)]
    pub proxy: Proxy,

    pub admin: Option<Admin>,

    #[serde(flatten)]
    pub source: Source,

    // Limit struct creation to the builder. We use an Optional<Phantom>
    // so that we can create instances though deserialization.
    #[serde(skip_serializing)]
    pub(super) phantom: Option<PhantomData<()>>,
}

impl Source {
    /// Returns the list of filters if the config is a static config and None otherwise.
    /// This is a convenience function and should only be used for doc tests and tests.
    pub fn get_static_filters(&self) -> Option<&[Filter]> {
        match self {
            Source::Static {
                filters,
                endpoints: _,
            } => Some(filters),
            Source::Dynamic {
                management_servers: _,
            } => None,
        }
    }
}

/// Filter is the configuration for a single filter
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct Filter {
    pub name: String,
    pub config: Option<serde_yaml::Value>,
}

/// A singular endpoint, to pass on UDP packets to.
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)]
pub struct EndPoint {
    pub address: SocketAddr,
    pub metadata: Option<serde_yaml::Value>,
}

impl EndPoint {
    pub fn new(address: SocketAddr) -> Self {
        EndPoint::with_metadata(address, None)
    }

    pub fn with_metadata(address: SocketAddr, metadata: Option<serde_yaml::Value>) -> Self {
        EndPoint { address, metadata }
    }
}

impl Config {
    /// from_reader returns a config from a given Reader
    pub fn from_reader<R: io::Read>(input: R) -> Result<Config, serde_yaml::Error> {
        serde_yaml::from_reader(input)
    }
}

#[cfg(test)]
mod tests {
    use serde_yaml::Value;

    use crate::config::{Builder, Config, EndPoint, ManagementServer, Source};
    use std::collections::HashMap;

    fn parse_config(yaml: &str) -> Config {
        Config::from_reader(yaml.as_bytes()).unwrap()
    }

    fn assert_static_endpoints(source: &Source, expected_endpoints: Vec<EndPoint>) {
        match source {
            Source::Static {
                filters: _,
                endpoints,
            } => {
                assert_eq!(&expected_endpoints, endpoints,);
            }
            _ => unreachable!("expected static config source"),
        }
    }

    fn assert_management_servers(source: &Source, expected: Vec<ManagementServer>) {
        match source {
            Source::Dynamic { management_servers } => {
                assert_eq!(&expected, management_servers,);
            }
            _ => unreachable!("expected dynamic config source"),
        }
    }

    #[test]
    fn deserialise_client() {
        let config = Builder::empty()
            .with_port(7000)
            .with_static(
                vec![],
                vec![EndPoint::new("127.0.0.1:25999".parse().unwrap())],
            )
            .build();
        let _ = serde_yaml::to_string(&config).unwrap();
    }

    #[test]
    fn deserialise_server() {
        let config = Builder::empty()
            .with_port(7000)
            .with_static(
                vec![],
                vec![
                    EndPoint::new("127.0.0.1:26000".parse().unwrap()),
                    EndPoint::new("127.0.0.1:26001".parse().unwrap()),
                ],
            )
            .build();
        let _ = serde_yaml::to_string(&config).unwrap();
    }

    #[test]
    fn parse_default_values() {
        let yaml = "
version: v1alpha1
static:
  endpoints:
    - address: 127.0.0.1:25999
  ";
        let config = parse_config(yaml);

        assert_eq!(config.proxy.port, 7000);
        assert_eq!(config.proxy.id.len(), 36);
    }

    #[test]
    fn parse_filter_config() {
        let yaml = "
version: v1alpha1
proxy:
  id: client-proxy
  port: 7000 # the port to receive traffic to locally
static:
  filters: # new filters section
    - name: quilkin.core.v1.rate-limiter
      config:
        map: of arbitrary key value pairs
        could:
          - also
          - be
          - 27
          - true
  endpoints:
    - address: 127.0.0.1:7001
        ";
        let config = parse_config(yaml);

        let filter = config.source.get_static_filters().unwrap().get(0).unwrap();
        assert_eq!("quilkin.core.v1.rate-limiter", filter.name);
        let config = filter.config.as_ref().unwrap();
        let filter_config = config.as_mapping().unwrap();

        let key = Value::from("map");
        assert_eq!(
            "of arbitrary key value pairs",
            filter_config.get(&key).unwrap().as_str().unwrap()
        );

        let key = Value::from("could");
        let could = filter_config.get(&key).unwrap().as_sequence().unwrap();
        assert_eq!("also", could.get(0).unwrap().as_str().unwrap());
        assert_eq!("be", could.get(1).unwrap().as_str().unwrap());
        assert_eq!(27, could.get(2).unwrap().as_i64().unwrap());
        assert_eq!(true, could.get(3).unwrap().as_bool().unwrap());
    }

    #[test]
    fn parse_proxy() {
        let yaml = "
version: v1alpha1
proxy:
  id: server-proxy
  port: 7000
static:
  endpoints:
    - address: 127.0.0.1:25999
  ";
        let config = parse_config(yaml);

        assert_eq!(config.proxy.port, 7000);
        assert_eq!(config.proxy.id.as_str(), "server-proxy");
    }

    #[test]
    fn parse_client() {
        let yaml = "
version: v1alpha1
static:
  endpoints:
    - name: ep-1
      address: 127.0.0.1:25999
  ";
        let config = parse_config(yaml);

        assert_static_endpoints(
            &config.source,
            vec![EndPoint::new("127.0.0.1:25999".parse().unwrap())],
        );
    }

    #[test]
    fn parse_server() {
        let yaml = "
---
version: v1alpha1
static:
  endpoints:
    - address: 127.0.0.1:26000
      metadata:
        quilkin.dev:
          tokens:
            - MXg3aWp5Ng== #1x7ijy6
            - OGdqM3YyaQ== #8gj3v2i
    - address: 127.0.0.1:26001
      metadata:
        quilkin.dev:
          tokens:
            - bmt1eTcweA== #nkuy70x";
        let config = parse_config(yaml);
        assert_static_endpoints(
            &config.source,
            vec![
                EndPoint::with_metadata(
                    "127.0.0.1:26000".parse().unwrap(),
                    Some(
                        serde_yaml::to_value(
                            vec![(
                                "quilkin.dev",
                                vec![("tokens", vec!["MXg3aWp5Ng==", "OGdqM3YyaQ=="])]
                                    .into_iter()
                                    .collect::<HashMap<_, _>>(),
                            )]
                            .into_iter()
                            .collect::<HashMap<_, _>>(),
                        )
                        .unwrap(),
                    ),
                ),
                EndPoint::with_metadata(
                    "127.0.0.1:26001".parse().unwrap(),
                    Some(
                        serde_yaml::to_value(
                            vec![(
                                "quilkin.dev",
                                vec![("tokens", vec!["bmt1eTcweA=="])]
                                    .into_iter()
                                    .collect::<HashMap<_, _>>(),
                            )]
                            .into_iter()
                            .collect::<HashMap<_, _>>(),
                        )
                        .unwrap(),
                    ),
                ),
            ],
        );
    }

    #[test]
    fn parse_dynamic_source() {
        let yaml = "
version: v1alpha1
dynamic:
  filters:
    - name: quilkin.core.v1.rate-limiter
      config:
        map: of arbitrary key value pairs
        could:
          - also
          - be
          - 27
          - true
  management_servers:
    - address: 127.0.0.1:25999
    - address: 127.0.0.1:30000
  ";
        let config = parse_config(yaml);

        assert_management_servers(
            &config.source,
            vec![
                ManagementServer {
                    address: "127.0.0.1:25999".into(),
                },
                ManagementServer {
                    address: "127.0.0.1:30000".into(),
                },
            ],
        );
    }
}
<commit_msg>Fix old comment on Config. (#216)<commit_after>/*
 * Copyright 2020 Google LLC All Rights Reserved.
 *
 * 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
 *
 *     http://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 std::io;
use std::marker::PhantomData;
use std::net::SocketAddr;

use base64_serde::base64_serde_type;
use serde::{Deserialize, Serialize};
use uuid::Uuid;

mod builder;
mod endpoints;
mod error;
mod metadata;

pub use crate::config::endpoints::{
    EmptyListError, Endpoints, UpstreamEndpoints, UpstreamEndpointsIter,
};
pub(crate) use crate::config::error::ValueInvalidArgs;
pub use builder::Builder;
pub use error::ValidationError;
pub(crate) use metadata::{extract_endpoint_tokens, parse_endpoint_metadata_from_yaml};

base64_serde_type!(Base64Standard, base64::STANDARD);

#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum Version {
    #[serde(rename = "v1alpha1")]
    V1Alpha1,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Proxy {
    #[serde(default = "default_proxy_id")]
    pub id: String,
    #[serde(default = "default_proxy_port")]
    pub port: u16,
}

fn default_proxy_id() -> String {
    Uuid::new_v4().to_hyphenated().to_string()
}

fn default_proxy_port() -> u16 {
    7000
}

impl Default for Proxy {
    fn default() -> Self {
        Proxy {
            id: default_proxy_id(),
            port: default_proxy_port(),
        }
    }
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AdminAddress {
    port: u16,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Admin {
    address: Option<AdminAddress>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct ManagementServer {
    pub address: String,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum Source {
    #[serde(rename = "static")]
    Static {
        #[serde(default)]
        filters: Vec<Filter>,

        endpoints: Vec<EndPoint>,
    },
    #[serde(rename = "dynamic")]
    Dynamic {
        management_servers: Vec<ManagementServer>,
    },
}

/// Config is the configuration of a proxy
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Config {
    pub version: Version,

    #[serde(default)]
    pub proxy: Proxy,

    pub admin: Option<Admin>,

    #[serde(flatten)]
    pub source: Source,

    // Limit struct creation to the builder. We use an Optional<Phantom>
    // so that we can create instances though deserialization.
    #[serde(skip_serializing)]
    pub(super) phantom: Option<PhantomData<()>>,
}

impl Source {
    /// Returns the list of filters if the config is a static config and None otherwise.
    /// This is a convenience function and should only be used for doc tests and tests.
    pub fn get_static_filters(&self) -> Option<&[Filter]> {
        match self {
            Source::Static {
                filters,
                endpoints: _,
            } => Some(filters),
            Source::Dynamic {
                management_servers: _,
            } => None,
        }
    }
}

/// Filter is the configuration for a single filter
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct Filter {
    pub name: String,
    pub config: Option<serde_yaml::Value>,
}

/// A singular endpoint, to pass on UDP packets to.
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)]
pub struct EndPoint {
    pub address: SocketAddr,
    pub metadata: Option<serde_yaml::Value>,
}

impl EndPoint {
    pub fn new(address: SocketAddr) -> Self {
        EndPoint::with_metadata(address, None)
    }

    pub fn with_metadata(address: SocketAddr, metadata: Option<serde_yaml::Value>) -> Self {
        EndPoint { address, metadata }
    }
}

impl Config {
    /// from_reader returns a config from a given Reader
    pub fn from_reader<R: io::Read>(input: R) -> Result<Config, serde_yaml::Error> {
        serde_yaml::from_reader(input)
    }
}

#[cfg(test)]
mod tests {
    use serde_yaml::Value;

    use crate::config::{Builder, Config, EndPoint, ManagementServer, Source};
    use std::collections::HashMap;

    fn parse_config(yaml: &str) -> Config {
        Config::from_reader(yaml.as_bytes()).unwrap()
    }

    fn assert_static_endpoints(source: &Source, expected_endpoints: Vec<EndPoint>) {
        match source {
            Source::Static {
                filters: _,
                endpoints,
            } => {
                assert_eq!(&expected_endpoints, endpoints,);
            }
            _ => unreachable!("expected static config source"),
        }
    }

    fn assert_management_servers(source: &Source, expected: Vec<ManagementServer>) {
        match source {
            Source::Dynamic { management_servers } => {
                assert_eq!(&expected, management_servers,);
            }
            _ => unreachable!("expected dynamic config source"),
        }
    }

    #[test]
    fn deserialise_client() {
        let config = Builder::empty()
            .with_port(7000)
            .with_static(
                vec![],
                vec![EndPoint::new("127.0.0.1:25999".parse().unwrap())],
            )
            .build();
        let _ = serde_yaml::to_string(&config).unwrap();
    }

    #[test]
    fn deserialise_server() {
        let config = Builder::empty()
            .with_port(7000)
            .with_static(
                vec![],
                vec![
                    EndPoint::new("127.0.0.1:26000".parse().unwrap()),
                    EndPoint::new("127.0.0.1:26001".parse().unwrap()),
                ],
            )
            .build();
        let _ = serde_yaml::to_string(&config).unwrap();
    }

    #[test]
    fn parse_default_values() {
        let yaml = "
version: v1alpha1
static:
  endpoints:
    - address: 127.0.0.1:25999
  ";
        let config = parse_config(yaml);

        assert_eq!(config.proxy.port, 7000);
        assert_eq!(config.proxy.id.len(), 36);
    }

    #[test]
    fn parse_filter_config() {
        let yaml = "
version: v1alpha1
proxy:
  id: client-proxy
  port: 7000 # the port to receive traffic to locally
static:
  filters: # new filters section
    - name: quilkin.core.v1.rate-limiter
      config:
        map: of arbitrary key value pairs
        could:
          - also
          - be
          - 27
          - true
  endpoints:
    - address: 127.0.0.1:7001
        ";
        let config = parse_config(yaml);

        let filter = config.source.get_static_filters().unwrap().get(0).unwrap();
        assert_eq!("quilkin.core.v1.rate-limiter", filter.name);
        let config = filter.config.as_ref().unwrap();
        let filter_config = config.as_mapping().unwrap();

        let key = Value::from("map");
        assert_eq!(
            "of arbitrary key value pairs",
            filter_config.get(&key).unwrap().as_str().unwrap()
        );

        let key = Value::from("could");
        let could = filter_config.get(&key).unwrap().as_sequence().unwrap();
        assert_eq!("also", could.get(0).unwrap().as_str().unwrap());
        assert_eq!("be", could.get(1).unwrap().as_str().unwrap());
        assert_eq!(27, could.get(2).unwrap().as_i64().unwrap());
        assert_eq!(true, could.get(3).unwrap().as_bool().unwrap());
    }

    #[test]
    fn parse_proxy() {
        let yaml = "
version: v1alpha1
proxy:
  id: server-proxy
  port: 7000
static:
  endpoints:
    - address: 127.0.0.1:25999
  ";
        let config = parse_config(yaml);

        assert_eq!(config.proxy.port, 7000);
        assert_eq!(config.proxy.id.as_str(), "server-proxy");
    }

    #[test]
    fn parse_client() {
        let yaml = "
version: v1alpha1
static:
  endpoints:
    - name: ep-1
      address: 127.0.0.1:25999
  ";
        let config = parse_config(yaml);

        assert_static_endpoints(
            &config.source,
            vec![EndPoint::new("127.0.0.1:25999".parse().unwrap())],
        );
    }

    #[test]
    fn parse_server() {
        let yaml = "
---
version: v1alpha1
static:
  endpoints:
    - address: 127.0.0.1:26000
      metadata:
        quilkin.dev:
          tokens:
            - MXg3aWp5Ng== #1x7ijy6
            - OGdqM3YyaQ== #8gj3v2i
    - address: 127.0.0.1:26001
      metadata:
        quilkin.dev:
          tokens:
            - bmt1eTcweA== #nkuy70x";
        let config = parse_config(yaml);
        assert_static_endpoints(
            &config.source,
            vec![
                EndPoint::with_metadata(
                    "127.0.0.1:26000".parse().unwrap(),
                    Some(
                        serde_yaml::to_value(
                            vec![(
                                "quilkin.dev",
                                vec![("tokens", vec!["MXg3aWp5Ng==", "OGdqM3YyaQ=="])]
                                    .into_iter()
                                    .collect::<HashMap<_, _>>(),
                            )]
                            .into_iter()
                            .collect::<HashMap<_, _>>(),
                        )
                        .unwrap(),
                    ),
                ),
                EndPoint::with_metadata(
                    "127.0.0.1:26001".parse().unwrap(),
                    Some(
                        serde_yaml::to_value(
                            vec![(
                                "quilkin.dev",
                                vec![("tokens", vec!["bmt1eTcweA=="])]
                                    .into_iter()
                                    .collect::<HashMap<_, _>>(),
                            )]
                            .into_iter()
                            .collect::<HashMap<_, _>>(),
                        )
                        .unwrap(),
                    ),
                ),
            ],
        );
    }

    #[test]
    fn parse_dynamic_source() {
        let yaml = "
version: v1alpha1
dynamic:
  filters:
    - name: quilkin.core.v1.rate-limiter
      config:
        map: of arbitrary key value pairs
        could:
          - also
          - be
          - 27
          - true
  management_servers:
    - address: 127.0.0.1:25999
    - address: 127.0.0.1:30000
  ";
        let config = parse_config(yaml);

        assert_management_servers(
            &config.source,
            vec![
                ManagementServer {
                    address: "127.0.0.1:25999".into(),
                },
                ManagementServer {
                    address: "127.0.0.1:30000".into(),
                },
            ],
        );
    }
}
<|endoftext|>


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

//! # Note
//!
//! This API is completely unstable and subject to change.

#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
      html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]

#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(custom_attribute)]
#![allow(unused_attributes)]
#![feature(i128_type)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![feature(slice_patterns)]
#![feature(conservative_impl_trait)]

extern crate ar;
extern crate flate2;
#[macro_use]
extern crate log;

#[macro_use]
extern crate rustc;
extern crate rustc_back;
extern crate rustc_mir;
extern crate rustc_incremental;
#[macro_use]
extern crate syntax;
extern crate syntax_pos;
extern crate rustc_data_structures;

pub extern crate rustc as __rustc;

use rustc::ty::{TyCtxt, Instance};
use rustc::hir;
use rustc::hir::def_id::LOCAL_CRATE;
use rustc::hir::map as hir_map;
use rustc::util::nodemap::NodeSet;

pub mod diagnostics;
pub mod link;
pub mod trans_crate;
pub mod symbol_names;
pub mod symbol_names_test;

/// check for the #[rustc_error] annotation, which forces an
/// error in trans. This is used to write compile-fail tests
/// that actually test that compilation succeeds without
/// reporting an error.
pub fn check_for_rustc_errors_attr(tcx: TyCtxt) {
    if let Some((id, span)) = *tcx.sess.entry_fn.borrow() {
        let main_def_id = tcx.hir.local_def_id(id);

        if tcx.has_attr(main_def_id, "rustc_error") {
            tcx.sess.span_fatal(span, "compilation successful");
        }
    }
}

/// The context provided lists a set of reachable ids as calculated by
/// middle::reachable, but this contains far more ids and symbols than we're
/// actually exposing from the object file. This function will filter the set in
/// the context to the set of ids which correspond to symbols that are exposed
/// from the object file being generated.
///
/// This list is later used by linkers to determine the set of symbols needed to
/// be exposed from a dynamic library and it's also encoded into the metadata.
pub fn find_exported_symbols<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet {
    tcx.reachable_set(LOCAL_CRATE).0.iter().cloned().filter(|&id| {
        // Next, we want to ignore some FFI functions that are not exposed from
        // this crate. Reachable FFI functions can be lumped into two
        // categories:
        //
        // 1. Those that are included statically via a static library
        // 2. Those included otherwise (e.g. dynamically or via a framework)
        //
        // Although our LLVM module is not literally emitting code for the
        // statically included symbols, it's an export of our library which
        // needs to be passed on to the linker and encoded in the metadata.
        //
        // As a result, if this id is an FFI item (foreign item) then we only
        // let it through if it's included statically.
        match tcx.hir.get(id) {
            hir_map::NodeForeignItem(..) => {
                let def_id = tcx.hir.local_def_id(id);
                tcx.is_statically_included_foreign_item(def_id)
            }

            // Only consider nodes that actually have exported symbols.
            hir_map::NodeItem(&hir::Item {
                node: hir::ItemStatic(..), .. }) |
            hir_map::NodeItem(&hir::Item {
                node: hir::ItemFn(..), .. }) |
            hir_map::NodeImplItem(&hir::ImplItem {
                node: hir::ImplItemKind::Method(..), .. }) => {
                let def_id = tcx.hir.local_def_id(id);
                let generics = tcx.generics_of(def_id);
                (generics.parent_types == 0 && generics.types.is_empty()) &&
                // Functions marked with #[inline] are only ever translated
                // with "internal" linkage and are never exported.
                !Instance::mono(tcx, def_id).def.requires_local(tcx)
            }

            _ => false
        }
    }).collect()
}

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

//! # Note
//!
//! This API is completely unstable and subject to change.

#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
      html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]

#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(custom_attribute)]
#![allow(unused_attributes)]
#![feature(i128_type)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![feature(slice_patterns)]
#![feature(conservative_impl_trait)]

extern crate ar;
extern crate flate2;
#[macro_use]
extern crate log;

#[macro_use]
extern crate rustc;
extern crate rustc_back;
extern crate rustc_mir;
extern crate rustc_incremental;
#[macro_use]
extern crate syntax;
extern crate syntax_pos;
extern crate rustc_data_structures;

pub extern crate rustc as __rustc;

use rustc::ty::{TyCtxt, Instance};
use rustc::hir;
use rustc::hir::def_id::LOCAL_CRATE;
use rustc::hir::map as hir_map;
use rustc::util::nodemap::NodeSet;

pub mod diagnostics;
pub mod link;
pub mod trans_crate;
pub mod symbol_names;
pub mod symbol_names_test;

/// check for the #[rustc_error] annotation, which forces an
/// error in trans. This is used to write compile-fail tests
/// that actually test that compilation succeeds without
/// reporting an error.
pub fn check_for_rustc_errors_attr(tcx: TyCtxt) {
    if let Some((id, span)) = *tcx.sess.entry_fn.borrow() {
        let main_def_id = tcx.hir.local_def_id(id);

        if tcx.has_attr(main_def_id, "rustc_error") {
            tcx.sess.span_fatal(span, "compilation successful");
        }
    }
}

/// The context provided lists a set of reachable ids as calculated by
/// middle::reachable, but this contains far more ids and symbols than we're
/// actually exposing from the object file. This function will filter the set in
/// the context to the set of ids which correspond to symbols that are exposed
/// from the object file being generated.
///
/// This list is later used by linkers to determine the set of symbols needed to
/// be exposed from a dynamic library and it's also encoded into the metadata.
pub fn find_exported_symbols<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet {
    tcx.reachable_set(LOCAL_CRATE).0.iter().cloned().filter(|&id| {
        // Next, we want to ignore some FFI functions that are not exposed from
        // this crate. Reachable FFI functions can be lumped into two
        // categories:
        //
        // 1. Those that are included statically via a static library
        // 2. Those included otherwise (e.g. dynamically or via a framework)
        //
        // Although our LLVM module is not literally emitting code for the
        // statically included symbols, it's an export of our library which
        // needs to be passed on to the linker and encoded in the metadata.
        //
        // As a result, if this id is an FFI item (foreign item) then we only
        // let it through if it's included statically.
        match tcx.hir.get(id) {
            hir_map::NodeForeignItem(..) => {
                let def_id = tcx.hir.local_def_id(id);
                tcx.is_statically_included_foreign_item(def_id)
            }

            // Only consider nodes that actually have exported symbols.
            hir_map::NodeItem(&hir::Item {
                node: hir::ItemStatic(..), .. }) |
            hir_map::NodeItem(&hir::Item {
                node: hir::ItemFn(..), .. }) |
            hir_map::NodeImplItem(&hir::ImplItem {
                node: hir::ImplItemKind::Method(..), .. }) => {
                let def_id = tcx.hir.local_def_id(id);
                let generics = tcx.generics_of(def_id);
                (generics.parent_types == 0 && generics.types.is_empty()) &&
                // Functions marked with #[inline] are only ever translated
                // with "internal" linkage and are never exported.
                !Instance::mono(tcx, def_id).def.requires_local(tcx)
            }

            _ => false
        }
    }).collect()
}

#[cfg(not(stage0))] // remove after the next snapshot
__build_diagnostic_array! { librustc_trans_utils, DIAGNOSTICS }
<|endoftext|>


<commit_before>//! Less used details of `CxxVector` are exposed in this module. `CxxVector`
//! itself is exposed at the crate root.

use crate::extern_type::ExternType;
use crate::kind::Trivial;
use crate::string::CxxString;
use core::ffi::c_void;
use core::fmt::{self, Debug, Display};
use core::iter::FusedIterator;
use core::marker::{PhantomData, PhantomPinned};
use core::mem;
use core::pin::Pin;
use core::ptr;
use core::slice;

#[doc(inline)]
pub use crate::Vector;

/// Binding to C++ `std::vector<T, std::allocator<T>>`.
///
/// # Invariants
///
/// As an invariant of this API and the static analysis of the cxx::bridge
/// macro, in Rust code we can never obtain a `CxxVector` by value. Instead in
/// Rust code we will only ever look at a vector behind a reference or smart
/// pointer, as in `&CxxVector<T>` or `UniquePtr<CxxVector<T>>`.
#[repr(C, packed)]
pub struct CxxVector<T> {
    _private: [T; 0],
    _pinned: PhantomData<PhantomPinned>,
}

impl<T> CxxVector<T>
where
    T: VectorElement,
{
    /// Returns the number of elements in the vector.
    ///
    /// Matches the behavior of C++ [std::vector\<T\>::size][size].
    ///
    /// [size]: https://en.cppreference.com/w/cpp/container/vector/size
    pub fn len(&self) -> usize {
        T::__vector_size(self)
    }

    /// Returns true if the vector contains no elements.
    ///
    /// Matches the behavior of C++ [std::vector\<T\>::empty][empty].
    ///
    /// [empty]: https://en.cppreference.com/w/cpp/container/vector/empty
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns a reference to an element at the given position, or `None` if
    /// out of bounds.
    pub fn get(&self, pos: usize) -> Option<&T> {
        if pos < self.len() {
            Some(unsafe { self.get_unchecked(pos) })
        } else {
            None
        }
    }

    /// Returns a pinned mutable reference to an element at the given position,
    /// or `None` if out of bounds.
    pub fn get_mut(&mut self, pos: usize) -> Option<Pin<&mut T>> {
        if pos < self.len() {
            Some(unsafe { self.get_unchecked_mut(pos) })
        } else {
            None
        }
    }

    /// Returns a reference to an element without doing bounds checking.
    ///
    /// This is generally not recommended, use with caution! Calling this method
    /// with an out-of-bounds index is undefined behavior even if the resulting
    /// reference is not used.
    ///
    /// Matches the behavior of C++
    /// [std::vector\<T\>::operator\[\] const][operator_at].
    ///
    /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
    pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
        let this = self as *const CxxVector<T> as *mut CxxVector<T>;
        let ptr = T::__get_unchecked(this, pos) as *const T;
        &*ptr
    }

    /// Returns a pinned mutable reference to an element without doing bounds
    /// checking.
    ///
    /// This is generally not recommended, use with caution! Calling this method
    /// with an out-of-bounds index is undefined behavior even if the resulting
    /// reference is not used.
    ///
    /// Matches the behavior of C++
    /// [std::vector\<T\>::operator\[\]][operator_at].
    ///
    /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
    pub unsafe fn get_unchecked_mut(&mut self, pos: usize) -> Pin<&mut T> {
        let ptr = T::__get_unchecked(self, pos);
        Pin::new_unchecked(&mut *ptr)
    }

    /// Returns a slice to the underlying contiguous array of elements.
    pub fn as_slice(&self) -> &[T]
    where
        T: ExternType<Kind = Trivial>,
    {
        let len = self.len();
        if len == 0 {
            // The slice::from_raw_parts in the other branch requires a nonnull
            // and properly aligned data ptr. C++ standard does not guarantee
            // that data() on a vector with size 0 would return a nonnull
            // pointer or sufficiently aligned pointer, so using it would be
            // undefined behavior. Create our own empty slice in Rust instead
            // which upholds the invariants.
            &[]
        } else {
            let this = self as *const CxxVector<T> as *mut CxxVector<T>;
            let ptr = unsafe { T::__get_unchecked(this, 0) };
            unsafe { slice::from_raw_parts(ptr, len) }
        }
    }

    /// Returns an iterator over elements of type `&T`.
    pub fn iter(&self) -> Iter<T> {
        Iter { v: self, index: 0 }
    }
}

/// Iterator over elements of a `CxxVector` by shared reference.
///
/// The iterator element type is `&'a T`.
pub struct Iter<'a, T> {
    v: &'a CxxVector<T>,
    index: usize,
}

impl<'a, T> IntoIterator for &'a CxxVector<T>
where
    T: VectorElement,
{
    type Item = &'a T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, T> Iterator for Iter<'a, T>
where
    T: VectorElement,
{
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.v.get(self.index);
        self.index += next.is_some() as usize;
        next
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.len();
        (len, Some(len))
    }
}

impl<'a, T> ExactSizeIterator for Iter<'a, T>
where
    T: VectorElement,
{
    fn len(&self) -> usize {
        self.v.len() - self.index
    }
}

impl<'a, T> FusedIterator for Iter<'a, T> where T: VectorElement {}

impl<T> Debug for CxxVector<T>
where
    T: VectorElement + Debug,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.debug_list().entries(self).finish()
    }
}

pub(crate) struct TypeName<T> {
    element: PhantomData<T>,
}

impl<T> TypeName<T> {
    pub const fn new() -> Self {
        TypeName {
            element: PhantomData,
        }
    }
}

impl<T> Display for TypeName<T>
where
    T: VectorElement,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "CxxVector<{}>", T::__NAME)
    }
}

// Methods are private; not intended to be implemented outside of cxxbridge
// codebase.
#[doc(hidden)]
pub unsafe trait VectorElement: Sized {
    const __NAME: &'static dyn Display;
    fn __vector_size(v: &CxxVector<Self>) -> usize;
    unsafe fn __get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut Self;
    fn __unique_ptr_null() -> *mut c_void;
    unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void;
    unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self>;
    unsafe fn __unique_ptr_release(repr: *mut c_void) -> *mut CxxVector<Self>;
    unsafe fn __unique_ptr_drop(repr: *mut c_void);
}

macro_rules! impl_vector_element {
    ($segment:expr, $name:expr, $ty:ty) => {
        const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>());

        unsafe impl VectorElement for $ty {
            const __NAME: &'static dyn Display = &$name;
            fn __vector_size(v: &CxxVector<$ty>) -> usize {
                extern "C" {
                    attr! {
                        #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$size")]
                        fn __vector_size(_: &CxxVector<$ty>) -> usize;
                    }
                }
                unsafe { __vector_size(v) }
            }
            unsafe fn __get_unchecked(v: *mut CxxVector<$ty>, pos: usize) -> *mut $ty {
                extern "C" {
                    attr! {
                        #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$get_unchecked")]
                        fn __get_unchecked(_: *mut CxxVector<$ty>, _: usize) -> *mut $ty;
                    }
                }
                __get_unchecked(v, pos)
            }
            fn __unique_ptr_null() -> *mut c_void {
                extern "C" {
                    attr! {
                        #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$null")]
                        fn __unique_ptr_null(this: *mut *mut c_void);
                    }
                }
                let mut repr = ptr::null_mut::<c_void>();
                unsafe { __unique_ptr_null(&mut repr) }
                repr
            }
            unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void {
                extern "C" {
                    attr! {
                        #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$raw")]
                        fn __unique_ptr_raw(this: *mut *mut c_void, raw: *mut CxxVector<$ty>);
                    }
                }
                let mut repr = ptr::null_mut::<c_void>();
                __unique_ptr_raw(&mut repr, raw);
                repr
            }
            unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self> {
                extern "C" {
                    attr! {
                        #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$get")]
                        fn __unique_ptr_get(this: *const *mut c_void) -> *const CxxVector<$ty>;
                    }
                }
                __unique_ptr_get(&repr)
            }
            unsafe fn __unique_ptr_release(mut repr: *mut c_void) -> *mut CxxVector<Self> {
                extern "C" {
                    attr! {
                        #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$release")]
                        fn __unique_ptr_release(this: *mut *mut c_void) -> *mut CxxVector<$ty>;
                    }
                }
                __unique_ptr_release(&mut repr)
            }
            unsafe fn __unique_ptr_drop(mut repr: *mut c_void) {
                extern "C" {
                    attr! {
                        #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$drop")]
                        fn __unique_ptr_drop(this: *mut *mut c_void);
                    }
                }
                __unique_ptr_drop(&mut repr);
            }
        }
    };
}

macro_rules! impl_vector_element_for_primitive {
    ($ty:ident) => {
        impl_vector_element!(stringify!($ty), stringify!($ty), $ty);
    };
}

impl_vector_element_for_primitive!(u8);
impl_vector_element_for_primitive!(u16);
impl_vector_element_for_primitive!(u32);
impl_vector_element_for_primitive!(u64);
impl_vector_element_for_primitive!(usize);
impl_vector_element_for_primitive!(i8);
impl_vector_element_for_primitive!(i16);
impl_vector_element_for_primitive!(i32);
impl_vector_element_for_primitive!(i64);
impl_vector_element_for_primitive!(isize);
impl_vector_element_for_primitive!(f32);
impl_vector_element_for_primitive!(f64);

impl_vector_element!("string", "CxxString", CxxString);
<commit_msg>Simplify CxxVector iterator next method<commit_after>//! Less used details of `CxxVector` are exposed in this module. `CxxVector`
//! itself is exposed at the crate root.

use crate::extern_type::ExternType;
use crate::kind::Trivial;
use crate::string::CxxString;
use core::ffi::c_void;
use core::fmt::{self, Debug, Display};
use core::iter::FusedIterator;
use core::marker::{PhantomData, PhantomPinned};
use core::mem;
use core::pin::Pin;
use core::ptr;
use core::slice;

#[doc(inline)]
pub use crate::Vector;

/// Binding to C++ `std::vector<T, std::allocator<T>>`.
///
/// # Invariants
///
/// As an invariant of this API and the static analysis of the cxx::bridge
/// macro, in Rust code we can never obtain a `CxxVector` by value. Instead in
/// Rust code we will only ever look at a vector behind a reference or smart
/// pointer, as in `&CxxVector<T>` or `UniquePtr<CxxVector<T>>`.
#[repr(C, packed)]
pub struct CxxVector<T> {
    _private: [T; 0],
    _pinned: PhantomData<PhantomPinned>,
}

impl<T> CxxVector<T>
where
    T: VectorElement,
{
    /// Returns the number of elements in the vector.
    ///
    /// Matches the behavior of C++ [std::vector\<T\>::size][size].
    ///
    /// [size]: https://en.cppreference.com/w/cpp/container/vector/size
    pub fn len(&self) -> usize {
        T::__vector_size(self)
    }

    /// Returns true if the vector contains no elements.
    ///
    /// Matches the behavior of C++ [std::vector\<T\>::empty][empty].
    ///
    /// [empty]: https://en.cppreference.com/w/cpp/container/vector/empty
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns a reference to an element at the given position, or `None` if
    /// out of bounds.
    pub fn get(&self, pos: usize) -> Option<&T> {
        if pos < self.len() {
            Some(unsafe { self.get_unchecked(pos) })
        } else {
            None
        }
    }

    /// Returns a pinned mutable reference to an element at the given position,
    /// or `None` if out of bounds.
    pub fn get_mut(&mut self, pos: usize) -> Option<Pin<&mut T>> {
        if pos < self.len() {
            Some(unsafe { self.get_unchecked_mut(pos) })
        } else {
            None
        }
    }

    /// Returns a reference to an element without doing bounds checking.
    ///
    /// This is generally not recommended, use with caution! Calling this method
    /// with an out-of-bounds index is undefined behavior even if the resulting
    /// reference is not used.
    ///
    /// Matches the behavior of C++
    /// [std::vector\<T\>::operator\[\] const][operator_at].
    ///
    /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
    pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
        let this = self as *const CxxVector<T> as *mut CxxVector<T>;
        let ptr = T::__get_unchecked(this, pos) as *const T;
        &*ptr
    }

    /// Returns a pinned mutable reference to an element without doing bounds
    /// checking.
    ///
    /// This is generally not recommended, use with caution! Calling this method
    /// with an out-of-bounds index is undefined behavior even if the resulting
    /// reference is not used.
    ///
    /// Matches the behavior of C++
    /// [std::vector\<T\>::operator\[\]][operator_at].
    ///
    /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
    pub unsafe fn get_unchecked_mut(&mut self, pos: usize) -> Pin<&mut T> {
        let ptr = T::__get_unchecked(self, pos);
        Pin::new_unchecked(&mut *ptr)
    }

    /// Returns a slice to the underlying contiguous array of elements.
    pub fn as_slice(&self) -> &[T]
    where
        T: ExternType<Kind = Trivial>,
    {
        let len = self.len();
        if len == 0 {
            // The slice::from_raw_parts in the other branch requires a nonnull
            // and properly aligned data ptr. C++ standard does not guarantee
            // that data() on a vector with size 0 would return a nonnull
            // pointer or sufficiently aligned pointer, so using it would be
            // undefined behavior. Create our own empty slice in Rust instead
            // which upholds the invariants.
            &[]
        } else {
            let this = self as *const CxxVector<T> as *mut CxxVector<T>;
            let ptr = unsafe { T::__get_unchecked(this, 0) };
            unsafe { slice::from_raw_parts(ptr, len) }
        }
    }

    /// Returns an iterator over elements of type `&T`.
    pub fn iter(&self) -> Iter<T> {
        Iter { v: self, index: 0 }
    }
}

/// Iterator over elements of a `CxxVector` by shared reference.
///
/// The iterator element type is `&'a T`.
pub struct Iter<'a, T> {
    v: &'a CxxVector<T>,
    index: usize,
}

impl<'a, T> IntoIterator for &'a CxxVector<T>
where
    T: VectorElement,
{
    type Item = &'a T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, T> Iterator for Iter<'a, T>
where
    T: VectorElement,
{
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.v.get(self.index)?;
        self.index += 1;
        Some(next)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.len();
        (len, Some(len))
    }
}

impl<'a, T> ExactSizeIterator for Iter<'a, T>
where
    T: VectorElement,
{
    fn len(&self) -> usize {
        self.v.len() - self.index
    }
}

impl<'a, T> FusedIterator for Iter<'a, T> where T: VectorElement {}

impl<T> Debug for CxxVector<T>
where
    T: VectorElement + Debug,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.debug_list().entries(self).finish()
    }
}

pub(crate) struct TypeName<T> {
    element: PhantomData<T>,
}

impl<T> TypeName<T> {
    pub const fn new() -> Self {
        TypeName {
            element: PhantomData,
        }
    }
}

impl<T> Display for TypeName<T>
where
    T: VectorElement,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "CxxVector<{}>", T::__NAME)
    }
}

// Methods are private; not intended to be implemented outside of cxxbridge
// codebase.
#[doc(hidden)]
pub unsafe trait VectorElement: Sized {
    const __NAME: &'static dyn Display;
    fn __vector_size(v: &CxxVector<Self>) -> usize;
    unsafe fn __get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut Self;
    fn __unique_ptr_null() -> *mut c_void;
    unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void;
    unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self>;
    unsafe fn __unique_ptr_release(repr: *mut c_void) -> *mut CxxVector<Self>;
    unsafe fn __unique_ptr_drop(repr: *mut c_void);
}

macro_rules! impl_vector_element {
    ($segment:expr, $name:expr, $ty:ty) => {
        const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>());

        unsafe impl VectorElement for $ty {
            const __NAME: &'static dyn Display = &$name;
            fn __vector_size(v: &CxxVector<$ty>) -> usize {
                extern "C" {
                    attr! {
                        #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$size")]
                        fn __vector_size(_: &CxxVector<$ty>) -> usize;
                    }
                }
                unsafe { __vector_size(v) }
            }
            unsafe fn __get_unchecked(v: *mut CxxVector<$ty>, pos: usize) -> *mut $ty {
                extern "C" {
                    attr! {
                        #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$get_unchecked")]
                        fn __get_unchecked(_: *mut CxxVector<$ty>, _: usize) -> *mut $ty;
                    }
                }
                __get_unchecked(v, pos)
            }
            fn __unique_ptr_null() -> *mut c_void {
                extern "C" {
                    attr! {
                        #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$null")]
                        fn __unique_ptr_null(this: *mut *mut c_void);
                    }
                }
                let mut repr = ptr::null_mut::<c_void>();
                unsafe { __unique_ptr_null(&mut repr) }
                repr
            }
            unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void {
                extern "C" {
                    attr! {
                        #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$raw")]
                        fn __unique_ptr_raw(this: *mut *mut c_void, raw: *mut CxxVector<$ty>);
                    }
                }
                let mut repr = ptr::null_mut::<c_void>();
                __unique_ptr_raw(&mut repr, raw);
                repr
            }
            unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self> {
                extern "C" {
                    attr! {
                        #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$get")]
                        fn __unique_ptr_get(this: *const *mut c_void) -> *const CxxVector<$ty>;
                    }
                }
                __unique_ptr_get(&repr)
            }
            unsafe fn __unique_ptr_release(mut repr: *mut c_void) -> *mut CxxVector<Self> {
                extern "C" {
                    attr! {
                        #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$release")]
                        fn __unique_ptr_release(this: *mut *mut c_void) -> *mut CxxVector<$ty>;
                    }
                }
                __unique_ptr_release(&mut repr)
            }
            unsafe fn __unique_ptr_drop(mut repr: *mut c_void) {
                extern "C" {
                    attr! {
                        #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$drop")]
                        fn __unique_ptr_drop(this: *mut *mut c_void);
                    }
                }
                __unique_ptr_drop(&mut repr);
            }
        }
    };
}

macro_rules! impl_vector_element_for_primitive {
    ($ty:ident) => {
        impl_vector_element!(stringify!($ty), stringify!($ty), $ty);
    };
}

impl_vector_element_for_primitive!(u8);
impl_vector_element_for_primitive!(u16);
impl_vector_element_for_primitive!(u32);
impl_vector_element_for_primitive!(u64);
impl_vector_element_for_primitive!(usize);
impl_vector_element_for_primitive!(i8);
impl_vector_element_for_primitive!(i16);
impl_vector_element_for_primitive!(i32);
impl_vector_element_for_primitive!(i64);
impl_vector_element_for_primitive!(isize);
impl_vector_element_for_primitive!(f32);
impl_vector_element_for_primitive!(f64);

impl_vector_element!("string", "CxxString", CxxString);
<|endoftext|>


<commit_before>use dbus::{Connection, ConnPath, BusType};
use dbus::stdintf::OrgFreedesktopDBusProperties;

use general::{NM_DEVICE_INTERFACE, NM_SERVICE_INTERFACE, NM_SERVICE_PATH};
use dbus_helper::{variant_to_string_list, manager_path, property_as_string, property_as_i64,
                  property_as_bool};

#[derive(Debug)]
pub struct Device {
    interface: String,
    path: String,
    device_type: DeviceType,
    state: DeviceState,
    real: bool,
}

impl From<i64> for DeviceState {
    fn from(state: i64) -> Self {
        match state {
            0 => DeviceState::Unknown,
            10 => DeviceState::Unmanaged,
            20 => DeviceState::Unavailable,
            30 => DeviceState::Disconnected,
            100 => DeviceState::Activated,
            110 => DeviceState::Deactivating,
            120 => DeviceState::Failed,
            _ => DeviceState::Unknown,

        }
    }
}

#[derive(Debug)]
pub enum DeviceType {
    Unknown,
    Generic,
    Ethernet,
    WiFi,
    Bridge,
}

impl From<i64> for DeviceType {
    fn from(state: i64) -> Self {
        match state {
            0 => DeviceType::Unknown,
            14 => DeviceType::Generic,
            1 => DeviceType::Ethernet,
            2 => DeviceType::WiFi,
            13 => DeviceType::Bridge,
            _ => DeviceType::Unknown,

        }
    }
}

#[derive(Debug)]
pub enum DeviceState {
    Unknown,
    Unmanaged,
    Unavailable,
    Disconnected,
    Activated,
    Deactivating,
    Failed,
}

/// Get a list of Network Manager devices.
///
/// # Examples
///
/// ```
/// let devices = network_manager::device::list().unwrap();
/// println!("{:?}", devices);
/// ```
pub fn list() -> Result<Vec<Device>, String> {
    let connection = Connection::get_private(BusType::System).unwrap();

    let path = manager_path(&connection, NM_SERVICE_PATH);

    let devices = path.get(NM_SERVICE_INTERFACE, "Devices").unwrap();

    let device_paths = variant_to_string_list(devices).unwrap();

    let mut result = Vec::new();

    for device_path in device_paths {
        let path = manager_path(&connection, &device_path);

        let interface = device_string(&path, "Interface").unwrap();

        let device_type = DeviceType::from(device_i64(&path, "DeviceType").unwrap());

        let state = DeviceState::from(device_i64(&path, "State").unwrap());

        let real = device_bool(&path, "Real").unwrap();

        let device = Device {
            interface: interface,
            path: device_path.clone(),
            device_type: device_type,
            state: state,
            real: real,
        };

        result.push(device);
    }

    Ok(result)
}

#[test]
fn test_list_function() {
    let devices = list().unwrap();
    assert!(devices.len() > 0);
}

/// Enables a Network Manager device.
///
/// # Examples
///
/// ```
/// let devices = network_manager::device::list().unwrap();
/// let device = &devices[0];
/// let state = network_manager::device::enable(device, 10).unwrap();
/// println!("{:?}", state);
/// ```
pub fn enable(c: &Device, t: i32) -> Result<DeviceState, String> {
    // Enable device

    if t != 0 {
        // Wait until the device state is 'Activated' or
        // until the time has elapsed
    }

    Ok(DeviceState::Activated)
}

/// Disables a Network Manager device.
///
/// # Examples
///
/// ```
/// let devices = network_manager::device::list().unwrap();
/// let device = &devices[0];
/// let state = network_manager::device::disable(device, 10).unwrap();
/// println!("{:?}", state);
/// ```
pub fn disable(c: &Device, t: i32) -> Result<DeviceState, String> {
    // Disable device

    if t != 0 {
        // Wait until the device state is 'Unavailable' or
        // until the time has elapsed
    }

    Ok(DeviceState::Unavailable)
}

fn device_string(path: &ConnPath<&Connection>, property: &str) -> Option<String> {
    property_as_string(path, NM_DEVICE_INTERFACE, property)
}

fn device_i64(path: &ConnPath<&Connection>, property: &str) -> Option<i64> {
    property_as_i64(path, NM_DEVICE_INTERFACE, property)
}

fn device_bool(path: &ConnPath<&Connection>, property: &str) -> Option<bool> {
    property_as_bool(path, NM_DEVICE_INTERFACE, property)
}
<commit_msg>Moving DeviceState From implementation to the proper location<commit_after>use dbus::{Connection, ConnPath, BusType};
use dbus::stdintf::OrgFreedesktopDBusProperties;

use general::{NM_DEVICE_INTERFACE, NM_SERVICE_INTERFACE, NM_SERVICE_PATH};
use dbus_helper::{variant_to_string_list, manager_path, property_as_string, property_as_i64,
                  property_as_bool};

#[derive(Debug)]
pub struct Device {
    interface: String,
    path: String,
    device_type: DeviceType,
    state: DeviceState,
    real: bool,
}

#[derive(Debug)]
pub enum DeviceType {
    Unknown,
    Generic,
    Ethernet,
    WiFi,
    Bridge,
}

impl From<i64> for DeviceType {
    fn from(state: i64) -> Self {
        match state {
            0 => DeviceType::Unknown,
            14 => DeviceType::Generic,
            1 => DeviceType::Ethernet,
            2 => DeviceType::WiFi,
            13 => DeviceType::Bridge,
            _ => DeviceType::Unknown,

        }
    }
}

#[derive(Debug)]
pub enum DeviceState {
    Unknown,
    Unmanaged,
    Unavailable,
    Disconnected,
    Activated,
    Deactivating,
    Failed,
}

impl From<i64> for DeviceState {
    fn from(state: i64) -> Self {
        match state {
            0 => DeviceState::Unknown,
            10 => DeviceState::Unmanaged,
            20 => DeviceState::Unavailable,
            30 => DeviceState::Disconnected,
            100 => DeviceState::Activated,
            110 => DeviceState::Deactivating,
            120 => DeviceState::Failed,
            _ => DeviceState::Unknown,

        }
    }
}

/// Get a list of Network Manager devices.
///
/// # Examples
///
/// ```
/// let devices = network_manager::device::list().unwrap();
/// println!("{:?}", devices);
/// ```
pub fn list() -> Result<Vec<Device>, String> {
    let connection = Connection::get_private(BusType::System).unwrap();

    let path = manager_path(&connection, NM_SERVICE_PATH);

    let devices = path.get(NM_SERVICE_INTERFACE, "Devices").unwrap();

    let device_paths = variant_to_string_list(devices).unwrap();

    let mut result = Vec::new();

    for device_path in device_paths {
        let path = manager_path(&connection, &device_path);

        let interface = device_string(&path, "Interface").unwrap();

        let device_type = DeviceType::from(device_i64(&path, "DeviceType").unwrap());

        let state = DeviceState::from(device_i64(&path, "State").unwrap());

        let real = device_bool(&path, "Real").unwrap();

        let device = Device {
            interface: interface,
            path: device_path.clone(),
            device_type: device_type,
            state: state,
            real: real,
        };

        result.push(device);
    }

    Ok(result)
}

#[test]
fn test_list_function() {
    let devices = list().unwrap();
    assert!(devices.len() > 0);
}

/// Enables a Network Manager device.
///
/// # Examples
///
/// ```
/// let devices = network_manager::device::list().unwrap();
/// let device = &devices[0];
/// let state = network_manager::device::enable(device, 10).unwrap();
/// println!("{:?}", state);
/// ```
pub fn enable(c: &Device, t: i32) -> Result<DeviceState, String> {
    // Enable device

    if t != 0 {
        // Wait until the device state is 'Activated' or
        // until the time has elapsed
    }

    Ok(DeviceState::Activated)
}

/// Disables a Network Manager device.
///
/// # Examples
///
/// ```
/// let devices = network_manager::device::list().unwrap();
/// let device = &devices[0];
/// let state = network_manager::device::disable(device, 10).unwrap();
/// println!("{:?}", state);
/// ```
pub fn disable(c: &Device, t: i32) -> Result<DeviceState, String> {
    // Disable device

    if t != 0 {
        // Wait until the device state is 'Unavailable' or
        // until the time has elapsed
    }

    Ok(DeviceState::Unavailable)
}

fn device_string(path: &ConnPath<&Connection>, property: &str) -> Option<String> {
    property_as_string(path, NM_DEVICE_INTERFACE, property)
}

fn device_i64(path: &ConnPath<&Connection>, property: &str) -> Option<i64> {
    property_as_i64(path, NM_DEVICE_INTERFACE, property)
}

fn device_bool(path: &ConnPath<&Connection>, property: &str) -> Option<bool> {
    property_as_bool(path, NM_DEVICE_INTERFACE, property)
}
<|endoftext|>


<commit_before>use std;

use manager;
use manager::NetworkManager;

#[derive(Debug)]
pub struct Device {
    pub interface: String,
    pub path: String,
    pub device_type: DeviceType,
    pub state: DeviceState,
    pub real: bool,
}

impl Device {
    pub fn from_path(manager: &NetworkManager, path: &String) -> Result<Device, String> {
        let interface = try!(manager.get_device_interface(&path));

        let device_type = try!(manager.get_device_type(&path));

        let state = try!(manager.get_device_state(&path));

        let real = try!(manager.is_device_real(&path));

        Ok(Device {
               interface: interface,
               path: path.clone(),
               device_type: device_type,
               state: state,
               real: real,
           })
    }
}

#[derive(Debug)]
pub enum DeviceType {
    Unknown,
    Generic,
    Ethernet,
    WiFi,
    Bridge,
}

impl From<i64> for DeviceType {
    fn from(state: i64) -> Self {
        match state {
            0 => DeviceType::Unknown,
            14 => DeviceType::Generic,
            1 => DeviceType::Ethernet,
            2 => DeviceType::WiFi,
            13 => DeviceType::Bridge,
            _ => DeviceType::Unknown,

        }
    }
}

#[derive(Debug, PartialEq)]
pub enum DeviceState {
    Unknown,
    Unmanaged,
    Unavailable,
    Disconnected,
    Activated,
    Deactivating,
    Failed,
}

impl From<i64> for DeviceState {
    fn from(state: i64) -> Self {
        match state {
            0 => DeviceState::Unknown,
            10 => DeviceState::Unmanaged,
            20 => DeviceState::Unavailable,
            30 => DeviceState::Disconnected,
            100 => DeviceState::Activated,
            110 => DeviceState::Deactivating,
            120 => DeviceState::Failed,
            _ => DeviceState::Unknown,

        }
    }
}

/// Get a list of Network Manager devices.
///
/// # Examples
///
/// ```
/// use network_manager::device;
/// use network_manager::manager;
/// let manager = manager::new();
/// let devices = device::list(&manager).unwrap();
/// println!("{:?}", devices);
/// ```
pub fn list(manager: &NetworkManager) -> Result<Vec<Device>, String> {
    let device_paths = try!(manager.get_devices());

    let mut result = Vec::new();

    for path in device_paths {
        let device = try!(Device::from_path(manager, &path));

        result.push(device);
    }

    Ok(result)
}

#[test]
fn test_list_function() {
    let manager = manager::new();
    let devices = list(&manager).unwrap();
    assert!(devices.len() > 0);
}

/// Connects a Network Manager device.
///
/// # Examples
///
/// ```
/// use network_manager::device;
/// use network_manager::manager;
/// let manager = manager::new();
/// let mut devices = device::list(&manager).unwrap();
/// let device = &mut devices[0];
/// device::connect(&manager, device, 10).unwrap();
/// ```
pub fn connect(manager: &NetworkManager, device: &mut Device, time_out: i32) -> Result<(), String> {
    match device.state {
        DeviceState::Activated => Ok(()),
        _ => {
            try!(manager.activate_device(&device.path));

            wait(manager, device, time_out, DeviceState::Activated)
        }
    }
}

/// Disconnect a Network Manager device.
///
/// # Examples
///
/// ```
/// use network_manager::device;
/// use network_manager::manager;
/// let manager = manager::new();
/// let mut devices = device::list(&manager).unwrap();
/// let device = &mut devices[0];
/// device::disconnect(&manager, device, 10).unwrap();
/// ```
pub fn disconnect(manager: &NetworkManager,
                  device: &mut Device,
                  time_out: i32)
                  -> Result<(), String> {
    match device.state {
        DeviceState::Disconnected => Ok(()),
        _ => {
            try!(manager.disconnect_device(&device.path));

            wait(manager, device, time_out, DeviceState::Disconnected)
        }
    }
}

fn wait(manager: &NetworkManager,
        device: &mut Device,
        time_out: i32,
        target_state: DeviceState)
        -> Result<(), String> {
    if time_out == 0 {
        return Ok(());
    }

    let mut total_time = 0;

    while total_time < time_out {
        device.state = try!(manager.get_device_state(&device.path));

        if device.state == target_state {
            return Ok(());
        }

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

        total_time += 1;
    }

    Err("service timed out".to_string())
}

#[test]
fn test_connect_disconnect_functions() {
    use connection;

    let manager = manager::new();

    let connections = connection::list(&manager).unwrap();
    let mut connection;

    // set enviorment variable $TEST_WIFI_SSID with the wifi's SSID that you want to test
    // e.g.  export TEST_WIFI_SSID="Resin.io Wifi"
    let wifiEnvVar = "TEST_WIFI_SSID";
    match ::std::env::var(wifiEnvVar) {
        Ok(ssid) => {
            connection = connections
                .iter()
                .filter(|c| c.settings.ssid == ssid)
                .nth(0)
                .unwrap()
                .clone()
        }
        Err(e) => {
            panic!("couldn't retrieve enviorment variable {}: {}",
                   wifiEnvVar,
                   e)
        }
    };

    let device_paths = manager
        .get_connection_devices(&connection.active_path)
        .unwrap();
    assert!(device_paths.len() > 0);

    let mut device = Device::from_path(&manager, &device_paths[0]).unwrap();

    if device.state == DeviceState::Activated {
        disconnect(&manager, &mut device, 10).unwrap();
        assert_eq!(DeviceState::Disconnected, device.state);

        connect(&manager, &mut device, 10).unwrap();
        assert_eq!(DeviceState::Activated, device.state);
    } else {
        connect(&manager, &mut device, 10).unwrap();
        assert_eq!(DeviceState::Activated, device.state);

        disconnect(&manager, &mut device, 10).unwrap();
        assert_eq!(DeviceState::Disconnected, device.state);
    }
}
<commit_msg>Testing the wifi device in the device module tests<commit_after>use std;

use manager;
use manager::NetworkManager;

#[derive(Debug)]
pub struct Device {
    pub interface: String,
    pub path: String,
    pub device_type: DeviceType,
    pub state: DeviceState,
    pub real: bool,
}

impl Device {
    pub fn from_path(manager: &NetworkManager, path: &String) -> Result<Device, String> {
        let interface = try!(manager.get_device_interface(&path));

        let device_type = try!(manager.get_device_type(&path));

        let state = try!(manager.get_device_state(&path));

        let real = try!(manager.is_device_real(&path));

        Ok(Device {
               interface: interface,
               path: path.clone(),
               device_type: device_type,
               state: state,
               real: real,
           })
    }
}

#[derive(Debug, PartialEq)]
pub enum DeviceType {
    Unknown,
    Generic,
    Ethernet,
    WiFi,
    Bridge,
}

impl From<i64> for DeviceType {
    fn from(state: i64) -> Self {
        match state {
            0 => DeviceType::Unknown,
            14 => DeviceType::Generic,
            1 => DeviceType::Ethernet,
            2 => DeviceType::WiFi,
            13 => DeviceType::Bridge,
            _ => DeviceType::Unknown,

        }
    }
}

#[derive(Debug, PartialEq)]
pub enum DeviceState {
    Unknown,
    Unmanaged,
    Unavailable,
    Disconnected,
    Activated,
    Deactivating,
    Failed,
}

impl From<i64> for DeviceState {
    fn from(state: i64) -> Self {
        match state {
            0 => DeviceState::Unknown,
            10 => DeviceState::Unmanaged,
            20 => DeviceState::Unavailable,
            30 => DeviceState::Disconnected,
            100 => DeviceState::Activated,
            110 => DeviceState::Deactivating,
            120 => DeviceState::Failed,
            _ => DeviceState::Unknown,

        }
    }
}

/// Get a list of Network Manager devices.
///
/// # Examples
///
/// ```
/// use network_manager::device;
/// use network_manager::manager;
/// let manager = manager::new();
/// let devices = device::list(&manager).unwrap();
/// println!("{:?}", devices);
/// ```
pub fn list(manager: &NetworkManager) -> Result<Vec<Device>, String> {
    let device_paths = try!(manager.get_devices());

    let mut result = Vec::new();

    for path in device_paths {
        let device = try!(Device::from_path(manager, &path));

        result.push(device);
    }

    Ok(result)
}

#[test]
fn test_list_function() {
    let manager = manager::new();
    let devices = list(&manager).unwrap();
    assert!(devices.len() > 0);
}

/// Connects a Network Manager device.
///
/// # Examples
///
/// ```
/// use network_manager::device;
/// use network_manager::manager;
/// let manager = manager::new();
/// let mut devices = device::list(&manager).unwrap();
/// let i = devices.iter().position(|ref d| d.device_type == device::DeviceType::WiFi).unwrap();
/// let device = &mut devices[i];
/// device::connect(&manager, device, 10).unwrap();
/// ```
pub fn connect(manager: &NetworkManager, device: &mut Device, time_out: i32) -> Result<(), String> {
    match device.state {
        DeviceState::Activated => Ok(()),
        _ => {
            try!(manager.activate_device(&device.path));

            wait(manager, device, time_out, DeviceState::Activated)
        }
    }
}

/// Disconnect a Network Manager device.
///
/// # Examples
///
/// ```
/// use network_manager::device;
/// use network_manager::manager;
/// let manager = manager::new();
/// let mut devices = device::list(&manager).unwrap();
/// let i = devices.iter().position(|ref d| d.device_type == device::DeviceType::WiFi).unwrap();
/// let device = &mut devices[i];
/// device::disconnect(&manager, device, 10).unwrap();
/// ```
pub fn disconnect(manager: &NetworkManager,
                  device: &mut Device,
                  time_out: i32)
                  -> Result<(), String> {
    match device.state {
        DeviceState::Disconnected => Ok(()),
        _ => {
            try!(manager.disconnect_device(&device.path));

            wait(manager, device, time_out, DeviceState::Disconnected)
        }
    }
}

fn wait(manager: &NetworkManager,
        device: &mut Device,
        time_out: i32,
        target_state: DeviceState)
        -> Result<(), String> {
    if time_out == 0 {
        return Ok(());
    }

    let mut total_time = 0;

    while total_time < time_out {
        device.state = try!(manager.get_device_state(&device.path));

        if device.state == target_state {
            return Ok(());
        }

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

        total_time += 1;
    }

    Err("service timed out".to_string())
}

#[test]
fn test_connect_disconnect_functions() {
    let manager = manager::new();

    let mut devices = list(&manager).unwrap();

    let i = devices.iter().position(|ref d| d.device_type == DeviceType::WiFi).unwrap();
    let device = &mut devices[i];

    if device.state == DeviceState::Activated {
        disconnect(&manager, device, 10).unwrap();
        assert_eq!(DeviceState::Disconnected, device.state);

        connect(&manager, device, 10).unwrap();
        assert_eq!(DeviceState::Activated, device.state);
    } else {
        connect(&manager, device, 10).unwrap();
        assert_eq!(DeviceState::Activated, device.state);

        disconnect(&manager, device, 10).unwrap();
        assert_eq!(DeviceState::Disconnected, device.state);
    }
}
<|endoftext|>


<commit_before>use std::collections::{HashMap, HashSet};
use ecs::entity::*;

pub trait AssociatesEntities {
    fn has_entity(&self, entity: &Entity) -> bool;

    fn remove_entity(&mut self, entity: &Entity) -> bool;
}

pub trait IsSystem<C> {
    fn add_entity(&mut self, entity: &Entity, component: C) -> bool;

    fn has_component(&self, entity: &Entity) -> bool;

    fn get_component(&self, entity: &Entity) -> Option<&C>;
}

pub struct System<C> {
    entities: HashSet<Entity, EntityHashState>,
    map: HashMap<Entity, C, EntityHashState>
}

impl<C> System<C> {
    pub fn new() -> System<C> {
        System {
            map: HashMap::with_hasher(EntityHashState),
            entities: HashSet::with_hasher(EntityHashState)
        }
    }
}

impl<C> IsSystem<C> for System<C> {
    fn has_component(&self, entity: &Entity) -> bool {
        self.map.contains_key(entity)
    }

    fn add_entity(&mut self, entity: &Entity, component: C) -> bool {
        if self.map.contains_key(entity) {
            false
        } else {
            self.map.insert(*entity, component);
            self.entities.insert(*entity);
            true
        }
    }

    fn get_component(&self, entity: &Entity) -> Option<&C> {
        self.map.get(entity)
    }
}

impl<C> AssociatesEntities for System<C> {
    fn has_entity(&self, entity: &Entity) -> bool {
        self.entities.contains(entity)
    }

    fn remove_entity(&mut self, entity: &Entity) -> bool {
        if self.entities.contains(entity) {
            self.map.remove(entity);
            self.entities.remove(entity);
            true
        } else { false }
    }
}
<commit_msg>Updatable system traits<commit_after>use std::collections::{HashMap, HashSet};
use ecs::entity::{Entity, EntityHashState};
use ecs::container::ContainsMutSystem;

pub trait AssociatesEntities {
    fn has_entity(&self, entity: &Entity) -> bool;

    fn remove_entity(&mut self, entity: &Entity) -> bool;
}

pub trait IsSystem<C>: AssociatesEntities {
    fn add_entity(&mut self, entity: &Entity, component: C) -> bool;

    fn has_component(&self, entity: &Entity) -> bool;

    fn get_component(&self, entity: &Entity) -> Option<&C>;
}

pub trait PostUpdater<E: ContainsMutSystem> {
    fn post_update(self, ecs: &mut E);
}

pub trait IsUpdatableSystem<C, E: ContainsMutSystem, U: PostUpdater<E>>: IsSystem<C> {
    fn update(&mut self, ecs: &E, dt: f64) -> U;
}

pub struct System<C> {
    entities: HashSet<Entity, EntityHashState>,
    map: HashMap<Entity, C, EntityHashState>
}

impl<C> System<C> {
    pub fn new() -> System<C> {
        System {
            map: HashMap::with_hasher(EntityHashState),
            entities: HashSet::with_hasher(EntityHashState)
        }
    }
}

impl<C> IsSystem<C> for System<C> {
    fn has_component(&self, entity: &Entity) -> bool {
        self.map.contains_key(entity)
    }

    fn add_entity(&mut self, entity: &Entity, component: C) -> bool {
        if self.map.contains_key(entity) {
            false
        } else {
            self.map.insert(*entity, component);
            self.entities.insert(*entity);
            true
        }
    }

    fn get_component(&self, entity: &Entity) -> Option<&C> {
        self.map.get(entity)
    }
}

impl<C> AssociatesEntities for System<C> {
    fn has_entity(&self, entity: &Entity) -> bool {
        self.entities.contains(entity)
    }

    fn remove_entity(&mut self, entity: &Entity) -> bool {
        if self.entities.contains(entity) {
            self.map.remove(entity);
            self.entities.remove(entity);
            true
        } else { false }
    }
}
<|endoftext|>


<commit_before>use std::fs::{File, remove_file};
use std::io::{ErrorKind, Read, Write};

use rusoto::{AwsResult, ChainProvider, ProvideAwsCredentials, Region};
use rusoto::kms::{
    DecryptRequest,
    DecryptResponse,
    EncryptRequest,
    EncryptResponse,
    KmsClient,
};
use rustc_serialize::base64::{FromBase64, STANDARD, ToBase64};

use error::{KawsError, KawsResult};

pub struct Encryptor<'a, P> where P: ProvideAwsCredentials {
    client: KmsClient<P>,
    decrypted_files: Vec<String>,
    kms_master_key_id: Option<&'a str>,
}

impl<'a> Encryptor<'a, ChainProvider> {
    pub fn new(
        provider: ChainProvider,
        region: Region,
        kms_master_key_id: Option<&'a str>,
    ) -> Encryptor<'a, ChainProvider> {
        Encryptor {
            client: KmsClient::new(provider, region),
            decrypted_files: vec![],
            kms_master_key_id: kms_master_key_id,
        }
    }

    pub fn decrypt<'b>(&mut self, encrypted_data: &'b str) -> AwsResult<DecryptResponse> {
        let request = DecryptRequest {
            encryption_context: None,
            grant_tokens: None,
            ciphertext_blob: encrypted_data.as_bytes().to_vec()
        };

        self.client.decrypt(&request)
    }

    pub fn decrypt_file<'b>(&mut self, source: &'b str, destination: &'b str) -> KawsResult {
        let mut src = try!(File::open(source));

        let mut encoded_data = String::new();

        try!(src.read_to_string(&mut encoded_data));

        let encrypted_data = try!(encoded_data.from_base64());
        let decrypted_data = try!(self.decrypt(&String::from_utf8_lossy(&encrypted_data)));

        let mut dst = try!(File::create(destination));

        match decrypted_data.plaintext {
            Some(ref plaintext) => try!(dst.write_all(plaintext)),
            None => return Err(KawsError::new("No plaintext was returned from KMS".to_owned())),
        }

        self.decrypted_files.push(destination.to_owned());

        Ok(None)
    }

    pub fn encrypt<'b>(&mut self, decrypted_data: &'b str) -> AwsResult<EncryptResponse> {
        let request = EncryptRequest {
            plaintext: decrypted_data.as_bytes().to_vec(),
            encryption_context: None,
            key_id: self.kms_master_key_id.expect("KMS key must be supplied to encrypt").to_owned(),
            grant_tokens: None,
        };

        self.client.encrypt(&request)
    }

    pub fn encrypt_file<'b>(&mut self, source: &'b str, destination: &'b str) -> KawsResult {
        let mut src = try!(File::open(source));

        let mut contents = String::new();

        try!(src.read_to_string(&mut contents));

        let encrypted_data = try!(self.encrypt(&contents));

        let mut dst = try!(File::create(destination));

        match encrypted_data.ciphertext_blob {
            Some(ref ciphertext_blob) => {
                let encoded_data = ciphertext_blob.to_base64(STANDARD);

                try!(dst.write_all(encoded_data.as_bytes()));
            }
            None => return Err(KawsError::new("No ciphertext was returned from KMS".to_owned())),
        }

        self.decrypted_files.push(source.to_owned());

        Ok(None)
    }
}

impl<'a, P> Drop for Encryptor<'a, P> where P: ProvideAwsCredentials {
    fn drop(&mut self) {
        let mut failures = vec![];

        for file in self.decrypted_files.iter() {
            log_wrap!(&format!("Removing unencrypted file {:?}", file), {
                if let Err(error) = remove_file(file) {
                    match error.kind() {
                        ErrorKind::NotFound => {},
                        _ => failures.push(error),
                    }
                }
            });
        }

        if !failures.is_empty() {
            panic!(
                "Failed to remove one or more encrypted files! You should remove these files \
                manually if they are present: {:?}",
                failures,
            );
        }
    }
}
<commit_msg>Take a Vec instead of a str for encrypt/decrypt.<commit_after>use std::fs::{File, remove_file};
use std::io::{ErrorKind, Read, Write};

use rusoto::{AwsResult, ChainProvider, ProvideAwsCredentials, Region};
use rusoto::kms::{
    DecryptRequest,
    DecryptResponse,
    EncryptRequest,
    EncryptResponse,
    KmsClient,
};
use rustc_serialize::base64::{FromBase64, STANDARD, ToBase64};

use error::{KawsError, KawsResult};

pub struct Encryptor<'a, P> where P: ProvideAwsCredentials {
    client: KmsClient<P>,
    decrypted_files: Vec<String>,
    kms_master_key_id: Option<&'a str>,
}

impl<'a> Encryptor<'a, ChainProvider> {
    pub fn new(
        provider: ChainProvider,
        region: Region,
        kms_master_key_id: Option<&'a str>,
    ) -> Encryptor<'a, ChainProvider> {
        Encryptor {
            client: KmsClient::new(provider, region),
            decrypted_files: vec![],
            kms_master_key_id: kms_master_key_id,
        }
    }

    pub fn decrypt<'b>(&mut self, encrypted_data: Vec<u8>) -> AwsResult<DecryptResponse> {
        let request = DecryptRequest {
            encryption_context: None,
            grant_tokens: None,
            ciphertext_blob: encrypted_data,
        };

        self.client.decrypt(&request)
    }

    pub fn decrypt_file<'b>(&mut self, source: &'b str, destination: &'b str) -> KawsResult {
        let mut src = try!(File::open(source));

        let mut encoded_data = String::new();

        try!(src.read_to_string(&mut encoded_data));

        let encrypted_data = try!(encoded_data.from_base64());
        let decrypted_data = try!(self.decrypt(encrypted_data));

        let mut dst = try!(File::create(destination));

        match decrypted_data.plaintext {
            Some(ref plaintext) => try!(dst.write_all(plaintext)),
            None => return Err(KawsError::new("No plaintext was returned from KMS".to_owned())),
        }

        self.decrypted_files.push(destination.to_owned());

        Ok(None)
    }

    pub fn encrypt<'b>(&mut self, decrypted_data: Vec<u8>) -> AwsResult<EncryptResponse> {
        let request = EncryptRequest {
            plaintext: decrypted_data,
            encryption_context: None,
            key_id: self.kms_master_key_id.expect("KMS key must be supplied to encrypt").to_owned(),
            grant_tokens: None,
        };

        self.client.encrypt(&request)
    }

    pub fn encrypt_file<'b>(&mut self, source: &'b str, destination: &'b str) -> KawsResult {
        let mut src = try!(File::open(source));

        let mut contents = vec![];

        try!(src.read_to_end(&mut contents));

        let encrypted_data = try!(self.encrypt(contents));

        let mut dst = try!(File::create(destination));

        match encrypted_data.ciphertext_blob {
            Some(ref ciphertext_blob) => {
                let encoded_data = ciphertext_blob.to_base64(STANDARD);

                try!(dst.write_all(encoded_data.as_bytes()));
            }
            None => return Err(KawsError::new("No ciphertext was returned from KMS".to_owned())),
        }

        self.decrypted_files.push(source.to_owned());

        Ok(None)
    }
}

impl<'a, P> Drop for Encryptor<'a, P> where P: ProvideAwsCredentials {
    fn drop(&mut self) {
        let mut failures = vec![];

        for file in self.decrypted_files.iter() {
            log_wrap!(&format!("Removing unencrypted file {:?}", file), {
                if let Err(error) = remove_file(file) {
                    match error.kind() {
                        ErrorKind::NotFound => {},
                        _ => failures.push(error),
                    }
                }
            });
        }

        if !failures.is_empty() {
            panic!(
                "Failed to remove one or more encrypted files! You should remove these files \
                manually if they are present: {:?}",
                failures,
            );
        }
    }
}
<|endoftext|>