<commit_before>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Constructor methods for ndarray
//!
//!

use libnum::{Zero, One, Float};

use imp_prelude::*;
use StrideShape;
use dimension;
use linspace;
use error::{self, ShapeError, ErrorKind};
use Indexes;
use iterators::{to_vec, to_vec_mapped};

/// Constructor methods for one-dimensional arrays.
///
/// Note that the constructor methods apply to `Array` and `RcArray`,
/// the two array types that have owned storage.
impl<S> ArrayBase<S, Ix1>
    where S: DataOwned
{
    /// Create a one-dimensional array from a vector (no copying needed).
    ///
    /// ```rust
    /// use ndarray::Array;
    ///
    /// let array = Array::from_vec(vec![1., 2., 3., 4.]);
    /// ```
    pub fn from_vec(v: Vec<S::Elem>) -> Self {
        unsafe { Self::from_shape_vec_unchecked(v.len() as Ix, v) }
    }

    /// Create a one-dimensional array from an iterable.
    ///
    /// ```rust
    /// use ndarray::{Array, arr1};
    ///
    /// let array = Array::from_iter((0..5).map(|x| x * x));
    /// assert!(array == arr1(&[0, 1, 4, 9, 16]))
    /// ```
    pub fn from_iter(iterable: I) -> Self
        where I: IntoIterator<Item=S::Elem>
    {
        Self::from_vec(iterable.into_iter().collect())
    }

    /// Create a one-dimensional array from the inclusive interval
    /// `[start, end]` with `n` elements. `F` must be a floating point type.
    ///
    /// ```rust
    /// use ndarray::{Array, arr1};
    ///
    /// let array = Array::linspace(0., 1., 5);
    /// assert!(array == arr1(&[0.0, 0.25, 0.5, 0.75, 1.0]))
    /// ```
    pub fn linspace<F>(start: F, end: F, n: usize) -> Self
        where S: Data<Elem=F>,
              F: Float,
    {
        Self::from_vec(to_vec(linspace::linspace(start, end, n)))
    }

    /// Create a one-dimensional array from the half-open interval
    /// `[start, end)` with elements spaced by `step`. `F` must be a floating point type.
    ///
    /// ```rust
    /// use ndarray::{Array, arr1};
    ///
    /// let array = Array::range(0., 5., 1.);
    /// assert!(array == arr1(&[0., 1., 2., 3., 4.]))
    /// ```
    pub fn range<F>(start: F, end: F, step: F) -> Self
        where S: Data<Elem=F>,
              F: Float,
    {
        Self::from_vec(to_vec(linspace::range(start, end, step)))
    }
}

/// Constructor methods for two-dimensional arrays.
impl<S, A> ArrayBase<S, Ix2>
    where S: DataOwned<Elem=A>,
{
    /// Create an identity matrix of size `n` (square 2D array).
    ///
    /// **Panics** if `n * n` would overflow usize.
    pub fn eye(n: Ix) -> Self
        where S: DataMut,
              A: Clone + Zero + One,
    {
        let mut eye = Self::zeros((n, n));
        for a_ii in eye.diag_mut() {
            *a_ii = A::one();
        }
        eye
    }
}

macro_rules! size_checked_unwrap {
    ($dim:expr) => {
        match $dim.size_checked() {
            Some(sz) => sz,
            None => panic!("ndarray: Shape too large, number of elements overflows usize"),
        }
    }
}

/// Constructor methods for n-dimensional arrays.
impl<S, A, D> ArrayBase<S, D>
    where S: DataOwned<Elem=A>,
          D: Dimension,
{
    /// Create an array with copies of `elem`, shape `shape`.
    ///
    /// **Panics** if the number of elements in `shape` would overflow usize.
    ///
    /// ```
    /// use ndarray::{Array, arr3, ShapeBuilder};
    ///
    /// let a = Array::from_elem((2, 2, 2), 1.);
    ///
    /// assert!(
    ///     a == arr3(&[[[1., 1.],
    ///                  [1., 1.]],
    ///                 [[1., 1.],
    ///                  [1., 1.]]])
    /// );
    /// assert!(a.strides() == &[4, 2, 1]);
    ///
    /// let b = Array::from_elem((2, 2, 2).f(), 1.);
    /// assert!(b.strides() == &[1, 2, 4]);
    /// ```
    pub fn from_elem<Sh>(shape: Sh, elem: A) -> Self
        where A: Clone,
              Sh: ShapeBuilder<Dim=D>,
    {
        // Note: We don't need to check the case of a size between
        // isize::MAX -> usize::MAX; in this case, the vec constructor itself
        // panics.
        let shape = shape.into_shape();
        let size = size_checked_unwrap!(shape.dim);
        let v = vec![elem; size];
        unsafe { Self::from_shape_vec_unchecked(shape, v) }
    }

    /// Create an array with zeros, shape `shape`.
    ///
    /// **Panics** if the number of elements in `shape` would overflow usize.
    pub fn zeros<Sh>(shape: Sh) -> Self
        where A: Clone + Zero,
              Sh: ShapeBuilder<Dim=D>,
    {
        Self::from_elem(shape, A::zero())
    }

    /// Create an array with default values, shape `shape`
    ///
    /// **Panics** if the number of elements in `shape` would overflow usize.
    pub fn default<Sh>(shape: Sh) -> Self
        where A: Default,
              Sh: ShapeBuilder<Dim=D>,
    {
        let shape = shape.into_shape();
        let v = to_vec((0..shape.dim.size()).map(|_| A::default()));
        unsafe { Self::from_shape_vec_unchecked(shape, v) }
    }

    /// Create an array with values created by the function `f`.
    ///
    /// The elements are visited in arbitirary order.
    ///
    /// **Panics** if the number of elements in `shape` would overflow usize.
    pub fn from_shape_fn<Sh, F>(shape: Sh, f: F) -> Self
        where Sh: ShapeBuilder<Dim=D>,
              F: FnMut(D::Pattern) -> A,
    {
        let shape = shape.into_shape();
        let v = to_vec_mapped(Indexes::new(shape.dim.clone()), f);
        unsafe { Self::from_shape_vec_unchecked(shape, v) }
    }

    /// Create an array with the given shape from a vector. (No cloning of
    /// elements needed.)
    ///
    /// ----
    ///
    /// For a contiguous c- or f-order shape, the following applies:
    ///
    /// **Errors** if `shape` does not correspond to the number of elements in `v`.
    ///
    /// ----
    ///
    /// For custom strides, the following applies:
    ///
    /// **Errors** if strides and dimensions can point out of bounds of `v`.

    /// **Errors** if strides allow multiple indices to point to the same element.
    ///
    /// ```
    /// use ndarray::prelude::*;
    ///
    /// let a = Array::from_shape_vec((2, 2), vec![1., 2., 3., 4.]);
    /// assert!(a.is_ok());
    ///
    /// let b = Array::from_shape_vec((2, 2).strides((1, 2)),
    ///                                    vec![1., 2., 3., 4.]).unwrap();
    /// assert!(
    ///     b == arr2(&[[1., 3.],
    ///                 [2., 4.]])
    /// );
    /// ```
    pub fn from_shape_vec<Sh>(shape: Sh, v: Vec) -> Result<Self, ShapeError>
        where Sh: Into<StrideShape<D>>,
    {
        // eliminate the type parameter Sh as soon as possible
        Self::from_shape_vec_impl(shape.into(), v)
    }

    fn from_shape_vec_impl(shape: StrideShape<D>, v: Vec) -> Result<Self, ShapeError>
    {
        if shape.custom {
            Self::from_vec_dim_stride(shape.dim, shape.strides, v)
        } else {
            let dim = shape.dim;
            let strides = shape.strides;
            if dim.size_checked() != Some(v.len()) {
                return Err(error::incompatible_shapes(&Ix1(v.len()), &dim));
            }
            unsafe { Ok(Self::from_vec_dim_stride_unchecked(dim, strides, v)) }
        }
    }

    /// Create an array from a vector and interpret it according to the
    /// provided dimensions and strides. (No cloning of elements needed.)
    ///
    /// Unsafe because dimension and strides are unchecked.
    pub unsafe fn from_shape_vec_unchecked<Sh>(shape: Sh, v: Vec) -> Self
        where Sh: Into<StrideShape<D>>,
    {
        let shape = shape.into();
        Self::from_vec_dim_stride_unchecked(shape.dim, shape.strides, v)
    }

    fn from_vec_dim_stride(dim: D, strides: D, v: Vec)
        -> Result<Self, ShapeError>
    {
        dimension::can_index_slice(&v, &dim, &strides).map(|_| {
            unsafe {
                Self::from_vec_dim_stride_unchecked(dim, strides, v)
            }
        })
    }

    unsafe fn from_vec_dim_stride_unchecked(dim: D, strides: D, mut v: Vec)
        -> Self
    {
        // debug check for issues that indicates wrong use of this constructor
        debug_assert!(match dimension::can_index_slice(&v, &dim, &strides) {
            Ok(_) => true,
            Err(ref e) => match e.kind() {
                ErrorKind::OutOfBounds => false,
                ErrorKind::RangeLimited => false,
                _ => true,
            }
        });
        ArrayBase {
            ptr: v.as_mut_ptr(),
            data: DataOwned::new(v),
            strides: strides,
            dim: dim
        }
    }

}
<commit_msg>Change one-dimensional constructors to use `A` type parameter.<commit_after>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Constructor methods for ndarray
//!
//!

use libnum::{Zero, One, Float};

use imp_prelude::*;
use StrideShape;
use dimension;
use linspace;
use error::{self, ShapeError, ErrorKind};
use Indexes;
use iterators::{to_vec, to_vec_mapped};

/// Constructor methods for one-dimensional arrays.
///
/// Note that the constructor methods apply to `Array` and `RcArray`,
/// the two array types that have owned storage.
impl<S, A> ArrayBase<S, Ix1>
    where S: DataOwned<Elem=A>,
{
    /// Create a one-dimensional array from a vector (no copying needed).
    ///
    /// ```rust
    /// use ndarray::Array;
    ///
    /// let array = Array::from_vec(vec![1., 2., 3., 4.]);
    /// ```
    pub fn from_vec(v: Vec) -> Self {
        unsafe { Self::from_shape_vec_unchecked(v.len() as Ix, v) }
    }

    /// Create a one-dimensional array from an iterable.
    ///
    /// ```rust
    /// use ndarray::{Array, arr1};
    ///
    /// let array = Array::from_iter((0..5).map(|x| x * x));
    /// assert!(array == arr1(&[0, 1, 4, 9, 16]))
    /// ```
    pub fn from_iter(iterable: I) -> Self
        where I: IntoIterator<Item=A>
    {
        Self::from_vec(iterable.into_iter().collect())
    }

    /// Create a one-dimensional array from the inclusive interval
    /// `[start, end]` with `n` elements. `A` must be a floating point type.
    ///
    /// ```rust
    /// use ndarray::{Array, arr1};
    ///
    /// let array = Array::linspace(0., 1., 5);
    /// assert!(array == arr1(&[0.0, 0.25, 0.5, 0.75, 1.0]))
    /// ```
    pub fn linspace(start: A, end: A, n: usize) -> Self
        where A: Float,
    {
        Self::from_vec(to_vec(linspace::linspace(start, end, n)))
    }

    /// Create a one-dimensional array from the half-open interval
    /// `[start, end)` with elements spaced by `step`. `A` must be a floating
    /// point type.
    ///
    /// ```rust
    /// use ndarray::{Array, arr1};
    ///
    /// let array = Array::range(0., 5., 1.);
    /// assert!(array == arr1(&[0., 1., 2., 3., 4.]))
    /// ```
    pub fn range(start: A, end: A, step: A) -> Self
        where A: Float,
    {
        Self::from_vec(to_vec(linspace::range(start, end, step)))
    }
}

/// Constructor methods for two-dimensional arrays.
impl<S, A> ArrayBase<S, Ix2>
    where S: DataOwned<Elem=A>,
{
    /// Create an identity matrix of size `n` (square 2D array).
    ///
    /// **Panics** if `n * n` would overflow usize.
    pub fn eye(n: Ix) -> Self
        where S: DataMut,
              A: Clone + Zero + One,
    {
        let mut eye = Self::zeros((n, n));
        for a_ii in eye.diag_mut() {
            *a_ii = A::one();
        }
        eye
    }
}

macro_rules! size_checked_unwrap {
    ($dim:expr) => {
        match $dim.size_checked() {
            Some(sz) => sz,
            None => panic!("ndarray: Shape too large, number of elements overflows usize"),
        }
    }
}

/// Constructor methods for n-dimensional arrays.
impl<S, A, D> ArrayBase<S, D>
    where S: DataOwned<Elem=A>,
          D: Dimension,
{
    /// Create an array with copies of `elem`, shape `shape`.
    ///
    /// **Panics** if the number of elements in `shape` would overflow usize.
    ///
    /// ```
    /// use ndarray::{Array, arr3, ShapeBuilder};
    ///
    /// let a = Array::from_elem((2, 2, 2), 1.);
    ///
    /// assert!(
    ///     a == arr3(&[[[1., 1.],
    ///                  [1., 1.]],
    ///                 [[1., 1.],
    ///                  [1., 1.]]])
    /// );
    /// assert!(a.strides() == &[4, 2, 1]);
    ///
    /// let b = Array::from_elem((2, 2, 2).f(), 1.);
    /// assert!(b.strides() == &[1, 2, 4]);
    /// ```
    pub fn from_elem<Sh>(shape: Sh, elem: A) -> Self
        where A: Clone,
              Sh: ShapeBuilder<Dim=D>,
    {
        // Note: We don't need to check the case of a size between
        // isize::MAX -> usize::MAX; in this case, the vec constructor itself
        // panics.
        let shape = shape.into_shape();
        let size = size_checked_unwrap!(shape.dim);
        let v = vec![elem; size];
        unsafe { Self::from_shape_vec_unchecked(shape, v) }
    }

    /// Create an array with zeros, shape `shape`.
    ///
    /// **Panics** if the number of elements in `shape` would overflow usize.
    pub fn zeros<Sh>(shape: Sh) -> Self
        where A: Clone + Zero,
              Sh: ShapeBuilder<Dim=D>,
    {
        Self::from_elem(shape, A::zero())
    }

    /// Create an array with default values, shape `shape`
    ///
    /// **Panics** if the number of elements in `shape` would overflow usize.
    pub fn default<Sh>(shape: Sh) -> Self
        where A: Default,
              Sh: ShapeBuilder<Dim=D>,
    {
        let shape = shape.into_shape();
        let v = to_vec((0..shape.dim.size()).map(|_| A::default()));
        unsafe { Self::from_shape_vec_unchecked(shape, v) }
    }

    /// Create an array with values created by the function `f`.
    ///
    /// The elements are visited in arbitirary order.
    ///
    /// **Panics** if the number of elements in `shape` would overflow usize.
    pub fn from_shape_fn<Sh, F>(shape: Sh, f: F) -> Self
        where Sh: ShapeBuilder<Dim=D>,
              F: FnMut(D::Pattern) -> A,
    {
        let shape = shape.into_shape();
        let v = to_vec_mapped(Indexes::new(shape.dim.clone()), f);
        unsafe { Self::from_shape_vec_unchecked(shape, v) }
    }

    /// Create an array with the given shape from a vector. (No cloning of
    /// elements needed.)
    ///
    /// ----
    ///
    /// For a contiguous c- or f-order shape, the following applies:
    ///
    /// **Errors** if `shape` does not correspond to the number of elements in `v`.
    ///
    /// ----
    ///
    /// For custom strides, the following applies:
    ///
    /// **Errors** if strides and dimensions can point out of bounds of `v`.

    /// **Errors** if strides allow multiple indices to point to the same element.
    ///
    /// ```
    /// use ndarray::prelude::*;
    ///
    /// let a = Array::from_shape_vec((2, 2), vec![1., 2., 3., 4.]);
    /// assert!(a.is_ok());
    ///
    /// let b = Array::from_shape_vec((2, 2).strides((1, 2)),
    ///                                    vec![1., 2., 3., 4.]).unwrap();
    /// assert!(
    ///     b == arr2(&[[1., 3.],
    ///                 [2., 4.]])
    /// );
    /// ```
    pub fn from_shape_vec<Sh>(shape: Sh, v: Vec) -> Result<Self, ShapeError>
        where Sh: Into<StrideShape<D>>,
    {
        // eliminate the type parameter Sh as soon as possible
        Self::from_shape_vec_impl(shape.into(), v)
    }

    fn from_shape_vec_impl(shape: StrideShape<D>, v: Vec) -> Result<Self, ShapeError>
    {
        if shape.custom {
            Self::from_vec_dim_stride(shape.dim, shape.strides, v)
        } else {
            let dim = shape.dim;
            let strides = shape.strides;
            if dim.size_checked() != Some(v.len()) {
                return Err(error::incompatible_shapes(&Ix1(v.len()), &dim));
            }
            unsafe { Ok(Self::from_vec_dim_stride_unchecked(dim, strides, v)) }
        }
    }

    /// Create an array from a vector and interpret it according to the
    /// provided dimensions and strides. (No cloning of elements needed.)
    ///
    /// Unsafe because dimension and strides are unchecked.
    pub unsafe fn from_shape_vec_unchecked<Sh>(shape: Sh, v: Vec) -> Self
        where Sh: Into<StrideShape<D>>,
    {
        let shape = shape.into();
        Self::from_vec_dim_stride_unchecked(shape.dim, shape.strides, v)
    }

    fn from_vec_dim_stride(dim: D, strides: D, v: Vec)
        -> Result<Self, ShapeError>
    {
        dimension::can_index_slice(&v, &dim, &strides).map(|_| {
            unsafe {
                Self::from_vec_dim_stride_unchecked(dim, strides, v)
            }
        })
    }

    unsafe fn from_vec_dim_stride_unchecked(dim: D, strides: D, mut v: Vec)
        -> Self
    {
        // debug check for issues that indicates wrong use of this constructor
        debug_assert!(match dimension::can_index_slice(&v, &dim, &strides) {
            Ok(_) => true,
            Err(ref e) => match e.kind() {
                ErrorKind::OutOfBounds => false,
                ErrorKind::RangeLimited => false,
                _ => true,
            }
        });
        ArrayBase {
            ptr: v.as_mut_ptr(),
            data: DataOwned::new(v),
            strides: strides,
            dim: dim
        }
    }

}
<|endoftext|>


<commit_before>use std::{iter::Peekable, str};

#[derive(Debug, PartialEq, Eq, Hash)]
enum Quotes {
    Single,
    Double,
    None,
}

#[derive(Debug)]
struct EofMatcher {
    eof:       Vec<u8>,
    complete:  bool,
    match_idx: usize,
}

impl EofMatcher {
    fn new() -> Self { EofMatcher { eof: Vec::with_capacity(10), complete: false, match_idx: 0 } }

    #[inline]
    fn next(&mut self, c: u8) -> bool {
        if self.complete && self.eof.get(self.match_idx) == Some(&c) {
            self.match_idx += 1;
        } else if self.complete {
            self.match_idx = 0;
        } else if c == b'\n' {
            self.complete = true;
        } else {
            self.eof.push(c);
        }
        self.complete && self.match_idx == self.eof.len()
    }
}

/// Serves as a buffer for storing a string until that string can be terminated.
///
/// # Examples
///
/// This example comes from the shell's REPL, which ensures that the user's input
/// will only be submitted for execution once a terminated command is supplied.
#[derive(Debug)]
pub struct Terminator<I: Iterator<Item = u8>> {
    inner:      RearPeekable<I>,
    eof:        Option<EofMatcher>,
    array:      usize,
    read:       usize,
    skip_next:  bool,
    quotes:     Quotes,
    terminated: bool,
}

impl<'a> From<&'a str> for Terminator<std::str::Bytes<'a>> {
    fn from(string: &'a str) -> Self { Terminator::new(string.bytes()) }
}

#[derive(Clone, Debug)]
pub struct RearPeekable<I: Iterator> {
    iter: Peekable<I>,
    now:  Option<I::Item>,
    last: Option<I::Item>,
}

impl<I> Iterator for RearPeekable<I>
where
    I: Iterator,
    I::Item: Copy,
{
    type Item = I::Item;

    #[inline]
    fn next(&mut self) -> Option<I::Item> {
        self.last = self.now;
        self.now = self.iter.next();
        self.now
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
}

impl<I: Iterator> RearPeekable<I> {
    #[inline]
    pub fn peek(&mut self) -> Option<&I::Item> { self.iter.peek() }

    #[inline]
    pub fn prev(&self) -> Option<&I::Item> { self.last.as_ref() }
}

impl<I: Iterator<Item = u8>> Iterator for Terminator<I> {
    type Item = u8;

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        if self.terminated {
            return None;
        }

        let out = self
            .inner
            .next()
            .and_then(|character| {
                if let Some(matcher) = self.eof.as_mut() {
                    if matcher.next(character) {
                        self.eof = None;
                    }
                } else if self.skip_next {
                    self.skip_next = false;
                } else if self.quotes != Quotes::None && character != b'\\' {
                    match (character, &self.quotes) {
                        (b'\'', Quotes::Single) | (b'"', Quotes::Double) => {
                            self.quotes = Quotes::None;
                        }
                        _ => (),
                    }
                } else {
                    match character {
                        b'\'' => {
                            self.quotes = Quotes::Single;
                        }
                        b'"' => {
                            self.quotes = Quotes::Double;
                        }
                        b'<' if self.inner.prev() == Some(&b'<') => {
                            if let Some(&b'<') = self.inner.peek() {
                                self.skip_next = true; // avoid falling in the else at the next pass
                            } else {
                                self.eof = Some(EofMatcher::new());
                            }
                        }
                        b'[' => {
                            self.array += 1;
                        }
                        b']' => {
                            if self.array > 0 {
                                self.array -= 1;
                            }
                        }
                        b'#' if self
                            .inner
                            .prev()
                            .filter(|&c| ![b' ', b'\n'].contains(c))
                            .is_none() =>
                        {
                            return self.inner.find(|&c| c == b'\n')
                        }
                        b'\\' => {
                            if self.inner.peek() == Some(&b'\n') {
                                return self.inner.find(|&c| !(c as char).is_whitespace());
                            } else {
                                self.skip_next = true;
                            }
                        }
                        _ => {}
                    }
                }

                Some(character)
            })
            .map(|c| if c == b'\n' && self.array > 0 { b' ' } else { c });

        //let prev = self.inner.prev().cloned();
        //let next = self.inner.peek();
        /*println!(
            "debug: \n\tarray: {}\n\tquotes: {:?}\n\tcharacter: {:?}\n\ttrim: {}",
            self.array, self.quotes, out, self.skip_next
        );*/
        if (out == Some(b'\n') || out == None)
            && self.eof.is_none()
            && self.array == 0
            && self.quotes == Quotes::None
            //&& (![b'|', b'&'].contains(&character) || prev.filter(|c| c == character).is_none())
        {
            self.terminated = true;
        }

        out
    }
}

impl<I: Iterator<Item = u8>> Terminator<I> {
    /// Consumes lines until a statement is formed or the iterator runs dry, and returns the
    /// underlying `String`.
    pub fn terminate(self) -> Result<String, ()> {
        let stmt = self.collect::<Vec<_>>();
        let stmt = unsafe { String::from_utf8_unchecked(stmt) };
        // println!("statement {:?}", stmt);
        Ok(stmt)
    }

    /// Appends a string to the internal buffer.
    // fn append(&mut self, input: &str) {
    // if self.eof.as_ref().filter(|s| s.as_str() == input.trim()).is_some() {
    //     self.eof = None;
    //}

    pub fn new(inner: I) -> Terminator<I> {
        Terminator {
            inner:      RearPeekable { iter: inner.peekable(), now: None, last: None },
            eof:        None,
            array:      0,
            read:       0,
            skip_next:  false,
            quotes:     Quotes::None,
            terminated: false,
        }
    }
}
<commit_msg>Trim withspace and support && and ||<commit_after>use std::{iter::Peekable, str};

#[derive(Debug, PartialEq, Eq, Hash)]
enum Quotes {
    Single,
    Double,
    None,
}

#[derive(Debug)]
struct EofMatcher {
    eof:       Vec<u8>,
    complete:  bool,
    match_idx: usize,
}

impl EofMatcher {
    fn new() -> Self { EofMatcher { eof: Vec::with_capacity(10), complete: false, match_idx: 0 } }

    #[inline]
    fn next(&mut self, c: u8) -> bool {
        if self.complete && self.eof.get(self.match_idx) == Some(&c) {
            self.match_idx += 1;
        } else if self.complete {
            self.match_idx = 0;
        } else if c == b'\n' {
            self.complete = true;
        } else {
            self.eof.push(c);
        }
        self.complete && self.match_idx == self.eof.len()
    }
}

/// Serves as a buffer for storing a string until that string can be terminated.
///
/// # Examples
///
/// This example comes from the shell's REPL, which ensures that the user's input
/// will only be submitted for execution once a terminated command is supplied.
#[derive(Debug)]
pub struct Terminator<I: Iterator<Item = u8>> {
    inner:      RearPeekable<I>,
    eof:        Option<EofMatcher>,
    array:      usize,
    read:       usize,
    skip_next:  bool,
    quotes:     Quotes,
    terminated: bool,
    and_or:     bool,
    whitespace: bool,
}

impl<'a> From<&'a str> for Terminator<std::str::Bytes<'a>> {
    fn from(string: &'a str) -> Self { Terminator::new(string.bytes()) }
}

#[derive(Clone, Debug)]
pub struct RearPeekable<I: Iterator> {
    iter: Peekable<I>,
    now:  Option<I::Item>,
    last: Option<I::Item>,
}

impl<I> Iterator for RearPeekable<I>
where
    I: Iterator,
    I::Item: Copy,
{
    type Item = I::Item;

    #[inline]
    fn next(&mut self) -> Option<I::Item> {
        self.last = self.now;
        self.now = self.iter.next();
        self.now
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
}

impl<I: Iterator> RearPeekable<I> {
    #[inline]
    pub fn peek(&mut self) -> Option<&I::Item> { self.iter.peek() }

    #[inline]
    pub fn prev(&self) -> Option<&I::Item> { self.last.as_ref() }
}

impl<I: Iterator<Item = u8>> Iterator for Terminator<I> {
    type Item = u8;

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        if self.terminated {
            return None;
        }

        let next = self.inner.next();
        let out = self.handle_char(next);

        /*println!(
            "debug: \n\tarray: {}\n\tquotes: {:?}\n\tcharacter: {:?}\n\ttrim: {}\n\twhitespace: {}",
            self.array, self.quotes, out, self.skip_next, self.whitespace,
        );*/
        if out.is_none()
            && self.eof.is_none()
            && self.array == 0
            && self.quotes == Quotes::None
            && !self.and_or
        {
            self.terminated = true;
        }

        out
    }
}

impl<I: Iterator<Item = u8>> Terminator<I> {
    /// Consumes lines until a statement is formed or the iterator runs dry, and returns the
    /// underlying `String`.
    pub fn terminate(self) -> Result<String, ()> {
        let stmt = self.collect::<Vec<_>>();
        let stmt = unsafe { String::from_utf8_unchecked(stmt) };
        // println!("statement {:?}", stmt);
        Ok(stmt)
    }

    fn handle_char(&mut self, character: Option<u8>) -> Option<u8> {
        character
            .and_then(|character| {
            let prev_whitespace = self.whitespace;
            self.whitespace = false;

            if let Some(matcher) = self.eof.as_mut() {
                if matcher.next(character) {
                    self.eof = None;
                }
            } else if self.skip_next {
                self.skip_next = false;
            } else if self.quotes != Quotes::None && character != b'\\' {
                match (character, &self.quotes) {
                    (b'\'', Quotes::Single) | (b'"', Quotes::Double) => {
                        self.quotes = Quotes::None;
                    }
                    _ => (),
                }
            } else {
                match character {
                    b'\'' => {
                        self.quotes = Quotes::Single;
                    }
                    b'"' => {
                        self.quotes = Quotes::Double;
                    }
                    b'<' if self.inner.prev() == Some(&b'<') => {
                        if let Some(&b'<') = self.inner.peek() {
                            self.skip_next = true; // avoid falling in the else at the next pass
                        } else {
                            self.eof = Some(EofMatcher::new());
                        }
                    }
                    b'[' => {
                        self.array += 1;
                    }
                    b']' => {
                        if self.array > 0 {
                            self.array -= 1;
                        }
                    }
                    b'#' if self
                        .inner
                        .prev()
                        .filter(|&c| ![b' ', b'\n'].contains(c))
                        .is_none() =>
                    {
                        return self.inner.find(|&c| c == b'\n')
                    }
                    b'\\' => {
                        if self.inner.peek() == Some(&b'\n') {
                            let next = self.inner.find(|&c| !(c as char).is_whitespace());
                            return self.handle_char(next);
                        } else {
                            self.skip_next = true;
                        }
                    }
                    b'&' | b'|' if self.inner.prev() == Some(&character) => {
                        self.and_or = true;
                    }
                    b'\n' if self.array == 0 && !self.and_or => {
                        self.terminated = true;
                    }
                    _ if (character as char).is_whitespace() => {
                        if prev_whitespace {
                            let next = self.inner.find(|&c| !(c as char).is_whitespace());
                            return self.handle_char(next);
                        }
                        self.whitespace = true;
                    }
                    _ => {
                        self.and_or = false;
                    }
                }
            }

            Some(character)
        }).map(|c| if c == b'\n' && self.array > 0 { b' ' } else { c })
    }

    pub fn new(inner: I) -> Terminator<I> {
        Terminator {
            inner:      RearPeekable { iter: inner.peekable(), now: None, last: None },
            eof:        None,
            array:      0,
            read:       0,
            skip_next:  false,
            quotes:     Quotes::None,
            terminated: false,
            and_or:     false,
            whitespace: false,
        }
    }
}
<|endoftext|>


<commit_before>use std::vec::Vec;

use hyper::Client;
use hyper::header::Connection;

use std::io::Read;
use std::default::Default;

use tendril::StrTendril;

use html5ever::tokenizer::{Tokenizer, TokenizerOpts};

fn get_html(url: &str) -> StrTendril {
    let mut res = Client::new().get(url)
      .header(Connection::close()).send().unwrap();
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    let input = StrTendril::try_from_byte_slice(body.as_bytes()).unwrap();
    input.try_reinterpret().unwrap()
}

pub fn get_rows(url: &str) -> Vec<String> {
    let mut tok = Tokenizer::new(collector::RowCollector::new(), TokenizerOpts {
        .. Default::default()
    });
    tok.feed(get_html(url));
    tok.end();
    tok.unwrap().rows
}

mod collector {
    use std::vec::Vec;
    use std::str::FromStr;

    use html5ever::tokenizer::{TokenSink, Token, Tag};
    use html5ever::tokenizer::{TagToken, StartTag, EndTag};

    pub struct RowCollector {
        pub rows: Vec<String>
    }

    impl RowCollector {
        pub fn new() -> Self {
            RowCollector {
                rows: Vec::new(),
            }
        }

        fn get_url(&self, tag: Tag) -> Option<String> {
            if match tag.kind {
                StartTag => true,
                EndTag => false
            } && tag.name.as_ref() == "p" {
                for attr in tag.attrs.iter() {
                    if attr.name.local.as_ref() == "data-pid" {
                        return Some(String::from_str(attr.value.as_ref()).unwrap())
                    }
                }
            }

            return None
        }
    }

    impl TokenSink for RowCollector {
        fn process_token(&mut self, token: Token) {
            match token {
                TagToken(tag) => {
                    let url = self.get_url(tag);
                    if url.is_some() {
                        self.rows.push(url.unwrap());
                    }
                }
                _ => { }
            }
        }
    }
}
<commit_msg>update<commit_after>use std::vec::Vec;

use hyper::Client;
use hyper::header::Connection;

use std::io::Read;
use std::default::Default;

use tendril::StrTendril;

use html5ever::tokenizer::{Tokenizer, TokenizerOpts};

fn get_html(url: &str) -> StrTendril {
    let mut res = Client::new().get(url)
        .header(Connection::close()).send().unwrap();
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    let input = StrTendril::try_from_byte_slice(body.as_bytes()).unwrap();
    input.try_reinterpret().unwrap()
}

pub fn get_rows(url: &str) -> Vec<String> {
    let mut tok = Tokenizer::new(collector::RowCollector::new(), TokenizerOpts {
        .. Default::default()
    });
    tok.feed(get_html(url));
    tok.end();
    tok.unwrap().rows
}

mod collector {
    use std::vec::Vec;
    use std::str::FromStr;

    use html5ever::tokenizer::{TokenSink, Token, Tag};
    use html5ever::tokenizer::{TagToken, StartTag, EndTag};

    pub struct RowCollector {
        pub rows: Vec<String>
    }

    impl RowCollector {
        pub fn new() -> Self {
            RowCollector {
                rows: Vec::new(),
            }
        }

        fn get_url(&self, tag: Tag) -> Option<String> {
            if match tag.kind {
                StartTag => true,
                EndTag => false
            } && tag.name.as_ref() == "p" {
                for attr in tag.attrs.iter() {
                    if attr.name.local.as_ref() == "data-pid" {
                        return Some(String::from_str(attr.value.as_ref()).unwrap())
                    }
                }
            }

            return None
        }
    }

    impl TokenSink for RowCollector {
        fn process_token(&mut self, token: Token) {
            match token {
                TagToken(tag) => {
                    let url = self.get_url(tag);
                    if url.is_some() {
                        self.rows.push(url.unwrap());
                    }
                }
                _ => { }
            }
        }
    }
}
<|endoftext|>


<commit_before>//! An implementation of a buddy allocator.

use types::{UnsafeList, PhantomNode};

pub type FreeBlock = PhantomNode;

#[allow(dead_code)]
pub struct Buddy<'a> {
    min_block_size: usize,
    max_order: u32,
    free_lists: &'a mut [UnsafeList<FreeBlock>],
}
<commit_msg>libheap: Add dummy implementation of Allocator for Buddy<commit_after>//! An implementation of a buddy allocator.

use core::ptr;

use Allocator;

use types::{UnsafeList, PhantomNode};

pub type FreeBlock = PhantomNode;

#[allow(dead_code)]
pub struct Buddy<'a> {
    min_block_size: usize,
    max_order: u32,
    free_lists: &'a mut [UnsafeList<FreeBlock>],
}

impl<'a> Allocator for Buddy<'a> {
    unsafe fn allocate(&mut self, mut _size: usize, _align: usize) -> *mut u8 {
        ptr::null_mut()
    }

    unsafe fn deallocate(&mut self, _ptr: *mut u8, _old_size: usize,
                         _align: usize) {

    }
}
<|endoftext|>


<commit_before>//! Runtime code generation and execution.

use super::prelude::*;
use super::target::LLVMTargetDataRef;
use super::target_machine::{LLVMTargetMachineRef, LLVMCodeModel};

pub enum LLVMOpaqueGenericValue {}
pub enum LLVMOpaqueExecutionEngine {}
pub enum LLVMOpaqueMCJITMemoryManager {}

pub type LLVMGenericValueRef = *mut LLVMOpaqueGenericValue;
pub type LLVMExecutionEngineRef = *mut LLVMOpaqueExecutionEngine;
pub type LLVMMCJITMemoryManagerRef = *mut LLVMOpaqueMCJITMemoryManager;

#[repr(C)]
#[derive(Clone, Copy)]
#[allow(non_snake_case)]
pub struct LLVMMCJITCompilerOptions {
    pub OptLevel: ::libc::c_uint,
    pub CodeModel: LLVMCodeModel,
    pub NoFramePointerElim: LLVMBool,
    pub EnableFastISel: LLVMBool,
    pub MCJMM: LLVMMCJITMemoryManagerRef,
}

pub type LLVMMemoryManagerAllocateCodeSectionCallback =
    extern "C" fn(Opaque: *mut ::libc::c_void,
                  Size: usize,
                  Alignment: ::libc::c_uint,
                  SectionID: ::libc::c_uint,
                  SectionName: *const ::libc::c_char) -> *mut u8;
pub type LLVMMemoryManagerAllocateDataSectionCallback =
    extern "C" fn(Opaque: *mut ::libc::c_void,
                  Size: usize,
                  Alignment: ::libc::c_uint,
                  SectionID: ::libc::c_uint,
                  SectionName: *const ::libc::c_char,
                  IsReadOnly: LLVMBool) -> *mut u8;
pub type LLVMMemoryManagerFinalizeMemoryCallback =
    extern "C" fn(Opaque: *mut ::libc::c_void,
                  ErrMsg: *mut *mut ::libc::c_char) -> LLVMBool;
pub type LLVMMemoryManagerDestroyCallback =
    extern "C" fn(Opaque: *mut ::libc::c_void) -> ();

extern "C" {
    pub fn LLVMLinkInMCJIT() -> ();
    pub fn LLVMLinkInInterpreter() -> ();

    // Operations on generic values
    pub fn LLVMCreateGenericValueOfInt(Ty: LLVMTypeRef,
                                       N: ::libc::c_ulonglong,
                                       IsSigned: LLVMBool) -> LLVMGenericValueRef;
    pub fn LLVMCreateGenericValueOfPointer(P: *mut ::libc::c_void) -> LLVMGenericValueRef;
    pub fn LLVMCreateGenericValueOfFloat(Ty: LLVMTypeRef, N: ::libc::c_double) -> LLVMGenericValueRef;
    pub fn LLVMGenericValueIntWidth(GenValRef: LLVMGenericValueRef) -> ::libc::c_uint;
    pub fn LLVMGenericValueToInt(GenVal: LLVMGenericValueRef,
                                 IsSigned: LLVMBool) -> ::libc::c_ulonglong;
    pub fn LLVMGenericValueToPointer(GenVal: LLVMGenericValueRef) -> *mut ::libc::c_void;
    pub fn LLVMGenericValueToFloat(TyRef: LLVMTypeRef,
                                   GenVal: LLVMGenericValueRef) -> ::libc::c_double;
    pub fn LLVMDisposeGenericValue(GenVal: LLVMGenericValueRef) -> ();

    // Operations on execution engines
    pub fn LLVMCreateExecutionEngineForModule(OutEE:
                                                  *mut LLVMExecutionEngineRef,
                                              M: LLVMModuleRef,
                                              OutError:
                                                  *mut *mut ::libc::c_char)
     -> LLVMBool;
    pub fn LLVMCreateInterpreterForModule(OutInterp:
                                              *mut LLVMExecutionEngineRef,
                                          M: LLVMModuleRef,
                                          OutError: *mut *mut ::libc::c_char)
     -> LLVMBool;
    pub fn LLVMCreateJITCompilerForModule(OutJIT: *mut LLVMExecutionEngineRef,
                                          M: LLVMModuleRef,
                                          OptLevel: ::libc::c_uint,
                                          OutError: *mut *mut ::libc::c_char)
     -> LLVMBool;
    pub fn LLVMInitializeMCJITCompilerOptions(Options:
                                                  *mut LLVMMCJITCompilerOptions,
                                              SizeOfOptions: ::libc::size_t) -> ();

    /// Create an MCJIT execution engine for a module, with the given options.
    ///
    /// It is
    /// the responsibility of the caller to ensure that all fields in Options up to
    /// the given SizeOfOptions are initialized. It is correct to pass a smaller
    /// value of SizeOfOptions that omits some fields. The canonical way of using
    /// this is:
    ///
    /// ```c++
    /// LLVMMCJITCompilerOptions options;
    /// LLVMInitializeMCJITCompilerOptions(&options, sizeof(options));
    /// // ... fill in those options you care about
    /// LLVMCreateMCJITCompilerForModule(&jit, mod, &options, sizeof(options),
    ///                                  &error);
    /// ```
    ///
    /// Note that this is also correct, though possibly suboptimal:
    ///
    /// ```c++
    /// LLVMCreateMCJITCompilerForModule(&jit, mod, 0, 0, &error);
    /// ```
    ///
    /// 0 is returned on success, or 1 on failure.
    pub fn LLVMCreateMCJITCompilerForModule(OutJIT: *mut LLVMExecutionEngineRef,
                                            M: LLVMModuleRef,
                                            Options: *mut LLVMMCJITCompilerOptions,
                                            SizeOfOptions: ::libc::size_t,
                                            OutError: *mut *mut ::libc::c_char) -> LLVMBool;

    /// Deprecated: Use LLVMCreateExecutionEngineForModule instead
    pub fn LLVMCreateExecutionEngine(OutEE: *mut LLVMExecutionEngineRef,
                                     MP: LLVMModuleProviderRef,
                                     OutError: *mut *mut ::libc::c_char) -> LLVMBool;

    /// Deprecated: Use LLVMCreateInterpreterForModule instead
    pub fn LLVMCreateInterpreter(OutInterp: *mut LLVMExecutionEngineRef,
                                 MP: LLVMModuleProviderRef,
                                 OutError: *mut *mut ::libc::c_char) -> LLVMBool;

    /// Deprecated: Use LLVMCreateJITCompilerForModule instead
    pub fn LLVMCreateJITCompiler(OutJIT: *mut LLVMExecutionEngineRef,
                                 MP: LLVMModuleProviderRef,
                                 OptLevel: ::libc::c_uint,
                                 OutError: *mut *mut ::libc::c_char) -> LLVMBool;

    pub fn LLVMDisposeExecutionEngine(EE: LLVMExecutionEngineRef) -> ();
    pub fn LLVMRunStaticConstructors(EE: LLVMExecutionEngineRef) -> ();
    pub fn LLVMRunStaticDestructors(EE: LLVMExecutionEngineRef) -> ();
    pub fn LLVMRunFunctionAsMain(EE: LLVMExecutionEngineRef, F: LLVMValueRef,
                                 ArgC: ::libc::c_uint,
                                 ArgV: *const *const ::libc::c_char,
                                 EnvP: *const *const ::libc::c_char) -> ::libc::c_int;
    pub fn LLVMRunFunction(EE: LLVMExecutionEngineRef, F: LLVMValueRef,
                           NumArgs: ::libc::c_uint,
                           Args: *mut LLVMGenericValueRef) -> LLVMGenericValueRef;
    pub fn LLVMFreeMachineCodeForFunction(EE: LLVMExecutionEngineRef,
                                          F: LLVMValueRef) -> ();
    pub fn LLVMAddModule(EE: LLVMExecutionEngineRef, M: LLVMModuleRef) -> ();
    pub fn LLVMAddModuleProvider(EE: LLVMExecutionEngineRef,
                                 MP: LLVMModuleProviderRef) -> ();
    pub fn LLVMRemoveModule(EE: LLVMExecutionEngineRef, M: LLVMModuleRef,
                            OutMod: *mut LLVMModuleRef,
                            OutError: *mut *mut ::libc::c_char) -> LLVMBool;
    /// Deprecated: Use LLVMRemoveModule instead
    pub fn LLVMRemoveModuleProvider(EE: LLVMExecutionEngineRef,
                                    MP: LLVMModuleProviderRef,
                                    OutMod: *mut LLVMModuleRef,
                                    OutError: *mut *mut ::libc::c_char) -> LLVMBool;
    pub fn LLVMFindFunction(EE: LLVMExecutionEngineRef,
                            Name: *const ::libc::c_char,
                            OutFn: *mut LLVMValueRef) -> LLVMBool;
    pub fn LLVMRecompileAndRelinkFunction(EE: LLVMExecutionEngineRef,
                                          Fn: LLVMValueRef) -> *mut ::libc::c_void;
    pub fn LLVMGetExecutionEngineTargetData(EE: LLVMExecutionEngineRef) -> LLVMTargetDataRef;
    pub fn LLVMGetExecutionEngineTargetMachine(EE: LLVMExecutionEngineRef) -> LLVMTargetMachineRef;
    pub fn LLVMAddGlobalMapping(EE: LLVMExecutionEngineRef,
                                Global: LLVMValueRef,
                                Addr: *mut ::libc::c_void) -> ();
    pub fn LLVMGetPointerToGlobal(EE: LLVMExecutionEngineRef,
                                  Global: LLVMValueRef) -> *mut ::libc::c_void;
    pub fn LLVMGetGlobalValueAddress(EE: LLVMExecutionEngineRef,
                                     Name: *const ::libc::c_char) -> u64;
    pub fn LLVMGetFunctionAddress(EE: LLVMExecutionEngineRef,
                                  Name: *const ::libc::c_char) -> u64;

    // Operations on memory managers
    /// Create a simple custom MCJIT memory manager.
    ///
    /// This memory manager can intercept allocations in a module-oblivious way. It will
    /// return NULL if any of the passed functions are NULL.
    ///
    /// `AllocateCodeSection` and `AllocateDataSection` are called to allocate blocks
    /// of memory for executable code and data, respectively. `FinalizeMemory` is called
    /// to set page permissions and flush caches, returning 0 on success and 1 on error.
    ///
    /// `Opaque` will be passed to the callbacks.
    pub fn LLVMCreateSimpleMCJITMemoryManager(Opaque: *mut ::libc::c_void,
                                              AllocateCodeSection: LLVMMemoryManagerAllocateCodeSectionCallback,
                                              AllocateDataSection: LLVMMemoryManagerAllocateDataSectionCallback,
                                              FinalizeMemory: LLVMMemoryManagerFinalizeMemoryCallback,
                                              Destroy: LLVMMemoryManagerDestroyCallback) -> LLVMMCJITMemoryManagerRef;

    pub fn LLVMDisposeMCJITMemoryManager(MM: LLVMMCJITMemoryManagerRef) -> ();
}
<commit_msg>Replace usize with ::libc::uintptr_t in FFI.<commit_after>//! Runtime code generation and execution.

use super::prelude::*;
use super::target::LLVMTargetDataRef;
use super::target_machine::{LLVMTargetMachineRef, LLVMCodeModel};

pub enum LLVMOpaqueGenericValue {}
pub enum LLVMOpaqueExecutionEngine {}
pub enum LLVMOpaqueMCJITMemoryManager {}

pub type LLVMGenericValueRef = *mut LLVMOpaqueGenericValue;
pub type LLVMExecutionEngineRef = *mut LLVMOpaqueExecutionEngine;
pub type LLVMMCJITMemoryManagerRef = *mut LLVMOpaqueMCJITMemoryManager;

#[repr(C)]
#[derive(Clone, Copy)]
#[allow(non_snake_case)]
pub struct LLVMMCJITCompilerOptions {
    pub OptLevel: ::libc::c_uint,
    pub CodeModel: LLVMCodeModel,
    pub NoFramePointerElim: LLVMBool,
    pub EnableFastISel: LLVMBool,
    pub MCJMM: LLVMMCJITMemoryManagerRef,
}

pub type LLVMMemoryManagerAllocateCodeSectionCallback =
    extern "C" fn(Opaque: *mut ::libc::c_void,
                  Size: ::libc::uintptr_t,
                  Alignment: ::libc::c_uint,
                  SectionID: ::libc::c_uint,
                  SectionName: *const ::libc::c_char) -> *mut u8;
pub type LLVMMemoryManagerAllocateDataSectionCallback =
    extern "C" fn(Opaque: *mut ::libc::c_void,
                  Size: ::libc::uintptr_t,
                  Alignment: ::libc::c_uint,
                  SectionID: ::libc::c_uint,
                  SectionName: *const ::libc::c_char,
                  IsReadOnly: LLVMBool) -> *mut u8;
pub type LLVMMemoryManagerFinalizeMemoryCallback =
    extern "C" fn(Opaque: *mut ::libc::c_void,
                  ErrMsg: *mut *mut ::libc::c_char) -> LLVMBool;
pub type LLVMMemoryManagerDestroyCallback =
    extern "C" fn(Opaque: *mut ::libc::c_void) -> ();

extern "C" {
    pub fn LLVMLinkInMCJIT() -> ();
    pub fn LLVMLinkInInterpreter() -> ();

    // Operations on generic values
    pub fn LLVMCreateGenericValueOfInt(Ty: LLVMTypeRef,
                                       N: ::libc::c_ulonglong,
                                       IsSigned: LLVMBool) -> LLVMGenericValueRef;
    pub fn LLVMCreateGenericValueOfPointer(P: *mut ::libc::c_void) -> LLVMGenericValueRef;
    pub fn LLVMCreateGenericValueOfFloat(Ty: LLVMTypeRef, N: ::libc::c_double) -> LLVMGenericValueRef;
    pub fn LLVMGenericValueIntWidth(GenValRef: LLVMGenericValueRef) -> ::libc::c_uint;
    pub fn LLVMGenericValueToInt(GenVal: LLVMGenericValueRef,
                                 IsSigned: LLVMBool) -> ::libc::c_ulonglong;
    pub fn LLVMGenericValueToPointer(GenVal: LLVMGenericValueRef) -> *mut ::libc::c_void;
    pub fn LLVMGenericValueToFloat(TyRef: LLVMTypeRef,
                                   GenVal: LLVMGenericValueRef) -> ::libc::c_double;
    pub fn LLVMDisposeGenericValue(GenVal: LLVMGenericValueRef) -> ();

    // Operations on execution engines
    pub fn LLVMCreateExecutionEngineForModule(OutEE:
                                                  *mut LLVMExecutionEngineRef,
                                              M: LLVMModuleRef,
                                              OutError:
                                                  *mut *mut ::libc::c_char)
     -> LLVMBool;
    pub fn LLVMCreateInterpreterForModule(OutInterp:
                                              *mut LLVMExecutionEngineRef,
                                          M: LLVMModuleRef,
                                          OutError: *mut *mut ::libc::c_char)
     -> LLVMBool;
    pub fn LLVMCreateJITCompilerForModule(OutJIT: *mut LLVMExecutionEngineRef,
                                          M: LLVMModuleRef,
                                          OptLevel: ::libc::c_uint,
                                          OutError: *mut *mut ::libc::c_char)
     -> LLVMBool;
    pub fn LLVMInitializeMCJITCompilerOptions(Options:
                                                  *mut LLVMMCJITCompilerOptions,
                                              SizeOfOptions: ::libc::size_t) -> ();

    /// Create an MCJIT execution engine for a module, with the given options.
    ///
    /// It is
    /// the responsibility of the caller to ensure that all fields in Options up to
    /// the given SizeOfOptions are initialized. It is correct to pass a smaller
    /// value of SizeOfOptions that omits some fields. The canonical way of using
    /// this is:
    ///
    /// ```c++
    /// LLVMMCJITCompilerOptions options;
    /// LLVMInitializeMCJITCompilerOptions(&options, sizeof(options));
    /// // ... fill in those options you care about
    /// LLVMCreateMCJITCompilerForModule(&jit, mod, &options, sizeof(options),
    ///                                  &error);
    /// ```
    ///
    /// Note that this is also correct, though possibly suboptimal:
    ///
    /// ```c++
    /// LLVMCreateMCJITCompilerForModule(&jit, mod, 0, 0, &error);
    /// ```
    ///
    /// 0 is returned on success, or 1 on failure.
    pub fn LLVMCreateMCJITCompilerForModule(OutJIT: *mut LLVMExecutionEngineRef,
                                            M: LLVMModuleRef,
                                            Options: *mut LLVMMCJITCompilerOptions,
                                            SizeOfOptions: ::libc::size_t,
                                            OutError: *mut *mut ::libc::c_char) -> LLVMBool;

    /// Deprecated: Use LLVMCreateExecutionEngineForModule instead
    pub fn LLVMCreateExecutionEngine(OutEE: *mut LLVMExecutionEngineRef,
                                     MP: LLVMModuleProviderRef,
                                     OutError: *mut *mut ::libc::c_char) -> LLVMBool;

    /// Deprecated: Use LLVMCreateInterpreterForModule instead
    pub fn LLVMCreateInterpreter(OutInterp: *mut LLVMExecutionEngineRef,
                                 MP: LLVMModuleProviderRef,
                                 OutError: *mut *mut ::libc::c_char) -> LLVMBool;

    /// Deprecated: Use LLVMCreateJITCompilerForModule instead
    pub fn LLVMCreateJITCompiler(OutJIT: *mut LLVMExecutionEngineRef,
                                 MP: LLVMModuleProviderRef,
                                 OptLevel: ::libc::c_uint,
                                 OutError: *mut *mut ::libc::c_char) -> LLVMBool;

    pub fn LLVMDisposeExecutionEngine(EE: LLVMExecutionEngineRef) -> ();
    pub fn LLVMRunStaticConstructors(EE: LLVMExecutionEngineRef) -> ();
    pub fn LLVMRunStaticDestructors(EE: LLVMExecutionEngineRef) -> ();
    pub fn LLVMRunFunctionAsMain(EE: LLVMExecutionEngineRef, F: LLVMValueRef,
                                 ArgC: ::libc::c_uint,
                                 ArgV: *const *const ::libc::c_char,
                                 EnvP: *const *const ::libc::c_char) -> ::libc::c_int;
    pub fn LLVMRunFunction(EE: LLVMExecutionEngineRef, F: LLVMValueRef,
                           NumArgs: ::libc::c_uint,
                           Args: *mut LLVMGenericValueRef) -> LLVMGenericValueRef;
    pub fn LLVMFreeMachineCodeForFunction(EE: LLVMExecutionEngineRef,
                                          F: LLVMValueRef) -> ();
    pub fn LLVMAddModule(EE: LLVMExecutionEngineRef, M: LLVMModuleRef) -> ();
    pub fn LLVMAddModuleProvider(EE: LLVMExecutionEngineRef,
                                 MP: LLVMModuleProviderRef) -> ();
    pub fn LLVMRemoveModule(EE: LLVMExecutionEngineRef, M: LLVMModuleRef,
                            OutMod: *mut LLVMModuleRef,
                            OutError: *mut *mut ::libc::c_char) -> LLVMBool;
    /// Deprecated: Use LLVMRemoveModule instead
    pub fn LLVMRemoveModuleProvider(EE: LLVMExecutionEngineRef,
                                    MP: LLVMModuleProviderRef,
                                    OutMod: *mut LLVMModuleRef,
                                    OutError: *mut *mut ::libc::c_char) -> LLVMBool;
    pub fn LLVMFindFunction(EE: LLVMExecutionEngineRef,
                            Name: *const ::libc::c_char,
                            OutFn: *mut LLVMValueRef) -> LLVMBool;
    pub fn LLVMRecompileAndRelinkFunction(EE: LLVMExecutionEngineRef,
                                          Fn: LLVMValueRef) -> *mut ::libc::c_void;
    pub fn LLVMGetExecutionEngineTargetData(EE: LLVMExecutionEngineRef) -> LLVMTargetDataRef;
    pub fn LLVMGetExecutionEngineTargetMachine(EE: LLVMExecutionEngineRef) -> LLVMTargetMachineRef;
    pub fn LLVMAddGlobalMapping(EE: LLVMExecutionEngineRef,
                                Global: LLVMValueRef,
                                Addr: *mut ::libc::c_void) -> ();
    pub fn LLVMGetPointerToGlobal(EE: LLVMExecutionEngineRef,
                                  Global: LLVMValueRef) -> *mut ::libc::c_void;
    pub fn LLVMGetGlobalValueAddress(EE: LLVMExecutionEngineRef,
                                     Name: *const ::libc::c_char) -> u64;
    pub fn LLVMGetFunctionAddress(EE: LLVMExecutionEngineRef,
                                  Name: *const ::libc::c_char) -> u64;

    // Operations on memory managers
    /// Create a simple custom MCJIT memory manager.
    ///
    /// This memory manager can intercept allocations in a module-oblivious way. It will
    /// return NULL if any of the passed functions are NULL.
    ///
    /// `AllocateCodeSection` and `AllocateDataSection` are called to allocate blocks
    /// of memory for executable code and data, respectively. `FinalizeMemory` is called
    /// to set page permissions and flush caches, returning 0 on success and 1 on error.
    ///
    /// `Opaque` will be passed to the callbacks.
    pub fn LLVMCreateSimpleMCJITMemoryManager(Opaque: *mut ::libc::c_void,
                                              AllocateCodeSection: LLVMMemoryManagerAllocateCodeSectionCallback,
                                              AllocateDataSection: LLVMMemoryManagerAllocateDataSectionCallback,
                                              FinalizeMemory: LLVMMemoryManagerFinalizeMemoryCallback,
                                              Destroy: LLVMMemoryManagerDestroyCallback) -> LLVMMCJITMemoryManagerRef;

    pub fn LLVMDisposeMCJITMemoryManager(MM: LLVMMCJITMemoryManagerRef) -> ();
}
<|endoftext|>


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

use crate::errors::BuildProjectError;
use log::info;
use serde::{Serialize, Serializer};
use std::fs::{create_dir_all, File};
use std::io;
use std::io::prelude::*;
use std::{path::PathBuf, sync::Mutex};

type BuildProjectResult = Result<(), BuildProjectError>;

pub trait ArtifactWriter {
    fn write_if_changed(&self, path: PathBuf, content: Vec<u8>) -> BuildProjectResult;
    fn remove(&self, path: PathBuf) -> BuildProjectResult;
    fn finalize(&self) -> crate::errors::Result<()>;
}

pub struct ArtifactFileWriter;

impl ArtifactWriter for ArtifactFileWriter {
    fn write_if_changed(&self, path: PathBuf, content: Vec<u8>) -> BuildProjectResult {
        write_file(&path, &content).map_err(|error| BuildProjectError::WriteFileError {
            file: path,
            source: error,
        })
    }

    fn remove(&self, path: PathBuf) -> BuildProjectResult {
        std::fs::remove_file(&path).unwrap_or_else(|_| {
            info!("tried to delete already deleted file: {:?}", path);
        });
        Ok(())
    }

    fn finalize(&self) -> crate::errors::Result<()> {
        Ok(())
    }
}

#[derive(Serialize)]
struct CodegenRecords {
    pub removed: Vec<ArtifactDeletionRecord>,
    pub changed: Vec<ArtifactUpdateRecord>,
}

#[derive(Serialize)]
struct ArtifactDeletionRecord {
    pub path: PathBuf,
}

#[derive(Serialize)]
struct ArtifactUpdateRecord {
    pub path: PathBuf,
    #[serde(serialize_with = "from_utf8")]
    pub data: Vec<u8>,
}

fn from_utf8<S>(slice: &Vec<u8>, s: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    s.serialize_str(std::str::from_utf8(slice).unwrap())
}

pub struct ArtifactDifferenceWriter {
    codegen_records: Mutex<CodegenRecords>,
    codegen_filepath: PathBuf,
}

impl ArtifactDifferenceWriter {
    pub fn new(codegen_filepath: PathBuf) -> ArtifactDifferenceWriter {
        ArtifactDifferenceWriter {
            codegen_filepath,
            codegen_records: Mutex::new(CodegenRecords {
                changed: Vec::new(),
                removed: Vec::new(),
            }),
        }
    }
}

impl ArtifactWriter for ArtifactDifferenceWriter {
    fn write_if_changed(&self, path: PathBuf, content: Vec<u8>) -> BuildProjectResult {
        let content_is_same = content_is_same(&path, &content).map_err(|error| {
            BuildProjectError::WriteFileError {
                file: path.clone(),
                source: error,
            }
        })?;
        if !content_is_same {
            self.codegen_records
                .lock()
                .unwrap()
                .changed
                .push(ArtifactUpdateRecord {
                    path,
                    data: content,
                });
        }
        Ok(())
    }

    fn remove(&self, path: PathBuf) -> BuildProjectResult {
        if path.exists() {
            self.codegen_records
                .lock()
                .unwrap()
                .removed
                .push(ArtifactDeletionRecord { path });
        }
        Ok(())
    }

    fn finalize(&self) -> crate::errors::Result<()> {
        (|| {
            let mut file = File::create(&self.codegen_filepath)?;
            file.write_all(&serde_json::to_string(&self.codegen_records)?.as_bytes())
        })()
        .map_err(|error| crate::errors::Error::WriteFileError {
            file: self.codegen_filepath.clone(),
            source: error,
        })
    }
}

fn ensure_file_directory_exists(file_path: &PathBuf) -> io::Result<()> {
    if let Some(file_directory) = file_path.parent() {
        if !file_directory.exists() {
            create_dir_all(file_directory)?;
        }
    }

    Ok(())
}

fn write_file(path: &PathBuf, content: &[u8]) -> io::Result<()> {
    if path.exists() {
        let existing_content = std::fs::read(path)?;
        if existing_content == content {
            return Ok(());
        }
    } else {
        ensure_file_directory_exists(path)?;
    }

    let mut file = File::create(path)?;
    file.write_all(&content)?;
    Ok(())
}

fn content_is_same(path: &PathBuf, content: &Vec<u8>) -> io::Result<bool> {
    if path.exists() {
        let existing_content = std::fs::read(path)?;
        Ok(&existing_content == content)
    } else {
        Ok(false)
    }
}
<commit_msg>Rust compiler: don't verify changes against filesystem if --full-build is passed for codegen<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::errors::BuildProjectError;
use log::info;
use serde::{Serialize, Serializer};
use std::fs::{create_dir_all, File};
use std::io;
use std::io::prelude::*;
use std::{path::PathBuf, sync::Mutex};

type BuildProjectResult = Result<(), BuildProjectError>;

pub trait ArtifactWriter {
    fn write_if_changed(&self, path: PathBuf, content: Vec<u8>) -> BuildProjectResult;
    fn remove(&self, path: PathBuf) -> BuildProjectResult;
    fn finalize(&self) -> crate::errors::Result<()>;
}

pub struct ArtifactFileWriter;

impl ArtifactWriter for ArtifactFileWriter {
    fn write_if_changed(&self, path: PathBuf, content: Vec<u8>) -> BuildProjectResult {
        write_file(&path, &content).map_err(|error| BuildProjectError::WriteFileError {
            file: path,
            source: error,
        })
    }

    fn remove(&self, path: PathBuf) -> BuildProjectResult {
        std::fs::remove_file(&path).unwrap_or_else(|_| {
            info!("tried to delete already deleted file: {:?}", path);
        });
        Ok(())
    }

    fn finalize(&self) -> crate::errors::Result<()> {
        Ok(())
    }
}

#[derive(Serialize)]
struct CodegenRecords {
    pub removed: Vec<ArtifactDeletionRecord>,
    pub changed: Vec<ArtifactUpdateRecord>,
}

#[derive(Serialize)]
struct ArtifactDeletionRecord {
    pub path: PathBuf,
}

#[derive(Serialize)]
struct ArtifactUpdateRecord {
    pub path: PathBuf,
    #[serde(serialize_with = "from_utf8")]
    pub data: Vec<u8>,
}

fn from_utf8<S>(slice: &Vec<u8>, s: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    s.serialize_str(std::str::from_utf8(slice).unwrap())
}

pub struct ArtifactDifferenceWriter {
    codegen_records: Mutex<CodegenRecords>,
    codegen_filepath: PathBuf,
    verify_changes_against_filesystem: bool,
}

impl ArtifactDifferenceWriter {
    pub fn new(
        codegen_filepath: PathBuf,
        verify_changes_against_filesystem: bool,
    ) -> ArtifactDifferenceWriter {
        ArtifactDifferenceWriter {
            codegen_filepath,
            codegen_records: Mutex::new(CodegenRecords {
                changed: Vec::new(),
                removed: Vec::new(),
            }),
            verify_changes_against_filesystem,
        }
    }
}

impl ArtifactWriter for ArtifactDifferenceWriter {
    fn write_if_changed(&self, path: PathBuf, content: Vec<u8>) -> BuildProjectResult {
        let should_include_artifact_in_codegen = !self.verify_changes_against_filesystem
            || !content_is_same(&path, &content).map_err(|error| {
                BuildProjectError::WriteFileError {
                    file: path.clone(),
                    source: error,
                }
            })?;
        if should_include_artifact_in_codegen {
            self.codegen_records
                .lock()
                .unwrap()
                .changed
                .push(ArtifactUpdateRecord {
                    path,
                    data: content,
                });
        }
        Ok(())
    }

    fn remove(&self, path: PathBuf) -> BuildProjectResult {
        if path.exists() {
            self.codegen_records
                .lock()
                .unwrap()
                .removed
                .push(ArtifactDeletionRecord { path });
        }
        Ok(())
    }

    fn finalize(&self) -> crate::errors::Result<()> {
        (|| {
            let mut file = File::create(&self.codegen_filepath)?;
            file.write_all(&serde_json::to_string(&self.codegen_records)?.as_bytes())
        })()
        .map_err(|error| crate::errors::Error::WriteFileError {
            file: self.codegen_filepath.clone(),
            source: error,
        })
    }
}

fn ensure_file_directory_exists(file_path: &PathBuf) -> io::Result<()> {
    if let Some(file_directory) = file_path.parent() {
        if !file_directory.exists() {
            create_dir_all(file_directory)?;
        }
    }

    Ok(())
}

fn write_file(path: &PathBuf, content: &[u8]) -> io::Result<()> {
    if path.exists() {
        let existing_content = std::fs::read(path)?;
        if existing_content == content {
            return Ok(());
        }
    } else {
        ensure_file_directory_exists(path)?;
    }

    let mut file = File::create(path)?;
    file.write_all(&content)?;
    Ok(())
}

fn content_is_same(path: &PathBuf, content: &Vec<u8>) -> io::Result<bool> {
    if path.exists() {
        let existing_content = std::fs::read(path)?;
        Ok(&existing_content == content)
    } else {
        Ok(false)
    }
}
<|endoftext|>


<commit_before>#[cfg(not(feature = "static-link"))]
mod imp {
    pub fn build() {
        rocksdb();
    }

    #[cfg(unix)]
    fn rocksdb() {
        println!("cargo:rustc-link-lib=dylib=rocksdb");
    }

    #[cfg(windows)]
    fn rocksdb() {
        println!("cargo:rustc-link-lib=rocksdb");
        for lib in env!("LIB").split(";") {
            if !lib.is_empty() {
                println!("cargo:rustc-link-search=native={}", lib);
            }
        }
        println!("cargo:rustc-link-lib=static=shlwapi");
        println!("cargo:rustc-link-lib=static=rpcrt4");
    }
}

#[cfg(feature = "static-link")]
mod imp {
    use std::env;
    use std::fs;
    use std::path::Path;
    use std::process::Command;

    pub fn build() {
        println!("cargo:warning=static link feature enabled, it'll take minutes to finish compiling...");

        #[cfg(feature = "snappy")]
        snappy();

        #[cfg(feature = "zlib")]
        zlib();

        #[cfg(feature = "bzip2")]
        bzip2();

        #[cfg(feature = "lz4")]
        lz4();

        #[cfg(feature = "zstd")]
        zstd();

        rocksdb();
    }

    #[cfg(feature = "snappy")]
    fn snappy() {
        if !Path::new("snappy/.git").exists() {
            let _ = Command::new("git")
                .args(&["submodule", "update", "--init", "snappy"])
                .status();
        }

        // cmake can only have 1 run in 1 crate
        // or else the `build` directory will be overwritten
        let out_dir = env::var("OUT_DIR").unwrap();
        let this_out_dir = Path::new(&out_dir).join("snappy_out");
        let _ = fs::create_dir(&this_out_dir);

        let dst = cmake::Config::new("snappy")
            .define("CMAKE_POSITION_INDEPENDENT_CODE", "ON")
            .build_target("snappy")
            .out_dir(this_out_dir)
            .very_verbose(true)
            .uses_cxx11()
            .build();

        println!("cargo:rustc-link-search=native={}/build/", dst.display());
        println!("cargo:rustc-link-lib=static=snappy");
    }

    #[cfg(feature = "zlib")]
    fn zlib() {
        if !Path::new("zlib/.git").exists() {
            let _ = Command::new("git")
                .args(&["submodule", "update", "--init", "zlib"])
                .status();
        }

        Command::new(env::current_dir().unwrap().join("zlib/configure"))
            .current_dir(env::current_dir().unwrap().join("zlib"))
            .arg("--static")
            .output()
            .expect("failed to execute ./configure");

        let mut cfg = ::cc::Build::new();
        cfg.warnings(false);
        cfg.include("zlib");

        // TODO: borrow following list form Makefile
        let filez = "adler32.c crc32.c deflate.c infback.c inffast.c inflate.c inftrees.c trees.c zutil.c";
        let fileg = "compress.c uncompr.c gzclose.c gzlib.c gzread.c gzwrite.c";

        for file in filez.split(" ") {
            cfg.file(format!("zlib/{}", file));
        }
        for file in fileg.split(" ") {
            cfg.file(format!("zlib/{}", file));
        }

        cfg.pic(true);
        cfg.opt_level(2);
        cfg.compile("libz.a");
    }

    // Yes, copied from alexcrichton/bzip2-rs
    #[cfg(feature = "bzip2")]
    fn bzip2() {
        if !Path::new("bzip2/.git").exists() {
            let _ = Command::new("git")
                .args(&["submodule", "update", "--init", "bzip2"])
                .status();
        }

        let mut cfg = ::cc::Build::new();

        if cfg!(windows) {
            cfg.define("_WIN32", None);
            cfg.define("BZ_EXPORT", None);
        }

        cfg.include("bzip2")
            .define("_FILE_OFFSET_BITS", Some("64"))
            .define("BZ_NO_STDIO", None)
            .opt_level(2)
            .warnings(false)
            .file("bzip2/blocksort.c")
            .file("bzip2/huffman.c")
            .file("bzip2/crctable.c")
            .file("bzip2/randtable.c")
            .file("bzip2/compress.c")
            .file("bzip2/decompress.c")
            .file("bzip2/bzlib.c")
            .compile("libbz2.a");
    }

    #[cfg(feature = "lz4")]
    fn lz4() {
        if !Path::new("lz4/.git").exists() {
            let _ = Command::new("git")
                .args(&["submodule", "update", "--init", "lz4"])
                .status();
        }

        ::cc::Build::new()
            .warnings(false)
            .include("lz4/lib")
            .opt_level(2)
            .pic(true)
            .file("lz4/lib/lz4.c")
            .file("lz4/lib/lz4frame.c")
            .file("lz4/lib/lz4hc.c")
            .file("lz4/lib/xxhash.c")
            .compile("liblz4.a");
    }

    #[cfg(feature = "zstd")]
    fn zstd() {
        if !Path::new("zstd/.git").exists() {
            let _ = Command::new("git")
                .args(&["submodule", "update", "--init", "zstd"])
                .status();
        }

        let files = [
            "zstd/lib/common/entropy_common.c",
            "zstd/lib/common/error_private.c",
            "zstd/lib/common/fse_decompress.c",
            "zstd/lib/common/pool.c",
            "zstd/lib/common/threading.c",
            "zstd/lib/common/xxhash.c",
            "zstd/lib/common/zstd_common.c",
            "zstd/lib/compress/fse_compress.c",
            "zstd/lib/compress/huf_compress.c",
            "zstd/lib/compress/zstd_compress.c",
            "zstd/lib/compress/zstdmt_compress.c",
            "zstd/lib/decompress/huf_decompress.c",
            "zstd/lib/decompress/zstd_decompress.c",
            "zstd/lib/dictBuilder/cover.c",
            "zstd/lib/dictBuilder/divsufsort.c",
            "zstd/lib/dictBuilder/zdict.c",
        ];

        ::cc::Build::new()
            .define("ZSTD_LEGACY_SUPPORT", Some("0"))
            .include("zstd/lib")
            .include("zstd/lib/common")
            .opt_level(3)
            .warnings(false)
            .files(&files)
            .compile("libzstd.a");
    }

    fn rocksdb() {
        if !Path::new("rocksdb/.git").exists() {
            let _ = Command::new("git")
                .args(&["submodule", "update", "--init", "rocksdb"])
                .status();
        }

        let mut cfg = cmake::Config::new("rocksdb");

        #[cfg(feature = "snappy")]
        {
            let src = std::env::current_dir().unwrap();
            let out_dir = env::var("OUT_DIR").unwrap();
            let snappy_out_dir = Path::new(&out_dir).join("snappy_out");

            // FIXME: how to use cmake's define?
            cfg.cxxflag("-DSNAPPY");
            cfg.cxxflag(format!("-I{}", src.join("snappy").display()));
            // snappy-stubs-public.h
            cfg.cxxflag(format!("-I{}", snappy_out_dir.join("build").display()));
        }

        #[cfg(feature = "zlib")]
        {
            cfg.cxxflag("-DZLIB");
            cfg.cxxflag("-Izlib");
        }

        #[cfg(feature = "bzip2")]
        {
            cfg.cxxflag("-DBZIP2");
            cfg.cxxflag("-Ibzip2");
        }

        #[cfg(feature = "lz4")]
        {
            cfg.cxxflag("-DLZ4");
            cfg.cxxflag("-Ilz4/lib");
        }

        #[cfg(feature = "zstd")]
        {
            cfg.cxxflag("-DZSTD");
            cfg.cxxflag("-Izstd/lib");
        }

        let dst = cfg
            // .define("CMAKE_BUILD_TYPE", "Release") //  RelWithDebInfo
            .define("WITH_GFLAGS", "OFF")
            .build_target("rocksdb")
            .build();

        println!("cargo:rustc-link-search=native={}/build/", dst.display());
        println!("cargo:rustc-link-lib=static=rocksdb");
    }
}

fn main() {
    if cfg!(not(target_pointer_width = "64")) {
        panic!("only 64 bit system supported");
    }

    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=src/c.rs");
    println!("cargo:rerun-if-changed=src/lib.rs");

    imp::build();

    let mut build = ::cc::Build::new();

    #[cfg(feature = "static-link")]
    build.include("rocksdb/include");

    #[cfg(unix)]
    {
        build.flag("-std=c++11");
        build.flag("-fno-rtti");
    }

    #[cfg(windows)]
    {
        let lib = vcpkg::Config::new()
            .emit_includes(true)
            .find_package("rocksdb")
            .unwrap();

        for inc in lib.include_paths {
            build.include(inc);
        }
        build.static_crt(true);
    }

    build
        .cpp(true)
        .pic(true)
        .opt_level(2)
        .warnings(false)
        .include(".")
        .file("rocks/cache.cc")
        .file("rocks/comparator.cc")
        .file("rocks/convenience.cc")
        .file("rocks/db.cc")
        .file("rocks/db_dump_tool.cc")
        .file("rocks/env.cc")
        .file("rocks/filter_policy.cc")
        .file("rocks/iostats_context.cc")
        .file("rocks/iterator.cc")
        .file("rocks/metadata.cc")
        .file("rocks/options.cc")
        .file("rocks/perf_context.cc")
        .file("rocks/perf_level.cc")
        .file("rocks/rate_limiter.cc")
        .file("rocks/slice.cc")
        .file("rocks/snapshot.cc")
        .file("rocks/sst_file_writer.cc")
        .file("rocks/statistics.cc")
        .file("rocks/status.cc")
        .file("rocks/table.cc")
        .file("rocks/table_properties.cc")
        .file("rocks/transaction_log.cc")
        .file("rocks/universal_compaction.cc")
        .file("rocks/util.cc")
        .file("rocks/write_batch.cc")
        .file("rocks/write_buffer_manager.cc")
        .file("rocks/debug.cc")
        .file("rocks/listener.cc")
        .file("rocks/compaction_job_stats.cc")
        .file("rocks/thread_status.cc")
        .file("rocks/options_util.cc")
        .compile("librocksdb_wrap");
}
<commit_msg>fix(build): use MT under windows<commit_after>#[cfg(not(feature = "static-link"))]
mod imp {
    pub fn build() {
        rocksdb();
    }

    #[cfg(unix)]
    fn rocksdb() {
        println!("cargo:rustc-link-lib=dylib=rocksdb");
    }

    #[cfg(windows)]
    fn rocksdb() {
        println!("cargo:rustc-link-lib=rocksdb");
        for lib in env!("LIB").split(";") {
            if !lib.is_empty() {
                println!("cargo:rustc-link-search=native={}", lib);
            }
        }
        println!("cargo:rustc-link-lib=static=shlwapi");
        println!("cargo:rustc-link-lib=static=rpcrt4");
    }
}

#[cfg(feature = "static-link")]
mod imp {
    use std::env;
    use std::fs;
    use std::path::Path;
    use std::process::Command;

    pub fn build() {
        println!("cargo:warning=static link feature enabled, it'll take minutes to finish compiling...");

        #[cfg(feature = "snappy")]
        snappy();

        #[cfg(feature = "zlib")]
        zlib();

        #[cfg(feature = "bzip2")]
        bzip2();

        #[cfg(feature = "lz4")]
        lz4();

        #[cfg(feature = "zstd")]
        zstd();

        rocksdb();
    }

    #[cfg(feature = "snappy")]
    fn snappy() {
        if !Path::new("snappy/.git").exists() {
            let _ = Command::new("git")
                .args(&["submodule", "update", "--init", "snappy"])
                .status();
        }

        // cmake can only have 1 run in 1 crate
        // or else the `build` directory will be overwritten
        let out_dir = env::var("OUT_DIR").unwrap();
        let this_out_dir = Path::new(&out_dir).join("snappy_out");
        let _ = fs::create_dir(&this_out_dir);

        let dst = cmake::Config::new("snappy")
            .define("CMAKE_POSITION_INDEPENDENT_CODE", "ON")
            .build_target("snappy")
            .out_dir(this_out_dir)
            .very_verbose(true)
            .uses_cxx11()
            .build();

        println!("cargo:rustc-link-search=native={}/build/", dst.display());
        println!("cargo:rustc-link-lib=static=snappy");
    }

    #[cfg(feature = "zlib")]
    fn zlib() {
        if !Path::new("zlib/.git").exists() {
            let _ = Command::new("git")
                .args(&["submodule", "update", "--init", "zlib"])
                .status();
        }

        Command::new(env::current_dir().unwrap().join("zlib/configure"))
            .current_dir(env::current_dir().unwrap().join("zlib"))
            .arg("--static")
            .output()
            .expect("failed to execute ./configure");

        let mut cfg = ::cc::Build::new();
        cfg.warnings(false);
        cfg.include("zlib");

        // TODO: borrow following list form Makefile
        let filez = "adler32.c crc32.c deflate.c infback.c inffast.c inflate.c inftrees.c trees.c zutil.c";
        let fileg = "compress.c uncompr.c gzclose.c gzlib.c gzread.c gzwrite.c";

        for file in filez.split(" ") {
            cfg.file(format!("zlib/{}", file));
        }
        for file in fileg.split(" ") {
            cfg.file(format!("zlib/{}", file));
        }

        cfg.pic(true);
        cfg.opt_level(2);
        cfg.compile("libz.a");
    }

    // Yes, copied from alexcrichton/bzip2-rs
    #[cfg(feature = "bzip2")]
    fn bzip2() {
        if !Path::new("bzip2/.git").exists() {
            let _ = Command::new("git")
                .args(&["submodule", "update", "--init", "bzip2"])
                .status();
        }

        let mut cfg = ::cc::Build::new();

        if cfg!(windows) {
            cfg.define("_WIN32", None);
            cfg.define("BZ_EXPORT", None);
        }

        cfg.include("bzip2")
            .define("_FILE_OFFSET_BITS", Some("64"))
            .define("BZ_NO_STDIO", None)
            .opt_level(2)
            .warnings(false)
            .file("bzip2/blocksort.c")
            .file("bzip2/huffman.c")
            .file("bzip2/crctable.c")
            .file("bzip2/randtable.c")
            .file("bzip2/compress.c")
            .file("bzip2/decompress.c")
            .file("bzip2/bzlib.c")
            .compile("libbz2.a");
    }

    #[cfg(feature = "lz4")]
    fn lz4() {
        if !Path::new("lz4/.git").exists() {
            let _ = Command::new("git")
                .args(&["submodule", "update", "--init", "lz4"])
                .status();
        }

        ::cc::Build::new()
            .warnings(false)
            .include("lz4/lib")
            .opt_level(2)
            .pic(true)
            .file("lz4/lib/lz4.c")
            .file("lz4/lib/lz4frame.c")
            .file("lz4/lib/lz4hc.c")
            .file("lz4/lib/xxhash.c")
            .compile("liblz4.a");
    }

    #[cfg(feature = "zstd")]
    fn zstd() {
        if !Path::new("zstd/.git").exists() {
            let _ = Command::new("git")
                .args(&["submodule", "update", "--init", "zstd"])
                .status();
        }

        let files = [
            "zstd/lib/common/entropy_common.c",
            "zstd/lib/common/error_private.c",
            "zstd/lib/common/fse_decompress.c",
            "zstd/lib/common/pool.c",
            "zstd/lib/common/threading.c",
            "zstd/lib/common/xxhash.c",
            "zstd/lib/common/zstd_common.c",
            "zstd/lib/compress/fse_compress.c",
            "zstd/lib/compress/huf_compress.c",
            "zstd/lib/compress/zstd_compress.c",
            "zstd/lib/compress/zstdmt_compress.c",
            "zstd/lib/decompress/huf_decompress.c",
            "zstd/lib/decompress/zstd_decompress.c",
            "zstd/lib/dictBuilder/cover.c",
            "zstd/lib/dictBuilder/divsufsort.c",
            "zstd/lib/dictBuilder/zdict.c",
        ];

        ::cc::Build::new()
            .define("ZSTD_LEGACY_SUPPORT", Some("0"))
            .include("zstd/lib")
            .include("zstd/lib/common")
            .opt_level(3)
            .warnings(false)
            .files(&files)
            .compile("libzstd.a");
    }

    fn rocksdb() {
        if !Path::new("rocksdb/.git").exists() {
            let _ = Command::new("git")
                .args(&["submodule", "update", "--init", "rocksdb"])
                .status();
        }

        let mut cfg = cmake::Config::new("rocksdb");

        #[cfg(feature = "snappy")]
        {
            let src = std::env::current_dir().unwrap();
            let out_dir = env::var("OUT_DIR").unwrap();
            let snappy_out_dir = Path::new(&out_dir).join("snappy_out");

            // FIXME: how to use cmake's define?
            cfg.cxxflag("-DSNAPPY");
            cfg.cxxflag(format!("-I{}", src.join("snappy").display()));
            // snappy-stubs-public.h
            cfg.cxxflag(format!("-I{}", snappy_out_dir.join("build").display()));
        }

        #[cfg(feature = "zlib")]
        {
            cfg.cxxflag("-DZLIB");
            cfg.cxxflag("-Izlib");
        }

        #[cfg(feature = "bzip2")]
        {
            cfg.cxxflag("-DBZIP2");
            cfg.cxxflag("-Ibzip2");
        }

        #[cfg(feature = "lz4")]
        {
            cfg.cxxflag("-DLZ4");
            cfg.cxxflag("-Ilz4/lib");
        }

        #[cfg(feature = "zstd")]
        {
            cfg.cxxflag("-DZSTD");
            cfg.cxxflag("-Izstd/lib");
        }

        let dst = cfg
            // .define("CMAKE_BUILD_TYPE", "Release") //  RelWithDebInfo
            .define("WITH_GFLAGS", "OFF")
            .build_target("rocksdb")
            .build();

        println!("cargo:rustc-link-search=native={}/build/", dst.display());
        println!("cargo:rustc-link-lib=static=rocksdb");
    }
}

fn main() {
    if cfg!(not(target_pointer_width = "64")) {
        panic!("only 64 bit system supported");
    }

    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=src/c.rs");
    println!("cargo:rerun-if-changed=src/lib.rs");

    imp::build();

    let mut build = ::cc::Build::new();

    #[cfg(feature = "static-link")]
    build.include("rocksdb/include");

    #[cfg(unix)]
    {
        build.flag("-std=c++11");
        build.flag("-fno-rtti");
    }

    #[cfg(windows)]
    {
        let lib = vcpkg::Config::new()
            .emit_includes(true)
            .find_package("rocksdb")
            .unwrap();

        for inc in lib.include_paths {
            build.include(inc);
        }
    }

    build
        .cpp(true)
        .pic(true)
        .opt_level(2)
        .warnings(false)
        .include(".")
        .file("rocks/cache.cc")
        .file("rocks/comparator.cc")
        .file("rocks/convenience.cc")
        .file("rocks/db.cc")
        .file("rocks/db_dump_tool.cc")
        .file("rocks/env.cc")
        .file("rocks/filter_policy.cc")
        .file("rocks/iostats_context.cc")
        .file("rocks/iterator.cc")
        .file("rocks/metadata.cc")
        .file("rocks/options.cc")
        .file("rocks/perf_context.cc")
        .file("rocks/perf_level.cc")
        .file("rocks/rate_limiter.cc")
        .file("rocks/slice.cc")
        .file("rocks/snapshot.cc")
        .file("rocks/sst_file_writer.cc")
        .file("rocks/statistics.cc")
        .file("rocks/status.cc")
        .file("rocks/table.cc")
        .file("rocks/table_properties.cc")
        .file("rocks/transaction_log.cc")
        .file("rocks/universal_compaction.cc")
        .file("rocks/util.cc")
        .file("rocks/write_batch.cc")
        .file("rocks/write_buffer_manager.cc")
        .file("rocks/debug.cc")
        .file("rocks/listener.cc")
        .file("rocks/compaction_job_stats.cc")
        .file("rocks/thread_status.cc")
        .file("rocks/options_util.cc")
        .compile("librocksdb_wrap");
}
<|endoftext|>


<commit_before>pub mod client;
pub mod lsm;
pub mod sm;
mod trees;

#[cfg(test)]
mod tests {
    use super::lsm::btree::storage;
    use super::lsm::btree::Ordering;
    use super::*;
    use crate::client::*;
    use crate::index::ranged::lsm::btree;
    use crate::index::EntryKey;
    use crate::ram::schema::*;
    use crate::ram::types::Id;
    use crate::server::*;
    use dovahkiin::types::Type;
    use futures::stream::FuturesUnordered;
    use itertools::Itertools;
    use rand::seq::SliceRandom;
    use std::sync::Arc;
    use std::time::Duration;
    use tokio_stream::StreamExt;

    // #[ignore]
    #[tokio::test(flavor = "multi_thread")]
    async fn general() {
        let _ = env_logger::try_init();
        let server_group = "ranged_index_test";
        let server_addr = String::from("127.0.0.1:5711");
        let server = NebServer::new_from_opts(
            &ServerOptions {
                chunk_count: 1,
                memory_size: 32 * 1024 * 1024 * 1024, // G
                backup_storage: None,
                wal_storage: None,
                index_enabled: false, // We don't use the high level index builder here
                services: vec![Service::Cell, Service::RangedIndexer],
            },
            &server_addr,
            server_group,
        )
        .await;
        let client = Arc::new(
            AsyncClient::new(
                &server.rpc,
                &server.membership,
                &vec![server_addr],
                server_group,
            )
            .await
            .unwrap(),
        );
        let index_client = Arc::new(client::RangedQueryClient::new(
            &server.consh,
            &server.raft_client,
        ));
        info!("Tree stat {:?}", index_client.tree_stats().await.unwrap());
        client.new_schema_with_id(schema()).await.unwrap().unwrap();
        let test_capacity = btree::ideal_capacity_from_node_size(btree::level::LEVEL_1) * 3;
        let mut futs = FuturesUnordered::new();
        info!(
            "Testing ranged indexer preesure test with {} items",
            test_capacity
        );
        info!("Generating test set");
        let mut rng = rand::thread_rng();
        let nums = (0..test_capacity).collect_vec();
        let mut nums_2 = nums.clone();
        let mut nums_3 = nums.clone();
        nums_2.as_mut_slice().shuffle(&mut rng);
        nums_3.as_mut_slice().shuffle(&mut rng);
        info!("Adding insertion tasks");
        for i in nums_2 {
            let index_client = index_client.clone();
            futs.push(tokio::time::timeout(
                Duration::from_secs(240),
                tokio::spawn(async move {
                    let id = Id::new(1, i as u64);
                    let key = EntryKey::from_id(&id);
                    index_client.insert(&key).await
                }),
            ));
        }
        info!("All tasks queued, waiting for finish");
        while let Some(result) = futs.next().await {
            assert!(result.unwrap().unwrap().unwrap(), "Insertion return false");
        }
        info!("All keys inserted. The background task should merging trees. Doing searches.");
        let mut futs = FuturesUnordered::new();
        for (i, num) in nums_3.into_iter().enumerate() {
            let index_client = index_client.clone();
            futs.push(tokio::spawn(async move {
                trace!("Seeking Id at {}, index {}", num, i);
                let id = Id::new(1, num as u64);
                let key = EntryKey::from_id(&id);
                let rt_cursor =
                    client::RangedQueryClient::seek(&index_client, &key, Ordering::Forward, 1)
                        .await
                        .unwrap()
                        .unwrap();
                assert_eq!(&id, rt_cursor.current().unwrap(), "at {}", i);
                trace!("Id at {}, index {} have been checked", num, i);
            }));
        }
        while let Some(_) = futs.next().await {}
        debug!("Selection check pased, waiting for 10 secs");
        tokio::time::sleep(Duration::from_secs(10)).await;
        info!("Waiting tree storage");
        storage::wait_until_updated().await;
        info!(
            "Total cells {}, Tree stat {:?}",
            client.count().await.unwrap(),
            index_client.tree_stats().await.unwrap()
        );
        info!("Scanning forward...");
        let start_id = Id::new(1, 0);
        let mut rt_cursor = client::RangedQueryClient::seek(
            &index_client,
            &EntryKey::from_id(&start_id),
            Ordering::Forward,
            128,
        )
        .await
        .unwrap()
        .unwrap();
        assert_eq!(rt_cursor.current(), Some(&start_id));
        for (i, num) in nums.iter().enumerate() {
            let id = Id::new(1, *num as u64);
            let current = rt_cursor.current().expect(&format!("Checking {}", num));
            assert_eq!(
                &id,
                current,
                "Expecting {:?}, key {:?}, got {:?}, list index {}, cursor ids {:?}, cursor pos {:?}",
                id,
                EntryKey::from_id(&id),
                current,
                i,
                rt_cursor.ids,
                rt_cursor.pos
            );
            let _ = rt_cursor.next().await.unwrap();
            if num % (test_capacity / 128) == 0 {
                debug!("Scanned {} of {}", num, test_capacity);
            }
        }
        info!("Scan finished");
        let end_of_list = rt_cursor.next().await.unwrap();
        assert!(
            end_of_list.is_none(),
            "End of the list have id {:?}",
            end_of_list.unwrap()
        );
        assert!(
            end_of_list.is_none(),
            "After end of the list have id {:?}",
            end_of_list.unwrap()
        );
        debug!("All check pased, waiting for 10 secs for statistics");
        tokio::time::sleep(Duration::from_secs(10)).await;
        info!(
            "Total cells {}, Tree stat {:?}",
            client.count().await.unwrap(),
            index_client.tree_stats().await.unwrap()
        );
    }

    fn schema() -> Schema {
        Schema::new_with_id(
            11,
            &String::from("test"),
            None,
            Field::new(
                "*",
                Type::Id,
                false,
                false,
                Some(vec![Field::new(
                    "data",
                    Type::U8,
                    false,
                    false,
                    None,
                    vec![],
                )]),
                vec![],
            ),
            false,
            false,
        )
    }
}
<commit_msg>a little bit modification to pass the tests<commit_after>pub mod client;
pub mod lsm;
pub mod sm;
mod trees;

#[cfg(test)]
mod tests {
    use super::lsm::btree::storage;
    use super::lsm::btree::Ordering;
    use super::*;
    use crate::client::*;
    use crate::index::ranged::lsm::btree;
    use crate::index::EntryKey;
    use crate::ram::schema::*;
    use crate::ram::types::Id;
    use crate::server::*;
    use dovahkiin::types::Type;
    use futures::stream::FuturesUnordered;
    use itertools::Itertools;
    use rand::seq::SliceRandom;
    use std::sync::Arc;
    use std::time::Duration;
    use tokio_stream::StreamExt;

    // #[ignore]
    #[tokio::test(flavor = "multi_thread")]
    async fn general() {
        let _ = env_logger::try_init();
        let server_group = "ranged_index_test";
        let server_addr = String::from("127.0.0.1:5711");
        let server = NebServer::new_from_opts(
            &ServerOptions {
                chunk_count: 1,
                memory_size: 32 * 1024 * 1024 * 1024, // G
                backup_storage: None,
                wal_storage: None,
                index_enabled: false, // We don't use the high level index builder here
                services: vec![Service::Cell, Service::RangedIndexer],
            },
            &server_addr,
            server_group,
        )
        .await;
        let client = Arc::new(
            AsyncClient::new(
                &server.rpc,
                &server.membership,
                &vec![server_addr],
                server_group,
            )
            .await
            .unwrap(),
        );
        let index_client = Arc::new(client::RangedQueryClient::new(
            &server.consh,
            &server.raft_client,
        ));
        info!("Tree stat {:?}", index_client.tree_stats().await.unwrap());
        client.new_schema_with_id(schema()).await.unwrap().unwrap();
        let test_capacity = btree::ideal_capacity_from_node_size(btree::level::LEVEL_1) * 3;
        let mut futs = FuturesUnordered::new();
        info!(
            "Testing ranged indexer preesure test with {} items",
            test_capacity
        );
        info!("Generating test set");
        let mut rng = rand::thread_rng();
        let nums = (0..test_capacity).collect_vec();
        let mut nums_2 = nums.clone();
        let mut nums_3 = nums.clone();
        nums_2.as_mut_slice().shuffle(&mut rng);
        nums_3.as_mut_slice().shuffle(&mut rng);
        info!("Adding insertion tasks");
        for i in nums_2 {
            let index_client = index_client.clone();
            futs.push(tokio::time::timeout(
                Duration::from_secs(240),
                async move {
                    let id = Id::new(1, i as u64);
                    let key = EntryKey::from_id(&id);
                    index_client.insert(&key).await
                },
            ));
        }
        info!("All tasks queued, waiting for finish");
        while let Some(result) = futs.next().await {
            assert!(result.unwrap().unwrap(), "Insertion return false");
        }
        info!("All keys inserted. The background task should merging trees. Doing searches.");
        let mut futs = FuturesUnordered::new();
        for (i, num) in nums_3.into_iter().enumerate() {
            let index_client = index_client.clone();
            futs.push(tokio::spawn(async move {
                trace!("Seeking Id at {}, index {}", num, i);
                let id = Id::new(1, num as u64);
                let key = EntryKey::from_id(&id);
                let rt_cursor =
                    client::RangedQueryClient::seek(&index_client, &key, Ordering::Forward, 1)
                        .await
                        .unwrap()
                        .unwrap();
                assert_eq!(&id, rt_cursor.current().unwrap(), "at {}", i);
                trace!("Id at {}, index {} have been checked", num, i);
            }));
        }
        while let Some(_) = futs.next().await {}
        debug!("Selection check pased, waiting for 10 secs");
        tokio::time::sleep(Duration::from_secs(10)).await;
        info!("Waiting tree storage");
        storage::wait_until_updated().await;
        info!(
            "Total cells {}, Tree stat {:?}",
            client.count().await.unwrap(),
            index_client.tree_stats().await.unwrap()
        );
        info!("Scanning forward...");
        let start_id = Id::new(1, 0);
        let mut rt_cursor = client::RangedQueryClient::seek(
            &index_client,
            &EntryKey::from_id(&start_id),
            Ordering::Forward,
            128,
        )
        .await
        .unwrap()
        .unwrap();
        assert_eq!(rt_cursor.current(), Some(&start_id));
        for (i, num) in nums.iter().enumerate() {
            let id = Id::new(1, *num as u64);
            let current = rt_cursor.current().expect(&format!("Checking {}", num));
            assert_eq!(
                &id,
                current,
                "Expecting {:?}, key {:?}, got {:?}, list index {}, cursor ids {:?}, cursor pos {:?}",
                id,
                EntryKey::from_id(&id),
                current,
                i,
                rt_cursor.ids,
                rt_cursor.pos
            );
            let _ = rt_cursor.next().await.unwrap();
            if num % (test_capacity / 128) == 0 {
                debug!("Scanned {} of {}", num, test_capacity);
            }
        }
        info!("Scan finished");
        let end_of_list = rt_cursor.next().await.unwrap();
        assert!(
            end_of_list.is_none(),
            "End of the list have id {:?}",
            end_of_list.unwrap()
        );
        assert!(
            end_of_list.is_none(),
            "After end of the list have id {:?}",
            end_of_list.unwrap()
        );
        debug!("All check pased, waiting for 10 secs for statistics");
        tokio::time::sleep(Duration::from_secs(10)).await;
        info!(
            "Total cells {}, Tree stat {:?}",
            client.count().await.unwrap(),
            index_client.tree_stats().await.unwrap()
        );
    }

    fn schema() -> Schema {
        Schema::new_with_id(
            11,
            &String::from("test"),
            None,
            Field::new(
                "*",
                Type::Id,
                false,
                false,
                Some(vec![Field::new(
                    "data",
                    Type::U8,
                    false,
                    false,
                    None,
                    vec![],
                )]),
                vec![],
            ),
            false,
            false,
        )
    }
}
<|endoftext|>


<commit_before>pub mod global_expression_methods;
pub mod bool_expression_methods;
pub mod text_expression_methods;

pub use self::global_expression_methods::*;
pub use self::bool_expression_methods::*;
pub use self::text_expression_methods::*;
<commit_msg>Ensure the expression method traits appear in the module level docs<commit_after>#[doc(hidden)]
pub mod global_expression_methods;
#[doc(hidden)]
pub mod bool_expression_methods;
#[doc(hidden)]
pub mod text_expression_methods;

pub use self::global_expression_methods::ExpressionMethods;
pub use self::bool_expression_methods::BoolExpressionMethods;
pub use self::text_expression_methods::{TextExpressionMethods, VarCharExpressionMethods};
<|endoftext|>