<commit_before>use std::default::Default;
use ::internal::prelude::*;

macro_rules! colour {
    ($struct_:ident; $(#[$attr:meta] $name:ident, $val:expr;)*) => {
        impl $struct_ {
            $(
                #[$attr]
                pub fn $name() -> Colour {
                    Colour::new($val)
                }
            )*
        }
    }
}

/// A utility struct to help with working with the basic representation of a
/// colour. This is particularly useful when working with a [`Role`]'s colour,
/// as the API works with an integer value instead of an RGB value.
///
/// Instances can be created by using the struct's associated functions. These
/// produce presets equivilant to those found in the official client's colour
/// picker.
///
/// # Examples
///
/// Passing in a role's colour, and then retrieving its green component
/// via [`get_g`]:
///
/// ```rust,ignore
/// use serenity::utils::Colour;
///
/// // assuming a `role` has already been bound
///
/// let colour = Colour::new(role.colour);
/// let green = colour.get_g();
///
/// println!("The green component is: {}", green);
/// ```
///
/// Creating an instance with the [`dark_teal`] presets:
///
/// ```rust
/// use serenity::utils::Colour;
///
/// let colour = Colour::dark_teal();
///
/// assert_eq!(colour.get_tuple(), (17, 128, 106));
/// ```
///
/// [`Role`]: ../model/struct.Role.html
/// [`dark_teal`]: #method.dark_teal
/// [`get_g`]: #method.get_g
#[derive(Clone, Copy, Debug)]
pub struct Colour {
    /// The raw inner 32-bit unsigned integer value of this Colour. This is
    /// worked with to generate values such as the red component value.
    pub value: u32,
}

impl Colour {
    /// Generates a new Colour with the given integer value set.
    ///
    /// # Examples
    ///
    /// Create a new Colour, and then ensure that its inner value is equivilant
    /// to a specific RGB value, retrieved via [`get_tuple`]:
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// let colour = Colour::new(6573123);
    ///
    /// assert_eq!(colour.get_tuple(), (100, 76, 67));
    /// ```
    ///
    /// [`get_tuple`]: #method.get_tuple
    pub fn new(value: u32) -> Colour {
        Colour {
            value: value,
        }
    }

    /// Generates a new Colour from an RGB value, creating an inner u32
    /// representation.
    ///
    /// # Examples
    ///
    /// Creating a `Colour` via its RGB values will set its inner u32 correctly:
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert!(Colour::from_rgb(255, 0, 0).value == 0xFF0000);
    /// assert!(Colour::from_rgb(217, 23, 211).value == 0xD917D3);
    /// ```
    ///
    /// And you can then retrieve those same RGB values via its methods:
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// let colour = Colour::from_rgb(217, 45, 215);
    ///
    /// assert_eq!(colour.get_r(), 217);
    /// assert_eq!(colour.get_g(), 45);
    /// assert_eq!(colour.get_b(), 215);
    /// assert_eq!(colour.get_tuple(), (217, 45, 215));
    /// ```
    pub fn from_rgb(r: u8, g: u8, b: u8) -> Colour {
        let mut uint = r as u32;
        uint = (uint << 8) | (g as u32);
        uint = (uint << 8) | (b as u32);

        Colour::new(uint)
    }

    #[doc(hidden)]
    pub fn decode(value: Value) -> Result<Colour> {
        match value {
            Value::U64(v) => Ok(Colour::new(v as u32)),
            Value::I64(v) => Ok(Colour::new(v as u32)),
            other => Err(Error::Decode("Expected valid colour", other)),
        }
    }

    /// Returns the red RGB component of this Colour.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::new(6573123).get_r(), 100);
    /// ```
    pub fn get_r(&self) -> u8 {
        ((self.value >> 16) & 255) as u8
    }

    /// Returns the green RGB component of this Colour.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::new(6573123).get_g(), 76);
    /// ```
    pub fn get_g(&self) -> u8 {
        ((self.value >> 8) & 255) as u8
    }

    /// Returns the blue RGB component of this Colour.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::new(6573123).get_b(), 67);
    pub fn get_b(&self) -> u8 {
        (self.value & 255) as u8
    }

    /// Returns a tuple of the red, green, and blue components of this Colour.
    ///
    /// This is equivilant to creating a tuple with the return values of
    /// [`get_r`], [`get_g`], and [`get_b`].
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::new(6573123).get_tuple(), (100, 76, 67));
    /// ```
    ///
    /// [`get_r`]: #method.get_r
    /// [`get_g`]: #method.get_g
    /// [`get_b`]: #method.get_b
    pub fn get_tuple(&self) -> (u8, u8, u8) {
        (self.get_r(), self.get_g(), self.get_b())
    }
}

impl From<i32> for Colour {
    /// Constructs a Colour from a i32.
    ///
    /// This is used for functions that accept `Into<Colour>`.
    ///
    /// This is useful when providing hex values.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::from(0xDEA584).get_tuple(), (222, 165, 132));
    /// ```
    fn from(value: i32) -> Colour {
        Colour::new(value as u32)
    }
}

impl From<u32> for Colour {
    /// Constructs a Colour from a u32.
    ///
    /// This is used for functions that accept `Into<Colour>`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::from(6573123u32).get_r(), 100);
    /// ```
    fn from(value: u32) -> Colour {
        Colour::new(value)
    }
}

impl From<u64> for Colour {
    /// Constructs a Colour from a u32.
    ///
    /// This is used for functions that accept `Into<Colour>`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::from(6573123u64).get_r(), 100);
    /// ```
    fn from(value: u64) -> Colour {
        Colour::new(value as u32)
    }
}

colour! {
    Colour;
    /// Creates a new `Colour`, setting its RGB value to `(111, 198, 226)`.
    blitz_blue, 0x6FC6E2;
    /// Creates a new `Colour`, setting its RGB value to `(52, 152, 219)`.
    blue, 0x3498DB;
    /// Creates a new `Colour`, setting its RGB value to `(114, 137, 218)`.
    blurple, 0x7289DA;
    /// Creates a new `Colour`, setting its RGB value to `(32, 102, 148)`.
    dark_blue, 0x206694;
    /// Creates a new `Colour`, setting its RGB value to `(31, 139, 76)`.
    dark_green, 0x1F8B4C;
    /// Creates a new `Colour`, setting its RGB value to `(194, 124, 14)`.
    dark_gold, 0xC27C0E;
    /// Creates a new `Colour`, setting its RGB value to `(96, 125, 139)`.
    dark_grey, 0x607D8B;
    /// Creates a new `Colour`, setting its RGB value to `(173, 20, 87)`.
    dark_magenta, 0xAD1457;
    /// Creates a new `Colour`, setting its RGB value to `(168, 67, 0)`.
    dark_orange, 0xA84300;
    /// Creates a new `Colour`, setting its RGB value to `(113, 54, 138)`.
    dark_purple, 0x71368A;
    /// Creates a new `Colour`, setting its RGB value to `(153, 45, 34)`.
    dark_red, 0x992D22;
    /// Creates a new `Colour`, setting its RGB value to `(17, 128, 106)`.
    dark_teal, 0x11806A;
    /// Creates a new `Colour`, setting its RGB value to `(84, 110, 122)`.
    darker_grey, 0x546E7A;
    /// Creates a new `Colour`, setting its RGB value to `(241, 196, 15)`.
    gold, 0xF1C40F;
    /// Creates a new `Colour`, setting its RGB value to `(186, 218, 85)`.
    kerbal, 0xBADA55;
    /// Creates a new `Colour`, setting its RGB value to `(151, 156, 159)`.
    light_grey, 0x979C9F;
    /// Creates a new `Colour`, setting its RGB value to `(149, 165, 166)`.
    lighter_grey, 0x95A5A6;
    /// Creates a new `Colour`, setting its RGB value to `(233, 30, 99)`.
    magenta, 0xE91E63;
    /// Creates a new `Colour`, setting its RGB value to `(230, 126, 34)`.
    orange, 0xE67E22;
    /// Creates a new `Colour`, setting its RGB value to `(155, 89, 182)`.
    purple, 0x9B59B6;
    /// Creates a new `Colour`, setting its RGB value to `(231, 76, 60)`.
    red, 0xE74C3C;
    /// Creates a new `Colour`, setting its RGB value to `(26, 188, 156)`.
    teal, 0x1ABC9C;
}

impl Default for Colour {
    /// Creates a default value for a `Colour`, setting the inner value to `0`.
    /// This is equivilant to setting the RGB value to `(0, 0, 0)`.
    fn default() -> Colour {
        Colour {
            value: 0,
        }
    }
}
<commit_msg>Re-order dark_green colour alphabetically<commit_after>use std::default::Default;
use ::internal::prelude::*;

macro_rules! colour {
    ($struct_:ident; $(#[$attr:meta] $name:ident, $val:expr;)*) => {
        impl $struct_ {
            $(
                #[$attr]
                pub fn $name() -> Colour {
                    Colour::new($val)
                }
            )*
        }
    }
}

/// A utility struct to help with working with the basic representation of a
/// colour. This is particularly useful when working with a [`Role`]'s colour,
/// as the API works with an integer value instead of an RGB value.
///
/// Instances can be created by using the struct's associated functions. These
/// produce presets equivilant to those found in the official client's colour
/// picker.
///
/// # Examples
///
/// Passing in a role's colour, and then retrieving its green component
/// via [`get_g`]:
///
/// ```rust,ignore
/// use serenity::utils::Colour;
///
/// // assuming a `role` has already been bound
///
/// let colour = Colour::new(role.colour);
/// let green = colour.get_g();
///
/// println!("The green component is: {}", green);
/// ```
///
/// Creating an instance with the [`dark_teal`] presets:
///
/// ```rust
/// use serenity::utils::Colour;
///
/// let colour = Colour::dark_teal();
///
/// assert_eq!(colour.get_tuple(), (17, 128, 106));
/// ```
///
/// [`Role`]: ../model/struct.Role.html
/// [`dark_teal`]: #method.dark_teal
/// [`get_g`]: #method.get_g
#[derive(Clone, Copy, Debug)]
pub struct Colour {
    /// The raw inner 32-bit unsigned integer value of this Colour. This is
    /// worked with to generate values such as the red component value.
    pub value: u32,
}

impl Colour {
    /// Generates a new Colour with the given integer value set.
    ///
    /// # Examples
    ///
    /// Create a new Colour, and then ensure that its inner value is equivilant
    /// to a specific RGB value, retrieved via [`get_tuple`]:
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// let colour = Colour::new(6573123);
    ///
    /// assert_eq!(colour.get_tuple(), (100, 76, 67));
    /// ```
    ///
    /// [`get_tuple`]: #method.get_tuple
    pub fn new(value: u32) -> Colour {
        Colour {
            value: value,
        }
    }

    /// Generates a new Colour from an RGB value, creating an inner u32
    /// representation.
    ///
    /// # Examples
    ///
    /// Creating a `Colour` via its RGB values will set its inner u32 correctly:
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert!(Colour::from_rgb(255, 0, 0).value == 0xFF0000);
    /// assert!(Colour::from_rgb(217, 23, 211).value == 0xD917D3);
    /// ```
    ///
    /// And you can then retrieve those same RGB values via its methods:
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// let colour = Colour::from_rgb(217, 45, 215);
    ///
    /// assert_eq!(colour.get_r(), 217);
    /// assert_eq!(colour.get_g(), 45);
    /// assert_eq!(colour.get_b(), 215);
    /// assert_eq!(colour.get_tuple(), (217, 45, 215));
    /// ```
    pub fn from_rgb(r: u8, g: u8, b: u8) -> Colour {
        let mut uint = r as u32;
        uint = (uint << 8) | (g as u32);
        uint = (uint << 8) | (b as u32);

        Colour::new(uint)
    }

    #[doc(hidden)]
    pub fn decode(value: Value) -> Result<Colour> {
        match value {
            Value::U64(v) => Ok(Colour::new(v as u32)),
            Value::I64(v) => Ok(Colour::new(v as u32)),
            other => Err(Error::Decode("Expected valid colour", other)),
        }
    }

    /// Returns the red RGB component of this Colour.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::new(6573123).get_r(), 100);
    /// ```
    pub fn get_r(&self) -> u8 {
        ((self.value >> 16) & 255) as u8
    }

    /// Returns the green RGB component of this Colour.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::new(6573123).get_g(), 76);
    /// ```
    pub fn get_g(&self) -> u8 {
        ((self.value >> 8) & 255) as u8
    }

    /// Returns the blue RGB component of this Colour.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::new(6573123).get_b(), 67);
    pub fn get_b(&self) -> u8 {
        (self.value & 255) as u8
    }

    /// Returns a tuple of the red, green, and blue components of this Colour.
    ///
    /// This is equivilant to creating a tuple with the return values of
    /// [`get_r`], [`get_g`], and [`get_b`].
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::new(6573123).get_tuple(), (100, 76, 67));
    /// ```
    ///
    /// [`get_r`]: #method.get_r
    /// [`get_g`]: #method.get_g
    /// [`get_b`]: #method.get_b
    pub fn get_tuple(&self) -> (u8, u8, u8) {
        (self.get_r(), self.get_g(), self.get_b())
    }
}

impl From<i32> for Colour {
    /// Constructs a Colour from a i32.
    ///
    /// This is used for functions that accept `Into<Colour>`.
    ///
    /// This is useful when providing hex values.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::from(0xDEA584).get_tuple(), (222, 165, 132));
    /// ```
    fn from(value: i32) -> Colour {
        Colour::new(value as u32)
    }
}

impl From<u32> for Colour {
    /// Constructs a Colour from a u32.
    ///
    /// This is used for functions that accept `Into<Colour>`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::from(6573123u32).get_r(), 100);
    /// ```
    fn from(value: u32) -> Colour {
        Colour::new(value)
    }
}

impl From<u64> for Colour {
    /// Constructs a Colour from a u32.
    ///
    /// This is used for functions that accept `Into<Colour>`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use serenity::utils::Colour;
    ///
    /// assert_eq!(Colour::from(6573123u64).get_r(), 100);
    /// ```
    fn from(value: u64) -> Colour {
        Colour::new(value as u32)
    }
}

colour! {
    Colour;
    /// Creates a new `Colour`, setting its RGB value to `(111, 198, 226)`.
    blitz_blue, 0x6FC6E2;
    /// Creates a new `Colour`, setting its RGB value to `(52, 152, 219)`.
    blue, 0x3498DB;
    /// Creates a new `Colour`, setting its RGB value to `(114, 137, 218)`.
    blurple, 0x7289DA;
    /// Creates a new `Colour`, setting its RGB value to `(32, 102, 148)`.
    dark_blue, 0x206694;
    /// Creates a new `Colour`, setting its RGB value to `(194, 124, 14)`.
    dark_gold, 0xC27C0E;
    /// Creates a new `Colour`, setting its RGB value to `(31, 139, 76)`.
    dark_green, 0x1F8B4C;
    /// Creates a new `Colour`, setting its RGB value to `(96, 125, 139)`.
    dark_grey, 0x607D8B;
    /// Creates a new `Colour`, setting its RGB value to `(173, 20, 87)`.
    dark_magenta, 0xAD1457;
    /// Creates a new `Colour`, setting its RGB value to `(168, 67, 0)`.
    dark_orange, 0xA84300;
    /// Creates a new `Colour`, setting its RGB value to `(113, 54, 138)`.
    dark_purple, 0x71368A;
    /// Creates a new `Colour`, setting its RGB value to `(153, 45, 34)`.
    dark_red, 0x992D22;
    /// Creates a new `Colour`, setting its RGB value to `(17, 128, 106)`.
    dark_teal, 0x11806A;
    /// Creates a new `Colour`, setting its RGB value to `(84, 110, 122)`.
    darker_grey, 0x546E7A;
    /// Creates a new `Colour`, setting its RGB value to `(241, 196, 15)`.
    gold, 0xF1C40F;
    /// Creates a new `Colour`, setting its RGB value to `(186, 218, 85)`.
    kerbal, 0xBADA55;
    /// Creates a new `Colour`, setting its RGB value to `(151, 156, 159)`.
    light_grey, 0x979C9F;
    /// Creates a new `Colour`, setting its RGB value to `(149, 165, 166)`.
    lighter_grey, 0x95A5A6;
    /// Creates a new `Colour`, setting its RGB value to `(233, 30, 99)`.
    magenta, 0xE91E63;
    /// Creates a new `Colour`, setting its RGB value to `(230, 126, 34)`.
    orange, 0xE67E22;
    /// Creates a new `Colour`, setting its RGB value to `(155, 89, 182)`.
    purple, 0x9B59B6;
    /// Creates a new `Colour`, setting its RGB value to `(231, 76, 60)`.
    red, 0xE74C3C;
    /// Creates a new `Colour`, setting its RGB value to `(26, 188, 156)`.
    teal, 0x1ABC9C;
}

impl Default for Colour {
    /// Creates a default value for a `Colour`, setting the inner value to `0`.
    /// This is equivilant to setting the RGB value to `(0, 0, 0)`.
    fn default() -> Colour {
        Colour {
            value: 0,
        }
    }
}
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// 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.

//! Cortex-M3 specific support code for scheduler.

use core::ops::Drop;
use core::intrinsics::abort;

use os::task::Task;
use super::scb;

/// Force context switch. Triggers PendSV interrupt.
#[inline(always)]
pub fn switch_context() {
   scb::set_pendsv(true);
}

/// Sets task stack pointer (PSP).
#[cfg(not(test))]
#[inline(always)]
pub fn set_task_stack_pointer(val: u32) {
  unsafe { asm!("msr psp, $0" :: "r"(val)) };
}

#[cfg(test)]
pub fn set_task_stack_pointer(val: u32) { unimplemented!() }

/// Returns task stack pointer (PSP).
#[cfg(not(test))]
#[inline(always)]
pub fn get_task_stack_pointer() -> u32 {
  let mut val: u32;
  unsafe { asm!("mrs $0, psp" : "=r"(val)) };
  val
}

#[cfg(test)]
pub fn get_task_stack_pointer() -> u32 { unimplemented!() }

/// Returns current stack pointer (SP, which may be PSP or MSP).
#[cfg(not(test))]
#[inline(always)]
pub fn get_current_stack_pointer() -> u32 {
  let mut val: u32;
  unsafe { asm!("mov $0, sp" : "=r"(val)) };
  val
}

#[cfg(test)]
pub fn get_current_stack_pointer() -> u32 { unimplemented!() }

/// State, that's saved by hardware upon entering an ISR.
pub struct SavedState {
  pub r0: u32,
  pub r1: u32,
  pub r2: u32,
  pub r3: u32,
  pub r12: u32,
  pub lr: u32,
  pub pc: u32,
  pub psr: u32,
}

impl SavedState {
  #[inline(always)]
  pub fn new(t: Task, arg: u32) -> SavedState {
    SavedState {
      r0:  arg,
      r1:  0,
      r2:  0,
      r3:  0,
      r12: 0,
      lr:  task_finished as u32,
      pc:  t as u32,
      psr: 0x01000000,  // thumb state
    }
  }
}

// TODO(farcaller): this should actually kill the task.
// TODO(bgamari): It should also unlock anything the task holds
/// Default handler for task that tries to return.
#[cfg(not(test))]
unsafe fn task_finished() {
  asm!("bkpt" :::: "volatile");
}

#[cfg(test)]
unsafe fn task_finished() { unimplemented!() }

/// Phantom type to indicate that interrupts are disabled
pub struct NoInterrupts {
  contents: ()
}

impl NoInterrupts {
  pub fn new() -> NoInterrupts {
    unsafe {
      disable_irqs();
    }
    NoInterrupts { contents: () }
  }
}

impl Drop for NoInterrupts {
  fn drop(&mut self) {
    unsafe {
      enable_irqs();
    }
  }
}

static mut irq_level : uint = 0;

/// Disables all interrupts except Reset, HardFault, and NMI.
/// Note that this is reference counted: if `disable_irqs` is called
/// twice then interrupts will only be re-enabled upon the second call
/// to `enable_irqs`.
#[cfg(not(test))]
#[inline(always)]
unsafe fn disable_irqs() {
  if irq_level == 0 {
    asm!("cpsid i" :::: "volatile");
  }
  irq_level += 1;
}

#[cfg(test)]
unsafe fn disable_irqs() { unimplemented!() }

/// Enables all interrupts except Reset, HardFault, and NMI.
#[cfg(not(test))]
#[inline(always)]
unsafe fn enable_irqs() {
  if irq_level == 0 {
    abort();
  }
  irq_level -= 1;
  if irq_level == 0 {
    asm!("cpsie i" :::: "volatile");
  }
}

#[cfg(test)]
unsafe fn enable_irqs() { unimplemented!() }
<commit_msg>sched: Mark asm! uses as volatile<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// 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.

//! Cortex-M3 specific support code for scheduler.

use core::ops::Drop;
use core::intrinsics::abort;

use os::task::Task;
use super::scb;

/// Force context switch. Triggers PendSV interrupt.
#[inline(always)]
pub fn switch_context() {
   scb::set_pendsv(true);
}

/// Sets task stack pointer (PSP).
#[cfg(not(test))]
#[inline(always)]
pub fn set_task_stack_pointer(val: u32) {
  unsafe { asm!("msr psp, $0" :: "r"(val) :: "volatile") };
}

#[cfg(test)]
pub fn set_task_stack_pointer(val: u32) { unimplemented!() }

/// Returns task stack pointer (PSP).
#[cfg(not(test))]
#[inline(always)]
pub fn get_task_stack_pointer() -> u32 {
  let mut val: u32;
  unsafe { asm!("mrs $0, psp" : "=r"(val) ::: "volatile") };
  val
}

#[cfg(test)]
pub fn get_task_stack_pointer() -> u32 { unimplemented!() }

/// Returns current stack pointer (SP, which may be PSP or MSP).
#[cfg(not(test))]
#[inline(always)]
pub fn get_current_stack_pointer() -> u32 {
  let mut val: u32;
  unsafe { asm!("mov $0, sp" : "=r"(val) ::: "volatile") };
  val
}

#[cfg(test)]
pub fn get_current_stack_pointer() -> u32 { unimplemented!() }

/// State, that's saved by hardware upon entering an ISR.
pub struct SavedState {
  pub r0: u32,
  pub r1: u32,
  pub r2: u32,
  pub r3: u32,
  pub r12: u32,
  pub lr: u32,
  pub pc: u32,
  pub psr: u32,
}

impl SavedState {
  #[inline(always)]
  pub fn new(t: Task, arg: u32) -> SavedState {
    SavedState {
      r0:  arg,
      r1:  0,
      r2:  0,
      r3:  0,
      r12: 0,
      lr:  task_finished as u32,
      pc:  t as u32,
      psr: 0x01000000,  // thumb state
    }
  }
}

// TODO(farcaller): this should actually kill the task.
// TODO(bgamari): It should also unlock anything the task holds
/// Default handler for task that tries to return.
#[cfg(not(test))]
unsafe fn task_finished() {
  asm!("bkpt" :::: "volatile");
}

#[cfg(test)]
unsafe fn task_finished() { unimplemented!() }

/// Phantom type to indicate that interrupts are disabled
pub struct NoInterrupts {
  contents: ()
}

impl NoInterrupts {
  pub fn new() -> NoInterrupts {
    unsafe {
      disable_irqs();
    }
    NoInterrupts { contents: () }
  }
}

impl Drop for NoInterrupts {
  fn drop(&mut self) {
    unsafe {
      enable_irqs();
    }
  }
}

static mut irq_level : uint = 0;

/// Disables all interrupts except Reset, HardFault, and NMI.
/// Note that this is reference counted: if `disable_irqs` is called
/// twice then interrupts will only be re-enabled upon the second call
/// to `enable_irqs`.
#[cfg(not(test))]
#[inline(always)]
unsafe fn disable_irqs() {
  if irq_level == 0 {
    asm!("cpsid i" :::: "volatile");
  }
  irq_level += 1;
}

#[cfg(test)]
unsafe fn disable_irqs() { unimplemented!() }

/// Enables all interrupts except Reset, HardFault, and NMI.
#[cfg(not(test))]
#[inline(always)]
unsafe fn enable_irqs() {
  if irq_level == 0 {
    abort();
  }
  irq_level -= 1;
  if irq_level == 0 {
    asm!("cpsie i" :::: "volatile");
  }
}

#[cfg(test)]
unsafe fn enable_irqs() { unimplemented!() }
<|endoftext|>


<commit_before>use super::placement::sm::client::SMClient;
use super::placement::sm::CmdError;
use super::service::{AsyncServiceClient, DEFAULT_SERVICE_ID};
use bifrost::rpc::RPCError;
use bifrost::rpc::DEFAULT_CLIENT_POOL;
use client::AsyncClient;
use dovahkiin::types::custom_types::id::Id;
use futures::prelude::*;
use index::lsmtree::tree::LSMTree;
use index::Cursor;
use index::EntryKey;
use index::Ordering::{Forward, Backward};
use index::btree::max_entry_key;
use itertools::Itertools;
use ram::types::RandValue;
use rayon::prelude::*;
use smallvec::SmallVec;
use std::sync::Arc;
use std::sync::atomic::Ordering::Relaxed;

pub struct SplitStatus {
    start: EntryKey,
    target: Id,
}

pub fn mid_key(tree: &LSMTree) -> EntryKey {
    // TODO: more accurate mid key take account of all tree levels
    // Current implementation only take the mid key from the tree with the most number of keys
    tree.trees
        .iter()
        .map(|tree| (tree.mid_key(), tree.count()))
        .filter_map(|(mid, count)| mid.map(|mid| (mid, count)))
        .max_by_key(|(mid, count)| *count)
        .map(|(mid, _)| mid)
        .unwrap()
}

pub fn placement_client(
    id: &Id,
    client: &Arc<AsyncClient>,
) -> impl Future<Item = Arc<AsyncServiceClient>, Error = RPCError> {
    let server_id = client.locate_server_id(id).unwrap();
    let client = client.clone();
    DEFAULT_CLIENT_POOL
        .get_by_id_async(server_id, move |sid| client.conshash().to_server_name(sid))
        .map_err(|e| RPCError::IOError(e))
        .map(move |c| AsyncServiceClient::new(DEFAULT_SERVICE_ID, &c))
}

pub fn check_and_split(tree: &LSMTree, sm: &Arc<SMClient>, client: &Arc<AsyncClient>) -> bool {
    if tree.is_full() && tree.split.lock().is_none() {
        // need to initiate a split
        let tree_key_range = tree.range.lock();
        let mut mid_key = mid_key(tree);
        let mut new_placement_id = Id::rand();
        // First check with the placement driver
        match sm.prepare_split(&tree.id).wait() {
            Ok(Err(CmdError::AnotherSplitInProgress(split))) => {
                mid_key = SmallVec::from(split.mid);
                new_placement_id = split.dest;
            }
            Ok(Ok(())) => {}
            _ => panic!("Error on split"),
        }
        // Then save this metadata to current tree 'split' field
        let mut split = tree.split.lock();
        *split = Some(SplitStatus {
            start: mid_key.clone(),
            target: new_placement_id,
        });
        // Create the tree in split host
        let client = placement_client(&new_placement_id, client).wait().unwrap();
        let mid_vec = mid_key.iter().cloned().collect_vec();
        client.new_tree(
            mid_vec.clone(),
            tree_key_range.1.iter().cloned().collect(),
            new_placement_id,
        );
        // Inform the placement driver that this tree is going to split so it can direct all write
        // and read request to the new tree
        let src_epoch = tree.epoch.fetch_add(1, Relaxed) + 1;
        sm.start_split(&tree.id, &new_placement_id, &mid_vec, &src_epoch).wait().unwrap();
    }
    let mut tree_split = tree.split.lock();
    // check if current tree is in the middle of split, so it can (re)start from the process
    if let Some(tree_split) = &*tree_split {
        // Get a cursor from the last key, backwards
        // Backwards are better for rolling batch migration for migrated keys in a batch can be
        // removed from the source tree right after they have been transferred to split tree
        let mut cursor = tree.seek(max_entry_key(), Backward);
        let batch_size = tree.last_level_size();
        loop {
            let mut batch = Vec::with_capacity(batch_size);
            while batch.len() < batch_size && cursor.current().is_some() {
                let key = cursor.current().unwrap().clone();
                if &key < &tree_split.start {
                    // break batch loop when current key out of mid key bound
                    break;
                }
                batch.push(key);
                cursor.next();
            }
            if batch.is_empty() {
                // break the main transfer loop when this batch is empty
                break;
            }
            // submit this batch to new tree
            unimplemented!();
            // remove this batch in current tree
            unimplemented!();
        }
        // split completed
        tree.remove_following_tombstones(&tree_split.start);
        // Set new tree epoch from 0 to 1
        unimplemented!();
        // Inform the placement driver this tree have completed split
        unimplemented!();
    } else {
        return false;
    }
    *tree_split = None;
    true
}
<commit_msg>will not split a placement when epoch is 0<commit_after>use super::placement::sm::client::SMClient;
use super::placement::sm::CmdError;
use super::service::{AsyncServiceClient, DEFAULT_SERVICE_ID};
use bifrost::rpc::RPCError;
use bifrost::rpc::DEFAULT_CLIENT_POOL;
use client::AsyncClient;
use dovahkiin::types::custom_types::id::Id;
use futures::prelude::*;
use index::lsmtree::tree::LSMTree;
use index::Cursor;
use index::EntryKey;
use index::Ordering::{Forward, Backward};
use index::btree::max_entry_key;
use itertools::Itertools;
use ram::types::RandValue;
use rayon::prelude::*;
use smallvec::SmallVec;
use std::sync::Arc;
use std::sync::atomic::Ordering::Relaxed;

pub struct SplitStatus {
    start: EntryKey,
    target: Id,
}

pub fn mid_key(tree: &LSMTree) -> EntryKey {
    // TODO: more accurate mid key take account of all tree levels
    // Current implementation only take the mid key from the tree with the most number of keys
    tree.trees
        .iter()
        .map(|tree| (tree.mid_key(), tree.count()))
        .filter_map(|(mid, count)| mid.map(|mid| (mid, count)))
        .max_by_key(|(mid, count)| *count)
        .map(|(mid, _)| mid)
        .unwrap()
}

pub fn placement_client(
    id: &Id,
    client: &Arc<AsyncClient>,
) -> impl Future<Item = Arc<AsyncServiceClient>, Error = RPCError> {
    let server_id = client.locate_server_id(id).unwrap();
    let client = client.clone();
    DEFAULT_CLIENT_POOL
        .get_by_id_async(server_id, move |sid| client.conshash().to_server_name(sid))
        .map_err(|e| RPCError::IOError(e))
        .map(move |c| AsyncServiceClient::new(DEFAULT_SERVICE_ID, &c))
}

pub fn check_and_split(tree: &LSMTree, sm: &Arc<SMClient>, client: &Arc<AsyncClient>) -> bool {
    if tree.epoch() > 0 && tree.is_full() && tree.split.lock().is_none() {
        // need to initiate a split
        let tree_key_range = tree.range.lock();
        let mut mid_key = mid_key(tree);
        let mut new_placement_id = Id::rand();
        // First check with the placement driver
        match sm.prepare_split(&tree.id).wait() {
            Ok(Err(CmdError::AnotherSplitInProgress(split))) => {
                mid_key = SmallVec::from(split.mid);
                new_placement_id = split.dest;
            }
            Ok(Ok(())) => {}
            _ => panic!("Error on split"),
        }
        // Then save this metadata to current tree 'split' field
        let mut split = tree.split.lock();
        *split = Some(SplitStatus {
            start: mid_key.clone(),
            target: new_placement_id,
        });
        // Create the tree in split host
        let client = placement_client(&new_placement_id, client).wait().unwrap();
        let mid_vec = mid_key.iter().cloned().collect_vec();
        client.new_tree(
            mid_vec.clone(),
            tree_key_range.1.iter().cloned().collect(),
            new_placement_id,
        );
        // Inform the placement driver that this tree is going to split so it can direct all write
        // and read request to the new tree
        let src_epoch = tree.epoch.fetch_add(1, Relaxed) + 1;
        sm.start_split(&tree.id, &new_placement_id, &mid_vec, &src_epoch).wait().unwrap();
    }
    let mut tree_split = tree.split.lock();
    // check if current tree is in the middle of split, so it can (re)start from the process
    if let Some(tree_split) = &*tree_split {
        // Get a cursor from the last key, backwards
        // Backwards are better for rolling batch migration for migrated keys in a batch can be
        // removed from the source tree right after they have been transferred to split tree
        let mut cursor = tree.seek(max_entry_key(), Backward);
        let batch_size = tree.last_level_size();
        loop {
            let mut batch = Vec::with_capacity(batch_size);
            while batch.len() < batch_size && cursor.current().is_some() {
                let key = cursor.current().unwrap().clone();
                if &key < &tree_split.start {
                    // break batch loop when current key out of mid key bound
                    break;
                }
                batch.push(key);
                cursor.next();
            }
            if batch.is_empty() {
                // break the main transfer loop when this batch is empty
                break;
            }
            // submit this batch to new tree
            unimplemented!();
            // remove this batch in current tree
            unimplemented!();
        }
        // split completed
        tree.remove_following_tombstones(&tree_split.start);
        // Set new tree epoch from 0 to 1
        unimplemented!();
        // Inform the placement driver this tree have completed split
        unimplemented!();
    } else {
        return false;
    }
    *tree_split = None;
    true
}
<|endoftext|>


<commit_before>//! Complete fields in record literals and patterns.
use ide_db::helpers::FamousDefs;
use syntax::ast::Expr;

use crate::{
    item::CompletionKind, CompletionContext, CompletionItem, CompletionItemKind, Completions,
};

pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
    let missing_fields = match (ctx.record_pat_syntax.as_ref(), ctx.record_lit_syntax.as_ref()) {
        (None, None) => return None,
        (Some(_), Some(_)) => unreachable!("A record cannot be both a literal and a pattern"),
        (Some(record_pat), _) => ctx.sema.record_pattern_missing_fields(record_pat),
        (_, Some(record_lit)) => {
            let ty = ctx.sema.type_of_expr(&Expr::RecordExpr(record_lit.clone()));
            let default_trait = FamousDefs(&ctx.sema, ctx.krate).core_default_Default();
            let impl_default_trait = default_trait
                .and_then(|default_trait| ty.map(|ty| ty.impls_trait(ctx.db, default_trait, &[])))
                .unwrap_or(false);

            let missing_fields = ctx.sema.record_literal_missing_fields(record_lit);
            if impl_default_trait && !missing_fields.is_empty() {
                acc.add(
                    CompletionItem::new(
                        CompletionKind::Snippet,
                        ctx.source_range(),
                        "..Default::default()",
                    )
                    .insert_text("..Default::default()")
                    .kind(CompletionItemKind::Field)
                    .build(),
                );
            }

            missing_fields
        }
    };

    for (field, ty) in missing_fields {
        acc.add_field(ctx, field, &ty);
    }

    Some(())
}

#[cfg(test)]
mod tests {
    use expect_test::{expect, Expect};
    use ide_db::helpers::FamousDefs;

    use crate::{test_utils::completion_list, CompletionKind};

    fn check(ra_fixture: &str, expect: Expect) {
        let actual = completion_list(ra_fixture, CompletionKind::Reference);
        expect.assert_eq(&actual);
    }

    fn check_snippet(ra_fixture: &str, expect: Expect) {
        let actual = completion_list(
            &format!("//- /main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE),
            CompletionKind::Snippet,
        );
        expect.assert_eq(&actual);
    }

    #[test]
    fn test_record_literal_field_default() {
        let test_code = r#"
struct S { foo: u32, bar: usize }

impl core::default::Default for S {
    fn default() -> Self {
        S {
            foo: 0,
            bar: 0,
        }
    }
}

fn process(f: S) {
    let other = S {
        foo: 5,
        .<|>
    };
}
"#;
        check(
            test_code,
            expect![[r#"
                fd bar usize
            "#]],
        );

        check_snippet(
            test_code,
            expect![[r#"
                sn pd
                sn ppd
                fd ..Default::default()
            "#]],
        );
    }

    #[test]
    fn test_record_literal_field_without_default() {
        let test_code = r#"
struct S { foo: u32, bar: usize }

fn process(f: S) {
    let other = S {
        foo: 5,
        .<|>
    };
}
"#;
        check(
            test_code,
            expect![[r#"
                fd bar usize
            "#]],
        );

        check_snippet(
            test_code,
            expect![[r#"
                sn pd
                sn ppd
            "#]],
        );
    }

    #[test]
    fn test_record_pattern_field() {
        check(
            r#"
struct S { foo: u32 }

fn process(f: S) {
    match f {
        S { f<|>: 92 } => (),
    }
}
"#,
            expect![[r#"
                fd foo u32
            "#]],
        );
    }

    #[test]
    fn test_record_pattern_enum_variant() {
        check(
            r#"
enum E { S { foo: u32, bar: () } }

fn process(e: E) {
    match e {
        E::S { <|> } => (),
    }
}
"#,
            expect![[r#"
                fd foo u32
                fd bar ()
            "#]],
        );
    }

    #[test]
    fn test_record_pattern_field_in_simple_macro() {
        check(
            r"
macro_rules! m { ($e:expr) => { $e } }
struct S { foo: u32 }

fn process(f: S) {
    m!(match f {
        S { f<|>: 92 } => (),
    })
}
",
            expect![[r#"
                fd foo u32
            "#]],
        );
    }

    #[test]
    fn only_missing_fields_are_completed_in_destruct_pats() {
        check(
            r#"
struct S {
    foo1: u32, foo2: u32,
    bar: u32, baz: u32,
}

fn main() {
    let s = S {
        foo1: 1, foo2: 2,
        bar: 3, baz: 4,
    };
    if let S { foo1, foo2: a, <|> } = s {}
}
"#,
            expect![[r#"
                fd bar u32
                fd baz u32
            "#]],
        );
    }

    #[test]
    fn test_record_literal_field() {
        check(
            r#"
struct A { the_field: u32 }
fn foo() {
   A { the<|> }
}
"#,
            expect![[r#"
                fd the_field u32
            "#]],
        );
    }

    #[test]
    fn test_record_literal_enum_variant() {
        check(
            r#"
enum E { A { a: u32 } }
fn foo() {
    let _ = E::A { <|> }
}
"#,
            expect![[r#"
                fd a u32
            "#]],
        );
    }

    #[test]
    fn test_record_literal_two_structs() {
        check(
            r#"
struct A { a: u32 }
struct B { b: u32 }

fn foo() {
   let _: A = B { <|> }
}
"#,
            expect![[r#"
                fd b u32
            "#]],
        );
    }

    #[test]
    fn test_record_literal_generic_struct() {
        check(
            r#"
struct A<T> { a: T }

fn foo() {
   let _: A<u32> = A { <|> }
}
"#,
            expect![[r#"
                fd a u32
            "#]],
        );
    }

    #[test]
    fn test_record_literal_field_in_simple_macro() {
        check(
            r#"
macro_rules! m { ($e:expr) => { $e } }
struct A { the_field: u32 }
fn foo() {
   m!(A { the<|> })
}
"#,
            expect![[r#"
                fd the_field u32
            "#]],
        );
    }

    #[test]
    fn only_missing_fields_are_completed() {
        check(
            r#"
struct S {
    foo1: u32, foo2: u32,
    bar: u32, baz: u32,
}

fn main() {
    let foo1 = 1;
    let s = S { foo1, foo2: 5, <|> }
}
"#,
            expect![[r#"
                fd bar u32
                fd baz u32
            "#]],
        );
    }

    #[test]
    fn completes_functional_update() {
        check(
            r#"
struct S { foo1: u32, foo2: u32 }

fn main() {
    let foo1 = 1;
    let s = S { foo1, <|> .. loop {} }
}
"#,
            expect![[r#"
                fd foo2 u32
            "#]],
        );
    }
}
<commit_msg>Fix completion of Default struct update syntax<commit_after>//! Complete fields in record literals and patterns.
use ide_db::helpers::FamousDefs;
use syntax::ast::Expr;

use crate::{
    item::CompletionKind, CompletionContext, CompletionItem, CompletionItemKind, Completions,
};

pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
    let missing_fields = match (ctx.record_pat_syntax.as_ref(), ctx.record_lit_syntax.as_ref()) {
        (None, None) => return None,
        (Some(_), Some(_)) => unreachable!("A record cannot be both a literal and a pattern"),
        (Some(record_pat), _) => ctx.sema.record_pattern_missing_fields(record_pat),
        (_, Some(record_lit)) => {
            let ty = ctx.sema.type_of_expr(&Expr::RecordExpr(record_lit.clone()));
            let default_trait = FamousDefs(&ctx.sema, ctx.krate).core_default_Default();
            let impl_default_trait = default_trait
                .and_then(|default_trait| ty.map(|ty| ty.impls_trait(ctx.db, default_trait, &[])))
                .unwrap_or(false);

            let missing_fields = ctx.sema.record_literal_missing_fields(record_lit);
            if impl_default_trait && !missing_fields.is_empty() {
                let completion_text = if ctx.token.to_string() == "." {
                    ".Default::default()"
                } else {
                    "..Default::default()"
                };
                acc.add(
                    CompletionItem::new(
                        CompletionKind::Snippet,
                        ctx.source_range(),
                        "..Default::default()",
                    )
                    .insert_text(completion_text)
                    .kind(CompletionItemKind::Field)
                    .build(),
                );
            }

            missing_fields
        }
    };

    for (field, ty) in missing_fields {
        acc.add_field(ctx, field, &ty);
    }

    Some(())
}

#[cfg(test)]
mod tests {
    use expect_test::{expect, Expect};
    use ide_db::helpers::FamousDefs;

    use crate::{test_utils::completion_list, CompletionKind};

    fn check(ra_fixture: &str, expect: Expect) {
        let actual = completion_list(ra_fixture, CompletionKind::Reference);
        expect.assert_eq(&actual);
    }

    fn check_snippet(ra_fixture: &str, expect: Expect) {
        let actual = completion_list(
            &format!("//- /main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE),
            CompletionKind::Snippet,
        );
        expect.assert_eq(&actual);
    }

    #[test]
    fn test_record_literal_field_default() {
        let test_code = r#"
struct S { foo: u32, bar: usize }

impl core::default::Default for S {
    fn default() -> Self {
        S {
            foo: 0,
            bar: 0,
        }
    }
}

fn process(f: S) {
    let other = S {
        foo: 5,
        .<|>
    };
}
"#;
        check(
            test_code,
            expect![[r#"
                fd bar usize
            "#]],
        );

        check_snippet(
            test_code,
            expect![[r#"
                sn pd
                sn ppd
                fd ..Default::default()
            "#]],
        );
    }

    #[test]
    fn test_record_literal_field_without_default() {
        let test_code = r#"
struct S { foo: u32, bar: usize }

fn process(f: S) {
    let other = S {
        foo: 5,
        .<|>
    };
}
"#;
        check(
            test_code,
            expect![[r#"
                fd bar usize
            "#]],
        );

        check_snippet(
            test_code,
            expect![[r#"
                sn pd
                sn ppd
            "#]],
        );
    }

    #[test]
    fn test_record_pattern_field() {
        check(
            r#"
struct S { foo: u32 }

fn process(f: S) {
    match f {
        S { f<|>: 92 } => (),
    }
}
"#,
            expect![[r#"
                fd foo u32
            "#]],
        );
    }

    #[test]
    fn test_record_pattern_enum_variant() {
        check(
            r#"
enum E { S { foo: u32, bar: () } }

fn process(e: E) {
    match e {
        E::S { <|> } => (),
    }
}
"#,
            expect![[r#"
                fd foo u32
                fd bar ()
            "#]],
        );
    }

    #[test]
    fn test_record_pattern_field_in_simple_macro() {
        check(
            r"
macro_rules! m { ($e:expr) => { $e } }
struct S { foo: u32 }

fn process(f: S) {
    m!(match f {
        S { f<|>: 92 } => (),
    })
}
",
            expect![[r#"
                fd foo u32
            "#]],
        );
    }

    #[test]
    fn only_missing_fields_are_completed_in_destruct_pats() {
        check(
            r#"
struct S {
    foo1: u32, foo2: u32,
    bar: u32, baz: u32,
}

fn main() {
    let s = S {
        foo1: 1, foo2: 2,
        bar: 3, baz: 4,
    };
    if let S { foo1, foo2: a, <|> } = s {}
}
"#,
            expect![[r#"
                fd bar u32
                fd baz u32
            "#]],
        );
    }

    #[test]
    fn test_record_literal_field() {
        check(
            r#"
struct A { the_field: u32 }
fn foo() {
   A { the<|> }
}
"#,
            expect![[r#"
                fd the_field u32
            "#]],
        );
    }

    #[test]
    fn test_record_literal_enum_variant() {
        check(
            r#"
enum E { A { a: u32 } }
fn foo() {
    let _ = E::A { <|> }
}
"#,
            expect![[r#"
                fd a u32
            "#]],
        );
    }

    #[test]
    fn test_record_literal_two_structs() {
        check(
            r#"
struct A { a: u32 }
struct B { b: u32 }

fn foo() {
   let _: A = B { <|> }
}
"#,
            expect![[r#"
                fd b u32
            "#]],
        );
    }

    #[test]
    fn test_record_literal_generic_struct() {
        check(
            r#"
struct A<T> { a: T }

fn foo() {
   let _: A<u32> = A { <|> }
}
"#,
            expect![[r#"
                fd a u32
            "#]],
        );
    }

    #[test]
    fn test_record_literal_field_in_simple_macro() {
        check(
            r#"
macro_rules! m { ($e:expr) => { $e } }
struct A { the_field: u32 }
fn foo() {
   m!(A { the<|> })
}
"#,
            expect![[r#"
                fd the_field u32
            "#]],
        );
    }

    #[test]
    fn only_missing_fields_are_completed() {
        check(
            r#"
struct S {
    foo1: u32, foo2: u32,
    bar: u32, baz: u32,
}

fn main() {
    let foo1 = 1;
    let s = S { foo1, foo2: 5, <|> }
}
"#,
            expect![[r#"
                fd bar u32
                fd baz u32
            "#]],
        );
    }

    #[test]
    fn completes_functional_update() {
        check(
            r#"
struct S { foo1: u32, foo2: u32 }

fn main() {
    let foo1 = 1;
    let s = S { foo1, <|> .. loop {} }
}
"#,
            expect![[r#"
                fd foo2 u32
            "#]],
        );
    }
}
<|endoftext|>


<commit_before>//! Analyze all modules in a project for diagnostics. Exits with a non-zero status
//! code if any errors are found.

use std::path::Path;

use anyhow::anyhow;
use rustc_hash::FxHashSet;

use hir::Crate;
use ide::{DiagnosticsConfig, Severity};
use ide_db::base_db::SourceDatabaseExt;

use crate::cli::{load_cargo::load_cargo, Result};

pub fn diagnostics(path: &Path, load_output_dirs: bool, with_proc_macro: bool) -> Result<()> {
    let (host, _vfs) = load_cargo(path, load_output_dirs, with_proc_macro)?;
    let db = host.raw_database();
    let analysis = host.analysis();

    let mut found_error = false;
    let mut visited_files = FxHashSet::default();

    let mut work = Vec::new();
    let krates = Crate::all(db);
    for krate in krates {
        let module = krate.root_module(db);
        let file_id = module.definition_source(db).file_id;
        let file_id = file_id.original_file(db);
        let source_root = db.file_source_root(file_id);
        let source_root = db.source_root(source_root);
        if !source_root.is_library {
            work.push(module);
        }
    }

    for module in work {
        let file_id = module.definition_source(db).file_id.original_file(db);
        if !visited_files.contains(&file_id) {
            let crate_name =
                module.krate().display_name(db).as_deref().unwrap_or("unknown").to_string();
            println!("processing crate: {}, module: {}", crate_name, _vfs.file_path(file_id));
            for diagnostic in analysis.diagnostics(&DiagnosticsConfig::default(), file_id).unwrap()
            {
                if matches!(diagnostic.severity, Severity::Error) {
                    found_error = true;
                }

                println!("{:?}", diagnostic);
            }

            visited_files.insert(file_id);
        }
    }

    println!();
    println!("diagnostic scan complete");

    if found_error {
        println!();
        Err(anyhow!("diagnostic error detected"))
    } else {
        Ok(())
    }
}
<commit_msg>Fix `diagnostics` subcommand, look at all modules<commit_after>//! Analyze all modules in a project for diagnostics. Exits with a non-zero status
//! code if any errors are found.

use std::path::Path;

use anyhow::anyhow;
use rustc_hash::FxHashSet;

use hir::{db::HirDatabase, Crate, Module};
use ide::{DiagnosticsConfig, Severity};
use ide_db::base_db::SourceDatabaseExt;

use crate::cli::{load_cargo::load_cargo, Result};

fn all_modules(db: &dyn HirDatabase) -> Vec<Module> {
    let mut worklist: Vec<_> =
        Crate::all(db).into_iter().map(|krate| krate.root_module(db)).collect();
    let mut modules = Vec::new();

    while let Some(module) = worklist.pop() {
        modules.push(module);
        worklist.extend(module.children(db));
    }

    modules
}

pub fn diagnostics(path: &Path, load_output_dirs: bool, with_proc_macro: bool) -> Result<()> {
    let (host, _vfs) = load_cargo(path, load_output_dirs, with_proc_macro)?;
    let db = host.raw_database();
    let analysis = host.analysis();

    let mut found_error = false;
    let mut visited_files = FxHashSet::default();

    let work = all_modules(db).into_iter().filter(|module| {
        let file_id = module.definition_source(db).file_id.original_file(db);
        let source_root = db.file_source_root(file_id);
        let source_root = db.source_root(source_root);
        !source_root.is_library
    });

    for module in work {
        let file_id = module.definition_source(db).file_id.original_file(db);
        if !visited_files.contains(&file_id) {
            let crate_name =
                module.krate().display_name(db).as_deref().unwrap_or("unknown").to_string();
            println!("processing crate: {}, module: {}", crate_name, _vfs.file_path(file_id));
            for diagnostic in analysis.diagnostics(&DiagnosticsConfig::default(), file_id).unwrap()
            {
                if matches!(diagnostic.severity, Severity::Error) {
                    found_error = true;
                }

                println!("{:?}", diagnostic);
            }

            visited_files.insert(file_id);
        }
    }

    println!();
    println!("diagnostic scan complete");

    if found_error {
        println!();
        Err(anyhow!("diagnostic error detected"))
    } else {
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! FIXME: write short doc here

use std::mem;

use parser::{ParseError, TreeSink};

use crate::{
    ast,
    parsing::Token,
    syntax_node::GreenNode,
    SyntaxError,
    SyntaxKind::{self, *},
    SyntaxTreeBuilder, TextRange, TextSize,
};

/// Bridges the parser with our specific syntax tree representation.
///
/// `TextTreeSink` also handles attachment of trivia (whitespace) to nodes.
pub(crate) struct TextTreeSink<'a> {
    text: &'a str,
    tokens: &'a [Token],
    text_pos: TextSize,
    token_pos: usize,
    state: State,
    inner: SyntaxTreeBuilder,
}

enum State {
    PendingStart,
    Normal,
    PendingFinish,
}

impl<'a> TreeSink for TextTreeSink<'a> {
    fn token(&mut self, kind: SyntaxKind, n_tokens: u8) {
        match mem::replace(&mut self.state, State::Normal) {
            State::PendingStart => unreachable!(),
            State::PendingFinish => self.inner.finish_node(),
            State::Normal => (),
        }
        self.eat_trivias();
        let n_tokens = n_tokens as usize;
        let len = self.tokens[self.token_pos..self.token_pos + n_tokens]
            .iter()
            .map(|it| it.len)
            .sum::<TextSize>();
        self.do_token(kind, len, n_tokens);
    }

    fn start_node(&mut self, kind: SyntaxKind) {
        match mem::replace(&mut self.state, State::Normal) {
            State::PendingStart => {
                self.inner.start_node(kind);
                // No need to attach trivias to previous node: there is no
                // previous node.
                return;
            }
            State::PendingFinish => self.inner.finish_node(),
            State::Normal => (),
        }

        let n_trivias =
            self.tokens[self.token_pos..].iter().take_while(|it| it.kind.is_trivia()).count();
        let leading_trivias = &self.tokens[self.token_pos..self.token_pos + n_trivias];
        let mut trivia_end =
            self.text_pos + leading_trivias.iter().map(|it| it.len).sum::<TextSize>();

        let n_attached_trivias = {
            let leading_trivias = leading_trivias.iter().rev().map(|it| {
                let next_end = trivia_end - it.len;
                let range = TextRange::new(next_end, trivia_end);
                trivia_end = next_end;
                (it.kind, &self.text[range])
            });
            n_attached_trivias(kind, leading_trivias)
        };
        self.eat_n_trivias(n_trivias - n_attached_trivias);
        self.inner.start_node(kind);
        self.eat_n_trivias(n_attached_trivias);
    }

    fn finish_node(&mut self) {
        match mem::replace(&mut self.state, State::PendingFinish) {
            State::PendingStart => unreachable!(),
            State::PendingFinish => self.inner.finish_node(),
            State::Normal => (),
        }
    }

    fn error(&mut self, error: ParseError) {
        self.inner.error(error, self.text_pos)
    }
}

impl<'a> TextTreeSink<'a> {
    pub(super) fn new(text: &'a str, tokens: &'a [Token]) -> Self {
        Self {
            text,
            tokens,
            text_pos: 0.into(),
            token_pos: 0,
            state: State::PendingStart,
            inner: SyntaxTreeBuilder::default(),
        }
    }

    pub(super) fn finish(mut self) -> (GreenNode, Vec<SyntaxError>) {
        match mem::replace(&mut self.state, State::Normal) {
            State::PendingFinish => {
                self.eat_trivias();
                self.inner.finish_node()
            }
            State::PendingStart | State::Normal => unreachable!(),
        }

        self.inner.finish_raw()
    }

    fn eat_trivias(&mut self) {
        while let Some(&token) = self.tokens.get(self.token_pos) {
            if !token.kind.is_trivia() {
                break;
            }
            self.do_token(token.kind, token.len, 1);
        }
    }

    fn eat_n_trivias(&mut self, n: usize) {
        for _ in 0..n {
            let token = self.tokens[self.token_pos];
            assert!(token.kind.is_trivia());
            self.do_token(token.kind, token.len, 1);
        }
    }

    fn do_token(&mut self, kind: SyntaxKind, len: TextSize, n_tokens: usize) {
        let range = TextRange::at(self.text_pos, len);
        let text = &self.text[range];
        self.text_pos += len;
        self.token_pos += n_tokens;
        self.inner.token(kind, text);
    }
}

fn n_attached_trivias<'a>(
    kind: SyntaxKind,
    trivias: impl Iterator<Item = (SyntaxKind, &'a str)>,
) -> usize {
    match kind {
        MACRO_CALL | MACRO_RULES | CONST | TYPE_ALIAS | STRUCT | ENUM | VARIANT | FN | TRAIT
        | MODULE | RECORD_FIELD | STATIC | USE => {
            let mut res = 0;
            let mut trivias = trivias.enumerate().peekable();

            while let Some((i, (kind, text))) = trivias.next() {
                match kind {
                    WHITESPACE if text.contains("\n\n") => {
                        // we check whether the next token is a doc-comment
                        // and skip the whitespace in this case
                        if let Some((COMMENT, peek_text)) = trivias.peek().map(|(_, pair)| pair) {
                            let comment_kind = ast::CommentKind::from_text(peek_text);
                            if comment_kind.doc == Some(ast::CommentPlacement::Outer) {
                                continue;
                            }
                        }
                        break;
                    }
                    COMMENT => {
                        let comment_kind = ast::CommentKind::from_text(text);
                        if comment_kind.doc == Some(ast::CommentPlacement::Inner) {
                            break;
                        }
                        res = i + 1;
                    }
                    _ => (),
                }
            }
            res
        }
        _ => 0,
    }
}
<commit_msg>Attach trivia to ast::Union nodes<commit_after>//! FIXME: write short doc here

use std::mem;

use parser::{ParseError, TreeSink};

use crate::{
    ast,
    parsing::Token,
    syntax_node::GreenNode,
    SyntaxError,
    SyntaxKind::{self, *},
    SyntaxTreeBuilder, TextRange, TextSize,
};

/// Bridges the parser with our specific syntax tree representation.
///
/// `TextTreeSink` also handles attachment of trivia (whitespace) to nodes.
pub(crate) struct TextTreeSink<'a> {
    text: &'a str,
    tokens: &'a [Token],
    text_pos: TextSize,
    token_pos: usize,
    state: State,
    inner: SyntaxTreeBuilder,
}

enum State {
    PendingStart,
    Normal,
    PendingFinish,
}

impl<'a> TreeSink for TextTreeSink<'a> {
    fn token(&mut self, kind: SyntaxKind, n_tokens: u8) {
        match mem::replace(&mut self.state, State::Normal) {
            State::PendingStart => unreachable!(),
            State::PendingFinish => self.inner.finish_node(),
            State::Normal => (),
        }
        self.eat_trivias();
        let n_tokens = n_tokens as usize;
        let len = self.tokens[self.token_pos..self.token_pos + n_tokens]
            .iter()
            .map(|it| it.len)
            .sum::<TextSize>();
        self.do_token(kind, len, n_tokens);
    }

    fn start_node(&mut self, kind: SyntaxKind) {
        match mem::replace(&mut self.state, State::Normal) {
            State::PendingStart => {
                self.inner.start_node(kind);
                // No need to attach trivias to previous node: there is no
                // previous node.
                return;
            }
            State::PendingFinish => self.inner.finish_node(),
            State::Normal => (),
        }

        let n_trivias =
            self.tokens[self.token_pos..].iter().take_while(|it| it.kind.is_trivia()).count();
        let leading_trivias = &self.tokens[self.token_pos..self.token_pos + n_trivias];
        let mut trivia_end =
            self.text_pos + leading_trivias.iter().map(|it| it.len).sum::<TextSize>();

        let n_attached_trivias = {
            let leading_trivias = leading_trivias.iter().rev().map(|it| {
                let next_end = trivia_end - it.len;
                let range = TextRange::new(next_end, trivia_end);
                trivia_end = next_end;
                (it.kind, &self.text[range])
            });
            n_attached_trivias(kind, leading_trivias)
        };
        self.eat_n_trivias(n_trivias - n_attached_trivias);
        self.inner.start_node(kind);
        self.eat_n_trivias(n_attached_trivias);
    }

    fn finish_node(&mut self) {
        match mem::replace(&mut self.state, State::PendingFinish) {
            State::PendingStart => unreachable!(),
            State::PendingFinish => self.inner.finish_node(),
            State::Normal => (),
        }
    }

    fn error(&mut self, error: ParseError) {
        self.inner.error(error, self.text_pos)
    }
}

impl<'a> TextTreeSink<'a> {
    pub(super) fn new(text: &'a str, tokens: &'a [Token]) -> Self {
        Self {
            text,
            tokens,
            text_pos: 0.into(),
            token_pos: 0,
            state: State::PendingStart,
            inner: SyntaxTreeBuilder::default(),
        }
    }

    pub(super) fn finish(mut self) -> (GreenNode, Vec<SyntaxError>) {
        match mem::replace(&mut self.state, State::Normal) {
            State::PendingFinish => {
                self.eat_trivias();
                self.inner.finish_node()
            }
            State::PendingStart | State::Normal => unreachable!(),
        }

        self.inner.finish_raw()
    }

    fn eat_trivias(&mut self) {
        while let Some(&token) = self.tokens.get(self.token_pos) {
            if !token.kind.is_trivia() {
                break;
            }
            self.do_token(token.kind, token.len, 1);
        }
    }

    fn eat_n_trivias(&mut self, n: usize) {
        for _ in 0..n {
            let token = self.tokens[self.token_pos];
            assert!(token.kind.is_trivia());
            self.do_token(token.kind, token.len, 1);
        }
    }

    fn do_token(&mut self, kind: SyntaxKind, len: TextSize, n_tokens: usize) {
        let range = TextRange::at(self.text_pos, len);
        let text = &self.text[range];
        self.text_pos += len;
        self.token_pos += n_tokens;
        self.inner.token(kind, text);
    }
}

fn n_attached_trivias<'a>(
    kind: SyntaxKind,
    trivias: impl Iterator<Item = (SyntaxKind, &'a str)>,
) -> usize {
    match kind {
        MACRO_CALL | MACRO_RULES | CONST | TYPE_ALIAS | STRUCT | UNION | ENUM | VARIANT | FN
        | TRAIT | MODULE | RECORD_FIELD | STATIC | USE => {
            let mut res = 0;
            let mut trivias = trivias.enumerate().peekable();

            while let Some((i, (kind, text))) = trivias.next() {
                match kind {
                    WHITESPACE if text.contains("\n\n") => {
                        // we check whether the next token is a doc-comment
                        // and skip the whitespace in this case
                        if let Some((COMMENT, peek_text)) = trivias.peek().map(|(_, pair)| pair) {
                            let comment_kind = ast::CommentKind::from_text(peek_text);
                            if comment_kind.doc == Some(ast::CommentPlacement::Outer) {
                                continue;
                            }
                        }
                        break;
                    }
                    COMMENT => {
                        let comment_kind = ast::CommentKind::from_text(text);
                        if comment_kind.doc == Some(ast::CommentPlacement::Inner) {
                            break;
                        }
                        res = i + 1;
                    }
                    _ => (),
                }
            }
            res
        }
        _ => 0,
    }
}
<|endoftext|>


<commit_before>/// Module with functions and structs specific to brigde the las crate and laz crate to allow
/// writing & reading LAZ data

use std::io::{Write, Seek, Cursor, Read, SeekFrom};
use {Header, Point, Result, Vlr};
use writer::{PointWriter, write_point_to, write_header_and_vlrs_to};
use reader::{PointReader, read_point_from};
use laz::las::laszip::{LazVlr, LASZIP_DESCRIPTION, LASZIP_RECORD_ID, LASZIP_USER_ID};
use std::fmt::Debug;
use error::Error;

pub(crate) fn create_laszip_vlr(laszip_vlr: &LazVlr) -> std::io::Result<Vlr> {
    let mut cursor = Cursor::new(Vec::<u8>::new());
    laszip_vlr.write_to(&mut cursor)?;
    Ok(Vlr{
        user_id: LASZIP_USER_ID.to_owned(),
        record_id: LASZIP_RECORD_ID,
        description: LASZIP_DESCRIPTION.to_owned(),
        data: cursor.into_inner()
    })
}

pub(crate) fn extract_laszip_vlr(header: &mut Header) -> Option<Vlr> {
    let mut index = None;
    for (i, vlr) in header.vlrs().iter().enumerate() {
        if &vlr.user_id == LASZIP_USER_ID && vlr.record_id == LASZIP_RECORD_ID {
            index = Some(i);
        }
    }
    match index {
        Some(i) => Some(header.vlrs_mut().remove(i)),
        None => None
    }
}

/// struct that knows how to decompress LAZ
///
/// Decompression is done in 2 step:
/// 1) call the decompressor the read & decompress the next point
/// and put its data in a in-memory buffer
/// 2) read the buffer to get the decompress point
pub(crate) struct CompressedPointReader<R: Read +Seek> {
    /// decompressor that does the actual job
    decompressor: laz::las::laszip::LasZipDecompressor<R>,
    header: Header,
    /// in-memory buffer where the decompressor writes deompression result
    decomp_out: Cursor<Vec<u8>>,
    last_point_idx: u64,
}

impl<R: Read + Seek> CompressedPointReader<R> {
    pub(crate) fn new(source: R, mut header: Header) -> Result<Self> {
        let laszip_vlr = match extract_laszip_vlr(&mut header) {
            None => return Err(Error::LasZipVlrNotFound),
            Some(vlr) => laz::las::laszip::LazVlr::from_buffer(&vlr.data)?
        };
        let decomp_out = Cursor::new(vec![0u8; header.point_format().len() as usize]);

        Ok(Self {
            decompressor: laz::las::laszip::LasZipDecompressor::new(source, laszip_vlr)?,
            header,
            decomp_out,
            last_point_idx: 0,
        })
    }
}

impl<R: Read + Seek> Debug for CompressedPointReader<R> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "CompressedPointReader(num_read: {}, header: {:?})", self.last_point_idx, self.header)
    }
}

impl<R: Read + Seek> PointReader for CompressedPointReader<R> {
    fn read_next(&mut self) -> Option<Result<Point>> {
        if self.last_point_idx < self.header.number_of_points() {
            self.last_point_idx += 1;
            self.decompressor.decompress_one(&mut self.decomp_out.get_mut()).unwrap();
            if let Err(e) = self.decomp_out.seek(SeekFrom::Start(0)) {
                Some(Err(e.into()))
            } else {
                Some(read_point_from(&mut self.decomp_out, &self.header))
            }
        } else {

            None
        }
    }

    fn seek(&mut self, position: u64) -> Result<()> {
        self.last_point_idx = position - 1;
        self.decompressor.seek(position)?;
        Ok(())
    }

    fn header(&self) -> &Header {
        &self.header
    }
}

/// struct that knows how to write LAZ
///
/// Writing a point compressed is done in 2 steps
/// 1) write the point to a in-memory buffer
/// 2) call the laz compressor on this buffer
pub(crate) struct CompressedPointWriter<W: Write + Seek> {
    header: Header,
    /// buffer used to write the un compressed point
    compression_in: Cursor<Vec<u8>>,
    /// The compressor that actually doest the job of compressing the data
    compressor: laz::las::laszip::LasZipCompressor<W>
}

impl<W: Write + Seek> CompressedPointWriter<W> {
    pub(crate) fn new(mut dest: W, mut header: Header) -> Result<Self> {
        if header.point_format().is_extended {
            panic!("Writing Extended point data is not supported");
        }

        let mut laz_items = laz::las::laszip::LazItemRecordBuilder::new();
        laz_items.add_item(laz::las::laszip::LazItemType::Point10);

        if header.point_format().has_gps_time {
            laz_items.add_item(laz::las::laszip::LazItemType::GpsTime);
        }

        if header.point_format().has_color {
            laz_items.add_item(laz::las::laszip::LazItemType::RGB12);
        }

        if header.point_format().extra_bytes > 0 {
            laz_items.add_item(laz::las::laszip::LazItemType::Byte(header.point_format().extra_bytes));
        }

        let laz_vlr = LazVlr::from_laz_items(laz_items.build());
        header.vlrs_mut().push(create_laszip_vlr(&laz_vlr)?);

        write_header_and_vlrs_to(&mut dest, &header)?;

        let compression_in = Cursor::new(vec![0u8; header.point_format().len() as usize]);
        let compressor = laz::las::laszip::LasZipCompressor::from_laz_vlr(dest, laz_vlr)?;

        Ok(Self {
            header,
            compression_in,
            compressor
        })
    }
}

impl<W: Write + Seek> PointWriter<W> for CompressedPointWriter<W> {
    fn write_next(&mut self, point: Point) -> Result<()> {
        self.header.add_point(&point);
        self.compression_in.seek(SeekFrom::Start(0))?;
        write_point_to(&mut self.compression_in, point, &self.header)?;
        self.compressor.compress_one(self.compression_in.get_ref())?;
        Ok(())
    }

    fn into_inner(self: Box<Self>) -> W {
        self.compressor.into_stream()
    }

    fn get_mut(&mut self) -> &mut W {
        self.compressor.get_mut()
    }

    fn header(&self) -> &Header {
        &self.header
    }

    fn done(&mut self) -> Result<()> {
        self.compressor.done()?;
        Ok(())
    }
}

impl<W: Write + Seek> Debug for CompressedPointWriter<W> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "CompressedPointWriter(header: {:?})", self.header)
    }
}<commit_msg>typos<commit_after>/// Module with functions and structs specific to brigde the las crate and laz crate to allow
/// writing & reading LAZ data

use std::io::{Write, Seek, Cursor, Read, SeekFrom};
use {Header, Point, Result, Vlr};
use writer::{PointWriter, write_point_to, write_header_and_vlrs_to};
use reader::{PointReader, read_point_from};
use laz::las::laszip::{LazVlr, LASZIP_DESCRIPTION, LASZIP_RECORD_ID, LASZIP_USER_ID};
use std::fmt::Debug;
use error::Error;

pub(crate) fn create_laszip_vlr(laszip_vlr: &LazVlr) -> std::io::Result<Vlr> {
    let mut cursor = Cursor::new(Vec::<u8>::new());
    laszip_vlr.write_to(&mut cursor)?;
    Ok(Vlr{
        user_id: LASZIP_USER_ID.to_owned(),
        record_id: LASZIP_RECORD_ID,
        description: LASZIP_DESCRIPTION.to_owned(),
        data: cursor.into_inner()
    })
}

pub(crate) fn extract_laszip_vlr(header: &mut Header) -> Option<Vlr> {
    let mut index = None;
    for (i, vlr) in header.vlrs().iter().enumerate() {
        if &vlr.user_id == LASZIP_USER_ID && vlr.record_id == LASZIP_RECORD_ID {
            index = Some(i);
        }
    }
    match index {
        Some(i) => Some(header.vlrs_mut().remove(i)),
        None => None
    }
}

/// struct that knows how to decompress LAZ
///
/// Decompression is done in 2 steps:
/// 1) call the decompressor that reads & decompress the next point
/// and put its data in an in-memory buffer
/// 2) read the buffer to get the decompress point
pub(crate) struct CompressedPointReader<R: Read +Seek> {
    /// decompressor that does the actual job
    decompressor: laz::las::laszip::LasZipDecompressor<R>,
    header: Header,
    /// in-memory buffer where the decompressor writes decompression result
    decompressor_output: Cursor<Vec<u8>>,
    last_point_idx: u64,
}

impl<R: Read + Seek> CompressedPointReader<R> {
    pub(crate) fn new(source: R, mut header: Header) -> Result<Self> {
        let laszip_vlr = match extract_laszip_vlr(&mut header) {
            None => return Err(Error::LasZipVlrNotFound),
            Some(vlr) => laz::las::laszip::LazVlr::from_buffer(&vlr.data)?
        };
        let decompressor_output = Cursor::new(vec![0u8; header.point_format().len() as usize]);

        Ok(Self {
            decompressor: laz::las::laszip::LasZipDecompressor::new(source, laszip_vlr)?,
            header,
            decompressor_output,
            last_point_idx: 0,
        })
    }
}

impl<R: Read + Seek> Debug for CompressedPointReader<R> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "CompressedPointReader(num_read: {}, header: {:?})", self.last_point_idx, self.header)
    }
}

impl<R: Read + Seek> PointReader for CompressedPointReader<R> {
    fn read_next(&mut self) -> Option<Result<Point>> {
        if self.last_point_idx < self.header.number_of_points() {
            self.last_point_idx += 1;
            self.decompressor.decompress_one(&mut self.decompressor_output.get_mut()).unwrap();
            if let Err(e) = self.decompressor_output.seek(SeekFrom::Start(0)) {
                Some(Err(e.into()))
            } else {
                Some(read_point_from(&mut self.decompressor_output, &self.header))
            }
        } else {

            None
        }
    }

    fn seek(&mut self, position: u64) -> Result<()> {
        self.last_point_idx = position - 1;
        self.decompressor.seek(position)?;
        Ok(())
    }

    fn header(&self) -> &Header {
        &self.header
    }
}

/// struct that knows how to write LAZ
///
/// Writing a point compressed is done in 2 steps
/// 1) write the point to a in-memory buffer
/// 2) call the laz compressor on this buffer
pub(crate) struct CompressedPointWriter<W: Write + Seek> {
    header: Header,
    /// buffer used to write the uncompressed point
    compressor_input: Cursor<Vec<u8>>,
    /// The compressor that actually does the job of compressing the data
    compressor: laz::las::laszip::LasZipCompressor<W>
}

impl<W: Write + Seek> CompressedPointWriter<W> {
    pub(crate) fn new(mut dest: W, mut header: Header) -> Result<Self> {
        if header.point_format().is_extended {
            panic!("Writing Extended point data is not supported");
        }

        let mut laz_items = laz::las::laszip::LazItemRecordBuilder::new();
        laz_items.add_item(laz::las::laszip::LazItemType::Point10);

        if header.point_format().has_gps_time {
            laz_items.add_item(laz::las::laszip::LazItemType::GpsTime);
        }

        if header.point_format().has_color {
            laz_items.add_item(laz::las::laszip::LazItemType::RGB12);
        }

        if header.point_format().extra_bytes > 0 {
            laz_items.add_item(laz::las::laszip::LazItemType::Byte(header.point_format().extra_bytes));
        }

        let laz_vlr = LazVlr::from_laz_items(laz_items.build());
        header.vlrs_mut().push(create_laszip_vlr(&laz_vlr)?);

        write_header_and_vlrs_to(&mut dest, &header)?;

        let compressor_input = Cursor::new(vec![0u8; header.point_format().len() as usize]);
        let compressor = laz::las::laszip::LasZipCompressor::from_laz_vlr(dest, laz_vlr)?;

        Ok(Self {
            header,
            compressor_input,
            compressor
        })
    }
}

impl<W: Write + Seek> PointWriter<W> for CompressedPointWriter<W> {
    fn write_next(&mut self, point: Point) -> Result<()> {
        self.header.add_point(&point);
        self.compressor_input.seek(SeekFrom::Start(0))?;
        write_point_to(&mut self.compressor_input, point, &self.header)?;
        self.compressor.compress_one(self.compressor_input.get_ref())?;
        Ok(())
    }

    fn into_inner(self: Box<Self>) -> W {
        self.compressor.into_stream()
    }

    fn get_mut(&mut self) -> &mut W {
        self.compressor.get_mut()
    }

    fn header(&self) -> &Header {
        &self.header
    }

    fn done(&mut self) -> Result<()> {
        self.compressor.done()?;
        Ok(())
    }
}

impl<W: Write + Seek> Debug for CompressedPointWriter<W> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "CompressedPointWriter(header: {:?})", self.header)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Tibor Benke <ihrwein@gmail.com>
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use handlebars::{Handlebars, Template};
use std::collections::BTreeMap;
use std::sync::Arc;

use message::Message;
use state::State;
use timer::TimerEvent;
use context::base::BaseContext;
use dispatcher::request::Request;
use dispatcher::response::ResponseSender;

const CONTEXT_ID: &'static str = ".context.id";

pub struct MapContext {
    base: BaseContext,
    map: BTreeMap<String, State>,
    context_id: Handlebars,
}

impl MapContext {
    pub fn new(base: BaseContext, context_id: Template) -> MapContext {
        let mut handlebars = Handlebars::new();
        handlebars.register_template(CONTEXT_ID, context_id);
        MapContext {
            base: base,
            map: BTreeMap::new(),
            context_id: handlebars,
        }
    }

    pub fn on_event(&mut self, event: Request, responder: &mut ResponseSender) {
        trace!("MapContext: received event");
        match event {
            Request::Timer(event) => self.on_timer(&event, responder),
            Request::Message(message) => self.on_message(message, responder),
            _ => {}
        }
    }

    pub fn on_timer(&mut self, event: &TimerEvent, responder: &mut ResponseSender) {
        for (_, mut state) in &mut self.map {
            state.on_timer(event, &self.base, responder);
        }
        self.remove_closed_states();
    }

    fn get_closed_state_ids(&self) -> Vec<String> {
        self.map
            .iter()
            .filter_map(|(id, state)| {
                if !state.is_open() {
                    Some(id.clone())
                } else {
                    None
                }
            })
            .collect::<Vec<String>>()
    }

    fn remove_closed_states(&mut self) {
        for id in self.get_closed_state_ids() {
            let _ = self.map.remove(&id);
        }
    }

    pub fn on_message(&mut self, event: Arc<Message>, responder: &mut ResponseSender) {
        self.update_state(event, responder);
        self.remove_closed_states();
    }

    fn update_state(&mut self, event: Arc<Message>, responder: &mut ResponseSender) {
        if let Ok(id) = self.context_id.render(CONTEXT_ID, event.values()) {
            let state = self.map.entry(id).or_insert_with(State::new);
            state.on_message(event, &self.base, responder);
        } else {
            error!("Failed to render the context-id: {:?}",
                   self.context_id.get_template(&CONTEXT_ID.to_owned()));
        }
    }

    #[allow(dead_code)]
    pub fn is_open(&self) -> bool {
        !self.map.is_empty()
    }

    pub fn patterns(&self) -> &[String] {
        &self.base.conditions().patterns
    }
}
<commit_msg>MapContext: use BaseContext's patterns<commit_after>// Copyright (c) 2016 Tibor Benke <ihrwein@gmail.com>
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use handlebars::{Handlebars, Template};
use std::collections::BTreeMap;
use std::sync::Arc;

use message::Message;
use state::State;
use timer::TimerEvent;
use context::base::BaseContext;
use dispatcher::request::Request;
use dispatcher::response::ResponseSender;

const CONTEXT_ID: &'static str = ".context.id";

pub struct MapContext {
    base: BaseContext,
    map: BTreeMap<String, State>,
    context_id: Handlebars,
}

impl MapContext {
    pub fn new(base: BaseContext, context_id: Template) -> MapContext {
        let mut handlebars = Handlebars::new();
        handlebars.register_template(CONTEXT_ID, context_id);
        MapContext {
            base: base,
            map: BTreeMap::new(),
            context_id: handlebars,
        }
    }

    pub fn on_event(&mut self, event: Request, responder: &mut ResponseSender) {
        trace!("MapContext: received event");
        match event {
            Request::Timer(event) => self.on_timer(&event, responder),
            Request::Message(message) => self.on_message(message, responder),
            _ => {}
        }
    }

    pub fn on_timer(&mut self, event: &TimerEvent, responder: &mut ResponseSender) {
        for (_, mut state) in &mut self.map {
            state.on_timer(event, &self.base, responder);
        }
        self.remove_closed_states();
    }

    fn get_closed_state_ids(&self) -> Vec<String> {
        self.map
            .iter()
            .filter_map(|(id, state)| {
                if !state.is_open() {
                    Some(id.clone())
                } else {
                    None
                }
            })
            .collect::<Vec<String>>()
    }

    fn remove_closed_states(&mut self) {
        for id in self.get_closed_state_ids() {
            let _ = self.map.remove(&id);
        }
    }

    pub fn on_message(&mut self, event: Arc<Message>, responder: &mut ResponseSender) {
        self.update_state(event, responder);
        self.remove_closed_states();
    }

    fn update_state(&mut self, event: Arc<Message>, responder: &mut ResponseSender) {
        if let Ok(id) = self.context_id.render(CONTEXT_ID, event.values()) {
            let state = self.map.entry(id).or_insert_with(State::new);
            state.on_message(event, &self.base, responder);
        } else {
            error!("Failed to render the context-id: {:?}",
                   self.context_id.get_template(&CONTEXT_ID.to_owned()));
        }
    }

    #[allow(dead_code)]
    pub fn is_open(&self) -> bool {
        !self.map.is_empty()
    }

    pub fn patterns(&self) -> &[String] {
        &self.base.patterns
    }
}
<|endoftext|>


<commit_before>use config;
use conditions;
use Correlator;
use dispatcher::ResponseHandler;
use message;
use Response;

use uuid::Uuid;
use std::rc::Rc;
use std::cell::RefCell;
use std::thread;

use reactor::EventHandler;
use action::MessageResponse;

struct MessageEventHandler{
    responses: Rc<RefCell<Vec<MessageResponse>>>
}

impl EventHandler<Response> for MessageEventHandler {
    fn handle_event(&mut self, event: Response) {
        if let Response::Message(event) = event {
            self.responses.borrow_mut().push(event);
        }
    }
    fn handler(&self) -> ResponseHandler {
        ResponseHandler::Message
    }
}

#[test]
fn test_given_manually_built_correlator_when_it_closes_a_context_then_the_actions_are_executed() {
    let uuid1 = "1b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
    let uuid2 = "2b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
    let uuid3 = "3b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
    let patterns = vec![
        uuid1.clone(),
        uuid2.clone(),
        uuid3.clone(),
    ];
    let condition = conditions::Builder::new(100).patterns(patterns)
                                                .first_opens(true)
                                                .last_closes(true)
                                                .build();
    let actions = vec![ config::action::MessageAction.into() ];
    let contexts = vec!{
        config::ContextBuilder::new(Uuid::new_v4(), condition.clone()).actions(actions.clone()).build(),
        config::ContextBuilder::new(Uuid::new_v4(), condition.clone()).actions(actions.clone()).build(),
        config::ContextBuilder::new(Uuid::new_v4(), condition.clone()).actions(actions.clone()).build(),
    };
    let responses = Rc::new(RefCell::new(Vec::new()));
    let message_event_handler = Box::new(MessageEventHandler{responses: responses.clone()});
    let mut correlator = Correlator::new(contexts);
    correlator.register_handler(message_event_handler);
    let _ = correlator.push_message(message::Builder::new(&uuid1).build());
    thread::sleep_ms(20);
    let _ = correlator.push_message(message::Builder::new(&uuid2).build());
    thread::sleep_ms(80);
    let _ = correlator.push_message(message::Builder::new(&uuid3).build());
    let _ = correlator.stop();
    assert_eq!(3, responses.borrow().len());
}
<commit_msg>Correlator: add tests<commit_after>use config;
use conditions;
use Correlator;
use dispatcher::ResponseHandler;
use message;
use Response;

use uuid::Uuid;
use serde_json::from_str;
use std::rc::Rc;
use std::cell::RefCell;
use std::thread;

use reactor::EventHandler;
use action::MessageResponse;

const JSON_CONFIG: &'static str = r#"
      [
        {
          "name": "CONTEXT_NAME_1",
          "uuid": "185e96da-c00e-454b-b4fe-9d0a14a86335",
          "conditions": {
            "timeout": 100,
            "patterns": [
              "p1",
              "p2",
              "p3"
            ],
            "first_opens": true
          },
          "actions": [
            {
              "message": null
            }
          ]
        },
        {
          "name": "CONTEXT_NAME_2",
          "uuid": "285e96da-c00e-454b-b4fe-9d0a14a86335",
          "conditions": {
            "timeout": 10000,
            "max_size": 5
          },
          "actions": [
            {
              "message": null
            },
            {
              "message": null
            }
          ]
        },
        {
          "name": "CONTEXT_NAME_3",
          "uuid": "385e96da-c00e-454b-b4fe-9d0a14a86335",
          "conditions": {
            "timeout": 100,
            "patterns": [
              "p1"
            ]
          },
          "actions": [
            {
              "message": null
            }
          ]
        }
      ]
    "#;

struct MessageEventHandler {
    responses: Rc<RefCell<Vec<MessageResponse>>>
}

impl EventHandler<Response> for MessageEventHandler {
    fn handle_event(&mut self, event: Response) {
        if let Response::Message(event) = event {
            self.responses.borrow_mut().push(event);
        }
    }
    fn handler(&self) -> ResponseHandler {
        ResponseHandler::Message
    }
}

#[test]
fn test_given_manually_built_correlator_when_it_closes_a_context_then_the_actions_are_executed() {
    let uuid1 = "1b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
    let uuid2 = "2b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
    let uuid3 = "3b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
    let patterns = vec![
        uuid1.clone(),
        uuid2.clone(),
        uuid3.clone(),
    ];
    let condition = conditions::Builder::new(100).patterns(patterns)
                                                .first_opens(true)
                                                .last_closes(true)
                                                .build();
    let actions = vec![ config::action::MessageAction.into() ];
    let contexts = vec!{
        config::ContextBuilder::new(Uuid::new_v4(), condition.clone()).actions(actions.clone()).build(),
        config::ContextBuilder::new(Uuid::new_v4(), condition.clone()).actions(actions.clone()).build(),
        config::ContextBuilder::new(Uuid::new_v4(), condition.clone()).actions(actions.clone()).build(),
    };
    let responses = Rc::new(RefCell::new(Vec::new()));
    let message_event_handler = Box::new(MessageEventHandler{responses: responses.clone()});
    let mut correlator = Correlator::new(contexts);
    correlator.register_handler(message_event_handler);
    let _ = correlator.push_message(message::Builder::new(&uuid1).build());
    thread::sleep_ms(20);
    let _ = correlator.push_message(message::Builder::new(&uuid2).build());
    thread::sleep_ms(80);
    let _ = correlator.push_message(message::Builder::new(&uuid3).build());
    let _ = correlator.stop();
    assert_eq!(3, responses.borrow().len());
}

#[test]
fn test_given_correlator_when_it_is_built_from_json_then_we_get_the_expected_correlator() {
    let result = from_str::<Vec<config::Context>>(JSON_CONFIG);
    let expected_name = "CONTEXT_NAME_1".to_string();
    let expected_uuid = "185e96da-c00e-454b-b4fe-9d0a14a86335".to_string();
    println!("{:?}", &result);
    let mut contexts = result.ok().expect("Failed to deserialize a config::Context from JSON");
    for i in &contexts {
        assert_eq!(true, i.name.is_some());
    }
    let context = contexts.remove(0);
    assert_eq!(Some(&expected_name), context.name.as_ref());
    assert_eq!(&expected_uuid, &context.uuid.to_hyphenated_string());
}

#[test]
fn test_given_correlator_when_it_is_built_from_json_then_it_produces_the_expected_number_of_messages() {
    let uuid1 = "1b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
    let uuid2 = "2b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
    let uuid3 = "3b47ba91-d867-4a8c-9553-a5dfd6ea1274".to_string();
    let result = from_str::<Vec<config::Context>>(JSON_CONFIG);
    println!("{:?}", &result);
    let contexts = result.ok().expect("Failed to deserialize a config::Context from JSON");
    let responses = Rc::new(RefCell::new(Vec::new()));
    let message_event_handler = Box::new(MessageEventHandler{responses: responses.clone()});
    let mut correlator = Correlator::new(contexts);
    correlator.register_handler(message_event_handler);
    let _ = correlator.push_message(message::Builder::new(&uuid1).name("p1".to_string()).build());
    thread::sleep_ms(20);
    let _ = correlator.push_message(message::Builder::new(&uuid2).name("p2".to_string()).build());
    let _ = correlator.push_message(message::Builder::new(&uuid3).name("p3".to_string()).build());
    let _ = correlator.push_message(message::Builder::new(&uuid3).name("p3".to_string()).build());
    let _ = correlator.push_message(message::Builder::new(&uuid3).name("p3".to_string()).build());
    let _ = correlator.push_message(message::Builder::new(&uuid3).name("p3".to_string()).build());
    let _ = correlator.push_message(message::Builder::new(&uuid3).name("p3".to_string()).build());
    thread::sleep_ms(200);
    let _ = correlator.stop();
    println!("{:?}", &responses.borrow());
    assert_eq!(4, responses.borrow().len());
}
<|endoftext|>


<commit_before>use std::io::Write;

fn one_set_of_reftests(outfile: &'static str, indir: &'static str) {
    let out_dir = std::env::var("OUT_DIR").unwrap();
    let destination = std::path::Path::new(&out_dir).join(outfile);
    let mut f = std::fs::File::create(&destination).unwrap();

    let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
    let reftests_dir = std::path::Path::new(&root_dir).join(indir);
    let files = std::fs::read_dir(reftests_dir).unwrap();

    for file in files {
        let path = file.expect("failed to get path").path();
        let ext = path.extension().expect("bogus reftest filename (doesn't have extension)");
        if ext == "json" || ext == "fail" {
            let path = path.canonicalize().unwrap();

            let id_string = path.file_name().unwrap().to_str().unwrap().chars().map(|x| match x {
                'A'...'Z' | 'a'...'z' | '0'...'9' => x,
                _ => '_',
            }).collect::<String>();

            if ext == "fail" {
                write!(f, "#[should_panic]\n").unwrap();
            }
            write!(f, r#"
                #[test]
                fn reftest_{}() {{
                    run_one_reftest("{}");
                }}
                "#, id_string, path.to_str().unwrap()).unwrap();
        }
    }
}

fn main() {
    one_set_of_reftests("frontend-reftests.rs", "../../tests/xc2par/frontend-reftests");
    one_set_of_reftests("netlist-reftests.rs", "../../tests/xc2par/netlist-reftests");
    one_set_of_reftests("par-reftests.rs", "../../tests/xc2par/par-reftests");
}
<commit_msg>xc2par: Hack build.rs so that it uploads<commit_after>use std::io::Write;

fn one_set_of_reftests(outfile: &'static str, indir: &'static str) {
    let out_dir = std::env::var("OUT_DIR").unwrap();
    let destination = std::path::Path::new(&out_dir).join(outfile);
    let mut f = std::fs::File::create(&destination).unwrap();

    let root_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
    let reftests_dir = std::path::Path::new(&root_dir).join(indir);
    let files = std::fs::read_dir(reftests_dir);

    if let Ok(files) = files {
        for file in files {
            let path = file.expect("failed to get path").path();
            let ext = path.extension().expect("bogus reftest filename (doesn't have extension)");
            if ext == "json" || ext == "fail" {
                let path = path.canonicalize().unwrap();

                let id_string = path.file_name().unwrap().to_str().unwrap().chars().map(|x| match x {
                    'A'...'Z' | 'a'...'z' | '0'...'9' => x,
                    _ => '_',
                }).collect::<String>();

                if ext == "fail" {
                    write!(f, "#[should_panic]\n").unwrap();
                }
                write!(f, r#"
                    #[test]
                    fn reftest_{}() {{
                        run_one_reftest("{}");
                    }}
                    "#, id_string, path.to_str().unwrap()).unwrap();
            }
        }
    }
}

fn main() {
    one_set_of_reftests("frontend-reftests.rs", "../../tests/xc2par/frontend-reftests");
    one_set_of_reftests("netlist-reftests.rs", "../../tests/xc2par/netlist-reftests");
    one_set_of_reftests("par-reftests.rs", "../../tests/xc2par/par-reftests");
}
<|endoftext|>