<commit_before>use std::error::Error as StdError;
use std::fmt::{Display, Formatter, Result as FmtResult};

use serde::ser::{self, Serialize};

pub mod pretty;

/// Serializes `value` and returns it as string.
pub fn to_string<T>(value: &T) -> Result<String>
    where T: Serialize
{
    let mut s = Serializer {
        output: String::new(),
        pretty: None,
        struct_names: false,
    };
    value.serialize(&mut s)?;
    Ok(s.output)
}

type Result<T> = ::std::result::Result<T, Error>;

/// Serialization error.
#[derive(Clone, Debug, PartialEq)]
pub enum Error {
    /// A custom error emitted by a serialized value.
    Message(String),
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match *self {
            Error::Message(ref e) => write!(f, "Custom message: {}", e),
        }
    }
}

impl ser::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error::Message(msg.to_string())
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Message(ref e) => e,
        }
    }
}

struct Pretty {
    indent: usize,
}

pub struct Serializer {
    output: String,
    pretty: Option<Pretty>,
    struct_names: bool,
}

impl Serializer {
    fn start_indent(&mut self) {
        if let Some(ref mut pretty) = self.pretty {
            pretty.indent += 1;
            self.output += "\n";
        }
    }

    fn indent(&mut self) {
        if let Some(ref pretty) = self.pretty {
            self.output.extend((0..pretty.indent * 4).map(|_| " "));
        }
    }

    fn end_indent(&mut self) {
        if let Some(ref mut pretty) = self.pretty {
            pretty.indent -= 1;
            self.output.extend((0..pretty.indent * 4).map(|_| " "));
        }
    }
}

impl<'a> ser::Serializer for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    type SerializeSeq = Self;
    type SerializeTuple = Self;
    type SerializeTupleStruct = Self;
    type SerializeTupleVariant = Self;
    type SerializeMap = Self;
    type SerializeStruct = Self;
    type SerializeStructVariant = Self;

    fn serialize_bool(self, v: bool) -> Result<()> {
        self.output += if v { "true" } else { "false" };
        Ok(())
    }

    fn serialize_i8(self, v: i8) -> Result<()> {
        self.serialize_i64(v as i64)
    }

    fn serialize_i16(self, v: i16) -> Result<()> {
        self.serialize_i64(v as i64)
    }

    fn serialize_i32(self, v: i32) -> Result<()> {
        self.serialize_i64(v as i64)
    }

    fn serialize_i64(self, v: i64) -> Result<()> {
        // TODO optimize
        self.output += &v.to_string();
        Ok(())
    }

    fn serialize_u8(self, v: u8) -> Result<()> {
        self.serialize_u64(v as u64)
    }

    fn serialize_u16(self, v: u16) -> Result<()> {
        self.serialize_u64(v as u64)
    }

    fn serialize_u32(self, v: u32) -> Result<()> {
        self.serialize_u64(v as u64)
    }

    fn serialize_u64(self, v: u64) -> Result<()> {
        self.output += &v.to_string();
        Ok(())
    }

    fn serialize_f32(self, v: f32) -> Result<()> {
        self.serialize_f64(v as f64)
    }

    fn serialize_f64(self, v: f64) -> Result<()> {
        self.output += &v.to_string();
        Ok(())
    }

    fn serialize_char(self, v: char) -> Result<()> {
        self.output += "'";
        if v == '\\' || v == '\'' {
            self.output.push('\\');
        }
        self.output.push(v);
        self.output += "'";
        Ok(())
    }

    fn serialize_str(self, v: &str) -> Result<()> {
        self.output += "\"";
        for char in v.chars() {
            if char == '\\' || char == '"' {
                self.output.push('\\');
            }
            self.output.push(char);
        }
        self.output += "\"";
        Ok(())
    }

    fn serialize_bytes(self, v: &[u8]) -> Result<()> {
        use serde::ser::SerializeSeq;
        let mut seq = self.serialize_seq(Some(v.len()))?;
        for byte in v {
            seq.serialize_element(byte)?;
        }
        seq.end()
    }

    fn serialize_none(self) -> Result<()> {
        self.output += "None";

        Ok(())
    }

    fn serialize_some<T>(self, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        self.output += "Some(";
        value.serialize(&mut *self)?;
        self.output += ")";

        Ok(())
    }

    fn serialize_unit(self) -> Result<()> {
        self.output += "()";

        Ok(())
    }

    fn serialize_unit_struct(self, name: &'static str) -> Result<()> {
        if self.struct_names {
            self.output += name;

            Ok(())
        } else {
            self.serialize_unit()
        }
    }

    fn serialize_unit_variant(
        self,
        _: &'static str,
        _: u32,
        variant: &'static str
    ) -> Result<()> {
        self.output += variant;

        Ok(())
    }

    fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        if self.struct_names {
            self.output += name;
        }

        self.output += "(";
        value.serialize(&mut *self)?;
        self.output += ")";
        Ok(())
    }

    fn serialize_newtype_variant<T>(
        self,
        _: &'static str,
        _: u32,
        variant: &'static str,
        value: &T
    ) -> Result<()>
        where T: ?Sized + Serialize
    {
        self.output += variant;
        self.output += "(";
        value.serialize(&mut *self)?;
        self.output += ")";
        Ok(())
    }

    fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq> {
        self.output += "[";

        self.start_indent();

        Ok(self)
    }

    fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple> {
        self.output += "(";

        Ok(self)
    }

    fn serialize_tuple_struct(
        self,
        name: &'static str,
        len: usize
    ) -> Result<Self::SerializeTupleStruct> {
        if self.struct_names {
            self.output += name;
        }

        self.serialize_tuple(len)
    }

    fn serialize_tuple_variant(
        self,
        _: &'static str,
        _: u32,
        variant: &'static str,
        _: usize
    ) -> Result<Self::SerializeTupleVariant> {
        self.output += variant;
        self.output += "(";

        self.start_indent();

        Ok(self)
    }

    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
        self.output += "{";

        self.start_indent();

        Ok(self)
    }

    fn serialize_struct(
        self,
        name: &'static str,
        _: usize
    ) -> Result<Self::SerializeStruct> {
        if self.struct_names {
            self.output += name;
        }
        self.output += "(";

        self.start_indent();

        Ok(self)
    }

    fn serialize_struct_variant(
        self,
        _: &'static str,
        _: u32,
        variant: &'static str,
        _: usize
    ) -> Result<Self::SerializeStructVariant> {
        self.output += variant;
        self.output += "(";

        self.start_indent();

        Ok(self)
    }
}

impl<'a> ser::SerializeSeq for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        self.indent();

        value.serialize(&mut **self)?;
        self.output += ",";

        if self.pretty.is_some() {
            self.output += "\n";
        }

        Ok(())
    }

    fn end(self) -> Result<()> {
        self.end_indent();

        self.output += "]";
        Ok(())
    }
}

impl<'a> ser::SerializeTuple for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        value.serialize(&mut **self)?;
        self.output += ",";

        if self.pretty.is_some() {
            self.output += " ";
        }

        Ok(())
    }

    fn end(self) -> Result<()> {
        if self.pretty.is_some() {
            self.output.pop();
            self.output.pop();
        }

        self.output += ")";

        Ok(())
    }
}

// Same thing but for tuple structs.
impl<'a> ser::SerializeTupleStruct for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        ser::SerializeTuple::serialize_element(self, value)
    }

    fn end(self) -> Result<()> {
        ser::SerializeTuple::end(self)
    }
}

impl<'a> ser::SerializeTupleVariant for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        ser::SerializeTuple::serialize_element(self, value)
    }

    fn end(self) -> Result<()> {
        ser::SerializeTuple::end(self)
    }
}

impl<'a> ser::SerializeMap for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    fn serialize_key<T>(&mut self, key: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        self.indent();

        key.serialize(&mut **self)
    }

    fn serialize_value<T>(&mut self, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        self.output += ":";

        if self.pretty.is_some() {
            self.output += " ";
        }

        value.serialize(&mut **self)?;
        self.output += ",";

        if self.pretty.is_some() {
            self.output += "\n";
        }

        Ok(())
    }

    fn end(self) -> Result<()> {
        self.end_indent();

        self.output += "}";
        Ok(())
    }
}

impl<'a> ser::SerializeStruct for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        self.indent();

        self.output += key;
        self.output += ":";

        if self.pretty.is_some() {
            self.output += " ";
        }

        value.serialize(&mut **self)?;
        self.output += ",";

        if self.pretty.is_some() {
            self.output += "\n";
        }

        Ok(())
    }

    fn end(self) -> Result<()> {
        self.end_indent();

        self.output += ")";
        Ok(())
    }
}

impl<'a> ser::SerializeStructVariant for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        ser::SerializeStruct::serialize_field(self, key, value)
    }

    fn end(self) -> Result<()> {
        ser::SerializeStruct::end(self)
    }
}

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

    #[derive(Serialize)]
    struct EmptyStruct1;

    #[derive(Serialize)]
    struct EmptyStruct2 {}

    #[derive(Serialize)]
    struct MyStruct { x: f32, y: f32 }

    #[derive(Serialize)]
    enum MyEnum {
        A,
        B(bool),
        C(bool, f32),
        D { a: i32, b: i32 }
    }

    #[test]
    fn test_empty_struct() {
        assert_eq!(to_string(&EmptyStruct1).unwrap(), "()");
        assert_eq!(to_string(&EmptyStruct2 {}).unwrap(), "()");
    }

    #[test]
    fn test_struct() {
        let my_struct = MyStruct { x: 4.0, y: 7.0 };

        assert_eq!(to_string(&my_struct).unwrap(), "(x:4,y:7,)");

        #[derive(Serialize)]
        struct NewType(i32);

        assert_eq!(to_string(&NewType(42)).unwrap(), "(42)");

        #[derive(Serialize)]
        struct TupleStruct(f32, f32);

        assert_eq!(to_string(&TupleStruct(2.0, 5.0)).unwrap(), "(2,5,)");
    }

    #[test]
    fn test_option() {
        assert_eq!(to_string(&Some(1u8)).unwrap(), "Some(1)");
        assert_eq!(to_string(&None::<u8>).unwrap(), "None");
    }

    #[test]
    fn test_enum() {
        assert_eq!(to_string(&MyEnum::A).unwrap(), "A");
        assert_eq!(to_string(&MyEnum::B(true)).unwrap(), "B(true)");
        assert_eq!(to_string(&MyEnum::C(true, 3.5)).unwrap(), "C(true,3.5,)");
        assert_eq!(to_string(&MyEnum::D { a: 2, b: 3 }).unwrap(), "D(a:2,b:3,)");
    }

    #[test]
    fn test_array() {
        let empty: [i32; 0] = [];
        assert_eq!(to_string(&empty).unwrap(), "()");
        let empty_ref: &[i32] = ∅
        assert_eq!(to_string(&empty_ref).unwrap(), "[]");

        assert_eq!(to_string(&[2, 3, 4i32]).unwrap(), "(2,3,4,)");
        assert_eq!(to_string(&(&[2, 3, 4i32] as &[i32])).unwrap(), "[2,3,4,]");
    }

    #[test]
    fn test_map() {
        use std::collections::HashMap;

        let mut map = HashMap::new();
        map.insert((true, false), 4);
        map.insert((false, false), 123);

        let s = to_string(&map).unwrap();
        s.starts_with("{");
        s.contains("(true,false,):4");
        s.contains("(false,false,):123");
        s.ends_with("}");
    }

    #[test]
    fn test_string() {
        assert_eq!(to_string(&"Some string").unwrap(), "\"Some string\"");
    }

    #[test]
    fn test_char() {
        assert_eq!(to_string(&'c').unwrap(), "'c'");
    }

    #[test]
    fn test_escape() {
        assert_eq!(to_string(&r#""Quoted""#).unwrap(), r#""\"Quoted\"""#);
    }
}
<commit_msg>Use CRLF for serialization on Windows<commit_after>use std::error::Error as StdError;
use std::fmt::{Display, Formatter, Result as FmtResult};

use serde::ser::{self, Serialize};

pub mod pretty;

#[cfg(not(target_os = "windows"))]
const NEWLINE: &str = "\n";

#[cfg(target_os = "windows")]
const NEWLINE: &str = "\r\n";

/// Serializes `value` and returns it as string.
pub fn to_string<T>(value: &T) -> Result<String>
    where T: Serialize
{
    let mut s = Serializer {
        output: String::new(),
        pretty: None,
        struct_names: false,
    };
    value.serialize(&mut s)?;
    Ok(s.output)
}

type Result<T> = ::std::result::Result<T, Error>;

/// Serialization error.
#[derive(Clone, Debug, PartialEq)]
pub enum Error {
    /// A custom error emitted by a serialized value.
    Message(String),
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match *self {
            Error::Message(ref e) => write!(f, "Custom message: {}", e),
        }
    }
}

impl ser::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error::Message(msg.to_string())
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Message(ref e) => e,
        }
    }
}

struct Pretty {
    indent: usize,
}

pub struct Serializer {
    output: String,
    pretty: Option<Pretty>,
    struct_names: bool,
}

impl Serializer {
    fn start_indent(&mut self) {
        if let Some(ref mut pretty) = self.pretty {
            pretty.indent += 1;
            self.output += NEWLINE;
        }
    }

    fn indent(&mut self) {
        if let Some(ref pretty) = self.pretty {
            self.output.extend((0..pretty.indent * 4).map(|_| " "));
        }
    }

    fn end_indent(&mut self) {
        if let Some(ref mut pretty) = self.pretty {
            pretty.indent -= 1;
            self.output.extend((0..pretty.indent * 4).map(|_| " "));
        }
    }
}

impl<'a> ser::Serializer for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    type SerializeSeq = Self;
    type SerializeTuple = Self;
    type SerializeTupleStruct = Self;
    type SerializeTupleVariant = Self;
    type SerializeMap = Self;
    type SerializeStruct = Self;
    type SerializeStructVariant = Self;

    fn serialize_bool(self, v: bool) -> Result<()> {
        self.output += if v { "true" } else { "false" };
        Ok(())
    }

    fn serialize_i8(self, v: i8) -> Result<()> {
        self.serialize_i64(v as i64)
    }

    fn serialize_i16(self, v: i16) -> Result<()> {
        self.serialize_i64(v as i64)
    }

    fn serialize_i32(self, v: i32) -> Result<()> {
        self.serialize_i64(v as i64)
    }

    fn serialize_i64(self, v: i64) -> Result<()> {
        // TODO optimize
        self.output += &v.to_string();
        Ok(())
    }

    fn serialize_u8(self, v: u8) -> Result<()> {
        self.serialize_u64(v as u64)
    }

    fn serialize_u16(self, v: u16) -> Result<()> {
        self.serialize_u64(v as u64)
    }

    fn serialize_u32(self, v: u32) -> Result<()> {
        self.serialize_u64(v as u64)
    }

    fn serialize_u64(self, v: u64) -> Result<()> {
        self.output += &v.to_string();
        Ok(())
    }

    fn serialize_f32(self, v: f32) -> Result<()> {
        self.serialize_f64(v as f64)
    }

    fn serialize_f64(self, v: f64) -> Result<()> {
        self.output += &v.to_string();
        Ok(())
    }

    fn serialize_char(self, v: char) -> Result<()> {
        self.output += "'";
        if v == '\\' || v == '\'' {
            self.output.push('\\');
        }
        self.output.push(v);
        self.output += "'";
        Ok(())
    }

    fn serialize_str(self, v: &str) -> Result<()> {
        self.output += "\"";
        for char in v.chars() {
            if char == '\\' || char == '"' {
                self.output.push('\\');
            }
            self.output.push(char);
        }
        self.output += "\"";
        Ok(())
    }

    fn serialize_bytes(self, v: &[u8]) -> Result<()> {
        use serde::ser::SerializeSeq;
        let mut seq = self.serialize_seq(Some(v.len()))?;
        for byte in v {
            seq.serialize_element(byte)?;
        }
        seq.end()
    }

    fn serialize_none(self) -> Result<()> {
        self.output += "None";

        Ok(())
    }

    fn serialize_some<T>(self, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        self.output += "Some(";
        value.serialize(&mut *self)?;
        self.output += ")";

        Ok(())
    }

    fn serialize_unit(self) -> Result<()> {
        self.output += "()";

        Ok(())
    }

    fn serialize_unit_struct(self, name: &'static str) -> Result<()> {
        if self.struct_names {
            self.output += name;

            Ok(())
        } else {
            self.serialize_unit()
        }
    }

    fn serialize_unit_variant(
        self,
        _: &'static str,
        _: u32,
        variant: &'static str
    ) -> Result<()> {
        self.output += variant;

        Ok(())
    }

    fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        if self.struct_names {
            self.output += name;
        }

        self.output += "(";
        value.serialize(&mut *self)?;
        self.output += ")";
        Ok(())
    }

    fn serialize_newtype_variant<T>(
        self,
        _: &'static str,
        _: u32,
        variant: &'static str,
        value: &T
    ) -> Result<()>
        where T: ?Sized + Serialize
    {
        self.output += variant;
        self.output += "(";
        value.serialize(&mut *self)?;
        self.output += ")";
        Ok(())
    }

    fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq> {
        self.output += "[";

        self.start_indent();

        Ok(self)
    }

    fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple> {
        self.output += "(";

        Ok(self)
    }

    fn serialize_tuple_struct(
        self,
        name: &'static str,
        len: usize
    ) -> Result<Self::SerializeTupleStruct> {
        if self.struct_names {
            self.output += name;
        }

        self.serialize_tuple(len)
    }

    fn serialize_tuple_variant(
        self,
        _: &'static str,
        _: u32,
        variant: &'static str,
        _: usize
    ) -> Result<Self::SerializeTupleVariant> {
        self.output += variant;
        self.output += "(";

        self.start_indent();

        Ok(self)
    }

    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
        self.output += "{";

        self.start_indent();

        Ok(self)
    }

    fn serialize_struct(
        self,
        name: &'static str,
        _: usize
    ) -> Result<Self::SerializeStruct> {
        if self.struct_names {
            self.output += name;
        }
        self.output += "(";

        self.start_indent();

        Ok(self)
    }

    fn serialize_struct_variant(
        self,
        _: &'static str,
        _: u32,
        variant: &'static str,
        _: usize
    ) -> Result<Self::SerializeStructVariant> {
        self.output += variant;
        self.output += "(";

        self.start_indent();

        Ok(self)
    }
}

impl<'a> ser::SerializeSeq for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        self.indent();

        value.serialize(&mut **self)?;
        self.output += ",";

        if self.pretty.is_some() {
            self.output += NEWLINE;
        }

        Ok(())
    }

    fn end(self) -> Result<()> {
        self.end_indent();

        self.output += "]";
        Ok(())
    }
}

impl<'a> ser::SerializeTuple for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T>(&mut self, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        value.serialize(&mut **self)?;
        self.output += ",";

        if self.pretty.is_some() {
            self.output += " ";
        }

        Ok(())
    }

    fn end(self) -> Result<()> {
        if self.pretty.is_some() {
            self.output.pop();
            self.output.pop();
        }

        self.output += ")";

        Ok(())
    }
}

// Same thing but for tuple structs.
impl<'a> ser::SerializeTupleStruct for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        ser::SerializeTuple::serialize_element(self, value)
    }

    fn end(self) -> Result<()> {
        ser::SerializeTuple::end(self)
    }
}

impl<'a> ser::SerializeTupleVariant for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T>(&mut self, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        ser::SerializeTuple::serialize_element(self, value)
    }

    fn end(self) -> Result<()> {
        ser::SerializeTuple::end(self)
    }
}

impl<'a> ser::SerializeMap for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    fn serialize_key<T>(&mut self, key: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        self.indent();

        key.serialize(&mut **self)
    }

    fn serialize_value<T>(&mut self, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        self.output += ":";

        if self.pretty.is_some() {
            self.output += " ";
        }

        value.serialize(&mut **self)?;
        self.output += ",";

        if self.pretty.is_some() {
            self.output += NEWLINE;
        }

        Ok(())
    }

    fn end(self) -> Result<()> {
        self.end_indent();

        self.output += "}";
        Ok(())
    }
}

impl<'a> ser::SerializeStruct for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        self.indent();

        self.output += key;
        self.output += ":";

        if self.pretty.is_some() {
            self.output += " ";
        }

        value.serialize(&mut **self)?;
        self.output += ",";

        if self.pretty.is_some() {
            self.output += NEWLINE;
        }

        Ok(())
    }

    fn end(self) -> Result<()> {
        self.end_indent();

        self.output += ")";
        Ok(())
    }
}

impl<'a> ser::SerializeStructVariant for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
        where T: ?Sized + Serialize
    {
        ser::SerializeStruct::serialize_field(self, key, value)
    }

    fn end(self) -> Result<()> {
        ser::SerializeStruct::end(self)
    }
}

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

    #[derive(Serialize)]
    struct EmptyStruct1;

    #[derive(Serialize)]
    struct EmptyStruct2 {}

    #[derive(Serialize)]
    struct MyStruct { x: f32, y: f32 }

    #[derive(Serialize)]
    enum MyEnum {
        A,
        B(bool),
        C(bool, f32),
        D { a: i32, b: i32 }
    }

    #[test]
    fn test_empty_struct() {
        assert_eq!(to_string(&EmptyStruct1).unwrap(), "()");
        assert_eq!(to_string(&EmptyStruct2 {}).unwrap(), "()");
    }

    #[test]
    fn test_struct() {
        let my_struct = MyStruct { x: 4.0, y: 7.0 };

        assert_eq!(to_string(&my_struct).unwrap(), "(x:4,y:7,)");

        #[derive(Serialize)]
        struct NewType(i32);

        assert_eq!(to_string(&NewType(42)).unwrap(), "(42)");

        #[derive(Serialize)]
        struct TupleStruct(f32, f32);

        assert_eq!(to_string(&TupleStruct(2.0, 5.0)).unwrap(), "(2,5,)");
    }

    #[test]
    fn test_option() {
        assert_eq!(to_string(&Some(1u8)).unwrap(), "Some(1)");
        assert_eq!(to_string(&None::<u8>).unwrap(), "None");
    }

    #[test]
    fn test_enum() {
        assert_eq!(to_string(&MyEnum::A).unwrap(), "A");
        assert_eq!(to_string(&MyEnum::B(true)).unwrap(), "B(true)");
        assert_eq!(to_string(&MyEnum::C(true, 3.5)).unwrap(), "C(true,3.5,)");
        assert_eq!(to_string(&MyEnum::D { a: 2, b: 3 }).unwrap(), "D(a:2,b:3,)");
    }

    #[test]
    fn test_array() {
        let empty: [i32; 0] = [];
        assert_eq!(to_string(&empty).unwrap(), "()");
        let empty_ref: &[i32] = ∅
        assert_eq!(to_string(&empty_ref).unwrap(), "[]");

        assert_eq!(to_string(&[2, 3, 4i32]).unwrap(), "(2,3,4,)");
        assert_eq!(to_string(&(&[2, 3, 4i32] as &[i32])).unwrap(), "[2,3,4,]");
    }

    #[test]
    fn test_map() {
        use std::collections::HashMap;

        let mut map = HashMap::new();
        map.insert((true, false), 4);
        map.insert((false, false), 123);

        let s = to_string(&map).unwrap();
        s.starts_with("{");
        s.contains("(true,false,):4");
        s.contains("(false,false,):123");
        s.ends_with("}");
    }

    #[test]
    fn test_string() {
        assert_eq!(to_string(&"Some string").unwrap(), "\"Some string\"");
    }

    #[test]
    fn test_char() {
        assert_eq!(to_string(&'c').unwrap(), "'c'");
    }

    #[test]
    fn test_escape() {
        assert_eq!(to_string(&r#""Quoted""#).unwrap(), r#""\"Quoted\"""#);
    }
}
<|endoftext|>


<commit_before>use proto::{server, NewService};
use proto::proto::pipeline;
use tokio_service::Service;
use tokio::LoopHandle;
use empty::Empty;
use futures::Future;
use std::io;
use std::net::SocketAddr;
use new_line_transport;

/// We want to encapsulate `pipeline::Message`. Since the line protocol does
/// not have any streaming bodies, we can make the service be a request &
/// response of type String. `LineService` takes the service supplied to
/// `serve` and adapts it to work with the `proto::pipeline::Server`
/// requirements.
struct LineService<T> {
    inner: T,
}

impl<T> Service for LineService<T>
    where T: Service<Req = String, Resp = String, Error = io::Error>,
{
    type Req = String;
    type Resp = pipeline::Message<String, Empty<(), io::Error>>;
    type Error = io::Error;

    // To make things easier, we are just going to box the future here, however
    // it is possible to not box the future and refer to `futures::Map`
    // directly.
    type Fut = Box<Future<Item = Self::Resp, Error = io::Error> + Send>;

    fn call(&self, req: String) -> Self::Fut {
        self.inner.call(req)
            .map(pipeline::Message::WithoutBody)
            .boxed()
    }
}

/// Serve a service up. Secret sauce here is 'NewService', a helper that must be able to create a
/// new 'Service' for each connection that we receive.
pub fn serve<T>(loop_handle: LoopHandle,  addr: SocketAddr, new_service: T)
        where T: NewService<Req = String, Resp = String, Error = io::Error> + Send + 'static
{
    // Spawn the server on the given loop
    server::listen(loop_handle, addr, move |stream| {
        // Initialize the pipeline dispatch with the service and the line
        // transport
        let service = LineService { inner: try!(new_service.new_service()) };
        pipeline::Server::new(service, new_line_transport(stream))
    }).forget();
}
<commit_msg>Update with futures master<commit_after>use proto::{server, NewService};
use proto::proto::pipeline;
use tokio_service::Service;
use tokio::LoopHandle;
use empty::Empty;
use futures::Future;
use std::io;
use std::net::SocketAddr;
use new_line_transport;

/// We want to encapsulate `pipeline::Message`. Since the line protocol does
/// not have any streaming bodies, we can make the service be a request &
/// response of type String. `LineService` takes the service supplied to
/// `serve` and adapts it to work with the `proto::pipeline::Server`
/// requirements.
struct LineService<T> {
    inner: T,
}

impl<T> Service for LineService<T>
    where T: Service<Req = String, Resp = String, Error = io::Error>,
{
    type Req = String;
    type Resp = pipeline::Message<String, Empty<(), io::Error>>;
    type Error = io::Error;

    // To make things easier, we are just going to box the future here, however
    // it is possible to not box the future and refer to `futures::Map`
    // directly.
    type Fut = Box<Future<Item = Self::Resp, Error = io::Error> + Send>;

    fn call(&self, req: String) -> Self::Fut {
        self.inner.call(req)
            .map(pipeline::Message::WithoutBody)
            .boxed()
    }
}

/// Serve a service up. Secret sauce here is 'NewService', a helper that must be able to create a
/// new 'Service' for each connection that we receive.
pub fn serve<T>(loop_handle: LoopHandle,  addr: SocketAddr, new_service: T)
    where T: NewService<Req = String, Resp = String, Error = io::Error> + Send + 'static
{
    // Spawn the server on the given loop
    loop_handle.clone().spawn(move |_| {
        server::listen(loop_handle, addr, move |stream| {
            // Initialize the pipeline dispatch with the service and the line
            // transport
            let service = LineService { inner: try!(new_service.new_service()) };
            pipeline::Server::new(service, new_line_transport(stream))
        }).then(|r| {
            r.expect("failed to listen");
            Ok(())
        })
    });
}
<|endoftext|>


<commit_before>// TODO: deny missing docs
#![allow(missing_docs)]

use dns::{Response, Result as LookupResult, Error as LookupError, Source};

use itertools::Itertools;
use std::collections::HashMap;
use trust_dns::rr::{RData, Record};

#[derive(Debug)]
pub struct RecordCount<'a> {
    record: &'a Record,
    sources: Vec<Source>,
}

impl<'a> RecordCount<'a> {
    pub fn count(&self) -> usize {
        self.sources.len()
    }

    pub fn record(&self) -> &Record {
        self.record
    }

    pub fn sources(&self) -> &Vec<Source> {
        &self.sources
    }
}

#[derive(Debug)]
pub struct Summary<'a> {
    pub num_of_samples: usize,
    pub num_of_ok_samples: usize,
    pub num_of_err_samples: usize,
    pub min_num_of_records: usize,
    pub max_num_of_records: usize,
    pub record_counts: HashMap<String, RecordCount<'a>>,
    pub failures: Vec<&'a LookupError>,
    pub alerts: Vec<Alert>
}

impl<'a> Summary<'a> {
    pub fn from(responses: &'a [LookupResult<Response>]) -> Self {
        let num_of_samples = responses.len();

        let (responses, failures): (Vec<_>, Vec<_>) =
            responses.into_iter().partition(|x| x.is_ok());
        let successes: Vec<&Response> =
            responses.into_iter().map(|x| x.as_ref().unwrap()).collect();
        let failures: Vec<&LookupError> = failures
            .into_iter()
            .map(|x| x.as_ref().unwrap_err())
            .collect();

        let num_of_ok_samples = successes.len();
        let num_of_err_samples = failures.len();

        let (min_num_of_records, max_num_of_records) = successes
            .iter()
            .map(|x| x.answers.len())
            .fold((::std::usize::MAX, 0), |(mut min, mut max), x| {
                if min > x {
                    min = x
                };
                if max < x {
                    max = x
                };
                (min, max)
            });

        let mut record_counts = HashMap::new();
        for response in &successes {
            for record in &response.answers {
                let key = format!("{:?}-{:?}", record.rr_type(), record.rdata());
                let value = record_counts.entry(key).or_insert( RecordCount{ record, sources: Vec::new() } );
                value.sources.push(response.server.source);
            }
        }

        let alerts = alerts(successes.as_slice());

        Summary {
            num_of_samples,
            num_of_ok_samples,
            num_of_err_samples,
            min_num_of_records,
            max_num_of_records,
            record_counts,
            failures,
            alerts
        }
    }
}

#[derive(Debug)]
pub enum Alert {
    SoaSnDiverge(HashMap<u32, u32>),
}

// TODO: &[&T] is totally weird -- cf. https://users.rust-lang.org/t/solved-function-taking-slice-of-objects-as-well-as-slice-of-references-to-objects/13553/9
fn alerts(responses: &[&Response]) -> Vec<Alert> {
    let mut alerts = Vec::new();
    if let Some(serials) = check_soa_serial_numbers(responses) {
        alerts.push(serials)
    }

    alerts
}

// TODO: &[&T] is totally weird
fn check_soa_serial_numbers(responses: &[&Response]) -> Option<Alert> {
    let mut serial_counts = HashMap::new();
    responses
        .iter()
        .map(|r| r.answers
            .iter()
            .map(|a| match *a.rdata() {
                RData::SOA(ref soa) => Some(soa.serial()),
                _ => None
            })
        )
        .flatten()
        .filter_map(|x| x)
        .for_each(|key| {
            let value = serial_counts.entry(key).or_insert(0);
            *value += 1;
        });

    if serial_counts.len() > 1 {
        Some(Alert::SoaSnDiverge(serial_counts))
    } else {
        None
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use dns::{ErrorKind as LookupErrorKind, Server, Source};
    use std::net::IpAddr;
    use std::str::FromStr;
    use trust_dns::rr::{domain, RecordType};
    use trust_dns::rr::rdata::SOA;

    #[test]
    fn simple_summary() {
        let records_1: Vec<Record> = vec![
            Record::with(
                domain::Name::from_str("www.example.com").unwrap(),
                RecordType::A,
                100
            ),
            Record::with(
                domain::Name::from_str("www.example.com").unwrap(),
                RecordType::MX,
                99
            ),
        ];
        let response_1 = Response {
            server: Server::udp_from(IpAddr::from([127, 0, 0, 1]), Source::Additional),
            answers: records_1,
        };
        let records_2: Vec<Record> = vec![
            Record::with(
                domain::Name::from_str("www.example.com").unwrap(),
                RecordType::A,
                98
            ),
        ];
        let response_2 = Response {
            server: Server::udp_from(IpAddr::from([127, 0, 0, 2]), Source::Additional),
            answers: records_2,
        };
        let responses: Vec<LookupResult<Response>> =
            vec![
                Ok(response_1),
                Ok(response_2),
                Err(
                    LookupErrorKind::QueryError(1, RecordType::AAAA, IpAddr::from([127, 0, 0, 3]))
                        .into()
                ),
            ];

        let summary = Summary::from(&responses);

        assert_eq!(summary.num_of_samples, 3);
        assert_eq!(summary.num_of_ok_samples, 2);
        assert_eq!(summary.num_of_err_samples, 1);
        assert_eq!(summary.min_num_of_records, 1);
        assert_eq!(summary.max_num_of_records, 2);
        assert_eq!(summary.record_counts.len(), 2);

        let mut record_counts: Vec<_> = summary
            .record_counts
            .values()
            .map(|ref rc| rc.count())
            .collect();
        record_counts.sort();
        assert_eq!(record_counts, vec![1, 2]);

        assert_eq!(summary.failures.len(), 1);
    }

    #[test]
    fn test_alert_for_diverging_soa_serials() {
        let records_1: Vec<Record> = vec![
            Record::from_rdata(
                domain::Name::from_str("www.example.com").unwrap(),
                99,
                RecordType::SOA,
                RData::SOA(
                    SOA::new(
                        domain::Name::from_str("sns.dns.icann.org.").unwrap(),
                        domain::Name::from_str("noc.dns.icann.org.").unwrap(),
                        100,
                        7200,
                        3600,
                        1209600,
                        3600
                    )
                )
            )
        ];
        let response_1 = Response {
            server: Server::udp_from(IpAddr::from([127, 0, 0, 1]), Source::Additional),
            answers: records_1,
        };
        let records_2: Vec<Record> = vec![
            Record::from_rdata(
                domain::Name::from_str("www.example.com").unwrap(),
                99,
                RecordType::SOA,
                RData::SOA(
                    SOA::new(
                        domain::Name::from_str("sns.dns.icann.org.").unwrap(),
                        domain::Name::from_str("noc.dns.icann.org.").unwrap(),
                        200,
                        7200,
                        3600,
                        1209600,
                        3600
                    )
                )
            )];
        let response_2 = Response {
            server: Server::udp_from(IpAddr::from([127, 0, 0, 2]), Source::Additional),
            answers: records_2,
        };
        let responses: Vec<Response> = vec![response_1, response_2, ];

        let alerts = alerts(&responses.iter().collect::<Vec<_>>());

        assert_eq!(alerts.len(), 1);
        let &Alert::SoaSnDiverge(ref soa_serials) = alerts.first().unwrap();
        let mut serials = soa_serials.keys().collect::<Vec<_>>();
        serials.sort();
        assert_eq!(serials, vec![&100, &200]);
        let mut counts = soa_serials.values().collect::<Vec<_>>();
        counts.sort();
        assert_eq!(counts, vec![&1, &1]);
    }
}
<commit_msg>Fix regression due to pending stabilization of Iterator::flatten<commit_after>// TODO: deny missing docs
#![allow(missing_docs)]

use dns::{Response, Result as LookupResult, Error as LookupError, Source};

use itertools::Itertools;
use std::collections::HashMap;
use trust_dns::rr::{RData, Record};

#[derive(Debug)]
pub struct RecordCount<'a> {
    record: &'a Record,
    sources: Vec<Source>,
}

impl<'a> RecordCount<'a> {
    pub fn count(&self) -> usize {
        self.sources.len()
    }

    pub fn record(&self) -> &Record {
        self.record
    }

    pub fn sources(&self) -> &Vec<Source> {
        &self.sources
    }
}

#[derive(Debug)]
pub struct Summary<'a> {
    pub num_of_samples: usize,
    pub num_of_ok_samples: usize,
    pub num_of_err_samples: usize,
    pub min_num_of_records: usize,
    pub max_num_of_records: usize,
    pub record_counts: HashMap<String, RecordCount<'a>>,
    pub failures: Vec<&'a LookupError>,
    pub alerts: Vec<Alert>
}

impl<'a> Summary<'a> {
    pub fn from(responses: &'a [LookupResult<Response>]) -> Self {
        let num_of_samples = responses.len();

        let (responses, failures): (Vec<_>, Vec<_>) =
            responses.into_iter().partition(|x| x.is_ok());
        let successes: Vec<&Response> =
            responses.into_iter().map(|x| x.as_ref().unwrap()).collect();
        let failures: Vec<&LookupError> = failures
            .into_iter()
            .map(|x| x.as_ref().unwrap_err())
            .collect();

        let num_of_ok_samples = successes.len();
        let num_of_err_samples = failures.len();

        let (min_num_of_records, max_num_of_records) = successes
            .iter()
            .map(|x| x.answers.len())
            .fold((::std::usize::MAX, 0), |(mut min, mut max), x| {
                if min > x {
                    min = x
                };
                if max < x {
                    max = x
                };
                (min, max)
            });

        let mut record_counts = HashMap::new();
        for response in &successes {
            for record in &response.answers {
                let key = format!("{:?}-{:?}", record.rr_type(), record.rdata());
                let value = record_counts.entry(key).or_insert( RecordCount{ record, sources: Vec::new() } );
                value.sources.push(response.server.source);
            }
        }

        let alerts = alerts(successes.as_slice());

        Summary {
            num_of_samples,
            num_of_ok_samples,
            num_of_err_samples,
            min_num_of_records,
            max_num_of_records,
            record_counts,
            failures,
            alerts
        }
    }
}

#[derive(Debug)]
pub enum Alert {
    SoaSnDiverge(HashMap<u32, u32>),
}

// TODO: &[&T] is totally weird -- cf. https://users.rust-lang.org/t/solved-function-taking-slice-of-objects-as-well-as-slice-of-references-to-objects/13553/9
fn alerts(responses: &[&Response]) -> Vec<Alert> {
    let mut alerts = Vec::new();
    if let Some(serials) = check_soa_serial_numbers(responses) {
        alerts.push(serials)
    }

    alerts
}

// TODO: &[&T] is totally weird
fn check_soa_serial_numbers(responses: &[&Response]) -> Option<Alert> {
    let mut serial_counts = HashMap::new();
    Itertools::flatten(
        responses
        .iter()
        .map(|r| r.answers
            .iter()
            .map(|a| match *a.rdata() {
                RData::SOA(ref soa) => Some(soa.serial()),
                _ => None
            })
        )
    )
    .filter_map(|x| x)
    .for_each(|key| {
        let value = serial_counts.entry(key).or_insert(0);
        *value += 1;
    });

    if serial_counts.len() > 1 {
        Some(Alert::SoaSnDiverge(serial_counts))
    } else {
        None
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use dns::{ErrorKind as LookupErrorKind, Server, Source};
    use std::net::IpAddr;
    use std::str::FromStr;
    use trust_dns::rr::{domain, RecordType};
    use trust_dns::rr::rdata::SOA;

    #[test]
    fn simple_summary() {
        let records_1: Vec<Record> = vec![
            Record::with(
                domain::Name::from_str("www.example.com").unwrap(),
                RecordType::A,
                100
            ),
            Record::with(
                domain::Name::from_str("www.example.com").unwrap(),
                RecordType::MX,
                99
            ),
        ];
        let response_1 = Response {
            server: Server::udp_from(IpAddr::from([127, 0, 0, 1]), Source::Additional),
            answers: records_1,
        };
        let records_2: Vec<Record> = vec![
            Record::with(
                domain::Name::from_str("www.example.com").unwrap(),
                RecordType::A,
                98
            ),
        ];
        let response_2 = Response {
            server: Server::udp_from(IpAddr::from([127, 0, 0, 2]), Source::Additional),
            answers: records_2,
        };
        let responses: Vec<LookupResult<Response>> =
            vec![
                Ok(response_1),
                Ok(response_2),
                Err(
                    LookupErrorKind::QueryError(1, RecordType::AAAA, IpAddr::from([127, 0, 0, 3]))
                        .into()
                ),
            ];

        let summary = Summary::from(&responses);

        assert_eq!(summary.num_of_samples, 3);
        assert_eq!(summary.num_of_ok_samples, 2);
        assert_eq!(summary.num_of_err_samples, 1);
        assert_eq!(summary.min_num_of_records, 1);
        assert_eq!(summary.max_num_of_records, 2);
        assert_eq!(summary.record_counts.len(), 2);

        let mut record_counts: Vec<_> = summary
            .record_counts
            .values()
            .map(|ref rc| rc.count())
            .collect();
        record_counts.sort();
        assert_eq!(record_counts, vec![1, 2]);

        assert_eq!(summary.failures.len(), 1);
    }

    #[test]
    fn test_alert_for_diverging_soa_serials() {
        let records_1: Vec<Record> = vec![
            Record::from_rdata(
                domain::Name::from_str("www.example.com").unwrap(),
                99,
                RecordType::SOA,
                RData::SOA(
                    SOA::new(
                        domain::Name::from_str("sns.dns.icann.org.").unwrap(),
                        domain::Name::from_str("noc.dns.icann.org.").unwrap(),
                        100,
                        7200,
                        3600,
                        1209600,
                        3600
                    )
                )
            )
        ];
        let response_1 = Response {
            server: Server::udp_from(IpAddr::from([127, 0, 0, 1]), Source::Additional),
            answers: records_1,
        };
        let records_2: Vec<Record> = vec![
            Record::from_rdata(
                domain::Name::from_str("www.example.com").unwrap(),
                99,
                RecordType::SOA,
                RData::SOA(
                    SOA::new(
                        domain::Name::from_str("sns.dns.icann.org.").unwrap(),
                        domain::Name::from_str("noc.dns.icann.org.").unwrap(),
                        200,
                        7200,
                        3600,
                        1209600,
                        3600
                    )
                )
            )];
        let response_2 = Response {
            server: Server::udp_from(IpAddr::from([127, 0, 0, 2]), Source::Additional),
            answers: records_2,
        };
        let responses: Vec<Response> = vec![response_1, response_2, ];

        let alerts = alerts(&responses.iter().collect::<Vec<_>>());

        assert_eq!(alerts.len(), 1);
        let &Alert::SoaSnDiverge(ref soa_serials) = alerts.first().unwrap();
        let mut serials = soa_serials.keys().collect::<Vec<_>>();
        serials.sort();
        assert_eq!(serials, vec![&100, &200]);
        let mut counts = soa_serials.values().collect::<Vec<_>>();
        counts.sort();
        assert_eq!(counts, vec![&1, &1]);
    }
}
<|endoftext|>


<commit_before>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::mem;
use libc::c_void;

#[cfg(any(target_os = "macos", target_os = "ios", feature = "dox"))]
use ffi::enums::Format;
#[cfg(any(target_os = "macos", target_os = "ios", feature = "dox"))]
use ffi::CGContextRef;

#[cfg(feature = "use_glib")]
use glib::translate::*;
use ffi;
use ffi::enums::{
    Content,
    Status,
    SurfaceType,
};

#[derive(Debug)]
pub struct Surface(*mut ffi::cairo_surface_t, bool);

impl Surface {
    #[doc(hidden)]
    pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        ffi::cairo_surface_reference(ptr);
        Surface(ptr, false)
    }

    #[doc(hidden)]
    pub unsafe fn from_raw_borrow(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        Surface(ptr, true)
    }

    #[doc(hidden)]
    pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        Surface(ptr, false)
    }

    #[doc(hidden)]
    pub fn to_raw_none(&self) -> *mut ffi::cairo_surface_t {
        self.0
    }

    pub fn status(&self) -> Status {
        unsafe { ffi::cairo_surface_status(self.0) }
    }

    pub fn create_similar(&self, content: Content, width: i32, height: i32) -> Surface {
        unsafe { Self::from_raw_full(ffi::cairo_surface_create_similar(self.0, content, width, height)) }
    }

    #[cfg(any(target_os = "macos", target_os = "ios", feature = "dox"))]
    pub fn quartz_create(format: Format, width: u32, height: u32) -> Surface {
        unsafe { Self::from_raw_full(ffi::cairo_quartz_surface_create(format, width, height)) }
    }

    #[cfg(any(target_os = "macos", target_os = "ios", feature = "dox"))]
    pub fn quartz_create_for_cg_context(cg_context: CGContextRef, width: u32, height: u32) -> Surface {
        unsafe { Self::from_raw_full(ffi::cairo_quartz_surface_create_for_cg_context(cg_context, width, height)) }
    }

    #[cfg(any(target_os = "macos", target_os = "ios", feature = "dox"))]
    pub fn quartz_get_cg_context(&self) -> CGContextRef {
        unsafe { ffi::cairo_quartz_surface_get_cg_context(self.to_raw_none()) }
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::cairo_surface_t> for Surface {
    type Storage = &'a Surface;

    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::cairo_surface_t, Self> {
        Stash(self.to_raw_none(), self)
    }

    #[inline]
    fn to_glib_full(&self) -> *mut ffi::cairo_surface_t {
        unsafe {
            ffi::cairo_surface_reference(self.to_raw_none())
        }
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_full(ptr)
    }
}

#[cfg(feature = "use_glib")]
gvalue_impl!(Surface, ffi::cairo_surface_t, ffi::gobject::cairo_gobject_surface_get_type);

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

impl Clone for Surface {
    fn clone(&self) -> Surface {
        unsafe { Self::from_raw_none(self.0) }
    }
}

impl Drop for Surface {
    fn drop(&mut self) {
        if !self.1 {
            unsafe { ffi::cairo_surface_destroy(self.0); }
        }
    }
}

pub trait SurfaceExt {
    fn flush(&self);
    fn finish(&self);
    fn get_type(&self) -> SurfaceType;
}

impl<O: AsRef<Surface>> SurfaceExt for O {
    fn flush(&self) {
        unsafe { ffi::cairo_surface_flush(self.as_ref().0); }
    }

    fn finish(&self) {
        unsafe { ffi::cairo_surface_finish(self.as_ref().0); }
    }

    fn get_type(&self) -> SurfaceType {
        unsafe { ffi::cairo_surface_get_type(self.as_ref().0) }
    }
}

pub trait SurfacePriv {
    unsafe fn set_user_data<K, T>(&self, key: &K, data: Box<T>) -> Result<(), Status>;
}

impl<O: AsRef<Surface>> SurfacePriv for O {
    unsafe fn set_user_data<K, T>(&self, key: &K, data: Box<T>) -> Result<(), Status> {
        let status = ffi::cairo_surface_set_user_data(self.as_ref().0, key as *const _ as *mut _,
            mem::transmute(data), Some(unbox::<T>));
        match status {
            Status::Success => Ok(()),
            x => Err(x),
        }
    }
}

unsafe extern "C" fn unbox<T>(data: *mut c_void) {
    let data: Box<T> = mem::transmute(data);
    drop(data);
}
<commit_msg>Get rid of some unneeded transmutes<commit_after>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::mem;
use libc::c_void;

#[cfg(any(target_os = "macos", target_os = "ios", feature = "dox"))]
use ffi::enums::Format;
#[cfg(any(target_os = "macos", target_os = "ios", feature = "dox"))]
use ffi::CGContextRef;

#[cfg(feature = "use_glib")]
use glib::translate::*;
use ffi;
use ffi::enums::{
    Content,
    Status,
    SurfaceType,
};

#[derive(Debug)]
pub struct Surface(*mut ffi::cairo_surface_t, bool);

impl Surface {
    #[doc(hidden)]
    pub unsafe fn from_raw_none(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        ffi::cairo_surface_reference(ptr);
        Surface(ptr, false)
    }

    #[doc(hidden)]
    pub unsafe fn from_raw_borrow(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        Surface(ptr, true)
    }

    #[doc(hidden)]
    pub unsafe fn from_raw_full(ptr: *mut ffi::cairo_surface_t) -> Surface {
        assert!(!ptr.is_null());
        Surface(ptr, false)
    }

    #[doc(hidden)]
    pub fn to_raw_none(&self) -> *mut ffi::cairo_surface_t {
        self.0
    }

    pub fn status(&self) -> Status {
        unsafe { ffi::cairo_surface_status(self.0) }
    }

    pub fn create_similar(&self, content: Content, width: i32, height: i32) -> Surface {
        unsafe { Self::from_raw_full(ffi::cairo_surface_create_similar(self.0, content, width, height)) }
    }

    #[cfg(any(target_os = "macos", target_os = "ios", feature = "dox"))]
    pub fn quartz_create(format: Format, width: u32, height: u32) -> Surface {
        unsafe { Self::from_raw_full(ffi::cairo_quartz_surface_create(format, width, height)) }
    }

    #[cfg(any(target_os = "macos", target_os = "ios", feature = "dox"))]
    pub fn quartz_create_for_cg_context(cg_context: CGContextRef, width: u32, height: u32) -> Surface {
        unsafe { Self::from_raw_full(ffi::cairo_quartz_surface_create_for_cg_context(cg_context, width, height)) }
    }

    #[cfg(any(target_os = "macos", target_os = "ios", feature = "dox"))]
    pub fn quartz_get_cg_context(&self) -> CGContextRef {
        unsafe { ffi::cairo_quartz_surface_get_cg_context(self.to_raw_none()) }
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::cairo_surface_t> for Surface {
    type Storage = &'a Surface;

    #[inline]
    fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::cairo_surface_t, Self> {
        Stash(self.to_raw_none(), self)
    }

    #[inline]
    fn to_glib_full(&self) -> *mut ffi::cairo_surface_t {
        unsafe {
            ffi::cairo_surface_reference(self.to_raw_none())
        }
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::cairo_surface_t> for Surface {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::cairo_surface_t) -> Surface {
        Self::from_raw_full(ptr)
    }
}

#[cfg(feature = "use_glib")]
gvalue_impl!(Surface, ffi::cairo_surface_t, ffi::gobject::cairo_gobject_surface_get_type);

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

impl Clone for Surface {
    fn clone(&self) -> Surface {
        unsafe { Self::from_raw_none(self.0) }
    }
}

impl Drop for Surface {
    fn drop(&mut self) {
        if !self.1 {
            unsafe { ffi::cairo_surface_destroy(self.0); }
        }
    }
}

pub trait SurfaceExt {
    fn flush(&self);
    fn finish(&self);
    fn get_type(&self) -> SurfaceType;
}

impl<O: AsRef<Surface>> SurfaceExt for O {
    fn flush(&self) {
        unsafe { ffi::cairo_surface_flush(self.as_ref().0); }
    }

    fn finish(&self) {
        unsafe { ffi::cairo_surface_finish(self.as_ref().0); }
    }

    fn get_type(&self) -> SurfaceType {
        unsafe { ffi::cairo_surface_get_type(self.as_ref().0) }
    }
}

pub trait SurfacePriv {
    unsafe fn set_user_data<K, T>(&self, key: &K, data: Box<T>) -> Result<(), Status>;
}

impl<O: AsRef<Surface>> SurfacePriv for O {
    unsafe fn set_user_data<K, T>(&self, key: &K, data: Box<T>) -> Result<(), Status> {
        let ptr: *mut T = Box::into_raw(data);

        assert_eq!(mem::size_of::<*mut c_void>(), mem::size_of_val(&ptr));

        let status = ffi::cairo_surface_set_user_data(self.as_ref().0, key as *const _ as *mut _,
            ptr as *mut c_void, Some(unbox::<T>));
        match status {
            Status::Success => Ok(()),
            x => Err(x),
        }
    }
}

unsafe extern "C" fn unbox<T>(data: *mut c_void) {
    let data: Box<T> = Box::from_raw(data as *mut T);
    drop(data);
}
<|endoftext|>


<commit_before>use linked_hash_map::LinkedHashMap;

use platform::time::time_now;

use super::errors::CacheError;
use super::key::Key;
use super::typedefs::CacheResult;
use super::value::Value;

struct CacheMetrics {
    pub bytes: u64, // Bytes currently stored
    pub evictions: u64, // Number of items removed to make space for new items
    pub get_hits: u64,
    pub get_misses: u64,
    pub reclaimed: u64, // Number of times an entry was reclaimed to store a new entry
    pub total_items: u64, // Total items stored since server started
}

impl CacheMetrics {
    pub fn new() -> CacheMetrics {
        CacheMetrics {
            bytes: 0,
            evictions: 0,
            get_hits: 0,
            get_misses: 0,
            reclaimed: 0,
            total_items: 0,
        }
    }

    fn bytes_add(&mut self, key: &Key, value: &Value) {
        self.bytes += key.len() as u64;
        self.bytes += value.len() as u64;
    }

    fn bytes_subtract(&mut self, key: &Key, value: &Value) {
        self.bytes -= key.len() as u64;
        self.bytes -= value.len() as u64;
    }
}

pub struct Cache {
    capacity: u64,
    item_lifetime: f64, // in seconds, <0 for unlimited
    key_maxlen: u64, // in bytes
    metrics: CacheMetrics,
    value_maxlen: u64, // in bytes
    storage: LinkedHashMap<Key, Value>,
}

impl Cache {
    pub fn new(capacity: u64) -> Cache {
        Cache {
            capacity: capacity,
            item_lifetime: -1.0,
            key_maxlen: 250, // 250b
            metrics: CacheMetrics::new(),
            value_maxlen: 1048576, // 1mb
            storage: LinkedHashMap::new(),
        }
    }

    pub fn with_item_lifetime(&mut self, item_lifetime: f64) -> &mut Cache {
        self.item_lifetime = item_lifetime;
        self
    }

    pub fn with_key_maxlen(&mut self, key_maxlen: u64) -> &mut Cache {
        self.key_maxlen = key_maxlen;
        self
    }

    pub fn with_value_maxlen(&mut self, value_maxlen: u64) -> &mut Cache {
        self.value_maxlen = value_maxlen;
        self
    }

    pub fn get_metrics(&self) -> &CacheMetrics {
        &self.metrics
    }

    fn check_key_len(&self, key: &Key) -> bool {
        key.len() as u64 <= self.key_maxlen
    }

    fn check_value_len(&self, value: &Value) -> bool {
        value.len() as u64 <= self.value_maxlen
    }

    fn evict_oldest(&mut self) -> CacheResult<()> {
        let opt = self.storage.pop_back();

        match opt {
            Some((key, value)) => {
                // Update metrics
                self.metrics.bytes_subtract(&key, &value);
                self.metrics.evictions += 1;

                Ok(())
            }
            None => Err(CacheError::EvictionFailed),
        }
    }

    fn value_is_alive(&self, value: &Value) -> bool {
        // if the value has an exptime set, that takes precedence
        if value.exptime > 0.0 {
            if value.exptime > time_now() {
                return true;
            } else {
                return false;
            }
        }

        // if we have no lifetime setting then values are always live
        if self.item_lifetime < 0.0 {
            return true;
        }

        // otherwise use lifetime to determine liveness
        value.atime + self.item_lifetime > time_now()
    }

    // TODO expose as public api
    fn remove(&mut self, key: &Key) -> CacheResult<()> {
        let opt = self.storage.remove(key);

        match opt {
            Some(_) => Ok(()),
            None => Err(CacheError::KeyNotFound),
        }
    }

    pub fn contains_key(&mut self, key: &Key) -> CacheResult<bool> {
        let result = self.get(key);

        match result {
            // We know how to interpret found and not found
            Ok(_) => Ok(true),
            Err(CacheError::KeyNotFound) => Ok(false),

            // Some other error
            Err(x) => Err(x),
        }
    }

    pub fn get(&mut self, key: &Key) -> CacheResult<&Value> {
        // Check key size
        if !self.check_key_len(key) {
            return Err(CacheError::KeyTooLong);
        }

        // Pop the value first
        let opt = self.storage.remove(key);

        // We didn't find it
        if opt.is_none() {
            self.metrics.get_misses += 1;
            return Err(CacheError::KeyNotFound);
        }

        // From here on we can assume we did find it
        let mut value = opt.unwrap();

        // The value has been successfully removed - update metrics
        self.metrics.bytes_subtract(key, &value);

        // Now check if the value is still alive
        if !self.value_is_alive(&value) {
            self.metrics.get_misses += 1;
            return Err(CacheError::KeyNotFound);
        }

        // Update the value to mark that it's been accessed just now
        value.touch();

        // We are going to re-instate the key - update metrics
        self.metrics.bytes_add(key, &value);
        self.metrics.get_hits += 1;

        // Now we reinsert the key to refresh it
        self.storage.insert(key.clone(), value);

        // Load since we need to return it
        let value = self.storage.get(key).unwrap();

        // Return success
        Ok(value)
    }

    pub fn len(&self) -> usize {
        self.storage.len()
    }

    pub fn set(&mut self, key: Key, mut value: Value) -> CacheResult<()> {
        // Check key & value sizes
        if !self.check_key_len(&key) {
            return Err(CacheError::KeyTooLong);
        }
        if !self.check_value_len(&value) {
            return Err(CacheError::ValueTooLong);
        }

        // Check capacity if adding new key
        if !self.storage.contains_key(&key) {
            if self.storage.len() as u64 == self.capacity {
                // Remove the oldest item to make space
                self.evict_oldest();

                // Update metrics
                self.metrics.reclaimed += 1;
            }
        }

        // Update metrics
        self.metrics.bytes_add(&key, &value);
        self.metrics.total_items += 1;

        // Update atime for value
        value.touch();

        // Store the value
        self.storage.insert(key, value);

        // Return success
        Ok(())
    }
}
<commit_msg>fix bytes count in case of updating key<commit_after>use linked_hash_map::LinkedHashMap;

use platform::time::time_now;

use super::errors::CacheError;
use super::key::Key;
use super::typedefs::CacheResult;
use super::value::Value;

struct CacheMetrics {
    pub bytes: u64, // Bytes currently stored
    pub evictions: u64, // Number of items removed to make space for new items
    pub get_hits: u64,
    pub get_misses: u64,
    pub reclaimed: u64, // Number of times an entry was reclaimed to store a new entry
    pub total_items: u64, // Total items stored since server started
}

impl CacheMetrics {
    pub fn new() -> CacheMetrics {
        CacheMetrics {
            bytes: 0,
            evictions: 0,
            get_hits: 0,
            get_misses: 0,
            reclaimed: 0,
            total_items: 0,
        }
    }

    fn bytes_add(&mut self, key: &Key, value: &Value) {
        self.bytes += key.len() as u64;
        self.bytes += value.len() as u64;
    }

    fn bytes_subtract(&mut self, key: &Key, value: &Value) {
        self.bytes -= key.len() as u64;
        self.bytes -= value.len() as u64;
    }
}

pub struct Cache {
    capacity: u64,
    item_lifetime: f64, // in seconds, <0 for unlimited
    key_maxlen: u64, // in bytes
    metrics: CacheMetrics,
    value_maxlen: u64, // in bytes
    storage: LinkedHashMap<Key, Value>,
}

impl Cache {
    pub fn new(capacity: u64) -> Cache {
        Cache {
            capacity: capacity,
            item_lifetime: -1.0,
            key_maxlen: 250, // 250b
            metrics: CacheMetrics::new(),
            value_maxlen: 1048576, // 1mb
            storage: LinkedHashMap::new(),
        }
    }

    pub fn with_item_lifetime(&mut self, item_lifetime: f64) -> &mut Cache {
        self.item_lifetime = item_lifetime;
        self
    }

    pub fn with_key_maxlen(&mut self, key_maxlen: u64) -> &mut Cache {
        self.key_maxlen = key_maxlen;
        self
    }

    pub fn with_value_maxlen(&mut self, value_maxlen: u64) -> &mut Cache {
        self.value_maxlen = value_maxlen;
        self
    }

    pub fn get_metrics(&self) -> &CacheMetrics {
        &self.metrics
    }

    fn check_key_len(&self, key: &Key) -> bool {
        key.len() as u64 <= self.key_maxlen
    }

    fn check_value_len(&self, value: &Value) -> bool {
        value.len() as u64 <= self.value_maxlen
    }

    fn evict_oldest(&mut self) -> CacheResult<()> {
        let opt = self.storage.pop_back();

        match opt {
            Some((key, value)) => {
                // Update metrics
                self.metrics.bytes_subtract(&key, &value);
                self.metrics.evictions += 1;

                Ok(())
            }
            None => Err(CacheError::EvictionFailed),
        }
    }

    fn value_is_alive(&self, value: &Value) -> bool {
        // if the value has an exptime set, that takes precedence
        if value.exptime > 0.0 {
            if value.exptime > time_now() {
                return true;
            } else {
                return false;
            }
        }

        // if we have no lifetime setting then values are always live
        if self.item_lifetime < 0.0 {
            return true;
        }

        // otherwise use lifetime to determine liveness
        value.atime + self.item_lifetime > time_now()
    }

    // TODO expose as public api
    fn remove(&mut self, key: &Key) -> CacheResult<()> {
        let opt = self.storage.remove(key);

        match opt {
            Some(_) => Ok(()),
            None => Err(CacheError::KeyNotFound),
        }
    }

    pub fn contains_key(&mut self, key: &Key) -> CacheResult<bool> {
        let result = self.get(key);

        match result {
            // We know how to interpret found and not found
            Ok(_) => Ok(true),
            Err(CacheError::KeyNotFound) => Ok(false),

            // Some other error
            Err(x) => Err(x),
        }
    }

    pub fn get(&mut self, key: &Key) -> CacheResult<&Value> {
        // Check key size
        if !self.check_key_len(key) {
            return Err(CacheError::KeyTooLong);
        }

        // Pop the value first
        let opt = self.storage.remove(key);

        // We didn't find it
        if opt.is_none() {
            self.metrics.get_misses += 1;
            return Err(CacheError::KeyNotFound);
        }

        // From here on we can assume we did find it
        let mut value = opt.unwrap();

        // The value has been successfully removed - update metrics
        self.metrics.bytes_subtract(key, &value);

        // Now check if the value is still alive
        if !self.value_is_alive(&value) {
            self.metrics.get_misses += 1;
            return Err(CacheError::KeyNotFound);
        }

        // Update the value to mark that it's been accessed just now
        value.touch();

        // We are going to re-instate the key - update metrics
        self.metrics.bytes_add(key, &value);
        self.metrics.get_hits += 1;

        // Now we reinsert the key to refresh it
        self.storage.insert(key.clone(), value);

        // Load since we need to return it
        let value = self.storage.get(key).unwrap();

        // Return success
        Ok(value)
    }

    pub fn len(&self) -> usize {
        self.storage.len()
    }

    pub fn set(&mut self, key: Key, mut value: Value) -> CacheResult<()> {
        // Check key & value sizes
        if !self.check_key_len(&key) {
            return Err(CacheError::KeyTooLong);
        }
        if !self.check_value_len(&value) {
            return Err(CacheError::ValueTooLong);
        }

        // Check capacity if adding new key
        if !self.storage.contains_key(&key) {
            if self.storage.len() as u64 == self.capacity {
                // Remove the oldest item to make space
                self.evict_oldest();

                // Update metrics
                self.metrics.reclaimed += 1;
            }
        } else {
            // We're updating the key, possibly with a different size value
            self.metrics.bytes_subtract(&key, &value);
        }

        // Update metrics
        self.metrics.bytes_add(&key, &value);
        self.metrics.total_items += 1;

        // Update atime for value
        value.touch();

        // Store the value
        self.storage.insert(key, value);

        // Return success
        Ok(())
    }
}
<|endoftext|>


<commit_before>macro_rules! event(
    (
        mod $mod_id:ident {
            extern_callback_type = $ext_cbfun:ty;
            intern_callback_type = $cbfun:ty;

            extern_params {
                $( $arg:ident : $arg_ty:ty => { $arg_conv:expr } ),+
            }
        }
    ) => (
        mod $mod_id {
            /**
             * A key for setting and retrieving the callback from task-
             * local storage
             */
            fn tls_key(_: @$cbfun) {}

            /**
             * Stores the callback in task-local storage and then calls
             * `f` with  with `extfun` as the argument.
             */
            pub fn set_callback(cbfun: $cbfun, f: &fn($ext_cbfun) ) {
                unsafe {
                    task::local_data::local_data_set(tls_key, @cbfun);
                    f(ext_cbfun);   // TODO: pass on return value from `::ml::set_*_callback` function
                }
            }

            /**
             * An external function that invokes the callback currently stored
             * in task-local storage, if it exists.
             */
            pub extern fn ext_cbfun( $($arg : $arg_ty),+ ) {
                unsafe {
                    do task::local_data::local_data_get(tls_key).map |&cb| {
                        (*cb)( $($arg_conv),+ )
                    };
                }
            }
        }
    )
)

// Error Event Module
pub event!(
    mod error {
        extern_callback_type = ::ll::GLFWerrorfun;
        intern_callback_type = ::ErrorFun;

        extern_params {
            err:    libc::c_int             => { err },
            format: *libc::c_char           => { str::raw::from_c_str(format) }
        }
    }
)

// Monitor Event Module
pub event!(
    mod monitor {
        extern_callback_type = ::ll::GLFWmonitorfun;
        intern_callback_type = ::MonitorFun;

        extern_params {
            monitor:    *::ll::GLFWmonitor  => { &::Monitor { ptr: monitor } },
            event:      libc::c_int         => { event }
        }
    }
)

// Window Position Event Module
pub event!(
    mod windowpos {
        extern_callback_type = ::ll::GLFWwindowposfun;
        intern_callback_type = ::WindowPosFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            x:          libc::c_int         => { x as int },
            y:          libc::c_int         => { y as int }
        }
    }
)

// Window Size Event Module
pub event!(
    mod windowsize {
        extern_callback_type = ::ll::GLFWwindowsizefun;
        intern_callback_type = ::WindowSizeFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            width:      libc::c_int         => { width as int },
            height:     libc::c_int         => { height as int }
        }
    }
)

// Window Close Event Module
pub event!(
    mod windowclose {
        extern_callback_type = ::ll::GLFWwindowclosefun;
        intern_callback_type = ::WindowCloseFun;

        extern_params {
            window:     *::ll::GLFWwindow  => { &::Window { ptr: window } }
        }
    }
)

// Window Refresh Event Module
pub event!(
    mod windowrefresh {
        extern_callback_type = ::ll::GLFWwindowrefreshfun;
        intern_callback_type = ::WindowRefreshFun;

        extern_params {
            window:     *::ll::GLFWwindow  => { &::Window { ptr: window } }
        }
    }
)

// Window Focus Event Module
pub event!(
    mod windowfocus {
        extern_callback_type = ::ll::GLFWwindowfocusfun;
        intern_callback_type = ::WindowFocusFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            activated:  libc::c_int         => { activated as bool }
        }
    }
)

// Window Iconify Event Module
pub event!(
    mod windowiconify {
        extern_callback_type = ::ll::GLFWwindowiconifyfun;
        intern_callback_type = ::WindowIconifyFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            iconified:  libc::c_int         => { iconified as bool }
        }
    }
)

// Key Event Module
pub event!(
    mod key {
        extern_callback_type = ::ll::GLFWkeyfun;
        intern_callback_type = ::KeyFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            key:        libc::c_int         => { key },
            action:     libc::c_int         => { action }
        }
    }
)

// Character Event Module
pub event!(
    mod char {
        extern_callback_type = ::ll::GLFWcharfun;
        intern_callback_type = ::CharFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            character:  libc::c_uint        => { character as char }
        }
    }
)

// Mouse Button Event Module
pub event!(
    mod mousebutton {
        extern_callback_type = ::ll::GLFWmousebuttonfun;
        intern_callback_type = ::MouseButtonFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            button:     libc::c_int         => { button },
            action:     libc::c_int         => { action }
        }
    }
)

// Cursor Position Event Module
pub event!(
    mod cursorpos {
        extern_callback_type = ::ll::GLFWscrollfun;
        intern_callback_type = ::CursorPosFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            xpos:       libc::c_double      => { xpos as float },
            ypos:       libc::c_double      => { ypos as float }
        }
    }
)

// Cursor Enter Event Module
pub event!(
    mod cursorenter {
        extern_callback_type = ::ll::GLFWcursorposfun;
        intern_callback_type = ::CursorEnterFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            entered:    libc::c_int         => { entered as bool }
        }
    }
)

// Scroll Event Module
pub event!(
    mod scroll {
        extern_callback_type = ::ll::GLFWscrollfun;
        intern_callback_type = ::ScrollFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            xpos:       libc::c_double      => { xpos as float },
            ypos:       libc::c_double      => { ypos as float }
        }
    }
)<commit_msg>Update event.rs<commit_after>macro_rules! event(
    (
        mod $mod_id:ident {
            extern_callback_type = $ext_cbfun:ty;
            intern_callback_type = $cbfun:ty;

            extern_params {
                $( $arg:ident : $arg_ty:ty => { $arg_conv:expr } ),+
            }
        }
    ) => (
        mod $mod_id {
            /**
             * A key for setting and retrieving the callback from task-
             * local storage
             */
            fn tls_key(_: @$cbfun) {}

            /**
             * Stores the callback in task-local storage and then calls
             * `f` with  with `extfun` as the argument.
             */
            pub fn set_callback(cbfun: $cbfun, f: &fn($ext_cbfun) ) {
                unsafe {
                    local_data::local_data_set(tls_key, @cbfun);
                    f(ext_cbfun);   // TODO: pass on return value from `::ml::set_*_callback` function
                }
            }

            /**
             * An external function that invokes the callback currently stored
             * in task-local storage, if it exists.
             */
            pub extern fn ext_cbfun( $($arg : $arg_ty),+ ) {
                unsafe {
                    do local_data::local_data_get(tls_key).map |&cb| {
                        (*cb)( $($arg_conv),+ )
                    };
                }
            }
        }
    )
)

// Error Event Module
pub event!(
    mod error {
        extern_callback_type = ::ll::GLFWerrorfun;
        intern_callback_type = ::ErrorFun;

        extern_params {
            err:    libc::c_int             => { err },
            format: *libc::c_char           => { str::raw::from_c_str(format) }
        }
    }
)

// Monitor Event Module
pub event!(
    mod monitor {
        extern_callback_type = ::ll::GLFWmonitorfun;
        intern_callback_type = ::MonitorFun;

        extern_params {
            monitor:    *::ll::GLFWmonitor  => { &::Monitor { ptr: monitor } },
            event:      libc::c_int         => { event }
        }
    }
)

// Window Position Event Module
pub event!(
    mod windowpos {
        extern_callback_type = ::ll::GLFWwindowposfun;
        intern_callback_type = ::WindowPosFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            x:          libc::c_int         => { x as int },
            y:          libc::c_int         => { y as int }
        }
    }
)

// Window Size Event Module
pub event!(
    mod windowsize {
        extern_callback_type = ::ll::GLFWwindowsizefun;
        intern_callback_type = ::WindowSizeFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            width:      libc::c_int         => { width as int },
            height:     libc::c_int         => { height as int }
        }
    }
)

// Window Close Event Module
pub event!(
    mod windowclose {
        extern_callback_type = ::ll::GLFWwindowclosefun;
        intern_callback_type = ::WindowCloseFun;

        extern_params {
            window:     *::ll::GLFWwindow  => { &::Window { ptr: window } }
        }
    }
)

// Window Refresh Event Module
pub event!(
    mod windowrefresh {
        extern_callback_type = ::ll::GLFWwindowrefreshfun;
        intern_callback_type = ::WindowRefreshFun;

        extern_params {
            window:     *::ll::GLFWwindow  => { &::Window { ptr: window } }
        }
    }
)

// Window Focus Event Module
pub event!(
    mod windowfocus {
        extern_callback_type = ::ll::GLFWwindowfocusfun;
        intern_callback_type = ::WindowFocusFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            activated:  libc::c_int         => { activated as bool }
        }
    }
)

// Window Iconify Event Module
pub event!(
    mod windowiconify {
        extern_callback_type = ::ll::GLFWwindowiconifyfun;
        intern_callback_type = ::WindowIconifyFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            iconified:  libc::c_int         => { iconified as bool }
        }
    }
)

// Key Event Module
pub event!(
    mod key {
        extern_callback_type = ::ll::GLFWkeyfun;
        intern_callback_type = ::KeyFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            key:        libc::c_int         => { key },
            action:     libc::c_int         => { action }
        }
    }
)

// Character Event Module
pub event!(
    mod char {
        extern_callback_type = ::ll::GLFWcharfun;
        intern_callback_type = ::CharFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            character:  libc::c_uint        => { character as char }
        }
    }
)

// Mouse Button Event Module
pub event!(
    mod mousebutton {
        extern_callback_type = ::ll::GLFWmousebuttonfun;
        intern_callback_type = ::MouseButtonFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            button:     libc::c_int         => { button },
            action:     libc::c_int         => { action }
        }
    }
)

// Cursor Position Event Module
pub event!(
    mod cursorpos {
        extern_callback_type = ::ll::GLFWscrollfun;
        intern_callback_type = ::CursorPosFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            xpos:       libc::c_double      => { xpos as float },
            ypos:       libc::c_double      => { ypos as float }
        }
    }
)

// Cursor Enter Event Module
pub event!(
    mod cursorenter {
        extern_callback_type = ::ll::GLFWcursorposfun;
        intern_callback_type = ::CursorEnterFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            entered:    libc::c_int         => { entered as bool }
        }
    }
)

// Scroll Event Module
pub event!(
    mod scroll {
        extern_callback_type = ::ll::GLFWscrollfun;
        intern_callback_type = ::ScrollFun;

        extern_params {
            window:     *::ll::GLFWwindow   => { &::Window { ptr: window } },
            xpos:       libc::c_double      => { xpos as float },
            ypos:       libc::c_double      => { ypos as float }
        }
    }
)
<|endoftext|>


<commit_before>use core::mem;
use core::ops::Range;
use alloc::string::String;
use alloc::vec::Vec;

use super::data::{Stat, TimeSpec};
use super::flag::*;
use super::number::*;
use super::validate::*;

// Copied from std
pub struct EscapeDefault {
    range: Range<usize>,
    data: [u8; 4],
}

pub fn escape_default(c: u8) -> EscapeDefault {
    let (data, len) = match c {
        b'\t' => ([b'\\', b't', 0, 0], 2),
        b'\r' => ([b'\\', b'r', 0, 0], 2),
        b'\n' => ([b'\\', b'n', 0, 0], 2),
        b'\\' => ([b'\\', b'\\', 0, 0], 2),
        b'\'' => ([b'\\', b'\'', 0, 0], 2),
        b'"' => ([b'\\', b'"', 0, 0], 2),
        b'\x20' ... b'\x7e' => ([c, 0, 0, 0], 1),
        _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
    };

    return EscapeDefault { range: (0.. len), data: data };

    fn hexify(b: u8) -> u8 {
        match b {
            0 ... 9 => b'0' + b,
            _ => b'a' + b - 10,
        }
    }
}

impl Iterator for EscapeDefault {
    type Item = u8;
    fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
    fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
}

struct ByteStr<'a>(&'a[u8]);

impl<'a> ::core::fmt::Debug for ByteStr<'a> {
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        write!(f, "\"")?;
        for i in self.0 {
            for ch in escape_default(*i) {
                write!(f, "{}", ch as char)?;
            }
        }
        write!(f, "\"")?;
        Ok(())
    }
}

pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> String {
    match a {
        SYS_OPEN => format!(
            "open({:?}, {:#X})",
            validate_slice(b as *const u8, c).map(ByteStr),
            d
        ),
        SYS_CHMOD => format!(
            "chmod({:?}, {:#o})",
            validate_slice(b as *const u8, c).map(ByteStr),
            d
        ),
        SYS_RMDIR => format!(
            "rmdir({:?})",
            validate_slice(b as *const u8, c).map(ByteStr)
        ),
        SYS_UNLINK => format!(
            "unlink({:?})",
            validate_slice(b as *const u8, c).map(ByteStr)
        ),
        SYS_CLOSE => format!(
            "close({})", b
        ),
        SYS_DUP => format!(
            "dup({}, {:?})",
            b,
            validate_slice(c as *const u8, d).map(ByteStr)
        ),
        SYS_DUP2 => format!(
            "dup2({}, {}, {:?})",
            b,
            c,
            validate_slice(d as *const u8, e).map(ByteStr)
        ),
        SYS_READ => format!(
            "read({}, {:#X}, {})",
            b,
            c,
            d
        ),
        SYS_WRITE => format!(
            "write({}, {:#X}, {})",
            b,
            c,
            d
        ),
        SYS_LSEEK => format!(
            "lseek({}, {}, {} ({}))",
            b,
            c as isize,
            match d {
                SEEK_SET => "SEEK_SET",
                SEEK_CUR => "SEEK_CUR",
                SEEK_END => "SEEK_END",
                _ => "UNKNOWN"
            },
            d
        ),
        SYS_FCNTL => format!(
            "fcntl({}, {} ({}), {:#X})",
            b,
            match c {
                F_DUPFD => "F_DUPFD",
                F_GETFD => "F_GETFD",
                F_SETFD => "F_SETFD",
                F_SETFL => "F_SETFL",
                F_GETFL => "F_GETFL",
                _ => "UNKNOWN"
            },
            c,
            d
        ),
        SYS_FMAP => format!(
            "fmap({}, {:#X}, {})",
            b,
            c,
            d
        ),
        SYS_FUNMAP => format!(
            "funmap({:#X})",
            b
        ),
        SYS_FPATH => format!(
            "fpath({}, {:#X}, {})",
            b,
            c,
            d
        ),
        SYS_FSTAT => format!(
            "fstat({}, {:?})",
            b,
            validate_slice(
                c as *const Stat,
                d/mem::size_of::<Stat>()
            ),
        ),
        SYS_FSTATVFS => format!(
            "fstatvfs({}, {:#X}, {})",
            b,
            c,
            d
        ),
        SYS_FSYNC => format!(
            "fsync({})",
            b
        ),
        SYS_FTRUNCATE => format!(
            "ftruncate({}, {})",
            b,
            c
        ),

        SYS_BRK => format!(
            "brk({:#X})",
            b
        ),
        SYS_CHDIR => format!(
            "chdir({:?})",
            validate_slice(b as *const u8, c).map(ByteStr)
        ),
        SYS_CLOCK_GETTIME => format!(
            "clock_gettime({}, {:?})",
            b,
            validate_slice_mut(c as *mut TimeSpec, 1)
        ),
        SYS_CLONE => format!(
            "clone({})",
            b
        ),
        SYS_EXIT => format!(
            "exit({})",
            b
        ),
        //TODO: Cleanup, do not allocate
        SYS_FEXEC => format!(
            "fexec({}, {:?}, {:?})",
            b,
            validate_slice(
                c as *const [usize; 2],
                d
            ).map(|slice| {
                slice.iter().map(|a|
                    validate_slice(a[0] as *const u8, a[1]).ok()
                    .and_then(|s| ::core::str::from_utf8(s).ok())
                ).collect::<Vec<Option<&str>>>()
            }),
            validate_slice(
                e as *const [usize; 2],
                f
            ).map(|slice| {
                slice.iter().map(|a|
                    validate_slice(a[0] as *const u8, a[1]).ok()
                    .and_then(|s| ::core::str::from_utf8(s).ok())
                ).collect::<Vec<Option<&str>>>()
            })
        ),
        SYS_FUTEX => format!(
            "futex({:#X} [{:?}], {}, {}, {}, {})",
            b,
            validate_slice_mut(b as *mut i32, 1).map(|uaddr| &mut uaddr[0]),
            c,
            d,
            e,
            f
        ),
        SYS_GETCWD => format!(
            "getcwd({:#X}, {})",
            b,
            c
        ),
        SYS_GETEGID => format!("getegid()"),
        SYS_GETENS => format!("getens()"),
        SYS_GETEUID => format!("geteuid()"),
        SYS_GETGID => format!("getgid()"),
        SYS_GETNS => format!("getns()"),
        SYS_GETPID => format!("getpid()"),
        SYS_GETUID => format!("getuid()"),
        SYS_IOPL => format!(
            "iopl({})",
            b
        ),
        SYS_KILL => format!(
            "kill({}, {})",
            b,
            c
        ),
        SYS_SIGRETURN => format!("sigreturn()"),
        SYS_SIGACTION => format!(
            "sigaction({}, {:#X}, {:#X}, {:#X})",
            b,
            c,
            d,
            e
        ),
        SYS_MKNS => format!(
            "mkns({:?})",
            validate_slice(b as *const [usize; 2], c)
        ),
        SYS_NANOSLEEP => format!(
            "nanosleep({:?}, ({}, {}))",
            validate_slice(b as *const TimeSpec, 1),
            c,
            d
        ),
        SYS_PHYSALLOC => format!(
            "physalloc({})",
            b
        ),
        SYS_PHYSFREE => format!(
            "physfree({:#X}, {})",
            b,
            c
        ),
        SYS_PHYSMAP => format!(
            "physmap({:#X}, {}, {:#X})",
            b,
            c,
            d
        ),
        SYS_PHYSUNMAP => format!(
            "physunmap({:#X})",
            b
        ),
        SYS_VIRTTOPHYS => format!(
            "virttophys({:#X})",
            b
        ),
        SYS_PIPE2 => format!(
            "pipe2({:?}, {})",
            validate_slice_mut(b as *mut usize, 2),
            c
        ),
        SYS_SETREGID => format!(
            "setregid({}, {})",
            b,
            c
        ),
        SYS_SETRENS => format!(
            "setrens({}, {})",
            b,
            c
        ),
        SYS_SETREUID => format!(
            "setreuid({}, {})",
            b,
            c
        ),
        SYS_WAITPID => format!(
            "waitpid({}, {:#X}, {})",
            b,
            c,
            d
        ),
        SYS_YIELD => format!("yield()"),
        _ => format!(
            "UNKNOWN{} {:#X}({:#X}, {:#X}, {:#X}, {:#X}, {:#X})",
            a, a,
            b,
            c,
            d,
            e,
            f
        )
    }
}
<commit_msg>Add umask to debug<commit_after>use core::mem;
use core::ops::Range;
use alloc::string::String;
use alloc::vec::Vec;

use super::data::{Stat, TimeSpec};
use super::flag::*;
use super::number::*;
use super::validate::*;

// Copied from std
pub struct EscapeDefault {
    range: Range<usize>,
    data: [u8; 4],
}

pub fn escape_default(c: u8) -> EscapeDefault {
    let (data, len) = match c {
        b'\t' => ([b'\\', b't', 0, 0], 2),
        b'\r' => ([b'\\', b'r', 0, 0], 2),
        b'\n' => ([b'\\', b'n', 0, 0], 2),
        b'\\' => ([b'\\', b'\\', 0, 0], 2),
        b'\'' => ([b'\\', b'\'', 0, 0], 2),
        b'"' => ([b'\\', b'"', 0, 0], 2),
        b'\x20' ... b'\x7e' => ([c, 0, 0, 0], 1),
        _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
    };

    return EscapeDefault { range: (0.. len), data: data };

    fn hexify(b: u8) -> u8 {
        match b {
            0 ... 9 => b'0' + b,
            _ => b'a' + b - 10,
        }
    }
}

impl Iterator for EscapeDefault {
    type Item = u8;
    fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
    fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
}

struct ByteStr<'a>(&'a[u8]);

impl<'a> ::core::fmt::Debug for ByteStr<'a> {
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        write!(f, "\"")?;
        for i in self.0 {
            for ch in escape_default(*i) {
                write!(f, "{}", ch as char)?;
            }
        }
        write!(f, "\"")?;
        Ok(())
    }
}

pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> String {
    match a {
        SYS_OPEN => format!(
            "open({:?}, {:#X})",
            validate_slice(b as *const u8, c).map(ByteStr),
            d
        ),
        SYS_CHMOD => format!(
            "chmod({:?}, {:#o})",
            validate_slice(b as *const u8, c).map(ByteStr),
            d
        ),
        SYS_RMDIR => format!(
            "rmdir({:?})",
            validate_slice(b as *const u8, c).map(ByteStr)
        ),
        SYS_UNLINK => format!(
            "unlink({:?})",
            validate_slice(b as *const u8, c).map(ByteStr)
        ),
        SYS_CLOSE => format!(
            "close({})", b
        ),
        SYS_DUP => format!(
            "dup({}, {:?})",
            b,
            validate_slice(c as *const u8, d).map(ByteStr)
        ),
        SYS_DUP2 => format!(
            "dup2({}, {}, {:?})",
            b,
            c,
            validate_slice(d as *const u8, e).map(ByteStr)
        ),
        SYS_READ => format!(
            "read({}, {:#X}, {})",
            b,
            c,
            d
        ),
        SYS_WRITE => format!(
            "write({}, {:#X}, {})",
            b,
            c,
            d
        ),
        SYS_LSEEK => format!(
            "lseek({}, {}, {} ({}))",
            b,
            c as isize,
            match d {
                SEEK_SET => "SEEK_SET",
                SEEK_CUR => "SEEK_CUR",
                SEEK_END => "SEEK_END",
                _ => "UNKNOWN"
            },
            d
        ),
        SYS_FCNTL => format!(
            "fcntl({}, {} ({}), {:#X})",
            b,
            match c {
                F_DUPFD => "F_DUPFD",
                F_GETFD => "F_GETFD",
                F_SETFD => "F_SETFD",
                F_SETFL => "F_SETFL",
                F_GETFL => "F_GETFL",
                _ => "UNKNOWN"
            },
            c,
            d
        ),
        SYS_FMAP => format!(
            "fmap({}, {:#X}, {})",
            b,
            c,
            d
        ),
        SYS_FUNMAP => format!(
            "funmap({:#X})",
            b
        ),
        SYS_FPATH => format!(
            "fpath({}, {:#X}, {})",
            b,
            c,
            d
        ),
        SYS_FSTAT => format!(
            "fstat({}, {:?})",
            b,
            validate_slice(
                c as *const Stat,
                d/mem::size_of::<Stat>()
            ),
        ),
        SYS_FSTATVFS => format!(
            "fstatvfs({}, {:#X}, {})",
            b,
            c,
            d
        ),
        SYS_FSYNC => format!(
            "fsync({})",
            b
        ),
        SYS_FTRUNCATE => format!(
            "ftruncate({}, {})",
            b,
            c
        ),

        SYS_BRK => format!(
            "brk({:#X})",
            b
        ),
        SYS_CHDIR => format!(
            "chdir({:?})",
            validate_slice(b as *const u8, c).map(ByteStr)
        ),
        SYS_CLOCK_GETTIME => format!(
            "clock_gettime({}, {:?})",
            b,
            validate_slice_mut(c as *mut TimeSpec, 1)
        ),
        SYS_CLONE => format!(
            "clone({})",
            b
        ),
        SYS_EXIT => format!(
            "exit({})",
            b
        ),
        //TODO: Cleanup, do not allocate
        SYS_FEXEC => format!(
            "fexec({}, {:?}, {:?})",
            b,
            validate_slice(
                c as *const [usize; 2],
                d
            ).map(|slice| {
                slice.iter().map(|a|
                    validate_slice(a[0] as *const u8, a[1]).ok()
                    .and_then(|s| ::core::str::from_utf8(s).ok())
                ).collect::<Vec<Option<&str>>>()
            }),
            validate_slice(
                e as *const [usize; 2],
                f
            ).map(|slice| {
                slice.iter().map(|a|
                    validate_slice(a[0] as *const u8, a[1]).ok()
                    .and_then(|s| ::core::str::from_utf8(s).ok())
                ).collect::<Vec<Option<&str>>>()
            })
        ),
        SYS_FUTEX => format!(
            "futex({:#X} [{:?}], {}, {}, {}, {})",
            b,
            validate_slice_mut(b as *mut i32, 1).map(|uaddr| &mut uaddr[0]),
            c,
            d,
            e,
            f
        ),
        SYS_GETCWD => format!(
            "getcwd({:#X}, {})",
            b,
            c
        ),
        SYS_GETEGID => format!("getegid()"),
        SYS_GETENS => format!("getens()"),
        SYS_GETEUID => format!("geteuid()"),
        SYS_GETGID => format!("getgid()"),
        SYS_GETNS => format!("getns()"),
        SYS_GETPID => format!("getpid()"),
        SYS_GETUID => format!("getuid()"),
        SYS_IOPL => format!(
            "iopl({})",
            b
        ),
        SYS_KILL => format!(
            "kill({}, {})",
            b,
            c
        ),
        SYS_SIGRETURN => format!("sigreturn()"),
        SYS_SIGACTION => format!(
            "sigaction({}, {:#X}, {:#X}, {:#X})",
            b,
            c,
            d,
            e
        ),
        SYS_MKNS => format!(
            "mkns({:?})",
            validate_slice(b as *const [usize; 2], c)
        ),
        SYS_NANOSLEEP => format!(
            "nanosleep({:?}, ({}, {}))",
            validate_slice(b as *const TimeSpec, 1),
            c,
            d
        ),
        SYS_PHYSALLOC => format!(
            "physalloc({})",
            b
        ),
        SYS_PHYSFREE => format!(
            "physfree({:#X}, {})",
            b,
            c
        ),
        SYS_PHYSMAP => format!(
            "physmap({:#X}, {}, {:#X})",
            b,
            c,
            d
        ),
        SYS_PHYSUNMAP => format!(
            "physunmap({:#X})",
            b
        ),
        SYS_VIRTTOPHYS => format!(
            "virttophys({:#X})",
            b
        ),
        SYS_PIPE2 => format!(
            "pipe2({:?}, {})",
            validate_slice_mut(b as *mut usize, 2),
            c
        ),
        SYS_SETREGID => format!(
            "setregid({}, {})",
            b,
            c
        ),
        SYS_SETRENS => format!(
            "setrens({}, {})",
            b,
            c
        ),
        SYS_SETREUID => format!(
            "setreuid({}, {})",
            b,
            c
        ),
        SYS_UMASK => format!(
            "umask({:#o}",
            b
        ),
        SYS_WAITPID => format!(
            "waitpid({}, {:#X}, {})",
            b,
            c,
            d
        ),
        SYS_YIELD => format!("yield()"),
        _ => format!(
            "UNKNOWN{} {:#X}({:#X}, {:#X}, {:#X}, {:#X}, {:#X})",
            a, a,
            b,
            c,
            d,
            e,
            f
        )
    }
}
<|endoftext|>