<commit_before>// Std
use std::{ops::BitOr, str::FromStr};

// Third party
use bitflags::bitflags;

bitflags! {
    struct Flags: u32 {
        const REQUIRED         = 1;
        const MULTIPLE_OCC     = 1 << 1;
        const NO_EMPTY_VALS    = 1 << 2;
        const GLOBAL           = 1 << 3;
        const HIDDEN           = 1 << 4;
        const TAKES_VAL        = 1 << 5;
        const USE_DELIM        = 1 << 6;
        const NEXT_LINE_HELP   = 1 << 7;
        const REQ_DELIM        = 1 << 9;
        const DELIM_NOT_SET    = 1 << 10;
        const HIDE_POS_VALS    = 1 << 11;
        const ALLOW_TAC_VALS   = 1 << 12;
        const REQUIRE_EQUALS   = 1 << 13;
        const LAST             = 1 << 14;
        const HIDE_DEFAULT_VAL = 1 << 15;
        const CASE_INSENSITIVE = 1 << 16;
        #[cfg(feature = "env")]
        const HIDE_ENV_VALS    = 1 << 17;
        const HIDDEN_SHORT_H   = 1 << 18;
        const HIDDEN_LONG_H    = 1 << 19;
        const MULTIPLE_VALS    = 1 << 20;
        const MULTIPLE         = Self::MULTIPLE_OCC.bits | Self::MULTIPLE_VALS.bits;
        #[cfg(feature = "env")]
        const HIDE_ENV         = 1 << 21;
        const UTF8_NONE        = 1 << 22;
        const NO_OP            = 0;
    }
}

#[doc(hidden)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ArgFlags(Flags);

impl Default for ArgFlags {
    fn default() -> Self {
        Self::empty()
    }
}

// @TODO @p6 @internal: Reorder alphabetically
impl_settings! { ArgSettings, ArgFlags,
    Required("required") => Flags::REQUIRED,
    MultipleOccurrences("multipleoccurrences") => Flags::MULTIPLE_OCC,
    MultipleValues("multiplevalues") => Flags::MULTIPLE_VALS,
    Multiple("multiple") => Flags::MULTIPLE,
    ForbidEmptyValues("forbidemptyvalues") => Flags::NO_EMPTY_VALS,
    EmptyValues("emptyvalues") => Flags::NO_OP,
    Hidden("hidden") => Flags::HIDDEN,
    TakesValue("takesvalue") => Flags::TAKES_VAL,
    UseValueDelimiter("usevaluedelimiter") => Flags::USE_DELIM,
    NextLineHelp("nextlinehelp") => Flags::NEXT_LINE_HELP,
    RequireDelimiter("requiredelimiter") => Flags::REQ_DELIM,
    HidePossibleValues("hidepossiblevalues") => Flags::HIDE_POS_VALS,
    AllowHyphenValues("allowhyphenvalues") => Flags::ALLOW_TAC_VALS,
    RequireEquals("requireequals") => Flags::REQUIRE_EQUALS,
    Last("last") => Flags::LAST,
    IgnoreCase("ignorecase") => Flags::CASE_INSENSITIVE,
    CaseInsensitive("ignorecase") => Flags::CASE_INSENSITIVE,
    #[cfg(feature = "env")]
    HideEnv("hideenv") => Flags::HIDE_ENV,
    #[cfg(feature = "env")]
    HideEnvValues("hideenvvalues") => Flags::HIDE_ENV_VALS,
    HideDefaultValue("hidedefaultvalue") => Flags::HIDE_DEFAULT_VAL,
    HiddenShortHelp("hiddenshorthelp") => Flags::HIDDEN_SHORT_H,
    HiddenLongHelp("hiddenlonghelp") => Flags::HIDDEN_LONG_H,
    AllowInvalidUtf8("allowinvalidutf8") => Flags::UTF8_NONE
}

/// Various settings that apply to arguments and may be set, unset, and checked via getter/setter
/// methods [`Arg::setting`], [`Arg::unset_setting`], and [`Arg::is_set`]. This is what the
/// [`Arg`] methods which accept a `bool` use internally.
///
/// [`Arg`]: crate::Arg
/// [`Arg::setting`]: crate::Arg::setting()
/// [`Arg::unset_setting`]: crate::Arg::unset_setting()
/// [`Arg::is_set`]: crate::Arg::is_set()
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum ArgSettings {
    /// Specifies that an arg must be used
    Required,
    /// Allows an arg to accept multiple values
    MultipleValues,
    /// Allows an arg to appear multiple times
    MultipleOccurrences,
    /// Deprecated, see [`ArgSettings::MultipleOccurrences`] (most likely what you want) and
    /// [`ArgSettings::MultipleValues`]
    #[deprecated(
        since = "3.0.0",
        note = "Split into `ArgSettings::MultipleOccurrences` (most likely what you want)  and `ArgSettings::MultipleValues`"
    )]
    Multiple,
    /// Forbids an arg from accepting empty values such as `""`
    ForbidEmptyValues,
    /// Deprecated, this is now the default, see [`ArgSettings::ForbidEmptyValues`] for the
    /// opposite.
    #[deprecated(
        since = "3.0.0",
        note = "This is now the default see [`ArgSettings::ForbidEmptyValues`] for the opposite."
    )]
    EmptyValues,
    /// Hides an arg from the help message
    Hidden,
    /// Allows an argument to take a value (such as `--option value`)
    TakesValue,
    /// Enables a delimiter to break up arguments `--option val1,val2,val3` becomes three values
    /// (`val1`, `val2`, and `val3`) instead of the default one (`val1,val2,val3`)
    UseValueDelimiter,
    /// Tells an arg to display it's help on the line below the arg itself in the help message
    NextLineHelp,
    /// Says that arg *must* use a delimiter to separate values
    RequireDelimiter,
    /// Hides the possible values from the help message
    HidePossibleValues,
    /// Allows values that start with a hyphen
    AllowHyphenValues,
    /// Requires that an equals be used to provide a value to an option such as `--option=value`
    RequireEquals,
    /// Says that a positional arg will be the last positional, and requires `--` to be accessed.
    /// It can also be accessed early (i.e. before other positionals) by providing `--`
    Last,
    /// Hides the default value from the help message
    HideDefaultValue,
    /// Possible values become case insensitive
    IgnoreCase,
    /// Deprecated, replaced with [`ArgSettings::IgnoreCase`]
    #[deprecated(since = "3.0.0", note = "Replaced with `ArgSettings::IgnoreCase`")]
    CaseInsensitive,
    /// Hides environment variable arguments from the help message
    #[cfg(feature = "env")]
    HideEnv,
    /// Hides any values currently assigned to ENV variables in the help message (good for sensitive
    /// information)
    #[cfg(feature = "env")]
    HideEnvValues,
    /// The argument should **not** be shown in short help text
    HiddenShortHelp,
    /// The argument should **not** be shown in long help text
    HiddenLongHelp,
    /// Specifies that option values that are invalid UTF-8 should *not* be treated as an error.
    AllowInvalidUtf8,
}

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

    #[test]
    fn arg_settings_fromstr() {
        assert_eq!(
            "allowhyphenvalues".parse::<ArgSettings>().unwrap(),
            ArgSettings::AllowHyphenValues
        );
        assert_eq!(
            "forbidemptyvalues".parse::<ArgSettings>().unwrap(),
            ArgSettings::ForbidEmptyValues
        );
        assert_eq!(
            "hidepossiblevalues".parse::<ArgSettings>().unwrap(),
            ArgSettings::HidePossibleValues
        );
        assert_eq!(
            "hidden".parse::<ArgSettings>().unwrap(),
            ArgSettings::Hidden
        );
        assert_eq!(
            "nextlinehelp".parse::<ArgSettings>().unwrap(),
            ArgSettings::NextLineHelp
        );
        assert_eq!(
            "requiredelimiter".parse::<ArgSettings>().unwrap(),
            ArgSettings::RequireDelimiter
        );
        assert_eq!(
            "required".parse::<ArgSettings>().unwrap(),
            ArgSettings::Required
        );
        assert_eq!(
            "takesvalue".parse::<ArgSettings>().unwrap(),
            ArgSettings::TakesValue
        );
        assert_eq!(
            "usevaluedelimiter".parse::<ArgSettings>().unwrap(),
            ArgSettings::UseValueDelimiter
        );
        assert_eq!(
            "requireequals".parse::<ArgSettings>().unwrap(),
            ArgSettings::RequireEquals
        );
        assert_eq!("last".parse::<ArgSettings>().unwrap(), ArgSettings::Last);
        assert_eq!(
            "hidedefaultvalue".parse::<ArgSettings>().unwrap(),
            ArgSettings::HideDefaultValue
        );
        assert_eq!(
            "ignorecase".parse::<ArgSettings>().unwrap(),
            ArgSettings::IgnoreCase
        );
        #[cfg(feature = "env")]
        assert_eq!(
            "hideenv".parse::<ArgSettings>().unwrap(),
            ArgSettings::HideEnv
        );
        #[cfg(feature = "env")]
        assert_eq!(
            "hideenvvalues".parse::<ArgSettings>().unwrap(),
            ArgSettings::HideEnvValues
        );
        assert_eq!(
            "hiddenshorthelp".parse::<ArgSettings>().unwrap(),
            ArgSettings::HiddenShortHelp
        );
        assert_eq!(
            "hiddenlonghelp".parse::<ArgSettings>().unwrap(),
            ArgSettings::HiddenLongHelp
        );
        assert_eq!(
            "allowinvalidutf8".parse::<ArgSettings>().unwrap(),
            ArgSettings::AllowInvalidUtf8
        );
        assert!("hahahaha".parse::<ArgSettings>().is_err());
    }
}
<commit_msg>fix: Deprecate, rather than remove, AllowLeadingHyphen<commit_after>// Std
use std::{ops::BitOr, str::FromStr};

// Third party
use bitflags::bitflags;

bitflags! {
    struct Flags: u32 {
        const REQUIRED         = 1;
        const MULTIPLE_OCC     = 1 << 1;
        const NO_EMPTY_VALS    = 1 << 2;
        const GLOBAL           = 1 << 3;
        const HIDDEN           = 1 << 4;
        const TAKES_VAL        = 1 << 5;
        const USE_DELIM        = 1 << 6;
        const NEXT_LINE_HELP   = 1 << 7;
        const REQ_DELIM        = 1 << 9;
        const DELIM_NOT_SET    = 1 << 10;
        const HIDE_POS_VALS    = 1 << 11;
        const ALLOW_TAC_VALS   = 1 << 12;
        const REQUIRE_EQUALS   = 1 << 13;
        const LAST             = 1 << 14;
        const HIDE_DEFAULT_VAL = 1 << 15;
        const CASE_INSENSITIVE = 1 << 16;
        #[cfg(feature = "env")]
        const HIDE_ENV_VALS    = 1 << 17;
        const HIDDEN_SHORT_H   = 1 << 18;
        const HIDDEN_LONG_H    = 1 << 19;
        const MULTIPLE_VALS    = 1 << 20;
        const MULTIPLE         = Self::MULTIPLE_OCC.bits | Self::MULTIPLE_VALS.bits;
        #[cfg(feature = "env")]
        const HIDE_ENV         = 1 << 21;
        const UTF8_NONE        = 1 << 22;
        const NO_OP            = 0;
    }
}

#[doc(hidden)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ArgFlags(Flags);

impl Default for ArgFlags {
    fn default() -> Self {
        Self::empty()
    }
}

// @TODO @p6 @internal: Reorder alphabetically
impl_settings! { ArgSettings, ArgFlags,
    Required("required") => Flags::REQUIRED,
    MultipleOccurrences("multipleoccurrences") => Flags::MULTIPLE_OCC,
    MultipleValues("multiplevalues") => Flags::MULTIPLE_VALS,
    Multiple("multiple") => Flags::MULTIPLE,
    ForbidEmptyValues("forbidemptyvalues") => Flags::NO_EMPTY_VALS,
    EmptyValues("emptyvalues") => Flags::NO_OP,
    Hidden("hidden") => Flags::HIDDEN,
    TakesValue("takesvalue") => Flags::TAKES_VAL,
    UseValueDelimiter("usevaluedelimiter") => Flags::USE_DELIM,
    NextLineHelp("nextlinehelp") => Flags::NEXT_LINE_HELP,
    RequireDelimiter("requiredelimiter") => Flags::REQ_DELIM,
    HidePossibleValues("hidepossiblevalues") => Flags::HIDE_POS_VALS,
    AllowHyphenValues("allowhyphenvalues") => Flags::ALLOW_TAC_VALS,
    AllowLeadingHyphen("allowleadinghypyhen") => Flags::ALLOW_TAC_VALS,
    RequireEquals("requireequals") => Flags::REQUIRE_EQUALS,
    Last("last") => Flags::LAST,
    IgnoreCase("ignorecase") => Flags::CASE_INSENSITIVE,
    CaseInsensitive("ignorecase") => Flags::CASE_INSENSITIVE,
    #[cfg(feature = "env")]
    HideEnv("hideenv") => Flags::HIDE_ENV,
    #[cfg(feature = "env")]
    HideEnvValues("hideenvvalues") => Flags::HIDE_ENV_VALS,
    HideDefaultValue("hidedefaultvalue") => Flags::HIDE_DEFAULT_VAL,
    HiddenShortHelp("hiddenshorthelp") => Flags::HIDDEN_SHORT_H,
    HiddenLongHelp("hiddenlonghelp") => Flags::HIDDEN_LONG_H,
    AllowInvalidUtf8("allowinvalidutf8") => Flags::UTF8_NONE
}

/// Various settings that apply to arguments and may be set, unset, and checked via getter/setter
/// methods [`Arg::setting`], [`Arg::unset_setting`], and [`Arg::is_set`]. This is what the
/// [`Arg`] methods which accept a `bool` use internally.
///
/// [`Arg`]: crate::Arg
/// [`Arg::setting`]: crate::Arg::setting()
/// [`Arg::unset_setting`]: crate::Arg::unset_setting()
/// [`Arg::is_set`]: crate::Arg::is_set()
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum ArgSettings {
    /// Specifies that an arg must be used
    Required,
    /// Allows an arg to accept multiple values
    MultipleValues,
    /// Allows an arg to appear multiple times
    MultipleOccurrences,
    /// Deprecated, see [`ArgSettings::MultipleOccurrences`] (most likely what you want) and
    /// [`ArgSettings::MultipleValues`]
    #[deprecated(
        since = "3.0.0",
        note = "Split into `ArgSettings::MultipleOccurrences` (most likely what you want)  and `ArgSettings::MultipleValues`"
    )]
    Multiple,
    /// Forbids an arg from accepting empty values such as `""`
    ForbidEmptyValues,
    /// Deprecated, this is now the default, see [`ArgSettings::ForbidEmptyValues`] for the
    /// opposite.
    #[deprecated(
        since = "3.0.0",
        note = "This is now the default see [`ArgSettings::ForbidEmptyValues`] for the opposite."
    )]
    EmptyValues,
    /// Hides an arg from the help message
    Hidden,
    /// Allows an argument to take a value (such as `--option value`)
    TakesValue,
    /// Enables a delimiter to break up arguments `--option val1,val2,val3` becomes three values
    /// (`val1`, `val2`, and `val3`) instead of the default one (`val1,val2,val3`)
    UseValueDelimiter,
    /// Tells an arg to display it's help on the line below the arg itself in the help message
    NextLineHelp,
    /// Says that arg *must* use a delimiter to separate values
    RequireDelimiter,
    /// Hides the possible values from the help message
    HidePossibleValues,
    /// Allows values that start with a hyphen
    AllowHyphenValues,
    /// Deprecated, replaced with [`ArgSettings::AllowHyphenValues`]
    #[deprecated(
        since = "3.0.0",
        note = "Replaced with `ArgSettings::AllowHyphenValues`"
    )]
    AllowLeadingHyphen,
    /// Requires that an equals be used to provide a value to an option such as `--option=value`
    RequireEquals,
    /// Says that a positional arg will be the last positional, and requires `--` to be accessed.
    /// It can also be accessed early (i.e. before other positionals) by providing `--`
    Last,
    /// Hides the default value from the help message
    HideDefaultValue,
    /// Possible values become case insensitive
    IgnoreCase,
    /// Deprecated, replaced with [`ArgSettings::IgnoreCase`]
    #[deprecated(since = "3.0.0", note = "Replaced with `ArgSettings::IgnoreCase`")]
    CaseInsensitive,
    /// Hides environment variable arguments from the help message
    #[cfg(feature = "env")]
    HideEnv,
    /// Hides any values currently assigned to ENV variables in the help message (good for sensitive
    /// information)
    #[cfg(feature = "env")]
    HideEnvValues,
    /// The argument should **not** be shown in short help text
    HiddenShortHelp,
    /// The argument should **not** be shown in long help text
    HiddenLongHelp,
    /// Specifies that option values that are invalid UTF-8 should *not* be treated as an error.
    AllowInvalidUtf8,
}

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

    #[test]
    fn arg_settings_fromstr() {
        assert_eq!(
            "allowhyphenvalues".parse::<ArgSettings>().unwrap(),
            ArgSettings::AllowHyphenValues
        );
        assert_eq!(
            "forbidemptyvalues".parse::<ArgSettings>().unwrap(),
            ArgSettings::ForbidEmptyValues
        );
        assert_eq!(
            "hidepossiblevalues".parse::<ArgSettings>().unwrap(),
            ArgSettings::HidePossibleValues
        );
        assert_eq!(
            "hidden".parse::<ArgSettings>().unwrap(),
            ArgSettings::Hidden
        );
        assert_eq!(
            "nextlinehelp".parse::<ArgSettings>().unwrap(),
            ArgSettings::NextLineHelp
        );
        assert_eq!(
            "requiredelimiter".parse::<ArgSettings>().unwrap(),
            ArgSettings::RequireDelimiter
        );
        assert_eq!(
            "required".parse::<ArgSettings>().unwrap(),
            ArgSettings::Required
        );
        assert_eq!(
            "takesvalue".parse::<ArgSettings>().unwrap(),
            ArgSettings::TakesValue
        );
        assert_eq!(
            "usevaluedelimiter".parse::<ArgSettings>().unwrap(),
            ArgSettings::UseValueDelimiter
        );
        assert_eq!(
            "requireequals".parse::<ArgSettings>().unwrap(),
            ArgSettings::RequireEquals
        );
        assert_eq!("last".parse::<ArgSettings>().unwrap(), ArgSettings::Last);
        assert_eq!(
            "hidedefaultvalue".parse::<ArgSettings>().unwrap(),
            ArgSettings::HideDefaultValue
        );
        assert_eq!(
            "ignorecase".parse::<ArgSettings>().unwrap(),
            ArgSettings::IgnoreCase
        );
        #[cfg(feature = "env")]
        assert_eq!(
            "hideenv".parse::<ArgSettings>().unwrap(),
            ArgSettings::HideEnv
        );
        #[cfg(feature = "env")]
        assert_eq!(
            "hideenvvalues".parse::<ArgSettings>().unwrap(),
            ArgSettings::HideEnvValues
        );
        assert_eq!(
            "hiddenshorthelp".parse::<ArgSettings>().unwrap(),
            ArgSettings::HiddenShortHelp
        );
        assert_eq!(
            "hiddenlonghelp".parse::<ArgSettings>().unwrap(),
            ArgSettings::HiddenLongHelp
        );
        assert_eq!(
            "allowinvalidutf8".parse::<ArgSettings>().unwrap(),
            ArgSettings::AllowInvalidUtf8
        );
        assert!("hahahaha".parse::<ArgSettings>().is_err());
    }
}
<|endoftext|>


<commit_before>use super::Position;
use super::Range;
use std::str::from_utf8;

pub struct GapBuffer {
    data: Vec<u8>,
    gap_start: usize,
    gap_length: usize,
}

pub fn new(mut data: String) -> GapBuffer {
    let mut bytes = data.into_bytes();
    let capacity = bytes.capacity();
    let gap_start = bytes.len();
    let gap_length = capacity - gap_start;
    unsafe {
        bytes.set_len(capacity);
    }
    GapBuffer{ data: bytes, gap_start: gap_start, gap_length: gap_length }
}

impl GapBuffer {
    // TODO: Return an optional error.
    pub fn insert(&mut self, data: &str, position: &Position) {
        // Ensure we have the capacity to insert this data.
        if data.len() > self.gap_length {
            // TODO: Move gap to the end before resizing buffer.
            self.data.reserve(data.len());
            let capacity = self.data.capacity();
            self.gap_length = capacity - self.gap_start;
            unsafe {
                self.data.set_len(capacity);
            }
        }

        let offset = match self.find_offset(position) {
            Some(o) => o,
            None => return,
        };

        self.move_gap(offset);
        self.write_to_gap(data);
    }

    pub fn to_string(&self) -> String {
        from_utf8(&self.data[..self.gap_start]).unwrap().to_string() + from_utf8(&self.data[self.gap_start+self.gap_length..]).unwrap()
    }

    // Maps a position to its offset equivalent in the data.
    fn find_offset(&self, position: &Position) -> Option<usize> {
        let first_half = from_utf8(&self.data[..self.gap_start]).unwrap();
        let mut line = 0;
        let mut line_offset = 0;

        for char_index in first_half.char_indices() {
            let (offset, character) = char_index;

            // Check to see if we've found the position yet.
            if line == position.line && line_offset == position.offset {
                return Some(offset);
            }

            // Advance the line and offset characters.
            if character == '\n' {
                line+=1;
                line_offset = 0;
            } else {
                line_offset+=1;
            }
        }

        // We didn't find the position *within* the first half, but it could
        // be right after it, which means it's right at the start of the gap.
        if line == position.line && line_offset == position.offset {
            return Some(self.gap_start);
        }

        // We haven't reached the position yet, so we'll move on to the other half.
        let second_half = from_utf8(&self.data[self.gap_start+self.gap_length..]).unwrap();
        for char_index in second_half.char_indices() {
            let (offset, character) = char_index;

            // Check to see if we've found the position yet.
            if line == position.line && line_offset == position.offset {
                return Some(self.gap_start + self.gap_length + offset);
            }

            // Advance the line and offset characters.
            if character == '\n' {
                line+=1;
                line_offset = 0;
            } else {
                line_offset+=1;
            }
        }

        // We didn't find the position *within* the second half, but it could
        // be right after it, which means it's at the end of the buffer.
        if line == position.line && line_offset == position.offset {
            return Some(self.data.len());
        }

        None
    }

    fn move_gap(&mut self, offset: usize) {
        // We don't need to move any data if the buffer is at capacity.
        if self.gap_length == 0 {
            self.gap_start = offset;
            return;
        }

        if offset < self.gap_start {
            // Shift the gap to the left one byte at a time.
            for index in (offset..self.gap_start) {
                self.data[index + self.gap_length] = self.data[index];
                self.data[index] = 0;
            }

            self.gap_start = offset;
        } else if offset > self.gap_start {
            // Shift the gap to the right one byte at a time.
            for index in (self.gap_start+self.gap_length..offset) {
                self.data[index-self.gap_length] = self.data[index];
                self.data[index] = 0;
            }

            // Because the offset was after the gap, its value included the
            // gap length. We must remove it to determine the starting point.
            self.gap_start = offset - self.gap_length;
        }
    }

    fn write_to_gap(&mut self, data: &str) {
        for byte in data.bytes() {
            self.data[self.gap_start] = byte;
            self.gap_start+=1;
            self.gap_length-=1;
        }
    }
}

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

    #[test]
    fn move_gap_works() {
        let mut gb = new("This is a test.".to_string());
        gb.move_gap(0);
        assert_eq!(gb.to_string(), "This is a test.");
    }

    #[test]
    fn inserting_at_the_start_works() {
        let mut gb = new("This is a test.".to_string());
        gb.insert("Hi. ", &Position { line: 0, offset: 0 });
        assert_eq!(gb.to_string(), "Hi. This is a test.");
    }

    #[test]
    fn inserting_in_the_middle_works() {
        let mut gb = new("This is a test.\nPlease be gentle.".to_string());
        gb.insert(" very", &Position { line: 1, offset: 9 });
        assert_eq!(gb.to_string(), "This is a test.\nPlease be very gentle.");
    }

    #[test]
    fn inserting_at_the_end_works() {
        let mut gb = new("This is a test.".to_string());
        gb.insert(" Seriously.", &Position { line: 0, offset: 15 });
        assert_eq!(gb.to_string(), "This is a test. Seriously.");
    }

    #[test]
    fn inserting_in_different_spots_twice_works() {
        let mut gb = new("This is a test.".to_string());
        gb.insert("Hi. ", &Position { line: 0, offset: 0 });
        gb.insert(" Thank you.", &Position { line: 0, offset: 19 });
        assert_eq!(gb.to_string(), "Hi. This is a test. Thank you.");
    }
}
<commit_msg>Implement remove method.<commit_after>use super::Position;
use super::Range;
use std::str::from_utf8;

pub struct GapBuffer {
    data: Vec<u8>,
    gap_start: usize,
    gap_length: usize,
}

pub fn new(mut data: String) -> GapBuffer {
    let mut bytes = data.into_bytes();
    let capacity = bytes.capacity();
    let gap_start = bytes.len();
    let gap_length = capacity - gap_start;
    unsafe {
        bytes.set_len(capacity);
    }
    GapBuffer{ data: bytes, gap_start: gap_start, gap_length: gap_length }
}

impl GapBuffer {
    // TODO: Return an optional error.
    pub fn insert(&mut self, data: &str, position: &Position) {
        // Ensure we have the capacity to insert this data.
        if data.len() > self.gap_length {
            // TODO: Move gap to the end before resizing buffer.
            self.data.reserve(data.len());
            let capacity = self.data.capacity();
            self.gap_length = capacity - self.gap_start;
            unsafe {
                self.data.set_len(capacity);
            }
        }

        let offset = match self.find_offset(position) {
            Some(o) => o,
            None => return,
        };

        self.move_gap(offset);
        self.write_to_gap(data);
    }

    pub fn to_string(&self) -> String {
        from_utf8(&self.data[..self.gap_start]).unwrap().to_string() + from_utf8(&self.data[self.gap_start+self.gap_length..]).unwrap()
    }

    pub fn remove(&mut self, range: &Range) {
        let start_offset = match self.find_offset(&range.start) {
            Some(o) => o,
            None => return,
        };
        self.move_gap(start_offset);

        let end_offset = match self.find_offset(&range.end) {
            Some(o) => o,
            None => return,
        };
        self.gap_length=end_offset-start_offset;
    }

    // Maps a position to its offset equivalent in the data.
    fn find_offset(&self, position: &Position) -> Option<usize> {
        let first_half = from_utf8(&self.data[..self.gap_start]).unwrap();
        let mut line = 0;
        let mut line_offset = 0;

        for char_index in first_half.char_indices() {
            let (offset, character) = char_index;

            // Check to see if we've found the position yet.
            if line == position.line && line_offset == position.offset {
                return Some(offset);
            }

            // Advance the line and offset characters.
            if character == '\n' {
                line+=1;
                line_offset = 0;
            } else {
                line_offset+=1;
            }
        }

        // We didn't find the position *within* the first half, but it could
        // be right after it, which means it's right at the start of the gap.
        if line == position.line && line_offset == position.offset {
            return Some(self.gap_start);
        }

        // We haven't reached the position yet, so we'll move on to the other half.
        let second_half = from_utf8(&self.data[self.gap_start+self.gap_length..]).unwrap();
        for char_index in second_half.char_indices() {
            let (offset, character) = char_index;

            // Check to see if we've found the position yet.
            if line == position.line && line_offset == position.offset {
                return Some(self.gap_start + self.gap_length + offset);
            }

            // Advance the line and offset characters.
            if character == '\n' {
                line+=1;
                line_offset = 0;
            } else {
                line_offset+=1;
            }
        }

        // We didn't find the position *within* the second half, but it could
        // be right after it, which means it's at the end of the buffer.
        if line == position.line && line_offset == position.offset {
            return Some(self.data.len());
        }

        None
    }

    fn move_gap(&mut self, offset: usize) {
        // We don't need to move any data if the buffer is at capacity.
        if self.gap_length == 0 {
            self.gap_start = offset;
            return;
        }

        if offset < self.gap_start {
            // Shift the gap to the left one byte at a time.
            for index in (offset..self.gap_start) {
                self.data[index + self.gap_length] = self.data[index];
                self.data[index] = 0;
            }

            self.gap_start = offset;
        } else if offset > self.gap_start {
            // Shift the gap to the right one byte at a time.
            for index in (self.gap_start+self.gap_length..offset) {
                self.data[index-self.gap_length] = self.data[index];
                self.data[index] = 0;
            }

            // Because the offset was after the gap, its value included the
            // gap length. We must remove it to determine the starting point.
            self.gap_start = offset - self.gap_length;
        }
    }

    fn write_to_gap(&mut self, data: &str) {
        for byte in data.bytes() {
            self.data[self.gap_start] = byte;
            self.gap_start+=1;
            self.gap_length-=1;
        }
    }
}

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

    #[test]
    fn move_gap_works() {
        let mut gb = new("This is a test.".to_string());
        gb.move_gap(0);
        assert_eq!(gb.to_string(), "This is a test.");
    }

    #[test]
    fn inserting_at_the_start_works() {
        let mut gb = new("This is a test.".to_string());
        gb.insert("Hi. ", &Position { line: 0, offset: 0 });
        assert_eq!(gb.to_string(), "Hi. This is a test.");
    }

    #[test]
    fn inserting_in_the_middle_works() {
        let mut gb = new("This is a test.\nPlease be gentle.".to_string());
        gb.insert(" very", &Position { line: 1, offset: 9 });
        assert_eq!(gb.to_string(), "This is a test.\nPlease be very gentle.");
    }

    #[test]
    fn inserting_at_the_end_works() {
        let mut gb = new("This is a test.".to_string());
        gb.insert(" Seriously.", &Position { line: 0, offset: 15 });
        assert_eq!(gb.to_string(), "This is a test. Seriously.");
    }

    #[test]
    fn inserting_in_different_spots_twice_works() {
        let mut gb = new("This is a test.".to_string());
        gb.insert("Hi. ", &Position { line: 0, offset: 0 });
        gb.insert(" Thank you.", &Position { line: 0, offset: 19 });
        assert_eq!(gb.to_string(), "Hi. This is a test. Thank you.");
    }

    #[test]
    fn removing_works() {
        let mut gb = new("This is a test.\nSee what happens.".to_string());
        let start = Position{ line: 0, offset: 8 };
        let end = Position{ line: 1, offset: 4 };
        gb.remove(&Range{ start: start, end: end });
        assert_eq!(gb.to_string(), "This is what happens.");
    }
}
<|endoftext|>


<commit_before>#![macro_escape]

use std::io::BufferedWriter;
use std::io::{File, Writer};
use std::str::Chars;
use std::vec::Vec;

struct ParseBranch {
    matches: Vec<u8>,
    result: Option<String>,
    children: Vec<ParseBranch>,
}

impl ParseBranch {
    fn new() -> ParseBranch {
        ParseBranch {
            matches: Vec::new(),
            result: None,
            children: Vec::new(),
        }
    }
}

#[allow(visible_private_types)]
pub fn branchify(options: &[(&str, &str)], case_sensitive: bool) -> Vec<ParseBranch> {
    let mut root = ParseBranch::new();

    fn go_down_moses(branch: &mut ParseBranch, mut chariter: Chars, result: &str, case_sensitive: bool) {
        match chariter.next() {
            Some(c) => {
                let first_case = if case_sensitive { c as u8 } else { c.to_ascii().to_uppercase().to_byte() };
                for next_branch in branch.children.mut_iter() {
                    if next_branch.matches.as_slice()[0] == first_case {
                        go_down_moses(next_branch, chariter, result, case_sensitive);
                        return;
                    }
                }
                let mut subbranch = ParseBranch::new();
                subbranch.matches.push(first_case);
                if !case_sensitive {
                    let second_case = c.to_ascii().to_lowercase().to_byte();
                    if first_case != second_case {
                        subbranch.matches.push(second_case);
                    }
                }
                branch.children.push(subbranch);
                let index = branch.children.len() -1;
                go_down_moses(&mut branch.children.as_mut_slice()[index], chariter, result, case_sensitive);
            },
            None => {
                assert!(branch.result.is_none());
                branch.result = Some(result.to_string());
            },
        }
    };

    for &(key, result) in options.iter() {
        go_down_moses(&mut root, key.chars(), result, case_sensitive);
    }

    root.children
}

macro_rules! branchify(
    (case sensitive, $($key:expr => $value:ident),*) => (
        ::branchify::branchify([$(($key, stringify!($value))),*], true)
    );
    (case insensitive, $($key:expr => $value:ident),*) => (
        branchify([$(($key, stringify!($value))),*], false)
    );
)

/// Prints the contents to stdout.
///
/// :param branches: the branches to search through
/// :param indent: the level of indentation (each level representing four leading spaces)
/// :param read_call: the function call to read a byte
/// :param end: the byte which marks the end of the sequence
/// :param max_len: the maximum length a value may be before giving up and returning ``None``
/// :param valid: the function call to if a byte ``b`` is valid
/// :param unknown: the expression to call for an unknown value; in this string, ``{}`` will be
///         replaced with an expression (literal or non-literal) evaluating to a ``~str`` (it is
///         ``{}`` only, not arbitrary format strings)
#[allow(visible_private_types)]
pub fn generate_branchified_method(
        writer: &mut BufferedWriter<File>,
        branches: &[ParseBranch],
        indent: uint,
        read_call: &str,
        end: &str,
        max_len: &str,
        valid: &str,
        unknown: &str) {

    // Write Formatted
    macro_rules! wf(($($x:tt)*) => ({
        let indentstr = " ".repeat(indent * 4);
        let s = format!($($x)*);
        let result = writer.write(indentstr.as_bytes())
        .and(writer.write(s.as_bytes()))
        .and(writer.write(b"\n"));

        match result {
            Ok(_)  => {},
            Err(e) => fail!("write error: {:s}", e.desc),
        }
    }))

    fn r(writer: &mut BufferedWriter<File>, branch: &ParseBranch, prefix: &str, indent: uint, read_call: &str,
            end: &str, max_len: &str, valid: &str, unknown: &str) {
        for &c in branch.matches.iter() {
            let next_prefix = format!("{}{}", prefix, c as char);
            wf!("Some(b) if b == '{}' as u8 => match {} {{", c as char, read_call);
            for b in branch.children.iter() {
                r(writer, b, next_prefix.as_slice(), indent + 1, read_call, end, max_len, valid, unknown);
            }
            match branch.result {
                Some(ref result) => wf!("    Some(b) if b == SP => return Some({}),", *result),
                None => wf!("    Some(b) if b == SP => return Some({}),",
                                unknown.replace("{}", format!("~\"{}\"", next_prefix.as_slice()).as_slice())),
            }
            wf!("    Some(b) if {} => (\"{}\", b),", valid, next_prefix.as_slice());
            wf!("    _ => return None,");
            wf!("}},");
        }
    }
    wf!("let (s, next_byte) = match {} {{", read_call);
    for b in branches.iter() {
        r(writer, b, "", indent + 1, read_call, end, max_len, valid, unknown);
    }
    wf!("    Some(b) if {} => (\"\", b),", valid);
    wf!("    _ => return None,");
    wf!("}};");
    wf!("// OK, that didn't pan out. Let's read the rest and see what we get.");
    wf!("let mut s = s.to_string();");
    wf!("s.push_char(next_byte as char);");
    wf!("loop {{");
    wf!("    match {} {{", read_call);
    wf!("        Some(b) if b == {} => return Some({}),", end, unknown.replace("{}", "s"));
    wf!("        Some(b) if {} => {{", valid);
    wf!("            if s.len() == {} {{", max_len);
    wf!("                // Too long; bad request");
    wf!("                return None;");
    wf!("            }}");
    wf!("            s.push_char(b as char);");
    wf!("        }},");
    wf!("        _ => return None,");
    wf!("    }}");
    wf!("}}");
}
<commit_msg>Build fix for latest Rust<commit_after>#![macro_escape]

use std::io::BufferedWriter;
use std::io::{File, Writer};
use std::str::Chars;
use std::vec::Vec;

struct ParseBranch {
    matches: Vec<u8>,
    result: Option<String>,
    children: Vec<ParseBranch>,
}

impl ParseBranch {
    fn new() -> ParseBranch {
        ParseBranch {
            matches: Vec::new(),
            result: None,
            children: Vec::new(),
        }
    }
}

#[allow(visible_private_types)]
pub fn branchify(options: &[(&str, &str)], case_sensitive: bool) -> Vec<ParseBranch> {
    let mut root = ParseBranch::new();

    fn go_down_moses(branch: &mut ParseBranch, mut chariter: Chars, result: &str, case_sensitive: bool) {
        match chariter.next() {
            Some(c) => {
                let first_case = if case_sensitive { c as u8 } else { c.to_ascii().to_uppercase().to_byte() };
                for next_branch in branch.children.mut_iter() {
                    if next_branch.matches.as_slice()[0] == first_case {
                        go_down_moses(next_branch, chariter, result, case_sensitive);
                        return;
                    }
                }
                let mut subbranch = ParseBranch::new();
                subbranch.matches.push(first_case);
                if !case_sensitive {
                    let second_case = c.to_ascii().to_lowercase().to_byte();
                    if first_case != second_case {
                        subbranch.matches.push(second_case);
                    }
                }
                branch.children.push(subbranch);
                let index = branch.children.len() -1;
                go_down_moses(&mut branch.children.as_mut_slice()[index], chariter, result, case_sensitive);
            },
            None => {
                assert!(branch.result.is_none());
                branch.result = Some(result.to_string());
            },
        }
    };

    for &(key, result) in options.iter() {
        go_down_moses(&mut root, key.chars(), result, case_sensitive);
    }

    root.children
}

macro_rules! branchify(
    (case sensitive, $($key:expr => $value:ident),*) => (
        ::branchify::branchify([$(($key, stringify!($value))),*], true)
    );
    (case insensitive, $($key:expr => $value:ident),*) => (
        branchify([$(($key, stringify!($value))),*], false)
    );
)

/// Prints the contents to stdout.
///
/// :param branches: the branches to search through
/// :param indent: the level of indentation (each level representing four leading spaces)
/// :param read_call: the function call to read a byte
/// :param end: the byte which marks the end of the sequence
/// :param max_len: the maximum length a value may be before giving up and returning ``None``
/// :param valid: the function call to if a byte ``b`` is valid
/// :param unknown: the expression to call for an unknown value; in this string, ``{}`` will be
///         replaced with an expression (literal or non-literal) evaluating to a ``~str`` (it is
///         ``{}`` only, not arbitrary format strings)
#[allow(visible_private_types)]
pub fn generate_branchified_method(
        writer: &mut BufferedWriter<File>,
        branches: &[ParseBranch],
        indent: uint,
        read_call: &str,
        end: &str,
        max_len: &str,
        valid: &str,
        unknown: &str) {

    // Write Formatted
    let mut wf = |s: String| {
        let indentstr = " ".repeat(indent * 4);
        let result = writer.write(indentstr.as_bytes())
        .and(writer.write(s.as_bytes()))
        .and(writer.write(b"\n"));

        match result {
            Ok(_)  => {},
            Err(e) => fail!("write error: {:s}", e.desc),
        }
    };

    fn r(branch: &ParseBranch, prefix: &str, read_call: &str,
         valid: &str, unknown: &str, write_fmt: &mut |String|) {

        for &c in branch.matches.iter() {
            let next_prefix = format!("{}{}", prefix, c as char);
            (*write_fmt)(format!("Some(b) if b == '{}' as u8 => match {} {{", c as char, read_call));
            for b in branch.children.iter() {
                r(b, next_prefix.as_slice(), read_call, valid, unknown, write_fmt);
            }
            match branch.result {
                Some(ref result) => (*write_fmt)(format!("    Some(b) if b == SP => return Some({}),", *result)),
                None => (*write_fmt)(format!("    Some(b) if b == SP => return Some({}),",
                                unknown.replace("{}", format!("~\"{}\"", next_prefix.as_slice()).as_slice()))),
            }
            (*write_fmt)(format!("    Some(b) if {} => (\"{}\", b),", valid, next_prefix.as_slice()));
            (*write_fmt)(format!("    _ => return None,"));
            (*write_fmt)(format!("}},"));
        }
    }

    wf(format!("let (s, next_byte) = match {} {{", read_call));
    for b in branches.iter() {
        r(b, "", read_call, valid, unknown, &mut wf);
    }
    wf(format!("    Some(b) if {} => (\"\", b),", valid));
    wf(format!("    _ => return None,"));
    wf(format!("}};"));
    wf(format!("// OK, that didn't pan out. Let's read the rest and see what we get."));
    wf(format!("let mut s = s.to_string();"));
    wf(format!("s.push_char(next_byte as char);"));
    wf(format!("loop {{"));
    wf(format!("    match {} {{", read_call));
    wf(format!("        Some(b) if b == {} => return Some({}),", end, unknown.replace("{}", "s")));
    wf(format!("        Some(b) if {} => {{", valid));
    wf(format!("            if s.len() == {} {{", max_len));
    wf(format!("                // Too long; bad request"));
    wf(format!("                return None;"));
    wf(format!("            }}"));
    wf(format!("            s.push_char(b as char);"));
    wf(format!("        }},"));
    wf(format!("        _ => return None,"));
    wf(format!("    }}"));
    wf(format!("}}"));
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

use io::net::ip;
use io::IoResult;
use libc;
use mem;
use ptr;
use prelude::*;
use super::{last_error, last_net_error, retry, sock_t};
use sync::{Arc, atomic};
use sys::fs::FileDesc;
use sys::{mod, c, set_nonblocking, wouldblock, timer};
use sys_common::{mod, timeout, eof, net};

pub use sys_common::net::TcpStream;

pub struct Event(c::WSAEVENT);

impl Event {
    pub fn new() -> IoResult<Event> {
        let event = unsafe { c::WSACreateEvent() };
        if event == c::WSA_INVALID_EVENT {
            Err(super::last_error())
        } else {
            Ok(Event(event))
        }
    }

    pub fn handle(&self) -> c::WSAEVENT { let Event(handle) = *self; handle }
}

impl Drop for Event {
    fn drop(&mut self) {
        unsafe { let _ = c::WSACloseEvent(self.handle()); }
    }
}

////////////////////////////////////////////////////////////////////////////////
// TCP listeners
////////////////////////////////////////////////////////////////////////////////

pub struct TcpListener { sock: sock_t }

impl TcpListener {
    pub fn bind(addr: ip::SocketAddr) -> IoResult<TcpListener> {
        sys::init_net();

        let sock = try!(net::socket(addr, libc::SOCK_STREAM));
        let ret = TcpListener { sock: sock };

        let mut storage = unsafe { mem::zeroed() };
        let len = net::addr_to_sockaddr(addr, &mut storage);
        let addrp = &storage as *const _ as *const libc::sockaddr;

        match unsafe { libc::bind(sock, addrp, len) } {
            -1 => Err(last_net_error()),
            _ => Ok(ret),
        }
    }

    pub fn socket(&self) -> sock_t { self.sock }

    pub fn listen(self, backlog: int) -> IoResult<TcpAcceptor> {
        match unsafe { libc::listen(self.socket(), backlog as libc::c_int) } {
            -1 => Err(last_net_error()),

            _ => {
                let accept = try!(Event::new());
                let ret = unsafe {
                    c::WSAEventSelect(self.socket(), accept.handle(), c::FD_ACCEPT)
                };
                if ret != 0 {
                    return Err(last_net_error())
                }
                Ok(TcpAcceptor {
                    inner: Arc::new(AcceptorInner {
                        listener: self,
                        abort: try!(Event::new()),
                        accept: accept,
                        closed: atomic::AtomicBool::new(false),
                    }),
                    deadline: 0,
                })
            }
        }
    }

    pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
        net::sockname(self.socket(), libc::getsockname)
    }
}

impl Drop for TcpListener {
    fn drop(&mut self) {
        unsafe { super::close_sock(self.sock); }
    }
}

pub struct TcpAcceptor {
    inner: Arc<AcceptorInner>,
    deadline: u64,
}

struct AcceptorInner {
    listener: TcpListener,
    abort: Event,
    accept: Event,
    closed: atomic::AtomicBool,
}

impl TcpAcceptor {
    pub fn socket(&self) -> sock_t { self.inner.listener.socket() }

    pub fn accept(&mut self) -> IoResult<TcpStream> {
        // Unlink unix, windows cannot invoke `select` on arbitrary file
        // descriptors like pipes, only sockets. Consequently, windows cannot
        // use the same implementation as unix for accept() when close_accept()
        // is considered.
        //
        // In order to implement close_accept() and timeouts, windows uses
        // event handles. An acceptor-specific abort event is created which
        // will only get set in close_accept(), and it will never be un-set.
        // Additionally, another acceptor-specific event is associated with the
        // FD_ACCEPT network event.
        //
        // These two events are then passed to WaitForMultipleEvents to see
        // which one triggers first, and the timeout passed to this function is
        // the local timeout for the acceptor.
        //
        // If the wait times out, then the accept timed out. If the wait
        // succeeds with the abort event, then we were closed, and if the wait
        // succeeds otherwise, then we do a nonblocking poll via `accept` to
        // see if we can accept a connection. The connection is candidate to be
        // stolen, so we do all of this in a loop as well.
        let events = [self.inner.abort.handle(), self.inner.accept.handle()];

        while !self.inner.closed.load(atomic::SeqCst) {
            let ms = if self.deadline == 0 {
                c::WSA_INFINITE as u64
            } else {
                let now = timer::now();
                if self.deadline < now {0} else {self.deadline - now}
            };
            let ret = unsafe {
                c::WSAWaitForMultipleEvents(2, events.as_ptr(), libc::FALSE,
                                            ms as libc::DWORD, libc::FALSE)
            };
            match ret {
                c::WSA_WAIT_TIMEOUT => {
                    return Err(timeout("accept timed out"))
                }
                c::WSA_WAIT_FAILED => return Err(last_net_error()),
                c::WSA_WAIT_EVENT_0 => break,
                n => assert_eq!(n, c::WSA_WAIT_EVENT_0 + 1),
            }

            let mut wsaevents: c::WSANETWORKEVENTS = unsafe { mem::zeroed() };
            let ret = unsafe {
                c::WSAEnumNetworkEvents(self.socket(), events[1], &mut wsaevents)
            };
            if ret != 0 { return Err(last_net_error()) }

            if wsaevents.lNetworkEvents & c::FD_ACCEPT == 0 { continue }
            match unsafe {
                libc::accept(self.socket(), ptr::null_mut(), ptr::null_mut())
            } {
                -1 if wouldblock() => {}
                -1 => return Err(last_net_error()),

                // Accepted sockets inherit the same properties as the caller,
                // so we need to deregister our event and switch the socket back
                // to blocking mode
                socket => {
                    let stream = TcpStream::new(socket);
                    let ret = unsafe {
                        c::WSAEventSelect(socket, events[1], 0)
                    };
                    if ret != 0 { return Err(last_net_error()) }
                    try!(set_nonblocking(socket, false));
                    return Ok(stream)
                }
            }
        }

        Err(eof())
    }

    pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
        net::sockname(self.socket(), libc::getsockname)
    }

    pub fn set_timeout(&mut self, timeout: Option<u64>) {
        self.deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
    }

    pub fn close_accept(&mut self) -> IoResult<()> {
        self.inner.closed.store(true, atomic::SeqCst);
        let ret = unsafe { c::WSASetEvent(self.inner.abort.handle()) };
        if ret == libc::TRUE {
            Ok(())
        } else {
            Err(last_net_error())
        }
    }
}

impl Clone for TcpAcceptor {
    fn clone(&self) -> TcpAcceptor {
        TcpAcceptor {
            inner: self.inner.clone(),
            deadline: 0,
        }
    }
}
<commit_msg>Implement Sync/Send for windows TCP types<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

use io::net::ip;
use io::IoResult;
use libc;
use mem;
use ptr;
use prelude::*;
use super::{last_error, last_net_error, retry, sock_t};
use sync::{Arc, atomic};
use sys::fs::FileDesc;
use sys::{mod, c, set_nonblocking, wouldblock, timer};
use sys_common::{mod, timeout, eof, net};

pub use sys_common::net::TcpStream;

pub struct Event(c::WSAEVENT);

unsafe impl Send for Event {}
unsafe impl Sync for Event {}

impl Event {
    pub fn new() -> IoResult<Event> {
        let event = unsafe { c::WSACreateEvent() };
        if event == c::WSA_INVALID_EVENT {
            Err(super::last_error())
        } else {
            Ok(Event(event))
        }
    }

    pub fn handle(&self) -> c::WSAEVENT { let Event(handle) = *self; handle }
}

impl Drop for Event {
    fn drop(&mut self) {
        unsafe { let _ = c::WSACloseEvent(self.handle()); }
    }
}

////////////////////////////////////////////////////////////////////////////////
// TCP listeners
////////////////////////////////////////////////////////////////////////////////

pub struct TcpListener { sock: sock_t }

unsafe impl Send for TcpListener {}
unsafe impl Sync for TcpListener {}

impl TcpListener {
    pub fn bind(addr: ip::SocketAddr) -> IoResult<TcpListener> {
        sys::init_net();

        let sock = try!(net::socket(addr, libc::SOCK_STREAM));
        let ret = TcpListener { sock: sock };

        let mut storage = unsafe { mem::zeroed() };
        let len = net::addr_to_sockaddr(addr, &mut storage);
        let addrp = &storage as *const _ as *const libc::sockaddr;

        match unsafe { libc::bind(sock, addrp, len) } {
            -1 => Err(last_net_error()),
            _ => Ok(ret),
        }
    }

    pub fn socket(&self) -> sock_t { self.sock }

    pub fn listen(self, backlog: int) -> IoResult<TcpAcceptor> {
        match unsafe { libc::listen(self.socket(), backlog as libc::c_int) } {
            -1 => Err(last_net_error()),

            _ => {
                let accept = try!(Event::new());
                let ret = unsafe {
                    c::WSAEventSelect(self.socket(), accept.handle(), c::FD_ACCEPT)
                };
                if ret != 0 {
                    return Err(last_net_error())
                }
                Ok(TcpAcceptor {
                    inner: Arc::new(AcceptorInner {
                        listener: self,
                        abort: try!(Event::new()),
                        accept: accept,
                        closed: atomic::AtomicBool::new(false),
                    }),
                    deadline: 0,
                })
            }
        }
    }

    pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
        net::sockname(self.socket(), libc::getsockname)
    }
}

impl Drop for TcpListener {
    fn drop(&mut self) {
        unsafe { super::close_sock(self.sock); }
    }
}

pub struct TcpAcceptor {
    inner: Arc<AcceptorInner>,
    deadline: u64,
}

unsafe impl Send for TcpAcceptor {}
unsafe impl Sync for TcpAcceptor {}

struct AcceptorInner {
    listener: TcpListener,
    abort: Event,
    accept: Event,
    closed: atomic::AtomicBool,
}

unsafe impl Send for AcceptorInner {}
unsafe impl Sync for AcceptorInner {}

impl TcpAcceptor {
    pub fn socket(&self) -> sock_t { self.inner.listener.socket() }

    pub fn accept(&mut self) -> IoResult<TcpStream> {
        // Unlink unix, windows cannot invoke `select` on arbitrary file
        // descriptors like pipes, only sockets. Consequently, windows cannot
        // use the same implementation as unix for accept() when close_accept()
        // is considered.
        //
        // In order to implement close_accept() and timeouts, windows uses
        // event handles. An acceptor-specific abort event is created which
        // will only get set in close_accept(), and it will never be un-set.
        // Additionally, another acceptor-specific event is associated with the
        // FD_ACCEPT network event.
        //
        // These two events are then passed to WaitForMultipleEvents to see
        // which one triggers first, and the timeout passed to this function is
        // the local timeout for the acceptor.
        //
        // If the wait times out, then the accept timed out. If the wait
        // succeeds with the abort event, then we were closed, and if the wait
        // succeeds otherwise, then we do a nonblocking poll via `accept` to
        // see if we can accept a connection. The connection is candidate to be
        // stolen, so we do all of this in a loop as well.
        let events = [self.inner.abort.handle(), self.inner.accept.handle()];

        while !self.inner.closed.load(atomic::SeqCst) {
            let ms = if self.deadline == 0 {
                c::WSA_INFINITE as u64
            } else {
                let now = timer::now();
                if self.deadline < now {0} else {self.deadline - now}
            };
            let ret = unsafe {
                c::WSAWaitForMultipleEvents(2, events.as_ptr(), libc::FALSE,
                                            ms as libc::DWORD, libc::FALSE)
            };
            match ret {
                c::WSA_WAIT_TIMEOUT => {
                    return Err(timeout("accept timed out"))
                }
                c::WSA_WAIT_FAILED => return Err(last_net_error()),
                c::WSA_WAIT_EVENT_0 => break,
                n => assert_eq!(n, c::WSA_WAIT_EVENT_0 + 1),
            }

            let mut wsaevents: c::WSANETWORKEVENTS = unsafe { mem::zeroed() };
            let ret = unsafe {
                c::WSAEnumNetworkEvents(self.socket(), events[1], &mut wsaevents)
            };
            if ret != 0 { return Err(last_net_error()) }

            if wsaevents.lNetworkEvents & c::FD_ACCEPT == 0 { continue }
            match unsafe {
                libc::accept(self.socket(), ptr::null_mut(), ptr::null_mut())
            } {
                -1 if wouldblock() => {}
                -1 => return Err(last_net_error()),

                // Accepted sockets inherit the same properties as the caller,
                // so we need to deregister our event and switch the socket back
                // to blocking mode
                socket => {
                    let stream = TcpStream::new(socket);
                    let ret = unsafe {
                        c::WSAEventSelect(socket, events[1], 0)
                    };
                    if ret != 0 { return Err(last_net_error()) }
                    try!(set_nonblocking(socket, false));
                    return Ok(stream)
                }
            }
        }

        Err(eof())
    }

    pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
        net::sockname(self.socket(), libc::getsockname)
    }

    pub fn set_timeout(&mut self, timeout: Option<u64>) {
        self.deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
    }

    pub fn close_accept(&mut self) -> IoResult<()> {
        self.inner.closed.store(true, atomic::SeqCst);
        let ret = unsafe { c::WSASetEvent(self.inner.abort.handle()) };
        if ret == libc::TRUE {
            Ok(())
        } else {
            Err(last_net_error())
        }
    }
}

impl Clone for TcpAcceptor {
    fn clone(&self) -> TcpAcceptor {
        TcpAcceptor {
            inner: self.inner.clone(),
            deadline: 0,
        }
    }
}
<|endoftext|>


<commit_before>use database::models::{ToU64, PartyFinderConfig};

use diesel::prelude::*;

use serenity::prelude::{RwLock, Mentionable};
use serenity::client::{Context, EventHandler};
use serenity::model::channel::{Reaction, Message, GuildChannel};
use serenity::model::id::{GuildId, ChannelId, UserId, MessageId};

use error::*;

use std::collections::HashMap;

const DATA_CENTERS: &[&str] = &[
  "aether",
  "chaos",
  "elemental",
  "gaia",
  "mana",
  "primal"
];

type StatusRegistry = HashMap<UserId, (PfStatus, Option<MessageId>)>;

#[derive(Default)]
pub struct PartyFinder {
  statuses: RwLock<StatusRegistry>
}

impl EventHandler for PartyFinder {
  fn reaction_add(&self, _: Context, reaction: Reaction) {
    let inner = move || -> Result<()> {
      let channel = reaction.channel()
        .chain_err(|| "could not get channel")?
        .guild()
        .chain_err(|| "could not get guild channel")?;
      let guild_id = channel.read().guild_id;
      let config = match PartyFinder::config(guild_id, channel.read().id) {
        Some(c) => c,
        None => return Ok(())
      };
      if reaction.message_id != *config.message_id {
        return Ok(());
      }
      if reaction.emoji != ::util::parse_emoji(&config.emoji) {
        return Ok(());
      }
      if let Err(e) = reaction.delete() {
        warn!("could not delete reaction: {}", e);
      }
      let mut member = guild_id.member(reaction.user_id).chain_err(|| "could not get member")?;
      if let Err(e) = member.add_role(*config.role_id) {
        bail!("could not add role: {}", e);
      }
      let mut writer = self.statuses.write();
      let entry = writer.entry(reaction.user_id).or_insert((PfStatus::Started, None));
      match entry.0 {
        PfStatus::Started => {},
        _ => return Ok(())
      }
      let res = channel.read()
        .send_message(|c| c.embed(|e| e
          .description(&format!("{}\n\nLet's make a PF ad for you!\n\nWhat data center is this PF for?", reaction.user_id.mention()))));
      match res {
        Ok(m) => { entry.1 = Some(m.id); },
        Err(e) => bail!("could not send message: {}", e)
      }
      Ok(())
    };
    if let Err(e) = inner() {
      warn!("error in PartyFinder::reaction_add: {}", e);
    }
  }

  fn message(&self, _: Context, message: Message) {
    if message.author.id == ::serenity::CACHE.read().user.id {
      return;
    }
    let inner = move || -> Result<()> {
      let channel = message.channel()
        .chain_err(|| "could not get channel")?
        .guild()
        .chain_err(|| "could not get guild channel")?;
      let config = match PartyFinder::config(channel.read().guild_id, channel.read().id) {
        Some(c) => c,
        None => return Ok(())
      };
      if let Err(e) = message.delete() {
        warn!("could not delete message: {}", e);
      }
      if message.content.to_lowercase().trim() == "cancel" {
        let removed = self.statuses.write().remove(&message.author.id);
        if let Some((_, Some(r))) = removed {
          message.channel_id.delete_message(r).ok();
        }
        return Ok(());
      }
      let (status, message_id) = match self.statuses.read().get(&message.author.id) {
        Some(&(ref a, Some(b))) => (a.clone(), b),
        _ => return Ok(())
      };
      status.process(config, message_id, message, channel.as_ref(), &self.statuses)
    };
    if let Err(e) = inner() {
      warn!("error in PartyFinder::message: {}", e);
    }
  }
}

impl PartyFinder {
  fn config(guild: GuildId, channel: ChannelId) -> Option<PartyFinderConfig> {
    ::bot::CONNECTION.with(|c| {
      use database::schema::party_finder_configs::dsl;
      dsl::party_finder_configs
        .filter(dsl::server_id.eq(guild.to_u64()).and(dsl::channel_id.eq(channel.to_u64())))
        .first(c)
        .ok()
    })
  }
}

#[derive(Clone)]
pub enum PfStatus {
  Started,
  DataCenter { data_center: String },
  Duty { data_center: String, duty: String }
}

impl PfStatus {
  fn process(&self, config: PartyFinderConfig, message_id: MessageId, message: Message, channel: &RwLock<GuildChannel>, statuses: &RwLock<StatusRegistry>) -> Result<()> {
    match *self {
      PfStatus::Started => self.process_started(config, message_id, message, channel, statuses),
      PfStatus::DataCenter { ref data_center } => self.process_data_center(data_center, config, message_id, message, channel, statuses),
      PfStatus::Duty { ref data_center, ref duty } => self.process_duty(data_center, duty, config, message_id, message, channel, statuses)
    }
  }

  fn process_started(&self, _: PartyFinderConfig, message_id: MessageId, message: Message, channel: &RwLock<GuildChannel>, statuses: &RwLock<StatusRegistry>) -> Result<()> {
    let data_center = message.content.trim().to_lowercase();
    if !DATA_CENTERS.contains(&data_center.as_str()) {
      return channel.read().edit_message(message_id, |m| m
        .embed(|e| e
          .description(&format!(
            "{}\n\n`{}` isn't a valid data center. Let's try again.\n\nWhat data center is this PF for?",
            message.author.mention(),
            data_center
          ))))
        .map(|_| ())
        .chain_err(|| "could not edit message");
    }

    channel.read().edit_message(message_id, |m| m
      .embed(|e| e
        .description(&format!(
          "{}\n\nOkay, we're making the PF for the {} data center.\n\nWhat duty is the PF for?",
          message.author.mention(),
          data_center
        ))))
      .chain_err(|| "could not edit message")?;
    statuses.write().get_mut(&message.author.id).unwrap().0 = PfStatus::DataCenter { data_center };
    Ok(())
  }

  fn process_data_center(&self, data_center: &str, _: PartyFinderConfig, message_id: MessageId, message: Message, channel: &RwLock<GuildChannel>, statuses: &RwLock<StatusRegistry>) -> Result<()> {
    let duty = message.content.trim().to_string();
    channel.read().edit_message(message_id, |m| m
      .embed(|e| e
        .description(&format!(
          "{}\n\nOkay, we're making the PF for `{}` on the {} data center.\n\nWhat message would you like to include?",
          message.author.mention(),
          duty,
          data_center
        ))))
      .chain_err(|| "could not edit message")?;
    statuses.write().get_mut(&message.author.id).unwrap().0 = PfStatus::Duty {
      data_center: data_center.to_string(),
      duty
    };
    Ok(())
  }

  fn process_duty(&self, data_center: &str, duty: &str, config: PartyFinderConfig, message_id: MessageId, message: Message, channel: &RwLock<GuildChannel>, statuses: &RwLock<StatusRegistry>) -> Result<()> {
    let guild_id = channel.read().guild_id;
    let mut member = guild_id.member(&message.author).chain_err(|| "could not get member")?;
    member.remove_role(*config.role_id).ok();
    statuses.write().remove(&message.author.id);
    let msg = message.content.trim().to_string();
    let chan_name = guild_id
      .find()
      .and_then(|g| g.read().channels.values()
        .find(|c| c.read().name == *data_center)
        .map(|c| c.read().id.mention().to_string()))
      .unwrap_or_else(|| data_center.to_string());
    channel.read().edit_message(message_id, |m| m
      .embed(|e| e
        .description(&format!("**PF listing by {}**", message.author.mention()))
        .fields(vec![
          ("Data center", &chan_name, true),
          ("Duty", &duty.to_string(), true),
          ("Message", &msg, false)
        ])))
      .chain_err(|| "could not edit message")?;
    Ok(())
  }
}
<commit_msg>refactor: fix clippy warnings<commit_after>use database::models::{ToU64, PartyFinderConfig};

use diesel::prelude::*;

use serenity::prelude::{RwLock, Mentionable};
use serenity::client::{Context, EventHandler};
use serenity::model::channel::{Reaction, Message, GuildChannel};
use serenity::model::id::{GuildId, ChannelId, UserId, MessageId};

use error::*;

use std::collections::HashMap;

const DATA_CENTERS: &[&str] = &[
  "aether",
  "chaos",
  "elemental",
  "gaia",
  "mana",
  "primal"
];

type StatusRegistry = HashMap<UserId, (PfStatus, Option<MessageId>)>;

#[derive(Default)]
pub struct PartyFinder {
  statuses: RwLock<StatusRegistry>
}

impl EventHandler for PartyFinder {
  fn reaction_add(&self, _: Context, reaction: Reaction) {
    let inner = move || -> Result<()> {
      let channel = reaction.channel()
        .chain_err(|| "could not get channel")?
        .guild()
        .chain_err(|| "could not get guild channel")?;
      let guild_id = channel.read().guild_id;
      let config = match PartyFinder::config(guild_id, channel.read().id) {
        Some(c) => c,
        None => return Ok(())
      };
      if reaction.message_id != *config.message_id {
        return Ok(());
      }
      if reaction.emoji != ::util::parse_emoji(&config.emoji) {
        return Ok(());
      }
      if let Err(e) = reaction.delete() {
        warn!("could not delete reaction: {}", e);
      }
      let mut member = guild_id.member(reaction.user_id).chain_err(|| "could not get member")?;
      if let Err(e) = member.add_role(*config.role_id) {
        bail!("could not add role: {}", e);
      }
      let mut writer = self.statuses.write();
      let entry = writer.entry(reaction.user_id).or_insert((PfStatus::Started, None));
      match entry.0 {
        PfStatus::Started => {},
        _ => return Ok(())
      }
      let res = channel.read()
        .send_message(|c| c.embed(|e| e
          .description(&format!("{}\n\nLet's make a PF ad for you!\n\nWhat data center is this PF for?", reaction.user_id.mention()))));
      match res {
        Ok(m) => { entry.1 = Some(m.id); },
        Err(e) => bail!("could not send message: {}", e)
      }
      Ok(())
    };
    if let Err(e) = inner() {
      warn!("error in PartyFinder::reaction_add: {}", e);
    }
  }

  fn message(&self, _: Context, message: Message) {
    if message.author.id == ::serenity::CACHE.read().user.id {
      return;
    }
    let inner = move || -> Result<()> {
      let channel = message.channel()
        .chain_err(|| "could not get channel")?
        .guild()
        .chain_err(|| "could not get guild channel")?;
      let config = match PartyFinder::config(channel.read().guild_id, channel.read().id) {
        Some(c) => c,
        None => return Ok(())
      };
      if let Err(e) = message.delete() {
        warn!("could not delete message: {}", e);
      }
      if message.content.to_lowercase().trim() == "cancel" {
        let removed = self.statuses.write().remove(&message.author.id);
        if let Some((_, Some(r))) = removed {
          message.channel_id.delete_message(r).ok();
        }
        return Ok(());
      }
      let (status, message_id) = match self.statuses.read().get(&message.author.id) {
        Some(&(ref a, Some(b))) => (a.clone(), b),
        _ => return Ok(())
      };
      status.process(&config, message_id, &message, channel.as_ref(), &self.statuses)
    };
    if let Err(e) = inner() {
      warn!("error in PartyFinder::message: {}", e);
    }
  }
}

impl PartyFinder {
  fn config(guild: GuildId, channel: ChannelId) -> Option<PartyFinderConfig> {
    ::bot::CONNECTION.with(|c| {
      use database::schema::party_finder_configs::dsl;
      dsl::party_finder_configs
        .filter(dsl::server_id.eq(guild.to_u64()).and(dsl::channel_id.eq(channel.to_u64())))
        .first(c)
        .ok()
    })
  }
}

#[derive(Clone)]
pub enum PfStatus {
  Started,
  DataCenter { data_center: String },
  Duty { data_center: String, duty: String }
}

impl PfStatus {
  fn process(&self, config: &PartyFinderConfig, message_id: MessageId, message: &Message, channel: &RwLock<GuildChannel>, statuses: &RwLock<StatusRegistry>) -> Result<()> {
    match *self {
      PfStatus::Started => self.process_started(config, message_id, message, channel, statuses),
      PfStatus::DataCenter { ref data_center } => self.process_data_center(data_center, config, message_id, message, channel, statuses),
      PfStatus::Duty { ref data_center, ref duty } => self.process_duty(data_center, duty, config, message_id, message, channel, statuses)
    }
  }

  fn process_started(&self, _: &PartyFinderConfig, message_id: MessageId, message: &Message, channel: &RwLock<GuildChannel>, statuses: &RwLock<StatusRegistry>) -> Result<()> {
    let data_center = message.content.trim().to_lowercase();
    if !DATA_CENTERS.contains(&data_center.as_str()) {
      return channel.read().edit_message(message_id, |m| m
        .embed(|e| e
          .description(&format!(
            "{}\n\n`{}` isn't a valid data center. Let's try again.\n\nWhat data center is this PF for?",
            message.author.mention(),
            data_center
          ))))
        .map(|_| ())
        .chain_err(|| "could not edit message");
    }

    channel.read().edit_message(message_id, |m| m
      .embed(|e| e
        .description(&format!(
          "{}\n\nOkay, we're making the PF for the {} data center.\n\nWhat duty is the PF for?",
          message.author.mention(),
          data_center
        ))))
      .chain_err(|| "could not edit message")?;
    statuses.write().get_mut(&message.author.id).unwrap().0 = PfStatus::DataCenter { data_center };
    Ok(())
  }

  fn process_data_center(&self, data_center: &str, _: &PartyFinderConfig, message_id: MessageId, message: &Message, channel: &RwLock<GuildChannel>, statuses: &RwLock<StatusRegistry>) -> Result<()> {
    let duty = message.content.trim().to_string();
    channel.read().edit_message(message_id, |m| m
      .embed(|e| e
        .description(&format!(
          "{}\n\nOkay, we're making the PF for `{}` on the {} data center.\n\nWhat message would you like to include?",
          message.author.mention(),
          duty,
          data_center
        ))))
      .chain_err(|| "could not edit message")?;
    statuses.write().get_mut(&message.author.id).unwrap().0 = PfStatus::Duty {
      data_center: data_center.to_string(),
      duty
    };
    Ok(())
  }

  #[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
  fn process_duty(&self, data_center: &str, duty: &str, config: &PartyFinderConfig, message_id: MessageId, message: &Message, channel: &RwLock<GuildChannel>, statuses: &RwLock<StatusRegistry>) -> Result<()> {
    let guild_id = channel.read().guild_id;
    let mut member = guild_id.member(&message.author).chain_err(|| "could not get member")?;
    member.remove_role(*config.role_id).ok();
    statuses.write().remove(&message.author.id);
    let msg = message.content.trim().to_string();
    let chan_name = guild_id
      .find()
      .and_then(|g| g.read().channels.values()
        .find(|c| c.read().name == *data_center)
        .map(|c| c.read().id.mention().to_string()))
      .unwrap_or_else(|| data_center.to_string());
    channel.read().edit_message(message_id, |m| m
      .embed(|e| e
        .description(&format!("**PF listing by {}**", message.author.mention()))
        .fields(vec![
          ("Data center", &chan_name, true),
          ("Duty", &duty.to_string(), true),
          ("Message", &msg, false)
        ])))
      .chain_err(|| "could not edit message")?;
    Ok(())
  }
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
// Copyright 2013 The Rust Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The normal and derived distributions.

use crate::utils::ziggurat;
use num_traits::Float;
use crate::{ziggurat_tables, Distribution, Open01};
use rand::Rng;
use core::fmt;

/// Samples floating-point numbers according to the normal distribution
/// `N(0, 1)` (a.k.a. a standard normal, or Gaussian). This is equivalent to
/// `Normal::new(0.0, 1.0)` but faster.
///
/// See `Normal` for the general normal distribution.
///
/// Implemented via the ZIGNOR variant[^1] of the Ziggurat method.
///
/// [^1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to
///       Generate Normal Random Samples*](
///       https://www.doornik.com/research/ziggurat.pdf).
///       Nuffield College, Oxford
///
/// # Example
/// ```
/// use rand::prelude::*;
/// use rand_distr::StandardNormal;
///
/// let val: f64 = thread_rng().sample(StandardNormal);
/// println!("{}", val);
/// ```
#[derive(Clone, Copy, Debug)]
pub struct StandardNormal;

impl Distribution<f32> for StandardNormal {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f32 {
        // TODO: use optimal 32-bit implementation
        let x: f64 = self.sample(rng);
        x as f32
    }
}

impl Distribution<f64> for StandardNormal {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
        #[inline]
        fn pdf(x: f64) -> f64 {
            (-x * x / 2.0).exp()
        }
        #[inline]
        fn zero_case<R: Rng + ?Sized>(rng: &mut R, u: f64) -> f64 {
            // compute a random number in the tail by hand

            // strange initial conditions, because the loop is not
            // do-while, so the condition should be true on the first
            // run, they get overwritten anyway (0 < 1, so these are
            // good).
            let mut x = 1.0f64;
            let mut y = 0.0f64;

            while -2.0 * y < x * x {
                let x_: f64 = rng.sample(Open01);
                let y_: f64 = rng.sample(Open01);

                x = x_.ln() / ziggurat_tables::ZIG_NORM_R;
                y = y_.ln();
            }

            if u < 0.0 {
                x - ziggurat_tables::ZIG_NORM_R
            } else {
                ziggurat_tables::ZIG_NORM_R - x
            }
        }

        ziggurat(
            rng,
            true, // this is symmetric
            &ziggurat_tables::ZIG_NORM_X,
            &ziggurat_tables::ZIG_NORM_F,
            pdf,
            zero_case,
        )
    }
}

/// The normal distribution `N(mean, std_dev**2)`.
///
/// This uses the ZIGNOR variant of the Ziggurat method, see [`StandardNormal`]
/// for more details.
///
/// Note that [`StandardNormal`] is an optimised implementation for mean 0, and
/// standard deviation 1.
///
/// # Example
///
/// ```
/// use rand_distr::{Normal, Distribution};
///
/// // mean 2, standard deviation 3
/// let normal = Normal::new(2.0, 3.0).unwrap();
/// let v = normal.sample(&mut rand::thread_rng());
/// println!("{} is from a N(2, 9) distribution", v)
/// ```
///
/// [`StandardNormal`]: crate::StandardNormal
#[derive(Clone, Copy, Debug)]
pub struct Normal<F>
where F: Float, StandardNormal: Distribution<F>
{
    mean: F,
    std_dev: F,
}

/// Error type returned from `Normal::new` and `LogNormal::new`.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Error {
    /// The mean value is too small (log-normal samples must be positive)
    MeanTooSmall,
    /// The standard deviation or other dispersion parameter is negative,
    /// infinite, or not-a-number.
    BadVariance,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(match self {
            Error::MeanTooSmall => "mean < 0 or NaN in log-normal distribution",
            Error::BadVariance => "variation parameter is negative or non-finite in (log)normal distribution",
        })
    }
}

#[cfg(feature = "std")]
impl std::error::Error for Error {}

impl<F> Normal<F>
where F: Float, StandardNormal: Distribution<F>
{
    /// Construct, from mean and standard deviation
    ///
    /// Parameters:
    ///
    /// -   mean (`μ`, unrestricted)
    /// -   standard deviation (`σ`, must be finite)
    #[inline]
    pub fn new(mean: F, std_dev: F) -> Result<Normal<F>, Error> {
        if !std_dev.is_finite() {
            return Err(Error::BadVariance);
        }
        Ok(Normal { mean, std_dev })
    }

    /// Construct, from mean and coefficient of variation
    ///
    /// Parameters:
    ///
    /// -   mean (`μ`, unrestricted)
    /// -   coefficient of variation (`cv = abs(σ / μ)`)
    #[inline]
    pub fn from_mean_cv(mean: F, cv: F) -> Result<Normal<F>, Error> {
        if !cv.is_finite() || cv < F::zero() {
            return Err(Error::BadVariance);
        }
        let std_dev = cv * mean;
        Ok(Normal { mean, std_dev })
    }

    /// Sample from a z-score
    ///
    /// This may be useful for generating correlated samples `x1` and `x2`
    /// from two different distributions, as follows.
    /// ```
    /// # use rand::prelude::*;
    /// # use rand_distr::{Normal, StandardNormal};
    /// let mut rng = thread_rng();
    /// let z = StandardNormal.sample(&mut rng);
    /// let x1 = Normal::new(0.0, 1.0).unwrap().from_zscore(z);
    /// let x2 = Normal::new(2.0, -3.0).unwrap().from_zscore(z);
    /// ```
    #[inline]
    pub fn from_zscore(&self, zscore: F) -> F {
        self.mean + self.std_dev * zscore
    }
}

impl<F> Distribution<F> for Normal<F>
where F: Float, StandardNormal: Distribution<F>
{
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> F {
        self.from_zscore(rng.sample(StandardNormal))
    }
}

/// The log-normal distribution `ln N(mean, std_dev**2)`.
///
/// If `X` is log-normal distributed, then `ln(X)` is `N(mean, std_dev**2)`
/// distributed.
///
/// # Example
///
/// ```
/// use rand_distr::{LogNormal, Distribution};
///
/// // mean 2, standard deviation 3
/// let log_normal = LogNormal::new(2.0, 3.0).unwrap();
/// let v = log_normal.sample(&mut rand::thread_rng());
/// println!("{} is from an ln N(2, 9) distribution", v)
/// ```
#[derive(Clone, Copy, Debug)]
pub struct LogNormal<F>
where F: Float, StandardNormal: Distribution<F>
{
    norm: Normal<F>,
}

impl<F> LogNormal<F>
where F: Float, StandardNormal: Distribution<F>
{
    /// Construct, from (log-space) mean and standard deviation
    ///
    /// Parameters are the "standard" log-space measures (these are the mean
    /// and standard deviation of the logarithm of samples):
    ///
    /// -   `mu` (`μ`, unrestricted) is the mean of the underlying distribution
    /// -   `sigma` (`σ`, must be finite) is the standard deviation of the
    ///     underlying Normal distribution
    #[inline]
    pub fn new(mu: F, sigma: F) -> Result<LogNormal<F>, Error> {
        let norm = Normal::new(mu, sigma)?;
        Ok(LogNormal { norm })
    }

    /// Construct, from (linear-space) mean and coefficient of variation
    ///
    /// Parameters are linear-space measures:
    ///
    /// -   mean (`μ > 0`) is the (real) mean of the distribution
    /// -   coefficient of variation (`cv = σ / μ`, requiring `cv ≥ 0`) is a
    ///     standardized measure of dispersion
    ///
    /// As a special exception, `μ = 0, cv = 0` is allowed (samples are `-inf`).
    #[inline]
    pub fn from_mean_cv(mean: F, cv: F) -> Result<LogNormal<F>, Error> {
        if cv == F::zero() {
            let mu = mean.ln();
            let norm = Normal::new(mu, F::zero()).unwrap();
            return Ok(LogNormal { norm });
        }
        if !(mean > F::zero()) {
            return Err(Error::MeanTooSmall);
        }
        if !(cv >= F::zero()) {
            return Err(Error::BadVariance);
        }

        // Using X ~ lognormal(μ, σ), CV² = Var(X) / E(X)²
        // E(X) = exp(μ + σ² / 2) = exp(μ) × exp(σ² / 2)
        // Var(X) = exp(2μ + σ²)(exp(σ²) - 1) = E(X)² × (exp(σ²) - 1)
        // but Var(X) = (CV × E(X))² so CV² = exp(σ²) - 1
        // thus σ² = log(CV² + 1)
        // and exp(μ) = E(X) / exp(σ² / 2) = E(X) / sqrt(CV² + 1)
        let a = F::one() + cv * cv; // e
        let mu = F::from(0.5).unwrap() * (mean * mean / a).ln();
        let sigma = a.ln().sqrt();
        let norm = Normal::new(mu, sigma)?;
        Ok(LogNormal { norm })
    }

    /// Sample from a z-score
    ///
    /// This may be useful for generating correlated samples `x1` and `x2`
    /// from two different distributions, as follows.
    /// ```
    /// # use rand::prelude::*;
    /// # use rand_distr::{LogNormal, StandardNormal};
    /// let mut rng = thread_rng();
    /// let z = StandardNormal.sample(&mut rng);
    /// let x1 = LogNormal::from_mean_cv(3.0, 1.0).unwrap().from_zscore(z);
    /// let x2 = LogNormal::from_mean_cv(2.0, 4.0).unwrap().from_zscore(z);
    /// ```
    #[inline]
    pub fn from_zscore(&self, zscore: F) -> F {
        self.norm.from_zscore(zscore).exp()
    }
}

impl<F> Distribution<F> for LogNormal<F>
where F: Float, StandardNormal: Distribution<F>
{
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> F {
        self.norm.sample(rng).exp()
    }
}

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

    #[test]
    fn test_normal() {
        let norm = Normal::new(10.0, 10.0).unwrap();
        let mut rng = crate::test::rng(210);
        for _ in 0..1000 {
            norm.sample(&mut rng);
        }
    }
    #[test]
    fn test_normal_cv() {
        let norm = Normal::from_mean_cv(1024.0, 1.0 / 256.0).unwrap();
        assert_eq!((norm.mean, norm.std_dev), (1024.0, 4.0));
    }
    #[test]
    fn test_normal_invalid_sd() {
        assert!(Normal::from_mean_cv(10.0, -1.0).is_err());
    }

    #[test]
    fn test_log_normal() {
        let lnorm = LogNormal::new(10.0, 10.0).unwrap();
        let mut rng = crate::test::rng(211);
        for _ in 0..1000 {
            lnorm.sample(&mut rng);
        }
    }
    #[test]
    fn test_log_normal_cv() {
        let lnorm = LogNormal::from_mean_cv(0.0, 0.0).unwrap();
        assert_eq!((lnorm.norm.mean, lnorm.norm.std_dev), (-std::f64::INFINITY, 0.0));

        let lnorm = LogNormal::from_mean_cv(1.0, 0.0).unwrap();
        assert_eq!((lnorm.norm.mean, lnorm.norm.std_dev), (0.0, 0.0));

        let e = std::f64::consts::E;
        let lnorm = LogNormal::from_mean_cv(e.sqrt(), (e - 1.0).sqrt()).unwrap();
        assert_almost_eq!(lnorm.norm.mean, 0.0, 2e-16);
        assert_almost_eq!(lnorm.norm.std_dev, 1.0, 2e-16);

        let lnorm = LogNormal::from_mean_cv(e.powf(1.5), (e - 1.0).sqrt()).unwrap();
        assert_eq!((lnorm.norm.mean, lnorm.norm.std_dev), (1.0, 1.0));
    }
    #[test]
    fn test_log_normal_invalid_sd() {
        assert!(LogNormal::from_mean_cv(-1.0, 1.0).is_err());
        assert!(LogNormal::from_mean_cv(0.0, 1.0).is_err());
        assert!(LogNormal::from_mean_cv(1.0, -1.0).is_err());
    }
}
<commit_msg>Adjust error message/doc<commit_after>// Copyright 2018 Developers of the Rand project.
// Copyright 2013 The Rust Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The normal and derived distributions.

use crate::utils::ziggurat;
use num_traits::Float;
use crate::{ziggurat_tables, Distribution, Open01};
use rand::Rng;
use core::fmt;

/// Samples floating-point numbers according to the normal distribution
/// `N(0, 1)` (a.k.a. a standard normal, or Gaussian). This is equivalent to
/// `Normal::new(0.0, 1.0)` but faster.
///
/// See `Normal` for the general normal distribution.
///
/// Implemented via the ZIGNOR variant[^1] of the Ziggurat method.
///
/// [^1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to
///       Generate Normal Random Samples*](
///       https://www.doornik.com/research/ziggurat.pdf).
///       Nuffield College, Oxford
///
/// # Example
/// ```
/// use rand::prelude::*;
/// use rand_distr::StandardNormal;
///
/// let val: f64 = thread_rng().sample(StandardNormal);
/// println!("{}", val);
/// ```
#[derive(Clone, Copy, Debug)]
pub struct StandardNormal;

impl Distribution<f32> for StandardNormal {
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f32 {
        // TODO: use optimal 32-bit implementation
        let x: f64 = self.sample(rng);
        x as f32
    }
}

impl Distribution<f64> for StandardNormal {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> f64 {
        #[inline]
        fn pdf(x: f64) -> f64 {
            (-x * x / 2.0).exp()
        }
        #[inline]
        fn zero_case<R: Rng + ?Sized>(rng: &mut R, u: f64) -> f64 {
            // compute a random number in the tail by hand

            // strange initial conditions, because the loop is not
            // do-while, so the condition should be true on the first
            // run, they get overwritten anyway (0 < 1, so these are
            // good).
            let mut x = 1.0f64;
            let mut y = 0.0f64;

            while -2.0 * y < x * x {
                let x_: f64 = rng.sample(Open01);
                let y_: f64 = rng.sample(Open01);

                x = x_.ln() / ziggurat_tables::ZIG_NORM_R;
                y = y_.ln();
            }

            if u < 0.0 {
                x - ziggurat_tables::ZIG_NORM_R
            } else {
                ziggurat_tables::ZIG_NORM_R - x
            }
        }

        ziggurat(
            rng,
            true, // this is symmetric
            &ziggurat_tables::ZIG_NORM_X,
            &ziggurat_tables::ZIG_NORM_F,
            pdf,
            zero_case,
        )
    }
}

/// The normal distribution `N(mean, std_dev**2)`.
///
/// This uses the ZIGNOR variant of the Ziggurat method, see [`StandardNormal`]
/// for more details.
///
/// Note that [`StandardNormal`] is an optimised implementation for mean 0, and
/// standard deviation 1.
///
/// # Example
///
/// ```
/// use rand_distr::{Normal, Distribution};
///
/// // mean 2, standard deviation 3
/// let normal = Normal::new(2.0, 3.0).unwrap();
/// let v = normal.sample(&mut rand::thread_rng());
/// println!("{} is from a N(2, 9) distribution", v)
/// ```
///
/// [`StandardNormal`]: crate::StandardNormal
#[derive(Clone, Copy, Debug)]
pub struct Normal<F>
where F: Float, StandardNormal: Distribution<F>
{
    mean: F,
    std_dev: F,
}

/// Error type returned from `Normal::new` and `LogNormal::new`.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Error {
    /// The mean value is too small (log-normal samples must be positive)
    MeanTooSmall,
    /// The standard deviation or other dispersion parameter is not finite.
    BadVariance,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(match self {
            Error::MeanTooSmall => "mean < 0 or NaN in log-normal distribution",
            Error::BadVariance => "variation parameter is non-finite in (log)normal distribution",
        })
    }
}

#[cfg(feature = "std")]
impl std::error::Error for Error {}

impl<F> Normal<F>
where F: Float, StandardNormal: Distribution<F>
{
    /// Construct, from mean and standard deviation
    ///
    /// Parameters:
    ///
    /// -   mean (`μ`, unrestricted)
    /// -   standard deviation (`σ`, must be finite)
    #[inline]
    pub fn new(mean: F, std_dev: F) -> Result<Normal<F>, Error> {
        if !std_dev.is_finite() {
            return Err(Error::BadVariance);
        }
        Ok(Normal { mean, std_dev })
    }

    /// Construct, from mean and coefficient of variation
    ///
    /// Parameters:
    ///
    /// -   mean (`μ`, unrestricted)
    /// -   coefficient of variation (`cv = abs(σ / μ)`)
    #[inline]
    pub fn from_mean_cv(mean: F, cv: F) -> Result<Normal<F>, Error> {
        if !cv.is_finite() || cv < F::zero() {
            return Err(Error::BadVariance);
        }
        let std_dev = cv * mean;
        Ok(Normal { mean, std_dev })
    }

    /// Sample from a z-score
    ///
    /// This may be useful for generating correlated samples `x1` and `x2`
    /// from two different distributions, as follows.
    /// ```
    /// # use rand::prelude::*;
    /// # use rand_distr::{Normal, StandardNormal};
    /// let mut rng = thread_rng();
    /// let z = StandardNormal.sample(&mut rng);
    /// let x1 = Normal::new(0.0, 1.0).unwrap().from_zscore(z);
    /// let x2 = Normal::new(2.0, -3.0).unwrap().from_zscore(z);
    /// ```
    #[inline]
    pub fn from_zscore(&self, zscore: F) -> F {
        self.mean + self.std_dev * zscore
    }
}

impl<F> Distribution<F> for Normal<F>
where F: Float, StandardNormal: Distribution<F>
{
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> F {
        self.from_zscore(rng.sample(StandardNormal))
    }
}

/// The log-normal distribution `ln N(mean, std_dev**2)`.
///
/// If `X` is log-normal distributed, then `ln(X)` is `N(mean, std_dev**2)`
/// distributed.
///
/// # Example
///
/// ```
/// use rand_distr::{LogNormal, Distribution};
///
/// // mean 2, standard deviation 3
/// let log_normal = LogNormal::new(2.0, 3.0).unwrap();
/// let v = log_normal.sample(&mut rand::thread_rng());
/// println!("{} is from an ln N(2, 9) distribution", v)
/// ```
#[derive(Clone, Copy, Debug)]
pub struct LogNormal<F>
where F: Float, StandardNormal: Distribution<F>
{
    norm: Normal<F>,
}

impl<F> LogNormal<F>
where F: Float, StandardNormal: Distribution<F>
{
    /// Construct, from (log-space) mean and standard deviation
    ///
    /// Parameters are the "standard" log-space measures (these are the mean
    /// and standard deviation of the logarithm of samples):
    ///
    /// -   `mu` (`μ`, unrestricted) is the mean of the underlying distribution
    /// -   `sigma` (`σ`, must be finite) is the standard deviation of the
    ///     underlying Normal distribution
    #[inline]
    pub fn new(mu: F, sigma: F) -> Result<LogNormal<F>, Error> {
        let norm = Normal::new(mu, sigma)?;
        Ok(LogNormal { norm })
    }

    /// Construct, from (linear-space) mean and coefficient of variation
    ///
    /// Parameters are linear-space measures:
    ///
    /// -   mean (`μ > 0`) is the (real) mean of the distribution
    /// -   coefficient of variation (`cv = σ / μ`, requiring `cv ≥ 0`) is a
    ///     standardized measure of dispersion
    ///
    /// As a special exception, `μ = 0, cv = 0` is allowed (samples are `-inf`).
    #[inline]
    pub fn from_mean_cv(mean: F, cv: F) -> Result<LogNormal<F>, Error> {
        if cv == F::zero() {
            let mu = mean.ln();
            let norm = Normal::new(mu, F::zero()).unwrap();
            return Ok(LogNormal { norm });
        }
        if !(mean > F::zero()) {
            return Err(Error::MeanTooSmall);
        }
        if !(cv >= F::zero()) {
            return Err(Error::BadVariance);
        }

        // Using X ~ lognormal(μ, σ), CV² = Var(X) / E(X)²
        // E(X) = exp(μ + σ² / 2) = exp(μ) × exp(σ² / 2)
        // Var(X) = exp(2μ + σ²)(exp(σ²) - 1) = E(X)² × (exp(σ²) - 1)
        // but Var(X) = (CV × E(X))² so CV² = exp(σ²) - 1
        // thus σ² = log(CV² + 1)
        // and exp(μ) = E(X) / exp(σ² / 2) = E(X) / sqrt(CV² + 1)
        let a = F::one() + cv * cv; // e
        let mu = F::from(0.5).unwrap() * (mean * mean / a).ln();
        let sigma = a.ln().sqrt();
        let norm = Normal::new(mu, sigma)?;
        Ok(LogNormal { norm })
    }

    /// Sample from a z-score
    ///
    /// This may be useful for generating correlated samples `x1` and `x2`
    /// from two different distributions, as follows.
    /// ```
    /// # use rand::prelude::*;
    /// # use rand_distr::{LogNormal, StandardNormal};
    /// let mut rng = thread_rng();
    /// let z = StandardNormal.sample(&mut rng);
    /// let x1 = LogNormal::from_mean_cv(3.0, 1.0).unwrap().from_zscore(z);
    /// let x2 = LogNormal::from_mean_cv(2.0, 4.0).unwrap().from_zscore(z);
    /// ```
    #[inline]
    pub fn from_zscore(&self, zscore: F) -> F {
        self.norm.from_zscore(zscore).exp()
    }
}

impl<F> Distribution<F> for LogNormal<F>
where F: Float, StandardNormal: Distribution<F>
{
    #[inline]
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> F {
        self.norm.sample(rng).exp()
    }
}

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

    #[test]
    fn test_normal() {
        let norm = Normal::new(10.0, 10.0).unwrap();
        let mut rng = crate::test::rng(210);
        for _ in 0..1000 {
            norm.sample(&mut rng);
        }
    }
    #[test]
    fn test_normal_cv() {
        let norm = Normal::from_mean_cv(1024.0, 1.0 / 256.0).unwrap();
        assert_eq!((norm.mean, norm.std_dev), (1024.0, 4.0));
    }
    #[test]
    fn test_normal_invalid_sd() {
        assert!(Normal::from_mean_cv(10.0, -1.0).is_err());
    }

    #[test]
    fn test_log_normal() {
        let lnorm = LogNormal::new(10.0, 10.0).unwrap();
        let mut rng = crate::test::rng(211);
        for _ in 0..1000 {
            lnorm.sample(&mut rng);
        }
    }
    #[test]
    fn test_log_normal_cv() {
        let lnorm = LogNormal::from_mean_cv(0.0, 0.0).unwrap();
        assert_eq!((lnorm.norm.mean, lnorm.norm.std_dev), (-std::f64::INFINITY, 0.0));

        let lnorm = LogNormal::from_mean_cv(1.0, 0.0).unwrap();
        assert_eq!((lnorm.norm.mean, lnorm.norm.std_dev), (0.0, 0.0));

        let e = std::f64::consts::E;
        let lnorm = LogNormal::from_mean_cv(e.sqrt(), (e - 1.0).sqrt()).unwrap();
        assert_almost_eq!(lnorm.norm.mean, 0.0, 2e-16);
        assert_almost_eq!(lnorm.norm.std_dev, 1.0, 2e-16);

        let lnorm = LogNormal::from_mean_cv(e.powf(1.5), (e - 1.0).sqrt()).unwrap();
        assert_eq!((lnorm.norm.mean, lnorm.norm.std_dev), (1.0, 1.0));
    }
    #[test]
    fn test_log_normal_invalid_sd() {
        assert!(LogNormal::from_mean_cv(-1.0, 1.0).is_err());
        assert!(LogNormal::from_mean_cv(0.0, 1.0).is_err());
        assert!(LogNormal::from_mean_cv(1.0, -1.0).is_err());
    }
}
<|endoftext|>


<commit_before>//! Implements a command for managing projects.
use clap::{App, AppSettings, ArgMatches};
use failure::Error;

use api::Api;
use config::Config;
use utils::args::ArgExt;
use utils::formatting::Table;

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b> {
    app.about("Manage projects on Sentry.")
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .org_arg()
        .subcommand(App::new("list").about("List all projects for an organization."))
}

pub fn execute<'a>(matches: &ArgMatches<'a>) -> Result<(), Error> {
    let config = Config::get_current();
    let api = Api::get_current();
    let org = config.get_org(matches)?;
    let mut projects = api.list_organization_projects(&org)?;
    projects.sort_by_key(|p| (p.team.name.clone(), p.name.clone()));

    let mut table = Table::new();
    table.title_row().add("Slug").add("Team").add("Name");

    for project in &projects {
        table
            .add_row()
            .add(&project.slug)
            .add(&project.team.name)
            .add(&project.name);
    }

    table.print();

    Ok(())
}
<commit_msg>feat: Show project ID in project listing (#384)<commit_after>//! Implements a command for managing projects.
use clap::{App, AppSettings, ArgMatches};
use failure::Error;

use api::Api;
use config::Config;
use utils::args::ArgExt;
use utils::formatting::Table;

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b> {
    app.about("Manage projects on Sentry.")
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .org_arg()
        .subcommand(App::new("list").about("List all projects for an organization."))
}

pub fn execute<'a>(matches: &ArgMatches<'a>) -> Result<(), Error> {
    let config = Config::get_current();
    let api = Api::get_current();
    let org = config.get_org(matches)?;
    let mut projects = api.list_organization_projects(&org)?;
    projects.sort_by_key(|p| (p.team.name.clone(), p.name.clone()));

    let mut table = Table::new();
    table
        .title_row()
        .add("ID")
        .add("Slug")
        .add("Team")
        .add("Name");

    for project in &projects {
        table
            .add_row()
            .add(&project.id)
            .add(&project.slug)
            .add(&project.team.name)
            .add(&project.name);
    }

    table.print();

    Ok(())
}
<|endoftext|>