<commit_before>//! A simplified implementation of the `bytes` crate, with different features, less safety.
//!
//! #Examples
//!
//! ```
//! use bytes::rc::Bytes;
//!
//! let bytes = vec![0u8; 1024];
//! let mut shared1 = Bytes::from(bytes);
//! let mut shared2 = shared1.extract_to(100);
//! let mut shared3 = shared1.extract_to(100);
//! let mut shared4 = shared2.extract_to(60);
//!
//! assert_eq!(shared1.len(), 824);
//! assert_eq!(shared2.len(), 40);
//! assert_eq!(shared3.len(), 100);
//! assert_eq!(shared4.len(), 60);
//!
//! for byte in shared1.iter_mut() { *byte = 1u8; }
//! for byte in shared2.iter_mut() { *byte = 2u8; }
//! for byte in shared3.iter_mut() { *byte = 3u8; }
//! for byte in shared4.iter_mut() { *byte = 4u8; }
//!
//! drop(shared1);
//! drop(shared2);
//! drop(shared3);
//!
//! if let Ok(bytes) = shared4.try_recover() {
//!     assert_eq!(bytes[200..1024].to_vec(), [1u8;824].to_vec());
//!     assert_eq!(bytes[60..100].to_vec(),   [2u8;40].to_vec());
//!     assert_eq!(bytes[100..200].to_vec(),  [3u8;100].to_vec());
//!     assert_eq!(bytes[0..60].to_vec(),     [4u8;60].to_vec());
//! }
//! else {
//!     panic!("unrecoverable!");
//! }
//! ```
#![forbid(missing_docs)]

/// An `Rc`-backed mutable byte slice backed by a common allocation.
pub mod rc {

    use std::ops::{Deref, DerefMut};
    use std::rc::Rc;

    /// A thread-local byte buffer backed by a shared allocation.
    pub struct Bytes<B: DerefMut<Target=[u8]>> {
        /// Pointer to the start of this slice (not the allocation).
        ptr: *mut u8,
        /// Length of this slice.
        len: usize,
        /// Shared access to underlying resources.
        ///
        /// Importantly, this is unavailable for as long as the struct exists, which may
        /// prevent shared access to ptr[0 .. len]. I'm not sure I understand Rust's rules
        /// enough to make a strong statement about this.
        sequestered: Rc<B>,
    }

    impl<B: DerefMut<Target=[u8]>> Bytes<B> {

        /// Create a new instance from a byte allocation.
        pub fn from(mut bytes: B) -> Bytes<B> {
            Bytes {
                ptr: bytes.as_mut_ptr(),
                len: bytes.len(),
                sequestered: Rc::new(bytes),
            }
        }

        /// Extracts [0, index) into a new `Bytes` which is returned, updating `self`.
        ///
        /// #Safety
        ///
        /// This method uses an `unsafe` region to advance the pointer by `index`. It first
        /// tests `index` against `self.len`, which should ensure that the offset is in-bounds.
        pub fn extract_to(&mut self, index: usize) -> Bytes<B> {

            assert!(index <= self.len);

            let result = Bytes {
                ptr: self.ptr,
                len: index,
                sequestered: self.sequestered.clone(),
            };

            unsafe { self.ptr = self.ptr.offset(index as isize); }
            self.len -= index;

            result
        }

        /// Recover the underlying storage.
        ///
        /// This method either results in the underlying storage if it is uniquely held, or the
        /// input `Bytes` if it is not uniquely held.
        pub fn try_recover(self) -> Result<B, Bytes<B>> {
            match Rc::try_unwrap(self.sequestered) {
                Ok(bytes) => Ok(bytes),
                Err(rc) => Err(Bytes {
                    ptr: self.ptr,
                    len: self.len,
                    sequestered: rc,
                }),
            }
        }
    }

    impl<B: DerefMut<Target=[u8]>+Clone> Deref for Bytes<B> {
        type Target = [u8];
        fn deref(&self) -> &[u8] {
            unsafe { ::std::slice::from_raw_parts(self.ptr, self.len) }
        }
    }

    impl<B: DerefMut<Target=[u8]>+Clone> DerefMut for Bytes<B> {
        fn deref_mut(&mut self) -> &mut [u8] {
            unsafe { ::std::slice::from_raw_parts_mut(self.ptr, self.len) }
        }
    }
}

/// An `Arc`-backed mutable byte slice backed by a common allocation.
pub mod arc {

    use std::ops::{Deref, DerefMut};
    use std::sync::Arc;

    /// A thread-local byte buffer backed by a shared allocation.
    pub struct Bytes<B: DerefMut<Target=[u8]>> {
        /// Pointer to the start of this slice (not the allocation).
        ptr: *mut u8,
        /// Length of this slice.
        len: usize,
        /// Shared access to underlying resources.
        ///
        /// Importantly, this is unavailable for as long as the struct exists, which may
        /// prevent shared access to ptr[0 .. len]. I'm not sure I understand Rust's rules
        /// enough to make a strong statement about this.
        sequestered: Arc<B>,
    }

    impl<B: DerefMut<Target=[u8]>> Bytes<B> {

        /// Create a new instance from a byte allocation.
        pub fn from(mut bytes: B) -> Bytes<B> {
            Bytes {
                ptr: bytes.as_mut_ptr(),
                len: bytes.len(),
                sequestered: Arc::new(bytes),
            }
        }

        /// Extracts [0, index) into a new `Bytes` which is returned, updating `self`.
        ///
        /// #Safety
        ///
        /// This method uses an `unsafe` region to advance the pointer by `index`. It first
        /// tests `index` against `self.len`, which should ensure that the offset is in-bounds.
        pub fn extract_to(&mut self, index: usize) -> Bytes<B> {

            assert!(index <= self.len);

            let result = Bytes {
                ptr: self.ptr,
                len: index,
                sequestered: self.sequestered.clone(),
            };

            unsafe { self.ptr = self.ptr.offset(index as isize); }
            self.len -= index;

            result
        }

        /// Recover the underlying storage.
        ///
        /// This method either results in the underlying storage if it is uniquely held, or the
        /// input `Bytes` if it is not uniquely held.
        pub fn try_recover(self) -> Result<B, Bytes<B>> {
            match Arc::try_unwrap(self.sequestered) {
                Ok(bytes) => Ok(bytes),
                Err(arc) => Err(Bytes {
                    ptr: self.ptr,
                    len: self.len,
                    sequestered: arc,
                }),
            }
        }
    }

    impl<B: DerefMut<Target=[u8]>+Clone> Deref for Bytes<B> {
        type Target = [u8];
        fn deref(&self) -> &[u8] {
            unsafe { ::std::slice::from_raw_parts(self.ptr, self.len) }
        }
    }

    impl<B: DerefMut<Target=[u8]>+Clone> DerefMut for Bytes<B> {
        fn deref_mut(&mut self) -> &mut [u8] {
            unsafe { ::std::slice::from_raw_parts_mut(self.ptr, self.len) }
        }
    }
}<commit_msg>move bytes before getting addr<commit_after>//! A simplified implementation of the `bytes` crate, with different features, less safety.
//!
//! #Examples
//!
//! ```
//! use bytes::rc::Bytes;
//!
//! let bytes = vec![0u8; 1024];
//! let mut shared1 = Bytes::from(bytes);
//! let mut shared2 = shared1.extract_to(100);
//! let mut shared3 = shared1.extract_to(100);
//! let mut shared4 = shared2.extract_to(60);
//!
//! assert_eq!(shared1.len(), 824);
//! assert_eq!(shared2.len(), 40);
//! assert_eq!(shared3.len(), 100);
//! assert_eq!(shared4.len(), 60);
//!
//! for byte in shared1.iter_mut() { *byte = 1u8; }
//! for byte in shared2.iter_mut() { *byte = 2u8; }
//! for byte in shared3.iter_mut() { *byte = 3u8; }
//! for byte in shared4.iter_mut() { *byte = 4u8; }
//!
//! drop(shared1);
//! drop(shared2);
//! drop(shared3);
//!
//! if let Ok(bytes) = shared4.try_recover() {
//!     assert_eq!(bytes[200..1024].to_vec(), [1u8;824].to_vec());
//!     assert_eq!(bytes[60..100].to_vec(),   [2u8;40].to_vec());
//!     assert_eq!(bytes[100..200].to_vec(),  [3u8;100].to_vec());
//!     assert_eq!(bytes[0..60].to_vec(),     [4u8;60].to_vec());
//! }
//! else {
//!     panic!("unrecoverable!");
//! }
//! ```
#![forbid(missing_docs)]

/// An `Rc`-backed mutable byte slice backed by a common allocation.
pub mod rc {

    use std::ops::{Deref, DerefMut};
    use std::rc::Rc;

    /// A thread-local byte buffer backed by a shared allocation.
    pub struct Bytes<B: DerefMut<Target=[u8]>> {
        /// Pointer to the start of this slice (not the allocation).
        ptr: *mut u8,
        /// Length of this slice.
        len: usize,
        /// Shared access to underlying resources.
        ///
        /// Importantly, this is unavailable for as long as the struct exists, which may
        /// prevent shared access to ptr[0 .. len]. I'm not sure I understand Rust's rules
        /// enough to make a strong statement about this.
        sequestered: Rc<B>,
    }

    impl<B: DerefMut<Target=[u8]>> Bytes<B> {

        /// Create a new instance from a byte allocation.
        pub fn from(bytes: B) -> Bytes<B> {

            let mut rc = Rc::new(bytes);

            Bytes {
                ptr: Rc::get_mut(&mut rc).unwrap().as_mut_ptr(),
                len: rc.len(),
                sequestered: rc,
            }
        }

        /// Extracts [0, index) into a new `Bytes` which is returned, updating `self`.
        ///
        /// #Safety
        ///
        /// This method uses an `unsafe` region to advance the pointer by `index`. It first
        /// tests `index` against `self.len`, which should ensure that the offset is in-bounds.
        pub fn extract_to(&mut self, index: usize) -> Bytes<B> {

            assert!(index <= self.len);

            let result = Bytes {
                ptr: self.ptr,
                len: index,
                sequestered: self.sequestered.clone(),
            };

            unsafe { self.ptr = self.ptr.offset(index as isize); }
            self.len -= index;

            result
        }

        /// Recover the underlying storage.
        ///
        /// This method either results in the underlying storage if it is uniquely held, or the
        /// input `Bytes` if it is not uniquely held.
        pub fn try_recover(self) -> Result<B, Bytes<B>> {
            match Rc::try_unwrap(self.sequestered) {
                Ok(bytes) => Ok(bytes),
                Err(rc) => Err(Bytes {
                    ptr: self.ptr,
                    len: self.len,
                    sequestered: rc,
                }),
            }
        }
    }

    impl<B: DerefMut<Target=[u8]>+Clone> Deref for Bytes<B> {
        type Target = [u8];
        fn deref(&self) -> &[u8] {
            unsafe { ::std::slice::from_raw_parts(self.ptr, self.len) }
        }
    }

    impl<B: DerefMut<Target=[u8]>+Clone> DerefMut for Bytes<B> {
        fn deref_mut(&mut self) -> &mut [u8] {
            unsafe { ::std::slice::from_raw_parts_mut(self.ptr, self.len) }
        }
    }
}

/// An `Arc`-backed mutable byte slice backed by a common allocation.
pub mod arc {

    use std::ops::{Deref, DerefMut};
    use std::sync::Arc;

    /// A thread-safe byte buffer backed by a shared allocation.
    pub struct Bytes<B: DerefMut<Target=[u8]>> {
        /// Pointer to the start of this slice (not the allocation).
        ptr: *mut u8,
        /// Length of this slice.
        len: usize,
        /// Shared access to underlying resources.
        ///
        /// Importantly, this is unavailable for as long as the struct exists, which may
        /// prevent shared access to ptr[0 .. len]. I'm not sure I understand Rust's rules
        /// enough to make a strong statement about this.
        sequestered: Arc<B>,
    }

    impl<B: DerefMut<Target=[u8]>> Bytes<B> {

        /// Create a new instance from a byte allocation.
        pub fn from(bytes: B) -> Bytes<B> {

            let mut arc = Arc::new(bytes);

            Bytes {
                ptr: Arc::get_mut(&mut arc).unwrap().as_mut_ptr(),
                len: arc.len(),
                sequestered: arc,
            }
        }

        /// Extracts [0, index) into a new `Bytes` which is returned, updating `self`.
        ///
        /// #Safety
        ///
        /// This method uses an `unsafe` region to advance the pointer by `index`. It first
        /// tests `index` against `self.len`, which should ensure that the offset is in-bounds.
        pub fn extract_to(&mut self, index: usize) -> Bytes<B> {

            assert!(index <= self.len);

            let result = Bytes {
                ptr: self.ptr,
                len: index,
                sequestered: self.sequestered.clone(),
            };

            unsafe { self.ptr = self.ptr.offset(index as isize); }
            self.len -= index;

            result
        }

        /// Recover the underlying storage.
        ///
        /// This method either results in the underlying storage if it is uniquely held, or the
        /// input `Bytes` if it is not uniquely held.
        pub fn try_recover(self) -> Result<B, Bytes<B>> {
            match Arc::try_unwrap(self.sequestered) {
                Ok(bytes) => Ok(bytes),
                Err(arc) => Err(Bytes {
                    ptr: self.ptr,
                    len: self.len,
                    sequestered: arc,
                }),
            }
        }
    }

    impl<B: DerefMut<Target=[u8]>+Clone> Deref for Bytes<B> {
        type Target = [u8];
        fn deref(&self) -> &[u8] {
            unsafe { ::std::slice::from_raw_parts(self.ptr, self.len) }
        }
    }

    impl<B: DerefMut<Target=[u8]>+Clone> DerefMut for Bytes<B> {
        fn deref_mut(&mut self) -> &mut [u8] {
            unsafe { ::std::slice::from_raw_parts_mut(self.ptr, self.len) }
        }
    }
}<|endoftext|>


<commit_before>mod documents;
mod executables;
mod exercises;
mod feeds;
mod git;
mod homebrew;
mod notes;
mod paths;
mod processes;
mod public;

pub fn setup() {
    homebrew::install_package("vim");
    homebrew::install_package("node");
    paths::create_dir(&paths::vim_plugins());
    git::clone(
        &paths::vim_plugins(),
        "https://github.com/octref/RootIgnore",
    );
    git::clone(&paths::vim_plugins(), "https://github.com/tpope/vim-sleuth");
}

pub fn clean() {
    git::check_all(&paths::repos());
    processes::stop("vim");
    processes::stop("rls");
    processes::stop("node");
    executables::upgrade("brew");
    executables::upgrade("rustup");
    homebrew::upgrade_package("vim");
    homebrew::upgrade_package("git");
    homebrew::upgrade_package("rustup-init");
    homebrew::upgrade_package("node");
    homebrew::clean_artifacts();
    git::pull_all(&paths::vim_plugins());
}

pub fn study() {
    feeds::next();
    exercises::next();
    documents::next();
    notes::next();
}

pub fn generate() {
    public::clean();
    public::build();
    public::configure();
}
<commit_msg>Re-add vim plugin for static analysis integrations to decrease feedback loop time<commit_after>mod documents;
mod executables;
mod exercises;
mod feeds;
mod git;
mod homebrew;
mod notes;
mod paths;
mod processes;
mod public;

pub fn setup() {
    homebrew::install_package("vim");
    homebrew::install_package("node");
    paths::create_dir(&paths::vim_plugins());
    git::clone(
        &paths::vim_plugins(),
        "https://github.com/octref/RootIgnore",
    );
    git::clone(&paths::vim_plugins(), "https://github.com/tpope/vim-sleuth");
    git::clone(
        &paths::vim_plugins(),
        "https://github.com/dense-analysis/ale",
    );
}

pub fn clean() {
    git::check_all(&paths::repos());
    processes::stop("vim");
    processes::stop("rls");
    processes::stop("node");
    executables::upgrade("brew");
    executables::upgrade("rustup");
    homebrew::upgrade_package("vim");
    homebrew::upgrade_package("git");
    homebrew::upgrade_package("rustup-init");
    homebrew::upgrade_package("node");
    homebrew::clean_artifacts();
    git::pull_all(&paths::vim_plugins());
}

pub fn study() {
    feeds::next();
    exercises::next();
    documents::next();
    notes::next();
}

pub fn generate() {
    public::clean();
    public::build();
    public::configure();
}
<|endoftext|>


<commit_before>//! Tools to work with expressions present in format string literals for the `format_args!` family of macros.
//! Primarily meant for assists and completions.

/// Enum for represenging extraced format string args.
/// Can either be extracted expressions (which includes identifiers),
/// or placeholders `{}`.
#[derive(Debug, PartialEq, Eq)]
pub enum Arg {
    Placeholder,
    Ident(String),
    Expr(String),
}

/**
 Add placeholders like `$1` and `$2` in place of [`Arg::Placeholder`],
 and unwraps the [`Arg::Ident`] and [`Arg::Expr`] enums.
 ```rust
 # use ide_db::syntax_helpers::format_string_exprs::*;
 assert_eq!(with_placeholders(vec![Arg::Ident("ident".to_owned()), Arg::Placeholder, Arg::Expr("expr + 2".to_owned())]), vec!["ident".to_owned(), "$1".to_owned(), "expr + 2".to_owned()])
 ```
*/

pub fn with_placeholders(args: Vec<Arg>) -> Vec<String> {
    let mut placeholder_id = 1;
    args.into_iter()
        .map(move |a| match a {
            Arg::Expr(s) | Arg::Ident(s) => s,
            Arg::Placeholder => {
                let s = format!("${placeholder_id}");
                placeholder_id += 1;
                s
            }
        })
        .collect()
}

/**
 Parser for a format-like string. It is more allowing in terms of string contents,
 as we expect variable placeholders to be filled with expressions.

 Built for completions and assists, and escapes `\` and `$` in output.
 (See the comments on `get_receiver_text()` for detail.)
 Splits a format string that may contain expressions
 like
 ```rust
 assert_eq!(parse("{ident} {} {expr + 42} ").unwrap(), ("{} {} {}", vec![Arg::Ident("ident"), Arg::Placeholder, Arg::Expr("expr + 42")]));
 ```
*/
pub fn parse_format_exprs(input: &str) -> Result<(String, Vec<Arg>), ()> {
    #[derive(Debug, Clone, Copy, PartialEq)]
    enum State {
        NotArg,
        MaybeArg,
        Expr,
        Ident,
        MaybeIncorrect,
        FormatOpts,
    }

    let mut state = State::NotArg;
    let mut current_expr = String::new();
    let mut extracted_expressions = Vec::new();
    let mut output = String::new();

    // Count of open braces inside of an expression.
    // We assume that user knows what they're doing, thus we treat it like a correct pattern, e.g.
    // "{MyStruct { val_a: 0, val_b: 1 }}".
    let mut inexpr_open_count = 0;

    let mut chars = input.chars().peekable();
    while let Some(chr) = chars.next() {
        match (state, chr) {
            (State::NotArg, '{') => {
                output.push(chr);
                state = State::MaybeArg;
            }
            (State::NotArg, '}') => {
                output.push(chr);
                state = State::MaybeIncorrect;
            }
            (State::NotArg, _) => {
                if matches!(chr, '\\' | '$') {
                    output.push('\\');
                }
                output.push(chr);
            }
            (State::MaybeIncorrect, '}') => {
                // It's okay, we met "}}".
                output.push(chr);
                state = State::NotArg;
            }
            (State::MaybeIncorrect, _) => {
                // Error in the string.
                return Err(());
            }
            // Escaped braces `{{`
            (State::MaybeArg, '{') => {
                output.push(chr);
                state = State::NotArg;
            }
            (State::MaybeArg, '}') => {
                // This is an empty sequence '{}'.
                output.push(chr);
                extracted_expressions.push(Arg::Placeholder);
                state = State::NotArg;
            },
            (State::MaybeArg, ':') => {
                output.push(chr);
                extracted_expressions.push(Arg::Placeholder);
                state = State::FormatOpts;
            },
            (State::MaybeArg, _) => {
                if matches!(chr, '\\' | '$') {
                    current_expr.push('\\');
                }
                current_expr.push(chr);

                // While Rust uses the unicode sets of XID_start and XID_continue for Identifiers
                // this is probably the best we can do to avoid a false positive
                if chr.is_alphabetic() || chr == '_' {
                    state = State::Ident;
                } else {
                    state = State::Expr;
                }
            },
            (State::Ident | State::Expr, ':') if matches!(chars.peek(), Some(':')) => {
                // path separator
                state = State::Expr;
                current_expr.push_str("::");
                chars.next();
            },
            (State::Ident | State::Expr, ':' | '}') => {
                if inexpr_open_count == 0 {
                    let trimmed = current_expr.trim();

                    // if the expression consists of a single number, like "0" or "12", it can refer to
                    // format args in the order they are specified.
                    // see: https://doc.rust-lang.org/std/fmt/#positional-parameters
                    if trimmed.chars().fold(true, |only_num, c| c.is_ascii_digit() && only_num) {
                        output.push_str(trimmed);
                    } else if matches!(state, State::Expr) {
                        extracted_expressions.push(Arg::Expr(trimmed.into()));
                    } else {
                        extracted_expressions.push(Arg::Ident(trimmed.into()));
                    }

                    output.push(chr);
                    current_expr.clear();
                    state = if chr == ':' {State::FormatOpts} else if chr == '}' {State::NotArg} else {unreachable!()};
                } else if chr == '}' {
                    // We're closing one brace met before inside of the expression.
                    current_expr.push(chr);
                    inexpr_open_count -= 1;
                } else if chr == ':' {
                    // We're inside of braced expression, assume that it's a struct field name/value delimiter.
                    current_expr.push(chr);
                }
            },
            (State::Ident | State::Expr, '{') => {
                state = State::Expr;
                current_expr.push(chr);
                inexpr_open_count += 1;
            }
            (State::Ident | State::Expr, _) => {
                if !(chr.is_alphanumeric() || chr == '_' || chr == '#') {
                    state = State::Expr;
                }

                if matches!(chr, '\\' | '$') {
                    current_expr.push('\\');
                }
                current_expr.push(chr);
            }
            (State::FormatOpts, '}') => {
                output.push(chr);
                state = State::NotArg;
            }
            (State::FormatOpts, _) => {
                if matches!(chr, '\\' | '$') {
                    output.push('\\');
                }
                output.push(chr);
            }
        }
    }

    if state != State::NotArg {
        return Err(());
    }

    Ok((output, extracted_expressions))
}

#[cfg(test)]
mod tests {
    use super::*;
    use expect_test::{expect, Expect};

    fn check(input: &str, expect: &Expect) {
        let (output, exprs) = parse_format_exprs(input).unwrap_or(("-".to_string(), vec![]));
        let outcome_repr = if !exprs.is_empty() {
            format!("{}; {}", output, with_placeholders(exprs).join(", "))
        } else {
            output
        };

        expect.assert_eq(&outcome_repr);
    }

    #[test]
    fn format_str_parser() {
        let test_vector = &[
            ("no expressions", expect![["no expressions"]]),
            (r"no expressions with \$0$1", expect![r"no expressions with \\\$0\$1"]),
            ("{expr} is {2 + 2}", expect![["{} is {}; expr, 2 + 2"]]),
            ("{expr:?}", expect![["{:?}; expr"]]),
            ("{expr:1$}", expect![[r"{:1\$}; expr"]]),
            ("{:1$}", expect![[r"{:1\$}; $1"]]),
            ("{:>padding$}", expect![[r"{:>padding\$}; $1"]]),
            ("{}, {}, {0}", expect![[r"{}, {}, {0}; $1, $2"]]),
            ("{}, {}, {0:b}", expect![[r"{}, {}, {0:b}; $1, $2"]]),
            ("{$0}", expect![[r"{}; \$0"]]),
            ("{malformed", expect![["-"]]),
            ("malformed}", expect![["-"]]),
            ("{{correct", expect![["{{correct"]]),
            ("correct}}", expect![["correct}}"]]),
            ("{correct}}}", expect![["{}}}; correct"]]),
            ("{correct}}}}}", expect![["{}}}}}; correct"]]),
            ("{incorrect}}", expect![["-"]]),
            ("placeholders {} {}", expect![["placeholders {} {}; $1, $2"]]),
            ("mixed {} {2 + 2} {}", expect![["mixed {} {} {}; $1, 2 + 2, $2"]]),
            (
                "{SomeStruct { val_a: 0, val_b: 1 }}",
                expect![["{}; SomeStruct { val_a: 0, val_b: 1 }"]],
            ),
            ("{expr:?} is {2.32f64:.5}", expect![["{:?} is {:.5}; expr, 2.32f64"]]),
            (
                "{SomeStruct { val_a: 0, val_b: 1 }:?}",
                expect![["{:?}; SomeStruct { val_a: 0, val_b: 1 }"]],
            ),
            ("{     2 + 2        }", expect![["{}; 2 + 2"]]),
            ("{strsim::jaro_winkle(a)}", expect![["{}; strsim::jaro_winkle(a)"]]),
            ("{foo::bar::baz()}", expect![["{}; foo::bar::baz()"]]),
            ("{foo::bar():?}", expect![["{:?}; foo::bar()"]]),
        ];

        for (input, output) in test_vector {
            check(input, output)
        }
    }

    #[test]
    fn arg_type() {
        assert_eq!(
            parse_format_exprs("{_ident} {r#raw_ident} {expr.obj} {name {thing: 42} } {}")
                .unwrap()
                .1,
            vec![
                Arg::Ident("_ident".to_owned()),
                Arg::Ident("r#raw_ident".to_owned()),
                Arg::Expr("expr.obj".to_owned()),
                Arg::Expr("name {thing: 42}".to_owned()),
                Arg::Placeholder
            ]
        );
    }
}
<commit_msg>run cargo fmt<commit_after>//! Tools to work with expressions present in format string literals for the `format_args!` family of macros.
//! Primarily meant for assists and completions.

/// Enum for represenging extraced format string args.
/// Can either be extracted expressions (which includes identifiers),
/// or placeholders `{}`.
#[derive(Debug, PartialEq, Eq)]
pub enum Arg {
    Placeholder,
    Ident(String),
    Expr(String),
}

/**
 Add placeholders like `$1` and `$2` in place of [`Arg::Placeholder`],
 and unwraps the [`Arg::Ident`] and [`Arg::Expr`] enums.
 ```rust
 # use ide_db::syntax_helpers::format_string_exprs::*;
 assert_eq!(with_placeholders(vec![Arg::Ident("ident".to_owned()), Arg::Placeholder, Arg::Expr("expr + 2".to_owned())]), vec!["ident".to_owned(), "$1".to_owned(), "expr + 2".to_owned()])
 ```
*/

pub fn with_placeholders(args: Vec<Arg>) -> Vec<String> {
    let mut placeholder_id = 1;
    args.into_iter()
        .map(move |a| match a {
            Arg::Expr(s) | Arg::Ident(s) => s,
            Arg::Placeholder => {
                let s = format!("${placeholder_id}");
                placeholder_id += 1;
                s
            }
        })
        .collect()
}

/**
 Parser for a format-like string. It is more allowing in terms of string contents,
 as we expect variable placeholders to be filled with expressions.

 Built for completions and assists, and escapes `\` and `$` in output.
 (See the comments on `get_receiver_text()` for detail.)
 Splits a format string that may contain expressions
 like
 ```rust
 assert_eq!(parse("{ident} {} {expr + 42} ").unwrap(), ("{} {} {}", vec![Arg::Ident("ident"), Arg::Placeholder, Arg::Expr("expr + 42")]));
 ```
*/
pub fn parse_format_exprs(input: &str) -> Result<(String, Vec<Arg>), ()> {
    #[derive(Debug, Clone, Copy, PartialEq)]
    enum State {
        NotArg,
        MaybeArg,
        Expr,
        Ident,
        MaybeIncorrect,
        FormatOpts,
    }

    let mut state = State::NotArg;
    let mut current_expr = String::new();
    let mut extracted_expressions = Vec::new();
    let mut output = String::new();

    // Count of open braces inside of an expression.
    // We assume that user knows what they're doing, thus we treat it like a correct pattern, e.g.
    // "{MyStruct { val_a: 0, val_b: 1 }}".
    let mut inexpr_open_count = 0;

    let mut chars = input.chars().peekable();
    while let Some(chr) = chars.next() {
        match (state, chr) {
            (State::NotArg, '{') => {
                output.push(chr);
                state = State::MaybeArg;
            }
            (State::NotArg, '}') => {
                output.push(chr);
                state = State::MaybeIncorrect;
            }
            (State::NotArg, _) => {
                if matches!(chr, '\\' | '$') {
                    output.push('\\');
                }
                output.push(chr);
            }
            (State::MaybeIncorrect, '}') => {
                // It's okay, we met "}}".
                output.push(chr);
                state = State::NotArg;
            }
            (State::MaybeIncorrect, _) => {
                // Error in the string.
                return Err(());
            }
            // Escaped braces `{{`
            (State::MaybeArg, '{') => {
                output.push(chr);
                state = State::NotArg;
            }
            (State::MaybeArg, '}') => {
                // This is an empty sequence '{}'.
                output.push(chr);
                extracted_expressions.push(Arg::Placeholder);
                state = State::NotArg;
            }
            (State::MaybeArg, ':') => {
                output.push(chr);
                extracted_expressions.push(Arg::Placeholder);
                state = State::FormatOpts;
            }
            (State::MaybeArg, _) => {
                if matches!(chr, '\\' | '$') {
                    current_expr.push('\\');
                }
                current_expr.push(chr);

                // While Rust uses the unicode sets of XID_start and XID_continue for Identifiers
                // this is probably the best we can do to avoid a false positive
                if chr.is_alphabetic() || chr == '_' {
                    state = State::Ident;
                } else {
                    state = State::Expr;
                }
            }
            (State::Ident | State::Expr, ':') if matches!(chars.peek(), Some(':')) => {
                // path separator
                state = State::Expr;
                current_expr.push_str("::");
                chars.next();
            }
            (State::Ident | State::Expr, ':' | '}') => {
                if inexpr_open_count == 0 {
                    let trimmed = current_expr.trim();

                    // if the expression consists of a single number, like "0" or "12", it can refer to
                    // format args in the order they are specified.
                    // see: https://doc.rust-lang.org/std/fmt/#positional-parameters
                    if trimmed.chars().fold(true, |only_num, c| c.is_ascii_digit() && only_num) {
                        output.push_str(trimmed);
                    } else if matches!(state, State::Expr) {
                        extracted_expressions.push(Arg::Expr(trimmed.into()));
                    } else {
                        extracted_expressions.push(Arg::Ident(trimmed.into()));
                    }

                    output.push(chr);
                    current_expr.clear();
                    state = if chr == ':' {
                        State::FormatOpts
                    } else if chr == '}' {
                        State::NotArg
                    } else {
                        unreachable!()
                    };
                } else if chr == '}' {
                    // We're closing one brace met before inside of the expression.
                    current_expr.push(chr);
                    inexpr_open_count -= 1;
                } else if chr == ':' {
                    // We're inside of braced expression, assume that it's a struct field name/value delimiter.
                    current_expr.push(chr);
                }
            }
            (State::Ident | State::Expr, '{') => {
                state = State::Expr;
                current_expr.push(chr);
                inexpr_open_count += 1;
            }
            (State::Ident | State::Expr, _) => {
                if !(chr.is_alphanumeric() || chr == '_' || chr == '#') {
                    state = State::Expr;
                }

                if matches!(chr, '\\' | '$') {
                    current_expr.push('\\');
                }
                current_expr.push(chr);
            }
            (State::FormatOpts, '}') => {
                output.push(chr);
                state = State::NotArg;
            }
            (State::FormatOpts, _) => {
                if matches!(chr, '\\' | '$') {
                    output.push('\\');
                }
                output.push(chr);
            }
        }
    }

    if state != State::NotArg {
        return Err(());
    }

    Ok((output, extracted_expressions))
}

#[cfg(test)]
mod tests {
    use super::*;
    use expect_test::{expect, Expect};

    fn check(input: &str, expect: &Expect) {
        let (output, exprs) = parse_format_exprs(input).unwrap_or(("-".to_string(), vec![]));
        let outcome_repr = if !exprs.is_empty() {
            format!("{}; {}", output, with_placeholders(exprs).join(", "))
        } else {
            output
        };

        expect.assert_eq(&outcome_repr);
    }

    #[test]
    fn format_str_parser() {
        let test_vector = &[
            ("no expressions", expect![["no expressions"]]),
            (r"no expressions with \$0$1", expect![r"no expressions with \\\$0\$1"]),
            ("{expr} is {2 + 2}", expect![["{} is {}; expr, 2 + 2"]]),
            ("{expr:?}", expect![["{:?}; expr"]]),
            ("{expr:1$}", expect![[r"{:1\$}; expr"]]),
            ("{:1$}", expect![[r"{:1\$}; $1"]]),
            ("{:>padding$}", expect![[r"{:>padding\$}; $1"]]),
            ("{}, {}, {0}", expect![[r"{}, {}, {0}; $1, $2"]]),
            ("{}, {}, {0:b}", expect![[r"{}, {}, {0:b}; $1, $2"]]),
            ("{$0}", expect![[r"{}; \$0"]]),
            ("{malformed", expect![["-"]]),
            ("malformed}", expect![["-"]]),
            ("{{correct", expect![["{{correct"]]),
            ("correct}}", expect![["correct}}"]]),
            ("{correct}}}", expect![["{}}}; correct"]]),
            ("{correct}}}}}", expect![["{}}}}}; correct"]]),
            ("{incorrect}}", expect![["-"]]),
            ("placeholders {} {}", expect![["placeholders {} {}; $1, $2"]]),
            ("mixed {} {2 + 2} {}", expect![["mixed {} {} {}; $1, 2 + 2, $2"]]),
            (
                "{SomeStruct { val_a: 0, val_b: 1 }}",
                expect![["{}; SomeStruct { val_a: 0, val_b: 1 }"]],
            ),
            ("{expr:?} is {2.32f64:.5}", expect![["{:?} is {:.5}; expr, 2.32f64"]]),
            (
                "{SomeStruct { val_a: 0, val_b: 1 }:?}",
                expect![["{:?}; SomeStruct { val_a: 0, val_b: 1 }"]],
            ),
            ("{     2 + 2        }", expect![["{}; 2 + 2"]]),
            ("{strsim::jaro_winkle(a)}", expect![["{}; strsim::jaro_winkle(a)"]]),
            ("{foo::bar::baz()}", expect![["{}; foo::bar::baz()"]]),
            ("{foo::bar():?}", expect![["{:?}; foo::bar()"]]),
        ];

        for (input, output) in test_vector {
            check(input, output)
        }
    }

    #[test]
    fn arg_type() {
        assert_eq!(
            parse_format_exprs("{_ident} {r#raw_ident} {expr.obj} {name {thing: 42} } {}")
                .unwrap()
                .1,
            vec![
                Arg::Ident("_ident".to_owned()),
                Arg::Ident("r#raw_ident".to_owned()),
                Arg::Expr("expr.obj".to_owned()),
                Arg::Expr("name {thing: 42}".to_owned()),
                Arg::Placeholder
            ]
        );
    }
}
<|endoftext|>


<commit_before>pub fn decode_u8(ch:char) -> Option<u8> {
  match ch {
    '0' => Some(0),
    '1' => Some(1),
    '2' => Some(2),
    '3' => Some(3),
    '4' => Some(4),
    '5' => Some(5),
    '6' => Some(6),
    '7' => Some(7),
    '8' => Some(8),
    '9' => Some(9),

    'b' => Some(10),
    'c' => Some(11),
    'd' => Some(12),
    'e' => Some(13),
    'f' => Some(14),
    'g' => Some(15),
    'h' => Some(16),
    'j' => Some(17),
    'k' => Some(18),
    'm' => Some(19),
    'n' => Some(20),
    'p' => Some(21),
    'q' => Some(22),
    'r' => Some(23),
    's' => Some(24),
    't' => Some(25),
    'u' => Some(26),
    'v' => Some(27),
    'w' => Some(28),
    'x' => Some(29),
    'y' => Some(30),
    'z' => Some(31),
    _   => None
  }
}

pub fn decode_tuple(ch:char) -> Option<(bool, bool, bool, bool, bool)> {
  match decode_u8(ch) {
    None     => None,
    Some(ch) => Some((
                is_bit_set(ch, BIT5),
                is_bit_set(ch, BIT4),
                is_bit_set(ch, BIT3),
                is_bit_set(ch, BIT2),
                is_bit_set(ch, BIT1)
                ))
  }
}

pub fn decode_vec(ch:char) -> Option<~[bool]> {
  let decoded_u8 : Option<u8> = decode_u8(ch);
  match decoded_u8 {
    None     => None,
    Some(ch) => Some(~[
                is_bit_set(ch, BIT5),
                is_bit_set(ch, BIT4),
                is_bit_set(ch, BIT3),
                is_bit_set(ch, BIT2),
                is_bit_set(ch, BIT1)
                ])
  }
}

pub fn encode(val:u8) -> Option<char> {
  match val {
    0   => Some('0'),
    1   => Some('1'),
    2   => Some('2'),
    3   => Some('3'),
    4   => Some('4'),
    5   => Some('5'),
    6   => Some('6'),
    7   => Some('7'),
    8   => Some('8'),
    9   => Some('9'),
    10  => Some('b'),
    11  => Some('c'),
    12  => Some('d'),
    13  => Some('e'),
    14  => Some('f'),
    15  => Some('g'),
    16  => Some('h'),
    17  => Some('j'),
    18  => Some('k'),
    19  => Some('m'),
    20  => Some('n'),
    21  => Some('p'),
    22  => Some('q'),
    23  => Some('r'),
    24  => Some('s'),
    25  => Some('t'),
    26  => Some('u'),
    27  => Some('v'),
    28  => Some('w'),
    29  => Some('x'),
    30  => Some('y'),
    31  => Some('z'),
    _   => None
  }
}

static BIT1: u8 = 0b00000001;
static BIT2: u8 = 0b00000010;
static BIT3: u8 = 0b00000100;
static BIT4: u8 = 0b00001000;
static BIT5: u8 = 0b00010000;

fn is_bit_set(byte:u8, position:u8) -> bool {
  (byte & position) > 0
}
<commit_msg>Adds base32::encode_vec and renamed encode to encode_u8<commit_after>pub fn decode_u8(ch:char) -> Option<u8> {
  match ch {
    '0' => Some(0),
    '1' => Some(1),
    '2' => Some(2),
    '3' => Some(3),
    '4' => Some(4),
    '5' => Some(5),
    '6' => Some(6),
    '7' => Some(7),
    '8' => Some(8),
    '9' => Some(9),

    'b' => Some(10),
    'c' => Some(11),
    'd' => Some(12),
    'e' => Some(13),
    'f' => Some(14),
    'g' => Some(15),
    'h' => Some(16),
    'j' => Some(17),
    'k' => Some(18),
    'm' => Some(19),
    'n' => Some(20),
    'p' => Some(21),
    'q' => Some(22),
    'r' => Some(23),
    's' => Some(24),
    't' => Some(25),
    'u' => Some(26),
    'v' => Some(27),
    'w' => Some(28),
    'x' => Some(29),
    'y' => Some(30),
    'z' => Some(31),
    _   => None
  }
}

pub fn decode_tuple(ch:char) -> Option<(bool, bool, bool, bool, bool)> {
  match decode_u8(ch) {
    None     => None,
    Some(ch) => Some((
                is_bit_set(ch, BIT5),
                is_bit_set(ch, BIT4),
                is_bit_set(ch, BIT3),
                is_bit_set(ch, BIT2),
                is_bit_set(ch, BIT1)
                ))
  }
}

pub fn decode_vec(ch:char) -> Option<~[bool]> {
  let decoded_u8 : Option<u8> = decode_u8(ch);
  match decoded_u8 {
    None     => None,
    Some(ch) => Some(~[
                is_bit_set(ch, BIT5),
                is_bit_set(ch, BIT4),
                is_bit_set(ch, BIT3),
                is_bit_set(ch, BIT2),
                is_bit_set(ch, BIT1)
                ])
  }
}

pub fn encode_u8(val:u8) -> Option<char> {
  match val {
    0   => Some('0'),
    1   => Some('1'),
    2   => Some('2'),
    3   => Some('3'),
    4   => Some('4'),
    5   => Some('5'),
    6   => Some('6'),
    7   => Some('7'),
    8   => Some('8'),
    9   => Some('9'),
    10  => Some('b'),
    11  => Some('c'),
    12  => Some('d'),
    13  => Some('e'),
    14  => Some('f'),
    15  => Some('g'),
    16  => Some('h'),
    17  => Some('j'),
    18  => Some('k'),
    19  => Some('m'),
    20  => Some('n'),
    21  => Some('p'),
    22  => Some('q'),
    23  => Some('r'),
    24  => Some('s'),
    25  => Some('t'),
    26  => Some('u'),
    27  => Some('v'),
    28  => Some('w'),
    29  => Some('x'),
    30  => Some('y'),
    31  => Some('z'),
    _   => None
  }
}

pub fn encode_vec(val:&[bool]) -> Option<char> {
  let mut result : u8 = 0b00000000;
  if val[0] { result |= BIT5 }
  if val[1] { result |= BIT4 }
  if val[2] { result |= BIT3 }
  if val[3] { result |= BIT2 }
  if val[4] { result |= BIT1 }

  encode_u8(result)
}

static BIT1: u8 = 0b00000001;
static BIT2: u8 = 0b00000010;
static BIT3: u8 = 0b00000100;
static BIT4: u8 = 0b00001000;
static BIT5: u8 = 0b00010000;

fn is_bit_set(byte:u8, position:u8) -> bool {
  (byte & position) > 0
}
<|endoftext|>


<commit_before>//! Assist for swapping traits inside of a trait bound list
//!
//! E.g. `A + B` => `B + A` when the cursor is placed by the `+` inside of a
//! trait bound list

use hir::db::HirDatabase;
use ra_syntax::{algo::non_trivia_sibling, ast::TypeBoundList, Direction, T};

use crate::{Assist, AssistCtx, AssistId};

/// Flip trait bound assist.
pub(crate) fn flip_trait_bound(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
    // Make sure we're in a `TypeBoundList`
    ctx.node_at_offset::<TypeBoundList>()?;

    // We want to replicate the behavior of `flip_binexpr` by only suggesting
    // the assist when the cursor is on a `+`
    let plus = ctx.token_at_offset().find(|tkn| tkn.kind() == T![+])?;

    let (before, after) = (
        non_trivia_sibling(plus.clone().into(), Direction::Prev)?,
        non_trivia_sibling(plus.clone().into(), Direction::Next)?,
    );

    ctx.add_action(AssistId("flip_trait_bound"), "flip trait bound", |edit| {
        edit.target(plus.text_range());
        edit.replace(before.text_range(), after.to_string());
        edit.replace(after.text_range(), before.to_string());
    });

    ctx.build()
}
<commit_msg>Add tests for the trait bound flip assist.<commit_after>//! Assist for swapping traits inside of a trait bound list
//!
//! E.g. `A + B` => `B + A` when the cursor is placed by the `+` inside of a
//! trait bound list

use hir::db::HirDatabase;
use ra_syntax::{algo::non_trivia_sibling, ast::TypeBoundList, Direction, T};

use crate::{Assist, AssistCtx, AssistId};

/// Flip trait bound assist.
pub(crate) fn flip_trait_bound(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
    // Make sure we're in a `TypeBoundList`
    ctx.node_at_offset::<TypeBoundList>()?;

    // We want to replicate the behavior of `flip_binexpr` by only suggesting
    // the assist when the cursor is on a `+`
    let plus = ctx.token_at_offset().find(|tkn| tkn.kind() == T![+])?;

    let (before, after) = (
        non_trivia_sibling(plus.clone().into(), Direction::Prev)?,
        non_trivia_sibling(plus.clone().into(), Direction::Next)?,
    );

    ctx.add_action(AssistId("flip_trait_bound"), "flip trait bound", |edit| {
        edit.target(plus.text_range());
        edit.replace(before.text_range(), after.to_string());
        edit.replace(after.text_range(), before.to_string());
    });

    ctx.build()
}

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

    use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};

    #[test]
    fn flip_trait_bound_assist_available() {
        check_assist_target(flip_trait_bound, "struct S<T> where T: A <|>+ B + C { }", "+")
    }

    #[test]
    fn flip_trait_bound_not_applicable_for_single_trait_bound() {
        check_assist_not_applicable(flip_trait_bound, "struct S<T> where T: <|>A { }")
    }

    #[test]
    fn flip_trait_bound_works_for_struct() {
        check_assist(
            flip_trait_bound,
            "struct S<T> where T: A <|>+ B { }",
            "struct S<T> where T: B <|>+ A { }",
        )
    }

    #[test]
    fn flip_trait_bound_works_for_trait_impl() {
        check_assist(
            flip_trait_bound,
            "impl X for S<T> where T: A +<|> B { }",
            "impl X for S<T> where T: B +<|> A { }",
        )
    }

    #[test]
    fn flip_trait_bound_works_for_fn() {
        check_assist(flip_trait_bound, "fn f<T: A <|>+ B>(t: T) { }", "fn f<T: B <|>+ A>(t: T) { }")
    }

    #[test]
    fn flip_trait_bound_works_for_fn_where_clause() {
        check_assist(
            flip_trait_bound,
            "fn f<T>(t: T) where T: A +<|> B { }",
            "fn f<T>(t: T) where T: B +<|> A { }",
        )
    }

    #[test]
    fn flip_trait_bound_works_for_lifetime() {
        check_assist(
            flip_trait_bound,
            "fn f<T>(t: T) where T: A <|>+ 'static { }",
            "fn f<T>(t: T) where T: 'static <|>+ A { }",
        )
    }

    #[test]
    fn flip_trait_bound_works_for_complex_bounds() {
        check_assist(
            flip_trait_bound,
            "struct S<T> where T: A<T> <|>+ b_mod::B<T> + C<T> { }",
            "struct S<T> where T: b_mod::B<T> <|>+ A<T> + C<T> { }",
        )
    }

    #[test]
    fn flip_trait_bound_works_for_long_bounds() {
        check_assist(
            flip_trait_bound,
            "struct S<T> where T: A + B + C + D + E + F +<|> G + H + I + J { }",
            "struct S<T> where T: A + B + C + D + E + G +<|> F + H + I + J { }",
        )
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use std::path::PathBuf;

use crate::lsp_runtime_error::{LSPRuntimeError, LSPRuntimeResult};
use common::{SourceLocationKey, Span};
use dashmap::DashMap;
use graphql_syntax::{
    parse_executable_with_error_recovery, ExecutableDefinition, ExecutableDocument, GraphQLSource,
};
use interner::StringKey;
use log::debug;
use lsp_types::{Position, TextDocumentPositionParams, Url};
use relay_compiler::{compiler_state::SourceSet, FileCategorizer, FileGroup};

pub fn extract_executable_definitions_from_text(
    text_document_position: &TextDocumentPositionParams,
    graphql_source_cache: &DashMap<Url, Vec<GraphQLSource>>,
) -> LSPRuntimeResult<Vec<ExecutableDefinition>> {
    let uri = &text_document_position.text_document.uri;

    let graphql_sources = graphql_source_cache
        .get(uri)
        // If the source isn't present in the source cache, then that means that
        // the source has no graphql documents.
        .ok_or(LSPRuntimeError::ExpectedError)?;

    let definitions = graphql_sources
        .iter()
        .map(|graphql_source| {
            let document = parse_executable_with_error_recovery(
                &graphql_source.text,
                SourceLocationKey::standalone(&uri.to_string()),
            )
            .item;

            document.definitions
        })
        .flatten()
        .collect::<Vec<ExecutableDefinition>>();

    Ok(definitions)
}

pub fn extract_project_name_from_url(
    file_categorizer: &FileCategorizer,
    url: &Url,
    root_dir: &PathBuf,
) -> LSPRuntimeResult<StringKey> {
    let absolute_file_path = PathBuf::from(url.path());
    let file_path = absolute_file_path.strip_prefix(root_dir).map_err(|_e| {
        LSPRuntimeError::UnexpectedError(format!(
            "Failed to strip prefix {:?} from {:?}",
            root_dir, absolute_file_path
        ))
    })?;

    let project_name = if let FileGroup::Source { source_set } = file_categorizer
        .categorize(&file_path)
        .ok_or(LSPRuntimeError::ExpectedError)?
    {
        match source_set {
            SourceSet::SourceSetName(source) => source,
            SourceSet::SourceSetNames(sources) => sources[0],
        }
    } else {
        return Err(LSPRuntimeError::UnexpectedError(format!(
            "File path {:?} is not a source set",
            file_path
        )));
    };
    Ok(project_name)
}

/// Return a parsed executable document for this LSP request, only if the request occurs
/// within a GraphQL document.
pub fn extract_executable_document_from_text(
    text_document_position: &TextDocumentPositionParams,
    graphql_source_cache: &DashMap<Url, Vec<GraphQLSource>>,
    file_categorizer: &FileCategorizer,
    root_dir: &PathBuf,
    index_offset: usize,
) -> LSPRuntimeResult<(ExecutableDocument, Span, StringKey)> {
    let uri = &text_document_position.text_document.uri;
    let position = text_document_position.position;

    let graphql_sources = graphql_source_cache
        .get(&uri)
        .ok_or(LSPRuntimeError::ExpectedError)?;

    let graphql_source = graphql_sources
        .iter()
        .find(|graphql_source| {
            let range = graphql_source.to_range();
            position >= range.start && position <= range.end
        })
        .ok_or(LSPRuntimeError::ExpectedError)?;

    let project_name = extract_project_name_from_url(file_categorizer, uri, root_dir)?;

    let document = parse_executable_with_error_recovery(
        &graphql_source.text,
        SourceLocationKey::standalone(&uri.to_string()),
    )
    .item;

    // Now we need to take the `Position` and map that to an offset relative
    // to this GraphQL document, as the `Span`s in the document are relative.
    debug!("Successfully parsed the definitions for a target GraphQL source");
    // Map the position to a zero-length span, relative to this GraphQL source.
    let position_span =
        position_to_span(&position, &graphql_source, index_offset).ok_or_else(|| {
            LSPRuntimeError::UnexpectedError("Failed to map positions to spans".to_string())
        })?;

    // Now we need to walk the Document, tracking our path along the way, until
    // we find the position within the document. Note that the GraphQLSource will
    // already be updated *with the characters that triggered the completion request*
    // since the change event fires before completion.
    debug!("position_span: {:?}", position_span);

    Ok((document, position_span, project_name))
}

/// Maps the LSP `Position` type back to a relative span, so we can find out which syntax node(s)
/// this request came from
pub(crate) fn position_to_span(
    position: &Position,
    source: &GraphQLSource,
    index_offset: usize,
) -> Option<Span> {
    position_to_offset(position, index_offset, source.line_index, &source.text)
        .map(|offset| Span::new(offset, offset))
}

pub fn position_to_offset(
    position: &Position,
    index_offset: usize,
    line_index: usize,
    text: &str,
) -> Option<u32> {
    let mut index_of_first_character_of_current_line = 0;
    let mut line_index = line_index as u32;

    let mut chars = text.chars().enumerate().peekable();

    while let Some((index, chr)) = chars.next() {
        let is_newline = match chr {
            // Line terminators: https://www.ecma-international.org/ecma-262/#sec-line-terminators
            '\u{000A}' | '\u{000D}' | '\u{2028}' | '\u{2029}' => {
                !matches!((chr, chars.peek()), ('\u{000D}', Some((_, '\u{000D}'))))
            }
            _ => false,
        };

        if is_newline {
            line_index += 1;
            // Add index_offset to account for different position index between hover and autocomplete
            index_of_first_character_of_current_line = index + index_offset;
        }

        if line_index == position.line {
            let start_offset =
                (index_of_first_character_of_current_line + position.character as usize) as u32;
            return Some(start_offset);
        }
    }
    None
}

#[derive(Debug)]
pub(crate) struct SameLineOffset {
    character_offset: u32,
}

#[derive(Debug)]
pub(crate) struct DifferentLineOffset {
    line_offset: u32,
    character: u32,
}

/// Represents the offset from a given position to another position.
/// The SameLineOffset variant represents moving to a later character
/// position on the same line. The NewPositionOffset represents moving to
/// a later line, and an arbitrary character position.
#[derive(Debug)]
pub(crate) enum PositionOffset {
    SameLineOffset(SameLineOffset),
    DifferentLineOffset(DifferentLineOffset),
}

impl std::ops::Add<PositionOffset> for Position {
    type Output = Self;

    fn add(self, offset: PositionOffset) -> Self::Output {
        match offset {
            PositionOffset::SameLineOffset(SameLineOffset { character_offset }) => Position {
                line: self.line,
                character: self.character + character_offset,
            },
            PositionOffset::DifferentLineOffset(DifferentLineOffset {
                line_offset,
                character,
            }) => Position {
                line: self.line + line_offset,
                character,
            },
        }
    }
}

#[derive(Debug)]
pub(crate) struct RangeOffset {
    pub start: PositionOffset,
    pub end: PositionOffset,
}

/// Returns a RangeOffset that represents the offset from the start
/// of the source to the contents of the span.
pub(crate) fn span_to_range_offset(span: Span, text: &str) -> Option<RangeOffset> {
    if text.len() < span.end as usize {
        return None;
    }

    let mut start_position_offset = None;
    let mut end_position_offset = None;
    let Span { start, end } = span;
    let span_start = start;
    let span_end = end;
    let mut characters_iterated = 0u32;

    // For each line, determine whether the start and end of the span
    // occur on that line.
    for (line_index, line) in text.lines().enumerate() {
        let line_length = line.len() as u32;
        if start_position_offset.is_none() && characters_iterated + line_length >= span_start {
            start_position_offset = Some(if line_index == 0 {
                PositionOffset::SameLineOffset(SameLineOffset {
                    character_offset: span_start,
                })
            } else {
                PositionOffset::DifferentLineOffset(DifferentLineOffset {
                    line_offset: line_index as u32,
                    character: span_start - characters_iterated,
                })
            });
        }
        if end_position_offset.is_none() && characters_iterated + line_length >= span_end {
            end_position_offset = Some(if line_index == 0 {
                PositionOffset::SameLineOffset(SameLineOffset {
                    character_offset: span_end,
                })
            } else {
                PositionOffset::DifferentLineOffset(DifferentLineOffset {
                    line_offset: line_index as u32,
                    character: span_end - characters_iterated,
                })
            });
            break;
        }
        characters_iterated += line_length;
        // we also need to advance characters_iterated by 1 to account for the line break
        characters_iterated += 1;
    }

    Some(RangeOffset {
        start: start_position_offset?,
        end: end_position_offset?,
    })
}
<commit_msg>Make `position_to_span` private<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use std::path::PathBuf;

use crate::lsp_runtime_error::{LSPRuntimeError, LSPRuntimeResult};
use common::{SourceLocationKey, Span};
use dashmap::DashMap;
use graphql_syntax::{
    parse_executable_with_error_recovery, ExecutableDefinition, ExecutableDocument, GraphQLSource,
};
use interner::StringKey;
use log::debug;
use lsp_types::{Position, TextDocumentPositionParams, Url};
use relay_compiler::{compiler_state::SourceSet, FileCategorizer, FileGroup};

pub fn extract_executable_definitions_from_text(
    text_document_position: &TextDocumentPositionParams,
    graphql_source_cache: &DashMap<Url, Vec<GraphQLSource>>,
) -> LSPRuntimeResult<Vec<ExecutableDefinition>> {
    let uri = &text_document_position.text_document.uri;

    let graphql_sources = graphql_source_cache
        .get(uri)
        // If the source isn't present in the source cache, then that means that
        // the source has no graphql documents.
        .ok_or(LSPRuntimeError::ExpectedError)?;

    let definitions = graphql_sources
        .iter()
        .map(|graphql_source| {
            let document = parse_executable_with_error_recovery(
                &graphql_source.text,
                SourceLocationKey::standalone(&uri.to_string()),
            )
            .item;

            document.definitions
        })
        .flatten()
        .collect::<Vec<ExecutableDefinition>>();

    Ok(definitions)
}

pub fn extract_project_name_from_url(
    file_categorizer: &FileCategorizer,
    url: &Url,
    root_dir: &PathBuf,
) -> LSPRuntimeResult<StringKey> {
    let absolute_file_path = PathBuf::from(url.path());
    let file_path = absolute_file_path.strip_prefix(root_dir).map_err(|_e| {
        LSPRuntimeError::UnexpectedError(format!(
            "Failed to strip prefix {:?} from {:?}",
            root_dir, absolute_file_path
        ))
    })?;

    let project_name = if let FileGroup::Source { source_set } = file_categorizer
        .categorize(&file_path)
        .ok_or(LSPRuntimeError::ExpectedError)?
    {
        match source_set {
            SourceSet::SourceSetName(source) => source,
            SourceSet::SourceSetNames(sources) => sources[0],
        }
    } else {
        return Err(LSPRuntimeError::UnexpectedError(format!(
            "File path {:?} is not a source set",
            file_path
        )));
    };
    Ok(project_name)
}

/// Return a parsed executable document for this LSP request, only if the request occurs
/// within a GraphQL document.
pub fn extract_executable_document_from_text(
    text_document_position: &TextDocumentPositionParams,
    graphql_source_cache: &DashMap<Url, Vec<GraphQLSource>>,
    file_categorizer: &FileCategorizer,
    root_dir: &PathBuf,
    index_offset: usize,
) -> LSPRuntimeResult<(ExecutableDocument, Span, StringKey)> {
    let uri = &text_document_position.text_document.uri;
    let position = text_document_position.position;

    let graphql_sources = graphql_source_cache
        .get(&uri)
        .ok_or(LSPRuntimeError::ExpectedError)?;

    let graphql_source = graphql_sources
        .iter()
        .find(|graphql_source| {
            let range = graphql_source.to_range();
            position >= range.start && position <= range.end
        })
        .ok_or(LSPRuntimeError::ExpectedError)?;

    let project_name = extract_project_name_from_url(file_categorizer, uri, root_dir)?;

    let document = parse_executable_with_error_recovery(
        &graphql_source.text,
        SourceLocationKey::standalone(&uri.to_string()),
    )
    .item;

    // Now we need to take the `Position` and map that to an offset relative
    // to this GraphQL document, as the `Span`s in the document are relative.
    debug!("Successfully parsed the definitions for a target GraphQL source");
    // Map the position to a zero-length span, relative to this GraphQL source.
    let position_span =
        position_to_span(&position, &graphql_source, index_offset).ok_or_else(|| {
            LSPRuntimeError::UnexpectedError("Failed to map positions to spans".to_string())
        })?;

    // Now we need to walk the Document, tracking our path along the way, until
    // we find the position within the document. Note that the GraphQLSource will
    // already be updated *with the characters that triggered the completion request*
    // since the change event fires before completion.
    debug!("position_span: {:?}", position_span);

    Ok((document, position_span, project_name))
}

/// Maps the LSP `Position` type back to a relative span, so we can find out which syntax node(s)
/// this request came from
fn position_to_span(
    position: &Position,
    source: &GraphQLSource,
    index_offset: usize,
) -> Option<Span> {
    position_to_offset(position, index_offset, source.line_index, &source.text)
        .map(|offset| Span::new(offset, offset))
}

/// Find a character position in the GraphQL source text
/// from the Position (line, character) of the cursor in the IDE.
/// If the Position is outside of the source text, return None.
pub fn position_to_offset(
    position: &Position,
    index_offset: usize,
    line_index: usize,
    graphql_source_text: &str,
) -> Option<u32> {
    let mut index_of_first_character_of_current_line = 0;
    let mut line_index = line_index as u32;

    let mut chars = graphql_source_text.chars().enumerate().peekable();

    while let Some((index, chr)) = chars.next() {
        let is_newline = match chr {
            // Line terminators: https://www.ecma-international.org/ecma-262/#sec-line-terminators
            '\u{000A}' | '\u{000D}' | '\u{2028}' | '\u{2029}' => {
                !matches!((chr, chars.peek()), ('\u{000D}', Some((_, '\u{000D}'))))
            }
            _ => false,
        };

        if is_newline {
            line_index += 1;
            // Add index_offset to account for different position index between hover and autocomplete
            index_of_first_character_of_current_line = index + index_offset;
        }

        if line_index == position.line {
            let start_offset =
                (index_of_first_character_of_current_line + position.character as usize) as u32;
            return Some(start_offset);
        }
    }
    None
}

#[derive(Debug)]
pub(crate) struct SameLineOffset {
    character_offset: u32,
}

#[derive(Debug)]
pub(crate) struct DifferentLineOffset {
    line_offset: u32,
    character: u32,
}

/// Represents the offset from a given position to another position.
/// The SameLineOffset variant represents moving to a later character
/// position on the same line. The NewPositionOffset represents moving to
/// a later line, and an arbitrary character position.
#[derive(Debug)]
pub(crate) enum PositionOffset {
    SameLineOffset(SameLineOffset),
    DifferentLineOffset(DifferentLineOffset),
}

impl std::ops::Add<PositionOffset> for Position {
    type Output = Self;

    fn add(self, offset: PositionOffset) -> Self::Output {
        match offset {
            PositionOffset::SameLineOffset(SameLineOffset { character_offset }) => Position {
                line: self.line,
                character: self.character + character_offset,
            },
            PositionOffset::DifferentLineOffset(DifferentLineOffset {
                line_offset,
                character,
            }) => Position {
                line: self.line + line_offset,
                character,
            },
        }
    }
}

#[derive(Debug)]
pub(crate) struct RangeOffset {
    pub start: PositionOffset,
    pub end: PositionOffset,
}

/// Returns a RangeOffset that represents the offset from the start
/// of the source to the contents of the span.
pub(crate) fn span_to_range_offset(span: Span, text: &str) -> Option<RangeOffset> {
    if text.len() < span.end as usize {
        return None;
    }

    let mut start_position_offset = None;
    let mut end_position_offset = None;
    let Span { start, end } = span;
    let span_start = start;
    let span_end = end;
    let mut characters_iterated = 0u32;

    // For each line, determine whether the start and end of the span
    // occur on that line.
    for (line_index, line) in text.lines().enumerate() {
        let line_length = line.len() as u32;
        if start_position_offset.is_none() && characters_iterated + line_length >= span_start {
            start_position_offset = Some(if line_index == 0 {
                PositionOffset::SameLineOffset(SameLineOffset {
                    character_offset: span_start,
                })
            } else {
                PositionOffset::DifferentLineOffset(DifferentLineOffset {
                    line_offset: line_index as u32,
                    character: span_start - characters_iterated,
                })
            });
        }
        if end_position_offset.is_none() && characters_iterated + line_length >= span_end {
            end_position_offset = Some(if line_index == 0 {
                PositionOffset::SameLineOffset(SameLineOffset {
                    character_offset: span_end,
                })
            } else {
                PositionOffset::DifferentLineOffset(DifferentLineOffset {
                    line_offset: line_index as u32,
                    character: span_end - characters_iterated,
                })
            });
            break;
        }
        characters_iterated += line_length;
        // we also need to advance characters_iterated by 1 to account for the line break
        characters_iterated += 1;
    }

    Some(RangeOffset {
        start: start_position_offset?,
        end: end_position_offset?,
    })
}
<|endoftext|>


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

//! A shareable mutable container for the DOM.

use crate::dom::bindings::root::{assert_in_layout, assert_in_script};
#[cfg(feature = "refcell_backtrace")]
pub use accountable_refcell::{ref_filter_map, Ref, RefCell, RefMut};
#[cfg(not(feature = "refcell_backtrace"))]
pub use ref_filter_map::ref_filter_map;
use std::cell::{BorrowError, BorrowMutError};
#[cfg(not(feature = "refcell_backtrace"))]
pub use std::cell::{Ref, RefCell, RefMut};

/// A mutable field in the DOM.
///
/// This extends the API of `std::cell::RefCell` to allow unsafe access in
/// certain situations, with dynamic checking in debug builds.
#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq)]
pub struct DomRefCell<T> {
    value: RefCell<T>,
}

// Functionality specific to Servo's `DomRefCell` type
// ===================================================

impl<T> DomRefCell<T> {
    /// Return a reference to the contents.
    ///
    /// For use in the layout thread only.
    #[allow(unsafe_code)]
    pub unsafe fn borrow_for_layout(&self) -> &T {
        assert_in_layout();
        self.value
            .try_borrow_unguarded()
            .expect("cell is mutably borrowed")
    }

    /// Borrow the contents for the purpose of script deallocation.
    ///
    #[allow(unsafe_code)]
    pub unsafe fn borrow_for_script_deallocation(&self) -> &mut T {
        assert_in_script();
        &mut *self.value.as_ptr()
    }

    /// Mutably borrow a cell for layout. Ideally this would use
    /// `RefCell::try_borrow_mut_unguarded` but that doesn't exist yet.
    #[allow(unsafe_code)]
    pub unsafe fn borrow_mut_for_layout(&self) -> &mut T {
        assert_in_layout();
        &mut *self.value.as_ptr()
    }
}

// Functionality duplicated with `std::cell::RefCell`
// ===================================================
impl<T> DomRefCell<T> {
    /// Create a new `DomRefCell` containing `value`.
    pub fn new(value: T) -> DomRefCell<T> {
        DomRefCell {
            value: RefCell::new(value),
        }
    }

    /// Immutably borrows the wrapped value.
    ///
    /// The borrow lasts until the returned `Ref` exits scope. Multiple
    /// immutable borrows can be taken out at the same time.
    ///
    /// # Panics
    ///
    /// Panics if this is called off the script thread.
    ///
    /// Panics if the value is currently mutably borrowed.
    pub fn borrow(&self) -> Ref<T> {
        self.try_borrow()
            .expect("DomRefCell<T> already mutably borrowed")
    }

    /// Mutably borrows the wrapped value.
    ///
    /// The borrow lasts until the returned `RefMut` exits scope. The value
    /// cannot be borrowed while this borrow is active.
    ///
    /// # Panics
    ///
    /// Panics if this is called off the script thread.
    ///
    /// Panics if the value is currently borrowed.
    pub fn borrow_mut(&self) -> RefMut<T> {
        self.try_borrow_mut()
            .expect("DomRefCell<T> already borrowed")
    }

    /// Attempts to immutably borrow the wrapped value.
    ///
    /// The borrow lasts until the returned `Ref` exits scope. Multiple
    /// immutable borrows can be taken out at the same time.
    ///
    /// Returns `None` if the value is currently mutably borrowed.
    ///
    /// # Panics
    ///
    /// Panics if this is called off the script thread.
    pub fn try_borrow(&self) -> Result<Ref<T>, BorrowError> {
        assert_in_script();
        self.value.try_borrow()
    }

    /// Mutably borrows the wrapped value.
    ///
    /// The borrow lasts until the returned `RefMut` exits scope. The value
    /// cannot be borrowed while this borrow is active.
    ///
    /// Returns `None` if the value is currently borrowed.
    ///
    /// # Panics
    ///
    /// Panics if this is called off the script thread.
    pub fn try_borrow_mut(&self) -> Result<RefMut<T>, BorrowMutError> {
        assert_in_script();
        self.value.try_borrow_mut()
    }
}
<commit_msg>Fix refcell_backtrace feature.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

//! A shareable mutable container for the DOM.

use crate::dom::bindings::root::{assert_in_layout, assert_in_script};
#[cfg(feature = "refcell_backtrace")]
pub use accountable_refcell::{ref_filter_map, Ref, RefCell, RefMut};
#[cfg(not(feature = "refcell_backtrace"))]
pub use ref_filter_map::ref_filter_map;
use std::cell::{BorrowError, BorrowMutError};
#[cfg(not(feature = "refcell_backtrace"))]
pub use std::cell::{Ref, RefCell, RefMut};

/// A mutable field in the DOM.
///
/// This extends the API of `std::cell::RefCell` to allow unsafe access in
/// certain situations, with dynamic checking in debug builds.
#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq)]
pub struct DomRefCell<T> {
    value: RefCell<T>,
}

// Functionality specific to Servo's `DomRefCell` type
// ===================================================

impl<T> DomRefCell<T> {
    /// Return a reference to the contents.
    ///
    /// For use in the layout thread only.
    #[allow(unsafe_code)]
    pub unsafe fn borrow_for_layout(&self) -> &T {
        assert_in_layout();
        self.value
            .try_borrow_unguarded()
            .expect("cell is mutably borrowed")
    }

    /// Borrow the contents for the purpose of script deallocation.
    ///
    #[allow(unsafe_code)]
    pub unsafe fn borrow_for_script_deallocation(&self) -> &mut T {
        assert_in_script();
        &mut *self.value.as_ptr()
    }

    /// Mutably borrow a cell for layout. Ideally this would use
    /// `RefCell::try_borrow_mut_unguarded` but that doesn't exist yet.
    #[allow(unsafe_code)]
    pub unsafe fn borrow_mut_for_layout(&self) -> &mut T {
        assert_in_layout();
        &mut *self.value.as_ptr()
    }
}

// Functionality duplicated with `std::cell::RefCell`
// ===================================================
impl<T> DomRefCell<T> {
    /// Create a new `DomRefCell` containing `value`.
    pub fn new(value: T) -> DomRefCell<T> {
        DomRefCell {
            value: RefCell::new(value),
        }
    }

    /// Immutably borrows the wrapped value.
    ///
    /// The borrow lasts until the returned `Ref` exits scope. Multiple
    /// immutable borrows can be taken out at the same time.
    ///
    /// # Panics
    ///
    /// Panics if this is called off the script thread.
    ///
    /// Panics if the value is currently mutably borrowed.
    pub fn borrow(&self) -> Ref<T> {
        self.value.borrow()
    }

    /// Mutably borrows the wrapped value.
    ///
    /// The borrow lasts until the returned `RefMut` exits scope. The value
    /// cannot be borrowed while this borrow is active.
    ///
    /// # Panics
    ///
    /// Panics if this is called off the script thread.
    ///
    /// Panics if the value is currently borrowed.
    pub fn borrow_mut(&self) -> RefMut<T> {
        self.value.borrow_mut()
    }

    /// Attempts to immutably borrow the wrapped value.
    ///
    /// The borrow lasts until the returned `Ref` exits scope. Multiple
    /// immutable borrows can be taken out at the same time.
    ///
    /// Returns `None` if the value is currently mutably borrowed.
    ///
    /// # Panics
    ///
    /// Panics if this is called off the script thread.
    pub fn try_borrow(&self) -> Result<Ref<T>, BorrowError> {
        assert_in_script();
        self.value.try_borrow()
    }

    /// Mutably borrows the wrapped value.
    ///
    /// The borrow lasts until the returned `RefMut` exits scope. The value
    /// cannot be borrowed while this borrow is active.
    ///
    /// Returns `None` if the value is currently borrowed.
    ///
    /// # Panics
    ///
    /// Panics if this is called off the script thread.
    pub fn try_borrow_mut(&self) -> Result<RefMut<T>, BorrowMutError> {
        assert_in_script();
        self.value.try_borrow_mut()
    }
}
<|endoftext|>


<commit_before>#![feature(question_mark)]
#[macro_use]
extern crate rustfbp;
extern crate capnp;

component! {
    shells_lain_flow, contracts(generic_text, list_text)
    inputs(input: list_text),
    inputs_array(),
    outputs(output: generic_text),
    outputs_array(),
    option(),
    acc(),
    fn run(&mut self) -> Result<()> {
        let mut ip_input = self.ports.recv("input")?;
        let input = {
            let input_reader: list_text::Reader = ip_input.get_root()?;
            input_reader.get_texts()
        };

        let mut out_ip_output = IP::new();
        {
          let mut variable = out_ip_output.init_root::<generic_text::Builder>();
          variable.set_text("generated nix subnet code!");
        }
        self.ports.send("output", out_ip_output)?;
        Ok(())
    }
}
<commit_msg>Problem: Lain didn't generate flowscript<commit_after>#![feature(question_mark)]
#[macro_use]
extern crate rustfbp;
extern crate capnp;

component! {
    shells_lain_flow, contracts(generic_text, list_text)
    inputs(input: list_text),
    inputs_array(),
    outputs(output: generic_text),
    outputs_array(),
    option(),
    acc(),
    fn run(&mut self) -> Result<()> {
        let mut ip_input = self.ports.recv("input")?;
        let mut flow = String::from("");
        let input_reader: list_text::Reader = ip_input.get_root()?;
        let mut cmd_iterator = input_reader.get_texts()?;
        let mut count = cmd_iterator.iter().count();
        let mut i :usize = 0;
        for cmd in cmd_iterator.iter() {
            if count == 1 {
                flow.push_str(format!("{}({})", cmd?, cmd?).as_str());
            } else {
                if count > 1 && i == 0 {
                    flow.push_str(format!("{}({}) output -> ", cmd?, cmd?).as_str());
                } else {
                    if (count - 1) == i {
                        flow.push_str(format!("input {}({})", cmd?, cmd?).as_str());
                    } else {
                        flow.push_str(format!("input {}({}) output -> ", cmd?, cmd?).as_str());
                    }
                }
            }
            i += 1;
        }
        let mut out_ip_output = IP::new();
        {
            let mut variable = out_ip_output.init_root::<generic_text::Builder>();
            variable.set_text(flow.as_str());
        }
        self.ports.send("output", out_ip_output)?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::marker;

use super::select_query;
use super::from;
use super::predicate;
use super::expression;

pub trait Deletable<M>: from::Table + marker::PhantomFn<M> + Sized {
    fn delete(&self) -> DeleteQuery<(), select_query::NoResult, M> {
        DeleteQuery::new(self)
    }
}

macro_rules! returning_for {
    ($query:ident) => (
        impl<T, L, M> $query<T, L, M> {
            pub fn returning_1<R: Clone>(mut self, field: &$crate::expression::Expression<R>) -> $query<(R), $crate::select_query::LimitMany, M> {
                self.returning = Some($crate::select_query::Select::Only(vec![field.upcast_expression()]));
                unsafe{ mem::transmute(self) }
            }

            pub fn returning_2<R1: Clone, R2: Clone>(mut self, field1: &$crate::expression::Expression<R1>, field2: &$crate::expression::Expression<R2>) -> $query<(R1, R2), $crate::select_query::LimitMany, M> {
                self.returning = Some($crate::select_query::Select::Only(vec![field1.upcast_expression(), field2.upcast_expression()]));
                unsafe{ mem::transmute(self) }
            }

            pub fn returning(mut self, fields: &[&$crate::expression::UntypedExpression]) -> $query<(), $crate::select_query::LimitMany, M> {
                self.returning = Some($crate::select_query::Select::Only(fields.iter().map(|f| f.upcast_expression()).collect()));
                unsafe{ mem::transmute(self) }
            }

            pub fn returning_all(mut self) -> $query<(), $crate::select_query::LimitMany, M> {
                self.returning = Some($crate::select_query::Select::All);
                unsafe{ mem::transmute(self) }
            }

            pub fn no_returning(mut self) -> $query<(), $crate::select_query::NoResult, M> {
                self.returning = None;
                unsafe{ mem::transmute(self) }
            }
        }
    )
}

#[derive(Clone)]
pub struct DeleteQuery<T, L, M> {
    only: bool,
    all: bool,
    table: from::SharedTable,
    using: Option<Vec<from::SharedFrom>>,
    where_: Option<predicate::SharedPredicate>,
    returning: Option<select_query::Select>,

    _marker_t: marker::PhantomData<T>,
    _marker_l: marker::PhantomData<L>,
    _marker_m: marker::PhantomData<M>,
}

impl<T, L, M> DeleteQuery<T, L, M> {

    pub fn is_only(&self) -> bool { self.only }
    pub fn is_all(&self) -> bool { self.all }
    pub fn get_table(&self) -> &from::SharedTable { &self.table }
    pub fn get_using(&self) -> &Option<Vec<from::SharedFrom>> { &self.using }
    pub fn get_where(&self) -> &Option<predicate::SharedPredicate> { &self.where_ }
    pub fn get_returning(&self) -> &Option<select_query::Select> { &self.returning }

    pub fn new(table: &from::Table) -> DeleteQuery<T, L, M> {
        DeleteQuery {
            only: false,
            table: table.upcast_table(),
            using: None,
            where_: None,
            all: false,
            returning: None,

            _marker_t: marker::PhantomData,
            _marker_l: marker::PhantomData,
            _marker_m: marker::PhantomData,
        }
    }

    pub fn only(mut self) -> DeleteQuery<T, L, M> {
        self.only = true;
        self
    }

    pub fn using(mut self, using: &from::From) -> DeleteQuery<T, L, M> {
        if self.using.is_none() {
            self.using = Some(vec![])
        }

        self.using.as_mut().unwrap().push(using.upcast_from());
        self
    }

    pub fn all(mut self) -> DeleteQuery<T, L, M> {
        self.where_ = None;
        self.all = true;
        self
    }
}

returning_for!(DeleteQuery);

impl<T:Clone, L:Clone, M:Clone> select_query::Queryable for DeleteQuery<T, L, M> {
    fn get_where(&self) -> &Option<predicate::SharedPredicate> { &self.where_ }
    fn set_where(&mut self, predicate: predicate::SharedPredicate) { self.where_ = Some(predicate); }
    fn unset_where(&mut self) { self.where_ = None; }
}

<commit_msg>refactor(rustup): remove unused import<commit_after>use std::mem;
use std::marker;

use super::select_query;
use super::from;
use super::predicate;

pub trait Deletable<M>: from::Table + marker::PhantomFn<M> + Sized {
    fn delete(&self) -> DeleteQuery<(), select_query::NoResult, M> {
        DeleteQuery::new(self)
    }
}

macro_rules! returning_for {
    ($query:ident) => (
        impl<T, L, M> $query<T, L, M> {
            pub fn returning_1<R: Clone>(mut self, field: &$crate::expression::Expression<R>) -> $query<(R), $crate::select_query::LimitMany, M> {
                self.returning = Some($crate::select_query::Select::Only(vec![field.upcast_expression()]));
                unsafe{ mem::transmute(self) }
            }

            pub fn returning_2<R1: Clone, R2: Clone>(mut self, field1: &$crate::expression::Expression<R1>, field2: &$crate::expression::Expression<R2>) -> $query<(R1, R2), $crate::select_query::LimitMany, M> {
                self.returning = Some($crate::select_query::Select::Only(vec![field1.upcast_expression(), field2.upcast_expression()]));
                unsafe{ mem::transmute(self) }
            }

            pub fn returning(mut self, fields: &[&$crate::expression::UntypedExpression]) -> $query<(), $crate::select_query::LimitMany, M> {
                self.returning = Some($crate::select_query::Select::Only(fields.iter().map(|f| f.upcast_expression()).collect()));
                unsafe{ mem::transmute(self) }
            }

            pub fn returning_all(mut self) -> $query<(), $crate::select_query::LimitMany, M> {
                self.returning = Some($crate::select_query::Select::All);
                unsafe{ mem::transmute(self) }
            }

            pub fn no_returning(mut self) -> $query<(), $crate::select_query::NoResult, M> {
                self.returning = None;
                unsafe{ mem::transmute(self) }
            }
        }
    )
}

#[derive(Clone)]
pub struct DeleteQuery<T, L, M> {
    only: bool,
    all: bool,
    table: from::SharedTable,
    using: Option<Vec<from::SharedFrom>>,
    where_: Option<predicate::SharedPredicate>,
    returning: Option<select_query::Select>,

    _marker_t: marker::PhantomData<T>,
    _marker_l: marker::PhantomData<L>,
    _marker_m: marker::PhantomData<M>,
}

impl<T, L, M> DeleteQuery<T, L, M> {

    pub fn is_only(&self) -> bool { self.only }
    pub fn is_all(&self) -> bool { self.all }
    pub fn get_table(&self) -> &from::SharedTable { &self.table }
    pub fn get_using(&self) -> &Option<Vec<from::SharedFrom>> { &self.using }
    pub fn get_where(&self) -> &Option<predicate::SharedPredicate> { &self.where_ }
    pub fn get_returning(&self) -> &Option<select_query::Select> { &self.returning }

    pub fn new(table: &from::Table) -> DeleteQuery<T, L, M> {
        DeleteQuery {
            only: false,
            table: table.upcast_table(),
            using: None,
            where_: None,
            all: false,
            returning: None,

            _marker_t: marker::PhantomData,
            _marker_l: marker::PhantomData,
            _marker_m: marker::PhantomData,
        }
    }

    pub fn only(mut self) -> DeleteQuery<T, L, M> {
        self.only = true;
        self
    }

    pub fn using(mut self, using: &from::From) -> DeleteQuery<T, L, M> {
        if self.using.is_none() {
            self.using = Some(vec![])
        }

        self.using.as_mut().unwrap().push(using.upcast_from());
        self
    }

    pub fn all(mut self) -> DeleteQuery<T, L, M> {
        self.where_ = None;
        self.all = true;
        self
    }
}

returning_for!(DeleteQuery);

impl<T:Clone, L:Clone, M:Clone> select_query::Queryable for DeleteQuery<T, L, M> {
    fn get_where(&self) -> &Option<predicate::SharedPredicate> { &self.where_ }
    fn set_where(&mut self, predicate: predicate::SharedPredicate) { self.where_ = Some(predicate); }
    fn unset_where(&mut self) { self.where_ = None; }
}

<|endoftext|>


<commit_before>extern crate clock;

use clock::Clock;

//
// Clock Creation
//

#[test]
fn test_on_the_hour() {
    assert_eq!(Clock::new(8, 0).to_string(), "08:00");
}

#[test]
#[ignore]
fn test_past_the_hour() {
    assert_eq!(Clock::new(11, 9).to_string(), "11:09");
}

#[test]
#[ignore]
fn test_midnight_is_zero_hours() {
    assert_eq!(Clock::new(24, 0).to_string(), "00:00");
}

#[test]
#[ignore]
fn test_hour_rolls_over() {
    assert_eq!(Clock::new(25, 0).to_string(), "01:00");
}

#[test]
#[ignore]
fn test_hour_rolls_over_continuously() {
    assert_eq!(Clock::new(100, 0).to_string(), "04:00");
}

#[test]
#[ignore]
fn test_sixty_minutes_is_next_hour() {
    assert_eq!(Clock::new(1, 60).to_string(), "02:00");
}

#[test]
#[ignore]
fn test_minutes_roll_over() {
    assert_eq!(Clock::new(0, 160).to_string(), "02:40");
}

#[test]
#[ignore]
fn test_minutes_roll_over_continuously() {
    assert_eq!(Clock::new(0, 1723).to_string(), "04:43");
}

#[test]
#[ignore]
fn test_hours_and_minutes_roll_over() {
    assert_eq!(Clock::new(25, 160).to_string(), "03:40");
}

#[test]
#[ignore]
fn test_hours_and_minutes_roll_over_continuously() {
    assert_eq!(Clock::new(201, 3001).to_string(), "11:01");
}

#[test]
#[ignore]
fn test_hours_and_minutes_roll_over_to_exactly_midnight() {
    assert_eq!(Clock::new(72, 8640).to_string(), "00:00");
}

#[test]
#[ignore]
fn test_negative_hour() {
    assert_eq!(Clock::new(-1, 15).to_string(), "23:15");
}

#[test]
#[ignore]
fn test_negative_hour_roll_over() {
    assert_eq!(Clock::new(-25, 00).to_string(), "23:00");
}

#[test]
#[ignore]
fn test_negative_hour_roll_over_continuously() {
    assert_eq!(Clock::new(-91, 00).to_string(), "05:00");
}

#[test]
#[ignore]
fn test_negative_minutes() {
    assert_eq!(Clock::new(1, -40).to_string(), "00:20");
}

#[test]
#[ignore]
fn test_negative_minutes_roll_over() {
    assert_eq!(Clock::new(1, -160).to_string(), "22:20");
}

#[test]
#[ignore]
fn test_negative_minutes_roll_over_continuously() {
    assert_eq!(Clock::new(1, -4820).to_string(), "16:40");
}

#[test]
#[ignore]
fn test_negative_hour_and_minutes_both_roll_over() {
    assert_eq!(Clock::new(-25, -160).to_string(), "20:20");
}

#[test]
#[ignore]
fn test_negative_hour_and_minutes_both_roll_over_continuously() {
    assert_eq!(Clock::new(-121, -5810).to_string(), "22:10");
}

//
// Clock Math
//

#[test]
#[ignore]
fn test_add_minutes() {
    let clock = Clock::new(10, 0).add_minutes(3);
    assert_eq!(clock.to_string(), "10:03");
}

#[test]
#[ignore]
fn test_add_no_minutes() {
    let clock = Clock::new(6, 41).add_minutes(0);
    assert_eq!(clock.to_string(), "06:41");
}

#[test]
#[ignore]
fn test_add_to_next_hour() {
    let clock = Clock::new(0, 45).add_minutes(40);
    assert_eq!(clock.to_string(), "01:25");
}

#[test]
#[ignore]
fn test_add_more_than_one_hour() {
    let clock = Clock::new(10, 0).add_minutes(61);
    assert_eq!(clock.to_string(), "11:01");
}

#[test]
#[ignore]
fn test_add_more_than_two_hours_with_carry() {
    let clock = Clock::new(0, 45).add_minutes(160);
    assert_eq!(clock.to_string(), "03:25");
}

#[test]
#[ignore]
fn test_add_across_midnight() {
    let clock = Clock::new(23, 59).add_minutes(2);
    assert_eq!(clock.to_string(), "00:01");
}

#[test]
#[ignore]
fn test_add_more_than_one_day() {
    let clock = Clock::new(5, 32).add_minutes(1500);
    assert_eq!(clock.to_string(), "06:32");
}

#[test]
#[ignore]
fn test_add_more_than_two_days() {
    let clock = Clock::new(1, 1).add_minutes(3500);
    assert_eq!(clock.to_string(), "11:21");
}

#[test]
#[ignore]
fn test_subtract_minutes() {
    let clock = Clock::new(10, 3).add_minutes(-3);
    assert_eq!(clock.to_string(), "10:00");
}

#[test]
#[ignore]
fn test_subtract_to_previous_hour() {
    let clock = Clock::new(10, 3).add_minutes(-30);
    assert_eq!(clock.to_string(), "09:33");
}

#[test]
#[ignore]
fn test_subtract_more_than_an_hour() {
    let clock = Clock::new(10, 3).add_minutes(-70);
    assert_eq!(clock.to_string(), "08:53");
}

#[test]
#[ignore]
fn test_subtract_across_midnight() {
    let clock = Clock::new(0, 3).add_minutes(-4);
    assert_eq!(clock.to_string(), "23:59");
}

#[test]
#[ignore]
fn test_subtract_more_than_two_hours() {
    let clock = Clock::new(0, 0).add_minutes(-160);
    assert_eq!(clock.to_string(), "21:20");
}

#[test]
#[ignore]
fn test_subtract_more_than_two_hours_with_borrow() {
    let clock = Clock::new(6, 15).add_minutes(-160);
    assert_eq!(clock.to_string(), "03:35");
}

#[test]
#[ignore]
fn test_subtract_more_than_one_day() {
    let clock = Clock::new(5, 32).add_minutes(-1500);
    assert_eq!(clock.to_string(), "04:32");
}

#[test]
#[ignore]
fn test_subtract_mores_than_two_days() {
    let clock = Clock::new(2, 20).add_minutes(-3000);
    assert_eq!(clock.to_string(), "00:20");
}

//
// Test Equality
//

#[test]
#[ignore]
fn test_compare_clocks_for_equality() {
    assert_eq!(Clock::new(15, 37), Clock::new(15, 37));
}

#[test]
#[ignore]
fn test_compare_clocks_a_minute_apart() {
    assert_ne!(Clock::new(15, 36), Clock::new(15, 37));
}

#[test]
#[ignore]
fn test_compare_clocks_an_hour_apart() {
    assert_ne!(Clock::new(14, 37), Clock::new(15, 37));
}

#[test]
#[ignore]
fn test_compare_clocks_with_hour_overflow() {
    assert_eq!(Clock::new(10, 37), Clock::new(34, 37));
}

#[test]
#[ignore]
fn test_compare_clocks_with_hour_overflow_by_several_days() {
    assert_eq!(Clock::new(3, 11), Clock::new(99, 11));
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hour() {
    assert_eq!(Clock::new(22, 40), Clock::new(-2, 40));
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hour_that_wraps() {
    assert_eq!(Clock::new(17, 3), Clock::new(-31, 3));
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hour_that_wraps_multiple_times() {
    assert_eq!(Clock::new(13, 49), Clock::new(-83, 49));
}

#[test]
#[ignore]
fn test_compare_clocks_with_minutes_overflow() {
    assert_eq!(Clock::new(0, 1), Clock::new(0, 1441));
}

#[test]
#[ignore]
fn test_compare_clocks_with_minutes_overflow_by_several_days() {
    assert_eq!(Clock::new(2, 2), Clock::new(2, 4322));
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_minute() {
    assert_eq!(Clock::new(2, 40), Clock::new(3, -20))
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_minute_that_wraps() {
    assert_eq!(Clock::new(4, 10), Clock::new(5, -1490))
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_minute_that_wraps_multiple() {
    assert_eq!(Clock::new(6, 15), Clock::new(6, -4305))
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hours_and_minutes() {
    assert_eq!(Clock::new(7, 32), Clock::new(-12, -268))
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hours_and_minutes_that_wrap() {
    assert_eq!(Clock::new(18, 7), Clock::new(-54, -11513))
}
<commit_msg>clock: added test case for comparing 24:00 and 00:00<commit_after>extern crate clock;

use clock::Clock;

//
// Clock Creation
//

#[test]
fn test_on_the_hour() {
    assert_eq!(Clock::new(8, 0).to_string(), "08:00");
}

#[test]
#[ignore]
fn test_past_the_hour() {
    assert_eq!(Clock::new(11, 9).to_string(), "11:09");
}

#[test]
#[ignore]
fn test_midnight_is_zero_hours() {
    assert_eq!(Clock::new(24, 0).to_string(), "00:00");
}

#[test]
#[ignore]
fn test_hour_rolls_over() {
    assert_eq!(Clock::new(25, 0).to_string(), "01:00");
}

#[test]
#[ignore]
fn test_hour_rolls_over_continuously() {
    assert_eq!(Clock::new(100, 0).to_string(), "04:00");
}

#[test]
#[ignore]
fn test_sixty_minutes_is_next_hour() {
    assert_eq!(Clock::new(1, 60).to_string(), "02:00");
}

#[test]
#[ignore]
fn test_minutes_roll_over() {
    assert_eq!(Clock::new(0, 160).to_string(), "02:40");
}

#[test]
#[ignore]
fn test_minutes_roll_over_continuously() {
    assert_eq!(Clock::new(0, 1723).to_string(), "04:43");
}

#[test]
#[ignore]
fn test_hours_and_minutes_roll_over() {
    assert_eq!(Clock::new(25, 160).to_string(), "03:40");
}

#[test]
#[ignore]
fn test_hours_and_minutes_roll_over_continuously() {
    assert_eq!(Clock::new(201, 3001).to_string(), "11:01");
}

#[test]
#[ignore]
fn test_hours_and_minutes_roll_over_to_exactly_midnight() {
    assert_eq!(Clock::new(72, 8640).to_string(), "00:00");
}

#[test]
#[ignore]
fn test_negative_hour() {
    assert_eq!(Clock::new(-1, 15).to_string(), "23:15");
}

#[test]
#[ignore]
fn test_negative_hour_roll_over() {
    assert_eq!(Clock::new(-25, 00).to_string(), "23:00");
}

#[test]
#[ignore]
fn test_negative_hour_roll_over_continuously() {
    assert_eq!(Clock::new(-91, 00).to_string(), "05:00");
}

#[test]
#[ignore]
fn test_negative_minutes() {
    assert_eq!(Clock::new(1, -40).to_string(), "00:20");
}

#[test]
#[ignore]
fn test_negative_minutes_roll_over() {
    assert_eq!(Clock::new(1, -160).to_string(), "22:20");
}

#[test]
#[ignore]
fn test_negative_minutes_roll_over_continuously() {
    assert_eq!(Clock::new(1, -4820).to_string(), "16:40");
}

#[test]
#[ignore]
fn test_negative_hour_and_minutes_both_roll_over() {
    assert_eq!(Clock::new(-25, -160).to_string(), "20:20");
}

#[test]
#[ignore]
fn test_negative_hour_and_minutes_both_roll_over_continuously() {
    assert_eq!(Clock::new(-121, -5810).to_string(), "22:10");
}

//
// Clock Math
//

#[test]
#[ignore]
fn test_add_minutes() {
    let clock = Clock::new(10, 0).add_minutes(3);
    assert_eq!(clock.to_string(), "10:03");
}

#[test]
#[ignore]
fn test_add_no_minutes() {
    let clock = Clock::new(6, 41).add_minutes(0);
    assert_eq!(clock.to_string(), "06:41");
}

#[test]
#[ignore]
fn test_add_to_next_hour() {
    let clock = Clock::new(0, 45).add_minutes(40);
    assert_eq!(clock.to_string(), "01:25");
}

#[test]
#[ignore]
fn test_add_more_than_one_hour() {
    let clock = Clock::new(10, 0).add_minutes(61);
    assert_eq!(clock.to_string(), "11:01");
}

#[test]
#[ignore]
fn test_add_more_than_two_hours_with_carry() {
    let clock = Clock::new(0, 45).add_minutes(160);
    assert_eq!(clock.to_string(), "03:25");
}

#[test]
#[ignore]
fn test_add_across_midnight() {
    let clock = Clock::new(23, 59).add_minutes(2);
    assert_eq!(clock.to_string(), "00:01");
}

#[test]
#[ignore]
fn test_add_more_than_one_day() {
    let clock = Clock::new(5, 32).add_minutes(1500);
    assert_eq!(clock.to_string(), "06:32");
}

#[test]
#[ignore]
fn test_add_more_than_two_days() {
    let clock = Clock::new(1, 1).add_minutes(3500);
    assert_eq!(clock.to_string(), "11:21");
}

#[test]
#[ignore]
fn test_subtract_minutes() {
    let clock = Clock::new(10, 3).add_minutes(-3);
    assert_eq!(clock.to_string(), "10:00");
}

#[test]
#[ignore]
fn test_subtract_to_previous_hour() {
    let clock = Clock::new(10, 3).add_minutes(-30);
    assert_eq!(clock.to_string(), "09:33");
}

#[test]
#[ignore]
fn test_subtract_more_than_an_hour() {
    let clock = Clock::new(10, 3).add_minutes(-70);
    assert_eq!(clock.to_string(), "08:53");
}

#[test]
#[ignore]
fn test_subtract_across_midnight() {
    let clock = Clock::new(0, 3).add_minutes(-4);
    assert_eq!(clock.to_string(), "23:59");
}

#[test]
#[ignore]
fn test_subtract_more_than_two_hours() {
    let clock = Clock::new(0, 0).add_minutes(-160);
    assert_eq!(clock.to_string(), "21:20");
}

#[test]
#[ignore]
fn test_subtract_more_than_two_hours_with_borrow() {
    let clock = Clock::new(6, 15).add_minutes(-160);
    assert_eq!(clock.to_string(), "03:35");
}

#[test]
#[ignore]
fn test_subtract_more_than_one_day() {
    let clock = Clock::new(5, 32).add_minutes(-1500);
    assert_eq!(clock.to_string(), "04:32");
}

#[test]
#[ignore]
fn test_subtract_mores_than_two_days() {
    let clock = Clock::new(2, 20).add_minutes(-3000);
    assert_eq!(clock.to_string(), "00:20");
}

//
// Test Equality
//

#[test]
#[ignore]
fn test_compare_clocks_for_equality() {
    assert_eq!(Clock::new(15, 37), Clock::new(15, 37));
}

#[test]
#[ignore]
fn test_compare_clocks_a_minute_apart() {
    assert_ne!(Clock::new(15, 36), Clock::new(15, 37));
}

#[test]
#[ignore]
fn test_compare_clocks_an_hour_apart() {
    assert_ne!(Clock::new(14, 37), Clock::new(15, 37));
}

#[test]
#[ignore]
fn test_compare_clocks_with_hour_overflow() {
    assert_eq!(Clock::new(10, 37), Clock::new(34, 37));
}

#[test]
#[ignore]
fn test_compare_clocks_with_hour_overflow_by_several_days() {
    assert_eq!(Clock::new(3, 11), Clock::new(99, 11));
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hour() {
    assert_eq!(Clock::new(22, 40), Clock::new(-2, 40));
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hour_that_wraps() {
    assert_eq!(Clock::new(17, 3), Clock::new(-31, 3));
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hour_that_wraps_multiple_times() {
    assert_eq!(Clock::new(13, 49), Clock::new(-83, 49));
}

#[test]
#[ignore]
fn test_compare_clocks_with_minutes_overflow() {
    assert_eq!(Clock::new(0, 1), Clock::new(0, 1441));
}

#[test]
#[ignore]
fn test_compare_clocks_with_minutes_overflow_by_several_days() {
    assert_eq!(Clock::new(2, 2), Clock::new(2, 4322));
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_minute() {
    assert_eq!(Clock::new(2, 40), Clock::new(3, -20))
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_minute_that_wraps() {
    assert_eq!(Clock::new(4, 10), Clock::new(5, -1490))
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_minute_that_wraps_multiple() {
    assert_eq!(Clock::new(6, 15), Clock::new(6, -4305))
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hours_and_minutes() {
    assert_eq!(Clock::new(7, 32), Clock::new(-12, -268))
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hours_and_minutes_that_wrap() {
    assert_eq!(Clock::new(18, 7), Clock::new(-54, -11513))
}

#[test]
#[ignore]
fn test_compare_full_clock_and_zeroed_clock() {
    assert_eq!(Clock::new(24, 0), Clock::new(0, 0))
}
<|endoftext|>


<commit_before>use glam::f32::Vec2;
use serde::{Deserialize, Serialize};

use crate::components::*;

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum PlayerUpdate {
    Move(PlayerMoveInputEvent),
    Shoot(PlayerShootInputEvent),
    Use(GameEntityId),
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum ClientMessage {
    JoinGame(PlayerId),
    LeaveGame,
    PlayerInputEvent(PlayerInputEvent),
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum PlayerInputEvent {
    Move(PlayerMoveInputEvent),
    Shoot(PlayerShootInputEvent),
    Use(GameEntityId),
    // The player wants to exit the current game session
    Exit,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct PlayerMoveInputEvent {
    pub direction: Vec2,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct PlayerShootInputEvent {
    pub direction: Vec2,
}
<commit_msg>Remove outdated PlayerUpdate<commit_after>use glam::f32::Vec2;
use serde::{Deserialize, Serialize};

use crate::components::*;

/// A message sent from a client to the server.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum ClientMessage {
    JoinGame(PlayerId),
    LeaveGame,
    PlayerInputEvent(PlayerInputEvent),
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum PlayerInputEvent {
    Move(PlayerMoveInputEvent),
    Shoot(PlayerShootInputEvent),
    Use(GameEntityId),
    // The player wants to exit the current game session
    Exit,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct PlayerMoveInputEvent {
    pub direction: Vec2,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct PlayerShootInputEvent {
    pub direction: Vec2,
}
<|endoftext|>