<commit_before>/*!

The `ToBytes` and `IterBytes` traits

*/

// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];

use io::Writer;

pub type Cb = fn(buf: &[const u8]) -> bool;

/**
 * A trait to implement in order to make a type hashable;
 * This works in combination with the trait `Hash::Hash`, and
 * may in the future be merged with that trait or otherwise
 * modified when default methods and trait inheritence are
 * completed.
 */
pub trait IterBytes {
    /**
     * Call the provided callback `f` one or more times with
     * byte-slices that should be used when computing a hash
     * value or otherwise "flattening" the structure into
     * a sequence of bytes. The `lsb0` parameter conveys
     * whether the caller is asking for little-endian bytes
     * (`true`) or big-endian (`false`); this should only be
     * relevant in implementations that represent a single
     * multi-byte datum such as a 32 bit integer or 64 bit
     * floating-point value. It can be safely ignored for
     * larger structured types as they are usually processed
     * left-to-right in declaration order, regardless of
     * underlying memory endianness.
     */
    pure fn iter_bytes(lsb0: bool, f: Cb);
}

impl bool: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(_lsb0: bool, f: Cb) {
        f([
            self as u8
        ]);
    }
}

impl u8: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(_lsb0: bool, f: Cb) {
        f([
            self
        ]);
    }
}

impl u16: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        if lsb0 {
            f([
                self as u8,
                (self >> 8) as u8
            ]);
        } else {
            f([
                (self >> 8) as u8,
                self as u8
            ]);
        }
    }
}

impl u32: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        if lsb0 {
            f([
                self as u8,
                (self >> 8) as u8,
                (self >> 16) as u8,
                (self >> 24) as u8,
            ]);
        } else {
            f([
                (self >> 24) as u8,
                (self >> 16) as u8,
                (self >> 8) as u8,
                self as u8
            ]);
        }
    }
}

impl u64: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        if lsb0 {
            f([
                self as u8,
                (self >> 8) as u8,
                (self >> 16) as u8,
                (self >> 24) as u8,
                (self >> 32) as u8,
                (self >> 40) as u8,
                (self >> 48) as u8,
                (self >> 56) as u8
            ]);
        } else {
            f([
                (self >> 56) as u8,
                (self >> 48) as u8,
                (self >> 40) as u8,
                (self >> 32) as u8,
                (self >> 24) as u8,
                (self >> 16) as u8,
                (self >> 8) as u8,
                self as u8
            ]);
        }
    }
}

impl i8: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as u8).iter_bytes(lsb0, f)
    }
}

impl i16: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as u16).iter_bytes(lsb0, f)
    }
}

impl i32: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as u32).iter_bytes(lsb0, f)
    }
}

impl i64: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as u64).iter_bytes(lsb0, f)
    }
}

impl char: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as u32).iter_bytes(lsb0, f)
    }
}

#[cfg(target_word_size = "32")]
impl uint: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as u32).iter_bytes(lsb0, f)
    }
}

#[cfg(target_word_size = "64")]
impl uint: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as u64).iter_bytes(lsb0, f)
    }
}

impl int: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as uint).iter_bytes(lsb0, f)
    }
}

impl<A: IterBytes> &[A]: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        for self.each |elt| {
            do elt.iter_bytes(lsb0) |bytes| {
                f(bytes)
            }
        }
    }
}

// Move this to vec, probably.
pure fn borrow<A>(a: &x/[A]) -> &x/[A] {
    a
}

impl<A: IterBytes> ~[A]: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        borrow(self).iter_bytes(lsb0, f)
    }
}

impl<A: IterBytes> @[A]: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        borrow(self).iter_bytes(lsb0, f)
    }
}

pub pure fn iter_bytes_2<A: IterBytes, B: IterBytes>(a: &A, b: &B,
                                            lsb0: bool, z: Cb) {
    let mut flag = true;
    a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}

pub pure fn iter_bytes_3<A: IterBytes,
                B: IterBytes,
                C: IterBytes>(a: &A, b: &B, c: &C,
                              lsb0: bool, z: Cb) {
    let mut flag = true;
    a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}

pub pure fn iter_bytes_4<A: IterBytes,
                B: IterBytes,
                C: IterBytes,
                D: IterBytes>(a: &A, b: &B, c: &C,
                              d: &D,
                              lsb0: bool, z: Cb) {
    let mut flag = true;
    a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    d.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}

pub pure fn iter_bytes_5<A: IterBytes,
                B: IterBytes,
                C: IterBytes,
                D: IterBytes,
                E: IterBytes>(a: &A, b: &B, c: &C,
                              d: &D, e: &E,
                              lsb0: bool, z: Cb) {
    let mut flag = true;
    a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    d.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    e.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}

pub pure fn iter_bytes_6<A: IterBytes,
                B: IterBytes,
                C: IterBytes,
                D: IterBytes,
                E: IterBytes,
                F: IterBytes>(a: &A, b: &B, c: &C,
                              d: &D, e: &E, f: &F,
                              lsb0: bool, z: Cb) {
    let mut flag = true;
    a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    d.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    e.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    f.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}

pub pure fn iter_bytes_7<A: IterBytes,
                B: IterBytes,
                C: IterBytes,
                D: IterBytes,
                E: IterBytes,
                F: IterBytes,
                G: IterBytes>(a: &A, b: &B, c: &C,
                              d: &D, e: &E, f: &F,
                              g: &G,
                              lsb0: bool, z: Cb) {
    let mut flag = true;
    a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    d.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    e.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    f.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    g.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}

impl &str: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(_lsb0: bool, f: Cb) {
        do str::byte_slice(self) |bytes| {
            f(bytes);
        }
    }
}

impl ~str: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(_lsb0: bool, f: Cb) {
        do str::byte_slice(self) |bytes| {
            f(bytes);
        }
    }
}

impl @str: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(_lsb0: bool, f: Cb) {
        do str::byte_slice(self) |bytes| {
            f(bytes);
        }
    }
}

impl<A: IterBytes> Option<A>: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        match self {
          Some(ref a) => iter_bytes_2(&0u8, a, lsb0, f),
          None => 1u8.iter_bytes(lsb0, f)
        }
    }
}

impl<A: IterBytes> &A: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (*self).iter_bytes(lsb0, f);
    }
}

impl<A: IterBytes> @A: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (*self).iter_bytes(lsb0, f);
    }
}

impl<A: IterBytes> ~A: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (*self).iter_bytes(lsb0, f);
    }
}

// NB: raw-pointer IterBytes does _not_ dereference
// to the target; it just gives you the pointer-bytes.
impl<A> *const A: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as uint).iter_bytes(lsb0, f);
    }
}

trait ToBytes {
    fn to_bytes(lsb0: bool) -> ~[u8];
}

impl<A: IterBytes> A: ToBytes {
    fn to_bytes(lsb0: bool) -> ~[u8] {
        do io::with_bytes_writer |wr| {
            for self.iter_bytes(lsb0) |bytes| {
                wr.write(bytes)
            }
        }
    }
}
<commit_msg>libcore/to_bytes.rs: add IterBytes impls for pairs and triples. r=pcwalton<commit_after>/*!

The `ToBytes` and `IterBytes` traits

*/

// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];

use io::Writer;

pub type Cb = fn(buf: &[const u8]) -> bool;

/**
 * A trait to implement in order to make a type hashable;
 * This works in combination with the trait `Hash::Hash`, and
 * may in the future be merged with that trait or otherwise
 * modified when default methods and trait inheritence are
 * completed.
 */
pub trait IterBytes {
    /**
     * Call the provided callback `f` one or more times with
     * byte-slices that should be used when computing a hash
     * value or otherwise "flattening" the structure into
     * a sequence of bytes. The `lsb0` parameter conveys
     * whether the caller is asking for little-endian bytes
     * (`true`) or big-endian (`false`); this should only be
     * relevant in implementations that represent a single
     * multi-byte datum such as a 32 bit integer or 64 bit
     * floating-point value. It can be safely ignored for
     * larger structured types as they are usually processed
     * left-to-right in declaration order, regardless of
     * underlying memory endianness.
     */
    pure fn iter_bytes(lsb0: bool, f: Cb);
}

impl bool: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(_lsb0: bool, f: Cb) {
        f([
            self as u8
        ]);
    }
}

impl u8: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(_lsb0: bool, f: Cb) {
        f([
            self
        ]);
    }
}

impl u16: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        if lsb0 {
            f([
                self as u8,
                (self >> 8) as u8
            ]);
        } else {
            f([
                (self >> 8) as u8,
                self as u8
            ]);
        }
    }
}

impl u32: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        if lsb0 {
            f([
                self as u8,
                (self >> 8) as u8,
                (self >> 16) as u8,
                (self >> 24) as u8,
            ]);
        } else {
            f([
                (self >> 24) as u8,
                (self >> 16) as u8,
                (self >> 8) as u8,
                self as u8
            ]);
        }
    }
}

impl u64: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        if lsb0 {
            f([
                self as u8,
                (self >> 8) as u8,
                (self >> 16) as u8,
                (self >> 24) as u8,
                (self >> 32) as u8,
                (self >> 40) as u8,
                (self >> 48) as u8,
                (self >> 56) as u8
            ]);
        } else {
            f([
                (self >> 56) as u8,
                (self >> 48) as u8,
                (self >> 40) as u8,
                (self >> 32) as u8,
                (self >> 24) as u8,
                (self >> 16) as u8,
                (self >> 8) as u8,
                self as u8
            ]);
        }
    }
}

impl i8: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as u8).iter_bytes(lsb0, f)
    }
}

impl i16: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as u16).iter_bytes(lsb0, f)
    }
}

impl i32: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as u32).iter_bytes(lsb0, f)
    }
}

impl i64: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as u64).iter_bytes(lsb0, f)
    }
}

impl char: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as u32).iter_bytes(lsb0, f)
    }
}

#[cfg(target_word_size = "32")]
impl uint: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as u32).iter_bytes(lsb0, f)
    }
}

#[cfg(target_word_size = "64")]
impl uint: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as u64).iter_bytes(lsb0, f)
    }
}

impl int: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as uint).iter_bytes(lsb0, f)
    }
}

impl<A: IterBytes> &[A]: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        for self.each |elt| {
            do elt.iter_bytes(lsb0) |bytes| {
                f(bytes)
            }
        }
    }
}

impl<A: IterBytes, B: IterBytes> (A,B): IterBytes {
  #[inline(always)]
  pure fn iter_bytes(lsb0: bool, f: Cb) {
    let &(ref a, ref b) = &self;
    a.iter_bytes(lsb0, f);
    b.iter_bytes(lsb0, f);
  }
}

impl<A: IterBytes, B: IterBytes, C: IterBytes> (A,B,C): IterBytes {
  #[inline(always)]
  pure fn iter_bytes(lsb0: bool, f: Cb) {
    let &(ref a, ref b, ref c) = &self;
    a.iter_bytes(lsb0, f);
    b.iter_bytes(lsb0, f);
    c.iter_bytes(lsb0, f);
  }
}

// Move this to vec, probably.
pure fn borrow<A>(a: &x/[A]) -> &x/[A] {
    a
}

impl<A: IterBytes> ~[A]: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        borrow(self).iter_bytes(lsb0, f)
    }
}

impl<A: IterBytes> @[A]: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        borrow(self).iter_bytes(lsb0, f)
    }
}

pub pure fn iter_bytes_2<A: IterBytes, B: IterBytes>(a: &A, b: &B,
                                            lsb0: bool, z: Cb) {
    let mut flag = true;
    a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}

pub pure fn iter_bytes_3<A: IterBytes,
                B: IterBytes,
                C: IterBytes>(a: &A, b: &B, c: &C,
                              lsb0: bool, z: Cb) {
    let mut flag = true;
    a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}

pub pure fn iter_bytes_4<A: IterBytes,
                B: IterBytes,
                C: IterBytes,
                D: IterBytes>(a: &A, b: &B, c: &C,
                              d: &D,
                              lsb0: bool, z: Cb) {
    let mut flag = true;
    a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    d.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}

pub pure fn iter_bytes_5<A: IterBytes,
                B: IterBytes,
                C: IterBytes,
                D: IterBytes,
                E: IterBytes>(a: &A, b: &B, c: &C,
                              d: &D, e: &E,
                              lsb0: bool, z: Cb) {
    let mut flag = true;
    a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    d.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    e.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}

pub pure fn iter_bytes_6<A: IterBytes,
                B: IterBytes,
                C: IterBytes,
                D: IterBytes,
                E: IterBytes,
                F: IterBytes>(a: &A, b: &B, c: &C,
                              d: &D, e: &E, f: &F,
                              lsb0: bool, z: Cb) {
    let mut flag = true;
    a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    d.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    e.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    f.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}

pub pure fn iter_bytes_7<A: IterBytes,
                B: IterBytes,
                C: IterBytes,
                D: IterBytes,
                E: IterBytes,
                F: IterBytes,
                G: IterBytes>(a: &A, b: &B, c: &C,
                              d: &D, e: &E, f: &F,
                              g: &G,
                              lsb0: bool, z: Cb) {
    let mut flag = true;
    a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    d.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    e.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    f.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
    if !flag { return; }
    g.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
}

impl &str: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(_lsb0: bool, f: Cb) {
        do str::byte_slice(self) |bytes| {
            f(bytes);
        }
    }
}

impl ~str: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(_lsb0: bool, f: Cb) {
        do str::byte_slice(self) |bytes| {
            f(bytes);
        }
    }
}

impl @str: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(_lsb0: bool, f: Cb) {
        do str::byte_slice(self) |bytes| {
            f(bytes);
        }
    }
}

impl<A: IterBytes> Option<A>: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        match self {
          Some(ref a) => iter_bytes_2(&0u8, a, lsb0, f),
          None => 1u8.iter_bytes(lsb0, f)
        }
    }
}

impl<A: IterBytes> &A: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (*self).iter_bytes(lsb0, f);
    }
}

impl<A: IterBytes> @A: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (*self).iter_bytes(lsb0, f);
    }
}

impl<A: IterBytes> ~A: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (*self).iter_bytes(lsb0, f);
    }
}

// NB: raw-pointer IterBytes does _not_ dereference
// to the target; it just gives you the pointer-bytes.
impl<A> *const A: IterBytes {
    #[inline(always)]
    pure fn iter_bytes(lsb0: bool, f: Cb) {
        (self as uint).iter_bytes(lsb0, f);
    }
}

trait ToBytes {
    fn to_bytes(lsb0: bool) -> ~[u8];
}

impl<A: IterBytes> A: ToBytes {
    fn to_bytes(lsb0: bool) -> ~[u8] {
        do io::with_bytes_writer |wr| {
            for self.iter_bytes(lsb0) |bytes| {
                wr.write(bytes)
            }
        }
    }
}
<|endoftext|>


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

pub struct MultiFile {
    files_iterator: Box<Iterator<Item = String>>,
    current_file: Option<File>,
}

impl MultiFile {
    pub fn new(filenames: Vec<String>) -> MultiFile {
        MultiFile {
            files_iterator: Box::new(filenames.into_iter()),
            current_file: None,
        }
    }
}

impl io::Read for MultiFile {
    fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
        let read_size;
        {
            let mut file = match self.current_file {
                Some(ref file) => file,
                None => {
                    self.current_file = match &self.files_iterator.next() {
                        Some(file) => Some(File::open(file)?),
                        None => {
                            return Ok(0);
                        }
                    };
                    return self.read(&mut buf);
                }
            };
            read_size = file.read(buf);
        }

        match read_size {
            Ok(0) => {
                self.current_file = match &self.files_iterator.next() {
                    Some(file) => Some(File::open(file).unwrap()),
                    None => {
                        return Ok(0);
                    }
                };
                return self.read(&mut buf);
            }
            Ok(read_size) => Ok(read_size),
            Err(err) => Err(err),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::Read;
    use std::io::BufRead;

    use super::*;

    #[test]
    fn test_read_all() {
        let filenames = vec![
            String::from("src/test/simple-1.log"),
            String::from("src/test/simple-2.log"),
        ];
        let input = MultiFile::new(filenames);

        let reader = io::BufReader::new(input);

        let result = reader.lines().count();
        assert_eq!(result, 8);
    }

    #[test]
    fn test_read_non_existent() {
        let filenames = vec![String::from("src/test/non-existent.log")];
        let mut input = MultiFile::new(filenames);
        let mut buffer = [0; 10];
        let result = input.read(&mut buffer);

        assert!(result.is_err());
    }

    #[test]
    fn test_read_no_files_means_eof() {
        let filenames = vec![];
        let mut input = MultiFile::new(filenames);
        let mut buffer = [0; 10];
        let result = input.read(&mut buffer);

        assert!(result.is_ok());
        assert_eq!(result.unwrap(), 0);
    }
}
<commit_msg>Handle non-existent files that are not the 1st file<commit_after>use io;
use std::fs::File;

pub struct MultiFile {
    files_iterator: Box<Iterator<Item = String>>,
    current_file: Option<File>,
}

impl MultiFile {
    pub fn new(filenames: Vec<String>) -> MultiFile {
        MultiFile {
            files_iterator: Box::new(filenames.into_iter()),
            current_file: None,
        }
    }
}

impl io::Read for MultiFile {
    fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
        let read_size;
        {
            let mut file = match self.current_file {
                Some(ref file) => file,
                None => {
                    self.current_file = match &self.files_iterator.next() {
                        Some(file) => Some(File::open(file)?),
                        None => {
                            return Ok(0);
                        }
                    };
                    return self.read(&mut buf);
                }
            };
            read_size = file.read(buf);
        }

        match read_size {
            Ok(0) => {
                self.current_file = match &self.files_iterator.next() {
                    Some(file) => Some(File::open(file)?),
                    None => {
                        return Ok(0);
                    }
                };
                return self.read(&mut buf);
            }
            Ok(read_size) => Ok(read_size),
            Err(err) => Err(err),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::Read;
    use std::io::BufRead;

    use super::*;

    #[test]
    fn test_read_all() {
        let filenames = vec![
            String::from("src/test/simple-1.log"),
            String::from("src/test/simple-2.log"),
        ];
        let input = MultiFile::new(filenames);

        let reader = io::BufReader::new(input);

        let result = reader.lines().count();
        assert_eq!(result, 8);
    }

    #[test]
    fn test_read_non_existent() {
        let filenames = vec![String::from("src/test/non-existent.log")];
        let mut input = MultiFile::new(filenames);
        let mut buffer = [0; 10];
        let result = input.read(&mut buffer);

        assert!(result.is_err());
    }

    #[test]
    fn test_read_second_non_existent() {
        let filenames = vec![
            String::from("src/test/empty.log"),
            String::from("src/test/non-existent.log"),
        ];
        let mut input = MultiFile::new(filenames);
        let mut buffer = [0; 10];
        let result = input.read(&mut buffer);

        assert!(result.is_err());
    }

    #[test]
    fn test_read_no_files_means_eof() {
        let filenames = vec![];
        let mut input = MultiFile::new(filenames);
        let mut buffer = [0; 10];
        let result = input.read(&mut buffer);

        assert!(result.is_ok());
        assert_eq!(result.unwrap(), 0);
    }
}
<|endoftext|>


<commit_before>// OpenAOE: An open source reimplementation of Age of Empires (1997)
// Copyright (c) 2016 Kevin Fuller
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use nalgebra::Vector2;

use std::collections::{HashMap, HashSet};

#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
struct CellKey {
    row: i32,
    col: i32,
}

impl CellKey {
    pub fn new(row: i32, col: i32) -> CellKey {
        CellKey {
            row: row,
            col: col,
        }
    }
}

struct Cell {
    entities: Vec<u32>,
}

impl Cell {
    fn new() -> Cell {
        Cell { entities: Vec::new() }
    }

    fn add(&mut self, entity_id: u32) {
        self.entities.push(entity_id);
    }

    fn remove(&mut self, entity_id: u32) {
        if let Some(index) = self.entities.iter().position(|id| *id == entity_id) {
            self.entities.swap_remove(index);
        }
    }

    #[inline]
    fn entities<'a>(&'a self) -> &Vec<u32> {
        &self.entities
    }
}

pub struct GridPartition {
    cell_width: i32,
    cell_height: i32,
    entities: HashMap<u32, CellKey>,
    cells: HashMap<CellKey, Cell>,
}

/// Infinite grid spatial partition
impl GridPartition {
    pub fn new(cell_width: i32, cell_height: i32) -> GridPartition {
        GridPartition {
            cell_width: cell_width,
            cell_height: cell_height,
            entities: HashMap::new(),
            cells: HashMap::new(),
        }
    }

    /// Tells the grid where an entity is so that it can be queried later
    pub fn update_entity(&mut self, entity_id: u32, position: &Vector2<i32>) {
        let cell_key = self.cell_key(&position);
        if !self.entities.contains_key(&entity_id) {
            self.entities.insert(entity_id, cell_key);
        } else {
            let old_cell_key = *self.entities.get(&entity_id).unwrap();
            self.remove_from_cell(old_cell_key, entity_id);
        }
        self.add_to_cell(cell_key, entity_id);
    }

    /// Returns the entity IDs that lie in the cells overlapped by the given bounds
    /// Note: the returned entity IDs can lie outside of the bounds
    pub fn query(&self, start_position: &Vector2<i32>, end_position: &Vector2<i32>) -> HashSet<u32> {
        let start = self.row_col(start_position);
        let end = self.row_col(end_position);

        let mut entities = HashSet::new();
        for row in start.y..(end.y + 1) {
            for col in start.x..(end.x + 1) {
                if let Some(cell) = self.cell(CellKey::new(row, col)) {
                    entities.extend(cell.entities().iter());
                }
            }
        }
        entities
    }

    pub fn contains(&self, entity_id: u32) -> bool {
        self.entities.contains_key(&entity_id)
    }

    fn add_to_cell(&mut self, cell_key: CellKey, entity_id: u32) {
        self.cell_mut(cell_key).add(entity_id);
    }

    fn remove_from_cell(&mut self, cell_key: CellKey, entity_id: u32) {
        self.cell_mut(cell_key).remove(entity_id);
    }

    #[inline]
    fn cell<'a>(&'a self, cell_key: CellKey) -> Option<&'a Cell> {
        self.cells.get(&cell_key)
    }

    fn cell_mut<'a>(&'a mut self, cell_key: CellKey) -> &'a mut Cell {
        if !self.cells.contains_key(&cell_key) {
            self.cells.insert(cell_key, Cell::new());
        }
        self.cells.get_mut(&cell_key).unwrap()
    }

    fn cell_key(&self, position: &Vector2<i32>) -> CellKey {
        let row_col = self.row_col(position);
        CellKey::new(row_col.y, row_col.x)
    }

    fn row_col(&self, position: &Vector2<i32>) -> Vector2<i32> {
        Vector2::new(position.x / self.cell_width, position.y / self.cell_height)
    }
}

#[cfg(test)]
mod tests {
    use super::{Cell, CellKey, GridPartition};
    use nalgebra::Vector2;
    use std::collections::HashSet;

    macro_rules! ids {
        [ $($id:expr),* ] => {
            {
                let mut set: HashSet<u32> = HashSet::new();
                $(set.insert($id);)*
                set
            }
        }
    }

    fn v(x: i32, y: i32) -> Vector2<i32> {
        Vector2::new(x, y)
    }

    #[test]
    fn test_cell_add_remove() {
        let mut cell = Cell::new();
        cell.remove(5); // shouldn't panic

        cell.add(4);
        assert_eq!(&vec![4], cell.entities());

        cell.add(5);
        cell.add(6);
        assert_eq!(&vec![4, 5, 6], cell.entities());

        cell.remove(4);
        assert_eq!(&vec![6, 5], cell.entities());
    }

    #[test]
    fn test_cell_key_from_position() {
        let grid = GridPartition::new(10, 10);
        assert_eq!(CellKey::new(0, 0), grid.cell_key(&v(0, 0)));
        assert_eq!(CellKey::new(0, 0), grid.cell_key(&v(5, 5)));
        assert_eq!(CellKey::new(0, 1), grid.cell_key(&v(10, 5)));
        assert_eq!(CellKey::new(1, 0), grid.cell_key(&v(5, 10)));
    }

    #[test]
    fn test_grid_update_entity() {
        let mut grid = GridPartition::new(10, 10);
        grid.update_entity(1, &v(5, 5));
        grid.update_entity(2, &v(15, 5));

        assert_eq!(&vec![1], grid.cell_mut(CellKey::new(0, 0)).entities());
        assert_eq!(&vec![2], grid.cell_mut(CellKey::new(0, 1)).entities());

        grid.update_entity(1, &v(25, 15));
        assert!(grid.cell_mut(CellKey::new(0, 0)).entities().is_empty());
        assert_eq!(&vec![2], grid.cell_mut(CellKey::new(0, 1)).entities());
        assert_eq!(&vec![1], grid.cell_mut(CellKey::new(1, 2)).entities());
    }

    #[test]
    fn test_grid_query() {
        let mut grid = GridPartition::new(10, 10);
        grid.update_entity(1, &v(5, 5));
        grid.update_entity(2, &v(6, 5));
        grid.update_entity(3, &v(15, 5));
        grid.update_entity(4, &v(5, 15));

        assert_eq!(ids![1, 2], grid.query(&v(1, 1), &v(9, 9)));
        assert_eq!(ids![1, 2, 3, 4], grid.query(&v(0, 0), &v(20, 20)));
        assert_eq!(ids![1, 2, 3, 4], grid.query(&v(9, 0), &v(20, 10)));
        assert_eq!(ids![3], grid.query(&v(10, 0), &v(20, 10)));
    }
}
<commit_msg>Store positions in the GridPartition<commit_after>// OpenAOE: An open source reimplementation of Age of Empires (1997)
// Copyright (c) 2016 Kevin Fuller
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use nalgebra::Vector2;

use std::collections::{HashMap, HashSet};

#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
struct CellKey {
    row: i32,
    col: i32,
}

impl CellKey {
    pub fn new(row: i32, col: i32) -> CellKey {
        CellKey {
            row: row,
            col: col,
        }
    }
}

struct Cell {
    entities: Vec<GridEntity>,
}

impl Cell {
    fn new() -> Cell {
        Cell { entities: Vec::new() }
    }

    fn add(&mut self, entity: GridEntity) {
        self.entities.push(entity);
    }

    fn remove(&mut self, entity_id: u32) {
        if let Some(index) = self.entities.iter().position(|entity| entity.entity_id == entity_id) {
            self.entities.swap_remove(index);
        }
    }

    #[inline]
    fn entities<'a>(&'a self) -> &Vec<GridEntity> {
        &self.entities
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct GridEntity {
    entity_id: u32,
    position: Vector2<i32>,
}

impl GridEntity {
    fn new(entity_id: u32, position: Vector2<i32>) -> GridEntity {
        GridEntity {
            entity_id: entity_id,
            position: position,
        }
    }
}

pub struct GridPartition {
    cell_width: i32,
    cell_height: i32,
    entities: HashMap<u32, CellKey>,
    cells: HashMap<CellKey, Cell>,
}

/// Infinite grid spatial partition
impl GridPartition {
    pub fn new(cell_width: i32, cell_height: i32) -> GridPartition {
        GridPartition {
            cell_width: cell_width,
            cell_height: cell_height,
            entities: HashMap::new(),
            cells: HashMap::new(),
        }
    }

    /// Tells the grid where an entity is so that it can be queried later
    pub fn update_entity(&mut self, entity_id: u32, position: &Vector2<i32>) {
        let cell_key = self.cell_key(&position);
        if !self.entities.contains_key(&entity_id) {
            self.entities.insert(entity_id, cell_key);
        } else {
            let old_cell_key = *self.entities.get(&entity_id).unwrap();
            self.remove_from_cell(old_cell_key, entity_id);
        }
        self.add_to_cell(cell_key, GridEntity::new(entity_id, *position));
    }

    /// Returns the entity IDs that lie in the cells overlapped by the given bounds
    /// Note: the returned entity IDs can lie outside of the bounds
    pub fn query(&self, start_position: &Vector2<i32>, end_position: &Vector2<i32>) -> HashSet<u32> {
        let start = self.row_col(start_position);
        let end = self.row_col(end_position);

        let mut entities = HashSet::new();
        for row in start.y..(end.y + 1) {
            for col in start.x..(end.x + 1) {
                if let Some(cell) = self.cell(CellKey::new(row, col)) {
                    for entity in cell.entities() {
                        if entity.position.x >= start_position.x &&
                            entity.position.x <= end_position.x &&
                            entity.position.y >= start_position.y &&
                            entity.position.y <= end_position.y {
                            entities.insert(entity.entity_id);
                        }
                    }
                }
            }
        }
        entities
    }

    pub fn contains(&self, entity_id: u32) -> bool {
        self.entities.contains_key(&entity_id)
    }

    fn add_to_cell(&mut self, cell_key: CellKey, entity: GridEntity) {
        self.cell_mut(cell_key).add(entity);
    }

    fn remove_from_cell(&mut self, cell_key: CellKey, entity_id: u32) {
        self.cell_mut(cell_key).remove(entity_id);
    }

    #[inline]
    fn cell<'a>(&'a self, cell_key: CellKey) -> Option<&'a Cell> {
        self.cells.get(&cell_key)
    }

    fn cell_mut<'a>(&'a mut self, cell_key: CellKey) -> &'a mut Cell {
        if !self.cells.contains_key(&cell_key) {
            self.cells.insert(cell_key, Cell::new());
        }
        self.cells.get_mut(&cell_key).unwrap()
    }

    fn cell_key(&self, position: &Vector2<i32>) -> CellKey {
        let row_col = self.row_col(position);
        CellKey::new(row_col.y, row_col.x)
    }

    fn row_col(&self, position: &Vector2<i32>) -> Vector2<i32> {
        Vector2::new(position.x / self.cell_width, position.y / self.cell_height)
    }
}

#[cfg(test)]
mod tests {
    use super::{Cell, CellKey, GridEntity, GridPartition};
    use nalgebra::Vector2;
    use std::collections::HashSet;

    macro_rules! ids {
        [ $($id:expr),* ] => {
            {
                let mut set: HashSet<u32> = HashSet::new();
                $(set.insert($id);)*
                set
            }
        }
    }

    fn v(x: i32, y: i32) -> Vector2<i32> {
        Vector2::new(x, y)
    }

    #[test]
    fn test_cell_add_remove() {
        let mut cell = Cell::new();
        cell.remove(5); // shouldn't panic

        let entity4 = GridEntity::new(4, Vector2::new(0, 0));
        let entity5 = GridEntity::new(5, Vector2::new(1, 0));
        let entity6 = GridEntity::new(6, Vector2::new(0, 2));

        cell.add(entity4);
        assert_eq!(&vec![entity4], cell.entities());

        cell.add(entity5);
        cell.add(entity6);
        assert_eq!(&vec![entity4, entity5, entity6], cell.entities());

        cell.remove(4);
        assert_eq!(&vec![entity6, entity5], cell.entities());
    }

    #[test]
    fn test_cell_key_from_position() {
        let grid = GridPartition::new(10, 10);
        assert_eq!(CellKey::new(0, 0), grid.cell_key(&v(0, 0)));
        assert_eq!(CellKey::new(0, 0), grid.cell_key(&v(5, 5)));
        assert_eq!(CellKey::new(0, 1), grid.cell_key(&v(10, 5)));
        assert_eq!(CellKey::new(1, 0), grid.cell_key(&v(5, 10)));
    }

    #[test]
    fn test_grid_update_entity() {
        let mut grid = GridPartition::new(10, 10);
        grid.update_entity(1, &v(5, 5));
        grid.update_entity(2, &v(15, 5));

        let entity1 = GridEntity::new(1, Vector2::new(5, 5));
        let entity2 = GridEntity::new(2, Vector2::new(15, 5));

        assert_eq!(&vec![entity1], grid.cell_mut(CellKey::new(0, 0)).entities());
        assert_eq!(&vec![entity2], grid.cell_mut(CellKey::new(0, 1)).entities());

        grid.update_entity(1, &v(25, 15));
        let entity1 = GridEntity::new(1, Vector2::new(25, 15));

        assert!(grid.cell_mut(CellKey::new(0, 0)).entities().is_empty());
        assert_eq!(&vec![entity2], grid.cell_mut(CellKey::new(0, 1)).entities());
        assert_eq!(&vec![entity1], grid.cell_mut(CellKey::new(1, 2)).entities());
    }

    #[test]
    fn test_grid_query() {
        let mut grid = GridPartition::new(10, 10);
        grid.update_entity(1, &v(5, 5));
        grid.update_entity(2, &v(6, 5));
        grid.update_entity(3, &v(15, 5));
        grid.update_entity(4, &v(5, 15));

        assert_eq!(ids![1, 2], grid.query(&v(1, 1), &v(9, 9)));
        assert_eq!(ids![1, 2, 3, 4], grid.query(&v(0, 0), &v(20, 20)));
        assert_eq!(ids![3], grid.query(&v(9, 0), &v(20, 10)));
        assert_eq!(ids![3], grid.query(&v(10, 0), &v(20, 10)));
    }
}
<|endoftext|>


<commit_before>//! (see [`lower_simpleast`](lower_simpleast))

use super::simple_ast as sast;
use middle::ir;
use middle::ir::MOpcode as IrOpcode;
use middle::ssa::cfg_traits::{CFGMod, CFG};
use middle::ssa::ssa_traits::{SSAExtra, SSAMod, ValueInfo, ValueType, SSA};
use middle::ssa::ssastorage::{NodeData, SSAStorage};
use std::collections::HashMap;
use std::error;
use std::fmt;
use std::mem;

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

/// Lowers [AST](sast) into the provided [`SSAStorage`](SSAStorage)
pub fn lower_simpleast<'a>(ssa: &'a mut SSAStorage, sfn: sast::Function) -> Result<()> {
    LowerSsa::new(ssa).lower_function(sfn)
}

#[derive(Debug)]
pub enum LoweringError {
    /// If an operation on the [`SSAStorage`](SSAStorage) fails
    SsaError,
    /// If the AST was invalid somehow
    InvalidAst(String),
}

type SSABlock = <SSAStorage as CFG>::ActionRef;
type SSAValue = <SSAStorage as SSA>::ValueRef;

/// from [`ssaconstructor`](::frontend::ssaconstructor)
const FALSE_EDGE: u8 = 0;
const TRUE_EDGE: u8 = 1;
const UNCOND_EDGE: u8 = 2;

struct LowerSsa<'a> {
    ssa: &'a mut SSAStorage,
    blocks: HashMap<ir::MAddress, SSABlock>,
    values: HashMap<sast::ValueRef, SSAValue>,
    regnames: Vec<sast::PhysReg>,
}

impl<'a> LowerSsa<'a> {
    fn new(ssa: &'a mut SSAStorage) -> Self {
        LowerSsa {
            ssa,
            blocks: HashMap::new(),
            values: HashMap::new(),
            regnames: Vec::new(),
        }
    }

    fn lower_function(mut self, sfn: sast::Function) -> Result<()> {
        self.regnames = sfn.register_list;
        if self.regnames.len() >= u8::max_value() as usize {
            return Err(LoweringError::InvalidAst(format!(
                "too many registers: {}",
                self.regnames.len()
            )));
        }

        let exit_node = self.ssa.insert_dynamic()?;
        self.ssa.set_exit_node(exit_node);

        let entry_node = self.ssa.insert_block(ir::MAddress::new(0, 0))?;
        self.ssa.set_entry_node(entry_node);

        // when we're lowering a block, we need to know what block comes afterwards;
        // so when we iterate over the blocks, we lower the *previous* block we saw,
        // so then that block's next block is just the current block
        let mut opt_prev_sbb: Option<sast::BasicBlock> = None;
        for sbb in sfn.basic_blocks {
            let sbb_addr = sbb.addr;
            if let Some(prev_sbb) = mem::replace(&mut opt_prev_sbb, Some(sbb)) {
                // lower `prev`; `sbb` is `prev`'s next
                self.lower_basicblock(prev_sbb, Some(sbb_addr))?;
            } else {
                // `sbb` is the first block
                let bb = self.block_at(sbb_addr)?;
                self.ssa.insert_control_edge(entry_node, bb, UNCOND_EDGE);
            }
        }
        if let Some(last_sbb) = opt_prev_sbb {
            // lower the last block
            self.lower_basicblock(last_sbb, None)?;
        } else {
            // there were 0 blocks
            // I think this is a sane thing to do in this case :P
            self.ssa
                .insert_control_edge(entry_node, exit_node, UNCOND_EDGE);
        }

        let final_state = self.ssa.registers_in(exit_node)?;
        for (sreg, sop) in sfn.final_reg_state {
            // a bit of a hack...
            let reg_idx = if sreg.0 != "mem" {
                self.index_of_reg(&sreg)?
            } else {
                self.regnames.len() as u8
            };
            let op = self.lower_operand(sop)?;
            self.ssa.op_use(final_state, reg_idx, op);
        }

        self.ssa
            .map_registers(self.regnames.into_iter().map(|x| x.0).collect());

        Ok(())
    }

    fn lower_basicblock(
        &mut self,
        sbb: sast::BasicBlock,
        opt_next_addr: Option<ir::MAddress>,
    ) -> Result<()> {
        let bb = self.block_at(sbb.addr)?;

        for sop in sbb.ops {
            let (res, opt_op_addr) = self.lower_operation(sop)?;
            let op_addr = opt_op_addr.unwrap_or(sbb.addr);
            self.ssa.insert_into_block(res, bb, op_addr);
        }

        // can't use `map_or_else` because either operation may fail
        let next_node = if let Some(next_addr) = opt_next_addr {
            self.block_at(next_addr)?
        } else {
            self.ssa.exit_node()?
        };
        match sbb.jump {
            Some(sast::Jump::Uncond(tgt)) => {
                let tgt_bb = self.block_at(tgt)?;
                self.ssa.insert_control_edge(bb, tgt_bb, UNCOND_EDGE);
            }
            Some(sast::Jump::Cond(sel_sop, if_tgt, opt_else_tgt)) => {
                let sel_op = self.lower_operand(sel_sop)?;
                let if_bb = self.block_at(if_tgt)?;
                let else_bb = opt_else_tgt.map_or(Ok(next_node), |a| self.block_at(a))?;
                self.ssa.set_selector(sel_op, bb);
                self.ssa.insert_control_edge(bb, if_bb, TRUE_EDGE);
                self.ssa.insert_control_edge(bb, else_bb, FALSE_EDGE);
            }
            None => {
                // fallthrough to `next`
                self.ssa.insert_control_edge(bb, next_node, UNCOND_EDGE);
            }
        }

        Ok(())
    }

    fn lower_operation(
        &mut self,
        sopn: sast::Operation,
    ) -> Result<(SSAValue, Option<ir::MAddress>)> {
        Ok(match sopn {
            sast::Operation::Phi(vr, ty, sops) => {
                let vi = lower_valueinfo(ty);
                let res = self.ssa.insert_phi(vi)?;
                for sop in sops.into_iter().rev() {
                    let op = self.lower_operand(sop)?;
                    self.ssa.phi_use(res, op);
                }
                self.values.insert(vr, res);
                (res, None)
            }

            sast::Operation::Assign(opt_addr, vr, ty, sexpr) => {
                let vi = lower_valueinfo(ty);
                let (opcode, sops) = match sexpr {
                    sast::Expr::Infix(sop0, sopcode, sop1) => {
                        (lower_infix_op(sopcode), vec![sop0, sop1])
                    }
                    sast::Expr::Prefix(sopcode, sop0) => (lower_prefix_op(sopcode), vec![sop0]),
                    sast::Expr::Load(sop0, sop1) => (IrOpcode::OpLoad, vec![sop0, sop1]),
                    sast::Expr::Store(sop0, sop1, sop2) => {
                        (IrOpcode::OpStore, vec![sop0, sop1, sop2])
                    }
                    sast::Expr::Resize(rst, ws, sop0) => (lower_resize_op(rst, ws), vec![sop0]),
                };
                let res = self.ssa.insert_op(opcode, vi, None)?;
                for (i, sop) in sops.into_iter().enumerate() {
                    let op = self.lower_operand(sop)?;
                    self.ssa.op_use(res, i as u8, op);
                }
                self.values.insert(vr, res);
                (res, opt_addr)
            }

            sast::Operation::Call(opt_addr, tgt, sargs) => {
                // TODO: round-trip call `ValueInfo`
                let vi = ValueInfo::new_unresolved(ir::WidthSpec::Unknown);
                let res = self.ssa.insert_op(IrOpcode::OpCall, vi, None)?;
                let tgt_op = self.lower_operand(tgt)?;
                self.ssa.op_use(res, 0, tgt_op);
                for sarg in sargs {
                    let reg_idx = self.index_of_reg(&sarg.formal)?;
                    let op = self.lower_operand(sarg.actual)?;
                    self.ssa.op_use(res, reg_idx + 1, op);
                }
                (res, opt_addr)
            }
        })
    }

    fn lower_operand(&mut self, sop: sast::Operand) -> Result<SSAValue> {
        match sop {
            sast::Operand::Comment(s) => {
                // TODO: round-trip comment `ValueInfo`
                let vi = ValueInfo::new_unresolved(ir::WidthSpec::Unknown);
                Ok(self.ssa.insert_comment(vi, s)?)
            }
            sast::Operand::ValueRef(r) => {
                if let Some(x) = self.values.get(&r).cloned() {
                    Ok(x)
                } else {
                    Err(LoweringError::InvalidAst(format!(
                        "no value reference: %{}",
                        r.0
                    )))
                }
            }
            sast::Operand::Const(v) => Ok(self.ssa.insert_const(v)?),
        }
    }

    fn block_at(&mut self, at: ir::MAddress) -> Result<SSABlock> {
        use std::collections::hash_map::Entry;
        // can't use `or_insert_with` because `ssa.insert_block` may fail
        Ok(*match self.blocks.entry(at) {
            Entry::Occupied(o) => o.into_mut(),
            Entry::Vacant(v) => v.insert(self.ssa.insert_block(at)?),
        })
    }

    fn index_of_reg(&self, sreg: &sast::PhysReg) -> Result<u8> {
        // TODO: more efficient as a HashMap<Reg, u8>?
        if let Some(x) = self.regnames.iter().position(|r| r == sreg) {
            // we already checked that `regnames.len() < u8::max_value()`
            Ok(x as u8)
        } else {
            Err(LoweringError::InvalidAst(format!(
                "no physical register: {}",
                sreg.0
            )))
        }
    }
}

fn lower_infix_op(siop: sast::InfixOp) -> IrOpcode {
    match siop {
        sast::InfixOp::Add => IrOpcode::OpAdd,
        sast::InfixOp::Sub => IrOpcode::OpSub,
        sast::InfixOp::Mul => IrOpcode::OpMul,
        sast::InfixOp::Div => IrOpcode::OpDiv,
        sast::InfixOp::Mod => IrOpcode::OpMod,
        sast::InfixOp::And => IrOpcode::OpAnd,
        sast::InfixOp::Or => IrOpcode::OpOr,
        sast::InfixOp::Xor => IrOpcode::OpXor,
        sast::InfixOp::Eq => IrOpcode::OpEq,
        sast::InfixOp::Gt => IrOpcode::OpGt,
        sast::InfixOp::Lt => IrOpcode::OpLt,
        sast::InfixOp::Lsl => IrOpcode::OpLsl,
        sast::InfixOp::Lsr => IrOpcode::OpLsr,
    }
}

fn lower_prefix_op(spop: sast::PrefixOp) -> IrOpcode {
    match spop {
        sast::PrefixOp::Not => IrOpcode::OpNot,
    }
}

fn lower_resize_op(srst: sast::ResizeType, sws: sast::WidthSpec) -> IrOpcode {
    match srst {
        sast::ResizeType::Narrow => IrOpcode::OpNarrow(sws.0),
        sast::ResizeType::SignExt => IrOpcode::OpSignExt(sws.0),
        sast::ResizeType::ZeroExt => IrOpcode::OpZeroExt(sws.0),
    }
}

fn lower_valueinfo(sty: sast::Type) -> ValueInfo {
    let ws = ir::WidthSpec::Known((sty.0).0);
    match sty.1 {
        sast::RefSpec::Scalar => ValueInfo::new_scalar(ws),
        sast::RefSpec::Reference => ValueInfo::new_reference(ws),
        sast::RefSpec::Unknown => ValueInfo::new_unresolved(ws),
    }
}

/// [`SSAStorage`][SSAStorage] methods return `Option`,
/// so we convert `None`s into [`SsaError`][LoweringError::SsaError]
impl From<::std::option::NoneError> for LoweringError {
    fn from(_: ::std::option::NoneError) -> Self {
        LoweringError::SsaError
    }
}

impl error::Error for LoweringError {
    fn description(&self) -> &str {
        match *self {
            LoweringError::SsaError => "could not perform an `SSAStorage` operation",
            LoweringError::InvalidAst(_) => "invalid ast",
        }
    }
}

impl fmt::Display for LoweringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            LoweringError::SsaError => write!(f, "could not perform an `SSAStorage` operation"),
            LoweringError::InvalidAst(ref s) => write!(f, "invalid ast: {}", s),
        }
    }
}
<commit_msg>Fix lowering final register state<commit_after>//! (see [`lower_simpleast`](lower_simpleast))

use super::simple_ast as sast;
use middle::ir;
use middle::ir::MOpcode as IrOpcode;
use middle::ssa::cfg_traits::{CFGMod, CFG};
use middle::ssa::ssa_traits::{SSAExtra, SSAMod, ValueInfo, ValueType, SSA};
use middle::ssa::ssastorage::{NodeData, SSAStorage};
use std::collections::HashMap;
use std::error;
use std::fmt;
use std::mem;

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

/// Lowers [AST](sast) into the provided [`SSAStorage`](SSAStorage)
pub fn lower_simpleast<'a>(ssa: &'a mut SSAStorage, sfn: sast::Function) -> Result<()> {
    LowerSsa::new(ssa).lower_function(sfn)
}

#[derive(Debug)]
pub enum LoweringError {
    /// If an operation on the [`SSAStorage`](SSAStorage) fails
    SsaError,
    /// If the AST was invalid somehow
    InvalidAst(String),
}

type SSABlock = <SSAStorage as CFG>::ActionRef;
type SSAValue = <SSAStorage as SSA>::ValueRef;

/// from [`ssaconstructor`](::frontend::ssaconstructor)
const FALSE_EDGE: u8 = 0;
const TRUE_EDGE: u8 = 1;
const UNCOND_EDGE: u8 = 2;

struct LowerSsa<'a> {
    ssa: &'a mut SSAStorage,
    blocks: HashMap<ir::MAddress, SSABlock>,
    values: HashMap<sast::ValueRef, SSAValue>,
    regnames: Vec<sast::PhysReg>,
}

impl<'a> LowerSsa<'a> {
    fn new(ssa: &'a mut SSAStorage) -> Self {
        LowerSsa {
            ssa,
            blocks: HashMap::new(),
            values: HashMap::new(),
            regnames: Vec::new(),
        }
    }

    fn lower_function(mut self, sfn: sast::Function) -> Result<()> {
        self.regnames = sfn.register_list;
        if self.regnames.len() >= u8::max_value() as usize {
            return Err(LoweringError::InvalidAst(format!(
                "too many registers: {}",
                self.regnames.len()
            )));
        }

        let exit_node = self.ssa.insert_dynamic()?;
        self.ssa.set_exit_node(exit_node);

        let entry_node = self.ssa.insert_block(ir::MAddress::new(0, 0))?;
        self.ssa.set_entry_node(entry_node);

        // when we're lowering a block, we need to know what block comes afterwards;
        // so when we iterate over the blocks, we lower the *previous* block we saw,
        // so then that block's next block is just the current block
        let mut opt_prev_sbb: Option<sast::BasicBlock> = None;
        for sbb in sfn.basic_blocks {
            let sbb_addr = sbb.addr;
            if let Some(prev_sbb) = mem::replace(&mut opt_prev_sbb, Some(sbb)) {
                // lower `prev`; `sbb` is `prev`'s next
                self.lower_basicblock(prev_sbb, Some(sbb_addr))?;
            } else {
                // `sbb` is the first block
                let bb = self.block_at(sbb_addr)?;
                self.ssa.insert_control_edge(entry_node, bb, UNCOND_EDGE);
            }
        }
        if let Some(last_sbb) = opt_prev_sbb {
            // lower the last block
            self.lower_basicblock(last_sbb, None)?;
        } else {
            // there were 0 blocks
            // I think this is a sane thing to do in this case :P
            self.ssa
                .insert_control_edge(entry_node, exit_node, UNCOND_EDGE);
        }

        let mut sfinal_state: Vec<Option<SSAValue>> = vec![None; self.regnames.len() + 1];
        for (sreg, sop) in sfn.final_reg_state {
            // a bit of a hack...
            let reg_idx = if sreg.0 != "mem" {
                self.index_of_reg(&sreg)? as usize
            } else {
                self.regnames.len()
            };
            let op = self.lower_operand(sop)?;
            sfinal_state[reg_idx] = Some(op);
        }
        let final_state = self.ssa.registers_in(exit_node)?;
        for (reg_i, opt_op) in sfinal_state.into_iter().enumerate() {
            let op = if let Some(op) = opt_op {
                op
            } else {
                let cmnt = if reg_i != self.regnames.len() {
                    self.regnames[reg_i].0.clone()
                } else {
                    "mem".to_owned()
                };
                self.lower_operand(sast::Operand::Comment(cmnt))?
            };
            self.ssa.op_use(final_state, reg_i as u8, op);
        }

        self.ssa
            .map_registers(self.regnames.into_iter().map(|x| x.0).collect());

        Ok(())
    }

    fn lower_basicblock(
        &mut self,
        sbb: sast::BasicBlock,
        opt_next_addr: Option<ir::MAddress>,
    ) -> Result<()> {
        let bb = self.block_at(sbb.addr)?;

        for sop in sbb.ops {
            let (res, opt_op_addr) = self.lower_operation(sop)?;
            let op_addr = opt_op_addr.unwrap_or(sbb.addr);
            self.ssa.insert_into_block(res, bb, op_addr);
        }

        // can't use `map_or_else` because either operation may fail
        let next_node = if let Some(next_addr) = opt_next_addr {
            self.block_at(next_addr)?
        } else {
            self.ssa.exit_node()?
        };
        match sbb.jump {
            Some(sast::Jump::Uncond(tgt)) => {
                let tgt_bb = self.block_at(tgt)?;
                self.ssa.insert_control_edge(bb, tgt_bb, UNCOND_EDGE);
            }
            Some(sast::Jump::Cond(sel_sop, if_tgt, opt_else_tgt)) => {
                let sel_op = self.lower_operand(sel_sop)?;
                let if_bb = self.block_at(if_tgt)?;
                let else_bb = opt_else_tgt.map_or(Ok(next_node), |a| self.block_at(a))?;
                self.ssa.set_selector(sel_op, bb);
                self.ssa.insert_control_edge(bb, if_bb, TRUE_EDGE);
                self.ssa.insert_control_edge(bb, else_bb, FALSE_EDGE);
            }
            None => {
                // fallthrough to `next`
                self.ssa.insert_control_edge(bb, next_node, UNCOND_EDGE);
            }
        }

        Ok(())
    }

    fn lower_operation(
        &mut self,
        sopn: sast::Operation,
    ) -> Result<(SSAValue, Option<ir::MAddress>)> {
        Ok(match sopn {
            sast::Operation::Phi(vr, ty, sops) => {
                let vi = lower_valueinfo(ty);
                let res = self.ssa.insert_phi(vi)?;
                for sop in sops.into_iter().rev() {
                    let op = self.lower_operand(sop)?;
                    self.ssa.phi_use(res, op);
                }
                self.values.insert(vr, res);
                (res, None)
            }

            sast::Operation::Assign(opt_addr, vr, ty, sexpr) => {
                let vi = lower_valueinfo(ty);
                let (opcode, sops) = match sexpr {
                    sast::Expr::Infix(sop0, sopcode, sop1) => {
                        (lower_infix_op(sopcode), vec![sop0, sop1])
                    }
                    sast::Expr::Prefix(sopcode, sop0) => (lower_prefix_op(sopcode), vec![sop0]),
                    sast::Expr::Load(sop0, sop1) => (IrOpcode::OpLoad, vec![sop0, sop1]),
                    sast::Expr::Store(sop0, sop1, sop2) => {
                        (IrOpcode::OpStore, vec![sop0, sop1, sop2])
                    }
                    sast::Expr::Resize(rst, ws, sop0) => (lower_resize_op(rst, ws), vec![sop0]),
                };
                let res = self.ssa.insert_op(opcode, vi, None)?;
                for (i, sop) in sops.into_iter().enumerate() {
                    let op = self.lower_operand(sop)?;
                    self.ssa.op_use(res, i as u8, op);
                }
                self.values.insert(vr, res);
                (res, opt_addr)
            }

            sast::Operation::Call(opt_addr, tgt, sargs) => {
                // TODO: round-trip call `ValueInfo`
                let vi = ValueInfo::new_unresolved(ir::WidthSpec::Unknown);
                let res = self.ssa.insert_op(IrOpcode::OpCall, vi, None)?;
                let tgt_op = self.lower_operand(tgt)?;
                self.ssa.op_use(res, 0, tgt_op);
                for sarg in sargs {
                    let reg_idx = self.index_of_reg(&sarg.formal)?;
                    let op = self.lower_operand(sarg.actual)?;
                    self.ssa.op_use(res, reg_idx + 1, op);
                }
                (res, opt_addr)
            }
        })
    }

    fn lower_operand(&mut self, sop: sast::Operand) -> Result<SSAValue> {
        match sop {
            sast::Operand::Comment(s) => {
                // TODO: round-trip comment `ValueInfo`
                let vi = ValueInfo::new_unresolved(ir::WidthSpec::Unknown);
                Ok(self.ssa.insert_comment(vi, s)?)
            }
            sast::Operand::ValueRef(r) => {
                if let Some(x) = self.values.get(&r).cloned() {
                    Ok(x)
                } else {
                    Err(LoweringError::InvalidAst(format!(
                        "no value reference: %{}",
                        r.0
                    )))
                }
            }
            sast::Operand::Const(v) => Ok(self.ssa.insert_const(v)?),
        }
    }

    fn block_at(&mut self, at: ir::MAddress) -> Result<SSABlock> {
        use std::collections::hash_map::Entry;
        // can't use `or_insert_with` because `ssa.insert_block` may fail
        Ok(*match self.blocks.entry(at) {
            Entry::Occupied(o) => o.into_mut(),
            Entry::Vacant(v) => v.insert(self.ssa.insert_block(at)?),
        })
    }

    fn index_of_reg(&self, sreg: &sast::PhysReg) -> Result<u8> {
        // TODO: more efficient as a HashMap<Reg, u8>?
        if let Some(x) = self.regnames.iter().position(|r| r == sreg) {
            // we already checked that `regnames.len() < u8::max_value()`
            Ok(x as u8)
        } else {
            Err(LoweringError::InvalidAst(format!(
                "no physical register: {}",
                sreg.0
            )))
        }
    }
}

fn lower_infix_op(siop: sast::InfixOp) -> IrOpcode {
    match siop {
        sast::InfixOp::Add => IrOpcode::OpAdd,
        sast::InfixOp::Sub => IrOpcode::OpSub,
        sast::InfixOp::Mul => IrOpcode::OpMul,
        sast::InfixOp::Div => IrOpcode::OpDiv,
        sast::InfixOp::Mod => IrOpcode::OpMod,
        sast::InfixOp::And => IrOpcode::OpAnd,
        sast::InfixOp::Or => IrOpcode::OpOr,
        sast::InfixOp::Xor => IrOpcode::OpXor,
        sast::InfixOp::Eq => IrOpcode::OpEq,
        sast::InfixOp::Gt => IrOpcode::OpGt,
        sast::InfixOp::Lt => IrOpcode::OpLt,
        sast::InfixOp::Lsl => IrOpcode::OpLsl,
        sast::InfixOp::Lsr => IrOpcode::OpLsr,
    }
}

fn lower_prefix_op(spop: sast::PrefixOp) -> IrOpcode {
    match spop {
        sast::PrefixOp::Not => IrOpcode::OpNot,
    }
}

fn lower_resize_op(srst: sast::ResizeType, sws: sast::WidthSpec) -> IrOpcode {
    match srst {
        sast::ResizeType::Narrow => IrOpcode::OpNarrow(sws.0),
        sast::ResizeType::SignExt => IrOpcode::OpSignExt(sws.0),
        sast::ResizeType::ZeroExt => IrOpcode::OpZeroExt(sws.0),
    }
}

fn lower_valueinfo(sty: sast::Type) -> ValueInfo {
    let ws = ir::WidthSpec::Known((sty.0).0);
    match sty.1 {
        sast::RefSpec::Scalar => ValueInfo::new_scalar(ws),
        sast::RefSpec::Reference => ValueInfo::new_reference(ws),
        sast::RefSpec::Unknown => ValueInfo::new_unresolved(ws),
    }
}

/// [`SSAStorage`][SSAStorage] methods return `Option`,
/// so we convert `None`s into [`SsaError`][LoweringError::SsaError]
impl From<::std::option::NoneError> for LoweringError {
    fn from(_: ::std::option::NoneError) -> Self {
        LoweringError::SsaError
    }
}

impl error::Error for LoweringError {
    fn description(&self) -> &str {
        match *self {
            LoweringError::SsaError => "could not perform an `SSAStorage` operation",
            LoweringError::InvalidAst(_) => "invalid ast",
        }
    }
}

impl fmt::Display for LoweringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            LoweringError::SsaError => write!(f, "could not perform an `SSAStorage` operation"),
            LoweringError::InvalidAst(ref s) => write!(f, "invalid ast: {}", s),
        }
    }
}
<|endoftext|>


<commit_before>use rusqlite::Connection;

#[derive(Debug)]
pub enum Version {
    Version1,
    Version2,
}

#[derive(Debug)]
pub struct Job {
    pub id: i32,
    pub fk_file: i32,
    pub name: String,
}

trait JobModuleTrait {
    // Static method signature; `Self` refers to the implementor type.
    fn new(name: &'static str) -> Self;
    fn hashmap(conn: &Connection) -> Vec<Job>;
    // fn update_hashcache(&self, &hashcache) -> &'static str;
}

pub fn table_create_job(conn: &Connection) {
    let load_table = conn.execute(
        "CREATE TABLE JOB (
                  id              INTEGER PRIMARY KEY ASC,
                  fk_file         INTEGER NOT NULL,
                  name            TEXT NOT NULL UNIQUE,
                  FOREIGN KEY(fk_file) REFERENCES FS_FILE(id) ON UPDATE CASCADE
                  )",
        &[],
    );
    if load_table.is_err() {
        error!("table_create_job Failed {:?}", load_table);
        return;
    }
    load_table.unwrap();
}

pub fn insert_job(
    conn: &Connection,
    fk_file: &i32,
    name: &String,
) -> Result<Version, &'static str> {

    let me = Job {
        id: 0,
        fk_file: fk_file.clone(),
        name: name.clone(),
    };
    let load_instance = conn.execute(
        "INSERT INTO JOB (name, fk_file)
                  VALUES (?1, ?2)",
        &[&me.name, fk_file],
    );
    if load_instance.is_err() {
        return Err("Insert failed");
    }
    load_instance.unwrap();
    return Ok(Version::Version1);
}

pub fn list_job(conn: &Connection) -> Vec<Job> {
    let mut stmt = conn.prepare("SELECT id, fk_file, name FROM JOB").unwrap();
    let wraped_job_iter = stmt.query_map(&[], |row| {
        Job {
            id: row.get(0),
            fk_file: row.get(1),
            name: row.get(2),
        }
    });
    let mut items = Vec::<Job>::new();
    if wraped_job_iter.is_err() {
        return items;
    }
    let job_iter = wraped_job_iter.unwrap();
    for person in job_iter {
        items.push(person.unwrap());
    }
    return items;
}

pub fn pk_job_by_name(
    conn: &Connection,
    name: &String,
    pk: &mut i32,
) -> Result<Version, &'static str> {
    let bill = name.clone();
    let mut stmt = conn.prepare("SELECT id, fk_file, name  FROM JOB WHERE name = ?1")
        .unwrap();
    let job_iter = stmt.query_map(&[&bill], |row| {
        Job {
            id: row.get(0),
            fk_file: row.get(1),
            name: row.get(2),
        }
    }).unwrap();
    let mut found = 0;
    let mut items = Vec::<Job>::new();
    for person in job_iter {
        let bill = person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found == 1 {
        return Ok(Version::Version1);
    }
    return Err("None found");
}
<commit_msg>Remove unused variables<commit_after>use rusqlite::Connection;

#[derive(Debug)]
pub enum Version {
    Version1,
    Version2,
}

#[derive(Debug)]
pub struct Job {
    pub id: i32,
    pub fk_file: i32,
    pub name: String,
}

trait JobModuleTrait {
    // Static method signature; `Self` refers to the implementor type.
    fn new(name: &'static str) -> Self;
    fn hashmap(conn: &Connection) -> Vec<Job>;
    // fn update_hashcache(&self, &hashcache) -> &'static str;
}

pub fn table_create_job(conn: &Connection) {
    let load_table = conn.execute(
        "CREATE TABLE JOB (
                  id              INTEGER PRIMARY KEY ASC,
                  fk_file         INTEGER NOT NULL,
                  name            TEXT NOT NULL UNIQUE,
                  FOREIGN KEY(fk_file) REFERENCES FS_FILE(id) ON UPDATE CASCADE
                  )",
        &[],
    );
    if load_table.is_err() {
        error!("table_create_job Failed {:?}", load_table);
        return;
    }
    load_table.unwrap();
}

pub fn insert_job(
    conn: &Connection,
    fk_file: &i32,
    name: &String,
) -> Result<Version, &'static str> {

    let me = Job {
        id: 0,
        fk_file: fk_file.clone(),
        name: name.clone(),
    };
    let load_instance = conn.execute(
        "INSERT INTO JOB (name, fk_file)
                  VALUES (?1, ?2)",
        &[&me.name, fk_file],
    );
    if load_instance.is_err() {
        return Err("Insert failed");
    }
    load_instance.unwrap();
    return Ok(Version::Version1);
}

pub fn list_job(conn: &Connection) -> Vec<Job> {
    let mut stmt = conn.prepare("SELECT id, fk_file, name FROM JOB").unwrap();
    let wraped_job_iter = stmt.query_map(&[], |row| {
        Job {
            id: row.get(0),
            fk_file: row.get(1),
            name: row.get(2),
        }
    });
    let mut items = Vec::<Job>::new();
    if wraped_job_iter.is_err() {
        return items;
    }
    let job_iter = wraped_job_iter.unwrap();
    for person in job_iter {
        items.push(person.unwrap());
    }
    return items;
}

pub fn pk_job_by_name(
    conn: &Connection,
    name: &String,
    pk: &mut i32,
) -> Result<Version, &'static str> {
    let bill = name.clone();
    let mut stmt = conn.prepare("SELECT id, fk_file, name  FROM JOB WHERE name = ?1")
        .unwrap();
    let job_iter = stmt.query_map(&[&bill], |row| {
        Job {
            id: row.get(0),
            fk_file: row.get(1),
            name: row.get(2),
        }
    }).unwrap();
    let mut found = 0;
    for person in job_iter {
        let bill = person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found == 1 {
        return Ok(Version::Version1);
    }
    return Err("None found");
}
<|endoftext|>


<commit_before>extern crate regex;

use self::regex::Regex;

pub fn valid(num: &str) -> bool {
    let re_text = concat!(
        "^",
        "(M(MM?)?)?",
        "(CM|CD|D|D?C(CC?)?)?",
        "(XC|XL|L|L?X(XX?)?)?",
        "(IX|IV|V|V?I(II?)?)?",
        "$");

    let re = Regex::new(re_text).unwrap();
    re.is_match(num)
}

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

    #[test]
    fn i_is_valid() {
        assert!(valid("I"));
    }

    #[test]
    fn lower_i_is_invalid() {
        assert!(!valid("i"));
    }

    #[test]
    fn prefixes_are_not_valid() {
        assert!(!valid(" I"));
    }

    #[test]
    fn suffixes_are_not_valid() {
        assert!(!valid("I "));
    }

    #[test]
    fn ii_is_valid() {
        assert!(valid("II"));
    }

    #[test]
    fn iii_is_valid() {
        assert!(valid("III"));
    }

    #[test]
    fn iiii_is_not_valid() {
        assert!(!valid("IIII"));
    }

    #[test]
    fn iv_is_valid() {
        assert!(valid("IV"));
    }

    #[test]
    fn ivi_is_not_valid() {
        assert!(!valid("IVI"));
    }

    #[test]
    fn v_is_valid() {
        assert!(valid("V"));
    }

    #[test]
    fn vi_is_valid() {
        assert!(valid("VI"));
    }

    #[test]
    fn vii_is_valid() {
        assert!(valid("VII"));
    }

    #[test]
    fn viii_is_valid() {
        assert!(valid("VIII"));
    }

    #[test]
    fn ix_is_valid() {
        assert!(valid("IX"));
    }

    #[test]
    fn ixi_is_invalid() {
        assert!(!valid("IXI"));
    }

    #[test]
    fn ixv_is_invalid() {
        assert!(!valid("IXV"));
    }

    #[test]
    fn viv_is_invalid() {
        assert!(!valid("VIV"));
    }

    #[test]
    fn empty_is_invalid() {
        assert!(!valid(""));
    }

    #[test]
    fn x_is_valid() {
        assert!(valid("X"));
    }

    #[test]
    fn xi_is_valid() {
        assert!(valid("XI"));
    }

    #[test]
    fn xx_is_valid() {
        assert!(valid("XX"));
    }

    #[test]
    fn xxx_is_valid() {
        assert!(valid("XXX"));
    }

    #[test]
    fn xxxix_is_valid() {
        assert!(valid("XXXIX"));
    }

    #[test]
    fn xxxx_is_not_valid() {
        assert!(!valid("XXXX"));
    }

    #[test]
    fn xl_is_valid() {
        assert!(valid("XL"));
    }

    #[test]
    fn xlx_is_not_valid() {
        assert!(!valid("XLX"));
    }

    #[test]
    fn l_is_valid() {
        assert!(valid("L"));
    }

    #[test]
    fn lx_is_valid() {
        assert!(valid("LX"));
    }

    #[test]
    fn lxx_is_valid() {
        assert!(valid("LXX"));
    }

    #[test]
    fn lxxx_is_valid() {
        assert!(valid("LXXX"));
    }

    #[test]
    fn xc_is_valid() {
        assert!(valid("XC"));
    }

    #[test]
    fn xcx_is_invalid() {
        assert!(!valid("XCX"));
    }

    #[test]
    fn c_is_valid() {
        assert!(valid("C"));
    }

    #[test]
    fn cx_is_valid() {
        assert!(valid("CX"));
    }

    #[test]
    fn cc_is_valid() {
        assert!(valid("CC"));
    }

    #[test]
    fn ccc_is_valid() {
        assert!(valid("CCC"));
    }

    #[test]
    fn cccxc_is_valid() {
        assert!(valid("CCCXC"));
    }

    #[test]
    fn cccc_is_not_valid() {
        assert!(!valid("CCCC"));
    }

    #[test]
    fn cd_is_valid() {
        assert!(valid("CD"));
    }

    #[test]
    fn cdc_is_not_valid() {
        assert!(!valid("CDC"));
    }

    #[test]
    fn d_is_valid() {
        assert!(valid("D"));
    }

    #[test]
    fn dc_is_valid() {
        assert!(valid("DC"));
    }

    #[test]
    fn dcc_is_valid() {
        assert!(valid("DCC"));
    }

    #[test]
    fn dccc_is_valid() {
        assert!(valid("DCCC"));
    }

    #[test]
    fn cm_is_valid() {
        assert!(valid("CM"));
    }

    #[test]
    fn cmc_is_invalid() {
        assert!(!valid("CMC"));
    }

    #[test]
    fn m_is_valid() {
        assert!(valid("M"));
    }

    #[test]
    fn mc_is_valid() {
        assert!(valid("MC"));
    }

    #[test]
    fn mm_is_valid() {
        assert!(valid("MM"));
    }

    #[test]
    fn mmm_is_valid() {
        assert!(valid("MMM"));
    }

    #[test]
    fn mmmcm_is_valid() {
        assert!(valid("MMMCM"));
    }

    #[test]
    fn mmmm_is_invalid() {
        assert!(!valid("MMMM"));
    }
}
<commit_msg>Handle empty (invalid) string in rust<commit_after>extern crate regex;

use self::regex::Regex;

pub fn valid(num: &str) -> bool {
    if num.len() == 0 {
        false
    } else {
        let re_text = concat!(
            "^",
            "(M(MM?)?)?",
            "(CM|CD|D|D?C(CC?)?)?",
            "(XC|XL|L|L?X(XX?)?)?",
            "(IX|IV|V|V?I(II?)?)?",
            "$");

        let re = Regex::new(re_text).unwrap();
        re.is_match(num)
    }
}

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

    #[test]
    fn i_is_valid() {
        assert!(valid("I"));
    }

    #[test]
    fn lower_i_is_invalid() {
        assert!(!valid("i"));
    }

    #[test]
    fn prefixes_are_not_valid() {
        assert!(!valid(" I"));
    }

    #[test]
    fn suffixes_are_not_valid() {
        assert!(!valid("I "));
    }

    #[test]
    fn ii_is_valid() {
        assert!(valid("II"));
    }

    #[test]
    fn iii_is_valid() {
        assert!(valid("III"));
    }

    #[test]
    fn iiii_is_not_valid() {
        assert!(!valid("IIII"));
    }

    #[test]
    fn iv_is_valid() {
        assert!(valid("IV"));
    }

    #[test]
    fn ivi_is_not_valid() {
        assert!(!valid("IVI"));
    }

    #[test]
    fn v_is_valid() {
        assert!(valid("V"));
    }

    #[test]
    fn vi_is_valid() {
        assert!(valid("VI"));
    }

    #[test]
    fn vii_is_valid() {
        assert!(valid("VII"));
    }

    #[test]
    fn viii_is_valid() {
        assert!(valid("VIII"));
    }

    #[test]
    fn ix_is_valid() {
        assert!(valid("IX"));
    }

    #[test]
    fn ixi_is_invalid() {
        assert!(!valid("IXI"));
    }

    #[test]
    fn ixv_is_invalid() {
        assert!(!valid("IXV"));
    }

    #[test]
    fn viv_is_invalid() {
        assert!(!valid("VIV"));
    }

    #[test]
    fn empty_is_invalid() {
        assert!(!valid(""));
    }

    #[test]
    fn x_is_valid() {
        assert!(valid("X"));
    }

    #[test]
    fn xi_is_valid() {
        assert!(valid("XI"));
    }

    #[test]
    fn xx_is_valid() {
        assert!(valid("XX"));
    }

    #[test]
    fn xxx_is_valid() {
        assert!(valid("XXX"));
    }

    #[test]
    fn xxxix_is_valid() {
        assert!(valid("XXXIX"));
    }

    #[test]
    fn xxxx_is_not_valid() {
        assert!(!valid("XXXX"));
    }

    #[test]
    fn xl_is_valid() {
        assert!(valid("XL"));
    }

    #[test]
    fn xlx_is_not_valid() {
        assert!(!valid("XLX"));
    }

    #[test]
    fn l_is_valid() {
        assert!(valid("L"));
    }

    #[test]
    fn lx_is_valid() {
        assert!(valid("LX"));
    }

    #[test]
    fn lxx_is_valid() {
        assert!(valid("LXX"));
    }

    #[test]
    fn lxxx_is_valid() {
        assert!(valid("LXXX"));
    }

    #[test]
    fn xc_is_valid() {
        assert!(valid("XC"));
    }

    #[test]
    fn xcx_is_invalid() {
        assert!(!valid("XCX"));
    }

    #[test]
    fn c_is_valid() {
        assert!(valid("C"));
    }

    #[test]
    fn cx_is_valid() {
        assert!(valid("CX"));
    }

    #[test]
    fn cc_is_valid() {
        assert!(valid("CC"));
    }

    #[test]
    fn ccc_is_valid() {
        assert!(valid("CCC"));
    }

    #[test]
    fn cccxc_is_valid() {
        assert!(valid("CCCXC"));
    }

    #[test]
    fn cccc_is_not_valid() {
        assert!(!valid("CCCC"));
    }

    #[test]
    fn cd_is_valid() {
        assert!(valid("CD"));
    }

    #[test]
    fn cdc_is_not_valid() {
        assert!(!valid("CDC"));
    }

    #[test]
    fn d_is_valid() {
        assert!(valid("D"));
    }

    #[test]
    fn dc_is_valid() {
        assert!(valid("DC"));
    }

    #[test]
    fn dcc_is_valid() {
        assert!(valid("DCC"));
    }

    #[test]
    fn dccc_is_valid() {
        assert!(valid("DCCC"));
    }

    #[test]
    fn cm_is_valid() {
        assert!(valid("CM"));
    }

    #[test]
    fn cmc_is_invalid() {
        assert!(!valid("CMC"));
    }

    #[test]
    fn m_is_valid() {
        assert!(valid("M"));
    }

    #[test]
    fn mc_is_valid() {
        assert!(valid("MC"));
    }

    #[test]
    fn mm_is_valid() {
        assert!(valid("MM"));
    }

    #[test]
    fn mmm_is_valid() {
        assert!(valid("MMM"));
    }

    #[test]
    fn mmmcm_is_valid() {
        assert!(valid("MMMCM"));
    }

    #[test]
    fn mmmm_is_invalid() {
        assert!(!valid("MMMM"));
    }
}
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   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,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! # Regular language
//!
//! This provides a data structure representing a regular language. This is a more generalised form of a regular
//! expression (it supports symbol types other than simple strings). A regular language using the `u8` symbol forms
//! a simple regular expression.
//!

use std::slice::*;

///
/// A phrase iterator can be used to return the symbols in a phrase one at a time
///
pub trait PhraseIterator<Symbol> {
    fn next_symbol(&mut self) -> Option<&Symbol>;
}

///
/// Phrases are sequences of symbols, matched in order
///
pub trait Phrase<Symbol> {
    type PhraseIterator: PhraseIterator<Symbol>;

    ///
    /// Retrieves an iterator that can be used to read the symbols for this phrase
    ///
    fn get_symbols(self) -> Self::PhraseIterator;
}

impl<'a, Symbol> Phrase<Symbol> for &'a Vec<Symbol> {
    type PhraseIterator = Iter<'a, Symbol>;

    #[inline]
    fn get_symbols(self) -> Self::PhraseIterator {
        self.iter()
    }
}

impl<'a, Symbol> PhraseIterator<Symbol> for Iter<'a, Symbol> {
    #[inline]
    fn next_symbol(&mut self) -> Option<&Symbol> {
        self.next()
    }
}

impl<'a, Symbol> Phrase<Symbol> for &'a [Symbol] {
    type PhraseIterator = Iter<'a, Symbol>;

    #[inline]
    fn get_symbols(self) -> Self::PhraseIterator {
        self.iter()
    }
}
<commit_msg>Add tests for the phrases<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   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,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! # Regular language
//!
//! This provides a data structure representing a regular language. This is a more generalised form of a regular
//! expression (it supports symbol types other than simple strings). A regular language using the `u8` symbol forms
//! a simple regular expression.
//!

use std::slice::*;

///
/// A phrase iterator can be used to return the symbols in a phrase one at a time
///
pub trait PhraseIterator<Symbol> {
    fn next_symbol(&mut self) -> Option<&Symbol>;
}

///
/// Phrases are sequences of symbols, matched in order
///
pub trait Phrase<Symbol> {
    type PhraseIterator: PhraseIterator<Symbol>;

    ///
    /// Retrieves an iterator that can be used to read the symbols for this phrase
    ///
    fn get_symbols(self) -> Self::PhraseIterator;
}

impl<'a, Symbol> Phrase<Symbol> for &'a Vec<Symbol> {
    type PhraseIterator = Iter<'a, Symbol>;

    #[inline]
    fn get_symbols(self) -> Self::PhraseIterator {
        self.iter()
    }
}

impl<'a, Symbol> PhraseIterator<Symbol> for Iter<'a, Symbol> {
    #[inline]
    fn next_symbol(&mut self) -> Option<&Symbol> {
        self.next()
    }
}

impl<'a, Symbol> Phrase<Symbol> for &'a [Symbol] {
    type PhraseIterator = Iter<'a, Symbol>;

    #[inline]
    fn get_symbols(self) -> Self::PhraseIterator {
        self.iter()
    }
}

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

    #[test]
    fn can_iterate_vector_phrase() {
        let some_phrase     = vec![1, 2, 3];
        let mut iterator    = some_phrase.get_symbols();

        assert!(iterator.next_symbol() == Some(&1));
        assert!(iterator.next_symbol() == Some(&2));
        assert!(iterator.next_symbol() == Some(&3));
        assert!(iterator.next_symbol() == None);
    }

    #[test]
    fn can_iterate_array_phrase() {
        let some_phrase     = [1, 2, 3];
        let mut iterator    = some_phrase.get_symbols();

        assert!(iterator.next_symbol() == Some(&1));
        assert!(iterator.next_symbol() == Some(&2));
        assert!(iterator.next_symbol() == Some(&3));
        assert!(iterator.next_symbol() == None);
    }
}
<|endoftext|>


<commit_before>extern crate websocket;

use self::websocket::WebSocketError;
use futures::future::Future;
use futures::stream::Stream;

use std::cell::RefCell;
use std::rc::Rc;

use self::websocket::server::upgrade::async::IntoWs;

use super::readdebt::{DebtHandling, ReadDebt};
use super::ws_peer::{Mode1, PeerForWs, WsReadWrapper, WsWriteWrapper};
use super::{box_up_err, io_other_error, BoxedNewPeerFuture, Peer};
use super::{ConstructParams, PeerConstructor, Specifier};

#[derive(Debug)]
pub struct WsServer<T: Specifier>(pub T);
impl<T: Specifier> Specifier for WsServer<T> {
    fn construct(&self, cp: ConstructParams) -> PeerConstructor {
        let mode1 = if cp.program_options.websocket_text_mode {
            Mode1::Text
        } else {
            Mode1::Binary
        };
        let inner = self.0.construct(cp.clone());
        inner.map(move |p| ws_upgrade_peer(p, mode1, cp.program_options.read_debt_handling))
    }
    specifier_boilerplate!(typ=WebSocket noglobalstate has_subspec);
    self_0_is_subspecifier!(proxy_is_multiconnect);
}
specifier_class!(
    name = WsServerClass,
    target = WsServer,
    prefixes = ["ws-upgrade:", "upgrade-ws:", "ws-u:", "u-ws:"],
    arg_handling = subspec,
    overlay = true,
    MessageOriented,
    MulticonnectnessDependsOnInnerType,
    help = r#"
WebSocket upgrader / raw server. Specify your own protocol instead of usual TCP. [A]

All other WebSocket server modes actually use this overlay under the hood.

Example: serve incoming connection from socat

    socat tcp-l:1234,fork,reuseaddr exec:'websocat -t ws-u\:stdio\: mirror\:'
"#
);

specifier_alias!(
    name = WsTcpServerClass,
    prefixes = ["ws-listen:", "ws-l:", "l-ws:", "listen-ws:"],
    alias = "ws-u:tcp-l:",
    help = r#"
WebSocket server. Argument is host and port to listen.

Example: Dump all incoming websocket data to console

    websocat ws-l:127.0.0.1:8808 -

Example: the same, but more verbose:

    websocat ws-l:tcp-l:127.0.0.1:8808 reuse:-
"#
);

specifier_alias!(
    name = WsInetdServerClass,
    prefixes = ["inetd-ws:", "ws-inetd:"],
    alias = "ws-u:inetd:",
    help = r#"
WebSocket inetd server. [A]

TODO: transfer the example here
"#
);

specifier_alias!(
    name = WsUnixServerClass,
    prefixes = ["l-ws-unix:"],
    alias = "ws-l:unix-l:",
    help = r#"
WebSocket UNIX socket-based server. [A]
"#
);

specifier_alias!(
    name = WsAbstractUnixServerClass,
    prefixes = ["l-ws-abstract:"],
    alias = "ws-l:abstract-l:",
    help = r#"
WebSocket abstract-namespaced UNIX socket server. [A]
"#
);

/*

     if x == "" {
                Err("Specify underlying protocol for ws-l:")?;
            }
            if let Some(c) = x.chars().next() {
                if c.is_numeric() || c == '[' {
                    // Assuming user uses old format like ws-l:127.0.0.1:8080
                    return spec(&("ws-l:tcp-l:".to_owned() + x));
                }
            }
            boxup(super::ws_server_peer::WsUpgrade(spec(x)?))
*/

pub fn ws_upgrade_peer(
    inner_peer: Peer,
    mode1: Mode1,
    ws_read_debt_handling: DebtHandling,
) -> BoxedNewPeerFuture {
    let step1 = PeerForWs(inner_peer);
    let step2: Box<
        Future<Item = self::websocket::server::upgrade::async::Upgrade<_>, Error = _>,
    > = step1.into_ws();
    let step3 = step2
        .map_err(|(_, _, _, e)| WebSocketError::IoError(io_other_error(e)))
        .and_then(move |x| {
            info!("Incoming connection to websocket: {}", x.request.subject.1);
            debug!("{:?}", x.request);
            debug!("{:?}", x.headers);
            x.accept().map(move |(y, headers)| {
                debug!("{:?}", headers);
                info!("Upgraded");
                let (sink, stream) = y.split();
                let mpsink = Rc::new(RefCell::new(sink));

                let ws_str = WsReadWrapper {
                    s: stream,
                    pingreply: mpsink.clone(),
                    debt: ReadDebt(Default::default(), ws_read_debt_handling),
                };
                let ws_sin = WsWriteWrapper(mpsink, mode1, true /* send Close on shutdown */);

                Peer::new(ws_str, ws_sin)
            })
        });
    let step4 = step3.map_err(box_up_err);
    Box::new(step4) as BoxedNewPeerFuture
}
<commit_msg>Fix `l-ws-unix:` alias.<commit_after>extern crate websocket;

use self::websocket::WebSocketError;
use futures::future::Future;
use futures::stream::Stream;

use std::cell::RefCell;
use std::rc::Rc;

use self::websocket::server::upgrade::async::IntoWs;

use super::readdebt::{DebtHandling, ReadDebt};
use super::ws_peer::{Mode1, PeerForWs, WsReadWrapper, WsWriteWrapper};
use super::{box_up_err, io_other_error, BoxedNewPeerFuture, Peer};
use super::{ConstructParams, PeerConstructor, Specifier};

#[derive(Debug)]
pub struct WsServer<T: Specifier>(pub T);
impl<T: Specifier> Specifier for WsServer<T> {
    fn construct(&self, cp: ConstructParams) -> PeerConstructor {
        let mode1 = if cp.program_options.websocket_text_mode {
            Mode1::Text
        } else {
            Mode1::Binary
        };
        let inner = self.0.construct(cp.clone());
        inner.map(move |p| ws_upgrade_peer(p, mode1, cp.program_options.read_debt_handling))
    }
    specifier_boilerplate!(typ=WebSocket noglobalstate has_subspec);
    self_0_is_subspecifier!(proxy_is_multiconnect);
}
specifier_class!(
    name = WsServerClass,
    target = WsServer,
    prefixes = ["ws-upgrade:", "upgrade-ws:", "ws-u:", "u-ws:"],
    arg_handling = subspec,
    overlay = true,
    MessageOriented,
    MulticonnectnessDependsOnInnerType,
    help = r#"
WebSocket upgrader / raw server. Specify your own protocol instead of usual TCP. [A]

All other WebSocket server modes actually use this overlay under the hood.

Example: serve incoming connection from socat

    socat tcp-l:1234,fork,reuseaddr exec:'websocat -t ws-u\:stdio\: mirror\:'
"#
);

specifier_alias!(
    name = WsTcpServerClass,
    prefixes = ["ws-listen:", "ws-l:", "l-ws:", "listen-ws:"],
    alias = "ws-u:tcp-l:",
    help = r#"
WebSocket server. Argument is host and port to listen.

Example: Dump all incoming websocket data to console

    websocat ws-l:127.0.0.1:8808 -

Example: the same, but more verbose:

    websocat ws-l:tcp-l:127.0.0.1:8808 reuse:-
"#
);

specifier_alias!(
    name = WsInetdServerClass,
    prefixes = ["inetd-ws:", "ws-inetd:"],
    alias = "ws-u:inetd:",
    help = r#"
WebSocket inetd server. [A]

TODO: transfer the example here
"#
);

specifier_alias!(
    name = WsUnixServerClass,
    prefixes = ["l-ws-unix:"],
    alias = "ws-u:unix-l:",
    help = r#"
WebSocket UNIX socket-based server. [A]
"#
);

specifier_alias!(
    name = WsAbstractUnixServerClass,
    prefixes = ["l-ws-abstract:"],
    alias = "ws-l:abstract-l:",
    help = r#"
WebSocket abstract-namespaced UNIX socket server. [A]
"#
);

/*

     if x == "" {
                Err("Specify underlying protocol for ws-l:")?;
            }
            if let Some(c) = x.chars().next() {
                if c.is_numeric() || c == '[' {
                    // Assuming user uses old format like ws-l:127.0.0.1:8080
                    return spec(&("ws-l:tcp-l:".to_owned() + x));
                }
            }
            boxup(super::ws_server_peer::WsUpgrade(spec(x)?))
*/

pub fn ws_upgrade_peer(
    inner_peer: Peer,
    mode1: Mode1,
    ws_read_debt_handling: DebtHandling,
) -> BoxedNewPeerFuture {
    let step1 = PeerForWs(inner_peer);
    let step2: Box<
        Future<Item = self::websocket::server::upgrade::async::Upgrade<_>, Error = _>,
    > = step1.into_ws();
    let step3 = step2
        .map_err(|(_, _, _, e)| WebSocketError::IoError(io_other_error(e)))
        .and_then(move |x| {
            info!("Incoming connection to websocket: {}", x.request.subject.1);
            debug!("{:?}", x.request);
            debug!("{:?}", x.headers);
            x.accept().map(move |(y, headers)| {
                debug!("{:?}", headers);
                info!("Upgraded");
                let (sink, stream) = y.split();
                let mpsink = Rc::new(RefCell::new(sink));

                let ws_str = WsReadWrapper {
                    s: stream,
                    pingreply: mpsink.clone(),
                    debt: ReadDebt(Default::default(), ws_read_debt_handling),
                };
                let ws_sin = WsWriteWrapper(mpsink, mode1, true /* send Close on shutdown */);

                Peer::new(ws_str, ws_sin)
            })
        });
    let step4 = step3.map_err(box_up_err);
    Box::new(step4) as BoxedNewPeerFuture
}
<|endoftext|>


<commit_before>use screen::*;
use context::{Context, GameState};
use ui_utils;
use piston_window::{self, PistonWindow};
use conrod::{self, Canvas, Button, Widget, Positionable, Sizeable, Labelable};
use conrod::color::{self, Colorable};

pub struct MainMenu {
    ui: conrod::Ui<piston_window::Glyphs>,
    state: Option<State>,
}

impl MainMenu {
    pub fn new(window: &PistonWindow, context: &mut Context) -> Self {
        MainMenu {
            ui: ui_utils::create_ui(&window, &context.assets_path),
            state: None,
        }
    }
}

enum State {
    NewGame,
    Options,
    Exit,
}

impl Screen for MainMenu {
    fn on_input(&mut self, _: &piston_window::Input, window: &PistonWindow, context: &mut Context) -> InputResults {
        self.ui.handle_event(window);
        let mut result = Vec::new();

        match self.state.take() {
            Some(State::NewGame) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(Battle::new(&window, context))));
                context.game_state = GameState::InProgress;
            }
            Some(State::Options) => {
                result.push(InputResult::PushScreen(Box::new(Options::new(&window, context))));
            }
            Some(State::Exit) => {
                result.push(InputResult::Exit);
            }
            None => {}
        }

        result
    }

    fn on_draw(&mut self, _: &piston_window::RenderArgs, window: &PistonWindow) {
        self.ui.handle_event(window);
        window.draw_2d(|context, graphics| self.ui.draw_if_changed(context, graphics));
    }

    fn on_update(&mut self, _: &piston_window::UpdateArgs) {
        let button_color = color::rgb(0.4, 0.75, 0.6);

        let state = &mut self.state;

        self.ui.set_widgets(|ui| {
            Canvas::new()
                .pad(30.)
                .color(color::rgb(0.2, 0.35, 0.45))
                .scroll_kids()
                .set(CANVAS, ui);

            Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .color(button_color)
                .label("New game")
                .react(|| *state = Some(State::NewGame))
                .set(NEW_GAME_BUTTON, ui);

            Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .down_from(NEW_GAME_BUTTON, 45.0)
                .color(button_color)
                .label("Options")
                .react(|| *state = Some(State::Options))
                .set(OPTIONS_BUTTON, ui);

            Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .down_from(OPTIONS_BUTTON, 45.0)
                .color(button_color)
                .label("Exit")
                .react(|| *state = Some(State::Exit))
                .set(EXIT_BUTTON, ui);
        });
    }
}

widget_ids! {
    CANVAS,
    NEW_GAME_BUTTON,
    OPTIONS_BUTTON,
    EXIT_BUTTON,
}
<commit_msg>'Work in progress'<commit_after>use screen::*;
use context::{Context, GameState};
use ui_utils;
use piston_window::{self, PistonWindow, Glyphs};
use conrod::{self, Canvas, Button, Widget, Positionable, Sizeable, Labelable};
use conrod::color::{self, Colorable};

pub struct MainMenu {
//    ui: conrod::Ui<piston_window::Glyphs>,
    ui: conrod::Ui<(<piston_window::G2d<'static> as conrod::Graphics>::Texture, Glyphs)>,
    state: Option<State>,
}

impl MainMenu {
    pub fn new(window: &PistonWindow, context: &mut Context) -> Self {
        MainMenu {
            ui: ui_utils::create_ui(&window, &context.assets_path),
            state: None,
        }
    }
}

enum State {
    NewGame,
    Options,
    Exit,
}

impl Screen for MainMenu {
    fn on_input(&mut self, _: &piston_window::Input, window: &PistonWindow, context: &mut Context) -> InputResults {
        self.ui.handle_event(window);
        let mut result = Vec::new();

        match self.state.take() {
            Some(State::NewGame) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(Battle::new(&window, context))));
                context.game_state = GameState::InProgress;
            }
            Some(State::Options) => {
                result.push(InputResult::PushScreen(Box::new(Options::new(&window, context))));
            }
            Some(State::Exit) => {
                result.push(InputResult::Exit);
            }
            None => {}
        }

        result
    }

    fn on_draw(&mut self, _: &piston_window::RenderArgs, window: &PistonWindow) {
        self.ui.handle_event(window);
        window.draw_2d(|context, graphics| self.ui.draw_if_changed(context, graphics));
    }

    fn on_update(&mut self, _: &piston_window::UpdateArgs) {
        let button_color = color::rgb(0.4, 0.75, 0.6);

        let state = &mut self.state;

        self.ui.set_widgets(|ui| {
            Canvas::new()
                .pad(30.)
                .color(color::rgb(0.2, 0.35, 0.45))
                .scroll_kids()
                .set(CANVAS, ui);

            Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .color(button_color)
                .label("New game")
                .react(|| *state = Some(State::NewGame))
                .set(NEW_GAME_BUTTON, ui);

            Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .down_from(NEW_GAME_BUTTON, 45.0)
                .color(button_color)
                .label("Options")
                .react(|| *state = Some(State::Options))
                .set(OPTIONS_BUTTON, ui);

            Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .down_from(OPTIONS_BUTTON, 45.0)
                .color(button_color)
                .label("Exit")
                .react(|| *state = Some(State::Exit))
                .set(EXIT_BUTTON, ui);
        });
    }
}

widget_ids! {
    CANVAS,
    NEW_GAME_BUTTON,
    OPTIONS_BUTTON,
    EXIT_BUTTON,
}
<|endoftext|>