<commit_before>extern crate postgres;

use std::io::prelude::*;

use self::postgres::Connection;
use self::postgres::types::{Type, ToSql, FromSql, SessionInfo, IsNull};
use self::postgres::error::Error as PostgresError;

use super::Adapter;
use attribute::{Attribute, Attributes};
use model::Model;

macro_rules! accepts {
    ($($expected:pat),+) => (
        fn accepts(ty: &Type) -> bool {
            match *ty {
                $($expected)|+ => true,
                _ => false
            }
        }
    )
}

macro_rules! to_sql_checked {
    () => {
        fn to_sql_checked(&self, ty: &Type, out: &mut ::std::io::Write, ctx: &SessionInfo) -> Result<IsNull, PostgresError> {
            if !<Self as ToSql>::accepts(ty) {
                return Err(PostgresError::WrongType(ty.clone()));
            }
            self.to_sql(ty, out, ctx)
        }
    }
}

pub struct PostgresAdapter {
    conn: Connection,
}

impl ToSql for Attribute {
    to_sql_checked!();

    fn to_sql<W: Write+?Sized>(&self, ty: &Type, w: &mut W, ctx: &SessionInfo) -> Result<IsNull, PostgresError> {
        match *self {
            Attribute::Bool(ref attribute) => attribute.to_sql(ty, w, ctx),
            Attribute::I8(ref attribute) => attribute.to_sql(ty, w, ctx),
            Attribute::I16(ref attribute) => attribute.to_sql(ty, w, ctx),
            Attribute::I32(ref attribute) => attribute.to_sql(ty, w, ctx),
            Attribute::I64(ref attribute) => attribute.to_sql(ty, w, ctx),
            Attribute::F32(ref attribute) => attribute.to_sql(ty, w, ctx),
            Attribute::F64(ref attribute) => attribute.to_sql(ty, w, ctx),
            Attribute::String(ref attribute) => attribute.to_sql(ty, w, ctx),
        }
    }

    accepts!(
        // Bool
        Type::Bool,
        // I8
        Type::Char,
        // I16
        Type::Int2,
        // I32
        Type::Int4,
        // I64
        Type::Int8,
        // F32
        Type::Float4,
        // F64
        Type::Float8,
        // String
        Type::Varchar, Type::Text, Type::Bpchar, Type::Name,
        // Postgres Enum as String
        Type::Other(_)
    );
}

impl FromSql for Attribute {
    fn from_sql<R: Read>(ty: &Type, raw: &mut R, ctx: &SessionInfo) -> Result<Self, PostgresError> {
        match *ty {
            Type::Bool => Ok(Attribute::Bool(Some(try!(<bool as FromSql>::from_sql(ty, raw, ctx))))),
            Type::Char => Ok(Attribute::I8(Some(try!(<i8 as FromSql>::from_sql(ty, raw, ctx))))),
            Type::Int2 => Ok(Attribute::I16(Some(try!(<i16 as FromSql>::from_sql(ty, raw, ctx))))),
            Type::Int4 => Ok(Attribute::I32(Some(try!(<i32 as FromSql>::from_sql(ty, raw, ctx))))),
            Type::Int8 => Ok(Attribute::I64(Some(try!(<i64 as FromSql>::from_sql(ty, raw, ctx))))),
            Type::Float4 => Ok(Attribute::F32(Some(try!(<f32 as FromSql>::from_sql(ty, raw, ctx))))),
            Type::Float8 => Ok(Attribute::F64(Some(try!(<f64 as FromSql>::from_sql(ty, raw, ctx))))),
            Type::Varchar | Type::Text | Type::Bpchar | Type::Name | Type::Other(_)
                => Ok(Attribute::String(Some(try!(<String as FromSql>::from_sql(ty, raw, ctx))))),
            _ => Err(PostgresError::WrongType(ty.clone()))
        }
    }

    accepts!(
        // Bool
        Type::Bool,
        // I8
        Type::Char,
        // I16
        Type::Int2,
        // I32
        Type::Int4,
        // I64
        Type::Int8,
        // F32
        Type::Float4,
        // F64
        Type::Float8,
        // String
        Type::Varchar, Type::Text, Type::Bpchar, Type::Name,
        // Postgres Enum as String
        Type::Other(_)
    );
}

impl Adapter for PostgresAdapter {
    fn find(&self, model: &Model, id: &Attribute) -> Option<Attributes> {
        let sql = format!("SELECT * FROM {} WHERE {} = $1 ORDER BY {} LIMIT 1", model.ty, model.primary_key, model.primary_key);
        let stmt = self.conn.prepare(&sql).unwrap();
        let rows = stmt.query(&[id]).unwrap();
        let row = try_opt!(rows.iter().next());

        Some(row.columns().iter().fold(Attributes::new(), |mut attributes, column| {
            if let Some(attribute) = row.get_opt::<&str, Attribute>(column.name()).ok() {
                attributes.insert(column.name().to_string(), attribute);
            }

            attributes
        }))
    }

    fn find_all(&self, _: &Model) -> Vec<Attributes> {
        unimplemented!()
    }

    fn find_many(&self, _: &Model, _: &[&Attribute]) -> Vec<Attributes> {
        unimplemented!()
    }
}
<commit_msg>Simplify `PostgresAdapter`<commit_after>extern crate postgres;

use std::io::prelude::*;

use self::postgres::Connection;
use self::postgres::types::{Type, ToSql, FromSql, SessionInfo, IsNull};
use self::postgres::error::Error as PostgresError;

use super::Adapter;
use attribute::{Attribute, Attributes};
use model::Model;

macro_rules! accepts {
    ($($expected:pat),+) => (
        fn accepts(ty: &Type) -> bool {
            match *ty {
                $($expected)|+ => true,
                _ => false
            }
        }
    )
}

macro_rules! to_sql_checked {
    () => {
        fn to_sql_checked(&self, ty: &Type, out: &mut ::std::io::Write, ctx: &SessionInfo) -> Result<IsNull, PostgresError> {
            if !<Self as ToSql>::accepts(ty) {
                return Err(PostgresError::WrongType(ty.clone()));
            }
            self.to_sql(ty, out, ctx)
        }
    }
}

macro_rules! accepts_for_attribute {
    () => {
        accepts!(
            // Bool
            Type::Bool,
            // I8
            Type::Char,
            // I16
            Type::Int2,
            // I32
            Type::Int4,
            // I64
            Type::Int8,
            // F32
            Type::Float4,
            // F64
            Type::Float8,
            // String
            Type::Varchar, Type::Text, Type::Bpchar, Type::Name,
            // Postgres Enum as String
            Type::Other(_)
        );
    }
}

pub struct PostgresAdapter {
    conn: Connection,
}

impl ToSql for Attribute {
    to_sql_checked!();

    fn to_sql<W: Write+?Sized>(&self, ty: &Type, w: &mut W, ctx: &SessionInfo) -> Result<IsNull, PostgresError> {
        match *self {
            Attribute::Bool(ref attribute) => attribute.to_sql(ty, w, ctx),
            Attribute::I8(ref attribute) => attribute.to_sql(ty, w, ctx),
            Attribute::I16(ref attribute) => attribute.to_sql(ty, w, ctx),
            Attribute::I32(ref attribute) => attribute.to_sql(ty, w, ctx),
            Attribute::I64(ref attribute) => attribute.to_sql(ty, w, ctx),
            Attribute::F32(ref attribute) => attribute.to_sql(ty, w, ctx),
            Attribute::F64(ref attribute) => attribute.to_sql(ty, w, ctx),
            Attribute::String(ref attribute) => attribute.to_sql(ty, w, ctx),
        }
    }

    accepts_for_attribute!();
}

impl FromSql for Attribute {
    fn from_sql<R: Read>(ty: &Type, raw: &mut R, ctx: &SessionInfo) -> Result<Self, PostgresError> {
        match *ty {
            Type::Bool => Ok(Attribute::Bool(Some(try!(FromSql::from_sql(ty, raw, ctx))))),
            Type::Char => Ok(Attribute::I8(Some(try!(FromSql::from_sql(ty, raw, ctx))))),
            Type::Int2 => Ok(Attribute::I16(Some(try!(FromSql::from_sql(ty, raw, ctx))))),
            Type::Int4 => Ok(Attribute::I32(Some(try!(FromSql::from_sql(ty, raw, ctx))))),
            Type::Int8 => Ok(Attribute::I64(Some(try!(FromSql::from_sql(ty, raw, ctx))))),
            Type::Float4 => Ok(Attribute::F32(Some(try!(FromSql::from_sql(ty, raw, ctx))))),
            Type::Float8 => Ok(Attribute::F64(Some(try!(FromSql::from_sql(ty, raw, ctx))))),
            Type::Varchar | Type::Text | Type::Bpchar | Type::Name | Type::Other(_)
                => Ok(Attribute::String(Some(try!(FromSql::from_sql(ty, raw, ctx))))),
            _ => Err(PostgresError::WrongType(ty.clone()))
        }
    }

    accepts_for_attribute!();
}

impl Adapter for PostgresAdapter {
    fn find(&self, model: &Model, id: &Attribute) -> Option<Attributes> {
        let sql = format!("SELECT * FROM {} WHERE {} = $1 ORDER BY {} LIMIT 1", model.ty, model.primary_key, model.primary_key);
        let stmt = self.conn.prepare(&sql).unwrap();
        let rows = stmt.query(&[id]).unwrap();
        let row = try_opt!(rows.iter().next());

        Some(row.columns().iter().fold(Attributes::new(), |mut attributes, column| {
            if let Some(attribute) = row.get_opt::<&str, Attribute>(column.name()).ok() {
                attributes.insert(column.name().to_string(), attribute);
            }

            attributes
        }))
    }

    fn find_all(&self, _: &Model) -> Vec<Attributes> {
        unimplemented!()
    }

    fn find_many(&self, _: &Model, _: &[&Attribute]) -> Vec<Attributes> {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>//! Rope slices
//!
//! While we could just have the slicing methods on `Rope`s return `&str`s,
//! this would have some serious drawbacks: to slice a rope as `&str`, we'd have
//! to collect all the `Rope`'s characters into a `String` and then slice that
//! `String`. Creating an intermediate `String` would be slow, would cause
//! unnecessary allocations, and, in the case of `Rope::slice_mut()`, would
//! return a mutable slice of a _new `String`_ –- mutating the slice would _not_
//! mutate the underlying `Rope`.
// TODO: implement Borrow<RopeSlice> for Rope?

use std::fmt;
use std::cmp;

use collections::range::RangeArgument;

use super::internals::Node;

/// An immutable borrowed slice of a `Rope`.
///
/// A RopeSlice represents an immutable borrowed slice of some or all the
/// characters in a `Rope`.
#[derive(Debug)]
pub struct RopeSlice<'a> { node: &'a Node
                         , offset: usize
                         , len: usize
                         }

impl<'a> fmt::Display for RopeSlice<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // TODO: don't create an intermediate string?
        write!(f, "{}", self.chars().collect::<String>())
    }
}

/// An mutable borrowed slice of a `Rope`.
///
/// A `RopeSliceMut` represents a mutable borrowed slice of some or all the
/// characters in a `Rope`.
#[derive(Debug)]
pub struct RopeSliceMut<'a> { node: &'a mut Node
                            , offset: usize
                            , len: usize
                            }

impl<'a> RopeSliceMut<'a>  {

    // TODO: share duplicate functionality with non-mutable RopeSlice in a less
    //       ugly way. Maybe an added generic?
    //          - eliza, 12/23/16

    // TODO: add mutable iterators

    pub fn new<R>(node: &'a mut Node, range: R) -> Self
    where R: RangeArgument<usize> {
        let len = node.len();

        // if the RangeArgument doesn't have a defined start index,
        // the slice begins at the 0th index.
        let start = *range.start().unwrap_or(&0);
        // similarly, if there's no defined end, then the end index
        // is the last index in the Rope.
        let end = *range.end().unwrap_or(&node.len());

        let slice_len = end - start;

        // find the lowest node that contains both the slice start index and
        // the end index
        let (node, offset) = if start == 0 && end == len {
            // if the slice contains the entire rope, then the spanning node
            // is the root node
            (node, 0)
        } else {
            node.spanning_mut(start, slice_len)
        };

        RopeSliceMut { node: node
                     , offset: offset
                     , len: slice_len }
    }

    #[inline]
    fn slice_char_iter<I, T>(&'a self, i: I) -> impl Iterator<Item=T> + 'a
    where I: Iterator<Item=T>
        , I: 'a
        , T: Copy {
            i.skip(self.offset).take(self.len)
    }

    fn slice_strings_iter<I>(&'a self, i: I) -> impl Iterator<Item=&'a str> +'a
    where I: Iterator<Item=&'a str>
        , I: 'a {
        i.scan((self.offset, self.len), |curr, s| {
            match *curr {
                (0, 0) => None
              , (0, ref mut remaining) if *remaining < s.len() => {
                    let r = *remaining;
                    *remaining = 0;
                    Some(&s[..r])
                }
              , (0, ref mut remaining) => {
                    *remaining -= s.len();
                    Some(s)
                }
              , (ref mut offset, _) if *offset > s.len() => {
                    *offset -= s.len();
                    Some("")
                }
              , (ref mut offset, _) => {
                    let c = *offset;
                    *offset -= s.len();
                    Some(&s[c..])
                }
            }
            // if curr_len > 0 {
            //     let c = curr_offset;
            //     let res = if c > 0 {
            //         curr_offset -= s.len();
            //         if c < s.len()  {
            //             &s[c..]
            //         } else {
            //             ""
            //         }
            //     } else {
            //         s
            //     };
            //     Some(res)
            })
         .skip_while(|&s| s == "")
    }

    pub fn chars(&'a self) -> impl Iterator<Item=char> +'a  {
        self.slice_char_iter(self.node.chars())
    }

    pub fn bytes(&'a self) -> impl Iterator<Item=u8> + 'a  {
        self.slice_char_iter(self.node.bytes())
    }

    #[inline]
    pub fn split_whitespace(&'a self) -> impl Iterator<Item=&'a str> {
        self.slice_strings_iter(self.node.split_whitespace())
    }

    #[inline]
    pub fn lines(&'a self) -> impl Iterator<Item=&'a str> {
        self.slice_strings_iter(self.node.lines())
    }

    #[inline]
    pub fn char_indices(&'a self) -> impl Iterator<Item=(usize, char)> + 'a {
        self.chars().enumerate()
    }

    /// Returns true if the bytes in `self` equal the bytes in `other`
    #[inline]
    fn bytes_eq<I>(&self, other: I) -> bool
    where I: Iterator<Item=u8> {
        self.bytes().zip(other).all(|(a, b)| a == b)
    }

    #[inline]
    pub fn len(&self) -> usize { self.len }
}

impl<'a> RopeSlice<'a> {
    pub fn new<R>(node: &'a Node, range: R) -> Self
    where R: RangeArgument<usize> {
        let len = node.len();

        // if the RangeArgument doesn't have a defined start index,
        // the slice begins at the 0th index.
        let start = *range.start().unwrap_or(&0);
        // similarly, if there's no defined end, then the end index
        // is the last index in the Rope.
        let end = *range.end().unwrap_or(&node.len());

        let slice_len = end - start;

        // find the lowest node that contains both the slice start index and
        // the end index
        let (node, offset) = if start == 0 && end == len {
            // if the slice contains the entire rope, then the spanning node
            // is the root node
            (node, 0)
        } else {
            node.spanning(start, slice_len)
        };

        RopeSlice { node: node
                  , offset: offset
                  , len: slice_len }
    }

    #[inline]
    fn slice_char_iter<I, T>(&'a self, i: I) -> impl Iterator<Item=T> + 'a
    where I: Iterator<Item=T>
        , I: 'a
        , T: Copy {
            i.skip(self.offset).take(self.len)
    }

    fn slice_strings_iter<I>(&'a self, i: I) -> impl Iterator<Item=&'a str> +'a
    where I: Iterator<Item=&'a str>
        , I: 'a {
        i.scan((self.offset, self.len), |curr, s| {
            match *curr {
                (0, 0) => None
              , (0, ref mut remaining) if *remaining < s.len() => {
                    let r = *remaining;
                    *remaining = 0;
                    Some(&s[..r])
                }
              , (0, ref mut remaining) => {
                    *remaining -= s.len();
                    Some(s)
                }
              , (ref mut offset, _) if *offset > s.len() => {
                    *offset -= s.len();
                    Some("")
                }
              , (ref mut offset, _) => {
                    let c = *offset;
                    *offset -= s.len();
                    Some(&s[c..])
                }
            }
            // if curr_len > 0 {
            //     let c = curr_offset;
            //     let res = if c > 0 {
            //         curr_offset -= s.len();
            //         if c < s.len()  {
            //             &s[c..]
            //         } else {
            //             ""
            //         }
            //     } else {
            //         s
            //     };
            //     Some(res)
            })
         .skip_while(|&s| s == "")
    }

    pub fn chars(&'a self) -> impl Iterator<Item=char> +'a  {
        self.slice_char_iter(self.node.chars())
    }

    pub fn bytes(&'a self) -> impl Iterator<Item=u8> + 'a  {
        self.slice_char_iter(self.node.bytes())
    }

    #[inline]
    pub fn split_whitespace(&'a self) -> impl Iterator<Item=&'a str> {
        self.slice_strings_iter(self.node.split_whitespace())
    }

    #[inline]
    pub fn lines(&'a self) -> impl Iterator<Item=&'a str> {
        self.slice_strings_iter(self.node.lines())
    }

    #[inline]
    pub fn char_indices(&'a self) -> impl Iterator<Item=(usize, char)> + 'a {
        self.chars().enumerate()
    }

    /// Returns true if the bytes in `self` equal the bytes in `other`
    #[inline]
    fn bytes_eq<I>(&self, other: I) -> bool
    where I: Iterator<Item=u8> {
        self.bytes().zip(other).all(|(a, b)| a == b)
    }

    #[inline]
    pub fn len(&self) -> usize { self.len }
}

//-- comparisons ----------------------------------------------------
impl<'a> cmp::Eq for RopeSlice<'a> {}
impl<'a> cmp::PartialEq for RopeSlice<'a> {
    /// A rope equals another rope if all the bytes in both are equal.

    #[inline]
    fn eq(&self, other: &RopeSlice<'a>) -> bool {
        if self.len() == other.len() {
            self.bytes_eq(other.bytes())
        } else {
            false
        }
    }
}

impl<'a> cmp::PartialEq<str> for RopeSlice<'a> {
    /// A rope equals another rope if all the bytes in both are equal.

    #[inline]
    fn eq(&self, other: &str) -> bool {
        if self.len() == other.len() {
            self.bytes_eq(other.bytes())
        } else {
            false
        }
    }
}

impl<'a> cmp::Eq for RopeSliceMut<'a> {}
impl<'a> cmp::PartialEq for RopeSliceMut<'a> {
    /// A rope equals another rope if all the bytes in both are equal.

    #[inline]
    fn eq(&self, other: &RopeSliceMut<'a>) -> bool {
        if self.len() == other.len() {
            self.bytes_eq(other.bytes())
        } else {
            false
        }
    }
}

impl<'a, 'b> cmp::PartialEq<RopeSlice<'b>> for RopeSliceMut<'a> {
    /// A rope equals another rope if all the bytes in both are equal.

    #[inline]
    fn eq(&self, other: &RopeSlice<'b>) -> bool {
        if self.len() == other.len() {
            self.bytes_eq(other.bytes())
        } else {
            false
        }
    }
}

impl<'a> cmp::PartialEq<str> for RopeSliceMut<'a> {
    /// A rope equals another rope if all the bytes in both are equal.

    #[inline]
    fn eq(&self, other: &str) -> bool {
        if self.len() == other.len() {
            self.bytes_eq(other.bytes())
        } else {
            false
        }
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    use ::Rope;

    #[test]
    fn char_indices() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(4..8);
        let string_slice = &string[4..8];
        let indices = rope_slice.char_indices().zip(string_slice.char_indices());
        for ((ridx, rch), (sidx, sch)) in indices {
            assert_eq!(rch, sch);
            assert_eq!(ridx, sidx);
        }
    }

    #[test]
    fn to() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(1..10);
        let string_slice = &string[1..10];
        assert_eq!(&rope_slice, string_slice)
    }

    // #[test]
    // fn between() {
    //     let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
    //     let rope = Rope::from(string);
    //     let rope_slice = rope.slice(1...10usize);
    //     let string_slice = &string[1...10];
    //     assert_eq!(&rope_slice, string_slice)
    // }

    #[test]
    fn until() {
        let string = "aaaaabbbbbbccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(..10);
        let string_slice = &string[..10];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn from() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(5..);
        let string_slice = &string[5..];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn full() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(..);
        let string_slice = &string[..];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn mut_char_indices() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice_mut(4..8);
        let string_slice = &mut string[4..8];
        let indices = rope_slice.char_indices().zip(string_slice.char_indices());
        for ((ridx, rch), (sidx, sch)) in indices {
            assert_eq!(rch, sch);
            assert_eq!(ridx, sidx);
        }
    }

    #[test]
    fn mut_to() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice_mut(1..10);
        let string_slice = &mut string[1..10];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn mut_until() {
        let string = "aaaaabbbbbbccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice_mut(..10);
        let string_slice = &string[..10];
        assert_eq!(&mut rope_slice, string_slice)
    }

    #[test]
    fn mut_from() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice_mut(5..);
        let string_slice = &mut string[5..];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn mut_full() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice_mut(..);
        let string_slice = &mut string[..];
        assert_eq!(&rope_slice, string_slice)
    }
}
<commit_msg>rope: fix borrowing issues in RopeSliceMut tests<commit_after>//! Rope slices
//!
//! While we could just have the slicing methods on `Rope`s return `&str`s,
//! this would have some serious drawbacks: to slice a rope as `&str`, we'd have
//! to collect all the `Rope`'s characters into a `String` and then slice that
//! `String`. Creating an intermediate `String` would be slow, would cause
//! unnecessary allocations, and, in the case of `Rope::slice_mut()`, would
//! return a mutable slice of a _new `String`_ –- mutating the slice would _not_
//! mutate the underlying `Rope`.
// TODO: implement Borrow<RopeSlice> for Rope?

use std::fmt;
use std::cmp;

use collections::range::RangeArgument;

use super::internals::Node;

/// An immutable borrowed slice of a `Rope`.
///
/// A RopeSlice represents an immutable borrowed slice of some or all the
/// characters in a `Rope`.
#[derive(Debug)]
pub struct RopeSlice<'a> { node: &'a Node
                         , offset: usize
                         , len: usize
                         }

impl<'a> fmt::Display for RopeSlice<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // TODO: don't create an intermediate string?
        write!(f, "{}", self.chars().collect::<String>())
    }
}

/// An mutable borrowed slice of a `Rope`.
///
/// A `RopeSliceMut` represents a mutable borrowed slice of some or all the
/// characters in a `Rope`.
#[derive(Debug)]
pub struct RopeSliceMut<'a> { node: &'a mut Node
                            , offset: usize
                            , len: usize
                            }

impl<'a> RopeSliceMut<'a>  {

    // TODO: share duplicate functionality with non-mutable RopeSlice in a less
    //       ugly way. Maybe an added generic?
    //          - eliza, 12/23/16

    // TODO: add mutable iterators

    pub fn new<R>(node: &'a mut Node, range: R) -> Self
    where R: RangeArgument<usize> {
        let len = node.len();

        // if the RangeArgument doesn't have a defined start index,
        // the slice begins at the 0th index.
        let start = *range.start().unwrap_or(&0);
        // similarly, if there's no defined end, then the end index
        // is the last index in the Rope.
        let end = *range.end().unwrap_or(&node.len());

        let slice_len = end - start;

        // find the lowest node that contains both the slice start index and
        // the end index
        let (node, offset) = if start == 0 && end == len {
            // if the slice contains the entire rope, then the spanning node
            // is the root node
            (node, 0)
        } else {
            node.spanning_mut(start, slice_len)
        };

        RopeSliceMut { node: node
                     , offset: offset
                     , len: slice_len }
    }

    #[inline]
    fn slice_char_iter<I, T>(&'a self, i: I) -> impl Iterator<Item=T> + 'a
    where I: Iterator<Item=T>
        , I: 'a
        , T: Copy {
            i.skip(self.offset).take(self.len)
    }

    fn slice_strings_iter<I>(&'a self, i: I) -> impl Iterator<Item=&'a str> +'a
    where I: Iterator<Item=&'a str>
        , I: 'a {
        i.scan((self.offset, self.len), |curr, s| {
            match *curr {
                (0, 0) => None
              , (0, ref mut remaining) if *remaining < s.len() => {
                    let r = *remaining;
                    *remaining = 0;
                    Some(&s[..r])
                }
              , (0, ref mut remaining) => {
                    *remaining -= s.len();
                    Some(s)
                }
              , (ref mut offset, _) if *offset > s.len() => {
                    *offset -= s.len();
                    Some("")
                }
              , (ref mut offset, _) => {
                    let c = *offset;
                    *offset -= s.len();
                    Some(&s[c..])
                }
            }
            // if curr_len > 0 {
            //     let c = curr_offset;
            //     let res = if c > 0 {
            //         curr_offset -= s.len();
            //         if c < s.len()  {
            //             &s[c..]
            //         } else {
            //             ""
            //         }
            //     } else {
            //         s
            //     };
            //     Some(res)
            })
         .skip_while(|&s| s == "")
    }

    pub fn chars(&'a self) -> impl Iterator<Item=char> +'a  {
        self.slice_char_iter(self.node.chars())
    }

    pub fn bytes(&'a self) -> impl Iterator<Item=u8> + 'a  {
        self.slice_char_iter(self.node.bytes())
    }

    #[inline]
    pub fn split_whitespace(&'a self) -> impl Iterator<Item=&'a str> {
        self.slice_strings_iter(self.node.split_whitespace())
    }

    #[inline]
    pub fn lines(&'a self) -> impl Iterator<Item=&'a str> {
        self.slice_strings_iter(self.node.lines())
    }

    #[inline]
    pub fn char_indices(&'a self) -> impl Iterator<Item=(usize, char)> + 'a {
        self.chars().enumerate()
    }

    /// Returns true if the bytes in `self` equal the bytes in `other`
    #[inline]
    fn bytes_eq<I>(&self, other: I) -> bool
    where I: Iterator<Item=u8> {
        self.bytes().zip(other).all(|(a, b)| a == b)
    }

    #[inline]
    pub fn len(&self) -> usize { self.len }
}

impl<'a> RopeSlice<'a> {
    pub fn new<R>(node: &'a Node, range: R) -> Self
    where R: RangeArgument<usize> {
        let len = node.len();

        // if the RangeArgument doesn't have a defined start index,
        // the slice begins at the 0th index.
        let start = *range.start().unwrap_or(&0);
        // similarly, if there's no defined end, then the end index
        // is the last index in the Rope.
        let end = *range.end().unwrap_or(&node.len());

        let slice_len = end - start;

        // find the lowest node that contains both the slice start index and
        // the end index
        let (node, offset) = if start == 0 && end == len {
            // if the slice contains the entire rope, then the spanning node
            // is the root node
            (node, 0)
        } else {
            node.spanning(start, slice_len)
        };

        RopeSlice { node: node
                  , offset: offset
                  , len: slice_len }
    }

    #[inline]
    fn slice_char_iter<I, T>(&'a self, i: I) -> impl Iterator<Item=T> + 'a
    where I: Iterator<Item=T>
        , I: 'a
        , T: Copy {
            i.skip(self.offset).take(self.len)
    }

    fn slice_strings_iter<I>(&'a self, i: I) -> impl Iterator<Item=&'a str> +'a
    where I: Iterator<Item=&'a str>
        , I: 'a {
        i.scan((self.offset, self.len), |curr, s| {
            match *curr {
                (0, 0) => None
              , (0, ref mut remaining) if *remaining < s.len() => {
                    let r = *remaining;
                    *remaining = 0;
                    Some(&s[..r])
                }
              , (0, ref mut remaining) => {
                    *remaining -= s.len();
                    Some(s)
                }
              , (ref mut offset, _) if *offset > s.len() => {
                    *offset -= s.len();
                    Some("")
                }
              , (ref mut offset, _) => {
                    let c = *offset;
                    *offset -= s.len();
                    Some(&s[c..])
                }
            }
            // if curr_len > 0 {
            //     let c = curr_offset;
            //     let res = if c > 0 {
            //         curr_offset -= s.len();
            //         if c < s.len()  {
            //             &s[c..]
            //         } else {
            //             ""
            //         }
            //     } else {
            //         s
            //     };
            //     Some(res)
            })
         .skip_while(|&s| s == "")
    }

    pub fn chars(&'a self) -> impl Iterator<Item=char> +'a  {
        self.slice_char_iter(self.node.chars())
    }

    pub fn bytes(&'a self) -> impl Iterator<Item=u8> + 'a  {
        self.slice_char_iter(self.node.bytes())
    }

    #[inline]
    pub fn split_whitespace(&'a self) -> impl Iterator<Item=&'a str> {
        self.slice_strings_iter(self.node.split_whitespace())
    }

    #[inline]
    pub fn lines(&'a self) -> impl Iterator<Item=&'a str> {
        self.slice_strings_iter(self.node.lines())
    }

    #[inline]
    pub fn char_indices(&'a self) -> impl Iterator<Item=(usize, char)> + 'a {
        self.chars().enumerate()
    }

    /// Returns true if the bytes in `self` equal the bytes in `other`
    #[inline]
    fn bytes_eq<I>(&self, other: I) -> bool
    where I: Iterator<Item=u8> {
        self.bytes().zip(other).all(|(a, b)| a == b)
    }

    #[inline]
    pub fn len(&self) -> usize { self.len }
}

//-- comparisons ----------------------------------------------------
impl<'a> cmp::Eq for RopeSlice<'a> {}
impl<'a> cmp::PartialEq for RopeSlice<'a> {
    /// A rope equals another rope if all the bytes in both are equal.

    #[inline]
    fn eq(&self, other: &RopeSlice<'a>) -> bool {
        if self.len() == other.len() {
            self.bytes_eq(other.bytes())
        } else {
            false
        }
    }
}

impl<'a> cmp::PartialEq<str> for RopeSlice<'a> {
    /// A rope equals another rope if all the bytes in both are equal.

    #[inline]
    fn eq(&self, other: &str) -> bool {
        if self.len() == other.len() {
            self.bytes_eq(other.bytes())
        } else {
            false
        }
    }
}

impl<'a> cmp::Eq for RopeSliceMut<'a> {}
impl<'a> cmp::PartialEq for RopeSliceMut<'a> {
    /// A rope equals another rope if all the bytes in both are equal.

    #[inline]
    fn eq(&self, other: &RopeSliceMut<'a>) -> bool {
        if self.len() == other.len() {
            self.bytes_eq(other.bytes())
        } else {
            false
        }
    }
}

impl<'a, 'b> cmp::PartialEq<RopeSlice<'b>> for RopeSliceMut<'a> {
    /// A rope equals another rope if all the bytes in both are equal.

    #[inline]
    fn eq(&self, other: &RopeSlice<'b>) -> bool {
        if self.len() == other.len() {
            self.bytes_eq(other.bytes())
        } else {
            false
        }
    }
}

impl<'a> cmp::PartialEq<str> for RopeSliceMut<'a> {
    /// A rope equals another rope if all the bytes in both are equal.

    #[inline]
    fn eq(&self, other: &str) -> bool {
        if self.len() == other.len() {
            self.bytes_eq(other.bytes())
        } else {
            false
        }
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    use ::Rope;

    #[test]
    fn char_indices() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(4..8);
        let string_slice = &string[4..8];
        let indices = rope_slice.char_indices().zip(string_slice.char_indices());
        for ((ridx, rch), (sidx, sch)) in indices {
            assert_eq!(rch, sch);
            assert_eq!(ridx, sidx);
        }
    }

    #[test]
    fn to() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(1..10);
        let string_slice = &string[1..10];
        assert_eq!(&rope_slice, string_slice)
    }

    // #[test]
    // fn between() {
    //     let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
    //     let rope = Rope::from(string);
    //     let rope_slice = rope.slice(1...10usize);
    //     let string_slice = &string[1...10];
    //     assert_eq!(&rope_slice, string_slice)
    // }

    #[test]
    fn until() {
        let string = "aaaaabbbbbbccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(..10);
        let string_slice = &string[..10];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn from() {
        let mut string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let mut rope = Rope::from(string);
        let rope_slice = rope.slice(5..);
        let string_slice = &string[5..];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn full() {
        let string = "aaaaabbbbbbccccccccccccdefgdefgaabababab";
        let rope = Rope::from(string);
        let rope_slice = rope.slice(..);
        let string_slice = &string[..];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn mut_char_indices() {
        let mut string =
            String::from("aaaaabbbbbbccccccccccccdefgdefgaabababab");
        let mut rope = Rope::from(string.clone());
        let rope_slice = rope.slice_mut(4..8);
        let string_slice = &mut string[4..8];
        let indices = rope_slice.char_indices().zip(string_slice.char_indices());
        for ((ridx, rch), (sidx, sch)) in indices {
            assert_eq!(rch, sch);
            assert_eq!(ridx, sidx);
        }
    }

    #[test]
    fn mut_to() {
        let mut string =
            String::from("aaaaabbbbbbccccccccccccdefgdefgaabababab");
        let mut rope = Rope::from(string.clone());
        let rope_slice = rope.slice_mut(1..10);
        let string_slice = &mut string[1..10];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn mut_until() {
        let mut string =
            String::from("aaaaabbbbbbccccccccccccdefgdefgaabababab");
        let mut rope = Rope::from(string.clone());
        let rope_slice = rope.slice_mut(..10);
        let string_slice = &mut string[..10];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn mut_from() {
        let mut string =
            String::from("aaaaabbbbbbccccccccccccdefgdefgaabababab");
        let mut rope = Rope::from(string.clone());
        let rope_slice = rope.slice_mut(5..);
        let string_slice = &mut string[5..];
        assert_eq!(&rope_slice, string_slice)
    }

    #[test]
    fn mut_full() {
        let mut string =
            String::from("aaaaabbbbbbccccccccccccdefgdefgaabababab");
        let mut rope = Rope::from(string.clone());
        let rope_slice = rope.slice_mut(..);
        let string_slice = &mut string[..];
        assert_eq!(&rope_slice, string_slice)
    }
}
<|endoftext|>


<commit_before>//! Example of basic search-and-replace functionality implemented on top
//! of Ropey.
//!
//! Usage:
//!     search_and_replace <search_pattern> <replacement_text> <input_filepath>
//!
//! The file contents with the search-and-replace performed on it is sent to
//! stdout.

extern crate ropey;

use std::fs::File;
use std::io;

use ropey::{iter::Chars, Rope, RopeSlice};

fn main() {
    // Get arguments from commandline
    let (search_pattern, replacement_text, filepath) = if std::env::args().count() > 3 {
        (
            std::env::args().nth(1).unwrap(),
            std::env::args().nth(2).unwrap(),
            std::env::args().nth(3).unwrap(),
        )
    } else {
        eprintln!(
            "Usage:\n    search_and_replace <search_pattern> <replacement_text> <input_filepath>"
        );
        return;
    };

    // Load file contents into a rope.
    let mut text = Rope::from_reader(io::BufReader::new(File::open(&filepath).unwrap())).expect("Cannot read file: either it doesn't exist, file permissions don't allow reading, or is not utf8 text.");

    // Do the search-and-replace.
    search_and_replace(&mut text, &search_pattern, &replacement_text);

    // Print the new text to stdout.
    println!("{}", text);
}

/// Searches the rope for `search_pattern` and replaces all matches with
/// `replacement_text`.
///
/// There are several ways this could be done:
///
/// 1. Clone the rope and then do the search on the original while replacing
///    on the clone.  This isn't as awful as it sounds because the clone
///    operation is constant-time and the two ropes will share most of their
///    storage in typical cases.  However, this probably isn't the best
///    general solution because it will use a lot of additional space if a
///    large percentage of the text is being replaced.
///
/// 2. A two-stage approach: first find and collect all the matches, then
///    do the replacements on the original rope.  This is a good solution
///    when a relatively small number of matches are expected.  However, if
///    there are a large number of matches then the space to store the
///    matches themselves can become large.
///
/// 3. A piece-meal approach: search for the first match, replace it, then
///    restart the search from there, repeat.  This is a good solution for
///    memory-constrained situations.  However, computationally it is likely
///    the most expensive when there are a large number of matches and there
///    are costs associated with repeatedly restarting the search.
///
/// 4. Combine approaches #2 and #3: collect a fixed number of matches and
///    replace them, then collect another batch of matches and replace them,
///    and so on.  This is probably the best general solution, because it
///    combines the best of both #2 and #3: it allows you to collect the
///    matches in a bounded amount of space, and any costs associated with
///    restarting the search are amortized over multiple matches.
///
/// In this implementation we take approach #4 because it seems the
/// all-around best.
fn search_and_replace(rope: &mut Rope, search_pattern: &str, replacement_text: &str) {
    const BATCH_SIZE: usize = 256;
    let replacement_text_len = replacement_text.chars().count();

    let mut head = 0; // Keep track of where we are between searches
    let mut matches = Vec::with_capacity(BATCH_SIZE);
    loop {
        // Collect the next batch of matches.  Note that we don't use
        // `Iterator::collect()` to collect the batch because we want to
        // re-use the same Vec to avoid unnecessary allocations.
        matches.clear();
        for m in SearchIter::from_rope_slice(&rope.slice(head..), &search_pattern).take(BATCH_SIZE)
        {
            matches.push(m);
        }

        // If there are no matches, we're done!
        if matches.is_empty() {
            break;
        }

        // Replace the collected matches.
        let mut index_diff: isize = 0;
        for &(start, end) in matches.iter() {
            // Get the properly offset indices.
            let start_d = (head as isize + start as isize + index_diff) as usize;
            let end_d = (head as isize + end as isize + index_diff) as usize;

            // Do the replacement.
            rope.remove(start_d..end_d);
            rope.insert(start_d, &replacement_text);

            // Update the index offset.
            let match_len = (end - start) as isize;
            index_diff = index_diff - match_len + replacement_text_len as isize;
        }

        // Update head for next iteration.
        head = (head as isize + index_diff + matches.last().unwrap().1 as isize) as usize;
    }
}

/// An iterator over simple textual matches in a RopeSlice.
///
/// This implementation is somewhat naive, and could be sped up by using a
/// more sophisticated text searching algorithm such as Boyer-Moore or
/// Knuth-Morris-Pratt.
///
/// The important thing, however, is the interface.  For example, a regex
/// implementation providing an equivalent interface could easily be dropped
/// in, and the search-and-replace function above would work with it quite
/// happily.
struct SearchIter<'a> {
    char_iter: Chars<'a>,
    search_pattern: &'a str,
    search_pattern_char_len: usize,
    cur_index: usize, // The current char index of the search head.
    possible_matches: Vec<std::str::Chars<'a>>, // Tracks where we are in the search pattern for the current possible matches.
}

impl<'a> SearchIter<'a> {
    fn from_rope_slice<'b>(slice: &'b RopeSlice, search_pattern: &'b str) -> SearchIter<'b> {
        assert!(
            !search_pattern.is_empty(),
            "Can't search using an empty search pattern."
        );
        SearchIter {
            char_iter: slice.chars(),
            search_pattern: search_pattern,
            search_pattern_char_len: search_pattern.chars().count(),
            cur_index: 0,
            possible_matches: Vec::new(),
        }
    }
}

impl<'a> Iterator for SearchIter<'a> {
    type Item = (usize, usize);

    // Return the start/end char indices of the next match.
    fn next(&mut self) -> Option<(usize, usize)> {
        while let Some(next_char) = self.char_iter.next() {
            self.cur_index += 1;

            // Push new potential match, for a possible match starting at the
            // current char.
            self.possible_matches.push(self.search_pattern.chars());

            // Check the rope's char against the next character in each of
            // the potential matches, removing the potential matches that
            // don't match.  We're using indexing instead of iteration here
            // so that we can remove the possible matches as we go.
            let mut i = 0;
            while i < self.possible_matches.len() {
                let pattern_char = self.possible_matches[i].next().unwrap();
                if next_char == pattern_char {
                    if self.possible_matches[i].clone().next() == None {
                        // We have a match!  Reset possible matches and
                        // return the successful match's char indices.
                        let char_match_range = (
                            self.cur_index - self.search_pattern_char_len,
                            self.cur_index,
                        );
                        self.possible_matches.clear();
                        return Some(char_match_range);
                    } else {
                        // Match isn't complete yet, move on to the next.
                        i += 1;
                    }
                } else {
                    // Doesn't match, remove it.
                    self.possible_matches.swap_remove(i);
                }
            }
        }

        None
    }
}
<commit_msg>Silence warning in the search_and_replace example.<commit_after>//! Example of basic search-and-replace functionality implemented on top
//! of Ropey.
//!
//! Usage:
//!     search_and_replace <search_pattern> <replacement_text> <input_filepath>
//!
//! The file contents with the search-and-replace performed on it is sent to
//! stdout.

extern crate ropey;

use std::fs::File;
use std::io;

use ropey::{iter::Chars, Rope, RopeSlice};

fn main() {
    // Get arguments from commandline
    let (search_pattern, replacement_text, filepath) = if std::env::args().count() > 3 {
        (
            std::env::args().nth(1).unwrap(),
            std::env::args().nth(2).unwrap(),
            std::env::args().nth(3).unwrap(),
        )
    } else {
        eprintln!(
            "Usage:\n    search_and_replace <search_pattern> <replacement_text> <input_filepath>"
        );
        return;
    };

    // Load file contents into a rope.
    let mut text = Rope::from_reader(io::BufReader::new(File::open(&filepath).unwrap())).expect("Cannot read file: either it doesn't exist, file permissions don't allow reading, or is not utf8 text.");

    // Do the search-and-replace.
    search_and_replace(&mut text, &search_pattern, &replacement_text);

    // Print the new text to stdout.
    println!("{}", text);
}

/// Searches the rope for `search_pattern` and replaces all matches with
/// `replacement_text`.
///
/// There are several ways this could be done:
///
/// 1. Clone the rope and then do the search on the original while replacing
///    on the clone.  This isn't as awful as it sounds because the clone
///    operation is constant-time and the two ropes will share most of their
///    storage in typical cases.  However, this probably isn't the best
///    general solution because it will use a lot of additional space if a
///    large percentage of the text is being replaced.
///
/// 2. A two-stage approach: first find and collect all the matches, then
///    do the replacements on the original rope.  This is a good solution
///    when a relatively small number of matches are expected.  However, if
///    there are a large number of matches then the space to store the
///    matches themselves can become large.
///
/// 3. A piece-meal approach: search for the first match, replace it, then
///    restart the search from there, repeat.  This is a good solution for
///    memory-constrained situations.  However, computationally it is likely
///    the most expensive when there are a large number of matches and there
///    are costs associated with repeatedly restarting the search.
///
/// 4. Combine approaches #2 and #3: collect a fixed number of matches and
///    replace them, then collect another batch of matches and replace them,
///    and so on.  This is probably the best general solution, because it
///    combines the best of both #2 and #3: it allows you to collect the
///    matches in a bounded amount of space, and any costs associated with
///    restarting the search are amortized over multiple matches.
///
/// In this implementation we take approach #4 because it seems the
/// all-around best.
fn search_and_replace(rope: &mut Rope, search_pattern: &str, replacement_text: &str) {
    const BATCH_SIZE: usize = 256;
    let replacement_text_len = replacement_text.chars().count();

    let mut head = 0; // Keep track of where we are between searches
    let mut matches = Vec::with_capacity(BATCH_SIZE);
    loop {
        // Collect the next batch of matches.  Note that we don't use
        // `Iterator::collect()` to collect the batch because we want to
        // re-use the same Vec to avoid unnecessary allocations.
        matches.clear();
        for m in SearchIter::from_rope_slice(&rope.slice(head..), &search_pattern).take(BATCH_SIZE)
        {
            matches.push(m);
        }

        // If there are no matches, we're done!
        if matches.is_empty() {
            break;
        }

        // Replace the collected matches.
        let mut index_diff: isize = 0;
        for &(start, end) in matches.iter() {
            // Get the properly offset indices.
            let start_d = (head as isize + start as isize + index_diff) as usize;
            let end_d = (head as isize + end as isize + index_diff) as usize;

            // Do the replacement.
            rope.remove(start_d..end_d);
            rope.insert(start_d, &replacement_text);

            // Update the index offset.
            let match_len = (end - start) as isize;
            index_diff = index_diff - match_len + replacement_text_len as isize;
        }

        // Update head for next iteration.
        head = (head as isize + index_diff + matches.last().unwrap().1 as isize) as usize;
    }
}

/// An iterator over simple textual matches in a RopeSlice.
///
/// This implementation is somewhat naive, and could be sped up by using a
/// more sophisticated text searching algorithm such as Boyer-Moore or
/// Knuth-Morris-Pratt.
///
/// The important thing, however, is the interface.  For example, a regex
/// implementation providing an equivalent interface could easily be dropped
/// in, and the search-and-replace function above would work with it quite
/// happily.
struct SearchIter<'a> {
    char_iter: Chars<'a>,
    search_pattern: &'a str,
    search_pattern_char_len: usize,
    cur_index: usize, // The current char index of the search head.
    possible_matches: Vec<std::str::Chars<'a>>, // Tracks where we are in the search pattern for the current possible matches.
}

impl<'a> SearchIter<'a> {
    fn from_rope_slice<'b>(slice: &'b RopeSlice, search_pattern: &'b str) -> SearchIter<'b> {
        assert!(
            !search_pattern.is_empty(),
            "Can't search using an empty search pattern."
        );
        SearchIter {
            char_iter: slice.chars(),
            search_pattern: search_pattern,
            search_pattern_char_len: search_pattern.chars().count(),
            cur_index: 0,
            possible_matches: Vec::new(),
        }
    }
}

impl<'a> Iterator for SearchIter<'a> {
    type Item = (usize, usize);

    // Return the start/end char indices of the next match.
    fn next(&mut self) -> Option<(usize, usize)> {
        while let Some(next_char) = self.char_iter.next() {
            self.cur_index += 1;

            // Push new potential match, for a possible match starting at the
            // current char.
            self.possible_matches.push(self.search_pattern.chars());

            // Check the rope's char against the next character in each of
            // the potential matches, removing the potential matches that
            // don't match.  We're using indexing instead of iteration here
            // so that we can remove the possible matches as we go.
            let mut i = 0;
            while i < self.possible_matches.len() {
                let pattern_char = self.possible_matches[i].next().unwrap();
                if next_char == pattern_char {
                    if self.possible_matches[i].clone().next() == None {
                        // We have a match!  Reset possible matches and
                        // return the successful match's char indices.
                        let char_match_range = (
                            self.cur_index - self.search_pattern_char_len,
                            self.cur_index,
                        );
                        self.possible_matches.clear();
                        return Some(char_match_range);
                    } else {
                        // Match isn't complete yet, move on to the next.
                        i += 1;
                    }
                } else {
                    // Doesn't match, remove it.
                    let _ = self.possible_matches.swap_remove(i);
                }
            }
        }

        None
    }
}
<|endoftext|>


<commit_before>//! Trap codes describing the reason for a trap.

use std::fmt::{self, Display, Formatter};
use std::str::FromStr;

/// A trap code describing the reason for a trap.
///
/// All trap instructions have an explicit trap code.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum TrapCode {
    /// The current stack space was exhausted.
    ///
    /// On some platforms, a stack overflow may also be indicated by a segmentation fault from the
    /// stack guard page.
    StackOverflow,

    /// A `heap_addr` instruction detected an out-of-bounds error.
    ///
    /// Some out-of-bounds heap accesses are detected by a segmentation fault on the heap guard
    /// pages.
    HeapOutOfBounds,

    /// An integer arithmetic operation caused an overflow.
    IntegerOverflow,

    /// An integer division by zero.
    IntegerDivisionByZero,

    /// A user-defined trap code.
    User(u16),
}

impl Display for TrapCode {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        use self::TrapCode::*;
        let identifier = match *self {
            StackOverflow => "stk_ovf",
            HeapOutOfBounds => "heap_oob",
            IntegerOverflow => "int_ovf",
            IntegerDivisionByZero => "int_divz",
            User(x) => return write!(f, "user{}", x),
        };
        f.write_str(identifier)
    }
}

impl FromStr for TrapCode {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use self::TrapCode::*;
        match s {
            "stk_ovf" => Ok(StackOverflow),
            "heap_oob" => Ok(HeapOutOfBounds),
            "int_ovf" => Ok(IntegerOverflow),
            "int_divz" => Ok(IntegerDivisionByZero),
            _ if s.starts_with("user") => s[4..].parse().map(User).map_err(|_| ()),
            _ => Err(()),
        }
    }
}

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

    // Everything but user-defined codes.
    const CODES: [TrapCode; 4] = [
        TrapCode::StackOverflow,
        TrapCode::HeapOutOfBounds,
        TrapCode::IntegerOverflow,
        TrapCode::IntegerDivisionByZero,
    ];

    #[test]
    fn display() {
        for r in &CODES {
            let tc = *r;
            assert_eq!(tc.to_string().parse(), Ok(tc));
        }
        assert_eq!("bogus".parse::<TrapCode>(), Err(()));

        assert_eq!(TrapCode::User(17).to_string(), "user17");
        assert_eq!("user22".parse(), Ok(TrapCode::User(22)));
        assert_eq!("user".parse::<TrapCode>(), Err(()));
        assert_eq!("user-1".parse::<TrapCode>(), Err(()));
        assert_eq!("users".parse::<TrapCode>(), Err(()));
    }
}
<commit_msg>Add more trap codes.<commit_after>//! Trap codes describing the reason for a trap.

use std::fmt::{self, Display, Formatter};
use std::str::FromStr;

/// A trap code describing the reason for a trap.
///
/// All trap instructions have an explicit trap code.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum TrapCode {
    /// The current stack space was exhausted.
    ///
    /// On some platforms, a stack overflow may also be indicated by a segmentation fault from the
    /// stack guard page.
    StackOverflow,

    /// A `heap_addr` instruction detected an out-of-bounds error.
    ///
    /// Some out-of-bounds heap accesses are detected by a segmentation fault on the heap guard
    /// pages.
    HeapOutOfBounds,

    /// Other bounds checking error.
    OutOfBounds,

    /// Indirect call to a null table entry.
    IndirectCallToNull,

    /// Signature mismatch on indirect call.
    BadSignature,

    /// An integer arithmetic operation caused an overflow.
    IntegerOverflow,

    /// An integer division by zero.
    IntegerDivisionByZero,

    /// Failed float-to-int conversion.
    BadConversionToInteger,

    /// A user-defined trap code.
    User(u16),
}

impl Display for TrapCode {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        use self::TrapCode::*;
        let identifier = match *self {
            StackOverflow => "stk_ovf",
            HeapOutOfBounds => "heap_oob",
            OutOfBounds => "oob",
            IndirectCallToNull => "icall_null",
            BadSignature => "bad_sig",
            IntegerOverflow => "int_ovf",
            IntegerDivisionByZero => "int_divz",
            BadConversionToInteger => "bad_toint",
            User(x) => return write!(f, "user{}", x),
        };
        f.write_str(identifier)
    }
}

impl FromStr for TrapCode {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use self::TrapCode::*;
        match s {
            "stk_ovf" => Ok(StackOverflow),
            "heap_oob" => Ok(HeapOutOfBounds),
            "oob" => Ok(OutOfBounds),
            "icall_null" => Ok(IndirectCallToNull),
            "bad_sig" => Ok(BadSignature),
            "int_ovf" => Ok(IntegerOverflow),
            "int_divz" => Ok(IntegerDivisionByZero),
            "bad_toint" => Ok(BadConversionToInteger),
            _ if s.starts_with("user") => s[4..].parse().map(User).map_err(|_| ()),
            _ => Err(()),
        }
    }
}

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

    // Everything but user-defined codes.
    const CODES: [TrapCode; 8] = [
        TrapCode::StackOverflow,
        TrapCode::HeapOutOfBounds,
        TrapCode::OutOfBounds,
        TrapCode::IndirectCallToNull,
        TrapCode::BadSignature,
        TrapCode::IntegerOverflow,
        TrapCode::IntegerDivisionByZero,
        TrapCode::BadConversionToInteger,
    ];

    #[test]
    fn display() {
        for r in &CODES {
            let tc = *r;
            assert_eq!(tc.to_string().parse(), Ok(tc));
        }
        assert_eq!("bogus".parse::<TrapCode>(), Err(()));

        assert_eq!(TrapCode::User(17).to_string(), "user17");
        assert_eq!("user22".parse(), Ok(TrapCode::User(22)));
        assert_eq!("user".parse::<TrapCode>(), Err(()));
        assert_eq!("user-1".parse::<TrapCode>(), Err(()));
        assert_eq!("users".parse::<TrapCode>(), Err(()));
    }
}
<|endoftext|>


<commit_before>//! Parallelization features for ndarray.
//!
//! The array views and references to owned arrays all implement
//! `IntoParallelIterator`; the default parallel iterators (each element by
//! reference or mutable reference) have no ordering guarantee in their parallel
//! implementations.
//!
//! `.axis_iter()` and `.axis_iter_mut()` also have parallel counterparts.
//!
//! # Examples
//!
//! Compute the exponential of each element in an array, parallelized.
//!
//! ```
//! extern crate ndarray;
//! extern crate ndarray_parallel;
//!
//! use ndarray::Array2;
//! use ndarray_parallel::prelude::*;
//!
//! fn main() {
//!     let mut a = Array2::<f64>::zeros((128, 128));
//!     a.par_iter_mut().for_each(|x| *x = x.exp());
//! }
//! ```
//!
//! Use the parallel `.axis_iter()` to compute the sum of each row.
//!
//! ```
//! extern crate ndarray;
//! extern crate ndarray_parallel;
//!
//! use ndarray::Array;
//! use ndarray::Axis;
//! use ndarray_parallel::prelude::*;
//!
//! fn main() {
//!     let a = Array::linspace(0., 63., 64).into_shape((4, 16)).unwrap();
//!     let mut sums = Vec::new();
//!     a.axis_iter(Axis(0))
//!      .into_par_iter()
//!      .map(|row| row.scalar_sum())
//!      .collect_into(&mut sums);
//!
//!     assert_eq!(sums, [120., 376., 632., 888.]);
//! }
//! ```

extern crate ndarray;
extern crate rayon;

pub mod prelude {
    // happy and insane; ignorance is bluss
    pub use NdarrayIntoParallelIterator;
    pub use NdarrayIntoParallelRefIterator;
    pub use NdarrayIntoParallelRefMutIterator;

    #[doc(no_inline)]
    pub use rayon::prelude::{ParallelIterator, ExactParallelIterator};
}

pub use par::Parallel;
pub use into_traits::{
    NdarrayIntoParallelIterator,
    NdarrayIntoParallelRefIterator,
    NdarrayIntoParallelRefMutIterator,
};

mod par;
mod into_traits;
mod into_impls;
<commit_msg>parallel: Edit docs<commit_after>//! Parallelization features for ndarray.
//!
//! The array views and references to owned arrays all implement
//! `NdarrayIntoParallelIterator` (*); the default parallel iterators (each element
//! by reference or mutable reference) have no ordering guarantee in their
//! parallel implementations.
//!
//! `.axis_iter()` and `.axis_iter_mut()` also have parallel counterparts.
//!
//! (*) This regime of a custom trait instead of rayon’s own is since we
//! use this intermediate ndarray-parallel crate.
//!
//! # Examples
//!
//! Compute the exponential of each element in an array, parallelized.
//!
//! ```
//! extern crate ndarray;
//! extern crate ndarray_parallel;
//!
//! use ndarray::Array2;
//! use ndarray_parallel::prelude::*;
//!
//! fn main() {
//!     let mut a = Array2::<f64>::zeros((128, 128));
//!     a.par_iter_mut().for_each(|x| *x = x.exp());
//! }
//! ```
//!
//! Use the parallel `.axis_iter()` to compute the sum of each row.
//!
//! ```
//! extern crate ndarray;
//! extern crate ndarray_parallel;
//!
//! use ndarray::Array;
//! use ndarray::Axis;
//! use ndarray_parallel::prelude::*;
//!
//! fn main() {
//!     let a = Array::linspace(0., 63., 64).into_shape((4, 16)).unwrap();
//!     let mut sums = Vec::new();
//!     a.axis_iter(Axis(0))
//!      .into_par_iter()
//!      .map(|row| row.scalar_sum())
//!      .collect_into(&mut sums);
//!
//!     assert_eq!(sums, [120., 376., 632., 888.]);
//! }
//! ```

extern crate ndarray;
extern crate rayon;

/// Into- traits for creating parallelized iterators.
pub mod prelude {
    // happy and insane; ignorance is bluss
    pub use NdarrayIntoParallelIterator;
    pub use NdarrayIntoParallelRefIterator;
    pub use NdarrayIntoParallelRefMutIterator;

    #[doc(no_inline)]
    pub use rayon::prelude::{ParallelIterator, ExactParallelIterator};
}

pub use par::Parallel;
pub use into_traits::{
    NdarrayIntoParallelIterator,
    NdarrayIntoParallelRefIterator,
    NdarrayIntoParallelRefMutIterator,
};

mod par;
mod into_traits;
mod into_impls;
<|endoftext|>


<commit_before>use fizzy::*;

macro_rules! expect {
    () => {
        vec![
            "1", "2", "fizz", "4", "buzz", "fizz", "7", "8", "fizz", "buzz", "11", "fizz", "13",
            "14", "fizzbuzz", "16",
        ]
    };
}

#[test]
fn test_simple() {
    let got = fizz_buzz::<i32>().apply(1..=16).collect::<Vec<_>>();
    assert_eq!(expect!(), got);
}

#[test]
#[ignore]
fn test_u8() {
    let got = fizz_buzz::<u8>().apply(1_u8..=16).collect::<Vec<_>>();
    assert_eq!(expect!(), got);
}

#[test]
#[ignore]
fn test_u64() {
    let got = fizz_buzz::<u64>().apply(1_u64..=16).collect::<Vec<_>>();
    assert_eq!(expect!(), got);
}

#[test]
#[ignore]
fn test_nonsequential() {
    let collatz_12 = &[12, 6, 3, 10, 5, 16, 8, 4, 2, 1];
    let expect = vec![
        "fizz", "fizz", "fizz", "buzz", "buzz", "16", "8", "4", "2", "1",
    ];
    let got = fizz_buzz::<i32>()
        .apply(collatz_12.into_iter().cloned())
        .collect::<Vec<_>>();
    assert_eq!(expect, got);
}

#[test]
#[ignore]
fn test_custom() {
    let expect = vec![
        "1", "2", "Fizz", "4", "Buzz", "Fizz", "Bam", "8", "Fizz", "Buzz", "11", "Fizz", "13",
        "Bam", "BuzzFizz", "16",
    ];
    let fizzer: Fizzy<i32> = Fizzy::new()
        .add_matcher(Matcher::new(|n: i32| n % 5 == 0, "Buzz"))
        .add_matcher(Matcher::new(|n: i32| n % 3 == 0, "Fizz"))
        .add_matcher(Matcher::new(|n: i32| n % 7 == 0, "Bam"));
    let got = fizzer.apply(1..=16).collect::<Vec<_>>();
    assert_eq!(expect, got);
}

#[test]
#[ignore]
fn test_f64() {
    // a tiny bit more complicated becuase range isn't natively implemented on floats
    // NOTE: this test depends on a language feature introduced in Rust 1.34. If you
    // have an older compiler, upgrade. If you have an older compiler and cannot upgrade,
    // feel free to ignore this test.
    let got = fizz_buzz::<f64>()
        .apply(std::iter::successors(Some(1.0), |prev| Some(prev + 1.0)))
        .take(16)
        .collect::<Vec<_>>();
    assert_eq!(expect!(), got);
}

#[test]
#[ignore]
fn test_minimal_generic_bounds() {
    // NOTE: this test depends on a language feature introduced in Rust 1.34. If you
    // have an older compiler, upgrade. If you have an older compiler and cannot upgrade,
    // feel free to ignore this test.
    use std::fmt;
    use std::ops::{Add, Rem};

    #[derive(Clone, Copy, Debug, Default, PartialEq)]
    struct Fizzable(u8);

    impl From<u8> for Fizzable {
        fn from(i: u8) -> Fizzable {
            Fizzable(i)
        }
    }

    impl fmt::Display for Fizzable {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            let Fizzable(ref n) = self;
            write!(f, "{}", n)
        }
    }

    impl Add for Fizzable {
        type Output = Fizzable;
        fn add(self, rhs: Fizzable) -> Fizzable {
            let Fizzable(n1) = self;
            let Fizzable(n2) = rhs;
            Fizzable(n1 + n2)
        }
    }

    impl Rem for Fizzable {
        type Output = Fizzable;
        fn rem(self, rhs: Fizzable) -> Fizzable {
            let Fizzable(n1) = self;
            let Fizzable(n2) = rhs;
            Fizzable(n1 % n2)
        }
    }

    let got = fizz_buzz::<Fizzable>()
        .apply(std::iter::successors(Some(Fizzable(1)), |prev| {
            Some(*prev + 1.into())
        }))
        .take(16)
        .collect::<Vec<_>>();
    assert_eq!(expect!(), got);
}
<commit_msg>fizzy: iter instead of into_iter (#1004)<commit_after>use fizzy::*;

macro_rules! expect {
    () => {
        vec![
            "1", "2", "fizz", "4", "buzz", "fizz", "7", "8", "fizz", "buzz", "11", "fizz", "13",
            "14", "fizzbuzz", "16",
        ]
    };
}

#[test]
fn test_simple() {
    let got = fizz_buzz::<i32>().apply(1..=16).collect::<Vec<_>>();
    assert_eq!(expect!(), got);
}

#[test]
#[ignore]
fn test_u8() {
    let got = fizz_buzz::<u8>().apply(1_u8..=16).collect::<Vec<_>>();
    assert_eq!(expect!(), got);
}

#[test]
#[ignore]
fn test_u64() {
    let got = fizz_buzz::<u64>().apply(1_u64..=16).collect::<Vec<_>>();
    assert_eq!(expect!(), got);
}

#[test]
#[ignore]
fn test_nonsequential() {
    let collatz_12 = &[12, 6, 3, 10, 5, 16, 8, 4, 2, 1];
    let expect = vec![
        "fizz", "fizz", "fizz", "buzz", "buzz", "16", "8", "4", "2", "1",
    ];
    let got = fizz_buzz::<i32>()
        .apply(collatz_12.iter().cloned())
        .collect::<Vec<_>>();
    assert_eq!(expect, got);
}

#[test]
#[ignore]
fn test_custom() {
    let expect = vec![
        "1", "2", "Fizz", "4", "Buzz", "Fizz", "Bam", "8", "Fizz", "Buzz", "11", "Fizz", "13",
        "Bam", "BuzzFizz", "16",
    ];
    let fizzer: Fizzy<i32> = Fizzy::new()
        .add_matcher(Matcher::new(|n: i32| n % 5 == 0, "Buzz"))
        .add_matcher(Matcher::new(|n: i32| n % 3 == 0, "Fizz"))
        .add_matcher(Matcher::new(|n: i32| n % 7 == 0, "Bam"));
    let got = fizzer.apply(1..=16).collect::<Vec<_>>();
    assert_eq!(expect, got);
}

#[test]
#[ignore]
fn test_f64() {
    // a tiny bit more complicated becuase range isn't natively implemented on floats
    // NOTE: this test depends on a language feature introduced in Rust 1.34. If you
    // have an older compiler, upgrade. If you have an older compiler and cannot upgrade,
    // feel free to ignore this test.
    let got = fizz_buzz::<f64>()
        .apply(std::iter::successors(Some(1.0), |prev| Some(prev + 1.0)))
        .take(16)
        .collect::<Vec<_>>();
    assert_eq!(expect!(), got);
}

#[test]
#[ignore]
fn test_minimal_generic_bounds() {
    // NOTE: this test depends on a language feature introduced in Rust 1.34. If you
    // have an older compiler, upgrade. If you have an older compiler and cannot upgrade,
    // feel free to ignore this test.
    use std::fmt;
    use std::ops::{Add, Rem};

    #[derive(Clone, Copy, Debug, Default, PartialEq)]
    struct Fizzable(u8);

    impl From<u8> for Fizzable {
        fn from(i: u8) -> Fizzable {
            Fizzable(i)
        }
    }

    impl fmt::Display for Fizzable {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            let Fizzable(ref n) = self;
            write!(f, "{}", n)
        }
    }

    impl Add for Fizzable {
        type Output = Fizzable;
        fn add(self, rhs: Fizzable) -> Fizzable {
            let Fizzable(n1) = self;
            let Fizzable(n2) = rhs;
            Fizzable(n1 + n2)
        }
    }

    impl Rem for Fizzable {
        type Output = Fizzable;
        fn rem(self, rhs: Fizzable) -> Fizzable {
            let Fizzable(n1) = self;
            let Fizzable(n2) = rhs;
            Fizzable(n1 % n2)
        }
    }

    let got = fizz_buzz::<Fizzable>()
        .apply(std::iter::successors(Some(Fizzable(1)), |prev| {
            Some(*prev + 1.into())
        }))
        .take(16)
        .collect::<Vec<_>>();
    assert_eq!(expect!(), got);
}
<|endoftext|>


<commit_before>pub fn raindrops(n: usize) -> String {
    unimplemented!()
}
<commit_msg>raindrops: eliminate stub warnings<commit_after>pub fn raindrops(n: usize) -> String {
    unimplemented!("what sound does Raindrop #{} make?", n)
}
<|endoftext|>


<commit_before>//! [GET /_matrix/federation/v1/event/{eventId}](https://matrix.org/docs/spec/server_server/r0.1.4#get-matrix-federation-v1-event-eventid)

use ruma_api::ruma_api;
use ruma_events::pdu::Pdu;
use ruma_identifiers::{EventId, ServerNameBox};
use std::time::SystemTime;

ruma_api! {
    metadata: {
        description: "Retrieves a single event.",
        method: GET,
        name: "get_event",
        path: "/_matrix/federation/v1/event/:event_id",
        rate_limited: false,
        authentication: ServerSignatures,
    }

    request: {
        /// The event ID to get.
        #[ruma_api(path)]
        pub event_id: &'a EventId,
    }

    response: {
        /// The `server_name` of the homeserver sending this transaction.
        pub origin: ServerNameBox,

        /// Time on originating homeserver when this transaction started.
        #[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
        pub origin_server_ts: SystemTime,

        /// The event.
        #[serde(rename = "pdus", with = "ruma_serde::single_element_seq")]
        pub pdu: Pdu,
    }
}

impl<'a> Request<'a> {
    /// Creates a new `Request` with the given event id.
    pub fn new(event_id: &'a EventId) -> Self {
        Self { event_id }
    }
}

impl Response {
    /// Creates a new `Response` with the given server name, timestamp, and event.
    pub fn new(origin: ServerNameBox, origin_server_ts: SystemTime, pdu: Pdu) -> Self {
        Self { origin, origin_server_ts, pdu }
    }
}
<commit_msg>Use Raw<Pdu> in get_event Response over Pdu<commit_after>//! [GET /_matrix/federation/v1/event/{eventId}](https://matrix.org/docs/spec/server_server/r0.1.4#get-matrix-federation-v1-event-eventid)

use std::time::SystemTime;

use ruma_api::ruma_api;
use ruma_events::pdu::Pdu;
use ruma_identifiers::{EventId, ServerNameBox};
use ruma_serde::Raw;

ruma_api! {
    metadata: {
        description: "Retrieves a single event.",
        method: GET,
        name: "get_event",
        path: "/_matrix/federation/v1/event/:event_id",
        rate_limited: false,
        authentication: ServerSignatures,
    }

    request: {
        /// The event ID to get.
        #[ruma_api(path)]
        pub event_id: &'a EventId,
    }

    response: {
        /// The `server_name` of the homeserver sending this transaction.
        pub origin: ServerNameBox,

        /// Time on originating homeserver when this transaction started.
        #[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
        pub origin_server_ts: SystemTime,

        /// The event.
        #[serde(rename = "pdus", with = "ruma_serde::single_element_seq")]
        pub pdu: Raw<Pdu>,
    }
}

impl<'a> Request<'a> {
    /// Creates a new `Request` with the given event id.
    pub fn new(event_id: &'a EventId) -> Self {
        Self { event_id }
    }
}

impl Response {
    /// Creates a new `Response` with the given server name, timestamp, and event.
    pub fn new(origin: ServerNameBox, origin_server_ts: SystemTime, pdu: Raw<Pdu>) -> Self {
        Self { origin, origin_server_ts, pdu }
    }
}
<|endoftext|>


<commit_before>use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::higher;
use clippy_utils::is_lang_ctor;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{eq_expr_value, path_to_local, path_to_local_id};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultOk};
use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, PatKind, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;

declare_clippy_lint! {
    /// ### What it does
    /// Checks for expressions that could be replaced by the question mark operator.
    ///
    /// ### Why is this bad?
    /// Question mark usage is more idiomatic.
    ///
    /// ### Example
    /// ```ignore
    /// if option.is_none() {
    ///     return None;
    /// }
    /// ```
    ///
    /// Could be written:
    ///
    /// ```ignore
    /// option?;
    /// ```
    pub QUESTION_MARK,
    style,
    "checks for expressions that could be replaced by the question mark operator"
}

declare_lint_pass!(QuestionMark => [QUESTION_MARK]);

impl QuestionMark {
    /// Checks if the given expression on the given context matches the following structure:
    ///
    /// ```ignore
    /// if option.is_none() {
    ///    return None;
    /// }
    /// ```
    ///
    /// ```ignore
    /// if result.is_err() {
    ///     return result;
    /// }
    /// ```
    ///
    /// If it matches, it will suggest to use the question mark operator instead
    fn check_is_none_or_err_and_early_return(cx: &LateContext<'_>, expr: &Expr<'_>) {
        if_chain! {
            if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr);
            if let ExprKind::MethodCall(segment, _, args, _) = &cond.kind;
            if let Some(subject) = args.get(0);
            if (Self::is_option(cx, subject)
                && Self::expression_returns_none(cx, then)
                && segment.ident.name == sym!(is_none))
                ||
                (Self::is_result(cx, subject)
                && Self::expression_returns_unmodified_err(cx, then, subject)
                && segment.ident.name == sym!(is_err));
            then {
                let mut applicability = Applicability::MachineApplicable;
                let receiver_str = &Sugg::hir_with_applicability(cx, subject, "..", &mut applicability);
                let mut replacement: Option<String> = None;
                if let Some(else_inner) = r#else {
                    if_chain! {
                        if let ExprKind::Block(block, None) = &else_inner.kind;
                        if block.stmts.is_empty();
                        if let Some(block_expr) = &block.expr;
                        if eq_expr_value(cx, subject, block_expr);
                        then {
                            replacement = Some(format!("Some({}?)", receiver_str));
                        }
                    }
                } else if Self::moves_by_default(cx, subject)
                    && !matches!(subject.kind, ExprKind::Call(..) | ExprKind::MethodCall(..))
                {
                    replacement = Some(format!("{}.as_ref()?;", receiver_str));
                } else {
                    replacement = Some(format!("{}?;", receiver_str));
                }

                if let Some(replacement_str) = replacement {
                    span_lint_and_sugg(
                        cx,
                        QUESTION_MARK,
                        expr.span,
                        "this block may be rewritten with the `?` operator",
                        "replace it with",
                        replacement_str,
                        applicability,
                    );
                }
            }
        }
    }

    fn check_if_let_some_or_err_and_early_return(cx: &LateContext<'_>, expr: &Expr<'_>) {
        if_chain! {
            if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: Some(if_else) })
                = higher::IfLet::hir(cx, expr);
            if let PatKind::TupleStruct(ref path1, fields, None) = let_pat.kind;
            if (Self::is_option(cx, let_expr)
                && Self::expression_returns_none(cx, if_else)
                && is_lang_ctor(cx, path1, OptionSome))
                ||
                (Self::is_result(cx, let_expr)
                 && Self::expression_returns_unmodified_err(cx, if_else, let_expr)
                 && is_lang_ctor(cx, path1, ResultOk));

            if let PatKind::Binding(annot, bind_id, _, _) = fields[0].kind;
            let by_ref = matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut);
            if let ExprKind::Block(block, None) = if_then.kind;
            if block.stmts.is_empty();
            if let Some(trailing_expr) = &block.expr;
            if path_to_local_id(trailing_expr, bind_id);
            then {
                let mut applicability = Applicability::MachineApplicable;
                let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
                let replacement = format!("{}{}?", receiver_str, if by_ref { ".as_ref()" } else { "" },);

                span_lint_and_sugg(
                    cx,
                    QUESTION_MARK,
                    expr.span,
                    "this if-let-else may be rewritten with the `?` operator",
                    "replace it with",
                    replacement,
                    applicability,
                );
            }
        }
    }

    fn moves_by_default(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool {
        let expr_ty = cx.typeck_results().expr_ty(expression);

        !expr_ty.is_copy_modulo_regions(cx.tcx.at(expression.span), cx.param_env)
    }

    fn is_option(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool {
        let expr_ty = cx.typeck_results().expr_ty(expression);

        is_type_diagnostic_item(cx, expr_ty, sym::Option)
    }

    fn is_result(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool {
        let expr_ty = cx.typeck_results().expr_ty(expression);

        is_type_diagnostic_item(cx, expr_ty, sym::Result)
    }

    fn expression_returns_none(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool {
        match expression.kind {
            ExprKind::Block(block, _) => {
                if let Some(return_expression) = Self::return_expression(block) {
                    return Self::expression_returns_none(cx, return_expression);
                }

                false
            },
            ExprKind::Ret(Some(expr)) => Self::expression_returns_none(cx, expr),
            ExprKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone),
            _ => false,
        }
    }

    fn expression_returns_unmodified_err(
        cx: &LateContext<'_>,
        expression: &Expr<'_>,
        origin_hir_id: &Expr<'_>,
    ) -> bool {
        match expression.kind {
            ExprKind::Block(block, _) => {
                if let Some(return_expression) = Self::return_expression(block) {
                    return Self::expression_returns_unmodified_err(cx, return_expression, origin_hir_id);
                }

                false
            },
            ExprKind::Ret(Some(expr)) | ExprKind::Call(expr, _) => {
                Self::expression_returns_unmodified_err(cx, expr, origin_hir_id)
            },
            ExprKind::Path(_) => path_to_local(expression) == path_to_local(origin_hir_id),
            _ => false,
        }
    }

    fn return_expression<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> {
        // Check if last expression is a return statement. Then, return the expression
        if_chain! {
            if block.stmts.len() == 1;
            if let Some(expr) = block.stmts.iter().last();
            if let StmtKind::Semi(expr) = expr.kind;
            if let ExprKind::Ret(Some(ret_expr)) = expr.kind;

            then {
                return Some(ret_expr);
            }
        }

        // Check for `return` without a semicolon.
        if_chain! {
            if block.stmts.is_empty();
            if let Some(ExprKind::Ret(Some(ret_expr))) = block.expr.as_ref().map(|e| &e.kind);
            then {
                return Some(ret_expr);
            }
        }

        None
    }
}

impl<'tcx> LateLintPass<'tcx> for QuestionMark {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        Self::check_is_none_or_err_and_early_return(cx, expr);
        Self::check_if_let_some_or_err_and_early_return(cx, expr);
    }
}
<commit_msg>Small refactor on `question_mark` condition checks<commit_after>use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::higher;
use clippy_utils::is_lang_ctor;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{eq_expr_value, path_to_local, path_to_local_id};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultOk};
use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, PatKind, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;

declare_clippy_lint! {
    /// ### What it does
    /// Checks for expressions that could be replaced by the question mark operator.
    ///
    /// ### Why is this bad?
    /// Question mark usage is more idiomatic.
    ///
    /// ### Example
    /// ```ignore
    /// if option.is_none() {
    ///     return None;
    /// }
    /// ```
    ///
    /// Could be written:
    ///
    /// ```ignore
    /// option?;
    /// ```
    pub QUESTION_MARK,
    style,
    "checks for expressions that could be replaced by the question mark operator"
}

declare_lint_pass!(QuestionMark => [QUESTION_MARK]);

impl QuestionMark {
    /// Checks if the given expression on the given context matches the following structure:
    ///
    /// ```ignore
    /// if option.is_none() {
    ///    return None;
    /// }
    /// ```
    ///
    /// ```ignore
    /// if result.is_err() {
    ///     return result;
    /// }
    /// ```
    ///
    /// If it matches, it will suggest to use the question mark operator instead
    fn check_is_none_or_err_and_early_return(cx: &LateContext<'_>, expr: &Expr<'_>) {
        if_chain! {
            if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr);
            if let ExprKind::MethodCall(segment, _, args, _) = &cond.kind;
            if let Some(subject) = args.get(0);
            if (Self::option_check_and_early_return(cx, subject, then) && segment.ident.name == sym!(is_none)) ||
                (Self::result_check_and_early_return(cx, subject, then) && segment.ident.name == sym!(is_err));
            then {
                let mut applicability = Applicability::MachineApplicable;
                let receiver_str = &Sugg::hir_with_applicability(cx, subject, "..", &mut applicability);
                let mut replacement: Option<String> = None;
                if let Some(else_inner) = r#else {
                    if_chain! {
                        if let ExprKind::Block(block, None) = &else_inner.kind;
                        if block.stmts.is_empty();
                        if let Some(block_expr) = &block.expr;
                        if eq_expr_value(cx, subject, block_expr);
                        then {
                            replacement = Some(format!("Some({}?)", receiver_str));
                        }
                    }
                } else if Self::moves_by_default(cx, subject)
                    && !matches!(subject.kind, ExprKind::Call(..) | ExprKind::MethodCall(..))
                {
                    replacement = Some(format!("{}.as_ref()?;", receiver_str));
                } else {
                    replacement = Some(format!("{}?;", receiver_str));
                }

                if let Some(replacement_str) = replacement {
                    span_lint_and_sugg(
                        cx,
                        QUESTION_MARK,
                        expr.span,
                        "this block may be rewritten with the `?` operator",
                        "replace it with",
                        replacement_str,
                        applicability,
                    );
                }
            }
        }
    }

    fn check_if_let_some_or_err_and_early_return(cx: &LateContext<'_>, expr: &Expr<'_>) {
        if_chain! {
            if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: Some(if_else) })
                = higher::IfLet::hir(cx, expr);
            if let PatKind::TupleStruct(ref path1, fields, None) = let_pat.kind;
            if (Self::option_check_and_early_return(cx, let_expr, if_else) && is_lang_ctor(cx, path1, OptionSome)) ||
                (Self::result_check_and_early_return(cx, let_expr, if_else) && is_lang_ctor(cx, path1, ResultOk));

            if let PatKind::Binding(annot, bind_id, _, _) = fields[0].kind;
            let by_ref = matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut);
            if let ExprKind::Block(block, None) = if_then.kind;
            if block.stmts.is_empty();
            if let Some(trailing_expr) = &block.expr;
            if path_to_local_id(trailing_expr, bind_id);
            then {
                let mut applicability = Applicability::MachineApplicable;
                let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
                let replacement = format!("{}{}?", receiver_str, if by_ref { ".as_ref()" } else { "" },);

                span_lint_and_sugg(
                    cx,
                    QUESTION_MARK,
                    expr.span,
                    "this if-let-else may be rewritten with the `?` operator",
                    "replace it with",
                    replacement,
                    applicability,
                );
            }
        }
    }

    fn result_check_and_early_return(cx: &LateContext<'_>, expr: &Expr<'_>, nested_expr: &Expr<'_>) -> bool {
        Self::is_result(cx, expr) && Self::expression_returns_unmodified_err(cx, nested_expr, expr)
    }

    fn option_check_and_early_return(cx: &LateContext<'_>, expr: &Expr<'_>, nested_expr: &Expr<'_>) -> bool {
        Self::is_option(cx, expr) && Self::expression_returns_none(cx, nested_expr)
    }

    fn moves_by_default(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool {
        let expr_ty = cx.typeck_results().expr_ty(expression);

        !expr_ty.is_copy_modulo_regions(cx.tcx.at(expression.span), cx.param_env)
    }

    fn is_option(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool {
        let expr_ty = cx.typeck_results().expr_ty(expression);

        is_type_diagnostic_item(cx, expr_ty, sym::Option)
    }

    fn is_result(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool {
        let expr_ty = cx.typeck_results().expr_ty(expression);

        is_type_diagnostic_item(cx, expr_ty, sym::Result)
    }

    fn expression_returns_none(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool {
        match expression.kind {
            ExprKind::Block(block, _) => {
                if let Some(return_expression) = Self::return_expression(block) {
                    return Self::expression_returns_none(cx, return_expression);
                }

                false
            },
            ExprKind::Ret(Some(expr)) => Self::expression_returns_none(cx, expr),
            ExprKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone),
            _ => false,
        }
    }

    fn expression_returns_unmodified_err(
        cx: &LateContext<'_>,
        expression: &Expr<'_>,
        origin_hir_id: &Expr<'_>,
    ) -> bool {
        match expression.kind {
            ExprKind::Block(block, _) => {
                if let Some(return_expression) = Self::return_expression(block) {
                    return Self::expression_returns_unmodified_err(cx, return_expression, origin_hir_id);
                }

                false
            },
            ExprKind::Ret(Some(expr)) | ExprKind::Call(expr, _) => {
                Self::expression_returns_unmodified_err(cx, expr, origin_hir_id)
            },
            ExprKind::Path(_) => path_to_local(expression) == path_to_local(origin_hir_id),
            _ => false,
        }
    }

    fn return_expression<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> {
        // Check if last expression is a return statement. Then, return the expression
        if_chain! {
            if block.stmts.len() == 1;
            if let Some(expr) = block.stmts.iter().last();
            if let StmtKind::Semi(expr) = expr.kind;
            if let ExprKind::Ret(Some(ret_expr)) = expr.kind;

            then {
                return Some(ret_expr);
            }
        }

        // Check for `return` without a semicolon.
        if_chain! {
            if block.stmts.is_empty();
            if let Some(ExprKind::Ret(Some(ret_expr))) = block.expr.as_ref().map(|e| &e.kind);
            then {
                return Some(ret_expr);
            }
        }

        None
    }
}

impl<'tcx> LateLintPass<'tcx> for QuestionMark {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        Self::check_is_none_or_err_and_early_return(cx, expr);
        Self::check_if_let_some_or_err_and_early_return(cx, expr);
    }
}
<|endoftext|>


<commit_before>
use std;
import std::io;
import result;

type reader = obj {
    fn read_row() -> result::t<[str], str>;
};

fn mk_reader(f: std::io::reader, delim: char, quote: char, has_header: bool) -> reader {
    tag state {
        start;
        field([char]);
        escapedfield([char]);
        inquote([char]);
        escapeend([char]);
    };
    type readerstate = {
        f: std::io::reader,
        delim: char,
        quote: char,
        has_header: bool,
        mutable buf : [char],
        mutable offset : uint,
        mutable state : state,
    };
    obj reader(st: readerstate) {
        fn read_row() -> result::t<[str], str> {
            st.buf = st.f.read_chars(1024u);
            /* should probably use a result */
            if vec::len(st.buf) == 0u {
                ret result::err("EOF");
            }
            st.offset = 0u;
            st.state = start;
            let row: [str] = [];
            while st.offset < vec::len(st.buf) {
                let c : char = st.buf[st.offset];
                st.offset += 1u;
                alt st.state {
                    start() {
                        if c == '"' {
                            st.state = escapedfield([]);
                        } if c == '\n' {
                            break;
                        } else {
                            st.state = field([c]);
                        }
                    }
                    field(x) {
                        if c == '\n' {
                            row += [str::from_chars(x)];
                            break;
                        } else if c == ',' {
                            st.state = start;
                            row += [str::from_chars(x)];
                        } else {
                            st.state = field(x + [c]);
                        }
                    }
                    escapedfield(x) {
                        if c == '"' {
                            st.state = inquote(x);
                        } else {
                            st.state = field(x + [c]);
                        }
                    }
                    inquote(x) {
                        if c == '"' {
                            st.state = escapedfield(x + ['"']);
                        } else {
                            st.state = escapeend(x);
                        }
                    }
                    escapeend(x) {
                        // swallow odd chars, eg. space between field and "
                        if c == ',' {
                            st.state = start;
                            row += [str::from_chars(x)];
                        }
                    }
                }
            }
            ret result::ok(row);
        }
    }

    let st = { f: f, delim: delim, quote: quote, has_header: has_header, mutable buf: [], mutable offset: 0u, mutable state: start };
    let r = reader(st);
    ret r;
}

fn main(args : [str])
{
    if (vec::len(args) != 2u) {
        ret;
    }
    let f : io::reader = result::get(io::file_reader(args[1]));
    let r = mk_reader(f, ',', '"', true);
    while true {
        let res = r.read_row();
        if result::failure(res) {
            break;
        }
        for field in result::get(res) {
            io::println("FIELD: " + field);
        }
    }
}

<commit_msg>seems to work<commit_after>
use std;
import std::io;
import result;

type reader = obj {
    fn read_row() -> result::t<[str], str>;
};

fn mk_reader(f: std::io::reader, delim: char, quote: char, has_header: bool) -> reader {
    tag state {
        start;
        field([char]);
        escapedfield([char]);
        inquote([char]);
        escapeend([char]);
    };
    type readerstate = {
        f: std::io::reader,
        delim: char,
        quote: char,
        has_header: bool,
        mutable buf : [char],
        mutable offset : uint,
        mutable state : state,
    };
    obj reader(st: readerstate) {
        fn read_row() -> result::t<[str], str> {
            fn row_from_buf(st: readerstate, &row: [str]) -> bool {
                while st.offset < vec::len(st.buf) {
                    let c : char = st.buf[st.offset];
                    st.offset += 1u;
                    alt st.state {
                        start() {
                            if c == st.quote {
                                st.state = escapedfield([]);
                            } if c == '\n' {
                                ret true;
                            } if c == st.delim {
                                st.state = start;
                                row += [""];
                            } else {
                                st.state = field([c]);
                            }
                        }
                        field(x) {
                            if c == '\n' {
                                row += [str::from_chars(x)];
                                ret true;
                            } else if c == st.delim {
                                st.state = start;
                                row += [str::from_chars(x)];
                            } else {
                                st.state = field(x + [c]);
                            }
                        }
                        escapedfield(x) {
                            if c == st.quote {
                                st.state = inquote(x);
                            } else {
                                st.state = field(x + [c]);
                            }
                        }
                        inquote(x) {
                            if c == st.quote {
                                st.state = escapedfield(x + [st.quote]);
                            } else {
                                st.state = escapeend(x);
                            }
                        }
                        escapeend(x) {
                            // swallow odd chars, eg. space between field and "
                            if c == st.delim {
                                st.state = start;
                                row += [str::from_chars(x)];
                            }
                        }
                    }
                }
                ret false;
            }

            let row: [str] = [];
            st.state = start;
            while true {
                if st.offset >= vec::len(st.buf) {
                    st.offset = 0u;
                    st.buf = st.f.read_chars(1024u);
                    /* should probably use a result */
                    if vec::len(st.buf) == 0u {
                        ret result::err("EOF");
                    }
                }
                if (row_from_buf(st, row)) {
                    ret result::ok(row);
                }
            }
            ret result::err("EOF");
        }
    }

    let st = { f: f, delim: delim, quote: quote, has_header: has_header, mutable buf: [], mutable offset: 0u, mutable state: start };
    let r = reader(st);
    ret r;
}

fn main(args : [str])
{
    if (vec::len(args) != 2u) {
        ret;
    }
    let f : io::reader = result::get(io::file_reader(args[1]));
    let r = mk_reader(f, ',', '"', true);
    while true {
        let res = r.read_row();
        if result::failure(res) {
            break;
        }
        io::println("---------------");
        for field in result::get(res) {
            io::println("FIELD: " + field);
        }
    }
}

<|endoftext|>