<commit_before>use std::fmt;
use std::io::{self, Read};

use hyper::header::{Headers, ContentEncoding, ContentLength, Encoding, TransferEncoding};
use hyper::status::StatusCode;
use hyper::version::HttpVersion;
use hyper::Url;
use libflate::gzip;
use serde::de::DeserializeOwned;
use serde_json;

/// A Response to a submitted `Request`.
pub struct Response {
    inner: Decoder,
}

pub fn new(res: ::hyper::client::Response, gzip: bool) -> Response {
    info!("Response: '{}' for {}", res.status, res.url);
    Response {
        inner: Decoder::from_hyper_response(res, gzip)
    }
}

impl fmt::Debug for Response {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.inner {
            Decoder::PlainText(ref hyper_response) => {
                f.debug_struct("Response")
                    .field("url", &hyper_response.url)
                    .field("status", &hyper_response.status)
                    .field("headers", &hyper_response.headers)
                    .field("version", &hyper_response.version)
                    .finish()
            },
            Decoder::Gzip{ ref head, .. } |
            Decoder::Errored { ref head, .. } => {
                f.debug_struct("Response")
                    .field("url", &head.url)
                    .field("status", &head.status)
                    .field("headers", &head.headers)
                    .field("version", &head.version)
                    .finish()
            }
        }
    }
}

impl Response {
    /// Get the final `Url` of this response.
    #[inline]
    pub fn url(&self) -> &Url {
        match self.inner {
            Decoder::PlainText(ref hyper_response) => &hyper_response.url,
            Decoder::Gzip{ ref head, .. } |
            Decoder::Errored { ref head, .. } => &head.url,
        }
    }

    /// Get the `StatusCode`.
    #[inline]
    pub fn status(&self) -> &StatusCode {
        match self.inner {
            Decoder::PlainText(ref hyper_response) => &hyper_response.status,
            Decoder::Gzip{ ref head, .. } |
            Decoder::Errored { ref head, .. } => &head.status,
        }
    }

    /// Get the `Headers`.
    #[inline]
    pub fn headers(&self) -> &Headers {
        match self.inner {
            Decoder::PlainText(ref hyper_response) => &hyper_response.headers,
            Decoder::Gzip{ ref head, .. } |
            Decoder::Errored { ref head, .. } => &head.headers,
        }
    }

    /// Get the `HttpVersion`.
    #[inline]
    pub fn version(&self) -> &HttpVersion {
        match self.inner {
            Decoder::PlainText(ref hyper_response) => &hyper_response.version,
            Decoder::Gzip{ ref head, .. } |
            Decoder::Errored { ref head, .. } => &head.version,
        }
    }

    /// Try and deserialize the response body as JSON.
    #[inline]
    pub fn json<T: DeserializeOwned>(&mut self) -> ::Result<T> {
        serde_json::from_reader(self).map_err(::error::from)
    }
}

enum Decoder {
    /// A `PlainText` decoder just returns the response content as is.
    PlainText(::hyper::client::Response),
    /// A `Gzip` decoder will uncompress the gziped response content before returning it.
    Gzip {
        decoder: gzip::Decoder<Peeked>,
        head: Head,
    },
    /// An error occured reading the Gzip header, so return that error
    /// when the user tries to read on the `Response`.
    Errored {
        err: Option<io::Error>,
        head: Head,
    }
}

impl Decoder {
    /// Constructs a Decoder from a hyper request.
    ///
    /// A decoder is just a wrapper around the hyper request that knows
    /// how to decode the content body of the request.
    ///
    /// Uses the correct variant by inspecting the Content-Encoding header.
    fn from_hyper_response(mut res: ::hyper::client::Response, check_gzip: bool) -> Self {
        if !check_gzip {
            return Decoder::PlainText(res);
        }
        let content_encoding_gzip: bool;
        let mut is_gzip = {
            content_encoding_gzip = res.headers.get::<ContentEncoding>().map_or(false, |encs|{
                encs.contains(&Encoding::Gzip)
            });
            content_encoding_gzip || res.headers.get::<TransferEncoding>().map_or(false, |encs|{
                encs.contains(&Encoding::Gzip)
            })
        };
        if is_gzip {
            if let Some(content_length) = res.headers.get::<ContentLength>() {
                if content_length.0 == 0 {
                    warn!("GZipped response with content-length of 0");
                    is_gzip = false;
                }
            }
        }
        if content_encoding_gzip {
            res.headers.remove::<ContentEncoding>();
            res.headers.remove::<ContentLength>();
        }
        if is_gzip {
            new_gzip(res)
        } else {
            Decoder::PlainText(res)
        }
    }
}

fn new_gzip(mut res: ::hyper::client::Response) -> Decoder {
    // libflate does a read_exact([0; 2]), so its impossible to tell
    // if the stream was empty, or truly had an UnexpectedEof.
    // Therefore, we need to peek a byte to make check for EOF first.
    let mut peek = [0];
    match res.read(&mut peek) {
        Ok(0) => return Decoder::PlainText(res),
        Ok(n) => {
            debug_assert_eq!(n, 1);
        },
        Err(e) => return Decoder::Errored {
            err: Some(e),
            head: Head {
                headers: res.headers.clone(),
                status: res.status,
                url: res.url.clone(),
                version: res.version,
            }
        },
    }

    let head = Head {
        headers: res.headers.clone(),
        status: res.status,
        url: res.url.clone(),
        version: res.version,
    };

    let reader = Peeked {
        peeked: Some(peek[0]),
        inner: res,
    };
    match gzip::Decoder::new(reader) {
        Ok(gzip) => Decoder::Gzip {
            decoder: gzip,
            head: head,
        },
        Err(e) => Decoder::Errored {
            err: Some(e),
            head: head,
        }
    }
}

struct Head {
    headers: ::hyper::header::Headers,
    url: ::hyper::Url,
    version: ::hyper::version::HttpVersion,
    status: ::hyper::status::StatusCode,
}

struct Peeked {
    peeked: Option<u8>,
    inner: ::hyper::client::Response,
}

impl Read for Peeked {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        if buf.is_empty() {
            return Ok(0);
        }
        if let Some(byte) = self.peeked.take() {
            buf[0] = byte;
            Ok(1)
        } else {
            self.inner.read(buf)
        }
    }
}

impl Read for Decoder {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match *self {
            Decoder::PlainText(ref mut hyper_response) => {
                hyper_response.read(buf)
            },
            Decoder::Gzip{ref mut decoder, ..} => {
                decoder.read(buf)
            },
            Decoder::Errored { ref mut err, .. } => {
                Err(err.take().unwrap_or_else(previously_errored))
            }
        }
    }
}

#[inline]
fn previously_errored() -> io::Error {
    io::Error::new(io::ErrorKind::Other, "permanently errored")
}

/// Read the body of the Response.
impl Read for Response {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.inner.read(buf)
    }
}

<commit_msg>Add full example for `Response::json`.<commit_after>use std::fmt;
use std::io::{self, Read};

use hyper::header::{Headers, ContentEncoding, ContentLength, Encoding, TransferEncoding};
use hyper::status::StatusCode;
use hyper::version::HttpVersion;
use hyper::Url;
use libflate::gzip;
use serde::de::DeserializeOwned;
use serde_json;

/// A Response to a submitted `Request`.
pub struct Response {
    inner: Decoder,
}

pub fn new(res: ::hyper::client::Response, gzip: bool) -> Response {
    info!("Response: '{}' for {}", res.status, res.url);
    Response {
        inner: Decoder::from_hyper_response(res, gzip)
    }
}

impl fmt::Debug for Response {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.inner {
            Decoder::PlainText(ref hyper_response) => {
                f.debug_struct("Response")
                    .field("url", &hyper_response.url)
                    .field("status", &hyper_response.status)
                    .field("headers", &hyper_response.headers)
                    .field("version", &hyper_response.version)
                    .finish()
            },
            Decoder::Gzip{ ref head, .. } |
            Decoder::Errored { ref head, .. } => {
                f.debug_struct("Response")
                    .field("url", &head.url)
                    .field("status", &head.status)
                    .field("headers", &head.headers)
                    .field("version", &head.version)
                    .finish()
            }
        }
    }
}

impl Response {
    /// Get the final `Url` of this response.
    #[inline]
    pub fn url(&self) -> &Url {
        match self.inner {
            Decoder::PlainText(ref hyper_response) => &hyper_response.url,
            Decoder::Gzip{ ref head, .. } |
            Decoder::Errored { ref head, .. } => &head.url,
        }
    }

    /// Get the `StatusCode`.
    #[inline]
    pub fn status(&self) -> &StatusCode {
        match self.inner {
            Decoder::PlainText(ref hyper_response) => &hyper_response.status,
            Decoder::Gzip{ ref head, .. } |
            Decoder::Errored { ref head, .. } => &head.status,
        }
    }

    /// Get the `Headers`.
    #[inline]
    pub fn headers(&self) -> &Headers {
        match self.inner {
            Decoder::PlainText(ref hyper_response) => &hyper_response.headers,
            Decoder::Gzip{ ref head, .. } |
            Decoder::Errored { ref head, .. } => &head.headers,
        }
    }

    /// Get the `HttpVersion`.
    #[inline]
    pub fn version(&self) -> &HttpVersion {
        match self.inner {
            Decoder::PlainText(ref hyper_response) => &hyper_response.version,
            Decoder::Gzip{ ref head, .. } |
            Decoder::Errored { ref head, .. } => &head.version,
        }
    }

    /// Try and deserialize the response body as JSON.
    ///
    /// # Examples
    ///
    /// ```rust,no_run
    /// extern crate reqwest;
    /// #[macro_use]
    /// extern crate serde_derive;
    ///
    /// #[derive(Deserialize)]
    /// struct User {
    ///     name: String,
    ///     age: u8,
    /// }
    ///
    /// fn main() {
    ///     let user: User = reqwest::get("http://127.0.0.1/user.json")
    ///         .expect("network error")
    ///         .json()
    ///         .expect("malformed json");
    /// }
    /// ```
    #[inline]
    pub fn json<T: DeserializeOwned>(&mut self) -> ::Result<T> {
        serde_json::from_reader(self).map_err(::error::from)
    }
}

enum Decoder {
    /// A `PlainText` decoder just returns the response content as is.
    PlainText(::hyper::client::Response),
    /// A `Gzip` decoder will uncompress the gziped response content before returning it.
    Gzip {
        decoder: gzip::Decoder<Peeked>,
        head: Head,
    },
    /// An error occured reading the Gzip header, so return that error
    /// when the user tries to read on the `Response`.
    Errored {
        err: Option<io::Error>,
        head: Head,
    }
}

impl Decoder {
    /// Constructs a Decoder from a hyper request.
    ///
    /// A decoder is just a wrapper around the hyper request that knows
    /// how to decode the content body of the request.
    ///
    /// Uses the correct variant by inspecting the Content-Encoding header.
    fn from_hyper_response(mut res: ::hyper::client::Response, check_gzip: bool) -> Self {
        if !check_gzip {
            return Decoder::PlainText(res);
        }
        let content_encoding_gzip: bool;
        let mut is_gzip = {
            content_encoding_gzip = res.headers.get::<ContentEncoding>().map_or(false, |encs|{
                encs.contains(&Encoding::Gzip)
            });
            content_encoding_gzip || res.headers.get::<TransferEncoding>().map_or(false, |encs|{
                encs.contains(&Encoding::Gzip)
            })
        };
        if is_gzip {
            if let Some(content_length) = res.headers.get::<ContentLength>() {
                if content_length.0 == 0 {
                    warn!("GZipped response with content-length of 0");
                    is_gzip = false;
                }
            }
        }
        if content_encoding_gzip {
            res.headers.remove::<ContentEncoding>();
            res.headers.remove::<ContentLength>();
        }
        if is_gzip {
            new_gzip(res)
        } else {
            Decoder::PlainText(res)
        }
    }
}

fn new_gzip(mut res: ::hyper::client::Response) -> Decoder {
    // libflate does a read_exact([0; 2]), so its impossible to tell
    // if the stream was empty, or truly had an UnexpectedEof.
    // Therefore, we need to peek a byte to make check for EOF first.
    let mut peek = [0];
    match res.read(&mut peek) {
        Ok(0) => return Decoder::PlainText(res),
        Ok(n) => {
            debug_assert_eq!(n, 1);
        },
        Err(e) => return Decoder::Errored {
            err: Some(e),
            head: Head {
                headers: res.headers.clone(),
                status: res.status,
                url: res.url.clone(),
                version: res.version,
            }
        },
    }

    let head = Head {
        headers: res.headers.clone(),
        status: res.status,
        url: res.url.clone(),
        version: res.version,
    };

    let reader = Peeked {
        peeked: Some(peek[0]),
        inner: res,
    };
    match gzip::Decoder::new(reader) {
        Ok(gzip) => Decoder::Gzip {
            decoder: gzip,
            head: head,
        },
        Err(e) => Decoder::Errored {
            err: Some(e),
            head: head,
        }
    }
}

struct Head {
    headers: ::hyper::header::Headers,
    url: ::hyper::Url,
    version: ::hyper::version::HttpVersion,
    status: ::hyper::status::StatusCode,
}

struct Peeked {
    peeked: Option<u8>,
    inner: ::hyper::client::Response,
}

impl Read for Peeked {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        if buf.is_empty() {
            return Ok(0);
        }
        if let Some(byte) = self.peeked.take() {
            buf[0] = byte;
            Ok(1)
        } else {
            self.inner.read(buf)
        }
    }
}

impl Read for Decoder {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match *self {
            Decoder::PlainText(ref mut hyper_response) => {
                hyper_response.read(buf)
            },
            Decoder::Gzip{ref mut decoder, ..} => {
                decoder.read(buf)
            },
            Decoder::Errored { ref mut err, .. } => {
                Err(err.take().unwrap_or_else(previously_errored))
            }
        }
    }
}

#[inline]
fn previously_errored() -> io::Error {
    io::Error::new(io::ErrorKind::Other, "permanently errored")
}

/// Read the body of the Response.
impl Read for Response {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.inner.read(buf)
    }
}

<|endoftext|>


<commit_before>use serde::Deserialize;
use std::str::FromStr;
use std::time::SystemTime;

#[derive(Debug, Deserialize, PartialEq)]
#[serde(rename = "usage_report")]
pub struct UsageReport {
    pub metric: String,
    pub period: String,
    pub period_start: String,
    pub period_end: String,
    pub max_value: u64,
    pub current_value: u64,
}

// Unfortunately the XML output from Apisonator includes a rather useless "usage_reports" tag that
// is then followed by a "usage_report" tag in each UsageReport, so we need to wrap that up.
#[derive(Debug, Deserialize, PartialEq)]
pub enum UsageReports {
    #[serde(rename = "usage_report")]
    UsageReports(Vec<UsageReport>),
}

#[derive(Debug, Deserialize, PartialEq)]
#[serde(rename = "status")]
pub struct Authorization {
    authorized: bool,
    plan: String,
    usage_reports: UsageReports,
}

#[derive(Debug, Deserialize, PartialEq)]
pub struct PeriodInstance {
    start: SystemTime,
    end: SystemTime,
}

#[derive(Debug, Deserialize, PartialEq)]
pub enum Period {
    Minute(PeriodInstance),
    Hour(PeriodInstance),
    Day(PeriodInstance),
    Week(PeriodInstance),
    Month(PeriodInstance),
    Year(PeriodInstance),
    Eternity,
}

#[derive(Debug, Deserialize, PartialEq)]
pub struct UsageData {
    max_value: u64,
    current_value: u64,
}

#[derive(Debug, Deserialize, PartialEq)]
pub struct Metric(pub String);

impl FromStr for Authorization {
    type Err = serde_xml_rs::Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        serde_xml_rs::from_str(s)
    }
}

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

    #[test]
    fn parse() {
        let s = r##"
        <?xml version="1.0" encoding="UTF-8"?>
        <status>
            <authorized>true</authorized>
            <plan>App Plan</plan>
            <usage_reports>
                <usage_report metric="products" period="minute">
                    <period_start>2019-06-05 16:24:00 +0000</period_start>
                    <period_end>2019-06-05 16:25:00 +0000</period_end>
                    <max_value>5</max_value>
                    <current_value>0</current_value>
                </usage_report>
                <usage_report metric="products" period="month">
                    <period_start>2019-06-01 00:00:00 +0000</period_start>
                    <period_end>2019-07-01 00:00:00 +0000</period_end>
                    <max_value>50</max_value>
                    <current_value>0</current_value>
                </usage_report>
            </usage_reports>
        </status>
        "##;

        let parsed_auth = Authorization::from_str(s).unwrap();

        let expected_auth = Authorization {
            authorized: true,
            plan: String::from("App Plan"),
            usage_reports: UsageReports::UsageReports(vec![
                UsageReport {
                    metric: String::from("products"),
                    period: String::from("minute"),
                    period_start: String::from("2019-06-05 16:24:00 +0000"),
                    period_end: String::from("2019-06-05 16:25:00 +0000"),
                    max_value: 5,
                    current_value: 0,
                },
                UsageReport {
                    metric: String::from("products"),
                    period: String::from("month"),
                    period_start: String::from("2019-06-01 00:00:00 +0000"),
                    period_end: String::from("2019-07-01 00:00:00 +0000"),
                    max_value: 50,
                    current_value: 0,
                },
            ]),
        };

        assert_eq!(parsed_auth, expected_auth);
    }
}
<commit_msg>response: convert period field to enum<commit_after>use serde::de::{self, Deserializer, Visitor};
use serde::Deserialize;
use std::fmt;
use std::str::FromStr;
use std::time::SystemTime;

#[derive(Debug, Deserialize, PartialEq)]
#[serde(rename = "usage_report")]
pub struct UsageReport {
    pub metric: String,
    pub period: Period,
    pub period_start: String,
    pub period_end: String,
    pub max_value: u64,
    pub current_value: u64,
}

// Unfortunately the XML output from Apisonator includes a rather useless "usage_reports" tag that
// is then followed by a "usage_report" tag in each UsageReport, so we need to wrap that up.
#[derive(Debug, Deserialize, PartialEq)]
pub enum UsageReports {
    #[serde(rename = "usage_report")]
    UsageReports(Vec<UsageReport>),
}

#[derive(Debug, Deserialize, PartialEq)]
#[serde(rename = "status")]
pub struct Authorization {
    authorized: bool,
    plan: String,
    usage_reports: UsageReports,
}

#[derive(Debug, Deserialize, PartialEq)]
pub struct PeriodInstance {
    start: SystemTime,
    end: SystemTime,
}

#[derive(Debug, PartialEq)]
pub enum Period {
    Minute,
    Hour,
    Day,
    Week,
    Month,
    Year,
    Eternity,
}

struct PeriodStringVisitor;

impl<'de> Visitor<'de> for PeriodStringVisitor {
    type Value = Period;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a string that represents a period")
    }

    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        match v {
            "minute" => Ok(Period::Minute),
            "hour" => Ok(Period::Hour),
            "day" => Ok(Period::Day),
            "week" => Ok(Period::Week),
            "month" => Ok(Period::Month),
            "year" => Ok(Period::Year),
            "eternity" => Ok(Period::Eternity),
            _ => Err(E::custom("Invalid period")),
        }
    }
}

impl<'de> Deserialize<'de> for Period {
    fn deserialize<D>(deserializer: D) -> Result<Period, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_any(PeriodStringVisitor)
    }
}

#[derive(Debug, Deserialize, PartialEq)]
pub struct UsageData {
    max_value: u64,
    current_value: u64,
}

#[derive(Debug, Deserialize, PartialEq)]
pub struct Metric(pub String);

impl FromStr for Authorization {
    type Err = serde_xml_rs::Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        serde_xml_rs::from_str(s)
    }
}

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

    #[test]
    fn parse() {
        let s = r##"
        <?xml version="1.0" encoding="UTF-8"?>
        <status>
            <authorized>true</authorized>
            <plan>App Plan</plan>
            <usage_reports>
                <usage_report metric="products" period="minute">
                    <period_start>2019-06-05 16:24:00 +0000</period_start>
                    <period_end>2019-06-05 16:25:00 +0000</period_end>
                    <max_value>5</max_value>
                    <current_value>0</current_value>
                </usage_report>
                <usage_report metric="products" period="month">
                    <period_start>2019-06-01 00:00:00 +0000</period_start>
                    <period_end>2019-07-01 00:00:00 +0000</period_end>
                    <max_value>50</max_value>
                    <current_value>0</current_value>
                </usage_report>
            </usage_reports>
        </status>
        "##;

        let parsed_auth = Authorization::from_str(s).unwrap();

        let expected_auth = Authorization {
            authorized: true,
            plan: String::from("App Plan"),
            usage_reports: UsageReports::UsageReports(vec![
                UsageReport {
                    metric: String::from("products"),
                    period: Period::Minute,
                    period_start: String::from("2019-06-05 16:24:00 +0000"),
                    period_end: String::from("2019-06-05 16:25:00 +0000"),
                    max_value: 5,
                    current_value: 0,
                },
                UsageReport {
                    metric: String::from("products"),
                    period: Period::Month,
                    period_start: String::from("2019-06-01 00:00:00 +0000"),
                    period_end: String::from("2019-07-01 00:00:00 +0000"),
                    max_value: 50,
                    current_value: 0,
                },
            ]),
        };

        assert_eq!(parsed_auth, expected_auth);
    }
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/RSA_code
extern crate num;

use num::bigint::BigUint;
use num::traits::{Zero, One};
use num::integer::Integer;

fn mod_exp(b: &BigUint, e: &BigUint, n: &BigUint) -> Result<BigUint, &'static str> {
    if n.is_zero() {
        return Err("modulus is zero");
    }
    if b >= n {
        // base is too large and should be split into blocks
        return Err("base is >= modulus");
    }
    if b.gcd(n) != BigUint::one() {
        return Err("base and modulus are not relatively prime");
    }

    let mut bb = b.clone();
    let mut ee = e.clone();
    let mut result = BigUint::one();
    while !ee.is_zero() {
        if ee.is_odd() {
            result = (result * &bb) % n;
        }
        ee = ee >> 1;
        bb = (&bb * &bb) % n;
    }
    Ok(result)
}

fn main() {
    let msg = "Rosetta Code";

    let n = "9516311845790656153499716760847001433441357".parse().unwrap();
    let e = "65537".parse().unwrap();
    let d = "5617843187844953170308463622230283376298685".parse().unwrap();

    let msg_int = BigUint::from_bytes_be(msg.as_bytes());
    let enc = mod_exp(&msg_int, &e, &n).unwrap();
    let dec = mod_exp(&enc, &d, &n).unwrap();
    let msg_dec = String::from_utf8(dec.to_bytes_be()).unwrap();

    println!("msg as txt: {}", msg);
    println!("msg as num: {}", msg_int);
    println!("enc as num: {}", enc);
    println!("dec as num: {}", dec);
    println!("dec as txt: {}", msg_dec);
}

#[cfg(test)]
mod tests {
    use super::mod_exp;
    use num::bigint::BigUint;
    use num::integer::Integer;
    use num::traits::{Zero, FromPrimitive};

    const N: &'static str = "9516311845790656153499716760847001433441357";
    const E: &'static str = "65537";
    const D: &'static str = "5617843187844953170308463622230283376298685";

    fn rsa_numbers() -> (BigUint, BigUint, BigUint) {
        let n = N.parse().unwrap();
        let e = E.parse().unwrap();
        let d = D.parse().unwrap();
        (n, e, d)
    }

    #[test]
    fn test_enc_dec() {
        let (n, e, d) = rsa_numbers();
        let msg = "Rosetta Code";
        let msg_int = BigUint::from_bytes_be(msg.as_bytes());
        let enc = mod_exp(&msg_int, &e, &n).unwrap();
        let dec = mod_exp(&enc, &d, &n).unwrap();
        let msg_dec = String::from_utf8(dec.to_bytes_be()).unwrap();
        assert_eq!(msg, msg_dec);
    }

    #[test]
    fn test_enc_too_large_base() {
        let (n, e, _) = rsa_numbers();
        let msg = "I am too large for this modulus!";
        let msg_int = BigUint::from_bytes_be(msg.as_bytes());
        assert!(msg_int > n);
        let result = mod_exp(&msg_int, &e, &n);
        assert_eq!(Err("base is >= modulus"), result);
    }

    #[test]
    fn test_enc_zero_modulus() {
        let (_, e, _) = rsa_numbers();
        let msg_int = BigUint::from_bytes_be("msg".as_bytes());
        let result = mod_exp(&msg_int, &e, &BigUint::zero());
        assert_eq!(Err("modulus is zero"), result);
    }

    #[test]
    fn test_base_modulus_not_relatively_prime() {
        let (_, e, _) = rsa_numbers();
        let b = BigUint::from_u8(12).unwrap();
        let n = BigUint::from_u8(18).unwrap();
        assert_eq!(&BigUint::from_u8(6).unwrap(), &b.gcd(&n));
        let result = mod_exp(&b, &e, &n);
        assert_eq!(Err("base and modulus are not relatively prime"), result);
    }
}
<commit_msg>use byte string literals instead of `as_bytes()`<commit_after>// http://rosettacode.org/wiki/RSA_code
extern crate num;

use num::bigint::BigUint;
use num::traits::{Zero, One};
use num::integer::Integer;

fn mod_exp(b: &BigUint, e: &BigUint, n: &BigUint) -> Result<BigUint, &'static str> {
    if n.is_zero() {
        return Err("modulus is zero");
    }
    if b >= n {
        // base is too large and should be split into blocks
        return Err("base is >= modulus");
    }
    if b.gcd(n) != BigUint::one() {
        return Err("base and modulus are not relatively prime");
    }

    let mut bb = b.clone();
    let mut ee = e.clone();
    let mut result = BigUint::one();
    while !ee.is_zero() {
        if ee.is_odd() {
            result = (result * &bb) % n;
        }
        ee = ee >> 1;
        bb = (&bb * &bb) % n;
    }
    Ok(result)
}

fn main() {
    let msg = "Rosetta Code";

    let n = "9516311845790656153499716760847001433441357".parse().unwrap();
    let e = "65537".parse().unwrap();
    let d = "5617843187844953170308463622230283376298685".parse().unwrap();

    let msg_int = BigUint::from_bytes_be(msg.as_bytes());
    let enc = mod_exp(&msg_int, &e, &n).unwrap();
    let dec = mod_exp(&enc, &d, &n).unwrap();
    let msg_dec = String::from_utf8(dec.to_bytes_be()).unwrap();

    println!("msg as txt: {}", msg);
    println!("msg as num: {}", msg_int);
    println!("enc as num: {}", enc);
    println!("dec as num: {}", dec);
    println!("dec as txt: {}", msg_dec);
}

#[cfg(test)]
mod tests {
    use super::mod_exp;
    use num::bigint::BigUint;
    use num::integer::Integer;
    use num::traits::{Zero, FromPrimitive};

    const N: &'static str = "9516311845790656153499716760847001433441357";
    const E: &'static str = "65537";
    const D: &'static str = "5617843187844953170308463622230283376298685";

    fn rsa_numbers() -> (BigUint, BigUint, BigUint) {
        let n = N.parse().unwrap();
        let e = E.parse().unwrap();
        let d = D.parse().unwrap();
        (n, e, d)
    }

    #[test]
    fn test_enc_dec() {
        let (n, e, d) = rsa_numbers();
        let msg = "Rosetta Code";
        let msg_int = BigUint::from_bytes_be(msg.as_bytes());
        let enc = mod_exp(&msg_int, &e, &n).unwrap();
        let dec = mod_exp(&enc, &d, &n).unwrap();
        let msg_dec = String::from_utf8(dec.to_bytes_be()).unwrap();
        assert_eq!(msg, msg_dec);
    }

    #[test]
    fn test_enc_too_large_base() {
        let (n, e, _) = rsa_numbers();
        let msg = "I am too large for this modulus!";
        let msg_int = BigUint::from_bytes_be(msg.as_bytes());
        assert!(msg_int > n);
        let result = mod_exp(&msg_int, &e, &n);
        assert_eq!(Err("base is >= modulus"), result);
    }

    #[test]
    fn test_enc_zero_modulus() {
        let (_, e, _) = rsa_numbers();
        let msg_int = BigUint::from_bytes_be(b"msg");
        let result = mod_exp(&msg_int, &e, &BigUint::zero());
        assert_eq!(Err("modulus is zero"), result);
    }

    #[test]
    fn test_base_modulus_not_relatively_prime() {
        let (_, e, _) = rsa_numbers();
        let b = BigUint::from_u8(12).unwrap();
        let n = BigUint::from_u8(18).unwrap();
        assert_eq!(&BigUint::from_u8(6).unwrap(), &b.gcd(&n));
        let result = mod_exp(&b, &e, &n);
        assert_eq!(Err("base and modulus are not relatively prime"), result);
    }
}
<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate failure;
extern crate geo;
extern crate mimir;
extern crate osmpbfreader;

use super::osm_utils::get_way_coord;
use super::OsmPbfReader;
use admin_geofinder::AdminGeoFinder;
use failure::ResultExt;
use std::collections::{BTreeMap, BTreeSet};
use std::sync::Arc;
use utils::{format_label, get_zip_codes_from_admins};
use Error;

pub type AdminSet = BTreeSet<Arc<mimir::Admin>>;
pub type NameAdminMap = BTreeMap<StreetKey, Vec<osmpbfreader::OsmId>>;
pub type StreetsVec = Vec<mimir::Street>;
pub type StreetWithRelationSet = BTreeSet<osmpbfreader::OsmId>;

#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub struct StreetKey {
    pub name: String,
    pub admins: AdminSet,
}

pub fn streets(
    pbf: &mut OsmPbfReader,
    admins_geofinder: &AdminGeoFinder,
) -> Result<StreetsVec, Error> {
    fn is_valid_obj(obj: &osmpbfreader::OsmObj) -> bool {
        match *obj {
            osmpbfreader::OsmObj::Way(ref way) => {
                way.tags.get("highway").map_or(false, |v| !v.is_empty())
                    && way.tags.get("name").map_or(false, |v| !v.is_empty())
            }
            osmpbfreader::OsmObj::Relation(ref rel) => rel
                .tags
                .get("type")
                .map_or(false, |v| v == "associatedStreet"),
            _ => false,
        }
    }
    info!("reading pbf...");
    let objs_map = pbf
        .get_objs_and_deps(is_valid_obj)
        .context("Error occurred when reading pbf")?;
    info!("reading pbf done.");
    let mut street_rel: StreetWithRelationSet = BTreeSet::new();
    let mut street_list: StreetsVec = vec![];
    // Sometimes, streets can be divided into several "way"s that still have the same street name.
    // The reason why a street is divided may be that a part of the street become
    // a bridge/tunnel/etc. In this case, a "relation" tagged with (type = associatedStreet) is used
    // to group all these "way"s. In order not to have duplicates in autocompletion, we should tag
    // the osm ways in the relation not to index them twice.

    for rel in objs_map.iter().filter_map(|(_, obj)| obj.relation()) {
        let way_name = rel.tags.get("name");
        for ref_obj in &rel.refs {
            use mdo::option::*;
            let objs_map = &objs_map;
            let street_list = &mut street_list;
            let admins_geofinder = &admins_geofinder;

            let inserted = mdo! {
                when ref_obj.member.is_way();
                when ref_obj.role == "street";
                obj =<< objs_map.get(&ref_obj.member);
                way =<< obj.way();
                way_name =<< way_name.or_else(|| way.tags.get("name"));
                let admin = get_street_admin(admins_geofinder, objs_map, way);
                ret ret(street_list.push(mimir::Street {
                    id: format!("street:osm:rel:{}", rel.id.0.to_string()),
                    name: way_name.to_string(),
                    label: format_label(&admin, way_name),
                    weight: 0.,
                    zip_codes: get_zip_codes_from_admins(&admin),
                    administrative_regions: admin,
                    coord: get_way_coord(objs_map, way),
                }))
            };
            if inserted.is_some() {
                break;
            }
        }

        // Add osmid of all the relation members in the set
        // We don't create any street for all the osmid present in street_rel
        for ref_obj in &rel.refs {
            if ref_obj.member.is_way() {
                street_rel.insert(ref_obj.member);
            }
        }
    }

    // we merge all the ways with a key = way_name + admin list of level(=city_level)
    // we use a map NameAdminMap <key, value> to manage the merging of ways
    let mut name_admin_map: NameAdminMap = BTreeMap::new();
    for (osmid, obj) in &objs_map {
        if street_rel.contains(osmid) {
            continue;
        }
        use mdo::option::*;
        let admins_geofinder = &admins_geofinder;
        let objs_map = &objs_map;
        let name_admin_map = &mut name_admin_map;
        mdo! {
            way =<< obj.way();
            let admins: BTreeSet<Arc<mimir::Admin>> = get_street_admin(admins_geofinder,
                objs_map, way)
                .into_iter()
                .filter(|admin| admin.is_city())
                .collect();

            way_name =<< way.tags.get("name");
            let key = StreetKey{name: way_name.to_string(), admins: admins};
            ret ret(name_admin_map.entry(key).or_insert(vec![]).push(*osmid))
        };
    }

    // Create a street for each way with osmid present in objs_map
    for way_ids in name_admin_map.values() {
        use mdo::option::*;
        let objs_map = &objs_map;
        let street_list = &mut street_list;
        let admins_geofinder = &admins_geofinder;
        mdo! {
            min_id =<< way_ids.iter().min();
            obj =<< objs_map.get(&min_id);
            way =<< obj.way();
            way_name =<< way.tags.get("name");
            let admins = get_street_admin(admins_geofinder, objs_map, way);
            ret ret(street_list.push(mimir::Street {
                id: format!("street:osm:way:{}", way.id.0.to_string()),
                name: way_name.to_string(),
                label: format_label(&admins, way_name),
                weight: 0.,
                zip_codes: get_zip_codes_from_admins(&admins),
                administrative_regions: admins,
                coord: get_way_coord(objs_map, way),
            }))
        };
    }

    Ok(street_list)
}

fn get_street_admin(
    admins_geofinder: &AdminGeoFinder,
    obj_map: &BTreeMap<osmpbfreader::OsmId, osmpbfreader::OsmObj>,
    way: &osmpbfreader::objects::Way,
) -> Vec<Arc<mimir::Admin>> {
    /*
        To avoid corner cases where the ends of the way are near
        administrative boundaries, the geofinder is called
        on a middle node.
    */
    let nb_nodes = way.nodes.len();
    way.nodes
        .iter()
        .skip(nb_nodes / 2)
        .filter_map(|node_id| obj_map.get(&(*node_id).into()))
        .filter_map(|node_obj| node_obj.node())
        .map(|node| geo::Coordinate {
            x: node.lon(),
            y: node.lat(),
        }).next()
        .map_or(vec![], |c| admins_geofinder.get(&c))
}

pub fn compute_street_weight(streets: &mut StreetsVec) {
    for st in streets {
        for admin in &mut st.administrative_regions {
            if admin.is_city() {
                st.weight = admin.weight;
                break;
            }
        }
    }
}
<commit_msg>relation instead of rel<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate failure;
extern crate geo;
extern crate mimir;
extern crate osmpbfreader;

use super::osm_utils::get_way_coord;
use super::OsmPbfReader;
use admin_geofinder::AdminGeoFinder;
use failure::ResultExt;
use std::collections::{BTreeMap, BTreeSet};
use std::sync::Arc;
use utils::{format_label, get_zip_codes_from_admins};
use Error;

pub type AdminSet = BTreeSet<Arc<mimir::Admin>>;
pub type NameAdminMap = BTreeMap<StreetKey, Vec<osmpbfreader::OsmId>>;
pub type StreetsVec = Vec<mimir::Street>;
pub type StreetWithRelationSet = BTreeSet<osmpbfreader::OsmId>;

#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub struct StreetKey {
    pub name: String,
    pub admins: AdminSet,
}

pub fn streets(
    pbf: &mut OsmPbfReader,
    admins_geofinder: &AdminGeoFinder,
) -> Result<StreetsVec, Error> {
    fn is_valid_obj(obj: &osmpbfreader::OsmObj) -> bool {
        match *obj {
            osmpbfreader::OsmObj::Way(ref way) => {
                way.tags.get("highway").map_or(false, |v| !v.is_empty())
                    && way.tags.get("name").map_or(false, |v| !v.is_empty())
            }
            osmpbfreader::OsmObj::Relation(ref rel) => rel
                .tags
                .get("type")
                .map_or(false, |v| v == "associatedStreet"),
            _ => false,
        }
    }
    info!("reading pbf...");
    let objs_map = pbf
        .get_objs_and_deps(is_valid_obj)
        .context("Error occurred when reading pbf")?;
    info!("reading pbf done.");
    let mut street_rel: StreetWithRelationSet = BTreeSet::new();
    let mut street_list: StreetsVec = vec![];
    // Sometimes, streets can be divided into several "way"s that still have the same street name.
    // The reason why a street is divided may be that a part of the street become
    // a bridge/tunnel/etc. In this case, a "relation" tagged with (type = associatedStreet) is used
    // to group all these "way"s. In order not to have duplicates in autocompletion, we should tag
    // the osm ways in the relation not to index them twice.

    for rel in objs_map.iter().filter_map(|(_, obj)| obj.relation()) {
        let way_name = rel.tags.get("name");
        for ref_obj in &rel.refs {
            use mdo::option::*;
            let objs_map = &objs_map;
            let street_list = &mut street_list;
            let admins_geofinder = &admins_geofinder;

            let inserted = mdo! {
                when ref_obj.member.is_way();
                when ref_obj.role == "street";
                obj =<< objs_map.get(&ref_obj.member);
                way =<< obj.way();
                way_name =<< way_name.or_else(|| way.tags.get("name"));
                let admin = get_street_admin(admins_geofinder, objs_map, way);
                ret ret(street_list.push(mimir::Street {
                    id: format!("street:osm:relation:{}", rel.id.0.to_string()),
                    name: way_name.to_string(),
                    label: format_label(&admin, way_name),
                    weight: 0.,
                    zip_codes: get_zip_codes_from_admins(&admin),
                    administrative_regions: admin,
                    coord: get_way_coord(objs_map, way),
                }))
            };
            if inserted.is_some() {
                break;
            }
        }

        // Add osmid of all the relation members in the set
        // We don't create any street for all the osmid present in street_rel
        for ref_obj in &rel.refs {
            if ref_obj.member.is_way() {
                street_rel.insert(ref_obj.member);
            }
        }
    }

    // we merge all the ways with a key = way_name + admin list of level(=city_level)
    // we use a map NameAdminMap <key, value> to manage the merging of ways
    let mut name_admin_map: NameAdminMap = BTreeMap::new();
    for (osmid, obj) in &objs_map {
        if street_rel.contains(osmid) {
            continue;
        }
        use mdo::option::*;
        let admins_geofinder = &admins_geofinder;
        let objs_map = &objs_map;
        let name_admin_map = &mut name_admin_map;
        mdo! {
            way =<< obj.way();
            let admins: BTreeSet<Arc<mimir::Admin>> = get_street_admin(admins_geofinder,
                objs_map, way)
                .into_iter()
                .filter(|admin| admin.is_city())
                .collect();

            way_name =<< way.tags.get("name");
            let key = StreetKey{name: way_name.to_string(), admins: admins};
            ret ret(name_admin_map.entry(key).or_insert(vec![]).push(*osmid))
        };
    }

    // Create a street for each way with osmid present in objs_map
    for way_ids in name_admin_map.values() {
        use mdo::option::*;
        let objs_map = &objs_map;
        let street_list = &mut street_list;
        let admins_geofinder = &admins_geofinder;
        mdo! {
            min_id =<< way_ids.iter().min();
            obj =<< objs_map.get(&min_id);
            way =<< obj.way();
            way_name =<< way.tags.get("name");
            let admins = get_street_admin(admins_geofinder, objs_map, way);
            ret ret(street_list.push(mimir::Street {
                id: format!("street:osm:way:{}", way.id.0.to_string()),
                name: way_name.to_string(),
                label: format_label(&admins, way_name),
                weight: 0.,
                zip_codes: get_zip_codes_from_admins(&admins),
                administrative_regions: admins,
                coord: get_way_coord(objs_map, way),
            }))
        };
    }

    Ok(street_list)
}

fn get_street_admin(
    admins_geofinder: &AdminGeoFinder,
    obj_map: &BTreeMap<osmpbfreader::OsmId, osmpbfreader::OsmObj>,
    way: &osmpbfreader::objects::Way,
) -> Vec<Arc<mimir::Admin>> {
    /*
        To avoid corner cases where the ends of the way are near
        administrative boundaries, the geofinder is called
        on a middle node.
    */
    let nb_nodes = way.nodes.len();
    way.nodes
        .iter()
        .skip(nb_nodes / 2)
        .filter_map(|node_id| obj_map.get(&(*node_id).into()))
        .filter_map(|node_obj| node_obj.node())
        .map(|node| geo::Coordinate {
            x: node.lon(),
            y: node.lat(),
        }).next()
        .map_or(vec![], |c| admins_geofinder.get(&c))
}

pub fn compute_street_weight(streets: &mut StreetsVec) {
    for st in streets {
        for admin in &mut st.administrative_regions {
            if admin.is_city() {
                st.weight = admin.weight;
                break;
            }
        }
    }
}
<|endoftext|>


<commit_before>//
// Sysinfo
//
// Copyright (c) 2017 Guillaume Gomez
//

#[cfg(not(target_os = "windows"))]
use std::fs;
#[cfg(not(target_os = "windows"))]
use std::path::{Path, PathBuf};
#[cfg(not(target_os = "windows"))]
use libc::{c_char, lstat, stat, S_IFLNK, S_IFMT};

#[cfg(not(target_os = "windows"))]
pub fn realpath(original: &Path) -> PathBuf {
    let ori = Path::new(original.to_str().unwrap());

    // Right now lstat on windows doesn't work quite well
    if cfg!(windows) {
        return PathBuf::from(ori);
    }
    let result = PathBuf::from(original);
    let mut buf: stat = unsafe { ::std::mem::uninitialized() };
    let res = unsafe { lstat(result.to_str().unwrap().as_ptr() as *const c_char,
                             &mut buf as *mut stat) };
    if res < 0 || (buf.st_mode & S_IFMT) != S_IFLNK {
        PathBuf::new()
    } else {
        match fs::read_link(&result) {
            Ok(f) => f,
            Err(_) => PathBuf::new(),
        }
    }
}
<commit_msg>Fix invalid str to C conversion<commit_after>//
// Sysinfo
//
// Copyright (c) 2017 Guillaume Gomez
//

#[cfg(not(target_os = "windows"))]
use std::fs;
#[cfg(not(target_os = "windows"))]
use std::path::{Path, PathBuf};
#[cfg(not(target_os = "windows"))]
use libc::{c_char, lstat, stat, S_IFLNK, S_IFMT};

#[cfg(not(target_os = "windows"))]
pub fn realpath(original: &Path) -> PathBuf {
    let ori = Path::new(original.to_str().unwrap());

    // Right now lstat on windows doesn't work quite well
    if cfg!(windows) {
        return PathBuf::from(ori);
    }
    let result = PathBuf::from(original);
    let mut result_s = result.to_str().unwrap().as_bytes().to_vec();
    result_s.push(0);
    let mut buf: stat = unsafe { ::std::mem::uninitialized() };
    let res = unsafe { lstat(result_s.as_ptr() as *const c_char,
                             &mut buf as *mut stat) };
    if res < 0 || (buf.st_mode & S_IFMT) != S_IFLNK {
        PathBuf::new()
    } else {
        match fs::read_link(&result) {
            Ok(f) => f,
            Err(_) => PathBuf::new(),
        }
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::fs::File;
use std::path::Path;
use memory::Memory;
use loader::{hexloader, rawloader, LoadError, Result};

pub fn load_file(filename: &Path) -> Result<Box<Memory>> {
    let mut file = File::open(filename)?;
    match Path::new(filename).extension().and_then(|ext| ext.to_str()) {
        Some("img") | Some("bin") | Some("raw") | None => rawloader::load_with_seek(&mut file),
        Some("hex") => hexloader::load(&mut file),
        ext => Err(LoadError::from_message(format!(
            "Unknown file extension: {:?}",
            ext
        ))),
    }
}

pub static SUPPORTED_FORMATS: [&str; 4] = ["img", "bin", "raw", "hex"];
<commit_msg>docs(utils): Update documentation<commit_after>//! Various utils to work with osci.
use std::io;
use std::fs::File;
use std::path::Path;
use memory::Memory;
use loader::{hexloader, rawloader, LoadError, Result};

/// Turn a file into a memory.
///
/// `load_file` recognizes multiple file formats. A file type is recognized by its file extension and mapped to one of the implemented loaders.
///
/// - “.raw”, “.bin”, “.img” or no extension: `rawloader`
/// - “.hex”: `hexloader`
pub fn load_file(filename: &Path) -> Result<Box<Memory>> {
    let mut file = File::open(filename)?;
    match Path::new(filename).extension().and_then(|ext| ext.to_str()) {
        Some("img") | Some("bin") | Some("raw") | None => rawloader::load_with_seek(&mut file),
        Some("hex") => hexloader::load(&mut file),
        ext => Err(LoadError::from_message(format!(
            "Unknown file extension: {:?}",
            ext
        ))),
    }
}

/// List of formats supported by `load_file`.
///
/// The list contains file extensions that are recognized by `load_file`.
pub static SUPPORTED_FORMATS: [&str; 4] = ["img", "bin", "raw", "hex"];
<|endoftext|>


<commit_before>use io::prelude::*;
use io;
use core::cmp;

pub trait ReadSeek: Read + Seek {}
impl<T> ReadSeek for T where T: Read + Seek {}

pub trait ReadWriteSeek: Read + Write + Seek {}
impl<T> ReadWriteSeek for T where T: Read + Write + Seek {}

const BUF_SIZE: usize = 512;

pub struct BufStream<T: Read+Write+Seek>  {
    inner: T,
    buf: [u8; BUF_SIZE],
    len: usize,
    pos: usize,
    write: bool,
}

/// The BufStream struct adds buffering to underlying file or device.
///
/// It's basically composition of BufReader and BufWritter.
impl<T: Read+Write+Seek> BufStream<T> {
    /// Creates new BufStream object for given stream.
    pub fn new(inner: T) -> Self {
        BufStream::<T> {
            inner,
            buf: [0; BUF_SIZE],
            pos: 0,
            len: 0,
            write: false,
        }
    }

    fn flush_buf(&mut self) -> io::Result<()> {
        if self.write {
            self.inner.write_all(&self.buf[..self.pos])?;
            self.pos = 0;
        }
        Ok(())
    }

    fn make_reader(&mut self) -> io::Result<()> {
        if self.write {
            self.flush_buf()?;
            self.write = false;
            self.len = 0;
            self.pos = 0;
        }
        Ok(())
    }

    fn make_writter(&mut self) -> io::Result<()> {
        if !self.write {
            self.inner.seek(io::SeekFrom::Current(-(self.len as i64 - self.pos as i64)))?;
            self.write = true;
            self.len = 0;
            self.pos = 0;
        }
        Ok(())
    }
}

impl<T: Read+Write+Seek> BufRead for BufStream<T> {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        self.make_reader()?;
        if self.pos >= self.len {
            self.len = self.inner.read(&mut self.buf)?;
            self.pos = 0;
        }
        Ok(&self.buf[self.pos..self.len])
    }

    fn consume(&mut self, amt: usize) {
        self.pos = cmp::min(self.pos + amt, self.len);
    }
}

impl<T: Read+Write+Seek> Read for BufStream<T> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        // Make sure we are in read mode
        self.make_reader()?;
        // Check if this read is bigger than buffer size
        if self.pos == self.len && buf.len() >= BUF_SIZE {
            return self.inner.read(buf);
        }
        let nread = {
            let mut rem = self.fill_buf()?;
            rem.read(buf)?
        };
        self.consume(nread);
        Ok(nread)
    }
}

impl<T: Read+Write+Seek> Write for BufStream<T> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        // Make sure we are in write mode
        self.make_writter()?;
        if self.pos + buf.len() > BUF_SIZE {
            self.flush_buf()?;
            if buf.len() >= BUF_SIZE {
                return self.inner.write(buf);
            }
        }
        let written = (&mut self.buf[self.pos..]).write(buf)?;
        self.pos += written;
        Ok(written)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.flush_buf()?;
        self.inner.flush()
    }
}

impl<T: Read+Write+Seek> Seek for BufStream<T> {
    fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
        self.flush_buf()?;
        let new_pos = match pos {
            io::SeekFrom::Current(x) => io::SeekFrom::Current(x - (self.len as i64 - self.pos as i64)),
            _ => pos,
        };
        self.pos = 0;
        self.len = 0;
        self.inner.seek(new_pos)
    }
}

impl<T: Read+Write+Seek> Drop for BufStream<T> {
    fn drop(&mut self) {
        if let Err(err) = self.flush() {
            error!("flush failed {}", err);
        }
    }
}
<commit_msg>Remove ReadSeek and ReadWriteSeek traits duplicated definition<commit_after>use io::prelude::*;
use io;
use core::cmp;

const BUF_SIZE: usize = 512;

pub struct BufStream<T: Read+Write+Seek>  {
    inner: T,
    buf: [u8; BUF_SIZE],
    len: usize,
    pos: usize,
    write: bool,
}

/// The BufStream struct adds buffering to underlying file or device.
///
/// It's basically composition of BufReader and BufWritter.
impl<T: Read+Write+Seek> BufStream<T> {
    /// Creates new BufStream object for given stream.
    pub fn new(inner: T) -> Self {
        BufStream::<T> {
            inner,
            buf: [0; BUF_SIZE],
            pos: 0,
            len: 0,
            write: false,
        }
    }

    fn flush_buf(&mut self) -> io::Result<()> {
        if self.write {
            self.inner.write_all(&self.buf[..self.pos])?;
            self.pos = 0;
        }
        Ok(())
    }

    fn make_reader(&mut self) -> io::Result<()> {
        if self.write {
            self.flush_buf()?;
            self.write = false;
            self.len = 0;
            self.pos = 0;
        }
        Ok(())
    }

    fn make_writter(&mut self) -> io::Result<()> {
        if !self.write {
            self.inner.seek(io::SeekFrom::Current(-(self.len as i64 - self.pos as i64)))?;
            self.write = true;
            self.len = 0;
            self.pos = 0;
        }
        Ok(())
    }
}

impl<T: Read+Write+Seek> BufRead for BufStream<T> {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        self.make_reader()?;
        if self.pos >= self.len {
            self.len = self.inner.read(&mut self.buf)?;
            self.pos = 0;
        }
        Ok(&self.buf[self.pos..self.len])
    }

    fn consume(&mut self, amt: usize) {
        self.pos = cmp::min(self.pos + amt, self.len);
    }
}

impl<T: Read+Write+Seek> Read for BufStream<T> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        // Make sure we are in read mode
        self.make_reader()?;
        // Check if this read is bigger than buffer size
        if self.pos == self.len && buf.len() >= BUF_SIZE {
            return self.inner.read(buf);
        }
        let nread = {
            let mut rem = self.fill_buf()?;
            rem.read(buf)?
        };
        self.consume(nread);
        Ok(nread)
    }
}

impl<T: Read+Write+Seek> Write for BufStream<T> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        // Make sure we are in write mode
        self.make_writter()?;
        if self.pos + buf.len() > BUF_SIZE {
            self.flush_buf()?;
            if buf.len() >= BUF_SIZE {
                return self.inner.write(buf);
            }
        }
        let written = (&mut self.buf[self.pos..]).write(buf)?;
        self.pos += written;
        Ok(written)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.flush_buf()?;
        self.inner.flush()
    }
}

impl<T: Read+Write+Seek> Seek for BufStream<T> {
    fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
        self.flush_buf()?;
        let new_pos = match pos {
            io::SeekFrom::Current(x) => io::SeekFrom::Current(x - (self.len as i64 - self.pos as i64)),
            _ => pos,
        };
        self.pos = 0;
        self.len = 0;
        self.inner.seek(new_pos)
    }
}

impl<T: Read+Write+Seek> Drop for BufStream<T> {
    fn drop(&mut self) {
        if let Err(err) = self.flush() {
            error!("flush failed {}", err);
        }
    }
}
<|endoftext|>


<commit_before>use std::{mem};

use num::{BigInt, One};
use num::bigint::{Sign};

use deserializer::{DeserializationError, DeserializationResult};

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ObjectIdentifier {
    pub parts: Vec<u32>
}

impl ObjectIdentifier {
    pub fn new(oid: Vec<u32>) -> Option<ObjectIdentifier> {
        if oid.len() < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
            return None;
        }

        return Some(ObjectIdentifier{
            parts: oid,
        });
    }
}

fn _int_length(v: i64) -> usize {
    let mut num_bytes = 1;
    let mut i = v;

    while i > 127 || i < -128 {
        num_bytes += 1;
        i >>= 8;
    }
    return num_bytes;
}

pub trait Integer {
    fn encode(&self) -> Vec<u8>;
    fn decode(Vec<u8>) -> DeserializationResult<Self>;
}

macro_rules! primitive_integer {
    ($Int:ident) => {
        impl Integer for $Int {
            fn encode(&self) -> Vec<u8> {
                let n = _int_length(*self as i64);
                let mut result = Vec::with_capacity(n);
                for i in (1..n+1).rev() {
                    result.push((self >> ((i - 1) * 8)) as u8);
                }
                return result;
            }

            fn decode(data: Vec<u8>) -> DeserializationResult<$Int> {
                if data.len() > mem::size_of::<$Int>() {
                    return Err(DeserializationError::IntegerOverflow);
                }
                let mut ret = 0;
                for b in data.iter() {
                    ret <<= 8;
                    ret |= *b as i64;
                }
                // Shift up and down in order to sign extend the result.
                ret <<= 64 - data.len() * 8;
                ret >>= 64 - data.len() * 8;
                return Ok(ret as $Int);
            }
        }
    }
}

primitive_integer!(i8);
primitive_integer!(i32);
primitive_integer!(i64);

impl Integer for BigInt {
    fn encode(&self) -> Vec<u8> {
        // TODO: allocating the bytes to get the sign is silly.
        let (sign, _) = self.to_bytes_be();
        match sign {
            Sign::Plus => {
                let (_, mut bytes) = self.to_bytes_be();
                if bytes[0] & 0x80 != 0 {
                    // If the data has a leading 0x80, pad with a zero-byte.
                    bytes.insert(0, 0);
                }
                return bytes;
            },
            Sign::NoSign => {
                return b"\x00".to_vec();
            },
            Sign::Minus => {
                // Convert negative numbers to two's-complement by subtracting one and inverting.
                let n_minus_1 = -self - BigInt::one();
                let (_, mut bytes) = n_minus_1.to_bytes_be();
                // TODO: rewrite this in-place.
                bytes = bytes.iter().map(|b| b ^ 0xff).collect();
                if bytes[0] & 0x80 == 0 {
                    bytes.insert(0, 0xff);
                }
                return bytes;
            },
        }
    }

    fn decode(data: Vec<u8>) -> DeserializationResult<BigInt> {
        if data[0] & 0x80 == 0x80 {
            let inverse_bytes = data.iter().map(|b| !b).collect::<Vec<u8>>();
            return Ok(-(BigInt::from_bytes_be(Sign::Plus, &inverse_bytes[..]) + BigInt::one()));
        } else {
            return Ok(BigInt::from_bytes_be(Sign::Plus, &data[..]));
        }
    }
}

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

    #[test]
    fn test_object_identifier_new() {
        assert!(ObjectIdentifier::new(vec![]).is_none());
        assert!(ObjectIdentifier::new(vec![3, 10]).is_none());
        assert!(ObjectIdentifier::new(vec![1, 50]).is_none());
    }
}
<commit_msg>factor out a var so it has a name<commit_after>use std::{mem};

use num::{BigInt, One};
use num::bigint::{Sign};

use deserializer::{DeserializationError, DeserializationResult};

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ObjectIdentifier {
    pub parts: Vec<u32>
}

impl ObjectIdentifier {
    pub fn new(oid: Vec<u32>) -> Option<ObjectIdentifier> {
        if oid.len() < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
            return None;
        }

        return Some(ObjectIdentifier{
            parts: oid,
        });
    }
}

fn _int_length(v: i64) -> usize {
    let mut num_bytes = 1;
    let mut i = v;

    while i > 127 || i < -128 {
        num_bytes += 1;
        i >>= 8;
    }
    return num_bytes;
}

pub trait Integer {
    fn encode(&self) -> Vec<u8>;
    fn decode(Vec<u8>) -> DeserializationResult<Self>;
}

macro_rules! primitive_integer {
    ($Int:ident) => {
        impl Integer for $Int {
            fn encode(&self) -> Vec<u8> {
                let n = _int_length(*self as i64);
                let mut result = Vec::with_capacity(n);
                for i in (1..n+1).rev() {
                    result.push((self >> ((i - 1) * 8)) as u8);
                }
                return result;
            }

            fn decode(data: Vec<u8>) -> DeserializationResult<$Int> {
                if data.len() > mem::size_of::<$Int>() {
                    return Err(DeserializationError::IntegerOverflow);
                }
                let mut ret = 0;
                for b in data.iter() {
                    ret <<= 8;
                    ret |= *b as i64;
                }
                // Shift up and down in order to sign extend the result.
                ret <<= 64 - data.len() * 8;
                ret >>= 64 - data.len() * 8;
                return Ok(ret as $Int);
            }
        }
    }
}

primitive_integer!(i8);
primitive_integer!(i32);
primitive_integer!(i64);

impl Integer for BigInt {
    fn encode(&self) -> Vec<u8> {
        // TODO: allocating the bytes to get the sign is silly.
        let (sign, _) = self.to_bytes_be();
        match sign {
            Sign::Plus => {
                let (_, mut bytes) = self.to_bytes_be();
                if bytes[0] & 0x80 != 0 {
                    // If the data has a leading 0x80, pad with a zero-byte.
                    bytes.insert(0, 0);
                }
                return bytes;
            },
            Sign::NoSign => {
                return b"\x00".to_vec();
            },
            Sign::Minus => {
                // Convert negative numbers to two's-complement by subtracting one and inverting.
                let n_minus_1 = -self - BigInt::one();
                let (_, mut bytes) = n_minus_1.to_bytes_be();
                // TODO: rewrite this in-place.
                bytes = bytes.iter().map(|b| b ^ 0xff).collect();
                if bytes[0] & 0x80 == 0 {
                    bytes.insert(0, 0xff);
                }
                return bytes;
            },
        }
    }

    fn decode(data: Vec<u8>) -> DeserializationResult<BigInt> {
        if data[0] & 0x80 == 0x80 {
            let inverse_bytes = data.iter().map(|b| !b).collect::<Vec<u8>>();
            let n_minus_1 = BigInt::from_bytes_be(Sign::Plus, &inverse_bytes[..]);
            return Ok(-(n_minus_1 + BigInt::one()));
        } else {
            return Ok(BigInt::from_bytes_be(Sign::Plus, &data[..]));
        }
    }
}

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

    #[test]
    fn test_object_identifier_new() {
        assert!(ObjectIdentifier::new(vec![]).is_none());
        assert!(ObjectIdentifier::new(vec![3, 10]).is_none());
        assert!(ObjectIdentifier::new(vec![1, 50]).is_none());
    }
}
<|endoftext|>


<commit_before>use std::path::Path;
use std::io::{Error,ErrorKind};

pub fn full_name_from_path(path: &Path, is_dir: bool) -> String {
    let name = path.to_string_lossy().into_owned();
    if is_dir {
        name + "/"
    } else {
        name
    }
}

pub fn short_name_from_path(path: &Path, is_dir: bool) -> String {
    match path.file_name() {
        Some(file_name) => {
            let name = file_name.to_string_lossy().into_owned();
            if is_dir {
                name + "/"
            } else {
                name
            }
        },
        None => full_name_from_path(path, is_dir)
    }
}

pub fn describe_io_error(error: Error) -> String {
    match error.kind() {
        ErrorKind::NotFound => "File not found",
        ErrorKind::PermissionDenied => "Permission denied",
        ErrorKind::TimedOut => "Timed out",
        ErrorKind::Interrupted => "Interrupted",
        _ => "Unrecognized error"
    }.to_string()
}

pub trait SizeDisplay {
    fn as_size_display(&self) -> String;
}

const KILO: f64 = 1e3 as f64;
const MEGA: f64 = 1e6 as f64;
const GIGA: f64 = 1e9 as f64;

const KILO_CUTOFF: u64 = (0.6 * KILO) as u64;
const MEGA_CUTOFF: u64 = (1.4 * MEGA) as u64;
const GIGA_CUTOFF: u64 = (1.4 * GIGA) as u64;

impl SizeDisplay for u64 {
    fn as_size_display(&self) -> String {
        if *self < KILO_CUTOFF {
            return format!("{} B", *self)
        }

        let (scaled, unit) = match *self {
            KILO_CUTOFF...MEGA_CUTOFF => (*self as f64 / KILO, "kB"),
            MEGA_CUTOFF...GIGA_CUTOFF => (*self as f64 / MEGA, "MB"),
            _ => (*self as f64 / GIGA, "GB"),
        };
        format!("{:.2} {}", scaled, unit)
    }
}

<commit_msg>Add tests for utils module<commit_after>use std::path::Path;
use std::io::{Error,ErrorKind};

pub fn full_name_from_path(path: &Path, is_dir: bool) -> String {
    let name = path.to_string_lossy().into_owned();
    if is_dir {
        name + "/"
    } else {
        name
    }
}

pub fn short_name_from_path(path: &Path, is_dir: bool) -> String {
    match path.file_name() {
        Some(file_name) => {
            let name = file_name.to_string_lossy().into_owned();
            if is_dir {
                name + "/"
            } else {
                name
            }
        },
        None => full_name_from_path(path, is_dir)
    }
}

pub fn describe_io_error(error: Error) -> String {
    match error.kind() {
        ErrorKind::NotFound => "File not found",
        ErrorKind::PermissionDenied => "Permission denied",
        ErrorKind::TimedOut => "Timed out",
        ErrorKind::Interrupted => "Interrupted",
        _ => "Unrecognized error"
    }.to_string()
}

pub trait SizeDisplay {
    fn as_size_display(&self) -> String;
}

const KILO: f64 = 1e3 as f64;
const MEGA: f64 = 1e6 as f64;
const GIGA: f64 = 1e9 as f64;

const KILO_CUTOFF: u64 = (0.6 * KILO) as u64;
const MEGA_CUTOFF: u64 = (1.4 * MEGA) as u64;
const GIGA_CUTOFF: u64 = (1.4 * GIGA) as u64;

impl SizeDisplay for u64 {
    fn as_size_display(&self) -> String {
        if *self < KILO_CUTOFF {
            return format!("{} B", *self)
        }

        let (scaled, unit) = match *self {
            KILO_CUTOFF...MEGA_CUTOFF => (*self as f64 / KILO, "kB"),
            MEGA_CUTOFF...GIGA_CUTOFF => (*self as f64 / MEGA, "MB"),
            _ => (*self as f64 / GIGA, "GB"),
        };
        format!("{:.2} {}", scaled, unit)
    }
}

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

    #[test]
    fn it_can_convert_a_path_to_a_string() {
        let path = Path::new("/path/to");

        assert_eq!(full_name_from_path(&path, false), "/path/to");
        assert_eq!(full_name_from_path(&path, true), "/path/to/");
    }

    #[test]
    fn it_can_convert_a_filename_to_a_string() {
        let path = Path::new("/path/to");

        assert_eq!(short_name_from_path(&path, false), "to");
        assert_eq!(short_name_from_path(&path, true), "to/");
    }

    #[test]
    fn it_can_format_sizes() {
        assert_eq!(          1.as_size_display(),       "1 B");
        assert_eq!(        345.as_size_display(),     "345 B");
        assert_eq!(       1000.as_size_display(),   "1.00 kB");
        assert_eq!(       1100.as_size_display(),   "1.10 kB");
        assert_eq!(      11000.as_size_display(),  "11.00 kB");
        assert_eq!(123_456_789.as_size_display(), "123.46 MB");
        assert_eq!(123_452_000.as_size_display(), "123.45 MB");

        assert_eq!(    867_000_000_000.as_size_display(),    "867.00 GB");
        assert_eq!(867_000_000_000_000.as_size_display(), "867000.00 GB");
    }
}
<|endoftext|>


<commit_before>
use ::std;
use ::std::ffi::{OsString, OsStr};
use ::std::os::windows::ffi::{OsStringExt, OsStrExt};

use ::WCString;
use ::NoNulError;
use ::error;

/// Representation of a borrowed Win32 style "wide" string.
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct WCStr {
    inner: [u16]
}

impl WCStr {
    /// Create a ```&WCStr``` from a raw pointer and a length.
    ///
    /// This function is unsafe for the reasons mentioned below.
    ///
    /// This function assumes that the pointer passed in has these properties:
    ///
    /// * It is not null.
    /// * It is a valid pointer.
    /// * It points to an array of ```u16```'s that does not contain any ```nul``` values.
    /// * It points to an array of ```u16```'s that is terminated with a ```nul``` at exactly the offset "```len```".
    ///
    /// This function will assert/panic when ```nul``` is not found at offset "```len```".
    ///
    /// The lifetime of the ```&WCStr``` returned from this function is not guranteed to be correct and
    /// it is up to the caller to determine the appropriate lifetime.
    ///
    /// # ```from_raw_parts()``` example
    ///
    ///     use wcstr::WCStr;
    ///     static a : &'static [u16] = &[116u16, 101u16, 115u16, 116u16, 0];
    ///     let s = unsafe { WCStr::from_raw_parts(a.as_ptr(), a.len() - 1) };
    ///     assert!(s.len() == (a.len() - 1));
    pub unsafe fn from_raw_parts<'a>(ptr: *const u16, len: usize) -> &'a WCStr {
        assert!(*ptr.offset(len as isize) == 0u16);
        std::mem::transmute(std::slice::from_raw_parts(ptr, len + 1))
    }

    /// Create a ```&WCStr``` from a slice of ```u16```'s.
    /// This function will scan the slice for ```nul``` and assume that ```nul``` terminates the string.
    /// If no ```nul``` is found in the slice, it will return ```Err(NoNulError(None))```
    /// # ```frm_slice_with_nul()``` example
    ///
    ///     use wcstr::WCStr;
    ///     static a : &'static [u16] = &[116u16, 101u16, 115u16, 116u16, 0];
    ///     let s = WCStr::from_slice_with_nul(a).unwrap();
    ///     assert!(s.len() == (a.len() - 1));
    pub fn from_slice_with_nul<'a>(slice: &'a [u16]) -> Result<&'a WCStr, NoNulError> {
        match slice.iter().position(|x| *x == 0) {
            None => Err(error::no_nul(None)),
            Some(i) => Ok(unsafe { std::mem::transmute(&slice[..i + 1]) }),
        }
    }

    /// length of the string in u16 units
    pub fn len(&self) -> usize {
        self.inner.len() - 1
    }

    /// Return a raw pointer to this "wide" string.
    ///
    ///  * The pointer remains valid only as long as this string is valid.
    ///  * The pointer points to a contiguous region of memory terminated with ```nul```.
    pub fn as_ptr(&self) -> *const u16 {
        self.inner.as_ptr()
    }

    /// Return this "wide" string as a slice of ```u16```s without a ```nul``` terminator.
    pub fn to_slice(&self) -> &[u16] {
        &self.inner[..self.len()]
    }

    /// Return this "wide" string as a slice of ```u16```s with a ```nul``` terminator.
    pub fn to_slice_with_nul(&self) -> &[u16] {
        &self.inner
    }

    /// Convert this "wide" string to a ```String``` by using ```String::from_utf16```
    pub fn to_string(&self) -> Result<String, std::string::FromUtf16Error> {
        String::from_utf16(self.to_slice())
    }

    /// Convert this "wide" string to a ```String``` by using ```String::from_utf16_lossy```
    pub fn to_string_lossy(&self) -> String {
        String::from_utf16_lossy(self.to_slice())
    }

    /// Convert this "wide" string to an ```OsString``` by using ```OsString::from_wide```
    pub fn to_os_string(&self) -> OsString {
        OsString::from_wide(self.to_slice())
    }

    /// starts with a string.
    ///
    /// # ```starts_with()``` example
    ///
    ///     use wcstr::{WCStr, WCString};
    ///     let s = WCString::from_str("abcefg").unwrap();
    ///     let t = WCString::from_str("abc").unwrap();
    ///     let u = WCString::from_str("efg").unwrap();
    ///     let v = WCString::from_str("abcefgh").unwrap();
    ///     assert!(s.starts_with(t));
    ///     assert!(!s.starts_with(u));
    ///     assert!(!s.starts_with(v));
    pub fn starts_with<T>(&self, s: T) -> bool
        where T: AsRef<WCStr> {
        let s = s.as_ref();
        let len = self.len();
        if s.len() > len {
            return false;
        }

        self.to_slice().iter().zip(s.to_slice().iter()).all(|(&a, &b)| a == b)
    }

    /// starts with a string.
    ///
    /// # ```starts_with()``` example
    ///
    ///     use wcstr::{WCStr, WCString};
    ///     let s = WCString::from_str("abcefg").unwrap();
    ///     assert!(s.starts_with_str("abc"));
    ///     assert!(!s.starts_with_str("efg"));
    ///     assert!(!s.starts_with_str("abcefgh"));
    pub fn starts_with_str<T>(&self, s: T) -> bool
        where T: AsRef<OsStr> {
        let s = s.as_ref();
        let mut s_iter = s.encode_wide();
        let mut t_iter = self.to_slice().iter();

        while let Some(a) = s_iter.next() {
            match t_iter.next() {
                Some(&b) if a == b => (),
                _ => return false,
            }
        }

        true
    }
}

impl std::fmt::Debug for WCStr {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        try!(write!(f, "\""));
        for &w in self.to_slice().iter() {
            if w < 0xD800 || w >= 0xE000 {
                for c in std::char::from_u32(w as u32).unwrap().escape_default() {
                    use std::fmt::Write;
                    try!(f.write_char(c));
                }
            }
            else {
                try!(write!(f, "\\u{{{:X}}}", w));
            }
        }
        write!(f, "\"")
    }
}

impl AsRef<WCStr> for WCStr {
    fn as_ref(&self) -> &WCStr {
        self
    }
}

impl AsRef<[u16]> for WCStr {
    fn as_ref(&self) -> &[u16] {
        &self.inner[..self.len()]
    }
}

impl ToOwned for WCStr {
    type Owned = WCString;
    fn to_owned(&self) -> WCString {
        unsafe {
            WCString::from_vec_with_nul_unchecked(self.inner.to_owned())
        }
    }
}

<commit_msg>fix typo<commit_after>
use ::std;
use ::std::ffi::{OsString, OsStr};
use ::std::os::windows::ffi::{OsStringExt, OsStrExt};

use ::WCString;
use ::NoNulError;
use ::error;

/// Representation of a borrowed Win32 style "wide" string.
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct WCStr {
    inner: [u16]
}

impl WCStr {
    /// Create a ```&WCStr``` from a raw pointer and a length.
    ///
    /// This function is unsafe for the reasons mentioned below.
    ///
    /// This function assumes that the pointer passed in has these properties:
    ///
    /// * It is not null.
    /// * It is a valid pointer.
    /// * It points to an array of ```u16```'s that does not contain any ```nul``` values.
    /// * It points to an array of ```u16```'s that is terminated with a ```nul``` at exactly the offset "```len```".
    ///
    /// This function will assert/panic when ```nul``` is not found at offset "```len```".
    ///
    /// The lifetime of the ```&WCStr``` returned from this function is not guranteed to be correct and
    /// it is up to the caller to determine the appropriate lifetime.
    ///
    /// # ```from_raw_parts()``` example
    ///
    ///     use wcstr::WCStr;
    ///     static a : &'static [u16] = &[116u16, 101u16, 115u16, 116u16, 0];
    ///     let s = unsafe { WCStr::from_raw_parts(a.as_ptr(), a.len() - 1) };
    ///     assert!(s.len() == (a.len() - 1));
    pub unsafe fn from_raw_parts<'a>(ptr: *const u16, len: usize) -> &'a WCStr {
        assert!(*ptr.offset(len as isize) == 0u16);
        std::mem::transmute(std::slice::from_raw_parts(ptr, len + 1))
    }

    /// Create a ```&WCStr``` from a slice of ```u16```'s.
    /// This function will scan the slice for ```nul``` and assume that ```nul``` terminates the string.
    /// If no ```nul``` is found in the slice, it will return ```Err(NoNulError(None))```
    /// # ```frm_slice_with_nul()``` example
    ///
    ///     use wcstr::WCStr;
    ///     static a : &'static [u16] = &[116u16, 101u16, 115u16, 116u16, 0];
    ///     let s = WCStr::from_slice_with_nul(a).unwrap();
    ///     assert!(s.len() == (a.len() - 1));
    pub fn from_slice_with_nul<'a>(slice: &'a [u16]) -> Result<&'a WCStr, NoNulError> {
        match slice.iter().position(|x| *x == 0) {
            None => Err(error::no_nul(None)),
            Some(i) => Ok(unsafe { std::mem::transmute(&slice[..i + 1]) }),
        }
    }

    /// length of the string in u16 units
    pub fn len(&self) -> usize {
        self.inner.len() - 1
    }

    /// Return a raw pointer to this "wide" string.
    ///
    ///  * The pointer remains valid only as long as this string is valid.
    ///  * The pointer points to a contiguous region of memory terminated with ```nul```.
    pub fn as_ptr(&self) -> *const u16 {
        self.inner.as_ptr()
    }

    /// Return this "wide" string as a slice of ```u16```s without a ```nul``` terminator.
    pub fn to_slice(&self) -> &[u16] {
        &self.inner[..self.len()]
    }

    /// Return this "wide" string as a slice of ```u16```s with a ```nul``` terminator.
    pub fn to_slice_with_nul(&self) -> &[u16] {
        &self.inner
    }

    /// Convert this "wide" string to a ```String``` by using ```String::from_utf16```
    pub fn to_string(&self) -> Result<String, std::string::FromUtf16Error> {
        String::from_utf16(self.to_slice())
    }

    /// Convert this "wide" string to a ```String``` by using ```String::from_utf16_lossy```
    pub fn to_string_lossy(&self) -> String {
        String::from_utf16_lossy(self.to_slice())
    }

    /// Convert this "wide" string to an ```OsString``` by using ```OsString::from_wide```
    pub fn to_os_string(&self) -> OsString {
        OsString::from_wide(self.to_slice())
    }

    /// starts with a string.
    ///
    /// # ```starts_with()``` example
    ///
    ///     use wcstr::{WCStr, WCString};
    ///     let s = WCString::from_str("abcefg").unwrap();
    ///     let t = WCString::from_str("abc").unwrap();
    ///     let u = WCString::from_str("efg").unwrap();
    ///     let v = WCString::from_str("abcefgh").unwrap();
    ///     assert!(s.starts_with(t));
    ///     assert!(!s.starts_with(u));
    ///     assert!(!s.starts_with(v));
    pub fn starts_with<T>(&self, s: T) -> bool
        where T: AsRef<WCStr> {
        let s = s.as_ref();
        let len = self.len();
        if s.len() > len {
            return false;
        }

        self.to_slice().iter().zip(s.to_slice().iter()).all(|(&a, &b)| a == b)
    }

    /// starts with a string.
    ///
    /// # ```starts_with_str()``` example
    ///
    ///     use wcstr::{WCStr, WCString};
    ///     let s = WCString::from_str("abcefg").unwrap();
    ///     assert!(s.starts_with_str("abc"));
    ///     assert!(!s.starts_with_str("efg"));
    ///     assert!(!s.starts_with_str("abcefgh"));
    pub fn starts_with_str<T>(&self, s: T) -> bool
        where T: AsRef<OsStr> {
        let s = s.as_ref();
        let mut s_iter = s.encode_wide();
        let mut t_iter = self.to_slice().iter();

        while let Some(a) = s_iter.next() {
            match t_iter.next() {
                Some(&b) if a == b => (),
                _ => return false,
            }
        }

        true
    }
}

impl std::fmt::Debug for WCStr {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        try!(write!(f, "\""));
        for &w in self.to_slice().iter() {
            if w < 0xD800 || w >= 0xE000 {
                for c in std::char::from_u32(w as u32).unwrap().escape_default() {
                    use std::fmt::Write;
                    try!(f.write_char(c));
                }
            }
            else {
                try!(write!(f, "\\u{{{:X}}}", w));
            }
        }
        write!(f, "\"")
    }
}

impl AsRef<WCStr> for WCStr {
    fn as_ref(&self) -> &WCStr {
        self
    }
}

impl AsRef<[u16]> for WCStr {
    fn as_ref(&self) -> &[u16] {
        &self.inner[..self.len()]
    }
}

impl ToOwned for WCStr {
    type Owned = WCString;
    fn to_owned(&self) -> WCString {
        unsafe {
            WCString::from_vec_with_nul_unchecked(self.inner.to_owned())
        }
    }
}

<|endoftext|>