<commit_before>//! A wrapper around a drawable. This controls all the other state about
//! the surface, such as the cursor used or where it on the screen.

// NOTE need to store the drawable in lua, because it's a reference to a
// drawable a lua object

use {
    cairo::ImageSurface,
    rlua::{
        self, prelude::LuaInteger, Table, ToLua, UserData, UserDataMethods,
        Value
    }
};

use crate::{
    area::{Area, Origin, Size},
    common::{
        class::{self, Class, ClassBuilder},
        object::{self, Object, ObjectBuilder},
        property::Property
    },
    objects::drawable::Drawable
};

pub const DRAWINS_HANDLE: &'static str = "__drawins";

#[derive(Debug, Default)]
pub struct DrawinState {
    // NOTE This has a drawable, but it is stored in lua.
    ontop: bool,
    visible: bool,
    cursor: String,
    geometry: Area,
    geometry_dirty: bool,
    surface: Option<ImageSurface>
}

pub type Drawin<'lua> = Object<'lua, DrawinState>;

impl UserData for DrawinState {
    fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
        object::default_add_methods(methods);
    }
}

impl<'lua> Drawin<'lua> {
    fn new(
        lua: rlua::Context<'lua>,
        args: Table<'lua>
    ) -> rlua::Result<Drawin<'lua>> {
        let class = class::class_setup(lua, "drawin")?;
        let mut drawins =
            lua.named_registry_value::<str, Vec<Drawin>>(DRAWINS_HANDLE)?;
        let drawin = object_setup(lua, Drawin::allocate(lua, class)?)?
            .handle_constructor_argument(args)?
            .build();
        drawins.push(drawin.clone());
        lua.set_named_registry_value(DRAWINS_HANDLE, drawins.to_lua(lua)?)?;
        Ok(drawin)
    }

    /// Get the drawable associated with this drawin.
    ///
    /// It has the surface that is needed to render to the screen.
    #[allow(dead_code)]
    pub fn drawable(&mut self) -> rlua::Result<Drawable<'lua>> {
        self.get_associated_data::<Drawable>("drawable")
    }

    fn update_drawing(&mut self, lua: rlua::Context<'lua>) -> rlua::Result<()> {
        let mut drawable: Drawable = self.get_associated_data("drawable")?;
        {
            let mut state = self.state_mut()?;
            if state.geometry_dirty {
                drawable.set_geometry(lua, state.geometry)?;
                state.geometry_dirty = false;
            }
        }
        self.set_associated_data("drawable", drawable)?;
        Ok(())
    }

    pub fn get_visible(&mut self) -> rlua::Result<bool> {
        let drawin = self.state()?;
        Ok(drawin.visible)
    }

    fn set_visible(
        &mut self,
        lua: rlua::Context<'lua>,
        val: bool
    ) -> rlua::Result<()> {
        {
            let mut drawin = self.state_mut()?;
            drawin.visible = val;
        }
        if val {
            self.map(lua)
        } else {
            self.unmap()
        }
    }

    fn map(&mut self, lua: rlua::Context<'lua>) -> rlua::Result<()> {
        // TODO other things
        self.update_drawing(lua)?;
        Ok(())
    }

    fn unmap(&mut self) -> rlua::Result<()> {
        // TODO?
        Ok(())
    }

    pub fn get_geometry(&self) -> rlua::Result<Area> {
        Ok(self.state()?.geometry)
    }

    fn resize(
        &mut self,
        lua: rlua::Context<'lua>,
        geometry: Area
    ) -> rlua::Result<()> {
        {
            let mut state = self.state_mut()?;
            let old_geometry = state.geometry;
            state.geometry = geometry;
            {
                let Size {
                    ref mut width,
                    ref mut height
                } = state.geometry.size;
                if *width == 0 {
                    *width = old_geometry.size.width;
                }
                if *height == 0 {
                    *height = old_geometry.size.height
                }
            }
            state.geometry_dirty = true;
            // TODO emit signals
            // TODO update screen workareas like in awesome? Might not be necessary
        }
        self.update_drawing(lua)
    }
}

pub fn init(lua: rlua::Context) -> rlua::Result<Class<DrawinState>> {
    let drawins: Vec<Drawin> = Vec::new();
    lua.set_named_registry_value(DRAWINS_HANDLE, drawins.to_lua(lua)?)?;
    property_setup(
        lua,
        method_setup(lua, Class::builder(lua, "drawin", None)?)?
    )?
    .save_class("drawin")?
    .build()
}

fn method_setup<'lua>(
    lua: rlua::Context<'lua>,
    builder: ClassBuilder<'lua, DrawinState>
) -> rlua::Result<ClassBuilder<'lua, DrawinState>> {
    // TODO Do properly
    builder
           // TODO This should be adding properties, e.g like luaA_class_new
           .method("__call".into(), lua.create_function(|lua, args: Table| Drawin::new(lua, args))?)
}

fn property_setup<'lua>(
    lua: rlua::Context<'lua>,
    builder: ClassBuilder<'lua, DrawinState>
) -> rlua::Result<ClassBuilder<'lua, DrawinState>> {
    builder
        .property(Property::new(
            "x".into(),
            Some(lua.create_function(set_x)?),
            Some(lua.create_function(get_x)?),
            Some(lua.create_function(set_x)?)
        ))?
        .property(Property::new(
            "y".into(),
            Some(lua.create_function(set_y)?),
            Some(lua.create_function(get_y)?),
            Some(lua.create_function(set_y)?)
        ))?
        .property(Property::new(
            "width".into(),
            Some(lua.create_function(set_width)?),
            Some(lua.create_function(get_width)?),
            Some(lua.create_function(set_width)?)
        ))?
        .property(Property::new(
            "height".into(),
            Some(lua.create_function(set_height)?),
            Some(lua.create_function(get_height)?),
            Some(lua.create_function(set_height)?)
        ))?
        .property(Property::new(
            "visible".into(),
            Some(lua.create_function(set_visible)?),
            Some(lua.create_function(get_visible)?),
            Some(lua.create_function(set_visible)?)
        ))
}

fn object_setup<'lua>(
    lua: rlua::Context<'lua>,
    builder: ObjectBuilder<'lua, DrawinState>
) -> rlua::Result<ObjectBuilder<'lua, DrawinState>> {
    let drawable_table = Drawable::new(lua)?.to_lua(lua)?;

    let table = lua.create_table()?;
    table.set("drawable", drawable_table)?;
    table.set("geometry", lua.create_function(drawin_geometry)?)?;
    table.set("struts", lua.create_function(drawin_struts)?)?;
    table.set("buttons", lua.create_function(super::dummy)?)?;
    builder.add_to_meta(table)
}

fn set_visible<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, visible): (Drawin<'lua>, bool)
) -> rlua::Result<()> {
    drawin.set_visible(lua, visible)?;
    // TODO signal
    Object::emit_signal(lua, &drawin, "property::visible".into(), Value::Nil)
}

fn get_visible<'lua>(
    _: rlua::Context<'lua>,
    mut drawin: Drawin<'lua>
) -> rlua::Result<bool> {
    drawin.get_visible()
    // TODO signal
}

fn drawin_geometry<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, geometry): (Drawin<'lua>, Option<Table<'lua>>)
) -> rlua::Result<Table<'lua>> {
    if let Some(geometry) = geometry {
        let width = geometry.get::<_, u32>("width")?;
        let height = geometry.get::<_, u32>("height")?;
        let x = geometry.get::<_, i32>("x")?;
        let y = geometry.get::<_, i32>("y")?;
        if width > 0 && height > 0 {
            let geo = Area {
                origin: Origin { x, y },
                size: Size { width, height }
            };
            drawin.resize(lua, geo)?;
        }
    }
    let new_geo = drawin.get_geometry()?;
    let Size { width, height } = new_geo.size;
    let Origin { x, y } = new_geo.origin;
    let res = lua.create_table()?;
    res.set("x", x)?;
    res.set("y", y)?;
    res.set("height", height)?;
    res.set("width", width)?;
    Ok(res)
}

fn get_x<'lua>(
    _: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<LuaInteger> {
    let Origin { x, .. } = drawin.get_geometry()?.origin;
    Ok(x as LuaInteger)
}

fn set_x<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, x): (Drawin<'lua>, LuaInteger)
) -> rlua::Result<()> {
    let mut geo = drawin.get_geometry()?;
    geo.origin.x = x as i32;
    drawin.resize(lua, geo)?;
    Ok(())
}

fn get_y<'lua>(
    _: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<LuaInteger> {
    let Origin { y, .. } = drawin.get_geometry()?.origin;
    Ok(y as LuaInteger)
}

fn set_y<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, y): (Drawin<'lua>, LuaInteger)
) -> rlua::Result<()> {
    let mut geo = drawin.get_geometry()?;
    geo.origin.y = y as i32;
    drawin.resize(lua, geo)?;
    Ok(())
}

fn get_width<'lua>(
    _: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<LuaInteger> {
    let Size { width, .. } = drawin.get_geometry()?.size;
    Ok(width as LuaInteger)
}

fn set_width<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, width): (Drawin<'lua>, LuaInteger)
) -> rlua::Result<()> {
    let mut geo = drawin.get_geometry()?;
    if width > 0 {
        geo.size.width = width as u32;
        drawin.resize(lua, geo)?;
    }
    Ok(())
}

fn get_height<'lua>(
    _lua: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<LuaInteger> {
    let Size { height, .. } = drawin.get_geometry()?.size;
    Ok(height as LuaInteger)
}

fn set_height<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, height): (Drawin<'lua>, LuaInteger)
) -> rlua::Result<()> {
    let mut geo = drawin.get_geometry()?;
    if height > 0 {
        geo.size.height = height as u32;
        drawin.resize(lua, geo)?;
    }
    Ok(())
}

fn drawin_struts<'lua>(
    lua: rlua::Context<'lua>,
    _drawin: Drawin<'lua>
) -> rlua::Result<Table<'lua>> {
    // TODO: Implement this properly. Struts means this drawin reserves some space
    // on the screen that it is visible on, shrinking the workarea in the
    // specified directions.
    let res = lua.create_table()?;
    res.set("left", 0)?;
    res.set("right", 0)?;
    res.set("top", 0)?;
    res.set("bottom", 0)?;
    Ok(res)
}
<commit_msg>remove todo<commit_after>//! A wrapper around a drawable. This controls all the other state about
//! the surface, such as the cursor used or where it on the screen.

// NOTE need to store the drawable in lua, because it's a reference to a
// drawable a lua object

use {
    cairo::ImageSurface,
    rlua::{
        self, prelude::LuaInteger, Table, ToLua, UserData, UserDataMethods,
        Value
    }
};

use crate::{
    area::{Area, Origin, Size},
    common::{
        class::{self, Class, ClassBuilder},
        object::{self, Object, ObjectBuilder},
        property::Property
    },
    objects::drawable::Drawable
};

pub const DRAWINS_HANDLE: &'static str = "__drawins";

#[derive(Debug, Default)]
pub struct DrawinState {
    // NOTE This has a drawable, but it is stored in lua.
    ontop: bool,
    visible: bool,
    cursor: String,
    geometry: Area,
    geometry_dirty: bool,
    surface: Option<ImageSurface>
}

pub type Drawin<'lua> = Object<'lua, DrawinState>;

impl UserData for DrawinState {
    fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
        object::default_add_methods(methods);
    }
}

impl<'lua> Drawin<'lua> {
    fn new(
        lua: rlua::Context<'lua>,
        args: Table<'lua>
    ) -> rlua::Result<Drawin<'lua>> {
        let class = class::class_setup(lua, "drawin")?;
        let mut drawins =
            lua.named_registry_value::<str, Vec<Drawin>>(DRAWINS_HANDLE)?;
        let drawin = object_setup(lua, Drawin::allocate(lua, class)?)?
            .handle_constructor_argument(args)?
            .build();
        drawins.push(drawin.clone());
        lua.set_named_registry_value(DRAWINS_HANDLE, drawins.to_lua(lua)?)?;
        Ok(drawin)
    }

    /// Get the drawable associated with this drawin.
    ///
    /// It has the surface that is needed to render to the screen.
    #[allow(dead_code)]
    pub fn drawable(&mut self) -> rlua::Result<Drawable<'lua>> {
        self.get_associated_data::<Drawable>("drawable")
    }

    fn update_drawing(&mut self, lua: rlua::Context<'lua>) -> rlua::Result<()> {
        let mut drawable: Drawable = self.get_associated_data("drawable")?;
        {
            let mut state = self.state_mut()?;
            if state.geometry_dirty {
                drawable.set_geometry(lua, state.geometry)?;
                state.geometry_dirty = false;
            }
        }
        self.set_associated_data("drawable", drawable)?;
        Ok(())
    }

    pub fn get_visible(&mut self) -> rlua::Result<bool> {
        let drawin = self.state()?;
        Ok(drawin.visible)
    }

    fn set_visible(
        &mut self,
        lua: rlua::Context<'lua>,
        val: bool
    ) -> rlua::Result<()> {
        {
            let mut drawin = self.state_mut()?;
            drawin.visible = val;
        }
        if val {
            self.map(lua)
        } else {
            self.unmap()
        }
    }

    fn map(&mut self, lua: rlua::Context<'lua>) -> rlua::Result<()> {
        // TODO other things
        self.update_drawing(lua)?;
        Ok(())
    }

    fn unmap(&mut self) -> rlua::Result<()> {
        // TODO?
        Ok(())
    }

    pub fn get_geometry(&self) -> rlua::Result<Area> {
        Ok(self.state()?.geometry)
    }

    fn resize(
        &mut self,
        lua: rlua::Context<'lua>,
        geometry: Area
    ) -> rlua::Result<()> {
        {
            let mut state = self.state_mut()?;
            let old_geometry = state.geometry;
            state.geometry = geometry;
            {
                let Size {
                    ref mut width,
                    ref mut height
                } = state.geometry.size;
                if *width == 0 {
                    *width = old_geometry.size.width;
                }
                if *height == 0 {
                    *height = old_geometry.size.height
                }
            }
            state.geometry_dirty = true;
            // TODO emit signals
            // TODO update screen workareas like in awesome? Might not be necessary
        }
        self.update_drawing(lua)
    }
}

pub fn init(lua: rlua::Context) -> rlua::Result<Class<DrawinState>> {
    let drawins: Vec<Drawin> = Vec::new();
    lua.set_named_registry_value(DRAWINS_HANDLE, drawins.to_lua(lua)?)?;
    property_setup(
        lua,
        method_setup(lua, Class::builder(lua, "drawin", None)?)?
    )?
    .save_class("drawin")?
    .build()
}

fn method_setup<'lua>(
    lua: rlua::Context<'lua>,
    builder: ClassBuilder<'lua, DrawinState>
) -> rlua::Result<ClassBuilder<'lua, DrawinState>> {
    // TODO Do properly
    builder
           // TODO This should be adding properties, e.g like luaA_class_new
           .method("__call".into(), lua.create_function(|lua, args: Table| Drawin::new(lua, args))?)
}

fn property_setup<'lua>(
    lua: rlua::Context<'lua>,
    builder: ClassBuilder<'lua, DrawinState>
) -> rlua::Result<ClassBuilder<'lua, DrawinState>> {
    builder
        .property(Property::new(
            "x".into(),
            Some(lua.create_function(set_x)?),
            Some(lua.create_function(get_x)?),
            Some(lua.create_function(set_x)?)
        ))?
        .property(Property::new(
            "y".into(),
            Some(lua.create_function(set_y)?),
            Some(lua.create_function(get_y)?),
            Some(lua.create_function(set_y)?)
        ))?
        .property(Property::new(
            "width".into(),
            Some(lua.create_function(set_width)?),
            Some(lua.create_function(get_width)?),
            Some(lua.create_function(set_width)?)
        ))?
        .property(Property::new(
            "height".into(),
            Some(lua.create_function(set_height)?),
            Some(lua.create_function(get_height)?),
            Some(lua.create_function(set_height)?)
        ))?
        .property(Property::new(
            "visible".into(),
            Some(lua.create_function(set_visible)?),
            Some(lua.create_function(get_visible)?),
            Some(lua.create_function(set_visible)?)
        ))
}

fn object_setup<'lua>(
    lua: rlua::Context<'lua>,
    builder: ObjectBuilder<'lua, DrawinState>
) -> rlua::Result<ObjectBuilder<'lua, DrawinState>> {
    let drawable_table = Drawable::new(lua)?.to_lua(lua)?;

    let table = lua.create_table()?;
    table.set("drawable", drawable_table)?;
    table.set("geometry", lua.create_function(drawin_geometry)?)?;
    table.set("struts", lua.create_function(drawin_struts)?)?;
    table.set("buttons", lua.create_function(super::dummy)?)?;
    builder.add_to_meta(table)
}

fn set_visible<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, visible): (Drawin<'lua>, bool)
) -> rlua::Result<()> {
    drawin.set_visible(lua, visible)?;
    Object::emit_signal(lua, &drawin, "property::visible".into(), Value::Nil)
}

fn get_visible<'lua>(
    _: rlua::Context<'lua>,
    mut drawin: Drawin<'lua>
) -> rlua::Result<bool> {
    drawin.get_visible()
    // TODO signal
}

fn drawin_geometry<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, geometry): (Drawin<'lua>, Option<Table<'lua>>)
) -> rlua::Result<Table<'lua>> {
    if let Some(geometry) = geometry {
        let width = geometry.get::<_, u32>("width")?;
        let height = geometry.get::<_, u32>("height")?;
        let x = geometry.get::<_, i32>("x")?;
        let y = geometry.get::<_, i32>("y")?;
        if width > 0 && height > 0 {
            let geo = Area {
                origin: Origin { x, y },
                size: Size { width, height }
            };
            drawin.resize(lua, geo)?;
        }
    }
    let new_geo = drawin.get_geometry()?;
    let Size { width, height } = new_geo.size;
    let Origin { x, y } = new_geo.origin;
    let res = lua.create_table()?;
    res.set("x", x)?;
    res.set("y", y)?;
    res.set("height", height)?;
    res.set("width", width)?;
    Ok(res)
}

fn get_x<'lua>(
    _: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<LuaInteger> {
    let Origin { x, .. } = drawin.get_geometry()?.origin;
    Ok(x as LuaInteger)
}

fn set_x<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, x): (Drawin<'lua>, LuaInteger)
) -> rlua::Result<()> {
    let mut geo = drawin.get_geometry()?;
    geo.origin.x = x as i32;
    drawin.resize(lua, geo)?;
    Ok(())
}

fn get_y<'lua>(
    _: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<LuaInteger> {
    let Origin { y, .. } = drawin.get_geometry()?.origin;
    Ok(y as LuaInteger)
}

fn set_y<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, y): (Drawin<'lua>, LuaInteger)
) -> rlua::Result<()> {
    let mut geo = drawin.get_geometry()?;
    geo.origin.y = y as i32;
    drawin.resize(lua, geo)?;
    Ok(())
}

fn get_width<'lua>(
    _: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<LuaInteger> {
    let Size { width, .. } = drawin.get_geometry()?.size;
    Ok(width as LuaInteger)
}

fn set_width<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, width): (Drawin<'lua>, LuaInteger)
) -> rlua::Result<()> {
    let mut geo = drawin.get_geometry()?;
    if width > 0 {
        geo.size.width = width as u32;
        drawin.resize(lua, geo)?;
    }
    Ok(())
}

fn get_height<'lua>(
    _lua: rlua::Context<'lua>,
    drawin: Drawin<'lua>
) -> rlua::Result<LuaInteger> {
    let Size { height, .. } = drawin.get_geometry()?.size;
    Ok(height as LuaInteger)
}

fn set_height<'lua>(
    lua: rlua::Context<'lua>,
    (mut drawin, height): (Drawin<'lua>, LuaInteger)
) -> rlua::Result<()> {
    let mut geo = drawin.get_geometry()?;
    if height > 0 {
        geo.size.height = height as u32;
        drawin.resize(lua, geo)?;
    }
    Ok(())
}

fn drawin_struts<'lua>(
    lua: rlua::Context<'lua>,
    _drawin: Drawin<'lua>
) -> rlua::Result<Table<'lua>> {
    // TODO: Implement this properly. Struts means this drawin reserves some space
    // on the screen that it is visible on, shrinking the workarea in the
    // specified directions.
    let res = lua.create_table()?;
    res.set("left", 0)?;
    res.set("right", 0)?;
    res.set("top", 0)?;
    res.set("bottom", 0)?;
    Ok(res)
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use graphql_cli::SourcePrinter;
use std::ops::Range;

const EXAMPLE: &'static str = "fragment Example on User {
  photo(size: 40) {
    url
  }
}
some
more
lines
";

fn main() {
    // println!("char index, byte index, char");
    // for (ci, (bi, chr)) in EXAMPLE.char_indices().enumerate() {
    //     println!("{:>2}, {:>2}: {:?}", ci, bi, chr);
    // }

    let test_cases: Vec<Range<usize>> = vec![
        // first char
        0..1,
        // second char
        1..2,
        // photo
        29..34,
        // new line
        46..47,
        // outer {} block
        25..60,
    ];
    let printer = SourcePrinter::new();
    for test_case in test_cases.into_iter() {
        let mut res = String::new();
        printer
            .write_span(&mut res, &test_case.into(), &EXAMPLE)
            .unwrap();
        println!("{}", res);
    }
}
<commit_msg>Unbreak graphql-cli cargo build<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use graphql_cli::SourcePrinter;
use std::ops::Range;

const EXAMPLE: &'static str = "fragment Example on User {
  photo(size: 40) {
    url
  }
}
some
more
lines
";

fn main() {
    // println!("char index, byte index, char");
    // for (ci, (bi, chr)) in EXAMPLE.char_indices().enumerate() {
    //     println!("{:>2}, {:>2}: {:?}", ci, bi, chr);
    // }

    let test_cases: Vec<Range<usize>> = vec![
        // first char
        0..1,
        // second char
        1..2,
        // photo
        29..34,
        // new line
        46..47,
        // outer {} block
        25..60,
    ];
    let printer = SourcePrinter::default();
    for test_case in test_cases.into_iter() {
        let mut res = String::new();
        printer
            .write_span(&mut res, &test_case.into(), &EXAMPLE)
            .unwrap();
        println!("{}", res);
    }
}
<|endoftext|>


<commit_before>use crate::error::Error;
use bytes::buf::BufMutExt;
use bytes::{BufMut, Bytes, BytesMut};
use serde::{Serialize};

/// Body of an API call.
pub trait Body {
    /// Write to a buffer that will be written to the request stream
    fn write(&self, bytes: &mut BytesMut) -> Result<(), Error>;
}

/// A JSON body of an API call
pub struct JsonBody<T>(pub(crate) T);

impl<T> JsonBody<T>
where
    T: Serialize,
{
    /// Creates a new instance of [JsonBody]
    pub fn new(t: T) -> Self {
        Self(t)
    }
}

impl<T> From<T> for JsonBody<T>
where
    T: Serialize,
{
    /// Creates a new instance of [JsonBody] from a type `T` that implements [serde::Serialize]
    fn from(t: T) -> Self {
        JsonBody(t)
    }
}

impl<T> Body for JsonBody<T>
where
    T: Serialize,
{
    fn write(&self, bytes: &mut BytesMut) -> Result<(), Error> {
        let writer = bytes.writer();
        match serde_json::to_writer(writer, &self.0) {
            Ok(_) => Ok(()),
            Err(e) => Err(Error::Json(e)),
        }
    }
}

/// A Newline-delimited body of an API call
pub struct NdBody<T>(pub(crate) Vec<T>);

impl<T> NdBody<T>
where
    T: Body,
{
    /// Creates a new instance of [NdBody]
    pub fn new(b: Vec<T>) -> Self {
        Self(b)
    }
}

// Accepts T as Body as opposed to Serialize, because each T may need to
// serialize to newline delimited in future e.g. A BulkOperation struct
// that implements Body could contain the operation and a document.
impl<T> Body for NdBody<T>
where
    T: Body,
{
    fn write(&self, bytes: &mut BytesMut) -> Result<(), Error> {
        for line in &self.0 {
            line.write(bytes)?;
            bytes.put_u8(b'\n');
        }
        Ok(())
    }
}

impl Body for Bytes {
    fn write(&self, bytes: &mut BytesMut) -> Result<(), Error> {
        bytes.resize(self.len(), 0);
        bytes.copy_from_slice(&self[..]);
        Ok(())
    }
}

impl Body for Vec<u8> {
    fn write(&self, bytes: &mut BytesMut) -> Result<(), Error> {
        bytes.resize(self.len(), 0);
        bytes.copy_from_slice(&self[..]);
        Ok(())
    }
}

impl Body for &'static [u8] {
    fn write(&self, bytes: &mut BytesMut) -> Result<(), Error> {
        bytes.resize(self.len(), 0);
        bytes.copy_from_slice(&self[..]);
        Ok(())
    }
}

impl Body for String {
    fn write(&self, bytes: &mut BytesMut) -> Result<(), Error> {
        bytes.resize(self.len(), 0);
        bytes.copy_from_slice(self.as_bytes());
        Ok(())
    }
}

impl Body for &'static str {
    fn write(&self, bytes: &mut BytesMut) -> Result<(), Error> {
        bytes.resize(self.len(), 0);
        bytes.copy_from_slice(self.as_bytes());
        Ok(())
    }
}

impl Body for () {
    fn write(&self, _bytes: &mut BytesMut) -> Result<(), Error> {
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use crate::http::request::{Body, JsonBody, NdBody};
    use bytes::BytesMut;
    use serde_json::json;

    #[test]
    fn serialize_into_jsonbody_writes_to_bytes() -> Result<(), failure::Error> {
        let mut bytes = BytesMut::with_capacity(21);
        let body: JsonBody<_> = json!({"foo":"bar","baz":1}).into();
        let _ = body.write(&mut bytes)?;
        // NOTE: serde_json writes properties lexicographically
        assert_eq!(b"{\"baz\":1,\"foo\":\"bar\"}", &bytes[..]);

        Ok(())
    }

    #[test]
    fn bodies_into_ndbody_writes_to_bytes() -> Result<(), failure::Error> {
        let mut bytes = BytesMut::with_capacity(22);
        let mut bodies: Vec<JsonBody<_>> = Vec::with_capacity(2);
        bodies.push(json!({"item":1}).into());
        bodies.push(json!({"item":2}).into());

        let body = NdBody(bodies);
        let _ = body.write(&mut bytes)?;
        assert_eq!(b"{\"item\":1}\n{\"item\":2}\n", &bytes[..]);

        Ok(())
    }

    #[test]
    fn bytes_body_writes_to_bytes_mut() -> Result<(), failure::Error> {
        let mut bytes_mut = BytesMut::with_capacity(21);
        let bytes = bytes::Bytes::from(&b"{\"foo\":\"bar\",\"baz\":1}"[..]);
        let _ = bytes.write(&mut bytes_mut)?;
        assert_eq!(&bytes[..], &bytes_mut[..]);

        Ok(())
    }

    #[test]
    fn vec_body_writes_to_bytes_mut() -> Result<(), failure::Error> {
        let mut bytes_mut = BytesMut::with_capacity(21);
        let bytes = b"{\"foo\":\"bar\",\"baz\":1}".to_vec();
        let _ = bytes.write(&mut bytes_mut)?;
        assert_eq!(&bytes[..], &bytes_mut[..]);

        Ok(())
    }

    #[test]
    fn bytes_slice_body_writes_to_bytes_mut() -> Result<(), failure::Error> {
        let mut bytes_mut = BytesMut::with_capacity(21);
        let bytes: &'static [u8] = b"{\"foo\":\"bar\",\"baz\":1}";
        let _ = bytes.write(&mut bytes_mut)?;
        assert_eq!(&bytes[..], &bytes_mut[..]);

        Ok(())
    }

    #[test]
    fn string_body_writes_to_bytes_mut() -> Result<(), failure::Error> {
        let mut bytes_mut = BytesMut::with_capacity(21);
        let s = String::from("{\"foo\":\"bar\",\"baz\":1}");
        let _ = s.write(&mut bytes_mut)?;
        assert_eq!(s.as_bytes(), &bytes_mut[..]);

        Ok(())
    }

    #[test]
    fn string_slice_body_writes_to_bytes_mut() -> Result<(), failure::Error> {
        let mut bytes_mut = BytesMut::with_capacity(21);
        let s: &'static str = "{\"foo\":\"bar\",\"baz\":1}";
        let _ = s.write(&mut bytes_mut)?;
        assert_eq!(s.as_bytes(), &bytes_mut[..]);

        Ok(())
    }
}
<commit_msg>Add doc comments for Body impls<commit_after>use crate::error::Error;
use bytes::buf::BufMutExt;
use bytes::{BufMut, Bytes, BytesMut};
use serde::{Serialize};

/// Body of an API call.
///
/// Some Elasticsearch APIs accept a body as part of the API call. Most APIs
/// expect JSON, however, there are some APIs that expect newline-delimited JSON (NDJSON).
/// [Body] allows modelling different API body implementations.
pub trait Body {
    /// Write to a buffer that will be written to the request stream
    fn write(&self, bytes: &mut BytesMut) -> Result<(), Error>;
}

/// A JSON body of an API call.
pub struct JsonBody<T>(pub(crate) T);

impl<T> JsonBody<T>
where
    T: Serialize,
{
    /// Creates a new instance of [JsonBody] for a type `T` that implements [serde::Serialize]
    pub fn new(t: T) -> Self {
        Self(t)
    }
}

impl<T> From<T> for JsonBody<T>
where
    T: Serialize,
{
    /// Creates a new instance of [JsonBody] from a type `T` that implements [serde::Serialize]
    fn from(t: T) -> Self {
        JsonBody(t)
    }
}

impl<T> Body for JsonBody<T>
where
    T: Serialize,
{
    fn write(&self, bytes: &mut BytesMut) -> Result<(), Error> {
        let writer = bytes.writer();
        match serde_json::to_writer(writer, &self.0) {
            Ok(_) => Ok(()),
            Err(e) => Err(Error::Json(e)),
        }
    }
}

/// A Newline-delimited body of an API call
pub struct NdBody<T>(pub(crate) Vec<T>);

impl<T> NdBody<T>
where
    T: Body,
{
    /// Creates a new instance of [NdBody], for a collection of `T` that implement [Body].
    ///
    /// Accepts `T` that implement [Body] as opposed to [serde::Serialize], because each `T`
    /// itself may need to serialize to newline delimited.
    pub fn new(b: Vec<T>) -> Self {
        Self(b)
    }
}

impl<T> Body for NdBody<T>
where
    T: Body,
{
    fn write(&self, bytes: &mut BytesMut) -> Result<(), Error> {
        for line in &self.0 {
            line.write(bytes)?;
            bytes.put_u8(b'\n');
        }
        Ok(())
    }
}

impl Body for Bytes {
    fn write(&self, bytes: &mut BytesMut) -> Result<(), Error> {
        bytes.resize(self.len(), 0);
        bytes.copy_from_slice(&self[..]);
        Ok(())
    }
}

impl Body for Vec<u8> {
    fn write(&self, bytes: &mut BytesMut) -> Result<(), Error> {
        bytes.resize(self.len(), 0);
        bytes.copy_from_slice(&self[..]);
        Ok(())
    }
}

impl Body for &'static [u8] {
    fn write(&self, bytes: &mut BytesMut) -> Result<(), Error> {
        bytes.resize(self.len(), 0);
        bytes.copy_from_slice(&self[..]);
        Ok(())
    }
}

impl Body for String {
    fn write(&self, bytes: &mut BytesMut) -> Result<(), Error> {
        bytes.resize(self.len(), 0);
        bytes.copy_from_slice(self.as_bytes());
        Ok(())
    }
}

impl Body for &'static str {
    fn write(&self, bytes: &mut BytesMut) -> Result<(), Error> {
        bytes.resize(self.len(), 0);
        bytes.copy_from_slice(self.as_bytes());
        Ok(())
    }
}

impl Body for () {
    fn write(&self, _bytes: &mut BytesMut) -> Result<(), Error> {
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use crate::http::request::{Body, JsonBody, NdBody};
    use bytes::BytesMut;
    use serde_json::json;

    #[test]
    fn serialize_into_jsonbody_writes_to_bytes() -> Result<(), failure::Error> {
        let mut bytes = BytesMut::with_capacity(21);
        let body: JsonBody<_> = json!({"foo":"bar","baz":1}).into();
        let _ = body.write(&mut bytes)?;
        // NOTE: serde_json writes properties lexicographically
        assert_eq!(b"{\"baz\":1,\"foo\":\"bar\"}", &bytes[..]);

        Ok(())
    }

    #[test]
    fn bodies_into_ndbody_writes_to_bytes() -> Result<(), failure::Error> {
        let mut bytes = BytesMut::with_capacity(22);
        let mut bodies: Vec<JsonBody<_>> = Vec::with_capacity(2);
        bodies.push(json!({"item":1}).into());
        bodies.push(json!({"item":2}).into());

        let body = NdBody(bodies);
        let _ = body.write(&mut bytes)?;
        assert_eq!(b"{\"item\":1}\n{\"item\":2}\n", &bytes[..]);

        Ok(())
    }

    #[test]
    fn bytes_body_writes_to_bytes_mut() -> Result<(), failure::Error> {
        let mut bytes_mut = BytesMut::with_capacity(21);
        let bytes = bytes::Bytes::from(&b"{\"foo\":\"bar\",\"baz\":1}"[..]);
        let _ = bytes.write(&mut bytes_mut)?;
        assert_eq!(&bytes[..], &bytes_mut[..]);

        Ok(())
    }

    #[test]
    fn vec_body_writes_to_bytes_mut() -> Result<(), failure::Error> {
        let mut bytes_mut = BytesMut::with_capacity(21);
        let bytes = b"{\"foo\":\"bar\",\"baz\":1}".to_vec();
        let _ = bytes.write(&mut bytes_mut)?;
        assert_eq!(&bytes[..], &bytes_mut[..]);

        Ok(())
    }

    #[test]
    fn bytes_slice_body_writes_to_bytes_mut() -> Result<(), failure::Error> {
        let mut bytes_mut = BytesMut::with_capacity(21);
        let bytes: &'static [u8] = b"{\"foo\":\"bar\",\"baz\":1}";
        let _ = bytes.write(&mut bytes_mut)?;
        assert_eq!(&bytes[..], &bytes_mut[..]);

        Ok(())
    }

    #[test]
    fn string_body_writes_to_bytes_mut() -> Result<(), failure::Error> {
        let mut bytes_mut = BytesMut::with_capacity(21);
        let s = String::from("{\"foo\":\"bar\",\"baz\":1}");
        let _ = s.write(&mut bytes_mut)?;
        assert_eq!(s.as_bytes(), &bytes_mut[..]);

        Ok(())
    }

    #[test]
    fn string_slice_body_writes_to_bytes_mut() -> Result<(), failure::Error> {
        let mut bytes_mut = BytesMut::with_capacity(21);
        let s: &'static str = "{\"foo\":\"bar\",\"baz\":1}";
        let _ = s.write(&mut bytes_mut)?;
        assert_eq!(s.as_bytes(), &bytes_mut[..]);

        Ok(())
    }
}
<|endoftext|>


<commit_before>// This should fail even without validation
// compile-flags: -Zmiri-disable-validation

fn main() {
    for _ in 0..10 { // Try many times as this might work by chance.
        let x = 2u8;
        let x = &x as *const _ as *const [u32; 0];
        // This must fail because alignment is violated. Test specifically for loading ZST.
        let _x = unsafe { *x }; //~ERROR alignment 4 is required
    }
}
<commit_msg>another optimization work-around<commit_after>// This should fail even without validation
// compile-flags: -Zmiri-disable-validation

fn main() {
    for i in 0..10 { // Try many times as this might work by chance.
        let x = i as u8;
        let x = &x as *const _ as *const [u32; 0];
        // This must fail because alignment is violated. Test specifically for loading ZST.
        let _x = unsafe { *x }; //~ERROR alignment 4 is required
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
use crate::protocol::JsonPacketStream;
use crate::StreamId;
use serde_json::{Map, Value};
use servo_config::pref_util::PrefValue;
use servo_config::prefs::pref_map;
use std::net::TcpStream;

pub struct PreferenceActor {
    name: String,
}

impl PreferenceActor {
    pub fn new(name: String) -> Self {
        Self { name }
    }
}

impl Actor for PreferenceActor {
    fn name(&self) -> String {
        self.name.clone()
    }

    fn handle_message(
        &self,
        _registry: &ActorRegistry,
        msg_type: &str,
        _msg: &Map<String, Value>,
        stream: &mut TcpStream,
        _id: StreamId,
    ) -> Result<ActorMessageStatus, ()> {
        let pref_value = pref_map().get(msg_type);
        Ok(match pref_value {
            PrefValue::Float(value) => {
                let reply = FloatReply {
                    from: self.name(),
                    value: value,
                };
                let _ = stream.write_json_packet(&reply);
                ActorMessageStatus::Processed
            },
            PrefValue::Int(value) => {
                let reply = IntReply {
                    from: self.name(),
                    value: value,
                };
                let _ = stream.write_json_packet(&reply);
                ActorMessageStatus::Processed
            },
            PrefValue::Str(value) => {
                let reply = CharReply {
                    from: self.name(),
                    value: value,
                };
                let _ = stream.write_json_packet(&reply);
                ActorMessageStatus::Processed
            },
            PrefValue::Bool(value) => {
                let reply = BoolReply {
                    from: self.name(),
                    value: value,
                };
                let _ = stream.write_json_packet(&reply);
                ActorMessageStatus::Processed
            },
            PrefValue::Missing => ActorMessageStatus::Ignored,
        })
    }
}

#[derive(Serialize)]
struct BoolReply {
    from: String,
    value: bool,
}

#[derive(Serialize)]
struct CharReply {
    from: String,
    value: String,
}

#[derive(Serialize)]
struct IntReply {
    from: String,
    value: i64,
}

#[derive(Serialize)]
struct FloatReply {
    from: String,
    value: f64,
}
<commit_msg>Returns fake preferences if PrefValue::Missing.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
use crate::protocol::JsonPacketStream;
use crate::StreamId;
use serde_json::{Map, Value};
use servo_config::pref_util::PrefValue;
use servo_config::prefs::pref_map;
use std::net::TcpStream;

pub struct PreferenceActor {
    name: String,
}

impl PreferenceActor {
    pub fn new(name: String) -> Self {
        Self { name }
    }
}

impl Actor for PreferenceActor {
    fn name(&self) -> String {
        self.name.clone()
    }

    fn handle_message(
        &self,
        _registry: &ActorRegistry,
        msg_type: &str,
        _msg: &Map<String, Value>,
        stream: &mut TcpStream,
        _id: StreamId,
    ) -> Result<ActorMessageStatus, ()> {
        let pref_value = pref_map().get(msg_type);
        Ok(match pref_value {
            PrefValue::Float(value) => {
                let reply = FloatReply {
                    from: self.name(),
                    value: value,
                };
                let _ = stream.write_json_packet(&reply);
                ActorMessageStatus::Processed
            },
            PrefValue::Int(value) => {
                let reply = IntReply {
                    from: self.name(),
                    value: value,
                };
                let _ = stream.write_json_packet(&reply);
                ActorMessageStatus::Processed
            },
            PrefValue::Str(value) => {
                let reply = CharReply {
                    from: self.name(),
                    value: value,
                };
                let _ = stream.write_json_packet(&reply);
                ActorMessageStatus::Processed
            },
            PrefValue::Bool(value) => {
                let reply = BoolReply {
                    from: self.name(),
                    value: value,
                };
                let _ = stream.write_json_packet(&reply);
                ActorMessageStatus::Processed
            },
            PrefValue::Missing => handle_missing_preference(self.name(), msg_type, stream),
        })
    }
}

// if the preferences are missing from pref_map then we return a
// fake preference response based on msg_type.
fn handle_missing_preference(
    name: String,
    msg_type: &str,
    stream: &mut TcpStream,
) -> ActorMessageStatus {
    match msg_type {
        "getBoolPref" => {
            let reply = BoolReply {
                from: name,
                value: false,
            };
            let _ = stream.write_json_packet(&reply);
            ActorMessageStatus::Processed
        },

        "getCharPref" => {
            let reply = CharReply {
                from: name,
                value: "".to_owned(),
            };
            let _ = stream.write_json_packet(&reply);
            ActorMessageStatus::Processed
        },

        "getIntPref" => {
            let reply = IntReply {
                from: name,
                value: 0,
            };
            let _ = stream.write_json_packet(&reply);
            ActorMessageStatus::Processed
        },

        _ => ActorMessageStatus::Ignored,
    }
}

#[derive(Serialize)]
struct BoolReply {
    from: String,
    value: bool,
}

#[derive(Serialize)]
struct CharReply {
    from: String,
    value: String,
}

#[derive(Serialize)]
struct IntReply {
    from: String,
    value: i64,
}

#[derive(Serialize)]
struct FloatReply {
    from: String,
    value: f64,
}
<|endoftext|>


<commit_before>//! `POST /_matrix/client/*/rooms/{roomId}/receipt/{receiptType}/{eventId}`

pub mod v3 {
    //! `/v3/` ([spec])
    //!
    //! [spec]: https://spec.matrix.org/v1.2/client-server-api/#post_matrixclientv3roomsroomidreceiptreceipttypeeventid

    use ruma_common::{
        api::ruma_api,
        events::receipt::ReceiptThread,
        serde::{OrdAsRefStr, PartialEqAsRefStr, PartialOrdAsRefStr, StringEnum},
        EventId, RoomId,
    };

    use crate::PrivOwnedStr;

    ruma_api! {
        metadata: {
            description: "Send a receipt event to a room.",
            method: POST,
            name: "create_receipt",
            r0_path: "/_matrix/client/r0/rooms/:room_id/receipt/:receipt_type/:event_id",
            stable_path: "/_matrix/client/v3/rooms/:room_id/receipt/:receipt_type/:event_id",
            rate_limited: true,
            authentication: AccessToken,
            added: 1.0,
        }

        request: {
            /// The room in which to send the event.
            #[ruma_api(path)]
            pub room_id: &'a RoomId,

            /// The type of receipt to send.
            #[ruma_api(path)]
            pub receipt_type: ReceiptType,

            /// The event ID to acknowledge up to.
            #[ruma_api(path)]
            pub event_id: &'a EventId,

            /// The thread this receipt applies to.
            ///
            /// *Note* that this must be the default value if used with
            /// [`ReceiptType::FullyRead`].
            ///
            /// Defaults to [`ReceiptThread::Unthreaded`].
            #[serde(rename = "thread_id", skip_serializing_if = "ruma_common::serde::is_default")]
            pub thread: ReceiptThread,
        }

        #[derive(Default)]
        response: {}

        error: crate::Error
    }

    impl<'a> Request<'a> {
        /// Creates a new `Request` with the given room ID, receipt type and event ID.
        pub fn new(room_id: &'a RoomId, receipt_type: ReceiptType, event_id: &'a EventId) -> Self {
            Self { room_id, receipt_type, event_id, thread: ReceiptThread::default() }
        }
    }

    impl Response {
        /// Creates an empty `Response`.
        pub fn new() -> Self {
            Self {}
        }
    }

    /// The type of receipt.
    #[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/string_enum.md"))]
    #[derive(Clone, Debug, PartialOrdAsRefStr, OrdAsRefStr, PartialEqAsRefStr, Eq, StringEnum)]
    #[non_exhaustive]
    pub enum ReceiptType {
        /// A [public read receipt].
        ///
        /// Indicates that the given event has been presented to the user.
        ///
        /// This receipt is federated to other users.
        ///
        /// [public read receipt]: https://spec.matrix.org/v1.4/client-server-api/#receipts
        #[ruma_enum(rename = "m.read")]
        Read,

        /// A [private read receipt].
        ///
        /// Indicates that the given event has been presented to the user.
        ///
        /// This read receipt is not federated so only the user and their homeserver
        /// are aware of it.
        ///
        /// [private read receipt]: https://spec.matrix.org/v1.4/client-server-api/#private-read-receipts
        #[ruma_enum(rename = "m.read.private")]
        ReadPrivate,

        /// A [fully read marker].
        ///
        /// Indicates that the given event has been read by the user.
        ///
        /// This is actually not a receipt, but a piece of room account data. It is
        /// provided here for convenience.
        ///
        /// [fully read marker]: https://spec.matrix.org/v1.4/client-server-api/#fully-read-markers
        #[ruma_enum(rename = "m.fully_read")]
        FullyRead,

        #[doc(hidden)]
        _Custom(PrivOwnedStr),
    }
}
<commit_msg>client-api: Add missing default attribute to create_receipt::Request#thread<commit_after>//! `POST /_matrix/client/*/rooms/{roomId}/receipt/{receiptType}/{eventId}`

pub mod v3 {
    //! `/v3/` ([spec])
    //!
    //! [spec]: https://spec.matrix.org/v1.2/client-server-api/#post_matrixclientv3roomsroomidreceiptreceipttypeeventid

    use ruma_common::{
        api::ruma_api,
        events::receipt::ReceiptThread,
        serde::{OrdAsRefStr, PartialEqAsRefStr, PartialOrdAsRefStr, StringEnum},
        EventId, RoomId,
    };

    use crate::PrivOwnedStr;

    ruma_api! {
        metadata: {
            description: "Send a receipt event to a room.",
            method: POST,
            name: "create_receipt",
            r0_path: "/_matrix/client/r0/rooms/:room_id/receipt/:receipt_type/:event_id",
            stable_path: "/_matrix/client/v3/rooms/:room_id/receipt/:receipt_type/:event_id",
            rate_limited: true,
            authentication: AccessToken,
            added: 1.0,
        }

        request: {
            /// The room in which to send the event.
            #[ruma_api(path)]
            pub room_id: &'a RoomId,

            /// The type of receipt to send.
            #[ruma_api(path)]
            pub receipt_type: ReceiptType,

            /// The event ID to acknowledge up to.
            #[ruma_api(path)]
            pub event_id: &'a EventId,

            /// The thread this receipt applies to.
            ///
            /// *Note* that this must be the default value if used with
            /// [`ReceiptType::FullyRead`].
            ///
            /// Defaults to [`ReceiptThread::Unthreaded`].
            #[serde(rename = "thread_id", default, skip_serializing_if = "ruma_common::serde::is_default")]
            pub thread: ReceiptThread,
        }

        #[derive(Default)]
        response: {}

        error: crate::Error
    }

    impl<'a> Request<'a> {
        /// Creates a new `Request` with the given room ID, receipt type and event ID.
        pub fn new(room_id: &'a RoomId, receipt_type: ReceiptType, event_id: &'a EventId) -> Self {
            Self { room_id, receipt_type, event_id, thread: ReceiptThread::default() }
        }
    }

    impl Response {
        /// Creates an empty `Response`.
        pub fn new() -> Self {
            Self {}
        }
    }

    /// The type of receipt.
    #[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/string_enum.md"))]
    #[derive(Clone, Debug, PartialOrdAsRefStr, OrdAsRefStr, PartialEqAsRefStr, Eq, StringEnum)]
    #[non_exhaustive]
    pub enum ReceiptType {
        /// A [public read receipt].
        ///
        /// Indicates that the given event has been presented to the user.
        ///
        /// This receipt is federated to other users.
        ///
        /// [public read receipt]: https://spec.matrix.org/v1.4/client-server-api/#receipts
        #[ruma_enum(rename = "m.read")]
        Read,

        /// A [private read receipt].
        ///
        /// Indicates that the given event has been presented to the user.
        ///
        /// This read receipt is not federated so only the user and their homeserver
        /// are aware of it.
        ///
        /// [private read receipt]: https://spec.matrix.org/v1.4/client-server-api/#private-read-receipts
        #[ruma_enum(rename = "m.read.private")]
        ReadPrivate,

        /// A [fully read marker].
        ///
        /// Indicates that the given event has been read by the user.
        ///
        /// This is actually not a receipt, but a piece of room account data. It is
        /// provided here for convenience.
        ///
        /// [fully read marker]: https://spec.matrix.org/v1.4/client-server-api/#fully-read-markers
        #[ruma_enum(rename = "m.fully_read")]
        FullyRead,

        #[doc(hidden)]
        _Custom(PrivOwnedStr),
    }
}
<|endoftext|>


<commit_before>
use std::io::{Result, Error, ErrorKind, Read};
use byteorder::{ReadBytesExt, BigEndian};

use id::{MsgPackId};
use read::value::{Value};

//TODO high level reader

//internal trait and external trait

//read_trait with slice?

//complex callback interface?

pub trait MsgPackReader : Read
{
	//read value with a reader callback which uses a inner read wrapper to read value
		//read_bin_cb(&mut self, cb: Fn(usize, &Read) -> Result<()>);

	//read with stream?
	//direct reads (with streams)?

	//buffer style, stream style?

	//fn read_header() ->

	//TODO unsafe reading?

	fn read_msgpack_value(&mut self) -> Result<(Value,MsgPackId)>
	{
		let mut buf : [u8;1] = [0];
		let bytes_read = try!(self.read(&mut buf));

		if bytes_read == 0 {
			return Err(Error::new(ErrorKind::Other, "No data to read"));
		}

		let msgpack_id = MsgPackId::from_u8(buf[0]);
		if msgpack_id.is_none() {
			return Err(Error::new(ErrorKind::Other, "Not a valid start value for msgpack data"));
		}
		let msgpack_id =  msgpack_id.unwrap();

		match msgpack_id
		{
			MsgPackId::Nil => { return Ok((Value::Nil, msgpack_id)); }

			//Boolean
			MsgPackId::False => { return Ok((Value::Boolean(false), msgpack_id)); }
			MsgPackId::True => { return Ok((Value::Boolean(true), msgpack_id)); }

			//fixed integer
			MsgPackId::FixPosInt => { return Ok((Value::UInt8(buf[0] & 0x7f), msgpack_id)); }
			MsgPackId::FixNegInt => { return Ok((Value::Int8(-((buf[0] & 0x1f) as i8)), msgpack_id)); } //right?

			/*
			MsgPackId::FixMap => {
				return Ok(Value::MapStart((buf[0] & 0x0f) as usize));
			}

			MsgPackId::FixArray => {
				return Ok(Value::ArrayStart((buf[0] & 0x0f) as usize));
			}
			*/

			MsgPackId::FixStr => {
				let len = (buf[0] & 0x1f) as usize;
				let mut  buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));

				if let Ok(str) = String::from_utf8(buf) {
					return Ok((Value::Str(str), msgpack_id));
				}
				else {
					return Err(Error::new(ErrorKind::Other, "Not a valid utf8 string"));
				}
			}

			MsgPackId::Bin8 => {
				let len = try!(self.read_u8()) as usize;
				let mut buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));
				return Ok((Value::Bin(buf), msgpack_id));
			}

			MsgPackId::Bin16 => {
				let len = try!(self.read_u16::<BigEndian>()) as usize;
				let mut buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));
				return Ok((Value::Bin(buf), msgpack_id));
			}

			MsgPackId::Bin32 => {
				let len = try!(self.read_u32::<BigEndian>()) as usize;
				let mut buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));
				return Ok((Value::Bin(buf), msgpack_id));
			}

			MsgPackId::Ext8 => {
				let len = try!(self.read_u8()) as usize;
				let ty = try!(self.read_i8());
				let mut buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));
				return Ok((Value::Ext(ty, buf), msgpack_id));
			}

			MsgPackId::Ext16 => {
				let len = try!(self.read_u16::<BigEndian>()) as usize;
				let ty = try!(self.read_i8());
				let mut buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));
				return Ok((Value::Ext(ty, buf), msgpack_id));
			}

			MsgPackId::Ext32 => {
				let len = try!(self.read_u32::<BigEndian>()) as usize;
				let ty = try!(self.read_i8());
				let mut  buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));
				return Ok((Value::Ext(ty, buf), msgpack_id));
			}

			MsgPackId::Float32 => {
				let value = try!(self.read_f32::<BigEndian>());
				return Ok((Value::Float32(value), msgpack_id));
			}

			MsgPackId::Float64 => {
				let value = try!(self.read_f64::<BigEndian>());
				return Ok((Value::Float64(value), msgpack_id));
			}

			MsgPackId::UInt8 => {
				let value = try!(self.read_u8());
				return Ok((Value::UInt8(value), msgpack_id));
			}

			MsgPackId::UInt16 => {
				let value = try!(self.read_u16::<BigEndian>());
				return Ok((Value::UInt16(value), msgpack_id));
			}

			MsgPackId::UInt32 => {
				let value = try!(self.read_u32::<BigEndian>());
				return Ok((Value::UInt32(value), msgpack_id));
			}

			MsgPackId::UInt64 => {
				let value = try!(self.read_u64::<BigEndian>());
				return Ok((Value::UInt64(value), msgpack_id));
			}

			MsgPackId::Int8 => {
				let value = try!(self.read_i8());
				return Ok((Value::Int8(value), msgpack_id));
			}

			MsgPackId::Int16 => {
				let value = try!(self.read_i16::<BigEndian>());
				return Ok((Value::Int16(value), msgpack_id));
			}

			MsgPackId::Int32 => {
				let value = try!(self.read_i32::<BigEndian>());
				return Ok((Value::Int32(value), msgpack_id));
			}

			MsgPackId::Int64 => {
				let value = try!(self.read_i64::<BigEndian>());
				return Ok((Value::Int64(value), msgpack_id));
			}

			//0xd4 fixext 1
			MsgPackId::FixExt1 => {
				let ty = try!(self.read_i8());
				let mut buf : [u8;1] = [0];
				try!(self.read(&mut buf));
				return Ok((Value::Ext1(ty, buf[0]), msgpack_id));
			}

			//0xd5 fixext 2
			MsgPackId::FixExt2 => {
				let ty = try!(self.read_i8());
				let mut buf : [u8;2] = [0;2];
				try!(self.read(&mut buf));
				return Ok((Value::Ext2(ty, buf), msgpack_id));
			}

			//0xd6 fixext 4
			MsgPackId::FixExt4 => {
				let ty = try!(self.read_i8());
				let mut buf : [u8;4] = [0;4];
				try!(self.read(&mut buf));
				return Ok((Value::Ext4(ty, buf), msgpack_id));
			}

			//0xd7 fixext 8
			MsgPackId::FixExt8 => {
				let ty = try!(self.read_i8());
				let mut buf : [u8;8] = [0;8];
				try!(self.read(&mut buf));
				return Ok((Value::Ext8(ty, buf), msgpack_id));
			}

			//0xd8 fixext 16
			MsgPackId::FixExt16 => {
				let ty = try!(self.read_i8());
				let mut buf : [u8;16] = [0;16];
				try!(self.read(&mut buf));
				return Ok((Value::Ext16(ty, buf), msgpack_id));
			}

			//0xd9 str 8
			MsgPackId::Str8 => {
				let len = try!(self.read_u8()) as usize;
				let mut buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));

				if let Ok(str) = String::from_utf8(buf) {
					return Ok((Value::Str(str), msgpack_id));
				}
				else {
					return Err(Error::new(ErrorKind::Other, "Not a valid utf8 string"));
				}
			}

			//0xda str 16
			MsgPackId::Str16 => {
				let len = try!(self.read_u16::<BigEndian>()) as usize;
				let mut buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));

				if let Ok(str) = String::from_utf8(buf) {
					return Ok((Value::Str(str), msgpack_id));
				}
				else {
					return Err(Error::new(ErrorKind::Other, "Not a valid utf8 string"));
				}
			}

			//0xdb str 32
			MsgPackId::Str32 => {
				let len = try!(self.read_u32::<BigEndian>()) as usize;
				let mut buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));

				if let Ok(str) = String::from_utf8(buf) {
					return Ok((Value::Str(str), msgpack_id));
				}
				else {
					return Err(Error::new(ErrorKind::Other, "Not a valid utf8 string"));
				}
			}

			/*
			//0xdc array 16
			MsgPackId::Array16 => {
				let length = try!(self.read_u16::<BigEndian>());
				return Ok(Value::ArrayStart(length as usize));
			}

			//0xdd array 32
			MsgPackId::Array32 => {
				let length = try!(self.read_u32::<BigEndian>());
				return Ok(Value::ArrayStart(length as usize));
			}

			//0xde -> map 16
			MsgPackId::Map16 => {
				let length = try!(self.read_u16::<BigEndian>());
				return Ok(Value::MapStart(length as usize));
			}

			//0xdf -> map 32
			MsgPackId::Map32 => {
				let length = try!(self.read_u32::<BigEndian>());
				return Ok(Value::MapStart(length as usize));
			}
			*/

			_ => { return Err(Error::new(ErrorKind::Other, "Not implemented")); }
		}
	}

}

impl<T: Read> MsgPackReader for T {}

/*
trait MsgPackReaderExt : MsgPackReader
{
	fn read_u8(&mut self) -> Result<u8>
	{
		let v = self.read();
		if v.is_err() {
			return Err(v.err().unwrap());
		}

		if let Value::UInt8(x) = v.unwrap() {
			return Ok(x);
		}

		return Err(Error::new(ErrorKind::Other, "Wrong datatype", None));
	}
}
*/
<commit_msg>msgpackio: add missing implementations<commit_after>
use std::io::{Result, Error, ErrorKind, Read};
use byteorder::{ReadBytesExt, BigEndian};

use id::{MsgPackId};
use read::value::{Value};

//TODO high level reader

//internal trait and external trait

//read_trait with slice?

//complex callback interface?

pub trait MsgPackReader : Read
{
	//read value with a reader callback which uses a inner read wrapper to read value
		//read_bin_cb(&mut self, cb: Fn(usize, &Read) -> Result<()>);

	//read with stream?
	//direct reads (with streams)?

	//buffer style, stream style?

	//fn read_header() ->

	//TODO unsafe reading?

	fn read_msgpack_value(&mut self) -> Result<(Value,MsgPackId)>
	{
		let mut buf : [u8;1] = [0];
		let bytes_read = try!(self.read(&mut buf));

		if bytes_read == 0 {
			return Err(Error::new(ErrorKind::Other, "No data to read"));
		}

		let msgpack_id = MsgPackId::from_u8(buf[0]);
		if msgpack_id.is_none() {
			return Err(Error::new(ErrorKind::Other, "Not a valid start value for msgpack data"));
		}
		let msgpack_id =  msgpack_id.unwrap();

		match msgpack_id
		{
			MsgPackId::Nil => { return Ok((Value::Nil, msgpack_id)); }

			//Boolean
			MsgPackId::False => { return Ok((Value::Boolean(false), msgpack_id)); }
			MsgPackId::True => { return Ok((Value::Boolean(true), msgpack_id)); }

			//fixed integer
			MsgPackId::FixPosInt => { return Ok((Value::UInt8(buf[0] & 0x7f), msgpack_id)); }
			MsgPackId::FixNegInt => { return Ok((Value::Int8(-((buf[0] & 0x1f) as i8)), msgpack_id)); } //right?

			MsgPackId::FixMap => {
				let pair_count = (buf[0] & 0x0f) as usize;
				let mut map : Vec<(Value,Value)> = Vec::with_capacity(pair_count);
				for _ in 0..pair_count {
					let (key, _) = try!(self.read_msgpack_value());
					let (value, _) = try!(self.read_msgpack_value());
					map.push((key, value));
				}
				return Ok((Value::Map(map), msgpack_id));
			}

			MsgPackId::FixArray => {
				let element_count = (buf[0] & 0x0f) as usize;
				let mut array : Vec<Value> = Vec::with_capacity(element_count);
				for _ in 0..element_count {
					let (element, _) = try!(self.read_msgpack_value());
					array.push(element);
				}
				return Ok((Value::Array(array), msgpack_id));
			}

			MsgPackId::FixStr => {
				let len = (buf[0] & 0x1f) as usize;
				let mut  buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));

				if let Ok(str) = String::from_utf8(buf) {
					return Ok((Value::Str(str), msgpack_id));
				}
				else {
					return Err(Error::new(ErrorKind::Other, "Not a valid utf8 string"));
				}
			}

			MsgPackId::Bin8 => {
				let len = try!(self.read_u8()) as usize;
				let mut buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));
				return Ok((Value::Bin(buf), msgpack_id));
			}

			MsgPackId::Bin16 => {
				let len = try!(self.read_u16::<BigEndian>()) as usize;
				let mut buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));
				return Ok((Value::Bin(buf), msgpack_id));
			}

			MsgPackId::Bin32 => {
				let len = try!(self.read_u32::<BigEndian>()) as usize;
				let mut buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));
				return Ok((Value::Bin(buf), msgpack_id));
			}

			MsgPackId::Ext8 => {
				let len = try!(self.read_u8()) as usize;
				let ty = try!(self.read_i8());
				let mut buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));
				return Ok((Value::Ext(ty, buf), msgpack_id));
			}

			MsgPackId::Ext16 => {
				let len = try!(self.read_u16::<BigEndian>()) as usize;
				let ty = try!(self.read_i8());
				let mut buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));
				return Ok((Value::Ext(ty, buf), msgpack_id));
			}

			MsgPackId::Ext32 => {
				let len = try!(self.read_u32::<BigEndian>()) as usize;
				let ty = try!(self.read_i8());
				let mut  buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));
				return Ok((Value::Ext(ty, buf), msgpack_id));
			}

			MsgPackId::Float32 => {
				let value = try!(self.read_f32::<BigEndian>());
				return Ok((Value::Float32(value), msgpack_id));
			}

			MsgPackId::Float64 => {
				let value = try!(self.read_f64::<BigEndian>());
				return Ok((Value::Float64(value), msgpack_id));
			}

			MsgPackId::UInt8 => {
				let value = try!(self.read_u8());
				return Ok((Value::UInt8(value), msgpack_id));
			}

			MsgPackId::UInt16 => {
				let value = try!(self.read_u16::<BigEndian>());
				return Ok((Value::UInt16(value), msgpack_id));
			}

			MsgPackId::UInt32 => {
				let value = try!(self.read_u32::<BigEndian>());
				return Ok((Value::UInt32(value), msgpack_id));
			}

			MsgPackId::UInt64 => {
				let value = try!(self.read_u64::<BigEndian>());
				return Ok((Value::UInt64(value), msgpack_id));
			}

			MsgPackId::Int8 => {
				let value = try!(self.read_i8());
				return Ok((Value::Int8(value), msgpack_id));
			}

			MsgPackId::Int16 => {
				let value = try!(self.read_i16::<BigEndian>());
				return Ok((Value::Int16(value), msgpack_id));
			}

			MsgPackId::Int32 => {
				let value = try!(self.read_i32::<BigEndian>());
				return Ok((Value::Int32(value), msgpack_id));
			}

			MsgPackId::Int64 => {
				let value = try!(self.read_i64::<BigEndian>());
				return Ok((Value::Int64(value), msgpack_id));
			}

			//0xd4 fixext 1
			MsgPackId::FixExt1 => {
				let ty = try!(self.read_i8());
				let mut buf : [u8;1] = [0];
				try!(self.read(&mut buf));
				return Ok((Value::Ext1(ty, buf[0]), msgpack_id));
			}

			//0xd5 fixext 2
			MsgPackId::FixExt2 => {
				let ty = try!(self.read_i8());
				let mut buf : [u8;2] = [0;2];
				try!(self.read(&mut buf));
				return Ok((Value::Ext2(ty, buf), msgpack_id));
			}

			//0xd6 fixext 4
			MsgPackId::FixExt4 => {
				let ty = try!(self.read_i8());
				let mut buf : [u8;4] = [0;4];
				try!(self.read(&mut buf));
				return Ok((Value::Ext4(ty, buf), msgpack_id));
			}

			//0xd7 fixext 8
			MsgPackId::FixExt8 => {
				let ty = try!(self.read_i8());
				let mut buf : [u8;8] = [0;8];
				try!(self.read(&mut buf));
				return Ok((Value::Ext8(ty, buf), msgpack_id));
			}

			//0xd8 fixext 16
			MsgPackId::FixExt16 => {
				let ty = try!(self.read_i8());
				let mut buf : [u8;16] = [0;16];
				try!(self.read(&mut buf));
				return Ok((Value::Ext16(ty, buf), msgpack_id));
			}

			//0xd9 str 8
			MsgPackId::Str8 => {
				let len = try!(self.read_u8()) as usize;
				let mut buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));

				if let Ok(str) = String::from_utf8(buf) {
					return Ok((Value::Str(str), msgpack_id));
				}
				else {
					return Err(Error::new(ErrorKind::Other, "Not a valid utf8 string"));
				}
			}

			//0xda str 16
			MsgPackId::Str16 => {
				let len = try!(self.read_u16::<BigEndian>()) as usize;
				let mut buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));

				if let Ok(str) = String::from_utf8(buf) {
					return Ok((Value::Str(str), msgpack_id));
				}
				else {
					return Err(Error::new(ErrorKind::Other, "Not a valid utf8 string"));
				}
			}

			//0xdb str 32
			MsgPackId::Str32 => {
				let len = try!(self.read_u32::<BigEndian>()) as usize;
				let mut buf = Vec::with_capacity(len);
				try!(self.read(&mut buf));

				if let Ok(str) = String::from_utf8(buf) {
					return Ok((Value::Str(str), msgpack_id));
				}
				else {
					return Err(Error::new(ErrorKind::Other, "Not a valid utf8 string"));
				}
			}

			//0xdc array 16
			MsgPackId::Array16 => {
				let element_count = try!(self.read_u16::<BigEndian>());
				let mut array : Vec<Value> = Vec::with_capacity(element_count as usize);
				for _ in 0..element_count {
					let (element, _) = try!(self.read_msgpack_value());
					array.push(element);
				}
				return Ok((Value::Array(array), msgpack_id));
			}

			//0xdd array 32
			MsgPackId::Array32 => {
				let element_count = try!(self.read_u32::<BigEndian>());
				let mut array : Vec<Value> = Vec::with_capacity(element_count as usize);
				for _ in 0..element_count {
					let (element, _) = try!(self.read_msgpack_value());
					array.push(element);
				}
				return Ok((Value::Array(array), msgpack_id));
			}

			//0xde -> map 16
			MsgPackId::Map16 => {
				let pair_count = try!(self.read_u16::<BigEndian>());
				let mut map : Vec<(Value,Value)> = Vec::with_capacity(pair_count as usize);
				for _ in 0..pair_count {
					let (key, _) = try!(self.read_msgpack_value());
					let (value, _) = try!(self.read_msgpack_value());
					map.push((key, value));
				}
				return Ok((Value::Map(map), msgpack_id));
			}

			//0xdf -> map 32
			MsgPackId::Map32 => {
				let pair_count = try!(self.read_u32::<BigEndian>());
				let mut map : Vec<(Value,Value)> = Vec::with_capacity(pair_count as usize);
				for _ in 0..pair_count {
					let (key, _) = try!(self.read_msgpack_value());
					let (value, _) = try!(self.read_msgpack_value());
					map.push((key, value));
				}
				return Ok((Value::Map(map), msgpack_id));
			}

			//_ => { return Err(Error::new(ErrorKind::Other, "Not implemented")); }
		}
	}

}

impl<T: Read> MsgPackReader for T {}

/*
trait MsgPackReaderExt : MsgPackReader
{
	fn read_u8(&mut self) -> Result<u8>
	{
		let v = self.read();
		if v.is_err() {
			return Err(v.err().unwrap());
		}

		if let Value::UInt8(x) = v.unwrap() {
			return Ok(x);
		}

		return Err(Error::new(ErrorKind::Other, "Wrong datatype", None));
	}
}
*/
<|endoftext|>


<commit_before>#![allow(non_camel_case_types)] // I prefer to use ALL_CAPS for type parameters
#![cfg_attr(test, feature(conservative_impl_trait))]

// If you're not compiling the unstable code, it often happens that
// there is stuff that is considered "dead code" and so forth. So
// disable warnings in that scenario.
#![cfg_attr(not(feature = "unstable"), allow(warnings))]

#[allow(unused_imports)]
use log::Event::*;
use std::any::Any;
use std::env;
use std::error::Error;
use std::str::FromStr;
use std::fmt;

extern crate deque;
#[macro_use]
extern crate lazy_static;
#[cfg(feature = "unstable")]
extern crate futures;
extern crate libc;
extern crate num_cpus;
extern crate rand;

#[macro_use]
mod log;

mod latch;
mod join;
mod job;
mod registry;
#[cfg(feature = "unstable")]
mod future;
mod scope;
mod sleep;
#[cfg(feature = "unstable")]
mod spawn_async;
mod test;
mod thread_pool;
mod unwind;
mod util;

pub use thread_pool::ThreadPool;
pub use join::join;
pub use scope::{scope, Scope};
#[cfg(feature = "unstable")]
pub use spawn_async::spawn_async;
#[cfg(feature = "unstable")]
pub use spawn_async::spawn_future_async;
#[cfg(feature = "unstable")]
pub use future::RayonFuture;

/// Returns the number of threads in the current registry. If this
/// code is executing within the Rayon thread-pool, then this will be
/// the number of threads for the current thread-pool. Otherwise, it
/// will be the number of threads for the global thread-pool.
///
/// This can be useful when trying to judge how many times to split
/// parallel work (the parallel iterator traits use this value
/// internally for this purpose).
pub fn current_num_threads() -> usize {
    ::registry::Registry::current_num_threads()
}

/// Contains the rayon thread pool configuration.
pub struct Configuration {
    /// The number of threads in the rayon thread pool.
    /// If zero will use the RAYON_RS_NUM_CPUS environment variable.
    /// If RAYON_RS_NUM_CPUS is invalid or zero will use the default.
    num_threads: usize,

    /// Custom closure, if any, to handle a panic that we cannot propagate
    /// anywhere else.
    panic_handler: Option<Box<PanicHandler>>,

    /// Closure to compute the name of a thread.
    get_thread_name: Option<Box<FnMut(usize) -> String>>,

    /// The stack size for the created worker threads
    stack_size: Option<usize>,

    /// Closure invoked on worker thread start.
    start_handler: Option<Box<StartHandler>>,

    /// Closure invoked on worker thread exit.
    exit_handler: Option<Box<ExitHandler>>,
}

/// The type for a panic handling closure. Note that this same closure
/// may be invoked multiple times in parallel.
type PanicHandler = Fn(Box<Any + Send>) + Send + Sync;

/// The type for a closure that gets invoked when a thread starts. The
/// closure is passed the index of the thread on which it is invoked.
/// Note that this same closure may be invoked multiple times in parallel.
type StartHandler = Fn(usize) + Send + Sync;

/// The type for a closure that gets invoked when a thread exits. The
/// closure is passed the index of the thread on which is is invoked.
/// Note that this same closure may be invoked multiple times in parallel.
type ExitHandler = Fn(usize) + Send + Sync;

impl Configuration {
    /// Creates and return a valid rayon thread pool configuration, but does not initialize it.
    pub fn new() -> Configuration {
        Configuration {
            num_threads: 0,
            get_thread_name: None,
            panic_handler: None,
            stack_size: None,
            start_handler: None,
            exit_handler: None,
        }
    }

    /// Get the number of threads that will be used for the thread
    /// pool. See `set_num_threads` for more information.
    pub fn num_threads(&self) -> usize {
        if self.num_threads > 0 {
            self.num_threads
        } else {
            match env::var("RAYON_RS_NUM_CPUS").ok().and_then(|s| usize::from_str(&s).ok()) {
                Some(x) if x > 0 => x,
                _ => num_cpus::get(),
            }
        }
    }

    /// Get the thread name for the thread with the given index.
    pub fn thread_name(&mut self, index: usize) -> Option<String> {
        self.get_thread_name.as_mut().map(|c| c(index))
    }

    /// Set a closure which takes a thread index and returns
    /// the thread's name.
    pub fn set_thread_name<F>(mut self, closure: F) -> Self
    where F: FnMut(usize) -> String + 'static {
        self.get_thread_name = Some(Box::new(closure));
        self
    }

    /// Set the number of threads to be used in the rayon threadpool.
    /// If `num_threads` is 0 or you do not call this function,
    /// rayon will use the RAYON_RS_NUM_CPUS environment variable.
    /// If RAYON_RS_NUM_CPUS is invalid or is zero, a suitable default will be used.
    /// Currently, the default is one thread per logical CPU.
    pub fn set_num_threads(mut self, num_threads: usize) -> Configuration {
        self.num_threads = num_threads;
        self
    }

    /// Returns a copy of the current panic handler.
    fn take_panic_handler(&mut self) -> Option<Box<PanicHandler>> {
        self.panic_handler.take()
    }

    /// Normally, whenever Rayon catches a panic, it tries to
    /// propagate it to someplace sensible, to try and reflect the
    /// semantics of sequential execution. But in some cases,
    /// particularly with the `spawn_async()` APIs, there is no
    /// obvious place where we should propagate the panic to.
    /// In that case, this panic handler is invoked.
    ///
    /// If no panic handler is set, the default is to abort the
    /// process, under the principle that panics should not go
    /// unobserved.
    ///
    /// If the panic handler itself panics, this will abort the
    /// process. To prevent this, wrap the body of your panic handler
    /// in a call to `std::panic::catch_unwind()`.
    pub fn set_panic_handler<H>(mut self, panic_handler: H) -> Configuration
        where H: Fn(Box<Any + Send>) + Send + Sync + 'static
    {
        self.panic_handler = Some(Box::new(panic_handler));
        self
    }

    /// Get the stack size of the worker threads
    pub fn stack_size(&self) -> Option<usize>{
        self.stack_size
    }

    /// Set the stack size of the worker threads
    pub fn set_stack_size(mut self, stack_size: usize) -> Self {
        self.stack_size = Some(stack_size);
        self
    }

    /// Returns a copy of the current thread start callback.
    fn take_start_handler(&mut self) -> Option<Box<StartHandler>> {
        self.start_handler.take()
    }

    /// Set a callback to be invoked on thread start.
    ///
    /// If this closure panics, the panic will be passed to the panic handler.
    /// If that handler returns, then startup will continue normally.
    pub fn set_start_handler<H>(mut self, start_handler: H) -> Configuration
        where H: Fn(usize) + Send + Sync + 'static
    {
        self.start_handler = Some(Box::new(start_handler));
        self
    }

    /// Returns a copy of the current thread exit callback.
    fn take_exit_handler(&mut self) -> Option<Box<ExitHandler>> {
        self.exit_handler.take()
    }

    /// Set a callback to be invoked on thread exit.
    ///
    /// If this closure panics, the panic will be passed to the panic handler.
    /// If that handler returns, then the thread will exit normally.
    pub fn set_exit_handler<H>(mut self, exit_handler: H) -> Configuration
        where H: Fn(usize) + Send + Sync + 'static
    {
        self.exit_handler = Some(Box::new(exit_handler));
        self
    }
}

/// Initializes the global thread pool. This initialization is
/// **optional**.  If you do not call this function, the thread pool
/// will be automatically initialized with the default
/// configuration. In fact, calling `initialize` is not recommended,
/// except for in two scenarios:
///
/// - You wish to change the default configuration.
/// - You are running a benchmark, in which case initializing may
///   yield slightly more consistent results, since the worker threads
///   will already be ready to go even in the first iteration.  But
///   this cost is minimal.
///
/// Initialization of the global thread pool happens exactly
/// once. Once started, the configuration cannot be
/// changed. Therefore, if you call `initialize` a second time, it
/// will return an error. An `Ok` result indicates that this
/// is the first initialization of the thread pool.
pub fn initialize(config: Configuration) -> Result<(), Box<Error>> {
    let registry = try!(registry::init_global_registry(config));
    registry.wait_until_primed();
    Ok(())
}

/// This is a debugging API not really intended for end users. It will
/// dump some performance statistics out using `println`.
pub fn dump_stats() {
    dump_stats!();
}

impl fmt::Debug for Configuration {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let Configuration { ref num_threads, ref get_thread_name, ref panic_handler, ref stack_size,
                            ref start_handler, ref exit_handler } = *self;

        // Just print `Some("<closure>")` or `None` to the debug
        // output.
        let get_thread_name = get_thread_name.as_ref().map(|_| "<closure>");

        // Just print `Some("<closure>")` or `None` to the debug
        // output.
        let panic_handler = panic_handler.as_ref().map(|_| "<closure>");
        let start_handler = start_handler.as_ref().map(|_| "<closure>");
        let exit_handler = exit_handler.as_ref().map(|_| "<closure>");

        f.debug_struct("Configuration")
         .field("num_threads", num_threads)
         .field("get_thread_name", &get_thread_name)
         .field("panic_handler", &panic_handler)
         .field("stack_size", &stack_size)
         .field("start_handler", &start_handler)
         .field("exit_handler", &exit_handler)
         .finish()
    }
}
<commit_msg>remove all public getters from `Configuration`<commit_after>#![allow(non_camel_case_types)] // I prefer to use ALL_CAPS for type parameters
#![cfg_attr(test, feature(conservative_impl_trait))]

// If you're not compiling the unstable code, it often happens that
// there is stuff that is considered "dead code" and so forth. So
// disable warnings in that scenario.
#![cfg_attr(not(feature = "unstable"), allow(warnings))]

#[allow(unused_imports)]
use log::Event::*;
use std::any::Any;
use std::env;
use std::error::Error;
use std::str::FromStr;
use std::fmt;

extern crate deque;
#[macro_use]
extern crate lazy_static;
#[cfg(feature = "unstable")]
extern crate futures;
extern crate libc;
extern crate num_cpus;
extern crate rand;

#[macro_use]
mod log;

mod latch;
mod join;
mod job;
mod registry;
#[cfg(feature = "unstable")]
mod future;
mod scope;
mod sleep;
#[cfg(feature = "unstable")]
mod spawn_async;
mod test;
mod thread_pool;
mod unwind;
mod util;

pub use thread_pool::ThreadPool;
pub use join::join;
pub use scope::{scope, Scope};
#[cfg(feature = "unstable")]
pub use spawn_async::spawn_async;
#[cfg(feature = "unstable")]
pub use spawn_async::spawn_future_async;
#[cfg(feature = "unstable")]
pub use future::RayonFuture;

/// Returns the number of threads in the current registry. If this
/// code is executing within the Rayon thread-pool, then this will be
/// the number of threads for the current thread-pool. Otherwise, it
/// will be the number of threads for the global thread-pool.
///
/// This can be useful when trying to judge how many times to split
/// parallel work (the parallel iterator traits use this value
/// internally for this purpose).
pub fn current_num_threads() -> usize {
    ::registry::Registry::current_num_threads()
}

/// Contains the rayon thread pool configuration.
pub struct Configuration {
    /// The number of threads in the rayon thread pool.
    /// If zero will use the RAYON_RS_NUM_CPUS environment variable.
    /// If RAYON_RS_NUM_CPUS is invalid or zero will use the default.
    num_threads: usize,

    /// Custom closure, if any, to handle a panic that we cannot propagate
    /// anywhere else.
    panic_handler: Option<Box<PanicHandler>>,

    /// Closure to compute the name of a thread.
    get_thread_name: Option<Box<FnMut(usize) -> String>>,

    /// The stack size for the created worker threads
    stack_size: Option<usize>,

    /// Closure invoked on worker thread start.
    start_handler: Option<Box<StartHandler>>,

    /// Closure invoked on worker thread exit.
    exit_handler: Option<Box<ExitHandler>>,
}

/// The type for a panic handling closure. Note that this same closure
/// may be invoked multiple times in parallel.
type PanicHandler = Fn(Box<Any + Send>) + Send + Sync;

/// The type for a closure that gets invoked when a thread starts. The
/// closure is passed the index of the thread on which it is invoked.
/// Note that this same closure may be invoked multiple times in parallel.
type StartHandler = Fn(usize) + Send + Sync;

/// The type for a closure that gets invoked when a thread exits. The
/// closure is passed the index of the thread on which is is invoked.
/// Note that this same closure may be invoked multiple times in parallel.
type ExitHandler = Fn(usize) + Send + Sync;

impl Configuration {
    /// Creates and return a valid rayon thread pool configuration, but does not initialize it.
    pub fn new() -> Configuration {
        Configuration {
            num_threads: 0,
            get_thread_name: None,
            panic_handler: None,
            stack_size: None,
            start_handler: None,
            exit_handler: None,
        }
    }

    /// Get the number of threads that will be used for the thread
    /// pool. See `set_num_threads` for more information.
    fn num_threads(&self) -> usize {
        if self.num_threads > 0 {
            self.num_threads
        } else {
            match env::var("RAYON_RS_NUM_CPUS").ok().and_then(|s| usize::from_str(&s).ok()) {
                Some(x) if x > 0 => x,
                _ => num_cpus::get(),
            }
        }
    }

    /// Get the thread name for the thread with the given index.
    fn thread_name(&mut self, index: usize) -> Option<String> {
        self.get_thread_name.as_mut().map(|c| c(index))
    }

    /// Set a closure which takes a thread index and returns
    /// the thread's name.
    pub fn set_thread_name<F>(mut self, closure: F) -> Self
    where F: FnMut(usize) -> String + 'static {
        self.get_thread_name = Some(Box::new(closure));
        self
    }

    /// Set the number of threads to be used in the rayon threadpool.
    /// If `num_threads` is 0 or you do not call this function,
    /// rayon will use the RAYON_RS_NUM_CPUS environment variable.
    /// If RAYON_RS_NUM_CPUS is invalid or is zero, a suitable default will be used.
    /// Currently, the default is one thread per logical CPU.
    pub fn set_num_threads(mut self, num_threads: usize) -> Configuration {
        self.num_threads = num_threads;
        self
    }

    /// Returns a copy of the current panic handler.
    fn take_panic_handler(&mut self) -> Option<Box<PanicHandler>> {
        self.panic_handler.take()
    }

    /// Normally, whenever Rayon catches a panic, it tries to
    /// propagate it to someplace sensible, to try and reflect the
    /// semantics of sequential execution. But in some cases,
    /// particularly with the `spawn_async()` APIs, there is no
    /// obvious place where we should propagate the panic to.
    /// In that case, this panic handler is invoked.
    ///
    /// If no panic handler is set, the default is to abort the
    /// process, under the principle that panics should not go
    /// unobserved.
    ///
    /// If the panic handler itself panics, this will abort the
    /// process. To prevent this, wrap the body of your panic handler
    /// in a call to `std::panic::catch_unwind()`.
    pub fn set_panic_handler<H>(mut self, panic_handler: H) -> Configuration
        where H: Fn(Box<Any + Send>) + Send + Sync + 'static
    {
        self.panic_handler = Some(Box::new(panic_handler));
        self
    }

    /// Get the stack size of the worker threads
    fn stack_size(&self) -> Option<usize>{
        self.stack_size
    }

    /// Set the stack size of the worker threads
    pub fn set_stack_size(mut self, stack_size: usize) -> Self {
        self.stack_size = Some(stack_size);
        self
    }

    /// Returns a copy of the current thread start callback.
    fn take_start_handler(&mut self) -> Option<Box<StartHandler>> {
        self.start_handler.take()
    }

    /// Set a callback to be invoked on thread start.
    ///
    /// If this closure panics, the panic will be passed to the panic handler.
    /// If that handler returns, then startup will continue normally.
    pub fn set_start_handler<H>(mut self, start_handler: H) -> Configuration
        where H: Fn(usize) + Send + Sync + 'static
    {
        self.start_handler = Some(Box::new(start_handler));
        self
    }

    /// Returns a copy of the current thread exit callback.
    fn take_exit_handler(&mut self) -> Option<Box<ExitHandler>> {
        self.exit_handler.take()
    }

    /// Set a callback to be invoked on thread exit.
    ///
    /// If this closure panics, the panic will be passed to the panic handler.
    /// If that handler returns, then the thread will exit normally.
    pub fn set_exit_handler<H>(mut self, exit_handler: H) -> Configuration
        where H: Fn(usize) + Send + Sync + 'static
    {
        self.exit_handler = Some(Box::new(exit_handler));
        self
    }
}

/// Initializes the global thread pool. This initialization is
/// **optional**.  If you do not call this function, the thread pool
/// will be automatically initialized with the default
/// configuration. In fact, calling `initialize` is not recommended,
/// except for in two scenarios:
///
/// - You wish to change the default configuration.
/// - You are running a benchmark, in which case initializing may
///   yield slightly more consistent results, since the worker threads
///   will already be ready to go even in the first iteration.  But
///   this cost is minimal.
///
/// Initialization of the global thread pool happens exactly
/// once. Once started, the configuration cannot be
/// changed. Therefore, if you call `initialize` a second time, it
/// will return an error. An `Ok` result indicates that this
/// is the first initialization of the thread pool.
pub fn initialize(config: Configuration) -> Result<(), Box<Error>> {
    let registry = try!(registry::init_global_registry(config));
    registry.wait_until_primed();
    Ok(())
}

/// This is a debugging API not really intended for end users. It will
/// dump some performance statistics out using `println`.
pub fn dump_stats() {
    dump_stats!();
}

impl fmt::Debug for Configuration {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let Configuration { ref num_threads, ref get_thread_name, ref panic_handler, ref stack_size,
                            ref start_handler, ref exit_handler } = *self;

        // Just print `Some("<closure>")` or `None` to the debug
        // output.
        let get_thread_name = get_thread_name.as_ref().map(|_| "<closure>");

        // Just print `Some("<closure>")` or `None` to the debug
        // output.
        let panic_handler = panic_handler.as_ref().map(|_| "<closure>");
        let start_handler = start_handler.as_ref().map(|_| "<closure>");
        let exit_handler = exit_handler.as_ref().map(|_| "<closure>");

        f.debug_struct("Configuration")
         .field("num_threads", num_threads)
         .field("get_thread_name", &get_thread_name)
         .field("panic_handler", &panic_handler)
         .field("stack_size", &stack_size)
         .field("start_handler", &start_handler)
         .field("exit_handler", &exit_handler)
         .finish()
    }
}
<|endoftext|>


<commit_before>use proc_macro::TokenStream;
use quote::{Ident, Tokens};

use super::ast::*;

pub fn generate(name: &str, rules: Vec<Rule>) -> Tokens {
    rule_enum(rules.iter().collect())
}

fn rule_enum(rules: Vec<&Rule>) -> Tokens {
    let rules = rule_names(rules);

    quote! {
        #[allow(dead_code, non_camel_case_types)]
        #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
        pub enum Rule {
            any,
            soi,
            eoi,
            #( #rules ),*
        }
    }
}

fn rule_names(rules: Vec<&Rule>) -> Vec<Tokens> {
    rules.iter().flat_map(|rule| {
        match rule.body {
            Body::Normal(_) => {
                if rule.ty != RuleType::Silent {
                    let name = Ident::new(rule.name.clone());
                    vec![quote! { #name }]
                } else {
                    vec![]
                }
            },
            Body::Infix(_, ref rules) => {
                rule_names(rules.iter().map(|&(ref rule, _)| rule).collect())
            }
        }
    }).collect()
}

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

    #[test]
    fn rule_enum_complex() {
        let rules = vec![
            Rule {
                name: Ident::new("rule"),
                ty:   RuleType::Silent,
                body: Body::Infix(
                    Expr::Ident(Ident::new("a")),
                    vec![
                    (Rule {
                        name: Ident::new("b"),
                        ty:   RuleType::Atomic,
                        body: Body::Normal(Expr::Ident(Ident::new("c")))
                    }, false),
                    (Rule {
                        name: Ident::new("d"),
                        ty:   RuleType::Normal,
                        body: Body::Normal(Expr::Ident(Ident::new("e")))
                    }, true)
                    ]
                )
            },
            Rule {
                name: Ident::new("f"),
                ty: RuleType::Normal,
                body: Body::Normal(Expr::Ident(Ident::new("g")))
            }
        ];

        assert_eq!(rule_enum(rules.iter().collect()), quote! {
        #[allow(dead_code, non_camel_case_types)]
        #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
        pub enum Rule {
            any,
            soi,
            eoi,
            b,
            d,
            f
        }
        });
    }
}
<commit_msg>Fixed indentation.<commit_after>use proc_macro::TokenStream;
use quote::{Ident, Tokens};

use super::ast::*;

pub fn generate(name: &str, rules: Vec<Rule>) -> Tokens {
    rule_enum(rules.iter().collect())
}

fn rule_enum(rules: Vec<&Rule>) -> Tokens {
    let rules = rule_names(rules);

    quote! {
        #[allow(dead_code, non_camel_case_types)]
        #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
        pub enum Rule {
            any,
            soi,
            eoi,
            #( #rules ),*
        }
    }
}

fn rule_names(rules: Vec<&Rule>) -> Vec<Tokens> {
    rules.iter().flat_map(|rule| {
        match rule.body {
            Body::Normal(_) => {
                if rule.ty != RuleType::Silent {
                    let name = Ident::new(rule.name.clone());
                    vec![quote! { #name }]
                } else {
                    vec![]
                }
            },
            Body::Infix(_, ref rules) => {
                rule_names(rules.iter().map(|&(ref rule, _)| rule).collect())
            }
        }
    }).collect()
}

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

    #[test]
    fn rule_enum_complex() {
        let rules = vec![
            Rule {
                name: Ident::new("rule"),
                ty:   RuleType::Silent,
                body: Body::Infix(
                    Expr::Ident(Ident::new("a")),
                    vec![
                        (Rule {
                            name: Ident::new("b"),
                            ty:   RuleType::Atomic,
                            body: Body::Normal(Expr::Ident(Ident::new("c")))
                        }, false),
                        (Rule {
                            name: Ident::new("d"),
                            ty:   RuleType::Normal,
                            body: Body::Normal(Expr::Ident(Ident::new("e")))
                        }, true)
                    ]
                )
            },
            Rule {
                name: Ident::new("f"),
                ty: RuleType::Normal,
                body: Body::Normal(Expr::Ident(Ident::new("g")))
            }
        ];

        assert_eq!(rule_enum(rules.iter().collect()), quote! {
            #[allow(dead_code, non_camel_case_types)]
            #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
            pub enum Rule {
                any,
                soi,
                eoi,
                b,
                d,
                f
            }
        });
    }
}
<|endoftext|>