<commit_before>#![deny(clippy::all, clippy::pedantic)]

use std::fmt::Display;
use thiserror::Error;

fn assert<T: Display>(expected: &str, value: T) {
    assert_eq!(expected, value.to_string());
}

#[test]
fn test_braced() {
    #[derive(Error, Debug)]
    #[error("braced error: {msg}")]
    struct Error {
        msg: String,
    }

    let msg = "T".to_owned();
    assert("braced error: T", Error { msg });
}

#[test]
fn test_braced_unused() {
    #[derive(Error, Debug)]
    #[error("braced error")]
    struct Error {
        extra: usize,
    }

    assert("braced error", Error { extra: 0 });
}

#[test]
fn test_tuple() {
    #[derive(Error, Debug)]
    #[error("tuple error: {0}")]
    struct Error(usize);

    assert("tuple error: 0", Error(0));
}

#[test]
fn test_unit() {
    #[derive(Error, Debug)]
    #[error("unit error")]
    struct Error;

    assert("unit error", Error);
}

#[test]
fn test_enum() {
    #[derive(Error, Debug)]
    enum Error {
        #[error("braced error: {id}")]
        Braced { id: usize },
        #[error("tuple error: {0}")]
        Tuple(usize),
        #[error("unit error")]
        Unit,
    }

    assert("braced error: 0", Error::Braced { id: 0 });
    assert("tuple error: 0", Error::Tuple(0));
    assert("unit error", Error::Unit);
}

#[test]
fn test_constants() {
    #[derive(Error, Debug)]
    #[error("{MSG}: {id:?} (code {CODE:?})")]
    struct Error {
        id: &'static str,
    }

    const MSG: &str = "failed to do";
    const CODE: usize = 9;

    assert("failed to do: \"\" (code 9)", Error { id: "" });
}

#[test]
fn test_inherit() {
    #[derive(Error, Debug)]
    #[error("{0}")]
    enum Error {
        Some(&'static str),
        #[error("other error")]
        Other(&'static str),
    }

    assert("some error", Error::Some("some error"));
    assert("other error", Error::Other("..."));
}

#[test]
fn test_brace_escape() {
    #[derive(Error, Debug)]
    #[error("fn main() {{}}")]
    struct Error;

    assert("fn main() {}", Error);
}

#[test]
fn test_expr() {
    #[derive(Error, Debug)]
    #[error("1 + 1 = {}", 1 + 1)]
    struct Error;
    assert("1 + 1 = 2", Error);
}

#[test]
fn test_nested() {
    #[derive(Error, Debug)]
    #[error("!bool = {}", not(.0))]
    struct Error(bool);

    #[allow(clippy::trivially_copy_pass_by_ref)]
    fn not(bool: &bool) -> bool {
        !*bool
    }

    assert("!bool = false", Error(true));
}

#[test]
fn test_match() {
    #[derive(Error, Debug)]
    #[error("{}: {0}", match .1 {
        Some(n) => format!("error occurred with {}", n),
        None => "there was an empty error".to_owned(),
    })]
    struct Error(String, Option<usize>);

    assert(
        "error occurred with 1: ...",
        Error("...".to_owned(), Some(1)),
    );
    assert(
        "there was an empty error: ...",
        Error("...".to_owned(), None),
    );
}

#[test]
fn test_void() {
    #[allow(clippy::empty_enum)]
    #[derive(Error, Debug)]
    #[error("...")]
    pub enum Error {}

    let _: Error;
}

#[test]
fn test_mixed() {
    #[derive(Error, Debug)]
    #[error("a={a} :: b={} :: c={c} :: d={d}", 1, c = 2, d = 3)]
    struct Error {
        a: usize,
        d: usize,
    }

    assert("a=0 :: b=1 :: c=2 :: d=3", Error { a: 0, d: 0 });
}

#[test]
fn test_ints() {
    #[derive(Error, Debug)]
    enum Error {
        #[error("error {0}")]
        Tuple(usize, usize),
        #[error("error {0}", '?')]
        Struct { v: usize },
    }

    assert("error 9", Error::Tuple(9, 0));
    assert("error ?", Error::Struct { v: 0 });
}

#[test]
fn test_trailing_comma() {
    #[derive(Error, Debug)]
    #[error(
        "error {0}",
    )]
    #[rustfmt::skip]
    struct Error(char);

    assert("error ?", Error('?'));
}

#[test]
fn test_field() {
    #[derive(Debug)]
    struct Inner {
        data: usize,
    }

    #[derive(Error, Debug)]
    #[error("{}", .0.data)]
    struct Error(Inner);

    assert("0", Error(Inner { data: 0 }));
}

#[test]
fn test_macro_rules() {
    // Regression test for https://github.com/dtolnay/thiserror/issues/86

    macro_rules! decl_error {
        ($variant:ident($value:ident)) => {
            #[derive(Debug, Error)]
            pub enum Error0 {
                #[error("{0:?}")]
                $variant($value),
            }

            #[derive(Debug, Error)]
            #[error("{0:?}")]
            pub enum Error1 {
                $variant($value),
            }
        };
    }

    decl_error!(Repro(u8));

    assert("0", Error0::Repro(0));
    assert("0", Error1::Repro(0));
}

#[test]
fn test_raw() {
    #[derive(Error, Debug)]
    #[error("braced raw error: {r#fn}")]
    struct Error {
        r#fn: &'static str,
    }

    assert("braced raw error: T", Error { r#fn: "T" });
}

#[test]
fn test_raw_enum() {
    #[derive(Error, Debug)]
    enum Error {
        #[error("braced raw error: {r#fn}")]
        Braced { r#fn: &'static str },
    }

    assert("braced raw error: T", Error::Braced { r#fn: "T" });
}

#[test]
fn test_raw_conflict() {
    #[derive(Error, Debug)]
    enum Error {
        #[error("braced raw error: {r#func}, {func}", func = "U")]
        Braced { r#func: &'static str },
    }

    assert("braced raw error: T, U", Error::Braced { r#func: "T" });
}
<commit_msg>Add test of keyword fmt argument<commit_after>#![deny(clippy::all, clippy::pedantic)]

use std::fmt::Display;
use thiserror::Error;

fn assert<T: Display>(expected: &str, value: T) {
    assert_eq!(expected, value.to_string());
}

#[test]
fn test_braced() {
    #[derive(Error, Debug)]
    #[error("braced error: {msg}")]
    struct Error {
        msg: String,
    }

    let msg = "T".to_owned();
    assert("braced error: T", Error { msg });
}

#[test]
fn test_braced_unused() {
    #[derive(Error, Debug)]
    #[error("braced error")]
    struct Error {
        extra: usize,
    }

    assert("braced error", Error { extra: 0 });
}

#[test]
fn test_tuple() {
    #[derive(Error, Debug)]
    #[error("tuple error: {0}")]
    struct Error(usize);

    assert("tuple error: 0", Error(0));
}

#[test]
fn test_unit() {
    #[derive(Error, Debug)]
    #[error("unit error")]
    struct Error;

    assert("unit error", Error);
}

#[test]
fn test_enum() {
    #[derive(Error, Debug)]
    enum Error {
        #[error("braced error: {id}")]
        Braced { id: usize },
        #[error("tuple error: {0}")]
        Tuple(usize),
        #[error("unit error")]
        Unit,
    }

    assert("braced error: 0", Error::Braced { id: 0 });
    assert("tuple error: 0", Error::Tuple(0));
    assert("unit error", Error::Unit);
}

#[test]
fn test_constants() {
    #[derive(Error, Debug)]
    #[error("{MSG}: {id:?} (code {CODE:?})")]
    struct Error {
        id: &'static str,
    }

    const MSG: &str = "failed to do";
    const CODE: usize = 9;

    assert("failed to do: \"\" (code 9)", Error { id: "" });
}

#[test]
fn test_inherit() {
    #[derive(Error, Debug)]
    #[error("{0}")]
    enum Error {
        Some(&'static str),
        #[error("other error")]
        Other(&'static str),
    }

    assert("some error", Error::Some("some error"));
    assert("other error", Error::Other("..."));
}

#[test]
fn test_brace_escape() {
    #[derive(Error, Debug)]
    #[error("fn main() {{}}")]
    struct Error;

    assert("fn main() {}", Error);
}

#[test]
fn test_expr() {
    #[derive(Error, Debug)]
    #[error("1 + 1 = {}", 1 + 1)]
    struct Error;
    assert("1 + 1 = 2", Error);
}

#[test]
fn test_nested() {
    #[derive(Error, Debug)]
    #[error("!bool = {}", not(.0))]
    struct Error(bool);

    #[allow(clippy::trivially_copy_pass_by_ref)]
    fn not(bool: &bool) -> bool {
        !*bool
    }

    assert("!bool = false", Error(true));
}

#[test]
fn test_match() {
    #[derive(Error, Debug)]
    #[error("{}: {0}", match .1 {
        Some(n) => format!("error occurred with {}", n),
        None => "there was an empty error".to_owned(),
    })]
    struct Error(String, Option<usize>);

    assert(
        "error occurred with 1: ...",
        Error("...".to_owned(), Some(1)),
    );
    assert(
        "there was an empty error: ...",
        Error("...".to_owned(), None),
    );
}

#[test]
fn test_void() {
    #[allow(clippy::empty_enum)]
    #[derive(Error, Debug)]
    #[error("...")]
    pub enum Error {}

    let _: Error;
}

#[test]
fn test_mixed() {
    #[derive(Error, Debug)]
    #[error("a={a} :: b={} :: c={c} :: d={d}", 1, c = 2, d = 3)]
    struct Error {
        a: usize,
        d: usize,
    }

    assert("a=0 :: b=1 :: c=2 :: d=3", Error { a: 0, d: 0 });
}

#[test]
fn test_ints() {
    #[derive(Error, Debug)]
    enum Error {
        #[error("error {0}")]
        Tuple(usize, usize),
        #[error("error {0}", '?')]
        Struct { v: usize },
    }

    assert("error 9", Error::Tuple(9, 0));
    assert("error ?", Error::Struct { v: 0 });
}

#[test]
fn test_trailing_comma() {
    #[derive(Error, Debug)]
    #[error(
        "error {0}",
    )]
    #[rustfmt::skip]
    struct Error(char);

    assert("error ?", Error('?'));
}

#[test]
fn test_field() {
    #[derive(Debug)]
    struct Inner {
        data: usize,
    }

    #[derive(Error, Debug)]
    #[error("{}", .0.data)]
    struct Error(Inner);

    assert("0", Error(Inner { data: 0 }));
}

#[test]
fn test_macro_rules() {
    // Regression test for https://github.com/dtolnay/thiserror/issues/86

    macro_rules! decl_error {
        ($variant:ident($value:ident)) => {
            #[derive(Debug, Error)]
            pub enum Error0 {
                #[error("{0:?}")]
                $variant($value),
            }

            #[derive(Debug, Error)]
            #[error("{0:?}")]
            pub enum Error1 {
                $variant($value),
            }
        };
    }

    decl_error!(Repro(u8));

    assert("0", Error0::Repro(0));
    assert("0", Error1::Repro(0));
}

#[test]
fn test_raw() {
    #[derive(Error, Debug)]
    #[error("braced raw error: {r#fn}")]
    struct Error {
        r#fn: &'static str,
    }

    assert("braced raw error: T", Error { r#fn: "T" });
}

#[test]
fn test_raw_enum() {
    #[derive(Error, Debug)]
    enum Error {
        #[error("braced raw error: {r#fn}")]
        Braced { r#fn: &'static str },
    }

    assert("braced raw error: T", Error::Braced { r#fn: "T" });
}

#[test]
fn test_raw_conflict() {
    #[derive(Error, Debug)]
    enum Error {
        #[error("braced raw error: {r#func}, {func}", func = "U")]
        Braced { r#func: &'static str },
    }

    assert("braced raw error: T, U", Error::Braced { r#func: "T" });
}

#[test]
fn test_keyword() {
    #[derive(Error, Debug)]
    #[error("error: {type}", type = 1)]
    struct Error;

    assert("error: 1", Error);
}
<|endoftext|>


<commit_before>use bytes::Bytes;
use common::stream_handler::StreamHandlerInternal;
use error;
use result;
use ErrorCode;
use Headers;

/// Synchrnous callback of incoming data
pub trait ServerStreamHandler: 'static {
    /// DATA frame received
    fn data_frame(&mut self, data: Bytes, end_stream: bool) -> result::Result<()>;
    /// Trailers HEADERS received
    fn trailers(&mut self, trailers: Headers) -> result::Result<()>;
    /// RST_STREAM frame received
    fn rst(&mut self, error_code: ErrorCode) -> result::Result<()>;
    /// Any other error
    fn error(&mut self, error: error::Error) -> result::Result<()>;
}

pub(crate) struct ServerStreamHandlerHolder(pub(crate) Box<ServerStreamHandler>);

impl StreamHandlerInternal for ServerStreamHandlerHolder {
    fn data_frame(&mut self, data: Bytes, end_stream: bool) -> result::Result<()> {
        self.0.data_frame(data, end_stream)
    }

    fn trailers(&mut self, trailers: Headers) -> result::Result<()> {
        self.0.trailers(trailers)
    }

    fn rst(mut self, error_code: ErrorCode) -> result::Result<()> {
        self.0.rst(error_code)
    }

    fn error(mut self, error: error::Error) -> result::Result<()> {
        self.0.error(error)
    }
}
<commit_msg>Easier to use ServerStreamHandler<commit_after>use bytes::Bytes;
use common::stream_handler::StreamHandlerInternal;
use error;
use result;
use ErrorCode;
use Headers;

/// Synchronous callback of incoming data
pub trait ServerStreamHandler: 'static {
    /// DATA frame received
    fn data_frame(&mut self, data: Bytes, end_stream: bool) -> result::Result<()>;
    /// Trailers HEADERS received
    fn trailers(&mut self, trailers: Headers) -> result::Result<()>;
    /// RST_STREAM frame received
    fn rst(&mut self, error_code: ErrorCode) -> result::Result<()> {
        self.error(error::Error::CodeError(error_code))
    }
    /// Any other error
    fn error(&mut self, error: error::Error) -> result::Result<()>;
}

pub(crate) struct ServerStreamHandlerHolder(pub(crate) Box<ServerStreamHandler>);

impl StreamHandlerInternal for ServerStreamHandlerHolder {
    fn data_frame(&mut self, data: Bytes, end_stream: bool) -> result::Result<()> {
        self.0.data_frame(data, end_stream)
    }

    fn trailers(&mut self, trailers: Headers) -> result::Result<()> {
        self.0.trailers(trailers)
    }

    fn rst(mut self, error_code: ErrorCode) -> result::Result<()> {
        self.0.rst(error_code)
    }

    fn error(mut self, error: error::Error) -> result::Result<()> {
        self.0.error(error)
    }
}
<|endoftext|>


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

#![cfg_attr(feature = "benchmarks", feature(test))]
#![allow(
clippy::if_same_then_else,
clippy::needless_bool,
clippy::needless_pass_by_value,
clippy::ptr_arg
)]

#[cfg(all(test, feature = "benchmarks"))]
extern crate test;

use super::Sample;
use serde_json;
use std::io::{Error as IOError, Read, Write};

#[derive(Debug)]
pub enum Error {
    Io(IOError),
    Json(serde_json::Error),
    DecodingFormat(String),
}

#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
enum ChromeTraceArrayEntries {
    Array(Vec<Sample>),
}

/// This serializes the samples into the [Chrome trace event format](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwiJlZmDguXYAhUD4GMKHVmEDqIQFggpMAA&url=https%3A%2F%2Fdocs.google.com%2Fdocument%2Fd%2F1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU%2Fpreview&usg=AOvVaw0tBFlVbDVBikdzLqgrWK3g).
///
/// # Arguments
/// `samples` - Something that can be converted into an iterator of sample
/// references.
/// `format` - Which trace format to save the data in.  There are four total
/// formats described in the document.
/// `output` - Where to write the serialized result.
///
/// # Returns
/// A `Result<(), Error>` that indicates if serialization was successful or the
/// details of any error that occured.
///
/// # Examples
/// ```norun
/// let samples = xi_trace::samples_cloned_sorted();
/// let mut serialized = Vec::<u8>::new();
/// serialize(samples.iter(), serialized);
/// ```
pub fn serialize<W>(samples: &Vec<Sample>, output: W) -> Result<(), Error>
where
    W: Write,
{
    serde_json::to_writer(output, samples).map_err(Error::Json)
}

pub fn to_value(samples: &Vec<Sample>) -> Result<serde_json::Value, Error> {
    serde_json::to_value(samples).map_err(Error::Json)
}

pub fn decode(samples: serde_json::Value) -> Result<Vec<Sample>, Error> {
    serde_json::from_value(samples).map_err(Error::Json)
}

pub fn deserialize<R>(input: R) -> Result<Vec<Sample>, Error>
where
    R: Read,
{
    serde_json::from_reader(input).map_err(Error::Json)
}

#[cfg(test)]
mod tests {
    #[cfg(feature = "dict_payload")]
    use super::super::{StrCow, TracePayloadT};
    use super::*;
    #[cfg(feature = "benchmarks")]
    use test::Bencher;

    #[cfg(all(not(feature = "dict_payload"), not(feature = "json_payload")))]
    fn to_payload(value: &'static str) -> &'static str {
        value
    }

    #[cfg(feature = "dict_payload")]
    fn to_payload(value: &'static str) -> TracePayloadT {
        let mut d = TracePayloadT::with_capacity(1);
        d.insert(StrCow::from("test"), StrCow::from(value));
        d
    }

    #[cfg(feature = "json_payload")]
    fn to_payload(value: &'static str) -> TracePayloadT {
        json!({ "test": value })
    }

    #[cfg(feature = "chrome_trace_event")]
    #[test]
    fn test_chrome_trace_serialization() {
        use super::super::*;

        let trace = Trace::enabled(Config::with_limit_count(10));
        trace.instant("sample1", &["test", "chrome"]);
        trace.instant_payload("sample2", &["test", "chrome"], to_payload("payload 2"));
        trace.instant_payload("sample3", &["test", "chrome"], to_payload("payload 3"));
        trace.closure_payload(
            "sample4",
            &["test", "chrome"],
            || {
                let _guard = trace.block("sample5", &["test,chrome"]);
            },
            to_payload("payload 4"),
        );

        let samples = trace.samples_cloned_unsorted();

        let mut serialized = Vec::<u8>::new();

        let result = serialize(&samples, &mut serialized);
        assert!(result.is_ok(), "{:?}", result);

        let decoded_result: Vec<serde_json::Value> = serde_json::from_slice(&serialized).unwrap();
        assert_eq!(decoded_result.len(), 8);
        assert_eq!(decoded_result[0]["name"].as_str().unwrap(), "process_name");
        assert_eq!(decoded_result[1]["name"].as_str().unwrap(), "thread_name");
        for i in 2..5 {
            assert_eq!(decoded_result[i]["name"].as_str().unwrap(), samples[i].name);
            assert_eq!(decoded_result[i]["cat"].as_str().unwrap(), "test,chrome");
            assert_eq!(decoded_result[i]["ph"].as_str().unwrap(), "i");
            assert_eq!(decoded_result[i]["ts"], samples[i].timestamp_us);
            let nth_sample = &samples[i];
            let nth_args = nth_sample.args.as_ref().unwrap();
            assert_eq!(decoded_result[i]["args"]["xi_payload"], json!(nth_args.payload.as_ref()));
        }
        assert_eq!(decoded_result[5]["ph"], "B");
        assert_eq!(decoded_result[6]["ph"], "E");
        assert_eq!(decoded_result[7]["ph"], "X");
    }

    #[cfg(feature = "chrome_trace_event")]
    #[test]
    fn test_chrome_trace_deserialization() {
        use super::super::*;

        let trace = Trace::enabled(Config::with_limit_count(10));
        trace.instant("sample1", &["test", "chrome"]);
        trace.instant_payload("sample2", &["test", "chrome"], to_payload("payload 2"));
        trace.instant_payload("sample3", &["test", "chrome"], to_payload("payload 3"));
        trace.closure_payload("sample4", &["test", "chrome"], || (), to_payload("payload 4"));

        let samples = trace.samples_cloned_unsorted();

        let mut serialized = Vec::<u8>::new();
        let result = serialize(&samples, &mut serialized);
        assert!(result.is_ok(), "{:?}", result);

        let deserialized_samples = deserialize(serialized.as_slice()).unwrap();
        assert_eq!(deserialized_samples, samples);
    }

    #[cfg(all(feature = "chrome_trace_event", feature = "benchmarks"))]
    #[bench]
    fn bench_chrome_trace_serialization_one_element(b: &mut Bencher) {
        use super::chrome_trace_dump::*;

        let mut serialized = Vec::<u8>::new();
        let samples = [super::Sample::new_instant("trace1", &["benchmark", "test"], None)];
        b.iter(|| {
            serialized.clear();
            serialize(samples.iter(), &mut serialized).unwrap();
        });
    }

    #[cfg(all(feature = "chrome_trace_event", feature = "benchmarks"))]
    #[bench]
    fn bench_chrome_trace_serialization_multiple_elements(b: &mut Bencher) {
        use super::super::*;
        use super::chrome_trace_dump::*;

        let mut serialized = Vec::<u8>::new();
        let mut samples = [
            Sample::new_instant("trace1", &["benchmark", "test"], None),
            Sample::new_instant("trace2", &["benchmark"], None),
            Sample::new_duration("trace3", &["benchmark"], Some(to_payload("some payload"), 0)),
            Sample::new_instant("trace4", &["benchmark"], None),
        ];

        b.iter(|| {
            serialized.clear();
            serialize(samples.iter(), &mut serialized).unwrap();
        });
    }
}
<commit_msg>add save_traces utility function<commit_after>// Copyright 2018 The xi-editor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![cfg_attr(feature = "benchmarks", feature(test))]
#![allow(
    clippy::if_same_then_else,
    clippy::needless_bool,
    clippy::needless_pass_by_value,
    clippy::ptr_arg
)]

#[cfg(all(test, feature = "benchmarks"))]
extern crate test;

use super::Sample;
use serde_json;
use std::fs::File;
use std::io::{Error as IOError, Read, Write};

#[derive(Debug)]
pub enum Error {
    Io(IOError),
    Json(serde_json::Error),
    DecodingFormat(String),
}

#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
enum ChromeTraceArrayEntries {
    Array(Vec<Sample>),
}

/// This serializes the samples into the [Chrome trace event format](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwiJlZmDguXYAhUD4GMKHVmEDqIQFggpMAA&url=https%3A%2F%2Fdocs.google.com%2Fdocument%2Fd%2F1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU%2Fpreview&usg=AOvVaw0tBFlVbDVBikdzLqgrWK3g).
///
/// # Arguments
/// `samples` - Something that can be converted into an iterator of sample
/// references.
/// `format` - Which trace format to save the data in.  There are four total
/// formats described in the document.
/// `output` - Where to write the serialized result.
///
/// # Returns
/// A `Result<(), Error>` that indicates if serialization was successful or the
/// details of any error that occured.
///
/// # Examples
/// ```norun
/// let samples = xi_trace::samples_cloned_sorted();
/// let mut serialized = Vec::<u8>::new();
/// serialize(samples.iter(), serialized);
/// ```
pub fn serialize<W>(samples: &Vec<Sample>, output: W) -> Result<(), Error>
where
    W: Write,
{
    serde_json::to_writer(output, samples).map_err(Error::Json)
}

pub fn to_value(samples: &Vec<Sample>) -> Result<serde_json::Value, Error> {
    serde_json::to_value(samples).map_err(Error::Json)
}

pub fn decode(samples: serde_json::Value) -> Result<Vec<Sample>, Error> {
    serde_json::from_value(samples).map_err(Error::Json)
}

pub fn deserialize<R>(input: R) -> Result<Vec<Sample>, Error>
where
    R: Read,
{
    serde_json::from_reader(input).map_err(Error::Json)
}

/// Save tracing data to path pointed to by the environment variable TRACE_OUTPUT, using the Trace
/// Viewer format. Save path defaults to `./target/trace_output.trace`. Trace file can be opened
/// with the Chrome browser by visiting the URL `about:tracing`. If `sorted_chronologically` is true
/// then sort output traces chronologically by time of creation.
pub fn save_traces(sorted_chronologically: bool) {
    use std::env;

    let traces = if sorted_chronologically {
        super::samples_cloned_sorted()
    } else {
        super::samples_cloned_unsorted()
    };

    let trace_output_path = match env::var("TRACE_OUTPUT") {
        Ok(output_path) => output_path,
        Err(_) => {
            println!("Environment variable TRACE_OUTPUT not set, defaulting to ./target/trace_output.trace");
            String::from("./target/trace_output.trace")
        }
    };

    let mut trace_file = match File::create(&trace_output_path) {
        Ok(f) => f,
        Err(_) => {
            println!("Could not create trace output file at: {}.", &trace_output_path);
            return;
        }
    };

    if serialize(&traces, &mut trace_file).is_err() {
        println!("Could not save trace file at: {}.", &trace_output_path);
    } else {
        println!("Saved trace file at: {}", &trace_output_path);
    }
}

#[cfg(test)]
mod tests {
    #[cfg(feature = "dict_payload")]
    use super::super::{StrCow, TracePayloadT};
    use super::*;
    #[cfg(feature = "benchmarks")]
    use test::Bencher;

    #[cfg(all(not(feature = "dict_payload"), not(feature = "json_payload")))]
    fn to_payload(value: &'static str) -> &'static str {
        value
    }

    #[cfg(feature = "dict_payload")]
    fn to_payload(value: &'static str) -> TracePayloadT {
        let mut d = TracePayloadT::with_capacity(1);
        d.insert(StrCow::from("test"), StrCow::from(value));
        d
    }

    #[cfg(feature = "json_payload")]
    fn to_payload(value: &'static str) -> TracePayloadT {
        json!({ "test": value })
    }

    #[cfg(feature = "chrome_trace_event")]
    #[test]
    fn test_chrome_trace_serialization() {
        use super::super::*;

        let trace = Trace::enabled(Config::with_limit_count(10));
        trace.instant("sample1", &["test", "chrome"]);
        trace.instant_payload("sample2", &["test", "chrome"], to_payload("payload 2"));
        trace.instant_payload("sample3", &["test", "chrome"], to_payload("payload 3"));
        trace.closure_payload(
            "sample4",
            &["test", "chrome"],
            || {
                let _guard = trace.block("sample5", &["test,chrome"]);
            },
            to_payload("payload 4"),
        );

        let samples = trace.samples_cloned_unsorted();

        let mut serialized = Vec::<u8>::new();

        let result = serialize(&samples, &mut serialized);
        assert!(result.is_ok(), "{:?}", result);

        let decoded_result: Vec<serde_json::Value> = serde_json::from_slice(&serialized).unwrap();
        assert_eq!(decoded_result.len(), 8);
        assert_eq!(decoded_result[0]["name"].as_str().unwrap(), "process_name");
        assert_eq!(decoded_result[1]["name"].as_str().unwrap(), "thread_name");
        for i in 2..5 {
            assert_eq!(decoded_result[i]["name"].as_str().unwrap(), samples[i].name);
            assert_eq!(decoded_result[i]["cat"].as_str().unwrap(), "test,chrome");
            assert_eq!(decoded_result[i]["ph"].as_str().unwrap(), "i");
            assert_eq!(decoded_result[i]["ts"], samples[i].timestamp_us);
            let nth_sample = &samples[i];
            let nth_args = nth_sample.args.as_ref().unwrap();
            assert_eq!(decoded_result[i]["args"]["xi_payload"], json!(nth_args.payload.as_ref()));
        }
        assert_eq!(decoded_result[5]["ph"], "B");
        assert_eq!(decoded_result[6]["ph"], "E");
        assert_eq!(decoded_result[7]["ph"], "X");
    }

    #[cfg(feature = "chrome_trace_event")]
    #[test]
    fn test_chrome_trace_deserialization() {
        use super::super::*;

        let trace = Trace::enabled(Config::with_limit_count(10));
        trace.instant("sample1", &["test", "chrome"]);
        trace.instant_payload("sample2", &["test", "chrome"], to_payload("payload 2"));
        trace.instant_payload("sample3", &["test", "chrome"], to_payload("payload 3"));
        trace.closure_payload("sample4", &["test", "chrome"], || (), to_payload("payload 4"));

        let samples = trace.samples_cloned_unsorted();

        let mut serialized = Vec::<u8>::new();
        let result = serialize(&samples, &mut serialized);
        assert!(result.is_ok(), "{:?}", result);

        let deserialized_samples = deserialize(serialized.as_slice()).unwrap();
        assert_eq!(deserialized_samples, samples);
    }

    #[cfg(all(feature = "chrome_trace_event", feature = "benchmarks"))]
    #[bench]
    fn bench_chrome_trace_serialization_one_element(b: &mut Bencher) {
        use super::chrome_trace_dump::*;

        let mut serialized = Vec::<u8>::new();
        let samples = [super::Sample::new_instant("trace1", &["benchmark", "test"], None)];
        b.iter(|| {
            serialized.clear();
            serialize(samples.iter(), &mut serialized).unwrap();
        });
    }

    #[cfg(all(feature = "chrome_trace_event", feature = "benchmarks"))]
    #[bench]
    fn bench_chrome_trace_serialization_multiple_elements(b: &mut Bencher) {
        use super::super::*;
        use super::chrome_trace_dump::*;

        let mut serialized = Vec::<u8>::new();
        let mut samples = [
            Sample::new_instant("trace1", &["benchmark", "test"], None),
            Sample::new_instant("trace2", &["benchmark"], None),
            Sample::new_duration("trace3", &["benchmark"], Some(to_payload("some payload"), 0)),
            Sample::new_instant("trace4", &["benchmark"], None),
        ];

        b.iter(|| {
            serialized.clear();
            serialize(samples.iter(), &mut serialized).unwrap();
        });
    }
}
<|endoftext|>


<commit_before>macro_rules! assert_special {
    ($left:expr, $right:expr) => ({
        match (&$left, &$right) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    panic!("assertion_failed: `(left == right)`\
                            (left: `{:?}` right: `{:?}`)",
                    left_val, right_val)
                }

                true
            }
        }
    });
}

macro_rules! vector {
    ($elem:expr, $n:expr) => {
        ::std::vec::from_elem($elem, $n)
    };
    ($($x:expr),*) => {
        <[_]>::into_vec(Box::new([ $( $x ), *]))
    };
    ($($x:expr),+ ,) => {
        vector![$($x), *]
    }
}

fn main() {
    let val = assert_special!("hello", "hello");
    println!("{:?}", val);

    let some_vector = vector![10, 1];
    println!("{:?}", some_vector);
}
<commit_msg>full table of Rust macros match combinators<commit_after>macro_rules! assert_special {
    ($left:expr, $right:expr) => ({
        match (&$left, &$right) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    panic!("assertion_failed: `(left == right)`\
                            (left: `{:?}` right: `{:?}`)",
                    left_val, right_val)
                }

                true
            }
        }
    });
}

macro_rules! vector {
    ($elem:expr, $n:expr) => {
        ::std::vec::from_elem($elem, $n)
    };
    ($($x:expr),*) => {
        <[_]>::into_vec(Box::new([ $( $x ), *]))
    };
    ($($x:expr),+ ,) => {
        vector![$($x), *]
    }
}

// Pattern language of regular expressions:

// $( ... )* Match 0 or more times with no separator

// $( ... ),* Match 0 or more times, separated by commas

// $( ... );* Match 0 or more times, separated by semicolons

// $( ... )+ Match 1 or more times with no separator

// $( ... ),+ Match 1 or more times, separated by commas

// $( ... );+ Match 1 or more times, separated by semicolons

fn main() {
    let val = assert_special!("hello", "hello");
    println!("{:?}", val);

    let some_vector = vector![10, 1];
    println!("{:?}", some_vector);
}
<|endoftext|>


<commit_before>use super::{problem::*, submission::*, user::*, *};
use juniper::FieldResult;

pub struct Contest;

#[juniper::object(Context = Context)]
impl Contest {
    fn init(context: &Context) -> FieldResult<MutationOk> {
        // TODO: check admin credentials
        UserRepository::init(context)?;
        ProblemRepository::init(context)?;
        let connection = context.connect_db()?;
        return Ok(MutationOk);
    }

    fn user(context: &Context, id: String) -> FieldResult<Vec<User>> {
        // TODO: check user credentials
        let connection = context.connect_db()?;
        return Ok(users::table.find(id).load::<User>(&connection)?);
    }

    fn problems(context: &Context) -> FieldResult<Vec<Problem>> {
        let connection = context.connect_db()?;
        return Ok(problems::table.load::<Problem>(&connection)?);
    }
}
<commit_msg>contest: fix finding a single user<commit_after>use super::{problem::*, submission::*, user::*, *};
use juniper::FieldResult;

pub struct Contest;

#[juniper::object(Context = Context)]
impl Contest {
    fn init(context: &Context) -> FieldResult<MutationOk> {
        // TODO: check admin credentials
        UserRepository::init(context)?;
        ProblemRepository::init(context)?;
        let connection = context.connect_db()?;
        return Ok(MutationOk);
    }

    fn user(context: &Context, id: String) -> FieldResult<User> {
        // TODO: check user credentials
        let connection = context.connect_db()?;
        return Ok(users::table.find(id).first(&connection)?);
    }

    fn problems(context: &Context) -> FieldResult<Vec<Problem>> {
        let connection = context.connect_db()?;
        return Ok(problems::table.load::<Problem>(&connection)?);
    }
}
<|endoftext|>


<commit_before>//! Abstractions for page tables and other paging related structures.

pub use self::page_table::*;
pub use self::recursive::*;

use addr::{VirtAddr, PhysAddr};
use core::ops::{Add, AddAssign, Sub, SubAssign};
use ux::*;

mod page_table;
mod recursive;

/// The default page size on x86_64.
pub const PAGE_SIZE: u16 = 4096;

/// A virtual 4kB page.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Page {
   number: u64,
}

impl Page {
    /// Returns the page that contains the given virtual address.
    pub fn containing_address(address: VirtAddr) -> Page {
        Page { number: address.as_u64() / u64::from(PAGE_SIZE) }
    }

    pub fn from_page_table_indices(p4_index: u9, p3_index: u9, p2_index: u9, p1_index: u9)
        -> Page
    {
        use bit_field::BitField;

        let mut addr = 0;
        addr.set_bits(39..48, u64::from(p4_index));
        addr.set_bits(30..39, u64::from(p3_index));
        addr.set_bits(21..30, u64::from(p2_index));
        addr.set_bits(12..21, u64::from(p1_index));
        Page::containing_address(VirtAddr::new(addr))
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> VirtAddr {
        VirtAddr::new(self.number * u64::from(PAGE_SIZE))
    }

    /// Returns the level 4 page table index of this page.
    pub fn p4_index(&self) -> u9 {
        self.start_address().p4_index()
    }

    /// Returns the level 3 page table index of this page.
    pub fn p3_index(&self) -> u9 {
        self.start_address().p3_index()
    }

    /// Returns the level 2 page table index of this page.
    pub fn p2_index(&self) -> u9 {
        self.start_address().p2_index()
    }

    /// Returns the level 1 page table index of this page.
    pub fn p1_index(&self) -> u9 {
        self.start_address().p1_index()
    }
}

impl Add<u64> for Page {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() + rhs * u64::from(PAGE_SIZE))
    }
}

impl AddAssign<u64> for Page {
    fn add_assign(&mut self, rhs: u64) {
        *self = self.clone() + rhs;
    }
}

impl Sub<u64> for Page {
    type Output = Self;
    fn sub(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() - rhs * u64::from(PAGE_SIZE))
    }
}

impl SubAssign<u64> for Page {
    fn sub_assign(&mut self, rhs: u64) {
        *self = self.clone() - rhs;
    }
}

/// A physical 4kB frame.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct PhysFrame {
   number: u64,
}

impl PhysFrame {
    /// Returns the frame that contains the given physical address.
    pub fn containing_address(address: PhysAddr) -> PhysFrame {
        PhysFrame { number: address.as_u64() / u64::from(PAGE_SIZE) }
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> PhysAddr {
        PhysAddr::new(self.number * u64::from(PAGE_SIZE))
    }
}

impl Add<u64> for PhysFrame {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() + rhs * u64::from(PAGE_SIZE))
    }
}

impl AddAssign<u64> for PhysFrame {
    fn add_assign(&mut self, rhs: u64) {
        *self = self.clone() + rhs;
    }
}

impl Sub<u64> for PhysFrame {
    type Output = Self;
    fn sub(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() - rhs * u64::from(PAGE_SIZE))
    }
}

impl SubAssign<u64> for PhysFrame {
    fn sub_assign(&mut self, rhs: u64) {
        *self = self.clone() - rhs;
    }
}
<commit_msg>Add PageRange and PageRangeInclusive types<commit_after>//! Abstractions for page tables and other paging related structures.

pub use self::page_table::*;
pub use self::recursive::*;

use addr::{VirtAddr, PhysAddr};
use core::ops::{Add, AddAssign, Sub, SubAssign};
use ux::*;

mod page_table;
mod recursive;

/// The default page size on x86_64.
pub const PAGE_SIZE: u16 = 4096;

/// A virtual 4kB page.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Page {
   number: u64,
}

impl Page {
    /// Returns the page that contains the given virtual address.
    pub fn containing_address(address: VirtAddr) -> Page {
        Page { number: address.as_u64() / u64::from(PAGE_SIZE) }
    }

    pub fn from_page_table_indices(p4_index: u9, p3_index: u9, p2_index: u9, p1_index: u9)
        -> Page
    {
        use bit_field::BitField;

        let mut addr = 0;
        addr.set_bits(39..48, u64::from(p4_index));
        addr.set_bits(30..39, u64::from(p3_index));
        addr.set_bits(21..30, u64::from(p2_index));
        addr.set_bits(12..21, u64::from(p1_index));
        Page::containing_address(VirtAddr::new(addr))
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> VirtAddr {
        VirtAddr::new(self.number * u64::from(PAGE_SIZE))
    }

    /// Returns the level 4 page table index of this page.
    pub fn p4_index(&self) -> u9 {
        self.start_address().p4_index()
    }

    /// Returns the level 3 page table index of this page.
    pub fn p3_index(&self) -> u9 {
        self.start_address().p3_index()
    }

    /// Returns the level 2 page table index of this page.
    pub fn p2_index(&self) -> u9 {
        self.start_address().p2_index()
    }

    /// Returns the level 1 page table index of this page.
    pub fn p1_index(&self) -> u9 {
        self.start_address().p1_index()
    }

    pub fn range(start: Page, end: Page) -> PageRange {
        PageRange { start, end }
    }

    pub fn range_inclusive(start: Page, end: Page) -> PageRangeInclusive {
        PageRangeInclusive { start, end }
    }
}

impl Add<u64> for Page {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() + rhs * u64::from(PAGE_SIZE))
    }
}

impl AddAssign<u64> for Page {
    fn add_assign(&mut self, rhs: u64) {
        *self = self.clone() + rhs;
    }
}

impl Sub<u64> for Page {
    type Output = Self;
    fn sub(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() - rhs * u64::from(PAGE_SIZE))
    }
}

impl SubAssign<u64> for Page {
    fn sub_assign(&mut self, rhs: u64) {
        *self = self.clone() - rhs;
    }
}

pub struct PageRange {
    pub start: Page,
    pub end: Page,
}

impl Iterator for PageRange {
    type Item = Page;

    fn next(&mut self) -> Option<Page> {
        if self.start < self.end {
            let page = self.start.clone();
            self.start += 1;
            Some(page)
        } else {
            None
        }
    }
}

pub struct PageRangeInclusive {
    pub start: Page,
    pub end: Page,
}

impl Iterator for PageRangeInclusive {
    type Item = Page;

    fn next(&mut self) -> Option<Page> {
        if self.start <= self.end {
            let page = self.start.clone();
            self.start += 1;
            Some(page)
        } else {
            None
        }
    }
}

/// A physical 4kB frame.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct PhysFrame {
   number: u64,
}

impl PhysFrame {
    /// Returns the frame that contains the given physical address.
    pub fn containing_address(address: PhysAddr) -> PhysFrame {
        PhysFrame { number: address.as_u64() / u64::from(PAGE_SIZE) }
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> PhysAddr {
        PhysAddr::new(self.number * u64::from(PAGE_SIZE))
    }
}

impl Add<u64> for PhysFrame {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() + rhs * u64::from(PAGE_SIZE))
    }
}

impl AddAssign<u64> for PhysFrame {
    fn add_assign(&mut self, rhs: u64) {
        *self = self.clone() + rhs;
    }
}

impl Sub<u64> for PhysFrame {
    type Output = Self;
    fn sub(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() - rhs * u64::from(PAGE_SIZE))
    }
}

impl SubAssign<u64> for PhysFrame {
    fn sub_assign(&mut self, rhs: u64) {
        *self = self.clone() - rhs;
    }
}
<|endoftext|>


<commit_before>use ir;

pub fn select(module: &ir::Module) {

}

pub fn select_function(function: &ir::Function) {

}

pub fn select_block(block: &ir::Block) {

}
<commit_msg>Remove selection code<commit_after><|endoftext|>


<commit_before>// -*- rust -*-

use std;
import std.map;
import std._str;
import std.util;

fn test_simple() {
  log "*** starting test_simple";

  fn eq_uint(&uint x, &uint y) -> bool { ret x == y; }
  fn hash_uint(&uint u) -> uint {
    // FIXME: can't use std.util.id since we'd be capturing a type param,
    // and presently we can't close items over type params.
    ret u;
  }

  let map.hashfn[uint] hasher_uint = hash_uint;
  let map.eqfn[uint] eqer_uint = eq_uint;

  let map.hashfn[str] hasher_str = _str.hash;
  let map.eqfn[str] eqer_str = _str.eq;

  log "uint -> uint";

  let map.hashmap[uint, uint] hm_uu = map.mk_hashmap[uint, uint](hasher_uint,
                                                                 eqer_uint);

  check (hm_uu.insert(10u, 12u));
  check (hm_uu.insert(11u, 13u));
  check (hm_uu.insert(12u, 14u));

  check (hm_uu.get(11u) == 13u);
  check (hm_uu.get(12u) == 14u);
  check (hm_uu.get(10u) == 12u);

  check (!hm_uu.insert(12u, 14u));
  check (hm_uu.get(12u) == 14u);

  check (!hm_uu.insert(12u, 12u));
  check (hm_uu.get(12u) == 12u);

  log "str -> uint";

  let map.hashmap[str, uint] hm_su = map.mk_hashmap[str, uint](hasher_str,
                                                               eqer_str);

  check (hm_su.insert("ten", 12u));
  check (hm_su.insert("eleven", 13u));
  check (hm_su.insert("twelve", 14u));

  check (hm_su.get("eleven") == 13u);
  check (hm_su.get("twelve") == 14u);
  check (hm_su.get("ten") == 12u);

  check (!hm_su.insert("twelve", 14u));
  check (hm_su.get("twelve") == 14u);

  check (!hm_su.insert("twelve", 12u));
  check (hm_su.get("twelve") == 12u);

  log "uint -> str";

  let map.hashmap[uint, str] hm_us = map.mk_hashmap[uint, str](hasher_uint,
                                                               eqer_uint);

  check (hm_us.insert(10u, "twelve"));
  check (hm_us.insert(11u, "thirteen"));
  check (hm_us.insert(12u, "fourteen"));

  check (_str.eq(hm_us.get(11u), "thirteen"));
  check (_str.eq(hm_us.get(12u), "fourteen"));
  check (_str.eq(hm_us.get(10u), "twelve"));

  check (!hm_us.insert(12u, "fourteen"));
  check (_str.eq(hm_us.get(12u), "fourteen"));

  check (!hm_us.insert(12u, "twelve"));
  check (_str.eq(hm_us.get(12u), "twelve"));

  log "str -> str";

  let map.hashmap[str, str] hm_ss = map.mk_hashmap[str, str](hasher_str,
                                                             eqer_str);

  check (hm_ss.insert("ten", "twelve"));
  check (hm_ss.insert("eleven", "thirteen"));
  check (hm_ss.insert("twelve", "fourteen"));

  check (_str.eq(hm_ss.get("eleven"), "thirteen"));
  check (_str.eq(hm_ss.get("twelve"), "fourteen"));
  check (_str.eq(hm_ss.get("ten"), "twelve"));

  check (!hm_ss.insert("twelve", "fourteen"));
  check (_str.eq(hm_ss.get("twelve"), "fourteen"));

  check (!hm_ss.insert("twelve", "twelve"));
  check (_str.eq(hm_ss.get("twelve"), "twelve"));

  log "*** finished test_simple";
}

/**
 * Force map growth and rehashing.
 */
fn test_growth() {
  log "*** starting test_growth";

  let uint num_to_insert = 64u;

  fn eq(&uint x, &uint y) -> bool { ret x == y; }
  fn hash(&uint u) -> uint {
    // FIXME: can't use std.util.id since we'd be capturing a type param,
    // and presently we can't close items over type params.
    ret u;
  }

  let map.hashfn[uint] hasher = hash;
  let map.eqfn[uint] eqer = eq;
  let map.hashmap[uint, uint] hm = map.mk_hashmap[uint, uint](hasher, eqer);

  let uint i = 0u;
  while (i < num_to_insert) {
    check (hm.insert(i, i * i));
    log "inserting " + std._uint.to_str(i, 10u)
      + " -> " + std._uint.to_str(i * i, 10u);
    i += 1u;
  }

  log "-----";

  i = 0u;
  while (i < num_to_insert) {
    log "get(" + std._uint.to_str(i, 10u) + ") = "
      + std._uint.to_str(hm.get(i), 10u);
    check (hm.get(i) == i * i);
    i += 1u;
  }

  check (hm.insert(num_to_insert, 17u));
  check (hm.get(num_to_insert) == 17u);

  log "-----";

  hm.rehash();

  i = 0u;
  while (i < num_to_insert) {
    log "get(" + std._uint.to_str(i, 10u) + ") = "
      + std._uint.to_str(hm.get(i), 10u);
    check (hm.get(i) == i * i);
    i += 1u;
  }

  log "*** finished test_growth";
}

fn test_removal() {
  log "*** starting test_removal";

  let uint num_to_insert = 64u;

  fn eq(&uint x, &uint y) -> bool { ret x == y; }
  fn hash(&uint u) -> uint {
    // This hash function intentionally causes collisions between
    // consecutive integer pairs.
    ret (u / 2u) * 2u;
  }

  check (hash(0u) == hash(1u));
  check (hash(2u) == hash(3u));
  check (hash(0u) != hash(2u));

  let map.hashfn[uint] hasher = hash;
  let map.eqfn[uint] eqer = eq;
  let map.hashmap[uint, uint] hm = map.mk_hashmap[uint, uint](hasher, eqer);

  let uint i = 0u;
  while (i < num_to_insert) {
    check (hm.insert(i, i * i));
    log "inserting " + std._uint.to_str(i, 10u)
      + " -> " + std._uint.to_str(i * i, 10u);
    i += 1u;
  }

  check (hm.size() == num_to_insert);

  log "-----";
  log "removing evens";

  i = 0u;
  while (i < num_to_insert) {
    /**
     * FIXME (issue #150): we want to check the removed value as in the
     * following:

    let util.option[uint] v = hm.remove(i);
    alt (v) {
      case (util.some[uint](u)) {
        check (u == (i * i));
      }
      case (util.none[uint]()) { fail; }
    }

     * but we util.option is a tag type so util.some and util.none are
     * off limits until we parse the dwarf for tag types.
     */

    hm.remove(i);
    i += 2u;
  }

  check (hm.size() == (num_to_insert / 2u));

  log "-----";

  i = 1u;
  while (i < num_to_insert) {
    log "get(" + std._uint.to_str(i, 10u) + ") = "
      + std._uint.to_str(hm.get(i), 10u);
    check (hm.get(i) == i * i);
    i += 2u;
  }

  log "-----";
  log "rehashing";

  hm.rehash();

  log "-----";

  i = 1u;
  while (i < num_to_insert) {
    log "get(" + std._uint.to_str(i, 10u) + ") = "
      + std._uint.to_str(hm.get(i), 10u);
    check (hm.get(i) == i * i);
    i += 2u;
  }

  log "-----";

  i = 0u;
  while (i < num_to_insert) {
    check (hm.insert(i, i * i));
    log "inserting " + std._uint.to_str(i, 10u)
      + " -> " + std._uint.to_str(i * i, 10u);
    i += 2u;
  }

  check (hm.size() == num_to_insert);

  log "-----";

  i = 0u;
  while (i < num_to_insert) {
    log "get(" + std._uint.to_str(i, 10u) + ") = "
      + std._uint.to_str(hm.get(i), 10u);
    check (hm.get(i) == i * i);
    i += 1u;
  }

  log "-----";
  log "rehashing";

  hm.rehash();

  log "-----";

  check (hm.size() == num_to_insert);

  i = 0u;
  while (i < num_to_insert) {
    log "get(" + std._uint.to_str(i, 10u) + ") = "
      + std._uint.to_str(hm.get(i), 10u);
    check (hm.get(i) == i * i);
    i += 1u;
  }

  log "*** finished test_removal";
}

fn main() {
  test_simple();
  test_growth();
  test_removal();
}
<commit_msg>Comment out hashmap tests exercising maps with str as key or value type, as they appear to cause leaks.<commit_after>// -*- rust -*-

use std;
import std.map;
import std._str;
import std.util;

fn test_simple() {
  log "*** starting test_simple";

  fn eq_uint(&uint x, &uint y) -> bool { ret x == y; }
  fn hash_uint(&uint u) -> uint {
    // FIXME: can't use std.util.id since we'd be capturing a type param,
    // and presently we can't close items over type params.
    ret u;
  }

  let map.hashfn[uint] hasher_uint = hash_uint;
  let map.eqfn[uint] eqer_uint = eq_uint;

  let map.hashfn[str] hasher_str = _str.hash;
  let map.eqfn[str] eqer_str = _str.eq;

  log "uint -> uint";

  let map.hashmap[uint, uint] hm_uu = map.mk_hashmap[uint, uint](hasher_uint,
                                                                 eqer_uint);

  check (hm_uu.insert(10u, 12u));
  check (hm_uu.insert(11u, 13u));
  check (hm_uu.insert(12u, 14u));

  check (hm_uu.get(11u) == 13u);
  check (hm_uu.get(12u) == 14u);
  check (hm_uu.get(10u) == 12u);

  check (!hm_uu.insert(12u, 14u));
  check (hm_uu.get(12u) == 14u);

  check (!hm_uu.insert(12u, 12u));
  check (hm_uu.get(12u) == 12u);

  /*
  log "str -> uint";

  let map.hashmap[str, uint] hm_su = map.mk_hashmap[str, uint](hasher_str,
                                                               eqer_str);

  check (hm_su.insert("ten", 12u));
  check (hm_su.insert("eleven", 13u));
  check (hm_su.insert("twelve", 14u));

  check (hm_su.get("eleven") == 13u);
  check (hm_su.get("twelve") == 14u);
  check (hm_su.get("ten") == 12u);

  check (!hm_su.insert("twelve", 14u));
  check (hm_su.get("twelve") == 14u);

  check (!hm_su.insert("twelve", 12u));
  check (hm_su.get("twelve") == 12u);

  log "uint -> str";

  let map.hashmap[uint, str] hm_us = map.mk_hashmap[uint, str](hasher_uint,
                                                               eqer_uint);

  check (hm_us.insert(10u, "twelve"));
  check (hm_us.insert(11u, "thirteen"));
  check (hm_us.insert(12u, "fourteen"));

  check (_str.eq(hm_us.get(11u), "thirteen"));
  check (_str.eq(hm_us.get(12u), "fourteen"));
  check (_str.eq(hm_us.get(10u), "twelve"));

  check (!hm_us.insert(12u, "fourteen"));
  check (_str.eq(hm_us.get(12u), "fourteen"));

  check (!hm_us.insert(12u, "twelve"));
  check (_str.eq(hm_us.get(12u), "twelve"));

  log "str -> str";

  let map.hashmap[str, str] hm_ss = map.mk_hashmap[str, str](hasher_str,
                                                             eqer_str);

  check (hm_ss.insert("ten", "twelve"));
  check (hm_ss.insert("eleven", "thirteen"));
  check (hm_ss.insert("twelve", "fourteen"));

  check (_str.eq(hm_ss.get("eleven"), "thirteen"));
  check (_str.eq(hm_ss.get("twelve"), "fourteen"));
  check (_str.eq(hm_ss.get("ten"), "twelve"));

  check (!hm_ss.insert("twelve", "fourteen"));
  check (_str.eq(hm_ss.get("twelve"), "fourteen"));

  check (!hm_ss.insert("twelve", "twelve"));
  check (_str.eq(hm_ss.get("twelve"), "twelve"));
  */

  log "*** finished test_simple";
}

/**
 * Force map growth and rehashing.
 */
fn test_growth() {
  log "*** starting test_growth";

  let uint num_to_insert = 64u;

  fn eq(&uint x, &uint y) -> bool { ret x == y; }
  fn hash(&uint u) -> uint {
    // FIXME: can't use std.util.id since we'd be capturing a type param,
    // and presently we can't close items over type params.
    ret u;
  }

  let map.hashfn[uint] hasher = hash;
  let map.eqfn[uint] eqer = eq;
  let map.hashmap[uint, uint] hm = map.mk_hashmap[uint, uint](hasher, eqer);

  let uint i = 0u;
  while (i < num_to_insert) {
    check (hm.insert(i, i * i));
    log "inserting " + std._uint.to_str(i, 10u)
      + " -> " + std._uint.to_str(i * i, 10u);
    i += 1u;
  }

  log "-----";

  i = 0u;
  while (i < num_to_insert) {
    log "get(" + std._uint.to_str(i, 10u) + ") = "
      + std._uint.to_str(hm.get(i), 10u);
    check (hm.get(i) == i * i);
    i += 1u;
  }

  check (hm.insert(num_to_insert, 17u));
  check (hm.get(num_to_insert) == 17u);

  log "-----";

  hm.rehash();

  i = 0u;
  while (i < num_to_insert) {
    log "get(" + std._uint.to_str(i, 10u) + ") = "
      + std._uint.to_str(hm.get(i), 10u);
    check (hm.get(i) == i * i);
    i += 1u;
  }

  log "*** finished test_growth";
}

fn test_removal() {
  log "*** starting test_removal";

  let uint num_to_insert = 64u;

  fn eq(&uint x, &uint y) -> bool { ret x == y; }
  fn hash(&uint u) -> uint {
    // This hash function intentionally causes collisions between
    // consecutive integer pairs.
    ret (u / 2u) * 2u;
  }

  check (hash(0u) == hash(1u));
  check (hash(2u) == hash(3u));
  check (hash(0u) != hash(2u));

  let map.hashfn[uint] hasher = hash;
  let map.eqfn[uint] eqer = eq;
  let map.hashmap[uint, uint] hm = map.mk_hashmap[uint, uint](hasher, eqer);

  let uint i = 0u;
  while (i < num_to_insert) {
    check (hm.insert(i, i * i));
    log "inserting " + std._uint.to_str(i, 10u)
      + " -> " + std._uint.to_str(i * i, 10u);
    i += 1u;
  }

  check (hm.size() == num_to_insert);

  log "-----";
  log "removing evens";

  i = 0u;
  while (i < num_to_insert) {
    /**
     * FIXME (issue #150): we want to check the removed value as in the
     * following:

    let util.option[uint] v = hm.remove(i);
    alt (v) {
      case (util.some[uint](u)) {
        check (u == (i * i));
      }
      case (util.none[uint]()) { fail; }
    }

     * but we util.option is a tag type so util.some and util.none are
     * off limits until we parse the dwarf for tag types.
     */

    hm.remove(i);
    i += 2u;
  }

  check (hm.size() == (num_to_insert / 2u));

  log "-----";

  i = 1u;
  while (i < num_to_insert) {
    log "get(" + std._uint.to_str(i, 10u) + ") = "
      + std._uint.to_str(hm.get(i), 10u);
    check (hm.get(i) == i * i);
    i += 2u;
  }

  log "-----";
  log "rehashing";

  hm.rehash();

  log "-----";

  i = 1u;
  while (i < num_to_insert) {
    log "get(" + std._uint.to_str(i, 10u) + ") = "
      + std._uint.to_str(hm.get(i), 10u);
    check (hm.get(i) == i * i);
    i += 2u;
  }

  log "-----";

  i = 0u;
  while (i < num_to_insert) {
    check (hm.insert(i, i * i));
    log "inserting " + std._uint.to_str(i, 10u)
      + " -> " + std._uint.to_str(i * i, 10u);
    i += 2u;
  }

  check (hm.size() == num_to_insert);

  log "-----";

  i = 0u;
  while (i < num_to_insert) {
    log "get(" + std._uint.to_str(i, 10u) + ") = "
      + std._uint.to_str(hm.get(i), 10u);
    check (hm.get(i) == i * i);
    i += 1u;
  }

  log "-----";
  log "rehashing";

  hm.rehash();

  log "-----";

  check (hm.size() == num_to_insert);

  i = 0u;
  while (i < num_to_insert) {
    log "get(" + std._uint.to_str(i, 10u) + ") = "
      + std._uint.to_str(hm.get(i), 10u);
    check (hm.get(i) == i * i);
    i += 1u;
  }

  log "*** finished test_removal";
}

fn main() {
  test_simple();
  test_growth();
  test_removal();
}
<|endoftext|>


<commit_before>#![allow(clippy::single_match_else)]
use rustc_tools_util::VersionInfo;

#[test]
fn check_that_clippy_lints_has_the_same_version_as_clippy() {
    let clippy_meta = cargo_metadata::MetadataCommand::new()
        .no_deps()
        .exec()
        .expect("could not obtain cargo metadata");
    std::env::set_current_dir(std::env::current_dir().unwrap().join("clippy_lints")).unwrap();
    let clippy_lints_meta = cargo_metadata::MetadataCommand::new()
        .no_deps()
        .exec()
        .expect("could not obtain cargo metadata");
    assert_eq!(clippy_lints_meta.packages[0].version, clippy_meta.packages[0].version);
    for package in &clippy_meta.packages[0].dependencies {
        if package.name == "clippy_lints" {
            assert!(package.req.matches(&clippy_lints_meta.packages[0].version));
            return;
        }
    }
}

#[test]
fn check_that_clippy_has_the_same_major_version_as_rustc() {
    let clippy_version = rustc_tools_util::get_version_info!();
    let clippy_major = clippy_version.major;
    let clippy_minor = clippy_version.minor;
    let clippy_patch = clippy_version.patch;

    // get the rustc version
    // this way the rust-toolchain file version is honored
    let rustc_version = String::from_utf8(
        std::process::Command::new("rustc")
            .arg("--version")
            .output()
            .expect("failed to run `rustc --version`")
            .stdout,
    )
    .unwrap();
    // extract "1 XX 0" from "rustc 1.XX.0-nightly (<commit> <date>)"
    let vsplit: Vec<&str> = rustc_version
        .split(' ')
        .nth(1)
        .unwrap()
        .split('-')
        .next()
        .unwrap()
        .split('.')
        .collect();
    match vsplit.as_slice() {
        [rustc_major, rustc_minor, _rustc_patch] => {
            // clippy 0.1.XX should correspond to rustc 1.XX.0
            assert_eq!(clippy_major, 0); // this will probably stay the same for a long time
            assert_eq!(
                clippy_minor.to_string(),
                *rustc_major,
                "clippy minor version does not equal rustc major version"
            );
            assert_eq!(
                clippy_patch.to_string(),
                *rustc_minor,
                "clippy patch version does not equal rustc minor version"
            );
            // do not check rustc_patch because when a stable-patch-release is made (like 1.50.2),
            // we don't want our tests failing suddenly
        },
        _ => {
            panic!("Failed to parse rustc version: {:?}", vsplit);
        },
    };
}
<commit_msg>Use bootstrap rustc for versioncheck in Clippy<commit_after>#![allow(clippy::single_match_else)]
use rustc_tools_util::VersionInfo;

#[test]
fn check_that_clippy_lints_has_the_same_version_as_clippy() {
    let clippy_meta = cargo_metadata::MetadataCommand::new()
        .no_deps()
        .exec()
        .expect("could not obtain cargo metadata");
    std::env::set_current_dir(std::env::current_dir().unwrap().join("clippy_lints")).unwrap();
    let clippy_lints_meta = cargo_metadata::MetadataCommand::new()
        .no_deps()
        .exec()
        .expect("could not obtain cargo metadata");
    assert_eq!(clippy_lints_meta.packages[0].version, clippy_meta.packages[0].version);
    for package in &clippy_meta.packages[0].dependencies {
        if package.name == "clippy_lints" {
            assert!(package.req.matches(&clippy_lints_meta.packages[0].version));
            return;
        }
    }
}

#[test]
fn check_that_clippy_has_the_same_major_version_as_rustc() {
    let clippy_version = rustc_tools_util::get_version_info!();
    let clippy_major = clippy_version.major;
    let clippy_minor = clippy_version.minor;
    let clippy_patch = clippy_version.patch;

    // get the rustc version either from the rustc installed with the toolchain file or from
    // `RUSTC_REAL` if Clippy is build in the Rust repo with `./x.py`.
    let rustc = std::env::var("RUSTC_REAL").unwrap_or_else(|_| "rustc".to_string());
    let rustc_version = String::from_utf8(
        std::process::Command::new(&rustc)
            .arg("--version")
            .output()
            .expect("failed to run `rustc --version`")
            .stdout,
    )
    .unwrap();
    // extract "1 XX 0" from "rustc 1.XX.0-nightly (<commit> <date>)"
    let vsplit: Vec<&str> = rustc_version
        .split(' ')
        .nth(1)
        .unwrap()
        .split('-')
        .next()
        .unwrap()
        .split('.')
        .collect();
    match vsplit.as_slice() {
        [rustc_major, rustc_minor, _rustc_patch] => {
            // clippy 0.1.XX should correspond to rustc 1.XX.0
            assert_eq!(clippy_major, 0); // this will probably stay the same for a long time
            assert_eq!(
                clippy_minor.to_string(),
                *rustc_major,
                "clippy minor version does not equal rustc major version"
            );
            assert_eq!(
                clippy_patch.to_string(),
                *rustc_minor,
                "clippy patch version does not equal rustc minor version"
            );
            // do not check rustc_patch because when a stable-patch-release is made (like 1.50.2),
            // we don't want our tests failing suddenly
        },
        _ => {
            panic!("Failed to parse rustc version: {:?}", vsplit);
        },
    };
}
<|endoftext|>


<commit_before>//! TODO Documentation

use std::panic;
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;

use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::{timespec, wlr_subsurface, wlr_surface, wlr_surface_get_main_surface,
                  wlr_surface_has_buffer, wlr_surface_make_subsurface, wlr_surface_send_enter,
                  wlr_surface_send_frame_done, wlr_surface_send_leave, wlr_surface_subsurface_at};

use super::{Subsurface, SubsurfaceHandle, SubsurfaceManager, SurfaceState};
use Output;
use errors::{UpgradeHandleErr, UpgradeHandleResult};
use render::Texture;
use utils::c_to_rust_string;

/// The state stored in the wlr_surface user data.
struct InternalSurfaceState {
    /// Used to reconstruct a SurfaceHandle from just an *mut wlr_surface.
    handle: Weak<AtomicBool>,
    /// Weak reference to the manager for the list of subsurfaces.
    /// This is here so that we can reconstruct the Surface from a SurfaceHandle.
    subsurfaces_manager: Weak<Box<SubsurfaceManager>>
}

/// A Wayland object that represents the data that we display on the screen.
///
/// Most surfaces come from Wayland clients, though they can also be created
/// by the compositor directly.
#[derive(Debug)]
pub struct Surface {
    /// The structe that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `SurfaceHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `SurfaceHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The manager of the list of subsurfaces for this surface.
    ///
    /// When the subsurface destruction event fires the manager will deal with
    /// updating the list.
    ///
    /// When you have a reference to the Surface you can access its children
    /// through the getter for this list.
    subsurfaces_manager: Rc<Box<SubsurfaceManager>>,
    /// The pointer to the wlroots object that wraps a wl_surface.
    surface: *mut wlr_surface
}

/// See `Surface` for more information on how to use this structure.
#[derive(Clone, Debug)]
pub struct SurfaceHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the pointer associated with this handle,
    /// this can no longer be used.
    handle: Weak<AtomicBool>,
    /// Weak reference to the manager of the list of subsurfaces for this surface.
    ///
    /// Used when reconstructing a `Surface` so that we can access
    /// the list of subsurfaces.
    subsurfaces_manager: Weak<Box<SubsurfaceManager>>,
    /// The pointer to the wlroots object that wraps a wl_surface.
    surface: *mut wlr_surface
}

impl Surface {
    pub(crate) unsafe fn new(surface: *mut wlr_surface) -> Self {
        if !(*surface).data.is_null() {
            panic!("Tried to construct a Surface from an already initialized wlr_surface");
        }
        let liveliness = Rc::new(AtomicBool::new(false));
        let handle = Rc::downgrade(&liveliness);
        let subsurfaces_manager = Rc::new(Surface::create_manager(surface));
        let weak_manager = Rc::downgrade(&subsurfaces_manager);
        (*surface).data = Box::into_raw(Box::new(InternalSurfaceState { handle,
                                                                        subsurfaces_manager:
                                                                            weak_manager }))
                          as _;
        let liveliness = Some(liveliness);
        Surface { liveliness,
                  subsurfaces_manager,
                  surface }
    }

    /// Create the subsurface manager and ensures theat the listeners are
    /// set up correctly to listen for subsurface creation and deletion.
    fn create_manager(surface: *mut wlr_surface) -> Box<SubsurfaceManager> {
        unsafe {
            let mut subsurfaces = vec![];
            wl_list_for_each!((*surface).subsurface_list, parent_link,
                              (subsurface: wlr_subsurface) => {
                                  subsurfaces.push(Subsurface::new(subsurface))
                              });
            let mut manager = SubsurfaceManager::new(subsurfaces);
            for sub_surface in &mut manager.subsurfaces() {
                wl_signal_add(&mut (*sub_surface.as_ptr()).events.destroy as *mut _ as _,
                              manager.subsurface_destroyed_listener() as _);
            }
            wl_signal_add(&mut (*surface).events.new_subsurface as *mut _ as _,
                          manager.subsurface_created_listener() as _);
            manager
        }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_surface {
        self.surface
    }

    /// Get the surface state.
    pub fn current_state<'surface>(&'surface mut self) -> SurfaceState<'surface> {
        unsafe {
            let state = (*self.surface).current;
            SurfaceState::new(state)
        }
    }

    /// Get the pending surface state.
    pub fn pending_state<'surface>(&'surface mut self) -> SurfaceState<'surface> {
        unsafe {
            let state = (*self.surface).current;
            SurfaceState::new(state)
        }
    }

    /// Gets a list of handles to the `Subsurface`s of this `Surface`.
    pub fn subsurfaces(&self) -> Vec<SubsurfaceHandle> {
        self.subsurfaces_manager.subsurfaces()
    }

    /// Get the texture of this surface.
    pub fn texture(&self) -> Texture {
        unsafe { Texture::from_ptr((*self.surface).texture) }
    }

    /// Get the lifetime bound role (if one exists) for this surface.
    pub fn role(&self) -> Option<String> {
        unsafe { c_to_rust_string((*self.surface).role) }
    }

    /// Whether or not this surface currently has an attached buffer.
    ///
    /// A surface has an attached buffer when it commits with a non-null buffer in its pending
    /// state.
    ///
    /// A surface will not have a buffer if it has never committed one, has
    /// committed a null buffer, or something went wrong with uploading the buffer.
    pub fn has_buffer(&self) -> bool {
        unsafe { wlr_surface_has_buffer(self.surface) }
    }

    /// Find a subsurface within this surface at the surface-local coordinates.
    ///
    /// Returns the surface and coordinates in the topmost surface coordinate system
    /// or None if no subsurface is found at that location.
    pub fn subsurface_at(&mut self,
                         sx: f64,
                         sy: f64,
                         sub_x: &mut f64,
                         sub_y: &mut f64)
                         -> Option<SubsurfaceHandle> {
        unsafe {
            let surface = wlr_surface_subsurface_at(self.surface, sx, sy, sub_x, sub_y);
            if surface.is_null() {
                return None
            }
            for subsurface in self.subsurfaces() {
                if subsurface.as_ptr() == surface {
                    return Some(subsurface)
                }
            }
            return None
        }
    }

    /// Create the subsurface implementation for this surface.
    pub fn make_subsurface(&mut self, parent: &mut Surface, id: u32) {
        unsafe { wlr_surface_make_subsurface(self.surface, parent.as_ptr(), id) }
    }

    /// Get the top of the subsurface tree for this surface.
    pub fn get_main_surface(&self) -> Option<SurfaceHandle> {
        unsafe {
            let surface = wlr_surface_get_main_surface(self.surface);
            if surface.is_null() {
                None
            } else {
                Some(SurfaceHandle::from_ptr(surface))
            }
        }
    }

    pub fn send_enter(&mut self, output: &mut Output) {
        unsafe { wlr_surface_send_enter(self.surface, output.as_ptr()) }
    }

    pub fn send_leave(&mut self, output: &mut Output) {
        unsafe { wlr_surface_send_leave(self.surface, output.as_ptr()) }
    }

    /// Send the frame done event.
    pub fn send_frame_done(&mut self, duration: Duration) {
        unsafe {
            // FIXME
            // This is converting from a u64 -> i64
            // Something bad could happen!
            let when = timespec { tv_sec: duration.as_secs() as i64,
                                  tv_nsec: duration.subsec_nanos() as i64 };
            wlr_surface_send_frame_done(self.surface, &when);
        }
    }

    /// Get the matrix used to convert the internal byte buffer to use in the
    /// surface.
    pub fn buffer_to_surface_matrix(&self) -> [f32; 9] {
        unsafe { (*self.surface).buffer_to_surface_matrix }
    }

    /// Get the matrix used to convert the surface back to the internal byte
    /// buffer.
    pub fn surface_to_buffer_matrix(&self) -> [f32; 9] {
        unsafe { (*self.surface).surface_to_buffer_matrix }
    }

    /// Creates a weak reference to a `Surface`.
    ///
    /// # Panics
    /// If this `Surface` is a previously upgraded `SurfaceHandle`
    /// then this function will panic.
    pub fn weak_reference(&self) -> SurfaceHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade a previously upgraded OutputHandle");
        SurfaceHandle { handle: Rc::downgrade(arc),
                        surface: self.surface,
                        subsurfaces_manager: Rc::downgrade(&self.subsurfaces_manager) }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Surface")
            .store(val, Ordering::Release);
    }

    unsafe fn from_handle(handle: &SurfaceHandle) -> Self {
        let data = (*handle.surface).data as *mut InternalSurfaceState;
        let subsurfaces_manager = (*data).subsurfaces_manager
                                         .clone()
                                         .upgrade()
                                         .expect("Could not upgrade subsurfaces list");
        Surface { liveliness: None,
                  subsurfaces_manager,
                  surface: handle.surface }
    }
}

impl SurfaceHandle {
    /// Creates an SurfaceHandle from the raw pointer, using the saved
    /// user data to recreate the memory model.
    pub(crate) unsafe fn from_ptr(surface: *mut wlr_surface) -> Self {
        let data = (*surface).data as *mut InternalSurfaceState;
        let handle = (*data).handle.clone();
        let subsurfaces_manager = (*data).subsurfaces_manager.clone();
        SurfaceHandle { handle,
                        surface,
                        subsurfaces_manager }
    }

    /// Upgrades the surface handle to a reference to the backing `Surface`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbound `Surface`
    /// which may live forever..
    /// But no surface lives forever and might be disconnected at any time.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Surface> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::AlreadyDropped)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(Surface::from_handle(self))
            })
    }

    /// Run a function on the referenced Surface, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the surface
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Surface does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Surface`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<R>
        where F: FnOnce(&mut Surface) -> R
    {
        let mut surface = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| runner(&mut surface)));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running surface callback, mutable lock \
                                                    was false for: {:?}",
                                                   surface);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }
}

impl Drop for Surface {
    fn drop(&mut self) {
        match self.liveliness {
            None => return,
            Some(ref liveliness) => {
                if Rc::strong_count(liveliness) != 1 {
                    return
                }
                wlr_log!(L_DEBUG, "Dropped surface {:p}", self.surface);
                let weak_count = Rc::weak_count(liveliness);
                if weak_count > 0 {
                    wlr_log!(L_DEBUG,
                             "Still {} weak pointers to Surface {:p}",
                             weak_count,
                             self.surface);
                }
            }
        }
        unsafe {
            let _ = Box::from_raw((*self.surface).data as *mut InternalSurfaceState);
            let manager =
                Rc::into_raw(self.subsurfaces_manager.clone()) as *mut Box<SubsurfaceManager>;
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*(*manager).subsurface_created_listener()).link as *mut _ as _);
            for _ in &mut (*manager).subsurfaces() {
                ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                              wl_list_remove,
                              &mut (*(*manager).subsurface_destroyed_listener()).link as *mut _
                              as _);
            }
        }
    }
}
<commit_msg>Added Surface::accepts_input<commit_after>//! TODO Documentation

use libc::c_double;
use std::panic;
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;

use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::{timespec, wlr_subsurface, wlr_surface, wlr_surface_get_main_surface,
                  wlr_surface_has_buffer, wlr_surface_make_subsurface, wlr_surface_send_enter,
                  wlr_surface_send_frame_done, wlr_surface_send_leave, wlr_surface_subsurface_at, wlr_surface_point_accepts_input};

use super::{Subsurface, SubsurfaceHandle, SubsurfaceManager, SurfaceState};
use Output;
use errors::{UpgradeHandleErr, UpgradeHandleResult};
use render::Texture;
use utils::c_to_rust_string;

/// The state stored in the wlr_surface user data.
struct InternalSurfaceState {
    /// Used to reconstruct a SurfaceHandle from just an *mut wlr_surface.
    handle: Weak<AtomicBool>,
    /// Weak reference to the manager for the list of subsurfaces.
    /// This is here so that we can reconstruct the Surface from a SurfaceHandle.
    subsurfaces_manager: Weak<Box<SubsurfaceManager>>
}

/// A Wayland object that represents the data that we display on the screen.
///
/// Most surfaces come from Wayland clients, though they can also be created
/// by the compositor directly.
#[derive(Debug)]
pub struct Surface {
    /// The structe that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `SurfaceHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `SurfaceHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The manager of the list of subsurfaces for this surface.
    ///
    /// When the subsurface destruction event fires the manager will deal with
    /// updating the list.
    ///
    /// When you have a reference to the Surface you can access its children
    /// through the getter for this list.
    subsurfaces_manager: Rc<Box<SubsurfaceManager>>,
    /// The pointer to the wlroots object that wraps a wl_surface.
    surface: *mut wlr_surface
}

/// See `Surface` for more information on how to use this structure.
#[derive(Clone, Debug)]
pub struct SurfaceHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the pointer associated with this handle,
    /// this can no longer be used.
    handle: Weak<AtomicBool>,
    /// Weak reference to the manager of the list of subsurfaces for this surface.
    ///
    /// Used when reconstructing a `Surface` so that we can access
    /// the list of subsurfaces.
    subsurfaces_manager: Weak<Box<SubsurfaceManager>>,
    /// The pointer to the wlroots object that wraps a wl_surface.
    surface: *mut wlr_surface
}

impl Surface {
    pub(crate) unsafe fn new(surface: *mut wlr_surface) -> Self {
        if !(*surface).data.is_null() {
            panic!("Tried to construct a Surface from an already initialized wlr_surface");
        }
        let liveliness = Rc::new(AtomicBool::new(false));
        let handle = Rc::downgrade(&liveliness);
        let subsurfaces_manager = Rc::new(Surface::create_manager(surface));
        let weak_manager = Rc::downgrade(&subsurfaces_manager);
        (*surface).data = Box::into_raw(Box::new(InternalSurfaceState { handle,
                                                                        subsurfaces_manager:
                                                                            weak_manager }))
                          as _;
        let liveliness = Some(liveliness);
        Surface { liveliness,
                  subsurfaces_manager,
                  surface }
    }

    /// Create the subsurface manager and ensures theat the listeners are
    /// set up correctly to listen for subsurface creation and deletion.
    fn create_manager(surface: *mut wlr_surface) -> Box<SubsurfaceManager> {
        unsafe {
            let mut subsurfaces = vec![];
            wl_list_for_each!((*surface).subsurface_list, parent_link,
                              (subsurface: wlr_subsurface) => {
                                  subsurfaces.push(Subsurface::new(subsurface))
                              });
            let mut manager = SubsurfaceManager::new(subsurfaces);
            for sub_surface in &mut manager.subsurfaces() {
                wl_signal_add(&mut (*sub_surface.as_ptr()).events.destroy as *mut _ as _,
                              manager.subsurface_destroyed_listener() as _);
            }
            wl_signal_add(&mut (*surface).events.new_subsurface as *mut _ as _,
                          manager.subsurface_created_listener() as _);
            manager
        }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_surface {
        self.surface
    }

    /// Get the surface state.
    pub fn current_state<'surface>(&'surface mut self) -> SurfaceState<'surface> {
        unsafe {
            let state = (*self.surface).current;
            SurfaceState::new(state)
        }
    }

    /// Get the pending surface state.
    pub fn pending_state<'surface>(&'surface mut self) -> SurfaceState<'surface> {
        unsafe {
            let state = (*self.surface).current;
            SurfaceState::new(state)
        }
    }

    /// Gets a list of handles to the `Subsurface`s of this `Surface`.
    pub fn subsurfaces(&self) -> Vec<SubsurfaceHandle> {
        self.subsurfaces_manager.subsurfaces()
    }

    /// Get the texture of this surface.
    pub fn texture(&self) -> Texture {
        unsafe { Texture::from_ptr((*self.surface).texture) }
    }

    /// Get the lifetime bound role (if one exists) for this surface.
    pub fn role(&self) -> Option<String> {
        unsafe { c_to_rust_string((*self.surface).role) }
    }

    /// Whether or not this surface currently has an attached buffer.
    ///
    /// A surface has an attached buffer when it commits with a non-null buffer in its pending
    /// state.
    ///
    /// A surface will not have a buffer if it has never committed one, has
    /// committed a null buffer, or something went wrong with uploading the buffer.
    pub fn has_buffer(&self) -> bool {
        unsafe { wlr_surface_has_buffer(self.surface) }
    }

    /// Determines if this surface accepts input or not at the provided surface local coordinates.
    pub fn accepts_input(&self, sx: c_double, sy: c_double) -> bool {
        unsafe {
            wlr_surface_point_accepts_input(self.surface, sx, sy)
        }
    }

    /// Find a subsurface within this surface at the surface-local coordinates.
    ///
    /// Returns the surface and coordinates in the topmost surface coordinate system
    /// or None if no subsurface is found at that location.
    pub fn subsurface_at(&mut self,
                         sx: f64,
                         sy: f64,
                         sub_x: &mut f64,
                         sub_y: &mut f64)
                         -> Option<SubsurfaceHandle> {
        unsafe {
            let surface = wlr_surface_subsurface_at(self.surface, sx, sy, sub_x, sub_y);
            if surface.is_null() {
                return None
            }
            for subsurface in self.subsurfaces() {
                if subsurface.as_ptr() == surface {
                    return Some(subsurface)
                }
            }
            return None
        }
    }

    /// Create the subsurface implementation for this surface.
    pub fn make_subsurface(&mut self, parent: &mut Surface, id: u32) {
        unsafe { wlr_surface_make_subsurface(self.surface, parent.as_ptr(), id) }
    }

    /// Get the top of the subsurface tree for this surface.
    pub fn get_main_surface(&self) -> Option<SurfaceHandle> {
        unsafe {
            let surface = wlr_surface_get_main_surface(self.surface);
            if surface.is_null() {
                None
            } else {
                Some(SurfaceHandle::from_ptr(surface))
            }
        }
    }

    pub fn send_enter(&mut self, output: &mut Output) {
        unsafe { wlr_surface_send_enter(self.surface, output.as_ptr()) }
    }

    pub fn send_leave(&mut self, output: &mut Output) {
        unsafe { wlr_surface_send_leave(self.surface, output.as_ptr()) }
    }

    /// Send the frame done event.
    pub fn send_frame_done(&mut self, duration: Duration) {
        unsafe {
            // FIXME
            // This is converting from a u64 -> i64
            // Something bad could happen!
            let when = timespec { tv_sec: duration.as_secs() as i64,
                                  tv_nsec: duration.subsec_nanos() as i64 };
            wlr_surface_send_frame_done(self.surface, &when);
        }
    }

    /// Get the matrix used to convert the internal byte buffer to use in the
    /// surface.
    pub fn buffer_to_surface_matrix(&self) -> [f32; 9] {
        unsafe { (*self.surface).buffer_to_surface_matrix }
    }

    /// Get the matrix used to convert the surface back to the internal byte
    /// buffer.
    pub fn surface_to_buffer_matrix(&self) -> [f32; 9] {
        unsafe { (*self.surface).surface_to_buffer_matrix }
    }

    /// Creates a weak reference to a `Surface`.
    ///
    /// # Panics
    /// If this `Surface` is a previously upgraded `SurfaceHandle`
    /// then this function will panic.
    pub fn weak_reference(&self) -> SurfaceHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade a previously upgraded OutputHandle");
        SurfaceHandle { handle: Rc::downgrade(arc),
                        surface: self.surface,
                        subsurfaces_manager: Rc::downgrade(&self.subsurfaces_manager) }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Surface")
            .store(val, Ordering::Release);
    }

    unsafe fn from_handle(handle: &SurfaceHandle) -> Self {
        let data = (*handle.surface).data as *mut InternalSurfaceState;
        let subsurfaces_manager = (*data).subsurfaces_manager
                                         .clone()
                                         .upgrade()
                                         .expect("Could not upgrade subsurfaces list");
        Surface { liveliness: None,
                  subsurfaces_manager,
                  surface: handle.surface }
    }
}

impl SurfaceHandle {
    /// Creates an SurfaceHandle from the raw pointer, using the saved
    /// user data to recreate the memory model.
    pub(crate) unsafe fn from_ptr(surface: *mut wlr_surface) -> Self {
        let data = (*surface).data as *mut InternalSurfaceState;
        let handle = (*data).handle.clone();
        let subsurfaces_manager = (*data).subsurfaces_manager.clone();
        SurfaceHandle { handle,
                        surface,
                        subsurfaces_manager }
    }

    /// Upgrades the surface handle to a reference to the backing `Surface`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbound `Surface`
    /// which may live forever..
    /// But no surface lives forever and might be disconnected at any time.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Surface> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::AlreadyDropped)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(Surface::from_handle(self))
            })
    }

    /// Run a function on the referenced Surface, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the surface
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Surface does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Surface`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<R>
        where F: FnOnce(&mut Surface) -> R
    {
        let mut surface = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| runner(&mut surface)));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running surface callback, mutable lock \
                                                    was false for: {:?}",
                                                   surface);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }
}

impl Drop for Surface {
    fn drop(&mut self) {
        match self.liveliness {
            None => return,
            Some(ref liveliness) => {
                if Rc::strong_count(liveliness) != 1 {
                    return
                }
                wlr_log!(L_DEBUG, "Dropped surface {:p}", self.surface);
                let weak_count = Rc::weak_count(liveliness);
                if weak_count > 0 {
                    wlr_log!(L_DEBUG,
                             "Still {} weak pointers to Surface {:p}",
                             weak_count,
                             self.surface);
                }
            }
        }
        unsafe {
            let _ = Box::from_raw((*self.surface).data as *mut InternalSurfaceState);
            let manager =
                Rc::into_raw(self.subsurfaces_manager.clone()) as *mut Box<SubsurfaceManager>;
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_list_remove,
                          &mut (*(*manager).subsurface_created_listener()).link as *mut _ as _);
            for _ in &mut (*manager).subsurfaces() {
                ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                              wl_list_remove,
                              &mut (*(*manager).subsurface_destroyed_listener()).link as *mut _
                              as _);
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Echo everything received on STDIN to STDOUT and STDERR.

use futures_util::{FutureExt, SinkExt, StreamExt, TryFutureExt};

use tokio::codec::{FramedRead, FramedWrite, LinesCodec, LinesCodecError};
use tokio::future::ready;
use tokio_executor::threadpool::Builder;
use tokio_fs::{stderr, stdin, stdout};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let pool = Builder::new().pool_size(1).build();

    pool.spawn(
        async {
            let mut input = FramedRead::new(stdin(), LinesCodec::new());
            let mut output = FramedWrite::new(stdout(), LinesCodec::new());
            let mut error = FramedWrite::new(stderr(), LinesCodec::new());

            while let Some(line) = input.next().await {
                let line = line?;
                output.send(format!("OUT: {}", line)).await?;
                error.send(format!("ERR: {}", line)).await?;
            }
            Ok(())
        }
            .map_err(|e: LinesCodecError| panic!(e))
            .then(|_| ready(())),
    );

    pool.shutdown_on_idle().await;
    Ok(())
}
<commit_msg>Fix for rust-lang/rust#64477 (#1618)<commit_after>//! Echo everything received on STDIN to STDOUT and STDERR.

use futures_util::{FutureExt, SinkExt, StreamExt, TryFutureExt};

use tokio::codec::{FramedRead, FramedWrite, LinesCodec, LinesCodecError};
use tokio::future::ready;
use tokio_executor::threadpool::Builder;
use tokio_fs::{stderr, stdin, stdout};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let pool = Builder::new().pool_size(1).build();

    pool.spawn(
        async {
            let mut input = FramedRead::new(stdin(), LinesCodec::new());
            let mut output = FramedWrite::new(stdout(), LinesCodec::new());
            let mut error = FramedWrite::new(stderr(), LinesCodec::new());

            while let Some(line) = input.next().await {
                let line = line?;
                // https://github.com/rust-lang/rust/pull/64856
                let s = format!("OUT: {}", line);
                output.send(s).await?;
                let s = format!("ERR: {}", line);
                error.send(s).await?;
            }
            Ok(())
        }
            .map_err(|e: LinesCodecError| panic!(e))
            .then(|_| ready(())),
    );

    pool.shutdown_on_idle().await;
    Ok(())
}
<|endoftext|>


<commit_before>#[derive(Eq, PartialEq)]
enum Direction { North, East, South, West, Empty, }

struct Table {
    w: i32,
    h: i32,
}

struct Robot {
    x: i32,
    y: i32,
    d: Direction,
    t: Table,
}

impl Direction {
    fn string(&self) -> String {
        let s = match *self {
            Direction::North => "North",
            Direction::East => "East",
            Direction::South => "South",
            Direction::West => "West",
            _ => "Empty",
        };

        s.to_string()
    }
}

impl Default for Robot {
    fn default() -> Robot {
        let table = Table{w: 5, h: 5};

        Robot{x: 0, y: 0, d: Direction::Empty, t: table}
    }
}

impl Table {
    fn valid_pos(&self, x: i32, y: i32) -> bool {
        x >= 0 && x < self.w && y >= 0 && y < self.h
    }
}

impl Robot {
    fn place(&mut self, x: i32, y: i32, d: Direction) {
        if self.t.valid_pos(x, y) {
            self.x = x;
            self.y = y;
            self.d = d;
        }
    }

    fn right(&mut self) {
        let d = match self.d {
            Direction::North => Direction::East,
            Direction::East => Direction::South,
            Direction::South => Direction::West,
            Direction::West => Direction::North,
            _ => Direction::Empty,
        };

        self.d = d;
    }

    fn left(&mut self) {
        let d = match self.d {
            Direction::North => Direction::West,
            Direction::West => Direction::South,
            Direction::South => Direction::East,
            Direction::East => Direction::North,
            _ => Direction::Empty,
        };

        self.d = d;
    }

    fn step(&mut self) {
        match self.d {
            Direction::North => if self.t.valid_pos(self.x, self.y + 1) {self.y += 1;},
            Direction::East => if self.t.valid_pos(self.x + 1, self.y) {self.x += 1;},
            Direction::South => if self.t.valid_pos(self.x, self.y - 1) {self.y -= 1;},
            Direction::West => if self.t.valid_pos(self.x - 1, self.y) {self.y -= 1;},
            _ => (),
        }
    }

    fn report(&self) {
        println!("{}, {}, {}", self.x, self.y, self.d.string());
    }
}

fn main() {
    let mut robot: Robot = Default::default();
}
<commit_msg>Building parser and evaluator<commit_after>#[derive(Eq, PartialEq)]
enum Direction { North, East, South, West, Unplaced, }

use Direction::*;

struct Table {
    w: i32,
    h: i32,
}

struct Robot {
    x: i32,
    y: i32,
    d: Direction,
    t: Table,
}

impl Direction {
    fn from_string(d: String) -> Direction {
        match d {
            "NORTH" => North,
            "EAST" => East,
            "SOUTH" => South,
            "WEST" => West,
            _ => Unplaced,
        }
    }

    fn to_string(&self) -> String {
        let s = match *self {
            North => "NORTH",
            East => "EAST",
            South => "SOUTH",
            West => "WEST",
            _ => "UNPLACED",
        };

        s.to_string()
    }
}

impl Default for Robot {
    fn default() -> Robot {
        let table = Table{w: 5, h: 5};

        Robot{x: 0, y: 0, d: Unplaced, t: table}
    }
}

impl Table {
    fn valid_pos(&self, x: i32, y: i32) -> bool {
        x >= 0 && x < self.w && y >= 0 && y < self.h
    }
}

impl Robot {
    fn place(&mut self, x: i32, y: i32, d: Direction) {
        if self.t.valid_pos(x, y) && d != Unplaced {
            self.x = x;
            self.y = y;
            self.d = d;
        }
    }

    fn right(&mut self) {
        let d = match self.d {
            North => East,
            East => South,
            South => West,
            West => North,
            _ => Unplaced,
        };

        self.d = d;
    }

    fn left(&mut self) {
        let d = match self.d {
            North => West,
            West => South,
            South => East,
            East => North,
            _ => Unplaced,
        };

        self.d = d;
    }

    fn step(&mut self) {
        match self.d {
            North => if self.t.valid_pos(self.x, self.y + 1) {self.y += 1;},
            East => if self.t.valid_pos(self.x + 1, self.y) {self.x += 1;},
            South => if self.t.valid_pos(self.x, self.y - 1) {self.y -= 1;},
            West => if self.t.valid_pos(self.x - 1, self.y) {self.y -= 1;},
            _ => (),
        }
    }

    fn report(&self) {
        println!("{}, {}, {}", self.x, self.y, self.d.to_string());
    }
}

fn parse_place(args: &[&str]) -> (i32, i32, Direction) {
    (1, 2, East)
}

fn main() {
    let mut robot: Robot = Default::default();
    let commands = "MOVE
                    MOVE
                    LEFT
                    PLACE 1,2,EAST
                    MOVE
                    MOVE
                    LEFT
                    MOVE
                    REPORT";

    let parsed: Vec<&str> = commands.split("\n").map(|c| c.trim()).collect();

    for c in parsed {
        let args: Vec<&str> = c.split(" ").collect();

        if let Some(arg) = args.first() {
            match *arg {
                "PLACE" => {
                    let (x, y, d) = parse_place(args.tail());
                    robot.place(x, y, d);
                },
                "MOVE" => robot.step(),
                "LEFT" => robot.left(),
                "RIGHT" => robot.right(),
                "REPORT" => robot.report(),
                _ => (),
            }
        }
    }
}
<|endoftext|>