<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

The iteration traits and common implementation

*/

use cmp::{Eq, Ord};
use kinds::Copy;
use option::{None, Option, Some};
use vec;

/// A function used to initialize the elements of a sequence
pub type InitOp<T> = &fn(uint) -> T;

pub trait BaseIter<A> {
    pure fn each(&self, blk: fn(v: &A) -> bool);
    pure fn size_hint(&self) -> Option<uint>;
}

pub trait ReverseIter<A>: BaseIter<A> {
    pure fn each_reverse(&self, blk: fn(&A) -> bool);
}

pub trait ExtendedIter<A> {
    pure fn eachi(&self, blk: fn(uint, v: &A) -> bool);
    pure fn all(&self, blk: fn(&A) -> bool) -> bool;
    pure fn any(&self, blk: fn(&A) -> bool) -> bool;
    pure fn foldl<B>(&self, b0: B, blk: fn(&B, &A) -> B) -> B;
    pure fn position(&self, f: fn(&A) -> bool) -> Option<uint>;
    pure fn map_to_vec<B>(&self, op: fn(&A) -> B) -> ~[B];
    pure fn flat_map_to_vec<B,IB: BaseIter<B>>(&self, op: fn(&A) -> IB)
        -> ~[B];
}

pub trait EqIter<A:Eq> {
    pure fn contains(&self, x: &A) -> bool;
    pure fn count(&self, x: &A) -> uint;
}

pub trait Times {
    pure fn times(&self, it: fn() -> bool);
}

pub trait CopyableIter<A:Copy> {
    pure fn filter_to_vec(&self, pred: fn(&A) -> bool) -> ~[A];
    pure fn to_vec(&self) -> ~[A];
    pure fn find(&self, p: fn(&A) -> bool) -> Option<A>;
}

pub trait CopyableOrderedIter<A:Copy + Ord> {
    pure fn min(&self) -> A;
    pure fn max(&self) -> A;
}

pub trait CopyableNonstrictIter<A:Copy> {
    // Like "each", but copies out the value. If the receiver is mutated while
    // iterating over it, the semantics must not be memory-unsafe but are
    // otherwise undefined.
    pure fn each_val(&const self, f: &fn(A) -> bool);
}

// A trait for sequences that can be by imperatively pushing elements
// onto them.
pub trait Buildable<A> {
    /**
     * Builds a buildable sequence by calling a provided function with
     * an argument function that pushes an element onto the back of
     * the sequence.
     * This version takes an initial size for the sequence.
     *
     * # Arguments
     *
     * * size - A hint for an initial size of the sequence
     * * builder - A function that will construct the sequence. It receives
     *             as an argument a function that will push an element
     *             onto the sequence being constructed.
     */
     static pure fn build_sized(size: uint,
                                builder: fn(push: pure fn(A))) -> Self;
}

#[inline(always)]
pub pure fn eachi<A,IA:BaseIter<A>>(self: &IA,
                                    blk: fn(uint, &A) -> bool) {
    let mut i = 0;
    for self.each |a| {
        if !blk(i, a) { break; }
        i += 1;
    }
}

#[inline(always)]
pub pure fn all<A,IA:BaseIter<A>>(self: &IA,
                                  blk: fn(&A) -> bool) -> bool {
    for self.each |a| {
        if !blk(a) { return false; }
    }
    return true;
}

#[inline(always)]
pub pure fn any<A,IA:BaseIter<A>>(self: &IA,
                                  blk: fn(&A) -> bool) -> bool {
    for self.each |a| {
        if blk(a) { return true; }
    }
    return false;
}

#[inline(always)]
pub pure fn filter_to_vec<A:Copy,IA:BaseIter<A>>(
    self: &IA, prd: fn(&A) -> bool) -> ~[A] {
    do vec::build_sized_opt(self.size_hint()) |push| {
        for self.each |a| {
            if prd(a) { push(*a); }
        }
    }
}

#[inline(always)]
pub pure fn map_to_vec<A,B,IA:BaseIter<A>>(self: &IA,
                                           op: fn(&A) -> B)
    -> ~[B] {
    do vec::build_sized_opt(self.size_hint()) |push| {
        for self.each |a| {
            push(op(a));
        }
    }
}

#[inline(always)]
pub pure fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(
    self: &IA, op: fn(&A) -> IB) -> ~[B] {
    do vec::build |push| {
        for self.each |a| {
            for op(a).each |&b| {
                push(b);
            }
        }
    }
}

#[inline(always)]
pub pure fn foldl<A,B,IA:BaseIter<A>>(self: &IA, b0: B,
                                      blk: fn(&B, &A) -> B)
    -> B {
    let mut b = b0;
    for self.each |a| {
        b = blk(&b, a);
    }
    b
}

#[inline(always)]
pub pure fn to_vec<A:Copy,IA:BaseIter<A>>(self: &IA) -> ~[A] {
    foldl::<A,~[A],IA>(self, ~[], |r, a| vec::append(copy (*r), ~[*a]))
}

#[inline(always)]
pub pure fn contains<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> bool {
    for self.each |a| {
        if *a == *x { return true; }
    }
    return false;
}

#[inline(always)]
pub pure fn count<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> uint {
    do foldl(self, 0) |count, value| {
        if *value == *x {
            *count + 1
        } else {
            *count
        }
    }
}

#[inline(always)]
pub pure fn position<A,IA:BaseIter<A>>(self: &IA, f: fn(&A) -> bool)
    -> Option<uint>
{
    let mut i = 0;
    for self.each |a| {
        if f(a) { return Some(i); }
        i += 1;
    }
    return None;
}

// note: 'rposition' would only make sense to provide with a bidirectional
// iter interface, such as would provide "reach" in addition to "each". as is,
// it would have to be implemented with foldr, which is too inefficient.

#[inline(always)]
pub pure fn repeat(times: uint, blk: fn() -> bool) {
    let mut i = 0;
    while i < times {
        if !blk() { break }
        i += 1;
    }
}

#[inline(always)]
pub pure fn min<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
    match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
        match a {
          &Some(ref a_) if *a_ < *b => {
             *(a)
          }
          _ => Some(*b)
        }
    } {
        Some(val) => val,
        None => fail!(~"min called on empty iterator")
    }
}

#[inline(always)]
pub pure fn max<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
    match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
        match a {
          &Some(ref a_) if *a_ > *b => {
              *(a)
          }
          _ => Some(*b)
        }
    } {
        Some(val) => val,
        None => fail!(~"max called on empty iterator")
    }
}

#[inline(always)]
pub pure fn find<A:Copy,IA:BaseIter<A>>(self: &IA,
                                   f: fn(&A) -> bool) -> Option<A> {
    for self.each |i| {
        if f(i) { return Some(*i) }
    }
    return None;
}

// Some functions for just building

/**
 * Builds a sequence by calling a provided function with an argument
 * function that pushes an element to the back of a sequence.
 *
 * # Arguments
 *
 * * builder - A function that will construct the sequence. It receives
 *             as an argument a function that will push an element
 *             onto the sequence being constructed.
 */
#[inline(always)]
pub pure fn build<A,B: Buildable<A>>(builder: fn(push: pure fn(A)))
    -> B {
    Buildable::build_sized(4, builder)
}

/**
 * Builds a sequence by calling a provided function with an argument
 * function that pushes an element to the back of a sequence.
 * This version takes an initial size for the sequence.
 *
 * # Arguments
 *
 * * size - An option, maybe containing initial size of the sequence
 *          to reserve
 * * builder - A function that will construct the sequence. It receives
 *             as an argument a function that will push an element
 *             onto the sequence being constructed.
 */
#[inline(always)]
pub pure fn build_sized_opt<A,B: Buildable<A>>(
    size: Option<uint>,
    builder: fn(push: pure fn(A))) -> B {

    Buildable::build_sized(size.get_or_default(4), builder)
}

// Functions that combine iteration and building

/// Apply a function to each element of an iterable and return the results
#[inline(always)]
pub fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: &IT, f: fn(&T) -> U)
    -> BU {
    do build_sized_opt(v.size_hint()) |push| {
        for v.each() |elem| {
            push(f(elem));
        }
    }
}

/**
 * Creates and initializes a generic sequence from a function
 *
 * Creates a generic sequence of size `n_elts` and initializes the elements
 * to the value returned by the function `op`.
 */
#[inline(always)]
pub pure fn from_fn<T,BT: Buildable<T>>(n_elts: uint,
                                        op: InitOp<T>) -> BT {
    do Buildable::build_sized(n_elts) |push| {
        let mut i: uint = 0u;
        while i < n_elts { push(op(i)); i += 1u; }
    }
}

/**
 * Creates and initializes a generic sequence with some element
 *
 * Creates an immutable vector of size `n_elts` and initializes the elements
 * to the value `t`.
 */
#[inline(always)]
pub pure fn from_elem<T:Copy,BT:Buildable<T>>(n_elts: uint,
                                                t: T) -> BT {
    do Buildable::build_sized(n_elts) |push| {
        let mut i: uint = 0;
        while i < n_elts { push(t); i += 1; }
    }
}

/// Appending two generic sequences
#[inline(always)]
pub pure fn append<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(
    lhs: &IT, rhs: &IT) -> BT {
    let size_opt = lhs.size_hint().chain_ref(
        |sz1| rhs.size_hint().map(|sz2| *sz1+*sz2));
    do build_sized_opt(size_opt) |push| {
        for lhs.each |x| { push(*x); }
        for rhs.each |x| { push(*x); }
    }
}

/// Copies a generic sequence, possibly converting it to a different
/// type of sequence.
#[inline(always)]
pub pure fn copy_seq<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(
    v: &IT) -> BT {
    do build_sized_opt(v.size_hint()) |push| {
        for v.each |x| { push(*x); }
    }
}
<commit_msg>Various typos corrected<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

The iteration traits and common implementation

*/

use cmp::{Eq, Ord};
use kinds::Copy;
use option::{None, Option, Some};
use vec;

/// A function used to initialize the elements of a sequence
pub type InitOp<T> = &fn(uint) -> T;

pub trait BaseIter<A> {
    pure fn each(&self, blk: fn(v: &A) -> bool);
    pure fn size_hint(&self) -> Option<uint>;
}

pub trait ReverseIter<A>: BaseIter<A> {
    pure fn each_reverse(&self, blk: fn(&A) -> bool);
}

pub trait ExtendedIter<A> {
    pure fn eachi(&self, blk: fn(uint, v: &A) -> bool);
    pure fn all(&self, blk: fn(&A) -> bool) -> bool;
    pure fn any(&self, blk: fn(&A) -> bool) -> bool;
    pure fn foldl<B>(&self, b0: B, blk: fn(&B, &A) -> B) -> B;
    pure fn position(&self, f: fn(&A) -> bool) -> Option<uint>;
    pure fn map_to_vec<B>(&self, op: fn(&A) -> B) -> ~[B];
    pure fn flat_map_to_vec<B,IB: BaseIter<B>>(&self, op: fn(&A) -> IB)
        -> ~[B];
}

pub trait EqIter<A:Eq> {
    pure fn contains(&self, x: &A) -> bool;
    pure fn count(&self, x: &A) -> uint;
}

pub trait Times {
    pure fn times(&self, it: fn() -> bool);
}

pub trait CopyableIter<A:Copy> {
    pure fn filter_to_vec(&self, pred: fn(&A) -> bool) -> ~[A];
    pure fn to_vec(&self) -> ~[A];
    pure fn find(&self, p: fn(&A) -> bool) -> Option<A>;
}

pub trait CopyableOrderedIter<A:Copy + Ord> {
    pure fn min(&self) -> A;
    pure fn max(&self) -> A;
}

pub trait CopyableNonstrictIter<A:Copy> {
    // Like "each", but copies out the value. If the receiver is mutated while
    // iterating over it, the semantics must not be memory-unsafe but are
    // otherwise undefined.
    pure fn each_val(&const self, f: &fn(A) -> bool);
}

// A trait for sequences that can be built by imperatively pushing elements
// onto them.
pub trait Buildable<A> {
    /**
     * Builds a buildable sequence by calling a provided function with
     * an argument function that pushes an element onto the back of
     * the sequence.
     * This version takes an initial size for the sequence.
     *
     * # Arguments
     *
     * * size - A hint for an initial size of the sequence
     * * builder - A function that will construct the sequence. It receives
     *             as an argument a function that will push an element
     *             onto the sequence being constructed.
     */
     static pure fn build_sized(size: uint,
                                builder: fn(push: pure fn(A))) -> Self;
}

#[inline(always)]
pub pure fn eachi<A,IA:BaseIter<A>>(self: &IA,
                                    blk: fn(uint, &A) -> bool) {
    let mut i = 0;
    for self.each |a| {
        if !blk(i, a) { break; }
        i += 1;
    }
}

#[inline(always)]
pub pure fn all<A,IA:BaseIter<A>>(self: &IA,
                                  blk: fn(&A) -> bool) -> bool {
    for self.each |a| {
        if !blk(a) { return false; }
    }
    return true;
}

#[inline(always)]
pub pure fn any<A,IA:BaseIter<A>>(self: &IA,
                                  blk: fn(&A) -> bool) -> bool {
    for self.each |a| {
        if blk(a) { return true; }
    }
    return false;
}

#[inline(always)]
pub pure fn filter_to_vec<A:Copy,IA:BaseIter<A>>(
    self: &IA, prd: fn(&A) -> bool) -> ~[A] {
    do vec::build_sized_opt(self.size_hint()) |push| {
        for self.each |a| {
            if prd(a) { push(*a); }
        }
    }
}

#[inline(always)]
pub pure fn map_to_vec<A,B,IA:BaseIter<A>>(self: &IA,
                                           op: fn(&A) -> B)
    -> ~[B] {
    do vec::build_sized_opt(self.size_hint()) |push| {
        for self.each |a| {
            push(op(a));
        }
    }
}

#[inline(always)]
pub pure fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(
    self: &IA, op: fn(&A) -> IB) -> ~[B] {
    do vec::build |push| {
        for self.each |a| {
            for op(a).each |&b| {
                push(b);
            }
        }
    }
}

#[inline(always)]
pub pure fn foldl<A,B,IA:BaseIter<A>>(self: &IA, b0: B,
                                      blk: fn(&B, &A) -> B)
    -> B {
    let mut b = b0;
    for self.each |a| {
        b = blk(&b, a);
    }
    b
}

#[inline(always)]
pub pure fn to_vec<A:Copy,IA:BaseIter<A>>(self: &IA) -> ~[A] {
    foldl::<A,~[A],IA>(self, ~[], |r, a| vec::append(copy (*r), ~[*a]))
}

#[inline(always)]
pub pure fn contains<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> bool {
    for self.each |a| {
        if *a == *x { return true; }
    }
    return false;
}

#[inline(always)]
pub pure fn count<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> uint {
    do foldl(self, 0) |count, value| {
        if *value == *x {
            *count + 1
        } else {
            *count
        }
    }
}

#[inline(always)]
pub pure fn position<A,IA:BaseIter<A>>(self: &IA, f: fn(&A) -> bool)
    -> Option<uint>
{
    let mut i = 0;
    for self.each |a| {
        if f(a) { return Some(i); }
        i += 1;
    }
    return None;
}

// note: 'rposition' would only make sense to provide with a bidirectional
// iter interface, such as would provide "reach" in addition to "each". As is,
// it would have to be implemented with foldr, which is too inefficient.

#[inline(always)]
pub pure fn repeat(times: uint, blk: fn() -> bool) {
    let mut i = 0;
    while i < times {
        if !blk() { break }
        i += 1;
    }
}

#[inline(always)]
pub pure fn min<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
    match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
        match a {
          &Some(ref a_) if *a_ < *b => {
             *(a)
          }
          _ => Some(*b)
        }
    } {
        Some(val) => val,
        None => fail!(~"min called on empty iterator")
    }
}

#[inline(always)]
pub pure fn max<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
    match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
        match a {
          &Some(ref a_) if *a_ > *b => {
              *(a)
          }
          _ => Some(*b)
        }
    } {
        Some(val) => val,
        None => fail!(~"max called on empty iterator")
    }
}

#[inline(always)]
pub pure fn find<A:Copy,IA:BaseIter<A>>(self: &IA,
                                   f: fn(&A) -> bool) -> Option<A> {
    for self.each |i| {
        if f(i) { return Some(*i) }
    }
    return None;
}

// Some functions for just building

/**
 * Builds a sequence by calling a provided function with an argument
 * function that pushes an element to the back of a sequence.
 *
 * # Arguments
 *
 * * builder - A function that will construct the sequence. It receives
 *             as an argument a function that will push an element
 *             onto the sequence being constructed.
 */
#[inline(always)]
pub pure fn build<A,B: Buildable<A>>(builder: fn(push: pure fn(A)))
    -> B {
    Buildable::build_sized(4, builder)
}

/**
 * Builds a sequence by calling a provided function with an argument
 * function that pushes an element to the back of the sequence.
 * This version takes an initial size for the sequence.
 *
 * # Arguments
 *
 * * size - An option, maybe containing initial size of the sequence
 *          to reserve.
 * * builder - A function that will construct the sequence. It receives
 *             as an argument a function that will push an element
 *             onto the sequence being constructed.
 */
#[inline(always)]
pub pure fn build_sized_opt<A,B: Buildable<A>>(
    size: Option<uint>,
    builder: fn(push: pure fn(A))) -> B {

    Buildable::build_sized(size.get_or_default(4), builder)
}

// Functions that combine iteration and building

/// Applies a function to each element of an iterable and returns the results.
#[inline(always)]
pub fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: &IT, f: fn(&T) -> U)
    -> BU {
    do build_sized_opt(v.size_hint()) |push| {
        for v.each() |elem| {
            push(f(elem));
        }
    }
}

/**
 * Creates and initializes a generic sequence from a function.
 *
 * Creates a generic sequence of size `n_elts` and initializes the elements
 * to the value returned by the function `op`.
 */
#[inline(always)]
pub pure fn from_fn<T,BT: Buildable<T>>(n_elts: uint,
                                        op: InitOp<T>) -> BT {
    do Buildable::build_sized(n_elts) |push| {
        let mut i: uint = 0u;
        while i < n_elts { push(op(i)); i += 1u; }
    }
}

/**
 * Creates and initializes a generic sequence with some elements.
 *
 * Creates an immutable vector of size `n_elts` and initializes the elements
 * to the value `t`.
 */
#[inline(always)]
pub pure fn from_elem<T:Copy,BT:Buildable<T>>(n_elts: uint,
                                                t: T) -> BT {
    do Buildable::build_sized(n_elts) |push| {
        let mut i: uint = 0;
        while i < n_elts { push(t); i += 1; }
    }
}

/// Appends two generic sequences.
#[inline(always)]
pub pure fn append<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(
    lhs: &IT, rhs: &IT) -> BT {
    let size_opt = lhs.size_hint().chain_ref(
        |sz1| rhs.size_hint().map(|sz2| *sz1+*sz2));
    do build_sized_opt(size_opt) |push| {
        for lhs.each |x| { push(*x); }
        for rhs.each |x| { push(*x); }
    }
}

/// Copies a generic sequence, possibly converting it to a different
/// type of sequence.
#[inline(always)]
pub pure fn copy_seq<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(
    v: &IT) -> BT {
    do build_sized_opt(v.size_hint()) |push| {
        for v.each |x| { push(*x); }
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::prelude::*;

#[derive(Debug, Copy, Clone)]
enum ShuffleOperation {
  DealIntoNewStack,
  CutNCards(isize),
  DealWithIncrement(usize)
}

fn get_input() -> std::io::Result<String> {
  let mut file = File::open("22.txt")?;
  let mut contents = String::new();
  file.read_to_string(&mut contents)?;

  Ok(contents)
}

fn parse_instructions(input: &str) -> impl Iterator<Item = ShuffleOperation> + Clone + '_ {
  input.lines()
  .filter_map(|line| {
    if line == "deal into new stack" {
      Some(ShuffleOperation::DealIntoNewStack)
    } else if &line[.."cut".len()] == "cut" {
      line["cut".len()..].trim().parse::<isize>().ok()
      .map(|n| ShuffleOperation::CutNCards(n))
    } else if &line[.."deal with increment".len()] == "deal with increment" {
      line["deal with increment".len()..].trim().parse::<usize>().ok()
      .map(|n| ShuffleOperation::DealWithIncrement(n))
    } else {
      None
    }
  })
}

fn multiplicative_inverse(modulo: usize, n: usize) -> usize {
  let mut t = (0, 1);
  let mut r = (modulo as isize, n as isize);

  while r.1 != 0 {
    let (old_t, new_t) = t;
    let (old_r, new_r) = r;
    let quotient = old_r / new_r;

    t = (new_t, old_t - quotient * new_t);
    r = (new_r, old_r - quotient * new_r);
  }

  if t.0 < 0 { modulo - ((-t.0) as usize) } else { t.0 as usize }
}

fn mod_multiply(a: usize, b: usize, m: usize) -> usize {
  ((a as u128 * b as u128) % m as u128) as usize
}

fn parameters_multiply((a, b): (usize, usize), (c, d): (usize, usize), m: usize) -> (usize, usize) {
  (mod_multiply(a, c, m), (mod_multiply(a, d, m) + b) % m)
}

fn parameters_pow(parameters: (usize, usize), p: usize, m: usize) -> (usize, usize) {
  if p == 0 {
    (1, 0)
  } else if p == 1 {
    parameters
  } else if p % 2 == 1 {
    parameters_multiply(parameters, parameters_pow(parameters, p - 1, m), m)
  } else {
    let x = parameters_pow(parameters, p / 2, m);
    parameters_multiply(x, x, m)
  }
}

fn calculate_shuffle_parameters<I>(count: usize, instructions: I) -> (usize, usize)
where I: Iterator<Item = ShuffleOperation> {
  instructions
  .map(|instruction| match instruction {
    ShuffleOperation::DealIntoNewStack => (count - 1, count - 1),
    ShuffleOperation::CutNCards(n) => (1, (count as isize - n) as usize % count),
    ShuffleOperation::DealWithIncrement(n) => (n % count, 0)
  })
  .fold((1, 0), |acc, parameters| {
    parameters_multiply(parameters, acc, count)
  })
}

fn track_card_position((a, b): (usize, usize), card: usize, count: usize) -> usize {
  (mod_multiply(a, card, count) + b) % count
}

fn invert_instructions(count: usize, instructions: &[ShuffleOperation]) -> Vec<ShuffleOperation> {
  let mut inverse_instructions = instructions.to_vec();

  inverse_instructions.reverse();
  inverse_instructions.into_iter()
  .map(|instruction| match instruction {
    ShuffleOperation::DealIntoNewStack => ShuffleOperation::DealIntoNewStack,
    ShuffleOperation::CutNCards(n) => ShuffleOperation::CutNCards(-n),
    ShuffleOperation::DealWithIncrement(n) => {
      let inverse_n = multiplicative_inverse(count, n);
      ShuffleOperation::DealWithIncrement(inverse_n)
    }
  })
  .collect()
}

fn main() {
  let input = get_input().unwrap();

  let instructions = parse_instructions(&input).collect::<Vec<_>>();
  let count = 10007;
  let shuffle_parameters = calculate_shuffle_parameters(count, instructions.iter().cloned());
  let position = track_card_position(shuffle_parameters, 2019, count);

  println!("Part 1: {}", position);

  let times = 101741582076661;
  let count = 119315717514047;
  let inverse_instructions = invert_instructions(count, &instructions);
  let shuffle_parameters = calculate_shuffle_parameters(count, inverse_instructions.iter().cloned());
  let shuffle_parameters = parameters_pow(shuffle_parameters, times, count);
  let card = track_card_position(shuffle_parameters, 2020, count);

  println!("Part 2: {}", card);
}
<commit_msg>Add full extended_gcd algorithm<commit_after>use std::fs::File;
use std::io::prelude::*;

#[derive(Debug, Copy, Clone)]
enum ShuffleOperation {
  DealIntoNewStack,
  CutNCards(isize),
  DealWithIncrement(usize)
}

fn get_input() -> std::io::Result<String> {
  let mut file = File::open("22.txt")?;
  let mut contents = String::new();
  file.read_to_string(&mut contents)?;

  Ok(contents)
}

fn parse_instructions(input: &str) -> Vec<ShuffleOperation> {
  input.lines()
  .filter_map(|line| {
    if line == "deal into new stack" {
      Some(ShuffleOperation::DealIntoNewStack)
    } else if &line[.."cut".len()] == "cut" {
      line["cut".len()..].trim().parse::<isize>().ok()
      .map(|n| ShuffleOperation::CutNCards(n))
    } else if &line[.."deal with increment".len()] == "deal with increment" {
      line["deal with increment".len()..].trim().parse::<usize>().ok()
      .map(|n| ShuffleOperation::DealWithIncrement(n))
    } else {
      None
    }
  })
  .collect()
}

fn extended_gcd(a: isize, b: isize) -> (isize, isize, isize) {
  let mut r = (a, b);
  let mut s = (1, 0);
  let mut t = (0, 1);

  while r.1 != 0 {
    let (old_r, new_r) = r;
    let (old_s, new_s) = s;
    let (old_t, new_t) = t;
    let quotient = old_r / new_r;

    s = (new_s, old_s - quotient * new_s);
    r = (new_r, old_r - quotient * new_r);
    t = (new_t, old_t - quotient * new_t);
  }

  (s.0, t.0, r.0)
}

fn mod_multiply(a: usize, b: usize, m: usize) -> usize {
  ((a as u128 * b as u128) % m as u128) as usize
}

fn parameters_multiply((a, b): (usize, usize), (c, d): (usize, usize), m: usize) -> (usize, usize) {
  (mod_multiply(a, c, m), (mod_multiply(a, d, m) + b) % m)
}

fn parameters_pow(parameters: (usize, usize), p: usize, m: usize) -> (usize, usize) {
  if p == 0 {
    (1, 0)
  } else if p == 1 {
    parameters
  } else if p % 2 == 1 {
    parameters_multiply(parameters, parameters_pow(parameters, p - 1, m), m)
  } else {
    let x = parameters_pow(parameters, p / 2, m);
    parameters_multiply(x, x, m)
  }
}

fn calculate_shuffle_parameters<I>(count: usize, instructions: I) -> (usize, usize)
where I: Iterator<Item = ShuffleOperation> {
  instructions
  .map(|instruction| match instruction {
    ShuffleOperation::DealIntoNewStack => (count - 1, count - 1),
    ShuffleOperation::CutNCards(n) => (1, (count as isize - n) as usize % count),
    ShuffleOperation::DealWithIncrement(n) => (n % count, 0)
  })
  .fold((1, 0), |acc, parameters| {
    parameters_multiply(parameters, acc, count)
  })
}

fn track_card_position((a, b): (usize, usize), card: usize, count: usize) -> usize {
  (mod_multiply(a, card, count) + b) % count
}

fn invert_instructions(count: usize, instructions: &[ShuffleOperation]) -> Vec<ShuffleOperation> {
  let mut inverse_instructions = instructions.to_vec();

  inverse_instructions.reverse();
  inverse_instructions.into_iter()
  .map(|instruction| match instruction {
    ShuffleOperation::DealIntoNewStack => ShuffleOperation::DealIntoNewStack,
    ShuffleOperation::CutNCards(n) => ShuffleOperation::CutNCards(-n),
    ShuffleOperation::DealWithIncrement(n) => {
      let (_, inverse_n, _) = extended_gcd(count as isize, n as isize);
      let inverse_n = if inverse_n < 0 { count - (-inverse_n as usize) } else { inverse_n as usize };
      ShuffleOperation::DealWithIncrement(inverse_n)
    }
  })
  .collect()
}

fn main() {
  let input = get_input().unwrap();

  let instructions = parse_instructions(&input);
  let count = 10007;
  let shuffle_parameters = calculate_shuffle_parameters(count, instructions.iter().cloned());
  let position = track_card_position(shuffle_parameters, 2019, count);

  println!("Part 1: {}", position);

  let times = 101741582076661;
  let count = 119315717514047;
  let inverse_instructions = invert_instructions(count, &instructions);
  let shuffle_parameters = calculate_shuffle_parameters(count, inverse_instructions.iter().cloned());
  let shuffle_parameters = parameters_pow(shuffle_parameters, times, count);
  let card = track_card_position(shuffle_parameters, 2020, count);

  println!("Part 2: {}", card);
}
<|endoftext|>


<commit_before>use std::ffi::OsStr;
use walkdir::WalkDir;

use std::fs::File;
use std::io::prelude::*;

// The maximum length allowed for stderr files.
//
// We limit this because small files are easier to deal with than bigger files.
const LIMIT: usize = 320;

pub fn check() {
    let stderr_files = stderr_files();
    let exceeding_files = exceeding_stderr_files(stderr_files).collect::<Vec<String>>();

    if !exceeding_files.is_empty() {
        eprintln!("Error: stderr files exceeding limit of {} lines:", LIMIT);
        for path in exceeding_files {
            println!("{}", path);
        }
        std::process::exit(1);
    }
}

fn exceeding_stderr_files(files: impl Iterator<Item = walkdir::DirEntry>) -> impl Iterator<Item = String> {
    files.filter_map(|file| {
        let path = file.path().to_str().expect("Could not convert path to str").to_string();
        let linecount = count_linenumbers(&path);
        if linecount > LIMIT {
            Some(path)
        } else {
            None
        }
    })
}

fn stderr_files() -> impl Iterator<Item = walkdir::DirEntry> {
    // We use `WalkDir` instead of `fs::read_dir` here in order to recurse into subdirectories.
    WalkDir::new("../tests/ui")
        .into_iter()
        .filter_map(std::result::Result::ok)
        .filter(|f| f.path().extension() == Some(OsStr::new("stderr")))
}

fn count_linenumbers(filepath: &str) -> usize {
    if let Ok(mut file) = File::open(filepath) {
        let mut content = String::new();
        file.read_to_string(&mut content).expect("Failed to read file?");
        content.lines().count()
    } else {
        0
    }
}
<commit_msg>Decrease maximum length for stderr files<commit_after>use std::ffi::OsStr;
use walkdir::WalkDir;

use std::fs::File;
use std::io::prelude::*;

// The maximum length allowed for stderr files.
//
// We limit this because small files are easier to deal with than bigger files.
const LIMIT: usize = 275;

pub fn check() {
    let stderr_files = stderr_files();
    let exceeding_files = exceeding_stderr_files(stderr_files).collect::<Vec<String>>();

    if !exceeding_files.is_empty() {
        eprintln!("Error: stderr files exceeding limit of {} lines:", LIMIT);
        for path in exceeding_files {
            println!("{}", path);
        }
        std::process::exit(1);
    }
}

fn exceeding_stderr_files(files: impl Iterator<Item = walkdir::DirEntry>) -> impl Iterator<Item = String> {
    files.filter_map(|file| {
        let path = file.path().to_str().expect("Could not convert path to str").to_string();
        let linecount = count_linenumbers(&path);
        if linecount > LIMIT {
            Some(path)
        } else {
            None
        }
    })
}

fn stderr_files() -> impl Iterator<Item = walkdir::DirEntry> {
    // We use `WalkDir` instead of `fs::read_dir` here in order to recurse into subdirectories.
    WalkDir::new("../tests/ui")
        .into_iter()
        .filter_map(std::result::Result::ok)
        .filter(|f| f.path().extension() == Some(OsStr::new("stderr")))
}

fn count_linenumbers(filepath: &str) -> usize {
    if let Ok(mut file) = File::open(filepath) {
        let mut content = String::new();
        file.read_to_string(&mut content).expect("Failed to read file?");
        content.lines().count()
    } else {
        0
    }
}
<|endoftext|>


<commit_before>/*
Module: task

Task management.

An executing Rust program consists of a tree of tasks, each with their own
stack, and sole ownership of their allocated heap data. Tasks communicate
with each other using ports and channels.

When a task fails, that failure will propagate to its parent (the task
that spawned it) and the parent will fail as well. The reverse is not
true: when a parent task fails its children will continue executing. When
the root (main) task fails, all tasks fail, and then so does the entire
process.

A task may remove itself from this failure propagation mechanism by
calling the <unsupervise> function, after which failure will only
result in the termination of that task.

Tasks may execute in parallel and are scheduled automatically by the runtime.

Example:

> spawn("Hello, World", fn (&&msg: str) {
>   log msg;
> });

*/
import cast = unsafe::reinterpret_cast;
import comm;
import option::{some, none};
import option = option::t;
import ptr;

export task;
export joinable_task;
export sleep;
export yield;
export task_notification;
export join;
export unsupervise;
export pin;
export unpin;
export task_result;
export tr_success;
export tr_failure;
export get_task;
export spawn;
export spawn_notify;
export spawn_joinable;

#[abi = "rust-intrinsic"]
native mod rusti {
    // these must run on the Rust stack so that they can swap stacks etc:
    fn task_sleep(task: *rust_task, time_in_us: uint, &killed: bool);
}

#[link_name = "rustrt"]
#[abi = "cdecl"]
native mod rustrt {
    // these can run on the C stack:
    fn pin_task();
    fn unpin_task();
    fn get_task_id() -> task_id;
    fn rust_get_task() -> *rust_task;

    fn new_task() -> task_id;
    fn drop_task(task_id: *rust_task);
    fn get_task_pointer(id: task_id) -> *rust_task;

    fn migrate_alloc(alloc: *u8, target: task_id);

    fn start_task(id: task, closure: *u8);

}

/* Section: Types */

type rust_task =
    {id: task,
     mutable notify_enabled: int,
     mutable notify_chan: comm::chan<task_notification>,
     mutable stack_ptr: *u8};

resource rust_task_ptr(task: *rust_task) { rustrt::drop_task(task); }

type task_id = int;

/*
Type: task

A handle to a task
*/
type task = task_id;

/*
Type: joinable_task

A task that sends notification upon termination
*/
type joinable_task = (task, comm::port<task_notification>);

/*
Tag: task_result

Indicates the manner in which a task exited
*/
tag task_result {
    /* Variant: tr_success */
    tr_success;
    /* Variant: tr_failure */
    tr_failure;
}

/*
Tag: task_notification

Message sent upon task exit to indicate normal or abnormal termination
*/
tag task_notification {
    /* Variant: exit */
    exit(task, task_result);
}

/* Section: Operations */

/*
Type: get_task

Retreives a handle to the currently executing task
*/
fn get_task() -> task { rustrt::get_task_id() }

/*
Function: sleep

Hints the scheduler to yield this task for a specified ammount of time.

Parameters:

time_in_us - maximum number of microseconds to yield control for
*/
fn sleep(time_in_us: uint) {
    let task = rustrt::rust_get_task();
    let killed = false;
    // FIXME: uncomment this when extfmt is moved to core
    // in a snapshot.
    // log #fmt("yielding for %u us", time_in_us);
    rusti::task_sleep(task, time_in_us, killed);
    if killed {
        fail "killed";
    }
}

/*
Function: yield

Yield control to the task scheduler

The scheduler may schedule another task to execute.
*/
fn yield() { sleep(1u) }

/*
Function: join

Wait for a child task to exit

The child task must have been spawned with <spawn_joinable>, which
produces a notification port that the child uses to communicate its
exit status.

Returns:

A task_result indicating whether the task terminated normally or failed
*/
fn join(task_port: joinable_task) -> task_result {
    let (id, port) = task_port;
    alt comm::recv::<task_notification>(port) {
      exit(_id, res) {
        if _id == id {
            ret res
        } else {
            // FIXME: uncomment this when extfmt is moved to core
            // in a snapshot.
            // fail #fmt["join received id %d, expected %d", _id, id]
            fail;
        }
      }
    }
}

/*
Function: unsupervise

Detaches this task from its parent in the task tree

An unsupervised task will not propagate its failure up the task tree
*/
fn unsupervise() { ret sys::unsupervise(); }

/*
Function: pin

Pins the current task and future child tasks to a single scheduler thread
*/
fn pin() { rustrt::pin_task(); }

/*
Function: unpin

Unpin the current task and future child tasks
*/
fn unpin() { rustrt::unpin_task(); }

/*
Function: spawn

Creates and executes a new child task

Sets up a new task with its own call stack and schedules it to be executed.
Upon execution the new task will call function `f` with the provided
argument `data`.

Function `f` is a bare function, meaning it may not close over any data, as do
shared functions (fn@) and lambda blocks. `data` must be a uniquely owned
type; it is moved into the new task and thus can no longer be accessed
locally.

Parameters:

data - A unique-type value to pass to the new task
f - A function to execute in the new task

Returns:

A handle to the new task
*/
fn spawn<send T>(-data: T, f: fn(T)) -> task {
    spawn_inner(data, f, none)
}

/*
Function: spawn_notify

Create and execute a new child task, requesting notification upon its
termination

Immediately before termination, either on success or failure, the spawned
task will send a <task_notification> message on the provided channel.
*/
fn spawn_notify<send T>(-data: T, f: fn(T),
                         notify: comm::chan<task_notification>) -> task {
    spawn_inner(data, f, some(notify))
}

/*
Function: spawn_joinable

Create and execute a task which can later be joined with the <join> function

This is a convenience wrapper around spawn_notify which, when paired
with <join> can be easily used to spawn a task then wait for it to
complete.
*/
fn spawn_joinable<send T>(-data: T, f: fn(T)) -> joinable_task {
    let p = comm::port::<task_notification>();
    let id = spawn_notify(data, f, comm::chan::<task_notification>(p));
    ret (id, p);
}

// FIXME: To transition from the unsafe spawn that spawns a shared closure to
// the safe spawn that spawns a bare function we're going to write
// barefunc-spawn on top of unsafe-spawn.  Sadly, bind does not work reliably
// enough to suite our needs (#1034, probably others yet to be discovered), so
// we're going to copy the bootstrap data into a unique pointer, cast it to an
// unsafe pointer then wrap up the bare function and the unsafe pointer in a
// shared closure to spawn.
//
// After the transition this should all be rewritten.

fn spawn_inner<send T>(-data: T, f: fn(T),
                          notify: option<comm::chan<task_notification>>)
    -> task unsafe {

    fn wrapper<send T>(data: *u8, f: fn(T)) unsafe {
        let data: ~T = unsafe::reinterpret_cast(data);
        f(*data);
    }

    let data = ~data;
    let dataptr: *u8 = unsafe::reinterpret_cast(data);
    unsafe::leak(data);
    let wrapped = bind wrapper(dataptr, f);
    ret unsafe_spawn_inner(wrapped, notify);
}

// FIXME: This is the old spawn function that spawns a shared closure.
// It is a hack and needs to be rewritten.
fn unsafe_spawn_inner(-thunk: fn@(),
                      notify: option<comm::chan<task_notification>>) ->
   task unsafe {
    let id = rustrt::new_task();

    let raw_thunk: {code: uint, env: uint} = cast(thunk);

    // set up the task pointer
    let task_ptr <- rust_task_ptr(rustrt::get_task_pointer(id));

    assert (ptr::null() != (**task_ptr).stack_ptr);

    // copy the thunk from our stack to the new stack
    let sp: uint = cast((**task_ptr).stack_ptr);
    let ptrsize = sys::size_of::<*u8>();
    let thunkfn: *mutable uint = cast(sp - ptrsize * 2u);
    let thunkenv: *mutable uint = cast(sp - ptrsize);
    *thunkfn = cast(raw_thunk.code);;
    *thunkenv = cast(raw_thunk.env);;
    // align the stack to 16 bytes
    (**task_ptr).stack_ptr = cast(sp - ptrsize * 4u);

    // set up notifications if they are enabled.
    alt notify {
      some(c) {
        (**task_ptr).notify_enabled = 1;
        (**task_ptr).notify_chan = c;
      }
      none { }
    }

    // give the thunk environment's allocation to the new task
    rustrt::migrate_alloc(cast(raw_thunk.env), id);
    rustrt::start_task(id, cast(thunkfn));
    // don't cleanup the thunk in this task
    unsafe::leak(thunk);
    ret id;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>libcore: Remove stack alignment from task spawning<commit_after>/*
Module: task

Task management.

An executing Rust program consists of a tree of tasks, each with their own
stack, and sole ownership of their allocated heap data. Tasks communicate
with each other using ports and channels.

When a task fails, that failure will propagate to its parent (the task
that spawned it) and the parent will fail as well. The reverse is not
true: when a parent task fails its children will continue executing. When
the root (main) task fails, all tasks fail, and then so does the entire
process.

A task may remove itself from this failure propagation mechanism by
calling the <unsupervise> function, after which failure will only
result in the termination of that task.

Tasks may execute in parallel and are scheduled automatically by the runtime.

Example:

> spawn("Hello, World", fn (&&msg: str) {
>   log msg;
> });

*/
import cast = unsafe::reinterpret_cast;
import comm;
import option::{some, none};
import option = option::t;
import ptr;

export task;
export joinable_task;
export sleep;
export yield;
export task_notification;
export join;
export unsupervise;
export pin;
export unpin;
export task_result;
export tr_success;
export tr_failure;
export get_task;
export spawn;
export spawn_notify;
export spawn_joinable;

#[abi = "rust-intrinsic"]
native mod rusti {
    // these must run on the Rust stack so that they can swap stacks etc:
    fn task_sleep(task: *rust_task, time_in_us: uint, &killed: bool);
}

#[link_name = "rustrt"]
#[abi = "cdecl"]
native mod rustrt {
    // these can run on the C stack:
    fn pin_task();
    fn unpin_task();
    fn get_task_id() -> task_id;
    fn rust_get_task() -> *rust_task;

    fn new_task() -> task_id;
    fn drop_task(task_id: *rust_task);
    fn get_task_pointer(id: task_id) -> *rust_task;

    fn migrate_alloc(alloc: *u8, target: task_id);

    fn start_task(id: task, closure: *u8);

}

/* Section: Types */

type rust_task =
    {id: task,
     mutable notify_enabled: int,
     mutable notify_chan: comm::chan<task_notification>,
     mutable stack_ptr: *u8};

resource rust_task_ptr(task: *rust_task) { rustrt::drop_task(task); }

type task_id = int;

/*
Type: task

A handle to a task
*/
type task = task_id;

/*
Type: joinable_task

A task that sends notification upon termination
*/
type joinable_task = (task, comm::port<task_notification>);

/*
Tag: task_result

Indicates the manner in which a task exited
*/
tag task_result {
    /* Variant: tr_success */
    tr_success;
    /* Variant: tr_failure */
    tr_failure;
}

/*
Tag: task_notification

Message sent upon task exit to indicate normal or abnormal termination
*/
tag task_notification {
    /* Variant: exit */
    exit(task, task_result);
}

/* Section: Operations */

/*
Type: get_task

Retreives a handle to the currently executing task
*/
fn get_task() -> task { rustrt::get_task_id() }

/*
Function: sleep

Hints the scheduler to yield this task for a specified ammount of time.

Parameters:

time_in_us - maximum number of microseconds to yield control for
*/
fn sleep(time_in_us: uint) {
    let task = rustrt::rust_get_task();
    let killed = false;
    // FIXME: uncomment this when extfmt is moved to core
    // in a snapshot.
    // log #fmt("yielding for %u us", time_in_us);
    rusti::task_sleep(task, time_in_us, killed);
    if killed {
        fail "killed";
    }
}

/*
Function: yield

Yield control to the task scheduler

The scheduler may schedule another task to execute.
*/
fn yield() { sleep(1u) }

/*
Function: join

Wait for a child task to exit

The child task must have been spawned with <spawn_joinable>, which
produces a notification port that the child uses to communicate its
exit status.

Returns:

A task_result indicating whether the task terminated normally or failed
*/
fn join(task_port: joinable_task) -> task_result {
    let (id, port) = task_port;
    alt comm::recv::<task_notification>(port) {
      exit(_id, res) {
        if _id == id {
            ret res
        } else {
            // FIXME: uncomment this when extfmt is moved to core
            // in a snapshot.
            // fail #fmt["join received id %d, expected %d", _id, id]
            fail;
        }
      }
    }
}

/*
Function: unsupervise

Detaches this task from its parent in the task tree

An unsupervised task will not propagate its failure up the task tree
*/
fn unsupervise() { ret sys::unsupervise(); }

/*
Function: pin

Pins the current task and future child tasks to a single scheduler thread
*/
fn pin() { rustrt::pin_task(); }

/*
Function: unpin

Unpin the current task and future child tasks
*/
fn unpin() { rustrt::unpin_task(); }

/*
Function: spawn

Creates and executes a new child task

Sets up a new task with its own call stack and schedules it to be executed.
Upon execution the new task will call function `f` with the provided
argument `data`.

Function `f` is a bare function, meaning it may not close over any data, as do
shared functions (fn@) and lambda blocks. `data` must be a uniquely owned
type; it is moved into the new task and thus can no longer be accessed
locally.

Parameters:

data - A unique-type value to pass to the new task
f - A function to execute in the new task

Returns:

A handle to the new task
*/
fn spawn<send T>(-data: T, f: fn(T)) -> task {
    spawn_inner(data, f, none)
}

/*
Function: spawn_notify

Create and execute a new child task, requesting notification upon its
termination

Immediately before termination, either on success or failure, the spawned
task will send a <task_notification> message on the provided channel.
*/
fn spawn_notify<send T>(-data: T, f: fn(T),
                         notify: comm::chan<task_notification>) -> task {
    spawn_inner(data, f, some(notify))
}

/*
Function: spawn_joinable

Create and execute a task which can later be joined with the <join> function

This is a convenience wrapper around spawn_notify which, when paired
with <join> can be easily used to spawn a task then wait for it to
complete.
*/
fn spawn_joinable<send T>(-data: T, f: fn(T)) -> joinable_task {
    let p = comm::port::<task_notification>();
    let id = spawn_notify(data, f, comm::chan::<task_notification>(p));
    ret (id, p);
}

// FIXME: To transition from the unsafe spawn that spawns a shared closure to
// the safe spawn that spawns a bare function we're going to write
// barefunc-spawn on top of unsafe-spawn.  Sadly, bind does not work reliably
// enough to suite our needs (#1034, probably others yet to be discovered), so
// we're going to copy the bootstrap data into a unique pointer, cast it to an
// unsafe pointer then wrap up the bare function and the unsafe pointer in a
// shared closure to spawn.
//
// After the transition this should all be rewritten.

fn spawn_inner<send T>(-data: T, f: fn(T),
                          notify: option<comm::chan<task_notification>>)
    -> task unsafe {

    fn wrapper<send T>(data: *u8, f: fn(T)) unsafe {
        let data: ~T = unsafe::reinterpret_cast(data);
        f(*data);
    }

    let data = ~data;
    let dataptr: *u8 = unsafe::reinterpret_cast(data);
    unsafe::leak(data);
    let wrapped = bind wrapper(dataptr, f);
    ret unsafe_spawn_inner(wrapped, notify);
}

// FIXME: This is the old spawn function that spawns a shared closure.
// It is a hack and needs to be rewritten.
fn unsafe_spawn_inner(-thunk: fn@(),
                      notify: option<comm::chan<task_notification>>) ->
   task unsafe {
    let id = rustrt::new_task();

    let raw_thunk: {code: uint, env: uint} = cast(thunk);

    // set up the task pointer
    let task_ptr <- rust_task_ptr(rustrt::get_task_pointer(id));

    assert (ptr::null() != (**task_ptr).stack_ptr);

    // copy the thunk from our stack to the new stack
    let sp: uint = cast((**task_ptr).stack_ptr);
    let ptrsize = sys::size_of::<*u8>();
    let thunkfn: *mutable uint = cast(sp - ptrsize * 2u);
    let thunkenv: *mutable uint = cast(sp - ptrsize);
    *thunkfn = cast(raw_thunk.code);;
    *thunkenv = cast(raw_thunk.env);;
    // Advance the stack pointer. No need to align because
    // the native code will do that for us
    (**task_ptr).stack_ptr = cast(sp - ptrsize * 2u);

    // set up notifications if they are enabled.
    alt notify {
      some(c) {
        (**task_ptr).notify_enabled = 1;
        (**task_ptr).notify_chan = c;
      }
      none { }
    }

    // give the thunk environment's allocation to the new task
    rustrt::migrate_alloc(cast(raw_thunk.env), id);
    rustrt::start_task(id, cast(thunkfn));
    // don't cleanup the thunk in this task
    unsafe::leak(thunk);
    ret id;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>use bindings::*;
use compile::Compile;
use function::ABI;
use libc::c_uint;
use std::kinds::marker::{
    ContravariantLifetime,
    Managed
};
use std::mem::transmute;
use std::str::raw::from_c_str;
use std::c_str::ToCStr;
use util::NativeRef;
#[repr(i32)]
#[deriving(Eq, PartialEq, Show)]
pub enum TypeKind {
    Void         = 0,
    SByte        = 1,
    UByte        = 2,
    Short        = 3,
    UShort       = 4,
    Int          = 5,
    UInt         = 6,
    NInt         = 7,
    NUInt        = 8,
    Long         = 9,
    ULong        = 10,
    Float32      = 11,
    Float64      = 12,
    NFloat       = 13,
    Struct       = 14,
    Union        = 15,
    Signature    = 16,
    Pointer      = 17,
    FirstTagged  = 32,
    SysBool      = 10009,
    SysChar      = 10010
}
/// A single field of a struct
pub struct Field<'a> {
    /// The index of the field
    pub index: c_uint,
    _type: jit_type_t,
    marker: ContravariantLifetime<'a>
}
impl<'a> Field<'a> {
    #[inline]
    /// Get the field's name or none if it lacks one
    pub fn get_name(&self) -> Option<String> {
        unsafe {
            let c_name = jit_type_get_name(self._type, self.index);
            if c_name.is_null() {
                None
            } else {
                Some(from_c_str(c_name))
            }
        }
    }
    #[inline(always)]
    /// Get the type of the field
    pub fn get_type(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_get_field(self._type, self.index))
        }
    }
    #[inline(always)]
    /// Get the offset of the field
    pub fn get_offset(&self) -> uint {
        unsafe {
            jit_type_get_offset(self._type, self.index) as uint
        }
    }
}
/// A type field iterator
pub struct Fields<'a> {
    _type: jit_type_t,
    index: c_uint,
    length: c_uint,
    marker: ContravariantLifetime<'a>
}
impl<'a> Fields<'a> {
    #[inline(always)]
    fn new(ty:Type) -> Fields<'a> {
        unsafe {
            Fields {
                _type: ty.as_ptr(),
                index: 0 as c_uint,
                length: jit_type_num_fields(ty.as_ptr()),
                marker: ContravariantLifetime::<'a>
            }
        }
    }
}
impl<'a> Iterator<Field<'a>> for Fields<'a> {
    fn next(&mut self) -> Option<Field<'a>> {
        let index = self.index;
        self.index += 1;
        if index < self.length {
            Some(Field {
                _type: self._type.clone(),
                index: index,
                marker: ContravariantLifetime::<'a>
            })
        } else {
            None
        }
    }
    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        ((self.length - self.index) as uint, None)
    }
    #[inline]
    fn count(&mut self) -> uint {
        let count = self.length - self.index;
        self.index = self.length;
        count as uint
    }
    #[inline]
    fn nth(&mut self, n:uint) -> Option<Field<'a>> {
        self.index += n as c_uint;
        self.next()
    }
}
pub struct Params<'a> {
    _type: jit_type_t,
    index: c_uint,
    length: c_uint,
    marker: ContravariantLifetime<'a>
}
impl<'a> Params<'a> {
    #[inline(always)]
    fn new(ty:Type) -> Params<'a> {
        unsafe {
            Params {
                _type: ty.as_ptr(),
                index: 0 as c_uint,
                length: jit_type_num_params(ty.as_ptr()),
                marker: ContravariantLifetime::<'a>
            }
        }
    }
}
impl<'a> Iterator<Type> for Params<'a> {
    fn next(&mut self) -> Option<Type> {
        let index = self.index;
        self.index += 1;
        if index < self.length {
            Some(unsafe {
                NativeRef::from_ptr(jit_type_get_param(self._type, index))
            })
        } else {
            None
        }
    }
    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        ((self.length - self.index) as uint, None)
    }
    #[inline]
    fn count(&mut self) -> uint {
        let count = self.length - self.index;
        self.index = self.length;
        count as uint
    }
    #[inline]
    fn nth(&mut self, n:uint) -> Option<Type> {
        self.index += n as c_uint;
        self.next()
    }
}
/// An object that represents a native system type.
/// Each `Type` represents a basic system type, be it a primitive, a struct, a
/// union, a pointer, or a function signature. The library uses this information
/// to lay out values in memory.
#[deriving(PartialEq)]
pub struct Type {
    _type: jit_type_t,
    marker: Managed
}
impl NativeRef for Type {
    #[inline(always)]
    unsafe fn as_ptr(&self) -> jit_type_t {
        self._type
    }
    #[inline(always)]
    unsafe fn from_ptr(ptr:jit_type_t) -> Type {
        Type {
            _type: ptr,
            marker: Managed
        }
    }
}
impl Clone for Type {
    #[inline]
    /// Make a copy of the type descriptor by increasing its reference count.
    fn clone(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_copy(self.as_ptr()))
        }
    }
}
#[unsafe_destructor]
impl Drop for Type {
    #[inline(always)]
    /// Free a type descriptor by decreasing its reference count.
    /// This function is safe to use on pre-defined types, which are never
    /// actually freed.
    fn drop(&mut self) {
        unsafe {
            jit_type_free(self.as_ptr());
        }
    }
}
impl Type {
    /// Create a type descriptor for a function signature.
    pub fn create_signature(abi: ABI, return_type: Type, params: &mut [Type]) -> Type {
        unsafe {
            let mut native_params:Vec<jit_type_t> = params.iter().map(|param| param.as_ptr()).collect();
            let signature = jit_type_create_signature(abi as jit_abi_t, return_type.as_ptr(), native_params.as_mut_ptr(), params.len() as c_uint, 1);
            NativeRef::from_ptr(signature)
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a structure.
    pub fn create_struct(fields: &mut [Type]) -> Type {
        unsafe {
            let mut native_fields:Vec<_> = fields.iter().map(|field| field.as_ptr()).collect();
            NativeRef::from_ptr(jit_type_create_struct(native_fields.as_mut_ptr(), fields.len() as c_uint, 1))
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a union.
    pub fn create_union(fields: &mut [Type]) -> Type {
        unsafe {
            let mut native_fields:Vec<_> = fields.iter().map(|field| field.as_ptr()).collect();
            NativeRef::from_ptr(jit_type_create_union(native_fields.as_mut_ptr(), fields.len() as c_uint, 1))
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a pointer to another type.
    pub fn create_pointer(pointee: Type) -> Type {
        unsafe {
            let ptr = jit_type_create_pointer(pointee.as_ptr(), 1);
            NativeRef::from_ptr(ptr)
        }
    }
    #[inline(always)]
    /// Get the size of this type in bytes.
    pub fn get_size(&self) -> uint {
        unsafe {
            jit_type_get_size(self.as_ptr()) as uint
        }
    }
    #[inline]
    /// Get a value that indicates the kind of this type. This allows
    /// callers to quickly classify a type to determine how it should
    /// be handled further.
    pub fn get_kind(&self) -> TypeKind {
        unsafe {
            transmute(jit_type_get_kind(self.as_ptr()))
        }
    }
    #[inline(always)]
    /// Get the type that is referred to by this pointer type.
    pub fn get_ref(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_get_ref(self.as_ptr()))
        }
    }
    /// Set the field or parameter names of this type.
    pub fn set_names<T:ToCStr>(&self, names:&[T]) -> bool {
        unsafe {
            let native_names : Vec<*const i8> = names.iter().map(|name| name.to_c_str().unwrap()).collect();
            jit_type_set_names(self.as_ptr(), native_names.as_ptr() as *mut *mut i8, names.len() as u32) != 0
        }
    }
    #[inline(always)]
    /// Iterator over the type's fields
    pub fn fields<'a>(&'a self) -> Fields<'a> {
        Fields::new(self.clone())
    }
    #[inline(always)]
    /// Iterator over the function signature's parameters
    pub fn params<'a>(&'a self) -> Params<'a> {
        Params::new(self.clone())
    }
    #[inline]
    /// Find the field/parameter index for a particular name.
    pub fn find_name<'b, T:ToCStr>(&'b self, name:T) -> Field<'b> {
        name.with_c_str(|c_name| unsafe {
            Field {
                index: jit_type_find_name(self.as_ptr(), c_name),
                _type: self.as_ptr(),
                marker: ContravariantLifetime::<'b>
            }
        })
    }
    #[inline(always)]
    /// Check if this is a pointer
    pub fn is_pointer(&self) -> bool {
        unsafe {
            jit_type_is_pointer(self.as_ptr()) != 0
        }
    }
}
#[inline(always)]
/// Get the Rust type given as a type descriptor
pub fn get<T:Compile>() -> Type {
    Compile::jit_type(None::<T>)
}<commit_msg>Implement PartialEq for Field<commit_after>use bindings::*;
use compile::Compile;
use function::ABI;
use libc::c_uint;
use std::kinds::marker::{
    ContravariantLifetime,
    Managed
};
use std::mem::transmute;
use std::str::raw::from_c_str;
use std::c_str::ToCStr;
use util::NativeRef;
#[repr(i32)]
#[deriving(Eq, PartialEq, Show)]
pub enum TypeKind {
    Void         = 0,
    SByte        = 1,
    UByte        = 2,
    Short        = 3,
    UShort       = 4,
    Int          = 5,
    UInt         = 6,
    NInt         = 7,
    NUInt        = 8,
    Long         = 9,
    ULong        = 10,
    Float32      = 11,
    Float64      = 12,
    NFloat       = 13,
    Struct       = 14,
    Union        = 15,
    Signature    = 16,
    Pointer      = 17,
    FirstTagged  = 32,
    SysBool      = 10009,
    SysChar      = 10010
}
/// A single field of a struct
pub struct Field<'a> {
    /// The index of the field
    pub index: c_uint,
    _type: jit_type_t,
    marker: ContravariantLifetime<'a>
}
impl<'a> PartialEq for Field<'a> {
    fn eq(&self, other:&Field<'a>) -> bool {
        self.index == other.index && self._type == other._type
    }
}
impl<'a> Field<'a> {
    #[inline]
    /// Get the field's name or none if it lacks one
    pub fn get_name(&self) -> Option<String> {
        unsafe {
            let c_name = jit_type_get_name(self._type, self.index);
            if c_name.is_null() {
                None
            } else {
                Some(from_c_str(c_name))
            }
        }
    }
    #[inline(always)]
    /// Get the type of the field
    pub fn get_type(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_get_field(self._type, self.index))
        }
    }
    #[inline(always)]
    /// Get the offset of the field
    pub fn get_offset(&self) -> uint {
        unsafe {
            jit_type_get_offset(self._type, self.index) as uint
        }
    }
}
/// A type field iterator
pub struct Fields<'a> {
    _type: jit_type_t,
    index: c_uint,
    length: c_uint,
    marker: ContravariantLifetime<'a>
}
impl<'a> Fields<'a> {
    #[inline(always)]
    fn new(ty:Type) -> Fields<'a> {
        unsafe {
            Fields {
                _type: ty.as_ptr(),
                index: 0 as c_uint,
                length: jit_type_num_fields(ty.as_ptr()),
                marker: ContravariantLifetime::<'a>
            }
        }
    }
}
impl<'a> Iterator<Field<'a>> for Fields<'a> {
    fn next(&mut self) -> Option<Field<'a>> {
        let index = self.index;
        self.index += 1;
        if index < self.length {
            Some(Field {
                _type: self._type.clone(),
                index: index,
                marker: ContravariantLifetime::<'a>
            })
        } else {
            None
        }
    }
    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        ((self.length - self.index) as uint, None)
    }
    #[inline]
    fn count(&mut self) -> uint {
        let count = self.length - self.index;
        self.index = self.length;
        count as uint
    }
    #[inline]
    fn nth(&mut self, n:uint) -> Option<Field<'a>> {
        self.index += n as c_uint;
        self.next()
    }
}
pub struct Params<'a> {
    _type: jit_type_t,
    index: c_uint,
    length: c_uint,
    marker: ContravariantLifetime<'a>
}
impl<'a> Params<'a> {
    #[inline(always)]
    fn new(ty:Type) -> Params<'a> {
        unsafe {
            Params {
                _type: ty.as_ptr(),
                index: 0 as c_uint,
                length: jit_type_num_params(ty.as_ptr()),
                marker: ContravariantLifetime::<'a>
            }
        }
    }
}
impl<'a> Iterator<Type> for Params<'a> {
    fn next(&mut self) -> Option<Type> {
        let index = self.index;
        self.index += 1;
        if index < self.length {
            Some(unsafe {
                NativeRef::from_ptr(jit_type_get_param(self._type, index))
            })
        } else {
            None
        }
    }
    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        ((self.length - self.index) as uint, None)
    }
    #[inline]
    fn count(&mut self) -> uint {
        let count = self.length - self.index;
        self.index = self.length;
        count as uint
    }
    #[inline]
    fn nth(&mut self, n:uint) -> Option<Type> {
        self.index += n as c_uint;
        self.next()
    }
}
/// An object that represents a native system type.
/// Each `Type` represents a basic system type, be it a primitive, a struct, a
/// union, a pointer, or a function signature. The library uses this information
/// to lay out values in memory.
#[deriving(PartialEq)]
pub struct Type {
    _type: jit_type_t,
    marker: Managed
}
impl NativeRef for Type {
    #[inline(always)]
    unsafe fn as_ptr(&self) -> jit_type_t {
        self._type
    }
    #[inline(always)]
    unsafe fn from_ptr(ptr:jit_type_t) -> Type {
        Type {
            _type: ptr,
            marker: Managed
        }
    }
}
impl Clone for Type {
    #[inline]
    /// Make a copy of the type descriptor by increasing its reference count.
    fn clone(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_copy(self.as_ptr()))
        }
    }
}
#[unsafe_destructor]
impl Drop for Type {
    #[inline(always)]
    /// Free a type descriptor by decreasing its reference count.
    /// This function is safe to use on pre-defined types, which are never
    /// actually freed.
    fn drop(&mut self) {
        unsafe {
            jit_type_free(self.as_ptr());
        }
    }
}
impl Type {
    /// Create a type descriptor for a function signature.
    pub fn create_signature(abi: ABI, return_type: Type, params: &mut [Type]) -> Type {
        unsafe {
            let mut native_params:Vec<jit_type_t> = params.iter().map(|param| param.as_ptr()).collect();
            let signature = jit_type_create_signature(abi as jit_abi_t, return_type.as_ptr(), native_params.as_mut_ptr(), params.len() as c_uint, 1);
            NativeRef::from_ptr(signature)
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a structure.
    pub fn create_struct(fields: &mut [Type]) -> Type {
        unsafe {
            let mut native_fields:Vec<_> = fields.iter().map(|field| field.as_ptr()).collect();
            NativeRef::from_ptr(jit_type_create_struct(native_fields.as_mut_ptr(), fields.len() as c_uint, 1))
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a union.
    pub fn create_union(fields: &mut [Type]) -> Type {
        unsafe {
            let mut native_fields:Vec<_> = fields.iter().map(|field| field.as_ptr()).collect();
            NativeRef::from_ptr(jit_type_create_union(native_fields.as_mut_ptr(), fields.len() as c_uint, 1))
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a pointer to another type.
    pub fn create_pointer(pointee: Type) -> Type {
        unsafe {
            let ptr = jit_type_create_pointer(pointee.as_ptr(), 1);
            NativeRef::from_ptr(ptr)
        }
    }
    #[inline(always)]
    /// Get the size of this type in bytes.
    pub fn get_size(&self) -> uint {
        unsafe {
            jit_type_get_size(self.as_ptr()) as uint
        }
    }
    #[inline]
    /// Get a value that indicates the kind of this type. This allows
    /// callers to quickly classify a type to determine how it should
    /// be handled further.
    pub fn get_kind(&self) -> TypeKind {
        unsafe {
            transmute(jit_type_get_kind(self.as_ptr()))
        }
    }
    #[inline(always)]
    /// Get the type that is referred to by this pointer type.
    pub fn get_ref(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_get_ref(self.as_ptr()))
        }
    }
    /// Set the field or parameter names of this type.
    pub fn set_names<T:ToCStr>(&self, names:&[T]) -> bool {
        unsafe {
            let native_names : Vec<*const i8> = names.iter().map(|name| name.to_c_str().unwrap()).collect();
            jit_type_set_names(self.as_ptr(), native_names.as_ptr() as *mut *mut i8, names.len() as u32) != 0
        }
    }
    #[inline(always)]
    /// Iterator over the type's fields
    pub fn fields<'a>(&'a self) -> Fields<'a> {
        Fields::new(self.clone())
    }
    #[inline(always)]
    /// Iterator over the function signature's parameters
    pub fn params<'a>(&'a self) -> Params<'a> {
        Params::new(self.clone())
    }
    #[inline]
    /// Find the field/parameter index for a particular name.
    pub fn find_name<'b, T:ToCStr>(&'b self, name:T) -> Field<'b> {
        name.with_c_str(|c_name| unsafe {
            Field {
                index: jit_type_find_name(self.as_ptr(), c_name),
                _type: self.as_ptr(),
                marker: ContravariantLifetime::<'b>
            }
        })
    }
    #[inline(always)]
    /// Check if this is a pointer
    pub fn is_pointer(&self) -> bool {
        unsafe {
            jit_type_is_pointer(self.as_ptr()) != 0
        }
    }
}
#[inline(always)]
/// Get the Rust type given as a type descriptor
pub fn get<T:Compile>() -> Type {
    Compile::jit_type(None::<T>)
}<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// rust - central access to other rust tools
// FIXME #2238 Make commands run and test emit proper file endings on windows
// FIXME #2238 Make run only accept source that emits an executable

#[link(name = "rust",
       vers = "0.8-pre",
       uuid = "4a24da33-5cc8-4037-9352-2cbe9bd9d27c",
       url = "https://github.com/mozilla/rust/tree/master/src/rust")];

#[license = "MIT/ASL2"];
#[crate_type = "lib"];

extern mod rustpkg;
extern mod rustdoc;
extern mod rusti;
extern mod rustc;

use std::io;
use std::os;
use std::run;
use std::libc::exit;

enum ValidUsage {
    Valid(int), Invalid
}

impl ValidUsage {
    fn is_valid(&self) -> bool {
        match *self {
            Valid(_)   => true,
            Invalid    => false
        }
    }
}

enum Action {
    Call(extern "Rust" fn(args: &[~str]) -> ValidUsage),
    CallMain(&'static str, extern "Rust" fn()),
}

enum UsageSource<'self> {
    UsgStr(&'self str),
    UsgCall(extern "Rust" fn()),
}

struct Command<'self> {
    cmd: &'self str,
    action: Action,
    usage_line: &'self str,
    usage_full: UsageSource<'self>,
}

static COMMANDS: &'static [Command<'static>] = &[
    Command{
        cmd: "build",
        action: CallMain("rustc", rustc::main),
        usage_line: "compile rust source files",
        usage_full: UsgCall(rustc_help),
    },
    Command{
        cmd: "run",
        action: Call(cmd_run),
        usage_line: "build an executable, and run it",
        usage_full: UsgStr(
            "The run command is an shortcut for the command line \n\
             \"rustc <filename> -o <filestem>~ && ./<filestem>~ [<arguments>...]\".\
            \n\nUsage:\trust run <filename> [<arguments>...]"
        )
    },
    Command{
        cmd: "test",
        action: Call(cmd_test),
        usage_line: "build a test executable, and run it",
        usage_full: UsgStr(
            "The test command is an shortcut for the command line \n\
            \"rustc --test <filename> -o <filestem>test~ && \
            ./<filestem>test~\"\n\nUsage:\trust test <filename>"
        )
    },
    Command{
        cmd: "doc",
        action: CallMain("rustdoc", rustdoc::main),
        usage_line: "generate documentation from doc comments",
        usage_full: UsgCall(rustdoc::config::usage),
    },
    Command{
        cmd: "pkg",
        action: CallMain("rustpkg", rustpkg::main),
        usage_line: "download, build, install rust packages",
        usage_full: UsgCall(rustpkg::usage::general),
    },
    Command{
        cmd: "sketch",
        action: CallMain("rusti", rusti::main),
        usage_line: "run a rust interpreter",
        usage_full: UsgStr("\nUsage:\trusti"),
    },
    Command{
        cmd: "help",
        action: Call(cmd_help),
        usage_line: "show detailed usage of a command",
        usage_full: UsgStr(
            "The help command displays the usage text of another command.\n\
            The text is either build in, or provided by the corresponding \
            program.\n\nUsage:\trust help <command>"
        )
    }
];

fn rustc_help() {
    rustc::usage(os::args()[0].clone())
}

fn find_cmd(command_string: &str) -> Option<Command> {
    do COMMANDS.iter().find_ |command| {
        command.cmd == command_string
    }.map_consume(|x| *x)
}

fn cmd_help(args: &[~str]) -> ValidUsage {
    fn print_usage(command_string: ~str) -> ValidUsage {
        match find_cmd(command_string) {
            Some(command) => {
                match command.action {
                    CallMain(prog, _) => printfln!(
                        "The %s command is an alias for the %s program.",
                        command.cmd, prog),
                    _       => ()
                }
                match command.usage_full {
                    UsgStr(msg) => printfln!("%s\n", msg),
                    UsgCall(f)  => f(),
                }
                Valid(0)
            },
            None => Invalid
        }
    }

    match args {
        [ref command_string] => print_usage((*command_string).clone()),
        _                    => Invalid
    }
}

fn cmd_test(args: &[~str]) -> ValidUsage {
    match args {
        [ref filename] => {
            let test_exec = Path(*filename).filestem().unwrap() + "test~";
            invoke("rustc", &[~"--test", filename.to_owned(),
                              ~"-o", test_exec.to_owned()], rustc::main);
            let exit_code = run::process_status(~"./" + test_exec, []);
            Valid(exit_code)
        }
        _ => Invalid
    }
}

fn cmd_run(args: &[~str]) -> ValidUsage {
    match args {
        [ref filename, ..prog_args] => {
            let exec = Path(*filename).filestem().unwrap() + "~";
            invoke("rustc", &[filename.to_owned(), ~"-o", exec.to_owned()],
                   rustc::main);
            let exit_code = run::process_status(~"./"+exec, prog_args);
            Valid(exit_code)
        }
        _ => Invalid
    }
}

fn invoke(prog: &str, args: &[~str], f: &fn()) {
    let mut osargs = ~[prog.to_owned()];
    osargs.push_all_move(args.to_owned());
    os::set_args(osargs);
    f();
}

fn do_command(command: &Command, args: &[~str]) -> ValidUsage {
    match command.action {
        Call(f) => f(args),
        CallMain(prog, f) => {
            invoke(prog, args, f);
            Valid(0)
        }
    }
}

fn usage() {
    static INDENT: uint = 8;

    io::print(
        "The rust tool is a convenience for managing rust source code.\n\
        It acts as a shortcut for programs of the rust tool chain.\n\
        \n\
        Usage:\trust <command> [arguments]\n\
        \n\
        The commands are:\n\
        \n"
    );

    for COMMANDS.iter().advance |command| {
        let padding = " ".repeat(INDENT - command.cmd.len());
        printfln!("    %s%s%s", command.cmd, padding, command.usage_line);
    }

    io::print(
        "\n\
        Use \"rust help <command>\" for more information about a command.\n\
        \n"
    );

}

pub fn main() {
    let os_args = os::args();

    if (os_args.len() > 1 && (os_args[1] == ~"-v" || os_args[1] == ~"--version")) {
        rustc::version(os_args[0]);
        unsafe { exit(0); }
    }

    let args = os_args.tail();

    if !args.is_empty() {
        let r = find_cmd(*args.head());
        for r.iter().advance |command| {
            let result = do_command(command, args.tail());
            match result {
                Valid(exit_code) => unsafe { exit(exit_code.to_i32()) },
                _                => loop
            }
        }
    }

    usage();
}
<commit_msg>librust: Stop rust tool from crashing on macos.<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// rust - central access to other rust tools
// FIXME #2238 Make commands run and test emit proper file endings on windows
// FIXME #2238 Make run only accept source that emits an executable

#[link(name = "rust",
       vers = "0.8-pre",
       uuid = "4a24da33-5cc8-4037-9352-2cbe9bd9d27c",
       url = "https://github.com/mozilla/rust/tree/master/src/rust")];

#[license = "MIT/ASL2"];
#[crate_type = "lib"];

extern mod rustpkg;
extern mod rustdoc;
extern mod rusti;
extern mod rustc;

use std::io;
use std::os;
use std::run;
use std::libc::exit;

enum ValidUsage {
    Valid(int), Invalid
}

impl ValidUsage {
    fn is_valid(&self) -> bool {
        match *self {
            Valid(_)   => true,
            Invalid    => false
        }
    }
}

enum Action {
    Call(extern "Rust" fn(args: &[~str]) -> ValidUsage),
    CallMain(&'static str, extern "Rust" fn()),
}

enum UsageSource<'self> {
    UsgStr(&'self str),
    UsgCall(extern "Rust" fn()),
}

struct Command<'self> {
    cmd: &'self str,
    action: Action,
    usage_line: &'self str,
    usage_full: UsageSource<'self>,
}

static NUM_OF_COMMANDS: uint = 7;

// FIXME(#7617): should just be &'static [Command<'static>]
// but mac os doesn't seem to like that and tries to loop
// past the end of COMMANDS in usage thus passing garbage
// to str::repeat and eventually malloc and crashing.
static COMMANDS: [Command<'static>, .. NUM_OF_COMMANDS] = [
    Command{
        cmd: "build",
        action: CallMain("rustc", rustc::main),
        usage_line: "compile rust source files",
        usage_full: UsgCall(rustc_help),
    },
    Command{
        cmd: "run",
        action: Call(cmd_run),
        usage_line: "build an executable, and run it",
        usage_full: UsgStr(
            "The run command is an shortcut for the command line \n\
             \"rustc <filename> -o <filestem>~ && ./<filestem>~ [<arguments>...]\".\
            \n\nUsage:\trust run <filename> [<arguments>...]"
        )
    },
    Command{
        cmd: "test",
        action: Call(cmd_test),
        usage_line: "build a test executable, and run it",
        usage_full: UsgStr(
            "The test command is an shortcut for the command line \n\
            \"rustc --test <filename> -o <filestem>test~ && \
            ./<filestem>test~\"\n\nUsage:\trust test <filename>"
        )
    },
    Command{
        cmd: "doc",
        action: CallMain("rustdoc", rustdoc::main),
        usage_line: "generate documentation from doc comments",
        usage_full: UsgCall(rustdoc::config::usage),
    },
    Command{
        cmd: "pkg",
        action: CallMain("rustpkg", rustpkg::main),
        usage_line: "download, build, install rust packages",
        usage_full: UsgCall(rustpkg::usage::general),
    },
    Command{
        cmd: "sketch",
        action: CallMain("rusti", rusti::main),
        usage_line: "run a rust interpreter",
        usage_full: UsgStr("\nUsage:\trusti"),
    },
    Command{
        cmd: "help",
        action: Call(cmd_help),
        usage_line: "show detailed usage of a command",
        usage_full: UsgStr(
            "The help command displays the usage text of another command.\n\
            The text is either build in, or provided by the corresponding \
            program.\n\nUsage:\trust help <command>"
        )
    }
];

fn rustc_help() {
    rustc::usage(os::args()[0].clone())
}

fn find_cmd(command_string: &str) -> Option<Command> {
    do COMMANDS.iter().find_ |command| {
        command.cmd == command_string
    }.map_consume(|x| *x)
}

fn cmd_help(args: &[~str]) -> ValidUsage {
    fn print_usage(command_string: ~str) -> ValidUsage {
        match find_cmd(command_string) {
            Some(command) => {
                match command.action {
                    CallMain(prog, _) => printfln!(
                        "The %s command is an alias for the %s program.",
                        command.cmd, prog),
                    _       => ()
                }
                match command.usage_full {
                    UsgStr(msg) => printfln!("%s\n", msg),
                    UsgCall(f)  => f(),
                }
                Valid(0)
            },
            None => Invalid
        }
    }

    match args {
        [ref command_string] => print_usage((*command_string).clone()),
        _                    => Invalid
    }
}

fn cmd_test(args: &[~str]) -> ValidUsage {
    match args {
        [ref filename] => {
            let test_exec = Path(*filename).filestem().unwrap() + "test~";
            invoke("rustc", &[~"--test", filename.to_owned(),
                              ~"-o", test_exec.to_owned()], rustc::main);
            let exit_code = run::process_status(~"./" + test_exec, []);
            Valid(exit_code)
        }
        _ => Invalid
    }
}

fn cmd_run(args: &[~str]) -> ValidUsage {
    match args {
        [ref filename, ..prog_args] => {
            let exec = Path(*filename).filestem().unwrap() + "~";
            invoke("rustc", &[filename.to_owned(), ~"-o", exec.to_owned()],
                   rustc::main);
            let exit_code = run::process_status(~"./"+exec, prog_args);
            Valid(exit_code)
        }
        _ => Invalid
    }
}

fn invoke(prog: &str, args: &[~str], f: &fn()) {
    let mut osargs = ~[prog.to_owned()];
    osargs.push_all_move(args.to_owned());
    os::set_args(osargs);
    f();
}

fn do_command(command: &Command, args: &[~str]) -> ValidUsage {
    match command.action {
        Call(f) => f(args),
        CallMain(prog, f) => {
            invoke(prog, args, f);
            Valid(0)
        }
    }
}

fn usage() {
    static INDENT: uint = 8;

    io::print(
        "The rust tool is a convenience for managing rust source code.\n\
        It acts as a shortcut for programs of the rust tool chain.\n\
        \n\
        Usage:\trust <command> [arguments]\n\
        \n\
        The commands are:\n\
        \n"
    );

    for COMMANDS.iter().advance |command| {
        let padding = " ".repeat(INDENT - command.cmd.len());
        printfln!("    %s%s%s", command.cmd, padding, command.usage_line);
    }

    io::print(
        "\n\
        Use \"rust help <command>\" for more information about a command.\n\
        \n"
    );

}

pub fn main() {
    let os_args = os::args();

    if (os_args.len() > 1 && (os_args[1] == ~"-v" || os_args[1] == ~"--version")) {
        rustc::version(os_args[0]);
        unsafe { exit(0); }
    }

    let args = os_args.tail();

    if !args.is_empty() {
        let r = find_cmd(*args.head());
        for r.iter().advance |command| {
            let result = do_command(command, args.tail());
            match result {
                Valid(exit_code) => unsafe { exit(exit_code.to_i32()) },
                _                => loop
            }
        }
    }

    usage();
}
<|endoftext|>


<commit_before>use serde_json::from_str;
use config::action::{ActionType, ExecCondition};

#[test]
fn test_given_action_when_it_is_deserialized_then_we_get_the_right_result() {
    let text = r#"
        {
            "message": {
                "uuid": "uuid1",
                "message": "message"
            }
        }
    "#;

    let result = from_str::<ActionType>(text);
    println!("{:?}", &result);
    let action = result.ok().expect("Failed to deserialize a valid ActionType");
    match action {
        ActionType::Message(message) => {
            assert_eq!("uuid1", message.uuid());
        }
    }
}

#[test]
fn test_given_filled_exec_condition_when_it_is_deserialized_then_it_is_populated_with_the_specified_values
    () {
    let text = r#"
        {
            "on_opened": true,
            "on_closed": false
        }
    "#;

    let expected = ExecCondition {
        on_closed: false,
        on_opened: true,
    };
    let result = from_str::<ExecCondition>(text);
    println!("{:?}", &result);
    let cond = result.ok().expect("Failed to deserialize a valid ExecCondition");
    assert_eq!(expected, cond);
}

#[test]
fn test_given_filled_exec_condition_when_it_is_deserialized_then_its_missing_fields_are_populated_with_default_values
    () {
    let text = r#"
        {
        }
    "#;

    let expected: ExecCondition = Default::default();
    let result = from_str::<ExecCondition>(text);
    println!("{:?}", &result);
    let cond = result.ok().expect("Failed to deserialize a valid ExecCondition");
    assert_eq!(expected, cond);
}
<commit_msg>config/action/deser/test: add two more test cases<commit_after>use serde_json::from_str;
use config::action::{ActionType, ExecCondition};

#[test]
fn test_given_action_when_it_is_deserialized_then_we_get_the_right_result() {
    let text = r#"
        {
            "message": {
                "uuid": "uuid1",
                "message": "message"
            }
        }
    "#;

    let result = from_str::<ActionType>(text);
    println!("{:?}", &result);
    let action = result.ok().expect("Failed to deserialize a valid ActionType");
    match action {
        ActionType::Message(message) => {
            assert_eq!("uuid1", message.uuid());
        }
    }
}

#[test]
fn test_given_unknown_action_when_it_is_deserialized_then_we_get_an_error() {
    let text = r#"{ "unknown": {} }"#;
    let result = from_str::<ActionType>(text);
    println!("{:?}", &result);
    let _ = result.err().expect("Successfully deserialized an unknown action");
}

#[test]
fn test_given_filled_exec_condition_when_it_is_deserialized_then_it_is_populated_with_the_specified_values
    () {
    let text = r#"
        {
            "on_opened": true,
            "on_closed": false
        }
    "#;

    let expected = ExecCondition {
        on_closed: false,
        on_opened: true,
    };
    let result = from_str::<ExecCondition>(text);
    println!("{:?}", &result);
    let cond = result.ok().expect("Failed to deserialize a valid ExecCondition");
    assert_eq!(expected, cond);
}

#[test]
fn test_given_exec_condition_when_it_contains_an_unknown_key_then_the_deserialization_fails() {
    let text = r#"{ "unknown": true }"#;
    let result = from_str::<ExecCondition>(text);
    println!("{:?}", &result);
    let _ = result.err().expect("Failed to deserialize a valid ExecCondition");
}

#[test]
fn test_given_filled_exec_condition_when_it_is_deserialized_then_its_missing_fields_are_populated_with_default_values
    () {
    let text = r#"
        {
        }
    "#;

    let expected: ExecCondition = Default::default();
    let result = from_str::<ExecCondition>(text);
    println!("{:?}", &result);
    let cond = result.ok().expect("Failed to deserialize a valid ExecCondition");
    assert_eq!(expected, cond);
}
<|endoftext|>


<commit_before>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::io;
use std::convert::TryFrom;

use chrono::FixedOffset;

use tipb::expression::{Expr, ExprType, ScalarFuncSig, FieldType};

use coprocessor::codec::mysql::{Duration, Time, Decimal, MAX_FSP};
use coprocessor::codec::mysql::decimal::DecimalDecoder;
use coprocessor::codec::Datum;
use util;
use util::codec::number::NumberDecoder;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Io(err: io::Error) {
            from()
            description("io error")
            display("I/O error: {}", err)
            cause(err)
        }
        Type { has: &'static str, expected: &'static str } {
            description("type error")
            display("type error: cannot get {:?} result from {:?} expression", expected, has)
        }
        Codec(err: util::codec::Error) {
            from()
            description("codec error")
            display("codec error: {}", err)
            cause(err)
        }
        ColumnOffset(offset: usize) {
            description("column offset not found")
            display("illegal column offset: {}", offset)
        }
        Other(desc: &'static str) {
            description(desc)
            display("error {}", desc)
        }
    }
}

pub type Result<T> = ::std::result::Result<T, Error>;

pub const FLAG_IGNORE_TRUNCATE: u64 = 1;
pub const FLAG_TRUNCATE_AS_WARNING: u64 = 1 << 1;

pub struct StatementContext {
    ignore_truncate: bool,
    truncate_as_warning: bool,
    timezone: FixedOffset,
}

#[derive(Debug, Clone, PartialEq)]
pub struct Expression {
    expr: ExprKind,
    ret_type: FieldType,
}

#[derive(Debug, Clone, PartialEq)]
pub enum ExprKind {
    Constant(Datum),
    ColumnRef(usize),
    ScalarFn(FnCall),
}

/// A single scalar function call
#[derive(Debug, Clone, PartialEq)]
pub struct FnCall {
    sig: ScalarFuncSig,
    children: Vec<Expression>,
}

impl Expression {
    fn eval_int(&self, row: &[Datum], ctx: &StatementContext) -> Result<Option<i64>> {
        unimplemented!()
    }

    fn eval_real(&self, row: &[Datum], ctx: &StatementContext) -> Result<Option<f64>> {
        unimplemented!()
    }

    fn eval_decimal(&self, row: &[Datum], ctx: &StatementContext) -> Result<Option<Decimal>> {
        unimplemented!()
    }

    fn eval_string(&self, row: &[Datum], ctx: &StatementContext) -> Result<Option<String>> {
        unimplemented!()
    }

    fn eval_time(&self, row: &[Datum], ctx: &StatementContext) -> Result<Option<Time>> {
        unimplemented!()
    }

    fn eval_duration(&self, row: &[Datum], ctx: &StatementContext) -> Result<Option<Duration>> {
        unimplemented!()
    }
}

impl TryFrom<Expr> for Expression {
    type Error = Error;

    fn try_from(expr: Expr) -> ::std::result::Result<Expression, Self::Error> {
        let mut expr = expr;
        let ret_type = expr.take_field_type();
        match expr.get_tp() {
            ExprType::Null => {
                Ok(Expression {
                    expr: ExprKind::Constant(Datum::Null),
                    ret_type: ret_type,
                })
            }
            ExprType::Int64 => {
                expr.get_val()
                    .decode_i64()
                    .map(Datum::I64)
                    .map(|e| {
                        Expression {
                            expr: ExprKind::Constant(e),
                            ret_type: ret_type,
                        }
                    })
                    .map_err(Error::from)
            }
            ExprType::Uint64 => {
                expr.get_val()
                    .decode_u64()
                    .map(Datum::U64)
                    .map(|e| {
                        Expression {
                            expr: ExprKind::Constant(e),
                            ret_type: ret_type,
                        }
                    })
                    .map_err(Error::from)
            }
            ExprType::String | ExprType::Bytes => {
                Ok(Expression {
                    expr: ExprKind::Constant(Datum::Bytes(expr.take_val())),
                    ret_type: ret_type,
                })
            }
            ExprType::Float32 |
            ExprType::Float64 => {
                expr.get_val()
                    .decode_f64()
                    .map(Datum::F64)
                    .map(|e| {
                        Expression {
                            expr: ExprKind::Constant(e),
                            ret_type: ret_type,
                        }
                    })
                    .map_err(Error::from)
            }
            ExprType::MysqlDuration => {
                expr.get_val()
                    .decode_i64()
                    .and_then(|n| Duration::from_nanos(n, MAX_FSP))
                    .map(Datum::Dur)
                    .map(|e| {
                        Expression {
                            expr: ExprKind::Constant(e),
                            ret_type: ret_type,
                        }
                    })
                    .map_err(Error::from)
            }
            ExprType::MysqlDecimal => {
                expr.get_val()
                    .decode_decimal()
                    .map(Datum::Dec)
                    .map(|e| {
                        Expression {
                            expr: ExprKind::Constant(e),
                            ret_type: ret_type,
                        }
                    })
                    .map_err(Error::from)
            }
            // TODO(andelf): fn sig verification
            ExprType::ScalarFunc => {
                let sig = expr.get_sig();
                let mut expr = expr;
                expr.take_children()
                    .into_iter()
                    .map(Expression::try_from)
                    .collect::<Result<Vec<_>>>()
                    .map(|children| {
                        Expression {
                            expr: ExprKind::ScalarFn(FnCall {
                                sig: sig,
                                children: children,
                            }),
                            ret_type: ret_type,
                        }
                    })
            }
            ExprType::ColumnRef => {
                expr.get_val()
                    .decode_i64()
                    .map(|i| {
                        Expression {
                            expr: ExprKind::ColumnRef(i as usize),
                            ret_type: ret_type,
                        }
                    })
                    .map_err(Error::from)
            }
            unhandled => unreachable!("can't handle {:?} expr in DAG mode", unhandled),
        }
    }
}

#[test]
fn test_smoke() {
    use std::convert::TryInto;
    use util::codec::number::NumberEncoder;

    let mut pb = Expr::new();
    pb.set_tp(ExprType::ColumnRef);
    pb.mut_val().encode_i64(1).unwrap();

    let e: Result<Expression> = pb.try_into();
    let _ = e.unwrap();
}
<commit_msg>expr/mod: update expression (#2149)<commit_after>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::io;
use std::convert::TryFrom;

use tipb::expression::{Expr, ExprType, ScalarFuncSig, FieldType};

use coprocessor::codec::mysql::{Duration, Time, Decimal, MAX_FSP};
use coprocessor::codec::mysql::decimal::DecimalDecoder;
use coprocessor::codec::Datum;
use util;
use util::codec::number::NumberDecoder;

pub use coprocessor::select::xeval::EvalContext as StatementContext;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Io(err: io::Error) {
            from()
            description("io error")
            display("I/O error: {}", err)
            cause(err)
        }
        Type { has: &'static str, expected: &'static str } {
            description("type error")
            display("type error: cannot get {:?} result from {:?} expression", expected, has)
        }
        Codec(err: util::codec::Error) {
            from()
            description("codec error")
            display("codec error: {}", err)
            cause(err)
        }
        ColumnOffset(offset: usize) {
            description("column offset not found")
            display("illegal column offset: {}", offset)
        }
        Other(desc: &'static str) {
            description(desc)
            display("error {}", desc)
        }
    }
}

pub type Result<T> = ::std::result::Result<T, Error>;

#[derive(Debug, Clone, PartialEq)]
pub enum Expression {
    Constant(Constant),
    ColumnRef(Column),
    ScalarFn(FnCall),
}

#[derive(Debug, Clone, PartialEq)]
pub struct Column {
    offset: usize,
    tp: FieldType,
}

#[derive(Debug, Clone, PartialEq)]
pub struct Constant {
    val: Datum,
    tp: FieldType,
}

/// A single scalar function call
#[derive(Debug, Clone, PartialEq)]
pub struct FnCall {
    sig: ScalarFuncSig,
    children: Vec<Expression>,
    tp: FieldType,
}

impl Expression {
    fn new_const(v: Datum, field_type: FieldType) -> Expression {
        Expression::Constant(Constant {
            val: v,
            tp: field_type,
        })
    }

    fn eval_int(&self, ctx: &StatementContext, row: &[Datum]) -> Result<Option<i64>> {
        unimplemented!()
    }

    fn eval_real(&self, ctx: &StatementContext, row: &[Datum]) -> Result<Option<f64>> {
        unimplemented!()
    }

    fn eval_decimal(&self, ctx: &StatementContext, row: &[Datum]) -> Result<Option<Decimal>> {
        unimplemented!()
    }

    fn eval_string(&self, ctx: &StatementContext, row: &[Datum]) -> Result<Option<String>> {
        unimplemented!()
    }

    fn eval_time(&self, ctx: &StatementContext, row: &[Datum]) -> Result<Option<Time>> {
        unimplemented!()
    }

    fn eval_duration(&self, ctx: &StatementContext, row: &[Datum]) -> Result<Option<Duration>> {
        unimplemented!()
    }

    fn get_tp(&self) -> &FieldType {
        match *self {
            Expression::Constant(ref c) => &c.tp,
            Expression::ColumnRef(ref c) => &c.tp,
            Expression::ScalarFn(ref c) => &c.tp,
        }
    }
}

impl TryFrom<Expr> for Expression {
    type Error = Error;

    fn try_from(expr: Expr) -> ::std::result::Result<Expression, Self::Error> {
        let mut expr = expr;
        let tp = expr.take_field_type();
        match expr.get_tp() {
            ExprType::Null => Ok(Expression::new_const(Datum::Null, tp)),
            ExprType::Int64 => {
                expr.get_val()
                    .decode_i64()
                    .map(Datum::I64)
                    .map(|e| Expression::new_const(e, tp))
                    .map_err(Error::from)
            }
            ExprType::Uint64 => {
                expr.get_val()
                    .decode_u64()
                    .map(Datum::U64)
                    .map(|e| Expression::new_const(e, tp))
                    .map_err(Error::from)
            }
            ExprType::String | ExprType::Bytes => {
                Ok(Expression::new_const(Datum::Bytes(expr.take_val()), tp))
            }
            ExprType::Float32 |
            ExprType::Float64 => {
                expr.get_val()
                    .decode_f64()
                    .map(Datum::F64)
                    .map(|e| Expression::new_const(e, tp))
                    .map_err(Error::from)
            }
            ExprType::MysqlDuration => {
                expr.get_val()
                    .decode_i64()
                    .and_then(|n| Duration::from_nanos(n, MAX_FSP))
                    .map(Datum::Dur)
                    .map(|e| Expression::new_const(e, tp))
                    .map_err(Error::from)
            }
            ExprType::MysqlDecimal => {
                expr.get_val()
                    .decode_decimal()
                    .map(Datum::Dec)
                    .map(|e| Expression::new_const(e, tp))
                    .map_err(Error::from)
            }
            // TODO(andelf): fn sig verification
            ExprType::ScalarFunc => {
                let sig = expr.get_sig();
                let mut expr = expr;
                expr.take_children()
                    .into_iter()
                    .map(Expression::try_from)
                    .collect::<Result<Vec<_>>>()
                    .map(|children| {
                        Expression::ScalarFn(FnCall {
                            sig: sig,
                            children: children,
                            tp: tp,
                        })
                    })
            }
            ExprType::ColumnRef => {
                expr.get_val()
                    .decode_i64()
                    .map(|i| {
                        Expression::ColumnRef(Column {
                            offset: i as usize,
                            tp: tp,
                        })
                    })
                    .map_err(Error::from)
            }
            unhandled => unreachable!("can't handle {:?} expr in DAG mode", unhandled),
        }
    }
}

#[test]
fn test_smoke() {
    use std::convert::TryInto;
    use util::codec::number::NumberEncoder;

    let mut pb = Expr::new();
    pb.set_tp(ExprType::ColumnRef);
    pb.mut_val().encode_i64(1).unwrap();

    let e: Result<Expression> = pb.try_into();
    let _ = e.unwrap();
}
<|endoftext|>