<commit_before>// P_2_1_1_03
//
// Generative Gestaltung – Creative Coding im Web
// ISBN: 978-3-87439-902-9, First Edition, Hermann Schmidt, Mainz, 2018
// Benedikt Groß, Hartmut Bohnacker, Julia Laub, Claudius Lazzeroni
// with contributions by Joey Lee and Niels Poldervaart
// Copyright 2018
//
// http://www.generative-gestaltung.de
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * changing number, color and strokeweight on diagonals in a grid
 *
 * MOUSE
 * position x          : diagonal strokeweight
 * position y          : number diagonals
 * left click          : new random layout
 *
 * KEYS
 * s                   : save png
 * 1                   : color left diagonal
 * 2                   : color right diagonal
 * 3                   : switch transparency left diagonal on/off
 * 4                   : switch transparency right diagonal on/off
 * 0                   : default
 */
use nannou::prelude::*;
use nannou::rand::rngs::StdRng;
use nannou::rand::{Rng, SeedableRng};

fn main() {
    nannou::app(model).update(update).run();
}

struct Model {
    tile_count: u32,
    act_random_seed: u64,
    color_left: Hsv,
    color_right: Hsv,
    transparent_left: bool,
    transparent_right: bool,
}

fn model(app: &App) -> Model {
    let _window = app
        .new_window()
        .size(600, 600)
        .view(view)
        .mouse_pressed(mouse_pressed)
        .key_released(key_released)
        .key_pressed(key_pressed)
        .build()
        .unwrap();

    Model {
        tile_count: 1,
        act_random_seed: 0,
        color_left: hsv(0.88, 1.0, 0.77),
        color_right: hsv(0.0, 0.0, 0.0),
        transparent_left: false,
        transparent_right: false,
    }
}

fn update(app: &App, model: &mut Model, _update: Update) {
    model.tile_count = (app.mouse.y + app.window_rect().top()) as u32 / 15;
}

fn view(app: &App, model: &Model, frame: Frame) {
    // Prepare to draw.
    let draw = app.draw();
    draw.background().color(WHITE);
    let win = app.window_rect();

    let mut rng = StdRng::seed_from_u64(model.act_random_seed);

    for grid_y in 0..model.tile_count {
        for grid_x in 0..model.tile_count {
            let tile_w = win.w() / model.tile_count as f32;
            let tile_h = win.h() / model.tile_count as f32;
            let pos_x = win.left() + tile_w * grid_x as f32;
            let pos_y = (win.top() - tile_h) - tile_h * grid_y as f32;
            let mx = clamp(win.right() + app.mouse.x, 0.0, win.w());

            let toggle = rng.gen::<bool>();

            if toggle == false {
                let (h, s, v) = model.color_left.into_components();
                let a = calculate_alpha_left(grid_y, model.transparent_left);

                draw.line()
                    .hsva(h.into(), s, v, a)
                    .caps_round()
                    .weight(mx / 15.0)
                    .points(
                        pt2(pos_x, pos_y),
                        pt2(
                            pos_x + (win.w() / model.tile_count as f32) / 2.0,
                            pos_y + win.h() / model.tile_count as f32,
                        ),
                    );
                draw.line()
                    .hsva(h.into(), s, v, a)
                    .caps_round()
                    .weight(mx / 15.0)
                    .points(
                        pt2(pos_x + (win.w() / model.tile_count as f32) / 2.0, pos_y),
                        pt2(
                            pos_x + (win.w() / model.tile_count as f32),
                            pos_y + win.h() / model.tile_count as f32,
                        ),
                    );
            }
            if toggle == true {
                let (h, s, v) = model.color_right.into_components();
                let a = calculate_alpha_right(grid_y, model.transparent_right);

                draw.line()
                    .hsva(h.into(), s, v, a)
                    .caps_round()
                    .weight(mx / 15.0)
                    .points(
                        pt2(pos_x, pos_y + win.w() / model.tile_count as f32),
                        pt2(pos_x + (win.h() / model.tile_count as f32) / 2.0, pos_y),
                    );
                draw.line()
                    .hsva(h.into(), s, v, a)
                    .caps_round()
                    .weight(mx / 15.0)
                    .points(
                        pt2(
                            pos_x + (win.h() / model.tile_count as f32) / 2.0,
                            pos_y + win.w() / model.tile_count as f32,
                        ),
                        pt2(pos_x + win.h() / model.tile_count as f32, pos_y),
                    );
            }
        }
    }

    // Write to the window frame.
    draw.to_frame(app, &frame).unwrap();
}

fn calculate_alpha_left(grid_y: u32, transparent_left: bool) -> f32 {
    let max_alpha = 100.0;
    let alpha_left = if transparent_left {
        let a = grid_y as f32 * 10.0;
        match a {
            _ if a > max_alpha => 1.0,
            _ if a < 0.0 => 0.0,
            _ => a / max_alpha,
        }
    } else {
        1.0
    };

    alpha_left
}

fn calculate_alpha_right(grid_y: u32, transparent_right: bool) -> f32 {
    let max_alpha = 100.0;
    let alpha_right = if transparent_right {
        let a = max_alpha - (grid_y as f32 * 10.0);
        match a {
            _ if a > max_alpha => 1.0,
            _ if a < 0.0 => 0.0,
            _ => a / max_alpha,
        }
    } else {
        1.0
    };

    alpha_right
}

fn mouse_pressed(_app: &App, model: &mut Model, _button: MouseButton) {
    model.act_random_seed = (random_f32() * 100000.0) as u64;
}

fn key_pressed(app: &App, _model: &mut Model, key: Key) {
    if key == Key::S {
        app.main_window()
            .capture_frame(app.exe_name().unwrap() + ".png");
    }
}

fn key_released(_app: &App, model: &mut Model, key: Key) {
    match key {
        Key::Key1 => {
            if model
                .color_left
                .eq(&hsv(0.75, 0.73, 0.51))
            {
                model.color_left = hsv(0.89, 1.0, 0.77);
            } else {
                model.color_left = hsv(0.75, 0.73, 0.51);
            }
        }
        Key::Key2 => {
            if model
                .color_right
                .eq(&hsv(0.0, 0.0, 0.0))
            {
                model.color_right = hsv(0.53, 1.0, 0.64);
            } else {
                model.color_right = hsv(0.0, 0.0, 0.0);
            }
        }
        Key::Key3 => {
            model.transparent_left = !model.transparent_left;
        }
        Key::Key4 => {
            model.transparent_right = !model.transparent_right;
        }
        Key::Key0 => {
            model.transparent_left = false;
            model.transparent_right = false;
            model.color_left = hsv(0.89, 1.0, 0.77);
            model.color_right = hsv(0.0, 0.0, 0.0);
        }
        _other_key => {}
    }
}
<commit_msg>Correct formatting<commit_after>// P_2_1_1_03
//
// Generative Gestaltung – Creative Coding im Web
// ISBN: 978-3-87439-902-9, First Edition, Hermann Schmidt, Mainz, 2018
// Benedikt Groß, Hartmut Bohnacker, Julia Laub, Claudius Lazzeroni
// with contributions by Joey Lee and Niels Poldervaart
// Copyright 2018
//
// http://www.generative-gestaltung.de
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * changing number, color and strokeweight on diagonals in a grid
 *
 * MOUSE
 * position x          : diagonal strokeweight
 * position y          : number diagonals
 * left click          : new random layout
 *
 * KEYS
 * s                   : save png
 * 1                   : color left diagonal
 * 2                   : color right diagonal
 * 3                   : switch transparency left diagonal on/off
 * 4                   : switch transparency right diagonal on/off
 * 0                   : default
 */
use nannou::prelude::*;
use nannou::rand::rngs::StdRng;
use nannou::rand::{Rng, SeedableRng};

fn main() {
    nannou::app(model).update(update).run();
}

struct Model {
    tile_count: u32,
    act_random_seed: u64,
    color_left: Hsv,
    color_right: Hsv,
    transparent_left: bool,
    transparent_right: bool,
}

fn model(app: &App) -> Model {
    let _window = app
        .new_window()
        .size(600, 600)
        .view(view)
        .mouse_pressed(mouse_pressed)
        .key_released(key_released)
        .key_pressed(key_pressed)
        .build()
        .unwrap();

    Model {
        tile_count: 1,
        act_random_seed: 0,
        color_left: hsv(0.88, 1.0, 0.77),
        color_right: hsv(0.0, 0.0, 0.0),
        transparent_left: false,
        transparent_right: false,
    }
}

fn update(app: &App, model: &mut Model, _update: Update) {
    model.tile_count = (app.mouse.y + app.window_rect().top()) as u32 / 15;
}

fn view(app: &App, model: &Model, frame: Frame) {
    // Prepare to draw.
    let draw = app.draw();
    draw.background().color(WHITE);
    let win = app.window_rect();

    let mut rng = StdRng::seed_from_u64(model.act_random_seed);

    for grid_y in 0..model.tile_count {
        for grid_x in 0..model.tile_count {
            let tile_w = win.w() / model.tile_count as f32;
            let tile_h = win.h() / model.tile_count as f32;
            let pos_x = win.left() + tile_w * grid_x as f32;
            let pos_y = (win.top() - tile_h) - tile_h * grid_y as f32;
            let mx = clamp(win.right() + app.mouse.x, 0.0, win.w());

            let toggle = rng.gen::<bool>();

            if toggle == false {
                let (h, s, v) = model.color_left.into_components();
                let a = calculate_alpha_left(grid_y, model.transparent_left);

                draw.line()
                    .hsva(h.into(), s, v, a)
                    .caps_round()
                    .weight(mx / 15.0)
                    .points(
                        pt2(pos_x, pos_y),
                        pt2(
                            pos_x + (win.w() / model.tile_count as f32) / 2.0,
                            pos_y + win.h() / model.tile_count as f32,
                        ),
                    );
                draw.line()
                    .hsva(h.into(), s, v, a)
                    .caps_round()
                    .weight(mx / 15.0)
                    .points(
                        pt2(pos_x + (win.w() / model.tile_count as f32) / 2.0, pos_y),
                        pt2(
                            pos_x + (win.w() / model.tile_count as f32),
                            pos_y + win.h() / model.tile_count as f32,
                        ),
                    );
            }
            if toggle == true {
                let (h, s, v) = model.color_right.into_components();
                let a = calculate_alpha_right(grid_y, model.transparent_right);

                draw.line()
                    .hsva(h.into(), s, v, a)
                    .caps_round()
                    .weight(mx / 15.0)
                    .points(
                        pt2(pos_x, pos_y + win.w() / model.tile_count as f32),
                        pt2(pos_x + (win.h() / model.tile_count as f32) / 2.0, pos_y),
                    );
                draw.line()
                    .hsva(h.into(), s, v, a)
                    .caps_round()
                    .weight(mx / 15.0)
                    .points(
                        pt2(
                            pos_x + (win.h() / model.tile_count as f32) / 2.0,
                            pos_y + win.w() / model.tile_count as f32,
                        ),
                        pt2(pos_x + win.h() / model.tile_count as f32, pos_y),
                    );
            }
        }
    }

    // Write to the window frame.
    draw.to_frame(app, &frame).unwrap();
}

fn calculate_alpha_left(grid_y: u32, transparent_left: bool) -> f32 {
    let max_alpha = 100.0;
    let alpha_left = if transparent_left {
        let a = grid_y as f32 * 10.0;
        match a {
            _ if a > max_alpha => 1.0,
            _ if a < 0.0 => 0.0,
            _ => a / max_alpha,
        }
    } else {
        1.0
    };

    alpha_left
}

fn calculate_alpha_right(grid_y: u32, transparent_right: bool) -> f32 {
    let max_alpha = 100.0;
    let alpha_right = if transparent_right {
        let a = max_alpha - (grid_y as f32 * 10.0);
        match a {
            _ if a > max_alpha => 1.0,
            _ if a < 0.0 => 0.0,
            _ => a / max_alpha,
        }
    } else {
        1.0
    };

    alpha_right
}

fn mouse_pressed(_app: &App, model: &mut Model, _button: MouseButton) {
    model.act_random_seed = (random_f32() * 100000.0) as u64;
}

fn key_pressed(app: &App, _model: &mut Model, key: Key) {
    if key == Key::S {
        app.main_window()
            .capture_frame(app.exe_name().unwrap() + ".png");
    }
}

fn key_released(_app: &App, model: &mut Model, key: Key) {
    match key {
        Key::Key1 => {
            if model.color_left.eq(&hsv(0.75, 0.73, 0.51)) {
                model.color_left = hsv(0.89, 1.0, 0.77);
            } else {
                model.color_left = hsv(0.75, 0.73, 0.51);
            }
        }
        Key::Key2 => {
            if model.color_right.eq(&hsv(0.0, 0.0, 0.0)) {
                model.color_right = hsv(0.53, 1.0, 0.64);
            } else {
                model.color_right = hsv(0.0, 0.0, 0.0);
            }
        }
        Key::Key3 => {
            model.transparent_left = !model.transparent_left;
        }
        Key::Key4 => {
            model.transparent_right = !model.transparent_right;
        }
        Key::Key0 => {
            model.transparent_left = false;
            model.transparent_right = false;
            model.color_left = hsv(0.89, 1.0, 0.77);
            model.color_right = hsv(0.0, 0.0, 0.0);
        }
        _other_key => {}
    }
}
<|endoftext|>


<commit_before>/// Logging drain
///
/// `Drain`s typially mean destination for logs, but `slog` generalizes the
/// term.
///
/// `Drain`s are responsible for handling logging statements (`Record`s) from
/// `Logger`s associated with them: filtering, modifying, formatting
/// and writing the log records into given destination(s).
///
/// Implementing this trait allows writing custom `Drain`s.
///
/// It's a typical pattern to parametrize `Drain`s over `Drain` traits to allow
/// combining them into one `Drain`. See `Duplicate` as an example.
pub trait Drain {
    /// Type returned by this drain
    ///
    /// It can be useful in some circumstances, but rarely. It will probably default to `()` once
    /// https://github.com/rust-lang/rust/issues/29661 is stable.
    type Ok;
    /// Type of potential errors that can be returned by this `Drain`
    type Err;
    /// Handle one logging statement (`Record`)
    ///
    /// Every logging `Record` built from a logging statement (eg.
    /// `info!(...)`), and key-value lists of a `Logger` it was executed on
    /// will be passed to the root drain registered during `Logger::root`.
    ///
    /// Typically `Drain`s:
    ///
    /// * pass this information (or not) to the sub-logger(s) (filters)
    /// * format and write the information the a destination (writers)
    /// * deal with the errors returned from the sub-logger(s)
    fn log(&self, record: &Record, values : &OwnedKVList) -> result::Result<Self::Ok, Self::Err>;
}

impl<D: Drain+?Sized> Drain for Box<D> {
    type Ok = D::Ok;
    type Err = D::Err;
    fn log(&self, record: &Record, o: &OwnedKVList) -> result::Result<Self::Ok, D::Err> {
        (**self).log(record, o)
    }
}

impl<D: Drain+?Sized> Drain for Arc<D> {
    type Ok = D::Ok;
    type Err = D::Err;
    fn log(&self, record: &Record, o: &OwnedKVList) -> result::Result<Self::Ok, D::Err> {
        (**self).log(record, o)
    }
}

/// Convenience methods for building drains
///
/// `DrainExt` is implemented for every `Drain` and contains
/// convenience methods.
pub trait DrainExt: Sized + Drain {
    /// Map logging errors returned by this drain
    ///
    /// `f` is a closure that takes `Drain::Err` returned by a given
    /// drain, and returns new error of potentially different type
    fn map_err<F, E>(self, f : F) -> MapError<Self, E> where F : 'static + Sync + Send + Fn(<Self as Drain>::Err) -> E {
        MapError::new(self, f)
    }

    /// Make `Self` ignore and result
    fn ignore_res(self) -> IgnoreResult<Self> {
        IgnoreResult::new(self)
    }

    /// Make `Self` panic when returning any errors
    fn fuse(self) -> Fuse<Self> where <Self as Drain>::Err : fmt::Display {
       Fuse::new(self)
    }
}

impl<D : Drain> DrainExt for D {}

/// `Drain` discarding everything
///
/// `/dev/null` of `Drain`s
pub struct Discard;

impl Drain for Discard {
    type Ok = ();
    type Err = Never;
    fn log(&self, _: &Record, _: &OwnedKVList) -> result::Result<(), Never> {
        Ok(())
    }
}

/// `Drain` filtering records
///
/// Wraps another `Drain` and passes `Record`s to it, only if they satisfy a
/// given condition.
pub struct Filter<D: Drain> {
    drain: D,
    // eliminated dynamic dispatch, after rust learns `-> impl Trait`
    cond: Box<Fn(&Record) -> bool + 'static + Send + Sync>,
}

impl<D: Drain> Filter<D> {
    /// Create `Filter` wrapping given `drain`
    pub fn new<F: 'static + Sync + Send + Fn(&Record) -> bool>(drain: D, cond: F) -> Self {
        Filter {
            drain: drain,
            cond: Box::new(cond),
        }
    }
}

impl<D: Drain> Drain for Filter<D> {
    type Ok = Option<D::Ok>;
    type Err = D::Err;
    fn log(&self,
           record: &Record,
           logger_values: &OwnedKVList)
           -> result::Result<Self::Ok, Self::Err> {
        if (self.cond)(&record) {
            Ok(Some(self.drain.log(record, logger_values)?))
        } else {
            Ok(None)
        }
    }
}

/// `Drain` mapping error returned by another `Drain`
///
/// See `DrainExt::map_err` for convenience function.
pub struct MapError<D: Drain, E> {
    drain: D,
    // eliminated dynamic dispatch, after rust learns `-> impl Trait`
    map_fn: Box<Fn(D::Err) -> E + 'static+ Send+Sync>,
}

impl<D: Drain, E> MapError<D, E> {
    /// Create `Filter` wrapping given `drain`
    pub fn new<F: 'static + Sync + Send + Fn(<D as Drain>::Err) -> E>(drain: D, map_fn: F) -> Self {
        MapError {
            drain: drain,
            map_fn: Box::new(map_fn),
        }
    }
}

impl<D: Drain, E> Drain for MapError<D, E> {
    type Ok = D::Ok;
    type Err = E;
    fn log(&self,
           record: &Record,
           logger_values: &OwnedKVList)
           -> result::Result<Self::Ok, Self::Err> {
            self.drain.log(record, logger_values).map_err(|e| (self.map_fn)(e))
    }
}

/// `Drain` filtering records by `Record` logging level
///
/// Wraps a drain and passes records to it, only
/// if their level is at least given level.
///
/// TODO: Remove this type. This drain is a special case of `Filter`, but
/// because `Filter` can not use static dispatch ATM due to Rust limitations
/// that will be lifted in the future, it is a standalone type.
pub struct LevelFilter<D: Drain> {
    level: Level,
    drain: D,
}

impl<D: Drain> LevelFilter<D> {
    /// Create `LevelFilter`
    pub fn new(drain: D, level: Level) -> Self {
        LevelFilter {
            level: level,
            drain: drain,
        }
    }
}

impl<D: Drain> Drain for LevelFilter<D> {
    type Ok = Option<D::Ok>;
    type Err = D::Err;
    fn log(&self,
           record: &Record,
           logger_values: &OwnedKVList)
           -> result::Result<Self::Ok, Self::Err> {
        if record.level().is_at_least(self.level) {
            Ok(Some(self.drain.log(record, logger_values)?))
        } else {
            Ok(None)
        }
    }
}

/// `Drain` duplicating records into two other `Drain`s
///
/// Can be nested for more than two outputs.
pub struct Duplicate<D1: Drain, D2: Drain> {
    drain1: D1,
    drain2: D2,
}

impl<D1: Drain, D2: Drain> Duplicate<D1, D2> {
    /// Create `Duplicate`
    pub fn new(drain1: D1, drain2: D2) -> Self {
        Duplicate {
            drain1: drain1,
            drain2: drain2,
        }
    }
}

impl<D1 : Drain, D2 : Drain> Drain for Duplicate<D1, D2> {
    type Ok = (D1::Ok, D2::Ok);
    type Err = (result::Result<D1::Ok, D1::Err>, result::Result<D2::Ok, D2::Err>);
    fn log(&self,
           record: &Record,
           logger_values: &OwnedKVList)
           -> result::Result<Self::Ok, Self::Err> {
        let res1 = self.drain1.log(record, logger_values);
        let res2 = self.drain2.log(record, logger_values);

        match (res1, res2) {
            (Ok(o1), Ok(o2)) => Ok((o1, o2)),
            (r1, r2) => Err((r1, r2)),
        }
    }
}

/// `Drain` panicking on error
///
/// `Logger` requires a root drain to handle all errors (`Drain::Error == ()`),
/// `Fuse` will wrap a `Drain` and panic if it returns any errors.
///
/// Note: `Drain::Err` must implement `Display` (for displaying on panick). It's
/// easy to create own `Fuse` drain if this requirement can't be fulfilled.
pub struct Fuse<D: Drain> {
    drain: D,
}

impl<D: Drain> Fuse<D> {
    /// Create `Fuse` wrapping given `drain`
    pub fn new(drain: D) -> Self {
        Fuse {
            drain: drain,
        }
    }
}

impl<D: Drain> Drain for Fuse<D> where D::Err : fmt::Display {
    type Ok = ();
    type Err = Never;
    fn log(&self,
           record: &Record,
           logger_values: &OwnedKVList)
        -> result::Result<Self::Ok, Never> {
            let _ = self.drain.log(record, logger_values).unwrap_or_else(
                |e| panic!("slog::Fuse Drain: {}", e)
                );
            Ok(())
        }
}

/// `Drain` ignoring result
///
/// `Logger` requires a root drain to handle all errors (`Drain::Err=()`), and
/// returns nothing (`Drain::Ok=()`) `IgnoreResult` will ignore any result
/// returned by the `Drain` it wraps.
pub struct IgnoreResult<D: Drain> {
    drain: D,
}

impl<D: Drain> IgnoreResult<D> {
    /// Create `IgnoreResult` wrapping `drain`
    pub fn new(drain: D) -> Self {
        IgnoreResult {
            drain: drain,
        }
    }
}

impl<D: Drain> Drain for IgnoreResult<D> {
    type Ok = ();
    type Err = Never;
    fn log(&self,
           record: &Record,
           logger_values: &OwnedKVList)
        -> result::Result<(), Never> {
            let _ = self.drain.log(record, logger_values);
            Ok(())
        }
}

/// Filter by `cond` closure
pub fn filter<D: Drain, F: 'static + Send + Sync + Fn(&Record) -> bool>(
    cond: F,
    d: D
    ) -> Filter<D> {
    Filter::new(d, cond)
}

/// Filter by log level
pub fn level_filter<D: Drain>(level: Level, d: D) -> LevelFilter<D> {
    LevelFilter::new(d, level)
}

/// Duplicate records to two drains
///
/// Create `Duplicate` drain.
///
/// Can be nested for multiple outputs.
pub fn duplicate<D1: Drain, D2: Drain>(d1: D1, d2: D2) -> Duplicate<D1, D2> {
    Duplicate::new(d1, d2)
}

#[cfg(feature = "std")]
#[derive(Debug)]
/// Error returned by `Mutex<D : Drain>`
pub enum MutexDrainError<D : Drain> {
    /// Error aquiring mutex
    Mutex,
    /// Error returned by drain
    Drain(D::Err),
}

#[cfg(feature = "std")]
impl<'a, D : Drain> From<std::sync::PoisonError<std::sync::MutexGuard<'a, D>>> for MutexDrainError<D> {
    fn from(_ : std::sync::PoisonError<std::sync::MutexGuard<'a, D>>) -> MutexDrainError<D> {
        MutexDrainError::Mutex
    }
}
#[cfg(feature = "std")]
impl<D : Drain> fmt::Display for MutexDrainError<D>
where D::Err : fmt::Display {
    fn fmt(&self, f : &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
        match *self {
            MutexDrainError::Mutex => write!(f, "MutexError"),
            MutexDrainError::Drain(ref e) => write!(f, "{}", e),
        }
    }
}

#[cfg(feature = "std")]
impl<D: Drain> Drain for std::sync::Mutex<D> {
    type Ok = D::Ok;
    type Err = MutexDrainError<D>;
    fn log(&self,
           record: &Record,
           logger_values: &OwnedKVList)
        -> result::Result<Self::Ok, Self::Err> {
            let d = self.lock()?;
            d.log(record, logger_values).map_err(MutexDrainError::Drain)
        }
}
<commit_msg>Add more documentation on `LevelFilter`<commit_after>/// Logging drain
///
/// `Drain`s typially mean destination for logs, but `slog` generalizes the
/// term.
///
/// `Drain`s are responsible for handling logging statements (`Record`s) from
/// `Logger`s associated with them: filtering, modifying, formatting
/// and writing the log records into given destination(s).
///
/// Implementing this trait allows writing custom `Drain`s.
///
/// It's a typical pattern to parametrize `Drain`s over `Drain` traits to allow
/// combining them into one `Drain`. See `Duplicate` as an example.
pub trait Drain {
    /// Type returned by this drain
    ///
    /// It can be useful in some circumstances, but rarely. It will probably default to `()` once
    /// https://github.com/rust-lang/rust/issues/29661 is stable.
    type Ok;
    /// Type of potential errors that can be returned by this `Drain`
    type Err;
    /// Handle one logging statement (`Record`)
    ///
    /// Every logging `Record` built from a logging statement (eg.
    /// `info!(...)`), and key-value lists of a `Logger` it was executed on
    /// will be passed to the root drain registered during `Logger::root`.
    ///
    /// Typically `Drain`s:
    ///
    /// * pass this information (or not) to the sub-logger(s) (filters)
    /// * format and write the information the a destination (writers)
    /// * deal with the errors returned from the sub-logger(s)
    fn log(&self, record: &Record, values : &OwnedKVList) -> result::Result<Self::Ok, Self::Err>;
}

impl<D: Drain+?Sized> Drain for Box<D> {
    type Ok = D::Ok;
    type Err = D::Err;
    fn log(&self, record: &Record, o: &OwnedKVList) -> result::Result<Self::Ok, D::Err> {
        (**self).log(record, o)
    }
}

impl<D: Drain+?Sized> Drain for Arc<D> {
    type Ok = D::Ok;
    type Err = D::Err;
    fn log(&self, record: &Record, o: &OwnedKVList) -> result::Result<Self::Ok, D::Err> {
        (**self).log(record, o)
    }
}

/// Convenience methods for building drains
///
/// `DrainExt` is implemented for every `Drain` and contains
/// convenience methods.
pub trait DrainExt: Sized + Drain {
    /// Map logging errors returned by this drain
    ///
    /// `f` is a closure that takes `Drain::Err` returned by a given
    /// drain, and returns new error of potentially different type
    fn map_err<F, E>(self, f : F) -> MapError<Self, E> where F : 'static + Sync + Send + Fn(<Self as Drain>::Err) -> E {
        MapError::new(self, f)
    }

    /// Make `Self` ignore and result
    fn ignore_res(self) -> IgnoreResult<Self> {
        IgnoreResult::new(self)
    }

    /// Make `Self` panic when returning any errors
    fn fuse(self) -> Fuse<Self> where <Self as Drain>::Err : fmt::Display {
       Fuse::new(self)
    }
}

impl<D : Drain> DrainExt for D {}

/// `Drain` discarding everything
///
/// `/dev/null` of `Drain`s
pub struct Discard;

impl Drain for Discard {
    type Ok = ();
    type Err = Never;
    fn log(&self, _: &Record, _: &OwnedKVList) -> result::Result<(), Never> {
        Ok(())
    }
}

/// `Drain` filtering records
///
/// Wraps another `Drain` and passes `Record`s to it, only if they satisfy a
/// given condition.
pub struct Filter<D: Drain> {
    drain: D,
    // eliminated dynamic dispatch, after rust learns `-> impl Trait`
    cond: Box<Fn(&Record) -> bool + 'static + Send + Sync>,
}

impl<D: Drain> Filter<D> {
    /// Create `Filter` wrapping given `drain`
    pub fn new<F: 'static + Sync + Send + Fn(&Record) -> bool>(drain: D, cond: F) -> Self {
        Filter {
            drain: drain,
            cond: Box::new(cond),
        }
    }
}

impl<D: Drain> Drain for Filter<D> {
    type Ok = Option<D::Ok>;
    type Err = D::Err;
    fn log(&self,
           record: &Record,
           logger_values: &OwnedKVList)
           -> result::Result<Self::Ok, Self::Err> {
        if (self.cond)(&record) {
            Ok(Some(self.drain.log(record, logger_values)?))
        } else {
            Ok(None)
        }
    }
}

/// `Drain` mapping error returned by another `Drain`
///
/// See `DrainExt::map_err` for convenience function.
pub struct MapError<D: Drain, E> {
    drain: D,
    // eliminated dynamic dispatch, after rust learns `-> impl Trait`
    map_fn: Box<Fn(D::Err) -> E + 'static+ Send+Sync>,
}

impl<D: Drain, E> MapError<D, E> {
    /// Create `Filter` wrapping given `drain`
    pub fn new<F: 'static + Sync + Send + Fn(<D as Drain>::Err) -> E>(drain: D, map_fn: F) -> Self {
        MapError {
            drain: drain,
            map_fn: Box::new(map_fn),
        }
    }
}

impl<D: Drain, E> Drain for MapError<D, E> {
    type Ok = D::Ok;
    type Err = E;
    fn log(&self,
           record: &Record,
           logger_values: &OwnedKVList)
           -> result::Result<Self::Ok, Self::Err> {
            self.drain.log(record, logger_values).map_err(|e| (self.map_fn)(e))
    }
}

/// `Drain` filtering records by `Record` logging level
///
/// Wraps a drain and passes records to it, only
/// if their level is at least given level.
///
/// TODO: Remove this type. This drain is a special case of `Filter`, but
/// because `Filter` can not use static dispatch ATM due to Rust limitations
/// that will be lifted in the future, it is a standalone type.
/// Reference: https://github.com/rust-lang/rust/issues/34511
pub struct LevelFilter<D: Drain> {
    level: Level,
    drain: D,
}

impl<D: Drain> LevelFilter<D> {
    /// Create `LevelFilter`
    pub fn new(drain: D, level: Level) -> Self {
        LevelFilter {
            level: level,
            drain: drain,
        }
    }
}

impl<D: Drain> Drain for LevelFilter<D> {
    type Ok = Option<D::Ok>;
    type Err = D::Err;
    fn log(&self,
           record: &Record,
           logger_values: &OwnedKVList)
           -> result::Result<Self::Ok, Self::Err> {
        if record.level().is_at_least(self.level) {
            Ok(Some(self.drain.log(record, logger_values)?))
        } else {
            Ok(None)
        }
    }
}

/// `Drain` duplicating records into two other `Drain`s
///
/// Can be nested for more than two outputs.
pub struct Duplicate<D1: Drain, D2: Drain> {
    drain1: D1,
    drain2: D2,
}

impl<D1: Drain, D2: Drain> Duplicate<D1, D2> {
    /// Create `Duplicate`
    pub fn new(drain1: D1, drain2: D2) -> Self {
        Duplicate {
            drain1: drain1,
            drain2: drain2,
        }
    }
}

impl<D1 : Drain, D2 : Drain> Drain for Duplicate<D1, D2> {
    type Ok = (D1::Ok, D2::Ok);
    type Err = (result::Result<D1::Ok, D1::Err>, result::Result<D2::Ok, D2::Err>);
    fn log(&self,
           record: &Record,
           logger_values: &OwnedKVList)
           -> result::Result<Self::Ok, Self::Err> {
        let res1 = self.drain1.log(record, logger_values);
        let res2 = self.drain2.log(record, logger_values);

        match (res1, res2) {
            (Ok(o1), Ok(o2)) => Ok((o1, o2)),
            (r1, r2) => Err((r1, r2)),
        }
    }
}

/// `Drain` panicking on error
///
/// `Logger` requires a root drain to handle all errors (`Drain::Error == ()`),
/// `Fuse` will wrap a `Drain` and panic if it returns any errors.
///
/// Note: `Drain::Err` must implement `Display` (for displaying on panick). It's
/// easy to create own `Fuse` drain if this requirement can't be fulfilled.
pub struct Fuse<D: Drain> {
    drain: D,
}

impl<D: Drain> Fuse<D> {
    /// Create `Fuse` wrapping given `drain`
    pub fn new(drain: D) -> Self {
        Fuse {
            drain: drain,
        }
    }
}

impl<D: Drain> Drain for Fuse<D> where D::Err : fmt::Display {
    type Ok = ();
    type Err = Never;
    fn log(&self,
           record: &Record,
           logger_values: &OwnedKVList)
        -> result::Result<Self::Ok, Never> {
            let _ = self.drain.log(record, logger_values).unwrap_or_else(
                |e| panic!("slog::Fuse Drain: {}", e)
                );
            Ok(())
        }
}

/// `Drain` ignoring result
///
/// `Logger` requires a root drain to handle all errors (`Drain::Err=()`), and
/// returns nothing (`Drain::Ok=()`) `IgnoreResult` will ignore any result
/// returned by the `Drain` it wraps.
pub struct IgnoreResult<D: Drain> {
    drain: D,
}

impl<D: Drain> IgnoreResult<D> {
    /// Create `IgnoreResult` wrapping `drain`
    pub fn new(drain: D) -> Self {
        IgnoreResult {
            drain: drain,
        }
    }
}

impl<D: Drain> Drain for IgnoreResult<D> {
    type Ok = ();
    type Err = Never;
    fn log(&self,
           record: &Record,
           logger_values: &OwnedKVList)
        -> result::Result<(), Never> {
            let _ = self.drain.log(record, logger_values);
            Ok(())
        }
}

/// Filter by `cond` closure
pub fn filter<D: Drain, F: 'static + Send + Sync + Fn(&Record) -> bool>(
    cond: F,
    d: D
    ) -> Filter<D> {
    Filter::new(d, cond)
}

/// Filter by log level
pub fn level_filter<D: Drain>(level: Level, d: D) -> LevelFilter<D> {
    LevelFilter::new(d, level)
}

/// Duplicate records to two drains
///
/// Create `Duplicate` drain.
///
/// Can be nested for multiple outputs.
pub fn duplicate<D1: Drain, D2: Drain>(d1: D1, d2: D2) -> Duplicate<D1, D2> {
    Duplicate::new(d1, d2)
}

#[cfg(feature = "std")]
#[derive(Debug)]
/// Error returned by `Mutex<D : Drain>`
pub enum MutexDrainError<D : Drain> {
    /// Error aquiring mutex
    Mutex,
    /// Error returned by drain
    Drain(D::Err),
}

#[cfg(feature = "std")]
impl<'a, D : Drain> From<std::sync::PoisonError<std::sync::MutexGuard<'a, D>>> for MutexDrainError<D> {
    fn from(_ : std::sync::PoisonError<std::sync::MutexGuard<'a, D>>) -> MutexDrainError<D> {
        MutexDrainError::Mutex
    }
}
#[cfg(feature = "std")]
impl<D : Drain> fmt::Display for MutexDrainError<D>
where D::Err : fmt::Display {
    fn fmt(&self, f : &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
        match *self {
            MutexDrainError::Mutex => write!(f, "MutexError"),
            MutexDrainError::Drain(ref e) => write!(f, "{}", e),
        }
    }
}

#[cfg(feature = "std")]
impl<D: Drain> Drain for std::sync::Mutex<D> {
    type Ok = D::Ok;
    type Err = MutexDrainError<D>;
    fn log(&self,
           record: &Record,
           logger_values: &OwnedKVList)
        -> result::Result<Self::Ok, Self::Err> {
            let d = self.lock()?;
            d.log(record, logger_values).map_err(MutexDrainError::Drain)
        }
}
<|endoftext|>


<commit_before>use vk::*;

pub const SPEC_VERSION: u32 = 2;
pub const EXTENSION_NAME: &'static str = "VK_EXT_debug_report";

impl_enum!{Result;
    ERROR_VALIDATION_FAILED = -1000011001,
}
impl_enum!{StructureType;
    STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = 1000011000,
}
<commit_msg>Add the rest of the debug_report enums<commit_after>use vk::*;

pub const SPEC_VERSION: u32 = 2;
pub const EXTENSION_NAME: &'static str = "VK_debug_report";

impl_enum!{Result;
    ERROR_VALIDATION_FAILED = -1000011001,
}
impl_enum!{StructureType;
    STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO = 1000011000,
}
make_enum!{ObjectType;
    UNKNOWN = 0,
    INSTANCE = 1,
    PHYSICAL_DEVICE = 2,
    DEVICE = 3,
    QUEUE = 4,
    SEMAPHORE = 5,
    COMMAND_BUFFER = 6,
    FENCE = 7,
    DEVICE_MEMORY = 8,
    BUFFER = 9,
    IMAGE = 10,
    EVENT = 11,
    QUERY_POOL = 12,
    BUFFER_VIEW = 13,
    IMAGE_VIEW = 14,
    SHADER_MODULE = 15,
    PIPELINE_CACHE = 16,
    PIPELINE_LAYOUT = 17,
    RENDER_PASS = 18,
    PIPELINE = 19,
    DESCRIPTOR_SET_LAYOUT = 20,
    SAMPLER = 21,
    DESCRIPTOR_POOL = 22,
    DESCRIPTOR_SET = 23,
    FRAMEBUFFER = 24,
    COMMAND_POOL = 25,
    SURFACE_KHR = 26,
    SWAPCHAIN_KHR = 27,
    DEBUG_REPORT = 28,
}
make_enum!{Error;
    NONE = 0,
    CALLBACK_REF = 1,
}
make_flag!{Flags;
    INFO = 0x00000001,
    WARN = 0x00000002,
    PERF_WARN = 0x00000004,
    ERROR = 0x00000008,
    DEBUG = 0x00000010,
}
<|endoftext|>


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

use std::ptr;

use ffi;
use FFIWidget;

/// GtkTextBuffer — Stores attributed text for display in a GtkTextView

struct_Widget!(TextBuffer);

impl TextBuffer {
    pub fn new(text_tag_table: Option<::TextTagTable>) -> Option<TextBuffer> {
        let tmp_pointer = unsafe {
            match text_tag_table {
                Some(ttl) => ffi::gtk_text_buffer_new(ttl.unwrap_pointer()),
                None      => ffi::gtk_text_buffer_new(ptr::null_mut())
            }
        };

        check_pointer!(tmp_pointer, TextBuffer)
    }
}

impl_drop!(TextBuffer);
impl_TraitWidget!(TextBuffer);

impl ::TextBufferTrait for TextBuffer {}
<commit_msg>139 First pass at linking txt iterator to buffer<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::ptr;

use ffi;
use FFIWidget;
use TextIter;

use cast::GTK_TEXT_BUFFER;
use glib::translate::ToGlibPtrMut;
/// GtkTextBuffer — Stores attributed text for display in a GtkTextView

struct_Widget!(TextBuffer);

impl TextBuffer {
    pub fn new(text_tag_table: Option<::TextTagTable>) -> Option<TextBuffer> {
        let tmp_pointer = unsafe {
            match text_tag_table {
                Some(ttl) => ffi::gtk_text_buffer_new(ttl.unwrap_pointer()),
                None      => ffi::gtk_text_buffer_new(ptr::null_mut())
            }
        };

        check_pointer!(tmp_pointer, TextBuffer)
    }

    pub fn get_start_iter(&self) -> TextIter {
        unsafe {
            let mut target_iter = TextIter::uninitialized();
            ffi::gtk_text_buffer_get_start_iter(
                GTK_TEXT_BUFFER(self.unwrap_widget()),
                target_iter.to_glib_none_mut().0);
            target_iter
        }
    }
}

impl_drop!(TextBuffer);
impl_TraitWidget!(TextBuffer);

impl ::TextBufferTrait for TextBuffer {}
<|endoftext|>


<commit_before>//! The `ast` module contains a lot of useful functionality
//! to create and walk through the ast (abstract syntaxtree)

use frontend::parser;
use frontend::lexer::Token;
use backend::zcode::zfile;

//==============================
// ast

pub struct AST {
    passages: Vec<ASTNode>
}

/// add zcode based on tokens
fn stuff(node: &ASTNode, mut out: &mut zfile::Zfile) {
     match node {
        &ASTNode::Passage(ref t) => {
            debug!("{:?}", t.category);
            match &t.category{
                /*&Token::TokText(ref s) => {

                    //out.op_print(s);
                },
                &Token::TokFormatBold => {
                    out.op_set_text_style(true, false, false, false);
                },
                 &Token::TokFormatItalic => {
                    out.op_set_text_style(false, false, false, true);
                },*/
                _ => {
                    debug!("no match 1");
                }
            };
            for child in &t.childs {
                stuff(child, out);
            }
            out.op_set_text_style(false, false, false, false);
        },
        &ASTNode::Default(ref t) => {
            match &t.category{
                &Token::TokText(ref s) => {
                    out.op_print(s);
                },
                &Token::TokFormatBold => {
                    out.op_set_text_style(true, false, false, false);
                },
                 &Token::TokFormatItalic => {
                    out.op_set_text_style(false, false, false, true);
                },
                _ => {
                    debug!("no match 2");
                }
            };

            for child in &t.childs {
                stuff(child, out);
            }
            out.op_set_text_style(false, false, false, false);
        }
    };
}

impl AST {
    /// convert ast to zcode
    pub fn to_zcode(&self,  out: &mut zfile::Zfile){
        for child in &self.passages {
            stuff(child, out);
        }
    }

    pub fn new() -> AST {
        AST {
            passages: Vec::new()
        }
    }

    /// prints the tree
    pub fn print(&self) {
        debug!("Abstract Syntax Tree: ");
        for child in &self.passages {
            child.print(0);
        }
        debug!("");
    }

    /// adds a passage to the path in the ast
    pub fn add_passage(&mut self, token: Token) {
        let node = ASTNode::Passage(NodePassage { category: token, childs: Vec::new() });
        self.passages.push(node);
    }

    /// adds a child to the path in the ast
    pub fn add_child(&mut self, path: &Vec<usize>, token: Token) {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            self.passages[*index].add_child(new_path, token)
        } else {
            self.passages.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() }));
        }
    }

    /// counts the childs of the path in the asts
    pub fn cound_childs(&self, path: Vec<usize>) -> usize {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            self.passages[*index].cound_childs(new_path)
        } else {
            self.passages.len()
        }
    }
}

// ================================
// node types
enum ASTNode {
    Default (NodeDefault),
    Passage (NodePassage)
}

struct NodePassage {
    category: Token,
    pub childs: Vec<ASTNode>,
    /*tags: Vec<ASTNode>*/
}

struct NodeDefault {
    category: Token,
    childs: Vec<ASTNode>
}

impl ASTNode {
    /// adds an child to the path in the ast
    pub fn add_child(&mut self, path: Vec<usize>, token: Token) {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            match self {
                &mut ASTNode::Default(ref mut node) => node.childs[*index].add_child(new_path, token),
                &mut ASTNode::Passage(ref mut node) => node.childs[*index].add_child(new_path, token),
            }
        } else {
            match self {
                &mut ASTNode::Default(ref mut node) => node.childs.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() } )),
                &mut ASTNode::Passage(ref mut node) => node.childs.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() } )),
            }
        }
    }

    /// counts the childs of the current path in the ast
    pub fn cound_childs(&self, path: Vec<usize>) -> usize {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            match self {
                &ASTNode::Default(ref node) => node.childs[*index].cound_childs(new_path),
                &ASTNode::Passage(ref node) => node.childs[*index].cound_childs(new_path),
            }
        } else {
            match self {
                &ASTNode::Default(ref node) => node.childs.len(),
                &ASTNode::Passage(ref node) => node.childs.len(),
            }
        }
    }

    /// prints an node of an ast
    pub fn print(&self, indent: usize) {
        let mut spaces = "".to_string();
        for _ in 0..indent {
            spaces.push_str(" ");
        }

        match self {
            &ASTNode::Passage(ref t) => {
                debug!("{}|- : {:?}", spaces, t.category);
                for child in &t.childs {
                    child.print(indent+2);
                }
            },
            &ASTNode::Default(ref t) => {
                debug!("{}|- : {:?}", spaces, t.category);
                for child in &t.childs {
                    child.print(indent+2);
                }
            }
        }
    }
}

//==============================
//

#[test]
fn it_works() {

}

<commit_msg>-small changes<commit_after>//! The `ast` module contains a lot of useful functionality
//! to create and walk through the ast (abstract syntaxtree)

use frontend::lexer::Token;
use backend::zcode::zfile;

//==============================
// ast

pub struct AST {
    passages: Vec<ASTNode>
}

/// add zcode based on tokens
fn stuff(node: &ASTNode, mut out: &mut zfile::Zfile) {
     match node {
        &ASTNode::Passage(ref t) => {
            debug!("{:?}", t.category);
            match &t.category{
                /*&Token::TokText(ref s) => {

                    //out.op_print(s);
                },
                &Token::TokFormatBold => {
                    out.op_set_text_style(true, false, false, false);
                },
                 &Token::TokFormatItalic => {
                    out.op_set_text_style(false, false, false, true);
                },*/
                _ => {
                    debug!("no match 1");
                }
            };
            for child in &t.childs {
                stuff(child, out);
            }
            out.op_set_text_style(false, false, false, false);
        },
        &ASTNode::Default(ref t) => {
            match &t.category{
                &Token::TokText(ref s) => {
                    out.op_print(s);
                },
                &Token::TokFormatBold => {
                    out.op_set_text_style(true, false, false, false);
                },
                 &Token::TokFormatItalic => {
                    out.op_set_text_style(false, false, false, true);
                },
                _ => {
                    debug!("no match 2");
                }
            };

            for child in &t.childs {
                stuff(child, out);
            }
            out.op_set_text_style(false, false, false, false);
        }
    };
}

impl AST {
    /// convert ast to zcode
    pub fn to_zcode(&self,  out: &mut zfile::Zfile){
        for child in &self.passages {
            stuff(child, out);
        }
    }

    pub fn new() -> AST {
        AST {
            passages: Vec::new()
        }
    }

    /// prints the tree
    pub fn print(&self) {
        debug!("Abstract Syntax Tree: ");
        for child in &self.passages {
            child.print(0);
        }
        debug!("");
    }

    /// adds a passage to the path in the ast
    pub fn add_passage(&mut self, token: Token) {
        let node = ASTNode::Passage(NodePassage { category: token, childs: Vec::new() });
        self.passages.push(node);
    }

    /// adds a child to the path in the ast
    pub fn add_child(&mut self, path: &Vec<usize>, token: Token) {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            self.passages[*index].add_child(new_path, token)
        } else {
            self.passages.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() }));
        }
    }

    /// counts the childs of the path in the asts
    pub fn cound_childs(&self, path: Vec<usize>) -> usize {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            self.passages[*index].cound_childs(new_path)
        } else {
            self.passages.len()
        }
    }
}

// ================================
// node types
enum ASTNode {
    Default (NodeDefault),
    Passage (NodePassage)
}

struct NodePassage {
    category: Token,
    pub childs: Vec<ASTNode>,
    /*tags: Vec<ASTNode>*/
}

struct NodeDefault {
    category: Token,
    childs: Vec<ASTNode>
}

impl ASTNode {
    /// adds an child to the path in the ast
    pub fn add_child(&mut self, path: Vec<usize>, token: Token) {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            match self {
                &mut ASTNode::Default(ref mut node) => node.childs[*index].add_child(new_path, token),
                &mut ASTNode::Passage(ref mut node) => node.childs[*index].add_child(new_path, token),
            }
        } else {
            match self {
                &mut ASTNode::Default(ref mut node) => node.childs.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() } )),
                &mut ASTNode::Passage(ref mut node) => node.childs.push(ASTNode::Default(NodeDefault { category: token, childs: Vec::new() } )),
            }
        }
    }

    /// counts the childs of the current path in the ast
    pub fn cound_childs(&self, path: Vec<usize>) -> usize {
        if let Some(index) = path.first() {
            let mut new_path: Vec<usize> = path.to_vec();
            new_path.remove(0);

            match self {
                &ASTNode::Default(ref node) => node.childs[*index].cound_childs(new_path),
                &ASTNode::Passage(ref node) => node.childs[*index].cound_childs(new_path),
            }
        } else {
            match self {
                &ASTNode::Default(ref node) => node.childs.len(),
                &ASTNode::Passage(ref node) => node.childs.len(),
            }
        }
    }

    /// prints an node of an ast
    pub fn print(&self, indent: usize) {
        let mut spaces = "".to_string();
        for _ in 0..indent {
            spaces.push_str(" ");
        }

        match self {
            &ASTNode::Passage(ref t) => {
                debug!("{}|- : {:?}", spaces, t.category);
                for child in &t.childs {
                    child.print(indent+2);
                }
            },
            &ASTNode::Default(ref t) => {
                debug!("{}|- : {:?}", spaces, t.category);
                for child in &t.childs {
                    child.print(indent+2);
                }
            }
        }
    }
}

//==============================
//

#[test]
fn it_works() {

}

<|endoftext|>


<commit_before>use parser::Identifier;
use operations::{Operation, Error};
use operations::item_type::{ItemType, FuncArgType};
use operations::scope::{ScopeStack, TypeId};

pub fn define_u8(scope: &mut ScopeStack) -> TypeId {
    // Taking advantage of the scope system to simulate modules
    // This will be replaced with something better in:
    // https://github.com/brain-lang/brain/issues/37
    scope.push_scope();

    let u8_type = scope.declare_type(
        Identifier::from("u8"),
        ItemType::Primitive(1)
    );

    scope.declare_builtin_function(
        // Special method for converting from literal
        // This name is such that it could never be called directly
        // from the language itself
        Identifier::from("std::convert::From<{unsigned integer}>"),
        ItemType::Function {
            // This takes a single literal of the type specific within
            // the curly braces {} in the name
            args: vec![FuncArgType::Array {item: u8_type, size: None}],
            // Return type signifies which type we are declaring supports integer literals
            return_type: u8_type,
        },
        move |scope, args, target| {
            let value = args[0].numeric_literal_value();

            // 8 is the size of this numeric type in bytes
            // We use >= here because 0 is reserved for zero so we
            // have (2^size - 1) numbers available
            if value >= (1 << 8) {
                Err(Error::OverflowingLiteral {
                    typ: scope.get_type(u8_type).clone()
                })
            }
            else {
                Ok(vec![
                    Operation::Increment {
                        target: target.position(),
                        amount: value as usize,
                    }
                ])
            }
        }
    );

    u8_type
}
<commit_msg>Implementing specialized method of [u8; N] for printing to the screen<commit_after>use parser::Identifier;
use operations::{Operation, Error};
use operations::item_type::{ItemType, FuncArgType};
use operations::scope::{ScopeStack, ScopeItem, TypeId};

pub fn define_u8(scope: &mut ScopeStack) -> TypeId {
    // Taking advantage of the scope system to simulate modules
    // This will be replaced with something better in:
    // https://github.com/brain-lang/brain/issues/37
    scope.push_scope();

    let unit_type = scope.unit_type_id();

    let u8_type = scope.declare_type(
        Identifier::from("u8"),
        ItemType::Primitive(1)
    );

    scope.declare_builtin_function(
        // Special method for converting from literal
        // This name is such that it could never be called directly
        // from the language itself
        Identifier::from("std::convert::From<{unsigned integer}>"),
        ItemType::Function {
            // This takes a single literal of the type specific within
            // the curly braces {} in the name
            args: vec![FuncArgType::Array {item: u8_type, size: None}],
            // Return type signifies which type we are declaring supports integer literals
            return_type: u8_type,
        },
        move |scope, args, target| {
            let value = args[0].numeric_literal_value();

            // 8 is the size of this numeric type in bytes
            // We use >= here because 0 is reserved for zero so we
            // have (2^size - 1) numbers available
            if value >= (1 << 8) {
                Err(Error::OverflowingLiteral {
                    typ: scope.get_type(u8_type).clone()
                })
            }
            else {
                Ok(vec![
                    Operation::Increment {
                        target: target.position(),
                        amount: value as usize,
                    }
                ])
            }
        }
    );

    scope.declare_builtin_function(
        // Special method for displaying this primitive (used from print/println)
        // This name is such that it could never be called directly
        // from the language itself
        Identifier::from("std::fmt::Display::print"),
        ItemType::Function {
            args: vec![FuncArgType::Array {item: u8_type, size: None}],
            return_type: unit_type,
        },
        move |scope, args, target| {
            let mem = match args[0] {
                ScopeItem::Array {memory, ..} => memory,
                _ => unreachable!(),
            };

            Ok(vec![
                Operation::Write {
                    target: mem,
                }
            ])
        }
    );

    u8_type
}
<|endoftext|>


<commit_before>/*!
    A box that contains other controls. Can be used to group radio buttons
*/

use std::hash::Hash;

use controls::ControlTemplate;
use controls::base::{WindowBase, create_base, set_window_text, get_window_text,
 get_window_pos, set_window_pos, get_window_size, set_window_size, get_window_parent,
 set_window_parent, get_window_enabled, set_window_enabled, get_window_visibility,
 set_window_visibility, hook_native};
use actions::{Action, ActionReturn};
use events::Event;

use winapi::{HWND, BS_NOTIFY, BS_GROUPBOX};

/**
    Configuration properties to create simple groupbox

    * text: The button text
    * size: The button size (width, height) in pixels
    * position: The button position (x, y) in the parent control
    * parent: The control parent
*/
pub struct GroupBox<ID: Eq+Clone+Hash> {
    pub text: String,
    pub size: (u32, u32),
    pub position: (i32, i32),
    pub parent: ID,
}

impl<ID: Eq+Clone+Hash > ControlTemplate<ID> for GroupBox<ID> {

    fn create(&self, ui: &mut ::Ui<ID>, id: ID) -> Result<HWND, ()> {
        let base = WindowBase::<ID> {
            text: self.text.clone(),
            size: self.size.clone(),
            position: self.position.clone(),
            visible: true,
            resizable: false,
            extra_style: BS_GROUPBOX,
            class: Some("BUTTON".to_string()),
            parent: Some(self.parent.clone())
        };

        unsafe { create_base::<ID>(ui, base) }
    }

    fn supported_events(&self) -> Vec<Event> {
        Vec::new()
    }

    fn evaluator(&self) -> ::ActionEvaluator<ID> {
        Box::new( |ui, id, handle, action| {
            match action {
                Action::SetText(t) => set_window_text(handle, *t),
                Action::GetText => get_window_text(handle),
                Action::GetPosition => get_window_pos(handle, true),
                Action::SetPosition(x, y) => set_window_pos(handle, x, y),
                Action::GetSize => get_window_size(handle),
                Action::SetSize(w, h) => set_window_size(handle, w, h),
                Action::GetParent => get_window_parent(handle),
                Action::SetParent(p) => set_window_parent(ui, handle, *p, true),
                Action::GetEnabled => get_window_enabled(handle),
                Action::SetEnabled(e) => set_window_enabled(handle, e),
                Action::GetVisibility => get_window_visibility(handle),
                Action::SetVisibility(v) => set_window_visibility(handle, v),
                _ => ActionReturn::NotSupported
            }
        })
    }

}<commit_msg>groupbox textalign<commit_after>/*!
    A box that contains other controls. Can be used to group radio buttons
*/

use std::hash::Hash;

use controls::ControlTemplate;
use controls::base::{WindowBase, create_base, set_window_text, get_window_text,
 get_window_pos, set_window_pos, get_window_size, set_window_size, get_window_parent,
 set_window_parent, get_window_enabled, set_window_enabled, get_window_visibility,
 set_window_visibility, hook_native};
use actions::{Action, ActionReturn};
use events::Event;
use constants::HTextAlign;

use winapi::{HWND, BS_GROUPBOX, BS_LEFT, BS_RIGHT, BS_CENTER};

/**
    Configuration properties to create simple groupbox

    * text: The button text
    * size: The button size (width, height) in pixels
    * position: The button position (x, y) in the parent control
    * parent: The control parent
*/
pub struct GroupBox<ID: Eq+Clone+Hash> {
    pub text: String,
    pub size: (u32, u32),
    pub position: (i32, i32),
    pub parent: ID,
    pub text_align: HTextAlign,
}

impl<ID: Eq+Clone+Hash > ControlTemplate<ID> for GroupBox<ID> {

    fn create(&self, ui: &mut ::Ui<ID>, id: ID) -> Result<HWND, ()> {
        let h_align = match self.text_align {
            HTextAlign::Left => BS_LEFT,
            HTextAlign::Right => BS_RIGHT,
            HTextAlign::Center => BS_CENTER
        };

        let base = WindowBase::<ID> {
            text: self.text.clone(),
            size: self.size.clone(),
            position: self.position.clone(),
            visible: true,
            resizable: false,
            extra_style: BS_GROUPBOX | h_align,
            class: Some("BUTTON".to_string()),
            parent: Some(self.parent.clone())
        };

        unsafe { create_base::<ID>(ui, base) }
    }

    fn supported_events(&self) -> Vec<Event> {
        Vec::new()
    }

    fn evaluator(&self) -> ::ActionEvaluator<ID> {
        Box::new( |ui, id, handle, action| {
            match action {
                Action::SetText(t) => set_window_text(handle, *t),
                Action::GetText => get_window_text(handle),
                Action::GetPosition => get_window_pos(handle, true),
                Action::SetPosition(x, y) => set_window_pos(handle, x, y),
                Action::GetSize => get_window_size(handle),
                Action::SetSize(w, h) => set_window_size(handle, w, h),
                Action::GetParent => get_window_parent(handle),
                Action::SetParent(p) => set_window_parent(ui, handle, *p, true),
                Action::GetEnabled => get_window_enabled(handle),
                Action::SetEnabled(e) => set_window_enabled(handle, e),
                Action::GetVisibility => get_window_visibility(handle),
                Action::SetVisibility(v) => set_window_visibility(handle, v),
                _ => ActionReturn::NotSupported
            }
        })
    }

}<|endoftext|>


<commit_before>//! Ignoring globs in `.gitignore` files.
//!
//! This uses a cache because the file with the globs in might not be the same
//! directory that we’re listing!

use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use std::sync::RwLock;

use fs::filter::IgnorePatterns;

/// An **ignore cache** holds sets of glob patterns paired with the
/// directories that they should be ignored underneath. Believe it or not,
/// that’s a valid English sentence.
#[derive(Default, Debug)]
pub struct IgnoreCache {
    entries: RwLock<Vec<(PathBuf, IgnorePatterns)>>
}

impl IgnoreCache {
    pub fn new() -> IgnoreCache {
        IgnoreCache::default()
    }

    pub fn discover_underneath(&self, path: &Path) {
        let mut path = Some(path);
        let mut entries = self.entries.write().unwrap();

        while let Some(p) = path {
            if p.components().next().is_none() { break }

            let ignore_file = p.join(".gitignore");
            if ignore_file.is_file() {
                debug!("Found a .gitignore file: {:?}", ignore_file);
                if let Ok(mut file) = File::open(ignore_file) {
                    let mut contents = String::new();

                    match file.read_to_string(&mut contents) {
                        Ok(_) => {
                            let patterns = file_lines_to_patterns(contents.lines());
                            entries.push((p.into(), patterns));
                        }
                        Err(e) => debug!("Failed to read a .gitignore: {:?}", e)
                    }
                }
            }
            else {
                debug!("Found no .gitignore file at {:?}", ignore_file);
            }

            path = p.parent();
        }
    }

    pub fn is_ignored(&self, suspect: &Path) -> bool {
        let entries = self.entries.read().unwrap();
        entries.iter().any(|&(ref base_path, ref patterns)| {
            if let Ok(suffix) = suspect.strip_prefix(&base_path) {
                patterns.is_ignored_path(suffix)
            }
            else {
                false
            }
        })
    }
}

fn file_lines_to_patterns<'a, I>(iter: I) -> IgnorePatterns
where I: Iterator<Item=&'a str> {
    // Errors are currently being ignored... not a good look
    IgnorePatterns::parse_from_iter(iter).0
}

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

    #[test]
    fn parse_nothing() {
        use std::iter::empty;
        let (patterns, _) = IgnorePatterns::parse_from_iter(empty());
        assert_eq!(patterns, file_lines_to_patterns(empty()));
    }

    #[test]
    fn parse_some_globs() {
        let stuff = vec![ "*.mp3", "README.md" ];
        let (patterns, _) = IgnorePatterns::parse_from_iter(stuff.iter().cloned());
        assert_eq!(patterns, file_lines_to_patterns(stuff.into_iter()));
    }

    #[test]
    fn empty() {
        let ignores = IgnoreCache::default();
        assert_eq!(false, ignores.is_ignored(Path::new("/usr/bin/drinking")));
        assert_eq!(false, ignores.is_ignored(Path::new("target/debug/exa")));
    }
}
<commit_msg>Ignore comments and blank lines when ignoring<commit_after>//! Ignoring globs in `.gitignore` files.
//!
//! This uses a cache because the file with the globs in might not be the same
//! directory that we’re listing!

use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use std::sync::RwLock;

use fs::filter::IgnorePatterns;

/// An **ignore cache** holds sets of glob patterns paired with the
/// directories that they should be ignored underneath. Believe it or not,
/// that’s a valid English sentence.
#[derive(Default, Debug)]
pub struct IgnoreCache {
    entries: RwLock<Vec<(PathBuf, IgnorePatterns)>>
}

impl IgnoreCache {
    pub fn new() -> IgnoreCache {
        IgnoreCache::default()
    }

    pub fn discover_underneath(&self, path: &Path) {
        let mut path = Some(path);
        let mut entries = self.entries.write().unwrap();

        while let Some(p) = path {
            if p.components().next().is_none() { break }

            let ignore_file = p.join(".gitignore");
            if ignore_file.is_file() {
                debug!("Found a .gitignore file: {:?}", ignore_file);
                if let Ok(mut file) = File::open(ignore_file) {
                    let mut contents = String::new();

                    match file.read_to_string(&mut contents) {
                        Ok(_) => {
                            let patterns = file_lines_to_patterns(contents.lines());
                            entries.push((p.into(), patterns));
                        }
                        Err(e) => debug!("Failed to read a .gitignore: {:?}", e)
                    }
                }
            }
            else {
                debug!("Found no .gitignore file at {:?}", ignore_file);
            }

            path = p.parent();
        }
    }

    pub fn is_ignored(&self, suspect: &Path) -> bool {
        let entries = self.entries.read().unwrap();
        entries.iter().any(|&(ref base_path, ref patterns)| {
            if let Ok(suffix) = suspect.strip_prefix(&base_path) {
                patterns.is_ignored_path(suffix)
            }
            else {
                false
            }
        })
    }
}

fn file_lines_to_patterns<'a, I>(iter: I) -> IgnorePatterns
where I: Iterator<Item=&'a str>
{
    let iter = iter.filter(|el| !el.is_empty());
    let iter = iter.filter(|el| !el.starts_with("#"));

    // Errors are currently being ignored... not a good look
    IgnorePatterns::parse_from_iter(iter).0
}

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

    #[test]
    fn parse_nothing() {
        use std::iter::empty;
        let (patterns, _) = IgnorePatterns::parse_from_iter(empty());
        assert_eq!(patterns, file_lines_to_patterns(empty()));
    }

    #[test]
    fn parse_some_globs() {
        let stuff = vec![ "*.mp3", "README.md" ];
        let reals = vec![ "*.mp3", "README.md" ];
        let (patterns, _) = IgnorePatterns::parse_from_iter(reals.into_iter());
        assert_eq!(patterns, file_lines_to_patterns(stuff.into_iter()));
    }

    #[test]
    fn parse_some_comments() {
        let stuff = vec![ "*.mp3", "# I am a comment!", "#", "README.md" ];
        let reals = vec![ "*.mp3",                           "README.md" ];
        let (patterns, _) = IgnorePatterns::parse_from_iter(reals.into_iter());
        assert_eq!(patterns, file_lines_to_patterns(stuff.into_iter()));
    }

    #[test]
    fn parse_some_blank_lines() {
        let stuff = vec![ "*.mp3", "", "", "README.md" ];
        let reals = vec![ "*.mp3",         "README.md" ];
        let (patterns, _) = IgnorePatterns::parse_from_iter(reals.into_iter());
        assert_eq!(patterns, file_lines_to_patterns(stuff.into_iter()));
    }

    #[test]
    fn an_empty_cache_ignores_nothing() {
        let ignores = IgnoreCache::default();
        assert_eq!(false, ignores.is_ignored(Path::new("/usr/bin/drinking")));
        assert_eq!(false, ignores.is_ignored(Path::new("target/debug/exa")));
    }
}
<|endoftext|>


<commit_before>use std::io::{Cursor, Read, Write};
use bytes::Buf;

use input_buffer::{InputBuffer, MIN_READ};
use error::{Error, Result};
use util::NonBlockingResult;

/// A generic handshake state machine.
pub struct HandshakeMachine<Stream> {
    stream: Stream,
    state: HandshakeState,
}

impl<Stream> HandshakeMachine<Stream> {
    /// Start reading data from the peer.
    pub fn start_read(stream: Stream) -> Self {
        HandshakeMachine {
            stream: stream,
            state: HandshakeState::Reading(InputBuffer::with_capacity(MIN_READ)),
        }
    }
    /// Start writing data to the peer.
    pub fn start_write<D: Into<Vec<u8>>>(stream: Stream, data: D) -> Self {
        HandshakeMachine {
            stream: stream,
            state: HandshakeState::Writing(Cursor::new(data.into())),
        }
    }
    /// Returns a shared reference to the inner stream.
    pub fn get_ref(&self) -> &Stream {
        &self.stream
    }
    /// Returns a mutable reference to the inner stream.
    pub fn get_mut(&mut self) -> &mut Stream {
        &mut self.stream
    }
}

impl<Stream: Read + Write> HandshakeMachine<Stream> {
    /// Perform a single handshake round.
    pub fn single_round<Obj: TryParse>(mut self) -> Result<RoundResult<Obj, Stream>> {
        trace!("Doing handshake round.");
        Ok(match self.state {
            HandshakeState::Reading(mut buf) => {
                buf.reserve(MIN_READ, usize::max_value()) // TODO limit size
                    .map_err(|_| Error::Capacity("Header too long".into()))?;
                if let Some(_) = buf.read_from(&mut self.stream).no_block()? {
                    if let Some((size, obj)) = Obj::try_parse(Buf::bytes(&buf))? {
                        buf.advance(size);
                        RoundResult::StageFinished(StageResult::DoneReading {
                            result: obj,
                            stream: self.stream,
                            tail: buf.into_vec(),
                        })
                    } else {
                        RoundResult::Incomplete(HandshakeMachine {
                            state: HandshakeState::Reading(buf),
                            ..self
                        })
                    }
                } else {
                    RoundResult::WouldBlock(HandshakeMachine {
                        state: HandshakeState::Reading(buf),
                        ..self
                    })
                }
            }
            HandshakeState::Writing(mut buf) => {
                if let Some(size) = self.stream.write(Buf::bytes(&buf)).no_block()? {
                    buf.advance(size);
                    if buf.has_remaining() {
                        RoundResult::Incomplete(HandshakeMachine {
                            state: HandshakeState::Writing(buf),
                            ..self
                        })
                    } else {
                        RoundResult::StageFinished(StageResult::DoneWriting(self.stream))
                    }
                } else {
                    RoundResult::WouldBlock(HandshakeMachine {
                        state: HandshakeState::Writing(buf),
                        ..self
                    })
                }
            }
        })
    }
}

/// The result of the round.
pub enum RoundResult<Obj, Stream> {
    /// Round not done, I/O would block.
    WouldBlock(HandshakeMachine<Stream>),
    /// Round done, state unchanged.
    Incomplete(HandshakeMachine<Stream>),
    /// Stage complete.
    StageFinished(StageResult<Obj, Stream>),
}

/// The result of the stage.
pub enum StageResult<Obj, Stream> {
    /// Reading round finished.
    DoneReading { result: Obj, stream: Stream, tail: Vec<u8> },
    /// Writing round finished.
    DoneWriting(Stream),
}

/// The parseable object.
pub trait TryParse: Sized {
    /// Return Ok(None) if incomplete, Err on syntax error.
    fn try_parse(data: &[u8]) -> Result<Option<(usize, Self)>>;
}

/// The handshake state.
enum HandshakeState {
    /// Reading data from the peer.
    Reading(InputBuffer),
    /// Sending data to the peer.
    Writing(Cursor<Vec<u8>>),
}
<commit_msg>Fix possible deadlock in handshake.<commit_after>use std::io::{Cursor, Read, Write};
use bytes::Buf;

use input_buffer::{InputBuffer, MIN_READ};
use error::{Error, Result};
use util::NonBlockingResult;

/// A generic handshake state machine.
pub struct HandshakeMachine<Stream> {
    stream: Stream,
    state: HandshakeState,
}

impl<Stream> HandshakeMachine<Stream> {
    /// Start reading data from the peer.
    pub fn start_read(stream: Stream) -> Self {
        HandshakeMachine {
            stream: stream,
            state: HandshakeState::Reading(InputBuffer::with_capacity(MIN_READ)),
        }
    }
    /// Start writing data to the peer.
    pub fn start_write<D: Into<Vec<u8>>>(stream: Stream, data: D) -> Self {
        HandshakeMachine {
            stream: stream,
            state: HandshakeState::Writing(Cursor::new(data.into())),
        }
    }
    /// Returns a shared reference to the inner stream.
    pub fn get_ref(&self) -> &Stream {
        &self.stream
    }
    /// Returns a mutable reference to the inner stream.
    pub fn get_mut(&mut self) -> &mut Stream {
        &mut self.stream
    }
}

impl<Stream: Read + Write> HandshakeMachine<Stream> {
    /// Perform a single handshake round.
    pub fn single_round<Obj: TryParse>(mut self) -> Result<RoundResult<Obj, Stream>> {
        trace!("Doing handshake round.");
        match self.state {
            HandshakeState::Reading(mut buf) => {
                buf.reserve(MIN_READ, usize::max_value()) // TODO limit size
                    .map_err(|_| Error::Capacity("Header too long".into()))?;
                match buf.read_from(&mut self.stream).no_block()? {
                    Some(0) => {
                        Err(Error::Protocol("Handshake not finished".into()))
                    }
                    Some(_) => {
                        Ok(if let Some((size, obj)) = Obj::try_parse(Buf::bytes(&buf))? {
                            buf.advance(size);
                            RoundResult::StageFinished(StageResult::DoneReading {
                                result: obj,
                                stream: self.stream,
                                tail: buf.into_vec(),
                            })
                        } else {
                            RoundResult::Incomplete(HandshakeMachine {
                                state: HandshakeState::Reading(buf),
                                ..self
                            })
                        })
                    }
                    None => {
                        Ok(RoundResult::WouldBlock(HandshakeMachine {
                            state: HandshakeState::Reading(buf),
                            ..self
                        }))
                    }
                }
            }
            HandshakeState::Writing(mut buf) => {
                assert!(buf.has_remaining());
                if let Some(size) = self.stream.write(Buf::bytes(&buf)).no_block()? {
                    assert!(size > 0);
                    buf.advance(size);
                    Ok(if buf.has_remaining() {
                        RoundResult::Incomplete(HandshakeMachine {
                            state: HandshakeState::Writing(buf),
                            ..self
                        })
                    } else {
                        RoundResult::StageFinished(StageResult::DoneWriting(self.stream))
                    })
                } else {
                    Ok(RoundResult::WouldBlock(HandshakeMachine {
                        state: HandshakeState::Writing(buf),
                        ..self
                    }))
                }
            }
        }
    }
}

/// The result of the round.
pub enum RoundResult<Obj, Stream> {
    /// Round not done, I/O would block.
    WouldBlock(HandshakeMachine<Stream>),
    /// Round done, state unchanged.
    Incomplete(HandshakeMachine<Stream>),
    /// Stage complete.
    StageFinished(StageResult<Obj, Stream>),
}

/// The result of the stage.
pub enum StageResult<Obj, Stream> {
    /// Reading round finished.
    DoneReading { result: Obj, stream: Stream, tail: Vec<u8> },
    /// Writing round finished.
    DoneWriting(Stream),
}

/// The parseable object.
pub trait TryParse: Sized {
    /// Return Ok(None) if incomplete, Err on syntax error.
    fn try_parse(data: &[u8]) -> Result<Option<(usize, Self)>>;
}

/// The handshake state.
enum HandshakeState {
    /// Reading data from the peer.
    Reading(InputBuffer),
    /// Sending data to the peer.
    Writing(Cursor<Vec<u8>>),
}
<|endoftext|>


<commit_before>use super::{Open, Sink};
use std::io;
use libpulse_sys::*;
use std::ptr::{null, null_mut};
use std::mem::{transmute};
use std::ffi::CString;

pub struct PulseAudioSink(*mut pa_simple);

impl Open for PulseAudioSink {
   fn open() -> PulseAudioSink {
        println!("Using PulseAudioSink");

        let ss = pa_sample_spec {
            format: PA_SAMPLE_S16LE,
            channels: 2, // stereo
            rate: 44100
        };

        let name = CString::new("librespot").unwrap();
        let description = CString::new("A spoty client library").unwrap();

        let s = unsafe {
            pa_simple_new(null(),               // Use the default server.
                          name.as_ptr(),        // Our application's name.
                          PA_STREAM_PLAYBACK,
                          null(),               // Use the default device.
                          description.as_ptr(), // Description of our stream.
                          &ss,                  // Our sample format.
                          null(),               // Use default channel map
                          null(),               // Use default buffering attributes.
                          null_mut(),           // Ignore error code.
            )
        };
        assert!(s != null_mut());

        PulseAudioSink(s)
    }
}

impl Sink for PulseAudioSink {
    fn start(&self) -> io::Result<()> {
        Ok(())
    }

    fn stop(&self) -> io::Result<()> {
        Ok(())
    }

    fn write(&self, data: &[i16]) -> io::Result<()> {
        unsafe {
            let ptr = transmute(data.as_ptr());
            let bytes = data.len() as u64 * 2;
            pa_simple_write(self.0, ptr, bytes, null_mut());
        };

        Ok(())
    }
}

<commit_msg>Use usize for pointer size<commit_after>use super::{Open, Sink};
use std::io;
use libpulse_sys::*;
use std::ptr::{null, null_mut};
use std::mem::{transmute};
use std::ffi::CString;

pub struct PulseAudioSink(*mut pa_simple);

impl Open for PulseAudioSink {
   fn open() -> PulseAudioSink {
        println!("Using PulseAudioSink");

        let ss = pa_sample_spec {
            format: PA_SAMPLE_S16LE,
            channels: 2, // stereo
            rate: 44100
        };

        let name = CString::new("librespot").unwrap();
        let description = CString::new("A spoty client library").unwrap();

        let s = unsafe {
            pa_simple_new(null(),               // Use the default server.
                          name.as_ptr(),        // Our application's name.
                          PA_STREAM_PLAYBACK,
                          null(),               // Use the default device.
                          description.as_ptr(), // Description of our stream.
                          &ss,                  // Our sample format.
                          null(),               // Use default channel map
                          null(),               // Use default buffering attributes.
                          null_mut(),           // Ignore error code.
            )
        };
        assert!(s != null_mut());

        PulseAudioSink(s)
    }
}

impl Sink for PulseAudioSink {
    fn start(&self) -> io::Result<()> {
        Ok(())
    }

    fn stop(&self) -> io::Result<()> {
        Ok(())
    }

    fn write(&self, data: &[i16]) -> io::Result<()> {
        unsafe {
            let ptr = transmute(data.as_ptr());
            let bytes = data.len() as usize * 2;
            pa_simple_write(self.0, ptr, bytes, null_mut());
        };

        Ok(())
    }
}

<|endoftext|>


<commit_before>use super::{
    general::{doc_alias, doc_hidden},
    property_body,
};
use crate::{
    analysis::{child_properties::ChildProperty, rust_type::RustType},
    chunk::Chunk,
    env::Env,
    library,
    traits::IntoString,
    writer::{primitives::tabs, ToCode},
};
use std::io::{Result, Write};

pub fn generate(
    w: &mut dyn Write,
    env: &Env,
    prop: &ChildProperty,
    in_trait: bool,
    only_declaration: bool,
    indent: usize,
) -> Result<()> {
    generate_func(w, env, prop, in_trait, only_declaration, indent, true)?;
    generate_func(w, env, prop, in_trait, only_declaration, indent, false)?;

    Ok(())
}

fn generate_func(
    w: &mut dyn Write,
    env: &Env,
    prop: &ChildProperty,
    in_trait: bool,
    only_declaration: bool,
    indent: usize,
    is_get: bool,
) -> Result<()> {
    let pub_prefix = if in_trait { "" } else { "pub " };
    let decl_suffix = if only_declaration { ";" } else { " {" };
    let type_string = RustType::try_new(env, prop.typ);
    let comment_prefix = if type_string.is_err() { "//" } else { "" };

    writeln!(w)?;

    doc_hidden(w, prop.doc_hidden, comment_prefix, indent)?;
    let decl = declaration(env, prop, is_get);
    if !in_trait || only_declaration {
        let add_doc_alias = if is_get {
            prop.name != prop.getter_name && prop.name != prop.prop_name
        } else {
            prop.name != prop.prop_name
        };
        if add_doc_alias {
            doc_alias(
                w,
                &format!("{}.{}", &prop.child_name, &prop.name),
                comment_prefix,
                indent,
            )?;
        }
    }
    writeln!(
        w,
        "{}{}{}{}{}",
        tabs(indent),
        comment_prefix,
        pub_prefix,
        decl,
        decl_suffix
    )?;

    if !only_declaration {
        let body = body(env, prop, in_trait, is_get).to_code(env);
        for s in body {
            writeln!(w, "{}{}{}", tabs(indent), comment_prefix, s)?;
        }
    }

    Ok(())
}

fn declaration(env: &Env, prop: &ChildProperty, is_get: bool) -> String {
    let func_name = if is_get {
        format!("{}_{}", prop.child_name, prop.getter_name)
    } else {
        format!("set_{}_{}", prop.child_name, prop.prop_name)
    };
    let mut bounds = if let Some(typ) = prop.child_type {
        let child_type = RustType::try_new(env, typ).into_string();
        format!("T: IsA<{}>", child_type)
    } else {
        "T: IsA<Widget>".to_string()
    };
    if !is_get && !prop.bounds.is_empty() {
        bounds = format!("{}, {}", prop.bounds, bounds);
    }
    let return_str = if is_get {
        let dir = library::ParameterDirection::Return;
        let ret_type = RustType::builder(env, prop.typ)
            .direction(dir)
            .nullable(prop.nullable)
            .ref_mode(prop.get_out_ref_mode)
            .try_build_param()
            .into_string();
        format!(" -> {}", ret_type)
    } else {
        "".to_string()
    };
    format!(
        "fn {}<{}>(&self, item: &T{}){}",
        func_name,
        bounds,
        if is_get {
            "".to_owned()
        } else {
            format!(", {}", prop.set_params)
        },
        return_str
    )
}

fn body(env: &Env, prop: &ChildProperty, in_trait: bool, is_get: bool) -> Chunk {
    let mut builder = property_body::Builder::new_for_child_property(env);
    builder
        .name(&prop.name)
        .in_trait(in_trait)
        .var_name(&prop.prop_name)
        .is_get(is_get);

    if let Ok(type_) = RustType::try_new(env, prop.typ) {
        builder.type_(type_.as_str());
    } else {
        builder.type_("/*Unknown type*/");
    }

    builder.generate()
}
<commit_msg>codgen: don't assume child props are gtk only<commit_after>use super::{
    general::{doc_alias, doc_hidden},
    property_body,
};
use crate::{
    analysis::{child_properties::ChildProperty, rust_type::RustType},
    chunk::Chunk,
    env::Env,
    library,
    nameutil::use_gtk_type,
    traits::IntoString,
    writer::{primitives::tabs, ToCode},
};
use std::io::{Result, Write};

pub fn generate(
    w: &mut dyn Write,
    env: &Env,
    prop: &ChildProperty,
    in_trait: bool,
    only_declaration: bool,
    indent: usize,
) -> Result<()> {
    generate_func(w, env, prop, in_trait, only_declaration, indent, true)?;
    generate_func(w, env, prop, in_trait, only_declaration, indent, false)?;

    Ok(())
}

fn generate_func(
    w: &mut dyn Write,
    env: &Env,
    prop: &ChildProperty,
    in_trait: bool,
    only_declaration: bool,
    indent: usize,
    is_get: bool,
) -> Result<()> {
    let pub_prefix = if in_trait { "" } else { "pub " };
    let decl_suffix = if only_declaration { ";" } else { " {" };
    let type_string = RustType::try_new(env, prop.typ);
    let comment_prefix = if type_string.is_err() { "//" } else { "" };

    writeln!(w)?;

    doc_hidden(w, prop.doc_hidden, comment_prefix, indent)?;
    let decl = declaration(env, prop, is_get);
    if !in_trait || only_declaration {
        let add_doc_alias = if is_get {
            prop.name != prop.getter_name && prop.name != prop.prop_name
        } else {
            prop.name != prop.prop_name
        };
        if add_doc_alias {
            doc_alias(
                w,
                &format!("{}.{}", &prop.child_name, &prop.name),
                comment_prefix,
                indent,
            )?;
        }
    }
    writeln!(
        w,
        "{}{}{}{}{}",
        tabs(indent),
        comment_prefix,
        pub_prefix,
        decl,
        decl_suffix
    )?;

    if !only_declaration {
        let body = body(env, prop, in_trait, is_get).to_code(env);
        for s in body {
            writeln!(w, "{}{}{}", tabs(indent), comment_prefix, s)?;
        }
    }

    Ok(())
}

fn declaration(env: &Env, prop: &ChildProperty, is_get: bool) -> String {
    let func_name = if is_get {
        format!("{}_{}", prop.child_name, prop.getter_name)
    } else {
        format!("set_{}_{}", prop.child_name, prop.prop_name)
    };
    let mut bounds = if let Some(typ) = prop.child_type {
        let child_type = RustType::try_new(env, typ).into_string();
        format!("T: IsA<{}>", child_type)
    } else {
        format!("T: IsA<{}>", use_gtk_type(env, "Widget"))
    };
    if !is_get && !prop.bounds.is_empty() {
        bounds = format!("{}, {}", prop.bounds, bounds);
    }
    let return_str = if is_get {
        let dir = library::ParameterDirection::Return;
        let ret_type = RustType::builder(env, prop.typ)
            .direction(dir)
            .nullable(prop.nullable)
            .ref_mode(prop.get_out_ref_mode)
            .try_build_param()
            .into_string();
        format!(" -> {}", ret_type)
    } else {
        "".to_string()
    };
    format!(
        "fn {}<{}>(&self, item: &T{}){}",
        func_name,
        bounds,
        if is_get {
            "".to_owned()
        } else {
            format!(", {}", prop.set_params)
        },
        return_str
    )
}

fn body(env: &Env, prop: &ChildProperty, in_trait: bool, is_get: bool) -> Chunk {
    let mut builder = property_body::Builder::new_for_child_property(env);
    builder
        .name(&prop.name)
        .in_trait(in_trait)
        .var_name(&prop.prop_name)
        .is_get(is_get);

    if let Ok(type_) = RustType::try_new(env, prop.typ) {
        builder.type_(type_.as_str());
    } else {
        builder.type_("/*Unknown type*/");
    }

    builder.generate()
}
<|endoftext|>


<commit_before>use hir::{HasSource, InFile};
use ide_db::assists::{AssistId, AssistKind};
use syntax::{
    ast::{self, edit::IndentLevel},
    AstNode, TextSize,
};

use crate::assist_context::{AssistContext, Assists};

// Assist: generate_enum_variant
//
// Adds a variant to an enum.
//
// ```
// enum Countries {
//     Ghana,
// }
//
// fn main() {
//     let country = Countries::Lesotho$0;
// }
// ```
// ->
// ```
// enum Countries {
//     Ghana,
//     Lesotho,
// }
//
// fn main() {
//     let country = Countries::Lesotho;
// }
// ```
pub(crate) fn generate_enum_variant(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let path_expr: ast::PathExpr = ctx.find_node_at_offset()?;
    let path = path_expr.path()?;

    if ctx.sema.resolve_path(&path).is_some() {
        // No need to generate anything if the path resolves
        return None;
    }

    let name_ref = path.segment()?.name_ref()?;
    if name_ref.text().starts_with(char::is_lowercase) {
        // Don't suggest generating variant if the name starts with a lowercase letter
        return None;
    }

    if let Some(hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Enum(e)))) =
        ctx.sema.resolve_path(&path.qualifier()?)
    {
        let target = path.syntax().text_range();
        return add_variant_to_accumulator(acc, ctx, target, e, &name_ref);
    }

    None
}

fn add_variant_to_accumulator(
    acc: &mut Assists,
    ctx: &AssistContext,
    target: syntax::TextRange,
    adt: hir::Enum,
    name_ref: &ast::NameRef,
) -> Option<()> {
    let db = ctx.db();
    let InFile { file_id, value: enum_node } = adt.source(db)?.original_ast_node(db)?;
    let enum_indent = IndentLevel::from_node(&enum_node.syntax());

    let variant_list = enum_node.variant_list()?;
    let offset = variant_list.syntax().text_range().end() - TextSize::of('}');
    let empty_enum = variant_list.variants().next().is_none();

    acc.add(
        AssistId("generate_enum_variant", AssistKind::Generate),
        "Generate variant",
        target,
        |builder| {
            builder.edit_file(file_id.original_file(db));
            let text = format!(
                "{maybe_newline}{indent_1}{name},\n{enum_indent}",
                maybe_newline = if empty_enum { "\n" } else { "" },
                indent_1 = IndentLevel(1),
                name = name_ref,
                enum_indent = enum_indent
            );
            builder.insert(offset, text)
        },
    )
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn generate_basic_enum_variant_in_empty_enum() {
        check_assist(
            generate_enum_variant,
            r"
enum Foo {}
fn main() {
    Foo::Bar$0
}
",
            r"
enum Foo {
    Bar,
}
fn main() {
    Foo::Bar
}
",
        )
    }

    #[test]
    fn generate_basic_enum_variant_in_non_empty_enum() {
        check_assist(
            generate_enum_variant,
            r"
enum Foo {
    Bar,
}
fn main() {
    Foo::Baz$0
}
",
            r"
enum Foo {
    Bar,
    Baz,
}
fn main() {
    Foo::Baz
}
",
        )
    }

    #[test]
    fn not_applicable_for_existing_variant() {
        check_assist_not_applicable(
            generate_enum_variant,
            r"
enum Foo {
    Bar,
}
fn main() {
    Foo::Bar$0
}
",
        )
    }

    #[test]
    fn not_applicable_for_lowercase() {
        check_assist_not_applicable(
            generate_enum_variant,
            r"
enum Foo {
    Bar,
}
fn main() {
    Foo::new$0
}
",
        )
    }

    #[test]
    fn indentation_level_is_correct() {
        check_assist(
            generate_enum_variant,
            r"
mod m {
    enum Foo {
        Bar,
    }
}
fn main() {
    m::Foo::Baz$0
}
",
            r"
mod m {
    enum Foo {
        Bar,
        Baz,
    }
}
fn main() {
    m::Foo::Baz
}
",
        )
    }
}
<commit_msg>Add test for #12372 (generate enum variant in different file)<commit_after>use hir::{HasSource, InFile};
use ide_db::assists::{AssistId, AssistKind};
use syntax::{
    ast::{self, edit::IndentLevel},
    AstNode, TextSize,
};

use crate::assist_context::{AssistContext, Assists};

// Assist: generate_enum_variant
//
// Adds a variant to an enum.
//
// ```
// enum Countries {
//     Ghana,
// }
//
// fn main() {
//     let country = Countries::Lesotho$0;
// }
// ```
// ->
// ```
// enum Countries {
//     Ghana,
//     Lesotho,
// }
//
// fn main() {
//     let country = Countries::Lesotho;
// }
// ```
pub(crate) fn generate_enum_variant(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let path_expr: ast::PathExpr = ctx.find_node_at_offset()?;
    let path = path_expr.path()?;

    if ctx.sema.resolve_path(&path).is_some() {
        // No need to generate anything if the path resolves
        return None;
    }

    let name_ref = path.segment()?.name_ref()?;
    if name_ref.text().starts_with(char::is_lowercase) {
        // Don't suggest generating variant if the name starts with a lowercase letter
        return None;
    }

    if let Some(hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Enum(e)))) =
        ctx.sema.resolve_path(&path.qualifier()?)
    {
        let target = path.syntax().text_range();
        return add_variant_to_accumulator(acc, ctx, target, e, &name_ref);
    }

    None
}

fn add_variant_to_accumulator(
    acc: &mut Assists,
    ctx: &AssistContext,
    target: syntax::TextRange,
    adt: hir::Enum,
    name_ref: &ast::NameRef,
) -> Option<()> {
    let db = ctx.db();
    let InFile { file_id, value: enum_node } = adt.source(db)?.original_ast_node(db)?;
    let enum_indent = IndentLevel::from_node(&enum_node.syntax());

    let variant_list = enum_node.variant_list()?;
    let offset = variant_list.syntax().text_range().end() - TextSize::of('}');
    let empty_enum = variant_list.variants().next().is_none();

    acc.add(
        AssistId("generate_enum_variant", AssistKind::Generate),
        "Generate variant",
        target,
        |builder| {
            builder.edit_file(file_id.original_file(db));
            let text = format!(
                "{maybe_newline}{indent_1}{name},\n{enum_indent}",
                maybe_newline = if empty_enum { "\n" } else { "" },
                indent_1 = IndentLevel(1),
                name = name_ref,
                enum_indent = enum_indent
            );
            builder.insert(offset, text)
        },
    )
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn generate_basic_enum_variant_in_empty_enum() {
        check_assist(
            generate_enum_variant,
            r"
enum Foo {}
fn main() {
    Foo::Bar$0
}
",
            r"
enum Foo {
    Bar,
}
fn main() {
    Foo::Bar
}
",
        )
    }

    #[test]
    fn generate_basic_enum_variant_in_non_empty_enum() {
        check_assist(
            generate_enum_variant,
            r"
enum Foo {
    Bar,
}
fn main() {
    Foo::Baz$0
}
",
            r"
enum Foo {
    Bar,
    Baz,
}
fn main() {
    Foo::Baz
}
",
        )
    }

    #[test]
    fn generate_basic_enum_variant_in_different_file() {
        check_assist(
            generate_enum_variant,
            r"
//- /main.rs
mod foo;
use foo::Foo;

fn main() {
    Foo::Baz$0
}

//- /foo.rs
enum Foo {
    Bar,
}
",
            r"
//- /main.rs
mod foo;
use foo::Foo;

fn main() {
    Foo::Baz
}

//- /foo.rs
enum Foo {
    Bar,
    Baz,
}

",
        )
    }

    #[test]
    fn not_applicable_for_existing_variant() {
        check_assist_not_applicable(
            generate_enum_variant,
            r"
enum Foo {
    Bar,
}
fn main() {
    Foo::Bar$0
}
",
        )
    }

    #[test]
    fn not_applicable_for_lowercase() {
        check_assist_not_applicable(
            generate_enum_variant,
            r"
enum Foo {
    Bar,
}
fn main() {
    Foo::new$0
}
",
        )
    }

    #[test]
    fn indentation_level_is_correct() {
        check_assist(
            generate_enum_variant,
            r"
mod m {
    enum Foo {
        Bar,
    }
}
fn main() {
    m::Foo::Baz$0
}
",
            r"
mod m {
    enum Foo {
        Bar,
        Baz,
    }
}
fn main() {
    m::Foo::Baz
}
",
        )
    }
}
<|endoftext|>