<commit_before>//! An interpreter for the rust-installer package format.  Responsible
//! for installing from a directory or tarball to an installation
//! prefix, represented by a `Components` instance.

use crate::dist::component::components::*;
use crate::dist::component::transaction::*;

use crate::dist::temp;
use crate::errors::*;
use crate::utils::utils;

use std::collections::HashSet;
use std::fmt;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};

/// The current metadata revision used by rust-installer
pub const INSTALLER_VERSION: &str = "3";
pub const VERSION_FILE: &str = "rust-installer-version";

pub trait Package: fmt::Debug {
    fn contains(&self, component: &str, short_name: Option<&str>) -> bool;
    fn install<'a>(
        &self,
        target: &Components,
        component: &str,
        short_name: Option<&str>,
        tx: Transaction<'a>,
    ) -> Result<Transaction<'a>>;
    fn components(&self) -> Vec<String>;
}

#[derive(Debug)]
pub struct DirectoryPackage {
    path: PathBuf,
    components: HashSet<String>,
    copy: bool,
}

impl DirectoryPackage {
    pub fn new(path: PathBuf, copy: bool) -> Result<Self> {
        validate_installer_version(&path)?;

        let content = utils::read_file("package components", &path.join("components"))?;
        let components = content
            .lines()
            .map(std::borrow::ToOwned::to_owned)
            .collect();
        Ok(DirectoryPackage {
            path,
            components,
            copy,
        })
    }
}

fn validate_installer_version(path: &Path) -> Result<()> {
    let file = utils::read_file("installer version", &path.join(VERSION_FILE))?;
    let v = file.trim();
    if v == INSTALLER_VERSION {
        Ok(())
    } else {
        Err(ErrorKind::BadInstallerVersion(v.to_owned()).into())
    }
}

impl Package for DirectoryPackage {
    fn contains(&self, component: &str, short_name: Option<&str>) -> bool {
        self.components.contains(component)
            || if let Some(n) = short_name {
                self.components.contains(n)
            } else {
                false
            }
    }
    fn install<'a>(
        &self,
        target: &Components,
        name: &str,
        short_name: Option<&str>,
        tx: Transaction<'a>,
    ) -> Result<Transaction<'a>> {
        let actual_name = if self.components.contains(name) {
            name
        } else if let Some(n) = short_name {
            n
        } else {
            name
        };

        let root = self.path.join(actual_name);

        let manifest = utils::read_file("package manifest", &root.join("manifest.in"))?;
        let mut builder = target.add(name, tx);

        for l in manifest.lines() {
            let part = ComponentPart::decode(l)
                .ok_or_else(|| ErrorKind::CorruptComponent(name.to_owned()))?;

            let path = part.1;
            let src_path = root.join(&path);

            match &*part.0 {
                "file" => {
                    if self.copy {
                        builder.copy_file(path.clone(), &src_path)?
                    } else {
                        builder.move_file(path.clone(), &src_path)?
                    }
                }
                "dir" => {
                    if self.copy {
                        builder.copy_dir(path.clone(), &src_path)?
                    } else {
                        builder.move_dir(path.clone(), &src_path)?
                    }
                }
                _ => return Err(ErrorKind::CorruptComponent(name.to_owned()).into()),
            }

            set_file_perms(&target.prefix().path().join(path), &src_path)?;
        }

        let tx = builder.finish()?;

        Ok(tx)
    }

    fn components(&self) -> Vec<String> {
        self.components.iter().cloned().collect()
    }
}

// On Unix we need to set up the file permissions correctly so
// binaries are executable and directories readable. This shouldn't be
// necessary: the source files *should* have the right permissions,
// but due to rust-lang/rust#25479 they don't.
#[cfg(unix)]
fn set_file_perms(dest_path: &Path, src_path: &Path) -> Result<()> {
    use std::fs::{self, Metadata};
    use std::os::unix::fs::PermissionsExt;
    use walkdir::WalkDir;

    // Compute whether this entry needs the X bit
    fn needs_x(meta: &Metadata) -> bool {
        meta.is_dir() || // Directories need it
        meta.permissions().mode() & 0o700 == 0o700 // If it is rwx for the user, it gets the X bit
    }

    // By convention, anything in the bin/ directory of the package is a binary
    let is_bin = if let Some(p) = src_path.parent() {
        p.ends_with("bin")
    } else {
        false
    };

    let is_dir = utils::is_directory(dest_path);

    if is_dir {
        // Walk the directory setting everything
        for entry in WalkDir::new(dest_path) {
            let entry = entry.chain_err(|| ErrorKind::ComponentDirPermissionsFailed)?;
            let meta = entry
                .metadata()
                .chain_err(|| ErrorKind::ComponentDirPermissionsFailed)?;

            let mut perm = meta.permissions();
            perm.set_mode(if needs_x(&meta) { 0o755 } else { 0o644 });
            fs::set_permissions(entry.path(), perm)
                .chain_err(|| ErrorKind::ComponentFilePermissionsFailed)?;
        }
    } else {
        let meta =
            fs::metadata(dest_path).chain_err(|| ErrorKind::ComponentFilePermissionsFailed)?;
        let mut perm = meta.permissions();
        perm.set_mode(if is_bin || needs_x(&meta) {
            0o755
        } else {
            0o644
        });
        fs::set_permissions(dest_path, perm)
            .chain_err(|| ErrorKind::ComponentFilePermissionsFailed)?;
    }

    Ok(())
}

#[cfg(windows)]
fn set_file_perms(_dest_path: &Path, _src_path: &Path) -> Result<()> {
    Ok(())
}

#[derive(Debug)]
pub struct TarPackage<'a>(DirectoryPackage, temp::Dir<'a>);

impl<'a> TarPackage<'a> {
    pub fn new<R: Read>(stream: R, temp_cfg: &'a temp::Cfg) -> Result<Self> {
        let temp_dir = temp_cfg.new_directory()?;
        let mut archive = tar::Archive::new(stream);
        // The rust-installer packages unpack to a directory called
        // $pkgname-$version-$target. Skip that directory when
        // unpacking.
        unpack_without_first_dir(&mut archive, &*temp_dir)?;

        Ok(TarPackage(
            DirectoryPackage::new(temp_dir.to_owned(), false)?,
            temp_dir,
        ))
    }
}

fn unpack_without_first_dir<R: Read>(archive: &mut tar::Archive<R>, path: &Path) -> Result<()> {
    let entries = archive
        .entries()
        .chain_err(|| ErrorKind::ExtractingPackage)?;
    let mut checked_parents: HashSet<PathBuf> = HashSet::new();
    for entry in entries {
        let mut entry = entry.chain_err(|| ErrorKind::ExtractingPackage)?;
        let relpath = {
            let path = entry.path();
            let path = path.chain_err(|| ErrorKind::ExtractingPackage)?;
            path.into_owned()
        };
        let mut components = relpath.components();
        // Throw away the first path component
        components.next();
        let full_path = path.join(&components.as_path());

        // Create the full path to the entry if it does not exist already
        match full_path.parent() {
            Some(parent) => {
                if !checked_parents.contains(parent) {
                    checked_parents.insert(parent.clone().to_owned());
                    // It would be nice to optimise this stat out, but the tar could be like so:
                    // a/deep/file.txt
                    // a/file.txt
                    // which would require tracking the segments rather than a simple hash.
                    // Until profile shows that one stat per dir is a problem (vs one stat per file)
                    // leave till later.

                    if !parent.exists() {
                        ::std::fs::create_dir_all(&parent)
                            .chain_err(|| ErrorKind::ExtractingPackage)?
                    }
                }
            }
            _ => (),
        };

        entry
            .unpack(&full_path)
            .chain_err(|| ErrorKind::ExtractingPackage)?;
    }

    Ok(())
}

impl<'a> Package for TarPackage<'a> {
    fn contains(&self, component: &str, short_name: Option<&str>) -> bool {
        self.0.contains(component, short_name)
    }
    fn install<'b>(
        &self,
        target: &Components,
        component: &str,
        short_name: Option<&str>,
        tx: Transaction<'b>,
    ) -> Result<Transaction<'b>> {
        self.0.install(target, component, short_name, tx)
    }
    fn components(&self) -> Vec<String> {
        self.0.components()
    }
}

#[derive(Debug)]
pub struct TarGzPackage<'a>(TarPackage<'a>);

impl<'a> TarGzPackage<'a> {
    pub fn new<R: Read>(stream: R, temp_cfg: &'a temp::Cfg) -> Result<Self> {
        let stream = flate2::read::GzDecoder::new(stream);
        Ok(TarGzPackage(TarPackage::new(stream, temp_cfg)?))
    }
    pub fn new_file(path: &Path, temp_cfg: &'a temp::Cfg) -> Result<Self> {
        let file = File::open(path).chain_err(|| ErrorKind::ExtractingPackage)?;
        Self::new(file, temp_cfg)
    }
}

impl<'a> Package for TarGzPackage<'a> {
    fn contains(&self, component: &str, short_name: Option<&str>) -> bool {
        self.0.contains(component, short_name)
    }
    fn install<'b>(
        &self,
        target: &Components,
        component: &str,
        short_name: Option<&str>,
        tx: Transaction<'b>,
    ) -> Result<Transaction<'b>> {
        self.0.install(target, component, short_name, tx)
    }
    fn components(&self) -> Vec<String> {
        self.0.components()
    }
}

#[derive(Debug)]
pub struct TarXzPackage<'a>(TarPackage<'a>);

impl<'a> TarXzPackage<'a> {
    pub fn new<R: Read>(stream: R, temp_cfg: &'a temp::Cfg) -> Result<Self> {
        let stream = xz2::read::XzDecoder::new(stream);
        Ok(TarXzPackage(TarPackage::new(stream, temp_cfg)?))
    }
    pub fn new_file(path: &Path, temp_cfg: &'a temp::Cfg) -> Result<Self> {
        let file = File::open(path).chain_err(|| ErrorKind::ExtractingPackage)?;
        Self::new(file, temp_cfg)
    }
}

impl<'a> Package for TarXzPackage<'a> {
    fn contains(&self, component: &str, short_name: Option<&str>) -> bool {
        self.0.contains(component, short_name)
    }
    fn install<'b>(
        &self,
        target: &Components,
        component: &str,
        short_name: Option<&str>,
        tx: Transaction<'b>,
    ) -> Result<Transaction<'b>> {
        self.0.install(target, component, short_name, tx)
    }
    fn components(&self) -> Vec<String> {
        self.0.components()
    }
}
<commit_msg>Remove unused package functions<commit_after>//! An interpreter for the rust-installer package format.  Responsible
//! for installing from a directory or tarball to an installation
//! prefix, represented by a `Components` instance.

use crate::dist::component::components::*;
use crate::dist::component::transaction::*;

use crate::dist::temp;
use crate::errors::*;
use crate::utils::utils;

use std::collections::HashSet;
use std::fmt;
use std::io::Read;
use std::path::{Path, PathBuf};

/// The current metadata revision used by rust-installer
pub const INSTALLER_VERSION: &str = "3";
pub const VERSION_FILE: &str = "rust-installer-version";

pub trait Package: fmt::Debug {
    fn contains(&self, component: &str, short_name: Option<&str>) -> bool;
    fn install<'a>(
        &self,
        target: &Components,
        component: &str,
        short_name: Option<&str>,
        tx: Transaction<'a>,
    ) -> Result<Transaction<'a>>;
    fn components(&self) -> Vec<String>;
}

#[derive(Debug)]
pub struct DirectoryPackage {
    path: PathBuf,
    components: HashSet<String>,
    copy: bool,
}

impl DirectoryPackage {
    pub fn new(path: PathBuf, copy: bool) -> Result<Self> {
        validate_installer_version(&path)?;

        let content = utils::read_file("package components", &path.join("components"))?;
        let components = content
            .lines()
            .map(std::borrow::ToOwned::to_owned)
            .collect();
        Ok(DirectoryPackage {
            path,
            components,
            copy,
        })
    }
}

fn validate_installer_version(path: &Path) -> Result<()> {
    let file = utils::read_file("installer version", &path.join(VERSION_FILE))?;
    let v = file.trim();
    if v == INSTALLER_VERSION {
        Ok(())
    } else {
        Err(ErrorKind::BadInstallerVersion(v.to_owned()).into())
    }
}

impl Package for DirectoryPackage {
    fn contains(&self, component: &str, short_name: Option<&str>) -> bool {
        self.components.contains(component)
            || if let Some(n) = short_name {
                self.components.contains(n)
            } else {
                false
            }
    }
    fn install<'a>(
        &self,
        target: &Components,
        name: &str,
        short_name: Option<&str>,
        tx: Transaction<'a>,
    ) -> Result<Transaction<'a>> {
        let actual_name = if self.components.contains(name) {
            name
        } else if let Some(n) = short_name {
            n
        } else {
            name
        };

        let root = self.path.join(actual_name);

        let manifest = utils::read_file("package manifest", &root.join("manifest.in"))?;
        let mut builder = target.add(name, tx);

        for l in manifest.lines() {
            let part = ComponentPart::decode(l)
                .ok_or_else(|| ErrorKind::CorruptComponent(name.to_owned()))?;

            let path = part.1;
            let src_path = root.join(&path);

            match &*part.0 {
                "file" => {
                    if self.copy {
                        builder.copy_file(path.clone(), &src_path)?
                    } else {
                        builder.move_file(path.clone(), &src_path)?
                    }
                }
                "dir" => {
                    if self.copy {
                        builder.copy_dir(path.clone(), &src_path)?
                    } else {
                        builder.move_dir(path.clone(), &src_path)?
                    }
                }
                _ => return Err(ErrorKind::CorruptComponent(name.to_owned()).into()),
            }

            set_file_perms(&target.prefix().path().join(path), &src_path)?;
        }

        let tx = builder.finish()?;

        Ok(tx)
    }

    fn components(&self) -> Vec<String> {
        self.components.iter().cloned().collect()
    }
}

// On Unix we need to set up the file permissions correctly so
// binaries are executable and directories readable. This shouldn't be
// necessary: the source files *should* have the right permissions,
// but due to rust-lang/rust#25479 they don't.
#[cfg(unix)]
fn set_file_perms(dest_path: &Path, src_path: &Path) -> Result<()> {
    use std::fs::{self, Metadata};
    use std::os::unix::fs::PermissionsExt;
    use walkdir::WalkDir;

    // Compute whether this entry needs the X bit
    fn needs_x(meta: &Metadata) -> bool {
        meta.is_dir() || // Directories need it
        meta.permissions().mode() & 0o700 == 0o700 // If it is rwx for the user, it gets the X bit
    }

    // By convention, anything in the bin/ directory of the package is a binary
    let is_bin = if let Some(p) = src_path.parent() {
        p.ends_with("bin")
    } else {
        false
    };

    let is_dir = utils::is_directory(dest_path);

    if is_dir {
        // Walk the directory setting everything
        for entry in WalkDir::new(dest_path) {
            let entry = entry.chain_err(|| ErrorKind::ComponentDirPermissionsFailed)?;
            let meta = entry
                .metadata()
                .chain_err(|| ErrorKind::ComponentDirPermissionsFailed)?;

            let mut perm = meta.permissions();
            perm.set_mode(if needs_x(&meta) { 0o755 } else { 0o644 });
            fs::set_permissions(entry.path(), perm)
                .chain_err(|| ErrorKind::ComponentFilePermissionsFailed)?;
        }
    } else {
        let meta =
            fs::metadata(dest_path).chain_err(|| ErrorKind::ComponentFilePermissionsFailed)?;
        let mut perm = meta.permissions();
        perm.set_mode(if is_bin || needs_x(&meta) {
            0o755
        } else {
            0o644
        });
        fs::set_permissions(dest_path, perm)
            .chain_err(|| ErrorKind::ComponentFilePermissionsFailed)?;
    }

    Ok(())
}

#[cfg(windows)]
fn set_file_perms(_dest_path: &Path, _src_path: &Path) -> Result<()> {
    Ok(())
}

#[derive(Debug)]
pub struct TarPackage<'a>(DirectoryPackage, temp::Dir<'a>);

impl<'a> TarPackage<'a> {
    pub fn new<R: Read>(stream: R, temp_cfg: &'a temp::Cfg) -> Result<Self> {
        let temp_dir = temp_cfg.new_directory()?;
        let mut archive = tar::Archive::new(stream);
        // The rust-installer packages unpack to a directory called
        // $pkgname-$version-$target. Skip that directory when
        // unpacking.
        unpack_without_first_dir(&mut archive, &*temp_dir)?;

        Ok(TarPackage(
            DirectoryPackage::new(temp_dir.to_owned(), false)?,
            temp_dir,
        ))
    }
}

fn unpack_without_first_dir<R: Read>(archive: &mut tar::Archive<R>, path: &Path) -> Result<()> {
    let entries = archive
        .entries()
        .chain_err(|| ErrorKind::ExtractingPackage)?;
    let mut checked_parents: HashSet<PathBuf> = HashSet::new();
    for entry in entries {
        let mut entry = entry.chain_err(|| ErrorKind::ExtractingPackage)?;
        let relpath = {
            let path = entry.path();
            let path = path.chain_err(|| ErrorKind::ExtractingPackage)?;
            path.into_owned()
        };
        let mut components = relpath.components();
        // Throw away the first path component
        components.next();
        let full_path = path.join(&components.as_path());

        // Create the full path to the entry if it does not exist already
        match full_path.parent() {
            Some(parent) => {
                if !checked_parents.contains(parent) {
                    checked_parents.insert(parent.clone().to_owned());
                    // It would be nice to optimise this stat out, but the tar could be like so:
                    // a/deep/file.txt
                    // a/file.txt
                    // which would require tracking the segments rather than a simple hash.
                    // Until profile shows that one stat per dir is a problem (vs one stat per file)
                    // leave till later.

                    if !parent.exists() {
                        ::std::fs::create_dir_all(&parent)
                            .chain_err(|| ErrorKind::ExtractingPackage)?
                    }
                }
            }
            _ => (),
        };

        entry
            .unpack(&full_path)
            .chain_err(|| ErrorKind::ExtractingPackage)?;
    }

    Ok(())
}

impl<'a> Package for TarPackage<'a> {
    fn contains(&self, component: &str, short_name: Option<&str>) -> bool {
        self.0.contains(component, short_name)
    }
    fn install<'b>(
        &self,
        target: &Components,
        component: &str,
        short_name: Option<&str>,
        tx: Transaction<'b>,
    ) -> Result<Transaction<'b>> {
        self.0.install(target, component, short_name, tx)
    }
    fn components(&self) -> Vec<String> {
        self.0.components()
    }
}

#[derive(Debug)]
pub struct TarGzPackage<'a>(TarPackage<'a>);

impl<'a> TarGzPackage<'a> {
    pub fn new<R: Read>(stream: R, temp_cfg: &'a temp::Cfg) -> Result<Self> {
        let stream = flate2::read::GzDecoder::new(stream);
        Ok(TarGzPackage(TarPackage::new(stream, temp_cfg)?))
    }
}

impl<'a> Package for TarGzPackage<'a> {
    fn contains(&self, component: &str, short_name: Option<&str>) -> bool {
        self.0.contains(component, short_name)
    }
    fn install<'b>(
        &self,
        target: &Components,
        component: &str,
        short_name: Option<&str>,
        tx: Transaction<'b>,
    ) -> Result<Transaction<'b>> {
        self.0.install(target, component, short_name, tx)
    }
    fn components(&self) -> Vec<String> {
        self.0.components()
    }
}

#[derive(Debug)]
pub struct TarXzPackage<'a>(TarPackage<'a>);

impl<'a> TarXzPackage<'a> {
    pub fn new<R: Read>(stream: R, temp_cfg: &'a temp::Cfg) -> Result<Self> {
        let stream = xz2::read::XzDecoder::new(stream);
        Ok(TarXzPackage(TarPackage::new(stream, temp_cfg)?))
    }
}

impl<'a> Package for TarXzPackage<'a> {
    fn contains(&self, component: &str, short_name: Option<&str>) -> bool {
        self.0.contains(component, short_name)
    }
    fn install<'b>(
        &self,
        target: &Components,
        component: &str,
        short_name: Option<&str>,
        tx: Transaction<'b>,
    ) -> Result<Transaction<'b>> {
        self.0.install(target, component, short_name, tx)
    }
    fn components(&self) -> Vec<String> {
        self.0.components()
    }
}
<|endoftext|>


<commit_before>use crate::utils::deserialize::deserialize_opt_duration;
use cosmogony::ZoneType;
use geojson::{GeoJson, Geometry};
use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
use std::time::Duration;

use crate::adapters::primary::common::coord::Coord;
use crate::adapters::primary::common::filters::Filters;
use common::document::ContainerDocument;
use places::{addr::Addr, admin::Admin, poi::Poi, stop::Stop, street::Street};

pub const DEFAULT_LIMIT_RESULT_ES: i64 = 10;

#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ForwardGeocoderExplainQuery {
    pub doc_id: String,
    pub doc_type: String,

    #[serde(flatten)]
    pub query: ForwardGeocoderQuery,
}

/// This structure contains all the query parameters that
/// can be submitted for the autocomplete endpoint.
///
/// Only the `q` parameter is mandatory.
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ForwardGeocoderQuery {
    pub q: String,
    pub lat: Option<f32>,
    pub lon: Option<f32>,
    pub shape_scope: Option<Vec<Type>>,
    #[serde(default, rename = "type")]
    pub types: Option<Vec<Type>>,
    #[serde(default, rename = "zone_type")]
    pub zone_types: Option<Vec<ZoneType>>,
    pub poi_types: Option<Vec<String>>,
    #[serde(default = "default_result_limit")]
    pub limit: i64,
    #[serde(deserialize_with = "deserialize_opt_duration", default)]
    pub timeout: Option<Duration>,
    pub pt_dataset: Option<Vec<String>>,
    pub poi_dataset: Option<Vec<String>>,
    pub request_id: Option<String>,
    pub proximity_scale: Option<f64>,
    pub proximity_offset: Option<f64>,
    pub proximity_decay: Option<f64>,
}

fn default_result_limit() -> i64 {
    DEFAULT_LIMIT_RESULT_ES
}

impl From<(ForwardGeocoderQuery, Option<Geometry>)> for Filters {
    fn from(source: (ForwardGeocoderQuery, Option<Geometry>)) -> Self {
        let (query, geometry) = source;
        let zone_types = query.zone_types.map(|zts| {
            zts.iter()
                .map(|zt| serde_json::to_string(zt).unwrap())
                .collect()
        });
        Filters {
            // When option_zip_option becomes available: coord: input.lat.zip_with(input.lon, Coord::new),
            coord: match (query.lat, query.lon) {
                (Some(lat), Some(lon)) => Some(Coord::new(lat, lon)),
                _ => None,
            },
            shape: geometry.map(|geometry| {
                (
                    geometry,
                    query
                        .shape_scope
                        .map(|shape_scope| {
                            shape_scope.iter().map(|t| t.as_str().to_string()).collect()
                        })
                        .unwrap_or_else(|| {
                            vec![
                                Type::House,
                                Type::Poi,
                                Type::StopArea,
                                Type::Street,
                                Type::Zone,
                            ]
                            .iter()
                            .map(|t| t.as_str().to_string())
                            .collect()
                        }),
                )
            }),
            zone_types,
            poi_types: query.poi_types,
            limit: query.limit,
            timeout: query.timeout,
            proximity_scale: query.proximity_scale,
            proximity_offset: query.proximity_offset,
            proximity_decay: query.proximity_decay,
        }
    }
}

/// This structure contains all the query parameters that
/// can be submitted for the features endpoint.
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct FeaturesQuery {
    pub pt_dataset: Option<Vec<String>>,
    pub poi_dataset: Option<Vec<String>>,
    pub all_data: bool,
    #[serde(deserialize_with = "deserialize_opt_duration")]
    pub timeout: Option<Duration>,
}

/// This structure contains all the query parameters that
/// can be submitted for the reverse endpoint.
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ReverseGeocoderQuery {
    pub lat: f64,
    pub lon: f64,
    #[serde(default = "default_result_limit")]
    pub limit: i64,
    #[serde(deserialize_with = "deserialize_opt_duration")]
    pub timeout: Option<Duration>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct JsonParam {
    pub shape: GeoJson,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ExplainResponseBody {
    pub explanation: JsonValue,
}

impl From<JsonValue> for ExplainResponseBody {
    fn from(explanation: JsonValue) -> Self {
        ExplainResponseBody { explanation }
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct BragiStatus {
    pub version: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct MimirStatus {
    pub version: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ElasticsearchStatus {
    pub version: String,
    pub health: String,
    pub url: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct StatusResponseBody {
    pub bragi: BragiStatus,
    pub mimir: MimirStatus,
    pub elasticsearch: ElasticsearchStatus,
}

/// This macro is used to define the forward_geocoder route.
/// It takes a client (ElasticsearchStorage) and query settings
/// It can be either a GET request, with query parameters,
/// or a POST request, with both query parameters and a GeoJson shape
/// in the body.
#[macro_export]
macro_rules! forward_geocoder {
    ($cl:expr, $st:expr) => {
        routes::forward_geocoder_get()
            .or(routes::forward_geocoder_post())
            .unify()
            .and(routes::with_client($cl))
            .and(routes::with_settings($st))
            .and_then(handlers::forward_geocoder)
    };
}

pub use forward_geocoder;

#[macro_export]
macro_rules! forward_geocoder_explain {
    ($cl:expr, $st:expr) => {
        routes::forward_geocoder_explain_get()
            .or(routes::forward_geocoder_explain_post())
            .unify()
            .and(routes::with_client($cl))
            .and(routes::with_settings($st))
            .and_then(handlers::forward_geocoder_explain)
    };
}
pub use forward_geocoder_explain;

#[macro_export]
macro_rules! reverse_geocoder {
    ($cl:expr, $st:expr) => {
        routes::reverse_geocoder()
            .and(routes::with_client($cl))
            .and(routes::with_settings($st))
            .and_then(handlers::reverse_geocoder)
    };
}
pub use reverse_geocoder;

#[macro_export]
macro_rules! status {
    ($cl:expr, $es:expr) => {
        routes::status()
            .and(routes::with_client($cl))
            .and(routes::with_elasticsearch($es))
            .and_then(handlers::status)
    };
}
pub use status;

#[derive(PartialEq, Copy, Clone, Debug, Deserialize, Serialize)]
pub enum Type {
    #[serde(rename = "house")]
    House,
    #[serde(rename = "poi")]
    Poi,
    #[serde(rename = "public_transport:stop_area")]
    StopArea,
    #[serde(rename = "street")]
    Street,
    #[serde(rename = "zone")]
    Zone,
}

impl Type {
    pub fn as_str(&self) -> &'static str {
        match self {
            Type::House => "house",
            Type::Poi => "poi",
            Type::StopArea => "public_transport:stop_area",
            Type::Street => "street",
            Type::Zone => "zone",
        }
    }

    pub fn as_index_type(&self) -> &'static str {
        match self {
            Type::House => Addr::static_doc_type(),
            Type::Poi => Poi::static_doc_type(),
            Type::StopArea => Stop::static_doc_type(),
            Type::Street => Street::static_doc_type(),
            Type::Zone => Admin::static_doc_type(),
        }
    }
}
<commit_msg>remove struct (not for this PR)<commit_after>use crate::utils::deserialize::deserialize_opt_duration;
use cosmogony::ZoneType;
use geojson::{GeoJson, Geometry};
use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
use std::time::Duration;

use crate::adapters::primary::common::coord::Coord;
use crate::adapters::primary::common::filters::Filters;
use common::document::ContainerDocument;
use places::{addr::Addr, admin::Admin, poi::Poi, stop::Stop, street::Street};

pub const DEFAULT_LIMIT_RESULT_ES: i64 = 10;

#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ForwardGeocoderExplainQuery {
    pub doc_id: String,
    pub doc_type: String,

    #[serde(flatten)]
    pub query: ForwardGeocoderQuery,
}

/// This structure contains all the query parameters that
/// can be submitted for the autocomplete endpoint.
///
/// Only the `q` parameter is mandatory.
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ForwardGeocoderQuery {
    pub q: String,
    pub lat: Option<f32>,
    pub lon: Option<f32>,
    pub shape_scope: Option<Vec<Type>>,
    #[serde(default, rename = "type")]
    pub types: Option<Vec<Type>>,
    #[serde(default, rename = "zone_type")]
    pub zone_types: Option<Vec<ZoneType>>,
    pub poi_types: Option<Vec<String>>,
    #[serde(default = "default_result_limit")]
    pub limit: i64,
    #[serde(deserialize_with = "deserialize_opt_duration", default)]
    pub timeout: Option<Duration>,
    pub pt_dataset: Option<Vec<String>>,
    pub poi_dataset: Option<Vec<String>>,
    pub request_id: Option<String>,
    pub proximity_scale: Option<f64>,
    pub proximity_offset: Option<f64>,
    pub proximity_decay: Option<f64>,
}

fn default_result_limit() -> i64 {
    DEFAULT_LIMIT_RESULT_ES
}

impl From<(ForwardGeocoderQuery, Option<Geometry>)> for Filters {
    fn from(source: (ForwardGeocoderQuery, Option<Geometry>)) -> Self {
        let (query, geometry) = source;
        let zone_types = query.zone_types.map(|zts| {
            zts.iter()
                .map(|zt| serde_json::to_string(zt).unwrap())
                .collect()
        });
        Filters {
            // When option_zip_option becomes available: coord: input.lat.zip_with(input.lon, Coord::new),
            coord: match (query.lat, query.lon) {
                (Some(lat), Some(lon)) => Some(Coord::new(lat, lon)),
                _ => None,
            },
            shape: geometry.map(|geometry| {
                (
                    geometry,
                    query
                        .shape_scope
                        .map(|shape_scope| {
                            shape_scope.iter().map(|t| t.as_str().to_string()).collect()
                        })
                        .unwrap_or_else(|| {
                            vec![
                                Type::House,
                                Type::Poi,
                                Type::StopArea,
                                Type::Street,
                                Type::Zone,
                            ]
                            .iter()
                            .map(|t| t.as_str().to_string())
                            .collect()
                        }),
                )
            }),
            zone_types,
            poi_types: query.poi_types,
            limit: query.limit,
            timeout: query.timeout,
            proximity_scale: query.proximity_scale,
            proximity_offset: query.proximity_offset,
            proximity_decay: query.proximity_decay,
        }
    }
}

/// This structure contains all the query parameters that
/// can be submitted for the reverse endpoint.
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ReverseGeocoderQuery {
    pub lat: f64,
    pub lon: f64,
    #[serde(default = "default_result_limit")]
    pub limit: i64,
    #[serde(deserialize_with = "deserialize_opt_duration")]
    pub timeout: Option<Duration>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct JsonParam {
    pub shape: GeoJson,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ExplainResponseBody {
    pub explanation: JsonValue,
}

impl From<JsonValue> for ExplainResponseBody {
    fn from(explanation: JsonValue) -> Self {
        ExplainResponseBody { explanation }
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct BragiStatus {
    pub version: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct MimirStatus {
    pub version: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct ElasticsearchStatus {
    pub version: String,
    pub health: String,
    pub url: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct StatusResponseBody {
    pub bragi: BragiStatus,
    pub mimir: MimirStatus,
    pub elasticsearch: ElasticsearchStatus,
}

/// This macro is used to define the forward_geocoder route.
/// It takes a client (ElasticsearchStorage) and query settings
/// It can be either a GET request, with query parameters,
/// or a POST request, with both query parameters and a GeoJson shape
/// in the body.
#[macro_export]
macro_rules! forward_geocoder {
    ($cl:expr, $st:expr) => {
        routes::forward_geocoder_get()
            .or(routes::forward_geocoder_post())
            .unify()
            .and(routes::with_client($cl))
            .and(routes::with_settings($st))
            .and_then(handlers::forward_geocoder)
    };
}

pub use forward_geocoder;

#[macro_export]
macro_rules! forward_geocoder_explain {
    ($cl:expr, $st:expr) => {
        routes::forward_geocoder_explain_get()
            .or(routes::forward_geocoder_explain_post())
            .unify()
            .and(routes::with_client($cl))
            .and(routes::with_settings($st))
            .and_then(handlers::forward_geocoder_explain)
    };
}
pub use forward_geocoder_explain;

#[macro_export]
macro_rules! reverse_geocoder {
    ($cl:expr, $st:expr) => {
        routes::reverse_geocoder()
            .and(routes::with_client($cl))
            .and(routes::with_settings($st))
            .and_then(handlers::reverse_geocoder)
    };
}
pub use reverse_geocoder;

#[macro_export]
macro_rules! status {
    ($cl:expr, $es:expr) => {
        routes::status()
            .and(routes::with_client($cl))
            .and(routes::with_elasticsearch($es))
            .and_then(handlers::status)
    };
}
pub use status;

#[derive(PartialEq, Copy, Clone, Debug, Deserialize, Serialize)]
pub enum Type {
    #[serde(rename = "house")]
    House,
    #[serde(rename = "poi")]
    Poi,
    #[serde(rename = "public_transport:stop_area")]
    StopArea,
    #[serde(rename = "street")]
    Street,
    #[serde(rename = "zone")]
    Zone,
}

impl Type {
    pub fn as_str(&self) -> &'static str {
        match self {
            Type::House => "house",
            Type::Poi => "poi",
            Type::StopArea => "public_transport:stop_area",
            Type::Street => "street",
            Type::Zone => "zone",
        }
    }

    pub fn as_index_type(&self) -> &'static str {
        match self {
            Type::House => Addr::static_doc_type(),
            Type::Poi => Poi::static_doc_type(),
            Type::StopArea => Stop::static_doc_type(),
            Type::Street => Street::static_doc_type(),
            Type::Zone => Admin::static_doc_type(),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2016-2017 Sebastian Dröge <sebastian@centricular.com>
//
// 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.

use std::collections::VecDeque;
use std::cmp;

use gst;
use gst::prelude::*;

lazy_static! {
    static ref CAT: gst::DebugCategory = {
        gst::DebugCategory::new(
            "rsadapter",
            gst::DebugColorFlags::empty(),
            "Rust buffer adapter",
        )
    };
}

pub struct Adapter {
    deque: VecDeque<gst::MappedBuffer<gst::buffer::Readable>>,
    size: usize,
    skip: usize,
    scratch: Vec<u8>,
}

#[derive(Debug, PartialEq, Eq)]
pub enum AdapterError {
    NotEnoughData,
}

impl Adapter {
    pub fn new() -> Adapter {
        Adapter {
            deque: VecDeque::new(),
            size: 0,
            skip: 0,
            scratch: Vec::new(),
        }
    }

    pub fn push(&mut self, buffer: gst::Buffer) {
        let size = buffer.get_size();

        self.size += size;
        gst_trace!(
            CAT,
            "Storing {:?} of size {}, now have size {}",
            buffer,
            size,
            self.size
        );
        self.deque
            .push_back(buffer.into_mapped_buffer_readable().unwrap());
    }

    pub fn clear(&mut self) {
        self.deque.clear();
        self.size = 0;
        self.skip = 0;
        self.scratch.clear();
        gst_trace!(CAT, "Cleared adapter");
    }

    pub fn get_available(&self) -> usize {
        self.size
    }

    fn copy_data(
        deque: &VecDeque<gst::MappedBuffer<gst::buffer::Readable>>,
        skip: usize,
        data: &mut [u8],
        size: usize,
    ) {
        let mut skip = skip;
        let mut left = size;
        let mut idx = 0;

        gst_trace!(CAT, "Copying {} bytes", size);

        for item in deque {
            let data_item = item.as_slice();

            let to_copy = cmp::min(left, data_item.len() - skip);
            gst_trace!(
                CAT,
                "Copying {} bytes from {:?}, {} more to go",
                to_copy,
                item.get_buffer(),
                left - to_copy
            );

            data[idx..idx + to_copy].copy_from_slice(&data_item[skip..skip + to_copy]);
            skip = 0;
            idx += to_copy;
            left -= to_copy;
            if left == 0 {
                break;
            }
        }
        assert_eq!(left, 0);
    }

    pub fn peek_into(&self, data: &mut [u8]) -> Result<(), AdapterError> {
        let size = data.len();

        if self.size < size {
            gst_debug!(
                CAT,
                "Peeking {} bytes into, not enough data: have {}",
                size,
                self.size
            );
            return Err(AdapterError::NotEnoughData);
        }

        gst_trace!(CAT, "Peeking {} bytes into", size);
        if size == 0 {
            return Ok(());
        }

        Self::copy_data(&self.deque, self.skip, data, size);
        Ok(())
    }

    pub fn peek(&mut self, size: usize) -> Result<&[u8], AdapterError> {
        if self.size < size {
            gst_debug!(
                CAT,
                "Peeking {} bytes, not enough data: have {}",
                size,
                self.size
            );
            return Err(AdapterError::NotEnoughData);
        }

        if size == 0 {
            return Ok(&[]);
        }

        if let Some(front) = self.deque.front() {
            gst_trace!(CAT, "Peeking {} bytes, subbuffer of first", size);
            if front.get_size() - self.skip >= size {
                return Ok(&front.as_slice()[self.skip..self.skip + size]);
            }
        }

        gst_trace!(CAT, "Peeking {} bytes, copy to scratch", size);

        self.scratch.truncate(0);
        self.scratch.reserve(size);
        {
            let data = self.scratch.as_mut_slice();
            Self::copy_data(&self.deque, self.skip, data, size);
        }

        Ok(self.scratch.as_slice())
    }

    pub fn get_buffer(&mut self, size: usize) -> Result<gst::Buffer, AdapterError> {
        if self.size < size {
            gst_debug!(
                CAT,
                "Get buffer of {} bytes, not enough data: have {}",
                size,
                self.size
            );
            return Err(AdapterError::NotEnoughData);
        }

        if size == 0 {
            return Ok(gst::Buffer::new());
        }

        let sub = self.deque
            .front()
            .and_then(|front| if front.get_size() - self.skip >= size {
                gst_trace!(CAT, "Get buffer of {} bytes, subbuffer of first", size);
                let new = front
                    .get_buffer()
                    .copy_region(self.skip, Some(size))
                    .unwrap();
                Some(new)
            } else {
                None
            });

        if let Some(s) = sub {
            self.flush(size).unwrap();
            return Ok(s);
        }

        gst_trace!(CAT, "Get buffer of {} bytes, copy into new buffer", size);
        let mut new = gst::Buffer::with_size(size).unwrap();
        {
            let mut map = new.get_mut().unwrap().map_writable().unwrap();
            let data = map.as_mut_slice();
            Self::copy_data(&self.deque, self.skip, data, size);
        }
        self.flush(size).unwrap();
        Ok(new)
    }

    pub fn flush(&mut self, size: usize) -> Result<(), AdapterError> {
        if self.size < size {
            gst_debug!(
                CAT,
                "Flush {} bytes, not enough data: have {}",
                size,
                self.size
            );
            return Err(AdapterError::NotEnoughData);
        }

        if size == 0 {
            return Ok(());
        }

        gst_trace!(CAT, "Flushing {} bytes, have {}", size, self.size);

        let mut left = size;
        while left > 0 {
            let front_size = self.deque.front().unwrap().get_size() - self.skip;

            if front_size <= left {
                gst_trace!(
                    CAT,
                    "Flushing whole {:?}, {} more to go",
                    self.deque.front().map(|b| b.get_buffer()),
                    left - front_size
                );
                self.deque.pop_front();
                self.size -= front_size;
                self.skip = 0;
                left -= front_size;
            } else {
                gst_trace!(
                    CAT,
                    "Flushing partial {:?}, {} more left",
                    self.deque.front().map(|b| b.get_buffer()),
                    front_size - left
                );
                self.skip += left;
                self.size -= left;
                left = 0;
            }
        }

        Ok(())
    }
}

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

    #[test]
    fn test_push_get() {
        gst::init().unwrap();

        let mut a = Adapter::new();

        a.push(gst::Buffer::with_size(100).unwrap());
        assert_eq!(a.get_available(), 100);
        a.push(gst::Buffer::with_size(20).unwrap());
        assert_eq!(a.get_available(), 120);

        let b = a.get_buffer(20).unwrap();
        assert_eq!(a.get_available(), 100);
        assert_eq!(b.get_size(), 20);
        let b = a.get_buffer(90).unwrap();
        assert_eq!(a.get_available(), 10);
        assert_eq!(b.get_size(), 90);

        a.push(gst::Buffer::with_size(20).unwrap());
        assert_eq!(a.get_available(), 30);

        let b = a.get_buffer(20).unwrap();
        assert_eq!(a.get_available(), 10);
        assert_eq!(b.get_size(), 20);
        let b = a.get_buffer(10).unwrap();
        assert_eq!(a.get_available(), 0);
        assert_eq!(b.get_size(), 10);

        let b = a.get_buffer(1);
        assert_eq!(b.err().unwrap(), AdapterError::NotEnoughData);
    }
}
<commit_msg>adapter: Implement the `Read` trait<commit_after>// Copyright (C) 2016-2017 Sebastian Dröge <sebastian@centricular.com>
//
// 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.

use std::collections::VecDeque;
use std::cmp;
use std::io;

use gst;
use gst::prelude::*;

lazy_static! {
    static ref CAT: gst::DebugCategory = {
        gst::DebugCategory::new(
            "rsadapter",
            gst::DebugColorFlags::empty(),
            "Rust buffer adapter",
        )
    };
}

pub struct Adapter {
    deque: VecDeque<gst::MappedBuffer<gst::buffer::Readable>>,
    size: usize,
    skip: usize,
    scratch: Vec<u8>,
}

#[derive(Debug, PartialEq, Eq)]
pub enum AdapterError {
    NotEnoughData,
}

impl Adapter {
    pub fn new() -> Adapter {
        Adapter {
            deque: VecDeque::new(),
            size: 0,
            skip: 0,
            scratch: Vec::new(),
        }
    }

    pub fn push(&mut self, buffer: gst::Buffer) {
        let size = buffer.get_size();

        self.size += size;
        gst_trace!(
            CAT,
            "Storing {:?} of size {}, now have size {}",
            buffer,
            size,
            self.size
        );
        self.deque
            .push_back(buffer.into_mapped_buffer_readable().unwrap());
    }

    pub fn clear(&mut self) {
        self.deque.clear();
        self.size = 0;
        self.skip = 0;
        self.scratch.clear();
        gst_trace!(CAT, "Cleared adapter");
    }

    pub fn get_available(&self) -> usize {
        self.size
    }

    fn copy_data(
        deque: &VecDeque<gst::MappedBuffer<gst::buffer::Readable>>,
        skip: usize,
        data: &mut [u8],
        size: usize,
    ) {
        let mut skip = skip;
        let mut left = size;
        let mut idx = 0;

        gst_trace!(CAT, "Copying {} bytes", size);

        for item in deque {
            let data_item = item.as_slice();

            let to_copy = cmp::min(left, data_item.len() - skip);
            gst_trace!(
                CAT,
                "Copying {} bytes from {:?}, {} more to go",
                to_copy,
                item.get_buffer(),
                left - to_copy
            );

            data[idx..idx + to_copy].copy_from_slice(&data_item[skip..skip + to_copy]);
            skip = 0;
            idx += to_copy;
            left -= to_copy;
            if left == 0 {
                break;
            }
        }
        assert_eq!(left, 0);
    }

    pub fn peek_into(&self, data: &mut [u8]) -> Result<(), AdapterError> {
        let size = data.len();

        if self.size < size {
            gst_debug!(
                CAT,
                "Peeking {} bytes into, not enough data: have {}",
                size,
                self.size
            );
            return Err(AdapterError::NotEnoughData);
        }

        gst_trace!(CAT, "Peeking {} bytes into", size);
        if size == 0 {
            return Ok(());
        }

        Self::copy_data(&self.deque, self.skip, data, size);
        Ok(())
    }

    pub fn peek(&mut self, size: usize) -> Result<&[u8], AdapterError> {
        if self.size < size {
            gst_debug!(
                CAT,
                "Peeking {} bytes, not enough data: have {}",
                size,
                self.size
            );
            return Err(AdapterError::NotEnoughData);
        }

        if size == 0 {
            return Ok(&[]);
        }

        if let Some(front) = self.deque.front() {
            gst_trace!(CAT, "Peeking {} bytes, subbuffer of first", size);
            if front.get_size() - self.skip >= size {
                return Ok(&front.as_slice()[self.skip..self.skip + size]);
            }
        }

        gst_trace!(CAT, "Peeking {} bytes, copy to scratch", size);

        self.scratch.truncate(0);
        self.scratch.reserve(size);
        {
            let data = self.scratch.as_mut_slice();
            Self::copy_data(&self.deque, self.skip, data, size);
        }

        Ok(self.scratch.as_slice())
    }

    pub fn get_buffer(&mut self, size: usize) -> Result<gst::Buffer, AdapterError> {
        if self.size < size {
            gst_debug!(
                CAT,
                "Get buffer of {} bytes, not enough data: have {}",
                size,
                self.size
            );
            return Err(AdapterError::NotEnoughData);
        }

        if size == 0 {
            return Ok(gst::Buffer::new());
        }

        let sub = self.deque
            .front()
            .and_then(|front| if front.get_size() - self.skip >= size {
                gst_trace!(CAT, "Get buffer of {} bytes, subbuffer of first", size);
                let new = front
                    .get_buffer()
                    .copy_region(self.skip, Some(size))
                    .unwrap();
                Some(new)
            } else {
                None
            });

        if let Some(s) = sub {
            self.flush(size).unwrap();
            return Ok(s);
        }

        gst_trace!(CAT, "Get buffer of {} bytes, copy into new buffer", size);
        let mut new = gst::Buffer::with_size(size).unwrap();
        {
            let mut map = new.get_mut().unwrap().map_writable().unwrap();
            let data = map.as_mut_slice();
            Self::copy_data(&self.deque, self.skip, data, size);
        }
        self.flush(size).unwrap();
        Ok(new)
    }

    pub fn flush(&mut self, size: usize) -> Result<(), AdapterError> {
        if self.size < size {
            gst_debug!(
                CAT,
                "Flush {} bytes, not enough data: have {}",
                size,
                self.size
            );
            return Err(AdapterError::NotEnoughData);
        }

        if size == 0 {
            return Ok(());
        }

        gst_trace!(CAT, "Flushing {} bytes, have {}", size, self.size);

        let mut left = size;
        while left > 0 {
            let front_size = self.deque.front().unwrap().get_size() - self.skip;

            if front_size <= left {
                gst_trace!(
                    CAT,
                    "Flushing whole {:?}, {} more to go",
                    self.deque.front().map(|b| b.get_buffer()),
                    left - front_size
                );
                self.deque.pop_front();
                self.size -= front_size;
                self.skip = 0;
                left -= front_size;
            } else {
                gst_trace!(
                    CAT,
                    "Flushing partial {:?}, {} more left",
                    self.deque.front().map(|b| b.get_buffer()),
                    front_size - left
                );
                self.skip += left;
                self.size -= left;
                left = 0;
            }
        }

        Ok(())
    }
}

impl io::Read for Adapter {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
        let mut len = self.get_available();

        if buf.len() < len {
            len = buf.len();
        }

        if self.size == 0 {
            return Err(io::Error::new(
                    io::ErrorKind::WouldBlock,
                    format!("Missing data: requesting {} but only got {}.",
                            len, self.size)));
        }

        Self::copy_data(&self.deque, self.skip, buf, len);
        self.flush(len);
        Ok(len)
    }
}

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

    #[test]
    fn test_push_get() {
        gst::init().unwrap();

        let mut a = Adapter::new();

        a.push(gst::Buffer::with_size(100).unwrap());
        assert_eq!(a.get_available(), 100);
        a.push(gst::Buffer::with_size(20).unwrap());
        assert_eq!(a.get_available(), 120);

        let b = a.get_buffer(20).unwrap();
        assert_eq!(a.get_available(), 100);
        assert_eq!(b.get_size(), 20);
        let b = a.get_buffer(90).unwrap();
        assert_eq!(a.get_available(), 10);
        assert_eq!(b.get_size(), 90);

        a.push(gst::Buffer::with_size(20).unwrap());
        assert_eq!(a.get_available(), 30);

        let b = a.get_buffer(20).unwrap();
        assert_eq!(a.get_available(), 10);
        assert_eq!(b.get_size(), 20);
        let b = a.get_buffer(10).unwrap();
        assert_eq!(a.get_available(), 0);
        assert_eq!(b.get_size(), 10);

        let b = a.get_buffer(1);
        assert_eq!(b.err().unwrap(), AdapterError::NotEnoughData);
    }
}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, WriteBytesExt};
use std::collections::HashSet;
use std::io::prelude::*;
use std::io::{Cursor, Seek};
use std::iter::FromIterator;
use zip::write::FileOptions;
use zip::CompressionMethod;

// This test asserts that after creating a zip file, then reading its contents back out,
// the extracted data will *always* be exactly the same as the original data.
#[test]
fn end_to_end() {
    for method in CompressionMethod::supported_methods().iter() {
        let file = &mut Cursor::new(Vec::new());

        write_to_zip(file, *method).expect("Couldn't write to test file");

        check_zip_contents(file, ENTRY_NAME, Some(*method));
    }
}

// This test asserts that after copying a `ZipFile` to a new `ZipWriter`, then reading its
// contents back out, the extracted data will *always* be exactly the same as the original data.
#[test]
fn copy() {
    for method in CompressionMethod::supported_methods().iter() {
        let src_file = &mut Cursor::new(Vec::new());
        write_to_zip(src_file, *method).expect("Couldn't write to test file");

        let mut tgt_file = &mut Cursor::new(Vec::new());

        {
            let mut src_archive = zip::ZipArchive::new(src_file).unwrap();
            let mut zip = zip::ZipWriter::new(&mut tgt_file);

            {
                let file = src_archive
                    .by_name(ENTRY_NAME)
                    .expect("Missing expected file");

                zip.raw_copy_file(file).expect("Couldn't copy file");
            }

            {
                let file = src_archive
                    .by_name(ENTRY_NAME)
                    .expect("Missing expected file");

                zip.raw_copy_file_rename(file, COPY_ENTRY_NAME)
                    .expect("Couldn't copy and rename file");
            }
        }

        let mut tgt_archive = zip::ZipArchive::new(tgt_file).unwrap();

        check_zip_file_contents(&mut tgt_archive, ENTRY_NAME);
        check_zip_file_contents(&mut tgt_archive, COPY_ENTRY_NAME);
    }
}

// This test asserts that after appending to a `ZipWriter`, then reading its contents back out,
// both the prior data and the appended data will be exactly the same as their originals.
#[test]
fn append() {
    for method in CompressionMethod::supported_methods().iter() {
        let mut file = &mut Cursor::new(Vec::new());
        write_to_zip(file, *method).expect("Couldn't write to test file");

        {
            let mut zip = zip::ZipWriter::new_append(&mut file).unwrap();
            zip.start_file(
                COPY_ENTRY_NAME,
                FileOptions::default().compression_method(*method),
            )
            .unwrap();
            zip.write_all(LOREM_IPSUM).unwrap();
            zip.finish().unwrap();
        }

        let mut zip = zip::ZipArchive::new(&mut file).unwrap();
        check_zip_file_contents(&mut zip, ENTRY_NAME);
        check_zip_file_contents(&mut zip, COPY_ENTRY_NAME);
    }
}

fn write_to_zip(
    file: &mut Cursor<Vec<u8>>,
    method: CompressionMethod,
) -> zip::result::ZipResult<()> {
    let mut zip = zip::ZipWriter::new(file);

    zip.add_directory("test/", Default::default())?;

    let options = FileOptions::default()
        .compression_method(method)
        .unix_permissions(0o755);

    zip.start_file("test/☃.txt", options)?;
    zip.write_all(b"Hello, World!\n")?;

    zip.start_file_with_extra_data("test_with_extra_data/🐢.txt", options)?;
    zip.write_u16::<LittleEndian>(0xbeef)?;
    zip.write_u16::<LittleEndian>(EXTRA_DATA.len() as u16)?;
    zip.write_all(EXTRA_DATA)?;
    zip.end_extra_data()?;
    zip.write_all(b"Hello, World! Again.\n")?;

    zip.start_file(ENTRY_NAME, options)?;
    zip.write_all(LOREM_IPSUM)?;

    zip.finish()?;
    Ok(())
}

fn read_zip<R: Read + Seek>(zip_file: R) -> zip::result::ZipResult<zip::ZipArchive<R>> {
    let mut archive = zip::ZipArchive::new(zip_file).unwrap();

    let expected_file_names = [
        "test/",
        "test/☃.txt",
        "test_with_extra_data/🐢.txt",
        ENTRY_NAME,
    ];
    let expected_file_names = HashSet::from_iter(expected_file_names.iter().copied());
    let file_names = archive.file_names().collect::<HashSet<_>>();
    assert_eq!(file_names, expected_file_names);

    {
        let file_with_extra_data = archive.by_name("test_with_extra_data/🐢.txt")?;
        let mut extra_data = Vec::new();
        extra_data.write_u16::<LittleEndian>(0xbeef)?;
        extra_data.write_u16::<LittleEndian>(EXTRA_DATA.len() as u16)?;
        extra_data.write_all(EXTRA_DATA)?;
        assert_eq!(file_with_extra_data.extra_data(), extra_data.as_slice());
    }

    Ok(archive)
}

fn read_zip_file<R: Read + Seek>(
    archive: &mut zip::ZipArchive<R>,
    name: &str,
) -> zip::result::ZipResult<String> {
    let mut file = archive.by_name(name)?;

    let mut contents = String::new();
    file.read_to_string(&mut contents).unwrap();
    Ok(contents)
}

fn check_zip_contents(
    zip_file: &mut Cursor<Vec<u8>>,
    name: &str,
    expected_method: Option<CompressionMethod>,
) {
    let mut archive = read_zip(zip_file).unwrap();

    match expected_method {
        Some(method) => {
            let file = archive.by_name(name).unwrap();

            assert_eq!(
                method,
                file.compression(),
                "File does not have expected compression method"
            )
        }
        None => {}
    }

    check_zip_file_contents(&mut archive, name);
}

fn check_zip_file_contents<R: Read + Seek>(archive: &mut zip::ZipArchive<R>, name: &str) {
    let file_contents: String = read_zip_file(archive, name).unwrap();
    assert_eq!(file_contents.as_bytes(), LOREM_IPSUM);
}

const LOREM_IPSUM : &[u8] = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit. In tellus elit, tristique vitae mattis egestas, ultricies vitae risus. Quisque sit amet quam ut urna aliquet
molestie. Proin blandit ornare dui, a tempor nisl accumsan in. Praesent a consequat felis. Morbi metus diam, auctor in auctor vel, feugiat id odio. Curabitur ex ex,
dictum quis auctor quis, suscipit id lorem. Aliquam vestibulum dolor nec enim vehicula, porta tristique augue tincidunt. Vivamus ut gravida est. Sed pellentesque, dolor
vitae tristique consectetur, neque lectus pulvinar dui, sed feugiat purus diam id lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per
inceptos himenaeos. Maecenas feugiat velit in ex ultrices scelerisque id id neque.
";

const EXTRA_DATA: &[u8] = b"Extra Data";

const ENTRY_NAME: &str = "test/lorem_ipsum.txt";

const COPY_ENTRY_NAME: &str = "test/lorem_ipsum_renamed.txt";
<commit_msg>Use SUPPORTED_METHODS in tests<commit_after>use byteorder::{LittleEndian, WriteBytesExt};
use std::collections::HashSet;
use std::io::prelude::*;
use std::io::{Cursor, Seek};
use std::iter::FromIterator;
use zip::write::FileOptions;
use zip::{CompressionMethod, SUPPORTED_METHODS};

// This test asserts that after creating a zip file, then reading its contents back out,
// the extracted data will *always* be exactly the same as the original data.
#[test]
fn end_to_end() {
    for &method in SUPPORTED_METHODS {
        let file = &mut Cursor::new(Vec::new());

        println!("Writing file with {} compression", method);
        write_to_zip(file, method).expect("Couldn't write to test file");

        println!("Checking file contents");
        check_zip_contents(file, ENTRY_NAME, Some(method));
    }
}

// This test asserts that after copying a `ZipFile` to a new `ZipWriter`, then reading its
// contents back out, the extracted data will *always* be exactly the same as the original data.
#[test]
fn copy() {
    for &method in SUPPORTED_METHODS {
        let src_file = &mut Cursor::new(Vec::new());
        write_to_zip(src_file, method).expect("Couldn't write to test file");

        let mut tgt_file = &mut Cursor::new(Vec::new());

        {
            let mut src_archive = zip::ZipArchive::new(src_file).unwrap();
            let mut zip = zip::ZipWriter::new(&mut tgt_file);

            {
                let file = src_archive
                    .by_name(ENTRY_NAME)
                    .expect("Missing expected file");

                zip.raw_copy_file(file).expect("Couldn't copy file");
            }

            {
                let file = src_archive
                    .by_name(ENTRY_NAME)
                    .expect("Missing expected file");

                zip.raw_copy_file_rename(file, COPY_ENTRY_NAME)
                    .expect("Couldn't copy and rename file");
            }
        }

        let mut tgt_archive = zip::ZipArchive::new(tgt_file).unwrap();

        check_zip_file_contents(&mut tgt_archive, ENTRY_NAME);
        check_zip_file_contents(&mut tgt_archive, COPY_ENTRY_NAME);
    }
}

// This test asserts that after appending to a `ZipWriter`, then reading its contents back out,
// both the prior data and the appended data will be exactly the same as their originals.
#[test]
fn append() {
    for &method in SUPPORTED_METHODS {
        let mut file = &mut Cursor::new(Vec::new());
        write_to_zip(file, method).expect("Couldn't write to test file");

        {
            let mut zip = zip::ZipWriter::new_append(&mut file).unwrap();
            zip.start_file(
                COPY_ENTRY_NAME,
                FileOptions::default().compression_method(method),
            )
            .unwrap();
            zip.write_all(LOREM_IPSUM).unwrap();
            zip.finish().unwrap();
        }

        let mut zip = zip::ZipArchive::new(&mut file).unwrap();
        check_zip_file_contents(&mut zip, ENTRY_NAME);
        check_zip_file_contents(&mut zip, COPY_ENTRY_NAME);
    }
}

fn write_to_zip(
    file: &mut Cursor<Vec<u8>>,
    method: CompressionMethod,
) -> zip::result::ZipResult<()> {
    let mut zip = zip::ZipWriter::new(file);

    zip.add_directory("test/", Default::default())?;

    let options = FileOptions::default()
        .compression_method(method)
        .unix_permissions(0o755);

    zip.start_file("test/☃.txt", options)?;
    zip.write_all(b"Hello, World!\n")?;

    zip.start_file_with_extra_data("test_with_extra_data/🐢.txt", options)?;
    zip.write_u16::<LittleEndian>(0xbeef)?;
    zip.write_u16::<LittleEndian>(EXTRA_DATA.len() as u16)?;
    zip.write_all(EXTRA_DATA)?;
    zip.end_extra_data()?;
    zip.write_all(b"Hello, World! Again.\n")?;

    zip.start_file(ENTRY_NAME, options)?;
    zip.write_all(LOREM_IPSUM)?;

    zip.finish()?;
    Ok(())
}

fn read_zip<R: Read + Seek>(zip_file: R) -> zip::result::ZipResult<zip::ZipArchive<R>> {
    let mut archive = zip::ZipArchive::new(zip_file).unwrap();

    let expected_file_names = [
        "test/",
        "test/☃.txt",
        "test_with_extra_data/🐢.txt",
        ENTRY_NAME,
    ];
    let expected_file_names = HashSet::from_iter(expected_file_names.iter().copied());
    let file_names = archive.file_names().collect::<HashSet<_>>();
    assert_eq!(file_names, expected_file_names);

    {
        let file_with_extra_data = archive.by_name("test_with_extra_data/🐢.txt")?;
        let mut extra_data = Vec::new();
        extra_data.write_u16::<LittleEndian>(0xbeef)?;
        extra_data.write_u16::<LittleEndian>(EXTRA_DATA.len() as u16)?;
        extra_data.write_all(EXTRA_DATA)?;
        assert_eq!(file_with_extra_data.extra_data(), extra_data.as_slice());
    }

    Ok(archive)
}

fn read_zip_file<R: Read + Seek>(
    archive: &mut zip::ZipArchive<R>,
    name: &str,
) -> zip::result::ZipResult<String> {
    let mut file = archive.by_name(name)?;

    let mut contents = String::new();
    file.read_to_string(&mut contents).unwrap();
    Ok(contents)
}

fn check_zip_contents(
    zip_file: &mut Cursor<Vec<u8>>,
    name: &str,
    expected_method: Option<CompressionMethod>,
) {
    let mut archive = read_zip(zip_file).unwrap();

    match expected_method {
        Some(method) => {
            let file = archive.by_name(name).unwrap();

            assert_eq!(
                method,
                file.compression(),
                "File does not have expected compression method"
            )
        }
        None => {}
    }

    check_zip_file_contents(&mut archive, name);
}

fn check_zip_file_contents<R: Read + Seek>(archive: &mut zip::ZipArchive<R>, name: &str) {
    let file_contents: String = read_zip_file(archive, name).unwrap();
    assert_eq!(file_contents.as_bytes(), LOREM_IPSUM);
}

const LOREM_IPSUM : &[u8] = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit. In tellus elit, tristique vitae mattis egestas, ultricies vitae risus. Quisque sit amet quam ut urna aliquet
molestie. Proin blandit ornare dui, a tempor nisl accumsan in. Praesent a consequat felis. Morbi metus diam, auctor in auctor vel, feugiat id odio. Curabitur ex ex,
dictum quis auctor quis, suscipit id lorem. Aliquam vestibulum dolor nec enim vehicula, porta tristique augue tincidunt. Vivamus ut gravida est. Sed pellentesque, dolor
vitae tristique consectetur, neque lectus pulvinar dui, sed feugiat purus diam id lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per
inceptos himenaeos. Maecenas feugiat velit in ex ultrices scelerisque id id neque.
";

const EXTRA_DATA: &[u8] = b"Extra Data";

const ENTRY_NAME: &str = "test/lorem_ipsum.txt";

const COPY_ENTRY_NAME: &str = "test/lorem_ipsum_renamed.txt";
<|endoftext|>


<commit_before>use slack_api as slack;

use std::env;

fn get_setup(
) -> Result<(String, impl slack::requests::SlackWebRequestSender), Box<dyn std::error::Error>> {
    // You can generate a legacy token to quickly test these apis
    // https://api.slack.com/custom-integrations/legacy-tokens
    let token = env::var("SLACK_API_TOKEN").map_err(|_| "SLACK_API_TOKEN env var must be set")?;
    let client = slack::default_client().map_err(|_| "Could not get default_client")?;
    Ok((token, client))
}

#[test]
#[ignore]
fn smoke_test() -> Result<(), Box<dyn std::error::Error>> {
    let (_, client) = get_setup()?;

    let resp = slack::api::test(
        &client,
        &slack::api::TestRequest {
            error: Some("my_error"),
            foo: Some("it's me, foo"),
        },
    )
    .err()
    .ok_or("Expected error")?;

    assert_eq!(format!("{:?}", resp), "Unknown(\"my_error\")");
    Ok(())
}

#[test]
#[ignore]
fn smoke_channels() -> Result<(), Box<dyn std::error::Error>> {
    let (token, client) = get_setup()?;

    let all_channels = slack::channels::list(
        &client,
        &token,
        &slack::channels::ListRequest {
            ..slack::channels::ListRequest::default()
        },
    )?
    .channels
    .ok_or("Expected some channels")?;

    assert!(all_channels.len() > 0);

    for channel in &all_channels[..10] {
        let channel_id = channel.id.as_ref().ok_or("expected channel id")?;

        let channel_info = slack::channels::info(
            &client,
            &token,
            &slack::channels::InfoRequest {
                channel: &channel_id,
                ..Default::default()
            },
        )?
        .channel
        .ok_or("Expected some channel")?;

        dbg!(channel_info.name);

        let _channel_history = slack::channels::history(
            &client,
            &token,
            &slack::channels::HistoryRequest {
                channel: &channel_id,
                oldest: Some(1234567890.1234.into()),
                count: Some(1),
                ..Default::default()
            },
        )?
        .messages
        .ok_or("Expected some messages")?;
    }

    Ok(())
}
<commit_msg>request larger history, print json separately for readability<commit_after>use slack_api as slack;

use std::env;

fn get_setup(
) -> Result<(String, impl slack::requests::SlackWebRequestSender), Box<dyn std::error::Error>> {
    // You can generate a legacy token to quickly test these apis
    // https://api.slack.com/custom-integrations/legacy-tokens
    let token = env::var("SLACK_API_TOKEN").map_err(|_| "SLACK_API_TOKEN env var must be set")?;
    let client = slack::default_client().map_err(|_| "Could not get default_client")?;
    Ok((token, client))
}

#[test]
#[ignore]
fn smoke_test() -> Result<(), Box<dyn std::error::Error>> {
    let (_, client) = get_setup()?;

    let resp = slack::api::test(
        &client,
        &slack::api::TestRequest {
            error: Some("my_error"),
            foo: Some("it's me, foo"),
        },
    )
    .err()
    .ok_or("Expected error")?;

    assert_eq!(format!("{:?}", resp), "Unknown(\"my_error\")");
    Ok(())
}

#[test]
#[ignore]
fn smoke_channels() -> Result<(), Box<dyn std::error::Error>> {
    let (token, client) = get_setup()?;

    let all_channels = slack::channels::list(
        &client,
        &token,
        &slack::channels::ListRequest {
            ..slack::channels::ListRequest::default()
        },
    )?
    .channels
    .ok_or("Expected some channels")?;

    assert!(all_channels.len() > 0);

    for channel in &all_channels[..10] {
        let channel_id = channel.id.as_ref().ok_or("expected channel id")?;

        let channel_info = slack::channels::info(
            &client,
            &token,
            &slack::channels::InfoRequest {
                channel: &channel_id,
                ..Default::default()
            },
        )?
        .channel
        .ok_or("Expected some channel")?;

        dbg!(channel_info.name);

        let _channel_history = slack::channels::history(
            &client,
            &token,
            &slack::channels::HistoryRequest {
                channel: &channel_id,
                oldest: Some(1234567890.1234.into()),
                ..Default::default()
            },
        )
        .map_err(|e| {
            if let slack::channels::HistoryError::MalformedResponse(r, inner_e) = e {
                println!("{}", r);
                Box::new(inner_e) as Box<dyn std::error::Error>
            } else {
                Box::new(e)
            }
        })?
        .messages
        .ok_or("Expected some messages")?;
    }

    Ok(())
}
<|endoftext|>


<commit_before>use cssparser::Parser;

use error::*;
use parsers::{CssParserExt, Parse, ParseError};

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct UnitInterval(pub f64);

impl Default for UnitInterval {
    fn default() -> UnitInterval {
        UnitInterval(1.0)
    }
}

impl Parse for UnitInterval {
    type Data = ();
    type Err = ValueErrorKind;

    fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<UnitInterval, ValueErrorKind> {
        let x = f64::from(
            parser
                .expect_finite_number()
                .map_err(|_| ValueErrorKind::Parse(ParseError::new("expected number")))?,
        );

        let cx = if x < 0.0 {
            0.0
        } else if x > 1.0 {
            1.0
        } else {
            x
        };

        Ok(UnitInterval(cx))
    }
}

impl From<UnitInterval> for u8 {
    fn from(val: UnitInterval) -> u8 {
        let UnitInterval(x) = val;
        (x * 255.0 + 0.5).floor() as u8
    }
}

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

    #[test]
    fn parses_number() {
        assert_eq!(UnitInterval::parse_str("0", ()), Ok(UnitInterval(0.0)));
        assert_eq!(UnitInterval::parse_str("1", ()), Ok(UnitInterval(1.0)));
        assert_eq!(UnitInterval::parse_str("0.5", ()), Ok(UnitInterval(0.5)));
    }

    #[test]
    fn parses_out_of_range_number() {
        assert_eq!(UnitInterval::parse_str("-10", ()), Ok(UnitInterval(0.0)));
        assert_eq!(UnitInterval::parse_str("10", ()), Ok(UnitInterval(1.0)));
    }

    #[test]
    fn errors_on_invalid_input() {
        assert!(is_parse_error(&UnitInterval::parse_str("", ())));
        assert!(is_parse_error(&UnitInterval::parse_str("foo", ())));
        assert!(is_parse_error(&UnitInterval::parse_str("-x", ())));
        assert!(is_parse_error(&UnitInterval::parse_str("0.0foo", ())));
    }

    #[test]
    fn convert() {
        assert_eq!(u8::from(UnitInterval(0.0)), 0);
        assert_eq!(u8::from(UnitInterval(0.5)), 128);
        assert_eq!(u8::from(UnitInterval(1.0)), 255);
    }
}
<commit_msg>unit_interval: add constructor that clamps a f64<commit_after>use cssparser::Parser;

use error::*;
use parsers::{CssParserExt, Parse, ParseError};
use util;

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct UnitInterval(pub f64);

impl UnitInterval {
    pub fn clamp(val: f64) -> UnitInterval {
        UnitInterval(util::clamp(val, 0.0, 1.0))
    }
}

impl Parse for UnitInterval {
    type Data = ();
    type Err = ValueErrorKind;

    fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<UnitInterval, ValueErrorKind> {
        let x = f64::from(
            parser
                .expect_finite_number()
                .map_err(|_| ValueErrorKind::Parse(ParseError::new("expected number")))?,
        );

        Ok(UnitInterval::clamp(x))
    }
}

impl From<UnitInterval> for u8 {
    fn from(val: UnitInterval) -> u8 {
        let UnitInterval(x) = val;
        (x * 255.0 + 0.5).floor() as u8
    }
}

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

    #[test]
    fn clamps() {
        assert_eq!(UnitInterval::clamp(-1.0), UnitInterval(0.0));
        assert_eq!(UnitInterval::clamp(0.0), UnitInterval(0.0));
        assert_eq!(UnitInterval::clamp(0.5), UnitInterval(0.5));
        assert_eq!(UnitInterval::clamp(1.0), UnitInterval(1.0));
        assert_eq!(UnitInterval::clamp(2.0), UnitInterval(1.0));
    }

    #[test]
    fn parses_number() {
        assert_eq!(UnitInterval::parse_str("0", ()), Ok(UnitInterval(0.0)));
        assert_eq!(UnitInterval::parse_str("1", ()), Ok(UnitInterval(1.0)));
        assert_eq!(UnitInterval::parse_str("0.5", ()), Ok(UnitInterval(0.5)));
    }

    #[test]
    fn parses_out_of_range_number() {
        assert_eq!(UnitInterval::parse_str("-10", ()), Ok(UnitInterval(0.0)));
        assert_eq!(UnitInterval::parse_str("10", ()), Ok(UnitInterval(1.0)));
    }

    #[test]
    fn errors_on_invalid_input() {
        assert!(is_parse_error(&UnitInterval::parse_str("", ())));
        assert!(is_parse_error(&UnitInterval::parse_str("foo", ())));
        assert!(is_parse_error(&UnitInterval::parse_str("-x", ())));
        assert!(is_parse_error(&UnitInterval::parse_str("0.0foo", ())));
    }

    #[test]
    fn convert() {
        assert_eq!(u8::from(UnitInterval(0.0)), 0);
        assert_eq!(u8::from(UnitInterval(0.5)), 128);
        assert_eq!(u8::from(UnitInterval(1.0)), 255);
    }
}
<|endoftext|>


<commit_before>use core::sync::atomic::{Ordering};
use spin::Mutex;

use crate::device::uart_pl011::SerialPort;
use crate::init::device_tree;
use crate::memory::Frame;
use crate::paging::mapper::PageFlushAll;
use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, TableKind, VirtualAddress};

pub static COM1: Mutex<Option<SerialPort>> = Mutex::new(None);

pub unsafe fn init() {
    if let Some(ref mut serial_port) = *COM1.lock() {
        return;
    }
    let (base, size) = device_tree::diag_uart_range(crate::KERNEL_DTB_OFFSET, crate::KERNEL_DTB_MAX_SIZE).unwrap();

    let mut active_ktable = unsafe { ActivePageTable::new(TableKind::Kernel) };
    let mut flush_all = PageFlushAll::new();

    let start_frame = Frame::containing_address(PhysicalAddress::new(base));
    let end_frame = Frame::containing_address(PhysicalAddress::new(base + size - 1));
    for frame in Frame::range_inclusive(start_frame, end_frame) {
        let page = Page::containing_address(VirtualAddress::new(frame.start_address().data() + crate::KERNEL_DEVMAP_OFFSET));
        let result = active_ktable.map_to(page, frame, PageFlags::new().write(true));
        flush_all.consume(result);
    };
    flush_all.flush();

    let start_frame = Frame::containing_address(PhysicalAddress::new(base));
    let vaddr = start_frame.start_address().data() + crate::KERNEL_DEVMAP_OFFSET;

    *COM1.lock() = Some(SerialPort::new(vaddr));
    if let Some(ref mut serial_port) = *COM1.lock() {
        serial_port.init(true);
    }
}
<commit_msg>Re-init aarch64 serial port for interrupts<commit_after>use core::sync::atomic::{Ordering};
use spin::Mutex;

use crate::device::uart_pl011::SerialPort;
use crate::init::device_tree;
use crate::memory::Frame;
use crate::paging::mapper::PageFlushAll;
use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, TableKind, VirtualAddress};

pub static COM1: Mutex<Option<SerialPort>> = Mutex::new(None);

pub unsafe fn init() {
    if COM1.lock().is_none() {
        let (base, size) = device_tree::diag_uart_range(crate::KERNEL_DTB_OFFSET, crate::KERNEL_DTB_MAX_SIZE).unwrap();

        let mut active_ktable = unsafe { ActivePageTable::new(TableKind::Kernel) };
        let mut flush_all = PageFlushAll::new();

        let start_frame = Frame::containing_address(PhysicalAddress::new(base));
        let end_frame = Frame::containing_address(PhysicalAddress::new(base + size - 1));
        for frame in Frame::range_inclusive(start_frame, end_frame) {
            let page = Page::containing_address(VirtualAddress::new(frame.start_address().data() + crate::KERNEL_DEVMAP_OFFSET));
            let result = active_ktable.map_to(page, frame, PageFlags::new().write(true));
            flush_all.consume(result);
        };
        flush_all.flush();

        let start_frame = Frame::containing_address(PhysicalAddress::new(base));
        let vaddr = start_frame.start_address().data() + crate::KERNEL_DEVMAP_OFFSET;

        *COM1.lock() = Some(SerialPort::new(vaddr));
    }

    if let Some(ref mut serial_port) = *COM1.lock() {
        serial_port.init(true);
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]

#![plugin(clippy)]

#![deny(clippy)]
#![deny(clippy_pedantic)]
#![allow(print_stdout)]
#![allow(clone_on_copy)]

fn main() {
    let mut a = [1, 2, 3, 4, 5];

    //implicit Copy trait - the bane of Rust :)
    let first = a[0]; //can I prevent this Copy from happening? a lint for it? eg. I actually wanted &a[0] or a move
    let oldfirst = a[0].clone();//this is acceptable! but implicitly copy like above isn't! TODO: find a way to disable Copy trait!

    a[0] = 7;
    let reffirst:&i32 = &a[0]; //TODO: find out how to keep a ref and still allow assignment - eg. move this line above the assignment line a[0]=7; and have it work!

    println!("The value of first is: {} {} {}", first, oldfirst, reffirst);

    //same syntax can do either an implicity copy or an implicit move - i'd rather have one or the
    //other! if not at least warn me?
    let a1 = [1,2,3];
    let first1 = a[0]; // implicit copy
    let second = a[1];
    let b = [String::from("1"),String::from("2"),String::from("3")];
//    let fb=b[0]; // this wants to do an implicit move
//    let sb=b[1];
}
<commit_msg>ok let's be correct<commit_after>#![feature(plugin)]

#![plugin(clippy)]

#![deny(clippy)]
#![deny(clippy_pedantic)]
#![allow(print_stdout)]
#![allow(clone_on_copy)]

fn main() {
    let mut a = [1, 2, 3, 4, 5];

    //implicit copying OR moving - the bane of Rust :)
    let first = a[0]; //can I prevent this Copy from happening? a lint for it? eg. I actually wanted &a[0] or a move
    let oldfirst = a[0].clone();//this is acceptable! but implicitly copy like above isn't! TODO: find a way to disable Copy trait!

    a[0] = 7;
    let reffirst:&i32 = &a[0]; //TODO: find out how to keep a ref and still allow assignment - eg. move this line above the assignment line a[0]=7; and have it work!

    println!("The value of first is: {} {} {}", first, oldfirst, reffirst);

    //same syntax can do either an implicity copy or an implicit move - i'd rather have one or the
    //other! if not at least warn me?
    let a1 = [1,2,3];
    let first1 = a[0]; // implicit copy
    let second = a[1];
    let b = [String::from("1"),String::from("2"),String::from("3")];
//    let fb=b[0]; // this wants to do an implicit move
//    let sb=b[1];
}
<|endoftext|>


<commit_before>extern crate limonite;

use std::io::File;
use std::io::BufferedReader;
use limonite::syntax::lexer::{Lexer, Tokenizer};
use limonite::syntax::core::tokens::{Token, Comment, Keyword, Identifier, Indent, Punctuation, Str, EOF};
use limonite::syntax::core::keywords::{Print};
use limonite::syntax::core::punctuation::{ParenOpen, ParenClose};

fn cmp_tokens(mut lexer: Lexer, vec: Vec<Token>) {
    for desired_tok in vec.iter() {
        let tok = &lexer.get_tok();

        if tok != desired_tok {
            fail!(format!("Unexpected token {} found. Expected {}.", tok, desired_tok));
        }

        continue
    }
}

#[test]
fn test_hello_world() {
    let path = Path::new("tests/lang/test_hello_world.lim");
    let file = BufferedReader::new(File::open(&path));
    let mut lexer = Lexer::new(file);
    let desired_output = vec![Comment(" Hello World!".to_string()), Indent(0),
                              Comment(" Let's compile!".to_string()), Indent(0),
                              Keyword(Print), Indent(0),
                              Punctuation(ParenOpen), Str("Hello World!".to_string()), Punctuation(ParenClose)];

    cmp_tokens(lexer, desired_output);

}
<commit_msg>Fixed lexer test.<commit_after>extern crate limonite;

use std::io::File;
use std::io::BufferedReader;
use limonite::syntax::lexer::{Lexer, Tokenizer};
use limonite::syntax::core::tokens::{Token, Comment, Keyword, Identifier, Indent, Punctuation, Str, EOF};
use limonite::syntax::core::keywords::{Print};
use limonite::syntax::core::punctuation::{ParenOpen, ParenClose};

fn cmp_tokens(mut lexer: Lexer, vec: Vec<Token>) {
    for desired_tok in vec.iter() {
        let tok = &lexer.get_tok();

        if tok == desired_tok { continue; }

        fail!(format!("Unexpected token {} found. Expected {}.", tok, desired_tok));
    }
}

#[test]
fn test_hello_world() {
    let path = Path::new("tests/lang/test_hello_world.lim");
    let file = BufferedReader::new(File::open(&path));
    let mut lexer = Lexer::new(file);
    let desired_output = vec![Comment(" Hello World!".to_string()), Indent(0),
                              Comment(" Let's compile!".to_string()), Indent(0),
                              Keyword(Print), Indent(0),
                              Punctuation(ParenOpen), Str("Hello World!".to_string()), Punctuation(ParenClose), EOF];

    cmp_tokens(lexer, desired_output);

}
<|endoftext|>


<commit_before>use elements::deserialize_file;
use elements::Module;
use interpreter::{EnvParams, ExecutionParams, DefaultProgramInstance};
use interpreter::value::RuntimeValue;
use interpreter::module::{ModuleInstanceInterface, ItemIndex};

#[test]
fn interpreter_inc_i32() {
    // Name of function contained in WASM file (note the leading underline)
    const FUNCTION_NAME: &'static str = "_inc_i32";
    // The WASM file containing the module and function
    const WASM_FILE: &str = &"res/cases/v1/inc_i32.wasm";

    let program = DefaultProgramInstance::with_env_params(
        EnvParams {
        total_stack: 128 * 1024,
        total_memory: 2 * 1024 * 1024,
        allow_memory_growth: false,
    }).expect("Failed to instanciate program");

    let module: Module =
        deserialize_file(WASM_FILE).expect("Failed to deserialize module from buffer");
    let i32_val = 42;
    // the functions expects a single i32 parameter
    let args = vec![RuntimeValue::I32(i32_val)];
    let exp_retval = Some(RuntimeValue::I32(i32_val + 1));
    let execution_params = ExecutionParams::from(args);

    let module_result = program
        .add_module("main", module, None);

    let module = module_result
        .expect("Failed to initialize module");

    let retval = module
        .execute_export(FUNCTION_NAME, execution_params)
        .expect("");
    assert_eq!(exp_retval, retval);
}

#[test]
fn interpreter_accumulate_u8() {
    // Name of function contained in WASM file (note the leading underline)
    const FUNCTION_NAME: &'static str = "_accumulate_u8";
    // The WASM file containing the module and function
    const WASM_FILE: &str = &"res/cases/v1/accumulate_u8.wasm";
    // The octet sequence being accumulated
    const BUF : &[u8] = & [9,8,7,6,5,4,3,2,1];

    // Declare the memory limits of the runtime-environment
    let program = DefaultProgramInstance::with_env_params(EnvParams {
        total_stack: 128 * 1024,
        total_memory: 2 * 1024 * 1024,
        allow_memory_growth: false,
    }).expect("Failed to instanciate program");

    // Load the module-structure from wasm-file and add to program
    let module: Module =
        deserialize_file(WASM_FILE).expect("Failed to deserialize module from buffer");
    let module = program
        .add_module("main", module, None)
        .expect("Failed to initialize module");

    // => env module is created
    let env_instance = program.module("env").unwrap();
    // => linear memory is created
    let env_memory = env_instance.memory(ItemIndex::Internal(0)).unwrap();

    // Place the octet-sequence at index 0 in linear memory
    let offset : u32 = 0;
    let _ = env_memory.set(offset, BUF);

    // Set up the function argument list and invoke the function
    let args = vec![RuntimeValue::I32(BUF.len() as i32), RuntimeValue::I32(offset as i32)];
    let execution_params = ExecutionParams::from(args);
    let retval = module
        .execute_export(FUNCTION_NAME, execution_params)
        .expect("");

    // For verification, repeat accumulation using native code
    let accu = BUF.into_iter().fold(0 as i32, |a, b| a as i32 + *b as i32);
    let exp_retval: Option<RuntimeValue> = Some(RuntimeValue::I32(accu));

    // Verify calculation from WebAssembly runtime is identical to expected result
    assert_eq!(exp_retval, retval);
}
<commit_msg>code formatting<commit_after>use elements::deserialize_file;
use elements::Module;
use interpreter::{EnvParams, ExecutionParams, DefaultProgramInstance};
use interpreter::value::RuntimeValue;
use interpreter::module::{ModuleInstanceInterface, ItemIndex};

#[test]
fn interpreter_inc_i32() {
    // Name of function contained in WASM file (note the leading underline)
    const FUNCTION_NAME: &'static str = "_inc_i32";
    // The WASM file containing the module and function
    const WASM_FILE: &str = &"res/cases/v1/inc_i32.wasm";

    let program = DefaultProgramInstance::with_env_params(
        EnvParams {
        total_stack: 128 * 1024,
        total_memory: 2 * 1024 * 1024,
        allow_memory_growth: false,
    }).expect("Failed to instanciate program");

    let module: Module =
        deserialize_file(WASM_FILE).expect("Failed to deserialize module from buffer");
    let i32_val = 42;
    // the functions expects a single i32 parameter
    let args = vec![RuntimeValue::I32(i32_val)];
    let exp_retval = Some(RuntimeValue::I32(i32_val + 1));
    let execution_params = ExecutionParams::from(args);

    let module_result = program
        .add_module("main", module, None);

    let module = module_result
        .expect("Failed to initialize module");

    let retval = module
        .execute_export(FUNCTION_NAME, execution_params)
        .expect("");
    assert_eq!(exp_retval, retval);
}

#[test]
fn interpreter_accumulate_u8() {
    // Name of function contained in WASM file (note the leading underline)
    const FUNCTION_NAME: &'static str = "_accumulate_u8";
    // The WASM file containing the module and function
    const WASM_FILE: &str = &"res/cases/v1/accumulate_u8.wasm";
    // The octet sequence being accumulated
    const BUF: &[u8] = &[9,8,7,6,5,4,3,2,1];

    // Declare the memory limits of the runtime-environment
    let program = DefaultProgramInstance::with_env_params(EnvParams {
        total_stack: 128 * 1024,
        total_memory: 2 * 1024 * 1024,
        allow_memory_growth: false,
    }).expect("Failed to instanciate program");

    // Load the module-structure from wasm-file and add to program
    let module: Module =
        deserialize_file(WASM_FILE).expect("Failed to deserialize module from buffer");
    let module = program
        .add_module("main", module, None)
        .expect("Failed to initialize module");

    // => env module is created
    let env_instance = program.module("env").unwrap();
    // => linear memory is created
    let env_memory = env_instance.memory(ItemIndex::Internal(0)).unwrap();

    // Place the octet-sequence at index 0 in linear memory
    let offset: u32 = 0;
    let _ = env_memory.set(offset, BUF);

    // Set up the function argument list and invoke the function
    let args = vec![RuntimeValue::I32(BUF.len() as i32), RuntimeValue::I32(offset as i32)];
    let execution_params = ExecutionParams::from(args);
    let retval = module
        .execute_export(FUNCTION_NAME, execution_params)
        .expect("Failed to execute function");

    // For verification, repeat accumulation using native code
    let accu = BUF.into_iter().fold(0 as i32, |a, b| a + *b as i32);
    let exp_retval: Option<RuntimeValue> = Some(RuntimeValue::I32(accu));

    // Verify calculation from WebAssembly runtime is identical to expected result
    assert_eq!(exp_retval, retval);
}
<|endoftext|>


<commit_before>//! Definition of the `JoinAll` combinator, waiting for all of a list of futures
//! to finish.

use std::prelude::v1::*;

use std::fmt;
use std::mem;

use futures_core::{Future, IntoFuture, Poll, Async};
use futures_core::task;

#[derive(Debug)]
enum ElemState<T> where T: Future {
    Pending(T),
    Done(T::Item),
}

/// A future which takes a list of futures and resolves with a vector of the
/// completed values.
///
/// This future is created with the `join_all` method.
#[must_use = "futures do nothing unless polled"]
pub struct JoinAll<Item>
    where Item: IntoFuture,
{
    elems: Vec<ElemState<<Item as IntoFuture>::Future>>,
}

impl<I> fmt::Debug for JoinAll<I>
    where I: IntoFuture,
          <I as IntoFuture>::Future: fmt::Debug,
          <I as IntoFuture>::Item: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("JoinAll")
            .field("elems", &self.elems)
            .finish()
    }
}

/// Creates a future which represents a collection of the results of the futures
/// given.
///
/// The returned future will drive execution for all of its underlying futures,
/// collecting the results into a destination `Vec<T>` in the same order as they
/// were provided. If any future returns an error then all other futures will be
/// canceled and an error will be returned immediately. If all futures complete
/// successfully, however, then the returned future will succeed with a `Vec` of
/// all the successful results.
///
/// # Examples
///
/// ```
/// # extern crate futures;
/// use futures::prelude::*;
/// use futures::future::{join_all, ok, err};
///
/// # fn main() {
/// #
/// let f = join_all(vec![
///     ok::<u32, u32>(1),
///     ok::<u32, u32>(2),
///     ok::<u32, u32>(3),
/// ]);
/// let f = f.map(|x| {
///     assert_eq!(x, [1, 2, 3]);
/// });
///
/// let f = join_all(vec![
///     Box::new(ok::<u32, u32>(1)),
///     Box::new(err::<u32, u32>(2)),
///     Box::new(ok::<u32, u32>(3)),
/// ]);
/// let f = f.then(|x| {
///     assert_eq!(x, Err(2));
///     x
/// });
/// # }
/// ```
pub fn join_all<I>(i: I) -> JoinAll<I::Item>
    where I: IntoIterator,
          I::Item: IntoFuture,
{
    let elems = i.into_iter().map(|f| {
        ElemState::Pending(f.into_future())
    }).collect();
    JoinAll { elems: elems }
}

impl<Item> Future for JoinAll<Item>
    where Item: IntoFuture,
{
    type Item = Vec<<Item as IntoFuture>::Item>;
    type Error = <Item as IntoFuture>::Error;

    fn poll(&mut self, cx: &mut task::Context) -> Poll<Self::Item, Self::Error> {
        let mut all_done = true;

        for idx in 0 .. self.elems.len() {
            let done_val = match self.elems[idx] {
                ElemState::Pending(ref mut t) => {
                    match t.poll(cx) {
                        Ok(Async::Ready(v)) => Ok(v),
                        Ok(Async::Pending) => {
                            all_done = false;
                            continue
                        }
                        Err(e) => Err(e),
                    }
                }
                ElemState::Done(ref mut _v) => continue,
            };

            match done_val {
                Ok(v) => self.elems[idx] = ElemState::Done(v),
                Err(e) => {
                    // On completion drop all our associated resources
                    // ASAP.
                    self.elems = Vec::new();
                    return Err(e)
                }
            }
        }

        if all_done {
            let elems = mem::replace(&mut self.elems, Vec::new());
            let result = elems.into_iter().map(|e| {
                match e {
                    ElemState::Done(t) => t,
                    _ => unreachable!(),
                }
            }).collect();
            Ok(Async::Ready(result))
        } else {
            Ok(Async::Pending)
        }
    }
}
<commit_msg>Simplify JoinAll<commit_after>//! Definition of the `JoinAll` combinator, waiting for all of a list of futures
//! to finish.

use std::prelude::v1::*;

use std::fmt;
use std::mem;

use futures_core::{Future, IntoFuture, Poll, Async};
use futures_core::task;

#[derive(Debug)]
enum ElemState<F> where F: Future {
    Pending(F),
    Done(F::Item),
}

/// A future which takes a list of futures and resolves with a vector of the
/// completed values.
///
/// This future is created with the `join_all` method.
#[must_use = "futures do nothing unless polled"]
pub struct JoinAll<F>
    where F: Future,
{
    elems: Vec<ElemState<F>>,
}

impl<F> fmt::Debug for JoinAll<F>
    where F: Future + fmt::Debug,
          F::Item: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("JoinAll")
            .field("elems", &self.elems)
            .finish()
    }
}

/// Creates a future which represents a collection of the results of the futures
/// given.
///
/// The returned future will drive execution for all of its underlying futures,
/// collecting the results into a destination `Vec<T>` in the same order as they
/// were provided. If any future returns an error then all other futures will be
/// canceled and an error will be returned immediately. If all futures complete
/// successfully, however, then the returned future will succeed with a `Vec` of
/// all the successful results.
///
/// # Examples
///
/// ```
/// # extern crate futures;
/// use futures::prelude::*;
/// use futures::future::{join_all, ok, err};
///
/// # fn main() {
/// #
/// let f = join_all(vec![
///     ok::<u32, u32>(1),
///     ok::<u32, u32>(2),
///     ok::<u32, u32>(3),
/// ]);
/// let f = f.map(|x| {
///     assert_eq!(x, [1, 2, 3]);
/// });
///
/// let f = join_all(vec![
///     Box::new(ok::<u32, u32>(1)),
///     Box::new(err::<u32, u32>(2)),
///     Box::new(ok::<u32, u32>(3)),
/// ]);
/// let f = f.then(|x| {
///     assert_eq!(x, Err(2));
///     x
/// });
/// # }
/// ```
pub fn join_all<I>(i: I) -> JoinAll<<I::Item as IntoFuture>::Future>
    where I: IntoIterator,
          I::Item: IntoFuture,
{
    let elems = i.into_iter().map(|f| {
        ElemState::Pending(f.into_future())
    }).collect();
    JoinAll { elems }
}

impl<F> Future for JoinAll<F>
    where F: Future,
{
    type Item = Vec<F::Item>;
    type Error = F::Error;

    fn poll(&mut self, cx: &mut task::Context) -> Poll<Self::Item, Self::Error> {
        let mut all_done = true;

        for idx in 0 .. self.elems.len() {
            let done_val = match self.elems[idx] {
                ElemState::Pending(ref mut t) => {
                    match t.poll(cx) {
                        Ok(Async::Ready(v)) => Ok(v),
                        Ok(Async::Pending) => {
                            all_done = false;
                            continue
                        }
                        Err(e) => Err(e),
                    }
                }
                ElemState::Done(ref mut _v) => continue,
            };

            match done_val {
                Ok(v) => self.elems[idx] = ElemState::Done(v),
                Err(e) => {
                    // On completion drop all our associated resources
                    // ASAP.
                    self.elems = Vec::new();
                    return Err(e)
                }
            }
        }

        if all_done {
            let elems = mem::replace(&mut self.elems, Vec::new());
            let result = elems.into_iter().map(|e| {
                match e {
                    ElemState::Done(t) => t,
                    _ => unreachable!(),
                }
            }).collect();
            Ok(Async::Ready(result))
        } else {
            Ok(Async::Pending)
        }
    }
}
<|endoftext|>