<commit_before>extern crate byteorder;
extern crate num;

use self::byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use self::num::{One, Zero, ToPrimitive};
use super::Decimal;
use pg_crate::types::*;
use std::error;
use std::fmt;
use std::io::Cursor;
use std::result::*;

#[derive(Debug, Clone, Copy)]
pub struct InvalidDecimal;

impl fmt::Display for InvalidDecimal {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(error::Error::description(self))
    }
}

impl error::Error for InvalidDecimal {
    fn description(&self) -> &str {
        "Invalid Decimal"
    }
}

impl FromSql for Decimal {
    // Decimals are represented as follows:
    // Header:
    //  u16 numGroups
    //  i16 weightFirstGroup (10000^weight)
    //  u16 sign (0x0000 = positive, 0x4000 = negative, 0xC000 = NaN)
    //  i16 dscale. Number of digits (in base 10) to print after decimal separator
    //
    //  Psuedo code :
    //  const Decimals [
    //          0.0000000000000000000000000001,
    //          0.000000000000000000000001,
    //          0.00000000000000000001,
    //          0.0000000000000001,
    //          0.000000000001,
    //          0.00000001,
    //          0.0001,
    //          1,
    //          10000,
    //          100000000,
    //          1000000000000,
    //          10000000000000000,
    //          100000000000000000000,
    //          1000000000000000000000000,
    //          10000000000000000000000000000
    //  ]
    //  overflow = false
    //  result = 0
    //  for i = 0, weight = weightFirstGroup + 7; i < numGroups; i++, weight--
    //    group = read.u16
    //    if weight < 0 or weight > MaxNum
    //       overflow = true
    //    else
    //       result += Decimals[weight] * group
    //  sign == 0x4000 ? -result : result

    // So if we were to take the number: 3950.123456
    //
    //  Stored on Disk:
    //    00 03 00 00 00 00 00 06 0F 6E 04 D2 15 E0
    //
    //  Number of groups: 00 03
    //  Weight of first group: 00 00
    //  Sign: 00 00
    //  DScale: 00 06
    //
    // 0F 6E = 3950
    //   result = result + 3950 * 1;
    // 04 D2 = 1234
    //   result = result + 1234 * 0.0001;
    // 15 E0 = 5600
    //   result = result + 5600 * 0.00000001;
    //

    fn from_sql(_: &Type, raw: &[u8]) -> Result<Decimal, Box<error::Error + 'static + Sync + Send>> {
        let mut raw = Cursor::new(raw);
        let num_groups = try!(raw.read_u16::<BigEndian>());
        let weight = try!(raw.read_i16::<BigEndian>()); // 10000^weight
        // Sign: 0x0000 = positive, 0x4000 = negative, 0xC000 = NaN
        let sign = try!(raw.read_u16::<BigEndian>());
        // Number of digits (in base 10) to print after decimal separator
        let fixed_scale = try!(raw.read_u16::<BigEndian>()) as i32;

        // Build up a list of powers that will be used
        let mut powers = vec![Decimal::one()];
        let mut val = Decimal::one();
        let mult = Decimal::new(10000, 0);
        for _ in 1..num_groups {
            val *= mult;
            powers.push(val);
        }
        powers.reverse();

        // Now process the number
        let mut result = Decimal::zero();
        for i in 0..num_groups {
            let group = try!(raw.read_u16::<BigEndian>());
            let calculated = &powers[i as usize] * Decimal::new(group as i64, 0);
            result = result + calculated;
        }

        // Finally, adjust for the scale
        let mut scale = (num_groups as i16 - weight - 1) as i32 * 4;
        // Scale could be negative
        if scale < 0 {
            result *= Decimal::new(10i64.pow((scale * -1) as u32), 0);
            scale = 0;
        } else if scale > fixed_scale {
            result /= Decimal::new(10i64.pow((scale - fixed_scale) as u32), 0);
            scale = fixed_scale;
        }

        // Create the decimal
        let neg = sign == 0x4000;
        if result.set_scale(scale as u32).is_err() {
            return Err(Box::new(InvalidDecimal));
        }
        result.set_sign(!neg);

        // Normalize by truncating any trailing 0's from the decimal representation
        // This may not be the most efficient way of doing this
        if scale > 0 {
            let str_rep = result.to_string();
            let trailing_zeros = str_rep.chars().rev().take_while(|&x| x == '0').count();
            result = result.rescale(scale as u32 - trailing_zeros as u32);
        }

        Ok(result)
    }

    fn accepts(ty: &Type) -> bool {
        match *ty {
            NUMERIC => true,
            _ => false,
        }
    }
}

impl ToSql for Decimal {
    fn to_sql(&self, _: &Type, out: &mut Vec<u8>) -> Result<IsNull, Box<error::Error + 'static + Sync + Send>> {
        let sign = if self.is_negative() { 0x4000 } else { 0x0000 };
        let scale = self.scale() as u16;

        let mut whole = *self;
        whole.set_scale(0).ok();
        whole.set_sign(true);
        let mut digits = whole.to_string();
        let split_point = if scale as usize > digits.len() {
            let mut new_digits = vec!['0'; scale as usize - digits.len() as usize];
            new_digits.extend(digits.chars());
            digits = new_digits.into_iter().collect::<String>();
            0
        } else {
            digits.len() as isize - scale as isize
        };
        let (whole_digits, decimal_digits) = digits.split_at(split_point as usize);
        let whole_portion = whole_digits
            .chars()
            .rev()
            .collect::<Vec<char>>()
            .chunks(4)
            .map(|x| {
                let mut x = x.to_owned();
                while x.len() < 4 {
                    x.push('0');
                }
                x.into_iter().rev().collect::<String>()
            })
            .rev()
            .collect::<Vec<String>>();
        let decimal_portion = decimal_digits
            .chars()
            .collect::<Vec<char>>()
            .chunks(4)
            .map(|x| {
                let mut x = x.to_owned();
                while x.len() < 4 {
                    x.push('0');
                }
                x.into_iter().collect::<String>()
            })
            .collect::<Vec<String>>();
        let weight = if whole_portion.is_empty() {
            -(decimal_portion.len() as i16)
        } else {
            whole_portion.len() as i16 - 1
        };
        let all_groups = whole_portion
            .into_iter()
            .chain(decimal_portion.into_iter())
            .skip_while(|ref x| *x == "0000")
            .collect::<Vec<String>>();
        let num_groups = all_groups.len() as u16;

        // Number of groups
        try!(out.write_u16::<BigEndian>(num_groups));
        // Weight of first group
        try!(out.write_i16::<BigEndian>(weight));
        // Sign
        try!(out.write_u16::<BigEndian>(sign));
        // DScale
        try!(out.write_u16::<BigEndian>(scale));
        // Now process the number
        for chunk in all_groups {
            let calculated = chunk.parse::<u16>().unwrap();
            try!(out.write_u16::<BigEndian>(calculated.to_u16().unwrap()));
        }
        Ok(IsNull::No)
    }

    fn accepts(ty: &Type) -> bool {
        match *ty {
            NUMERIC => true,
            _ => false,
        }
    }

    to_sql_checked!();
}

#[cfg(test)]
mod test {
    use super::*;
    use pg_crate::{Connection, TlsMode};
    use std::str::FromStr;

    fn read_type(sql_type: &str, checks: &[&'static str]) {
        let conn = match Connection::connect("postgres://postgres@localhost", TlsMode::None) {

            Ok(x) => x,
            Err(err) => panic!("{:#?}", err),
        };
        for &val in checks.iter() {
            let stmt = match conn.prepare(&*format!("SELECT {}::{}", val, sql_type)) {
                Ok(x) => x,
                Err(err) => panic!("{:#?}", err),
            };
            let result: Decimal = match stmt.query(&[]) {
                Ok(x) => x.iter().next().unwrap().get(0),
                Err(err) => panic!("{:#?}", err),
            };
            assert_eq!(val, result.to_string());
        }
    }

    fn write_type(sql_type: &str, checks: &[&'static str]) {
        let conn = match Connection::connect("postgres://postgres@localhost", TlsMode::None) {
            Ok(x) => x,
            Err(err) => panic!("{:#?}", err),
        };
        for &val in checks.iter() {
            let stmt = match conn.prepare(&*format!("SELECT $1::{}", sql_type)) {
                Ok(x) => x,
                Err(err) => panic!("{:#?}", err),
            };
            let number = Decimal::from_str(val).unwrap();
            let result: Decimal = match stmt.query(&[&number]) {
                Ok(x) => x.iter().next().unwrap().get(0),
                Err(err) => panic!("{:#?}", err),
            };
            assert_eq!(val, result.to_string());
        }
    }

    #[test]
    fn test_null() {
        let conn = match Connection::connect("postgres://postgres@localhost", TlsMode::None) {
            Ok(x) => x,
            Err(err) => panic!("{:#?}", err),
        };

        // Test NULL
        let stmt = match conn.prepare(&"SELECT NULL::numeric") {
            Ok(x) => x,
            Err(err) => panic!("{:#?}", err),
        };
        let result: Option<Decimal> = match stmt.query(&[]) {
            Ok(x) => x.iter().next().unwrap().get(0),
            Err(err) => panic!("{:#?}", err),
        };
        assert_eq!(None, result);
    }

    #[test]
    fn read_numeric_type() {
        read_type(
            "NUMERIC(26,6)",
            &[
                "3950.123456",
                "3950",
                "0.1",
                "0.01",
                "0.001",
                "0.0001",
                "0.00001",
                "0.000001",
                "1",
                "-100",
                "-123.456",
                "119996.25",
                "1000000",
                "9999999.99999",
            ],
        );
    }

    #[test]
    fn write_numeric_type() {
        write_type(
            "NUMERIC(26,6)",
            &[
                "3950.123456",
                "3950",
                "0.1",
                "0.01",
                "0.001",
                "0.0001",
                "0.00001",
                "0.000001",
                "1",
                "-100",
                "-123.456",
                "119996.25",
                "1000000",
                "9999999.99999",
            ],
        );
    }
}
<commit_msg>Fixes use of private function by postgres module<commit_after>extern crate byteorder;
extern crate num;

use self::byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use self::num::{One, Zero, ToPrimitive};
use super::Decimal;
use pg_crate::types::*;
use std::error;
use std::fmt;
use std::io::Cursor;
use std::result::*;

#[derive(Debug, Clone, Copy)]
pub struct InvalidDecimal;

impl fmt::Display for InvalidDecimal {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(error::Error::description(self))
    }
}

impl error::Error for InvalidDecimal {
    fn description(&self) -> &str {
        "Invalid Decimal"
    }
}

impl FromSql for Decimal {
    // Decimals are represented as follows:
    // Header:
    //  u16 numGroups
    //  i16 weightFirstGroup (10000^weight)
    //  u16 sign (0x0000 = positive, 0x4000 = negative, 0xC000 = NaN)
    //  i16 dscale. Number of digits (in base 10) to print after decimal separator
    //
    //  Psuedo code :
    //  const Decimals [
    //          0.0000000000000000000000000001,
    //          0.000000000000000000000001,
    //          0.00000000000000000001,
    //          0.0000000000000001,
    //          0.000000000001,
    //          0.00000001,
    //          0.0001,
    //          1,
    //          10000,
    //          100000000,
    //          1000000000000,
    //          10000000000000000,
    //          100000000000000000000,
    //          1000000000000000000000000,
    //          10000000000000000000000000000
    //  ]
    //  overflow = false
    //  result = 0
    //  for i = 0, weight = weightFirstGroup + 7; i < numGroups; i++, weight--
    //    group = read.u16
    //    if weight < 0 or weight > MaxNum
    //       overflow = true
    //    else
    //       result += Decimals[weight] * group
    //  sign == 0x4000 ? -result : result

    // So if we were to take the number: 3950.123456
    //
    //  Stored on Disk:
    //    00 03 00 00 00 00 00 06 0F 6E 04 D2 15 E0
    //
    //  Number of groups: 00 03
    //  Weight of first group: 00 00
    //  Sign: 00 00
    //  DScale: 00 06
    //
    // 0F 6E = 3950
    //   result = result + 3950 * 1;
    // 04 D2 = 1234
    //   result = result + 1234 * 0.0001;
    // 15 E0 = 5600
    //   result = result + 5600 * 0.00000001;
    //

    fn from_sql(_: &Type, raw: &[u8]) -> Result<Decimal, Box<error::Error + 'static + Sync + Send>> {
        let mut raw = Cursor::new(raw);
        let num_groups = try!(raw.read_u16::<BigEndian>());
        let weight = try!(raw.read_i16::<BigEndian>()); // 10000^weight
        // Sign: 0x0000 = positive, 0x4000 = negative, 0xC000 = NaN
        let sign = try!(raw.read_u16::<BigEndian>());
        // Number of digits (in base 10) to print after decimal separator
        let fixed_scale = try!(raw.read_u16::<BigEndian>()) as i32;

        // Build up a list of powers that will be used
        let mut powers = vec![Decimal::one()];
        let mut val = Decimal::one();
        let mult = Decimal::new(10000, 0);
        for _ in 1..num_groups {
            val *= mult;
            powers.push(val);
        }
        powers.reverse();

        // Now process the number
        let mut result = Decimal::zero();
        for i in 0..num_groups {
            let group = try!(raw.read_u16::<BigEndian>());
            let calculated = &powers[i as usize] * Decimal::new(group as i64, 0);
            result = result + calculated;
        }

        // Finally, adjust for the scale
        let mut scale = (num_groups as i16 - weight - 1) as i32 * 4;
        // Scale could be negative
        if scale < 0 {
            result *= Decimal::new(10i64.pow((scale * -1) as u32), 0);
            scale = 0;
        } else if scale > fixed_scale {
            result /= Decimal::new(10i64.pow((scale - fixed_scale) as u32), 0);
            scale = fixed_scale;
        }

        // Create the decimal
        let neg = sign == 0x4000;
        if result.set_scale(scale as u32).is_err() {
            return Err(Box::new(InvalidDecimal));
        }
        result.set_sign(!neg);

        // Normalize by truncating any trailing 0's from the decimal representation
        // This may not be the most efficient way of doing this
        if scale > 0 {
            let str_rep = result.to_string();
            let trailing_zeros = str_rep.chars().rev().take_while(|&x| x == '0').count();
            result = result.round_dp(scale as u32 - trailing_zeros as u32);
        }

        Ok(result)
    }

    fn accepts(ty: &Type) -> bool {
        match *ty {
            NUMERIC => true,
            _ => false,
        }
    }
}

impl ToSql for Decimal {
    fn to_sql(&self, _: &Type, out: &mut Vec<u8>) -> Result<IsNull, Box<error::Error + 'static + Sync + Send>> {
        let sign = if self.is_negative() { 0x4000 } else { 0x0000 };
        let scale = self.scale() as u16;

        let mut whole = *self;
        whole.set_scale(0).ok();
        whole.set_sign(true);
        let mut digits = whole.to_string();
        let split_point = if scale as usize > digits.len() {
            let mut new_digits = vec!['0'; scale as usize - digits.len() as usize];
            new_digits.extend(digits.chars());
            digits = new_digits.into_iter().collect::<String>();
            0
        } else {
            digits.len() as isize - scale as isize
        };
        let (whole_digits, decimal_digits) = digits.split_at(split_point as usize);
        let whole_portion = whole_digits
            .chars()
            .rev()
            .collect::<Vec<char>>()
            .chunks(4)
            .map(|x| {
                let mut x = x.to_owned();
                while x.len() < 4 {
                    x.push('0');
                }
                x.into_iter().rev().collect::<String>()
            })
            .rev()
            .collect::<Vec<String>>();
        let decimal_portion = decimal_digits
            .chars()
            .collect::<Vec<char>>()
            .chunks(4)
            .map(|x| {
                let mut x = x.to_owned();
                while x.len() < 4 {
                    x.push('0');
                }
                x.into_iter().collect::<String>()
            })
            .collect::<Vec<String>>();
        let weight = if whole_portion.is_empty() {
            -(decimal_portion.len() as i16)
        } else {
            whole_portion.len() as i16 - 1
        };
        let all_groups = whole_portion
            .into_iter()
            .chain(decimal_portion.into_iter())
            .skip_while(|ref x| *x == "0000")
            .collect::<Vec<String>>();
        let num_groups = all_groups.len() as u16;

        // Number of groups
        try!(out.write_u16::<BigEndian>(num_groups));
        // Weight of first group
        try!(out.write_i16::<BigEndian>(weight));
        // Sign
        try!(out.write_u16::<BigEndian>(sign));
        // DScale
        try!(out.write_u16::<BigEndian>(scale));
        // Now process the number
        for chunk in all_groups {
            let calculated = chunk.parse::<u16>().unwrap();
            try!(out.write_u16::<BigEndian>(calculated.to_u16().unwrap()));
        }
        Ok(IsNull::No)
    }

    fn accepts(ty: &Type) -> bool {
        match *ty {
            NUMERIC => true,
            _ => false,
        }
    }

    to_sql_checked!();
}

#[cfg(test)]
mod test {
    use super::*;
    use pg_crate::{Connection, TlsMode};
    use std::str::FromStr;

    fn read_type(sql_type: &str, checks: &[&'static str]) {
        let conn = match Connection::connect("postgres://postgres@localhost", TlsMode::None) {

            Ok(x) => x,
            Err(err) => panic!("{:#?}", err),
        };
        for &val in checks.iter() {
            let stmt = match conn.prepare(&*format!("SELECT {}::{}", val, sql_type)) {
                Ok(x) => x,
                Err(err) => panic!("{:#?}", err),
            };
            let result: Decimal = match stmt.query(&[]) {
                Ok(x) => x.iter().next().unwrap().get(0),
                Err(err) => panic!("{:#?}", err),
            };
            assert_eq!(val, result.to_string());
        }
    }

    fn write_type(sql_type: &str, checks: &[&'static str]) {
        let conn = match Connection::connect("postgres://postgres@localhost", TlsMode::None) {
            Ok(x) => x,
            Err(err) => panic!("{:#?}", err),
        };
        for &val in checks.iter() {
            let stmt = match conn.prepare(&*format!("SELECT $1::{}", sql_type)) {
                Ok(x) => x,
                Err(err) => panic!("{:#?}", err),
            };
            let number = Decimal::from_str(val).unwrap();
            let result: Decimal = match stmt.query(&[&number]) {
                Ok(x) => x.iter().next().unwrap().get(0),
                Err(err) => panic!("{:#?}", err),
            };
            assert_eq!(val, result.to_string());
        }
    }

    #[test]
    fn test_null() {
        let conn = match Connection::connect("postgres://postgres@localhost", TlsMode::None) {
            Ok(x) => x,
            Err(err) => panic!("{:#?}", err),
        };

        // Test NULL
        let stmt = match conn.prepare(&"SELECT NULL::numeric") {
            Ok(x) => x,
            Err(err) => panic!("{:#?}", err),
        };
        let result: Option<Decimal> = match stmt.query(&[]) {
            Ok(x) => x.iter().next().unwrap().get(0),
            Err(err) => panic!("{:#?}", err),
        };
        assert_eq!(None, result);
    }

    #[test]
    fn read_numeric_type() {
        read_type(
            "NUMERIC(26,6)",
            &[
                "3950.123456",
                "3950",
                "0.1",
                "0.01",
                "0.001",
                "0.0001",
                "0.00001",
                "0.000001",
                "1",
                "-100",
                "-123.456",
                "119996.25",
                "1000000",
                "9999999.99999",
            ],
        );
    }

    #[test]
    fn write_numeric_type() {
        write_type(
            "NUMERIC(26,6)",
            &[
                "3950.123456",
                "3950",
                "0.1",
                "0.01",
                "0.001",
                "0.0001",
                "0.00001",
                "0.000001",
                "1",
                "-100",
                "-123.456",
                "119996.25",
                "1000000",
                "9999999.99999",
            ],
        );
    }
}
<|endoftext|>


<commit_before>//! Types for the *m.presence* event.

use ruma_identifiers::{EventId, UserId};

event! {
    /// Informs the client of a user's presence state change.
    pub struct PresenceEvent(PresenceEventContent) {
        /// The unique identifier for the event.
        pub event_id: EventId
    }
}

/// The payload of a `PresenceEvent`.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct PresenceEventContent {
    /// The current avatar URL for this user.
    #[serde(skip_serializing_if="Option::is_none")]
    pub avatar_url: Option<String>,

    /// Whether or not the user is currently active.
    pub currently_active: bool,

    /// The current display name for this user.
    #[serde(skip_serializing_if="Option::is_none")]
    pub displayname: Option<String>,

    /// The last time since this used performed some action, in milliseconds.
    #[serde(skip_serializing_if="Option::is_none")]
    pub last_active_ago: Option<u64>,

    /// The presence state for this user.
    pub presence: PresenceState,

    /// The unique identifier for the user associated with this event.
    pub user_id: UserId,
}

/// A description of a user's connectivity and availability for chat.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum PresenceState {
    /// Disconnected from the service.
    #[serde(rename="offline")]
    Offline,

    /// Connected to the service.
    #[serde(rename="online")]
    Online,

    /// Connected to the service but not available for chat.
    #[serde(rename="unavailable")]
    Unavailable,
}
<commit_msg>Add missing trait implementations for PresenceState<commit_after>//! Types for the *m.presence* event.

use ruma_identifiers::{EventId, UserId};

event! {
    /// Informs the client of a user's presence state change.
    pub struct PresenceEvent(PresenceEventContent) {
        /// The unique identifier for the event.
        pub event_id: EventId
    }
}

/// The payload of a `PresenceEvent`.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct PresenceEventContent {
    /// The current avatar URL for this user.
    #[serde(skip_serializing_if="Option::is_none")]
    pub avatar_url: Option<String>,

    /// Whether or not the user is currently active.
    pub currently_active: bool,

    /// The current display name for this user.
    #[serde(skip_serializing_if="Option::is_none")]
    pub displayname: Option<String>,

    /// The last time since this used performed some action, in milliseconds.
    #[serde(skip_serializing_if="Option::is_none")]
    pub last_active_ago: Option<u64>,

    /// The presence state for this user.
    pub presence: PresenceState,

    /// The unique identifier for the user associated with this event.
    pub user_id: UserId,
}

/// A description of a user's connectivity and availability for chat.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum PresenceState {
    /// Disconnected from the service.
    #[serde(rename="offline")]
    Offline,

    /// Connected to the service.
    #[serde(rename="online")]
    Online,

    /// Connected to the service but not available for chat.
    #[serde(rename="unavailable")]
    Unavailable,
}

impl_enum! {
    PresenceState {
        Offline => "offline",
        Online => "online",
        Unavailable => "unavailable",
    }
}
<|endoftext|>


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

//! Rust helpers for Gecko's `nsStyleAutoArray`.

use gecko_bindings::bindings::Gecko_EnsureStyleAnimationArrayLength;
use gecko_bindings::bindings::Gecko_EnsureStyleTransitionArrayLength;
use gecko_bindings::structs::{StyleAnimation, StyleTransition};
use gecko_bindings::structs::nsStyleAutoArray;
use std::iter::{once, Chain, Once, IntoIterator};
use std::ops::{Index, IndexMut};
use std::slice::{Iter, IterMut};

impl<T> Index<usize> for nsStyleAutoArray<T> {
    type Output = T;
    fn index(&self, index: usize) -> &T {
        if index > self.len() {
            panic!("out of range")
        }
        match index {
            0 => &self.mFirstElement,
            _ => &self.mOtherElements[index - 1],
        }
    }
}

impl<T> IndexMut<usize> for nsStyleAutoArray<T> {
    fn index_mut(&mut self, index: usize) -> &mut T {
        if index > self.len() {
            panic!("out of range")
        }
        match index {
            0 => &mut self.mFirstElement,
            _ => &mut self.mOtherElements[index - 1],
        }
    }
}

impl<T> nsStyleAutoArray<T> {
    /// Mutably iterate over the array elements.
    pub fn iter_mut(&mut self) -> Chain<Once<&mut T>, IterMut<T>> {
        once(&mut self.mFirstElement).chain(self.mOtherElements.iter_mut())
    }

    /// Iterate over the array elements.
    pub fn iter(&self) -> Chain<Once<&T>, Iter<T>> {
        once(&self.mFirstElement).chain(self.mOtherElements.iter())
    }

    /// Returns the length of the array.
    ///
    /// Note that often structs containing autoarrays will have additional
    /// member fields that contain the length, which must be kept in sync.
    pub fn len(&self) -> usize {
        1 + self.mOtherElements.len()
    }
}

impl nsStyleAutoArray<StyleAnimation> {
    /// Ensures that the array has length at least the given length.
    pub fn ensure_len(&mut self, len: usize) {
        unsafe {
            Gecko_EnsureStyleAnimationArrayLength(self as *mut nsStyleAutoArray<StyleAnimation> as *mut _, len);
        }
    }
}

impl nsStyleAutoArray<StyleTransition> {
    /// Ensures that the array has length at least the given length.
    pub fn ensure_len(&mut self, len: usize) {
        unsafe {
            Gecko_EnsureStyleTransitionArrayLength(self as *mut nsStyleAutoArray<StyleTransition> as *mut _, len);
        }
    }
}

impl<'a, T> IntoIterator for &'a mut nsStyleAutoArray<T> {
    type Item = &'a mut T;
    type IntoIter = Chain<Once<&'a mut T>, IterMut<'a, T>>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}
<commit_msg>style: Remove needless and bogus bounds-check.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Rust helpers for Gecko's `nsStyleAutoArray`.

use gecko_bindings::bindings::Gecko_EnsureStyleAnimationArrayLength;
use gecko_bindings::bindings::Gecko_EnsureStyleTransitionArrayLength;
use gecko_bindings::structs::{StyleAnimation, StyleTransition};
use gecko_bindings::structs::nsStyleAutoArray;
use std::iter::{once, Chain, Once, IntoIterator};
use std::ops::{Index, IndexMut};
use std::slice::{Iter, IterMut};

impl<T> Index<usize> for nsStyleAutoArray<T> {
    type Output = T;
    fn index(&self, index: usize) -> &T {
        match index {
            0 => &self.mFirstElement,
            _ => &self.mOtherElements[index - 1],
        }
    }
}

impl<T> IndexMut<usize> for nsStyleAutoArray<T> {
    fn index_mut(&mut self, index: usize) -> &mut T {
        match index {
            0 => &mut self.mFirstElement,
            _ => &mut self.mOtherElements[index - 1],
        }
    }
}

impl<T> nsStyleAutoArray<T> {
    /// Mutably iterate over the array elements.
    pub fn iter_mut(&mut self) -> Chain<Once<&mut T>, IterMut<T>> {
        once(&mut self.mFirstElement).chain(self.mOtherElements.iter_mut())
    }

    /// Iterate over the array elements.
    pub fn iter(&self) -> Chain<Once<&T>, Iter<T>> {
        once(&self.mFirstElement).chain(self.mOtherElements.iter())
    }

    /// Returns the length of the array.
    ///
    /// Note that often structs containing autoarrays will have additional
    /// member fields that contain the length, which must be kept in sync.
    pub fn len(&self) -> usize {
        1 + self.mOtherElements.len()
    }
}

impl nsStyleAutoArray<StyleAnimation> {
    /// Ensures that the array has length at least the given length.
    pub fn ensure_len(&mut self, len: usize) {
        unsafe {
            Gecko_EnsureStyleAnimationArrayLength(self as *mut nsStyleAutoArray<StyleAnimation> as *mut _, len);
        }
    }
}

impl nsStyleAutoArray<StyleTransition> {
    /// Ensures that the array has length at least the given length.
    pub fn ensure_len(&mut self, len: usize) {
        unsafe {
            Gecko_EnsureStyleTransitionArrayLength(self as *mut nsStyleAutoArray<StyleTransition> as *mut _, len);
        }
    }
}

impl<'a, T> IntoIterator for &'a mut nsStyleAutoArray<T> {
    type Item = &'a mut T;
    type IntoIter = Chain<Once<&'a mut T>, IterMut<'a, T>>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}
<|endoftext|>


<commit_before>//! Parse the result of `LineReader` into parts.
//!
//! Split the result of `LineReader` into property. A property contains:
//! - A name formated in uppercase.
//! - An optional list of parameters represented by a vector of `(key/value)` tuple . The key is
//! formatted in uppercase and the value stay untouched.
//! - A value stay untouched.
//!
//! It work for both the Vcard and Ical format.
//!
//! #### Warning
//!   The parsers `PropertyParser` only parse the content and set to uppercase the case-insensitive
//!   fields. No checks are made on the fields validity.
//!
//! # Examples
//!
//! ```toml
//! [dependencies.ical]
//! version = "0.3.*"
//! default-features = false
//! features = ["property"]
//! ```
//!
//! ```rust
//! extern crate ical;
//!
//! use std::io::BufReader;
//! use std::fs::File;
//!
//! let buf = BufReader::new(File::open("./tests/ressources/vcard_input.vcf")
//!     .unwrap());
//!
//! let reader = ical::PropertyParser::from_reader(buf);
//!
//! for line in reader {
//!     println!("{:?}", line);
//! }
//! ```

// Sys mods
use std::fmt;
use std::io::BufRead;
use std::iter::Iterator;

// Internal mods
use crate::line::{Line, LineReader};
use crate::property::errors::*;

/// A VCARD/ICAL property.
#[derive(Debug, Clone, Default)]
pub struct Property {
    /// Property name.
    pub name: String,
    /// Property list of parameters.
    pub params: Option<Vec<(String, Vec<String>)>>,
    /// Property value.
    pub value: Option<String>,
}

impl Property {
    /// Return a new `Property` object.
    pub fn new() -> Property {
        Property {
            name: String::new(),
            params: None,
            value: None,
        }
    }
}

impl fmt::Display for Property {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "name: {}\nparams: {:?}\nvalue: {:?}",
            self.name, self.params, self.value
        )
    }
}

/// Take a `LineReader` and return a list of `Property`.
#[derive(Debug, Clone)]
pub struct PropertyParser<B> {
    line_reader: LineReader<B>,
}

impl<B: BufRead> PropertyParser<B> {
    /// Return a new `PropertyParser` from a `LineReader`.
    pub fn new(line_reader: LineReader<B>) -> PropertyParser<B> {
        PropertyParser {
            line_reader: line_reader,
        }
    }

    /// Return a new `PropertyParser` from a `Reader`.
    pub fn from_reader(reader: B) -> PropertyParser<B> {
        let line_reader = LineReader::new(reader);

        PropertyParser {
            line_reader: line_reader,
        }
    }

    fn parse(&self, line: Line) -> Result<Property> {
        let mut property = Property::new();

        let mut to_parse = line.as_str();

        // Parse name.
        let end_name_index;

        let mut param_index = to_parse
            .find(::PARAM_DELIMITER)
            .unwrap_or(usize::max_value());
        let mut value_index = to_parse
            .find(::VALUE_DELIMITER)
            .unwrap_or(usize::max_value());

        if param_index < value_index && param_index != 0 {
            end_name_index = param_index;
        } else if value_index != usize::max_value() && value_index != 0 {
            end_name_index = value_index;
        } else {
            return Err(ErrorKind::MissingName(line.number()).into());
        }

        {
            let split = to_parse.split_at(end_name_index);
            property.name = split.0.to_string();
            to_parse = split.1;
        }

        // Parse parameters.
        value_index = to_parse
            .find(::VALUE_DELIMITER)
            .unwrap_or(usize::max_value());
        param_index = to_parse
            .find(::PARAM_DELIMITER)
            .unwrap_or(usize::max_value());

        // If there is a PARAM_DELIMITER and it not after the VALUE_DELIMITER
        // there is arguments.
        if param_index != usize::max_value() && value_index > param_index {
            let mut param_list = Vec::new();

            while to_parse.starts_with(::PARAM_DELIMITER) {
                to_parse = to_parse.trim_left_matches(::PARAM_DELIMITER);

                // Split the param key and the rest of the line
                let mut param_elements = to_parse.splitn(2, ::PARAM_NAME_DELIMITER);

                let key = param_elements
                    .next()
                    .and_then(|key| {
                        if key.is_empty() {
                            return None;
                        }

                        Some(key)
                    })
                    .ok_or_else(|| ErrorKind::MissingParamKey(line.number()))?;

                to_parse = param_elements.next().ok_or_else(|| {
                    ErrorKind::MissingDelimiter(::PARAM_NAME_DELIMITER, line.number())
                })?;

                let mut values = Vec::new();

                let mut i = 10;

                // Parse parameter value.
                while i > 0 {
                    i -= 1;
                    if to_parse.starts_with('"') {
                        // This is a dquoted value. (NAME:Foo="Bar":value)
                        let mut elements = to_parse.splitn(3, ::PARAM_QUOTE).skip(1);
                        // unwrap is safe here as we have already check above if there is on '"'.
                        values.push(
                            elements
                                .next()
                                .ok_or_else(|| ErrorKind::MissingClosingQuote(line.number()))?
                                .to_string(),
                        );

                        to_parse = elements
                            .next()
                            .ok_or_else(|| ErrorKind::MissingClosingQuote(line.number()))?
                    } else {
                        // This is a 'raw' value. (NAME;Foo=Bar:value)

                        // Try to find the next param separator.
                        let param_delimiter = to_parse
                            .find(::PARAM_DELIMITER)
                            .unwrap_or(usize::max_value());
                        let value_delimiter = to_parse
                            .find(::VALUE_DELIMITER)
                            .unwrap_or(usize::max_value());
                        let param_value_delimiter = to_parse
                            .find(::PARAM_VALUE_DELIMITER)
                            .unwrap_or(usize::max_value());

                        let end_param_value = {
                            if param_value_delimiter < value_delimiter
                                && param_value_delimiter < param_delimiter
                            {
                                Ok(param_value_delimiter)
                            } else if param_delimiter < value_delimiter
                                && param_delimiter < param_value_delimiter
                            {
                                Ok(param_delimiter)
                            } else if value_delimiter != usize::max_value() {
                                Ok(value_delimiter)
                            } else {
                                Err(ErrorKind::MissingContentAfter(
                                    ::PARAM_NAME_DELIMITER,
                                    line.number(),
                                ))
                            }
                        }?;

                        let elements = to_parse.split_at(end_param_value);
                        values.push(elements.0.to_string());
                        to_parse = elements.1;
                    }

                    if !to_parse.starts_with(::PARAM_VALUE_DELIMITER) {
                        break;
                    }

                    to_parse = to_parse.trim_left_matches(::PARAM_VALUE_DELIMITER);
                }

                param_list.push((key.to_uppercase(), values));
            }

            property.params = Some(param_list);
        } else {
            property.params = None;
        }

        // Parse value
        to_parse = to_parse.trim_left_matches(::VALUE_DELIMITER);
        if to_parse.is_empty() {
            property.value = None;
        } else {
            property.value = Some(to_parse.to_string());
        }

        Ok(property)
    }
}

impl<B: BufRead> Iterator for PropertyParser<B> {
    type Item = Result<Property>;

    fn next(&mut self) -> Option<Result<Property>> {
        self.line_reader.next().map(|line| self.parse(line))
    }
}

pub mod errors {
    //! The property errors

    error_chain! {
        types {
            Error, ErrorKind, ResultExt, Result;
        }

        foreign_links {
        }

        errors {

            /// A property name is missing.
            MissingName(line: usize) {
                description("missing property name")
                    display("Line {}: Missing property name.", line)
            }

            /// A quote is not closed.
            MissingClosingQuote(line: usize) {
                description("missing closing quote")
                    display("Line {}: Missing a closing quote.", line)
            }

            /// A delimiter is missing.
            MissingDelimiter(delimiter: char, line: usize) {
                description("missing delimiter")
                    display("Line {}: Missing a \"{}\" delimiter.", line, delimiter)
            }

            /// A delimiter is missing.
            MissingContentAfter(letter: char, line: usize) {
                description("missing content")
                    display("Line {}: Missing content after \"{}\".", line, letter)
            }

            /// A parameter need a key.
            MissingParamKey(line: usize) {
                description("missing param key")
                    display("Line {}: Missing a parameter key.", line)
            }
        }
    }
}
<commit_msg>Remove deprecated call to trim_left_matches<commit_after>//! Parse the result of `LineReader` into parts.
//!
//! Split the result of `LineReader` into property. A property contains:
//! - A name formated in uppercase.
//! - An optional list of parameters represented by a vector of `(key/value)` tuple . The key is
//! formatted in uppercase and the value stay untouched.
//! - A value stay untouched.
//!
//! It work for both the Vcard and Ical format.
//!
//! #### Warning
//!   The parsers `PropertyParser` only parse the content and set to uppercase the case-insensitive
//!   fields. No checks are made on the fields validity.
//!
//! # Examples
//!
//! ```toml
//! [dependencies.ical]
//! version = "0.3.*"
//! default-features = false
//! features = ["property"]
//! ```
//!
//! ```rust
//! extern crate ical;
//!
//! use std::io::BufReader;
//! use std::fs::File;
//!
//! let buf = BufReader::new(File::open("./tests/ressources/vcard_input.vcf")
//!     .unwrap());
//!
//! let reader = ical::PropertyParser::from_reader(buf);
//!
//! for line in reader {
//!     println!("{:?}", line);
//! }
//! ```

// Sys mods
use std::fmt;
use std::io::BufRead;
use std::iter::Iterator;

// Internal mods
use crate::line::{Line, LineReader};
use crate::property::errors::*;

/// A VCARD/ICAL property.
#[derive(Debug, Clone, Default)]
pub struct Property {
    /// Property name.
    pub name: String,
    /// Property list of parameters.
    pub params: Option<Vec<(String, Vec<String>)>>,
    /// Property value.
    pub value: Option<String>,
}

impl Property {
    /// Return a new `Property` object.
    pub fn new() -> Property {
        Property {
            name: String::new(),
            params: None,
            value: None,
        }
    }
}

impl fmt::Display for Property {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "name: {}\nparams: {:?}\nvalue: {:?}",
            self.name, self.params, self.value
        )
    }
}

/// Take a `LineReader` and return a list of `Property`.
#[derive(Debug, Clone)]
pub struct PropertyParser<B> {
    line_reader: LineReader<B>,
}

impl<B: BufRead> PropertyParser<B> {
    /// Return a new `PropertyParser` from a `LineReader`.
    pub fn new(line_reader: LineReader<B>) -> PropertyParser<B> {
        PropertyParser {
            line_reader: line_reader,
        }
    }

    /// Return a new `PropertyParser` from a `Reader`.
    pub fn from_reader(reader: B) -> PropertyParser<B> {
        let line_reader = LineReader::new(reader);

        PropertyParser {
            line_reader: line_reader,
        }
    }

    fn parse(&self, line: Line) -> Result<Property> {
        let mut property = Property::new();

        let mut to_parse = line.as_str();

        // Parse name.
        let end_name_index;

        let mut param_index = to_parse
            .find(::PARAM_DELIMITER)
            .unwrap_or(usize::max_value());
        let mut value_index = to_parse
            .find(::VALUE_DELIMITER)
            .unwrap_or(usize::max_value());

        if param_index < value_index && param_index != 0 {
            end_name_index = param_index;
        } else if value_index != usize::max_value() && value_index != 0 {
            end_name_index = value_index;
        } else {
            return Err(ErrorKind::MissingName(line.number()).into());
        }

        {
            let split = to_parse.split_at(end_name_index);
            property.name = split.0.to_string();
            to_parse = split.1;
        }

        // Parse parameters.
        value_index = to_parse
            .find(::VALUE_DELIMITER)
            .unwrap_or(usize::max_value());
        param_index = to_parse
            .find(::PARAM_DELIMITER)
            .unwrap_or(usize::max_value());

        // If there is a PARAM_DELIMITER and it not after the VALUE_DELIMITER
        // there is arguments.
        if param_index != usize::max_value() && value_index > param_index {
            let mut param_list = Vec::new();

            while to_parse.starts_with(::PARAM_DELIMITER) {
                to_parse = to_parse.trim_start_matches(::PARAM_DELIMITER);

                // Split the param key and the rest of the line
                let mut param_elements = to_parse.splitn(2, ::PARAM_NAME_DELIMITER);

                let key = param_elements
                    .next()
                    .and_then(|key| {
                        if key.is_empty() {
                            return None;
                        }

                        Some(key)
                    })
                    .ok_or_else(|| ErrorKind::MissingParamKey(line.number()))?;

                to_parse = param_elements.next().ok_or_else(|| {
                    ErrorKind::MissingDelimiter(::PARAM_NAME_DELIMITER, line.number())
                })?;

                let mut values = Vec::new();

                let mut i = 10;

                // Parse parameter value.
                while i > 0 {
                    i -= 1;
                    if to_parse.starts_with('"') {
                        // This is a dquoted value. (NAME:Foo="Bar":value)
                        let mut elements = to_parse.splitn(3, ::PARAM_QUOTE).skip(1);
                        // unwrap is safe here as we have already check above if there is on '"'.
                        values.push(
                            elements
                                .next()
                                .ok_or_else(|| ErrorKind::MissingClosingQuote(line.number()))?
                                .to_string(),
                        );

                        to_parse = elements
                            .next()
                            .ok_or_else(|| ErrorKind::MissingClosingQuote(line.number()))?
                    } else {
                        // This is a 'raw' value. (NAME;Foo=Bar:value)

                        // Try to find the next param separator.
                        let param_delimiter = to_parse
                            .find(::PARAM_DELIMITER)
                            .unwrap_or(usize::max_value());
                        let value_delimiter = to_parse
                            .find(::VALUE_DELIMITER)
                            .unwrap_or(usize::max_value());
                        let param_value_delimiter = to_parse
                            .find(::PARAM_VALUE_DELIMITER)
                            .unwrap_or(usize::max_value());

                        let end_param_value = {
                            if param_value_delimiter < value_delimiter
                                && param_value_delimiter < param_delimiter
                            {
                                Ok(param_value_delimiter)
                            } else if param_delimiter < value_delimiter
                                && param_delimiter < param_value_delimiter
                            {
                                Ok(param_delimiter)
                            } else if value_delimiter != usize::max_value() {
                                Ok(value_delimiter)
                            } else {
                                Err(ErrorKind::MissingContentAfter(
                                    ::PARAM_NAME_DELIMITER,
                                    line.number(),
                                ))
                            }
                        }?;

                        let elements = to_parse.split_at(end_param_value);
                        values.push(elements.0.to_string());
                        to_parse = elements.1;
                    }

                    if !to_parse.starts_with(::PARAM_VALUE_DELIMITER) {
                        break;
                    }

                    to_parse = to_parse.trim_start_matches(::PARAM_VALUE_DELIMITER);
                }

                param_list.push((key.to_uppercase(), values));
            }

            property.params = Some(param_list);
        } else {
            property.params = None;
        }

        // Parse value
        to_parse = to_parse.trim_start_matches(::VALUE_DELIMITER);
        if to_parse.is_empty() {
            property.value = None;
        } else {
            property.value = Some(to_parse.to_string());
        }

        Ok(property)
    }
}

impl<B: BufRead> Iterator for PropertyParser<B> {
    type Item = Result<Property>;

    fn next(&mut self) -> Option<Result<Property>> {
        self.line_reader.next().map(|line| self.parse(line))
    }
}

pub mod errors {
    //! The property errors

    error_chain! {
        types {
            Error, ErrorKind, ResultExt, Result;
        }

        foreign_links {
        }

        errors {

            /// A property name is missing.
            MissingName(line: usize) {
                description("missing property name")
                    display("Line {}: Missing property name.", line)
            }

            /// A quote is not closed.
            MissingClosingQuote(line: usize) {
                description("missing closing quote")
                    display("Line {}: Missing a closing quote.", line)
            }

            /// A delimiter is missing.
            MissingDelimiter(delimiter: char, line: usize) {
                description("missing delimiter")
                    display("Line {}: Missing a \"{}\" delimiter.", line, delimiter)
            }

            /// A delimiter is missing.
            MissingContentAfter(letter: char, line: usize) {
                description("missing content")
                    display("Line {}: Missing content after \"{}\".", line, letter)
            }

            /// A parameter need a key.
            MissingParamKey(line: usize) {
                description("missing param key")
                    display("Line {}: Missing a parameter key.", line)
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt::{self, Display};

pub static HEADER: &str = include_str!("include/cxx.h");

pub fn get(guard: &str) -> &'static str {
    let ifndef = format!("#ifndef {}", guard);
    let endif = format!("#endif // {}", guard);
    let begin = find_line(&ifndef);
    let end = find_line(&endif);
    if let (Some(begin), Some(end)) = (begin, end) {
        &HEADER[begin..end + endif.len()]
    } else {
        panic!("not found in cxx.h header: {}", guard)
    }
}

fn find_line(line: &str) -> Option<usize> {
    let mut offset = 0;
    loop {
        offset += HEADER[offset..].find(line)?;
        let rest = &HEADER[offset + line.len()..];
        if rest.starts_with('\n') || rest.starts_with('\r') {
            return Some(offset);
        }
        offset += line.len();
    }
}

#[derive(Default, PartialEq)]
pub struct Includes {
    custom: Vec<String>,
    pub array: bool,
    pub cstddef: bool,
    pub cstdint: bool,
    pub cstring: bool,
    pub exception: bool,
    pub memory: bool,
    pub string: bool,
    pub type_traits: bool,
    pub utility: bool,
    pub vector: bool,
    pub base_tsd: bool,
}

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

    pub fn insert(&mut self, include: String) {
        self.custom.push(include);
    }
}

impl Extend<String> for Includes {
    fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
        self.custom.extend(iter);
    }
}

impl Display for Includes {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for include in &self.custom {
            writeln!(f, "#include \"{}\"", include.escape_default())?;
        }
        if self.array {
            writeln!(f, "#include <array>")?;
        }
        if self.cstddef {
            writeln!(f, "#include <cstddef>")?;
        }
        if self.cstdint {
            writeln!(f, "#include <cstdint>")?;
        }
        if self.cstring {
            writeln!(f, "#include <cstring>")?;
        }
        if self.exception {
            writeln!(f, "#include <exception>")?;
        }
        if self.memory {
            writeln!(f, "#include <memory>")?;
        }
        if self.string {
            writeln!(f, "#include <string>")?;
        }
        if self.type_traits {
            writeln!(f, "#include <type_traits>")?;
        }
        if self.utility {
            writeln!(f, "#include <utility>")?;
        }
        if self.base_tsd {
            writeln!(f, "#if defined(_WIN32)")?;
            writeln!(f, "#include <BaseTsd.h>")?;
            writeln!(f, "#endif")?;
        }
        if *self != Self::default() {
            writeln!(f)?;
        }
        Ok(())
    }
}
<commit_msg>Emit <vector> include if generated code requires it<commit_after>use std::fmt::{self, Display};

pub static HEADER: &str = include_str!("include/cxx.h");

pub fn get(guard: &str) -> &'static str {
    let ifndef = format!("#ifndef {}", guard);
    let endif = format!("#endif // {}", guard);
    let begin = find_line(&ifndef);
    let end = find_line(&endif);
    if let (Some(begin), Some(end)) = (begin, end) {
        &HEADER[begin..end + endif.len()]
    } else {
        panic!("not found in cxx.h header: {}", guard)
    }
}

fn find_line(line: &str) -> Option<usize> {
    let mut offset = 0;
    loop {
        offset += HEADER[offset..].find(line)?;
        let rest = &HEADER[offset + line.len()..];
        if rest.starts_with('\n') || rest.starts_with('\r') {
            return Some(offset);
        }
        offset += line.len();
    }
}

#[derive(Default, PartialEq)]
pub struct Includes {
    custom: Vec<String>,
    pub array: bool,
    pub cstddef: bool,
    pub cstdint: bool,
    pub cstring: bool,
    pub exception: bool,
    pub memory: bool,
    pub string: bool,
    pub type_traits: bool,
    pub utility: bool,
    pub vector: bool,
    pub base_tsd: bool,
}

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

    pub fn insert(&mut self, include: String) {
        self.custom.push(include);
    }
}

impl Extend<String> for Includes {
    fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
        self.custom.extend(iter);
    }
}

impl Display for Includes {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for include in &self.custom {
            writeln!(f, "#include \"{}\"", include.escape_default())?;
        }
        if self.array {
            writeln!(f, "#include <array>")?;
        }
        if self.cstddef {
            writeln!(f, "#include <cstddef>")?;
        }
        if self.cstdint {
            writeln!(f, "#include <cstdint>")?;
        }
        if self.cstring {
            writeln!(f, "#include <cstring>")?;
        }
        if self.exception {
            writeln!(f, "#include <exception>")?;
        }
        if self.memory {
            writeln!(f, "#include <memory>")?;
        }
        if self.string {
            writeln!(f, "#include <string>")?;
        }
        if self.type_traits {
            writeln!(f, "#include <type_traits>")?;
        }
        if self.utility {
            writeln!(f, "#include <utility>")?;
        }
        if self.vector {
            writeln!(f, "#include <vector>")?;
        }
        if self.base_tsd {
            writeln!(f, "#if defined(_WIN32)")?;
            writeln!(f, "#include <BaseTsd.h>")?;
            writeln!(f, "#endif")?;
        }
        if *self != Self::default() {
            writeln!(f)?;
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use core::mem;
use raw::bitmask::BitMask;
use raw::EMPTY;

#[cfg(target_arch = "x86")]
use core::arch::x86;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64 as x86;

pub type BitMaskWord = u32;
pub const BITMASK_SHIFT: u32 = 0;
pub const BITMASK_MASK: u32 = 0xffff;

/// Abstraction over a group of control bytes which can be scanned in
/// parallel.
///
/// This implementation uses a 128-bit SSE value.
pub struct Group(x86::__m128i);

impl Group {
    /// Number of bytes in the group.
    pub const WIDTH: usize = mem::size_of::<Self>();

    /// Returns a full group of empty bytes, suitable for use as the initial
    /// value for an empty hash table.
    ///
    /// This is guaranteed to be aligned to the group size.
    #[inline]
    pub fn static_empty() -> &'static [u8] {
        #[repr(C)]
        struct Dummy {
            _align: [x86::__m128i; 0],
            bytes: [u8; Group::WIDTH],
        };
        const DUMMY: Dummy = Dummy {
            _align: [],
            bytes: [EMPTY; Group::WIDTH],
        };
        &DUMMY.bytes
    }

    /// Loads a group of bytes starting at the given address.
    #[inline]
    pub unsafe fn load(ptr: *const u8) -> Group {
        Group(x86::_mm_loadu_si128(ptr as *const _))
    }

    /// Loads a group of bytes starting at the given address, which must be
    /// aligned to `WIDTH`.
    #[inline]
    pub unsafe fn load_aligned(ptr: *const u8) -> Group {
        Group(x86::_mm_load_si128(ptr as *const _))
    }

    /// Stores the group of bytes to the given address, which must be
    /// aligned to `WIDTH`.
    #[inline]
    pub unsafe fn store_aligned(&self, ptr: *mut u8) {
        x86::_mm_store_si128(ptr as *mut _, self.0);
    }

    /// Returns a `BitMask` indicating all bytes in the group which have
    /// the given value.
    #[inline]
    pub fn match_byte(&self, byte: u8) -> BitMask {
        unsafe {
            let cmp = x86::_mm_cmpeq_epi8(self.0, x86::_mm_set1_epi8(byte as i8));
            BitMask(x86::_mm_movemask_epi8(cmp) as u32)
        }
    }

    /// Returns a `BitMask` indicating all bytes in the group which are
    /// `EMPTY`.
    #[inline]
    pub fn match_empty(&self) -> BitMask {
        self.match_byte(EMPTY)
    }

    /// Returns a `BitMask` indicating all bytes in the group which are
    /// `EMPTY` pr `DELETED`.
    #[inline]
    pub fn match_empty_or_deleted(&self) -> BitMask {
        unsafe { BitMask(x86::_mm_movemask_epi8(self.0) as u32) }
    }

    /// Performs the following transformation on all bytes in the group:
    /// - `EMPTY => EMPTY`
    /// - `DELETED => EMPTY`
    /// - `FULL => DELETED`
    #[inline]
    pub fn convert_special_to_empty_and_full_to_deleted(&self) -> Group {
        unsafe {
            let zero = x86::_mm_setzero_si128();
            let special = x86::_mm_cmpgt_epi8(zero, self.0);
            Group(x86::_mm_or_si128(special, x86::_mm_set1_epi8(0x80u8 as i8)))
        }
    }
}
<commit_msg>Change SSE2 mask to a u16<commit_after>use core::mem;
use raw::bitmask::BitMask;
use raw::EMPTY;

#[cfg(target_arch = "x86")]
use core::arch::x86;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64 as x86;

pub type BitMaskWord = u16;
pub const BITMASK_SHIFT: u32 = 0;
pub const BITMASK_MASK: u16 = 0xffff;

/// Abstraction over a group of control bytes which can be scanned in
/// parallel.
///
/// This implementation uses a 128-bit SSE value.
pub struct Group(x86::__m128i);

impl Group {
    /// Number of bytes in the group.
    pub const WIDTH: usize = mem::size_of::<Self>();

    /// Returns a full group of empty bytes, suitable for use as the initial
    /// value for an empty hash table.
    ///
    /// This is guaranteed to be aligned to the group size.
    #[inline]
    pub fn static_empty() -> &'static [u8] {
        #[repr(C)]
        struct Dummy {
            _align: [x86::__m128i; 0],
            bytes: [u8; Group::WIDTH],
        };
        const DUMMY: Dummy = Dummy {
            _align: [],
            bytes: [EMPTY; Group::WIDTH],
        };
        &DUMMY.bytes
    }

    /// Loads a group of bytes starting at the given address.
    #[inline]
    pub unsafe fn load(ptr: *const u8) -> Group {
        Group(x86::_mm_loadu_si128(ptr as *const _))
    }

    /// Loads a group of bytes starting at the given address, which must be
    /// aligned to `WIDTH`.
    #[inline]
    pub unsafe fn load_aligned(ptr: *const u8) -> Group {
        Group(x86::_mm_load_si128(ptr as *const _))
    }

    /// Stores the group of bytes to the given address, which must be
    /// aligned to `WIDTH`.
    #[inline]
    pub unsafe fn store_aligned(&self, ptr: *mut u8) {
        x86::_mm_store_si128(ptr as *mut _, self.0);
    }

    /// Returns a `BitMask` indicating all bytes in the group which have
    /// the given value.
    #[inline]
    pub fn match_byte(&self, byte: u8) -> BitMask {
        unsafe {
            let cmp = x86::_mm_cmpeq_epi8(self.0, x86::_mm_set1_epi8(byte as i8));
            BitMask(x86::_mm_movemask_epi8(cmp) as u16)
        }
    }

    /// Returns a `BitMask` indicating all bytes in the group which are
    /// `EMPTY`.
    #[inline]
    pub fn match_empty(&self) -> BitMask {
        self.match_byte(EMPTY)
    }

    /// Returns a `BitMask` indicating all bytes in the group which are
    /// `EMPTY` pr `DELETED`.
    #[inline]
    pub fn match_empty_or_deleted(&self) -> BitMask {
        unsafe { BitMask(x86::_mm_movemask_epi8(self.0) as u16) }
    }

    /// Performs the following transformation on all bytes in the group:
    /// - `EMPTY => EMPTY`
    /// - `DELETED => EMPTY`
    /// - `FULL => DELETED`
    #[inline]
    pub fn convert_special_to_empty_and_full_to_deleted(&self) -> Group {
        unsafe {
            let zero = x86::_mm_setzero_si128();
            let special = x86::_mm_cmpgt_epi8(zero, self.0);
            Group(x86::_mm_or_si128(special, x86::_mm_set1_epi8(0x80u8 as i8)))
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

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

#![allow(dead_code)]
use raft::errors::{Result, Error};
use raft::Storage;
use protobuf::{self, RepeatedField};
use kvproto::raftpb::{HardState, Entry, EntryType, Message, Snapshot, MessageType, ConfChange,
                      ConfChangeType, ConfState};
use raft::raft::{Config, Raft, SoftState, INVALID_ID};
use raft::Status;
use std::sync::Arc;

#[derive(Debug, Default)]
pub struct Peer {
    pub id: u64,
    pub context: Option<Vec<u8>>,
}

#[derive(Debug, PartialEq, Copy, Clone)]
pub enum SnapshotStatus {
    Finish,
    Failure,
}

fn is_local_msg(m: &Message) -> bool {
    match m.get_msg_type() {
        MessageType::MsgHup |
        MessageType::MsgBeat |
        MessageType::MsgUnreachable |
        MessageType::MsgSnapStatus |
        MessageType::MsgCheckQuorum => true,
        _ => false,
    }
}

fn is_response_msg(m: &Message) -> bool {
    match m.get_msg_type() {
        MessageType::MsgAppendResponse |
        MessageType::MsgRequestVoteResponse |
        MessageType::MsgHeartbeatResponse |
        MessageType::MsgUnreachable => true,
        _ => false,
    }
}

pub fn is_empty_snap(s: &Snapshot) -> bool {
    s.get_metadata().get_index() == 0
}

// Ready encapsulates the entries and messages that are ready to read,
// be saved to stable storage, committed or sent to other peers.
// All fields in Ready are read-only.
#[derive(Default, Debug, PartialEq)]
pub struct Ready {
    // The current volatile state of a Node.
    // SoftState will be nil if there is no update.
    // It is not required to consume or store SoftState.
    pub ss: Option<SoftState>,

    // The current state of a Node to be saved to stable storage BEFORE
    // Messages are sent.
    // HardState will be equal to empty state if there is no update.
    pub hs: Option<HardState>,

    // Entries specifies entries to be saved to stable storage BEFORE
    // Messages are sent.
    pub entries: Vec<Entry>,

    // Snapshot specifies the snapshot to be saved to stable storage.
    pub snapshot: Snapshot,

    // CommittedEntries specifies entries to be committed to a
    // store/state-machine. These have previously been committed to stable
    // store.
    pub committed_entries: Vec<Entry>,

    // Messages specifies outbound messages to be sent AFTER Entries are
    // committed to stable storage.
    // If it contains a MsgSnap message, the application MUST report back to raft
    // when the snapshot has been received or has failed by calling ReportSnapshot.
    pub messages: Vec<Message>,
}

impl Ready {
    fn new<T: Storage>(raft: &mut Raft<T>, prev_ss: &SoftState, prev_hs: &HardState) -> Ready {
        let mut rd = Ready {
            entries: raft.raft_log.unstable_entries().unwrap_or(&[]).to_vec(),
            committed_entries: raft.raft_log.next_entries().unwrap_or_else(Vec::new),
            messages: raft.msgs.drain(..).collect(),
            ..Default::default()
        };
        let ss = raft.soft_state();
        if &ss != prev_ss {
            rd.ss = Some(ss);
        }
        let hs = raft.hard_state();
        if &hs != prev_hs {
            rd.hs = Some(hs);
        }
        if raft.raft_log.get_unstable().snapshot.is_some() {
            rd.snapshot = raft.raft_log.get_unstable().snapshot.clone().unwrap();
        }
        rd
    }
}

// RawNode is a thread-unsafe Node.
// The methods of this struct correspond to the methods of Node and are described
// more fully there.
pub struct RawNode<T: Storage> {
    pub raft: Raft<T>,
    prev_ss: SoftState,
    prev_hs: HardState,
}

impl<T: Storage> RawNode<T> {
    // NewRawNode returns a new RawNode given configuration and a list of raft peers.
    pub fn new(config: &Config, store: Arc<T>, peers: &[Peer]) -> Result<RawNode<T>> {
        assert!(config.id != 0, "config.id must not be zero");
        let r = Raft::new(config, store);
        let mut rn = RawNode {
            raft: r,
            prev_hs: Default::default(),
            prev_ss: Default::default(),
        };
        let last_index = rn.raft.get_store().last_index().expect("");
        if last_index == 0 {
            rn.raft.become_follower(1, INVALID_ID);
            let mut ents = Vec::with_capacity(peers.len());
            for (i, peer) in peers.iter().enumerate() {
                let mut cc = ConfChange::new();
                cc.set_change_type(ConfChangeType::AddNode);
                cc.set_node_id(peer.id);
                if peer.context.is_some() {
                    cc.set_context(peer.context.as_ref().unwrap().clone());
                }
                let data = protobuf::Message::write_to_bytes(&cc)
                    .expect("unexpected marshal error");
                let mut e = Entry::new();
                e.set_entry_type(EntryType::EntryConfChange);
                e.set_term(1);
                e.set_index(i as u64 + 1);
                e.set_data(data);
                ents.push(e);
            }
            rn.raft.raft_log.append(&ents);
            rn.raft.raft_log.committed = ents.len() as u64;
            for peer in peers {
                rn.raft.add_node(peer.id);
            }
        }
        rn.prev_ss = rn.raft.soft_state();
        rn.prev_hs = rn.raft.hard_state();
        Ok(rn)
    }

    fn commit_ready(&mut self, rd: Ready) {
        if rd.ss.is_some() {
            self.prev_ss = rd.ss.unwrap();
        }
        if let Some(e) = rd.hs {
            if e != HardState::new() {
                self.prev_hs = e;
            }
        }
        if self.prev_hs.get_commit() != 0 {
            // In most cases, prevHardSt and rd.HardState will be the same
            // because when there are new entries to apply we just sent a
            // HardState with an updated Commit value. However, on initial
            // startup the two are different because we don't send a HardState
            // until something changes, but we do send any un-applied but
            // committed entries (and previously-committed entries may be
            // incorporated into the snapshot, even if rd.CommittedEntries is
            // empty). Therefore we mark all committed entries as applied
            // whether they were included in rd.HardState or not.
            self.raft.raft_log.applied_to(self.prev_hs.get_commit());
        }
        if !rd.entries.is_empty() {
            let e = rd.entries.last().unwrap();
            self.raft.raft_log.stable_to(e.get_index(), e.get_term());
        }
        if rd.snapshot != Snapshot::new() {
            self.raft.raft_log.stable_snap_to(rd.snapshot.get_metadata().get_index());
        }
    }

    // Tick advances the internal logical clock by a single tick.
    pub fn tick(&mut self) {
        self.raft.tick();
    }

    // Campaign causes this RawNode to transition to candidate state.
    pub fn campaign(&mut self) -> Result<()> {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgHup);
        self.raft.step(m)
    }

    // Propose proposes data be appended to the raft log.
    pub fn propose(&mut self, data: Vec<u8>) -> Result<()> {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgPropose);
        m.set_from(self.raft.id);
        let mut e = Entry::new();
        e.set_data(data);
        m.set_entries(RepeatedField::from_vec(vec![e]));
        self.raft.step(m)
    }

    // ProposeConfChange proposes a config change.
    pub fn propose_conf_change(&mut self, cc: ConfChange) -> Result<()> {
        let data = box_try!(protobuf::Message::write_to_bytes(&cc));
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgPropose);
        let mut e = Entry::new();
        e.set_entry_type(EntryType::EntryConfChange);
        e.set_data(data);
        m.set_entries(RepeatedField::from_vec(vec![e]));
        self.raft.step(m)
    }

    pub fn apply_conf_change(&mut self, cc: ConfChange) -> ConfState {
        if cc.get_node_id() == INVALID_ID {
            self.raft.reset_pending_conf();
            let mut cs = ConfState::new();
            cs.set_nodes(self.raft.nodes());
            return cs;
        }
        let nid = cc.get_node_id();
        assert!(cc.has_change_type(), "unexpected conf type");
        match cc.get_change_type() {
            ConfChangeType::AddNode => self.raft.add_node(nid),
            ConfChangeType::RemoveNode => self.raft.remove_node(nid),
        }
        let mut cs = ConfState::new();
        cs.set_nodes(self.raft.nodes());
        cs
    }

    // Step advances the state machine using the given message.
    pub fn step(&mut self, m: Message) -> Result<()> {
        // ignore unexpected local messages receiving over network
        if is_local_msg(&m) {
            return Err(Error::StepLocalMsg);
        }
        if self.raft.prs.contains_key(&m.get_from()) || !is_response_msg(&m) {
            return self.raft.step(m);
        }
        Err(Error::StepPeerNotFound)
    }

    // Ready returns the current point-in-time state of this RawNode.
    pub fn ready(&mut self) -> Ready {
        Ready::new(&mut self.raft, &self.prev_ss, &self.prev_hs)
    }

    // HasReady called when RawNode user need to check if any Ready pending.
    // Checking logic in this method should be consistent with Ready.containsUpdates().
    pub fn has_ready(&self) -> bool {
        let raft = &self.raft;
        if raft.soft_state() != self.prev_ss {
            return true;
        }
        let hs = raft.hard_state();
        if hs != HardState::new() && hs != self.prev_hs {
            return true;
        }
        if Some(true) == raft.raft_log.get_unstable().snapshot.as_ref().map(|s| !is_empty_snap(s)) {
            return true;
        }
        if !raft.msgs.is_empty() || raft.raft_log.unstable_entries().is_some() ||
           raft.raft_log.has_next_entries() {
            return true;
        }
        false
    }

    // Advance notifies the RawNode that the application has applied and saved progress in the
    // last Ready results.
    pub fn advance(&mut self, rd: Ready) {
        self.commit_ready(rd);
    }

    // Status returns the current status of the given group.
    pub fn status(&self) -> Status {
        Status::new(&self.raft)
    }

    // ReportUnreachable reports the given node is not reachable for the last send.
    pub fn report_unreachable(&mut self, id: u64) {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgUnreachable);
        m.set_from(id);
        // we don't care if it is ok actually
        self.raft.step(m).is_ok();
    }

    // ReportSnapshot reports the status of the sent snapshot.
    pub fn report_snapshot(&mut self, id: u64, status: SnapshotStatus) {
        let rej = status == SnapshotStatus::Failure;
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgSnapStatus);
        m.set_from(id);
        m.set_reject(rej);
        // we don't care if it is ok actually
        self.raft.step(m).is_ok();
    }
}
<commit_msg>raftstore: add transfer leader admin command (#590)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

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

#![allow(dead_code)]
use raft::errors::{Result, Error};
use raft::Storage;
use protobuf::{self, RepeatedField};
use kvproto::raftpb::{HardState, Entry, EntryType, Message, Snapshot, MessageType, ConfChange,
                      ConfChangeType, ConfState};
use raft::raft::{Config, Raft, SoftState, INVALID_ID};
use raft::Status;
use std::sync::Arc;

#[derive(Debug, Default)]
pub struct Peer {
    pub id: u64,
    pub context: Option<Vec<u8>>,
}

#[derive(Debug, PartialEq, Copy, Clone)]
pub enum SnapshotStatus {
    Finish,
    Failure,
}

fn is_local_msg(m: &Message) -> bool {
    match m.get_msg_type() {
        MessageType::MsgHup |
        MessageType::MsgBeat |
        MessageType::MsgUnreachable |
        MessageType::MsgSnapStatus |
        MessageType::MsgCheckQuorum => true,
        _ => false,
    }
}

fn is_response_msg(m: &Message) -> bool {
    match m.get_msg_type() {
        MessageType::MsgAppendResponse |
        MessageType::MsgRequestVoteResponse |
        MessageType::MsgHeartbeatResponse |
        MessageType::MsgUnreachable => true,
        _ => false,
    }
}

pub fn is_empty_snap(s: &Snapshot) -> bool {
    s.get_metadata().get_index() == 0
}

// Ready encapsulates the entries and messages that are ready to read,
// be saved to stable storage, committed or sent to other peers.
// All fields in Ready are read-only.
#[derive(Default, Debug, PartialEq)]
pub struct Ready {
    // The current volatile state of a Node.
    // SoftState will be nil if there is no update.
    // It is not required to consume or store SoftState.
    pub ss: Option<SoftState>,

    // The current state of a Node to be saved to stable storage BEFORE
    // Messages are sent.
    // HardState will be equal to empty state if there is no update.
    pub hs: Option<HardState>,

    // Entries specifies entries to be saved to stable storage BEFORE
    // Messages are sent.
    pub entries: Vec<Entry>,

    // Snapshot specifies the snapshot to be saved to stable storage.
    pub snapshot: Snapshot,

    // CommittedEntries specifies entries to be committed to a
    // store/state-machine. These have previously been committed to stable
    // store.
    pub committed_entries: Vec<Entry>,

    // Messages specifies outbound messages to be sent AFTER Entries are
    // committed to stable storage.
    // If it contains a MsgSnap message, the application MUST report back to raft
    // when the snapshot has been received or has failed by calling ReportSnapshot.
    pub messages: Vec<Message>,
}

impl Ready {
    fn new<T: Storage>(raft: &mut Raft<T>, prev_ss: &SoftState, prev_hs: &HardState) -> Ready {
        let mut rd = Ready {
            entries: raft.raft_log.unstable_entries().unwrap_or(&[]).to_vec(),
            committed_entries: raft.raft_log.next_entries().unwrap_or_else(Vec::new),
            messages: raft.msgs.drain(..).collect(),
            ..Default::default()
        };
        let ss = raft.soft_state();
        if &ss != prev_ss {
            rd.ss = Some(ss);
        }
        let hs = raft.hard_state();
        if &hs != prev_hs {
            rd.hs = Some(hs);
        }
        if raft.raft_log.get_unstable().snapshot.is_some() {
            rd.snapshot = raft.raft_log.get_unstable().snapshot.clone().unwrap();
        }
        rd
    }
}

// RawNode is a thread-unsafe Node.
// The methods of this struct correspond to the methods of Node and are described
// more fully there.
pub struct RawNode<T: Storage> {
    pub raft: Raft<T>,
    prev_ss: SoftState,
    prev_hs: HardState,
}

impl<T: Storage> RawNode<T> {
    // NewRawNode returns a new RawNode given configuration and a list of raft peers.
    pub fn new(config: &Config, store: Arc<T>, peers: &[Peer]) -> Result<RawNode<T>> {
        assert!(config.id != 0, "config.id must not be zero");
        let r = Raft::new(config, store);
        let mut rn = RawNode {
            raft: r,
            prev_hs: Default::default(),
            prev_ss: Default::default(),
        };
        let last_index = rn.raft.get_store().last_index().expect("");
        if last_index == 0 {
            rn.raft.become_follower(1, INVALID_ID);
            let mut ents = Vec::with_capacity(peers.len());
            for (i, peer) in peers.iter().enumerate() {
                let mut cc = ConfChange::new();
                cc.set_change_type(ConfChangeType::AddNode);
                cc.set_node_id(peer.id);
                if peer.context.is_some() {
                    cc.set_context(peer.context.as_ref().unwrap().clone());
                }
                let data = protobuf::Message::write_to_bytes(&cc)
                    .expect("unexpected marshal error");
                let mut e = Entry::new();
                e.set_entry_type(EntryType::EntryConfChange);
                e.set_term(1);
                e.set_index(i as u64 + 1);
                e.set_data(data);
                ents.push(e);
            }
            rn.raft.raft_log.append(&ents);
            rn.raft.raft_log.committed = ents.len() as u64;
            for peer in peers {
                rn.raft.add_node(peer.id);
            }
        }
        rn.prev_ss = rn.raft.soft_state();
        rn.prev_hs = rn.raft.hard_state();
        Ok(rn)
    }

    fn commit_ready(&mut self, rd: Ready) {
        if rd.ss.is_some() {
            self.prev_ss = rd.ss.unwrap();
        }
        if let Some(e) = rd.hs {
            if e != HardState::new() {
                self.prev_hs = e;
            }
        }
        if self.prev_hs.get_commit() != 0 {
            // In most cases, prevHardSt and rd.HardState will be the same
            // because when there are new entries to apply we just sent a
            // HardState with an updated Commit value. However, on initial
            // startup the two are different because we don't send a HardState
            // until something changes, but we do send any un-applied but
            // committed entries (and previously-committed entries may be
            // incorporated into the snapshot, even if rd.CommittedEntries is
            // empty). Therefore we mark all committed entries as applied
            // whether they were included in rd.HardState or not.
            self.raft.raft_log.applied_to(self.prev_hs.get_commit());
        }
        if !rd.entries.is_empty() {
            let e = rd.entries.last().unwrap();
            self.raft.raft_log.stable_to(e.get_index(), e.get_term());
        }
        if rd.snapshot != Snapshot::new() {
            self.raft.raft_log.stable_snap_to(rd.snapshot.get_metadata().get_index());
        }
    }

    // Tick advances the internal logical clock by a single tick.
    pub fn tick(&mut self) {
        self.raft.tick();
    }

    // Campaign causes this RawNode to transition to candidate state.
    pub fn campaign(&mut self) -> Result<()> {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgHup);
        self.raft.step(m)
    }

    // Propose proposes data be appended to the raft log.
    pub fn propose(&mut self, data: Vec<u8>) -> Result<()> {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgPropose);
        m.set_from(self.raft.id);
        let mut e = Entry::new();
        e.set_data(data);
        m.set_entries(RepeatedField::from_vec(vec![e]));
        self.raft.step(m)
    }

    // ProposeConfChange proposes a config change.
    pub fn propose_conf_change(&mut self, cc: ConfChange) -> Result<()> {
        let data = box_try!(protobuf::Message::write_to_bytes(&cc));
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgPropose);
        let mut e = Entry::new();
        e.set_entry_type(EntryType::EntryConfChange);
        e.set_data(data);
        m.set_entries(RepeatedField::from_vec(vec![e]));
        self.raft.step(m)
    }

    pub fn apply_conf_change(&mut self, cc: ConfChange) -> ConfState {
        if cc.get_node_id() == INVALID_ID {
            self.raft.reset_pending_conf();
            let mut cs = ConfState::new();
            cs.set_nodes(self.raft.nodes());
            return cs;
        }
        let nid = cc.get_node_id();
        assert!(cc.has_change_type(), "unexpected conf type");
        match cc.get_change_type() {
            ConfChangeType::AddNode => self.raft.add_node(nid),
            ConfChangeType::RemoveNode => self.raft.remove_node(nid),
        }
        let mut cs = ConfState::new();
        cs.set_nodes(self.raft.nodes());
        cs
    }

    // Step advances the state machine using the given message.
    pub fn step(&mut self, m: Message) -> Result<()> {
        // ignore unexpected local messages receiving over network
        if is_local_msg(&m) {
            return Err(Error::StepLocalMsg);
        }
        if self.raft.prs.contains_key(&m.get_from()) || !is_response_msg(&m) {
            return self.raft.step(m);
        }
        Err(Error::StepPeerNotFound)
    }

    // Ready returns the current point-in-time state of this RawNode.
    pub fn ready(&mut self) -> Ready {
        Ready::new(&mut self.raft, &self.prev_ss, &self.prev_hs)
    }

    // HasReady called when RawNode user need to check if any Ready pending.
    // Checking logic in this method should be consistent with Ready.containsUpdates().
    pub fn has_ready(&self) -> bool {
        let raft = &self.raft;
        if raft.soft_state() != self.prev_ss {
            return true;
        }
        let hs = raft.hard_state();
        if hs != HardState::new() && hs != self.prev_hs {
            return true;
        }
        if Some(true) == raft.raft_log.get_unstable().snapshot.as_ref().map(|s| !is_empty_snap(s)) {
            return true;
        }
        if !raft.msgs.is_empty() || raft.raft_log.unstable_entries().is_some() ||
           raft.raft_log.has_next_entries() {
            return true;
        }
        false
    }

    // Advance notifies the RawNode that the application has applied and saved progress in the
    // last Ready results.
    pub fn advance(&mut self, rd: Ready) {
        self.commit_ready(rd);
    }

    // Status returns the current status of the given group.
    pub fn status(&self) -> Status {
        Status::new(&self.raft)
    }

    // ReportUnreachable reports the given node is not reachable for the last send.
    pub fn report_unreachable(&mut self, id: u64) {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgUnreachable);
        m.set_from(id);
        // we don't care if it is ok actually
        self.raft.step(m).is_ok();
    }

    // ReportSnapshot reports the status of the sent snapshot.
    pub fn report_snapshot(&mut self, id: u64, status: SnapshotStatus) {
        let rej = status == SnapshotStatus::Failure;
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgSnapStatus);
        m.set_from(id);
        m.set_reject(rej);
        // we don't care if it is ok actually
        self.raft.step(m).is_ok();
    }

    // TransferLeader tries to transfer leadership to the given transferee.
    pub fn transfer_leader(&mut self, transferee: u64) {
        let mut m = Message::new();
        m.set_msg_type(MessageType::MsgTransferLeader);
        m.set_from(transferee);
        self.raft.step(m).is_ok();
    }
}
<|endoftext|>