<commit_before>// Copyright 2014 Tyler Neely
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
extern crate rocksdb;
mod util;

use rocksdb::{Direction, IteratorMode, MemtableFactory, Options, DB};
use util::DBPath;

fn cba(input: &Box<[u8]>) -> Box<[u8]> {
    input.iter().cloned().collect::<Vec<_>>().into_boxed_slice()
}

#[test]
pub fn test_iterator() {
    let n = DBPath::new("_rust_rocksdb_iteratortest");
    {
        let k1: Box<[u8]> = b"k1".to_vec().into_boxed_slice();
        let k2: Box<[u8]> = b"k2".to_vec().into_boxed_slice();
        let k3: Box<[u8]> = b"k3".to_vec().into_boxed_slice();
        let k4: Box<[u8]> = b"k4".to_vec().into_boxed_slice();
        let v1: Box<[u8]> = b"v1111".to_vec().into_boxed_slice();
        let v2: Box<[u8]> = b"v2222".to_vec().into_boxed_slice();
        let v3: Box<[u8]> = b"v3333".to_vec().into_boxed_slice();
        let v4: Box<[u8]> = b"v4444".to_vec().into_boxed_slice();
        let db = DB::open_default(&n).unwrap();
        let p = db.put(&*k1, &*v1);
        assert!(p.is_ok());
        let p = db.put(&*k2, &*v2);
        assert!(p.is_ok());
        let p = db.put(&*k3, &*v3);
        assert!(p.is_ok());
        let expected = vec![
            (cba(&k1), cba(&v1)),
            (cba(&k2), cba(&v2)),
            (cba(&k3), cba(&v3)),
        ];
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        // Test that it's idempotent
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        // Test it in reverse a few times
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        // Try it forward again
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }

        let old_iterator = db.iterator(IteratorMode::Start);
        let p = db.put(&*k4, &*v4);
        assert!(p.is_ok());
        let expected2 = vec![
            (cba(&k1), cba(&v1)),
            (cba(&k2), cba(&v2)),
            (cba(&k3), cba(&v3)),
            (cba(&k4), cba(&v4)),
        ];
        {
            assert_eq!(old_iterator.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected2);
        }
        {
            let iterator1 = db.iterator(IteratorMode::From(b"k2", Direction::Forward));
            let expected = vec![
                (cba(&k2), cba(&v2)),
                (cba(&k3), cba(&v3)),
                (cba(&k4), cba(&v4)),
            ];
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::From(b"k2", Direction::Reverse));
            let expected = vec![(cba(&k2), cba(&v2)), (cba(&k1), cba(&v1))];
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::From(b"zz", Direction::Reverse));
            let expected = vec![(cba(&k4), cba(&v4)), (cba(&k3), cba(&v3))];
            assert_eq!(iterator1.take(2).collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::From(b"k0", Direction::Forward));
            assert!(iterator1.valid());
            let iterator2 = db.iterator(IteratorMode::From(b"k1", Direction::Forward));
            assert!(iterator2.valid());
            let iterator3 = db.iterator(IteratorMode::From(b"k11", Direction::Forward));
            assert!(iterator3.valid());
            let iterator4 = db.iterator(IteratorMode::From(b"k5", Direction::Forward));
            assert!(!iterator4.valid());
            let iterator5 = db.iterator(IteratorMode::From(b"k0", Direction::Reverse));
            assert!(!iterator5.valid());
            let iterator6 = db.iterator(IteratorMode::From(b"k1", Direction::Reverse));
            assert!(iterator6.valid());
            let iterator7 = db.iterator(IteratorMode::From(b"k11", Direction::Reverse));
            assert!(iterator7.valid());
            let iterator8 = db.iterator(IteratorMode::From(b"k5", Direction::Reverse));
            assert!(iterator8.valid());
        }
        {
            let mut iterator1 = db.iterator(IteratorMode::From(b"k4", Direction::Forward));
            iterator1.next();
            assert!(iterator1.valid());
            iterator1.next();
            assert!(!iterator1.valid());
        }
    }
}

fn key(k: &[u8]) -> Box<[u8]> {
    k.to_vec().into_boxed_slice()
}

#[test]
pub fn test_prefix_iterator() {
    let n = DBPath::new("_rust_rocksdb_prefixiteratortest");
    {
        let a1: Box<[u8]> = key(b"aaa1");
        let a2: Box<[u8]> = key(b"aaa2");
        let b1: Box<[u8]> = key(b"bbb1");
        let b2: Box<[u8]> = key(b"bbb2");

        let prefix_extractor = rocksdb::SliceTransform::create_fixed_prefix(3);

        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_prefix_extractor(prefix_extractor);

        let db = DB::open(&opts, &n).unwrap();

        assert!(db.put(&*a1, &*a1).is_ok());
        assert!(db.put(&*a2, &*a2).is_ok());
        assert!(db.put(&*b1, &*b1).is_ok());
        assert!(db.put(&*b2, &*b2).is_ok());

        {
            let expected = vec![(cba(&a1), cba(&a1)), (cba(&a2), cba(&a2))];
            let a_iterator = db.prefix_iterator(b"aaa");
            assert_eq!(a_iterator.collect::<Vec<_>>(), expected)
        }

        {
            let expected = vec![(cba(&b1), cba(&b1)), (cba(&b2), cba(&b2))];
            let b_iterator = db.prefix_iterator(b"bbb");
            assert_eq!(b_iterator.collect::<Vec<_>>(), expected)
        }
    }
}

#[test]
pub fn test_prefix_iterator_uses_full_prefix() {
    // Test scenario derived from GitHub issue #221

    // Explanation: `db.prefix_iterator` sets the underlying
    // options to seek to the first key that matches the *entire*
    // prefix. From there, the iterator will continue to read pairs
    // as long as the prefix extracted from `key` matches the
    // prefix extracted from `prefix`.

    let path = DBPath::new("_rust_rocksdb_prefixiteratorusesfullprefixtest");
    {
        let data = [
            ([0,0,0,0], b"111"),
            ([0,0,0,1], b"222"),
            ([0,1,0,1], b"333"),
            ([0,1,1,1], b"444"),
            ([0,1,2,1], b"555"),
            ([0,2,0,0], b"666"),
            ([2,0,0,0], b"777"),
            ([2,2,2,2], b"888")
        ];

        let prefix_extractor = rocksdb::SliceTransform::create_fixed_prefix(1);

        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_prefix_extractor(prefix_extractor);

        let db = DB::open(&opts, &path).unwrap();

        for (key, value) in &data {
            assert!(db.put(key, *value).is_ok());
        }

        let prefix = [0,1,1];
        let results: Vec<_> = db.prefix_iterator(&prefix)
            .map(|(_,v)| std::str::from_utf8(&v).unwrap().to_string())
            .collect();

        assert_eq!(results, vec!("444", "555", "666"));
    }
}

#[test]
pub fn test_full_iterator() {
    let path = "_rust_rocksdb_fulliteratortest";
    {
        let a1: Box<[u8]> = key(b"aaa1");
        let a2: Box<[u8]> = key(b"aaa2");
        let b1: Box<[u8]> = key(b"bbb1");
        let b2: Box<[u8]> = key(b"bbb2");

        let prefix_extractor = rocksdb::SliceTransform::create_fixed_prefix(3);
        let factory = MemtableFactory::HashSkipList {
            bucket_count: 1_000_000,
            height: 4,
            branching_factor: 4,
        };

        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_prefix_extractor(prefix_extractor);
        opts.set_allow_concurrent_memtable_write(false);
        opts.set_memtable_factory(factory);

        let db = DB::open(&opts, path).unwrap();

        assert!(db.put(&*a1, &*a1).is_ok());
        assert!(db.put(&*a2, &*a2).is_ok());
        assert!(db.put(&*b1, &*b1).is_ok());
        assert!(db.put(&*b2, &*b2).is_ok());

        // A normal iterator won't work here since we're using a HashSkipList for our memtable
        // implementation (which buckets keys based on their prefix):
        let bad_iterator = db.iterator(IteratorMode::Start);
        assert_eq!(bad_iterator.collect::<Vec<_>>(), vec![]);

        let expected = vec![
            (cba(&a1), cba(&a1)),
            (cba(&a2), cba(&a2)),
            (cba(&b1), cba(&b1)),
            (cba(&b2), cba(&b2)),
        ];

        let a_iterator = db.full_iterator(IteratorMode::Start);
        assert_eq!(a_iterator.collect::<Vec<_>>(), expected)
    }
    let opts = Options::default();
    assert!(DB::destroy(&opts, path).is_ok());
}
<commit_msg>Minor tweak to test comment...<commit_after>// Copyright 2014 Tyler Neely
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
extern crate rocksdb;
mod util;

use rocksdb::{Direction, IteratorMode, MemtableFactory, Options, DB};
use util::DBPath;

fn cba(input: &Box<[u8]>) -> Box<[u8]> {
    input.iter().cloned().collect::<Vec<_>>().into_boxed_slice()
}

#[test]
pub fn test_iterator() {
    let n = DBPath::new("_rust_rocksdb_iteratortest");
    {
        let k1: Box<[u8]> = b"k1".to_vec().into_boxed_slice();
        let k2: Box<[u8]> = b"k2".to_vec().into_boxed_slice();
        let k3: Box<[u8]> = b"k3".to_vec().into_boxed_slice();
        let k4: Box<[u8]> = b"k4".to_vec().into_boxed_slice();
        let v1: Box<[u8]> = b"v1111".to_vec().into_boxed_slice();
        let v2: Box<[u8]> = b"v2222".to_vec().into_boxed_slice();
        let v3: Box<[u8]> = b"v3333".to_vec().into_boxed_slice();
        let v4: Box<[u8]> = b"v4444".to_vec().into_boxed_slice();
        let db = DB::open_default(&n).unwrap();
        let p = db.put(&*k1, &*v1);
        assert!(p.is_ok());
        let p = db.put(&*k2, &*v2);
        assert!(p.is_ok());
        let p = db.put(&*k3, &*v3);
        assert!(p.is_ok());
        let expected = vec![
            (cba(&k1), cba(&v1)),
            (cba(&k2), cba(&v2)),
            (cba(&k3), cba(&v3)),
        ];
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        // Test that it's idempotent
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        // Test it in reverse a few times
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        // Try it forward again
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }

        let old_iterator = db.iterator(IteratorMode::Start);
        let p = db.put(&*k4, &*v4);
        assert!(p.is_ok());
        let expected2 = vec![
            (cba(&k1), cba(&v1)),
            (cba(&k2), cba(&v2)),
            (cba(&k3), cba(&v3)),
            (cba(&k4), cba(&v4)),
        ];
        {
            assert_eq!(old_iterator.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected2);
        }
        {
            let iterator1 = db.iterator(IteratorMode::From(b"k2", Direction::Forward));
            let expected = vec![
                (cba(&k2), cba(&v2)),
                (cba(&k3), cba(&v3)),
                (cba(&k4), cba(&v4)),
            ];
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::From(b"k2", Direction::Reverse));
            let expected = vec![(cba(&k2), cba(&v2)), (cba(&k1), cba(&v1))];
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::From(b"zz", Direction::Reverse));
            let expected = vec![(cba(&k4), cba(&v4)), (cba(&k3), cba(&v3))];
            assert_eq!(iterator1.take(2).collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::From(b"k0", Direction::Forward));
            assert!(iterator1.valid());
            let iterator2 = db.iterator(IteratorMode::From(b"k1", Direction::Forward));
            assert!(iterator2.valid());
            let iterator3 = db.iterator(IteratorMode::From(b"k11", Direction::Forward));
            assert!(iterator3.valid());
            let iterator4 = db.iterator(IteratorMode::From(b"k5", Direction::Forward));
            assert!(!iterator4.valid());
            let iterator5 = db.iterator(IteratorMode::From(b"k0", Direction::Reverse));
            assert!(!iterator5.valid());
            let iterator6 = db.iterator(IteratorMode::From(b"k1", Direction::Reverse));
            assert!(iterator6.valid());
            let iterator7 = db.iterator(IteratorMode::From(b"k11", Direction::Reverse));
            assert!(iterator7.valid());
            let iterator8 = db.iterator(IteratorMode::From(b"k5", Direction::Reverse));
            assert!(iterator8.valid());
        }
        {
            let mut iterator1 = db.iterator(IteratorMode::From(b"k4", Direction::Forward));
            iterator1.next();
            assert!(iterator1.valid());
            iterator1.next();
            assert!(!iterator1.valid());
        }
    }
}

fn key(k: &[u8]) -> Box<[u8]> {
    k.to_vec().into_boxed_slice()
}

#[test]
pub fn test_prefix_iterator() {
    let n = DBPath::new("_rust_rocksdb_prefixiteratortest");
    {
        let a1: Box<[u8]> = key(b"aaa1");
        let a2: Box<[u8]> = key(b"aaa2");
        let b1: Box<[u8]> = key(b"bbb1");
        let b2: Box<[u8]> = key(b"bbb2");

        let prefix_extractor = rocksdb::SliceTransform::create_fixed_prefix(3);

        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_prefix_extractor(prefix_extractor);

        let db = DB::open(&opts, &n).unwrap();

        assert!(db.put(&*a1, &*a1).is_ok());
        assert!(db.put(&*a2, &*a2).is_ok());
        assert!(db.put(&*b1, &*b1).is_ok());
        assert!(db.put(&*b2, &*b2).is_ok());

        {
            let expected = vec![(cba(&a1), cba(&a1)), (cba(&a2), cba(&a2))];
            let a_iterator = db.prefix_iterator(b"aaa");
            assert_eq!(a_iterator.collect::<Vec<_>>(), expected)
        }

        {
            let expected = vec![(cba(&b1), cba(&b1)), (cba(&b2), cba(&b2))];
            let b_iterator = db.prefix_iterator(b"bbb");
            assert_eq!(b_iterator.collect::<Vec<_>>(), expected)
        }
    }
}

#[test]
pub fn test_prefix_iterator_uses_full_prefix() {
    // Test scenario derived from GitHub issue #221

    // Explanation: `db.prefix_iterator` sets the underlying
    // options to seek to the first key that matches the *entire*
    // `prefix`. From there, the iterator will continue to read pairs
    // as long as the prefix extracted from `key` matches the
    // prefix extracted from `prefix`.

    let path = DBPath::new("_rust_rocksdb_prefixiteratorusesfullprefixtest");
    {
        let data = [
            ([0,0,0,0], b"111"),
            ([0,0,0,1], b"222"),
            ([0,1,0,1], b"333"),
            ([0,1,1,1], b"444"),
            ([0,1,2,1], b"555"),
            ([0,2,0,0], b"666"),
            ([2,0,0,0], b"777"),
            ([2,2,2,2], b"888")
        ];

        let prefix_extractor = rocksdb::SliceTransform::create_fixed_prefix(1);

        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_prefix_extractor(prefix_extractor);

        let db = DB::open(&opts, &path).unwrap();

        for (key, value) in &data {
            assert!(db.put(key, *value).is_ok());
        }

        let prefix = [0,1,1];
        let results: Vec<_> = db.prefix_iterator(&prefix)
            .map(|(_,v)| std::str::from_utf8(&v).unwrap().to_string())
            .collect();

        assert_eq!(results, vec!("444", "555", "666"));
    }
}

#[test]
pub fn test_full_iterator() {
    let path = "_rust_rocksdb_fulliteratortest";
    {
        let a1: Box<[u8]> = key(b"aaa1");
        let a2: Box<[u8]> = key(b"aaa2");
        let b1: Box<[u8]> = key(b"bbb1");
        let b2: Box<[u8]> = key(b"bbb2");

        let prefix_extractor = rocksdb::SliceTransform::create_fixed_prefix(3);
        let factory = MemtableFactory::HashSkipList {
            bucket_count: 1_000_000,
            height: 4,
            branching_factor: 4,
        };

        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_prefix_extractor(prefix_extractor);
        opts.set_allow_concurrent_memtable_write(false);
        opts.set_memtable_factory(factory);

        let db = DB::open(&opts, path).unwrap();

        assert!(db.put(&*a1, &*a1).is_ok());
        assert!(db.put(&*a2, &*a2).is_ok());
        assert!(db.put(&*b1, &*b1).is_ok());
        assert!(db.put(&*b2, &*b2).is_ok());

        // A normal iterator won't work here since we're using a HashSkipList for our memtable
        // implementation (which buckets keys based on their prefix):
        let bad_iterator = db.iterator(IteratorMode::Start);
        assert_eq!(bad_iterator.collect::<Vec<_>>(), vec![]);

        let expected = vec![
            (cba(&a1), cba(&a1)),
            (cba(&a2), cba(&a2)),
            (cba(&b1), cba(&b1)),
            (cba(&b2), cba(&b2)),
        ];

        let a_iterator = db.full_iterator(IteratorMode::Start);
        assert_eq!(a_iterator.collect::<Vec<_>>(), expected)
    }
    let opts = Options::default();
    assert!(DB::destroy(&opts, path).is_ok());
}
<|endoftext|>


<commit_before>use std::mem;
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};

use time::{Timespec};
use byteorder::{ByteOrder, LittleEndian};

use super::super::crypto::{Hash, PublicKey};

use super::Error;

pub trait Field<'a> {
    // TODO: use Read and Cursor
    // TODO: debug_assert_eq!(to-from == size of Self)
    fn read(buffer: &'a [u8], from: usize, to: usize) -> Self;
    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize);

    #[allow(unused_variables)]
    fn check(buffer: &'a [u8], from: usize, to: usize)
        -> Result<(), Error> {
        Ok(())
    }
}

impl<'a> Field<'a> for bool {
    fn read(buffer: &'a [u8], from: usize, _: usize) -> bool {
        buffer[from] == 1
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, _: usize) {
        buffer[from] = if *self {1} else {0}
    }

    fn check(buffer: &'a [u8], from: usize, _: usize)
        -> Result<(), Error> {
        if buffer[from] != 0 && buffer[from] != 1 {
            Err(Error::IncorrectBoolean {
                position: from as u32,
                value: buffer[from]
            })
        } else {
            Ok(())
        }
    }
}

impl<'a> Field<'a> for u32 {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> u32 {
        LittleEndian::read_u32(&buffer[from..to])
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        LittleEndian::write_u32(&mut buffer[from..to], *self)
    }
}

impl<'a> Field<'a> for u64 {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> u64 {
        LittleEndian::read_u64(&buffer[from..to])
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        LittleEndian::write_u64(&mut buffer[from..to], *self)
    }
}

impl<'a> Field<'a> for &'a Hash {
    fn read(buffer: &'a [u8], from: usize, _: usize) -> &'a Hash {
        unsafe {
            mem::transmute(&buffer[from])
        }
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        &mut buffer[from..to].copy_from_slice(self.as_ref());
    }
}

impl<'a> Field<'a> for &'a PublicKey {
    fn read(buffer: &'a [u8], from: usize, _: usize) -> &'a PublicKey {
        unsafe {
            mem::transmute(&buffer[from])
        }
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        &mut buffer[from..to].copy_from_slice(self.as_ref());
    }
}

impl<'a> Field<'a> for Timespec {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> Timespec {
        let nsec = LittleEndian::read_u64(&buffer[from..to]);
        Timespec {
            sec:  (nsec / 1_000_000_000) as i64,
            nsec: (nsec % 1_000_000_000) as i32,
        }
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        let nsec = (self.sec as u64) * 1_000_000_000 + self.nsec as u64;
        LittleEndian::write_u64(&mut buffer[from..to], nsec)
    }
}

impl<'a> Field<'a> for SocketAddr {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> SocketAddr {
        let ip = Ipv4Addr::new(buffer[from+0], buffer[from+1],
                               buffer[from+2], buffer[from+3]);
        let port = LittleEndian::read_u16(&buffer[from+4..to]);
        SocketAddr::V4(SocketAddrV4::new(ip, port))
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        match *self {
            SocketAddr::V4(addr) => {
                &mut buffer[from..to-2].copy_from_slice(&addr.ip().octets());
            },
            SocketAddr::V6(_) => {
                // FIXME: Supporting Ipv6
                panic!("Ipv6 are currently unsupported")
            },
        }
        LittleEndian::write_u16(&mut buffer[to-2..to], self.port());
    }
}

pub trait SegmentField<'a> {
    const ITEM_SIZE: usize;

    fn from_slice(slice: &'a [u8]) -> Self;
    fn as_slice(&self) -> &'a [u8];
    fn count(&self) -> u32;

    #[allow(unused_variables)]
    fn check_data(slice: &'a [u8], pos: u32) -> Result<(), Error> {
        Ok(())
    }
}

impl<'a, T> Field<'a> for T where T: SegmentField<'a> {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> T {
        unsafe {
            let pos = LittleEndian::read_u32(&buffer[from..from+4]);
            let len = LittleEndian::read_u32(&buffer[from+4..to]);
            let ptr = buffer.as_ptr().offset(pos as isize);
            Self::from_slice(unsafe {
                ::std::slice::from_raw_parts(ptr as *const u8, len as usize)
            })
        }
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        let pos = buffer.len();
        LittleEndian::write_u32(&mut buffer[from..from+4], pos as u32);
        LittleEndian::write_u32(&mut buffer[from+4..to], self.count());
        buffer.extend_from_slice(self.as_slice());
    }

    fn check(buffer: &'a [u8], from: usize, to: usize)
        -> Result<(), Error> {
        let pos = LittleEndian::read_u32(&buffer[from..from+4]);
        let count = LittleEndian::read_u32(&buffer[from+4..to]);

        if count == 0 {
            return Ok(())
        }

        let start = pos as usize;

        if start < from + 8 {
            return Err(Error::IncorrectSegmentRefference {
                position: from as u32,
                value: pos
            })
        }

        let end = start + Self::ITEM_SIZE * (count as usize);

        if end > buffer.len() {
            return Err(Error::IncorrectSegmentSize {
                position: (from + 4) as u32,
                value: count
            })
        }

        return Self::check_data(unsafe {
            ::std::slice::from_raw_parts(pos as *const u8, count as usize)
        }, from as u32);
    }
}

impl<'a> SegmentField<'a> for &'a [u8] {
    const ITEM_SIZE: usize = 1;

    fn from_slice(slice: &'a [u8]) -> Self {
        slice
    }

    fn as_slice(&self) -> &'a [u8] {
        self
    }

    fn count(&self) -> u32 {
        self.len() as u32
    }
}

impl<'a> SegmentField<'a> for &'a [Hash] {
    const ITEM_SIZE: usize = 32;

    fn from_slice(slice: &'a [u8]) -> Self {
        unsafe {
            ::std::slice::from_raw_parts(slice.as_ptr() as *const Hash,
                                         slice.len() / 32)
        }
    }

    fn as_slice(&self) -> &'a [u8] {
        unsafe {
            ::std::slice::from_raw_parts(self.as_ptr() as *const u8,
                                         self.len() * 32)
        }
    }

    fn count(&self) -> u32 {
        self.len() as u32
    }
}

impl<'a> SegmentField<'a> for &'a str {
    const ITEM_SIZE: usize = 32;

    fn from_slice(slice: &'a [u8]) -> Self {
        unsafe {
            ::std::str::from_utf8_unchecked(slice)
        }
    }

    fn as_slice(&self) -> &'a [u8] {
        self.as_bytes()
    }

    fn count(&self) -> u32 {
        self.len() as u32
    }

    fn check_data(slice: &'a [u8], pos: u32) -> Result<(), Error> {
        if let Err(e) = ::std::str::from_utf8(slice) {
            return Err(Error::Utf8 {
                position: pos,
                error: e,
            });
        }
        Ok(())
    }
}
<commit_msg>Small fix (just for testing CI)<commit_after>use std::mem;
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};

use time::{Timespec};
use byteorder::{ByteOrder, LittleEndian};

use super::super::crypto::{Hash, PublicKey};

use super::Error;

pub trait Field<'a> {
    // TODO: use Read and Cursor
    // TODO: debug_assert_eq!(to-from == size of Self)
    fn read(buffer: &'a [u8], from: usize, to: usize) -> Self;
    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize);

    #[allow(unused_variables)]
    fn check(buffer: &'a [u8], from: usize, to: usize)
        -> Result<(), Error> {
        Ok(())
    }
}

impl<'a> Field<'a> for bool {
    fn read(buffer: &'a [u8], from: usize, _: usize) -> bool {
        buffer[from] == 1
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, _: usize) {
        buffer[from] = if *self {1} else {0}
    }

    fn check(buffer: &'a [u8], from: usize, _: usize)
        -> Result<(), Error> {
        if buffer[from] != 0 && buffer[from] != 1 {
            Err(Error::IncorrectBoolean {
                position: from as u32,
                value: buffer[from]
            })
        } else {
            Ok(())
        }
    }
}

impl<'a> Field<'a> for u32 {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> u32 {
        LittleEndian::read_u32(&buffer[from..to])
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        LittleEndian::write_u32(&mut buffer[from..to], *self)
    }
}

impl<'a> Field<'a> for u64 {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> u64 {
        LittleEndian::read_u64(&buffer[from..to])
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        LittleEndian::write_u64(&mut buffer[from..to], *self)
    }
}

impl<'a> Field<'a> for &'a Hash {
    fn read(buffer: &'a [u8], from: usize, _: usize) -> &'a Hash {
        unsafe {
            mem::transmute(&buffer[from])
        }
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        &mut buffer[from..to].copy_from_slice(self.as_ref());
    }
}

impl<'a> Field<'a> for &'a PublicKey {
    fn read(buffer: &'a [u8], from: usize, _: usize) -> &'a PublicKey {
        unsafe {
            mem::transmute(&buffer[from])
        }
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        &mut buffer[from..to].copy_from_slice(self.as_ref());
    }
}

impl<'a> Field<'a> for Timespec {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> Timespec {
        let nsec = LittleEndian::read_u64(&buffer[from..to]);
        Timespec {
            sec:  (nsec / 1_000_000_000) as i64,
            nsec: (nsec % 1_000_000_000) as i32,
        }
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        let nsec = (self.sec as u64) * 1_000_000_000 + self.nsec as u64;
        LittleEndian::write_u64(&mut buffer[from..to], nsec)
    }
}

impl<'a> Field<'a> for SocketAddr {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> SocketAddr {
        let ip = Ipv4Addr::new(buffer[from+0], buffer[from+1],
                               buffer[from+2], buffer[from+3]);
        let port = LittleEndian::read_u16(&buffer[from+4..to]);
        SocketAddr::V4(SocketAddrV4::new(ip, port))
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        match *self {
            SocketAddr::V4(addr) => {
                &mut buffer[from..to-2].copy_from_slice(&addr.ip().octets());
            },
            SocketAddr::V6(_) => {
                // FIXME: Supporting Ipv6
                panic!("Ipv6 are currently unsupported")
            },
        }
        LittleEndian::write_u16(&mut buffer[to-2..to], self.port());
    }
}

pub trait SegmentField<'a> {
    const ITEM_SIZE: usize;

    fn from_slice(slice: &'a [u8]) -> Self;
    fn as_slice(&self) -> &'a [u8];
    fn count(&self) -> u32;

    #[allow(unused_variables)]
    fn check_data(slice: &'a [u8], pos: u32) -> Result<(), Error> {
        Ok(())
    }
}

impl<'a, T> Field<'a> for T where T: SegmentField<'a> {
    fn read(buffer: &'a [u8], from: usize, to: usize) -> T {
        unsafe {
            let pos = LittleEndian::read_u32(&buffer[from..from+4]);
            let len = LittleEndian::read_u32(&buffer[from+4..to]);
            let ptr = buffer.as_ptr().offset(pos as isize);
            Self::from_slice(
                ::std::slice::from_raw_parts(ptr as *const u8, len as usize)
            )
        }
    }

    fn write(&self, buffer: &'a mut Vec<u8>, from: usize, to: usize) {
        let pos = buffer.len();
        LittleEndian::write_u32(&mut buffer[from..from+4], pos as u32);
        LittleEndian::write_u32(&mut buffer[from+4..to], self.count());
        buffer.extend_from_slice(self.as_slice());
    }

    fn check(buffer: &'a [u8], from: usize, to: usize)
        -> Result<(), Error> {
        let pos = LittleEndian::read_u32(&buffer[from..from+4]);
        let count = LittleEndian::read_u32(&buffer[from+4..to]);

        if count == 0 {
            return Ok(())
        }

        let start = pos as usize;

        if start < from + 8 {
            return Err(Error::IncorrectSegmentRefference {
                position: from as u32,
                value: pos
            })
        }

        let end = start + Self::ITEM_SIZE * (count as usize);

        if end > buffer.len() {
            return Err(Error::IncorrectSegmentSize {
                position: (from + 4) as u32,
                value: count
            })
        }

        return Self::check_data(unsafe {
            ::std::slice::from_raw_parts(pos as *const u8, count as usize)
        }, from as u32);
    }
}

impl<'a> SegmentField<'a> for &'a [u8] {
    const ITEM_SIZE: usize = 1;

    fn from_slice(slice: &'a [u8]) -> Self {
        slice
    }

    fn as_slice(&self) -> &'a [u8] {
        self
    }

    fn count(&self) -> u32 {
        self.len() as u32
    }
}

impl<'a> SegmentField<'a> for &'a [Hash] {
    const ITEM_SIZE: usize = 32;

    fn from_slice(slice: &'a [u8]) -> Self {
        unsafe {
            ::std::slice::from_raw_parts(slice.as_ptr() as *const Hash,
                                         slice.len() / 32)
        }
    }

    fn as_slice(&self) -> &'a [u8] {
        unsafe {
            ::std::slice::from_raw_parts(self.as_ptr() as *const u8,
                                         self.len() * 32)
        }
    }

    fn count(&self) -> u32 {
        self.len() as u32
    }
}

impl<'a> SegmentField<'a> for &'a str {
    const ITEM_SIZE: usize = 32;

    fn from_slice(slice: &'a [u8]) -> Self {
        unsafe {
            ::std::str::from_utf8_unchecked(slice)
        }
    }

    fn as_slice(&self) -> &'a [u8] {
        self.as_bytes()
    }

    fn count(&self) -> u32 {
        self.len() as u32
    }

    fn check_data(slice: &'a [u8], pos: u32) -> Result<(), Error> {
        if let Err(e) = ::std::str::from_utf8(slice) {
            return Err(Error::Utf8 {
                position: pos,
                error: e,
            });
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use super::ethereum_types::H256;
use super::{
    DecodeError,
    Decodable,
};

macro_rules! impl_decodable_for_uint {
    ($type: ident, $bit_size: expr) => {
        impl Decodable for $type {
            fn ssz_decode(bytes: &[u8], index: usize)
                -> Result<(Self, usize), DecodeError>
            {
                assert!((0 < $bit_size) &
                        ($bit_size <= 64) &
                        ($bit_size % 8 == 0));
                let max_bytes = $bit_size / 8;
                if bytes.len() >= (index + max_bytes) {
                    let end_bytes = index + max_bytes;
                    let mut result: $type = 0;
                    for i in index..end_bytes {
                        let offset = ((index + max_bytes) - i - 1) * 8;
                        result = ((bytes[i] as $type) << offset) | result;
                    };
                    Ok((result, end_bytes))
                } else {
                    Err(DecodeError::TooShort)
                }
            }
        }
    }
}

impl_decodable_for_uint!(u16, 16);
impl_decodable_for_uint!(u32, 32);
impl_decodable_for_uint!(u64, 64);
impl_decodable_for_uint!(usize, 64);

impl Decodable for H256 {
    fn ssz_decode(bytes: &[u8], index: usize)
        -> Result<(Self, usize), DecodeError>
    {
        if bytes.len() < 32 {
            return Err(DecodeError::TooShort)
        }
        else if bytes.len() - 32 < index {
            return Err(DecodeError::TooShort)
        }
        else {
            return Ok((H256::from(&bytes[index..(index + 32)]),
                       index + 32));
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::super::{
        DecodeError,
        decode_ssz,
    };

    #[test]
    fn test_ssz_decode_h256() {
        /*
         * Input is exact length
         */
        let input = vec![42_u8; 32];
        let (decoded, i) = H256::ssz_decode(&input, 0).unwrap();
        assert_eq!(decoded.to_vec(), input);
        assert_eq!(i, 32);

        /*
         * Input is too long
         */
        let mut input = vec![42_u8; 32];
        input.push(12);
        let (decoded, i) = H256::ssz_decode(&input, 0).unwrap();
        assert_eq!(decoded.to_vec()[..], input[0..32]);
        assert_eq!(i, 32);

        /*
         * Input is too short
         */
        let input = vec![42_u8; 31];
        let res = H256::ssz_decode(&input, 0);
        assert_eq!(res, Err(DecodeError::TooShort));
    }

    #[test]
    fn test_ssz_decode_u16() {
        let ssz = vec![0, 0];

        let (result, index): (u16, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(result, 0);
        assert_eq!(index, 2);

        let ssz = vec![0, 16];
        let (result, index): (u16, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(result, 16);
        assert_eq!(index, 2);

        let ssz = vec![1, 0];
        let (result, index): (u16, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(result, 256);
        assert_eq!(index, 2);

        let ssz = vec![255, 255];
        let (result, index): (u16, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(index, 2);
        assert_eq!(result, 65535);

        let ssz = vec![1];
        let result: Result<(u16, usize), DecodeError> =
            decode_ssz(&ssz, 0);
        assert_eq!(result, Err(DecodeError::TooShort));
    }

    #[test]
    fn test_ssz_decode_u32() {
        let ssz = vec![0, 0, 0, 0];
        let (result, index): (u32, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(result, 0);
        assert_eq!(index, 4);

        let ssz = vec![0, 0, 1, 0];
        let (result, index): (u32, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(index, 4);
        assert_eq!(result, 256);

        let ssz = vec![255, 255, 255, 0, 0, 1, 0];
        let (result, index): (u32, usize) = decode_ssz(&ssz, 3).unwrap();
        assert_eq!(index, 7);
        assert_eq!(result, 256);

        let ssz = vec![0,200, 1, 0];
        let (result, index): (u32, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(index, 4);
        assert_eq!(result, 13107456);

        let ssz = vec![255, 255, 255, 255];
        let (result, index): (u32, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(index, 4);
        assert_eq!(result, 4294967295);

        let ssz = vec![0, 0, 1];
        let result: Result<(u32, usize), DecodeError> =
            decode_ssz(&ssz, 0);
        assert_eq!(result, Err(DecodeError::TooShort));
    }

    #[test]
    fn test_ssz_decode_u64() {
        let ssz = vec![0, 0, 0, 0, 0, 0, 0, 0];
        let (result, index): (u64, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(index, 8);
        assert_eq!(result, 0);

        let ssz = vec![255, 255, 255, 255, 255, 255, 255, 255];
        let (result, index): (u64, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(index, 8);
        assert_eq!(result, 18446744073709551615);

        let ssz = vec![0, 0, 8, 255, 0, 0, 0, 0, 0, 0, 0];
        let (result, index): (u64, usize) = decode_ssz(&ssz, 3).unwrap();
        assert_eq!(index, 11);
        assert_eq!(result, 18374686479671623680);

        let ssz = vec![0,0,0,0,0,0,0];
        let result: Result<(u64, usize), DecodeError> =
            decode_ssz(&ssz, 0);
        assert_eq!(result, Err(DecodeError::TooShort));
    }

    #[test]
    fn test_ssz_decode_usize() {
        let ssz = vec![0, 0, 0, 0, 0, 0, 0, 0];
        let (result, index): (usize, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(index, 8);
        assert_eq!(result, 0);

        let ssz = vec![0, 0, 8, 255, 255, 255, 255, 255, 255, 255, 255];
        let (result, index): (usize, usize) = decode_ssz(&ssz, 3).unwrap();
        assert_eq!(index, 11);
        assert_eq!(result, 18446744073709551615);

        let ssz = vec![255, 255, 255, 255, 255, 255, 255, 255, 255];
        let (result, index): (usize, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(index, 8);
        assert_eq!(result, 18446744073709551615);

        let ssz = vec![0, 0, 0, 0, 0, 0, 1];
        let result: Result<(usize, usize), DecodeError> =
            decode_ssz(&ssz, 0);
        assert_eq!(result, Err(DecodeError::TooShort));
    }

    #[test]
    fn test_decode_ssz_bounds() {
        let err: Result<(u16, usize), DecodeError> = decode_ssz(
            &vec![1],
            2
        );
        assert_eq!(err, Err(DecodeError::OutOfBounds));

        let err: Result<(u16,usize), DecodeError> = decode_ssz(
            &vec![0, 0, 0, 0],
            3
        );
        assert_eq!(err, Err(DecodeError::TooShort));

        let result: u16 = decode_ssz(
            &vec![0,0,0,0,1],
            3
        ).unwrap().0;
        assert_eq!(result, 1);
    }
}
<commit_msg>Implement ssz::Decodable for u8<commit_after>use super::ethereum_types::H256;
use super::{
    DecodeError,
    Decodable,
};

macro_rules! impl_decodable_for_uint {
    ($type: ident, $bit_size: expr) => {
        impl Decodable for $type {
            fn ssz_decode(bytes: &[u8], index: usize)
                -> Result<(Self, usize), DecodeError>
            {
                assert!((0 < $bit_size) &
                        ($bit_size <= 64) &
                        ($bit_size % 8 == 0));
                let max_bytes = $bit_size / 8;
                if bytes.len() >= (index + max_bytes) {
                    let end_bytes = index + max_bytes;
                    let mut result: $type = 0;
                    for i in index..end_bytes {
                        let offset = ((index + max_bytes) - i - 1) * 8;
                        result = ((bytes[i] as $type) << offset) | result;
                    };
                    Ok((result, end_bytes))
                } else {
                    Err(DecodeError::TooShort)
                }
            }
        }
    }
}

impl_decodable_for_uint!(u16, 16);
impl_decodable_for_uint!(u32, 32);
impl_decodable_for_uint!(u64, 64);
impl_decodable_for_uint!(usize, 64);

impl Decodable for u8 {
    fn ssz_decode(bytes: &[u8], index: usize)
        -> Result<(Self, usize), DecodeError>
    {
        if index >= bytes.len() {
            Err(DecodeError::TooShort)
        } else {
            Ok((bytes[index], index + 1))
        }
    }
}

impl Decodable for H256 {
    fn ssz_decode(bytes: &[u8], index: usize)
        -> Result<(Self, usize), DecodeError>
    {
        if bytes.len() < 32 {
            return Err(DecodeError::TooShort)
        }
        else if bytes.len() - 32 < index {
            return Err(DecodeError::TooShort)
        }
        else {
            return Ok((H256::from(&bytes[index..(index + 32)]),
                       index + 32));
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::super::{
        DecodeError,
        decode_ssz,
    };

    #[test]
    fn test_ssz_decode_h256() {
        /*
         * Input is exact length
         */
        let input = vec![42_u8; 32];
        let (decoded, i) = H256::ssz_decode(&input, 0).unwrap();
        assert_eq!(decoded.to_vec(), input);
        assert_eq!(i, 32);

        /*
         * Input is too long
         */
        let mut input = vec![42_u8; 32];
        input.push(12);
        let (decoded, i) = H256::ssz_decode(&input, 0).unwrap();
        assert_eq!(decoded.to_vec()[..], input[0..32]);
        assert_eq!(i, 32);

        /*
         * Input is too short
         */
        let input = vec![42_u8; 31];
        let res = H256::ssz_decode(&input, 0);
        assert_eq!(res, Err(DecodeError::TooShort));
    }

    #[test]
    fn test_ssz_decode_u16() {
        let ssz = vec![0, 0];

        let (result, index): (u16, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(result, 0);
        assert_eq!(index, 2);

        let ssz = vec![0, 16];
        let (result, index): (u16, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(result, 16);
        assert_eq!(index, 2);

        let ssz = vec![1, 0];
        let (result, index): (u16, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(result, 256);
        assert_eq!(index, 2);

        let ssz = vec![255, 255];
        let (result, index): (u16, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(index, 2);
        assert_eq!(result, 65535);

        let ssz = vec![1];
        let result: Result<(u16, usize), DecodeError> =
            decode_ssz(&ssz, 0);
        assert_eq!(result, Err(DecodeError::TooShort));
    }

    #[test]
    fn test_ssz_decode_u32() {
        let ssz = vec![0, 0, 0, 0];
        let (result, index): (u32, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(result, 0);
        assert_eq!(index, 4);

        let ssz = vec![0, 0, 1, 0];
        let (result, index): (u32, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(index, 4);
        assert_eq!(result, 256);

        let ssz = vec![255, 255, 255, 0, 0, 1, 0];
        let (result, index): (u32, usize) = decode_ssz(&ssz, 3).unwrap();
        assert_eq!(index, 7);
        assert_eq!(result, 256);

        let ssz = vec![0,200, 1, 0];
        let (result, index): (u32, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(index, 4);
        assert_eq!(result, 13107456);

        let ssz = vec![255, 255, 255, 255];
        let (result, index): (u32, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(index, 4);
        assert_eq!(result, 4294967295);

        let ssz = vec![0, 0, 1];
        let result: Result<(u32, usize), DecodeError> =
            decode_ssz(&ssz, 0);
        assert_eq!(result, Err(DecodeError::TooShort));
    }

    #[test]
    fn test_ssz_decode_u64() {
        let ssz = vec![0, 0, 0, 0, 0, 0, 0, 0];
        let (result, index): (u64, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(index, 8);
        assert_eq!(result, 0);

        let ssz = vec![255, 255, 255, 255, 255, 255, 255, 255];
        let (result, index): (u64, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(index, 8);
        assert_eq!(result, 18446744073709551615);

        let ssz = vec![0, 0, 8, 255, 0, 0, 0, 0, 0, 0, 0];
        let (result, index): (u64, usize) = decode_ssz(&ssz, 3).unwrap();
        assert_eq!(index, 11);
        assert_eq!(result, 18374686479671623680);

        let ssz = vec![0,0,0,0,0,0,0];
        let result: Result<(u64, usize), DecodeError> =
            decode_ssz(&ssz, 0);
        assert_eq!(result, Err(DecodeError::TooShort));
    }

    #[test]
    fn test_ssz_decode_usize() {
        let ssz = vec![0, 0, 0, 0, 0, 0, 0, 0];
        let (result, index): (usize, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(index, 8);
        assert_eq!(result, 0);

        let ssz = vec![0, 0, 8, 255, 255, 255, 255, 255, 255, 255, 255];
        let (result, index): (usize, usize) = decode_ssz(&ssz, 3).unwrap();
        assert_eq!(index, 11);
        assert_eq!(result, 18446744073709551615);

        let ssz = vec![255, 255, 255, 255, 255, 255, 255, 255, 255];
        let (result, index): (usize, usize) = decode_ssz(&ssz, 0).unwrap();
        assert_eq!(index, 8);
        assert_eq!(result, 18446744073709551615);

        let ssz = vec![0, 0, 0, 0, 0, 0, 1];
        let result: Result<(usize, usize), DecodeError> =
            decode_ssz(&ssz, 0);
        assert_eq!(result, Err(DecodeError::TooShort));
    }

    #[test]
    fn test_decode_ssz_bounds() {
        let err: Result<(u16, usize), DecodeError> = decode_ssz(
            &vec![1],
            2
        );
        assert_eq!(err, Err(DecodeError::OutOfBounds));

        let err: Result<(u16,usize), DecodeError> = decode_ssz(
            &vec![0, 0, 0, 0],
            3
        );
        assert_eq!(err, Err(DecodeError::TooShort));

        let result: u16 = decode_ssz(
            &vec![0,0,0,0,1],
            3
        ).unwrap().0;
        assert_eq!(result, 1);
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;

use crossbeam_utils::atomic::AtomicCell;

#[test]
fn is_lock_free() {
    struct UsizeWrap(usize);
    struct U8Wrap(bool);
    struct I16Wrap(i16);
    #[repr(align(8))]
    struct U64Align8(u64);

    assert!(AtomicCell::<usize>::is_lock_free());
    assert!(AtomicCell::<isize>::is_lock_free());
    assert!(AtomicCell::<UsizeWrap>::is_lock_free());

    assert!(AtomicCell::<()>::is_lock_free());

    assert!(AtomicCell::<u8>::is_lock_free());
    assert!(AtomicCell::<i8>::is_lock_free());
    assert!(AtomicCell::<bool>::is_lock_free());
    assert!(AtomicCell::<U8Wrap>::is_lock_free());

    assert!(AtomicCell::<u16>::is_lock_free());
    assert!(AtomicCell::<i16>::is_lock_free());
    assert!(AtomicCell::<I16Wrap>::is_lock_free());

    assert!(AtomicCell::<u32>::is_lock_free());
    assert!(AtomicCell::<i32>::is_lock_free());

    // Sizes of both types must be equal, and the alignment of `u64` must be greater or equal than
    // that of `AtomicU64`. In i686-unknown-linux-gnu, the alignment of `u64` is `4` and alignment
    // of `AtomicU64` is `8`, so `AtomicCell<u64>` is not lock-free.
    assert_eq!(
        AtomicCell::<u64>::is_lock_free(),
        cfg!(not(crossbeam_no_atomic_64))
            && cfg!(any(
                target_pointer_width = "64",
                target_pointer_width = "128"
            ))
    );
    assert_eq!(mem::size_of::<U64Align8>(), 8);
    assert_eq!(mem::align_of::<U64Align8>(), 8);
    assert_eq!(
        AtomicCell::<U64Align8>::is_lock_free(),
        cfg!(not(crossbeam_no_atomic_64))
    );

    // AtomicU128 is unstable
    assert!(!AtomicCell::<u128>::is_lock_free());
}

#[test]
fn const_is_lock_free() {
    const _U: bool = AtomicCell::<usize>::is_lock_free();
    const _I: bool = AtomicCell::<isize>::is_lock_free();
}

#[test]
fn drops_unit() {
    static CNT: AtomicUsize = AtomicUsize::new(0);
    CNT.store(0, SeqCst);

    #[derive(Debug, PartialEq, Eq)]
    struct Foo();

    impl Foo {
        fn new() -> Foo {
            CNT.fetch_add(1, SeqCst);
            Foo()
        }
    }

    impl Drop for Foo {
        fn drop(&mut self) {
            CNT.fetch_sub(1, SeqCst);
        }
    }

    impl Default for Foo {
        fn default() -> Foo {
            Foo::new()
        }
    }

    let a = AtomicCell::new(Foo::new());

    assert_eq!(a.swap(Foo::new()), Foo::new());
    assert_eq!(CNT.load(SeqCst), 1);

    a.store(Foo::new());
    assert_eq!(CNT.load(SeqCst), 1);

    assert_eq!(a.swap(Foo::default()), Foo::new());
    assert_eq!(CNT.load(SeqCst), 1);

    drop(a);
    assert_eq!(CNT.load(SeqCst), 0);
}

#[test]
fn drops_u8() {
    static CNT: AtomicUsize = AtomicUsize::new(0);
    CNT.store(0, SeqCst);

    #[derive(Debug, PartialEq, Eq)]
    struct Foo(u8);

    impl Foo {
        fn new(val: u8) -> Foo {
            CNT.fetch_add(1, SeqCst);
            Foo(val)
        }
    }

    impl Drop for Foo {
        fn drop(&mut self) {
            CNT.fetch_sub(1, SeqCst);
        }
    }

    impl Default for Foo {
        fn default() -> Foo {
            Foo::new(0)
        }
    }

    let a = AtomicCell::new(Foo::new(5));

    assert_eq!(a.swap(Foo::new(6)), Foo::new(5));
    assert_eq!(a.swap(Foo::new(1)), Foo::new(6));
    assert_eq!(CNT.load(SeqCst), 1);

    a.store(Foo::new(2));
    assert_eq!(CNT.load(SeqCst), 1);

    assert_eq!(a.swap(Foo::default()), Foo::new(2));
    assert_eq!(CNT.load(SeqCst), 1);

    assert_eq!(a.swap(Foo::default()), Foo::new(0));
    assert_eq!(CNT.load(SeqCst), 1);

    drop(a);
    assert_eq!(CNT.load(SeqCst), 0);
}

#[test]
fn drops_usize() {
    static CNT: AtomicUsize = AtomicUsize::new(0);
    CNT.store(0, SeqCst);

    #[derive(Debug, PartialEq, Eq)]
    struct Foo(usize);

    impl Foo {
        fn new(val: usize) -> Foo {
            CNT.fetch_add(1, SeqCst);
            Foo(val)
        }
    }

    impl Drop for Foo {
        fn drop(&mut self) {
            CNT.fetch_sub(1, SeqCst);
        }
    }

    impl Default for Foo {
        fn default() -> Foo {
            Foo::new(0)
        }
    }

    let a = AtomicCell::new(Foo::new(5));

    assert_eq!(a.swap(Foo::new(6)), Foo::new(5));
    assert_eq!(a.swap(Foo::new(1)), Foo::new(6));
    assert_eq!(CNT.load(SeqCst), 1);

    a.store(Foo::new(2));
    assert_eq!(CNT.load(SeqCst), 1);

    assert_eq!(a.swap(Foo::default()), Foo::new(2));
    assert_eq!(CNT.load(SeqCst), 1);

    assert_eq!(a.swap(Foo::default()), Foo::new(0));
    assert_eq!(CNT.load(SeqCst), 1);

    drop(a);
    assert_eq!(CNT.load(SeqCst), 0);
}

#[test]
fn modular_u8() {
    #[derive(Clone, Copy, Eq, Debug, Default)]
    struct Foo(u8);

    impl PartialEq for Foo {
        fn eq(&self, other: &Foo) -> bool {
            self.0 % 5 == other.0 % 5
        }
    }

    let a = AtomicCell::new(Foo(1));

    assert_eq!(a.load(), Foo(1));
    assert_eq!(a.swap(Foo(2)), Foo(11));
    assert_eq!(a.load(), Foo(52));

    a.store(Foo(0));
    assert_eq!(a.compare_exchange(Foo(0), Foo(5)), Ok(Foo(100)));
    assert_eq!(a.load().0, 5);
    assert_eq!(a.compare_exchange(Foo(10), Foo(15)), Ok(Foo(100)));
    assert_eq!(a.load().0, 15);
}

#[test]
fn modular_usize() {
    #[derive(Clone, Copy, Eq, Debug, Default)]
    struct Foo(usize);

    impl PartialEq for Foo {
        fn eq(&self, other: &Foo) -> bool {
            self.0 % 5 == other.0 % 5
        }
    }

    let a = AtomicCell::new(Foo(1));

    assert_eq!(a.load(), Foo(1));
    assert_eq!(a.swap(Foo(2)), Foo(11));
    assert_eq!(a.load(), Foo(52));

    a.store(Foo(0));
    assert_eq!(a.compare_exchange(Foo(0), Foo(5)), Ok(Foo(100)));
    assert_eq!(a.load().0, 5);
    assert_eq!(a.compare_exchange(Foo(10), Foo(15)), Ok(Foo(100)));
    assert_eq!(a.load().0, 15);
}

#[test]
fn garbage_padding() {
    #[derive(Copy, Clone, Eq, PartialEq)]
    struct Object {
        a: i64,
        b: i32,
    }

    let cell = AtomicCell::new(Object { a: 0, b: 0 });
    let _garbage = [0xfe, 0xfe, 0xfe, 0xfe, 0xfe]; // Needed
    let next = Object { a: 0, b: 0 };

    let prev = cell.load();
    assert!(cell.compare_exchange(prev, next).is_ok());
    println!();
}

#[test]
fn const_atomic_cell_new() {
    static CELL: AtomicCell<usize> = AtomicCell::new(0);

    CELL.store(1);
    assert_eq!(CELL.load(), 1);
}

// https://github.com/crossbeam-rs/crossbeam/issues/748
#[cfg_attr(miri, ignore)] // TODO
#[rustversion::since(1.37)] // #[repr(align(N))] requires Rust 1.37
#[test]
fn issue_748() {
    #[allow(dead_code)]
    #[repr(align(8))]
    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    enum Test {
        Field(u32),
        FieldLess,
    }

    assert_eq!(mem::size_of::<Test>(), 8);
    assert_eq!(
        AtomicCell::<Test>::is_lock_free(),
        cfg!(not(crossbeam_no_atomic_64))
    );
    let x = AtomicCell::new(Test::FieldLess);
    assert_eq!(x.load(), Test::FieldLess);
}
<commit_msg>Add regression test for pr 767<commit_after>use std::mem;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering::SeqCst;

use crossbeam_utils::atomic::AtomicCell;

#[test]
fn is_lock_free() {
    struct UsizeWrap(usize);
    struct U8Wrap(bool);
    struct I16Wrap(i16);
    #[repr(align(8))]
    struct U64Align8(u64);

    assert!(AtomicCell::<usize>::is_lock_free());
    assert!(AtomicCell::<isize>::is_lock_free());
    assert!(AtomicCell::<UsizeWrap>::is_lock_free());

    assert!(AtomicCell::<()>::is_lock_free());

    assert!(AtomicCell::<u8>::is_lock_free());
    assert!(AtomicCell::<i8>::is_lock_free());
    assert!(AtomicCell::<bool>::is_lock_free());
    assert!(AtomicCell::<U8Wrap>::is_lock_free());

    assert!(AtomicCell::<u16>::is_lock_free());
    assert!(AtomicCell::<i16>::is_lock_free());
    assert!(AtomicCell::<I16Wrap>::is_lock_free());

    assert!(AtomicCell::<u32>::is_lock_free());
    assert!(AtomicCell::<i32>::is_lock_free());

    // Sizes of both types must be equal, and the alignment of `u64` must be greater or equal than
    // that of `AtomicU64`. In i686-unknown-linux-gnu, the alignment of `u64` is `4` and alignment
    // of `AtomicU64` is `8`, so `AtomicCell<u64>` is not lock-free.
    assert_eq!(
        AtomicCell::<u64>::is_lock_free(),
        cfg!(not(crossbeam_no_atomic_64))
            && cfg!(any(
                target_pointer_width = "64",
                target_pointer_width = "128"
            ))
    );
    assert_eq!(mem::size_of::<U64Align8>(), 8);
    assert_eq!(mem::align_of::<U64Align8>(), 8);
    assert_eq!(
        AtomicCell::<U64Align8>::is_lock_free(),
        cfg!(not(crossbeam_no_atomic_64))
    );

    // AtomicU128 is unstable
    assert!(!AtomicCell::<u128>::is_lock_free());
}

#[test]
fn const_is_lock_free() {
    const _U: bool = AtomicCell::<usize>::is_lock_free();
    const _I: bool = AtomicCell::<isize>::is_lock_free();
}

#[test]
fn drops_unit() {
    static CNT: AtomicUsize = AtomicUsize::new(0);
    CNT.store(0, SeqCst);

    #[derive(Debug, PartialEq, Eq)]
    struct Foo();

    impl Foo {
        fn new() -> Foo {
            CNT.fetch_add(1, SeqCst);
            Foo()
        }
    }

    impl Drop for Foo {
        fn drop(&mut self) {
            CNT.fetch_sub(1, SeqCst);
        }
    }

    impl Default for Foo {
        fn default() -> Foo {
            Foo::new()
        }
    }

    let a = AtomicCell::new(Foo::new());

    assert_eq!(a.swap(Foo::new()), Foo::new());
    assert_eq!(CNT.load(SeqCst), 1);

    a.store(Foo::new());
    assert_eq!(CNT.load(SeqCst), 1);

    assert_eq!(a.swap(Foo::default()), Foo::new());
    assert_eq!(CNT.load(SeqCst), 1);

    drop(a);
    assert_eq!(CNT.load(SeqCst), 0);
}

#[test]
fn drops_u8() {
    static CNT: AtomicUsize = AtomicUsize::new(0);
    CNT.store(0, SeqCst);

    #[derive(Debug, PartialEq, Eq)]
    struct Foo(u8);

    impl Foo {
        fn new(val: u8) -> Foo {
            CNT.fetch_add(1, SeqCst);
            Foo(val)
        }
    }

    impl Drop for Foo {
        fn drop(&mut self) {
            CNT.fetch_sub(1, SeqCst);
        }
    }

    impl Default for Foo {
        fn default() -> Foo {
            Foo::new(0)
        }
    }

    let a = AtomicCell::new(Foo::new(5));

    assert_eq!(a.swap(Foo::new(6)), Foo::new(5));
    assert_eq!(a.swap(Foo::new(1)), Foo::new(6));
    assert_eq!(CNT.load(SeqCst), 1);

    a.store(Foo::new(2));
    assert_eq!(CNT.load(SeqCst), 1);

    assert_eq!(a.swap(Foo::default()), Foo::new(2));
    assert_eq!(CNT.load(SeqCst), 1);

    assert_eq!(a.swap(Foo::default()), Foo::new(0));
    assert_eq!(CNT.load(SeqCst), 1);

    drop(a);
    assert_eq!(CNT.load(SeqCst), 0);
}

#[test]
fn drops_usize() {
    static CNT: AtomicUsize = AtomicUsize::new(0);
    CNT.store(0, SeqCst);

    #[derive(Debug, PartialEq, Eq)]
    struct Foo(usize);

    impl Foo {
        fn new(val: usize) -> Foo {
            CNT.fetch_add(1, SeqCst);
            Foo(val)
        }
    }

    impl Drop for Foo {
        fn drop(&mut self) {
            CNT.fetch_sub(1, SeqCst);
        }
    }

    impl Default for Foo {
        fn default() -> Foo {
            Foo::new(0)
        }
    }

    let a = AtomicCell::new(Foo::new(5));

    assert_eq!(a.swap(Foo::new(6)), Foo::new(5));
    assert_eq!(a.swap(Foo::new(1)), Foo::new(6));
    assert_eq!(CNT.load(SeqCst), 1);

    a.store(Foo::new(2));
    assert_eq!(CNT.load(SeqCst), 1);

    assert_eq!(a.swap(Foo::default()), Foo::new(2));
    assert_eq!(CNT.load(SeqCst), 1);

    assert_eq!(a.swap(Foo::default()), Foo::new(0));
    assert_eq!(CNT.load(SeqCst), 1);

    drop(a);
    assert_eq!(CNT.load(SeqCst), 0);
}

#[test]
fn modular_u8() {
    #[derive(Clone, Copy, Eq, Debug, Default)]
    struct Foo(u8);

    impl PartialEq for Foo {
        fn eq(&self, other: &Foo) -> bool {
            self.0 % 5 == other.0 % 5
        }
    }

    let a = AtomicCell::new(Foo(1));

    assert_eq!(a.load(), Foo(1));
    assert_eq!(a.swap(Foo(2)), Foo(11));
    assert_eq!(a.load(), Foo(52));

    a.store(Foo(0));
    assert_eq!(a.compare_exchange(Foo(0), Foo(5)), Ok(Foo(100)));
    assert_eq!(a.load().0, 5);
    assert_eq!(a.compare_exchange(Foo(10), Foo(15)), Ok(Foo(100)));
    assert_eq!(a.load().0, 15);
}

#[test]
fn modular_usize() {
    #[derive(Clone, Copy, Eq, Debug, Default)]
    struct Foo(usize);

    impl PartialEq for Foo {
        fn eq(&self, other: &Foo) -> bool {
            self.0 % 5 == other.0 % 5
        }
    }

    let a = AtomicCell::new(Foo(1));

    assert_eq!(a.load(), Foo(1));
    assert_eq!(a.swap(Foo(2)), Foo(11));
    assert_eq!(a.load(), Foo(52));

    a.store(Foo(0));
    assert_eq!(a.compare_exchange(Foo(0), Foo(5)), Ok(Foo(100)));
    assert_eq!(a.load().0, 5);
    assert_eq!(a.compare_exchange(Foo(10), Foo(15)), Ok(Foo(100)));
    assert_eq!(a.load().0, 15);
}

#[test]
fn garbage_padding() {
    #[derive(Copy, Clone, Eq, PartialEq)]
    struct Object {
        a: i64,
        b: i32,
    }

    let cell = AtomicCell::new(Object { a: 0, b: 0 });
    let _garbage = [0xfe, 0xfe, 0xfe, 0xfe, 0xfe]; // Needed
    let next = Object { a: 0, b: 0 };

    let prev = cell.load();
    assert!(cell.compare_exchange(prev, next).is_ok());
    println!();
}

#[test]
fn const_atomic_cell_new() {
    static CELL: AtomicCell<usize> = AtomicCell::new(0);

    CELL.store(1);
    assert_eq!(CELL.load(), 1);
}

// https://github.com/crossbeam-rs/crossbeam/pull/767
macro_rules! test_arithmetic {
    ($test_name:ident, $ty:ident) => {
        #[test]
        fn $test_name() {
            let a: AtomicCell<$ty> = AtomicCell::new(7);

            assert_eq!(a.fetch_add(3), 7);
            assert_eq!(a.load(), 10);

            assert_eq!(a.fetch_sub(3), 10);
            assert_eq!(a.load(), 7);

            assert_eq!(a.fetch_and(3), 7);
            assert_eq!(a.load(), 3);

            assert_eq!(a.fetch_or(16), 3);
            assert_eq!(a.load(), 19);

            assert_eq!(a.fetch_xor(2), 19);
            assert_eq!(a.load(), 17);
        }
    };
}
test_arithmetic!(arithmetic_u8, u8);
test_arithmetic!(arithmetic_i8, i8);
test_arithmetic!(arithmetic_u16, u16);
test_arithmetic!(arithmetic_i16, i16);
test_arithmetic!(arithmetic_u32, u32);
test_arithmetic!(arithmetic_i32, i32);
test_arithmetic!(arithmetic_u64, u64);
test_arithmetic!(arithmetic_i64, i64);
test_arithmetic!(arithmetic_u128, u128);
test_arithmetic!(arithmetic_i128, i128);

// https://github.com/crossbeam-rs/crossbeam/issues/748
#[cfg_attr(miri, ignore)] // TODO
#[rustversion::since(1.37)] // #[repr(align(N))] requires Rust 1.37
#[test]
fn issue_748() {
    #[allow(dead_code)]
    #[repr(align(8))]
    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    enum Test {
        Field(u32),
        FieldLess,
    }

    assert_eq!(mem::size_of::<Test>(), 8);
    assert_eq!(
        AtomicCell::<Test>::is_lock_free(),
        cfg!(not(crossbeam_no_atomic_64))
    );
    let x = AtomicCell::new(Test::FieldLess);
    assert_eq!(x.load(), Test::FieldLess);
}
<|endoftext|>


<commit_before>use std::sync::atomics::{AtomicUint, INIT_ATOMIC_UINT, SeqCst};

static mut next_tid: AtomicUint = INIT_ATOMIC_UINT;

local_data_key!(task_local_tid: uint)

/// Every task gets one, that's unique.
pub fn tid() -> uint {
    let ret =
        match task_local_tid.replace(None) {
            None => unsafe { next_tid.fetch_add(1, SeqCst) },
            Some(x) => x,
        };

    task_local_tid.replace(Some(ret));

    ret
}
<commit_msg>added valid license to tid.rs<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::sync::atomics::{AtomicUint, INIT_ATOMIC_UINT, SeqCst};

static mut next_tid: AtomicUint = INIT_ATOMIC_UINT;

local_data_key!(task_local_tid: uint)

/// Every task gets one, that's unique.
pub fn tid() -> uint {
    let ret =
        match task_local_tid.replace(None) {
            None => unsafe { next_tid.fetch_add(1, SeqCst) },
            Some(x) => x,
        };

    task_local_tid.replace(Some(ret));

    ret
}
<|endoftext|>


<commit_before>use super::internal::*;
use super::*;
use std::cmp::max;
use std::iter::{self, Chain, Once};
use std::str::{Chars, Split};

/// Test if a byte is the start of a UTF-8 character.
/// (extracted from `str::is_char_boundary`)
fn is_char_boundary(b: u8) -> bool {
    // This is bit magic equivalent to: b < 128 || b >= 192
    (b as i8) >= -0x40
}

/// Find the index of a character boundary near the midpoint.
fn find_char_midpoint(chars: &str) -> usize {
    let mid = chars.len() / 2;

    // We want to split near the midpoint, but we need to find an actual
    // character boundary.  So we look at the raw bytes, first scanning
    // forward from the midpoint for a boundary, then trying backward.
    let (left, right) = chars.as_bytes().split_at(mid);
    right.iter()
        .cloned()
        .position(is_char_boundary)
        .map(|i| mid + i)
        .or_else(|| left.iter().cloned().rposition(is_char_boundary))
        .unwrap_or(0)
}

impl<'a> ParallelString for &'a str {
    type Chars = ParChars<'a>;
    type Split = ParSplit<'a>;

    fn par_chars(self) -> Self::Chars {
        ParChars { chars: self }
    }

    fn par_split(self, separator: char) -> Self::Split {
        ParSplit::new(self, separator)
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParChars<'a> {
    chars: &'a str,
}

impl<'a> ParallelIterator for ParChars<'a> {
    type Item = char;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        bridge_unindexed(self, consumer)
    }
}

impl<'a> UnindexedProducer for ParChars<'a> {
    fn split(&mut self) -> Option<Self> {
        let index = find_char_midpoint(self.chars);
        if index > 0 {
            let (left, right) = self.chars.split_at(index);
            self.chars = left;
            Some(ParChars { chars: right })
        } else {
            None
        }
    }
}

impl<'a> IntoIterator for ParChars<'a> {
    type Item = char;
    type IntoIter = Chars<'a>;

    fn into_iter(self) -> Self::IntoIter {
        self.chars.chars()
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParSplit<'a> {
    chars: &'a str,
    separator: char,

    /// Keeps track of the first separator found in the string.  This lets us
    /// quickly answer `can_split`, and it also corresponds to what parts we've
    /// already scanned as we keep splitting smaller.
    first: Option<usize>,
}

impl<'a> ParSplit<'a> {
    fn new(chars: &'a str, separator: char) -> Self {
        ParSplit {
            chars: chars,
            separator: separator,
            first: chars.find(separator),
        }
    }
}

impl<'a> ParallelIterator for ParSplit<'a> {
    type Item = &'a str;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        bridge_unindexed(self, consumer)
    }
}

impl<'a> UnindexedProducer for ParSplit<'a> {
    fn split(&mut self) -> Option<Self> {
        let ParSplit { chars, separator, first } = *self;
        let first = match first {
            None => return None,
            Some(first) => first,
        };

        // First find a suitable UTF-8 boundary in the unsearched region.
        let char_index = find_char_midpoint(&chars[first..]) + first;

        // Find a separator in reverse, towards the `first` that we know exists.
        let index = chars[first..char_index]
            .rfind(separator)
            .map(|i| i + first)
            .unwrap_or(first);

        // Update `self` as the left side of the split.  It might not have a
        // `first` anymore if that's the exact separator we're splitting on now.
        self.chars = &chars[..index];
        if first == index {
            self.first = None;
        }

        // Return the right side of the split starting just after this separator.
        // We find its `first` starting from the `char_index` already scanned above.
        let right_index = index + separator.len_utf8();
        let right_search = max(char_index, right_index);
        let right_first = chars[right_search..]
            .find(separator)
            .map(|i| i + (right_search - right_index));
        Some(ParSplit {
            chars: &chars[right_index..],
            separator: separator,
            first: right_first,
        })
    }
}

impl<'a> IntoIterator for ParSplit<'a> {
    type Item = &'a str;
    type IntoIter = Chain<Once<&'a str>, Split<'a, char>>;

    fn into_iter(self) -> Self::IntoIter {
        if let Some(first) = self.first {
            // We know where the first separator is, so start with that
            // and then let `str::split` find the rest.
            let head = &self.chars[..first];
            let tail = &self.chars[first + self.separator.len_utf8()..];
            iter::once(head).chain(tail.split(self.separator))
        } else {
            // We know there are no separators at all.  Return our whole string,
            // but for type correctness we need to chain an emptied `Split` too.
            let head = self.chars;
            let mut tail = "".split('\0');
            Iterator::last(&mut tail);
            iter::once(head).chain(tail)
        }
    }
}
<commit_msg>Don't require pre-scans in ParSplit<commit_after>use super::internal::*;
use super::*;
use std::cmp::min;
use std::iter::Chain;
use std::option::IntoIter as OptionIter;
use std::str::{Chars, Split};

/// Test if a byte is the start of a UTF-8 character.
/// (extracted from `str::is_char_boundary`)
fn is_char_boundary(b: u8) -> bool {
    // This is bit magic equivalent to: b < 128 || b >= 192
    (b as i8) >= -0x40
}

/// Find the index of a character boundary near the midpoint.
fn find_char_midpoint(chars: &str) -> usize {
    let mid = chars.len() / 2;

    // We want to split near the midpoint, but we need to find an actual
    // character boundary.  So we look at the raw bytes, first scanning
    // forward from the midpoint for a boundary, then trying backward.
    let (left, right) = chars.as_bytes().split_at(mid);
    right.iter()
        .cloned()
        .position(is_char_boundary)
        .map(|i| mid + i)
        .or_else(|| left.iter().cloned().rposition(is_char_boundary))
        .unwrap_or(0)
}

impl<'a> ParallelString for &'a str {
    type Chars = ParChars<'a>;
    type Split = ParSplit<'a>;

    fn par_chars(self) -> Self::Chars {
        ParChars { chars: self }
    }

    fn par_split(self, separator: char) -> Self::Split {
        ParSplit::new(self, separator)
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParChars<'a> {
    chars: &'a str,
}

impl<'a> ParallelIterator for ParChars<'a> {
    type Item = char;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        bridge_unindexed(self, consumer)
    }
}

impl<'a> UnindexedProducer for ParChars<'a> {
    fn split(&mut self) -> Option<Self> {
        let index = find_char_midpoint(self.chars);
        if index > 0 {
            let (left, right) = self.chars.split_at(index);
            self.chars = left;
            Some(ParChars { chars: right })
        } else {
            None
        }
    }
}

impl<'a> IntoIterator for ParChars<'a> {
    type Item = char;
    type IntoIter = Chars<'a>;

    fn into_iter(self) -> Self::IntoIter {
        self.chars.chars()
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParSplit<'a> {
    chars: &'a str,
    separator: char,

    /// Marks the endpoint beyond which we've already found no separators.
    tail: usize,
}

impl<'a> ParSplit<'a> {
    fn new(chars: &'a str, separator: char) -> Self {
        ParSplit {
            chars: chars,
            separator: separator,
            tail: chars.len(),
        }
    }
}

impl<'a> ParallelIterator for ParSplit<'a> {
    type Item = &'a str;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        bridge_unindexed(self, consumer)
    }
}

impl<'a> UnindexedProducer for ParSplit<'a> {
    fn split(&mut self) -> Option<Self> {
        let ParSplit { chars, separator, tail } = *self;

        // First find a suitable UTF-8 boundary in the unsearched region.
        let char_index = find_char_midpoint(&chars[..tail]);

        // Look forward for the separator, and failing that look backward.
        let index = chars[char_index..tail]
            .find(separator)
            .map(|i| char_index + i)
            .or_else(|| chars[..char_index].rfind(separator));

        if let Some(index) = index {
            // Update `self` as the region before the separator.
            self.chars = &chars[..index];
            self.tail = min(char_index, index);

            // Create the right split following the separator.
            let right_index = index + separator.len_utf8();
            let mut right = ParSplit {
                chars: &chars[right_index..],
                separator: separator,
                tail: tail - right_index,
            };

            // If we scanned backwards to find the separator, everything in
            // the right side is exhausted, with no separators left to find.
            if index < char_index {
                right.tail = 0;
            }

            Some(right)

        } else {
            self.tail = 0;
            None
        }
    }
}

impl<'a> IntoIterator for ParSplit<'a> {
    type Item = &'a str;
    type IntoIter = Chain<Split<'a, char>, OptionIter<&'a str>>;

    fn into_iter(self) -> Self::IntoIter {
        let ParSplit { chars, separator, tail } = self;

        if tail == chars.len() {
            // No tail section, so just let `str::split` handle it.
            chars.split(separator).chain(None)

        } else if let Some(index) = chars[..tail].rfind(separator) {
            // We found the last separator to complete the tail, so
            // end with that slice after `str::split` finds the rest.
            let head = &chars[..index];
            let last = &chars[index + separator.len_utf8()..];
            head.split(separator).chain(Some(last))

        } else {
            // We know there are no separators at all.  Return our whole string,
            // but for type correctness we need to chain an emptied `Split` too.
            let mut empty = "".split('\0');
            Iterator::last(&mut empty);
            empty.chain(Some(chars))
        }
    }
}
<|endoftext|>


<commit_before>use git_version::git_version;
use target_info::Target;

/// Returns the current version of this build of Lighthouse.
///
/// A plus-sign (`+`) is appended to the git commit if the tree is dirty.
///
/// ## Example
///
/// `Lighthouse/v0.2.0-1419501f2+`
pub const VERSION: &str = git_version!(
    args = ["--always", "--dirty=+", "--abbrev=7", "--exclude=*"],
    prefix = "Lighthouse/v1.1.3-",
    fallback = "unknown"
);

/// Returns `VERSION`, but with platform information appended to the end.
///
/// ## Example
///
/// `Lighthouse/v0.2.0-1419501f2+/x86_64-linux`
pub fn version_with_platform() -> String {
    format!("{}/{}-{}", VERSION, Target::arch(), Target::os())
}

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

    #[test]
    fn version_formatting() {
        let re = Regex::new(r"^Lighthouse/v[0-9]+\.[0-9]+\.[0-9]+(-rc.[0-9])?-[[:xdigit:]]{7}\+?$")
            .unwrap();
        assert!(re.is_match(VERSION), VERSION);
    }
}
<commit_msg>Make lighthouse_version compatible with old Git (#2223)<commit_after>use git_version::git_version;
use target_info::Target;

/// Returns the current version of this build of Lighthouse.
///
/// A plus-sign (`+`) is appended to the git commit if the tree is dirty.
///
/// ## Example
///
/// `Lighthouse/v0.2.0-1419501f2+`
pub const VERSION: &str = git_version!(
    args = [
        "--always",
        "--dirty=+",
        "--abbrev=7",
        // NOTE: using --match instead of --exclude for compatibility with old Git
        "--match=thiswillnevermatchlol"
    ],
    prefix = "Lighthouse/v1.1.3-",
    fallback = "unknown"
);

/// Returns `VERSION`, but with platform information appended to the end.
///
/// ## Example
///
/// `Lighthouse/v0.2.0-1419501f2+/x86_64-linux`
pub fn version_with_platform() -> String {
    format!("{}/{}-{}", VERSION, Target::arch(), Target::os())
}

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

    #[test]
    fn version_formatting() {
        let re = Regex::new(r"^Lighthouse/v[0-9]+\.[0-9]+\.[0-9]+(-rc.[0-9])?-[[:xdigit:]]{7}\+?$")
            .unwrap();
        assert!(re.is_match(VERSION), VERSION);
    }
}
<|endoftext|>


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

pub struct Inner<T> {
    field: T,
}

unsafe impl<T> Send for Inner<T>
where
    T: Copy + Send,
{
}

// @has no_redundancy/struct.Outer.html
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<T> Send for \
// Outer<T> where T: Copy + Send"
pub struct Outer<T> {
    inner_field: Inner<T>,
}
<commit_msg>Comment out flakey test.<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/* This test is flakey, so it has been commented out.

pub struct Inner<T> {
    field: T,
}

unsafe impl<T> Send for Inner<T>
where
    T: Copy + Send,
{
}

// @has no_redundancy/struct.Outer.html
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<T> Send for \
// Outer<T> where T: Copy + Send"
pub struct Outer<T> {
    inner_field: Inner<T>,
}

*/
<|endoftext|>