<commit_before>use std::cmp::max;

use unicode_width::UnicodeWidthStr;

use buffer::Buffer;
use widgets::{Widget, Block};
use layout::Rect;
use style::Style;

/// A widget to display data in formatted column
///
/// # Examples
///
/// ```
/// # use tui::widgets::{Block, border, Table};
/// # use tui::style::{Style, Color};
/// # fn main() {
/// Table::default()
///     .block(Block::default().title("Table"))
///     .header(&["Col1", "Col2", "Col3"])
///     .header_style(Style::default().fg(Color::Yellow))
///     .widths(&[5, 5, 10])
///     .style(Style::default().fg(Color::White))
///     .column_spacing(1)
///     .rows(&[&["Row11", "Row12", "Row13"],
///                &["Row21", "Row22", "Row23"],
///                &["Row31", "Row32", "Row33"]]);
/// # }
/// ```

pub struct Table<'a> {
    /// A block to wrap the widget in
    block: Option<Block<'a>>,
    /// Base style for the widget
    style: Style,
    /// Header row for all columns
    header: &'a [&'a str],
    /// Style for the header
    header_style: Style,
    /// Width of each column (if the total width is greater than the widget width some columns may
    /// not be displayed)
    widths: &'a [u16],
    /// Space between each column
    column_spacing: u16,
    /// Data to display in each row
    rows: Vec<(Vec<&'a str>, &'a Style)>,
}

impl<'a> Default for Table<'a> {
    fn default() -> Table<'a> {
        Table {
            block: None,
            style: Style::default(),
            header: &[],
            header_style: Style::default(),
            widths: &[],
            rows: Vec::new(),
            column_spacing: 1,
        }
    }
}

impl<'a> Table<'a> {
    pub fn block(&'a mut self, block: Block<'a>) -> &mut Table<'a> {
        self.block = Some(block);
        self
    }

    pub fn header(&mut self, header: &'a [&'a str]) -> &mut Table<'a> {
        self.header = header;
        self
    }

    pub fn header_style(&mut self, style: Style) -> &mut Table<'a> {
        self.header_style = style;
        self
    }

    pub fn widths(&mut self, widths: &'a [u16]) -> &mut Table<'a> {
        self.widths = widths;
        self
    }

    pub fn rows<S, R>(&mut self, rows: &'a [(R, &'a Style)]) -> &mut Table<'a>
        where S: AsRef<str> + 'a,
              R: AsRef<[S]> + 'a
    {
        self.rows = rows.iter()
            .map(|&(ref r, style)| {
                (r.as_ref().iter().map(|i| i.as_ref()).collect::<Vec<&'a str>>(), style)
            })
            .collect::<Vec<(Vec<&'a str>, &'a Style)>>();
        self
    }

    pub fn style(&mut self, style: Style) -> &mut Table<'a> {
        self.style = style;
        self
    }

    pub fn column_spacing(&mut self, spacing: u16) -> &mut Table<'a> {
        self.column_spacing = spacing;
        self
    }
}

impl<'a> Widget for Table<'a> {
    fn draw(&self, area: &Rect, buf: &mut Buffer) {

        // Render block if necessary and get the drawing area
        let table_area = match self.block {
            Some(ref b) => {
                b.draw(area, buf);
                b.inner(area)
            }
            None => *area,
        };

        // Set the background
        self.background(&table_area, buf, self.style.bg);

        let mut x = 0;
        let mut widths = Vec::with_capacity(self.widths.len());
        for (width, title) in self.widths.iter().zip(self.header.iter()) {
            let w = max(title.width() as u16, *width);
            if x + w < table_area.width {
                widths.push(w);
            }
            x += w;
        }

        let mut y = table_area.top();

        // Header
        if y < table_area.bottom() {
            x = table_area.left();
            for (w, t) in widths.iter().zip(self.header.iter()) {
                buf.set_string(x, y, t, &self.header_style);
                x += *w + self.column_spacing;
            }
        }
        y += 2;

        if y < table_area.bottom() {
            let remaining = (table_area.bottom() - y) as usize;
            for (i, &(ref row, style)) in self.rows.iter().take(remaining).enumerate() {
                x = table_area.left();
                for (w, elt) in widths.iter().zip(row.iter()) {
                    buf.set_stringn(x, y + i as u16, elt, *w as usize, style);
                    x += *w + self.column_spacing;
                }
            }
        }
    }
}
<commit_msg>Fix table example<commit_after>use std::cmp::max;

use unicode_width::UnicodeWidthStr;

use buffer::Buffer;
use widgets::{Widget, Block};
use layout::Rect;
use style::Style;

/// A widget to display data in formatted column
///
/// # Examples
///
/// ```
/// # use tui::widgets::{Block, border, Table};
/// # use tui::style::{Style, Color};
/// # fn main() {
/// let row_style = Style::default().fg(Color::White);
/// Table::default()
///     .block(Block::default().title("Table"))
///     .header(&["Col1", "Col2", "Col3"])
///     .header_style(Style::default().fg(Color::Yellow))
///     .widths(&[5, 5, 10])
///     .style(Style::default().fg(Color::White))
///     .column_spacing(1)
///     .rows(&[(&["Row11", "Row12", "Row13"], &row_style),
///             (&["Row21", "Row22", "Row23"], &row_style),
///             (&["Row31", "Row32", "Row33"], &row_style)]);
/// # }
/// ```

pub struct Table<'a> {
    /// A block to wrap the widget in
    block: Option<Block<'a>>,
    /// Base style for the widget
    style: Style,
    /// Header row for all columns
    header: &'a [&'a str],
    /// Style for the header
    header_style: Style,
    /// Width of each column (if the total width is greater than the widget width some columns may
    /// not be displayed)
    widths: &'a [u16],
    /// Space between each column
    column_spacing: u16,
    /// Data to display in each row
    rows: Vec<(Vec<&'a str>, &'a Style)>,
}

impl<'a> Default for Table<'a> {
    fn default() -> Table<'a> {
        Table {
            block: None,
            style: Style::default(),
            header: &[],
            header_style: Style::default(),
            widths: &[],
            rows: Vec::new(),
            column_spacing: 1,
        }
    }
}

impl<'a> Table<'a> {
    pub fn block(&'a mut self, block: Block<'a>) -> &mut Table<'a> {
        self.block = Some(block);
        self
    }

    pub fn header(&mut self, header: &'a [&'a str]) -> &mut Table<'a> {
        self.header = header;
        self
    }

    pub fn header_style(&mut self, style: Style) -> &mut Table<'a> {
        self.header_style = style;
        self
    }

    pub fn widths(&mut self, widths: &'a [u16]) -> &mut Table<'a> {
        self.widths = widths;
        self
    }

    pub fn rows<S, R>(&mut self, rows: &'a [(R, &'a Style)]) -> &mut Table<'a>
        where S: AsRef<str> + 'a,
              R: AsRef<[S]> + 'a
    {
        self.rows = rows.iter()
            .map(|&(ref r, style)| {
                (r.as_ref().iter().map(|i| i.as_ref()).collect::<Vec<&'a str>>(), style)
            })
            .collect::<Vec<(Vec<&'a str>, &'a Style)>>();
        self
    }

    pub fn style(&mut self, style: Style) -> &mut Table<'a> {
        self.style = style;
        self
    }

    pub fn column_spacing(&mut self, spacing: u16) -> &mut Table<'a> {
        self.column_spacing = spacing;
        self
    }
}

impl<'a> Widget for Table<'a> {
    fn draw(&self, area: &Rect, buf: &mut Buffer) {

        // Render block if necessary and get the drawing area
        let table_area = match self.block {
            Some(ref b) => {
                b.draw(area, buf);
                b.inner(area)
            }
            None => *area,
        };

        // Set the background
        self.background(&table_area, buf, self.style.bg);

        let mut x = 0;
        let mut widths = Vec::with_capacity(self.widths.len());
        for (width, title) in self.widths.iter().zip(self.header.iter()) {
            let w = max(title.width() as u16, *width);
            if x + w < table_area.width {
                widths.push(w);
            }
            x += w;
        }

        let mut y = table_area.top();

        // Header
        if y < table_area.bottom() {
            x = table_area.left();
            for (w, t) in widths.iter().zip(self.header.iter()) {
                buf.set_string(x, y, t, &self.header_style);
                x += *w + self.column_spacing;
            }
        }
        y += 2;

        if y < table_area.bottom() {
            let remaining = (table_area.bottom() - y) as usize;
            for (i, &(ref row, style)) in self.rows.iter().take(remaining).enumerate() {
                x = table_area.left();
                for (w, elt) in widths.iter().zip(row.iter()) {
                    buf.set_stringn(x, y + i as u16, elt, *w as usize, style);
                    x += *w + self.column_spacing;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// * This file is part of the uutils coreutils package.
// *
// * (c) 2020 nicoo <nicoo@debian.org>
// *
// * For the full copyright and license information, please view the LICENSE file
// * that was distributed with this source code.

extern crate rand;

use std::cell::RefCell;
use std::fmt;

use crate::numeric::{gcd, Arithmetic, Montgomery};
use crate::{miller_rabin, rho, table};

type Exponent = u8;

#[derive(Clone, Debug)]
struct Decomposition(Vec<(u64, Exponent)>);

impl Decomposition {
    fn one() -> Decomposition {
        Decomposition(Vec::new())
    }

    fn add(&mut self, factor: u64, exp: Exponent) {
        debug_assert!(exp > 0);
        // Assert the factor doesn't already exist in the Decomposition object
        debug_assert_eq!(self.0.iter_mut().find(|(f, _)| *f == factor), None);

        self.0.push((factor, exp))
    }

    fn is_one(&self) -> bool {
        self.0.is_empty()
    }

    fn pop(&mut self) -> Option<(u64, Exponent)> {
        self.0.pop()
    }

    fn product(&self) -> u64 {
        self.0
            .iter()
            .fold(1, |acc, (p, exp)| acc * p.pow(*exp as u32))
    }

    fn get(&self, p: u64) -> Option<&(u64, u8)> {
        self.0.iter().find(|(q, _)| *q == p)
    }
}

impl PartialEq for Decomposition {
    fn eq(&self, other: &Decomposition) -> bool {
        for p in &self.0 {
            if other.get(p.0) != Some(p) {
                return false;
            }
        }

        for p in &other.0 {
            if self.get(p.0) != Some(p) {
                return false;
            }
        }

        true
    }
}
impl Eq for Decomposition {}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Factors(RefCell<Decomposition>);

impl Factors {
    pub fn one() -> Factors {
        Factors(RefCell::new(Decomposition::one()))
    }

    pub fn add(&mut self, prime: u64, exp: Exponent) {
        debug_assert!(miller_rabin::is_prime(prime));
        self.0.borrow_mut().add(prime, exp)
    }

    #[cfg(test)]
    pub fn push(&mut self, prime: u64) {
        self.add(prime, 1)
    }

    fn product(&self) -> u64 {
        self.0.borrow().product()
    }
}

impl fmt::Display for Factors {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let v = &mut (self.0).borrow_mut().0;
        v.sort_unstable();

        for (p, exp) in v.iter() {
            for _ in 0..*exp {
                write!(f, " {}", p)?
            }
        }

        Ok(())
    }
}

fn _find_factor<A: Arithmetic + miller_rabin::Basis>(num: u64) -> Option<u64> {
    use miller_rabin::Result::*;

    let n = A::new(num);
    match miller_rabin::test::<A>(n) {
        Prime => None,
        Composite(d) => Some(d),
        Pseudoprime => Some(rho::find_divisor::<A>(n)),
    }
}

fn find_factor(num: u64) -> Option<u64> {
    if num < (1 << 32) {
        _find_factor::<Montgomery<u32>>(num)
    } else {
        _find_factor::<Montgomery<u64>>(num)
    }
}

pub fn factor(num: u64) -> Factors {
    let mut factors = Factors::one();

    if num < 2 {
        return factors;
    }

    let mut n = num;
    let z = num.trailing_zeros();
    if z > 0 {
        factors.add(2, z as Exponent);
        n >>= z;
    }
    debug_assert_eq!(num, n * factors.product());

    if n == 1 {
        return factors;
    }

    table::factor(&mut n, &mut factors);
    debug_assert_eq!(num, n * factors.product());

    if n == 1 {
        return factors;
    }

    let mut dec = Decomposition::one();
    dec.add(n, 1);

    while !dec.is_one() {
        // Check correctness invariant
        debug_assert_eq!(num, factors.product() * dec.product());

        let (f, e) = dec.pop().unwrap();

        if let Some(d) = find_factor(f) {
            let mut gcd_queue = Decomposition::one();
            gcd_queue.add(d, e);
            gcd_queue.add(f / d, e);

            let mut non_trivial_gcd = true;
            while non_trivial_gcd {
                debug_assert_eq!(f, gcd_queue.product());

                let mut tmp = Decomposition::one();
                non_trivial_gcd = false;
                for i in 0..gcd_queue.0.len() - 1 {
                    let (a, e_a) = gcd_queue.0[i];
                    let (b, e_b) = gcd_queue.0[i + 1];

                    let g = gcd(a, b);
                    if g != 1 {
                        non_trivial_gcd = true;
                        tmp.add(a / g, e_a);
                        tmp.add(g, e_a + e_b);
                        if i + 1 == gcd_queue.0.len() {
                            tmp.add(b / g, e_b)
                        } else {
                            gcd_queue.0[i + 1] = (b / g, e_b);
                        }
                    } else {
                        tmp.add(a, e_a);
                        if i + 1 == gcd_queue.0.len() - 1 {
                            tmp.add(b, e_b)
                        }
                    }
                }
                gcd_queue = tmp;
            }

            debug_assert_eq!(f, gcd_queue.product());
            dec.0.extend(gcd_queue.0);
        } else {
            // f is prime
            factors.add(f, e);
        }
    }

    factors
}

#[cfg(test)]
mod tests {
    use super::{factor, Factors};
    use quickcheck::quickcheck;

    #[test]
    fn factor_recombines_small() {
        assert!((1..10_000)
            .map(|i| 2 * i + 1)
            .all(|i| factor(i).product() == i));
    }

    #[test]
    fn factor_recombines_overflowing() {
        assert!((0..250)
            .map(|i| 2 * i + 2u64.pow(32) + 1)
            .all(|i| factor(i).product() == i));
    }

    #[test]
    fn factor_recombines_strong_pseudoprime() {
        // This is a strong pseudoprime (wrt. miller_rabin::BASIS)
        //  and triggered a bug in rho::factor's codepath handling
        //  miller_rabbin::Result::Composite
        let pseudoprime = 17179869183;
        for _ in 0..20 {
            // Repeat the test 20 times, as it only fails some fraction
            // of the time.
            assert!(factor(pseudoprime).product() == pseudoprime);
        }
    }

    quickcheck! {
        fn factor_recombines(i: u64) -> bool {
            i == 0 || factor(i).product() == i
        }

        fn recombines_factors(f: Factors) -> bool {
            assert_eq!(factor(f.product()), f);
            true
        }
    }
}

#[cfg(test)]
impl quickcheck::Arbitrary for Factors {
    fn arbitrary<G: quickcheck::Gen>(gen: &mut G) -> Self {
        use rand::Rng;
        let mut f = Factors::one();
        let mut g = 1u64;
        let mut n = u64::MAX;

        // Adam Kalai's algorithm for generating uniformly-distributed
        // integers and their factorisation.
        //
        // See Generating Random Factored Numbers, Easily, J. Cryptology (2003)
        'attempt: loop {
            while n > 1 {
                n = gen.gen_range(1, n);
                if miller_rabin::is_prime(n) {
                    if let Some(h) = g.checked_mul(n) {
                        f.push(n);
                        g = h;
                    } else {
                        // We are overflowing u64, retry
                        continue 'attempt;
                    }
                }
            }

            return f;
        }
    }
}
<commit_msg>factor: Slightly refactor main loop, fix bug<commit_after>// * This file is part of the uutils coreutils package.
// *
// * (c) 2020 nicoo <nicoo@debian.org>
// *
// * For the full copyright and license information, please view the LICENSE file
// * that was distributed with this source code.

extern crate rand;

use std::cell::RefCell;
use std::fmt;

use crate::numeric::{gcd, Arithmetic, Montgomery};
use crate::{miller_rabin, rho, table};

type Exponent = u8;

#[derive(Clone, Debug)]
struct Decomposition(Vec<(u64, Exponent)>);

impl Decomposition {
    fn one() -> Decomposition {
        Decomposition(Vec::new())
    }

    fn add(&mut self, factor: u64, exp: Exponent) {
        debug_assert!(exp > 0);
        // Assert the factor doesn't already exist in the Decomposition object
        debug_assert_eq!(self.0.iter_mut().find(|(f, _)| *f == factor), None);

        self.0.push((factor, exp))
    }

    fn is_one(&self) -> bool {
        self.0.is_empty()
    }

    fn pop(&mut self) -> Option<(u64, Exponent)> {
        self.0.pop()
    }

    fn product(&self) -> u64 {
        self.0
            .iter()
            .fold(1, |acc, (p, exp)| acc * p.pow(*exp as u32))
    }

    fn get(&self, p: u64) -> Option<&(u64, u8)> {
        self.0.iter().find(|(q, _)| *q == p)
    }
}

impl PartialEq for Decomposition {
    fn eq(&self, other: &Decomposition) -> bool {
        for p in &self.0 {
            if other.get(p.0) != Some(p) {
                return false;
            }
        }

        for p in &other.0 {
            if self.get(p.0) != Some(p) {
                return false;
            }
        }

        true
    }
}
impl Eq for Decomposition {}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Factors(RefCell<Decomposition>);

impl Factors {
    pub fn one() -> Factors {
        Factors(RefCell::new(Decomposition::one()))
    }

    pub fn add(&mut self, prime: u64, exp: Exponent) {
        debug_assert!(miller_rabin::is_prime(prime));
        self.0.borrow_mut().add(prime, exp)
    }

    #[cfg(test)]
    pub fn push(&mut self, prime: u64) {
        self.add(prime, 1)
    }

    fn product(&self) -> u64 {
        self.0.borrow().product()
    }
}

impl fmt::Display for Factors {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let v = &mut (self.0).borrow_mut().0;
        v.sort_unstable();

        for (p, exp) in v.iter() {
            for _ in 0..*exp {
                write!(f, " {}", p)?
            }
        }

        Ok(())
    }
}

fn _find_factor<A: Arithmetic + miller_rabin::Basis>(num: u64) -> Option<u64> {
    use miller_rabin::Result::*;

    let n = A::new(num);
    match miller_rabin::test::<A>(n) {
        Prime => None,
        Composite(d) => Some(d),
        Pseudoprime => Some(rho::find_divisor::<A>(n)),
    }
}

fn find_factor(num: u64) -> Option<u64> {
    if num < (1 << 32) {
        _find_factor::<Montgomery<u32>>(num)
    } else {
        _find_factor::<Montgomery<u64>>(num)
    }
}

pub fn factor(num: u64) -> Factors {
    let mut factors = Factors::one();

    if num < 2 {
        return factors;
    }

    let mut n = num;
    let z = num.trailing_zeros();
    if z > 0 {
        factors.add(2, z as Exponent);
        n >>= z;
    }
    debug_assert_eq!(num, n * factors.product());

    if n == 1 {
        return factors;
    }

    table::factor(&mut n, &mut factors);
    debug_assert_eq!(num, n * factors.product());

    if n == 1 {
        return factors;
    }

    let mut dec = Decomposition::one();
    dec.add(n, 1);

    while !dec.is_one() {
        // Check correctness invariant
        debug_assert_eq!(num, factors.product() * dec.product());

        let (f, e) = dec.pop().unwrap();

        if let Some(d) = find_factor(f) {
            let mut gcd_queue = Decomposition::one();
            gcd_queue.add(d, e);
            gcd_queue.add(f / d, e);

            let mut non_trivial_gcd = true;
            while non_trivial_gcd {
                debug_assert_eq!(f, gcd_queue.product());

                let mut tmp = Decomposition::one();
                non_trivial_gcd = false;
                for i in 0..gcd_queue.0.len() - 1 {
                    let (mut a, e_a) = gcd_queue.0[i];
                    let (mut b, e_b) = gcd_queue.0[i + 1];

                    if a == 1 {
                        continue;
                    }

                    let g = gcd(a, b);
                    if g != 1 {
                        non_trivial_gcd = true;
                        a /= g;
                        b /= g;
                    }
                    if a != 1 {
                        tmp.add(a, e_a);
                    }
                    if g != 1 {
                        tmp.add(g, e_a + e_b);
                    }

                    if i + 1 != gcd_queue.0.len() - 1 {
                        gcd_queue.0[i + 1].0 = b;
                    } else if b != 1 {
                        tmp.add(b, e_b);
                    }
                }
                gcd_queue = tmp;
            }

            debug_assert_eq!(f, gcd_queue.product());
            dec.0.extend(gcd_queue.0);
        } else {
            // f is prime
            factors.add(f, e);
        }
    }

    factors
}

#[cfg(test)]
mod tests {
    use super::{factor, Factors};
    use quickcheck::quickcheck;

    #[test]
    fn factor_recombines_small() {
        assert!((1..10_000)
            .map(|i| 2 * i + 1)
            .all(|i| factor(i).product() == i));
    }

    #[test]
    fn factor_recombines_overflowing() {
        assert!((0..250)
            .map(|i| 2 * i + 2u64.pow(32) + 1)
            .all(|i| factor(i).product() == i));
    }

    #[test]
    fn factor_recombines_strong_pseudoprime() {
        // This is a strong pseudoprime (wrt. miller_rabin::BASIS)
        //  and triggered a bug in rho::factor's codepath handling
        //  miller_rabbin::Result::Composite
        let pseudoprime = 17179869183;
        for _ in 0..20 {
            // Repeat the test 20 times, as it only fails some fraction
            // of the time.
            assert!(factor(pseudoprime).product() == pseudoprime);
        }
    }

    quickcheck! {
        fn factor_recombines(i: u64) -> bool {
            i == 0 || factor(i).product() == i
        }

        fn recombines_factors(f: Factors) -> bool {
            assert_eq!(factor(f.product()), f);
            true
        }
    }
}

#[cfg(test)]
impl quickcheck::Arbitrary for Factors {
    fn arbitrary<G: quickcheck::Gen>(gen: &mut G) -> Self {
        use rand::Rng;
        let mut f = Factors::one();
        let mut g = 1u64;
        let mut n = u64::MAX;

        // Adam Kalai's algorithm for generating uniformly-distributed
        // integers and their factorisation.
        //
        // See Generating Random Factored Numbers, Easily, J. Cryptology (2003)
        'attempt: loop {
            while n > 1 {
                n = gen.gen_range(1, n);
                if miller_rabin::is_prime(n) {
                    if let Some(h) = g.checked_mul(n) {
                        f.push(n);
                        g = h;
                    } else {
                        // We are overflowing u64, retry
                        continue 'attempt;
                    }
                }
            }

            return f;
        }
    }
}
<|endoftext|>


<commit_before>/// Implements the [`AsChangeset`][changeset] trait for a given struct. This
/// macro should be called with the name of the table you wish to use the struct
/// with, followed by the entire struct body. This macro mirrors
/// `#[as_changeset]` from [`diesel_codegen`][diesel_codegen]
///
/// [changeset]: prelude/trait.AsChangeset.html
/// [diesel_codegen]: https://github.com/diesel-rs/diesel/tree/master/diesel_codegen
///
/// # Options
///
/// - `treat_none_as_null` (boolean)
///     - Default value: `"false"`
///     - When set to `"true"`, option fields will set the column to `NULL` when their value is
///       `None`. When set to `"false"`, the field will not be assigned.
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate diesel;
/// # table! { users { id -> Integer, name -> VarChar, } }
/// # include!("src/doctest_setup.rs");
///
/// #[derive(PartialEq, Debug)]
/// struct User {
///     id: i32,
///     name: String,
/// }
///
/// AsChangeset! {
///     (users)
///     struct User {
///         id: i32,
///         name: String,
///     }
/// }
///
/// # Queryable! {
/// #     struct User {
/// #         id: i32,
/// #         name: String,
/// #     }
/// # }
/// #
/// # impl User {
/// #     fn new(id: i32, name: &str) -> Self {
/// #         User {
/// #             id: id,
/// #             name: name.into(),
/// #         }
/// #     }
/// # }
///
///
/// # fn main() {
/// #     use users::dsl::*;
/// #     let connection = establish_connection();
/// let user = diesel::insert(&NewUser::new("Sean"))
///     .into(users)
///     .get_result::<User>(&connection)
///     .unwrap();
/// let changes = User::new(user.id, "Jim");
/// diesel::update(users.find(user.id))
///     .set(&changes)
///     .execute(&connection)
///     .unwrap();
///
/// let user_in_db = users.find(user.id).first(&connection);
/// assert_eq!(Ok(changes), user_in_db);
/// # }
/// ```
#[macro_export]
macro_rules! AsChangeset {
    // Provide a default value for treat_none_as_null if not provided
    (
        ($table_name:ident)
        $($body:tt)*
    ) => {
        AsChangeset! {
            ($table_name, treat_none_as_null="false")
            $($body)*
        }
    };

    // Strip meta items, pub (if present) and struct from definition
    (
        $args:tt
        $(#[$ignore:meta])*
        $(pub)* struct $($body:tt)*
    ) => {
        AsChangeset! {
            $args
            $($body)*
        }
    };

    // Handle struct with lifetimes
    (
        ($table_name:ident, treat_none_as_null=$treat_none_as_null:tt)
        $struct_name:ident <$($lifetime:tt),*>
        $body:tt $(;)*
    ) => {
        __diesel_parse_struct_body! {
            (
                struct_name = $struct_name,
                table_name = $table_name,
                treat_none_as_null = $treat_none_as_null,
                struct_ty = $struct_name<$($lifetime),*>,
                lifetimes = ($($lifetime),*),
            ),
            callback = AsChangeset,
            body = $body,
        }
    };

    // Handle struct with no lifetimes. We pass a dummy lifetime to reduce
    // the amount of branching later.
    (
        ($table_name:ident, treat_none_as_null=$treat_none_as_null:tt)
        $struct_name:ident
        $body:tt $(;)*
    ) => {
        __diesel_parse_struct_body! {
            (
                struct_name = $struct_name,
                table_name = $table_name,
                treat_none_as_null = $treat_none_as_null,
                struct_ty = $struct_name,
                lifetimes = ('a),
            ),
            callback = AsChangeset,
            body = $body,
        }
    };

    // Receive parsed fields of struct from `__diesel_parse_struct_body`
    (
        (
            struct_name = $struct_name:ident,
            table_name = $table_name:ident,
            treat_none_as_null = $treat_none_as_null:tt,
            $($headers:tt)*
        ),
        fields = $fields:tt,
    ) => {
        AsChangeset_construct_changeset_ty! {
            (
                fields = $fields,
                struct_name = $struct_name,
                table_name = $table_name,
                treat_none_as_null = $treat_none_as_null,
                $($headers)*
            ),
            table_name = $table_name,
            treat_none_as_null = $treat_none_as_null,
            fields = $fields,
            changeset_ty = (),
        }
    };

    // Receive changeset ty when tuple struct from `AsChangeset_construct_changeset_ty`
    (
        (
            fields = [$({
                column_name: $column_name:ident,
                field_ty: $field_ty:ty,
                field_kind: $field_kind:ident,
            })+],
            struct_name = $struct_name:ident,
            $($headers:tt)*
        ),
        changeset_ty = $changeset_ty:ty,
    ) => {
        AsChangeset! {
            $($headers)*
            self_to_columns = $struct_name($(ref $column_name),+),
            columns = ($($column_name, $field_kind),+),
            field_names = [],
            changeset_ty = $changeset_ty,
        }
    };

    // Receive changeset ty when named struct from `AsChangeset_construct_changeset_ty`
    (
        (
            fields = [$({
                field_name: $field_name:ident,
                column_name: $column_name:ident,
                field_ty: $field_ty:ty,
                field_kind: $field_kind:ident,
            })+],
            struct_name = $struct_name:ident,
            $($headers:tt)*
        ),
        changeset_ty = $changeset_ty:ty,
    ) => {
        AsChangeset! {
            $($headers)*
            self_to_columns = $struct_name { $($field_name: ref $column_name),+ },
            columns = ($($column_name, $field_kind),+),
            field_names = [$($field_name)+],
            changeset_ty = $changeset_ty,
        }
    };

    // Construct final impl
    (
        table_name = $table_name:ident,
        treat_none_as_null = $treat_none_as_null:tt,
        struct_ty = $struct_ty:ty,
        lifetimes = ($($lifetime:tt),*),
        self_to_columns = $self_to_columns:pat,
        columns = ($($column_name:ident, $field_kind:ident),+),
        field_names = $field_names:tt,
        changeset_ty = $changeset_ty:ty,
    ) => {
        __diesel_parse_as_item! {
            impl<$($lifetime: 'update,)* 'update> $crate::query_builder::AsChangeset
                for &'update $struct_ty
            {
                type Target = $table_name::table;
                type Changeset = $changeset_ty;

                #[allow(non_shorthand_field_patterns)]
                fn as_changeset(self) -> Self::Changeset {
                    let $self_to_columns = *self;
                    ($(
                        AsChangeset_column_expr!(
                            $table_name::$column_name,
                            $column_name,
                            none_as_null = $treat_none_as_null,
                            field_kind = $field_kind,
                        )
                    ,)+)
                }
            }
        }
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! AsChangeset_construct_changeset_ty {
    // Handle option field when treat none as null is false
    (
        $headers:tt,
        table_name = $table_name:ident,
        treat_none_as_null = "false",
        fields = [{
            $(field_name: $field_name:ident,)*
            column_name: $column_name:ident,
            field_ty: Option<$field_ty:ty>,
            field_kind: option,
        } $($tail:tt)*],
        changeset_ty = ($($changeset_ty:ty,)*),
    ) => {
        AsChangeset_construct_changeset_ty! {
            $headers,
            table_name = $table_name,
            treat_none_as_null = "false",
            fields = [$($tail)*],
            changeset_ty = ($($changeset_ty,)*
                Option<$crate::expression::predicates::Eq<
                    $table_name::$column_name,
                    $crate::expression::bound::Bound<
                        <$table_name::$column_name as $crate::expression::Expression>::SqlType,
                        &'update $field_ty,
                    >,
                >>,
            ),
        }
    };

    // Handle normal field or option when treat none as null is true
    (
        $headers:tt,
        table_name = $table_name:ident,
        treat_none_as_null = $treat_none_as_null:tt,
        fields = [{
            $(field_name: $field_name:ident,)*
            column_name: $column_name:ident,
            field_ty: $field_ty:ty,
            $($ignore:tt)*
        } $($tail:tt)*],
        changeset_ty = ($($changeset_ty:ty,)*),
    ) => {
        AsChangeset_construct_changeset_ty! {
            $headers,
            table_name = $table_name,
            treat_none_as_null = $treat_none_as_null,
            fields = [$($tail)*],
            changeset_ty = ($($changeset_ty,)*
                $crate::expression::predicates::Eq<
                    $table_name::$column_name,
                    $crate::expression::bound::Bound<
                        <$table_name::$column_name as $crate::expression::Expression>::SqlType,
                        &'update $field_ty,
                    >,
                >,
            ),
        }
    };

    // Finished parsing
    (
        $headers:tt,
        table_name = $table_name:ident,
        treat_none_as_null = $treat_none_as_null:tt,
        fields = [],
        changeset_ty = $changeset_ty:ty,
    ) => {
        AsChangeset!($headers, changeset_ty = $changeset_ty,);
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! AsChangeset_column_expr {
    // When none_as_null is false, we don't update fields which aren't present
    (
        $column:expr,
        $field_access:expr,
        none_as_null = "false",
        field_kind = option,
    ) => {
        $field_access.as_ref().map(|f| $column.eq(f))
    };

    // If none_as_null is true, or the field kind isn't option, assign blindly
    (
        $column:expr,
        $field_access:expr,
        $($args:tt)*
    ) => {
        $column.eq($field_access)
    };
}
<commit_msg>Note that type level macros will be stable soon<commit_after>/// Implements the [`AsChangeset`][changeset] trait for a given struct. This
/// macro should be called with the name of the table you wish to use the struct
/// with, followed by the entire struct body. This macro mirrors
/// `#[as_changeset]` from [`diesel_codegen`][diesel_codegen]
///
/// [changeset]: prelude/trait.AsChangeset.html
/// [diesel_codegen]: https://github.com/diesel-rs/diesel/tree/master/diesel_codegen
///
/// # Options
///
/// - `treat_none_as_null` (boolean)
///     - Default value: `"false"`
///     - When set to `"true"`, option fields will set the column to `NULL` when their value is
///       `None`. When set to `"false"`, the field will not be assigned.
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate diesel;
/// # table! { users { id -> Integer, name -> VarChar, } }
/// # include!("src/doctest_setup.rs");
///
/// #[derive(PartialEq, Debug)]
/// struct User {
///     id: i32,
///     name: String,
/// }
///
/// AsChangeset! {
///     (users)
///     struct User {
///         id: i32,
///         name: String,
///     }
/// }
///
/// # Queryable! {
/// #     struct User {
/// #         id: i32,
/// #         name: String,
/// #     }
/// # }
/// #
/// # impl User {
/// #     fn new(id: i32, name: &str) -> Self {
/// #         User {
/// #             id: id,
/// #             name: name.into(),
/// #         }
/// #     }
/// # }
///
///
/// # fn main() {
/// #     use users::dsl::*;
/// #     let connection = establish_connection();
/// let user = diesel::insert(&NewUser::new("Sean"))
///     .into(users)
///     .get_result::<User>(&connection)
///     .unwrap();
/// let changes = User::new(user.id, "Jim");
/// diesel::update(users.find(user.id))
///     .set(&changes)
///     .execute(&connection)
///     .unwrap();
///
/// let user_in_db = users.find(user.id).first(&connection);
/// assert_eq!(Ok(changes), user_in_db);
/// # }
/// ```
#[macro_export]
macro_rules! AsChangeset {
    // Provide a default value for treat_none_as_null if not provided
    (
        ($table_name:ident)
        $($body:tt)*
    ) => {
        AsChangeset! {
            ($table_name, treat_none_as_null="false")
            $($body)*
        }
    };

    // Strip meta items, pub (if present) and struct from definition
    (
        $args:tt
        $(#[$ignore:meta])*
        $(pub)* struct $($body:tt)*
    ) => {
        AsChangeset! {
            $args
            $($body)*
        }
    };

    // Handle struct with lifetimes
    (
        ($table_name:ident, treat_none_as_null=$treat_none_as_null:tt)
        $struct_name:ident <$($lifetime:tt),*>
        $body:tt $(;)*
    ) => {
        __diesel_parse_struct_body! {
            (
                struct_name = $struct_name,
                table_name = $table_name,
                treat_none_as_null = $treat_none_as_null,
                struct_ty = $struct_name<$($lifetime),*>,
                lifetimes = ($($lifetime),*),
            ),
            callback = AsChangeset,
            body = $body,
        }
    };

    // Handle struct with no lifetimes. We pass a dummy lifetime to reduce
    // the amount of branching later.
    (
        ($table_name:ident, treat_none_as_null=$treat_none_as_null:tt)
        $struct_name:ident
        $body:tt $(;)*
    ) => {
        __diesel_parse_struct_body! {
            (
                struct_name = $struct_name,
                table_name = $table_name,
                treat_none_as_null = $treat_none_as_null,
                struct_ty = $struct_name,
                lifetimes = ('a),
            ),
            callback = AsChangeset,
            body = $body,
        }
    };

    // Receive parsed fields of struct from `__diesel_parse_struct_body`
    (
        (
            struct_name = $struct_name:ident,
            table_name = $table_name:ident,
            treat_none_as_null = $treat_none_as_null:tt,
            $($headers:tt)*
        ),
        fields = $fields:tt,
    ) => {
        AsChangeset_construct_changeset_ty! {
            (
                fields = $fields,
                struct_name = $struct_name,
                table_name = $table_name,
                treat_none_as_null = $treat_none_as_null,
                $($headers)*
            ),
            table_name = $table_name,
            treat_none_as_null = $treat_none_as_null,
            fields = $fields,
            changeset_ty = (),
        }
    };

    // Receive changeset ty when tuple struct from `AsChangeset_construct_changeset_ty`
    (
        (
            fields = [$({
                column_name: $column_name:ident,
                field_ty: $field_ty:ty,
                field_kind: $field_kind:ident,
            })+],
            struct_name = $struct_name:ident,
            $($headers:tt)*
        ),
        changeset_ty = $changeset_ty:ty,
    ) => {
        AsChangeset! {
            $($headers)*
            self_to_columns = $struct_name($(ref $column_name),+),
            columns = ($($column_name, $field_kind),+),
            field_names = [],
            changeset_ty = $changeset_ty,
        }
    };

    // Receive changeset ty when named struct from `AsChangeset_construct_changeset_ty`
    (
        (
            fields = [$({
                field_name: $field_name:ident,
                column_name: $column_name:ident,
                field_ty: $field_ty:ty,
                field_kind: $field_kind:ident,
            })+],
            struct_name = $struct_name:ident,
            $($headers:tt)*
        ),
        changeset_ty = $changeset_ty:ty,
    ) => {
        AsChangeset! {
            $($headers)*
            self_to_columns = $struct_name { $($field_name: ref $column_name),+ },
            columns = ($($column_name, $field_kind),+),
            field_names = [$($field_name)+],
            changeset_ty = $changeset_ty,
        }
    };

    // Construct final impl
    (
        table_name = $table_name:ident,
        treat_none_as_null = $treat_none_as_null:tt,
        struct_ty = $struct_ty:ty,
        lifetimes = ($($lifetime:tt),*),
        self_to_columns = $self_to_columns:pat,
        columns = ($($column_name:ident, $field_kind:ident),+),
        field_names = $field_names:tt,
        changeset_ty = $changeset_ty:ty,
    ) => {
        __diesel_parse_as_item! {
            impl<$($lifetime: 'update,)* 'update> $crate::query_builder::AsChangeset
                for &'update $struct_ty
            {
                type Target = $table_name::table;
                type Changeset = $changeset_ty;

                #[allow(non_shorthand_field_patterns)]
                fn as_changeset(self) -> Self::Changeset {
                    let $self_to_columns = *self;
                    ($(
                        AsChangeset_column_expr!(
                            $table_name::$column_name,
                            $column_name,
                            none_as_null = $treat_none_as_null,
                            field_kind = $field_kind,
                        )
                    ,)+)
                }
            }
        }
    };
}

// FIXME: This can be cleaned up significantly when https://github.com/rust-lang/rust/issues/27245
// is stable
#[doc(hidden)]
#[macro_export]
macro_rules! AsChangeset_construct_changeset_ty {
    // Handle option field when treat none as null is false
    (
        $headers:tt,
        table_name = $table_name:ident,
        treat_none_as_null = "false",
        fields = [{
            $(field_name: $field_name:ident,)*
            column_name: $column_name:ident,
            field_ty: Option<$field_ty:ty>,
            field_kind: option,
        } $($tail:tt)*],
        changeset_ty = ($($changeset_ty:ty,)*),
    ) => {
        AsChangeset_construct_changeset_ty! {
            $headers,
            table_name = $table_name,
            treat_none_as_null = "false",
            fields = [$($tail)*],
            changeset_ty = ($($changeset_ty,)*
                Option<$crate::expression::predicates::Eq<
                    $table_name::$column_name,
                    $crate::expression::bound::Bound<
                        <$table_name::$column_name as $crate::expression::Expression>::SqlType,
                        &'update $field_ty,
                    >,
                >>,
            ),
        }
    };

    // Handle normal field or option when treat none as null is true
    (
        $headers:tt,
        table_name = $table_name:ident,
        treat_none_as_null = $treat_none_as_null:tt,
        fields = [{
            $(field_name: $field_name:ident,)*
            column_name: $column_name:ident,
            field_ty: $field_ty:ty,
            $($ignore:tt)*
        } $($tail:tt)*],
        changeset_ty = ($($changeset_ty:ty,)*),
    ) => {
        AsChangeset_construct_changeset_ty! {
            $headers,
            table_name = $table_name,
            treat_none_as_null = $treat_none_as_null,
            fields = [$($tail)*],
            changeset_ty = ($($changeset_ty,)*
                $crate::expression::predicates::Eq<
                    $table_name::$column_name,
                    $crate::expression::bound::Bound<
                        <$table_name::$column_name as $crate::expression::Expression>::SqlType,
                        &'update $field_ty,
                    >,
                >,
            ),
        }
    };

    // Finished parsing
    (
        $headers:tt,
        table_name = $table_name:ident,
        treat_none_as_null = $treat_none_as_null:tt,
        fields = [],
        changeset_ty = $changeset_ty:ty,
    ) => {
        AsChangeset!($headers, changeset_ty = $changeset_ty,);
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! AsChangeset_column_expr {
    // When none_as_null is false, we don't update fields which aren't present
    (
        $column:expr,
        $field_access:expr,
        none_as_null = "false",
        field_kind = option,
    ) => {
        $field_access.as_ref().map(|f| $column.eq(f))
    };

    // If none_as_null is true, or the field kind isn't option, assign blindly
    (
        $column:expr,
        $field_access:expr,
        $($args:tt)*
    ) => {
        $column.eq($field_access)
    };
}
<|endoftext|>


<commit_before>extern crate num;
use num::complex::Complex;
use std::num::Zero;

/*
    Regular O(n^2) DFT calculation
*/
pub fn dft(signal: &[Complex<f32>], spectrum: &mut [Complex<f32>])
{
    for (k, spec_bin) in spectrum.mut_iter().enumerate()
    {
        let mut sum: Complex<f32> = Zero::zero();
        let mut angle = 0f32;
        let rad_per_sample = (k as f32) * Float::two_pi() / (signal.len() as f32);
        for &x in signal.iter()
        {
            let twiddle: Complex<f32> = Complex::from_polar(&1f32, &angle);
            sum = sum + twiddle * x;
            angle = angle - rad_per_sample;
        }
        *spec_bin = sum;
    }
}

/*
    Testing
*/
fn compare_vectors(vec1: &[Complex<f32>], vec2: &[Complex<f32>]) -> bool
{
    let mut sse = 0f32;
    for (&a, &b) in vec1.iter().zip(vec2.iter())
    {
        sse = sse + (a - b).norm();
    }
    return sse < 1f32;
}

#[test]
fn dft_test()
{

    let signal = vec![Complex{re: 1f32, im: 0f32},
                      Complex{re:-1f32, im: 0f32}];
    let mut spectrum = signal.to_owned();
    dft(signal.as_slice(), spectrum.as_mut_slice());
    assert!(compare_vectors(spectrum.as_slice(), vec![Complex{re: 0f32, im: 0f32},
                                                      Complex{re: 2f32, im: 0f32}].as_slice()));

    let signal = vec![Complex{re: 1f32, im: 1f32},
                      Complex{re: 2f32, im:-3f32},
                      Complex{re:-1f32, im: 4f32}];
    let mut spectrum = signal.to_owned();
    dft(signal.as_slice(), spectrum.as_mut_slice());
    assert!(compare_vectors(spectrum.as_slice(), vec![Complex{re: 2f32, im: 2f32},
                                                      Complex{re: -5.562177f32, im: -2.098076f32},
                                                      Complex{re: 6.562178f32, im: 3.09807f32}].as_slice()));

    let signal = vec![Complex{re: 0f32, im: 1f32},
                      Complex{re: 2.5f32, im:-3f32},
                      Complex{re:-1f32, im: -1f32},
                      Complex{re: 4f32, im: 0f32}];
    let mut spectrum = signal.to_owned();
    dft(signal.as_slice(), spectrum.as_mut_slice());
    assert!(compare_vectors(spectrum.as_slice(), vec![Complex{re: 5.5f32, im: -3f32},
                                                      Complex{re: -2f32, im: 3.5f32},
                                                      Complex{re: -7.5f32, im: 3f32},
                                                      Complex{re: 4f32, im: 0.5f32}].as_slice()));

}
<commit_msg>Fixed bug where floating point errors accumulated<commit_after>extern crate num;
use num::complex::Complex;
use std::num::Zero;

/*
    Regular O(n^2) DFT calculation
*/
pub fn dft(signal: &[Complex<f32>], spectrum: &mut [Complex<f32>])
{
    for (k, spec_bin) in spectrum.mut_iter().enumerate()
    {
        let mut sum: Complex<f32> = Zero::zero();
        for (i, &x) in signal.iter().enumerate()
        {
            let angle = -1f32 * (i as f32) * (k as f32) * Float::two_pi() / (signal.len() as f32);
            let twiddle: Complex<f32> = Complex::from_polar(&1f32, &angle);
            sum = sum + twiddle * x;
        }
        *spec_bin = sum;
    }
}

/*
    Testing
*/
fn compare_vectors(vec1: &[Complex<f32>], vec2: &[Complex<f32>]) -> bool
{
    let mut sse = 0f32;
    for (&a, &b) in vec1.iter().zip(vec2.iter())
    {
        sse = sse + (a - b).norm();
    }
    return sse < 1f32;
}

#[test]
fn dft_test()
{

    let signal = vec![Complex{re: 1f32, im: 0f32},
                      Complex{re:-1f32, im: 0f32}];
    let mut spectrum = signal.to_owned();
    dft(signal.as_slice(), spectrum.as_mut_slice());
    assert!(compare_vectors(spectrum.as_slice(), vec![Complex{re: 0f32, im: 0f32},
                                                      Complex{re: 2f32, im: 0f32}].as_slice()));

    let signal = vec![Complex{re: 1f32, im: 1f32},
                      Complex{re: 2f32, im:-3f32},
                      Complex{re:-1f32, im: 4f32}];
    let mut spectrum = signal.to_owned();
    dft(signal.as_slice(), spectrum.as_mut_slice());
    assert!(compare_vectors(spectrum.as_slice(), vec![Complex{re: 2f32, im: 2f32},
                                                      Complex{re: -5.562177f32, im: -2.098076f32},
                                                      Complex{re: 6.562178f32, im: 3.09807f32}].as_slice()));

    let signal = vec![Complex{re: 0f32, im: 1f32},
                      Complex{re: 2.5f32, im:-3f32},
                      Complex{re:-1f32, im: -1f32},
                      Complex{re: 4f32, im: 0f32}];
    let mut spectrum = signal.to_owned();
    dft(signal.as_slice(), spectrum.as_mut_slice());
    assert!(compare_vectors(spectrum.as_slice(), vec![Complex{re: 5.5f32, im: -3f32},
                                                      Complex{re: -2f32, im: 3.5f32},
                                                      Complex{re: -7.5f32, im: 3f32},
                                                      Complex{re: 4f32, im: 0.5f32}].as_slice()));

}
<|endoftext|>


<commit_before>use hyper::header::{ContentLength, ContentType};
use hyper::server::Response;
use hyper::status::StatusCode;
use serde_json::{to_vec_pretty, Value};

pub trait MakeResponse {
    fn status(&self) -> StatusCode {
        StatusCode::Ok
    }

    fn content_type(&self) -> ContentType {
        ContentType::plaintext()
    }

    fn content_length(&self) -> ContentLength {
        ContentLength(0)
    }

    fn content(&self) -> &[u8] {
        &[]
    }

    fn make_response(&self, mut response: Response) {
        *response.status_mut() = self.status();
        response.headers_mut().set(self.content_type());
        response.send(self.content()).unwrap();
        // response.headers_mut().set(self.content_length());
        // response.start().unwrap().write(self.content()).unwrap();
    }
}

impl MakeResponse for StatusCode {
    fn status(&self) -> StatusCode {
        *self
    }
}

pub struct Html(pub String);

impl MakeResponse for Html {
    fn content_type(&self) -> ContentType {
        ContentType::html()
    }

    fn content_length(&self) -> ContentLength {
        ContentLength(self.0.as_bytes().len() as u64)
    }

    fn content(&self) -> &[u8] {
        self.0.as_bytes()
    }
}

impl MakeResponse for String {
    fn content_type(&self) -> ContentType {
        ContentType::plaintext()
    }

    fn content_length(&self) -> ContentLength {
        ContentLength(self.as_bytes().len() as u64)
    }

    fn content(&self) -> &[u8] {
        self.as_bytes()
    }
}

impl MakeResponse for Value {
    fn content_type(&self) -> ContentType {
        ContentType::json()
    }

    fn content_length(&self) -> ContentLength {
        to_vec_pretty(self).unwrap_or_else(|_| Vec::new()).len()
    }

    fn make_response(&self, mut response: Response) {
        *response.status_mut() = self.status();
        response.headers_mut().set(self.content_type());
        let body = to_vec_pretty(self).unwrap_or_else(|_| Vec::new());
        response.send(&body).unwrap();
    }
}
<commit_msg>Introduce MakeResponse::len()<commit_after>use hyper::header::{ContentLength, ContentType};
use hyper::server::Response;
use hyper::status::StatusCode;
use serde_json::{to_vec_pretty, Value};

pub trait MakeResponse {
    fn len(&self) -> usize {
        self.content().len()
    }

    fn status(&self) -> StatusCode {
        StatusCode::Ok
    }

    fn content_type(&self) -> ContentType {
        ContentType::plaintext()
    }

    fn content_length(&self) -> ContentLength {
        ContentLength(self.len() as u64)
    }

    fn content(&self) -> &[u8] {
        &[]
    }

    fn make_response(&self, mut response: Response) {
        *response.status_mut() = self.status();
        response.headers_mut().set(self.content_type());
        response.send(self.content()).unwrap();
        // response.headers_mut().set(self.content_length());
        // response.start().unwrap().write(self.content()).unwrap();
    }
}

impl MakeResponse for StatusCode {
    fn status(&self) -> StatusCode {
        *self
    }
}

pub struct Html(pub String);

impl MakeResponse for Html {
    fn content_type(&self) -> ContentType {
        ContentType::html()
    }

    fn content_length(&self) -> ContentLength {
        ContentLength(self.len() as u64)
    }

    fn content(&self) -> &[u8] {
        self.0.as_bytes()
    }
}

impl MakeResponse for String {
    fn content_type(&self) -> ContentType {
        ContentType::plaintext()
    }

    fn content_length(&self) -> ContentLength {
        ContentLength(self.len() as u64)
    }

    fn content(&self) -> &[u8] {
        self.as_bytes()
    }
}

impl MakeResponse for Value {
    fn content_type(&self) -> ContentType {
        ContentType::json()
    }

    fn len(&self) -> usize {
        to_vec_pretty(self).unwrap_or_else(|_| Vec::new()).len()
    }

    fn make_response(&self, mut response: Response) {
        *response.status_mut() = self.status();
        response.headers_mut().set(self.content_type());
        let body = to_vec_pretty(self).unwrap_or_else(|_| Vec::new());
        response.send(&body).unwrap();
    }
}
<|endoftext|>


<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! Cerberus manifest manipulation.
//!
//! Cerberus uses a number of signed "manifests" to describe both the physical
//! configuration of a system it protects, and to describe policies on what
//! firmware can run on those systems.
//!
//! # Wire Format
//!
//! On the wire (and in flash) every manifest has the following layout,
//! expressed as a pseudo-Rust struct. Integers are encoded in little-endian
//! order, and `_` indicates reserved fields or padding that should be set
//! to 0.
//! ```ignore
//! struct Manifest {
//!     // Overall header.
//!     total_len: u16,
//!     manifest_type: u16, // See `ManifestType`.
//!     version_id: u32,
//!     signature_len: u16,
//!     signature_type: u8,
//!     _: u8,
//!
//!     // Table-of-contents.
//!     entry_count: u8,
//!     hash_count: u8,
//!     hash_type: u8,
//!     _: u8,
//!     toc: [TocEntry; self.entry_count],
//!     hashes: [Hash<hash_type>; self.hash_count + 1],
//!
//!     body: [u8],
//!
//!     signature: [u8; self.signature_len],
//! }
//!
//! struct TocEntry {
//!     element_type: u8, // See `Manifest::ElementType`.
//!     parent: u8,
//!     format_version: u8,
//!     hash_id: u8,
//!     offset: u16,
//!     length: u16,
//! }
//! ```
//!
//! Each manifest consists of a number of "elements", whose format is
//! manifest-specific. The "table of contents" defines these elements; each
//! entry includes:
//! - The offset and length within the manifest corresponding to it.
//! - The encoding, given by the type and the format version.
//! - An optional parent index, referring to another element in the TOC
//!   (no parent indicated by `0xff`).
//! - An optional hash index, referring to a hash in the TOC's hash list.
//!   (Again, no hash indicated by `0xff`).
//!
//! The final hash in the list of hashes is a hash of the whole TOC.
//! For more information on how to interact with the `TOC`, see
//! the [`Toc`](struct.Toc.html) type.
//!
//! # Parsing and Encoding APIs
//!
//! The `manticore::manifest` module provides an API for reading a manifest
//! stored in remote flash with minimal memory overhead, allowing the caller
//! to specify which arena various book-keeping information should be allocated
//! in. The [`Container`] type is the entry-point for this functionality.
//!
//! This module also provides an "owned" API that eagerly parses the manifest
//! into a tree based on his TOC. This requires the `std` feature, and is intended
//! for use by tooling. The [`owned::Container`] type is the relevant entry
//! point.
//!
//! [`Container`]: struct.Container.html
//! [`owned::Container`]: owned/struct.Container.html

use crate::crypto::rsa;
use crate::crypto::sha256;
use crate::hardware::flash;
use crate::io;
use crate::mem::OutOfMemory;
use crate::protocol::wire::WireEnum;

mod container;
pub use container::Container;
pub use container::HashType;
pub use container::Metadata;
pub use container::Toc;
pub use container::TocEntry;

#[cfg(feature = "std")]
pub mod owned;
pub mod pfm;

wire_enum! {
    /// A Cerberus manifest type.
    ///
    /// This enum represents the "magic number" `u16` value in a maniest header.
    pub enum ManifestType: u16 {
        /// A ["Platform Firmware Manifest"], a manifest which describes
        /// firmware that is allowed to run on a platfrom.
        ///
        /// ["Platform Firmware Manifest"]: pfm/index.html
        Pfm = 0x706d,
    }
}

/// An error returned by a manifestoperation.
#[derive(Clone, Copy, Debug)]
pub enum Error {
    /// Indicates an error in a low-level [`io`] type.
    ///
    /// [`io`]: ../io/index.html
    Io(io::Error),

    /// Indicates that an error occured in a [`flash`] type.
    ///
    /// [`flash`]: ../hardware/flash/html
    Flash(flash::Error),

    /// Indicates that an arena ran out of memory.
    OutOfMemory,

    /// Indicates that a value was out of its expected range.
    OutOfRange,

    /// Indicates that a manifest's magic value did not match the
    /// expected one for this manifest type.
    ///
    /// Contains the bad value found.
    BadMagic(u16),

    /// Indicates that the overall TOC hash did not match the actual value.
    BadTocHash,

    /// Indicates that a TOC entry in the manifest had an invalid parent.
    BadParent {
        /// The index of the bad entry.
        toc_index: usize,
    },

    /// Indicates that a TOC entry in the manifest had an out-of-range
    /// hash index.
    BadHashIndex {
        /// The index of the bad entry.
        toc_index: usize,
    },

    /// Indicates that a TOC entry's hash did not match the actual value.
    BadElementHash {
        /// The index of the bad entry.
        toc_index: usize,
    },

    /// Indicates that parsing of a particular element failed because it was
    /// below the minimum length.
    TooShort {
        /// The index of the bad entry.
        toc_index: usize,
    },

    /// Indicates a bad range was found while parsing a particular element.
    ///
    /// This indicates that the given range, given as a start and an end, would
    /// have had negative length.
    BadRange {
        /// The index of the bad entry.
        toc_index: usize,
    },

    /// Indicates that some assumption about a manifest's alignment (internal
    /// or overall) was violated.
    Unaligned,

    /// Indicates that a manifest contained a signature type not supported by
    /// the hash engine being used.
    UnsupportedHashType(HashType),

    /// Indicates that the signature length is incompatible with either the
    /// given manifest length or the signature algorithm.
    BadSignatureLen,

    /// Indicates that a signature operation failed for some reason.
    SignatureFailure,
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Self::Io(e)
    }
}

impl From<flash::Error> for Error {
    fn from(e: flash::Error) -> Self {
        Self::Flash(e)
    }
}

impl From<OutOfMemory> for Error {
    fn from(_: OutOfMemory) -> Self {
        Self::OutOfMemory
    }
}

impl<E> From<rsa::Error<E>> for Error {
    fn from(_: rsa::Error<E>) -> Self {
        Self::SignatureFailure
    }
}

impl<E> From<sha256::Error<E>> for Error {
    fn from(_: sha256::Error<E>) -> Self {
        Self::SignatureFailure
    }
}

/// A manifest type.
///
/// All manifest types implement this trait, which tracks type information
/// about a particular manifest type (e.g., the PFM) that can be used by shared
/// generic code.
pub trait Manifest {
    /// A `WireEnum` representing the different kinds of valid element types
    /// for a Manifest that Manticore understands.
    type ElementType: WireEnum<Wire = u8>;

    /// The specific value of `ManifestType` representing the type implementing
    /// this trait.
    const TYPE: ManifestType;

    /// The minimum version of a particular `ElementType` understood by
    /// Manticore. All manifest elements must be future-compatible, so knowing
    /// a "maximum version" is not necessary.
    fn min_version(ty: Self::ElementType) -> u8;
}

/// Manifest provenances.
///
/// A *provenance* is a marker type used to indicate the source of a parsed
/// manifest, to help ensure that manifest signatures are properly checked
/// before the manifest is used.
///
/// These types are only really intended to be used as type parameters.
pub mod provenance {
    /// A provenance. This trait can be used to write code that is generic
    /// on provenances but which might choose to skip certain operations for
    /// the `Adhoc` provenenace.
    pub trait Provenance {
        /// Whether this provenance represents an authenticated source,
        /// i.e., whether it comes from a continuous chain of trust (via
        /// hashes) to a signature.
        const AUTHENTICATED: bool;
    }

    /// The "signed" provenance, indicating a manifest that has been
    /// appropriately verified.
    #[derive(Copy, Clone, PartialEq, Eq, Debug)]
    pub enum Signed {}

    impl Provenance for Signed {
        const AUTHENTICATED: bool = true;
    }

    /// The "ad-hoc" provenance, indicating a manifest that came from
    /// "somewhere else", such as `serde` or manual construction.
    #[derive(Copy, Clone, PartialEq, Eq, Debug)]
    pub enum Adhoc {}

    impl Provenance for Adhoc {
        const AUTHENTICATED: bool = false;
    }
}
<commit_msg>[manifest] Make hash engine failures their own error<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! Cerberus manifest manipulation.
//!
//! Cerberus uses a number of signed "manifests" to describe both the physical
//! configuration of a system it protects, and to describe policies on what
//! firmware can run on those systems.
//!
//! # Wire Format
//!
//! On the wire (and in flash) every manifest has the following layout,
//! expressed as a pseudo-Rust struct. Integers are encoded in little-endian
//! order, and `_` indicates reserved fields or padding that should be set
//! to 0.
//! ```ignore
//! struct Manifest {
//!     // Overall header.
//!     total_len: u16,
//!     manifest_type: u16, // See `ManifestType`.
//!     version_id: u32,
//!     signature_len: u16,
//!     signature_type: u8,
//!     _: u8,
//!
//!     // Table-of-contents.
//!     entry_count: u8,
//!     hash_count: u8,
//!     hash_type: u8,
//!     _: u8,
//!     toc: [TocEntry; self.entry_count],
//!     hashes: [Hash<hash_type>; self.hash_count + 1],
//!
//!     body: [u8],
//!
//!     signature: [u8; self.signature_len],
//! }
//!
//! struct TocEntry {
//!     element_type: u8, // See `Manifest::ElementType`.
//!     parent: u8,
//!     format_version: u8,
//!     hash_id: u8,
//!     offset: u16,
//!     length: u16,
//! }
//! ```
//!
//! Each manifest consists of a number of "elements", whose format is
//! manifest-specific. The "table of contents" defines these elements; each
//! entry includes:
//! - The offset and length within the manifest corresponding to it.
//! - The encoding, given by the type and the format version.
//! - An optional parent index, referring to another element in the TOC
//!   (no parent indicated by `0xff`).
//! - An optional hash index, referring to a hash in the TOC's hash list.
//!   (Again, no hash indicated by `0xff`).
//!
//! The final hash in the list of hashes is a hash of the whole TOC.
//! For more information on how to interact with the `TOC`, see
//! the [`Toc`](struct.Toc.html) type.
//!
//! # Parsing and Encoding APIs
//!
//! The `manticore::manifest` module provides an API for reading a manifest
//! stored in remote flash with minimal memory overhead, allowing the caller
//! to specify which arena various book-keeping information should be allocated
//! in. The [`Container`] type is the entry-point for this functionality.
//!
//! This module also provides an "owned" API that eagerly parses the manifest
//! into a tree based on his TOC. This requires the `std` feature, and is intended
//! for use by tooling. The [`owned::Container`] type is the relevant entry
//! point.
//!
//! [`Container`]: struct.Container.html
//! [`owned::Container`]: owned/struct.Container.html

use crate::crypto::rsa;
use crate::crypto::sha256;
use crate::hardware::flash;
use crate::io;
use crate::mem::OutOfMemory;
use crate::protocol::wire::WireEnum;

mod container;
pub use container::Container;
pub use container::HashType;
pub use container::Metadata;
pub use container::Toc;
pub use container::TocEntry;

#[cfg(feature = "std")]
pub mod owned;
pub mod pfm;

wire_enum! {
    /// A Cerberus manifest type.
    ///
    /// This enum represents the "magic number" `u16` value in a maniest header.
    pub enum ManifestType: u16 {
        /// A ["Platform Firmware Manifest"], a manifest which describes
        /// firmware that is allowed to run on a platfrom.
        ///
        /// ["Platform Firmware Manifest"]: pfm/index.html
        Pfm = 0x706d,
    }
}

/// An error returned by a manifestoperation.
#[derive(Clone, Copy, Debug)]
pub enum Error {
    /// Indicates an error in a low-level [`io`] type.
    ///
    /// [`io`]: ../io/index.html
    Io(io::Error),

    /// Indicates that an error occured in a [`flash`] type.
    ///
    /// [`flash`]: ../hardware/flash/html
    Flash(flash::Error),

    /// Indicates that an arena ran out of memory.
    OutOfMemory,

    /// Indicates that a value was out of its expected range.
    OutOfRange,

    /// Indicates that a manifest's magic value did not match the
    /// expected one for this manifest type.
    ///
    /// Contains the bad value found.
    BadMagic(u16),

    /// Indicates that the overall TOC hash did not match the actual value.
    BadTocHash,

    /// Indicates that a TOC entry in the manifest had an invalid parent.
    BadParent {
        /// The index of the bad entry.
        toc_index: usize,
    },

    /// Indicates that a TOC entry in the manifest had an out-of-range
    /// hash index.
    BadHashIndex {
        /// The index of the bad entry.
        toc_index: usize,
    },

    /// Indicates that a TOC entry's hash did not match the actual value.
    BadElementHash {
        /// The index of the bad entry.
        toc_index: usize,
    },

    /// Indicates that parsing of a particular element failed because it was
    /// below the minimum length.
    TooShort {
        /// The index of the bad entry.
        toc_index: usize,
    },

    /// Indicates a bad range was found while parsing a particular element.
    ///
    /// This indicates that the given range, given as a start and an end, would
    /// have had negative length.
    BadRange {
        /// The index of the bad entry.
        toc_index: usize,
    },

    /// Indicates that some assumption about a manifest's alignment (internal
    /// or overall) was violated.
    Unaligned,

    /// Indicates that a manifest contained a signature type not supported by
    /// the hash engine being used.
    UnsupportedHashType(HashType),

    /// Indicates that the signature length is incompatible with either the
    /// given manifest length or the signature algorithm.
    BadSignatureLen,

    /// Indicates that an error occured inside of a hashing engine.
    HashingError(sha256::Error),

    /// Indicates that a signature operation failed for some reason.
    SignatureFailure,
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Self::Io(e)
    }
}

impl From<flash::Error> for Error {
    fn from(e: flash::Error) -> Self {
        Self::Flash(e)
    }
}

impl From<OutOfMemory> for Error {
    fn from(_: OutOfMemory) -> Self {
        Self::OutOfMemory
    }
}

impl<E> From<rsa::Error<E>> for Error {
    fn from(_: rsa::Error<E>) -> Self {
        Self::SignatureFailure
    }
}

impl<E> From<sha256::Error<E>> for Error {
    fn from(e: sha256::Error<E>) -> Self {
        Self::HashingError(e.erased())
    }
}

/// A manifest type.
///
/// All manifest types implement this trait, which tracks type information
/// about a particular manifest type (e.g., the PFM) that can be used by shared
/// generic code.
pub trait Manifest {
    /// A `WireEnum` representing the different kinds of valid element types
    /// for a Manifest that Manticore understands.
    type ElementType: WireEnum<Wire = u8>;

    /// The specific value of `ManifestType` representing the type implementing
    /// this trait.
    const TYPE: ManifestType;

    /// The minimum version of a particular `ElementType` understood by
    /// Manticore. All manifest elements must be future-compatible, so knowing
    /// a "maximum version" is not necessary.
    fn min_version(ty: Self::ElementType) -> u8;
}

/// Manifest provenances.
///
/// A *provenance* is a marker type used to indicate the source of a parsed
/// manifest, to help ensure that manifest signatures are properly checked
/// before the manifest is used.
///
/// These types are only really intended to be used as type parameters.
pub mod provenance {
    /// A provenance. This trait can be used to write code that is generic
    /// on provenances but which might choose to skip certain operations for
    /// the `Adhoc` provenenace.
    pub trait Provenance {
        /// Whether this provenance represents an authenticated source,
        /// i.e., whether it comes from a continuous chain of trust (via
        /// hashes) to a signature.
        const AUTHENTICATED: bool;
    }

    /// The "signed" provenance, indicating a manifest that has been
    /// appropriately verified.
    #[derive(Copy, Clone, PartialEq, Eq, Debug)]
    pub enum Signed {}

    impl Provenance for Signed {
        const AUTHENTICATED: bool = true;
    }

    /// The "ad-hoc" provenance, indicating a manifest that came from
    /// "somewhere else", such as `serde` or manual construction.
    #[derive(Copy, Clone, PartialEq, Eq, Debug)]
    pub enum Adhoc {}

    impl Provenance for Adhoc {
        const AUTHENTICATED: bool = false;
    }
}
<|endoftext|>


<commit_before>extern crate scroll_phat_hd;

use scroll_phat_hd::display::*;
use scroll_phat_hd::scroller::*;

fn main() {
    println!("start");

    // let mut display = I2CDisplay::new(1);
    // let mut display = TermDisplay::new();
    let mut display = UnicodeDisplay::new();
    let mut scroller = Scroller::new(&mut display);

    scroller.set_text("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789+=-_,.:;!?;'\"\\/°#()[]@");
    for _ in 0..3000 {
        scroller.show();
        std::thread::sleep(std::time::Duration::from_millis(100));
        scroller.scroll();
    }

    println!("end");
}
<commit_msg>Make scroll faster in test<commit_after>extern crate scroll_phat_hd;

use scroll_phat_hd::display::*;
use scroll_phat_hd::scroller::*;

fn main() {
    println!("start");

    // let mut display = I2CDisplay::new(1);
    // let mut display = TermDisplay::new();
    let mut display = UnicodeDisplay::new();
    let mut scroller = Scroller::new(&mut display);

    scroller.set_text("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789+=-_,.:;!?;'\"\\/°#()[]@");
    for _ in 0..3000 {
        scroller.show();
        std::thread::sleep(std::time::Duration::from_millis(50));
        scroller.scroll();
    }

    println!("end");
}
<|endoftext|>


<commit_before>use crate::{
    ast::{Directive, FromInputValue, InputValue, Selection},
    value::{Object, ScalarRefValue, ScalarValue, Value},
};
use async_trait::async_trait;

use crate::{
    executor::{ExecutionResult, Executor},
    parser::Spanning,
};

use crate::BoxFuture;

use super::base::{is_excluded, merge_key_into, Arguments, GraphQLType};

#[async_trait]
pub trait GraphQLTypeAsync<S>: GraphQLType<S> + Send + Sync
where
    Self::Context: Send + Sync,
    Self::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    async fn resolve_field_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        field_name: &'a str,
        arguments: &'a Arguments<'a, S>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> ExecutionResult<S> {
        panic!("resolve_field must be implemented by object types");
    }

    async fn resolve_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        selection_set: Option<&'a [Selection<'a, S>]>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> Value<S> {
        if let Some(selection_set) = selection_set {
            resolve_selection_set_into_async(self, info, selection_set, executor).await
        } else {
            panic!("resolve() must be implemented by non-object output types");
        }
    }

    async fn resolve_into_type_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        type_name: &str,
        selection_set: Option<&'a [Selection<'a, S>]>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> ExecutionResult<S> {
        if Self::name(info).unwrap() == type_name {
            Ok(self.resolve_async(info, selection_set, executor).await)
        } else {
            panic!("resolve_into_type_async must be implemented by unions and interfaces");
        }
    }
}

// Wrapper function around resolve_selection_set_into_async_recursive.
// This wrapper is necessary because async fns can not be recursive.
#[cfg(feature = "async")]
pub(crate) fn resolve_selection_set_into_async<'a, 'e, T, CtxT, S>(
    instance: &'a T,
    info: &'a T::TypeInfo,
    selection_set: &'e [Selection<'e, S>],
    executor: &'e Executor<'e, CtxT, S>,
) -> BoxFuture<'a, Value<S>>
where
    T: GraphQLTypeAsync<S, Context = CtxT>,
    T::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    CtxT: Send + Sync,
    'e: 'a,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    Box::pin(resolve_selection_set_into_async_recursive(
        instance,
        info,
        selection_set,
        executor,
    ))
}

struct AsyncField<S> {
    name: String,
    value: Option<Value<S>>,
}

enum AsyncValue<S> {
    Field(AsyncField<S>),
    Nested(Value<S>),
}

#[cfg(feature = "async")]
pub(crate) async fn resolve_selection_set_into_async_recursive<'a, T, CtxT, S>(
    instance: &'a T,
    info: &'a T::TypeInfo,
    selection_set: &'a [Selection<'a, S>],
    executor: &'a Executor<'a, CtxT, S>,
) -> Value<S>
where
    T: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
    T::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    CtxT: Send + Sync,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    use futures::stream::{FuturesOrdered, StreamExt};

    let mut object = Object::with_capacity(selection_set.len());

    let mut async_values = FuturesOrdered::<BoxFuture<'a, AsyncValue<S>>>::new();

    let meta_type = executor
        .schema()
        .concrete_type_by_name(
            T::name(info)
                .expect("Resolving named type's selection set")
                .as_ref(),
        )
        .expect("Type not found in schema");

    for selection in selection_set {
        match *selection {
            Selection::Field(Spanning {
                item: ref f,
                start: ref start_pos,
                ..
            }) => {
                if is_excluded(&f.directives, executor.variables()) {
                    continue;
                }

                let response_name = f.alias.as_ref().unwrap_or(&f.name).item;

                if f.name.item == "__typename" {
                    object.add_field(
                        response_name,
                        Value::scalar(instance.concrete_type_name(executor.context(), info)),
                    );
                    continue;
                }

                let meta_field = meta_type.field_by_name(f.name.item).unwrap_or_else(|| {
                    panic!(format!(
                        "Field {} not found on type {:?}",
                        f.name.item,
                        meta_type.name()
                    ))
                });

                let exec_vars = executor.variables();

                let sub_exec = executor.field_sub_executor(
                    &response_name,
                    f.name.item,
                    start_pos.clone(),
                    f.selection_set.as_ref().map(|v| &v[..]),
                );
                let args = Arguments::new(
                    f.arguments.as_ref().map(|m| {
                        m.item
                            .iter()
                            .map(|&(ref k, ref v)| (k.item, v.item.clone().into_const(exec_vars)))
                            .collect()
                    }),
                    &meta_field.arguments,
                );

                let pos = start_pos.clone();
                let is_non_null = meta_field.field_type.is_non_null();

                let response_name = response_name.to_string();
                let field_future = async move {
                    // TODO: implement custom future type instead of
                    //       two-level boxing.
                    let res = instance
                        .resolve_field_async(info, f.name.item, &args, &sub_exec)
                        .await;

                    let value = match res {
                        Ok(Value::Null) if is_non_null => None,
                        Ok(v) => Some(v),
                        Err(e) => {
                            sub_exec.push_error_at(e, pos);

                            if is_non_null {
                                None
                            } else {
                                Some(Value::null())
                            }
                        }
                    };
                    AsyncValue::Field(AsyncField {
                        name: response_name,
                        value,
                    })
                };
                async_values.push(Box::pin(field_future));
            }
            Selection::FragmentSpread(Spanning {
                item: ref spread, ..
            }) => {
                if is_excluded(&spread.directives, executor.variables()) {
                    continue;
                }

                // TODO: prevent duplicate boxing.
                let f = async move {
                    let fragment = &executor
                        .fragment_by_name(spread.name.item)
                        .expect("Fragment could not be found");
                    let value = resolve_selection_set_into_async(
                        instance,
                        info,
                        &fragment.selection_set[..],
                        executor,
                    )
                    .await;
                    AsyncValue::Nested(value)
                };
                async_values.push(Box::pin(f));
            }
            Selection::InlineFragment(Spanning {
                item: ref fragment,
                start: ref start_pos,
                ..
            }) => {
                if is_excluded(&fragment.directives, executor.variables()) {
                    continue;
                }

                let sub_exec = executor.type_sub_executor(
                    fragment.type_condition.as_ref().map(|c| c.item),
                    Some(&fragment.selection_set[..]),
                );

                if let Some(ref type_condition) = fragment.type_condition {
                    let sub_result = instance
                        .resolve_into_type_async(
                            info,
                            type_condition.item,
                            Some(&fragment.selection_set[..]),
                            &sub_exec,
                        )
                        .await;

                    if let Ok(Value::Object(obj)) = sub_result {
                        for (k, v) in obj {
                            merge_key_into(&mut object, &k, v);
                        }
                    } else if let Err(e) = sub_result {
                        sub_exec.push_error_at(e, start_pos.clone());
                    }
                } else {
                    let f = async move {
                        let value = resolve_selection_set_into_async(
                            instance,
                            info,
                            &fragment.selection_set[..],
                            &sub_exec,
                        )
                        .await;
                        AsyncValue::Nested(value)
                    };
                    async_values.push(Box::pin(f));
                }
            }
        }
    }

    while let Some(item) = async_values.next().await {
        match item {
            AsyncValue::Field(AsyncField { name, value }) => {
                if let Some(value) = value {
                    object.add_field(&name, value);
                } else {
                    return Value::null();
                }
            }
            AsyncValue::Nested(obj) => match obj {
                v @ Value::Null => {
                    return v;
                }
                Value::Object(obj) => {
                    for (k, v) in obj {
                        merge_key_into(&mut object, &k, v);
                    }
                }
                _ => unreachable!(),
            },
        }
    }

    Value::Object(object)
}
<commit_msg>Format<commit_after>use crate::{
    ast::{Directive, FromInputValue, InputValue, Selection},
    value::{Object, ScalarRefValue, ScalarValue, Value},
};

use crate::{
    executor::{ExecutionResult, Executor},
    parser::Spanning,
};

use crate::BoxFuture;

use super::base::{is_excluded, merge_key_into, Arguments, GraphQLType};

#[async_trait::async_trait]
pub trait GraphQLTypeAsync<S>: GraphQLType<S> + Send + Sync
where
    Self::Context: Send + Sync,
    Self::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    async fn resolve_field_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        field_name: &'a str,
        arguments: &'a Arguments<'a, S>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> ExecutionResult<S> {
        panic!("resolve_field must be implemented by object types");
    }

    async fn resolve_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        selection_set: Option<&'a [Selection<'a, S>]>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> Value<S> {
        if let Some(selection_set) = selection_set {
            resolve_selection_set_into_async(self, info, selection_set, executor).await
        } else {
            panic!("resolve() must be implemented by non-object output types");
        }
    }

    async fn resolve_into_type_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        type_name: &str,
        selection_set: Option<&'a [Selection<'a, S>]>,
        executor: &'a Executor<'a, Self::Context, S>,
    ) -> ExecutionResult<S> {
        if Self::name(info).unwrap() == type_name {
            Ok(self.resolve_async(info, selection_set, executor).await)
        } else {
            panic!("resolve_into_type_async must be implemented by unions and interfaces");
        }
    }
}

// Wrapper function around resolve_selection_set_into_async_recursive.
// This wrapper is necessary because async fns can not be recursive.
#[cfg(feature = "async")]
pub(crate) fn resolve_selection_set_into_async<'a, 'e, T, CtxT, S>(
    instance: &'a T,
    info: &'a T::TypeInfo,
    selection_set: &'e [Selection<'e, S>],
    executor: &'e Executor<'e, CtxT, S>,
) -> BoxFuture<'a, Value<S>>
where
    T: GraphQLTypeAsync<S, Context = CtxT>,
    T::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    CtxT: Send + Sync,
    'e: 'a,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    Box::pin(resolve_selection_set_into_async_recursive(
        instance,
        info,
        selection_set,
        executor,
    ))
}

struct AsyncField<S> {
    name: String,
    value: Option<Value<S>>,
}

enum AsyncValue<S> {
    Field(AsyncField<S>),
    Nested(Value<S>),
}

#[cfg(feature = "async")]
pub(crate) async fn resolve_selection_set_into_async_recursive<'a, T, CtxT, S>(
    instance: &'a T,
    info: &'a T::TypeInfo,
    selection_set: &'a [Selection<'a, S>],
    executor: &'a Executor<'a, CtxT, S>,
) -> Value<S>
where
    T: GraphQLTypeAsync<S, Context = CtxT> + Send + Sync,
    T::TypeInfo: Send + Sync,
    S: ScalarValue + Send + Sync,
    CtxT: Send + Sync,
    for<'b> &'b S: ScalarRefValue<'b>,
{
    use futures::stream::{FuturesOrdered, StreamExt};

    let mut object = Object::with_capacity(selection_set.len());

    let mut async_values = FuturesOrdered::<BoxFuture<'a, AsyncValue<S>>>::new();

    let meta_type = executor
        .schema()
        .concrete_type_by_name(
            T::name(info)
                .expect("Resolving named type's selection set")
                .as_ref(),
        )
        .expect("Type not found in schema");

    for selection in selection_set {
        match *selection {
            Selection::Field(Spanning {
                item: ref f,
                start: ref start_pos,
                ..
            }) => {
                if is_excluded(&f.directives, executor.variables()) {
                    continue;
                }

                let response_name = f.alias.as_ref().unwrap_or(&f.name).item;

                if f.name.item == "__typename" {
                    object.add_field(
                        response_name,
                        Value::scalar(instance.concrete_type_name(executor.context(), info)),
                    );
                    continue;
                }

                let meta_field = meta_type.field_by_name(f.name.item).unwrap_or_else(|| {
                    panic!(format!(
                        "Field {} not found on type {:?}",
                        f.name.item,
                        meta_type.name()
                    ))
                });

                let exec_vars = executor.variables();

                let sub_exec = executor.field_sub_executor(
                    &response_name,
                    f.name.item,
                    start_pos.clone(),
                    f.selection_set.as_ref().map(|v| &v[..]),
                );
                let args = Arguments::new(
                    f.arguments.as_ref().map(|m| {
                        m.item
                            .iter()
                            .map(|&(ref k, ref v)| (k.item, v.item.clone().into_const(exec_vars)))
                            .collect()
                    }),
                    &meta_field.arguments,
                );

                let pos = start_pos.clone();
                let is_non_null = meta_field.field_type.is_non_null();

                let response_name = response_name.to_string();
                let field_future = async move {
                    // TODO: implement custom future type instead of
                    //       two-level boxing.
                    let res = instance
                        .resolve_field_async(info, f.name.item, &args, &sub_exec)
                        .await;

                    let value = match res {
                        Ok(Value::Null) if is_non_null => None,
                        Ok(v) => Some(v),
                        Err(e) => {
                            sub_exec.push_error_at(e, pos);

                            if is_non_null {
                                None
                            } else {
                                Some(Value::null())
                            }
                        }
                    };
                    AsyncValue::Field(AsyncField {
                        name: response_name,
                        value,
                    })
                };
                async_values.push(Box::pin(field_future));
            }
            Selection::FragmentSpread(Spanning {
                item: ref spread, ..
            }) => {
                if is_excluded(&spread.directives, executor.variables()) {
                    continue;
                }

                // TODO: prevent duplicate boxing.
                let f = async move {
                    let fragment = &executor
                        .fragment_by_name(spread.name.item)
                        .expect("Fragment could not be found");
                    let value = resolve_selection_set_into_async(
                        instance,
                        info,
                        &fragment.selection_set[..],
                        executor,
                    )
                    .await;
                    AsyncValue::Nested(value)
                };
                async_values.push(Box::pin(f));
            }
            Selection::InlineFragment(Spanning {
                item: ref fragment,
                start: ref start_pos,
                ..
            }) => {
                if is_excluded(&fragment.directives, executor.variables()) {
                    continue;
                }

                let sub_exec = executor.type_sub_executor(
                    fragment.type_condition.as_ref().map(|c| c.item),
                    Some(&fragment.selection_set[..]),
                );

                if let Some(ref type_condition) = fragment.type_condition {
                    let sub_result = instance
                        .resolve_into_type_async(
                            info,
                            type_condition.item,
                            Some(&fragment.selection_set[..]),
                            &sub_exec,
                        )
                        .await;

                    if let Ok(Value::Object(obj)) = sub_result {
                        for (k, v) in obj {
                            merge_key_into(&mut object, &k, v);
                        }
                    } else if let Err(e) = sub_result {
                        sub_exec.push_error_at(e, start_pos.clone());
                    }
                } else {
                    let f = async move {
                        let value = resolve_selection_set_into_async(
                            instance,
                            info,
                            &fragment.selection_set[..],
                            &sub_exec,
                        )
                        .await;
                        AsyncValue::Nested(value)
                    };
                    async_values.push(Box::pin(f));
                }
            }
        }
    }

    while let Some(item) = async_values.next().await {
        match item {
            AsyncValue::Field(AsyncField { name, value }) => {
                if let Some(value) = value {
                    object.add_field(&name, value);
                } else {
                    return Value::null();
                }
            }
            AsyncValue::Nested(obj) => match obj {
                v @ Value::Null => {
                    return v;
                }
                Value::Object(obj) => {
                    for (k, v) in obj {
                        merge_key_into(&mut object, &k, v);
                    }
                }
                _ => unreachable!(),
            },
        }
    }

    Value::Object(object)
}
<|endoftext|>


<commit_before>extern crate cursive;
extern crate rand;

use rand::Rng;

use cursive::prelude::*;
use cursive::views::Counter;

use std::thread;
use std::cmp::min;
use std::time::Duration;

fn main() {
    let mut siv = Cursive::new();

    // We'll start slowly with a simple start button...
    siv.add_layer(Dialog::empty()
        .title("Progress bar example")
        .padding((0, 0, 1, 1))
        .content(Button::new("Start", phase_1)));

    // Auto-refresh is currently required for animated views
    siv.set_fps(30);

    siv.run();
}

// Function to simulate a long process.
fn fake_load(n_max: usize, counter: Counter) {
    for _ in 0..n_max {
        thread::sleep(Duration::from_millis(5));
        // The `counter.tick()` method increases the progress value
        counter.tick(1);
    }
}

fn phase_1(s: &mut Cursive) {
    // Phase 1 is easy: a simple pre-loading.

    // Number of ticks
    let n_max = 500;

    // This is the callback channel
    let cb = s.cb_sink().clone();

    s.pop_layer();
    s.add_layer(Panel::new(ProgressBar::new()
        .range(0, n_max)
        .with_task(move |counter| {
            // This closure will be called in a separate thread.
            fake_load(n_max, counter);

            // When we're done, send a callback through the channel
            cb.send(Box::new(coffee_break)).unwrap();
        })
        .full_width()));
}

fn coffee_break(s: &mut Cursive) {
    // A little break before things get serious.
    s.pop_layer();
    s.add_layer(Dialog::empty()
        .title("Preparation complete")
        .content(TextView::new("Now, the real deal!").center())
        .button("Again??", phase_2));
}

fn phase_2(s: &mut Cursive) {
    // Now, we'll run N tasks
    // (It could be downloading a file, extracting an archive,
    // reticulating sprites, ...)
    let n_bars = 10;
    // Each task will have its own shiny counter
    let counters: Vec<_> = (0..n_bars).map(|_| Counter::new(0)).collect();
    // To make things more interesting, we'll give a random speed to each bar
    let speeds: Vec<_> =
        (0..n_bars).map(|_| rand::thread_rng().gen_range(50, 150)).collect();

    let n_max = 100000;
    let cb = s.cb_sink().clone();

    // Let's prepare the progress bars...
    let mut linear = LinearLayout::vertical();
    for c in &counters {
        linear.add_child(ProgressBar::new()
            .max(n_max)
            .with_value(c.clone()));
    }

    s.pop_layer();
    s.add_layer(Dialog::new(linear.full_width())
        .title("Just a moment..."));

    // And we start the worker thread.
    thread::spawn(move || {
        loop {
            thread::sleep(Duration::from_millis(5));
            let mut done = true;
            for (c, s) in counters.iter().zip(&speeds) {
                let ticks = min(n_max - c.get(), *s);
                c.tick(ticks);
                if c.get() < n_max {
                    done = false;
                }
            }
            if done {
                break;
            }
        }

        cb.send(Box::new(final_step)).unwrap();
    });
}

fn final_step(s: &mut Cursive) {
    // A little break before things get serious.
    s.pop_layer();
    s.add_layer(Dialog::empty()
        .title("Report")
        .content(TextView::new("Time travel was a success!\n\
                               We went forward a few seconds!!")
                 .center())
        .button("That's it?", |s| s.quit()));
}
<commit_msg>Use Dialog instead of Panel in progress example<commit_after>extern crate cursive;
extern crate rand;

use rand::Rng;

use cursive::prelude::*;
use cursive::views::Counter;

use std::thread;
use std::cmp::min;
use std::time::Duration;

fn main() {
    let mut siv = Cursive::new();

    // We'll start slowly with a simple start button...
    siv.add_layer(Dialog::empty()
        .title("Progress bar example")
        .padding((0, 0, 1, 1))
        .content(Button::new("Start", phase_1)));

    // Auto-refresh is currently required for animated views
    siv.set_fps(30);

    siv.run();
}

// Function to simulate a long process.
fn fake_load(n_max: usize, counter: Counter) {
    for _ in 0..n_max {
        thread::sleep(Duration::from_millis(5));
        // The `counter.tick()` method increases the progress value
        counter.tick(1);
    }
}

fn phase_1(s: &mut Cursive) {
    // Phase 1 is easy: a simple pre-loading.

    // Number of ticks
    let n_max = 500;

    // This is the callback channel
    let cb = s.cb_sink().clone();

    s.pop_layer();
    s.add_layer(Dialog::new(ProgressBar::new()
        .range(0, n_max)
        .with_task(move |counter| {
            // This closure will be called in a separate thread.
            fake_load(n_max, counter);

            // When we're done, send a callback through the channel
            cb.send(Box::new(coffee_break)).unwrap();
        })
        .full_width()));
}

fn coffee_break(s: &mut Cursive) {
    // A little break before things get serious.
    s.pop_layer();
    s.add_layer(Dialog::empty()
        .title("Preparation complete")
        .content(TextView::new("Now, the real deal!").center())
        .button("Again??", phase_2));
}

fn phase_2(s: &mut Cursive) {
    // Now, we'll run N tasks
    // (It could be downloading a file, extracting an archive,
    // reticulating sprites, ...)
    let n_bars = 10;
    // Each task will have its own shiny counter
    let counters: Vec<_> = (0..n_bars).map(|_| Counter::new(0)).collect();
    // To make things more interesting, we'll give a random speed to each bar
    let speeds: Vec<_> =
        (0..n_bars).map(|_| rand::thread_rng().gen_range(50, 150)).collect();

    let n_max = 100000;
    let cb = s.cb_sink().clone();

    // Let's prepare the progress bars...
    let mut linear = LinearLayout::vertical();
    for c in &counters {
        linear.add_child(ProgressBar::new()
            .max(n_max)
            .with_value(c.clone()));
    }

    s.pop_layer();
    s.add_layer(Dialog::new(linear.full_width())
        .title("Just a moment..."));

    // And we start the worker thread.
    thread::spawn(move || {
        loop {
            thread::sleep(Duration::from_millis(5));
            let mut done = true;
            for (c, s) in counters.iter().zip(&speeds) {
                let ticks = min(n_max - c.get(), *s);
                c.tick(ticks);
                if c.get() < n_max {
                    done = false;
                }
            }
            if done {
                break;
            }
        }

        cb.send(Box::new(final_step)).unwrap();
    });
}

fn final_step(s: &mut Cursive) {
    // A little break before things get serious.
    s.pop_layer();
    s.add_layer(Dialog::empty()
        .title("Report")
        .content(TextView::new("Time travel was a success!\n\
                               We went forward a few seconds!!")
                 .center())
        .button("That's it?", |s| s.quit()));
}
<|endoftext|>