<commit_before>#![deny(warnings)]

extern crate extra;

use std::env;
use std::fs;
use std::path::Path;
use std::io::{stdout, stderr, Stderr, Write};
use extra::option::OptionalExt;
use std::process::exit;

const MAN_PAGE: &'static str = /* @MANSTART{ls} */ r#"
NAME
    ls - list directory contents

SYNOPSIS
    ls [ -h | --help ][FILE]...

DESCRIPTION
    List information about the FILE(s), or the current directory

OPTIONS
    -h
    --help
        display this help and exit
"#; /* @MANEND */

fn list_dir(path: &str, string: &mut String, stderr: &mut Stderr) {
    if fs::metadata(path).try(stderr).is_dir() {
        let read_dir = Path::new(path).read_dir().try(stderr);

        let mut entries: Vec<String> = read_dir.filter_map(|x| x.ok()).map(|dir| {
                let mut file_name = dir.file_name().to_string_lossy().into_owned();
                if dir.file_type().try(stderr).is_dir() {
                    file_name.push('/');
                }
                file_name
            })
            .collect();

        entries.sort();

        for entry in entries.iter() {
            string.push_str(entry);
            string.push('\n');
        }
    } else {
        string.push_str(path);
        string.push('\n');
    }
}

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();

    for arg in env::args().skip(1) {
        if arg.as_str() == "-h" || arg.as_str() == "--help" {
            stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
            stdout.flush().try(&mut stderr);
            exit(0);
        }
    }

    let mut string = String::new();
    let args = env::args().skip(1);
    if args.len() > 0 {
        for dir in args {
            list_dir(&dir, &mut string, &mut stderr);
        }
    } else {
        list_dir(".", &mut string, &mut stderr);
    }
    stdout.write(string.as_bytes()).try(&mut stderr);
}
<commit_msg>Long format (#75)<commit_after>#![deny(warnings)]

extern crate extra;

use std::env;
use std::fs;
use std::path::Path;
use std::io::{stdout, stderr, Stderr, Write};
use std::os::unix::fs::MetadataExt;
use extra::option::OptionalExt;
use std::process::exit;

const MAN_PAGE: &'static str = /* @MANSTART{ls} */ r#"
NAME
    ls - list directory contents

SYNOPSIS
    ls [ -h | --help ][FILE]...

DESCRIPTION
    List information about the FILE(s), or the current directory

OPTIONS
    -h
    --help
        display this help and exit
"#; /* @MANEND */

fn list_dir(path: &str, long_format: bool, string: &mut String, stderr: &mut Stderr) {
    let metadata = fs::metadata(path).try(stderr);
    if metadata.is_dir() {
        let read_dir = Path::new(path).read_dir().try(stderr);

        let mut entries: Vec<String> = read_dir.filter_map(|x| x.ok()).map(|dir| {
                let mut file_name = dir.file_name().to_string_lossy().into_owned();
                if dir.file_type().try(stderr).is_dir() {
                    file_name.push('/');
                }
                file_name
            })
            .collect();

        entries.sort();

        for entry in entries.iter() {
            if long_format {
                let mut entry_path = path.to_owned();
                if !entry_path.ends_with('/') {
                    entry_path.push('/');
                }
                entry_path.push_str(&entry);

                let metadata = fs::metadata(entry_path).try(stderr);
                string.push_str(&format!("{:>7o} {:>5} {:>5} {:>8} ", metadata.mode(), metadata.uid(), metadata.gid(), metadata.size()/1024));
            }
            string.push_str(entry);
            string.push('\n');
        }
    } else {
        if long_format {
            string.push_str(&format!("{:>7o} {:>5} {:>5} {:>8} ", metadata.mode(), metadata.uid(), metadata.gid(), metadata.size()/1024));
        }
        string.push_str(path);
        string.push('\n');
    }
}

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();

    let mut long_format = false;
    let mut args = Vec::new();
    for arg in env::args().skip(1) {
        if arg.as_str() == "-h" || arg.as_str() == "--help" {
            stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
            stdout.flush().try(&mut stderr);
            exit(0);
        } else if arg.as_str() == "-l" {
            long_format = true;
        } else {
            args.push(arg);
        }
    }

    let mut string = String::new();
    if args.is_empty() {
        list_dir(".", long_format, &mut string, &mut stderr);
    } else {
        for dir in args {
            list_dir(&dir, long_format, &mut string, &mut stderr);
        }
    }
    stdout.write(string.as_bytes()).try(&mut stderr);
}
<|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/. */

//! Computed types for text properties.

#[cfg(feature = "servo")]
use crate::properties::StyleBuilder;
use crate::values::computed::length::{Length, LengthPercentage};
use crate::values::computed::{Context, NonNegativeLength, NonNegativeNumber, ToComputedValue};
use crate::values::generics::text::InitialLetter as GenericInitialLetter;
use crate::values::generics::text::LineHeight as GenericLineHeight;
use crate::values::generics::text::Spacing;
use crate::values::specified::text::{self as specified, TextOverflowSide};
use crate::values::specified::text::{TextEmphasisFillMode, TextEmphasisShapeKeyword};
use crate::values::{CSSFloat, CSSInteger};
use crate::Zero;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};

pub use crate::values::specified::TextAlignKeyword as TextAlign;
pub use crate::values::specified::{LineBreak, OverflowWrap, WordBreak};
pub use crate::values::specified::{TextDecorationLine, TextEmphasisPosition};
pub use crate::values::specified::{TextDecorationSkipInk, TextTransform};

/// A computed value for the `initial-letter` property.
pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;

/// A computed value for the `letter-spacing` property.
#[repr(transparent)]
#[derive(
    Animate,
    Clone,
    ComputeSquaredDistance,
    Copy,
    Debug,
    MallocSizeOf,
    PartialEq,
    ToAnimatedValue,
    ToAnimatedZero,
    ToResolvedValue,
)]
pub struct LetterSpacing(pub Length);

impl LetterSpacing {
    /// Return the `normal` computed value, which is just zero.
    #[inline]
    pub fn normal() -> Self {
        LetterSpacing(Length::zero())
    }
}

impl ToCss for LetterSpacing {
    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
    where
        W: Write,
    {
        // https://drafts.csswg.org/css-text/#propdef-letter-spacing
        //
        // For legacy reasons, a computed letter-spacing of zero yields a
        // resolved value (getComputedStyle() return value) of normal.
        if self.0.is_zero() {
            return dest.write_str("normal");
        }
        self.0.to_css(dest)
    }
}

impl ToComputedValue for specified::LetterSpacing {
    type ComputedValue = LetterSpacing;
    fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
        match *self {
            Spacing::Normal => LetterSpacing(Length::zero()),
            Spacing::Value(ref v) => LetterSpacing(v.to_computed_value(context)),
        }
    }

    fn from_computed_value(computed: &Self::ComputedValue) -> Self {
        if computed.0.is_zero() {
            return Spacing::Normal;
        }
        Spacing::Value(ToComputedValue::from_computed_value(&computed.0))
    }
}

/// A computed value for the `word-spacing` property.
pub type WordSpacing = LengthPercentage;

impl ToComputedValue for specified::WordSpacing {
    type ComputedValue = WordSpacing;

    fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
        match *self {
            Spacing::Normal => LengthPercentage::zero(),
            Spacing::Value(ref v) => v.to_computed_value(context),
        }
    }

    fn from_computed_value(computed: &Self::ComputedValue) -> Self {
        Spacing::Value(ToComputedValue::from_computed_value(computed))
    }
}

/// A computed value for the `line-height` property.
pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeLength>;

#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToResolvedValue)]
#[repr(C)]
/// text-overflow.
/// When the specified value only has one side, that's the "second"
/// side, and the sides are logical, so "second" means "end".  The
/// start side is Clip in that case.
///
/// When the specified value has two sides, those are our "first"
/// and "second" sides, and they are physical sides ("left" and
/// "right").
pub struct TextOverflow {
    /// First side
    pub first: TextOverflowSide,
    /// Second side
    pub second: TextOverflowSide,
    /// True if the specified value only has one side.
    pub sides_are_logical: bool,
}

impl TextOverflow {
    /// Returns the initial `text-overflow` value
    pub fn get_initial_value() -> TextOverflow {
        TextOverflow {
            first: TextOverflowSide::Clip,
            second: TextOverflowSide::Clip,
            sides_are_logical: true,
        }
    }
}

impl ToCss for TextOverflow {
    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
    where
        W: Write,
    {
        if self.sides_are_logical {
            debug_assert_eq!(self.first, TextOverflowSide::Clip);
            self.second.to_css(dest)?;
        } else {
            self.first.to_css(dest)?;
            dest.write_str(" ")?;
            self.second.to_css(dest)?;
        }
        Ok(())
    }
}

/// A struct that represents the _used_ value of the text-decoration property.
///
/// FIXME(emilio): This is done at style resolution time, though probably should
/// be done at layout time, otherwise we need to account for display: contents
/// and similar stuff when we implement it.
///
/// FIXME(emilio): Also, should be just a bitfield instead of three bytes.
#[derive(Clone, Copy, Debug, Default, MallocSizeOf, PartialEq, ToResolvedValue)]
pub struct TextDecorationsInEffect {
    /// Whether an underline is in effect.
    pub underline: bool,
    /// Whether an overline decoration is in effect.
    pub overline: bool,
    /// Whether a line-through style is in effect.
    pub line_through: bool,
}

impl TextDecorationsInEffect {
    /// Computes the text-decorations in effect for a given style.
    #[cfg(feature = "servo")]
    pub fn from_style(style: &StyleBuilder) -> Self {
        // Start with no declarations if this is an atomic inline-level box;
        // otherwise, start with the declarations in effect and add in the text
        // decorations that this block specifies.
        let mut result = if style.get_box().clone_display().is_atomic_inline_level() {
            Self::default()
        } else {
            style
                .get_parent_inherited_text()
                .text_decorations_in_effect
                .clone()
        };

        let line = style.get_text().clone_text_decoration_line();

        result.underline |= line.contains(TextDecorationLine::UNDERLINE);
        result.overline |= line.contains(TextDecorationLine::OVERLINE);
        result.line_through |= line.contains(TextDecorationLine::LINE_THROUGH);

        result
    }
}

/// Computed value for the text-emphasis-style property
///
/// cbindgen:derive-tagged-enum-copy-constructor=true
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue)]
#[allow(missing_docs)]
#[repr(C, u8)]
pub enum TextEmphasisStyle {
    /// [ <fill> || <shape> ]
    Keyword {
        fill: TextEmphasisFillMode,
        shape: TextEmphasisShapeKeyword,
    },
    /// `none`
    None,
    /// `<string>` (of which only the first grapheme cluster will be used).
    String(crate::OwnedStr),
}
<commit_msg>style: Use shortest serialization for computed text-emphasis-style too.<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/. */

//! Computed types for text properties.

#[cfg(feature = "servo")]
use crate::properties::StyleBuilder;
use crate::values::computed::length::{Length, LengthPercentage};
use crate::values::computed::{Context, NonNegativeLength, NonNegativeNumber, ToComputedValue};
use crate::values::generics::text::InitialLetter as GenericInitialLetter;
use crate::values::generics::text::LineHeight as GenericLineHeight;
use crate::values::generics::text::Spacing;
use crate::values::specified::text::{self as specified, TextOverflowSide};
use crate::values::specified::text::{TextEmphasisFillMode, TextEmphasisShapeKeyword};
use crate::values::{CSSFloat, CSSInteger};
use crate::Zero;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};

pub use crate::values::specified::TextAlignKeyword as TextAlign;
pub use crate::values::specified::{LineBreak, OverflowWrap, WordBreak};
pub use crate::values::specified::{TextDecorationLine, TextEmphasisPosition};
pub use crate::values::specified::{TextDecorationSkipInk, TextTransform};

/// A computed value for the `initial-letter` property.
pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;

/// A computed value for the `letter-spacing` property.
#[repr(transparent)]
#[derive(
    Animate,
    Clone,
    ComputeSquaredDistance,
    Copy,
    Debug,
    MallocSizeOf,
    PartialEq,
    ToAnimatedValue,
    ToAnimatedZero,
    ToResolvedValue,
)]
pub struct LetterSpacing(pub Length);

impl LetterSpacing {
    /// Return the `normal` computed value, which is just zero.
    #[inline]
    pub fn normal() -> Self {
        LetterSpacing(Length::zero())
    }
}

impl ToCss for LetterSpacing {
    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
    where
        W: Write,
    {
        // https://drafts.csswg.org/css-text/#propdef-letter-spacing
        //
        // For legacy reasons, a computed letter-spacing of zero yields a
        // resolved value (getComputedStyle() return value) of normal.
        if self.0.is_zero() {
            return dest.write_str("normal");
        }
        self.0.to_css(dest)
    }
}

impl ToComputedValue for specified::LetterSpacing {
    type ComputedValue = LetterSpacing;
    fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
        match *self {
            Spacing::Normal => LetterSpacing(Length::zero()),
            Spacing::Value(ref v) => LetterSpacing(v.to_computed_value(context)),
        }
    }

    fn from_computed_value(computed: &Self::ComputedValue) -> Self {
        if computed.0.is_zero() {
            return Spacing::Normal;
        }
        Spacing::Value(ToComputedValue::from_computed_value(&computed.0))
    }
}

/// A computed value for the `word-spacing` property.
pub type WordSpacing = LengthPercentage;

impl ToComputedValue for specified::WordSpacing {
    type ComputedValue = WordSpacing;

    fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
        match *self {
            Spacing::Normal => LengthPercentage::zero(),
            Spacing::Value(ref v) => v.to_computed_value(context),
        }
    }

    fn from_computed_value(computed: &Self::ComputedValue) -> Self {
        Spacing::Value(ToComputedValue::from_computed_value(computed))
    }
}

/// A computed value for the `line-height` property.
pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeLength>;

#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToResolvedValue)]
#[repr(C)]
/// text-overflow.
/// When the specified value only has one side, that's the "second"
/// side, and the sides are logical, so "second" means "end".  The
/// start side is Clip in that case.
///
/// When the specified value has two sides, those are our "first"
/// and "second" sides, and they are physical sides ("left" and
/// "right").
pub struct TextOverflow {
    /// First side
    pub first: TextOverflowSide,
    /// Second side
    pub second: TextOverflowSide,
    /// True if the specified value only has one side.
    pub sides_are_logical: bool,
}

impl TextOverflow {
    /// Returns the initial `text-overflow` value
    pub fn get_initial_value() -> TextOverflow {
        TextOverflow {
            first: TextOverflowSide::Clip,
            second: TextOverflowSide::Clip,
            sides_are_logical: true,
        }
    }
}

impl ToCss for TextOverflow {
    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
    where
        W: Write,
    {
        if self.sides_are_logical {
            debug_assert_eq!(self.first, TextOverflowSide::Clip);
            self.second.to_css(dest)?;
        } else {
            self.first.to_css(dest)?;
            dest.write_str(" ")?;
            self.second.to_css(dest)?;
        }
        Ok(())
    }
}

/// A struct that represents the _used_ value of the text-decoration property.
///
/// FIXME(emilio): This is done at style resolution time, though probably should
/// be done at layout time, otherwise we need to account for display: contents
/// and similar stuff when we implement it.
///
/// FIXME(emilio): Also, should be just a bitfield instead of three bytes.
#[derive(Clone, Copy, Debug, Default, MallocSizeOf, PartialEq, ToResolvedValue)]
pub struct TextDecorationsInEffect {
    /// Whether an underline is in effect.
    pub underline: bool,
    /// Whether an overline decoration is in effect.
    pub overline: bool,
    /// Whether a line-through style is in effect.
    pub line_through: bool,
}

impl TextDecorationsInEffect {
    /// Computes the text-decorations in effect for a given style.
    #[cfg(feature = "servo")]
    pub fn from_style(style: &StyleBuilder) -> Self {
        // Start with no declarations if this is an atomic inline-level box;
        // otherwise, start with the declarations in effect and add in the text
        // decorations that this block specifies.
        let mut result = if style.get_box().clone_display().is_atomic_inline_level() {
            Self::default()
        } else {
            style
                .get_parent_inherited_text()
                .text_decorations_in_effect
                .clone()
        };

        let line = style.get_text().clone_text_decoration_line();

        result.underline |= line.contains(TextDecorationLine::UNDERLINE);
        result.overline |= line.contains(TextDecorationLine::OVERLINE);
        result.line_through |= line.contains(TextDecorationLine::LINE_THROUGH);

        result
    }
}

/// Computed value for the text-emphasis-style property
///
/// cbindgen:derive-tagged-enum-copy-constructor=true
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue)]
#[allow(missing_docs)]
#[repr(C, u8)]
pub enum TextEmphasisStyle {
    /// [ <fill> || <shape> ]
    Keyword {
        #[css(skip_if = "TextEmphasisFillMode::is_filled")]
        fill: TextEmphasisFillMode,
        shape: TextEmphasisShapeKeyword,
    },
    /// `none`
    None,
    /// `<string>` (of which only the first grapheme cluster will be used).
    String(crate::OwnedStr),
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::collections::BTreeSet;
use std::str::FromStr;
use std::fmt;
use twiddle::Twiddle;

use board::Board;
use board::Square;
use piece::Piece;
use piece::Player;
use piece;
use point::Point;

//TODO: Copy? (s needs to be removed first)
#[derive(Clone, Debug, RustcDecodable, RustcEncodable)]
pub struct Board5 {
    grid: [ [u16; 5]; 5],
    continuations: [u16; 7],
    s: Square, // This is just a stupid hack for compilation - 4/23/16

}

impl fmt::Display for Board5 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Not Implemented")
    }
}

impl Board for Board5 {
    fn new(board_size: usize) -> Board5 {
        assert!(board_size == 5);
        Board5 {
            grid: [[0; 5]; 5],
            continuations: [0; 7],
            s: Square::new(),
        }
    }

    fn at(&self, point: &Point) -> Result<&Square, &str> {
        Err("Not implemented")
    }

    fn at_mut(&mut self, point: &Point) -> Result<&mut Square, &str> {
        Err("Not implemented")
    }

    fn at_reset(&mut self, point: &Point) -> Result<Square, &str> {
        Err("Not implemented")
    }

    fn size(&self) -> usize {
        self.grid.len()
    }

    fn squares(&self) -> Vec<&Square> {
        vec![&self.s]
    }

    /// Checks to see if all spaces have at least one piece
    fn full(&self) -> bool {
        false
    }

    fn place_piece(&mut self, point: &Point, piece: Piece) -> Result<(), String> {
        if self.grid[point.x][point.y].bits(16..13) == 0 {
            self.grid[point.x][point.y] = (piece.to3bits() as u16) << 13;
            Ok(())
        } else {
            return Err("Cannot place stone on top of existing stone.".into());
        }
    }

    fn add_piece(&mut self, point: &Point, piece: Piece) -> Result<(), String> {
        Err("Not implemented".into())
    }

    fn used_up(&self, piece: &Piece) -> bool {
        false
    }

    fn follow(&self,
              starts: &mut VecDeque<Point>,
              player: Player)
              -> BTreeSet<Point> {
        BTreeSet::new()
    }
}

impl FromStr for Board5 {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Board5::new(5))
    }
}
<commit_msg>Implement size and full properly for Board5<commit_after>use std::collections::VecDeque;
use std::collections::BTreeSet;
use std::str::FromStr;
use std::fmt;
use twiddle::Twiddle;

use board::Board;
use board::Square;
use piece::Piece;
use piece::Player;
use piece;
use point::Point;

//TODO: Copy? (s needs to be removed first)
#[derive(Clone, Debug, RustcDecodable, RustcEncodable)]
pub struct Board5 {
    grid: [ [u16; 5]; 5],
    continuations: [u16; 7],
    s: Square, // This is just a stupid hack for compilation - 4/23/16

}

impl fmt::Display for Board5 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Not Implemented")
    }
}

impl Board for Board5 {
    fn new(board_size: usize) -> Board5 {
        assert!(board_size == 5);
        Board5 {
            grid: [[0; 5]; 5],
            continuations: [0; 7],
            s: Square::new(),
        }
    }

    fn at(&self, point: &Point) -> Result<&Square, &str> {
        Err("Not implemented")
    }

    fn at_mut(&mut self, point: &Point) -> Result<&mut Square, &str> {
        Err("Not implemented")
    }

    fn at_reset(&mut self, point: &Point) -> Result<Square, &str> {
        Err("Not implemented")
    }

    fn size(&self) -> usize {
        5
    }

    fn squares(&self) -> Vec<&Square> {
        vec![&self.s]
    }

    /// Checks to see if all spaces have at least one piece
    fn full(&self) -> bool {
        for row in self.grid.iter() {
            for square in row.iter() {
                if square.bits(16..13) == 0 {
                    return false
                }
            }
        }
        true
    }

    fn place_piece(&mut self, point: &Point, piece: Piece) -> Result<(), String> {
        if self.grid[point.x][point.y].bits(16..13) == 0 {
            self.grid[point.x][point.y] = (piece.to3bits() as u16) << 13;
            Ok(())
        } else {
            return Err("Cannot place stone on top of existing stone.".into());
        }
    }

    fn add_piece(&mut self, point: &Point, piece: Piece) -> Result<(), String> {
        Err("Not implemented".into())
    }

    fn used_up(&self, piece: &Piece) -> bool {
        false
    }

    fn follow(&self,
              starts: &mut VecDeque<Point>,
              player: Player)
              -> BTreeSet<Point> {
        BTreeSet::new()
    }
}

impl FromStr for Board5 {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Board5::new(5))
    }
}
<|endoftext|>


<commit_before>use serde::{Deserialize, Serialize};
use serde_with::{serde_as, CommaSeparator, DisplayFromStr, StringWithSeparator, TryFromInto};
use shakmaty::{san::SanPlus, uci::Uci, ByColor, Color};

use crate::{
    model::{
        GameId, GameInfo, GameInfoPlayer, MasterGame, Mode, Month, RatingGroup, Speed, Stats,
        UserName, Year,
    },
    opening::Opening,
    util::ByColorDef,
};

mod error;
mod fen;
mod nd_json;
mod variant;

pub use error::Error;
pub use fen::LaxFen;
pub use nd_json::NdJson;
pub use variant::LilaVariant;

#[serde_as]
#[derive(Deserialize, Debug)]
pub struct MasterQuery {
    #[serde_as(as = "Option<DisplayFromStr>")]
    #[serde(default)]
    pub fen: Option<LaxFen>,
    #[serde_as(as = "StringWithSeparator<CommaSeparator, Uci>")]
    #[serde(default)]
    pub play: Vec<Uci>,
    #[serde_as(as = "TryFromInto<u16>")]
    #[serde(default)]
    pub since: Year,
    #[serde_as(as = "TryFromInto<u16>")]
    #[serde(default = "Year::max_value")]
    pub until: Year,
    #[serde(flatten)]
    pub limits: Limits,
}

#[serde_as]
#[derive(Deserialize, Debug)]
pub struct LichessQuery {
    #[serde(default)]
    pub variant: LilaVariant,
    #[serde_as(as = "Option<DisplayFromStr>")]
    #[serde(default)]
    pub fen: Option<LaxFen>,
    #[serde_as(as = "StringWithSeparator<CommaSeparator, Uci>")]
    #[serde(default)]
    pub play: Vec<Uci>,
    #[serde(flatten)]
    pub limits: Limits,
    #[serde_as(as = "Option<StringWithSeparator<CommaSeparator, Speed>>")]
    #[serde(default)]
    pub speeds: Option<Vec<Speed>>,
    #[serde_as(as = "Option<StringWithSeparator<CommaSeparator, RatingGroup>>")]
    #[serde(default)]
    pub ratings: Option<Vec<RatingGroup>>,
    #[serde_as(as = "DisplayFromStr")]
    #[serde(default)]
    pub since: Month,
    #[serde_as(as = "DisplayFromStr")]
    #[serde(default = "Month::max_value")]
    pub until: Month,
}

#[serde_as]
#[derive(Deserialize, Debug)]
pub struct PersonalQuery {
    #[serde(default)]
    pub variant: LilaVariant,
    #[serde_as(as = "Option<DisplayFromStr>")]
    #[serde(default)]
    pub fen: Option<LaxFen>,
    #[serde_as(as = "StringWithSeparator<CommaSeparator, Uci>")]
    #[serde(default)]
    pub play: Vec<Uci>,
    #[serde_as(as = "DisplayFromStr")]
    pub player: UserName,
    #[serde_as(as = "DisplayFromStr")]
    pub color: Color,
    #[serde(flatten)]
    pub filter: PersonalQueryFilter,
    #[serde(flatten)]
    pub limits: Limits,
}

#[serde_as]
#[derive(Deserialize, Debug)]
pub struct PersonalQueryFilter {
    #[serde_as(as = "Option<StringWithSeparator<CommaSeparator, Mode>>")]
    #[serde(default)]
    pub modes: Option<Vec<Mode>>,
    #[serde_as(as = "Option<StringWithSeparator<CommaSeparator, Speed>>")]
    #[serde(default)]
    pub speeds: Option<Vec<Speed>>,
    #[serde_as(as = "DisplayFromStr")]
    #[serde(default)]
    pub since: Month,
    #[serde_as(as = "DisplayFromStr")]
    #[serde(default = "Month::max_value")]
    pub until: Month,
}

#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Limits {
    #[serde(default = "usize::max_value")]
    pub top_games: usize,
    #[serde(default = "usize::max_value")]
    pub recent_games: usize,
    #[serde(default)]
    pub moves: Option<usize>,
}

#[serde_as]
#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ExplorerResponse {
    #[serde(flatten)]
    pub total: Stats,
    pub moves: Vec<ExplorerMove>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub recent_games: Option<Vec<ExplorerGameWithUci>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub top_games: Option<Vec<ExplorerGameWithUci>>,
    pub opening: Option<&'static Opening>,
}

#[serde_as]
#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ExplorerMove {
    #[serde_as(as = "DisplayFromStr")]
    pub uci: Uci,
    #[serde_as(as = "DisplayFromStr")]
    pub san: SanPlus,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub average_rating: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub average_opponent_rating: Option<u64>,
    #[serde(flatten)]
    pub stats: Stats,
    pub game: Option<ExplorerGame>,
}

#[serde_as]
#[derive(Serialize, Debug)]
pub struct ExplorerGameWithUci {
    #[serde_as(as = "DisplayFromStr")]
    pub uci: Uci,
    #[serde(flatten)]
    pub row: ExplorerGame,
}

#[serde_as]
#[derive(Serialize, Debug)]
pub struct ExplorerGame {
    #[serde_as(as = "DisplayFromStr")]
    pub id: GameId,
    #[serde_as(as = "Option<DisplayFromStr>")]
    pub winner: Option<Color>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub speed: Option<Speed>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub mode: Option<Mode>,
    #[serde(flatten, with = "ByColorDef")]
    pub players: ByColor<GameInfoPlayer>,
    #[serde_as(as = "TryFromInto<u16>")]
    pub year: Year,
    #[serde_as(as = "Option<DisplayFromStr>")]
    pub month: Option<Month>,
}

impl ExplorerGame {
    pub fn from_lichess(id: GameId, info: GameInfo) -> ExplorerGame {
        ExplorerGame {
            id,
            winner: info.outcome.winner(),
            speed: Some(info.speed),
            mode: Some(info.mode),
            players: info.players,
            year: info.month.year(),
            month: Some(info.month),
        }
    }

    pub fn from_master(id: GameId, info: MasterGame) -> ExplorerGame {
        ExplorerGame {
            id,
            winner: info.winner,
            speed: None,
            mode: None,
            players: info.players,
            year: info.date.year(),
            month: info.date.month(),
        }
    }
}
<commit_msg>fix parsing integers from query string<commit_after>use serde::{Deserialize, Serialize};
use serde_with::{serde_as, CommaSeparator, DisplayFromStr, StringWithSeparator, TryFromInto};
use shakmaty::{san::SanPlus, uci::Uci, ByColor, Color};

use crate::{
    model::{
        GameId, GameInfo, GameInfoPlayer, MasterGame, Mode, Month, RatingGroup, Speed, Stats,
        UserName, Year,
    },
    opening::Opening,
    util::ByColorDef,
};

mod error;
mod fen;
mod nd_json;
mod variant;

pub use error::Error;
pub use fen::LaxFen;
pub use nd_json::NdJson;
pub use variant::LilaVariant;

#[serde_as]
#[derive(Deserialize, Debug)]
pub struct MasterQuery {
    #[serde_as(as = "Option<DisplayFromStr>")]
    #[serde(default)]
    pub fen: Option<LaxFen>,
    #[serde_as(as = "StringWithSeparator<CommaSeparator, Uci>")]
    #[serde(default)]
    pub play: Vec<Uci>,
    #[serde_as(as = "TryFromInto<u16>")]
    #[serde(default)]
    pub since: Year,
    #[serde_as(as = "TryFromInto<u16>")]
    #[serde(default = "Year::max_value")]
    pub until: Year,
    #[serde(flatten)]
    pub limits: Limits,
}

#[serde_as]
#[derive(Deserialize, Debug)]
pub struct LichessQuery {
    #[serde(default)]
    pub variant: LilaVariant,
    #[serde_as(as = "Option<DisplayFromStr>")]
    #[serde(default)]
    pub fen: Option<LaxFen>,
    #[serde_as(as = "StringWithSeparator<CommaSeparator, Uci>")]
    #[serde(default)]
    pub play: Vec<Uci>,
    #[serde(flatten)]
    pub limits: Limits,
    #[serde_as(as = "Option<StringWithSeparator<CommaSeparator, Speed>>")]
    #[serde(default)]
    pub speeds: Option<Vec<Speed>>,
    #[serde_as(as = "Option<StringWithSeparator<CommaSeparator, RatingGroup>>")]
    #[serde(default)]
    pub ratings: Option<Vec<RatingGroup>>,
    #[serde_as(as = "DisplayFromStr")]
    #[serde(default)]
    pub since: Month,
    #[serde_as(as = "DisplayFromStr")]
    #[serde(default = "Month::max_value")]
    pub until: Month,
}

#[serde_as]
#[derive(Deserialize, Debug)]
pub struct PersonalQuery {
    #[serde(default)]
    pub variant: LilaVariant,
    #[serde_as(as = "Option<DisplayFromStr>")]
    #[serde(default)]
    pub fen: Option<LaxFen>,
    #[serde_as(as = "StringWithSeparator<CommaSeparator, Uci>")]
    #[serde(default)]
    pub play: Vec<Uci>,
    #[serde_as(as = "DisplayFromStr")]
    pub player: UserName,
    #[serde_as(as = "DisplayFromStr")]
    pub color: Color,
    #[serde(flatten)]
    pub filter: PersonalQueryFilter,
    #[serde(flatten)]
    pub limits: Limits,
}

#[serde_as]
#[derive(Deserialize, Debug)]
pub struct PersonalQueryFilter {
    #[serde_as(as = "Option<StringWithSeparator<CommaSeparator, Mode>>")]
    #[serde(default)]
    pub modes: Option<Vec<Mode>>,
    #[serde_as(as = "Option<StringWithSeparator<CommaSeparator, Speed>>")]
    #[serde(default)]
    pub speeds: Option<Vec<Speed>>,
    #[serde_as(as = "DisplayFromStr")]
    #[serde(default)]
    pub since: Month,
    #[serde_as(as = "DisplayFromStr")]
    #[serde(default = "Month::max_value")]
    pub until: Month,
}

#[serde_as]
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Limits {
    #[serde_as(as = "DisplayFromStr")]
    #[serde(default = "usize::max_value")]
    pub top_games: usize,
    #[serde_as(as = "DisplayFromStr")]
    #[serde(default = "usize::max_value")]
    pub recent_games: usize,
    #[serde_as(as = "Option<DisplayFromStr>")]
    #[serde(default)]
    pub moves: Option<usize>,
}

#[serde_as]
#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ExplorerResponse {
    #[serde(flatten)]
    pub total: Stats,
    pub moves: Vec<ExplorerMove>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub recent_games: Option<Vec<ExplorerGameWithUci>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub top_games: Option<Vec<ExplorerGameWithUci>>,
    pub opening: Option<&'static Opening>,
}

#[serde_as]
#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ExplorerMove {
    #[serde_as(as = "DisplayFromStr")]
    pub uci: Uci,
    #[serde_as(as = "DisplayFromStr")]
    pub san: SanPlus,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub average_rating: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub average_opponent_rating: Option<u64>,
    #[serde(flatten)]
    pub stats: Stats,
    pub game: Option<ExplorerGame>,
}

#[serde_as]
#[derive(Serialize, Debug)]
pub struct ExplorerGameWithUci {
    #[serde_as(as = "DisplayFromStr")]
    pub uci: Uci,
    #[serde(flatten)]
    pub row: ExplorerGame,
}

#[serde_as]
#[derive(Serialize, Debug)]
pub struct ExplorerGame {
    #[serde_as(as = "DisplayFromStr")]
    pub id: GameId,
    #[serde_as(as = "Option<DisplayFromStr>")]
    pub winner: Option<Color>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub speed: Option<Speed>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub mode: Option<Mode>,
    #[serde(flatten, with = "ByColorDef")]
    pub players: ByColor<GameInfoPlayer>,
    #[serde_as(as = "TryFromInto<u16>")]
    pub year: Year,
    #[serde_as(as = "Option<DisplayFromStr>")]
    pub month: Option<Month>,
}

impl ExplorerGame {
    pub fn from_lichess(id: GameId, info: GameInfo) -> ExplorerGame {
        ExplorerGame {
            id,
            winner: info.outcome.winner(),
            speed: Some(info.speed),
            mode: Some(info.mode),
            players: info.players,
            year: info.month.year(),
            month: Some(info.month),
        }
    }

    pub fn from_master(id: GameId, info: MasterGame) -> ExplorerGame {
        ExplorerGame {
            id,
            winner: info.winner,
            speed: None,
            mode: None,
            players: info.players,
            year: info.date.year(),
            month: info.date.month(),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use capnp::{any_pointer};
use capnp::Error;
use capnp::private::capability::{ClientHook, ParamsHook, PipelineHook, PipelineOp,
                                 RequestHook, ResultsHook, ResultsDoneHook};

use gj::{Promise};

use std::rc::{Rc};

pub struct Pipeline {
    error: Error,
}

impl Pipeline {
    pub fn new(error: Error) -> Pipeline {
        Pipeline {
            error: error
        }
    }
}

impl PipelineHook for Pipeline {
    fn add_ref(&self) -> Box<PipelineHook> {
        Box::new(Pipeline::new(self.error.clone()))
    }
    fn get_pipelined_cap(&self, _ops: &[PipelineOp]) -> Box<ClientHook> {
        new_cap(self.error.clone())
    }
}

pub struct Request {
    error: Error,
    message: ::capnp::message::Builder<::capnp::message::HeapAllocator>,
}

impl Request {
    pub fn new(error: Error, _size_hint: Option<::capnp::MessageSize>) -> Request {
        Request {
            error: error,
            message: ::capnp::message::Builder::new_default(),
        }
    }
}

impl RequestHook for Request {
    fn get<'a>(&'a mut self) -> any_pointer::Builder<'a> {
        self.message.get_root().unwrap()
    }
    fn get_brand(&self) -> usize {
        0
    }
    fn send<'a>(self: Box<Self>) -> ::capnp::capability::RemotePromise<any_pointer::Owned> {
        let pipeline = Pipeline::new(self.error.clone());
        ::capnp::capability::RemotePromise {
            promise: Promise::err(self.error),
            pipeline: any_pointer::Pipeline::new(Box::new(pipeline)),
        }
    }
    fn tail_send(self: Box<Self>)
                 -> Option<(u32, Promise<(), Error>, Box<PipelineHook>)>
    {
        None
    }
}

struct ClientInner {
    error: Error,
    _resolved: bool,
    brand: usize,
}

pub struct Client {
    inner: Rc<ClientInner>,
}

impl Client {
    pub fn new(error: Error, resolved: bool, brand: usize) -> Client {
        Client {
            inner: Rc::new(ClientInner {
                error: error,
                _resolved: resolved,
                brand: brand,
            }),
        }
    }
}

impl ClientHook for Client {
    fn add_ref(&self) -> Box<ClientHook> {
        Box::new(Client { inner: self.inner.clone() } )
    }
    fn new_call(&self, _interface_id: u64, _method_id: u16,
                size_hint: Option<::capnp::MessageSize>)
                -> ::capnp::capability::Request<any_pointer::Owned, any_pointer::Owned>
    {
        ::capnp::capability::Request::new(
            Box::new(Request::new(self.inner.error.clone(), size_hint)))
    }

    fn call(&self, _interface_id: u64, _method_id: u16, _params: Box<ParamsHook>,
            _results: Box<ResultsHook>,
            _results_done: Promise<Box<ResultsDoneHook>, Error>)
        -> (Promise<(), Error>, Box<PipelineHook>)
    {
        (Promise::err(self.inner.error.clone()),
         Box::new(Pipeline::new(self.inner.error.clone())))
    }

    fn get_ptr(&self) -> usize {
        unimplemented!()
    }

    fn get_brand(&self) -> usize {
        self.inner.brand
    }

    fn get_resolved(&self) -> Option<Box<ClientHook>> {
        None
    }

    fn when_more_resolved(&self) -> Option<::gj::Promise<Box<ClientHook>, Error>> {
        None
    }
}

pub fn new_cap(exception: Error) -> Box<ClientHook> {
    Box::new(Client::new(exception, false, 0))
}
<commit_msg>implement broken::Client::as_ptr()<commit_after>// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use capnp::{any_pointer};
use capnp::Error;
use capnp::private::capability::{ClientHook, ParamsHook, PipelineHook, PipelineOp,
                                 RequestHook, ResultsHook, ResultsDoneHook};

use gj::{Promise};

use std::rc::{Rc};

pub struct Pipeline {
    error: Error,
}

impl Pipeline {
    pub fn new(error: Error) -> Pipeline {
        Pipeline {
            error: error
        }
    }
}

impl PipelineHook for Pipeline {
    fn add_ref(&self) -> Box<PipelineHook> {
        Box::new(Pipeline::new(self.error.clone()))
    }
    fn get_pipelined_cap(&self, _ops: &[PipelineOp]) -> Box<ClientHook> {
        new_cap(self.error.clone())
    }
}

pub struct Request {
    error: Error,
    message: ::capnp::message::Builder<::capnp::message::HeapAllocator>,
}

impl Request {
    pub fn new(error: Error, _size_hint: Option<::capnp::MessageSize>) -> Request {
        Request {
            error: error,
            message: ::capnp::message::Builder::new_default(),
        }
    }
}

impl RequestHook for Request {
    fn get<'a>(&'a mut self) -> any_pointer::Builder<'a> {
        self.message.get_root().unwrap()
    }
    fn get_brand(&self) -> usize {
        0
    }
    fn send<'a>(self: Box<Self>) -> ::capnp::capability::RemotePromise<any_pointer::Owned> {
        let pipeline = Pipeline::new(self.error.clone());
        ::capnp::capability::RemotePromise {
            promise: Promise::err(self.error),
            pipeline: any_pointer::Pipeline::new(Box::new(pipeline)),
        }
    }
    fn tail_send(self: Box<Self>)
                 -> Option<(u32, Promise<(), Error>, Box<PipelineHook>)>
    {
        None
    }
}

struct ClientInner {
    error: Error,
    _resolved: bool,
    brand: usize,
}

pub struct Client {
    inner: Rc<ClientInner>,
}

impl Client {
    pub fn new(error: Error, resolved: bool, brand: usize) -> Client {
        Client {
            inner: Rc::new(ClientInner {
                error: error,
                _resolved: resolved,
                brand: brand,
            }),
        }
    }
}

impl ClientHook for Client {
    fn add_ref(&self) -> Box<ClientHook> {
        Box::new(Client { inner: self.inner.clone() } )
    }
    fn new_call(&self, _interface_id: u64, _method_id: u16,
                size_hint: Option<::capnp::MessageSize>)
                -> ::capnp::capability::Request<any_pointer::Owned, any_pointer::Owned>
    {
        ::capnp::capability::Request::new(
            Box::new(Request::new(self.inner.error.clone(), size_hint)))
    }

    fn call(&self, _interface_id: u64, _method_id: u16, _params: Box<ParamsHook>,
            _results: Box<ResultsHook>,
            _results_done: Promise<Box<ResultsDoneHook>, Error>)
        -> (Promise<(), Error>, Box<PipelineHook>)
    {
        (Promise::err(self.inner.error.clone()),
         Box::new(Pipeline::new(self.inner.error.clone())))
    }

    fn get_ptr(&self) -> usize {
        (self.inner.as_ref()) as * const _ as usize
    }

    fn get_brand(&self) -> usize {
        self.inner.brand
    }

    fn get_resolved(&self) -> Option<Box<ClientHook>> {
        None
    }

    fn when_more_resolved(&self) -> Option<::gj::Promise<Box<ClientHook>, Error>> {
        None
    }
}

pub fn new_cap(exception: Error) -> Box<ClientHook> {
    Box::new(Client::new(exception, false, 0))
}
<|endoftext|>


<commit_before>use crate::{generate::*, inner::*, norm::Norm, types::*};
use ndarray::*;

#[derive(Debug, Clone)]
pub struct MGS<A> {
    dim: usize,
    q: Vec<Array1<A>>,
    r: Vec<Array1<A>>,
}

impl<A: Scalar + Lapack> MGS<A> {
    pub fn new(dim: usize) -> Self {
        Self {
            dim,
            q: Vec::new(),
            r: Vec::new(),
        }
    }

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

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

    pub fn append<S>(&mut self, a: ArrayBase<S, Ix1>) -> A::Real
    where
        S: Data<Elem = A>,
    {
        assert_eq!(a.len(), self.dim());
        let mut a = a.into_owned();
        let mut coef = Array1::zeros(self.len() + 1);
        for i in 0..self.len() {
            let q = &self.q[i];
            let c = q.inner(&a);
            azip!(mut a, q (q) in { *a = *a - c * q } );
            coef[i] = c;
        }
        let nrm = a.norm_l2();
        coef[self.len()] = A::from_real(nrm);
        self.r.push(coef);
        azip!(mut a in { *a = *a / A::from_real(nrm) });
        self.q.push(a);
        nrm
    }

    /// Get orthogonal basis as Q matrix
    pub fn get_q(&self) -> Array2<A> {
        hstack(&self.q).unwrap()
    }

    /// Get each vector norm and coefficients as R matrix
    pub fn get_r(&self) -> Array2<A> {
        let len = self.len();
        let mut r = Array2::zeros((len, len));
        for i in 0..len {
            for j in 0..=i {
                r[(j, i)] = self.r[i][j];
            }
        }
        r
    }
}

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

    const N: usize = 5;

    #[test]
    fn new() {
        let mgs: MGS<f32> = MGS::new(N);
        assert_eq!(mgs.dim(), N);
        assert_eq!(mgs.len(), 0);
    }

    fn test<A: Scalar + Lapack>(rtol: A::Real) {
        let mut mgs: MGS<A> = MGS::new(N);
        let a: Array2<A> = crate::generate::random((N, 3));
        dbg!(&a);
        for col in a.axis_iter(Axis(1)) {
            let res = mgs.append(col);
            dbg!(res);
        }
        let q = mgs.get_q();
        dbg!(&q);
        let r = mgs.get_r();
        dbg!(&r);

        dbg!(q.dot(&r));
        close_l2(&q.dot(&r), &a, rtol).unwrap();

        let qt: Array2<_> = conjugate(&q);
        dbg!(qt.dot(&q));
        close_l2(&qt.dot(&q), &Array2::eye(3), rtol).unwrap();
    }

    #[test]
    fn test_f32() {
        test::<f32>(1e-5);
    }

    #[test]
    fn test_c32() {
        test::<c32>(1e-5);
    }

    #[test]
    fn test_f64() {
        test::<f64>(1e-9);
    }

    #[test]
    fn test_c64() {
        test::<c64>(1e-9);
    }
}
<commit_msg>append_if<commit_after>use crate::{generate::*, inner::*, norm::Norm, types::*};
use ndarray::*;
use num_traits::Zero;

#[derive(Debug, Clone)]
pub struct MGS<A> {
    dim: usize,
    q: Vec<Array1<A>>,
    r: Vec<Array1<A>>,
}

pub enum Dependence<A: Scalar> {
    Orthogonal(A::Real),
    Coefficient(Array1<A>),
}

impl<A: Scalar + Lapack> MGS<A> {
    pub fn new(dim: usize) -> Self {
        Self {
            dim,
            q: Vec::new(),
            r: Vec::new(),
        }
    }

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

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

    /// Add new vector, return residual norm
    pub fn append<S>(&mut self, a: ArrayBase<S, Ix1>) -> A::Real
    where
        S: Data<Elem = A>,
    {
        self.append_if(a, A::Real::zero()).unwrap()
    }

    /// Add new vector if the residual is larger than relative tolerance
    pub fn append_if<S>(&mut self, a: ArrayBase<S, Ix1>, rtol: A::Real) -> Option<A::Real>
    where
        S: Data<Elem = A>,
    {
        assert_eq!(a.len(), self.dim());
        let mut a = a.into_owned();
        let mut coef = Array1::zeros(self.len() + 1);
        for i in 0..self.len() {
            let q = &self.q[i];
            let c = q.inner(&a);
            azip!(mut a, q (q) in { *a = *a - c * q } );
            coef[i] = c;
        }
        let nrm = a.norm_l2();
        if nrm < rtol {
            return None;
        }
        coef[self.len()] = A::from_real(nrm);
        self.r.push(coef);
        azip!(mut a in { *a = *a / A::from_real(nrm) });
        self.q.push(a);
        Some(nrm)
    }

    /// Get orthogonal basis as Q matrix
    pub fn get_q(&self) -> Array2<A> {
        hstack(&self.q).unwrap()
    }

    /// Get each vector norm and coefficients as R matrix
    pub fn get_r(&self) -> Array2<A> {
        let len = self.len();
        let mut r = Array2::zeros((len, len));
        for i in 0..len {
            for j in 0..=i {
                r[(j, i)] = self.r[i][j];
            }
        }
        r
    }
}

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

    const N: usize = 5;

    #[test]
    fn new() {
        let mgs: MGS<f32> = MGS::new(N);
        assert_eq!(mgs.dim(), N);
        assert_eq!(mgs.len(), 0);
    }

    fn test_append<A: Scalar + Lapack>(rtol: A::Real) {
        let mut mgs: MGS<A> = MGS::new(N);
        let a: Array2<A> = crate::generate::random((N, 3));
        dbg!(&a);
        for col in a.axis_iter(Axis(1)) {
            let res = mgs.append(col);
            dbg!(res);
        }
        let q = mgs.get_q();
        dbg!(&q);
        let r = mgs.get_r();
        dbg!(&r);

        dbg!(q.dot(&r));
        close_l2(&q.dot(&r), &a, rtol).unwrap();

        let qt: Array2<_> = conjugate(&q);
        dbg!(qt.dot(&q));
        close_l2(&qt.dot(&q), &Array2::eye(3), rtol).unwrap();
    }

    #[test]
    fn append() {
        test_append::<f32>(1e-5);
        test_append::<c32>(1e-5);
        test_append::<f64>(1e-9);
        test_append::<c64>(1e-9);
    }

    fn test_append_if<A: Scalar + Lapack>(rtol: A::Real) {
        let mut mgs: MGS<A> = MGS::new(N);
        let a: Array2<A> = crate::generate::random((N, 8));
        dbg!(&a);
        for col in a.axis_iter(Axis(1)) {
            match mgs.append_if(col, rtol) {
                Some(res) => {
                    dbg!(res);
                }
                None => break,
            }
        }
        let q = mgs.get_q();
        dbg!(&q);
        let r = mgs.get_r();
        dbg!(&r);

        dbg!(q.dot(&r));
        close_l2(&q.dot(&r), &a.slice(s![.., 0..N]), rtol).unwrap();

        let qt: Array2<_> = conjugate(&q);
        dbg!(qt.dot(&q));
        close_l2(&qt.dot(&q), &Array2::eye(N), rtol).unwrap();
    }

    #[test]
    fn append_if() {
        test_append_if::<f32>(1e-5);
        test_append_if::<c32>(1e-5);
        test_append_if::<f64>(1e-9);
        test_append_if::<c64>(1e-9);
    }
}
<|endoftext|>


<commit_before>use libc;
use std;
use std::ffi::CString;
use std::io::{Error, ErrorKind};

#[derive(Debug)]
pub struct Buffer {
    buf: *mut libc::c_char,
    offset: isize,
    buflen: libc::size_t,
}

impl Buffer {
    pub fn new(buf: *mut libc::c_char, buflen: libc::size_t) -> Self { Self { buf, offset: 0, buflen } }

    fn write(&mut self, data: *const libc::c_char, len: usize) -> Result<*mut libc::c_char, Error> {
        if self.buflen < len + self.offset as libc::size_t {
            return Err(Error::new(ErrorKind::AddrNotAvailable, "ERANGE"));
        }
        unsafe {
            let pos = self.buf.offset(self.offset);
            std::ptr::copy(data as *mut i8, pos as *mut i8, len);
            self.offset += len as isize;
            self.buflen -= len as libc::size_t;
            Ok(pos)
        }
    }

    fn add_pointers(&mut self, ptrs: &Vec<*mut libc::c_char>) -> Result<*mut *mut libc::c_char, Error> {
        use std::mem::size_of;
        let step = std::cmp::max(size_of::<*mut libc::c_char>() / size_of::<libc::c_char>(), 1);
        if self.buflen < (((ptrs.len() + 1) * step) as isize + self.offset) as libc::size_t {
            return Err(Error::new(ErrorKind::AddrNotAvailable, "ERANGE"));
        }
        unsafe {
            let mem = self.buf.offset(self.offset) as *mut *mut libc::c_char;
            for (i, p) in ptrs.iter().enumerate() {
                *(mem.offset(i as isize)) = *p;
                self.offset += step as isize;
                self.buflen -= step as libc::size_t;
            }
            *(mem.offset(ptrs.len() as isize)) = std::ptr::null_mut::<libc::c_char>();
            self.offset += step as isize;
            self.buflen -= step as libc::size_t;
            Ok(mem)
        }
    }

    pub fn write_string(&mut self, s: &str) -> Result<*mut libc::c_char, Error> {
        let cs = CString::new(s).unwrap();
        self.write(cs.as_ptr(), s.len() + 1)
    }

    pub fn write_vecstr(&mut self, ss: &Vec<&str>) -> Result<*mut *mut libc::c_char, Error> {
        let mut ptrs = Vec::<*mut libc::c_char>::new();
        for s in ss {
            ptrs.push(self.write_string(s)?);
        }
        self.add_pointers(&ptrs)
    }
}
<commit_msg>Use pointer::add instead of pointer::offset<commit_after>use libc;
use std;
use std::ffi::CString;
use std::io::{Error, ErrorKind};

#[derive(Debug)]
pub struct Buffer {
    buf: *mut libc::c_char,
    offset: isize,
    buflen: libc::size_t,
}

impl Buffer {
    pub fn new(buf: *mut libc::c_char, buflen: libc::size_t) -> Self { Self { buf, offset: 0, buflen } }

    fn write(&mut self, data: *const libc::c_char, len: usize) -> Result<*mut libc::c_char, Error> {
        if self.buflen < len + self.offset as libc::size_t {
            return Err(Error::new(ErrorKind::AddrNotAvailable, "ERANGE"));
        }
        unsafe {
            let pos = self.buf.offset(self.offset);
            std::ptr::copy(data as *mut i8, pos as *mut i8, len);
            self.offset += len as isize;
            self.buflen -= len as libc::size_t;
            Ok(pos)
        }
    }

    fn add_pointers(&mut self, ptrs: &Vec<*mut libc::c_char>) -> Result<*mut *mut libc::c_char, Error> {
        use std::mem::size_of;
        let step = std::cmp::max(size_of::<*mut libc::c_char>() / size_of::<libc::c_char>(), 1);
        if self.buflen < (((ptrs.len() + 1) * step) as isize + self.offset) as libc::size_t {
            return Err(Error::new(ErrorKind::AddrNotAvailable, "ERANGE"));
        }
        unsafe {
            let mem = self.buf.offset(self.offset) as *mut *mut libc::c_char;
            for (i, p) in ptrs.iter().enumerate() {
                *(mem.add(i)) = *p;
                self.offset += step as isize;
                self.buflen -= step as libc::size_t;
            }
            *(mem.add(ptrs.len())) = std::ptr::null_mut::<libc::c_char>();
            self.offset += step as isize;
            self.buflen -= step as libc::size_t;
            Ok(mem)
        }
    }

    pub fn write_string(&mut self, s: &str) -> Result<*mut libc::c_char, Error> {
        let cs = CString::new(s).unwrap();
        self.write(cs.as_ptr(), s.len() + 1)
    }

    pub fn write_vecstr(&mut self, ss: &Vec<&str>) -> Result<*mut *mut libc::c_char, Error> {
        let mut ptrs = Vec::<*mut libc::c_char>::new();
        for s in ss {
            ptrs.push(self.write_string(s)?);
        }
        self.add_pointers(&ptrs)
    }
}
<|endoftext|>


<commit_before>//! A stably addressed token buffer supporting efficient traversal based on a
//! cheaply copyable cursor.
//!
//! *This module is available only if Syn is built with the `"parsing"` feature.*

// This module is heavily commented as it contains most of the unsafe code in
// Syn, and caution should be used when editing it. The public-facing interface
// is 100% safe but the implementation is fragile internally.

#[cfg(all(
    not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
    feature = "proc-macro"
))]
use crate::proc_macro as pm;
use crate::Lifetime;
use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
use std::marker::PhantomData;

/// Internal type which is used instead of `TokenTree` to represent a token tree
/// within a `TokenBuffer`.
enum Entry {
    // Mimicking types from proc-macro.
    // Group entries contain the offset to the matching End entry.
    Group(Group, usize),
    Ident(Ident),
    Punct(Punct),
    Literal(Literal),
    End,
}

/// A buffer that can be efficiently traversed multiple times, unlike
/// `TokenStream` which requires a deep copy in order to traverse more than
/// once.
///
/// *This type is available only if Syn is built with the `"parsing"` feature.*
pub struct TokenBuffer {
    // NOTE: Do not implement clone on this - while the current design could be
    // cloned, other designs which could be desirable may not be cloneable.
    entries: Box<[Entry]>,
}

impl TokenBuffer {
    fn new_inner(entries: &mut Vec<Entry>, stream: TokenStream) {
        for tt in stream {
            match tt {
                TokenTree::Ident(ident) => entries.push(Entry::Ident(ident)),
                TokenTree::Punct(punct) => entries.push(Entry::Punct(punct)),
                TokenTree::Literal(literal) => entries.push(Entry::Literal(literal)),
                TokenTree::Group(group) => {
                    let group_start_index = entries.len();
                    entries.push(Entry::End); // we replace this below
                    Self::new_inner(entries, group.stream());
                    let group_end_index = entries.len();
                    entries.push(Entry::End);
                    let group_end_offset = group_end_index - group_start_index;
                    entries[group_start_index] = Entry::Group(group, group_end_offset);
                }
            }
        }
    }

    /// Creates a `TokenBuffer` containing all the tokens from the input
    /// `proc_macro::TokenStream`.
    ///
    /// *This method is available only if Syn is built with both the `"parsing"` and
    /// `"proc-macro"` features.*
    #[cfg(all(
        not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
        feature = "proc-macro"
    ))]
    pub fn new(stream: pm::TokenStream) -> Self {
        Self::new2(stream.into())
    }

    /// Creates a `TokenBuffer` containing all the tokens from the input
    /// `proc_macro2::TokenStream`.
    pub fn new2(stream: TokenStream) -> Self {
        let mut entries = Vec::new();
        Self::new_inner(&mut entries, stream);
        entries.push(Entry::End);
        Self {
            entries: entries.into_boxed_slice(),
        }
    }

    /// Creates a cursor referencing the first token in the buffer and able to
    /// traverse until the end of the buffer.
    pub fn begin(&self) -> Cursor {
        let ptr = self.entries.as_ptr();
        unsafe { Cursor::create(ptr, ptr.add(self.entries.len() - 1)) }
    }
}

/// A cheaply copyable cursor into a `TokenBuffer`.
///
/// This cursor holds a shared reference into the immutable data which is used
/// internally to represent a `TokenStream`, and can be efficiently manipulated
/// and copied around.
///
/// An empty `Cursor` can be created directly, or one may create a `TokenBuffer`
/// object and get a cursor to its first token with `begin()`.
///
/// Two cursors are equal if they have the same location in the same input
/// stream, and have the same scope.
///
/// *This type is available only if Syn is built with the `"parsing"` feature.*
pub struct Cursor<'a> {
    // The current entry which the `Cursor` is pointing at.
    ptr: *const Entry,
    // This is the only `Entry::End` object which this cursor is allowed to
    // point at. All other `End` objects are skipped over in `Cursor::create`.
    scope: *const Entry,
    // Cursor is covariant in 'a. This field ensures that our pointers are still
    // valid.
    marker: PhantomData<&'a Entry>,
}

impl<'a> Cursor<'a> {
    /// Creates a cursor referencing a static empty TokenStream.
    pub fn empty() -> Self {
        // It's safe in this situation for us to put an `Entry` object in global
        // storage, despite it not actually being safe to send across threads
        // (`Ident` is a reference into a thread-local table). This is because
        // this entry never includes a `Ident` object.
        //
        // This wrapper struct allows us to break the rules and put a `Sync`
        // object in global storage.
        struct UnsafeSyncEntry(Entry);
        unsafe impl Sync for UnsafeSyncEntry {}
        static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End);

        Cursor {
            ptr: &EMPTY_ENTRY.0,
            scope: &EMPTY_ENTRY.0,
            marker: PhantomData,
        }
    }

    /// This create method intelligently exits non-explicitly-entered
    /// `None`-delimited scopes when the cursor reaches the end of them,
    /// allowing for them to be treated transparently.
    unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
        // NOTE: If we're looking at a `End`, we want to advance the cursor
        // past it, unless `ptr == scope`, which means that we're at the edge of
        // our cursor's scope. We should only have `ptr != scope` at the exit
        // from None-delimited groups entered with `ignore_none`.
        while let Entry::End = *ptr {
            if ptr == scope {
                break;
            }
            ptr = ptr.add(1);
        }

        Cursor {
            ptr,
            scope,
            marker: PhantomData,
        }
    }

    /// Get the current entry.
    fn entry(self) -> &'a Entry {
        unsafe { &*self.ptr }
    }

    /// Bump the cursor to point at the next token after the current one. This
    /// is undefined behavior if the cursor is currently looking at an
    /// `Entry::End`.
    ///
    /// If the cursor is looking at an `Entry::Group`, the bumped cursor will
    /// point at the first token in the group (with the same scope end).
    unsafe fn bump_ignore_group(self) -> Cursor<'a> {
        Cursor::create(self.ptr.offset(1), self.scope)
    }

    /// While the cursor is looking at a `None`-delimited group, move it to look
    /// at the first token inside instead. If the group is empty, this will move
    /// the cursor past the `None`-delimited group.
    ///
    /// WARNING: This mutates its argument.
    fn ignore_none(&mut self) {
        while let Entry::Group(group, _) = self.entry() {
            if group.delimiter() == Delimiter::None {
                unsafe { *self = self.bump_ignore_group() };
            } else {
                break;
            }
        }
    }

    /// Checks whether the cursor is currently pointing at the end of its valid
    /// scope.
    pub fn eof(self) -> bool {
        // We're at eof if we're at the end of our scope.
        self.ptr == self.scope
    }

    /// If the cursor is pointing at a `Group` with the given delimiter, returns
    /// a cursor into that group and one pointing to the next `TokenTree`.
    pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, Span, Cursor<'a>)> {
        // If we're not trying to enter a none-delimited group, we want to
        // ignore them. We have to make sure to _not_ ignore them when we want
        // to enter them, of course. For obvious reasons.
        if delim != Delimiter::None {
            self.ignore_none();
        }

        if let Entry::Group(group, end_offset) = self.entry() {
            if group.delimiter() == delim {
                let end_of_group = unsafe { self.ptr.add(*end_offset) };
                let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) };
                let after_group = unsafe { Cursor::create(end_of_group, self.scope) };
                return Some((inside_of_group, group.span(), after_group));
            }
        }

        None
    }

    /// If the cursor is pointing at a `Ident`, returns it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn ident(mut self) -> Option<(Ident, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Ident(ident) => Some((ident.clone(), unsafe { self.bump_ignore_group() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Punct`, returns it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Punct(punct) if punct.as_char() != '\'' => {
                Some((punct.clone(), unsafe { self.bump_ignore_group() }))
            }
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Literal`, return it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Literal(literal) => Some((literal.clone(), unsafe { self.bump_ignore_group() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Lifetime`, returns it along with a
    /// cursor pointing at the next `TokenTree`.
    pub fn lifetime(mut self) -> Option<(Lifetime, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
                let next = unsafe { self.bump_ignore_group() };
                let (ident, rest) = next.ident()?;
                let lifetime = Lifetime {
                    apostrophe: punct.span(),
                    ident,
                };
                Some((lifetime, rest))
            }
            _ => None,
        }
    }

    /// Copies all remaining tokens visible from this cursor into a
    /// `TokenStream`.
    pub fn token_stream(self) -> TokenStream {
        let mut tts = Vec::new();
        let mut cursor = self;
        while let Some((tt, rest)) = cursor.token_tree() {
            tts.push(tt);
            cursor = rest;
        }
        tts.into_iter().collect()
    }

    /// If the cursor is pointing at a `TokenTree`, returns it along with a
    /// cursor pointing at the next `TokenTree`.
    ///
    /// Returns `None` if the cursor has reached the end of its stream.
    ///
    /// This method does not treat `None`-delimited groups as transparent, and
    /// will return a `Group(None, ..)` if the cursor is looking at one.
    pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> {
        let (tree, len) = match self.entry() {
            Entry::Group(group, end_offset) => (group.clone().into(), *end_offset),
            Entry::Literal(literal) => (literal.clone().into(), 1),
            Entry::Ident(ident) => (ident.clone().into(), 1),
            Entry::Punct(punct) => (punct.clone().into(), 1),
            Entry::End => return None,
        };

        let rest = unsafe { Cursor::create(self.ptr.add(len), self.scope) };
        Some((tree, rest))
    }

    /// Returns the `Span` of the current token, or `Span::call_site()` if this
    /// cursor points to eof.
    pub fn span(self) -> Span {
        match self.entry() {
            Entry::Group(group, _) => group.span(),
            Entry::Literal(literal) => literal.span(),
            Entry::Ident(ident) => ident.span(),
            Entry::Punct(punct) => punct.span(),
            Entry::End => Span::call_site(),
        }
    }

    /// Skip over the next token without cloning it. Returns `None` if this
    /// cursor points to eof.
    ///
    /// This method treats `'lifetimes` as a single token.
    pub(crate) fn skip(self) -> Option<Cursor<'a>> {
        let len = match self.entry() {
            Entry::End => return None,

            // Treat lifetimes as a single tt for the purposes of 'skip'.
            Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
                match unsafe { &*self.ptr.add(1) } {
                    Entry::Ident(_) => 2,
                    _ => 1,
                }
            }

            Entry::Group(_, end_offset) => *end_offset,
            _ => 1,
        };

        Some(unsafe { Cursor::create(self.ptr.add(len), self.scope) })
    }
}

impl<'a> Copy for Cursor<'a> {}

impl<'a> Clone for Cursor<'a> {
    fn clone(&self) -> Self {
        *self
    }
}

impl<'a> Eq for Cursor<'a> {}

impl<'a> PartialEq for Cursor<'a> {
    fn eq(&self, other: &Self) -> bool {
        let Cursor { ptr, scope, marker } = self;
        let _ = marker;
        *ptr == other.ptr && *scope == other.scope
    }
}

pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool {
    a.scope == b.scope
}

pub(crate) fn open_span_of_group(cursor: Cursor) -> Span {
    match cursor.entry() {
        Entry::Group(group, _) => group.span_open(),
        _ => cursor.span(),
    }
}

pub(crate) fn close_span_of_group(cursor: Cursor) -> Span {
    match cursor.entry() {
        Entry::Group(group, _) => group.span_close(),
        _ => cursor.span(),
    }
}
<commit_msg>Rename TokenBuffer's recursive construction logic<commit_after>//! A stably addressed token buffer supporting efficient traversal based on a
//! cheaply copyable cursor.
//!
//! *This module is available only if Syn is built with the `"parsing"` feature.*

// This module is heavily commented as it contains most of the unsafe code in
// Syn, and caution should be used when editing it. The public-facing interface
// is 100% safe but the implementation is fragile internally.

#[cfg(all(
    not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
    feature = "proc-macro"
))]
use crate::proc_macro as pm;
use crate::Lifetime;
use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
use std::marker::PhantomData;

/// Internal type which is used instead of `TokenTree` to represent a token tree
/// within a `TokenBuffer`.
enum Entry {
    // Mimicking types from proc-macro.
    // Group entries contain the offset to the matching End entry.
    Group(Group, usize),
    Ident(Ident),
    Punct(Punct),
    Literal(Literal),
    End,
}

/// A buffer that can be efficiently traversed multiple times, unlike
/// `TokenStream` which requires a deep copy in order to traverse more than
/// once.
///
/// *This type is available only if Syn is built with the `"parsing"` feature.*
pub struct TokenBuffer {
    // NOTE: Do not implement clone on this - while the current design could be
    // cloned, other designs which could be desirable may not be cloneable.
    entries: Box<[Entry]>,
}

impl TokenBuffer {
    fn recursive_new(entries: &mut Vec<Entry>, stream: TokenStream) {
        for tt in stream {
            match tt {
                TokenTree::Ident(ident) => entries.push(Entry::Ident(ident)),
                TokenTree::Punct(punct) => entries.push(Entry::Punct(punct)),
                TokenTree::Literal(literal) => entries.push(Entry::Literal(literal)),
                TokenTree::Group(group) => {
                    let group_start_index = entries.len();
                    entries.push(Entry::End); // we replace this below
                    Self::recursive_new(entries, group.stream());
                    let group_end_index = entries.len();
                    entries.push(Entry::End);
                    let group_end_offset = group_end_index - group_start_index;
                    entries[group_start_index] = Entry::Group(group, group_end_offset);
                }
            }
        }
    }

    /// Creates a `TokenBuffer` containing all the tokens from the input
    /// `proc_macro::TokenStream`.
    ///
    /// *This method is available only if Syn is built with both the `"parsing"` and
    /// `"proc-macro"` features.*
    #[cfg(all(
        not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
        feature = "proc-macro"
    ))]
    pub fn new(stream: pm::TokenStream) -> Self {
        Self::new2(stream.into())
    }

    /// Creates a `TokenBuffer` containing all the tokens from the input
    /// `proc_macro2::TokenStream`.
    pub fn new2(stream: TokenStream) -> Self {
        let mut entries = Vec::new();
        Self::recursive_new(&mut entries, stream);
        entries.push(Entry::End);
        Self {
            entries: entries.into_boxed_slice(),
        }
    }

    /// Creates a cursor referencing the first token in the buffer and able to
    /// traverse until the end of the buffer.
    pub fn begin(&self) -> Cursor {
        let ptr = self.entries.as_ptr();
        unsafe { Cursor::create(ptr, ptr.add(self.entries.len() - 1)) }
    }
}

/// A cheaply copyable cursor into a `TokenBuffer`.
///
/// This cursor holds a shared reference into the immutable data which is used
/// internally to represent a `TokenStream`, and can be efficiently manipulated
/// and copied around.
///
/// An empty `Cursor` can be created directly, or one may create a `TokenBuffer`
/// object and get a cursor to its first token with `begin()`.
///
/// Two cursors are equal if they have the same location in the same input
/// stream, and have the same scope.
///
/// *This type is available only if Syn is built with the `"parsing"` feature.*
pub struct Cursor<'a> {
    // The current entry which the `Cursor` is pointing at.
    ptr: *const Entry,
    // This is the only `Entry::End` object which this cursor is allowed to
    // point at. All other `End` objects are skipped over in `Cursor::create`.
    scope: *const Entry,
    // Cursor is covariant in 'a. This field ensures that our pointers are still
    // valid.
    marker: PhantomData<&'a Entry>,
}

impl<'a> Cursor<'a> {
    /// Creates a cursor referencing a static empty TokenStream.
    pub fn empty() -> Self {
        // It's safe in this situation for us to put an `Entry` object in global
        // storage, despite it not actually being safe to send across threads
        // (`Ident` is a reference into a thread-local table). This is because
        // this entry never includes a `Ident` object.
        //
        // This wrapper struct allows us to break the rules and put a `Sync`
        // object in global storage.
        struct UnsafeSyncEntry(Entry);
        unsafe impl Sync for UnsafeSyncEntry {}
        static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End);

        Cursor {
            ptr: &EMPTY_ENTRY.0,
            scope: &EMPTY_ENTRY.0,
            marker: PhantomData,
        }
    }

    /// This create method intelligently exits non-explicitly-entered
    /// `None`-delimited scopes when the cursor reaches the end of them,
    /// allowing for them to be treated transparently.
    unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
        // NOTE: If we're looking at a `End`, we want to advance the cursor
        // past it, unless `ptr == scope`, which means that we're at the edge of
        // our cursor's scope. We should only have `ptr != scope` at the exit
        // from None-delimited groups entered with `ignore_none`.
        while let Entry::End = *ptr {
            if ptr == scope {
                break;
            }
            ptr = ptr.add(1);
        }

        Cursor {
            ptr,
            scope,
            marker: PhantomData,
        }
    }

    /// Get the current entry.
    fn entry(self) -> &'a Entry {
        unsafe { &*self.ptr }
    }

    /// Bump the cursor to point at the next token after the current one. This
    /// is undefined behavior if the cursor is currently looking at an
    /// `Entry::End`.
    ///
    /// If the cursor is looking at an `Entry::Group`, the bumped cursor will
    /// point at the first token in the group (with the same scope end).
    unsafe fn bump_ignore_group(self) -> Cursor<'a> {
        Cursor::create(self.ptr.offset(1), self.scope)
    }

    /// While the cursor is looking at a `None`-delimited group, move it to look
    /// at the first token inside instead. If the group is empty, this will move
    /// the cursor past the `None`-delimited group.
    ///
    /// WARNING: This mutates its argument.
    fn ignore_none(&mut self) {
        while let Entry::Group(group, _) = self.entry() {
            if group.delimiter() == Delimiter::None {
                unsafe { *self = self.bump_ignore_group() };
            } else {
                break;
            }
        }
    }

    /// Checks whether the cursor is currently pointing at the end of its valid
    /// scope.
    pub fn eof(self) -> bool {
        // We're at eof if we're at the end of our scope.
        self.ptr == self.scope
    }

    /// If the cursor is pointing at a `Group` with the given delimiter, returns
    /// a cursor into that group and one pointing to the next `TokenTree`.
    pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, Span, Cursor<'a>)> {
        // If we're not trying to enter a none-delimited group, we want to
        // ignore them. We have to make sure to _not_ ignore them when we want
        // to enter them, of course. For obvious reasons.
        if delim != Delimiter::None {
            self.ignore_none();
        }

        if let Entry::Group(group, end_offset) = self.entry() {
            if group.delimiter() == delim {
                let end_of_group = unsafe { self.ptr.add(*end_offset) };
                let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) };
                let after_group = unsafe { Cursor::create(end_of_group, self.scope) };
                return Some((inside_of_group, group.span(), after_group));
            }
        }

        None
    }

    /// If the cursor is pointing at a `Ident`, returns it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn ident(mut self) -> Option<(Ident, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Ident(ident) => Some((ident.clone(), unsafe { self.bump_ignore_group() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Punct`, returns it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Punct(punct) if punct.as_char() != '\'' => {
                Some((punct.clone(), unsafe { self.bump_ignore_group() }))
            }
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Literal`, return it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Literal(literal) => Some((literal.clone(), unsafe { self.bump_ignore_group() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Lifetime`, returns it along with a
    /// cursor pointing at the next `TokenTree`.
    pub fn lifetime(mut self) -> Option<(Lifetime, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
                let next = unsafe { self.bump_ignore_group() };
                let (ident, rest) = next.ident()?;
                let lifetime = Lifetime {
                    apostrophe: punct.span(),
                    ident,
                };
                Some((lifetime, rest))
            }
            _ => None,
        }
    }

    /// Copies all remaining tokens visible from this cursor into a
    /// `TokenStream`.
    pub fn token_stream(self) -> TokenStream {
        let mut tts = Vec::new();
        let mut cursor = self;
        while let Some((tt, rest)) = cursor.token_tree() {
            tts.push(tt);
            cursor = rest;
        }
        tts.into_iter().collect()
    }

    /// If the cursor is pointing at a `TokenTree`, returns it along with a
    /// cursor pointing at the next `TokenTree`.
    ///
    /// Returns `None` if the cursor has reached the end of its stream.
    ///
    /// This method does not treat `None`-delimited groups as transparent, and
    /// will return a `Group(None, ..)` if the cursor is looking at one.
    pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> {
        let (tree, len) = match self.entry() {
            Entry::Group(group, end_offset) => (group.clone().into(), *end_offset),
            Entry::Literal(literal) => (literal.clone().into(), 1),
            Entry::Ident(ident) => (ident.clone().into(), 1),
            Entry::Punct(punct) => (punct.clone().into(), 1),
            Entry::End => return None,
        };

        let rest = unsafe { Cursor::create(self.ptr.add(len), self.scope) };
        Some((tree, rest))
    }

    /// Returns the `Span` of the current token, or `Span::call_site()` if this
    /// cursor points to eof.
    pub fn span(self) -> Span {
        match self.entry() {
            Entry::Group(group, _) => group.span(),
            Entry::Literal(literal) => literal.span(),
            Entry::Ident(ident) => ident.span(),
            Entry::Punct(punct) => punct.span(),
            Entry::End => Span::call_site(),
        }
    }

    /// Skip over the next token without cloning it. Returns `None` if this
    /// cursor points to eof.
    ///
    /// This method treats `'lifetimes` as a single token.
    pub(crate) fn skip(self) -> Option<Cursor<'a>> {
        let len = match self.entry() {
            Entry::End => return None,

            // Treat lifetimes as a single tt for the purposes of 'skip'.
            Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
                match unsafe { &*self.ptr.add(1) } {
                    Entry::Ident(_) => 2,
                    _ => 1,
                }
            }

            Entry::Group(_, end_offset) => *end_offset,
            _ => 1,
        };

        Some(unsafe { Cursor::create(self.ptr.add(len), self.scope) })
    }
}

impl<'a> Copy for Cursor<'a> {}

impl<'a> Clone for Cursor<'a> {
    fn clone(&self) -> Self {
        *self
    }
}

impl<'a> Eq for Cursor<'a> {}

impl<'a> PartialEq for Cursor<'a> {
    fn eq(&self, other: &Self) -> bool {
        let Cursor { ptr, scope, marker } = self;
        let _ = marker;
        *ptr == other.ptr && *scope == other.scope
    }
}

pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool {
    a.scope == b.scope
}

pub(crate) fn open_span_of_group(cursor: Cursor) -> Span {
    match cursor.entry() {
        Entry::Group(group, _) => group.span_open(),
        _ => cursor.span(),
    }
}

pub(crate) fn close_span_of_group(cursor: Cursor) -> Span {
    match cursor.entry() {
        Entry::Group(group, _) => group.span_close(),
        _ => cursor.span(),
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

use std::env;

use env_logger::Builder;
use log::LevelFilter;

use cnx::text::*;
use cnx::widgets::*;
use cnx::*;

fn init_log() -> Result<()> {
    let mut builder = Builder::new();
    builder.filter(Some("cnx"), LevelFilter::Trace);
    if let Ok(rust_log) = env::var("RUST_LOG") {
        builder.parse_filters(&rust_log);
    }
    builder.try_init()?;
    Ok(())
}

fn main() -> Result<()> {
    init_log()?;

    let attr = Attributes {
        font: Font::new("Envy Code R 22"),
        fg_color: Color::white(),
        bg_color: None,
        padding: Padding::new(8.0, 8.0, 0.0, 0.0),
    };
    let mut active_attr = attr.clone();
    active_attr.bg_color = Some(Color::blue());

    let mut cnx = Cnx::new(Position::Bottom)?;

    cnx_add_widget!(cnx, Pager::new(&cnx, active_attr, attr.clone()));
    cnx_add_widget!(cnx, ActiveWindowTitle::new(&cnx, attr.clone()));
    cnx_add_widget!(
        cnx,
        Sensors::new(&cnx, attr.clone(), vec!["Core 0", "Core 1"])
    );
    #[cfg(feature = "volume-widget")]
    cnx_add_widget!(cnx, Volume::new(&cnx, attr.clone()));
    cnx_add_widget!(cnx, Battery::new(&cnx, attr.clone(), Color::red()));
    cnx_add_widget!(cnx, Clock::new(&cnx, attr.clone()));

    cnx.run()?;

    Ok(())
}
<commit_msg>Remove non-BSD friendly sensors.<commit_after>#![deny(warnings)]

use std::env;

use env_logger::Builder;
use log::LevelFilter;

use cnx::text::*;
use cnx::widgets::*;
use cnx::*;

fn init_log() -> Result<()> {
    let mut builder = Builder::new();
    builder.filter(Some("cnx"), LevelFilter::Trace);
    if let Ok(rust_log) = env::var("RUST_LOG") {
        builder.parse_filters(&rust_log);
    }
    builder.try_init()?;
    Ok(())
}

fn main() -> Result<()> {
    init_log()?;

    let attr = Attributes {
        font: Font::new("Envy Code R 22"),
        fg_color: Color::white(),
        bg_color: None,
        padding: Padding::new(8.0, 8.0, 0.0, 0.0),
    };
    let mut active_attr = attr.clone();
    active_attr.bg_color = Some(Color::blue());

    let mut cnx = Cnx::new(Position::Bottom)?;

    cnx_add_widget!(cnx, Pager::new(&cnx, active_attr, attr.clone()));
    cnx_add_widget!(cnx, ActiveWindowTitle::new(&cnx, attr.clone()));
    // cnx_add_widget!(
    //    cnx,
    //    Sensors::new(&cnx, attr.clone(), vec!["Core 0", "Core 1"])
    // );
    #[cfg(feature = "volume-widget")]
    cnx_add_widget!(cnx, Volume::new(&cnx, attr.clone()));
    // cnx_add_widget!(cnx, Battery::new(&cnx, attr.clone(), Color::red()));
    cnx_add_widget!(cnx, Clock::new(&cnx, attr.clone()));

    cnx.run()?;

    Ok(())
}
<|endoftext|>


<commit_before>use std::fmt;

use base::{FromAscii};

/// An error returned when parsing a `bool` from a ascii string fails.
#[derive(Debug, Clone, PartialEq)]
pub enum ParseBoolError {
    ParseBoolError
}

impl fmt::Display for ParseBoolError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        "provided string was not `true` or `false`".fmt(f)
    }
}

impl FromAscii for bool {
    type Err = ParseBoolError;

    #[inline]
    fn from_ascii(s: &[u8]) -> Result<bool, ParseBoolError> {
        match s {
            b"true"  => Ok(true),
            b"false" => Ok(false),
            _       => Err(ParseBoolError::ParseBoolError),
        }
    }
}

#[cfg(test)]
mod test {
    use super::ParseBoolError;
    use super::super::base::FromAscii;

    #[test]
    fn test_parse_bool() {
        assert_eq!(bool::from_ascii(b"true"), Ok(true));
        assert_eq!(bool::from_ascii(b"false"), Ok(false));
        assert_eq!(bool::from_ascii(b""), Err(ParseBoolError::ParseBoolError));
        assert_eq!(bool::from_ascii(b"true "), Err(ParseBoolError::ParseBoolError));
        assert_eq!(bool::from_ascii(b"false "), Err(ParseBoolError::ParseBoolError));
    }
}
<commit_msg>Change ParseBoolError type<commit_after>use std::fmt;

use base::{FromAscii};

/// An error returned when parsing a `bool` from a ascii string fails.
#[derive(Debug, Clone, PartialEq)]
pub struct ParseBoolError {
    kind: BoolErrorKind
}

#[derive(Debug, Clone, PartialEq)]
enum BoolErrorKind {
    BoolErrorKind
}

impl fmt::Display for ParseBoolError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        "provided string was not `true` or `false`".fmt(f)
    }
}

impl FromAscii for bool {
    type Err = ParseBoolError;

    #[inline]
    fn from_ascii(s: &[u8]) -> Result<bool, ParseBoolError> {
        match s {
            b"true"  => Ok(true),
            b"false" => Ok(false),
            _       => Err(ParseBoolError { kind: BoolErrorKind::BoolErrorKind }),
        }
    }
}

#[cfg(test)]
mod test {
    use super::ParseBoolError;
    use super::super::base::FromAscii;

    #[test]
    fn test_parse_bool() {
        assert_eq!(bool::from_ascii(b"true"), Ok(true));
        assert_eq!(bool::from_ascii(b"false"), Ok(false));
        assert_eq!(bool::from_ascii(b""), Err(ParseBoolError::ParseBoolError));
        assert_eq!(bool::from_ascii(b"true "), Err(ParseBoolError::ParseBoolError));
        assert_eq!(bool::from_ascii(b"false "), Err(ParseBoolError::ParseBoolError));
    }
}
<|endoftext|>


<commit_before>use byteorder::{ByteOrder, BigEndian, WriteBytesExt};

use {Opcode, ResponseCode, Header, QueryType, QueryClass};

pub struct Builder {
    buf: Vec<u8>,
}

/// Allows to build a DNS packet
///
/// Both query and answer packets may be built with this interface, although,
/// much of functionality is not implemented yet.
impl Builder {
    /// Creates a new query
    ///
    /// Initially all sections are empty. You're expected to fill
    /// the questions section with `add_question`
    pub fn new_query(id: u16, recursion: bool) -> Builder {
        let mut buf = Vec::with_capacity(512);
        let head = Header {
            id: id,
            query: true,
            opcode: Opcode::StandardQuery,
            authoritative: false,
            truncated: false,
            recursion_desired: recursion,
            recursion_available: false,
            response_code: ResponseCode::NoError,
            questions: 0,
            answers: 0,
            nameservers: 0,
            additional: 0,
        };
        buf.extend([0u8; 12].iter());
        head.write(&mut buf[..12]);
        Builder { buf: buf }
    }
    /// Adds a question to the packet
    ///
    /// # Panics
    ///
    /// * Answers, nameservers or additional section has already been written
    /// * There are already 65535 questions in the buffer.
    /// * When name is invalid
    pub fn add_question(&mut self, qname: &str,
        qtype: QueryType, qclass: QueryClass)
        -> &mut Builder
    {
        println!("BUF {:?}", self.buf);
        if &self.buf[6..12] != b"\x00\x00\x00\x00\x00\x00" {
            panic!("Too late to add a question");
        }
        self.write_name(qname);
        self.buf.write_u16::<BigEndian>(qtype as u16).unwrap();
        self.buf.write_u16::<BigEndian>(qclass as u16).unwrap();
        let oldq = BigEndian::read_u16(&self.buf[4..6]);
        if oldq == 65535 {
            panic!("Too many questions");
        }
        BigEndian::write_u16(&mut self.buf[4..6], oldq+1);
        self
    }
    fn write_name(&mut self, name: &str) {
        for part in name.split('.') {
            assert!(part.len() < 63);
            let ln = part.len() as u8;
            self.buf.push(ln);
            self.buf.extend(part.as_bytes());
        }
        self.buf.push(0);
    }
    /// Returns the final packet
    ///
    /// When packet is not truncated method returns `Ok(packet)`. If
    /// packet is truncated the method returns `Err(packet)`. In both
    /// cases the packet is fully valid.
    ///
    /// In the server implementation you may use
    /// `x.build().unwrap_or_else(|x| x)`.
    ///
    /// In the client implementation it's probably unwise to send truncated
    /// packet, as it doesn't make sense. Even panicking may be more
    /// appropriate.
    // TODO(tailhook) does the truncation make sense for TCP, and how
    // to treat it for EDNS0?
    pub fn build(mut self) -> Result<Vec<u8>,Vec<u8>> {
        // TODO(tailhook) optimize labels
        if self.buf.len() > 512 {
            Header::set_truncated(&mut self.buf[..12]);
            Err(self.buf)
        } else {
            Ok(self.buf)
        }
    }
}

#[cfg(test)]
mod test {
    use QueryType as QT;
    use QueryClass as QC;
    use super::Builder;

    #[test]
    fn build_query() {
        let mut bld = Builder::new_query(1573, true);
        bld.add_question("example.com", QT::A, QC::IN);
        let result = b"\x06%\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\
                      \x07example\x03com\x00\x00\x01\x00\x01";
        assert_eq!(&bld.build().unwrap()[..], &result[..]);
    }
}
<commit_msg>Properly placed docstring on Builder<commit_after>use byteorder::{ByteOrder, BigEndian, WriteBytesExt};

use {Opcode, ResponseCode, Header, QueryType, QueryClass};

/// Allows to build a DNS packet
///
/// Both query and answer packets may be built with this interface, although,
/// much of functionality is not implemented yet.
pub struct Builder {
    buf: Vec<u8>,
}

impl Builder {
    /// Creates a new query
    ///
    /// Initially all sections are empty. You're expected to fill
    /// the questions section with `add_question`
    pub fn new_query(id: u16, recursion: bool) -> Builder {
        let mut buf = Vec::with_capacity(512);
        let head = Header {
            id: id,
            query: true,
            opcode: Opcode::StandardQuery,
            authoritative: false,
            truncated: false,
            recursion_desired: recursion,
            recursion_available: false,
            response_code: ResponseCode::NoError,
            questions: 0,
            answers: 0,
            nameservers: 0,
            additional: 0,
        };
        buf.extend([0u8; 12].iter());
        head.write(&mut buf[..12]);
        Builder { buf: buf }
    }
    /// Adds a question to the packet
    ///
    /// # Panics
    ///
    /// * Answers, nameservers or additional section has already been written
    /// * There are already 65535 questions in the buffer.
    /// * When name is invalid
    pub fn add_question(&mut self, qname: &str,
        qtype: QueryType, qclass: QueryClass)
        -> &mut Builder
    {
        println!("BUF {:?}", self.buf);
        if &self.buf[6..12] != b"\x00\x00\x00\x00\x00\x00" {
            panic!("Too late to add a question");
        }
        self.write_name(qname);
        self.buf.write_u16::<BigEndian>(qtype as u16).unwrap();
        self.buf.write_u16::<BigEndian>(qclass as u16).unwrap();
        let oldq = BigEndian::read_u16(&self.buf[4..6]);
        if oldq == 65535 {
            panic!("Too many questions");
        }
        BigEndian::write_u16(&mut self.buf[4..6], oldq+1);
        self
    }
    fn write_name(&mut self, name: &str) {
        for part in name.split('.') {
            assert!(part.len() < 63);
            let ln = part.len() as u8;
            self.buf.push(ln);
            self.buf.extend(part.as_bytes());
        }
        self.buf.push(0);
    }
    /// Returns the final packet
    ///
    /// When packet is not truncated method returns `Ok(packet)`. If
    /// packet is truncated the method returns `Err(packet)`. In both
    /// cases the packet is fully valid.
    ///
    /// In the server implementation you may use
    /// `x.build().unwrap_or_else(|x| x)`.
    ///
    /// In the client implementation it's probably unwise to send truncated
    /// packet, as it doesn't make sense. Even panicking may be more
    /// appropriate.
    // TODO(tailhook) does the truncation make sense for TCP, and how
    // to treat it for EDNS0?
    pub fn build(mut self) -> Result<Vec<u8>,Vec<u8>> {
        // TODO(tailhook) optimize labels
        if self.buf.len() > 512 {
            Header::set_truncated(&mut self.buf[..12]);
            Err(self.buf)
        } else {
            Ok(self.buf)
        }
    }
}

#[cfg(test)]
mod test {
    use QueryType as QT;
    use QueryClass as QC;
    use super::Builder;

    #[test]
    fn build_query() {
        let mut bld = Builder::new_query(1573, true);
        bld.add_question("example.com", QT::A, QC::IN);
        let result = b"\x06%\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\
                      \x07example\x03com\x00\x00\x01\x00\x01";
        assert_eq!(&bld.build().unwrap()[..], &result[..]);
    }
}
<|endoftext|>