<commit_before>use consts::LINK_CONTROL_BYTES;
use util::{slice_u16, slice_u24};

use trunking::fields::{
    TalkGroup,
    Channel,
    SystemServices,
    ServiceOptions,
    ChannelUpdates,
    parse_updates,
};

pub type Buf = [u8; LINK_CONTROL_BYTES];

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum LinkControlOpcode {
    GroupVoiceTraffic,
    GroupVoiceUpdate,
    UnitVoiceTraffic,
    GroupVoiceUpdateExplicit,
    UnitVoiceRequest,
    PhoneVoiceTraffic,
    PhoneVoiceRequest,
    CallTermination,
    GroupAffiliationQuery,
    UnitRegistrationRequest,
    UnitAuthenticationRequst,
    UnitStatusRequest,
    SystemServiceBroadcast,
    AltControlChannel,
    AdjacentSite,
    RFSSStatusBroadcast,
    NetworkStatusBroadcast,
    UnitStatusUpdate,
    UnitShortMessage,
    UnitCallAlert,
    ExtendedFunction,
    ChannelParamsUpdate,
    ProtectionParamBroadcast,
    AltControlChannelExplicit,
    AdjacentSiteExplicit,
    ChannelParamsExplicit,
    RFSSStatusExplicit,
    NetworkStatusExplicit,
}

impl LinkControlOpcode {
    pub fn from_bits(bits: u8) -> Option<LinkControlOpcode> {
        use self::LinkControlOpcode::*;

        match bits {
            0b000000 => Some(GroupVoiceTraffic),
            0b000010 => Some(GroupVoiceUpdate),
            0b000011 => Some(UnitVoiceTraffic),
            0b000100 => Some(GroupVoiceUpdateExplicit),
            0b000101 => Some(UnitVoiceRequest),
            0b000110 => Some(PhoneVoiceTraffic),
            0b000111 => Some(PhoneVoiceRequest),
            0b001111 => Some(CallTermination),
            0b010000 => Some(GroupAffiliationQuery),
            0b010001 => Some(UnitRegistrationRequest),
            0b010010 => Some(UnitAuthenticationRequst),
            0b010011 => Some(UnitStatusRequest),
            0b100000 => Some(SystemServiceBroadcast),
            0b100001 => Some(AltControlChannel),
            0b100010 => Some(AdjacentSite),
            0b100011 => Some(RFSSStatusBroadcast),
            0b100100 => Some(NetworkStatusBroadcast),
            0b010100 => Some(UnitStatusUpdate),
            0b010101 => Some(UnitShortMessage),
            0b010110 => Some(UnitCallAlert),
            0b010111 => Some(ExtendedFunction),
            0b011000 => Some(ChannelParamsUpdate),
            0b100101 => Some(ProtectionParamBroadcast),
            0b100110 => Some(AltControlChannelExplicit),
            0b100111 => Some(AdjacentSiteExplicit),
            0b011001 => Some(ChannelParamsExplicit),
            0b101000 => Some(RFSSStatusExplicit),
            0b101001 => Some(NetworkStatusExplicit),
            _ => None,
        }
    }
}

/// Link Control information carried within voice packets.
#[derive(Copy, Clone)]
pub struct LinkControlFields(Buf);

impl LinkControlFields {
    /// Interpret the given bytes as a link control packet.
    pub fn new(buf: Buf) -> Self { LinkControlFields(buf) }

    /// Whether the packet is encrypted.
    pub fn protected(&self) -> bool { self.0[0] >> 7 == 1 }

    /// Type of data contained in the payload.
    pub fn opcode(&self) -> Option<LinkControlOpcode> {
        LinkControlOpcode::from_bits(self.0[0] & 0x3F)
    }
}

pub struct GroupVoiceTraffic(Buf);

impl GroupVoiceTraffic {
    pub fn new(lc: LinkControlFields) -> Self { GroupVoiceTraffic(lc.0) }

    pub fn mfg(&self) -> u8 { self.0[1] }
    pub fn opts(&self) -> ServiceOptions { ServiceOptions::new(self.0[2]) }
    pub fn talk_group(&self) -> TalkGroup { TalkGroup::new(&self.0[4..]) }
    pub fn src_unit(&self) -> u32 { slice_u24(&self.0[6..]) }
}

pub struct GroupVoiceUpdate(Buf);

impl GroupVoiceUpdate {
    pub fn new(lc: LinkControlFields) -> Self { GroupVoiceUpdate(lc.0) }

    pub fn updates(&self) -> ChannelUpdates { parse_updates(&self.0[1...8]) }
}

pub struct UnitVoiceTraffic(Buf);

impl UnitVoiceTraffic {
    pub fn new(lc: LinkControlFields) -> Self { UnitVoiceTraffic(lc.0) }

    pub fn mfg(&self) -> u8 { self.0[1] }
    pub fn opts(&self) -> ServiceOptions { ServiceOptions::new(self.0[2]) }
    pub fn dest_unit(&self) -> u32 { slice_u24(&self.0[3..]) }
    pub fn src_unit(&self) -> u32 { slice_u24(&self.0[6..]) }
}

pub struct CallTermination(Buf);

impl CallTermination {
    pub fn new(lc: LinkControlFields) -> Self { CallTermination(lc.0) }
    pub fn unit(&self) -> u32 { slice_u24(&self.0[6..]) }
}

pub struct AdjacentSiteBroadcast(Buf);

impl AdjacentSiteBroadcast {
    pub fn new(lc: LinkControlFields) -> Self { AdjacentSiteBroadcast(lc.0) }
    pub fn area(&self) -> u8 { self.0[1] }
    pub fn system(&self) -> u16 { slice_u16(&self.0[2..]) & 0xFFF }
    pub fn rfss(&self) -> u8 { self.0[4] }
    pub fn site(&self) -> u8 { self.0[5] }
    pub fn channel(&self) -> Channel { Channel::new(&self.0[6..]) }
    pub fn services(&self) -> SystemServices { SystemServices::new(self.0[8]) }
}

#[cfg(test)]
mod test {
    use super::*;
    use trunking::fields::{TalkGroup};

    #[test]
    fn test_lc() {
        let lc = LinkControlFields::new([
            0b00000000,
            0b00000000,
            0b10110101, 0b00000000,
            0b00000000, 0b00000001,
            0xDE, 0xAD, 0xBE,
        ]);

        assert_eq!(lc.opcode(), Some(LinkControlOpcode::GroupVoiceTraffic));
        assert_eq!(lc.protected(), false);

        let dec = GroupVoiceTraffic::new(lc);
        let opts = dec.opts();

        assert_eq!(dec.mfg(), 0);
        assert_eq!(dec.talk_group(), TalkGroup::Default);
        assert_eq!(dec.src_unit(), 0xDEADBE);

        assert_eq!(opts.emergency(), true);
        assert_eq!(opts.protected(), false);
        assert_eq!(opts.duplex(), true);
        assert_eq!(opts.packet_switched(), true);
        assert_eq!(opts.prio(), 5);
    }
}
<commit_msg>Split up test<commit_after>use consts::LINK_CONTROL_BYTES;
use util::{slice_u16, slice_u24};

use trunking::fields::{
    TalkGroup,
    Channel,
    SystemServices,
    ServiceOptions,
    ChannelUpdates,
    parse_updates,
};

pub type Buf = [u8; LINK_CONTROL_BYTES];

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum LinkControlOpcode {
    GroupVoiceTraffic,
    GroupVoiceUpdate,
    UnitVoiceTraffic,
    GroupVoiceUpdateExplicit,
    UnitVoiceRequest,
    PhoneVoiceTraffic,
    PhoneVoiceRequest,
    CallTermination,
    GroupAffiliationQuery,
    UnitRegistrationRequest,
    UnitAuthenticationRequst,
    UnitStatusRequest,
    SystemServiceBroadcast,
    AltControlChannel,
    AdjacentSite,
    RFSSStatusBroadcast,
    NetworkStatusBroadcast,
    UnitStatusUpdate,
    UnitShortMessage,
    UnitCallAlert,
    ExtendedFunction,
    ChannelParamsUpdate,
    ProtectionParamBroadcast,
    AltControlChannelExplicit,
    AdjacentSiteExplicit,
    ChannelParamsExplicit,
    RFSSStatusExplicit,
    NetworkStatusExplicit,
}

impl LinkControlOpcode {
    pub fn from_bits(bits: u8) -> Option<LinkControlOpcode> {
        use self::LinkControlOpcode::*;

        match bits {
            0b000000 => Some(GroupVoiceTraffic),
            0b000010 => Some(GroupVoiceUpdate),
            0b000011 => Some(UnitVoiceTraffic),
            0b000100 => Some(GroupVoiceUpdateExplicit),
            0b000101 => Some(UnitVoiceRequest),
            0b000110 => Some(PhoneVoiceTraffic),
            0b000111 => Some(PhoneVoiceRequest),
            0b001111 => Some(CallTermination),
            0b010000 => Some(GroupAffiliationQuery),
            0b010001 => Some(UnitRegistrationRequest),
            0b010010 => Some(UnitAuthenticationRequst),
            0b010011 => Some(UnitStatusRequest),
            0b100000 => Some(SystemServiceBroadcast),
            0b100001 => Some(AltControlChannel),
            0b100010 => Some(AdjacentSite),
            0b100011 => Some(RFSSStatusBroadcast),
            0b100100 => Some(NetworkStatusBroadcast),
            0b010100 => Some(UnitStatusUpdate),
            0b010101 => Some(UnitShortMessage),
            0b010110 => Some(UnitCallAlert),
            0b010111 => Some(ExtendedFunction),
            0b011000 => Some(ChannelParamsUpdate),
            0b100101 => Some(ProtectionParamBroadcast),
            0b100110 => Some(AltControlChannelExplicit),
            0b100111 => Some(AdjacentSiteExplicit),
            0b011001 => Some(ChannelParamsExplicit),
            0b101000 => Some(RFSSStatusExplicit),
            0b101001 => Some(NetworkStatusExplicit),
            _ => None,
        }
    }
}

/// Link Control information carried within voice packets.
#[derive(Copy, Clone)]
pub struct LinkControlFields(Buf);

impl LinkControlFields {
    /// Interpret the given bytes as a link control packet.
    pub fn new(buf: Buf) -> Self { LinkControlFields(buf) }

    /// Whether the packet is encrypted.
    pub fn protected(&self) -> bool { self.0[0] >> 7 == 1 }

    /// Type of data contained in the payload.
    pub fn opcode(&self) -> Option<LinkControlOpcode> {
        LinkControlOpcode::from_bits(self.0[0] & 0x3F)
    }
}

pub struct GroupVoiceTraffic(Buf);

impl GroupVoiceTraffic {
    pub fn new(lc: LinkControlFields) -> Self { GroupVoiceTraffic(lc.0) }

    pub fn mfg(&self) -> u8 { self.0[1] }
    pub fn opts(&self) -> ServiceOptions { ServiceOptions::new(self.0[2]) }
    pub fn talk_group(&self) -> TalkGroup { TalkGroup::new(&self.0[4..]) }
    pub fn src_unit(&self) -> u32 { slice_u24(&self.0[6..]) }
}

pub struct GroupVoiceUpdate(Buf);

impl GroupVoiceUpdate {
    pub fn new(lc: LinkControlFields) -> Self { GroupVoiceUpdate(lc.0) }

    pub fn updates(&self) -> ChannelUpdates { parse_updates(&self.0[1...8]) }
}

pub struct UnitVoiceTraffic(Buf);

impl UnitVoiceTraffic {
    pub fn new(lc: LinkControlFields) -> Self { UnitVoiceTraffic(lc.0) }

    pub fn mfg(&self) -> u8 { self.0[1] }
    pub fn opts(&self) -> ServiceOptions { ServiceOptions::new(self.0[2]) }
    pub fn dest_unit(&self) -> u32 { slice_u24(&self.0[3..]) }
    pub fn src_unit(&self) -> u32 { slice_u24(&self.0[6..]) }
}

pub struct CallTermination(Buf);

impl CallTermination {
    pub fn new(lc: LinkControlFields) -> Self { CallTermination(lc.0) }
    pub fn unit(&self) -> u32 { slice_u24(&self.0[6..]) }
}

pub struct AdjacentSiteBroadcast(Buf);

impl AdjacentSiteBroadcast {
    pub fn new(lc: LinkControlFields) -> Self { AdjacentSiteBroadcast(lc.0) }
    pub fn area(&self) -> u8 { self.0[1] }
    pub fn system(&self) -> u16 { slice_u16(&self.0[2..]) & 0xFFF }
    pub fn rfss(&self) -> u8 { self.0[4] }
    pub fn site(&self) -> u8 { self.0[5] }
    pub fn channel(&self) -> Channel { Channel::new(&self.0[6..]) }
    pub fn services(&self) -> SystemServices { SystemServices::new(self.0[8]) }
}

#[cfg(test)]
mod test {
    use super::*;
    use trunking::fields::{TalkGroup};

    #[test]
    fn test_lc() {
        let lc = LinkControlFields::new([
            0b00000000,
            0b00000000,
            0b10110101, 0b00000000,
            0b00000000, 0b00000001,
            0xDE, 0xAD, 0xBE,
        ]);

        assert_eq!(lc.opcode(), Some(LinkControlOpcode::GroupVoiceTraffic));
        assert_eq!(lc.protected(), false);
    }

    #[test]
    fn test_group_voice_traffic() {
        let lc = LinkControlFields::new([
            0b00000000,
            0b00000000,
            0b10110101, 0b00000000,
            0b00000000, 0b00000001,
            0xDE, 0xAD, 0xBE,
        ]);

        let dec = GroupVoiceTraffic::new(lc);
        let opts = dec.opts();

        assert_eq!(dec.mfg(), 0);
        assert_eq!(dec.talk_group(), TalkGroup::Default);
        assert_eq!(dec.src_unit(), 0xDEADBE);

        assert_eq!(opts.emergency(), true);
        assert_eq!(opts.protected(), false);
        assert_eq!(opts.duplex(), true);
        assert_eq!(opts.packet_switched(), true);
        assert_eq!(opts.prio(), 5);
    }
}
<|endoftext|>


<commit_before>use std::fmt;

use bytes::Bytes;
use js_sys::Uint8Array;
use http::{HeaderMap, StatusCode};
use url::Url;

#[cfg(feature = "json")]
use serde::de::DeserializeOwned;

/// A Response to a submitted `Request`.
pub struct Response {
    http: http::Response<web_sys::Response>,
    // Boxed to save space (11 words to 1 word), and it's not accessed
    // frequently internally.
    url: Box<Url>,
}

impl Response {
    pub(super) fn new(
        res: http::Response<web_sys::Response>,
        url: Url,
    ) -> Response {
        Response {
            http: res,
            url: Box::new(url),
        }
    }

    /// Get the `StatusCode` of this `Response`.
    #[inline]
    pub fn status(&self) -> StatusCode {
        self.http.status()
    }

    /// Get the `Headers` of this `Response`.
    #[inline]
    pub fn headers(&self) -> &HeaderMap {
        self.http.headers()
    }

    /// Get a mutable reference to the `Headers` of this `Response`.
    #[inline]
    pub fn headers_mut(&mut self) -> &mut HeaderMap {
        self.http.headers_mut()
    }

    /// Get the content-length of this response, if known.
    ///
    /// Reasons it may not be known:
    ///
    /// - The server didn't send a `content-length` header.
    /// - The response is compressed and automatically decoded (thus changing
    //   the actual decoded length).
    pub fn content_length(&self) -> Option<u64> {
        self.headers()
            .get(http::header::CONTENT_LENGTH)?
            .to_str()
            .ok()?
            .parse()
            .ok()
    }

    /// Get the final `Url` of this `Response`.
    #[inline]
    pub fn url(&self) -> &Url {
        &self.url
    }

    /* It might not be possible to detect this in JS?
    /// Get the HTTP `Version` of this `Response`.
    #[inline]
    pub fn version(&self) -> Version {
        self.http.version()
    }
    */

    /// Try to deserialize the response body as JSON.
    #[cfg(feature = "json")]
    pub async fn json<T: DeserializeOwned>(self) -> crate::Result<T> {
        let full = self.bytes().await?;

        serde_json::from_slice(&full).map_err(crate::error::decode)
    }

    /// Get the response text.
    pub async fn text(self) -> crate::Result<String> {
        let p = self.http.body().text()
            .map_err(crate::error::wasm)
            .map_err(crate::error::decode)?;
        let js_val = super::promise::<wasm_bindgen::JsValue>(p)
            .await
            .map_err(crate::error::decode)?;
        if let Some(s) = js_val.as_string() {
            Ok(s)
        } else {
            Err(crate::error::decode("response.text isn't string"))
        }
    }

    /// Get the response as bytes
    pub async fn bytes(self) -> crate::Result<Bytes> {
        let p = self.http.body().array_buffer()
            .map_err(crate::error::wasm)
            .map_err(crate::error::decode)?;

        let buf_js = super::promise::<wasm_bindgen::JsValue>(p)
            .await
            .map_err(crate::error::decode)?;

        let buffer = Uint8Array::new(&buf_js);
        let mut bytes = vec![0; buffer.length() as usize];
        buffer.copy_to(&mut bytes);
        Ok(bytes.into())
    }

    // util methods

    /// Turn a response into an error if the server returned an error.
    pub fn error_for_status(self) -> crate::Result<Self> {
        let status = self.status();
        if status.is_client_error() || status.is_server_error() {
            Err(crate::error::status_code(*self.url, status))
        } else {
            Ok(self)
        }
    }

    /// Turn a reference to a response into an error if the server returned an error.
    pub fn error_for_status_ref(&self) -> crate::Result<&Self> {
        let status = self.status();
        if status.is_client_error() || status.is_server_error() {
            Err(crate::error::status_code(*self.url.clone(), status))
        } else {
            Ok(self)
        }
    }
}

impl fmt::Debug for Response {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Response")
            //.field("url", self.url())
            .field("status", &self.status())
            .field("headers", self.headers())
            .finish()
    }
}
<commit_msg>Fix documentation line in for wasm Response<commit_after>use std::fmt;

use bytes::Bytes;
use js_sys::Uint8Array;
use http::{HeaderMap, StatusCode};
use url::Url;

#[cfg(feature = "json")]
use serde::de::DeserializeOwned;

/// A Response to a submitted `Request`.
pub struct Response {
    http: http::Response<web_sys::Response>,
    // Boxed to save space (11 words to 1 word), and it's not accessed
    // frequently internally.
    url: Box<Url>,
}

impl Response {
    pub(super) fn new(
        res: http::Response<web_sys::Response>,
        url: Url,
    ) -> Response {
        Response {
            http: res,
            url: Box::new(url),
        }
    }

    /// Get the `StatusCode` of this `Response`.
    #[inline]
    pub fn status(&self) -> StatusCode {
        self.http.status()
    }

    /// Get the `Headers` of this `Response`.
    #[inline]
    pub fn headers(&self) -> &HeaderMap {
        self.http.headers()
    }

    /// Get a mutable reference to the `Headers` of this `Response`.
    #[inline]
    pub fn headers_mut(&mut self) -> &mut HeaderMap {
        self.http.headers_mut()
    }

    /// Get the content-length of this response, if known.
    ///
    /// Reasons it may not be known:
    ///
    /// - The server didn't send a `content-length` header.
    /// - The response is compressed and automatically decoded (thus changing
    ///  the actual decoded length).
    pub fn content_length(&self) -> Option<u64> {
        self.headers()
            .get(http::header::CONTENT_LENGTH)?
            .to_str()
            .ok()?
            .parse()
            .ok()
    }

    /// Get the final `Url` of this `Response`.
    #[inline]
    pub fn url(&self) -> &Url {
        &self.url
    }

    /* It might not be possible to detect this in JS?
    /// Get the HTTP `Version` of this `Response`.
    #[inline]
    pub fn version(&self) -> Version {
        self.http.version()
    }
    */

    /// Try to deserialize the response body as JSON.
    #[cfg(feature = "json")]
    pub async fn json<T: DeserializeOwned>(self) -> crate::Result<T> {
        let full = self.bytes().await?;

        serde_json::from_slice(&full).map_err(crate::error::decode)
    }

    /// Get the response text.
    pub async fn text(self) -> crate::Result<String> {
        let p = self.http.body().text()
            .map_err(crate::error::wasm)
            .map_err(crate::error::decode)?;
        let js_val = super::promise::<wasm_bindgen::JsValue>(p)
            .await
            .map_err(crate::error::decode)?;
        if let Some(s) = js_val.as_string() {
            Ok(s)
        } else {
            Err(crate::error::decode("response.text isn't string"))
        }
    }

    /// Get the response as bytes
    pub async fn bytes(self) -> crate::Result<Bytes> {
        let p = self.http.body().array_buffer()
            .map_err(crate::error::wasm)
            .map_err(crate::error::decode)?;

        let buf_js = super::promise::<wasm_bindgen::JsValue>(p)
            .await
            .map_err(crate::error::decode)?;

        let buffer = Uint8Array::new(&buf_js);
        let mut bytes = vec![0; buffer.length() as usize];
        buffer.copy_to(&mut bytes);
        Ok(bytes.into())
    }

    // util methods

    /// Turn a response into an error if the server returned an error.
    pub fn error_for_status(self) -> crate::Result<Self> {
        let status = self.status();
        if status.is_client_error() || status.is_server_error() {
            Err(crate::error::status_code(*self.url, status))
        } else {
            Ok(self)
        }
    }

    /// Turn a reference to a response into an error if the server returned an error.
    pub fn error_for_status_ref(&self) -> crate::Result<&Self> {
        let status = self.status();
        if status.is_client_error() || status.is_server_error() {
            Err(crate::error::status_code(*self.url.clone(), status))
        } else {
            Ok(self)
        }
    }
}

impl fmt::Debug for Response {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Response")
            //.field("url", self.url())
            .field("status", &self.status())
            .field("headers", self.headers())
            .finish()
    }
}
<|endoftext|>


<commit_before>use std::fmt;

use bytes::Bytes;
use js_sys::Uint8Array;
use http::{HeaderMap, StatusCode};
use url::Url;

/// A Response to a submitted `Request`.
pub struct Response {
    http: http::Response<web_sys::Response>,
    // Boxed to save space (11 words to 1 word), and it's not accessed
    // frequently internally.
    url: Box<Url>,
}

impl Response {
    pub(super) fn new(
        res: http::Response<web_sys::Response>,
        url: Url,
    ) -> Response {
        Response {
            http: res,
            url: Box::new(url),
        }
    }

    /// Get the `StatusCode` of this `Response`.
    #[inline]
    pub fn status(&self) -> StatusCode {
        self.http.status()
    }

    /// Get the `Headers` of this `Response`.
    #[inline]
    pub fn headers(&self) -> &HeaderMap {
        self.http.headers()
    }

    /// Get a mutable reference to the `Headers` of this `Response`.
    #[inline]
    pub fn headers_mut(&mut self) -> &mut HeaderMap {
        self.http.headers_mut()
    }

    /// Get the final `Url` of this `Response`.
    #[inline]
    pub fn url(&self) -> &Url {
        &self.url
    }

    /* It might not be possible to detect this in JS?
    /// Get the HTTP `Version` of this `Response`.
    #[inline]
    pub fn version(&self) -> Version {
        self.http.version()
    }
    */

    // pub async fn json()

    /// Get the response text.
    pub async fn text(self) -> crate::Result<String> {
        let p = self.http.body().text()
            .map_err(crate::error::wasm)
            .map_err(crate::error::decode)?;
        let js_val = super::promise::<wasm_bindgen::JsValue>(p)
            .await
            .map_err(crate::error::decode)?;
        if let Some(s) = js_val.as_string() {
            Ok(s)
        } else {
            Err(crate::error::decode("response.text isn't string"))
        }
    }

    /// Get the response as bytes
    pub async fn bytes(self) -> crate::Result<Bytes> {
        let p = self.http.body().array_buffer()
            .map_err(crate::error::wasm)
            .map_err(crate::error::decode)?;

        let buf_js = super::promise::<wasm_bindgen::JsValue>(p)
            .await
            .map_err(crate::error::decode)?;

        let buffer = Uint8Array::new(&buf_js);
        let mut bytes = vec![0; buffer.length() as usize];
        buffer.copy_to(&mut bytes);
        Ok(bytes.into())
    }
}

impl fmt::Debug for Response {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Response")
            //.field("url", self.url())
            .field("status", &self.status())
            .field("headers", self.headers())
            .finish()
    }
}
<commit_msg>wasm: add error_for_status to wasm response (#779)<commit_after>use std::fmt;

use bytes::Bytes;
use js_sys::Uint8Array;
use http::{HeaderMap, StatusCode};
use url::Url;

/// A Response to a submitted `Request`.
pub struct Response {
    http: http::Response<web_sys::Response>,
    // Boxed to save space (11 words to 1 word), and it's not accessed
    // frequently internally.
    url: Box<Url>,
}

impl Response {
    pub(super) fn new(
        res: http::Response<web_sys::Response>,
        url: Url,
    ) -> Response {
        Response {
            http: res,
            url: Box::new(url),
        }
    }

    /// Get the `StatusCode` of this `Response`.
    #[inline]
    pub fn status(&self) -> StatusCode {
        self.http.status()
    }

    /// Get the `Headers` of this `Response`.
    #[inline]
    pub fn headers(&self) -> &HeaderMap {
        self.http.headers()
    }

    /// Get a mutable reference to the `Headers` of this `Response`.
    #[inline]
    pub fn headers_mut(&mut self) -> &mut HeaderMap {
        self.http.headers_mut()
    }

    /// Get the final `Url` of this `Response`.
    #[inline]
    pub fn url(&self) -> &Url {
        &self.url
    }

    /* It might not be possible to detect this in JS?
    /// Get the HTTP `Version` of this `Response`.
    #[inline]
    pub fn version(&self) -> Version {
        self.http.version()
    }
    */

    // pub async fn json()

    /// Get the response text.
    pub async fn text(self) -> crate::Result<String> {
        let p = self.http.body().text()
            .map_err(crate::error::wasm)
            .map_err(crate::error::decode)?;
        let js_val = super::promise::<wasm_bindgen::JsValue>(p)
            .await
            .map_err(crate::error::decode)?;
        if let Some(s) = js_val.as_string() {
            Ok(s)
        } else {
            Err(crate::error::decode("response.text isn't string"))
        }
    }

    /// Get the response as bytes
    pub async fn bytes(self) -> crate::Result<Bytes> {
        let p = self.http.body().array_buffer()
            .map_err(crate::error::wasm)
            .map_err(crate::error::decode)?;

        let buf_js = super::promise::<wasm_bindgen::JsValue>(p)
            .await
            .map_err(crate::error::decode)?;

        let buffer = Uint8Array::new(&buf_js);
        let mut bytes = vec![0; buffer.length() as usize];
        buffer.copy_to(&mut bytes);
        Ok(bytes.into())
    }

    // util methods

    /// Turn a response into an error if the server returned an error.
    pub fn error_for_status(self) -> crate::Result<Self> {
        let status = self.status();
        if status.is_client_error() || status.is_server_error() {
            Err(crate::error::status_code(*self.url, status))
        } else {
            Ok(self)
        }
    }

    /// Turn a reference to a response into an error if the server returned an error.
    pub fn error_for_status_ref(&self) -> crate::Result<&Self> {
        let status = self.status();
        if status.is_client_error() || status.is_server_error() {
            Err(crate::error::status_code(*self.url.clone(), status))
        } else {
            Ok(self)
        }
    }
}

impl fmt::Debug for Response {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Response")
            //.field("url", self.url())
            .field("status", &self.status())
            .field("headers", self.headers())
            .finish()
    }
}
<|endoftext|>


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

use std::path::Path;

const CARGO_LOCK: &'static str = "Cargo.lock";

pub fn check(path: &Path, bad: &mut bool) {
    use std::process::Command;

    super::walk(path,
                &mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
                &mut |file| {
        let name = file.file_name().unwrap().to_string_lossy();
        if name == CARGO_LOCK {
            let rel_path = file.strip_prefix(path).unwrap();
            let ret_code = Command::new("git")
                                        .arg("diff-index")
                                        .arg("--quiet")
                                        .arg("HEAD")
                                        .arg(rel_path)
                                        .current_dir(path)
                                        .status()
                                        .unwrap_or_else(|e| {
                                            panic!("could not run git diff-index: {}", e);
                                        });
            if !ret_code.success() {
                let parent_path = file.parent().unwrap().join("Cargo.toml");
                print!("dirty lock file found at {} ", rel_path.display());
                println!("please commit your changes or update the lock file by running:");
                println!("\n\tcargo update --manifest-path {}", parent_path.display());
                *bad = true;
            }
        }
    });
}
<commit_msg>Fix make-tidy lock file checks<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::path::Path;
use std::ffi::OsStr;

const CARGO_LOCK: &'static str = "Cargo.lock";

pub fn check(path: &Path, bad: &mut bool) {
    use std::process::Command;

    super::walk(path,
                &mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
                &mut |file| {
        if let Some(CARGO_LOCK) = file.file_name().and_then(OsStr::to_str) {
            let rel_path = file.strip_prefix(path).unwrap();
            let git_friendly_path = rel_path.to_str().unwrap().replace("\\", "/");
            let ret_code = Command::new("git")
                                        .arg("diff")
                                        .arg("--exit-code")
                                        .arg("--patch")
                                        .arg("HEAD")
                                        .arg(&git_friendly_path)
                                        .current_dir(path)
                                        .status()
                                        .unwrap_or_else(|e| {
                                            panic!("could not run git diff-index: {}", e);
                                        });
            if !ret_code.success() {
                let parent_path = file.parent().unwrap().join("Cargo.toml");
                print!("dirty lock file found at {} ", rel_path.display());
                println!("please commit your changes or update the lock file by running:");
                println!("\n\tcargo update --manifest-path {}", parent_path.display());
                *bad = true;
            }
        }
    });
}
<|endoftext|>


<commit_before>//! Eigenvalue decomposition for non-symmetric square matrices

use crate::error::*;
use crate::layout::*;
use crate::types::*;
use ndarray::*;

/// Eigenvalue decomposition of general matrix reference
pub trait Eig {
    /// EigVec is the right eivenvector
    type EigVal;
    type EigVec;
    /// Calculate eigenvalues with the right eigenvector
    ///
    /// $$ A u_i = \lambda_i u_i $$
    ///
    /// ```
    /// use ndarray::*;
    /// use ndarray_linalg::*;
    ///
    /// let a: Array2<f64> = array![
    ///     [-1.01,  0.86, -4.60,  3.31, -4.81],
    ///     [ 3.98,  0.53, -7.04,  5.29,  3.55],
    ///     [ 3.30,  8.26, -3.89,  8.20, -1.51],
    ///     [ 4.43,  4.96, -7.66, -7.33,  6.18],
    ///     [ 7.31, -6.43, -6.16,  2.47,  5.58],
    /// ];
    /// let (eigs, vecs) = a.eig().unwrap();
    ///
    /// let a = a.map(|v| v.as_c());
    /// for (&e, vec) in eigs.iter().zip(vecs.axis_iter(Axis(1))) {
    ///     let ev = vec.map(|v| v * e);
    ///     let av = a.dot(&vec);
    ///     assert_close_l2!(&av, &ev, 1e-5);
    /// }
    /// ```
    fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)>;
}

impl<A, S> Eig for ArrayBase<S, Ix2>
where
    A: Scalar + Lapack,
    S: Data<Elem = A>,
{
    type EigVal = Array1<A::Complex>;
    type EigVec = Array2<A::Complex>;

    fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)> {
        let mut a = self.to_owned();
        let layout = a.square_layout()?;
        let (s, t) = A::eig(true, layout, a.as_allocated_mut()?)?;
        let n = layout.len() as usize;
        Ok((
            ArrayBase::from(s),
            Array2::from_shape_vec((n, n).f(), t).unwrap(),
        ))
    }
}

/// Calculate eigenvalues without eigenvectors
pub trait EigVals {
    type EigVal;
    fn eigvals(&self) -> Result<Self::EigVal>;
}

impl<A, S> EigVals for ArrayBase<S, Ix2>
where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>,
{
    type EigVal = Array1<A::Complex>;

    fn eigvals(&self) -> Result<Self::EigVal> {
        let mut a = self.to_owned();
        let (s, _) = A::eig(false, a.square_layout()?, a.as_allocated_mut()?)?;
        Ok(ArrayBase::from(s))
    }
}
<commit_msg>Relax bound on EigVals from DataMut to Data<commit_after>//! Eigenvalue decomposition for non-symmetric square matrices

use crate::error::*;
use crate::layout::*;
use crate::types::*;
use ndarray::*;

/// Eigenvalue decomposition of general matrix reference
pub trait Eig {
    /// EigVec is the right eivenvector
    type EigVal;
    type EigVec;
    /// Calculate eigenvalues with the right eigenvector
    ///
    /// $$ A u_i = \lambda_i u_i $$
    ///
    /// ```
    /// use ndarray::*;
    /// use ndarray_linalg::*;
    ///
    /// let a: Array2<f64> = array![
    ///     [-1.01,  0.86, -4.60,  3.31, -4.81],
    ///     [ 3.98,  0.53, -7.04,  5.29,  3.55],
    ///     [ 3.30,  8.26, -3.89,  8.20, -1.51],
    ///     [ 4.43,  4.96, -7.66, -7.33,  6.18],
    ///     [ 7.31, -6.43, -6.16,  2.47,  5.58],
    /// ];
    /// let (eigs, vecs) = a.eig().unwrap();
    ///
    /// let a = a.map(|v| v.as_c());
    /// for (&e, vec) in eigs.iter().zip(vecs.axis_iter(Axis(1))) {
    ///     let ev = vec.map(|v| v * e);
    ///     let av = a.dot(&vec);
    ///     assert_close_l2!(&av, &ev, 1e-5);
    /// }
    /// ```
    fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)>;
}

impl<A, S> Eig for ArrayBase<S, Ix2>
where
    A: Scalar + Lapack,
    S: Data<Elem = A>,
{
    type EigVal = Array1<A::Complex>;
    type EigVec = Array2<A::Complex>;

    fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)> {
        let mut a = self.to_owned();
        let layout = a.square_layout()?;
        let (s, t) = A::eig(true, layout, a.as_allocated_mut()?)?;
        let n = layout.len() as usize;
        Ok((
            ArrayBase::from(s),
            Array2::from_shape_vec((n, n).f(), t).unwrap(),
        ))
    }
}

/// Calculate eigenvalues without eigenvectors
pub trait EigVals {
    type EigVal;
    fn eigvals(&self) -> Result<Self::EigVal>;
}

impl<A, S> EigVals for ArrayBase<S, Ix2>
where
    A: Scalar + Lapack,
    S: Data<Elem = A>,
{
    type EigVal = Array1<A::Complex>;

    fn eigvals(&self) -> Result<Self::EigVal> {
        let mut a = self.to_owned();
        let (s, _) = A::eig(false, a.square_layout()?, a.as_allocated_mut()?)?;
        Ok(ArrayBase::from(s))
    }
}
<|endoftext|>


<commit_before>#![feature(core, os, io, env, path)]

extern crate zip;

use std::old_io::File;
use zip::ZipReader;
use zip::fileinfo::FileInfo;

fn main() {

    for arg in std::env::args() {
            println!("{:?}", arg.into_string());
    }

    let args = std::os::args();
    match args.len(){
        2 => list_content(&mut zip_file(&args[1][])),
        3 => extract_file(&mut zip_file(&args[1][]), &args[2][]),
        _ => print_usage(&args[0][])
    }
}

macro_rules! do_or_die{
    ($expr:expr) => (match $expr {
        Ok(val) => val,
        Err(err) => {println!("{}",err); panic!()}
    })
}

fn zip_file(file: &str) -> ZipReader<File>{
    do_or_die!(zip::ZipReader::open(&Path::new(file)))
}

fn output_file(file: &str)->File{
    do_or_die!(File::create(&Path::new(file)))
}

fn zipped_file_info(zip: &mut ZipReader<File>, file: &str) -> FileInfo{
    do_or_die!(zip.info(file))
}

fn list_content(reader: &mut ZipReader<File>)->(){
    for file in reader.files(){
        let (year, month, day, hour, minute, second) = file.last_modified_datetime;
        let mod_time = format!("{:04}-{:02}-{:02} {:02}:{:02}:{:02}", year, month, day, hour, minute, second);
        println!("{} ({}): bytes: {:10}, compressed: {:10}",
            file.name, mod_time, file.compressed_size, file.uncompressed_size);
    }
}

fn extract_file(zip: &mut ZipReader<File>, file: &str)->(){
    let mut out = output_file(file);
    let info = zipped_file_info(zip, file);
    do_or_die!(zip.extract(&info, &mut out));
}

fn print_usage(this: &str)->(){
    println!("Usage: {} [file.zip] [file_to_extract]", this);
}
<commit_msg>demo build errors<commit_after>#![feature(core, os, io, env, path)]

extern crate zip;

use std::env;
use std::old_io::File;
use zip::ZipReader;
use zip::fileinfo::FileInfo;

fn main() {
    let args: Vec<_> = env::args().map(|s| s.into_string().unwrap()).collect();
    match args.len(){
        2 => list_content(&mut zip_file(&args[1])),
        3 => extract_file(&mut zip_file(&args[1]), &args[2]),
        _ => print_usage(&args[0])
    }
}

macro_rules! do_or_die{
    ($expr:expr) => (match $expr {
        Ok(val) => val,
        Err(err) => {println!("{}",err); panic!()}
    })
}

fn zip_file(file: &str) -> ZipReader<File>{
    do_or_die!(zip::ZipReader::open(&Path::new(file)))
}

fn output_file(file: &str)->File{
    do_or_die!(File::create(&Path::new(file)))
}

fn zipped_file_info(zip: &mut ZipReader<File>, file: &str) -> FileInfo{
    do_or_die!(zip.info(file))
}

fn list_content(reader: &mut ZipReader<File>)->(){
    for file in reader.files(){
        let (year, month, day, hour, minute, second) = file.last_modified_datetime;
        let mod_time = format!("{:04}-{:02}-{:02} {:02}:{:02}:{:02}", year, month, day, hour, minute, second);
        println!("{} ({}): bytes: {:10}, compressed: {:10}",
            file.name, mod_time, file.compressed_size, file.uncompressed_size);
    }
}

fn extract_file(zip: &mut ZipReader<File>, file: &str)->(){
    let mut out = output_file(file);
    let info = zipped_file_info(zip, file);
    do_or_die!(zip.extract(&info, &mut out));
}

fn print_usage(this: &str)->(){
    println!("Usage: {} [file.zip] [file_to_extract]", this);
}
<|endoftext|>


<commit_before>#[macro_use] extern crate diesel;

use diesel::*;
use diesel::sql_types::*;
use diesel::dsl::*;

table! {
    users {
        id -> Integer,
        name -> VarChar,
    }
}

sql_function!(fn lower(x: VarChar) -> VarChar);

#[derive(Insertable)]
#[table_name="users"]
struct NewUser(#[column_name = "name"] &'static str);

// NOTE: This test is meant to be comprehensive, but not exhaustive.
fn main() {
    use self::users::dsl::*;
    let connection = SqliteConnection::establish(":memory:").unwrap();

    users.select(id).filter(name.eq(any(Vec::<String>::new())))
        .load::<i32>(&connection);
    //~^ ERROR type mismatch resolving `<diesel::SqliteConnection as diesel::Connection>::Backend == diesel::pg::Pg`
    users.select(id).filter(name.is_not_distinct_from("Sean"))
        .load::<i32>(&connection);
    //~^ ERROR type mismatch resolving `<diesel::SqliteConnection as diesel::Connection>::Backend == diesel::pg::Pg`
    users.select(id).filter(now.eq(now.at_time_zone("UTC")))
        .load::<i32>(&connection);
    //~^ ERROR type mismatch resolving `<diesel::SqliteConnection as diesel::Connection>::Backend == diesel::pg::Pg`
}
<commit_msg>Revert "Remove on_conflict_do_nothing test case"<commit_after>#[macro_use] extern crate diesel;

use diesel::*;
use diesel::sql_types::*;
use diesel::dsl::*;

table! {
    users {
        id -> Integer,
        name -> VarChar,
    }
}

sql_function!(fn lower(x: VarChar) -> VarChar);

#[derive(Insertable)]
#[table_name="users"]
struct NewUser(#[column_name = "name"] &'static str);

// NOTE: This test is meant to be comprehensive, but not exhaustive.
fn main() {
    use self::users::dsl::*;
    let connection = SqliteConnection::establish(":memory:").unwrap();

    users.select(id).filter(name.eq(any(Vec::<String>::new())))
        .load::<i32>(&connection);
    //~^ ERROR type mismatch resolving `<diesel::SqliteConnection as diesel::Connection>::Backend == diesel::pg::Pg`
    users.select(id).filter(name.is_not_distinct_from("Sean"))
        .load::<i32>(&connection);
    //~^ ERROR type mismatch resolving `<diesel::SqliteConnection as diesel::Connection>::Backend == diesel::pg::Pg`
    users.select(id).filter(now.eq(now.at_time_zone("UTC")))
        .load::<i32>(&connection);
    //~^ ERROR type mismatch resolving `<diesel::SqliteConnection as diesel::Connection>::Backend == diesel::pg::Pg`
    insert_into(users).values(&NewUser("Sean"))
        .on_conflict_do_nothing()
        .execute(&connection);
    //~^ ERROR type mismatch resolving `<diesel::SqliteConnection as diesel::Connection>::Backend == diesel::pg::Pg`
}
<|endoftext|>


<commit_before>use crate::io::util::lines::{lines, Lines};
use crate::io::util::read_line::{read_line, ReadLine};
use crate::io::util::read_until::{read_until, ReadUntil};
use crate::io::util::split::{split, Split};
use crate::io::AsyncBufRead;

cfg_io_util! {
    /// An extension trait which adds utility methods to [`AsyncBufRead`] types.
    ///
    /// [`AsyncBufRead`]: crate::io::AsyncBufRead
    pub trait AsyncBufReadExt: AsyncBufRead {
        /// Reads all bytes into `buf` until the delimiter `byte` or EOF is reached.
        ///
        /// Equivalent to:
        ///
        /// ```ignore
        /// async fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize>;
        /// ```
        ///
        /// This function will read bytes from the underlying stream until the
        /// delimiter or EOF is found. Once found, all bytes up to, and including,
        /// the delimiter (if found) will be appended to `buf`.
        ///
        /// If successful, this function will return the total number of bytes read.
        ///
        /// # Errors
        ///
        /// This function will ignore all instances of [`ErrorKind::Interrupted`] and
        /// will otherwise return any errors returned by [`fill_buf`].
        ///
        /// If an I/O error is encountered then all bytes read so far will be
        /// present in `buf` and its length will have been adjusted appropriately.
        ///
        /// [`fill_buf`]: AsyncBufRead::poll_fill_buf
        /// [`ErrorKind::Interrupted`]: std::io::ErrorKind::Interrupted
        ///
        /// # Examples
        ///
        /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
        /// this example, we use [`Cursor`] to read all the bytes in a byte slice
        /// in hyphen delimited segments:
        ///
        /// [`Cursor`]: std::io::Cursor
        ///
        /// ```
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// use std::io::Cursor;
        ///
        /// #[tokio::main]
        /// async fn main() {
        ///     let mut cursor = Cursor::new(b"lorem-ipsum");
        ///     let mut buf = vec![];
        ///
        ///     // cursor is at 'l'
        ///     let num_bytes = cursor.read_until(b'-', &mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 6);
        ///     assert_eq!(buf, b"lorem-");
        ///     buf.clear();
        ///
        ///     // cursor is at 'i'
        ///     let num_bytes = cursor.read_until(b'-', &mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 5);
        ///     assert_eq!(buf, b"ipsum");
        ///     buf.clear();
        ///
        ///     // cursor is at EOF
        ///     let num_bytes = cursor.read_until(b'-', &mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///     assert_eq!(num_bytes, 0);
        ///     assert_eq!(buf, b"");
        /// }
        /// ```
        fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec<u8>) -> ReadUntil<'a, Self>
        where
            Self: Unpin,
        {
            read_until(self, byte, buf)
        }

        /// Reads all bytes until a newline (the 0xA byte) is reached, and append
        /// them to the provided buffer.
        ///
        /// Equivalent to:
        ///
        /// ```ignore
        /// async fn read_line(&mut self, buf: &mut String) -> io::Result<usize>;
        /// ```
        ///
        /// This function will read bytes from the underlying stream until the
        /// newline delimiter (the 0xA byte) or EOF is found. Once found, all bytes
        /// up to, and including, the delimiter (if found) will be appended to
        /// `buf`.
        ///
        /// If successful, this function will return the total number of bytes read.
        ///
        /// If this function returns `Ok(0)`, the stream has reached EOF.
        ///
        /// # Errors
        ///
        /// This function has the same error semantics as [`read_until`] and will
        /// also return an error if the read bytes are not valid UTF-8. If an I/O
        /// error is encountered then `buf` may contain some bytes already read in
        /// the event that all data read so far was valid UTF-8.
        ///
        /// [`read_until`]: AsyncBufReadExt::read_until
        ///
        /// # Examples
        ///
        /// [`std::io::Cursor`][`Cursor`] is a type that implements
        /// `AsyncBufRead`. In this example, we use [`Cursor`] to read all the
        /// lines in a byte slice:
        ///
        /// [`Cursor`]: std::io::Cursor
        ///
        /// ```
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// use std::io::Cursor;
        ///
        /// #[tokio::main]
        /// async fn main() {
        ///     let mut cursor = Cursor::new(b"foo\nbar");
        ///     let mut buf = String::new();
        ///
        ///     // cursor is at 'f'
        ///     let num_bytes = cursor.read_line(&mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 4);
        ///     assert_eq!(buf, "foo\n");
        ///     buf.clear();
        ///
        ///     // cursor is at 'b'
        ///     let num_bytes = cursor.read_line(&mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 3);
        ///     assert_eq!(buf, "bar");
        ///     buf.clear();
        ///
        ///     // cursor is at EOF
        ///     let num_bytes = cursor.read_line(&mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 0);
        ///     assert_eq!(buf, "");
        /// }
        /// ```
        fn read_line<'a>(&'a mut self, buf: &'a mut String) -> ReadLine<'a, Self>
        where
            Self: Unpin,
        {
            read_line(self, buf)
        }

        /// Returns a stream of the contents of this reader split on the byte
        /// `byte`.
        ///
        /// This method is the asynchronous equivalent to
        /// [`BufRead::split`](std::io::BufRead::split).
        ///
        /// The stream returned from this function will yield instances of
        /// [`io::Result`]`<`[`Vec<u8>`]`>`. Each vector returned will *not* have
        /// the delimiter byte at the end.
        ///
        /// [`io::Result`]: std::io::Result
        /// [`Vec<u8>`]: std::vec::Vec
        ///
        /// # Errors
        ///
        /// Each item of the stream has the same error semantics as
        /// [`AsyncBufReadExt::read_until`](AsyncBufReadExt::read_until).
        ///
        /// # Examples
        ///
        /// ```
        /// # use tokio::io::AsyncBufRead;
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// # async fn dox(my_buf_read: impl AsyncBufRead + Unpin) -> std::io::Result<()> {
        /// let mut segments = my_buf_read.split(b'f');
        ///
        /// while let Some(segment) = segments.next_segment().await? {
        ///     println!("length = {}", segment.len())
        /// }
        /// # Ok(())
        /// # }
        /// ```
        fn split(self, byte: u8) -> Split<Self>
        where
            Self: Sized + Unpin,
        {
            split(self, byte)
        }

        /// Returns a stream over the lines of this reader.
        /// This method is the async equivalent to [`BufRead::lines`](std::io::BufRead::lines).
        ///
        /// The stream returned from this function will yield instances of
        /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline
        /// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end.
        ///
        /// [`io::Result`]: std::io::Result
        /// [`String`]: String
        ///
        /// # Errors
        ///
        /// Each line of the stream has the same error semantics as [`AsyncBufReadExt::read_line`].
        ///
        /// # Examples
        ///
        /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
        /// this example, we use [`Cursor`] to iterate over all the lines in a byte
        /// slice.
        ///
        /// [`Cursor`]: std::io::Cursor
        ///
        /// ```
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// use std::io::Cursor;
        ///
        /// #[tokio::main]
        /// async fn main() {
        ///     let cursor = Cursor::new(b"lorem\nipsum\r\ndolor");
        ///
        ///     let mut lines = cursor.lines();
        ///
        ///     assert_eq!(lines.next_line().await.unwrap(), Some(String::from("lorem")));
        ///     assert_eq!(lines.next_line().await.unwrap(), Some(String::from("ipsum")));
        ///     assert_eq!(lines.next_line().await.unwrap(), Some(String::from("dolor")));
        ///     assert_eq!(lines.next_line().await.unwrap(), None);
        /// }
        /// ```
        ///
        /// [`AsyncBufReadExt::read_line`]: AsyncBufReadExt::read_line
        fn lines(self) -> Lines<Self>
        where
            Self: Sized,
        {
            lines(self)
        }
    }
}

impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}
<commit_msg>doc: note the EOF behaviour of read_until (#3536)<commit_after>use crate::io::util::lines::{lines, Lines};
use crate::io::util::read_line::{read_line, ReadLine};
use crate::io::util::read_until::{read_until, ReadUntil};
use crate::io::util::split::{split, Split};
use crate::io::AsyncBufRead;

cfg_io_util! {
    /// An extension trait which adds utility methods to [`AsyncBufRead`] types.
    ///
    /// [`AsyncBufRead`]: crate::io::AsyncBufRead
    pub trait AsyncBufReadExt: AsyncBufRead {
        /// Reads all bytes into `buf` until the delimiter `byte` or EOF is reached.
        ///
        /// Equivalent to:
        ///
        /// ```ignore
        /// async fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize>;
        /// ```
        ///
        /// This function will read bytes from the underlying stream until the
        /// delimiter or EOF is found. Once found, all bytes up to, and including,
        /// the delimiter (if found) will be appended to `buf`.
        ///
        /// If successful, this function will return the total number of bytes read.
        ///
        /// If this function returns `Ok(0)`, the stream has reached EOF.
        ///
        /// # Errors
        ///
        /// This function will ignore all instances of [`ErrorKind::Interrupted`] and
        /// will otherwise return any errors returned by [`fill_buf`].
        ///
        /// If an I/O error is encountered then all bytes read so far will be
        /// present in `buf` and its length will have been adjusted appropriately.
        ///
        /// [`fill_buf`]: AsyncBufRead::poll_fill_buf
        /// [`ErrorKind::Interrupted`]: std::io::ErrorKind::Interrupted
        ///
        /// # Examples
        ///
        /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
        /// this example, we use [`Cursor`] to read all the bytes in a byte slice
        /// in hyphen delimited segments:
        ///
        /// [`Cursor`]: std::io::Cursor
        ///
        /// ```
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// use std::io::Cursor;
        ///
        /// #[tokio::main]
        /// async fn main() {
        ///     let mut cursor = Cursor::new(b"lorem-ipsum");
        ///     let mut buf = vec![];
        ///
        ///     // cursor is at 'l'
        ///     let num_bytes = cursor.read_until(b'-', &mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 6);
        ///     assert_eq!(buf, b"lorem-");
        ///     buf.clear();
        ///
        ///     // cursor is at 'i'
        ///     let num_bytes = cursor.read_until(b'-', &mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 5);
        ///     assert_eq!(buf, b"ipsum");
        ///     buf.clear();
        ///
        ///     // cursor is at EOF
        ///     let num_bytes = cursor.read_until(b'-', &mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///     assert_eq!(num_bytes, 0);
        ///     assert_eq!(buf, b"");
        /// }
        /// ```
        fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec<u8>) -> ReadUntil<'a, Self>
        where
            Self: Unpin,
        {
            read_until(self, byte, buf)
        }

        /// Reads all bytes until a newline (the 0xA byte) is reached, and append
        /// them to the provided buffer.
        ///
        /// Equivalent to:
        ///
        /// ```ignore
        /// async fn read_line(&mut self, buf: &mut String) -> io::Result<usize>;
        /// ```
        ///
        /// This function will read bytes from the underlying stream until the
        /// newline delimiter (the 0xA byte) or EOF is found. Once found, all bytes
        /// up to, and including, the delimiter (if found) will be appended to
        /// `buf`.
        ///
        /// If successful, this function will return the total number of bytes read.
        ///
        /// If this function returns `Ok(0)`, the stream has reached EOF.
        ///
        /// # Errors
        ///
        /// This function has the same error semantics as [`read_until`] and will
        /// also return an error if the read bytes are not valid UTF-8. If an I/O
        /// error is encountered then `buf` may contain some bytes already read in
        /// the event that all data read so far was valid UTF-8.
        ///
        /// [`read_until`]: AsyncBufReadExt::read_until
        ///
        /// # Examples
        ///
        /// [`std::io::Cursor`][`Cursor`] is a type that implements
        /// `AsyncBufRead`. In this example, we use [`Cursor`] to read all the
        /// lines in a byte slice:
        ///
        /// [`Cursor`]: std::io::Cursor
        ///
        /// ```
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// use std::io::Cursor;
        ///
        /// #[tokio::main]
        /// async fn main() {
        ///     let mut cursor = Cursor::new(b"foo\nbar");
        ///     let mut buf = String::new();
        ///
        ///     // cursor is at 'f'
        ///     let num_bytes = cursor.read_line(&mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 4);
        ///     assert_eq!(buf, "foo\n");
        ///     buf.clear();
        ///
        ///     // cursor is at 'b'
        ///     let num_bytes = cursor.read_line(&mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 3);
        ///     assert_eq!(buf, "bar");
        ///     buf.clear();
        ///
        ///     // cursor is at EOF
        ///     let num_bytes = cursor.read_line(&mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 0);
        ///     assert_eq!(buf, "");
        /// }
        /// ```
        fn read_line<'a>(&'a mut self, buf: &'a mut String) -> ReadLine<'a, Self>
        where
            Self: Unpin,
        {
            read_line(self, buf)
        }

        /// Returns a stream of the contents of this reader split on the byte
        /// `byte`.
        ///
        /// This method is the asynchronous equivalent to
        /// [`BufRead::split`](std::io::BufRead::split).
        ///
        /// The stream returned from this function will yield instances of
        /// [`io::Result`]`<`[`Vec<u8>`]`>`. Each vector returned will *not* have
        /// the delimiter byte at the end.
        ///
        /// [`io::Result`]: std::io::Result
        /// [`Vec<u8>`]: std::vec::Vec
        ///
        /// # Errors
        ///
        /// Each item of the stream has the same error semantics as
        /// [`AsyncBufReadExt::read_until`](AsyncBufReadExt::read_until).
        ///
        /// # Examples
        ///
        /// ```
        /// # use tokio::io::AsyncBufRead;
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// # async fn dox(my_buf_read: impl AsyncBufRead + Unpin) -> std::io::Result<()> {
        /// let mut segments = my_buf_read.split(b'f');
        ///
        /// while let Some(segment) = segments.next_segment().await? {
        ///     println!("length = {}", segment.len())
        /// }
        /// # Ok(())
        /// # }
        /// ```
        fn split(self, byte: u8) -> Split<Self>
        where
            Self: Sized + Unpin,
        {
            split(self, byte)
        }

        /// Returns a stream over the lines of this reader.
        /// This method is the async equivalent to [`BufRead::lines`](std::io::BufRead::lines).
        ///
        /// The stream returned from this function will yield instances of
        /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline
        /// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end.
        ///
        /// [`io::Result`]: std::io::Result
        /// [`String`]: String
        ///
        /// # Errors
        ///
        /// Each line of the stream has the same error semantics as [`AsyncBufReadExt::read_line`].
        ///
        /// # Examples
        ///
        /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
        /// this example, we use [`Cursor`] to iterate over all the lines in a byte
        /// slice.
        ///
        /// [`Cursor`]: std::io::Cursor
        ///
        /// ```
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// use std::io::Cursor;
        ///
        /// #[tokio::main]
        /// async fn main() {
        ///     let cursor = Cursor::new(b"lorem\nipsum\r\ndolor");
        ///
        ///     let mut lines = cursor.lines();
        ///
        ///     assert_eq!(lines.next_line().await.unwrap(), Some(String::from("lorem")));
        ///     assert_eq!(lines.next_line().await.unwrap(), Some(String::from("ipsum")));
        ///     assert_eq!(lines.next_line().await.unwrap(), Some(String::from("dolor")));
        ///     assert_eq!(lines.next_line().await.unwrap(), None);
        /// }
        /// ```
        ///
        /// [`AsyncBufReadExt::read_line`]: AsyncBufReadExt::read_line
        fn lines(self) -> Lines<Self>
        where
            Self: Sized,
        {
            lines(self)
        }
    }
}

impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}
<|endoftext|>


<commit_before>fn main() {
    let test = vec![
        30, 63, 83, 40, 15, 45, 46, 15, 56, 39, 82, 97, 59, 88, 3, 1, 40, 95, 83, 32, 38, 70, 4,
        87, 54, 48, 19, 8, 52, 49, 64, 72, 46, 72, 59, 36, 21, 68, 81, 34, 23, 6, 70, 80, 80, 12,
        32, 84, 17, 19, 28, 58, 68, 19, 65, 46, 43, 22, 12, 95, 89, 15, 39, 88, 64, 95, 99, 25, 2,
        7, 86, 36, 73, 90, 30, 31, 0, 62, 73, 35, 4, 26, 0, 93, 91, 77, 34, 92, 31, 56, 34, 61, 23,
        47, 78, 5, 5, 26, 36, 71, 50, 5, 59, 22, 21, 0, 72, 72, 72, 69, 5, 11, 95, 5, 0, 14, 34,
        91, 4, 27, 46, 21, 94, 96, 48, 58, 79, 21, 65, 35, 17, 16, 57, 91, 36, 50, 16, 82, 92, 1,
        29, 52, 74, 90, 48, 79, 81, 53, 46, 82, 36, 43, 64, 24, 55, 48, 27, 21, 69, 93, 49, 70, 58,
        8, 50, 97, 30, 68, 1, 34, 15, 38, 52, 27, 50, 10, 22, 67, 25, 37, 84, 91, 13, 15, 0, 5, 31,
        18, 5, 31, 49, 93, 95, 3, 86, 11, 37, 68, 43, 74,
    ];
}
<commit_msg>finish<commit_after>fn bubble_sort<T>(a: Vec<T>) -> Vec<T>
where
    T: PartialEq + PartialOrd + Clone,
{
    let length = a.len();
    let mut flag = true;
    let mut b = a;
    while (flag) {
        flag = false;
        let mut temp: Vec<T> = vec![];
        let mut this = b[0].clone();
        for i in 1..length {
            if b[i] < this {
                temp.push(b[i].clone());
                flag = true;
            } else {
                temp.push(this);
                this = b[i].clone();
            }
        }
        temp.push(this);
        b = temp;
    }
    b
}

fn main() {
    let test = vec![
        30, 63, 83, 40, 15, 45, 46, 15, 56, 39, 82, 97, 59, 88, 3, 1, 40, 95, 83, 32, 38, 70, 4,
        87, 54, 48, 19, 8, 52, 49, 64, 72, 46, 72, 59, 36, 21, 68, 81, 34, 23, 6, 70, 80, 80, 12,
        32, 84, 17, 19, 28, 58, 68, 19, 65, 46, 43, 22, 12, 95, 89, 15, 39, 88, 64, 95, 99, 25, 2,
        7, 86, 36, 73, 90, 30, 31, 0, 62, 73, 35, 4, 26, 0, 93, 91, 77, 34, 92, 31, 56, 34, 61, 23,
        47, 78, 5, 5, 26, 36, 71, 50, 5, 59, 22, 21, 0, 72, 72, 72, 69, 5, 11, 95, 5, 0, 14, 34,
        91, 4, 27, 46, 21, 94, 96, 48, 58, 79, 21, 65, 35, 17, 16, 57, 91, 36, 50, 16, 82, 92, 1,
        29, 52, 74, 90, 48, 79, 81, 53, 46, 82, 36, 43, 64, 24, 55, 48, 27, 21, 69, 93, 49, 70, 58,
        8, 50, 97, 30, 68, 1, 34, 15, 38, 52, 27, 50, 10, 22, 67, 25, 37, 84, 91, 13, 15, 0, 5, 31,
        18, 5, 31, 49, 93, 95, 3, 86, 11, 37, 68, 43, 74,
    ];
    println!("{:?}", bubble_sort(test));
}
<|endoftext|>


<commit_before>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

pub use crate::generated::plugin::*;

/// Converts protobuf representation of CpuId data into KVM format.
pub fn cpuid_proto_to_kvm(entry: &CpuidEntry) -> kvm_sys::kvm_cpuid_entry2 {
    // Safe: C structures are expected to be zero-initialized.
    let mut e: kvm_sys::kvm_cpuid_entry2 = unsafe { std::mem::zeroed() };
    e.function = entry.function;
    if entry.has_index {
        e.flags = kvm_sys::KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
    }
    e.index = entry.index;
    e.eax = entry.eax;
    e.ebx = entry.ebx;
    e.ecx = entry.ecx;
    e.edx = entry.edx;

    e
}

/// Converts KVM representation of CpuId data into protobuf format.
pub fn cpuid_kvm_to_proto(entry: &kvm_sys::kvm_cpuid_entry2) -> CpuidEntry {
    let mut e = CpuidEntry::new();
    e.function = entry.function;
    e.has_index = entry.flags & kvm_sys::KVM_CPUID_FLAG_SIGNIFCANT_INDEX != 0;
    e.index = entry.index;
    e.eax = entry.eax;
    e.ebx = entry.ebx;
    e.ecx = entry.ecx;
    e.edx = entry.edx;

    e
}
<commit_msg>protos: add arch = x86 guards around CPUID helpers<commit_after>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

pub use crate::generated::plugin::*;

/// Converts protobuf representation of CpuId data into KVM format.
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn cpuid_proto_to_kvm(entry: &CpuidEntry) -> kvm_sys::kvm_cpuid_entry2 {
    // Safe: C structures are expected to be zero-initialized.
    let mut e: kvm_sys::kvm_cpuid_entry2 = unsafe { std::mem::zeroed() };
    e.function = entry.function;
    if entry.has_index {
        e.flags = kvm_sys::KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
    }
    e.index = entry.index;
    e.eax = entry.eax;
    e.ebx = entry.ebx;
    e.ecx = entry.ecx;
    e.edx = entry.edx;

    e
}

/// Converts KVM representation of CpuId data into protobuf format.
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn cpuid_kvm_to_proto(entry: &kvm_sys::kvm_cpuid_entry2) -> CpuidEntry {
    let mut e = CpuidEntry::new();
    e.function = entry.function;
    e.has_index = entry.flags & kvm_sys::KVM_CPUID_FLAG_SIGNIFCANT_INDEX != 0;
    e.index = entry.index;
    e.eax = entry.eax;
    e.ebx = entry.ebx;
    e.ecx = entry.ecx;
    e.edx = entry.edx;

    e
}
<|endoftext|>


<commit_before>use std::path::PathBuf;

use semver::Version;
use std::fmt::{Display, Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;

use libimagerror::into::IntoError;

use error::StoreErrorKind as SEK;
use store::Result;
use store::Store;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId {
    base: Option<PathBuf>,
    id:   PathBuf,
}

impl StoreId {

    pub fn new(base: Option<PathBuf>, id: PathBuf) -> Result<StoreId> {
        StoreId::new_baseless(id).map(|mut sid| { sid.base = base; sid })
    }

    pub fn new_baseless(id: PathBuf) -> Result<StoreId> {
        if id.is_absolute() {
            Err(SEK::StoreIdLocalPartAbsoluteError.into_error())
        } else {
            Ok(StoreId {
                base: None,
                id: id
            })
        }
    }

    pub fn without_base(mut self) -> StoreId {
        self.base = None;
        self
    }

    pub fn with_base(mut self, base: PathBuf) -> Self {
        self.base = Some(base);
        self
    }

    pub fn storified(self, store: &Store) -> StoreId {
        StoreId {
            base: Some(store.path().clone()),
            id: self.id
        }
    }

    pub fn exists(&self) -> bool {
        let pb : PathBuf = self.clone().into();
        pb.exists()
    }

    pub fn is_file(&self) -> bool {
        true
    }

    pub fn is_dir(&self) -> bool {
        false
    }

    pub fn to_str(&self) -> Result<String> {
        if self.base.is_some() {
            let mut base = self.base.as_ref().cloned().unwrap();
            base.push(self.id.clone());
            base
        } else {
            self.id.clone()
        }
        .to_str()
        .map(String::from)
        .ok_or(SEK::StoreIdHandlingError.into_error())
    }

}

impl Into<PathBuf> for StoreId {

    fn into(self) -> PathBuf {
        let mut base = self.base.unwrap_or(PathBuf::from("/"));
        base.push(self.id);
        base
    }

}

impl Display for StoreId {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        match self.id.to_str() {
            Some(s) => write!(fmt, "{}", s),
            None    => write!(fmt, "{}", self.id.to_string_lossy()),
        }
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> Result<StoreId>;
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> Result<StoreId> {
        Ok(self)
    }
}

pub fn build_entry_path(store: &Store, path_elem: &str) -> Result<PathBuf> {
    debug!("Checking path element for version");
    if path_elem.split('~').last().map_or(false, |v| Version::parse(v).is_err()) {
        debug!("Version cannot be parsed from {:?}", path_elem);
        debug!("Path does not contain version!");
        return Err(SEK::StorePathLacksVersion.into());
    }
    debug!("Version checking succeeded");

    debug!("Building path from {:?}", path_elem);
    let mut path = store.path().clone();

    if path_elem.starts_with('/') {
        path.push(&path_elem[1..]);
    } else {
        path.push(path_elem);
    }

    Ok(path)
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr, $version:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use semver::Version;
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;
            use $crate::store::Result;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let version = Version::parse($version).unwrap();
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(format!("{}~{}",
                                               name,
                                               version));
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> Result<$crate::storeid::StoreId> {
                    StoreId::new(None, self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test", "0.2.0-alpha+leet1337");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().unwrap().to_str().unwrap(), "test/test~0.2.0-alpha+leet1337");
    }

}
<commit_msg>Add StoreId::components() to get components of StoreId "id" part<commit_after>use std::path::PathBuf;

use semver::Version;
use std::fmt::{Display, Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;
use std::path::Components;

use libimagerror::into::IntoError;

use error::StoreErrorKind as SEK;
use store::Result;
use store::Store;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId {
    base: Option<PathBuf>,
    id:   PathBuf,
}

impl StoreId {

    pub fn new(base: Option<PathBuf>, id: PathBuf) -> Result<StoreId> {
        StoreId::new_baseless(id).map(|mut sid| { sid.base = base; sid })
    }

    pub fn new_baseless(id: PathBuf) -> Result<StoreId> {
        if id.is_absolute() {
            Err(SEK::StoreIdLocalPartAbsoluteError.into_error())
        } else {
            Ok(StoreId {
                base: None,
                id: id
            })
        }
    }

    pub fn without_base(mut self) -> StoreId {
        self.base = None;
        self
    }

    pub fn with_base(mut self, base: PathBuf) -> Self {
        self.base = Some(base);
        self
    }

    pub fn storified(self, store: &Store) -> StoreId {
        StoreId {
            base: Some(store.path().clone()),
            id: self.id
        }
    }

    pub fn exists(&self) -> bool {
        let pb : PathBuf = self.clone().into();
        pb.exists()
    }

    pub fn is_file(&self) -> bool {
        true
    }

    pub fn is_dir(&self) -> bool {
        false
    }

    pub fn to_str(&self) -> Result<String> {
        if self.base.is_some() {
            let mut base = self.base.as_ref().cloned().unwrap();
            base.push(self.id.clone());
            base
        } else {
            self.id.clone()
        }
        .to_str()
        .map(String::from)
        .ok_or(SEK::StoreIdHandlingError.into_error())
    }

    /// Returns the components of the `id` part of the StoreId object.
    ///
    /// Can be used to check whether a StoreId points to an entry in a specific collection of
    /// StoreIds.
    pub fn components(&self) -> Components {
        self.id.components()
    }

}

impl Into<PathBuf> for StoreId {

    fn into(self) -> PathBuf {
        let mut base = self.base.unwrap_or(PathBuf::from("/"));
        base.push(self.id);
        base
    }

}

impl Display for StoreId {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        match self.id.to_str() {
            Some(s) => write!(fmt, "{}", s),
            None    => write!(fmt, "{}", self.id.to_string_lossy()),
        }
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> Result<StoreId>;
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> Result<StoreId> {
        Ok(self)
    }
}

pub fn build_entry_path(store: &Store, path_elem: &str) -> Result<PathBuf> {
    debug!("Checking path element for version");
    if path_elem.split('~').last().map_or(false, |v| Version::parse(v).is_err()) {
        debug!("Version cannot be parsed from {:?}", path_elem);
        debug!("Path does not contain version!");
        return Err(SEK::StorePathLacksVersion.into());
    }
    debug!("Version checking succeeded");

    debug!("Building path from {:?}", path_elem);
    let mut path = store.path().clone();

    if path_elem.starts_with('/') {
        path.push(&path_elem[1..]);
    } else {
        path.push(path_elem);
    }

    Ok(path)
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr, $version:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use semver::Version;
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;
            use $crate::store::Result;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let version = Version::parse($version).unwrap();
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(format!("{}~{}",
                                               name,
                                               version));
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> Result<$crate::storeid::StoreId> {
                    StoreId::new(None, self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test", "0.2.0-alpha+leet1337");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().unwrap().to_str().unwrap(), "test/test~0.2.0-alpha+leet1337");
    }

}
<|endoftext|>


<commit_before>#[macro_use] extern crate nickel;

use nickel::{Nickel, HttpRouter};
use std::collections::HashMap;

fn main() {
    let mut server = Nickel::new();

    // * NOTE *
    // This example is deprecated, you should use nickel-mustache from crates.io
    server.get("/", middleware! { |_, res|
        let mut data = HashMap::<&str, &str>::new();
        data.insert("name", "user");
        return res.render("examples/assets/template.tpl", &data)
    });

    server.listen("127.0.0.1:6767");
}
<commit_msg>doc(examples): Point to correct crate<commit_after>#[macro_use] extern crate nickel;

use nickel::{Nickel, HttpRouter};
use std::collections::HashMap;

fn main() {
    let mut server = Nickel::new();

    // * NOTE *
    // This example is deprecated, you should use nickel_mustache from crates.io
    server.get("/", middleware! { |_, res|
        let mut data = HashMap::<&str, &str>::new();
        data.insert("name", "user");
        return res.render("examples/assets/template.tpl", &data)
    });

    server.listen("127.0.0.1:6767");
}
<|endoftext|>


<commit_before>extern crate robin_core;

extern crate nom;

#[cfg(test)]
mod parser_tests {
    use nom::IResult;

    use robin_core::parser::identifier;

    #[test]
    fn parse_a_left_brace() {
        assert_eq!(identifier::symbol_identifier(b"{"),
                   IResult::Done(&b""[..], "{".to_string()));
    }

    #[test]
    fn parse_a_right_brace() {
        assert_eq!(identifier::symbol_identifier(b"}"),
                   IResult::Done(&b""[..], "}".to_string()));
    }

    #[test]
    fn parse_a_left_bracket() {
        assert_eq!(identifier::symbol_identifier(b"("),
                   IResult::Done(&b""[..], "(".to_string()));
    }

    #[test]
    fn parse_a_right_bracket() {
        assert_eq!(identifier::symbol_identifier(b")"),
                   IResult::Done(&b""[..], ")".to_string()));
    }

    #[test]
    fn parse_a_left_square_bracket() {
        assert_eq!(identifier::symbol_identifier(b"["),
                   IResult::Done(&b""[..], "[".to_string()));
    }

    #[test]
    fn parse_a_right_square_bracket() {
        assert_eq!(identifier::symbol_identifier(b"]"),
                   IResult::Done(&b""[..], "]".to_string()));
    }

    #[test]
    fn parse_a_fullstop() {
        assert_eq!(identifier::symbol_identifier(b"."),
                   IResult::Done(&b""[..], ".".to_string()));
    }

    #[test]
    fn parse_a_semicolon() {
        assert_eq!(identifier::symbol_identifier(b";"),
                   IResult::Done(&b""[..], ";".to_string()));
    }

    #[test]
    fn parse_a_comma() {
        assert_eq!(identifier::symbol_identifier(b","),
                   IResult::Done(&b""[..], ",".to_string()));
    }

    #[test]
    fn parse_less_than() {
        assert_eq!(identifier::symbol_identifier(b"<"),
                   IResult::Done(&b""[..], "<".to_string()));
    }

    #[test]
    fn parse_greater_than() {
        assert_eq!(identifier::symbol_identifier(b">"),
                   IResult::Done(&b""[..], ">".to_string()));
    }

    #[test]
    fn parse_equals() {
        assert_eq!(identifier::symbol_identifier(b"="),
                   IResult::Done(&b""[..], "=".to_string()));
    }

    #[test]
    fn parse_exclamation() {
        assert_eq!(identifier::symbol_identifier(b"!"),
                   IResult::Done(&b""[..], "!".to_string()));
    }

    #[test]
    fn parse_plus() {
        assert_eq!(identifier::symbol_identifier(b"+"),
                   IResult::Done(&b""[..], "+".to_string()));
    }

    #[test]
    fn parse_minus() {
        assert_eq!(identifier::symbol_identifier(b"-"),
                   IResult::Done(&b""[..], "-".to_string()));
    }

    #[test]
    fn parse_times() {
        assert_eq!(identifier::symbol_identifier(b"*"),
                   IResult::Done(&b""[..], "*".to_string()));
    }

    #[test]
    fn parse_divide() {
        assert_eq!(identifier::symbol_identifier(b"/"),
                   IResult::Done(&b""[..], "/".to_string()));
    }

    #[test]
    fn parse_ampersand() {
        assert_eq!(identifier::symbol_identifier(b"&"),
                   IResult::Done(&b""[..], "&".to_string()));
    }

    #[test]
    fn parse_pipe() {
        assert_eq!(identifier::symbol_identifier(b"|"),
                   IResult::Done(&b""[..], "|".to_string()));
    }

    #[test]
    fn parse_power_of() {
        assert_eq!(identifier::symbol_identifier(b"^"),
                   IResult::Done(&b""[..], "^".to_string()));
    }

    #[test]
    fn parse_tilde() {
        assert_eq!(identifier::symbol_identifier(b"~"),
                   IResult::Done(&b""[..], "~".to_string()));
    }

    #[test]
    fn parse_question() {
        assert_eq!(identifier::symbol_identifier(b"?"),
                   IResult::Done(&b""[..], "?".to_string()));
    }

    #[test]
    fn parse_colon() {
        assert_eq!(identifier::symbol_identifier(b":"),
                   IResult::Done(&b""[..], ":".to_string()));
    }

    #[test]
    fn parse_multiple_symbols() {
        assert_eq!(identifier::symbol_identifier(b"|>+"),
                   IResult::Done(&b""[..], "|>+".to_string()));
    }

    #[test]
    fn parse_a_single_alpha_identifier() {
        assert_eq!(identifier::alpha_identifier(b"g"),
                   IResult::Done(&b""[..], "g".to_string()));
    }

    #[test]
    fn parse_multiple_alpha_identifiers() {
        assert_eq!(identifier::alpha_identifier(b"gbd"),
                   IResult::Done(&b""[..], "gbd".to_string()));
    }

    #[test]
    fn parse_a_symbol_and_an_alpha() {
        assert_eq!(identifier::alpha_identifier(b"gg{"),
                   IResult::Done(&b""[..], "gg{".to_string()));
    }
}
<commit_msg>Add a new test<commit_after>extern crate robin_core;

extern crate nom;

#[cfg(test)]
mod parser_tests {
    use nom::IResult;

    use robin_core::parser::identifier;

    // I think this test is correct
    #[test]
    fn do_not_parse_a_symbol_then_an_alpha() {
        assert_ne!(identifier::identifier_literal(b"+g"),
                   IResult::Done(&b""[..], "+g".to_string()));
    }

    #[test]
    fn parse_a_left_brace() {
        assert_eq!(identifier::symbol_identifier(b"{"),
                   IResult::Done(&b""[..], "{".to_string()));
    }

    #[test]
    fn parse_a_right_brace() {
        assert_eq!(identifier::symbol_identifier(b"}"),
                   IResult::Done(&b""[..], "}".to_string()));
    }

    #[test]
    fn parse_a_left_bracket() {
        assert_eq!(identifier::symbol_identifier(b"("),
                   IResult::Done(&b""[..], "(".to_string()));
    }

    #[test]
    fn parse_a_right_bracket() {
        assert_eq!(identifier::symbol_identifier(b")"),
                   IResult::Done(&b""[..], ")".to_string()));
    }

    #[test]
    fn parse_a_left_square_bracket() {
        assert_eq!(identifier::symbol_identifier(b"["),
                   IResult::Done(&b""[..], "[".to_string()));
    }

    #[test]
    fn parse_a_right_square_bracket() {
        assert_eq!(identifier::symbol_identifier(b"]"),
                   IResult::Done(&b""[..], "]".to_string()));
    }

    #[test]
    fn parse_a_fullstop() {
        assert_eq!(identifier::symbol_identifier(b"."),
                   IResult::Done(&b""[..], ".".to_string()));
    }

    #[test]
    fn parse_a_semicolon() {
        assert_eq!(identifier::symbol_identifier(b";"),
                   IResult::Done(&b""[..], ";".to_string()));
    }

    #[test]
    fn parse_a_comma() {
        assert_eq!(identifier::symbol_identifier(b","),
                   IResult::Done(&b""[..], ",".to_string()));
    }

    #[test]
    fn parse_less_than() {
        assert_eq!(identifier::symbol_identifier(b"<"),
                   IResult::Done(&b""[..], "<".to_string()));
    }

    #[test]
    fn parse_greater_than() {
        assert_eq!(identifier::symbol_identifier(b">"),
                   IResult::Done(&b""[..], ">".to_string()));
    }

    #[test]
    fn parse_equals() {
        assert_eq!(identifier::symbol_identifier(b"="),
                   IResult::Done(&b""[..], "=".to_string()));
    }

    #[test]
    fn parse_exclamation() {
        assert_eq!(identifier::symbol_identifier(b"!"),
                   IResult::Done(&b""[..], "!".to_string()));
    }

    #[test]
    fn parse_plus() {
        assert_eq!(identifier::symbol_identifier(b"+"),
                   IResult::Done(&b""[..], "+".to_string()));
    }

    #[test]
    fn parse_minus() {
        assert_eq!(identifier::symbol_identifier(b"-"),
                   IResult::Done(&b""[..], "-".to_string()));
    }

    #[test]
    fn parse_times() {
        assert_eq!(identifier::symbol_identifier(b"*"),
                   IResult::Done(&b""[..], "*".to_string()));
    }

    #[test]
    fn parse_divide() {
        assert_eq!(identifier::symbol_identifier(b"/"),
                   IResult::Done(&b""[..], "/".to_string()));
    }

    #[test]
    fn parse_ampersand() {
        assert_eq!(identifier::symbol_identifier(b"&"),
                   IResult::Done(&b""[..], "&".to_string()));
    }

    #[test]
    fn parse_pipe() {
        assert_eq!(identifier::symbol_identifier(b"|"),
                   IResult::Done(&b""[..], "|".to_string()));
    }

    #[test]
    fn parse_power_of() {
        assert_eq!(identifier::symbol_identifier(b"^"),
                   IResult::Done(&b""[..], "^".to_string()));
    }

    #[test]
    fn parse_tilde() {
        assert_eq!(identifier::symbol_identifier(b"~"),
                   IResult::Done(&b""[..], "~".to_string()));
    }

    #[test]
    fn parse_question() {
        assert_eq!(identifier::symbol_identifier(b"?"),
                   IResult::Done(&b""[..], "?".to_string()));
    }

    #[test]
    fn parse_colon() {
        assert_eq!(identifier::symbol_identifier(b":"),
                   IResult::Done(&b""[..], ":".to_string()));
    }

    #[test]
    fn parse_multiple_symbols() {
        assert_eq!(identifier::symbol_identifier(b"|>+"),
                   IResult::Done(&b""[..], "|>+".to_string()));
    }

    #[test]
    fn parse_a_single_alpha_identifier() {
        assert_eq!(identifier::alpha_identifier(b"g"),
                   IResult::Done(&b""[..], "g".to_string()));
    }

    #[test]
    fn parse_multiple_alpha_identifiers() {
        assert_eq!(identifier::alpha_identifier(b"gbd"),
                   IResult::Done(&b""[..], "gbd".to_string()));
    }

    #[test]
    fn parse_a_symbol_and_an_alpha() {
        assert_eq!(identifier::alpha_identifier(b"gg{"),
                   IResult::Done(&b""[..], "gg{".to_string()));
    }
}
<|endoftext|>


<commit_before>use std::io::fs::File;

use config::builders::UbuntuRepoInfo;
use super::super::context::BuildContext;
use super::super::download::download_file;
use super::super::tarcmd::unpack_file;
use super::generic::run_command;
use container::sha256::{Sha256, Digest};

pub fn fetch_ubuntu_core(ctx: &mut BuildContext, release: &String)
    -> Result<(), String>
{
    let kind = "core";
    let arch = "amd64";
    let url = format!(concat!(
        "http://cdimage.ubuntu.com/ubuntu-{kind}/{release}/",
        "daily/current/{release}-{kind}-{arch}.tar.gz",
        ), kind=kind, arch=arch, release=release);
    let filename = try!(download_file(ctx, &url));
    try!(unpack_file(ctx, &filename, &Path::new("/vagga/root"), &[],
        &[Path::new("dev")]));

    ctx.ubuntu_release = Some(release.to_string());
    try!(init_debian_build(ctx));

    return Ok(());
}

fn init_debian_build(ctx: &mut BuildContext) -> Result<(), String> {
    // Do not attempt to start init scripts
    try!(File::create(
            &Path::new("/vagga/root/usr/sbin/policy-rc.d"))
        .and_then(|mut f| f.write(b"#!/bin/sh\nexit 101\n"))
        .map_err(|e| format!("Error writing policy-rc.d file: {}", e)));

    // Do not need to fsync() after package installation
    try!(File::create(
            &Path::new("/vagga/root/etc/dpkg/dpkg.cfg.d/02apt-speedup"))
        .and_then(|mut f| f.write(b"force-unsafe-io"))
        .map_err(|e| format!("Error writing dpkg config: {}", e)));

    try!(ctx.add_cache_dir(Path::new("/var/cache/apt"),
                           "apt-cache".to_string()));
    // TODO(tailhook) remove apt and dpkg
    ctx.add_remove_dir(Path::new("/var/lib/apt"));
    ctx.add_remove_dir(Path::new("/var/lib/dpkg"));
    ctx.apt_update = true;
    return Ok(());
}

pub fn apt_install(ctx: &mut BuildContext, pkgs: &Vec<String>)
    -> Result<(), String>
{
    if ctx.apt_update {
        ctx.apt_update = false;
        try!(run_command(ctx, &[
            "/usr/bin/apt-get".to_string(),
            "update".to_string(),
            ]));
    }
    let mut args = vec!(
        "/usr/bin/apt-get".to_string(),
        "install".to_string(),
        "-y".to_string(),
        );
    args.extend(pkgs.clone().into_iter());
    run_command(ctx, args.as_slice())
}

pub fn add_debian_repo(ctx: &mut BuildContext, repo: &UbuntuRepoInfo)
    -> Result<(), String>
{

    let mut hash = Sha256::new();
    hash.input_str(repo.url.as_slice());
    hash.input(&[0]);
    hash.input_str(repo.suite.as_slice());
    hash.input(&[0]);
    for cmp in repo.components.iter() {
        hash.input_str(cmp.as_slice());
        hash.input(&[0]);
    }
    let name = format!("{}-{}.list",
        hash.result_str()[..8].to_string(),
        repo.suite);

    ctx.apt_update = true;

    File::create(&Path::new("/vagga/root/etc/apt/sources.list.d")
                 .join(name.as_slice()))
        .and_then(|mut f| {
            try!(write!(f, "deb {} {}", repo.url, repo.suite))
            for item in repo.components.iter() {
                try!(write!(f, " {}", item));
            }
            Ok(())
        })
        .map_err(|e| format!("Error writing {} file: {}", name, e))
    // TODO(tailhook) add `update` command
}

pub fn ubuntu_add_universe(ctx: &mut BuildContext)
    -> Result<(), String>
{
    let release = try!(ctx.ubuntu_release.as_ref()
        .ok_or(format!("Unknown ubuntu release")));
    let target = "/vagga/root/etc/apt/sources.list.d/universe.list";

    ctx.apt_update = true;

    File::create(&Path::new(target))
        .and_then(|mut f| {
            try!(writeln!(f,
                "deb http://archive.ubuntu.com/ubuntu/ {} universe",
                release));
            try!(writeln!(f,
                "deb http://archive.ubuntu.com/ubuntu/ {}-updates universe",
                release));
            try!(writeln!(f,
                "deb http://archive.ubuntu.com/ubuntu/ {}-security universe",
                release));
            Ok(())
        })
        .map_err(|e| format!("Error writing universe.list file: {}", e))
}
<commit_msg>Set DEBIAN_FRONTEND for debian-based systems<commit_after>use std::io::fs::File;

use config::builders::UbuntuRepoInfo;
use super::super::context::BuildContext;
use super::super::download::download_file;
use super::super::tarcmd::unpack_file;
use super::generic::run_command;
use container::sha256::{Sha256, Digest};

pub fn fetch_ubuntu_core(ctx: &mut BuildContext, release: &String)
    -> Result<(), String>
{
    let kind = "core";
    let arch = "amd64";
    let url = format!(concat!(
        "http://cdimage.ubuntu.com/ubuntu-{kind}/{release}/",
        "daily/current/{release}-{kind}-{arch}.tar.gz",
        ), kind=kind, arch=arch, release=release);
    let filename = try!(download_file(ctx, &url));
    try!(unpack_file(ctx, &filename, &Path::new("/vagga/root"), &[],
        &[Path::new("dev")]));

    ctx.ubuntu_release = Some(release.to_string());
    try!(init_debian_build(ctx));

    return Ok(());
}

fn init_debian_build(ctx: &mut BuildContext) -> Result<(), String> {
    // Do not attempt to start init scripts
    try!(File::create(
            &Path::new("/vagga/root/usr/sbin/policy-rc.d"))
        .and_then(|mut f| f.write(b"#!/bin/sh\nexit 101\n"))
        .map_err(|e| format!("Error writing policy-rc.d file: {}", e)));

    // Do not need to fsync() after package installation
    try!(File::create(
            &Path::new("/vagga/root/etc/dpkg/dpkg.cfg.d/02apt-speedup"))
        .and_then(|mut f| f.write(b"force-unsafe-io"))
        .map_err(|e| format!("Error writing dpkg config: {}", e)));

    try!(ctx.add_cache_dir(Path::new("/var/cache/apt"),
                           "apt-cache".to_string()));
    ctx.environ.insert("DEBIAN_FRONTEND".to_string(),
                       "noninteractive".to_string());

    ctx.add_remove_dir(Path::new("/var/lib/apt"));
    ctx.add_remove_dir(Path::new("/var/lib/dpkg"));
    ctx.apt_update = true;
    return Ok(());
}

pub fn apt_install(ctx: &mut BuildContext, pkgs: &Vec<String>)
    -> Result<(), String>
{
    if ctx.apt_update {
        ctx.apt_update = false;
        try!(run_command(ctx, &[
            "/usr/bin/apt-get".to_string(),
            "update".to_string(),
            ]));
    }
    let mut args = vec!(
        "/usr/bin/apt-get".to_string(),
        "install".to_string(),
        "-y".to_string(),
        );
    args.extend(pkgs.clone().into_iter());
    run_command(ctx, args.as_slice())
}

pub fn add_debian_repo(ctx: &mut BuildContext, repo: &UbuntuRepoInfo)
    -> Result<(), String>
{

    let mut hash = Sha256::new();
    hash.input_str(repo.url.as_slice());
    hash.input(&[0]);
    hash.input_str(repo.suite.as_slice());
    hash.input(&[0]);
    for cmp in repo.components.iter() {
        hash.input_str(cmp.as_slice());
        hash.input(&[0]);
    }
    let name = format!("{}-{}.list",
        hash.result_str()[..8].to_string(),
        repo.suite);

    ctx.apt_update = true;

    File::create(&Path::new("/vagga/root/etc/apt/sources.list.d")
                 .join(name.as_slice()))
        .and_then(|mut f| {
            try!(write!(f, "deb {} {}", repo.url, repo.suite))
            for item in repo.components.iter() {
                try!(write!(f, " {}", item));
            }
            Ok(())
        })
        .map_err(|e| format!("Error writing {} file: {}", name, e))
    // TODO(tailhook) add `update` command
}

pub fn ubuntu_add_universe(ctx: &mut BuildContext)
    -> Result<(), String>
{
    let release = try!(ctx.ubuntu_release.as_ref()
        .ok_or(format!("Unknown ubuntu release")));
    let target = "/vagga/root/etc/apt/sources.list.d/universe.list";

    ctx.apt_update = true;

    File::create(&Path::new(target))
        .and_then(|mut f| {
            try!(writeln!(f,
                "deb http://archive.ubuntu.com/ubuntu/ {} universe",
                release));
            try!(writeln!(f,
                "deb http://archive.ubuntu.com/ubuntu/ {}-updates universe",
                release));
            try!(writeln!(f,
                "deb http://archive.ubuntu.com/ubuntu/ {}-security universe",
                release));
            Ok(())
        })
        .map_err(|e| format!("Error writing universe.list file: {}", e))
}
<|endoftext|>