<commit_before>/// Rust TNetStrings serialization library.

/// Represents a TNetString value.
pub enum TNetString {
    Str(~[u8]),
    Int(int),
    Float(float),
    Bool(bool),
    Null,
    Map(Map),
    Vec(~[TNetString]),
}

pub type Map = ~send_map::linear::LinearMap<~[u8], TNetString>;

/// Serializes a TNetString value into a io::Writer.
pub fn to_writer(writer: io::Writer, tnetstring: &TNetString) {
    fn write_str(wr: io::Writer, s: &[u8]) {
        wr.write_str(#fmt("%u:", s.len()));
        wr.write(s);
        wr.write_char(',');
    }

    match *tnetstring {
        Str(s) => write_str(writer, s),
        Int(i) => {
            let s = int::str(i);
            writer.write_str(#fmt("%u:%s#", s.len(), s));
        }
        Float(f) => {
            let s = float::to_str(f, 6u);
            writer.write_str(#fmt("%u:%s^", s.len(), s));
        }
        Bool(b) => {
            let s = bool::to_str(b);
            writer.write_str(#fmt("%u:%s!", s.len(), s));
        }
        Map(m) => {
            let payload = do io::with_bytes_writer |wr| {
                for m.each |key, value| {
                    write_str(wr, *key);
                    to_writer(wr, value);
                }
            };
            writer.write_str(#fmt("%u:", payload.len()));
            writer.write(payload);
            writer.write_char('}');
        }
        Vec(v) => {
            let payload = do io::with_bytes_writer |wr| {
                for v.each |e| { to_writer(wr, e) }
            };
            writer.write_str(#fmt("%u:", payload.len()));
            writer.write(payload);
            writer.write_char(']');
        }
        Null => writer.write_str("0:~"),
    }
}

/// Serializes a TNetString value into a byte string.
pub fn to_bytes(tnetstring: &TNetString) -> ~[u8] {
    do io::with_bytes_writer |wr| {
        to_writer(wr, tnetstring);
    }
}

/// Serializes a TNetString value into a string.
pub impl TNetString: to_str::ToStr {
    fn to_str() -> ~str {
        do io::with_str_writer |wr| {
            to_writer(wr, &self);
        }
    }
}

/// Deserializes a TNetString value from an io::Reader.
pub fn from_reader(reader: io::Reader) -> Option<TNetString> {
    assert !reader.eof();

    let mut c = reader.read_byte();
    let mut len = 0u;

    // Note that netstring spec explicitly forbids padding zeros.
    // If the first char is zero, it must be the only char.
    if c < '0' as int || c > '9' as int {
        fail ~"Not a TNetString: invalid or missing length prefix";
    } else if c == '0' as int {
        c = reader.read_byte();
    } else {
        loop {
            len = (10u * len) + ((c as uint) - ('0' as uint));

            if reader.eof() {
                fail ~"Not a TNetString: invalid or missing length prefix";
            }
            c = reader.read_byte();

            if c < '0' as int || c > '9' as int {
                break;
            }
        }
    }

    // Validate end-of-length-prefix marker.
    if c != ':' as int {
        fail ~"Not a TNetString: missing length prefix";
    }

    // Read the data plus terminating type tag.
    let payload = reader.read_bytes(len);

    if payload.len() != len {
        fail ~"Not a TNetString: invalid length prefix";
    }

    if reader.eof() {
        fail ~"Not a TNetString: missing type tag";
    }

    match reader.read_byte() as char {
      '#' => {
        let s = unsafe { str::raw::from_bytes(payload) };
        int::from_str(s).map(|v| Int(*v))
      }
      '}' => Some(Map(parse_map(payload))),
      ']' => Some(Vec(parse_vec(payload))),
      '!' => {
        let s = unsafe { str::raw::from_bytes(payload) };
        bool::from_str(s).map(|v| Bool(*v))
      }
      '^' => {
        let s = unsafe { str::raw::from_bytes(payload) };
        float::from_str(s).map(|v| Float(*v))
      }
      '~' => {
        assert payload.len() == 0u;
        Some(Null)
      }
      ',' => Some(Str(payload)),
      c => {
        let s = str::from_char(c);
        fail #fmt("Invalid payload type: %?", s)
      }
    }
}

fn parse_vec(data: &[u8]) -> ~[TNetString] {
    if data.len() == 0u { return ~[]; }

    do io::with_bytes_reader(data) |reader| {
        let mut result = ~[];

        match move from_reader(reader) {
            Some(move value) => result.push(value),
            None => fail ~"invalid value"
        }

        while !reader.eof() {
            match move from_reader(reader) {
                Some(move value) => result.push(value),
                None => fail ~"invalid TNetString"
            }
        }

        result
    }
}

fn parse_pair(reader: io::Reader) -> (~[u8], TNetString) {
    match move from_reader(reader) {
        Some(Str(move key)) => {
            match move from_reader(reader) {
                Some(move value) => (key, value),
                None => fail ~"invalid TNetString",
            }
        }
        Some(_) => fail ~"Keys can only be strings.",
        None => fail ~"Invalid TNetString",
    }
}

fn parse_map(data: &[u8]) -> ~send_map::linear::LinearMap<~[u8], TNetString> {
    let mut result = ~send_map::linear::LinearMap();

    if data.len() != 0u {
        do io::with_bytes_reader(data) |reader| {
            let (key, value) = parse_pair(reader);
            result.insert(key, value);

            while !reader.eof() {
                let (key, value) = parse_pair(reader);
                result.insert(key, value);
            }
        }
    }

    result
}

/// Deserializes a TNetString value from a byte string.
pub fn from_bytes(data: &[u8]) -> (Option<TNetString>, ~[u8]) {
    do io::with_bytes_reader(data) |reader| {
        let TNetString = from_reader(reader);
        (TNetString, reader.read_whole_stream())
    }
}

/// Deserializes a TNetString value from a string.
pub fn from_str(data: &str) -> (Option<TNetString>, ~str) {
    do io::with_str_reader(data) |rdr| {
        let tnetstring = from_reader(rdr);
        let bytes = rdr.read_whole_stream();
        (tnetstring, str::from_bytes(bytes))
    }

}

/// Test the equality between two TNetString values
pub impl TNetString: cmp::Eq {
    pure fn eq(other: &TNetString) -> bool {
        // FIXME: https://github.com/mozilla/rust/issues/2855
        match (&self, other) {
            (&Str(s0), &Str(s1)) => s0 == s1,
            (&Int(i0), &Int(i1)) => i0 == i1,
            (&Float(f0), &Float(f1)) => f0 == f1,
            (&Bool(b0), &Bool(b1)) => b0 == b1,
            (&Null, &Null) => true,
            (&Map(d0), &Map(d1)) => {
                if d0.len() == d1.len() {
                    for d0.each |k0, v0| {
                        let result = match d1.find_ref(k0) {
                            Some(v1) => v0 == v1,
                            None => false,
                        };
                        if !result { return false; }
                    }
                    true
                } else {
                    false
                }
            }
            (&Vec(v0), &Vec(v1)) => vec::all2(v0, v1, |x0, x1| x0 == x1),
            _ => false
        }
    }

    pure fn ne(other: &TNetString) -> bool { !self.eq(other) }
}

#[cfg(test)]
mod tests {
    // Tests inspired by https://github.com/rfk/TNetString.

    fn test(+s: ~str, expected: &TNetString) {
        let (actual, rest) = from_str(s);
        assert actual.is_some();
        assert rest == ~"";

        let actual = option::unwrap(actual);
        assert actual == *expected;
        assert expected.to_str() == s;
    }

    #[test]
    fn test_format() {
        test(~"11:hello world,", &Str(str::to_bytes("hello world")));
        test(~"0:}", &Map(~send_map::linear::LinearMap()));
        test(~"0:]", &Vec(~[]));

        let mut d = ~send_map::linear::LinearMap();
        d.insert(str::to_bytes("hello"),
                Vec(~[
                    Int(12345678901),
                    Str(str::to_bytes("this")),
                    Bool(true),
                    Null,
                    Str(str::to_bytes("\x00\x00\x00\x00"))]));

        test(~"51:5:hello,39:11:12345678901#4:this,4:true!0:~4:\x00\x00\x00\
               \x00,]}", &Map(d));

        test(~"5:12345#", &Int(12345));
        test(~"12:this is cool,", &Str(str::to_bytes("this is cool")));
        test(~"0:,", &Str(str::to_bytes("")));
        test(~"0:~", &Null);
        test(~"4:true!", &Bool(true));
        test(~"5:false!", &Bool(false));
        test(~"10:\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,",
            &Str(str::to_bytes("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")));
        test(~"24:5:12345#5:67890#5:xxxxx,]",
            &Vec(~[
                Int(12345),
                Int(67890),
                Str(str::to_bytes("xxxxx"))]));
        test(~"18:3:0.1^3:0.2^3:0.4^]",
           &Vec(~[Float(0.1), Float(0.2), Float(0.4)]));
        test(~"243:238:233:228:223:218:213:208:203:198:193:188:183:178:173:\
               168:163:158:153:148:143:138:133:128:123:118:113:108:103:99:95:\
               91:87:83:79:75:71:67:63:59:55:51:47:43:39:35:31:27:23:19:15:\
               11:hello-there,]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\
               ]]]]",
            &Vec(
                ~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(
                ~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(
                ~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(
                ~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(
                ~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(
                ~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(
                ~[Vec(~[Vec(~[
                    Str(str::to_bytes("hello-there"))
                ])])])])])])])])])])])])])])])])])])])])])])])])])])])])
                ])])])])])])])])])])])])])])])])])])])])])])]));
    }

    #[test]
    fn test_random() {
        fn randint(rng: rand::Rng, a: u32, b: u32) -> u32 {
            (rng.next() % (b - a + 1u32)) + a
        }

        fn get_random_object(rng: rand::Rng, depth: u32) -> TNetString {
            if randint(rng, depth, 10u32) <= 4u32 {
                if randint(rng, 0u32, 1u32) == 0u32 {
                    let n = randint(rng, 0u32, 10u32);
                    Vec(vec::from_fn(n as uint, |_i|
                        get_random_object(rng, depth + 1u32)
                    ))
                } else {
                    let mut d = ~send_map::linear::LinearMap();

                    let mut i = randint(rng, 0u32, 10u32);
                    while i != 0u32 {
                        let s = rng.gen_bytes(randint(rng, 0u32, 100u32) as uint);
                        d.insert(s, get_random_object(rng, depth + 1u32));
                        i -= 1u32;
                    }
                    Map(d)
                }
            } else {
                match randint(rng, 0u32, 5u32) {
                  0u32 => Null,
                  1u32 => Bool(true),
                  2u32 => Bool(false),
                  3u32 => {
                    if randint(rng, 0u32, 1u32) == 0u32 {
                        Int(rng.next() as int)
                    } else {
                        Int(-rng.next() as int)
                    }
                  }
                  4u32 => {
                    let mut f = rng.gen_float();

                    // Generate a float that can be exactly converted to
                    // and from a string.
                    loop {
                        match float::from_str(float::to_str(f, 6u)) {
                          Some(f1) => {
                            if f == f1 { break; }
                            f = f1;
                          }
                          None => fail ~"invalid float"
                        }
                    }

                    if randint(rng, 0u32, 1u32) == 0u32 {
                        Float(f)
                    } else {
                        Float(-f)
                    }
                  }
                  5u32 => {
                    Str(rng.gen_bytes(randint(rng, 0u32, 100u32) as uint))
                  }
                  _ => fail
                }
            }
        }

        let rng = rand::Rng();

        let mut i = 500u;
        while i != 0u {
            let v0 = get_random_object(rng, 0u32);

            match from_bytes(to_bytes(&v0)) {
                (Some(v1), rest) if rest == ~[] => assert v0 == v1,
                _ => fail ~"invalid TNetString"
            }
            i -= 1u;
        }
    }
}
<commit_msg>Update to work with rust 0.4.<commit_after>/// Rust TNetStrings serialization library.

/// Represents a TNetString value.
pub enum TNetString {
    Str(~[u8]),
    Int(int),
    Float(float),
    Bool(bool),
    Null,
    Map(Map),
    Vec(~[TNetString]),
}

pub type Map = ~send_map::linear::LinearMap<~[u8], TNetString>;

/// Serializes a TNetString value into a io::Writer.
pub fn to_writer(writer: io::Writer, tnetstring: &TNetString) {
    fn write_str(wr: io::Writer, s: &[u8]) {
        wr.write_str(#fmt("%u:", s.len()));
        wr.write(s);
        wr.write_char(',');
    }

    match *tnetstring {
        Str(s) => write_str(writer, s),
        Int(i) => {
            let s = int::str(i);
            writer.write_str(#fmt("%u:%s#", s.len(), s));
        }
        Float(f) => {
            let s = float::to_str(f, 6u);
            writer.write_str(#fmt("%u:%s^", s.len(), s));
        }
        Bool(b) => {
            let s = bool::to_str(b);
            writer.write_str(#fmt("%u:%s!", s.len(), s));
        }
        Map(m) => {
            let payload = do io::with_bytes_writer |wr| {
                for m.each |key, value| {
                    write_str(wr, *key);
                    to_writer(wr, value);
                }
            };
            writer.write_str(#fmt("%u:", payload.len()));
            writer.write(payload);
            writer.write_char('}');
        }
        Vec(v) => {
            let payload = do io::with_bytes_writer |wr| {
                for v.each |e| { to_writer(wr, e) }
            };
            writer.write_str(#fmt("%u:", payload.len()));
            writer.write(payload);
            writer.write_char(']');
        }
        Null => writer.write_str("0:~"),
    }
}

/// Serializes a TNetString value into a byte string.
pub fn to_bytes(tnetstring: &TNetString) -> ~[u8] {
    do io::with_bytes_writer |wr| {
        to_writer(wr, tnetstring);
    }
}

/// Serializes a TNetString value into a string.
pub impl TNetString: to_str::ToStr {
    pure fn to_str() -> ~str {
        // FIXME: https://github.com/mozilla/rust/issues/3758
        unsafe {
            do io::with_str_writer |wr| {
                to_writer(wr, &self);
            }
        }
    }
}

/// Deserializes a TNetString value from an io::Reader.
pub fn from_reader(reader: io::Reader) -> Option<TNetString> {
    assert !reader.eof();

    let mut c = reader.read_byte();
    let mut len = 0u;

    // Note that netstring spec explicitly forbids padding zeros.
    // If the first char is zero, it must be the only char.
    if c < '0' as int || c > '9' as int {
        fail ~"Not a TNetString: invalid or missing length prefix";
    } else if c == '0' as int {
        c = reader.read_byte();
    } else {
        loop {
            len = (10u * len) + ((c as uint) - ('0' as uint));

            if reader.eof() {
                fail ~"Not a TNetString: invalid or missing length prefix";
            }
            c = reader.read_byte();

            if c < '0' as int || c > '9' as int {
                break;
            }
        }
    }

    // Validate end-of-length-prefix marker.
    if c != ':' as int {
        fail ~"Not a TNetString: missing length prefix";
    }

    // Read the data plus terminating type tag.
    let payload = reader.read_bytes(len);

    if payload.len() != len {
        fail ~"Not a TNetString: invalid length prefix";
    }

    if reader.eof() {
        fail ~"Not a TNetString: missing type tag";
    }

    match reader.read_byte() as char {
      '#' => {
        let s = unsafe { str::raw::from_bytes(payload) };
        int::from_str(s).map(|v| Int(*v))
      }
      '}' => Some(Map(parse_map(payload))),
      ']' => Some(Vec(parse_vec(payload))),
      '!' => {
        let s = unsafe { str::raw::from_bytes(payload) };
        bool::from_str(s).map(|v| Bool(*v))
      }
      '^' => {
        let s = unsafe { str::raw::from_bytes(payload) };
        float::from_str(s).map(|v| Float(*v))
      }
      '~' => {
        assert payload.len() == 0u;
        Some(Null)
      }
      ',' => Some(Str(move payload)),
      c => {
        let s = str::from_char(c);
        fail #fmt("Invalid payload type: %?", s)
      }
    }
}

fn parse_vec(data: &[u8]) -> ~[TNetString] {
    if data.len() == 0u { return ~[]; }

    do io::with_bytes_reader(data) |reader| {
        let mut result = ~[];

        match move from_reader(reader) {
            Some(move value) => result.push(move value),
            None => fail ~"invalid value"
        }

        while !reader.eof() {
            match move from_reader(reader) {
                Some(move value) => result.push(move value),
                None => fail ~"invalid TNetString"
            }
        }

        move result
    }
}

fn parse_pair(reader: io::Reader) -> (~[u8], TNetString) {
    match from_reader(reader) {
        Some(Str(move key)) => {
            match from_reader(reader) {
                Some(move value) => (move key, move value),
                None => fail ~"invalid TNetString",
            }
        }
        Some(_) => fail ~"Keys can only be strings.",
        None => fail ~"Invalid TNetString",
    }
}

fn parse_map(data: &[u8]) -> ~send_map::linear::LinearMap<~[u8], TNetString> {
    let mut result = ~send_map::linear::LinearMap();

    if data.len() != 0u {
        do io::with_bytes_reader(data) |reader| {
            let (key, value) = parse_pair(reader);
            result.insert(move key, move value);

            while !reader.eof() {
                let (key, value) = parse_pair(reader);
                result.insert(move key, move value);
            }
        }
    }

    move result
}

/// Deserializes a TNetString value from a byte string.
pub fn from_bytes(data: &[u8]) -> (Option<TNetString>, ~[u8]) {
    do io::with_bytes_reader(data) |reader| {
        let tnetstring = from_reader(reader);
        (move tnetstring, reader.read_whole_stream())
    }
}

/// Deserializes a TNetString value from a string.
pub fn from_str(data: &str) -> (Option<TNetString>, ~str) {
    do io::with_str_reader(data) |rdr| {
        let tnetstring = from_reader(rdr);
        let bytes = rdr.read_whole_stream();
        (move tnetstring, str::from_bytes(bytes))
    }

}

/// Test the equality between two TNetString values
pub impl TNetString: cmp::Eq {
    pure fn eq(other: &TNetString) -> bool {
        match (&self, other) {
            (&Str(s0), &Str(s1)) => s0 == s1,
            (&Int(i0), &Int(i1)) => i0 == i1,
            (&Float(f0), &Float(f1)) => f0 == f1,
            (&Bool(b0), &Bool(b1)) => b0 == b1,
            (&Null, &Null) => true,
            (&Map(d0), &Map(d1)) => {
                if d0.len() == d1.len() {
                    for d0.each |k0, v0| {
                        let result = match d1.find_ref(k0) {
                            Some(v1) => v0 == v1,
                            None => false,
                        };
                        if !result { return false; }
                    }
                    true
                } else {
                    false
                }
            }
            (&Vec(v0), &Vec(v1)) => vec::all2(v0, v1, |x0, x1| x0 == x1),
            _ => false
        }
    }

    pure fn ne(other: &TNetString) -> bool { !self.eq(other) }
}

#[cfg(test)]
mod tests {
    // Tests inspired by https://github.com/rfk/TNetString.

    fn test(s: &~str, expected: &TNetString) {
        let (actual, rest) = from_str(*s);
        assert actual.is_some();
        assert rest == ~"";

        let actual = option::unwrap(move actual);
        assert actual == *expected;
        assert expected.to_str() == *s;
    }

    #[test]
    fn test_format() {
        test(&~"11:hello world,", &Str(str::to_bytes("hello world")));
        test(&~"0:}", &Map(~send_map::linear::LinearMap()));
        test(&~"0:]", &Vec(~[]));

        let mut d = ~send_map::linear::LinearMap();
        d.insert(str::to_bytes("hello"),
                Vec(~[
                    Int(12345678901),
                    Str(str::to_bytes("this")),
                    Bool(true),
                    Null,
                    Str(str::to_bytes("\x00\x00\x00\x00"))]));

        test(&~"51:5:hello,39:11:12345678901#4:this,4:true!0:~4:\x00\x00\x00\
               \x00,]}", &Map(move d));

        test(&~"5:12345#", &Int(12345));
        test(&~"12:this is cool,", &Str(str::to_bytes("this is cool")));
        test(&~"0:,", &Str(str::to_bytes("")));
        test(&~"0:~", &Null);
        test(&~"4:true!", &Bool(true));
        test(&~"5:false!", &Bool(false));
        test(&~"10:\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,",
            &Str(str::to_bytes("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")));
        test(&~"24:5:12345#5:67890#5:xxxxx,]",
            &Vec(~[
                Int(12345),
                Int(67890),
                Str(str::to_bytes("xxxxx"))]));
        test(&~"18:3:0.1^3:0.2^3:0.4^]",
           &Vec(~[Float(0.1), Float(0.2), Float(0.4)]));
        test(&~"243:238:233:228:223:218:213:208:203:198:193:188:183:178:173:\
               168:163:158:153:148:143:138:133:128:123:118:113:108:103:99:95:\
               91:87:83:79:75:71:67:63:59:55:51:47:43:39:35:31:27:23:19:15:\
               11:hello-there,]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\
               ]]]]",
            &Vec(
                ~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(
                ~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(
                ~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(
                ~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(
                ~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(
                ~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(~[Vec(
                ~[Vec(~[Vec(~[
                    Str(str::to_bytes("hello-there"))
                ])])])])])])])])])])])])])])])])])])])])])])])])])])])])
                ])])])])])])])])])])])])])])])])])])])])])])]));
    }

    #[test]
    fn test_random() {
        fn randint(rng: rand::Rng, a: u32, b: u32) -> u32 {
            (rng.next() % (b - a + 1u32)) + a
        }

        fn get_random_object(rng: rand::Rng, depth: u32) -> TNetString {
            if randint(rng, depth, 10u32) <= 4u32 {
                if randint(rng, 0u32, 1u32) == 0u32 {
                    let n = randint(rng, 0u32, 10u32);
                    Vec(vec::from_fn(n as uint, |_i|
                        get_random_object(rng, depth + 1u32)
                    ))
                } else {
                    let mut d = ~send_map::linear::LinearMap();

                    let mut i = randint(rng, 0u32, 10u32);
                    while i != 0u32 {
                        let s = rng.gen_bytes(randint(rng, 0u32, 100u32) as uint);
                        d.insert(
                            move s,
                            move get_random_object(rng, depth + 1u32)
                        );
                        i -= 1u32;
                    }
                    Map(move d)
                }
            } else {
                match randint(rng, 0u32, 5u32) {
                  0u32 => Null,
                  1u32 => Bool(true),
                  2u32 => Bool(false),
                  3u32 => {
                    if randint(rng, 0u32, 1u32) == 0u32 {
                        Int(rng.next() as int)
                    } else {
                        Int(-rng.next() as int)
                    }
                  }
                  4u32 => {
                    let mut f = rng.gen_float();

                    // Generate a float that can be exactly converted to
                    // and from a string.
                    loop {
                        match float::from_str(float::to_str(f, 6u)) {
                          Some(f1) => {
                            if f == f1 { break; }
                            f = f1;
                          }
                          None => fail ~"invalid float"
                        }
                    }

                    if randint(rng, 0u32, 1u32) == 0u32 {
                        Float(f)
                    } else {
                        Float(-f)
                    }
                  }
                  5u32 => {
                    Str(rng.gen_bytes(randint(rng, 0u32, 100u32) as uint))
                  }
                  _ => fail
                }
            }
        }

        let rng = rand::Rng();

        let mut i = 500u;
        while i != 0u {
            let v0 = get_random_object(rng, 0u32);

            match from_bytes(to_bytes(&v0)) {
                (Some(v1), rest) if rest == ~[] => assert v0 == v1,
                _ => fail ~"invalid TNetString"
            }
            i -= 1u;
        }
    }
}
<|endoftext|>


<commit_before>use intern::intern;
use grammar::parse_tree::TerminalLiteral;
use grammar::repr::*;
use lr1::build_states;
use lr1::interpret::interpret_partial;
use lr1::{Item, Lookahead};
use session::Session;
use test_util::{expect_debug, normalized_grammar};

use super::Tracer;

fn nt(t: &str) -> NonterminalString {
    NonterminalString(intern(t))
}

fn term(t: &str) -> TerminalString {
    TerminalString::Literal(TerminalLiteral::Quoted(intern(t)))
}

macro_rules! terms {
    ($($t:expr),*) => {
        vec![$(term($t)),*]
    }
}

fn test_grammar1() -> Grammar {
    normalized_grammar(r#"
    grammar;

    pub Start: () = Stmt;

    pub Stmt: () = {
        Exprs ";",
        Exprs
    };

    Exprs: () = {
        Expr,
        Exprs "," Expr
    };

    Expr: () = {
        "Int",
        Expr "+" "Int",
    };
"#)
}

#[test]
fn backtrace1() {
    let grammar = test_grammar1();
    let session = Session::test();
    let states = build_states(&session, &grammar, nt("Start")).unwrap();
    let mut tracer = Tracer::new(&session, &grammar, &states);
    let state_stack = interpret_partial(&states, terms!["Int"]).unwrap();
    let top_state = *state_stack.last().unwrap();

    // Top state will have items like:
    //
    // Expr = "Int" (*) [EOF],
    // Expr = "Int" (*) ["+"],
    // Expr = "Int" (*) [","],
    // Expr = "Int" (*) [";"]
    //
    // Select the last one.
    let semi = Lookahead::Terminal(term(";"));
    let semi_item = states[top_state.0].items.vec.iter()
                                                 .filter(|item| item.lookahead == semi)
                                                 .next()
                                                 .unwrap();

    let backtrace = tracer.backtrace(top_state, *semi_item);

    println!("{:#?}", backtrace);
    expect_debug(&backtrace, r#"BacktraceNode {
    item: Expr = "Int" (*),
    parents: [
        BacktraceNode {
            item: Exprs = (*) Expr,
            parents: [
                BacktraceNode {
                    item: Stmt = (*) Exprs ";",
                    parents: []
                }
            ]
        },
        BacktraceNode {
            item: Exprs = Exprs "," (*) Expr,
            parents: [
                BacktraceNode {
                    item: Stmt = (*) Exprs ";",
                    parents: []
                }
            ]
        }
    ]
}"#);
}

#[test]
fn backtrace2() {
    let grammar = test_grammar1();
    let session = Session::test();
    let states = build_states(&session, &grammar, nt("Start")).unwrap();
    let mut tracer = Tracer::new(&session, &grammar, &states);
    let state_stack = interpret_partial(&states, terms!["Int"]).unwrap();
    let top_state = *state_stack.last().unwrap();

    // Top state will have items like:
    //
    // Expr = "Int" (*) [EOF],
    // Expr = "Int" (*) ["+"],
    // Expr = "Int" (*) [","],
    // Expr = "Int" (*) [";"]
    //
    // Select the last one.
    let plus = Lookahead::Terminal(term("+"));
    let plus_item = states[top_state.0].items.vec.iter()
                                                 .filter(|item| item.lookahead == plus)
                                                 .next()
                                                 .unwrap();

    let backtrace = tracer.backtrace(top_state, *plus_item);

    println!("{:#?}", backtrace);
    expect_debug(&backtrace, r#"BacktraceNode {
    item: Expr = "Int" (*),
    parents: [
        BacktraceNode {
            item: Expr = (*) Expr "+" "Int",
            parents: []
        }
    ]
}"#);
}

#[test]
fn backtrace3() {
    // This grammar yields a S/R conflict. Is it (int -> int) -> int
    // or int -> (int -> int)?
    let grammar = normalized_grammar(r#"
grammar;
pub Ty: () = {
    "int" => (),
    "bool" => (),
    <t1:Ty> "->" <t2:Ty> => (),
};
"#);
    let session = Session::test();
    let states = build_states(&session, &grammar, nt("Ty")).unwrap_err().states;
    let mut tracer = Tracer::new(&session, &grammar, &states);
    let (&lookahead, conflict) =
        states.iter()
              .flat_map(|s| &s.conflicts)
              .flat_map(|(l, cs)| cs.iter().map(move |c| (l, c)))
              .next()
              .unwrap();
    println!("conflict={:?}", conflict);
    let item = Item { production: conflict.production,
                      index: conflict.production.symbols.len(),
                      lookahead: lookahead };
    println!("item={:?}", item);
    let backtrace = tracer.backtrace(conflict.state, item);
    println!("{:#?}", backtrace);
    expect_debug(&backtrace, r#"BacktraceNode {
    item: Ty = Ty "->" Ty (*),
    parents: [
        BacktraceNode {
            item: Ty = (*) Ty "->" Ty,
            parents: []
        },
        BacktraceNode {
            item: Ty = Ty "->" (*) Ty,
            parents: [
                BacktraceNode {
                    item: Ty = (*) Ty "->" Ty,
                    parents: []
                },
                BacktraceNode {
                    item: Ty = Ty "->" (*) Ty,
                    parents: []
                }
            ]
        }
    ]
}"#);
}
<commit_msg>Test that we can enumerate/paint the examples.<commit_after>use intern::intern;
use grammar::parse_tree::TerminalLiteral;
use grammar::repr::*;
use lr1::build_states;
use lr1::interpret::interpret_partial;
use lr1::{Item, Lookahead};
use session::Session;
use test_util::{expect_debug, normalized_grammar};

use super::Tracer;

fn nt(t: &str) -> NonterminalString {
    NonterminalString(intern(t))
}

fn term(t: &str) -> TerminalString {
    TerminalString::Literal(TerminalLiteral::Quoted(intern(t)))
}

macro_rules! terms {
    ($($t:expr),*) => {
        vec![$(term($t)),*]
    }
}

fn test_grammar1() -> Grammar {
    normalized_grammar(r#"
    grammar;

    pub Start: () = Stmt;

    pub Stmt: () = {
        Exprs ";",
        Exprs
    };

    Exprs: () = {
        Expr,
        Exprs "," Expr
    };

    Expr: () = {
        "Int",
        Expr "+" "Int",
    };
"#)
}

#[test]
fn backtrace1() {
    let grammar = test_grammar1();
    let session = Session::test();
    let states = build_states(&session, &grammar, nt("Start")).unwrap();
    let mut tracer = Tracer::new(&session, &grammar, &states);
    let state_stack = interpret_partial(&states, terms!["Int"]).unwrap();
    let top_state = *state_stack.last().unwrap();

    // Top state will have items like:
    //
    // Expr = "Int" (*) [EOF],
    // Expr = "Int" (*) ["+"],
    // Expr = "Int" (*) [","],
    // Expr = "Int" (*) [";"]
    //
    // Select the last one.
    let semi = Lookahead::Terminal(term(";"));
    let semi_item = states[top_state.0].items.vec.iter()
                                                 .filter(|item| item.lookahead == semi)
                                                 .next()
                                                 .unwrap();

    let backtrace = tracer.backtrace(top_state, *semi_item);

    println!("{:#?}", backtrace);
    expect_debug(&backtrace, r#"BacktraceNode {
    item: Expr = "Int" (*),
    parents: [
        BacktraceNode {
            item: Exprs = (*) Expr,
            parents: [
                BacktraceNode {
                    item: Stmt = (*) Exprs ";",
                    parents: []
                }
            ]
        },
        BacktraceNode {
            item: Exprs = Exprs "," (*) Expr,
            parents: [
                BacktraceNode {
                    item: Stmt = (*) Exprs ";",
                    parents: []
                }
            ]
        }
    ]
}"#);
}

#[test]
fn backtrace2() {
    let grammar = test_grammar1();
    let session = Session::test();
    let states = build_states(&session, &grammar, nt("Start")).unwrap();
    let mut tracer = Tracer::new(&session, &grammar, &states);
    let state_stack = interpret_partial(&states, terms!["Int"]).unwrap();
    let top_state = *state_stack.last().unwrap();

    // Top state will have items like:
    //
    // Expr = "Int" (*) [EOF],
    // Expr = "Int" (*) ["+"],
    // Expr = "Int" (*) [","],
    // Expr = "Int" (*) [";"]
    //
    // Select the last one.
    let plus = Lookahead::Terminal(term("+"));
    let plus_item = states[top_state.0].items.vec.iter()
                                                 .filter(|item| item.lookahead == plus)
                                                 .next()
                                                 .unwrap();

    let backtrace = tracer.backtrace(top_state, *plus_item);

    println!("{:#?}", backtrace);
    expect_debug(&backtrace, r#"BacktraceNode {
    item: Expr = "Int" (*),
    parents: [
        BacktraceNode {
            item: Expr = (*) Expr "+" "Int",
            parents: []
        }
    ]
}"#);
}

#[test]
fn backtrace3() {
    // This grammar yields a S/R conflict. Is it (int -> int) -> int
    // or int -> (int -> int)?
    let grammar = normalized_grammar(r#"
grammar;
pub Ty: () = {
    "int" => (),
    "bool" => (),
    <t1:Ty> "->" <t2:Ty> => (),
};
"#);
    let session = Session::test();
    let states = build_states(&session, &grammar, nt("Ty")).unwrap_err().states;
    let mut tracer = Tracer::new(&session, &grammar, &states);
    let (&lookahead, conflict) =
        states.iter()
              .flat_map(|s| &s.conflicts)
              .flat_map(|(l, cs)| cs.iter().map(move |c| (l, c)))
              .next()
              .unwrap();
    println!("conflict={:?}", conflict);
    let item = Item { production: conflict.production,
                      index: conflict.production.symbols.len(),
                      lookahead: lookahead };
    println!("item={:?}", item);
    let backtrace = tracer.backtrace(conflict.state, item);
    println!("{:#?}", backtrace);
    expect_debug(&backtrace, r#"
BacktraceNode {
    item: Ty = Ty "->" Ty (*),
    parents: [
        BacktraceNode {
            item: Ty = (*) Ty "->" Ty,
            parents: []
        },
        BacktraceNode {
            item: Ty = Ty "->" (*) Ty,
            parents: [
                BacktraceNode {
                    item: Ty = (*) Ty "->" Ty,
                    parents: []
                },
                BacktraceNode {
                    item: Ty = Ty "->" (*) Ty,
                    parents: []
                }
            ]
        }
    ]
}
"#.trim());

    // Check that we can successfully enumerate and pain the examples
    // here.
    let pictures: Vec<_> = backtrace.examples().map(|e| e.paint()).collect();
    expect_debug(&pictures, r#"
[
    [
        "Ty \"->\" Ty \"->\" Ty",
        "|        |       |",
        "+-Ty-----+       |",
        "|                |",
        "+-Ty-------------+"
    ],
    [
        "Ty \"->\" Ty \"->\" Ty \"->\" Ty",
        "|       |        |       |",
        "|       +-Ty-----+       |",
        "|                |       |",
        "+-Ty-------------+       |",
        "|                        |",
        "+-Ty---------------------+"
    ],
    [
        "Ty \"->\" Ty \"->\" Ty \"->\" Ty",
        "|       |       |        |",
        "|       |       +-Ty-----+",
        "|       |                |",
        "|       +-Ty-------------+",
        "|                        |",
        "+-Ty---------------------+"
    ]
]
"#.trim());
}
<|endoftext|>


<commit_before><commit_msg>Missing newline. <Branch closed><commit_after><|endoftext|>


<commit_before>// The code below is a stub. Just enough to satisfy the compiler.
// In order to pass the tests you can add-to or change any of this code.

#[derive(PartialEq, Debug)]
pub enum Direction {
    North,
    East,
    South,
    West,
}

impl Direction {
    fn turn_right(self) -> Self {
        match self {
            Direction::North => Direction::East,
            Direction::East => Direction::South,
            Direction::South => Direction::West,
            Direction::West => Direction::North,
        }
    }

    fn turn_left(self) -> Self {
        match self {
            Direction::North => Direction::West,
            Direction::East => Direction::North,
            Direction::South => Direction::East,
            Direction::West => Direction::South,
        }
    }
}

pub struct Robot {
    rx: isize,
    ry: isize,
    rd: Direction,
}

impl Robot {
    #[allow(unused_variables)]
    pub fn new(x: isize, y: isize, d: Direction) -> Self {
        Robot {
            rx: x,
            ry: y,
            rd: d,
        }
    }

    pub fn turn_right(self) -> Self {
        Robot {
            rx: self.rx,
            ry: self.ry,
            rd: self.rd.turn_right(),
        }
    }

    pub fn turn_left(self) -> Self {
        Robot {
            rx: self.rx,
            ry: self.ry,
            rd: self.rd.turn_left(),
        }
    }

    pub fn advance(self) -> Self {
        let (x, y) = match self.rd {
            Direction::North => (self.rx, self.ry + 1),
            Direction::East => (self.rx + 1, self.ry),
            Direction::South => (self.rx, self.ry - 1),
            Direction::West => (self.rx - 1, self.ry),
        };

        Robot {
            rx: x,
            ry: y,
            rd: self.rd,
        }
    }

    #[allow(unused_variables)]
    pub fn instructions(self, instructions: &str) -> Self {
        let mut r = self;
        for c in instructions.chars() {
            r = match c {
                'L' => r.turn_left(),
                'R' => r.turn_right(),
                'A' => r.advance(),
                _ => r,
            };
        }

        r
    }

    pub fn position(&self) -> (isize, isize) {
        (self.rx, self.ry)
    }

    pub fn direction(&self) -> &Direction {
        &self.rd
    }
}
<commit_msg>Remove methods for Direction<commit_after>// The code below is a stub. Just enough to satisfy the compiler.
// In order to pass the tests you can add-to or change any of this code.

#[derive(PartialEq, Debug)]
pub enum Direction {
    North,
    East,
    South,
    West,
}

pub struct Robot {
    rx: isize,
    ry: isize,
    rd: Direction,
}

impl Robot {
    #[allow(unused_variables)]
    pub fn new(x: isize, y: isize, d: Direction) -> Self {
        Robot {
            rx: x,
            ry: y,
            rd: d,
        }
    }

    pub fn turn_right(self) -> Self {
        Robot {
            rx: self.rx,
            ry: self.ry,
            rd: match self.rd {
                Direction::North => Direction::East,
                Direction::East => Direction::South,
                Direction::South => Direction::West,
                Direction::West => Direction::North,
            },
        }
    }

    pub fn turn_left(self) -> Self {
        Robot {
            rx: self.rx,
            ry: self.ry,
            rd: match self.rd {
                Direction::North => Direction::West,
                Direction::East => Direction::North,
                Direction::South => Direction::East,
                Direction::West => Direction::South,
            },
        }
    }

    pub fn advance(self) -> Self {
        let (x, y) = match self.rd {
            Direction::North => (self.rx, self.ry + 1),
            Direction::East => (self.rx + 1, self.ry),
            Direction::South => (self.rx, self.ry - 1),
            Direction::West => (self.rx - 1, self.ry),
        };

        Robot {
            rx: x,
            ry: y,
            rd: self.rd,
        }
    }

    #[allow(unused_variables)]
    pub fn instructions(self, instructions: &str) -> Self {
        let mut r = self;
        for c in instructions.chars() {
            r = match c {
                'L' => r.turn_left(),
                'R' => r.turn_right(),
                'A' => r.advance(),
                _ => r,
            };
        }

        r
    }

    pub fn position(&self) -> (isize, isize) {
        (self.rx, self.ry)
    }

    pub fn direction(&self) -> &Direction {
        &self.rd
    }
}
<|endoftext|>


<commit_before>// This file is part of the uutils coreutils package.
//
// (c) Maciej Dziardziel <fiedzia@gmail.com>
//
// For the full copyright and license information, please view the LICENSE file
// that was distributed with this source code.

// spell-checker:ignore (vars/api) fcntl setrlimit setitimer
// spell-checker:ignore (vars/signals) ABRT ALRM CHLD SEGV SIGABRT SIGALRM SIGBUS SIGCHLD SIGCONT SIGEMT SIGFPE SIGHUP SIGILL SIGINFO SIGINT SIGIO SIGIOT SIGKILL SIGPIPE SIGPROF SIGQUIT SIGSEGV SIGSTOP SIGSYS SIGTERM SIGTRAP SIGTSTP SIGTTIN SIGTTOU SIGURG SIGUSR SIGVTALRM SIGWINCH SIGXCPU SIGXFSZ STKFLT TSTP TTIN TTOU VTALRM XCPU XFSZ

pub static DEFAULT_SIGNAL: usize = 15;

pub struct Signal<'a> {
    pub name: &'a str,
    pub value: usize,
}

/*

Linux Programmer's Manual

 1 HUP      2 INT      3 QUIT     4 ILL      5 TRAP     6 ABRT     7 BUS
 8 FPE      9 KILL    10 USR1    11 SEGV    12 USR2    13 PIPE    14 ALRM
15 TERM    16 STKFLT  17 CHLD    18 CONT    19 STOP    20 TSTP    21 TTIN
22 TTOU    23 URG     24 XCPU    25 XFSZ    26 VTALRM  27 PROF    28 WINCH
29 POLL    30 PWR     31 SYS

*/

#[cfg(target_os = "linux")]
pub static ALL_SIGNALS: [Signal<'static>; 32] = [
    Signal {
        name: "EXIT",
        value: 0,
    },
    Signal {
        name: "HUP",
        value: 1,
    },
    Signal {
        name: "INT",
        value: 2,
    },
    Signal {
        name: "QUIT",
        value: 3,
    },
    Signal {
        name: "ILL",
        value: 4,
    },
    Signal {
        name: "TRAP",
        value: 5,
    },
    Signal {
        name: "ABRT",
        value: 6,
    },
    Signal {
        name: "BUS",
        value: 7,
    },
    Signal {
        name: "FPE",
        value: 8,
    },
    Signal {
        name: "KILL",
        value: 9,
    },
    Signal {
        name: "USR1",
        value: 10,
    },
    Signal {
        name: "SEGV",
        value: 11,
    },
    Signal {
        name: "USR2",
        value: 12,
    },
    Signal {
        name: "PIPE",
        value: 13,
    },
    Signal {
        name: "ALRM",
        value: 14,
    },
    Signal {
        name: "TERM",
        value: 15,
    },
    Signal {
        name: "STKFLT",
        value: 16,
    },
    Signal {
        name: "CHLD",
        value: 17,
    },
    Signal {
        name: "CONT",
        value: 18,
    },
    Signal {
        name: "STOP",
        value: 19,
    },
    Signal {
        name: "TSTP",
        value: 20,
    },
    Signal {
        name: "TTIN",
        value: 21,
    },
    Signal {
        name: "TTOU",
        value: 22,
    },
    Signal {
        name: "URG",
        value: 23,
    },
    Signal {
        name: "XCPU",
        value: 24,
    },
    Signal {
        name: "XFSZ",
        value: 25,
    },
    Signal {
        name: "VTALRM",
        value: 26,
    },
    Signal {
        name: "PROF",
        value: 27,
    },
    Signal {
        name: "WINCH",
        value: 28,
    },
    Signal {
        name: "POLL",
        value: 29,
    },
    Signal {
        name: "PWR",
        value: 30,
    },
    Signal {
        name: "SYS",
        value: 31,
    },
];

/*

https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/signal.3.html

No    Name         Default Action       Description
1     SIGHUP       terminate process    terminal line hangup
2     SIGINT       terminate process    interrupt program
3     SIGQUIT      create core image    quit program
4     SIGILL       create core image    illegal instruction
5     SIGTRAP      create core image    trace trap
6     SIGABRT      create core image    abort program (formerly SIGIOT)
7     SIGEMT       create core image    emulate instruction executed
8     SIGFPE       create core image    floating-point exception
9     SIGKILL      terminate process    kill program
10    SIGBUS       create core image    bus error
11    SIGSEGV      create core image    segmentation violation
12    SIGSYS       create core image    non-existent system call invoked
13    SIGPIPE      terminate process    write on a pipe with no reader
14    SIGALRM      terminate process    real-time timer expired
15    SIGTERM      terminate process    software termination signal
16    SIGURG       discard signal       urgent condition present on socket
17    SIGSTOP      stop process         stop (cannot be caught or ignored)
18    SIGTSTP      stop process         stop signal generated from keyboard
19    SIGCONT      discard signal       continue after stop
20    SIGCHLD      discard signal       child status has changed
21    SIGTTIN      stop process         background read attempted from control terminal
22    SIGTTOU      stop process         background write attempted to control terminal
23    SIGIO        discard signal       I/O is possible on a descriptor (see fcntl(2))
24    SIGXCPU      terminate process    cpu time limit exceeded (see setrlimit(2))
25    SIGXFSZ      terminate process    file size limit exceeded (see setrlimit(2))
26    SIGVTALRM    terminate process    virtual time alarm (see setitimer(2))
27    SIGPROF      terminate process    profiling timer alarm (see setitimer(2))
28    SIGWINCH     discard signal       Window size change
29    SIGINFO      discard signal       status request from keyboard
30    SIGUSR1      terminate process    User defined signal 1
31    SIGUSR2      terminate process    User defined signal 2

*/

#[cfg(any(target_vendor = "apple", target_os = "freebsd"))]
pub static ALL_SIGNALS: [Signal<'static>; 32] = [
    Signal {
        name: "EXIT",
        value: 0,
    },
    Signal {
        name: "HUP",
        value: 1,
    },
    Signal {
        name: "INT",
        value: 2,
    },
    Signal {
        name: "QUIT",
        value: 3,
    },
    Signal {
        name: "ILL",
        value: 4,
    },
    Signal {
        name: "TRAP",
        value: 5,
    },
    Signal {
        name: "ABRT",
        value: 6,
    },
    Signal {
        name: "EMT",
        value: 7,
    },
    Signal {
        name: "FPE",
        value: 8,
    },
    Signal {
        name: "KILL",
        value: 9,
    },
    Signal {
        name: "BUS",
        value: 10,
    },
    Signal {
        name: "SEGV",
        value: 11,
    },
    Signal {
        name: "SYS",
        value: 12,
    },
    Signal {
        name: "PIPE",
        value: 13,
    },
    Signal {
        name: "ALRM",
        value: 14,
    },
    Signal {
        name: "TERM",
        value: 15,
    },
    Signal {
        name: "URG",
        value: 16,
    },
    Signal {
        name: "STOP",
        value: 17,
    },
    Signal {
        name: "TSTP",
        value: 18,
    },
    Signal {
        name: "CONT",
        value: 19,
    },
    Signal {
        name: "CHLD",
        value: 20,
    },
    Signal {
        name: "TTIN",
        value: 21,
    },
    Signal {
        name: "TTOU",
        value: 22,
    },
    Signal {
        name: "IO",
        value: 23,
    },
    Signal {
        name: "XCPU",
        value: 24,
    },
    Signal {
        name: "XFSZ",
        value: 25,
    },
    Signal {
        name: "VTALRM",
        value: 26,
    },
    Signal {
        name: "PROF",
        value: 27,
    },
    Signal {
        name: "WINCH",
        value: 28,
    },
    Signal {
        name: "INFO",
        value: 29,
    },
    Signal {
        name: "USR1",
        value: 30,
    },
    Signal {
        name: "USR2",
        value: 31,
    },
];

pub fn signal_by_name_or_value(signal_name_or_value: &str) -> Option<usize> {
    if let Ok(value) = signal_name_or_value.parse() {
        if is_signal(value) {
            return Some(value);
        } else {
            return None;
        }
    }
    let signal_name = signal_name_or_value.trim_start_matches("SIG");

    ALL_SIGNALS
        .iter()
        .find(|s| s.name == signal_name)
        .map(|s| s.value)
}

pub fn signal_name_by_value(signal_value: usize) -> Option<&'static str> {
    ALL_SIGNALS
        .iter()
        .find(|signal| signal.value == signal_value)
        .map(|signal| signal.name)
}

#[inline(always)]
pub fn is_signal(num: usize) -> bool {
    // Named signals start at 1
    num <= ALL_SIGNALS.len()
}

#[test]
fn signals_all_contiguous() {
    for (i, signal) in ALL_SIGNALS.iter().enumerate() {
        assert_eq!(signal.value, i);
    }
}

#[test]
fn signals_all_are_signal() {
    for signal in &ALL_SIGNALS {
        assert!(is_signal(signal.value));
    }
}

#[test]
fn signal_by_value() {
    assert_eq!(signal_by_name_or_value("0"), Some(0));
    for signal in &ALL_SIGNALS {
        assert_eq!(
            signal_by_name_or_value(&signal.value.to_string()),
            Some(signal.value)
        );
    }
}

#[test]
fn signal_by_short_name() {
    for signal in &ALL_SIGNALS {
        assert_eq!(signal_by_name_or_value(signal.name), Some(signal.value));
    }
}

#[test]
fn signal_by_long_name() {
    for signal in &ALL_SIGNALS {
        assert_eq!(
            signal_by_name_or_value(&format!("SIG{}", signal.name)),
            Some(signal.value)
        );
    }
}

#[test]
fn name() {
    for signal in &ALL_SIGNALS {
        assert_eq!(signal_name_by_value(signal.value), Some(signal.name));
    }
}
<commit_msg>core: represent signal values by  their index<commit_after>// This file is part of the uutils coreutils package.
//
// (c) Maciej Dziardziel <fiedzia@gmail.com>
//
// For the full copyright and license information, please view the LICENSE file
// that was distributed with this source code.

// spell-checker:ignore (vars/api) fcntl setrlimit setitimer
// spell-checker:ignore (vars/signals) ABRT ALRM CHLD SEGV SIGABRT SIGALRM SIGBUS SIGCHLD SIGCONT SIGEMT SIGFPE SIGHUP SIGILL SIGINFO SIGINT SIGIO SIGIOT SIGKILL SIGPIPE SIGPROF SIGQUIT SIGSEGV SIGSTOP SIGSYS SIGTERM SIGTRAP SIGTSTP SIGTTIN SIGTTOU SIGURG SIGUSR SIGVTALRM SIGWINCH SIGXCPU SIGXFSZ STKFLT TSTP TTIN TTOU VTALRM XCPU XFSZ

pub static DEFAULT_SIGNAL: usize = 15;

/*

Linux Programmer's Manual

 1 HUP      2 INT      3 QUIT     4 ILL      5 TRAP     6 ABRT     7 BUS
 8 FPE      9 KILL    10 USR1    11 SEGV    12 USR2    13 PIPE    14 ALRM
15 TERM    16 STKFLT  17 CHLD    18 CONT    19 STOP    20 TSTP    21 TTIN
22 TTOU    23 URG     24 XCPU    25 XFSZ    26 VTALRM  27 PROF    28 WINCH
29 POLL    30 PWR     31 SYS

*/

#[cfg(target_os = "linux")]
pub static ALL_SIGNALS: [&str; 32] = [
    "EXIT", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "BUS", "FPE", "KILL", "USR1", "SEGV",
    "USR2", "PIPE", "ALRM", "TERM", "STKFLT", "CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU",
    "URG", "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "POLL", "PWR", "SYS",
];

/*

https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/signal.3.html

No    Name         Default Action       Description
1     SIGHUP       terminate process    terminal line hangup
2     SIGINT       terminate process    interrupt program
3     SIGQUIT      create core image    quit program
4     SIGILL       create core image    illegal instruction
5     SIGTRAP      create core image    trace trap
6     SIGABRT      create core image    abort program (formerly SIGIOT)
7     SIGEMT       create core image    emulate instruction executed
8     SIGFPE       create core image    floating-point exception
9     SIGKILL      terminate process    kill program
10    SIGBUS       create core image    bus error
11    SIGSEGV      create core image    segmentation violation
12    SIGSYS       create core image    non-existent system call invoked
13    SIGPIPE      terminate process    write on a pipe with no reader
14    SIGALRM      terminate process    real-time timer expired
15    SIGTERM      terminate process    software termination signal
16    SIGURG       discard signal       urgent condition present on socket
17    SIGSTOP      stop process         stop (cannot be caught or ignored)
18    SIGTSTP      stop process         stop signal generated from keyboard
19    SIGCONT      discard signal       continue after stop
20    SIGCHLD      discard signal       child status has changed
21    SIGTTIN      stop process         background read attempted from control terminal
22    SIGTTOU      stop process         background write attempted to control terminal
23    SIGIO        discard signal       I/O is possible on a descriptor (see fcntl(2))
24    SIGXCPU      terminate process    cpu time limit exceeded (see setrlimit(2))
25    SIGXFSZ      terminate process    file size limit exceeded (see setrlimit(2))
26    SIGVTALRM    terminate process    virtual time alarm (see setitimer(2))
27    SIGPROF      terminate process    profiling timer alarm (see setitimer(2))
28    SIGWINCH     discard signal       Window size change
29    SIGINFO      discard signal       status request from keyboard
30    SIGUSR1      terminate process    User defined signal 1
31    SIGUSR2      terminate process    User defined signal 2

*/

#[cfg(any(target_vendor = "apple", target_os = "freebsd"))]
pub static ALL_SIGNALS: [&str; 32] = [
    "EXIT", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "EMT", "FPE", "KILL", "BUS", "SEGV",
    "SYS", "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", "CONT", "CHLD", "TTIN", "TTOU", "IO",
    "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "INFO", "USR1", "USR2",
];

pub fn signal_by_name_or_value(signal_name_or_value: &str) -> Option<usize> {
    if let Ok(value) = signal_name_or_value.parse() {
        if is_signal(value) {
            return Some(value);
        } else {
            return None;
        }
    }
    let signal_name = signal_name_or_value.trim_start_matches("SIG");

    ALL_SIGNALS.iter().position(|&s| s == signal_name)
}

pub fn is_signal(num: usize) -> bool {
    num < ALL_SIGNALS.len()
}

pub fn signal_name_by_value(signal_value: usize) -> Option<&'static str> {
    ALL_SIGNALS.get(signal_value).copied()
}

#[test]
fn signal_by_value() {
    assert_eq!(signal_by_name_or_value("0"), Some(0));
    for (value, _signal) in ALL_SIGNALS.iter().enumerate() {
        assert_eq!(signal_by_name_or_value(&value.to_string()), Some(value));
    }
}

#[test]
fn signal_by_short_name() {
    for (value, signal) in ALL_SIGNALS.iter().enumerate() {
        assert_eq!(signal_by_name_or_value(signal), Some(value));
    }
}

#[test]
fn signal_by_long_name() {
    for (value, signal) in ALL_SIGNALS.iter().enumerate() {
        assert_eq!(
            signal_by_name_or_value(&format!("SIG{}", signal)),
            Some(value)
        );
    }
}

#[test]
fn name() {
    for (value, signal) in ALL_SIGNALS.iter().enumerate() {
        assert_eq!(signal_name_by_value(value), Some(*signal));
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
extern crate collections;

use std::io;
use std::vec::Vec;
use std::io::Reader;
use self::collections::smallintmap::SmallIntMap;

priv struct Memory {
    mem: ~[u8],
    memptr: uint,
    codeptr: uint,
    cache: SmallIntMap<uint>
}

pub struct BrainfuckVM <'c> {
    code: ~Vec<u8>,
    length: uint
}

impl <'c> BrainfuckVM <'c> {
    pub fn new<T: Reader>(reader: &mut T) -> BrainfuckVM<'c> {

        let code = ~reader.read_to_end().ok().unwrap_or(Vec::new());
        let length = code.len().clone();

        BrainfuckVM {
            code: code,
            length: length
        }
    }

    pub fn run(&self) -> bool {
        let mut state = Memory{
            mem: ~[0],
            memptr: 0,
            codeptr: 0,
            cache: SmallIntMap::with_capacity(self.length/4)
        };
        state.mem.grow(self.length / 2, &0);
        self.eval(&mut state)

    }

    #[inline]
    fn eval(&self, state: &mut Memory) -> bool {
        while state.codeptr < self.length {
            match *self.code.get(state.codeptr) as char {
                '>' => {
                    state.memptr += 1;
                    if state.memptr as uint > state.mem.len()-1{
                        state.mem.push(0);
                    }
                },
                '<' => if !(state.memptr as uint <= 0) {
                    state.memptr -= 1;
                },
                '+' =>  state.mem[state.memptr] += 1,
                '-' => state.mem[state.memptr] -= 1,
                '.' => print!("{}", state.mem[state.memptr] as char),
                ',' => state.mem[state.memptr] = match io::stdin().read_byte() {
                    Ok(b) => b,
                    Err(_) =>  0
                },
                '[' =>  self.jump_to(state, ']'),
                ']' => self.jump_to(state, '['),
                _ => { }
            };
            state.codeptr += 1;
        }
        return true;
    }

    #[inline]
    fn jump_to(&self, state: &mut Memory, jumpToBrace: char) {
        let jump = match jumpToBrace {
            ']' => state.mem[state.memptr] == 0,
            '[' => state.mem[state.memptr] != 0,
            _ => false
        };
        if jump {
            self.jump_and_cache(state, jumpToBrace);
        }
    }

    #[inline]
    fn jump_and_cache(&self, state: &mut Memory, brace: char) {
        let mut depth = 0;
        let (otherBrace, incr) = if brace == '[' { (']', -1) } else { ('[', 1) };
        let start = state.codeptr;
        let found = *state.cache.find(&state.codeptr).unwrap_or(&0);
        if found > 0 {
            state.codeptr = found;
        } else {
            state.codeptr += incr;
            let mut currentChar = *self.code.get(state.codeptr) as char;
            while depth > 0 || currentChar != brace {
                if currentChar == otherBrace {
                    depth += 1;
                } else if currentChar == brace {
                    depth -= 1;
                }
                state.codeptr += incr;
                currentChar = *self.code.get(state.codeptr) as char;
            }
            state.cache.insert(start, state.codeptr);
        }
    }
}
<commit_msg>Remove lifetime parameter<commit_after>#![allow(dead_code)]
extern crate collections;

use std::io;
use std::vec::Vec;
use std::io::Reader;
use self::collections::smallintmap::SmallIntMap;

priv struct Memory {
    mem: ~[u8],
    memptr: uint,
    codeptr: uint,
    cache: SmallIntMap<uint>
}

pub struct BrainfuckVM {
    code: ~Vec<u8>,
    length: uint
}

impl BrainfuckVM {
    pub fn new<T: Reader>(reader: &mut T) -> BrainfuckVM {

        let code = ~reader.read_to_end().ok().unwrap_or(Vec::new());
        let length = code.len().clone();

        BrainfuckVM {
            code: code,
            length: length
        }
    }

    pub fn run(&self) -> bool {
        let mut state = Memory{
            mem: ~[0],
            memptr: 0,
            codeptr: 0,
            cache: SmallIntMap::with_capacity(self.length/4)
        };
        state.mem.grow(self.length / 2, &0);
        self.eval(&mut state)

    }

    #[inline]
    fn eval(&self, state: &mut Memory) -> bool {
        while state.codeptr < self.length {
            match *self.code.get(state.codeptr) as char {
                '>' => {
                    state.memptr += 1;
                    if state.memptr as uint > state.mem.len()-1{
                        state.mem.push(0);
                    }
                },
                '<' => if !(state.memptr as uint <= 0) {
                    state.memptr -= 1;
                },
                '+' =>  state.mem[state.memptr] += 1,
                '-' => state.mem[state.memptr] -= 1,
                '.' => print!("{}", state.mem[state.memptr] as char),
                ',' => state.mem[state.memptr] = match io::stdin().read_byte() {
                    Ok(b) => b,
                    Err(_) =>  0
                },
                '[' =>  self.jump_to(state, ']'),
                ']' => self.jump_to(state, '['),
                _ => { }
            };
            state.codeptr += 1;
        }
        return true;
    }

    #[inline]
    fn jump_to(&self, state: &mut Memory, jumpToBrace: char) {
        let jump = match jumpToBrace {
            ']' => state.mem[state.memptr] == 0,
            '[' => state.mem[state.memptr] != 0,
            _ => false
        };
        if jump {
            self.jump_and_cache(state, jumpToBrace);
        }
    }

    #[inline]
    fn jump_and_cache(&self, state: &mut Memory, brace: char) {
        let mut depth = 0;
        let (otherBrace, incr) = if brace == '[' { (']', -1) } else { ('[', 1) };
        let start = state.codeptr;
        let found = *state.cache.find(&state.codeptr).unwrap_or(&0);
        if found > 0 {
            state.codeptr = found;
        } else {
            state.codeptr += incr;
            let mut currentChar = *self.code.get(state.codeptr) as char;
            while depth > 0 || currentChar != brace {
                if currentChar == otherBrace {
                    depth += 1;
                } else if currentChar == brace {
                    depth -= 1;
                }
                state.codeptr += incr;
                currentChar = *self.code.get(state.codeptr) as char;
            }
            state.cache.insert(start, state.codeptr);
        }
    }
}
<|endoftext|>


<commit_before>use rand::os::OsRng;
use rand::{XorShiftRng, Rand, Rng};
use rand::distributions::{IndependentSample, Range};

use na::Pnt2 as Point2;

use tile::Tile;

use level::Level;

pub struct RoomGen {
    rand_x: XorShiftRng,
    rand_y: XorShiftRng,
    max_room_size: usize,
    min_room_size: usize,
    room_distance: usize,
    attempts: u64,
    rooms: Vec<Room>,
}

impl RoomGen {
    pub fn new(min_room_size: usize, max_room_size: usize, room_distance: usize, attempts :u64) -> RoomGen {
        RoomGen{
            rand_x: XorShiftRng::rand(&mut OsRng::new().unwrap()),
            rand_y: XorShiftRng::rand(&mut OsRng::new().unwrap()),
            max_room_size: max_room_size,
            min_room_size: min_room_size,
            room_distance: room_distance,
            attempts: attempts,
            rooms: Vec::new(),
        }
    }

    pub fn generate(&mut self, level: &mut Level) {
        for i in 0..self.attempts {
            let room = self.generate_box(level);

            let fits = !self.check_collisions(room);
            if fits {
                self.rooms.push(room);
            }
        }
        self.carve(level);
    }

    pub fn reset_rooms(&mut self) {
        self.rooms = Vec::new();
    }

    fn generate_box(&mut self, level: &mut Level) -> Room {
        let min_range_x = Range::new(0, level.get_width());
        let min_range_y = Range::new(0, level.get_height());
        let mut min = Point2::new(min_range_x.ind_sample(&mut self.rand_x), min_range_y.ind_sample(&mut self.rand_y));

        let max_range = Range::new(self.min_room_size, self.max_room_size);
        let mut max = Point2::new(max_range.ind_sample(&mut self.rand_x), max_range.ind_sample(&mut self.rand_y));
        max.x += min.x;
        max.y += min.y;
        max.x += self.room_distance;
        max.y += self.room_distance;

        Room{min: min, max: max}
    }

    fn check_collisions(&self, room: Room) -> bool {
        for b in self.rooms {
            if room.overlaps(b) {
                return true;
            }
        }
        false
    }

    fn carve(&self, level: &mut Level) {
        let room_distance = self.room_distance.clone();
        for room in self.rooms {
            for y in room.min.y..room.max.y-room_distance+1 {
                for x in room.min.x..room.max.x-room_distance+1 {
                    match level.get_mut_tile(x, y) {
                        Some(tile) => *tile = Tile::Floor,
                        None => {}
                    }
                }
            }
        }
    }
}

struct Room {
    pub min: Point2<usize>,
    pub max: Point2<usize>,
}

impl Room {
    pub fn overlaps(&self, room: Room) -> bool {
        if self.min.x > room.max.x || room.min.x > self.max.x {
            return false;
        }

        if self.min.y > room.max.y || room.min.y > self.max.y {
            return false;
        }
        true
    }
}
<commit_msg>RoomGen compiles.<commit_after>use rand::os::OsRng;
use rand::{XorShiftRng, Rand};
use rand::distributions::{IndependentSample, Range};

use na::Pnt2 as Point2;

use tile::Tile;

use level::Level;

pub struct RoomGen {
    rand_x: XorShiftRng,
    rand_y: XorShiftRng,
    max_room_size: usize,
    min_room_size: usize,
    room_distance: usize,
    attempts: u64,
    rooms: Vec<Room>,
}

impl RoomGen {
    pub fn new(min_room_size: usize, max_room_size: usize, room_distance: usize, attempts :u64) -> RoomGen {
        RoomGen{
            rand_x: XorShiftRng::rand(&mut OsRng::new().unwrap()),
            rand_y: XorShiftRng::rand(&mut OsRng::new().unwrap()),
            max_room_size: max_room_size,
            min_room_size: min_room_size,
            room_distance: room_distance,
            attempts: attempts,
            rooms: Vec::new(),
        }
    }

    pub fn generate(&mut self, level: &mut Level) {
        for _ in 0..self.attempts {
            let room = self.generate_box(level);

            let fits = !self.check_collisions(&room);
            if fits {
                self.rooms.push(room);
            }
        }
        self.carve(level);
    }

    pub fn reset_rooms(&mut self) {
        self.rooms = Vec::new();
    }

    fn generate_box(&mut self, level: &mut Level) -> Room {
        let min_range_x = Range::new(0, level.get_width());
        let min_range_y = Range::new(0, level.get_height());
        let min = Point2::new(min_range_x.ind_sample(&mut self.rand_x), min_range_y.ind_sample(&mut self.rand_y));

        let max_range = Range::new(self.min_room_size, self.max_room_size);
        let mut max = Point2::new(max_range.ind_sample(&mut self.rand_x), max_range.ind_sample(&mut self.rand_y));
        max.x += min.x;
        max.y += min.y;
        max.x += self.room_distance;
        max.y += self.room_distance;

        Room{min: min, max: max}
    }

    fn check_collisions(&self, room: &Room) -> bool {
        for b in &self.rooms {
            if room.overlaps(b) {
                return true;
            }
        }
        false
    }

    fn carve(&self, level: &mut Level) {
        let room_distance = self.room_distance.clone();
        for room in &self.rooms {
            for y in room.min.y..room.max.y-room_distance+1 {
                for x in room.min.x..room.max.x-room_distance+1 {
                    match level.get_mut_tile(x, y) {
                        Some(tile) => *tile = Tile::Floor,
                        None => {}
                    }
                }
            }
        }
    }
}

struct Room {
    pub min: Point2<usize>,
    pub max: Point2<usize>,
}

impl Room {
    pub fn overlaps(&self, room: &Room) -> bool {
        if self.min.x > room.max.x || room.min.x > self.max.x {
            return false;
        }

        if self.min.y > room.max.y || room.min.y > self.max.y {
            return false;
        }
        true
    }
}
<|endoftext|>


<commit_before>#[link(name="base64", vers="1.0.0", author="Jordy Dickinson")]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordy Dickinson <jordy.dickinson@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE file
 * that was distributed with this source code.
 */

extern mod extra;

use std::char;
use std::io::{File, stdin, stdout};
use std::os;
use std::str;

use extra::base64;
use extra::base64::{FromBase64, ToBase64};

fn main() {
    let mut conf = Conf::new(os::args());

    match conf.mode {
        Decode  => decode(&mut conf),
        Encode  => encode(&mut conf),
        Help    => help(&conf),
        Version => version()
    }
}

fn decode(conf: &mut Conf) {
    let mut to_decode = str::from_utf8_owned(conf.input_file.read_to_end());

    to_decode = to_decode.replace("\n", "");

    if conf.ignore_garbage {
        let standard_chars =
            bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
                   "abcdefghijklmnopqrstuvwxyz",
                   "0123456789+/").map(|b| char::from_u32(*b as u32).unwrap());

        to_decode = to_decode
            .trim_chars(&|c| !standard_chars.contains(&c))
            .to_owned();
    }

    match to_decode.from_base64() {
        Ok(bytes) => {
            let mut out = stdout();

            out.write(bytes);
            out.flush();
        }
        Err(s) => fail!(s)
    }
}

fn encode(conf: &mut Conf) {
    let b64_conf = base64::Config {
        char_set: base64::Standard,
        pad: true,
        line_length: match conf.line_wrap {
            0 => None,
            _ => Some(conf.line_wrap)
        }
    };
    let to_encode = conf.input_file.read_to_end();
    let mut encoded = to_encode.to_base64(b64_conf);

    // To my knowledge, RFC 3548 does not specify which line endings to use. It
    // seems that rust's base64 algorithm uses CRLF as prescribed by RFC 2045.
    // However, since GNU base64 outputs only LF (presumably because that is
    // the standard UNIX line ending), we strip CRs from the output to maintain
    // compatibility.
    encoded = encoded.replace("\r", "");

    println(encoded);
}

fn help(conf: &Conf) {
    println!("Usage: {:s} [OPTION]... [FILE]", conf.progname);
    println("");
    println(conf.usage);

    let msg = ~"With no FILE, or when FILE is -, read standard input.\n\n"
        + "The data are encoded as described for the base64 alphabet in RFC "
        + "3548. When\ndecoding, the input may contain newlines in addition "
        + "to the bytes of the formal\nbase64 alphabet. Use --ignore-garbage "
        + "to attempt to recover from any other\nnon-alphabet bytes in the "
        + "encoded stream.";

    println(msg);
}

fn version() {
    println("base64 1.0.0");
}

struct Conf {
    progname: ~str,
    usage: ~str,
    mode: Mode,
    ignore_garbage: bool,
    line_wrap: uint,
    input_file: ~Reader
}

impl Conf {
    fn new(args: &[~str]) -> Conf {
        // The use statement is here rather than at the top of the file so that
        // the reader is made directly aware that we're using getopts::groups,
        // and not just getopts. Also some names are somewhat vague taken out
        // of context (i.e., "usage").
        use extra::getopts::groups::{
            getopts,
            optflag,
            optopt,
            usage
        };

        let opts = ~[
            optflag("d", "decode", "decode data"),
            optflag("i", "ignore-garbage",
            "when decoding, ignore non-alphabetic characters"),
            optopt("w", "wrap",
            "wrap encoded lines after COLS character (default 76, 0 to disable"
            + " wrapping)", "COLS"),
            optflag("h", "help", "display this help text and exit"),
            optflag("V", "version", "output version information and exit")
        ];
        // TODO: The user should get a clean error message in the case that
        // unwrap() fails.
        let matches = getopts(args.tail(), opts).unwrap();

        Conf {
            progname: args[0].clone(),
            usage: usage("Base64 encode or decode FILE, or standard input, to "
                         + "standard output.", opts),
            mode: if matches.opt_present("help") {
                Help
            } else if matches.opt_present("version") {
                Version
            } else if matches.opt_present("decode") {
                Decode
            } else {
                Encode
            },
            ignore_garbage: matches.opt_present("ignore-garbage"),
            line_wrap: match matches.opt_str("wrap") {
                Some(s) => from_str(s).unwrap(),
                None => 76
            },
            input_file: if matches.free.is_empty()
                            || matches.free[0] == ~"-" {
                ~stdin() as ~Reader
            } else {
                let path = Path::new(matches.free[0]);
                ~File::open(&path) as ~Reader
            }
        }
    }
}

enum Mode {
    Decode,
    Encode,
    Help,
    Version
}

<commit_msg>base64: Improve error handling<commit_after>#[link(name="base64", vers="1.0.0", author="Jordy Dickinson")]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordy Dickinson <jordy.dickinson@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE file
 * that was distributed with this source code.
 */

extern mod extra;

use std::char;
use std::io::{File, stdin, stdout};
use std::os;
use std::str;

use extra::base64;
use extra::base64::{FromBase64, ToBase64};

fn main() {
    let mut conf = Conf::new(os::args());

    match conf.mode {
        Decode  => decode(&mut conf),
        Encode  => encode(&mut conf),
        Help    => help(&conf),
        Version => version()
    }
}

fn decode(conf: &mut Conf) {
    let mut to_decode = str::from_utf8_owned(conf.input_file.read_to_end());

    to_decode = to_decode.replace("\n", "");

    if conf.ignore_garbage {
        let standard_chars =
            bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
                   "abcdefghijklmnopqrstuvwxyz",
                   "0123456789+/").map(|b| char::from_u32(*b as u32).unwrap());

        to_decode = to_decode
            .trim_chars(&|c| !standard_chars.contains(&c))
            .to_owned();
    }

    match to_decode.from_base64() {
        Ok(bytes) => {
            let mut out = stdout();

            out.write(bytes);
            out.flush();
        }
        Err(s) => {
            error!("error: {:s}", s);
            fail!()
        }
    }
}

fn encode(conf: &mut Conf) {
    let b64_conf = base64::Config {
        char_set: base64::Standard,
        pad: true,
        line_length: match conf.line_wrap {
            0 => None,
            _ => Some(conf.line_wrap)
        }
    };
    let to_encode = conf.input_file.read_to_end();
    let mut encoded = to_encode.to_base64(b64_conf);

    // To my knowledge, RFC 3548 does not specify which line endings to use. It
    // seems that rust's base64 algorithm uses CRLF as prescribed by RFC 2045.
    // However, since GNU base64 outputs only LF (presumably because that is
    // the standard UNIX line ending), we strip CRs from the output to maintain
    // compatibility.
    encoded = encoded.replace("\r", "");

    println(encoded);
}

fn help(conf: &Conf) {
    println!("Usage: {:s} [OPTION]... [FILE]", conf.progname);
    println("");
    println(conf.usage);

    let msg = ~"With no FILE, or when FILE is -, read standard input.\n\n"
        + "The data are encoded as described for the base64 alphabet in RFC "
        + "3548. When\ndecoding, the input may contain newlines in addition "
        + "to the bytes of the formal\nbase64 alphabet. Use --ignore-garbage "
        + "to attempt to recover from any other\nnon-alphabet bytes in the "
        + "encoded stream.";

    println(msg);
}

fn version() {
    println("base64 1.0.0");
}

struct Conf {
    progname: ~str,
    usage: ~str,
    mode: Mode,
    ignore_garbage: bool,
    line_wrap: uint,
    input_file: ~Reader
}

impl Conf {
    fn new(args: &[~str]) -> Conf {
        // The use statement is here rather than at the top of the file so that
        // the reader is made directly aware that we're using getopts::groups,
        // and not just getopts. Also some names are somewhat vague taken out
        // of context (i.e., "usage").
        use extra::getopts::groups::{
            getopts,
            optflag,
            optopt,
            usage
        };

        let opts = ~[
            optflag("d", "decode", "decode data"),
            optflag("i", "ignore-garbage",
            "when decoding, ignore non-alphabetic characters"),
            optopt("w", "wrap",
            "wrap encoded lines after COLS character (default 76, 0 to disable"
            + " wrapping)", "COLS"),
            optflag("h", "help", "display this help text and exit"),
            optflag("V", "version", "output version information and exit")
        ];
        let matches = match getopts(args.tail(), opts) {
            Ok(m) => m,
            Err(e) => {
                error!("error: {:s}", e.to_err_msg());
                fail!()
            }
        };

        Conf {
            progname: args[0].clone(),
            usage: usage("Base64 encode or decode FILE, or standard input, to "
                         + "standard output.", opts),
            mode: if matches.opt_present("help") {
                Help
            } else if matches.opt_present("version") {
                Version
            } else if matches.opt_present("decode") {
                Decode
            } else {
                Encode
            },
            ignore_garbage: matches.opt_present("ignore-garbage"),
            line_wrap: match matches.opt_str("wrap") {
                Some(s) => match from_str(s) {
                    Some(s) => s,
                    None => {
                        error!("error: {:s}",
                               "Argument to option 'wrap' improperly "
                               + "formatted.");
                        fail!()
                    }
                },
                None => 76
            },
            input_file: if matches.free.is_empty()
                            || matches.free[0] == ~"-" {
                ~stdin() as ~Reader
            } else {
                let path = Path::new(matches.free[0]);
                ~File::open(&path) as ~Reader
            }
        }
    }
}

enum Mode {
    Decode,
    Encode,
    Help,
    Version
}

<|endoftext|>


<commit_before>//! Tests.

use std::str;

use {decompress, compress};

/// Test that the compressed string decompresses to the original string.
fn inverse(s: &str) {
    let compressed = compress(s.as_bytes());
    println!("Compressed '{}' into {:?}", s, compressed);
    let decompressed = decompress(&compressed).unwrap();
    println!("Decompressed it into {:?}", str::from_utf8(&decompressed).unwrap());
    assert_eq!(decompressed, s.as_bytes());
}

#[test]
fn shakespear() {
    inverse("to live or not to live");
    inverse("Love is a wonderful terrible thing");
}

#[test]
fn totally_not_antifa_propaganda() {
    inverse("The only good fascist is a dead fascist.");
    inverse("bash the fash");
    inverse("Dead fascists can't vote.");
    inverse("Good night, white pride.");
    inverse("Some say fascism started with gas chambers. I say that's where it ends.");
}

#[test]
fn not_compressible() {
    inverse("as6yhol.;jrew5tyuikbfewedfyjltre22459ba");
}

#[test]
fn short() {
    inverse("ahhd");
}

#[test]
fn empty_string() {
    inverse("");
}

#[test]
fn compression_works() {
    let s = "micah (Micah Cohen, politics editor): Clinton’s lead has shrunk to a hair above 4 percentage points in our polls-only model, down from about 7 points two weeks ago. So we find ourselves in an odd position where Clinton still holds a clear lead, but it’s shrinking by the day. I’ve been getting questions from Clinton supporters wondering how panicked they should be, and while we advise everyone of all political stripes to always remain calm, let’s try to answer that question today. How safe is Clinton’s lead/how panicked should Democrats be? As tacky as it is to cite your own tweet, I’m going to do it anyway — here’s a handy scale: natesilver: It’s uncertain, in part, because of the risk of a popular vote-Electoral College split. And, in part, because there are various reasons to think polling error could be high this year, such as the number of undecided voters. You can see those forces at play in the recent tightening. Clinton hasn’t really declined very much in these latest polls. But she was at only 46 percent in national polls, and that left a little bit of wiggle room for Trump.";

    inverse(s);

    assert!(compress(s.as_bytes()).len() < s.len());
}

#[test]
fn big_compression() {
    let mut s = Vec::with_capacity(80_000000);

    for n in 0..80_000000 {
        s.push((n as u8).wrapping_mul(0xA).wrapping_add(33) ^ 0xA2);
    }

    assert_eq!(&decompress(&compress(&s)).unwrap(), &s);
}
<commit_msg>Improve LZ4 testsuite.<commit_after>//! Tests.

use std::str;

use {decompress, compress};

/// Test that the compressed string decompresses to the original string.
fn inverse(s: &str) {
    let compressed = compress(s.as_bytes());
    println!("Compressed '{}' into {:?}", s, compressed);
    let decompressed = decompress(&compressed).unwrap();
    println!("Decompressed it into {:?}", str::from_utf8(&decompressed).unwrap());
    assert_eq!(decompressed, s.as_bytes());
}

#[test]
fn shakespear() {
    inverse("to live or not to live");
    inverse("Love is a wonderful terrible thing");
    inverse("There is nothing either good or bad, but thinking makes it so.");
    inverse("I burn, I pine, I perish.");
}

#[test]
fn totally_not_antifa_propaganda() {
    inverse("The only good fascist is a dead fascist.");
    inverse("bash the fash");
    inverse("the fash deserves no bash, only smash");
    inverse("Dead fascists can't vote.");
    inverse("Good night, white pride.");
    inverse("Some say fascism started with gas chambers. I say that's where it ends.");
}

#[test]
fn not_compressible() {
    inverse("as6yhol.;jrew5tyuikbfewedfyjltre22459ba");
    inverse("jhflkdjshaf9p8u89ybkvjsdbfkhvg4ut08yfrr");
}

#[test]
fn short() {
    inverse("ahhd");
    inverse("ahd");
    inverse("x-29");
    inverse("x");
    inverse("k");
    inverse(".");
    inverse("ajsdh");
}

#[test]
fn empty_string() {
    inverse("");
}

#[test]
fn nulls() {
    inverse("\0\0\0\0\0\0\0\0\0\0\0\0\0");
}

#[test]
fn compression_works() {
    let s = "micah (Micah Cohen, politics editor): Clinton’s lead has shrunk to a hair above 4 percentage points in our polls-only model, down from about 7 points two weeks ago. So we find ourselves in an odd position where Clinton still holds a clear lead, but it’s shrinking by the day. I’ve been getting questions from Clinton supporters wondering how panicked they should be, and while we advise everyone of all political stripes to always remain calm, let’s try to answer that question today. How safe is Clinton’s lead/how panicked should Democrats be? As tacky as it is to cite your own tweet, I’m going to do it anyway — here’s a handy scale: natesilver: It’s uncertain, in part, because of the risk of a popular vote-Electoral College split. And, in part, because there are various reasons to think polling error could be high this year, such as the number of undecided voters. You can see those forces at play in the recent tightening. Clinton hasn’t really declined very much in these latest polls. But she was at only 46 percent in national polls, and that left a little bit of wiggle room for Trump.";

    inverse(s);

    assert!(compress(s.as_bytes()).len() < s.len());
}

#[test]
fn big_compression() {
    let mut s = Vec::with_capacity(80_000000);

    for n in 0..80_000000 {
        s.push((n as u8).wrapping_mul(0xA).wrapping_add(33) ^ 0xA2);
    }

    assert_eq!(&decompress(&compress(&s)).unwrap(), &s);
}
<|endoftext|>


<commit_before>extern crate websocat;

extern crate env_logger;
extern crate futures;
extern crate tokio_core;
extern crate tokio_timer;

use futures::future::Future;

use tokio_core::reactor::Core;
use websocat::{spec, Options, WebsocatConfiguration};

fn dflt() -> Options {
    Default::default()
}

macro_rules! wt {
    ($core:ident, $s1:expr, $s2:expr,delay = $ms:expr, $($rest:tt)*) => {{
        let s1 = spec($s1).unwrap();
        let s2 = spec($s2).unwrap();
        let h2 = $core.handle();

        let t = tokio_timer::wheel().build();
        let delay = t
            .sleep(std::time::Duration::new(0, $ms * 1_000_000))
            .map_err(|_| ());

        delay.and_then(|()| wt!(stage2, h2, s1, s2, $($rest)*) )
    }};
    ($core:ident, $s1:expr, $s2:expr,nodelay,$($rest:tt)*) => {{
        let s1 = spec($s1).unwrap();
        let s2 = spec($s2).unwrap();
        let h2 = $core.handle();

        wt!(stage2, h2, s1, s2, $($rest)*)
    }};
    (stage2, $h2:ident, $s1:ident, $s2:ident, noopts,$($rest:tt)*) => {
        wt!(stage2, $h2, $s1, $s2, opts=Default::default(),$($rest)*)
    };
    (stage2, $h2:ident, $s1:ident, $s2:ident, opts=$opts:expr,$($rest:tt)*) => {{

        let websocat = WebsocatConfiguration {
            opts: $opts,
            $s1,
            $s2,
        };

        websocat.serve(
            $h2,
            wt!(stage3, $($rest)*),
        )
    }};
    (stage3, errpanic,) => {
        std::rc::Rc::new(|e| {
            eprintln!("{}", e);
            panic!();
        })
    };
    (stage3, errignore,) => {
        std::rc::Rc::new(|_| {

        })
    };
}

macro_rules! prepare {
    ($core:ident) => {
        let _ = env_logger::try_init();
        let mut $core = Core::new().unwrap();
    };
}
macro_rules! run {
    ($core:ident, $prog:expr) => {
        $core.run($prog).map_err(|()| panic!()).unwrap();
    };
}

#[test]
fn trivial() {
    prepare!(core);
    let prog = wt!(
        core,
        "literal:qwerty",
        "assert:qwerty",
        nodelay,
        noopts,
        errpanic,
    );
    run!(core, prog);
}

#[test]
fn tcp() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "literal:qwert2y",
        "tcp-l:127.0.0.1:45912",
        nodelay,
        noopts,
        errpanic,
    );
    let prog2 = wt!(
        core,
        "tcp:127.0.0.1:45912",
        "assert:qwert2y",
        delay = 200,
        noopts,
        errpanic,
    );

    let prog = prog1.join(prog2);
    run!(core, prog);
}

#[test]
fn ws() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "literal:qwert3y",
        "ws-l:127.0.0.1:45913",
        nodelay,
        noopts,
        errpanic,
    );
    let prog2 = wt!(
        core,
        "ws://127.0.0.1:45913/ololo",
        "assert:qwert3y",
        delay = 200,
        noopts,
        errpanic,
    );

    let prog = prog1.join(prog2);
    run!(core, prog);
}

#[test]
fn ws_persist() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "ws-l:127.0.0.1:45914",
        "literal:qwert4y",
        nodelay,
        noopts,
        errignore,
    );
    let prog2 = wt!(
        core,
        "literal:invalid_connection_request",
        "tcp:127.0.0.1:45914",
        delay = 200,
        noopts,
        errpanic,
    );
    let prog3 = wt!(
        core,
        "ws://127.0.0.1:45914/ololo",
        "assert:qwert4y",
        delay = 400,
        noopts,
        errpanic,
    );

    core.handle().spawn(prog1);
    core.handle().spawn(prog2);
    let prog = prog3;
    run!(core, prog);
}

#[test]
#[cfg(unix)]
fn unix() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "literal:qwert3y",
        "unix-l:zxc",
        nodelay,
        opts = Options {
            unlink_unix_socket: true,
            ..dflt()
        },
        errpanic,
    );
    let prog2 = wt!(
        core,
        "unix-c:zxc",
        "assert:qwert3y",
        delay = 200,
        noopts,
        errpanic,
    );

    let prog = prog1.join(prog2);
    run!(core, prog);
    let _ = ::std::fs::remove_file("zxc");
}

#[test]
#[cfg(any(target_os = "linux", target_os = "android"))]
fn abstract_() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "literal:qwert4y",
        "abstract-l:zxc",
        nodelay,
        noopts,
        errpanic,
    );
    let prog2 = wt!(
        core,
        "abstract-c:zxc",
        "assert:qwert4y",
        delay = 200,
        noopts,
        errpanic,
    );

    let prog = prog1.join(prog2);
    run!(core, prog);
}
<commit_msg>Fix the test<commit_after>extern crate websocat;

extern crate env_logger;
extern crate futures;
extern crate tokio_core;
extern crate tokio_timer;

use futures::future::Future;

use tokio_core::reactor::Core;
use websocat::{spec, Options, WebsocatConfiguration3};

fn dflt() -> Options {
    Default::default()
}

macro_rules! wt {
    ($core:ident, $s1:expr, $s2:expr,delay = $ms:expr, $($rest:tt)*) => {{
        let s1 = spec($s1).unwrap();
        let s2 = spec($s2).unwrap();
        let h2 = $core.handle();

        let t = tokio_timer::wheel().build();
        let delay = t
            .sleep(std::time::Duration::new(0, $ms * 1_000_000))
            .map_err(|_| ());

        delay.and_then(|()| wt!(stage2, h2, s1, s2, $($rest)*) )
    }};
    ($core:ident, $s1:expr, $s2:expr,nodelay,$($rest:tt)*) => {{
        let s1 = spec($s1).unwrap();
        let s2 = spec($s2).unwrap();
        let h2 = $core.handle();

        wt!(stage2, h2, s1, s2, $($rest)*)
    }};
    (stage2, $h2:ident, $s1:ident, $s2:ident, noopts,$($rest:tt)*) => {
        wt!(stage2, $h2, $s1, $s2, opts=Default::default(),$($rest)*)
    };
    (stage2, $h2:ident, $s1:ident, $s2:ident, opts=$opts:expr,$($rest:tt)*) => {{

        let websocat = WebsocatConfiguration3 {
            opts: $opts,
            $s1,
            $s2,
        };

        websocat.serve(
            $h2,
            wt!(stage3, $($rest)*),
        )
    }};
    (stage3, errpanic,) => {
        std::rc::Rc::new(|e| {
            eprintln!("{}", e);
            panic!();
        })
    };
    (stage3, errignore,) => {
        std::rc::Rc::new(|_| {

        })
    };
}

macro_rules! prepare {
    ($core:ident) => {
        let _ = env_logger::try_init();
        let mut $core = Core::new().unwrap();
    };
}
macro_rules! run {
    ($core:ident, $prog:expr) => {
        $core.run($prog).map_err(|()| panic!()).unwrap();
    };
}

#[test]
fn trivial() {
    prepare!(core);
    let prog = wt!(
        core,
        "literal:qwerty",
        "assert:qwerty",
        nodelay,
        noopts,
        errpanic,
    );
    run!(core, prog);
}

#[test]
fn tcp() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "literal:qwert2y",
        "tcp-l:127.0.0.1:45912",
        nodelay,
        noopts,
        errpanic,
    );
    let prog2 = wt!(
        core,
        "tcp:127.0.0.1:45912",
        "assert:qwert2y",
        delay = 200,
        noopts,
        errpanic,
    );

    let prog = prog1.join(prog2);
    run!(core, prog);
}

#[test]
fn ws() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "literal:qwert3y",
        "ws-l:127.0.0.1:45913",
        nodelay,
        noopts,
        errpanic,
    );
    let prog2 = wt!(
        core,
        "ws://127.0.0.1:45913/ololo",
        "assert:qwert3y",
        delay = 200,
        noopts,
        errpanic,
    );

    let prog = prog1.join(prog2);
    run!(core, prog);
}

#[test]
fn ws_persist() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "ws-l:127.0.0.1:45914",
        "literal:qwert4y",
        nodelay,
        noopts,
        errignore,
    );
    let prog2 = wt!(
        core,
        "literal:invalid_connection_request",
        "tcp:127.0.0.1:45914",
        delay = 200,
        noopts,
        errpanic,
    );
    let prog3 = wt!(
        core,
        "ws://127.0.0.1:45914/ololo",
        "assert:qwert4y",
        delay = 400,
        noopts,
        errpanic,
    );

    core.handle().spawn(prog1);
    core.handle().spawn(prog2);
    let prog = prog3;
    run!(core, prog);
}

#[test]
#[cfg(unix)]
fn unix() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "literal:qwert3y",
        "unix-l:zxc",
        nodelay,
        opts = Options {
            unlink_unix_socket: true,
            ..dflt()
        },
        errpanic,
    );
    let prog2 = wt!(
        core,
        "unix-c:zxc",
        "assert:qwert3y",
        delay = 200,
        noopts,
        errpanic,
    );

    let prog = prog1.join(prog2);
    run!(core, prog);
    let _ = ::std::fs::remove_file("zxc");
}

#[test]
#[cfg(any(target_os = "linux", target_os = "android"))]
fn abstract_() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "literal:qwert4y",
        "abstract-l:zxc",
        nodelay,
        noopts,
        errpanic,
    );
    let prog2 = wt!(
        core,
        "abstract-c:zxc",
        "assert:qwert4y",
        delay = 200,
        noopts,
        errpanic,
    );

    let prog = prog1.join(prog2);
    run!(core, prog);
}
<|endoftext|>