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

//! This module implements the interface that actual decoder devices need to
//! implement in order to provide video decoding capability to the guest.

use crate::virtio::video::{
    decoder::Capability,
    error::{VideoError, VideoResult},
    format::{Format, Rect},
    resource::{GuestResource, GuestResourceHandle},
};
use base::AsRawDescriptor;

#[cfg(feature = "libvda")]
pub mod vda;

/// Contains the device's state for one playback session, i.e. one stream.
pub trait DecoderSession {
    /// Tell how many output buffers will be used for this session and which format they will carry.
    /// This method must be called after a `ProvidePictureBuffers` event is emitted, and before the
    /// first call to `use_output_buffers()`.
    fn set_output_parameters(&mut self, buffer_count: usize, format: Format) -> VideoResult<()>;

    /// Decode the compressed stream contained in [`offset`..`offset`+`bytes_used`]
    /// of the shared memory in `descriptor`. `bitstream_id` is the identifier for that
    /// part of the stream (most likely, a timestamp).
    ///
    /// The device takes ownership of `descriptor` and is responsible for closing it
    /// once it is not used anymore.
    ///
    /// The device will emit a `NotifyEndOfBitstreamBuffer` event after the input
    /// buffer has been entirely processed.
    ///
    /// The device will emit a `PictureReady` event with the `bitstream_id` field
    /// set to the same value as the argument of the same name for each picture
    /// produced from that input buffer.
    fn decode(
        &mut self,
        bitstream_id: i32,
        resource: GuestResourceHandle,
        offset: u32,
        bytes_used: u32,
    ) -> VideoResult<()>;

    /// Flush the decoder device, i.e. finish processing of all queued decode
    /// requests.
    ///
    /// The device will emit a `FlushCompleted` event once the flush is done.
    fn flush(&mut self) -> VideoResult<()>;

    /// Reset the decoder device, i.e. cancel all pending decoding requests.
    ///
    /// The device will emit a `ResetCompleted` event once the reset is done.
    fn reset(&mut self) -> VideoResult<()>;

    /// Returns the event pipe on which the availability of events will be signaled. Note that the
    /// returned value is borrowed and only valid as long as the session is alive.
    fn event_pipe(&self) -> &dyn AsRawDescriptor;

    /// Ask the device to use `resource` to store decoded frames according to its layout.
    /// `picture_buffer_id` is the ID of the picture that will be reproduced in `PictureReady`
    /// events using this buffer.
    ///
    /// The device takes ownership of `resource` and is responsible for closing it once the buffer
    /// is not used anymore (either when the session is closed, or a new set of buffers is provided
    /// for the session).
    ///
    /// The device will emit a `PictureReady` event with the `picture_buffer_id` field set to the
    /// same value as the argument of the same name when a frame has been decoded into that buffer.
    fn use_output_buffer(
        &mut self,
        picture_buffer_id: i32,
        resource: GuestResource,
    ) -> VideoResult<()>;

    /// Ask the device to reuse an output buffer previously passed to
    /// `use_output_buffer` and that has previously been returned to the decoder
    /// in a `PictureReady` event.
    ///
    /// The device will emit a `PictureReady` event with the `picture_buffer_id`
    /// field set to the same value as the argument of the same name when a
    /// frame has been decoded into that buffer.
    fn reuse_output_buffer(&mut self, picture_buffer_id: i32) -> VideoResult<()>;

    /// Blocking call to read a single event from the event pipe.
    fn read_event(&mut self) -> VideoResult<DecoderEvent>;
}

pub trait DecoderBackend {
    type Session: DecoderSession;

    /// Return the decoding capabilities for this backend instance.
    fn get_capabilities(&self) -> Capability;

    /// Create a new decoding session for the passed `profile`.
    fn new_session(&mut self, format: Format) -> VideoResult<Self::Session>;
}

#[derive(Debug)]
pub enum DecoderEvent {
    /// Emitted when the device knows the buffer format it will need to decode
    /// frames, and how many buffers it will need. The decoder is supposed to
    /// provide buffers of the requested dimensions using `use_output_buffer`.
    ProvidePictureBuffers {
        min_num_buffers: u32,
        width: i32,
        height: i32,
        visible_rect: Rect,
    },
    /// Emitted when the decoder is done decoding a picture. `picture_buffer_id`
    /// corresponds to the argument of the same name passed to `use_output_buffer()`
    /// or `reuse_output_buffer()`. `bitstream_id` corresponds to the argument of
    /// the same name passed to `decode()` and can be used to match decoded frames
    /// to the input buffer they were produced from.
    PictureReady {
        picture_buffer_id: i32,
        bitstream_id: i32,
        visible_rect: Rect,
    },
    /// Emitted when an input buffer passed to `decode()` is not used by the
    /// device anymore and can be reused by the decoder. The parameter corresponds
    /// to the `bitstream_id` argument passed to `decode()`.
    NotifyEndOfBitstreamBuffer(i32),
    /// Emitted when a decoding error has occured.
    NotifyError(VideoError),
    /// Emitted after `flush()` has been called to signal that the flush is completed.
    FlushCompleted(VideoResult<()>),
    /// Emitted after `reset()` has been called to signal that the reset is completed.
    ResetCompleted(VideoResult<()>),
}
<commit_msg>virtio: video: fix decoder backend documentation<commit_after>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! This module implements the interface that actual decoder devices need to
//! implement in order to provide video decoding capability to the guest.

use crate::virtio::video::{
    decoder::Capability,
    error::{VideoError, VideoResult},
    format::{Format, Rect},
    resource::{GuestResource, GuestResourceHandle},
};
use base::AsRawDescriptor;

#[cfg(feature = "libvda")]
pub mod vda;

/// Contains the device's state for one playback session, i.e. one stream.
pub trait DecoderSession {
    /// Tell how many output buffers will be used for this session and which format they will carry.
    /// This method must be called after a `ProvidePictureBuffers` event is emitted, and before the
    /// first call to `use_output_buffer()`.
    fn set_output_parameters(&mut self, buffer_count: usize, format: Format) -> VideoResult<()>;

    /// Decode the compressed stream contained in [`offset`..`offset`+`bytes_used`]
    /// of the shared memory in `resource`. `bitstream_id` is the identifier for that
    /// part of the stream (most likely, a timestamp).
    ///
    /// The device takes ownership of `resource` and is responsible for closing it
    /// once it is not used anymore.
    ///
    /// The device will emit a `NotifyEndOfBitstreamBuffer` event after the input
    /// buffer has been entirely processed.
    ///
    /// The device will emit a `PictureReady` event with the `bitstream_id` field
    /// set to the same value as the argument of the same name for each picture
    /// produced from that input buffer.
    fn decode(
        &mut self,
        bitstream_id: i32,
        resource: GuestResourceHandle,
        offset: u32,
        bytes_used: u32,
    ) -> VideoResult<()>;

    /// Flush the decoder device, i.e. finish processing all queued decode requests and emit frames
    /// for them.
    ///
    /// The device will emit a `FlushCompleted` event once the flush is done.
    fn flush(&mut self) -> VideoResult<()>;

    /// Reset the decoder device, i.e. cancel all pending decoding requests.
    ///
    /// The device will emit a `ResetCompleted` event once the reset is done.
    fn reset(&mut self) -> VideoResult<()>;

    /// Returns the event pipe on which the availability of events will be signaled. Note that the
    /// returned value is borrowed and only valid as long as the session is alive.
    fn event_pipe(&self) -> &dyn AsRawDescriptor;

    /// Ask the device to use `resource` to store decoded frames according to its layout.
    /// `picture_buffer_id` is the ID of the picture that will be reproduced in `PictureReady`
    /// events using this buffer.
    ///
    /// The device takes ownership of `resource` and is responsible for closing it once the buffer
    /// is not used anymore (either when the session is closed, or a new set of buffers is provided
    /// for the session).
    ///
    /// The device will emit a `PictureReady` event with the `picture_buffer_id` field set to the
    /// same value as the argument of the same name when a frame has been decoded into that buffer.
    fn use_output_buffer(
        &mut self,
        picture_buffer_id: i32,
        resource: GuestResource,
    ) -> VideoResult<()>;

    /// Ask the device to reuse an output buffer previously passed to
    /// `use_output_buffer` and that has previously been returned to the decoder
    /// in a `PictureReady` event.
    ///
    /// The device will emit a `PictureReady` event with the `picture_buffer_id`
    /// field set to the same value as the argument of the same name when a
    /// frame has been decoded into that buffer.
    fn reuse_output_buffer(&mut self, picture_buffer_id: i32) -> VideoResult<()>;

    /// Blocking call to read a single event from the event pipe.
    fn read_event(&mut self) -> VideoResult<DecoderEvent>;
}

pub trait DecoderBackend {
    type Session: DecoderSession;

    /// Return the decoding capabilities for this backend instance.
    fn get_capabilities(&self) -> Capability;

    /// Create a new decoding session for the passed `format`.
    fn new_session(&mut self, format: Format) -> VideoResult<Self::Session>;
}

#[derive(Debug)]
pub enum DecoderEvent {
    /// Emitted when the device knows the buffer format it will need to decode frames, and how many
    /// buffers it will need. The decoder is supposed to call `set_output_parameters()` to confirm
    /// the pixel format and actual number of buffers used, and provide buffers of the requested
    /// dimensions using `use_output_buffer()`.
    ProvidePictureBuffers {
        min_num_buffers: u32,
        width: i32,
        height: i32,
        visible_rect: Rect,
    },
    /// Emitted when the decoder is done decoding a picture. `picture_buffer_id`
    /// corresponds to the argument of the same name passed to `use_output_buffer()`
    /// or `reuse_output_buffer()`. `bitstream_id` corresponds to the argument of
    /// the same name passed to `decode()` and can be used to match decoded frames
    /// to the input buffer they were produced from.
    PictureReady {
        picture_buffer_id: i32,
        bitstream_id: i32,
        visible_rect: Rect,
    },
    /// Emitted when an input buffer passed to `decode()` is not used by the
    /// device anymore and can be reused by the decoder. The parameter corresponds
    /// to the `bitstream_id` argument passed to `decode()`.
    NotifyEndOfBitstreamBuffer(i32),
    /// Emitted when a decoding error has occured.
    NotifyError(VideoError),
    /// Emitted after `flush()` has been called to signal that the flush is completed.
    FlushCompleted(VideoResult<()>),
    /// Emitted after `reset()` has been called to signal that the reset is completed.
    ResetCompleted(VideoResult<()>),
}
<|endoftext|>


<commit_before>use nom::branch::alt;
use nom::bytes::complete::{tag, take, take_till1, take_while};
use nom::multi::many0;
use nom::IResult;
use std::str;

/// Describes how formats should be padded: on the left, on the right, or not at all.
#[derive(PartialEq, Eq, Debug)]
pub enum Padding {
    /// Do not pad the value.
    None,
    /// Pad the value on the left until it reaches specified width.
    Left(usize),
    /// Pad the value on the right until it reaches specified width.
    Right(usize),
}

/// Describes all the different "format specifiers" we support, plus a chunk of text that would be
/// copied to the output verbatim.
#[derive(PartialEq, Eq, Debug)]
pub enum Specifier<'a> {
    /// Will expand to pad everything that comes next to the right. Given char is used for padding.
    Spacing(char),
    /// A format to be replaced with a value (`%a`, `%t` etc.), padded to the given width on the
    /// left (if it's positive) or on the right (if it's negative).
    Format(char, Padding),
    /// A chunk of text that will be copied to the output verbatim.
    Text(&'a str),
    /// Conditional format that is replaced by one of the sub-formats depending on the value of the
    /// given key. "Else" branch might be missing.
    Conditional(char, Vec<Specifier<'a>>, Option<Vec<Specifier<'a>>>),
}

fn escaped_percent_sign(input: &str) -> IResult<&str, Specifier> {
    tag("%%")(input).map(|result| (result.0, Specifier::Text(&result.1[0..1])))
}

fn spacing(input: &str) -> IResult<&str, Specifier> {
    let (input, _) = tag("%>")(input)?;
    let (input, c) = take(1usize)(input)?;

    // unwrap() won't panic because we use take!(1) in parser above
    let chr = c.chars().next().unwrap();

    Ok((input, Specifier::Spacing(chr)))
}

fn padded_format(input: &str) -> IResult<&str, Specifier> {
    let (input, _) = tag("%")(input)?;
    let (input, width) =
        take_while(|chr: char| chr.is_ascii() && (chr.is_numeric() || chr == '-'))(input)?;
    let (input, format) = take(1usize)(input)?;

    // unwrap() won't fail because parser uses take!(1) to get exactly one character
    let format = format.chars().next().unwrap();

    let width = width.parse::<isize>().unwrap_or(0);
    let padding = if width == 0isize {
        Padding::None
    } else if width > 0isize {
        Padding::Left(width.abs() as usize)
    } else {
        Padding::Right(width.abs() as usize)
    };

    Ok((input, Specifier::Format(format, padding)))
}

fn text_outside_conditional(input: &str) -> IResult<&str, Specifier> {
    let (input, text) = take_till1(|chr: char| chr == '%')(input)?;

    Ok((input, Specifier::Text(text)))
}

fn text_inside_conditional(input: &str) -> IResult<&str, Specifier> {
    let (input, text) = take_till1(|chr: char| chr == '%' || chr == '&' || chr == '?')(input)?;

    Ok((input, Specifier::Text(text)))
}

fn conditional(input: &str) -> IResult<&str, Specifier> {
    // Prepared partial parsers
    let start_tag = tag("%?");
    let condition = take(1usize);
    let then_tag = tag("?");
    let then_branch = conditional_branch;
    let else_tag = tag("&");
    let end_tag = tag("?");

    let some_else_branch = |input| {
        let (input, _) = else_tag(input)?;
        let (input, els) = conditional_branch(input)?;
        let (input, _) = end_tag(input)?;
        Ok((input, Some(els)))
    };
    let none_else_branch = |input| {
        let (input, _) = end_tag(input)?;
        Ok((input, None))
    };
    let else_branch = alt((some_else_branch, none_else_branch));

    // Input parsing
    let (input, _) = start_tag(input)?;
    let (input, cond) = condition(input)?;
    let (input, _) = then_tag(input)?;
    let (input, then) = then_branch(input)?;
    let (input, els) = else_branch(input)?;

    // unwrap() won't panic because we're using take!(1) to get exactly one character
    let cond = cond.chars().next().unwrap();

    Ok((input, Specifier::Conditional(cond, then, els)))
}

fn conditional_branch(input: &str) -> IResult<&str, Vec<Specifier>> {
    let alternatives = (
        escaped_percent_sign,
        spacing,
        padded_format,
        text_inside_conditional,
    );
    many0(alt(alternatives))(input)
}

fn parser(input: &str) -> IResult<&str, Vec<Specifier>> {
    let alternatives = (
        conditional,
        escaped_percent_sign,
        spacing,
        padded_format,
        text_outside_conditional,
    );
    many0(alt(alternatives))(input)
}

fn sanitize(mut input: Vec<Specifier>) -> Vec<Specifier> {
    input.retain(|s| {
        if let Specifier::Format(c, ref _b) = *s {
            c.is_ascii()
        } else {
            true
        }
    });
    input
}

pub fn parse(input: &str) -> Vec<Specifier> {
    match parser(input) {
        Ok((_leftovers, ast)) => sanitize(ast),
        Err(_) => vec![Specifier::Text("")],
    }
}

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

    #[test]
    fn t_parses_formats_without_specifiers() {
        let input = "Hello, world!";
        let (leftovers, result) = parser(input).unwrap();
        assert_eq!(leftovers, "");
        assert_eq!(result, vec![Specifier::Text("Hello, world!")]);
    }

    #[test]
    fn t_replaces_double_percent_with_a_single_percent() {
        let input = "%%";
        let (leftovers, result) = parser(input).unwrap();
        assert_eq!(leftovers, "");
        assert_eq!(result, vec![Specifier::Text("%")]);
    }

    #[test]
    fn t_parses_sequences_of_specifiers() {
        let input = "100%% pure Ceylon tea";
        let (leftovers, result) = parser(input).unwrap();
        assert_eq!(leftovers, "");

        let expected = vec![
            Specifier::Text("100"),
            Specifier::Text("%"),
            Specifier::Text(" pure Ceylon tea"),
        ];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_formats_with_letters() {
        let input = "%t (%a)";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![
            Specifier::Format('t', Padding::None),
            Specifier::Text(" ("),
            Specifier::Format('a', Padding::None),
            Specifier::Text(")"),
        ];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_formats_with_positive_padding() {
        let input = "%8a%4b%13x";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![
            Specifier::Format('a', Padding::Left(8)),
            Specifier::Format('b', Padding::Left(4)),
            Specifier::Format('x', Padding::Left(13)),
        ];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_formats_with_negative_padding() {
        let input = "%-8a%-4b%-13x";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![
            Specifier::Format('a', Padding::Right(8)),
            Specifier::Format('b', Padding::Right(4)),
            Specifier::Format('x', Padding::Right(13)),
        ];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_spacing_format() {
        let input = "%-8a%>m%4b%> %-13x";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![
            Specifier::Format('a', Padding::Right(8)),
            Specifier::Spacing('m'),
            Specifier::Format('b', Padding::Left(4)),
            Specifier::Spacing(' '),
            Specifier::Format('x', Padding::Right(13)),
        ];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_conditionals() {
        let input = "%?x?success&failure?";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![Specifier::Conditional(
            'x',
            vec![Specifier::Text("success")],
            Some(vec![Specifier::Text("failure")]),
        )];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_conditionals_without_else_branch() {
        let input = "%?x?success?";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![Specifier::Conditional(
            'x',
            vec![Specifier::Text("success")],
            None,
        )];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_conditionals_with_empty_then_branch() {
        let input = "%?x??";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![Specifier::Conditional('x', vec![], None)];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_conditionals_with_empty_then_nonempty_else_branches() {
        let input = "%?x?&nonempty?";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![Specifier::Conditional(
            'x',
            vec![],
            Some(vec![Specifier::Text("nonempty")]),
        )];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_conditionals_with_empty_then_and_else_branches() {
        let input = "%?x?&?";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![Specifier::Conditional('x', vec![], Some(vec![]))];
        assert_eq!(result, expected);
    }
}
<commit_msg>Clippy: rewrite if-ladder with `match` and `cmp`<commit_after>use nom::branch::alt;
use nom::bytes::complete::{tag, take, take_till1, take_while};
use nom::multi::many0;
use nom::IResult;
use std::cmp::Ordering;
use std::str;

/// Describes how formats should be padded: on the left, on the right, or not at all.
#[derive(PartialEq, Eq, Debug)]
pub enum Padding {
    /// Do not pad the value.
    None,
    /// Pad the value on the left until it reaches specified width.
    Left(usize),
    /// Pad the value on the right until it reaches specified width.
    Right(usize),
}

/// Describes all the different "format specifiers" we support, plus a chunk of text that would be
/// copied to the output verbatim.
#[derive(PartialEq, Eq, Debug)]
pub enum Specifier<'a> {
    /// Will expand to pad everything that comes next to the right. Given char is used for padding.
    Spacing(char),
    /// A format to be replaced with a value (`%a`, `%t` etc.), padded to the given width on the
    /// left (if it's positive) or on the right (if it's negative).
    Format(char, Padding),
    /// A chunk of text that will be copied to the output verbatim.
    Text(&'a str),
    /// Conditional format that is replaced by one of the sub-formats depending on the value of the
    /// given key. "Else" branch might be missing.
    Conditional(char, Vec<Specifier<'a>>, Option<Vec<Specifier<'a>>>),
}

fn escaped_percent_sign(input: &str) -> IResult<&str, Specifier> {
    tag("%%")(input).map(|result| (result.0, Specifier::Text(&result.1[0..1])))
}

fn spacing(input: &str) -> IResult<&str, Specifier> {
    let (input, _) = tag("%>")(input)?;
    let (input, c) = take(1usize)(input)?;

    // unwrap() won't panic because we use take!(1) in parser above
    let chr = c.chars().next().unwrap();

    Ok((input, Specifier::Spacing(chr)))
}

fn padded_format(input: &str) -> IResult<&str, Specifier> {
    let (input, _) = tag("%")(input)?;
    let (input, width) =
        take_while(|chr: char| chr.is_ascii() && (chr.is_numeric() || chr == '-'))(input)?;
    let (input, format) = take(1usize)(input)?;

    // unwrap() won't fail because parser uses take!(1) to get exactly one character
    let format = format.chars().next().unwrap();

    let width = width.parse::<isize>().unwrap_or(0);
    let padding = match width.cmp(&0isize) {
        Ordering::Equal => Padding::None,
        Ordering::Greater => Padding::Left(width.abs() as usize),
        Ordering::Less => Padding::Right(width.abs() as usize),
    };

    Ok((input, Specifier::Format(format, padding)))
}

fn text_outside_conditional(input: &str) -> IResult<&str, Specifier> {
    let (input, text) = take_till1(|chr: char| chr == '%')(input)?;

    Ok((input, Specifier::Text(text)))
}

fn text_inside_conditional(input: &str) -> IResult<&str, Specifier> {
    let (input, text) = take_till1(|chr: char| chr == '%' || chr == '&' || chr == '?')(input)?;

    Ok((input, Specifier::Text(text)))
}

fn conditional(input: &str) -> IResult<&str, Specifier> {
    // Prepared partial parsers
    let start_tag = tag("%?");
    let condition = take(1usize);
    let then_tag = tag("?");
    let then_branch = conditional_branch;
    let else_tag = tag("&");
    let end_tag = tag("?");

    let some_else_branch = |input| {
        let (input, _) = else_tag(input)?;
        let (input, els) = conditional_branch(input)?;
        let (input, _) = end_tag(input)?;
        Ok((input, Some(els)))
    };
    let none_else_branch = |input| {
        let (input, _) = end_tag(input)?;
        Ok((input, None))
    };
    let else_branch = alt((some_else_branch, none_else_branch));

    // Input parsing
    let (input, _) = start_tag(input)?;
    let (input, cond) = condition(input)?;
    let (input, _) = then_tag(input)?;
    let (input, then) = then_branch(input)?;
    let (input, els) = else_branch(input)?;

    // unwrap() won't panic because we're using take!(1) to get exactly one character
    let cond = cond.chars().next().unwrap();

    Ok((input, Specifier::Conditional(cond, then, els)))
}

fn conditional_branch(input: &str) -> IResult<&str, Vec<Specifier>> {
    let alternatives = (
        escaped_percent_sign,
        spacing,
        padded_format,
        text_inside_conditional,
    );
    many0(alt(alternatives))(input)
}

fn parser(input: &str) -> IResult<&str, Vec<Specifier>> {
    let alternatives = (
        conditional,
        escaped_percent_sign,
        spacing,
        padded_format,
        text_outside_conditional,
    );
    many0(alt(alternatives))(input)
}

fn sanitize(mut input: Vec<Specifier>) -> Vec<Specifier> {
    input.retain(|s| {
        if let Specifier::Format(c, ref _b) = *s {
            c.is_ascii()
        } else {
            true
        }
    });
    input
}

pub fn parse(input: &str) -> Vec<Specifier> {
    match parser(input) {
        Ok((_leftovers, ast)) => sanitize(ast),
        Err(_) => vec![Specifier::Text("")],
    }
}

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

    #[test]
    fn t_parses_formats_without_specifiers() {
        let input = "Hello, world!";
        let (leftovers, result) = parser(input).unwrap();
        assert_eq!(leftovers, "");
        assert_eq!(result, vec![Specifier::Text("Hello, world!")]);
    }

    #[test]
    fn t_replaces_double_percent_with_a_single_percent() {
        let input = "%%";
        let (leftovers, result) = parser(input).unwrap();
        assert_eq!(leftovers, "");
        assert_eq!(result, vec![Specifier::Text("%")]);
    }

    #[test]
    fn t_parses_sequences_of_specifiers() {
        let input = "100%% pure Ceylon tea";
        let (leftovers, result) = parser(input).unwrap();
        assert_eq!(leftovers, "");

        let expected = vec![
            Specifier::Text("100"),
            Specifier::Text("%"),
            Specifier::Text(" pure Ceylon tea"),
        ];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_formats_with_letters() {
        let input = "%t (%a)";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![
            Specifier::Format('t', Padding::None),
            Specifier::Text(" ("),
            Specifier::Format('a', Padding::None),
            Specifier::Text(")"),
        ];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_formats_with_positive_padding() {
        let input = "%8a%4b%13x";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![
            Specifier::Format('a', Padding::Left(8)),
            Specifier::Format('b', Padding::Left(4)),
            Specifier::Format('x', Padding::Left(13)),
        ];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_formats_with_negative_padding() {
        let input = "%-8a%-4b%-13x";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![
            Specifier::Format('a', Padding::Right(8)),
            Specifier::Format('b', Padding::Right(4)),
            Specifier::Format('x', Padding::Right(13)),
        ];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_spacing_format() {
        let input = "%-8a%>m%4b%> %-13x";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![
            Specifier::Format('a', Padding::Right(8)),
            Specifier::Spacing('m'),
            Specifier::Format('b', Padding::Left(4)),
            Specifier::Spacing(' '),
            Specifier::Format('x', Padding::Right(13)),
        ];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_conditionals() {
        let input = "%?x?success&failure?";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![Specifier::Conditional(
            'x',
            vec![Specifier::Text("success")],
            Some(vec![Specifier::Text("failure")]),
        )];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_conditionals_without_else_branch() {
        let input = "%?x?success?";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![Specifier::Conditional(
            'x',
            vec![Specifier::Text("success")],
            None,
        )];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_conditionals_with_empty_then_branch() {
        let input = "%?x??";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![Specifier::Conditional('x', vec![], None)];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_conditionals_with_empty_then_nonempty_else_branches() {
        let input = "%?x?&nonempty?";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![Specifier::Conditional(
            'x',
            vec![],
            Some(vec![Specifier::Text("nonempty")]),
        )];
        assert_eq!(result, expected);
    }

    #[test]
    fn t_parses_conditionals_with_empty_then_and_else_branches() {
        let input = "%?x?&?";
        let (leftovers, result) = parser(input).unwrap();

        assert_eq!(leftovers, "");

        let expected = vec![Specifier::Conditional('x', vec![], Some(vec![]))];
        assert_eq!(result, expected);
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>2019: Day 1, part 1.<commit_after>use std::io;
use std::io::BufRead;

fn main() -> io::Result<()> {
    let module_masses: Vec<i32> = io::BufReader::new(io::stdin())
        .lines()
        .map(|input| {
            input.and_then(|line| {
                line.parse::<i32>()
                    .map_err(|err| io::Error::new(io::ErrorKind::Other, err))
            })
        })
        .collect::<io::Result<_>>()?;

    let fuel: i32 = module_masses.iter().map(|mass| calculate_fuel(mass)).sum();

    println!("{}", fuel);

    Ok(())
}

fn calculate_fuel(mass: &i32) -> i32 {
    mass / 3 - 2
}
<|endoftext|>


<commit_before>use std::error::Error;

use diesel::result::Error::NotFound;

use super::data_structures::*;
use super::table_data::*;
use crate::database::InferConnection;
use crate::print_schema::ColumnSorting;

static RESERVED_NAMES: &[&str] = &[
    "abstract", "alignof", "as", "become", "box", "break", "const", "continue", "crate", "do",
    "else", "enum", "extern", "false", "final", "fn", "for", "if", "impl", "in", "let", "loop",
    "macro", "match", "mod", "move", "mut", "offsetof", "override", "priv", "proc", "pub", "pure",
    "ref", "return", "Self", "self", "sizeof", "static", "struct", "super", "trait", "true",
    "type", "typeof", "unsafe", "unsized", "use", "virtual", "where", "while", "yield", "bool",
    "columns", "is_nullable",
];

fn is_reserved_name(name: &str) -> bool {
    RESERVED_NAMES.contains(&name)
        || (
            // Names ending in an underscore are not considered reserved so that we
            // can always just append an underscore to generate an unreserved name.
            name.starts_with("__") && !name.ends_with('_')
        )
}

fn contains_unmappable_chars(name: &str) -> bool {
    // Rust identifier names are restricted to [a-zA-Z0-9_].
    !name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')
}

pub fn rust_name_for_sql_name(sql_name: &str) -> String {
    if is_reserved_name(sql_name) {
        format!("{}_", sql_name)
    } else if contains_unmappable_chars(sql_name) {
        // Map each non-alphanumeric character ([^a-zA-Z0-9]) to an underscore.
        let mut rust_name: String = sql_name
            .chars()
            .map(|c| if c.is_ascii_alphanumeric() { c } else { '_' })
            .collect();

        // Iteratively remove adjoining underscores ("__").
        let mut last_len = rust_name.len();
        'remove_adjoining: loop {
            rust_name = rust_name.replace("__", "_");
            if rust_name.len() == last_len {
                // No more underscore pairs left.
                break 'remove_adjoining;
            }
            last_len = rust_name.len();
        }

        rust_name
    } else {
        sql_name.to_string()
    }
}

pub fn load_table_names(
    database_url: &str,
    schema_name: Option<&str>,
) -> Result<Vec<TableName>, Box<dyn Error + Send + Sync + 'static>> {
    let mut connection = InferConnection::establish(database_url)?;

    match connection {
        #[cfg(feature = "sqlite")]
        InferConnection::Sqlite(ref mut c) => super::sqlite::load_table_names(c, schema_name),
        #[cfg(feature = "postgres")]
        InferConnection::Pg(ref mut c) => {
            super::information_schema::load_table_names(c, schema_name)
        }
        #[cfg(feature = "mysql")]
        InferConnection::Mysql(ref mut c) => {
            super::information_schema::load_table_names(c, schema_name)
        }
    }
}

fn get_table_comment(
    conn: &mut InferConnection,
    table: &TableName,
) -> Result<Option<String>, Box<dyn Error + Send + Sync + 'static>> {
    let table_comment = match *conn {
        #[cfg(feature = "sqlite")]
        InferConnection::Sqlite(_) => Ok(None),
        #[cfg(feature = "postgres")]
        InferConnection::Pg(ref mut c) => super::pg::get_table_comment(c, table),
        #[cfg(feature = "mysql")]
        InferConnection::Mysql(ref mut c) => super::mysql::get_table_comment(c, table),
    };
    if let Err(NotFound) = table_comment {
        Err(format!("no table exists named {}", table).into())
    } else {
        table_comment.map_err(Into::into)
    }
}

fn get_column_information(
    conn: &mut InferConnection,
    table: &TableName,
    column_sorting: &ColumnSorting,
) -> Result<Vec<ColumnInformation>, Box<dyn Error + Send + Sync + 'static>> {
    let column_info = match *conn {
        #[cfg(feature = "sqlite")]
        InferConnection::Sqlite(ref mut c) => {
            super::sqlite::get_table_data(c, table, column_sorting)
        }
        #[cfg(feature = "postgres")]
        InferConnection::Pg(ref mut c) => super::pg::get_table_data(c, table, column_sorting),
        #[cfg(feature = "mysql")]
        InferConnection::Mysql(ref mut c) => super::mysql::get_table_data(c, table, column_sorting),
    };
    if let Err(NotFound) = column_info {
        Err(format!("no table exists named {}", table).into())
    } else {
        column_info.map_err(Into::into)
    }
}

fn determine_column_type(
    attr: &ColumnInformation,
    conn: &mut InferConnection,
) -> Result<ColumnType, Box<dyn Error + Send + Sync + 'static>> {
    match *conn {
        #[cfg(feature = "sqlite")]
        InferConnection::Sqlite(_) => super::sqlite::determine_column_type(attr),
        #[cfg(feature = "postgres")]
        InferConnection::Pg(ref mut conn) => {
            use crate::infer_schema_internals::information_schema::DefaultSchema;

            super::pg::determine_column_type(attr, diesel::pg::Pg::default_schema(conn)?)
        }
        #[cfg(feature = "mysql")]
        InferConnection::Mysql(_) => super::mysql::determine_column_type(attr),
    }
}

pub(crate) fn get_primary_keys(
    conn: &mut InferConnection,
    table: &TableName,
) -> Result<Vec<String>, Box<dyn Error + Send + Sync + 'static>> {
    let primary_keys: Vec<String> = match *conn {
        #[cfg(feature = "sqlite")]
        InferConnection::Sqlite(ref mut c) => super::sqlite::get_primary_keys(c, table),
        #[cfg(feature = "postgres")]
        InferConnection::Pg(ref mut c) => super::information_schema::get_primary_keys(c, table),
        #[cfg(feature = "mysql")]
        InferConnection::Mysql(ref mut c) => super::information_schema::get_primary_keys(c, table),
    }?;
    if primary_keys.is_empty() {
        Err(format!(
            "Diesel only supports tables with primary keys. \
             Table {} has no primary key",
            table,
        )
        .into())
    } else {
        Ok(primary_keys)
    }
}

pub fn load_foreign_key_constraints(
    database_url: &str,
    schema_name: Option<&str>,
) -> Result<Vec<ForeignKeyConstraint>, Box<dyn Error + Send + Sync + 'static>> {
    let mut connection = InferConnection::establish(database_url)?;

    let constraints = match connection {
        #[cfg(feature = "sqlite")]
        InferConnection::Sqlite(ref mut c) => {
            super::sqlite::load_foreign_key_constraints(c, schema_name)
        }
        #[cfg(feature = "postgres")]
        InferConnection::Pg(ref mut c) => {
            super::information_schema::load_foreign_key_constraints(c, schema_name)
                .map_err(Into::into)
        }
        #[cfg(feature = "mysql")]
        InferConnection::Mysql(ref mut c) => {
            super::mysql::load_foreign_key_constraints(c, schema_name).map_err(Into::into)
        }
    };

    constraints.map(|mut ct| {
        ct.sort();
        ct.iter_mut().for_each(|foreign_key_constraint| {
            if is_reserved_name(&foreign_key_constraint.foreign_key_rust_name) {
                foreign_key_constraint.foreign_key_rust_name =
                    format!("{}_", foreign_key_constraint.foreign_key_rust_name);
            }
        });
        ct
    })
}

macro_rules! doc_comment {
    ($($token:tt)*) => {
        format!($($token)*)
            .lines()
            .map(str::trim)
            .collect::<Vec<_>>()
            .join("\n")
    };
}

pub fn load_table_data(
    database_url: &str,
    name: TableName,
    column_sorting: &ColumnSorting,
) -> Result<TableData, Box<dyn Error + Send + Sync + 'static>> {
    let mut connection = InferConnection::establish(database_url)?;

    let table_comment = get_table_comment(&mut connection, &name)?;
    let docs = table_comment.unwrap_or_else(|| {
        doc_comment!(
            "Representation of the `{}` table.

            (Automatically generated by Diesel.)",
            name.full_sql_name(),
        )
    });
    let primary_key = get_primary_keys(&mut connection, &name)?;
    let primary_key = primary_key
        .iter()
        .map(|k| rust_name_for_sql_name(k))
        .collect();

    let column_data = get_column_information(&mut connection, &name, column_sorting)?
        .into_iter()
        .map(|c| {
            let ty = determine_column_type(&c, &mut connection)?;

            let ColumnInformation {
                column_name,
                comment,
                ..
            } = c;
            let rust_name = rust_name_for_sql_name(&column_name);

            let docs = comment.unwrap_or_else(|| {
                doc_comment!(
                    "The `{}` column of the `{}` table.

                    Its SQL type is `{}`.

                    (Automatically generated by Diesel.)",
                    column_name,
                    name.full_sql_name(),
                    ty
                )
            });
            Ok(ColumnDefinition {
                docs,
                sql_name: column_name,
                ty,
                rust_name,
            })
        })
        .collect::<Result<_, Box<dyn Error + Send + Sync + 'static>>>()?;

    Ok(TableData {
        name,
        primary_key,
        column_data,
        docs,
    })
}
<commit_msg>rustfmt fix<commit_after>use std::error::Error;

use diesel::result::Error::NotFound;

use super::data_structures::*;
use super::table_data::*;
use crate::database::InferConnection;
use crate::print_schema::ColumnSorting;

static RESERVED_NAMES: &[&str] = &[
    "abstract",
    "alignof",
    "as",
    "become",
    "box",
    "break",
    "const",
    "continue",
    "crate",
    "do",
    "else",
    "enum",
    "extern",
    "false",
    "final",
    "fn",
    "for",
    "if",
    "impl",
    "in",
    "let",
    "loop",
    "macro",
    "match",
    "mod",
    "move",
    "mut",
    "offsetof",
    "override",
    "priv",
    "proc",
    "pub",
    "pure",
    "ref",
    "return",
    "Self",
    "self",
    "sizeof",
    "static",
    "struct",
    "super",
    "trait",
    "true",
    "type",
    "typeof",
    "unsafe",
    "unsized",
    "use",
    "virtual",
    "where",
    "while",
    "yield",
    "bool",
    "columns",
    "is_nullable",
];

fn is_reserved_name(name: &str) -> bool {
    RESERVED_NAMES.contains(&name)
        || (
            // Names ending in an underscore are not considered reserved so that we
            // can always just append an underscore to generate an unreserved name.
            name.starts_with("__") && !name.ends_with('_')
        )
}

fn contains_unmappable_chars(name: &str) -> bool {
    // Rust identifier names are restricted to [a-zA-Z0-9_].
    !name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')
}

pub fn rust_name_for_sql_name(sql_name: &str) -> String {
    if is_reserved_name(sql_name) {
        format!("{}_", sql_name)
    } else if contains_unmappable_chars(sql_name) {
        // Map each non-alphanumeric character ([^a-zA-Z0-9]) to an underscore.
        let mut rust_name: String = sql_name
            .chars()
            .map(|c| if c.is_ascii_alphanumeric() { c } else { '_' })
            .collect();

        // Iteratively remove adjoining underscores ("__").
        let mut last_len = rust_name.len();
        'remove_adjoining: loop {
            rust_name = rust_name.replace("__", "_");
            if rust_name.len() == last_len {
                // No more underscore pairs left.
                break 'remove_adjoining;
            }
            last_len = rust_name.len();
        }

        rust_name
    } else {
        sql_name.to_string()
    }
}

pub fn load_table_names(
    database_url: &str,
    schema_name: Option<&str>,
) -> Result<Vec<TableName>, Box<dyn Error + Send + Sync + 'static>> {
    let mut connection = InferConnection::establish(database_url)?;

    match connection {
        #[cfg(feature = "sqlite")]
        InferConnection::Sqlite(ref mut c) => super::sqlite::load_table_names(c, schema_name),
        #[cfg(feature = "postgres")]
        InferConnection::Pg(ref mut c) => {
            super::information_schema::load_table_names(c, schema_name)
        }
        #[cfg(feature = "mysql")]
        InferConnection::Mysql(ref mut c) => {
            super::information_schema::load_table_names(c, schema_name)
        }
    }
}

fn get_table_comment(
    conn: &mut InferConnection,
    table: &TableName,
) -> Result<Option<String>, Box<dyn Error + Send + Sync + 'static>> {
    let table_comment = match *conn {
        #[cfg(feature = "sqlite")]
        InferConnection::Sqlite(_) => Ok(None),
        #[cfg(feature = "postgres")]
        InferConnection::Pg(ref mut c) => super::pg::get_table_comment(c, table),
        #[cfg(feature = "mysql")]
        InferConnection::Mysql(ref mut c) => super::mysql::get_table_comment(c, table),
    };
    if let Err(NotFound) = table_comment {
        Err(format!("no table exists named {}", table).into())
    } else {
        table_comment.map_err(Into::into)
    }
}

fn get_column_information(
    conn: &mut InferConnection,
    table: &TableName,
    column_sorting: &ColumnSorting,
) -> Result<Vec<ColumnInformation>, Box<dyn Error + Send + Sync + 'static>> {
    let column_info = match *conn {
        #[cfg(feature = "sqlite")]
        InferConnection::Sqlite(ref mut c) => {
            super::sqlite::get_table_data(c, table, column_sorting)
        }
        #[cfg(feature = "postgres")]
        InferConnection::Pg(ref mut c) => super::pg::get_table_data(c, table, column_sorting),
        #[cfg(feature = "mysql")]
        InferConnection::Mysql(ref mut c) => super::mysql::get_table_data(c, table, column_sorting),
    };
    if let Err(NotFound) = column_info {
        Err(format!("no table exists named {}", table).into())
    } else {
        column_info.map_err(Into::into)
    }
}

fn determine_column_type(
    attr: &ColumnInformation,
    conn: &mut InferConnection,
) -> Result<ColumnType, Box<dyn Error + Send + Sync + 'static>> {
    match *conn {
        #[cfg(feature = "sqlite")]
        InferConnection::Sqlite(_) => super::sqlite::determine_column_type(attr),
        #[cfg(feature = "postgres")]
        InferConnection::Pg(ref mut conn) => {
            use crate::infer_schema_internals::information_schema::DefaultSchema;

            super::pg::determine_column_type(attr, diesel::pg::Pg::default_schema(conn)?)
        }
        #[cfg(feature = "mysql")]
        InferConnection::Mysql(_) => super::mysql::determine_column_type(attr),
    }
}

pub(crate) fn get_primary_keys(
    conn: &mut InferConnection,
    table: &TableName,
) -> Result<Vec<String>, Box<dyn Error + Send + Sync + 'static>> {
    let primary_keys: Vec<String> = match *conn {
        #[cfg(feature = "sqlite")]
        InferConnection::Sqlite(ref mut c) => super::sqlite::get_primary_keys(c, table),
        #[cfg(feature = "postgres")]
        InferConnection::Pg(ref mut c) => super::information_schema::get_primary_keys(c, table),
        #[cfg(feature = "mysql")]
        InferConnection::Mysql(ref mut c) => super::information_schema::get_primary_keys(c, table),
    }?;
    if primary_keys.is_empty() {
        Err(format!(
            "Diesel only supports tables with primary keys. \
             Table {} has no primary key",
            table,
        )
        .into())
    } else {
        Ok(primary_keys)
    }
}

pub fn load_foreign_key_constraints(
    database_url: &str,
    schema_name: Option<&str>,
) -> Result<Vec<ForeignKeyConstraint>, Box<dyn Error + Send + Sync + 'static>> {
    let mut connection = InferConnection::establish(database_url)?;

    let constraints = match connection {
        #[cfg(feature = "sqlite")]
        InferConnection::Sqlite(ref mut c) => {
            super::sqlite::load_foreign_key_constraints(c, schema_name)
        }
        #[cfg(feature = "postgres")]
        InferConnection::Pg(ref mut c) => {
            super::information_schema::load_foreign_key_constraints(c, schema_name)
                .map_err(Into::into)
        }
        #[cfg(feature = "mysql")]
        InferConnection::Mysql(ref mut c) => {
            super::mysql::load_foreign_key_constraints(c, schema_name).map_err(Into::into)
        }
    };

    constraints.map(|mut ct| {
        ct.sort();
        ct.iter_mut().for_each(|foreign_key_constraint| {
            if is_reserved_name(&foreign_key_constraint.foreign_key_rust_name) {
                foreign_key_constraint.foreign_key_rust_name =
                    format!("{}_", foreign_key_constraint.foreign_key_rust_name);
            }
        });
        ct
    })
}

macro_rules! doc_comment {
    ($($token:tt)*) => {
        format!($($token)*)
            .lines()
            .map(str::trim)
            .collect::<Vec<_>>()
            .join("\n")
    };
}

pub fn load_table_data(
    database_url: &str,
    name: TableName,
    column_sorting: &ColumnSorting,
) -> Result<TableData, Box<dyn Error + Send + Sync + 'static>> {
    let mut connection = InferConnection::establish(database_url)?;

    let table_comment = get_table_comment(&mut connection, &name)?;
    let docs = table_comment.unwrap_or_else(|| {
        doc_comment!(
            "Representation of the `{}` table.

            (Automatically generated by Diesel.)",
            name.full_sql_name(),
        )
    });
    let primary_key = get_primary_keys(&mut connection, &name)?;
    let primary_key = primary_key
        .iter()
        .map(|k| rust_name_for_sql_name(k))
        .collect();

    let column_data = get_column_information(&mut connection, &name, column_sorting)?
        .into_iter()
        .map(|c| {
            let ty = determine_column_type(&c, &mut connection)?;

            let ColumnInformation {
                column_name,
                comment,
                ..
            } = c;
            let rust_name = rust_name_for_sql_name(&column_name);

            let docs = comment.unwrap_or_else(|| {
                doc_comment!(
                    "The `{}` column of the `{}` table.

                    Its SQL type is `{}`.

                    (Automatically generated by Diesel.)",
                    column_name,
                    name.full_sql_name(),
                    ty
                )
            });
            Ok(ColumnDefinition {
                docs,
                sql_name: column_name,
                ty,
                rust_name,
            })
        })
        .collect::<Result<_, Box<dyn Error + Send + Sync + 'static>>>()?;

    Ok(TableData {
        name,
        primary_key,
        column_data,
        docs,
    })
}
<|endoftext|>


<commit_before>use core::intrinsics::{volatile_load, volatile_store};
use x86::cpuid::CpuId;
use x86::msr::*;

use memory::Frame;
use paging::{entry, ActivePageTable, PhysicalAddress};

/// Local APIC
pub struct LocalApic {
    pub address: u32,
    pub x2: bool
}

impl LocalApic {
    pub fn new(active_table: &mut ActivePageTable) -> Self {
        let mut apic = LocalApic {
            address: (unsafe { rdmsr(IA32_APIC_BASE) as u32 } & 0xFFFF0000),
            x2: false
        };

        unsafe { wrmsr(IA32_APIC_BASE, rdmsr(IA32_APIC_BASE) & !(1 << 11 | 1 << 10)) };

        unsafe { wrmsr(IA32_APIC_BASE, rdmsr(IA32_APIC_BASE) | 1 << 11) };

        if CpuId::new().get_feature_info().unwrap().has_x2apic() {
            unsafe { wrmsr(IA32_APIC_BASE, rdmsr(IA32_APIC_BASE) | 1 << 10) };
            apic.x2 = true;
        } else {
            active_table.identity_map(Frame::containing_address(PhysicalAddress::new(apic.address as usize)), entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE);
        }

        apic
    }

    unsafe fn read(&self, reg: u32) -> u32 {
        volatile_load((self.address + reg) as *const u32)
    }

    unsafe fn write(&self, reg: u32, value: u32) {
        volatile_store((self.address + reg) as *mut u32, value);
    }

    pub fn id(&self) -> u32 {
        if self.x2 {
            unsafe { rdmsr(IA32_X2APIC_APICID) as u32 }
        } else {
            unsafe { self.read(0x20) }
        }
    }

    pub fn version(&self) -> u32 {
        if self.x2 {
            unsafe { rdmsr(IA32_X2APIC_VERSION) as u32 }
        } else {
            unsafe { self.read(0x30) }
        }
    }

    pub fn icr(&self) -> u64 {
        if self.x2 {
            unsafe { rdmsr(IA32_X2APIC_ICR) }
        } else {
            unsafe {
                (self.read(0x310) as u64) << 32 | self.read(0x300) as u64
            }
        }
    }

    pub fn set_icr(&mut self, value: u64) {
        if self.x2 {
            unsafe { wrmsr(IA32_X2APIC_ICR, value); }
        } else {
            unsafe {
                while self.read(0x300) & 1 << 12 == 1 << 12 {}
                self.write(0x310, (value >> 32) as u32);
                self.write(0x300, value as u32);
                while self.read(0x300) & 1 << 12 == 1 << 12 {}
            }
        }
    }
}
<commit_msg>Do not disable local apic, it appears to turn off irqs on BSP<commit_after>use core::intrinsics::{volatile_load, volatile_store};
use x86::cpuid::CpuId;
use x86::msr::*;

use memory::Frame;
use paging::{entry, ActivePageTable, PhysicalAddress};

/// Local APIC
pub struct LocalApic {
    pub address: u32,
    pub x2: bool
}

impl LocalApic {
    pub fn new(active_table: &mut ActivePageTable) -> Self {
        let mut apic = LocalApic {
            address: (unsafe { rdmsr(IA32_APIC_BASE) as u32 } & 0xFFFF0000),
            x2: false
        };

        if CpuId::new().get_feature_info().unwrap().has_x2apic() {
            unsafe { wrmsr(IA32_APIC_BASE, rdmsr(IA32_APIC_BASE) | 1 << 10) };
            apic.x2 = true;
        } else {
            active_table.identity_map(Frame::containing_address(PhysicalAddress::new(apic.address as usize)), entry::PRESENT | entry::WRITABLE | entry::NO_EXECUTE);
        }

        apic
    }

    unsafe fn read(&self, reg: u32) -> u32 {
        volatile_load((self.address + reg) as *const u32)
    }

    unsafe fn write(&self, reg: u32, value: u32) {
        volatile_store((self.address + reg) as *mut u32, value);
    }

    pub fn id(&self) -> u32 {
        if self.x2 {
            unsafe { rdmsr(IA32_X2APIC_APICID) as u32 }
        } else {
            unsafe { self.read(0x20) }
        }
    }

    pub fn version(&self) -> u32 {
        if self.x2 {
            unsafe { rdmsr(IA32_X2APIC_VERSION) as u32 }
        } else {
            unsafe { self.read(0x30) }
        }
    }

    pub fn icr(&self) -> u64 {
        if self.x2 {
            unsafe { rdmsr(IA32_X2APIC_ICR) }
        } else {
            unsafe {
                (self.read(0x310) as u64) << 32 | self.read(0x300) as u64
            }
        }
    }

    pub fn set_icr(&mut self, value: u64) {
        if self.x2 {
            unsafe { wrmsr(IA32_X2APIC_ICR, value); }
        } else {
            unsafe {
                while self.read(0x300) & 1 << 12 == 1 << 12 {}
                self.write(0x310, (value >> 32) as u32);
                self.write(0x300, value as u32);
                while self.read(0x300) & 1 << 12 == 1 << 12 {}
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate http;
extern crate mount;

use std::io::net::ip::Ipv4Addr;

use iron::{Iron, Request, Response, Alloy, ServerT};
use iron::middleware::{Status, Continue, Unwind};
use iron::mixin::Serve;
use http::status;
use mount::Mount;

fn intercept(_req: &mut Request, _res: &mut Response,
             _alloy: &mut Alloy) -> Status {
    Unwind
}

fn send_hello(_req: &mut Request, res: &mut Response,
              _alloy: &mut Alloy) -> Status {
    let _ = res.serve(status::Ok, "Hello!");
    Continue
}

fn main() {
    let mut server: ServerT = Iron::new();
    server.link(Mount::new("/blocked", intercept));
    server.link(send_hello);
    server.listen(Ipv4Addr(127, 0, 0, 1), 3000);
}

<commit_msg>(doc) Updated example for chain.link changes.<commit_after>extern crate iron;
extern crate http;
extern crate mount;

use std::io::net::ip::Ipv4Addr;

use iron::{Iron, Request, Response, Alloy, ServerT, Chain};
use iron::middleware::{Status, Continue, Unwind};
use iron::mixin::Serve;
use http::status;
use mount::Mount;

fn intercept(_req: &mut Request, _res: &mut Response,
             _alloy: &mut Alloy) -> Status {
    Unwind
}

fn send_hello(_req: &mut Request, res: &mut Response,
              _alloy: &mut Alloy) -> Status {
    let _ = res.serve(status::Ok, "Hello!");
    Continue
}

fn main() {
    let mut server: ServerT = Iron::new();
    server.chain.link(Mount::new("/blocked", intercept));
    server.chain.link(send_hello);
    server.listen(Ipv4Addr(127, 0, 0, 1), 3000);
}

<|endoftext|>


<commit_before>use std::ops::{Deref, DerefMut};
use std::collections::HashMap;

use term::Term;
use token::Token;

#[derive(Debug, Clone, PartialEq)]
pub struct TermVector(HashMap<Term, Vec<u32>>);

impl TermVector {
    pub fn new() -> TermVector {
        TermVector(HashMap::new())
    }
}

impl Deref for TermVector {
    type Target = HashMap<Term, Vec<u32>>;

    fn deref(&self) -> &HashMap<Term, Vec<u32>> {
        &self.0
    }
}

impl DerefMut for TermVector {
    fn deref_mut(&mut self) -> &mut HashMap<Term, Vec<u32>> {
        &mut self.0
    }
}

impl Into<TermVector> for Vec<Token> {
    fn into(self) -> TermVector {
        let mut map = HashMap::new();

        for token in self {
            let mut positions = map.entry(token.term).or_insert_with(Vec::new);
            positions.push(token.position);
        }

         TermVector(map)
    }
}

impl Into<Vec<Token>> for TermVector {
    fn into(self) -> Vec<Token> {
        let mut vec = Vec::new();

        for (term, positions) in self.0 {
            for position in positions {
                vec.push(Token { term: term.clone(), position: position });
            }
        }

        vec.sort_by_key(|token| token.position);

        vec
    }
}
<commit_msg>Use roaring bitmaps for storing term positions<commit_after>use std::ops::{Deref, DerefMut};
use std::collections::HashMap;

use roaring::RoaringBitmap;

use term::Term;
use token::Token;

#[derive(Debug, Clone, PartialEq)]
pub struct TermVector(HashMap<Term, RoaringBitmap>);

impl TermVector {
    pub fn new() -> TermVector {
        TermVector(HashMap::new())
    }
}

impl Deref for TermVector {
    type Target = HashMap<Term, RoaringBitmap>;

    fn deref(&self) -> &HashMap<Term, RoaringBitmap> {
        &self.0
    }
}

impl DerefMut for TermVector {
    fn deref_mut(&mut self) -> &mut HashMap<Term, RoaringBitmap> {
        &mut self.0
    }
}

impl Into<TermVector> for Vec<Token> {
    fn into(self) -> TermVector {
        let mut map = HashMap::new();

        for token in self {
            let mut positions = map.entry(token.term).or_insert_with(RoaringBitmap::new);
            positions.insert(token.position);
        }

         TermVector(map)
    }
}

impl Into<Vec<Token>> for TermVector {
    fn into(self) -> Vec<Token> {
        let mut vec = Vec::new();

        for (term, positions) in self.0 {
            for position in positions {
                vec.push(Token { term: term.clone(), position: position });
            }
        }

        vec.sort_by_key(|token| token.position);

        vec
    }
}
<|endoftext|>


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

#[cfg(feature = "unstable")]
extern crate test;

/// request to change memcache verbosity
pub fn verbosity(level: usize) -> String {
    format!("verbosity {}\r\n", level)
}

#[test]
fn test_verbosity() {
    assert_eq!(verbosity(4), "verbosity 4\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn memcache_verbosity_benchmark(b: &mut test::Bencher) {
    b.iter(|| verbosity(4));
}

/// create a memcache version tcp request
pub fn version() -> String {
    "version\r\n".to_owned()
}

#[test]
fn test_version() {
    assert_eq!(version(), "version\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn memcache_version_benchmark(b: &mut test::Bencher) {
    b.iter(|| version());
}

/// create a memcache quit request
pub fn quit() -> String {
    "quit\r\n".to_owned()
}

#[test]
fn test_quit() {
    assert_eq!(quit(), "quit\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn memcache_quit_benchmark(b: &mut test::Bencher) {
    b.iter(|| quit());
}

/// create a set request
pub fn set(key: &str, value: &str, exptime: Option<u32>, flags: Option<u32>) -> String {
    let flags = flags.unwrap_or(0);
    let exptime = exptime.unwrap_or(0);
    format!("set {} {} {} {}\r\n{}\r\n",
            key,
            flags,
            exptime,
            value.len(),
            value)
}

#[test]
fn test_set() {
    assert_eq!(set("key", "value", None, None), "set key 0 0 5\r\nvalue\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn memcache_set_benchmark(b: &mut test::Bencher) {
    b.iter(|| set("key", "value", Some(1), None));
}

/// create a cas request
pub fn cas(key: &str, value: &str, exptime: Option<u32>, flags: Option<u32>, cas: u64) -> String {
    let flags = flags.unwrap_or(0);
    let exptime = exptime.unwrap_or(0);
    format!("cas {} {} {} {} {}\r\n{}\r\n",
            key,
            flags,
            exptime,
            value.len(),
            cas,
            value)
}

#[test]
fn test_cas() {
    assert_eq!(cas("key", "value", None, None, 100_u64), "cas key 0 0 5 100\r\nvalue\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn memcache_cas_benchmark(b: &mut test::Bencher) {
    b.iter(|| cas("key", "value", Some(1), None, 0));
}

/// create an add request
pub fn add(key: &str, value: &str, exptime: Option<u32>, flags: Option<u32>) -> String {
    let flags = flags.unwrap_or(0);
    let exptime = exptime.unwrap_or(0);
    format!("add {} {} {} {}\r\n{}\r\n",
            key,
            flags,
            exptime,
            value.len(),
            value)
}

#[test]
fn test_add() {
    assert_eq!(add("key", "value", None, None), "add key 0 0 5\r\nvalue\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn memcache_add_benchmark(b: &mut test::Bencher) {
    b.iter(|| add("key", "value", Some(1), None));
}

/// create a replace request
pub fn replace(key: &str, value: &str, exptime: Option<u32>, flags: Option<u32>) -> String {
    let flags = flags.unwrap_or(0);
    let exptime = exptime.unwrap_or(0);
    format!("replace {} {} {} {}\r\n{}\r\n",
            key,
            flags,
            exptime,
            value.len(),
            value)
}

#[test]
fn test_replace() {
    assert_eq!(replace("key", "value", None, None), "replace key 0 0 5\r\nvalue\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn memcache_replace_benchmark(b: &mut test::Bencher) {
    b.iter(|| replace("key", "value", Some(1), None));
}

/// create an append request
pub fn append(key: &str, value: &str, exptime: Option<u32>, flags: Option<u32>) -> String {
    let flags = flags.unwrap_or(0);
    let exptime = exptime.unwrap_or(0);
    format!("append {} {} {} {}\r\n{}\r\n",
            key,
            flags,
            exptime,
            value.len(),
            value)
}

#[test]
fn test_append() {
    assert_eq!(append("key", "value", None, None), "append key 0 0 5\r\nvalue\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn memcache_append_benchmark(b: &mut test::Bencher) {
    b.iter(|| append("key", "value", Some(1), None));
}

/// create an prepend request
pub fn prepend(key: &str, value: &str, exptime: Option<u32>, flags: Option<u32>) -> String {
    let flags = flags.unwrap_or(0);
    let exptime = exptime.unwrap_or(0);
    format!("prepend {} {} {} {}\r\n{}\r\n",
            key,
            flags,
            exptime,
            value.len(),
            value)
}

#[test]
fn test_prepend() {
    assert_eq!(prepend("key", "value", None, None), "prepend key 0 0 5\r\nvalue\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn prepend_benchmark(b: &mut test::Bencher) {
    b.iter(|| prepend("key", "value", Some(1), None));
}

/// create a incr request
pub fn incr(key: &str, value: u64) -> String {
    format!("incr {} {}\r\n", key, value)
}

#[test]
fn test_incr() {
    assert_eq!(incr("key", 1), "incr key 1\r\n");
    assert_eq!(incr("key", 1000), "incr key 1000\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn incr_benchmark(b: &mut test::Bencher) {
    b.iter(|| incr("key", 1));
}

/// create a decr request
pub fn decr(key: &str, value: u64) -> String {
    format!("decr {} {}\r\n", key, value)
}

#[test]
fn test_decr() {
    assert_eq!(decr("key", 1), "decr key 1\r\n");
    assert_eq!(decr("key", 1000), "decr key 1000\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn decr_benchmark(b: &mut test::Bencher) {
    b.iter(|| decr("key", 1));
}

/// create a touch request
pub fn touch(key: &str, exptime: Option<u32>) -> String {
    let exptime = exptime.unwrap_or(0);
    format!("touch {} {}\r\n", key, exptime)
}

#[test]
fn test_touch() {
    assert_eq!(touch("key", None), "touch key 0\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn touch_benchmark(b: &mut test::Bencher) {
    b.iter(|| touch("key", None));
}

/// create a get request
pub fn get(key: &str) -> String {
    format!("get {}\r\n", key)
}

#[test]
fn test_get() {
    assert_eq!(get("key"), "get key\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn get_benchmark(b: &mut test::Bencher) {
    b.iter(|| get("key"));
}

/// create a gets request
pub fn gets(key: &str) -> String {
    format!("gets {}\r\n", key)
}

#[test]
fn test_gets() {
    assert_eq!(gets("key"), "gets key\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn gets_benchmark(b: &mut test::Bencher) {
    b.iter(|| gets("key"));
}

/// create a delete request
pub fn delete(key: &str) -> String {
    format!("delete {}\r\n", key)
}

#[test]
fn test_delete() {
    assert_eq!(delete("key"), "delete key\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn delete_benchmark(b: &mut test::Bencher) {
    b.iter(|| delete("key"));
}

/// create a flush_all request
pub fn flush_all() -> String {
    "flush_all\r\n".to_owned()
}

#[test]
fn test_flush_all() {
    assert_eq!(flush_all(), "flush_all\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn flush_all_benchmark(b: &mut test::Bencher) {
    b.iter(|| flush_all());
}
<commit_msg>improve benchmark test naming<commit_after>//  rpc-perf - RPC Performance Testing
//  Copyright 2015 Twitter, Inc
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

#[cfg(feature = "unstable")]
extern crate test;

/// request to change memcache verbosity
pub fn verbosity(level: usize) -> String {
    format!("verbosity {}\r\n", level)
}

#[test]
fn test_verbosity() {
    assert_eq!(verbosity(4), "verbosity 4\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn verbosity_benchmark(b: &mut test::Bencher) {
    b.iter(|| verbosity(4));
}

/// create a memcache version tcp request
pub fn version() -> String {
    "version\r\n".to_owned()
}

#[test]
fn test_version() {
    assert_eq!(version(), "version\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn version_benchmark(b: &mut test::Bencher) {
    b.iter(|| version());
}

/// create a memcache quit request
pub fn quit() -> String {
    "quit\r\n".to_owned()
}

#[test]
fn test_quit() {
    assert_eq!(quit(), "quit\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn quit_benchmark(b: &mut test::Bencher) {
    b.iter(|| quit());
}

/// create a set request
pub fn set(key: &str, value: &str, exptime: Option<u32>, flags: Option<u32>) -> String {
    let flags = flags.unwrap_or(0);
    let exptime = exptime.unwrap_or(0);
    format!("set {} {} {} {}\r\n{}\r\n",
            key,
            flags,
            exptime,
            value.len(),
            value)
}

#[test]
fn test_set() {
    assert_eq!(set("key", "value", None, None), "set key 0 0 5\r\nvalue\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn set_benchmark(b: &mut test::Bencher) {
    b.iter(|| set("key", "value", Some(1), None));
}

/// create a cas request
pub fn cas(key: &str, value: &str, exptime: Option<u32>, flags: Option<u32>, cas: u64) -> String {
    let flags = flags.unwrap_or(0);
    let exptime = exptime.unwrap_or(0);
    format!("cas {} {} {} {} {}\r\n{}\r\n",
            key,
            flags,
            exptime,
            value.len(),
            cas,
            value)
}

#[test]
fn test_cas() {
    assert_eq!(cas("key", "value", None, None, 100_u64), "cas key 0 0 5 100\r\nvalue\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn cas_benchmark(b: &mut test::Bencher) {
    b.iter(|| cas("key", "value", Some(1), None, 0));
}

/// create an add request
pub fn add(key: &str, value: &str, exptime: Option<u32>, flags: Option<u32>) -> String {
    let flags = flags.unwrap_or(0);
    let exptime = exptime.unwrap_or(0);
    format!("add {} {} {} {}\r\n{}\r\n",
            key,
            flags,
            exptime,
            value.len(),
            value)
}

#[test]
fn test_add() {
    assert_eq!(add("key", "value", None, None), "add key 0 0 5\r\nvalue\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn add_benchmark(b: &mut test::Bencher) {
    b.iter(|| add("key", "value", Some(1), None));
}

/// create a replace request
pub fn replace(key: &str, value: &str, exptime: Option<u32>, flags: Option<u32>) -> String {
    let flags = flags.unwrap_or(0);
    let exptime = exptime.unwrap_or(0);
    format!("replace {} {} {} {}\r\n{}\r\n",
            key,
            flags,
            exptime,
            value.len(),
            value)
}

#[test]
fn test_replace() {
    assert_eq!(replace("key", "value", None, None), "replace key 0 0 5\r\nvalue\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn replace_benchmark(b: &mut test::Bencher) {
    b.iter(|| replace("key", "value", Some(1), None));
}

/// create an append request
pub fn append(key: &str, value: &str, exptime: Option<u32>, flags: Option<u32>) -> String {
    let flags = flags.unwrap_or(0);
    let exptime = exptime.unwrap_or(0);
    format!("append {} {} {} {}\r\n{}\r\n",
            key,
            flags,
            exptime,
            value.len(),
            value)
}

#[test]
fn test_append() {
    assert_eq!(append("key", "value", None, None), "append key 0 0 5\r\nvalue\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn append_benchmark(b: &mut test::Bencher) {
    b.iter(|| append("key", "value", Some(1), None));
}

/// create an prepend request
pub fn prepend(key: &str, value: &str, exptime: Option<u32>, flags: Option<u32>) -> String {
    let flags = flags.unwrap_or(0);
    let exptime = exptime.unwrap_or(0);
    format!("prepend {} {} {} {}\r\n{}\r\n",
            key,
            flags,
            exptime,
            value.len(),
            value)
}

#[test]
fn test_prepend() {
    assert_eq!(prepend("key", "value", None, None), "prepend key 0 0 5\r\nvalue\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn prepend_benchmark(b: &mut test::Bencher) {
    b.iter(|| prepend("key", "value", Some(1), None));
}

/// create a incr request
pub fn incr(key: &str, value: u64) -> String {
    format!("incr {} {}\r\n", key, value)
}

#[test]
fn test_incr() {
    assert_eq!(incr("key", 1), "incr key 1\r\n");
    assert_eq!(incr("key", 1000), "incr key 1000\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn incr_benchmark(b: &mut test::Bencher) {
    b.iter(|| incr("key", 1));
}

/// create a decr request
pub fn decr(key: &str, value: u64) -> String {
    format!("decr {} {}\r\n", key, value)
}

#[test]
fn test_decr() {
    assert_eq!(decr("key", 1), "decr key 1\r\n");
    assert_eq!(decr("key", 1000), "decr key 1000\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn decr_benchmark(b: &mut test::Bencher) {
    b.iter(|| decr("key", 1));
}

/// create a touch request
pub fn touch(key: &str, exptime: Option<u32>) -> String {
    let exptime = exptime.unwrap_or(0);
    format!("touch {} {}\r\n", key, exptime)
}

#[test]
fn test_touch() {
    assert_eq!(touch("key", None), "touch key 0\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn touch_benchmark(b: &mut test::Bencher) {
    b.iter(|| touch("key", None));
}

/// create a get request
pub fn get(key: &str) -> String {
    format!("get {}\r\n", key)
}

#[test]
fn test_get() {
    assert_eq!(get("key"), "get key\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn get_benchmark(b: &mut test::Bencher) {
    b.iter(|| get("key"));
}

/// create a gets request
pub fn gets(key: &str) -> String {
    format!("gets {}\r\n", key)
}

#[test]
fn test_gets() {
    assert_eq!(gets("key"), "gets key\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn gets_benchmark(b: &mut test::Bencher) {
    b.iter(|| gets("key"));
}

/// create a delete request
pub fn delete(key: &str) -> String {
    format!("delete {}\r\n", key)
}

#[test]
fn test_delete() {
    assert_eq!(delete("key"), "delete key\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn delete_benchmark(b: &mut test::Bencher) {
    b.iter(|| delete("key"));
}

/// create a flush_all request
pub fn flush_all() -> String {
    "flush_all\r\n".to_owned()
}

#[test]
fn test_flush_all() {
    assert_eq!(flush_all(), "flush_all\r\n");
}

#[cfg(feature = "unstable")]
#[bench]
fn flush_all_benchmark(b: &mut test::Bencher) {
    b.iter(|| flush_all());
}
<|endoftext|>