<commit_before>/*!

Sendable hash maps.  Very much a work in progress.

*/

use cmp::Eq;
use hash::Hash;
use to_bytes::IterBytes;

trait SendMap<K:Eq Hash, V: Copy> {
    // FIXME(#3148)  ^^^^ once find_ref() works, we can drop V:copy

    fn insert(&mut self, +k: K, +v: V) -> bool;
    fn remove(&mut self, k: &K) -> bool;
    fn clear(&mut self);
    pure fn len(&const self) -> uint;
    pure fn is_empty(&const self) -> bool;
    fn contains_key(&const self, k: &K) -> bool;
    fn each_ref(&self, blk: fn(k: &K, v: &V) -> bool);
    fn each_key_ref(&self, blk: fn(k: &K) -> bool);
    fn each_value_ref(&self, blk: fn(v: &V) -> bool);
    fn find(&const self, k: &K) -> Option<V>;
    fn get(&const self, k: &K) -> V;
    fn with_find_ref<T>(&const self, k: &K, blk: fn(Option<&V>) -> T) -> T;
    fn with_get_ref<T>(&const self, k: &K, blk: fn(v: &V) -> T) -> T;
}

/// Open addressing with linear probing.
mod linear {
    export LinearMap, linear_map, linear_map_with_capacity, public_methods;

    const initial_capacity: uint = 32u; // 2^5
    struct Bucket<K:Eq Hash,V> {
        hash: uint,
        key: K,
        value: V,
    }
    struct LinearMap<K:Eq Hash,V> {
        k0: u64,
        k1: u64,
        resize_at: uint,
        size: uint,
        buckets: ~[Option<Bucket<K,V>>],
    }

    // FIXME(#3148) -- we could rewrite found_entry
    // to have type option<&bucket<K,V>> which would be nifty
    // However, that won't work until #3148 is fixed
    enum SearchResult {
        FoundEntry(uint), FoundHole(uint), TableFull
    }

    fn resize_at(capacity: uint) -> uint {
        ((capacity as float) * 3. / 4.) as uint
    }

    fn LinearMap<K:Eq Hash,V>() -> LinearMap<K,V> {
        linear_map_with_capacity(32)
    }

    fn linear_map_with_capacity<K:Eq Hash,V>(
        initial_capacity: uint) -> LinearMap<K,V> {
        let r = rand::Rng();
        linear_map_with_capacity_and_keys(r.gen_u64(), r.gen_u64(),
                                          initial_capacity)
    }

    fn linear_map_with_capacity_and_keys<K:Eq Hash,V> (
        k0: u64, k1: u64,
        initial_capacity: uint) -> LinearMap<K,V> {
        LinearMap {
            k0: k0, k1: k1,
            resize_at: resize_at(initial_capacity),
            size: 0,
            buckets: vec::from_fn(initial_capacity, |_i| None)
        }
    }

    priv impl<K:Hash IterBytes Eq, V> LinearMap<K,V> {
        #[inline(always)]
        pure fn to_bucket(&const self,
                          h: uint) -> uint {
            // FIXME(#3041) borrow a more sophisticated technique here from
            // Gecko, for example borrowing from Knuth, as Eich so
            // colorfully argues for here:
            // https://bugzilla.mozilla.org/show_bug.cgi?id=743107#c22
            h % self.buckets.len()
        }

        #[inline(always)]
        pure fn next_bucket(&const self,
                            idx: uint,
                            len_buckets: uint) -> uint {
            let n = (idx + 1) % len_buckets;
            unsafe{ // argh. log not considered pure.
                debug!("next_bucket(%?, %?) = %?", idx, len_buckets, n);
            }
            return n;
        }

        #[inline(always)]
        pure fn bucket_sequence(&const self,
                                hash: uint,
                                op: fn(uint) -> bool) -> uint {
            let start_idx = self.to_bucket(hash);
            let len_buckets = self.buckets.len();
            let mut idx = start_idx;
            loop {
                if !op(idx) {
                    return idx;
                }
                idx = self.next_bucket(idx, len_buckets);
                if idx == start_idx {
                    return start_idx;
                }
            }
        }

        #[inline(always)]
        pure fn bucket_for_key(&const self,
                               buckets: &[Option<Bucket<K,V>>],
                               k: &K) -> SearchResult {
            let hash = k.hash_keyed(self.k0, self.k1) as uint;
            self.bucket_for_key_with_hash(buckets, hash, k)
        }

        #[inline(always)]
        pure fn bucket_for_key_with_hash(&const self,
                                         buckets: &[Option<Bucket<K,V>>],
                                         hash: uint,
                                         k: &K) -> SearchResult {
            let _ = for self.bucket_sequence(hash) |i| {
                match buckets[i] {
                    Some(bkt) => if bkt.hash == hash && *k == bkt.key {
                        return FoundEntry(i);
                    },
                    None => return FoundHole(i)
                }
            };
            return TableFull;
        }

        /// Expands the capacity of the array and re-inserts each
        /// of the existing buckets.
        fn expand(&mut self) {
            let old_capacity = self.buckets.len();
            let new_capacity = old_capacity * 2;
            self.resize_at = ((new_capacity as float) * 3.0 / 4.0) as uint;

            let mut old_buckets = vec::from_fn(new_capacity, |_i| None);
            self.buckets <-> old_buckets;

            for uint::range(0, old_capacity) |i| {
                let mut bucket = None;
                bucket <-> old_buckets[i];
                self.insert_opt_bucket(move bucket);
            }
        }

        fn insert_opt_bucket(&mut self, +bucket: Option<Bucket<K,V>>) {
            match move bucket {
                Some(Bucket {hash: move hash,
                             key: move key,
                             value: move value}) => {
                    self.insert_internal(hash, move key, move value);
                }
                None => {}
            }
        }

        /// Inserts the key value pair into the buckets.
        /// Assumes that there will be a bucket.
        /// True if there was no previous entry with that key
        fn insert_internal(&mut self, hash: uint, +k: K, +v: V) -> bool {
            match self.bucket_for_key_with_hash(self.buckets, hash, &k) {
                TableFull => { fail ~"Internal logic error"; }
                FoundHole(idx) => {
                    debug!("insert fresh (%?->%?) at idx %?, hash %?",
                           k, v, idx, hash);
                    self.buckets[idx] = Some(Bucket {hash: hash,
                                                     key: k,
                                                     value: v});
                    self.size += 1;
                    true
                }
                FoundEntry(idx) => {
                    debug!("insert overwrite (%?->%?) at idx %?, hash %?",
                           k, v, idx, hash);
                    self.buckets[idx] = Some(Bucket {hash: hash,
                                                     key: k,
                                                     value: v});
                    false
                }
            }
        }

        fn search(&self,
                  hash: uint,
                  op: fn(x: &Option<Bucket<K,V>>) -> bool) {
            let _ = self.bucket_sequence(hash, |i| op(&self.buckets[i]));
        }
    }

    impl<K:Hash IterBytes Eq,V> LinearMap<K,V> {
        fn insert(&mut self, +k: K, +v: V) -> bool {
            if self.size >= self.resize_at {
                // n.b.: We could also do this after searching, so
                // that we do not resize if this call to insert is
                // simply going to update a key in place.  My sense
                // though is that it's worse to have to search through
                // buckets to find the right spot twice than to just
                // resize in this corner case.
                self.expand();
            }

            let hash = k.hash_keyed(self.k0, self.k1) as uint;
            self.insert_internal(hash, move k, move v)
        }

        fn remove(&mut self, k: &K) -> bool {
            // Removing from an open-addressed hashtable
            // is, well, painful.  The problem is that
            // the entry may lie on the probe path for other
            // entries, so removing it would make you think that
            // those probe paths are empty.
            //
            // To address this we basically have to keep walking,
            // re-inserting entries we find until we reach an empty
            // bucket.  We know we will eventually reach one because
            // we insert one ourselves at the beginning (the removed
            // entry).
            //
            // I found this explanation elucidating:
            // http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf

            let mut idx = match self.bucket_for_key(self.buckets, k) {
                TableFull | FoundHole(_) => return false,
                FoundEntry(idx) => idx
            };

            let len_buckets = self.buckets.len();
            self.buckets[idx] = None;
            idx = self.next_bucket(idx, len_buckets);
            while self.buckets[idx].is_some() {
                let mut bucket = None;
                bucket <-> self.buckets[idx];
                self.insert_opt_bucket(move bucket);
                idx = self.next_bucket(idx, len_buckets);
            }
            self.size -= 1;
            return true;
        }

        fn clear(&mut self) {
            for uint::range(0, self.buckets.len()) |idx| {
                self.buckets[idx] = None;
            }
            self.size = 0;
        }

        pure fn len(&const self) -> uint {
            self.size
        }

        pure fn is_empty(&const self) -> bool {
            self.len() == 0
        }

        fn contains_key(&const self,
                        k: &K) -> bool {
            match self.bucket_for_key(self.buckets, k) {
                FoundEntry(_) => {true}
                TableFull | FoundHole(_) => {false}
            }
        }

        fn find_ref(&self, k: &K) -> Option<&self/V> {
            match self.bucket_for_key(self.buckets, k) {
                FoundEntry(idx) => {
                    match self.buckets[idx] {
                        Some(ref bkt) => {
                            let ptr = unsafe {
                                // FIXME(#3148)--region inference
                                // fails to capture needed deps.
                                // Here, the bucket value is known to
                                // live as long as self, because self
                                // is immutable.  But the region
                                // inference stupidly infers a
                                // lifetime for `ref bkt` that is
                                // shorter than it needs to be.
                                unsafe::copy_lifetime(self, &bkt.value)
                            };
                            Some(ptr)
                        }
                        None => {
                            fail ~"LinearMap::find: internal logic error"
                        }
                    }
                }
                TableFull | FoundHole(_) => {
                    None
                }
            }
        }

        fn each_ref(&self, blk: fn(k: &K, v: &V) -> bool) {
            for vec::each(self.buckets) |slot| {
                let mut broke = false;
                do slot.iter |bucket| {
                    if !blk(&bucket.key, &bucket.value) {
                        broke = true; // FIXME(#3064) just write "break;"
                    }
                }
                if broke { break; }
            }
        }

        fn each_key_ref(&self, blk: fn(k: &K) -> bool) {
            self.each_ref(|k, _v| blk(k))
        }

        fn each_value_ref(&self, blk: fn(v: &V) -> bool) {
            self.each_ref(|_k, v| blk(v))
        }
    }

    impl<K:Hash IterBytes Eq, V: Copy> LinearMap<K,V> {
        fn find(&const self, k: &K) -> Option<V> {
            match self.bucket_for_key(self.buckets, k) {
                FoundEntry(idx) => {
                    // FIXME (#3148): Once we rewrite found_entry, this
                    // failure case won't be necessary
                    match self.buckets[idx] {
                        Some(bkt) => {Some(copy bkt.value)}
                        None => fail ~"LinearMap::find: internal logic error"
                    }
                }
                TableFull | FoundHole(_) => {
                    None
                }
            }
        }

        fn get(&const self, k: &K) -> V {
            let value = self.find(k);
            if value.is_none() {
                fail fmt!("No entry found for key: %?", k);
            }
            option::unwrap(move value)
        }

    }

    impl<K: Hash IterBytes Eq Copy, V: Copy> LinearMap<K,V> {
        fn each(&self, blk: fn(+K,+V) -> bool) {
            self.each_ref(|k,v| blk(copy *k, copy *v));
        }
    }
    impl<K: Hash IterBytes Eq Copy, V> LinearMap<K,V> {
        fn each_key(&self, blk: fn(+K) -> bool) {
            self.each_key_ref(|k| blk(copy *k));
        }
    }
    impl<K: Hash IterBytes Eq, V: Copy> LinearMap<K,V> {
        fn each_value(&self, blk: fn(+V) -> bool) {
            self.each_value_ref(|v| blk(copy *v));
        }
    }
}

#[test]
mod test {

    use linear::LinearMap;

    fn int_linear_map<V>() -> LinearMap<uint,V> {
        return LinearMap();
    }

    #[test]
    fn inserts() {
        let mut m = int_linear_map();
        assert m.insert(1, 2);
        assert m.insert(2, 4);
        assert m.get(&1) == 2;
        assert m.get(&2) == 4;
    }

    #[test]
    fn overwrite() {
        let mut m = int_linear_map();
        assert m.insert(1, 2);
        assert m.get(&1) == 2;
        assert !m.insert(1, 3);
        assert m.get(&1) == 3;
    }

    #[test]
    fn conflicts() {
        let mut m = linear::linear_map_with_capacity(4);
        assert m.insert(1, 2);
        assert m.insert(5, 3);
        assert m.insert(9, 4);
        assert m.get(&9) == 4;
        assert m.get(&5) == 3;
        assert m.get(&1) == 2;
    }

    #[test]
    fn conflict_remove() {
        let mut m = linear::linear_map_with_capacity(4);
        assert m.insert(1, 2);
        assert m.insert(5, 3);
        assert m.insert(9, 4);
        assert m.remove(&1);
        assert m.get(&9) == 4;
        assert m.get(&5) == 3;
    }

    #[test]
    fn empty() {
        let mut m = linear::linear_map_with_capacity(4);
        assert m.insert(1, 2);
        assert !m.is_empty();
        assert m.remove(&1);
        assert m.is_empty();
    }

    #[test]
    fn iterate() {
        let mut m = linear::linear_map_with_capacity(4);
        for uint::range(0, 32) |i| {
            assert m.insert(i, i*2);
        }
        let mut observed = 0;
        for m.each |k, v| {
            assert v == k*2;
            observed |= (1 << k);
        }
        assert observed == 0xFFFF_FFFF;
    }

    #[test]
    fn find_ref() {
        let mut m = ~LinearMap();
        assert m.find_ref(&1).is_none();
        m.insert(1, 2);
        match m.find_ref(&1) {
            None => fail,
            Some(v) => assert *v == 2
        }
    }
}
<commit_msg>libcore: send_map test simplification.<commit_after>/*!

Sendable hash maps.  Very much a work in progress.

*/

use cmp::Eq;
use hash::Hash;
use to_bytes::IterBytes;

trait SendMap<K:Eq Hash, V: Copy> {
    // FIXME(#3148)  ^^^^ once find_ref() works, we can drop V:copy

    fn insert(&mut self, +k: K, +v: V) -> bool;
    fn remove(&mut self, k: &K) -> bool;
    fn clear(&mut self);
    pure fn len(&const self) -> uint;
    pure fn is_empty(&const self) -> bool;
    fn contains_key(&const self, k: &K) -> bool;
    fn each_ref(&self, blk: fn(k: &K, v: &V) -> bool);
    fn each_key_ref(&self, blk: fn(k: &K) -> bool);
    fn each_value_ref(&self, blk: fn(v: &V) -> bool);
    fn find(&const self, k: &K) -> Option<V>;
    fn get(&const self, k: &K) -> V;
    fn with_find_ref<T>(&const self, k: &K, blk: fn(Option<&V>) -> T) -> T;
    fn with_get_ref<T>(&const self, k: &K, blk: fn(v: &V) -> T) -> T;
}

/// Open addressing with linear probing.
mod linear {
    export LinearMap, linear_map, linear_map_with_capacity, public_methods;

    const initial_capacity: uint = 32u; // 2^5
    struct Bucket<K:Eq Hash,V> {
        hash: uint,
        key: K,
        value: V,
    }
    struct LinearMap<K:Eq Hash,V> {
        k0: u64,
        k1: u64,
        resize_at: uint,
        size: uint,
        buckets: ~[Option<Bucket<K,V>>],
    }

    // FIXME(#3148) -- we could rewrite found_entry
    // to have type option<&bucket<K,V>> which would be nifty
    // However, that won't work until #3148 is fixed
    enum SearchResult {
        FoundEntry(uint), FoundHole(uint), TableFull
    }

    fn resize_at(capacity: uint) -> uint {
        ((capacity as float) * 3. / 4.) as uint
    }

    fn LinearMap<K:Eq Hash,V>() -> LinearMap<K,V> {
        linear_map_with_capacity(32)
    }

    fn linear_map_with_capacity<K:Eq Hash,V>(
        initial_capacity: uint) -> LinearMap<K,V> {
        let r = rand::Rng();
        linear_map_with_capacity_and_keys(r.gen_u64(), r.gen_u64(),
                                          initial_capacity)
    }

    fn linear_map_with_capacity_and_keys<K:Eq Hash,V> (
        k0: u64, k1: u64,
        initial_capacity: uint) -> LinearMap<K,V> {
        LinearMap {
            k0: k0, k1: k1,
            resize_at: resize_at(initial_capacity),
            size: 0,
            buckets: vec::from_fn(initial_capacity, |_i| None)
        }
    }

    priv impl<K:Hash IterBytes Eq, V> LinearMap<K,V> {
        #[inline(always)]
        pure fn to_bucket(&const self,
                          h: uint) -> uint {
            // FIXME(#3041) borrow a more sophisticated technique here from
            // Gecko, for example borrowing from Knuth, as Eich so
            // colorfully argues for here:
            // https://bugzilla.mozilla.org/show_bug.cgi?id=743107#c22
            h % self.buckets.len()
        }

        #[inline(always)]
        pure fn next_bucket(&const self,
                            idx: uint,
                            len_buckets: uint) -> uint {
            let n = (idx + 1) % len_buckets;
            unsafe{ // argh. log not considered pure.
                debug!("next_bucket(%?, %?) = %?", idx, len_buckets, n);
            }
            return n;
        }

        #[inline(always)]
        pure fn bucket_sequence(&const self,
                                hash: uint,
                                op: fn(uint) -> bool) -> uint {
            let start_idx = self.to_bucket(hash);
            let len_buckets = self.buckets.len();
            let mut idx = start_idx;
            loop {
                if !op(idx) {
                    return idx;
                }
                idx = self.next_bucket(idx, len_buckets);
                if idx == start_idx {
                    return start_idx;
                }
            }
        }

        #[inline(always)]
        pure fn bucket_for_key(&const self,
                               buckets: &[Option<Bucket<K,V>>],
                               k: &K) -> SearchResult {
            let hash = k.hash_keyed(self.k0, self.k1) as uint;
            self.bucket_for_key_with_hash(buckets, hash, k)
        }

        #[inline(always)]
        pure fn bucket_for_key_with_hash(&const self,
                                         buckets: &[Option<Bucket<K,V>>],
                                         hash: uint,
                                         k: &K) -> SearchResult {
            let _ = for self.bucket_sequence(hash) |i| {
                match buckets[i] {
                    Some(bkt) => if bkt.hash == hash && *k == bkt.key {
                        return FoundEntry(i);
                    },
                    None => return FoundHole(i)
                }
            };
            return TableFull;
        }

        /// Expands the capacity of the array and re-inserts each
        /// of the existing buckets.
        fn expand(&mut self) {
            let old_capacity = self.buckets.len();
            let new_capacity = old_capacity * 2;
            self.resize_at = ((new_capacity as float) * 3.0 / 4.0) as uint;

            let mut old_buckets = vec::from_fn(new_capacity, |_i| None);
            self.buckets <-> old_buckets;

            for uint::range(0, old_capacity) |i| {
                let mut bucket = None;
                bucket <-> old_buckets[i];
                self.insert_opt_bucket(move bucket);
            }
        }

        fn insert_opt_bucket(&mut self, +bucket: Option<Bucket<K,V>>) {
            match move bucket {
                Some(Bucket {hash: move hash,
                             key: move key,
                             value: move value}) => {
                    self.insert_internal(hash, move key, move value);
                }
                None => {}
            }
        }

        /// Inserts the key value pair into the buckets.
        /// Assumes that there will be a bucket.
        /// True if there was no previous entry with that key
        fn insert_internal(&mut self, hash: uint, +k: K, +v: V) -> bool {
            match self.bucket_for_key_with_hash(self.buckets, hash, &k) {
                TableFull => { fail ~"Internal logic error"; }
                FoundHole(idx) => {
                    debug!("insert fresh (%?->%?) at idx %?, hash %?",
                           k, v, idx, hash);
                    self.buckets[idx] = Some(Bucket {hash: hash,
                                                     key: k,
                                                     value: v});
                    self.size += 1;
                    true
                }
                FoundEntry(idx) => {
                    debug!("insert overwrite (%?->%?) at idx %?, hash %?",
                           k, v, idx, hash);
                    self.buckets[idx] = Some(Bucket {hash: hash,
                                                     key: k,
                                                     value: v});
                    false
                }
            }
        }

        fn search(&self,
                  hash: uint,
                  op: fn(x: &Option<Bucket<K,V>>) -> bool) {
            let _ = self.bucket_sequence(hash, |i| op(&self.buckets[i]));
        }
    }

    impl<K:Hash IterBytes Eq,V> LinearMap<K,V> {
        fn insert(&mut self, +k: K, +v: V) -> bool {
            if self.size >= self.resize_at {
                // n.b.: We could also do this after searching, so
                // that we do not resize if this call to insert is
                // simply going to update a key in place.  My sense
                // though is that it's worse to have to search through
                // buckets to find the right spot twice than to just
                // resize in this corner case.
                self.expand();
            }

            let hash = k.hash_keyed(self.k0, self.k1) as uint;
            self.insert_internal(hash, move k, move v)
        }

        fn remove(&mut self, k: &K) -> bool {
            // Removing from an open-addressed hashtable
            // is, well, painful.  The problem is that
            // the entry may lie on the probe path for other
            // entries, so removing it would make you think that
            // those probe paths are empty.
            //
            // To address this we basically have to keep walking,
            // re-inserting entries we find until we reach an empty
            // bucket.  We know we will eventually reach one because
            // we insert one ourselves at the beginning (the removed
            // entry).
            //
            // I found this explanation elucidating:
            // http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf

            let mut idx = match self.bucket_for_key(self.buckets, k) {
                TableFull | FoundHole(_) => return false,
                FoundEntry(idx) => idx
            };

            let len_buckets = self.buckets.len();
            self.buckets[idx] = None;
            idx = self.next_bucket(idx, len_buckets);
            while self.buckets[idx].is_some() {
                let mut bucket = None;
                bucket <-> self.buckets[idx];
                self.insert_opt_bucket(move bucket);
                idx = self.next_bucket(idx, len_buckets);
            }
            self.size -= 1;
            return true;
        }

        fn clear(&mut self) {
            for uint::range(0, self.buckets.len()) |idx| {
                self.buckets[idx] = None;
            }
            self.size = 0;
        }

        pure fn len(&const self) -> uint {
            self.size
        }

        pure fn is_empty(&const self) -> bool {
            self.len() == 0
        }

        fn contains_key(&const self,
                        k: &K) -> bool {
            match self.bucket_for_key(self.buckets, k) {
                FoundEntry(_) => {true}
                TableFull | FoundHole(_) => {false}
            }
        }

        fn find_ref(&self, k: &K) -> Option<&self/V> {
            match self.bucket_for_key(self.buckets, k) {
                FoundEntry(idx) => {
                    match self.buckets[idx] {
                        Some(ref bkt) => {
                            let ptr = unsafe {
                                // FIXME(#3148)--region inference
                                // fails to capture needed deps.
                                // Here, the bucket value is known to
                                // live as long as self, because self
                                // is immutable.  But the region
                                // inference stupidly infers a
                                // lifetime for `ref bkt` that is
                                // shorter than it needs to be.
                                unsafe::copy_lifetime(self, &bkt.value)
                            };
                            Some(ptr)
                        }
                        None => {
                            fail ~"LinearMap::find: internal logic error"
                        }
                    }
                }
                TableFull | FoundHole(_) => {
                    None
                }
            }
        }

        fn each_ref(&self, blk: fn(k: &K, v: &V) -> bool) {
            for vec::each(self.buckets) |slot| {
                let mut broke = false;
                do slot.iter |bucket| {
                    if !blk(&bucket.key, &bucket.value) {
                        broke = true; // FIXME(#3064) just write "break;"
                    }
                }
                if broke { break; }
            }
        }

        fn each_key_ref(&self, blk: fn(k: &K) -> bool) {
            self.each_ref(|k, _v| blk(k))
        }

        fn each_value_ref(&self, blk: fn(v: &V) -> bool) {
            self.each_ref(|_k, v| blk(v))
        }
    }

    impl<K:Hash IterBytes Eq, V: Copy> LinearMap<K,V> {
        fn find(&const self, k: &K) -> Option<V> {
            match self.bucket_for_key(self.buckets, k) {
                FoundEntry(idx) => {
                    // FIXME (#3148): Once we rewrite found_entry, this
                    // failure case won't be necessary
                    match self.buckets[idx] {
                        Some(bkt) => {Some(copy bkt.value)}
                        None => fail ~"LinearMap::find: internal logic error"
                    }
                }
                TableFull | FoundHole(_) => {
                    None
                }
            }
        }

        fn get(&const self, k: &K) -> V {
            let value = self.find(k);
            if value.is_none() {
                fail fmt!("No entry found for key: %?", k);
            }
            option::unwrap(move value)
        }

    }

    impl<K: Hash IterBytes Eq Copy, V: Copy> LinearMap<K,V> {
        fn each(&self, blk: fn(+K,+V) -> bool) {
            self.each_ref(|k,v| blk(copy *k, copy *v));
        }
    }
    impl<K: Hash IterBytes Eq Copy, V> LinearMap<K,V> {
        fn each_key(&self, blk: fn(+K) -> bool) {
            self.each_key_ref(|k| blk(copy *k));
        }
    }
    impl<K: Hash IterBytes Eq, V: Copy> LinearMap<K,V> {
        fn each_value(&self, blk: fn(+V) -> bool) {
            self.each_value_ref(|v| blk(copy *v));
        }
    }
}

#[test]
mod test {

    use linear::LinearMap;

    #[test]
    fn inserts() {
        let mut m = ~LinearMap();
        assert m.insert(1, 2);
        assert m.insert(2, 4);
        assert m.get(&1) == 2;
        assert m.get(&2) == 4;
    }

    #[test]
    fn overwrite() {
        let mut m = ~LinearMap();
        assert m.insert(1, 2);
        assert m.get(&1) == 2;
        assert !m.insert(1, 3);
        assert m.get(&1) == 3;
    }

    #[test]
    fn conflicts() {
        let mut m = linear::linear_map_with_capacity(4);
        assert m.insert(1, 2);
        assert m.insert(5, 3);
        assert m.insert(9, 4);
        assert m.get(&9) == 4;
        assert m.get(&5) == 3;
        assert m.get(&1) == 2;
    }

    #[test]
    fn conflict_remove() {
        let mut m = linear::linear_map_with_capacity(4);
        assert m.insert(1, 2);
        assert m.insert(5, 3);
        assert m.insert(9, 4);
        assert m.remove(&1);
        assert m.get(&9) == 4;
        assert m.get(&5) == 3;
    }

    #[test]
    fn empty() {
        let mut m = linear::linear_map_with_capacity(4);
        assert m.insert(1, 2);
        assert !m.is_empty();
        assert m.remove(&1);
        assert m.is_empty();
    }

    #[test]
    fn iterate() {
        let mut m = linear::linear_map_with_capacity(4);
        for uint::range(0, 32) |i| {
            assert m.insert(i, i*2);
        }
        let mut observed = 0;
        for m.each |k, v| {
            assert v == k*2;
            observed |= (1 << k);
        }
        assert observed == 0xFFFF_FFFF;
    }

    #[test]
    fn find_ref() {
        let mut m = ~LinearMap();
        assert m.find_ref(&1).is_none();
        m.insert(1, 2);
        match m.find_ref(&1) {
            None => fail,
            Some(v) => assert *v == 2
        }
    }
}
<|endoftext|>


<commit_before>use alloc::boxed::Box;

use collections::string::ToString;
use collections::vec::Vec;

use core::intrinsics::{volatile_load, volatile_store};
use core::{cmp, mem, ptr, slice};

use scheduler::context::{self, Context};
use common::debug;
use common::event::MouseEvent;
use common::memory::{self, Memory};
use common::time::{self, Duration};

use drivers::pciconfig::PciConfig;
use drivers::pio::*;

use graphics::display::VBEMODEINFO;

use schemes::KScheme;

use super::UsbMsg;
use super::desc::*;
use super::setup::Setup;

pub struct Uhci {
    pub base: usize,
    pub irq: u8,
}

impl KScheme for Uhci {
    fn on_irq(&mut self, irq: u8) {
        if irq == self.irq {
            // d("UHCI IRQ\n");
        }
    }

    fn on_poll(&mut self) {
    }
}

#[repr(packed)]
#[derive(Copy, Clone, Debug, Default)]
struct Td {
    link_ptr: u32,
    ctrl_sts: u32,
    token: u32,
    buffer: u32,
}

#[repr(packed)]
#[derive(Copy, Clone, Debug, Default)]
struct Qh {
    head_ptr: u32,
    element_ptr: u32,
}

impl Uhci {
    pub unsafe fn new(mut pci: PciConfig) -> Box<Self> {
        pci.flag(4, 4, true); // Bus mastering

        let module = box Uhci {
            base: pci.read(0x20) as usize & 0xFFFFFFF0,
            irq: pci.read(0x3C) as u8 & 0xF,
        };

        module.init();

        return module;
    }

    unsafe fn msg(&self, frame_list: *mut u32, address: u8, msgs: &[UsbMsg]) {
        debugln!("{}: {} Messages", address, msgs.len());

        for msg in msgs.iter() {
            debugln!("{:#?}", msg);
        }

        let mut tds = Vec::new();
        for msg in msgs.iter().rev() {
            let link_ptr = match tds.get(0) {
                Some(td) => (td as *const Td) as u32 | 4,
                None => 1
            };

            match *msg {
                UsbMsg::Setup(setup) => tds.push(Td {
                    link_ptr: link_ptr,
                    ctrl_sts: 1 << 23,
                    token: (mem::size_of::<Setup>() as u32 - 1) << 21 | (address as u32) << 8 | 0x2D,
                    buffer: (&*setup as *const Setup) as u32,
                }),
                UsbMsg::In(ref data) => tds.push(Td {
                    link_ptr: link_ptr,
                    ctrl_sts: 1 << 23,
                    token: ((data.len() as u32 - 1) & 0x7FF) << 21 | (address as u32) << 8 | 0x69,
                    buffer: data.as_ptr() as u32,
                }),
                UsbMsg::Out(ref data) => tds.push(Td {
                    link_ptr: link_ptr,
                    ctrl_sts: 1 << 23,
                    token: ((data.len() as u32 - 1) & 0x7FF) << 21 | (address as u32) << 8 | 0xE1,
                    buffer: data.as_ptr() as u32,
                })
            }
        }

        if ! tds.is_empty() {
            let queue_head = box Qh {
                 head_ptr: 1,
                 element_ptr: (tds.last().unwrap() as *const Td) as u32,
            };

            let frnum = Pio16::new(self.base as u16 + 6);
            let frame = (frnum.read() + 2) & 0x3FF;
            ptr::write(frame_list.offset(frame as isize),
                       (&*queue_head as *const Qh) as u32 | 2);

            for td in tds.iter().rev() {
                debugln!("Start {:#?}", volatile_load(td as *const Td));
                let mut i = 1000000;
                while volatile_load(td as *const Td).ctrl_sts & 1 << 23 == 1 << 23 && i > 0 {
                    i -= 1;
                }
                debugln!("End {:#?}", volatile_load(td as *const Td));
            }

            ptr::write(frame_list.offset(frame as isize), 1);
        }
    }

    unsafe fn set_address(&self, frame_list: *mut u32, address: u8) {
        self.msg(frame_list, 0, &[
            UsbMsg::Setup(&Setup::set_address(address)),
            UsbMsg::In(&mut [])
        ]);
    }

    unsafe fn descriptor(&self,
                         frame_list: *mut u32,
                         address: u8,
                         descriptor_type: u8,
                         descriptor_index: u8,
                         descriptor_ptr: usize,
                         descriptor_len: usize) {
        self.msg(frame_list, address, &[
            UsbMsg::Setup(&Setup::get_descriptor(descriptor_type, descriptor_index, 0, descriptor_len as u16)),
            UsbMsg::In(&mut slice::from_raw_parts_mut(descriptor_ptr as *mut u8, descriptor_len as usize)),
            UsbMsg::Out(&[])
        ]);
    }

    unsafe fn device(&self, frame_list: *mut u32, address: u8) {
        self.set_address(frame_list, address);

        let mut desc_dev = box DeviceDescriptor::default();
        self.descriptor(frame_list,
                        address,
                        DESC_DEV,
                        0,
                        (&mut *desc_dev as *mut DeviceDescriptor) as usize,
                        mem::size_of_val(&*desc_dev));
        debugln!("{:#?}", *desc_dev);

        for configuration in 0..(*desc_dev).configurations {
            let desc_cfg_len = 1023;
            let desc_cfg_buf = memory::alloc(desc_cfg_len) as *mut u8;
            for i in 0..desc_cfg_len as isize {
                ptr::write(desc_cfg_buf.offset(i), 0);
            }
            self.descriptor(frame_list,
                            address,
                            DESC_CFG,
                            configuration,
                            desc_cfg_buf as usize,
                            desc_cfg_len);

            let desc_cfg = ptr::read(desc_cfg_buf as *const ConfigDescriptor);
            debugln!("{:#?}", desc_cfg);

            let mut hid = false;

            let mut i = desc_cfg.length as isize;
            while i < desc_cfg.total_length as isize {
                let length = ptr::read(desc_cfg_buf.offset(i));
                let descriptor_type = ptr::read(desc_cfg_buf.offset(i + 1));
                match descriptor_type {
                    DESC_INT => {
                        let desc_int = ptr::read(desc_cfg_buf.offset(i) as *const InterfaceDescriptor);
                        debugln!("{:#?}", desc_int);
                    }
                    DESC_END => {
                        let desc_end = ptr::read(desc_cfg_buf.offset(i) as *const EndpointDescriptor);
                        debugln!("{:#?}", desc_end);

                        let endpoint = desc_end.address & 0xF;
                        let in_len = desc_end.max_packet_size as usize;

                        let base = self.base as u16;
                        let frnum = base + 0x6;

                        if hid {
                            Context::spawn("kuhci_hid".to_string(), box move || {
                                debugln!("Starting HID driver");

                                let in_ptr = memory::alloc(in_len) as *mut u8;
                                let mut in_td = Memory::<Td>::new(1).unwrap();

                                loop {
                                    for i in 0..in_len as isize {
                                        volatile_store(in_ptr.offset(i), 0);
                                    }

                                    in_td.store(0,
                                               Td {
                                                   link_ptr: 1,
                                                   ctrl_sts: 1 << 25 | 1 << 23,
                                                   token: (in_len as u32 - 1) << 21 |
                                                          (endpoint as u32) << 15 |
                                                          (address as u32) << 8 |
                                                          0x69,
                                                   buffer: in_ptr as u32,
                                               });

                                    let frame = (inw(frnum) + 2) & 0x3FF;
                                    volatile_store(frame_list.offset(frame as isize), in_td.address() as u32);

                                    while in_td.load(0).ctrl_sts & 1 << 23 == 1 << 23 {
                                        context::context_switch(false);
                                    }

                                    volatile_store(frame_list.offset(frame as isize), 1);

                                    if in_td.load(0).ctrl_sts & 0x7FF > 0 {
                                       let buttons = ptr::read(in_ptr.offset(0) as *const u8) as usize;
                                       let x = ptr::read(in_ptr.offset(1) as *const u16) as usize;
                                       let y = ptr::read(in_ptr.offset(3) as *const u16) as usize;

                                       let mode_info = &*VBEMODEINFO;
                                       let mouse_x = (x * mode_info.xresolution as usize) / 32768;
                                       let mouse_y = (y * mode_info.yresolution as usize) / 32768;

                                       let mouse_event = MouseEvent {
                                           x: cmp::max(0, cmp::min(mode_info.xresolution as i32 - 1, mouse_x as i32)),
                                           y: cmp::max(0, cmp::min(mode_info.yresolution as i32 - 1, mouse_y as i32)),
                                           left_button: buttons & 1 == 1,
                                           middle_button: buttons & 4 == 4,
                                           right_button: buttons & 2 == 2,
                                       };
                                       ::env().events.lock().push_back(mouse_event.to_event());
                                    }

                                    Duration::new(0, 10 * time::NANOS_PER_MILLI).sleep();
                                }
                            });
                        }
                    }
                    DESC_HID => {
                        let desc_hid = &*(desc_cfg_buf.offset(i) as *const HIDDescriptor);
                        debugln!("{:#?}", desc_hid);
                        hid = true;
                    }
                    _ => {
                        debug::d("Unknown Descriptor Length ");
                        debug::dd(length as usize);
                        debug::d(" Type ");
                        debug::dh(descriptor_type as usize);
                        debug::dl();
                    }
                }
                i += length as isize;
            }

            memory::unalloc(desc_cfg_buf as usize);
        }
    }

    pub unsafe fn init(&self) {
        debug::d("UHCI on: ");
        debug::dh(self.base);
        debug::d(", IRQ: ");
        debug::dbh(self.irq);

        let base = self.base as u16;
        let usbcmd = base;
        let usbsts = base + 02;
        let usbintr = base + 0x4;
        let frnum = base + 0x6;
        let flbaseadd = base + 0x8;
        let portsc1 = base + 0x10;
        let portsc2 = base + 0x12;

        debug::d(" CMD ");
        debug::dh(inw(usbcmd) as usize);
        outw(usbcmd, 1 << 2 | 1 << 1);
        debug::d(" to ");
        debug::dh(inw(usbcmd) as usize);

        outw(usbcmd, 0);
        debug::d(" to ");
        debug::dh(inw(usbcmd) as usize);

        debug::d(" STS ");
        debug::dh(inw(usbsts) as usize);

        debug::d(" INTR ");
        debug::dh(inw(usbintr) as usize);

        debug::d(" FRNUM ");
        debug::dh(inw(frnum) as usize);
        outw(frnum, 0);
        debug::d(" to ");
        debug::dh(inw(frnum) as usize);

        debug::d(" FLBASEADD ");
        debug::dh(ind(flbaseadd) as usize);
        let frame_list = memory::alloc(1024 * 4) as *mut u32;
        for i in 0..1024 {
            ptr::write(frame_list.offset(i), 1);
        }
        outd(flbaseadd, frame_list as u32);
        debug::d(" to ");
        debug::dh(ind(flbaseadd) as usize);

        debug::d(" CMD ");
        debug::dh(inw(usbcmd) as usize);
        outw(usbcmd, 1);
        debug::d(" to ");
        debug::dh(inw(usbcmd) as usize);

        debug::dl();

        {
            debug::d(" PORTSC1 ");
            debug::dh(inw(portsc1) as usize);

            outw(portsc1, 1 << 9);
            debug::d(" to ");
            debug::dh(inw(portsc1) as usize);

            outw(portsc1, 0);
            debug::d(" to ");
            debug::dh(inw(portsc1) as usize);

            debug::dl();

            if inw(portsc1) & 1 == 1 {
                debug::d(" Device Found ");
                debug::dh(inw(portsc1) as usize);

                outw(portsc1, 4);
                debug::d(" to ");
                debug::dh(inw(portsc1) as usize);
                debug::dl();

                self.device(frame_list, 1);
            }
        }

        {
            debug::d(" PORTSC2 ");
            debug::dh(inw(portsc2) as usize);

            outw(portsc2, 1 << 9);
            debug::d(" to ");
            debug::dh(inw(portsc2) as usize);

            outw(portsc2, 0);
            debug::d(" to ");
            debug::dh(inw(portsc2) as usize);

            debug::dl();

            if inw(portsc2) & 1 == 1 {
                debug::d(" Device Found ");
                debug::dh(inw(portsc2) as usize);

                outw(portsc2, 4);
                debug::d(" to ");
                debug::dh(inw(portsc2) as usize);
                debug::dl();

                self.device(frame_list, 2);
            }
        }
    }
}
<commit_msg>Cleanup HID<commit_after>use alloc::boxed::Box;

use collections::string::ToString;
use collections::vec::Vec;

use core::intrinsics::volatile_load;
use core::{cmp, mem, ptr, slice};

use scheduler::context::{context_switch, Context};
use common::debug;
use common::event::MouseEvent;
use common::memory::{self, Memory};
use common::time::{self, Duration};

use drivers::pciconfig::PciConfig;
use drivers::pio::*;

use graphics::display::VBEMODEINFO;

use schemes::KScheme;

use super::UsbMsg;
use super::desc::*;
use super::setup::Setup;

pub struct Uhci {
    pub base: usize,
    pub irq: u8,
    pub frame_list: Memory<u32>,
}

impl KScheme for Uhci {
    fn on_irq(&mut self, irq: u8) {
        if irq == self.irq {
            // d("UHCI IRQ\n");
        }
    }

    fn on_poll(&mut self) {
    }
}

#[repr(packed)]
#[derive(Copy, Clone, Debug, Default)]
struct Td {
    link_ptr: u32,
    ctrl_sts: u32,
    token: u32,
    buffer: u32,
}

#[repr(packed)]
#[derive(Copy, Clone, Debug, Default)]
struct Qh {
    head_ptr: u32,
    element_ptr: u32,
}

impl Uhci {
    pub unsafe fn new(mut pci: PciConfig) -> Box<Self> {
        pci.flag(4, 4, true); // Bus mastering

        let mut module = box Uhci {
            base: pci.read(0x20) as usize & 0xFFFFFFF0,
            irq: pci.read(0x3C) as u8 & 0xF,
            frame_list: Memory::new(1024).unwrap(),
        };

        module.init();

        return module;
    }

    fn msg(&mut self, address: u8, endpoint: u8, msgs: &[UsbMsg]) -> usize {
        let mut tds = Vec::new();
        for msg in msgs.iter().rev() {
            let link_ptr = match tds.last() {
                Some(td) => (td as *const Td) as u32 | 4,
                None => 1
            };

            match *msg {
                UsbMsg::Setup(setup) => tds.push(Td {
                    link_ptr: link_ptr,
                    ctrl_sts: 1 << 23,
                    token: (mem::size_of::<Setup>() as u32 - 1) << 21 | (endpoint as u32) << 15 | (address as u32) << 8 | 0x2D,
                    buffer: (&*setup as *const Setup) as u32,
                }),
                UsbMsg::In(ref data) => tds.push(Td {
                    link_ptr: link_ptr,
                    ctrl_sts: 1 << 23,
                    token: ((data.len() as u32 - 1) & 0x7FF) << 21 | (endpoint as u32) << 15 | (address as u32) << 8 | 0x69,
                    buffer: data.as_ptr() as u32,
                }),
                UsbMsg::Out(ref data) => tds.push(Td {
                    link_ptr: link_ptr,
                    ctrl_sts: 1 << 23,
                    token: ((data.len() as u32 - 1) & 0x7FF) << 21 | (endpoint as u32) << 15 | (address as u32) << 8 | 0xE1,
                    buffer: data.as_ptr() as u32,
                })
            }
        }

        let mut count = 0;

        if tds.len() > 1 {
            let queue_head = box Qh {
                 head_ptr: 1,
                 element_ptr: (tds.last().unwrap() as *const Td) as u32,
            };

            let frnum = Pio16::new(self.base as u16 + 6);
            let frame = (unsafe { frnum.read() } + 1) & 0x3FF;
            unsafe { self.frame_list.write(frame as usize, (&*queue_head as *const Qh) as u32 | 2) };

            for td in tds.iter().rev() {
                while unsafe { volatile_load(td as *const Td).ctrl_sts } & 1 << 23 == 1 << 23 {
                    unsafe { context_switch(false) };
                }
                count += (unsafe { volatile_load(td as *const Td).ctrl_sts } & 0x7FF) as usize;
            }

            unsafe { self.frame_list.write(frame as usize, 1) };
        } else if tds.len() == 1 {
            tds[0].ctrl_sts |= 1 << 25;

            let frnum = Pio16::new(self.base as u16 + 6);
            let frame = (unsafe { frnum.read() } + 1) & 0x3FF;
            unsafe { self.frame_list.write(frame as usize, (&tds[0] as *const Td) as u32) };

            for td in tds.iter().rev() {
                while unsafe { volatile_load(td as *const Td).ctrl_sts } & 1 << 23 == 1 << 23 {
                    unsafe { context_switch(false) };
                }
                count += (unsafe { volatile_load(td as *const Td).ctrl_sts } & 0x7FF) as usize;
            }

            unsafe { self.frame_list.write(frame as usize, 1) };
        }

        count
    }

    fn descriptor(&mut self,
                         address: u8,
                         descriptor_type: u8,
                         descriptor_index: u8,
                         descriptor_ptr: usize,
                         descriptor_len: usize) {
        self.msg(address, 0, &[
            UsbMsg::Setup(&Setup::get_descriptor(descriptor_type, descriptor_index, 0, descriptor_len as u16)),
            UsbMsg::In(&mut unsafe { slice::from_raw_parts_mut(descriptor_ptr as *mut u8, descriptor_len as usize) }),
            UsbMsg::Out(&[])
        ]);
    }

    unsafe fn device(&mut self, address: u8) {
        self.msg(0, 0, &[
            UsbMsg::Setup(&Setup::set_address(address)),
            UsbMsg::In(&mut [])
        ]);

        let mut desc_dev = box DeviceDescriptor::default();
        self.descriptor(address,
                        DESC_DEV,
                        0,
                        (&mut *desc_dev as *mut DeviceDescriptor) as usize,
                        mem::size_of_val(&*desc_dev));
        debugln!("{:#?}", *desc_dev);

        for configuration in 0..(*desc_dev).configurations {
            let desc_cfg_len = 1023;
            let desc_cfg_buf = memory::alloc(desc_cfg_len) as *mut u8;
            for i in 0..desc_cfg_len as isize {
                ptr::write(desc_cfg_buf.offset(i), 0);
            }
            self.descriptor(address,
                            DESC_CFG,
                            configuration,
                            desc_cfg_buf as usize,
                            desc_cfg_len);

            let desc_cfg = ptr::read(desc_cfg_buf as *const ConfigDescriptor);
            debugln!("{:#?}", desc_cfg);

            let mut hid = false;

            let mut i = desc_cfg.length as isize;
            while i < desc_cfg.total_length as isize {
                let length = ptr::read(desc_cfg_buf.offset(i));
                let descriptor_type = ptr::read(desc_cfg_buf.offset(i + 1));
                match descriptor_type {
                    DESC_INT => {
                        let desc_int = ptr::read(desc_cfg_buf.offset(i) as *const InterfaceDescriptor);
                        debugln!("{:#?}", desc_int);
                    }
                    DESC_END => {
                        let desc_end = ptr::read(desc_cfg_buf.offset(i) as *const EndpointDescriptor);
                        debugln!("{:#?}", desc_end);

                        let endpoint = desc_end.address & 0xF;
                        let in_len = desc_end.max_packet_size as usize;

                        if hid {
                            let this = self as *mut Uhci;
                            Context::spawn("kuhci_hid".to_string(), box move || {
                                debugln!("Starting HID driver");

                                let in_ptr = memory::alloc(in_len) as *mut u8;

                                loop {
                                    for i in 0..in_len as isize {
                                        ptr::write(in_ptr.offset(i), 0);
                                    }

                                    if (*this).msg(address, endpoint, &[
                                        UsbMsg::In(&mut slice::from_raw_parts_mut(in_ptr, in_len))
                                    ]) > 0 {
                                        let buttons = ptr::read(in_ptr.offset(0) as *const u8) as usize;
                                        let x = ptr::read(in_ptr.offset(1) as *const u16) as usize;
                                        let y = ptr::read(in_ptr.offset(3) as *const u16) as usize;

                                        let mode_info = &*VBEMODEINFO;
                                        let mouse_x = (x * mode_info.xresolution as usize) / 32768;
                                        let mouse_y = (y * mode_info.yresolution as usize) / 32768;

                                        let mouse_event = MouseEvent {
                                            x: cmp::max(0, cmp::min(mode_info.xresolution as i32 - 1, mouse_x as i32)),
                                            y: cmp::max(0, cmp::min(mode_info.yresolution as i32 - 1, mouse_y as i32)),
                                            left_button: buttons & 1 == 1,
                                            middle_button: buttons & 4 == 4,
                                            right_button: buttons & 2 == 2,
                                        };
                                        ::env().events.lock().push_back(mouse_event.to_event());
                                    }

                                    Duration::new(0, 10 * time::NANOS_PER_MILLI).sleep();
                                }
                            });
                        }
                    }
                    DESC_HID => {
                        let desc_hid = &*(desc_cfg_buf.offset(i) as *const HIDDescriptor);
                        debugln!("{:#?}", desc_hid);
                        hid = true;
                    }
                    _ => {
                        debugln!("Unknown Descriptor Length {} Type {:X}", length as usize, descriptor_type);
                    }
                }
                i += length as isize;
            }

            memory::unalloc(desc_cfg_buf as usize);
        }
    }

    pub unsafe fn init(&mut self) {
        debugln!("UHCI on: {:X}, IRQ: {:X}", self.base, self.irq);

        let base = self.base as u16;
        let usbcmd = base;
        let usbsts = base + 02;
        let usbintr = base + 0x4;
        let frnum = base + 0x6;
        let flbaseadd = base + 0x8;
        let portsc1 = base + 0x10;
        let portsc2 = base + 0x12;

        debug::d(" CMD ");
        debug::dh(inw(usbcmd) as usize);
        outw(usbcmd, 1 << 2 | 1 << 1);
        debug::d(" to ");
        debug::dh(inw(usbcmd) as usize);

        outw(usbcmd, 0);
        debug::d(" to ");
        debug::dh(inw(usbcmd) as usize);

        debug::d(" STS ");
        debug::dh(inw(usbsts) as usize);

        debug::d(" INTR ");
        debug::dh(inw(usbintr) as usize);

        debug::d(" FRNUM ");
        debug::dh(inw(frnum) as usize);
        outw(frnum, 0);
        debug::d(" to ");
        debug::dh(inw(frnum) as usize);

        debug::d(" FLBASEADD ");
        debug::dh(ind(flbaseadd) as usize);
        for i in 0..1024 {
            self.frame_list.write(i, 1);
        }
        outd(flbaseadd, self.frame_list.address() as u32);
        debug::d(" to ");
        debug::dh(ind(flbaseadd) as usize);

        debug::d(" CMD ");
        debug::dh(inw(usbcmd) as usize);
        outw(usbcmd, 1);
        debug::d(" to ");
        debug::dh(inw(usbcmd) as usize);

        debug::dl();

        {
            debug::d(" PORTSC1 ");
            debug::dh(inw(portsc1) as usize);

            outw(portsc1, 1 << 9);
            debug::d(" to ");
            debug::dh(inw(portsc1) as usize);

            outw(portsc1, 0);
            debug::d(" to ");
            debug::dh(inw(portsc1) as usize);

            debug::dl();

            if inw(portsc1) & 1 == 1 {
                debug::d(" Device Found ");
                debug::dh(inw(portsc1) as usize);

                outw(portsc1, 4);
                debug::d(" to ");
                debug::dh(inw(portsc1) as usize);
                debug::dl();

                self.device(1);
            }
        }

        {
            debug::d(" PORTSC2 ");
            debug::dh(inw(portsc2) as usize);

            outw(portsc2, 1 << 9);
            debug::d(" to ");
            debug::dh(inw(portsc2) as usize);

            outw(portsc2, 0);
            debug::d(" to ");
            debug::dh(inw(portsc2) as usize);

            debug::dl();

            if inw(portsc2) & 1 == 1 {
                debug::d(" Device Found ");
                debug::dh(inw(portsc2) as usize);

                outw(portsc2, 4);
                debug::d(" to ");
                debug::dh(inw(portsc2) as usize);
                debug::dl();

                self.device(2);
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Shared type<commit_after>use core::prelude::*;
use core::cell::UnsafeCell;

// Should T be `Sync`?
pub struct Shared<T> {
    value: UnsafeCell<T>
}

impl<T> Shared<T> {
    pub fn new(value: T) -> Shared<T> {
        Shared {
            value: UnsafeCell::new(value)
        }
    }

    pub fn borrow_mut(&self) -> &mut T {
        unsafe { &mut *self.value.get() }
    }
}

<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;
use std::fs::File as FSFile;
use std::ops::Deref;
use std::io::Write;

pub mod path;
pub mod file;
pub mod parser;
pub mod json;

use module::Module;
use runtime::Runtime;
use storage::file::File;
use storage::file::id::FileID;
use storage::file::id_type::FileIDType;
use storage::file::hash::FileHash;
use storage::parser::{FileHeaderParser, Parser, ParserError};
use storage::file::header::data::FileHeaderData;

type Cache = HashMap<FileID, Rc<RefCell<File>>>;

pub struct Store {
    storepath: String,
    cache : RefCell<Cache>,
}

impl Store {

    pub fn new(storepath: String) -> Store {
        Store {
            storepath: storepath,
            cache: RefCell::new(HashMap::new()),
        }
    }

    fn put_in_cache(&self, f: File) -> FileID {
        let res = f.id().clone();
        self.cache.borrow_mut().insert(f.id().clone(), Rc::new(RefCell::new(f)));
        res
    }

    pub fn new_file(&self, module: &Module)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: FileHeaderData::Null,
            data: String::from(""),
            id: self.get_new_file_id(),
        };

        debug!("Create new File object: {:?}", &f);
        self.put_in_cache(f)
    }

    pub fn new_file_from_parser_result(&self,
                                       module: &Module,
                                       id: FileID,
                                       header: FileHeaderData,
                                       data: String)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: header,
            data: data,
            id: id,
        };
        debug!("Create new File object from parser result: {:?}", f);
        self.put_in_cache(f)
    }

    pub fn new_file_with_header(&self,
                                module: &Module,
                                h: FileHeaderData)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: h,
            data: String::from(""),
            id: self.get_new_file_id(),
        };
        debug!("Create new File object with header: {:?}", f);
        self.put_in_cache(f)
    }

    pub fn new_file_with_data(&self, module: &Module, d: String)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: FileHeaderData::Null,
            data: d,
            id: self.get_new_file_id(),
        };
        debug!("Create new File object with data: {:?}", f);
        self.put_in_cache(f)
    }

    pub fn new_file_with_content(&self,
                                 module: &Module,
                                 h: FileHeaderData,
                                 d: String)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: h,
            data: d,
            id: self.get_new_file_id(),
        };
        debug!("Create new File object with content: {:?}", f);
        self.put_in_cache(f)
    }

    pub fn persist<HP>(&self,
                       p: &Parser<HP>,
                       f: Rc<RefCell<File>>) -> bool
        where HP: FileHeaderParser
    {
        let file = f.deref().borrow();
        let text = p.write(file.contents());
        if text.is_err() {
            error!("Error: {}", text.err().unwrap());
            return false;
        }

        let path = {
            let ids : String = file.id().clone().into();
            format!("{}/{}-{}.imag", self.storepath, file.owning_module_name, ids)
        };

        self.ensure_store_path_exists();

        FSFile::create(&path).map(|mut fsfile| {
            fsfile.write_all(&text.unwrap().clone().into_bytes()[..])
        }).map_err(|writeerr|  {
            debug!("Could not create file at '{}'", path);
        }).and(Ok(true)).unwrap()
    }

    fn ensure_store_path_exists(&self) {
        use std::fs::create_dir_all;
        use std::process::exit;

        create_dir_all(&self.storepath).unwrap_or_else(|e| {
            error!("Could not create store: '{}'", self.storepath);
            error!("Error                 : '{}'", e);
            error!("Killing myself now");
            exit(1);
        })
    }

    pub fn load(&self, id: &FileID) -> Option<Rc<RefCell<File>>> {
        debug!("Loading '{:?}'", id);
        self.cache.borrow().get(id).cloned()
    }

    pub fn remove(&self, id: FileID) -> bool {
        use std::fs::remove_file;

        self.cache
            .borrow_mut()
            .remove(&id)
            .map(|file| {
                let idstr : String = id.into();
                let path = format!("{}/{}-{}.imag",
                                   self.storepath,
                                   file.deref().borrow().owner_name(),
                                   idstr);
                remove_file(path).is_ok()
            })
            .unwrap_or(false)
    }

    fn get_new_file_id(&self) -> FileID {
        use uuid::Uuid;
        let hash = FileHash::from(Uuid::new_v4().to_hyphenated_string());
        FileID::new(FileIDType::UUID, hash)
    }

}
<commit_msg>Add Store::load_in_cache(... FileID)<commit_after>use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;
use std::fs::File as FSFile;
use std::ops::Deref;
use std::io::Write;
use std::io::Read;

pub mod path;
pub mod file;
pub mod parser;
pub mod json;

use module::Module;
use runtime::Runtime;
use storage::file::File;
use storage::file::id::FileID;
use storage::file::id_type::FileIDType;
use storage::file::hash::FileHash;
use storage::parser::{FileHeaderParser, Parser, ParserError};
use storage::file::header::data::FileHeaderData;

type Cache = HashMap<FileID, Rc<RefCell<File>>>;

pub struct Store {
    storepath: String,
    cache : RefCell<Cache>,
}

impl Store {

    pub fn new(storepath: String) -> Store {
        Store {
            storepath: storepath,
            cache: RefCell::new(HashMap::new()),
        }
    }

    fn put_in_cache(&self, f: File) -> FileID {
        let res = f.id().clone();
        self.cache.borrow_mut().insert(f.id().clone(), Rc::new(RefCell::new(f)));
        res
    }

    pub fn load_in_cache<HP>(&self, m: &Module, parser: &Parser<HP>, id: FileID)
        -> Option<Rc<RefCell<File>>>
        where HP: FileHeaderParser
    {
        let idstr : String = id.clone().into();
        let path = format!("{}/{}-{}.imag", self.storepath, m.name(), idstr);
        let mut string = String::new();

        FSFile::open(&path).map(|mut file| {
            file.read_to_string(&mut string)
                .map_err(|e| error!("Failed reading file: '{}'", path));
        });

        parser.read(string).map(|(header, data)| {
            self.new_file_from_parser_result(m, id.clone(), header, data);
        });

        self.load(&id)
    }

    pub fn new_file(&self, module: &Module)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: FileHeaderData::Null,
            data: String::from(""),
            id: self.get_new_file_id(),
        };

        debug!("Create new File object: {:?}", &f);
        self.put_in_cache(f)
    }

    pub fn new_file_from_parser_result(&self,
                                       module: &Module,
                                       id: FileID,
                                       header: FileHeaderData,
                                       data: String)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: header,
            data: data,
            id: id,
        };
        debug!("Create new File object from parser result: {:?}", f);
        self.put_in_cache(f)
    }

    pub fn new_file_with_header(&self,
                                module: &Module,
                                h: FileHeaderData)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: h,
            data: String::from(""),
            id: self.get_new_file_id(),
        };
        debug!("Create new File object with header: {:?}", f);
        self.put_in_cache(f)
    }

    pub fn new_file_with_data(&self, module: &Module, d: String)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: FileHeaderData::Null,
            data: d,
            id: self.get_new_file_id(),
        };
        debug!("Create new File object with data: {:?}", f);
        self.put_in_cache(f)
    }

    pub fn new_file_with_content(&self,
                                 module: &Module,
                                 h: FileHeaderData,
                                 d: String)
        -> FileID
    {
        let f = File {
            owning_module_name: module.name(),
            header: h,
            data: d,
            id: self.get_new_file_id(),
        };
        debug!("Create new File object with content: {:?}", f);
        self.put_in_cache(f)
    }

    pub fn persist<HP>(&self,
                       p: &Parser<HP>,
                       f: Rc<RefCell<File>>) -> bool
        where HP: FileHeaderParser
    {
        let file = f.deref().borrow();
        let text = p.write(file.contents());
        if text.is_err() {
            error!("Error: {}", text.err().unwrap());
            return false;
        }

        let path = {
            let ids : String = file.id().clone().into();
            format!("{}/{}-{}.imag", self.storepath, file.owning_module_name, ids)
        };

        self.ensure_store_path_exists();

        FSFile::create(&path).map(|mut fsfile| {
            fsfile.write_all(&text.unwrap().clone().into_bytes()[..])
        }).map_err(|writeerr|  {
            debug!("Could not create file at '{}'", path);
        }).and(Ok(true)).unwrap()
    }

    fn ensure_store_path_exists(&self) {
        use std::fs::create_dir_all;
        use std::process::exit;

        create_dir_all(&self.storepath).unwrap_or_else(|e| {
            error!("Could not create store: '{}'", self.storepath);
            error!("Error                 : '{}'", e);
            error!("Killing myself now");
            exit(1);
        })
    }

    pub fn load(&self, id: &FileID) -> Option<Rc<RefCell<File>>> {
        debug!("Loading '{:?}'", id);
        self.cache.borrow().get(id).cloned()
    }

    pub fn remove(&self, id: FileID) -> bool {
        use std::fs::remove_file;

        self.cache
            .borrow_mut()
            .remove(&id)
            .map(|file| {
                let idstr : String = id.into();
                let path = format!("{}/{}-{}.imag",
                                   self.storepath,
                                   file.deref().borrow().owner_name(),
                                   idstr);
                remove_file(path).is_ok()
            })
            .unwrap_or(false)
    }

    fn get_new_file_id(&self) -> FileID {
        use uuid::Uuid;
        let hash = FileHash::from(Uuid::new_v4().to_hyphenated_string());
        FileID::new(FileIDType::UUID, hash)
    }

}
<|endoftext|>


<commit_before><commit_msg>Remove Redundant Pipeline Logic<commit_after><|endoftext|>


<commit_before>// Copyright 2012-2014 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.

use rustc::session::Session;

use generated_code;

use std::cell::Cell;

use syntax::parse::lexer::{self, StringReader};
use syntax::parse::token::{self, Token};
use syntax::symbol::keywords;
use syntax_pos::*;

#[derive(Clone)]
pub struct SpanUtils<'a> {
    pub sess: &'a Session,
    // FIXME given that we clone SpanUtils all over the place, this err_count is
    // probably useless and any logic relying on it is bogus.
    pub err_count: Cell<isize>,
}

impl<'a> SpanUtils<'a> {
    pub fn new(sess: &'a Session) -> SpanUtils<'a> {
        SpanUtils {
            sess,
            err_count: Cell::new(0),
        }
    }

    pub fn make_filename_string(&self, file: &SourceFile) -> String {
        match &file.name {
            FileName::Real(path) if !path.is_absolute() && !file.name_was_remapped => {
                self.sess.working_dir.0
                    .join(&path)
                    .display()
                    .to_string()
            },
            // If the file name is already remapped, we assume the user
            // configured it the way they wanted to, so use that directly
            filename => filename.to_string()
        }
    }

    pub fn snippet(&self, span: Span) -> String {
        match self.sess.source_map().span_to_snippet(span) {
            Ok(s) => s,
            Err(_) => String::new(),
        }
    }

    pub fn retokenise_span(&self, span: Span) -> StringReader<'a> {
        lexer::StringReader::retokenize(&self.sess.parse_sess, span)
    }

    // Re-parses a path and returns the span for the last identifier in the path
    pub fn span_for_last_ident(&self, span: Span) -> Option<Span> {
        let mut result = None;

        let mut toks = self.retokenise_span(span);
        let mut bracket_count = 0;
        loop {
            let ts = toks.real_token();
            if ts.tok == token::Eof {
                return result;
            }
            if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) {
                result = Some(ts.sp);
            }

            bracket_count += match ts.tok {
                token::Lt => 1,
                token::Gt => -1,
                token::BinOp(token::Shr) => -2,
                _ => 0,
            }
        }
    }

    // Return the span for the first identifier in the path.
    pub fn span_for_first_ident(&self, span: Span) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        let mut bracket_count = 0;
        loop {
            let ts = toks.real_token();
            if ts.tok == token::Eof {
                return None;
            }
            if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) {
                return Some(ts.sp);
            }

            bracket_count += match ts.tok {
                token::Lt => 1,
                token::Gt => -1,
                token::BinOp(token::Shr) => -2,
                _ => 0,
            }
        }
    }

    // Return the span for the last ident before a `<` and outside any
    // angle brackets, or the last span.
    pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        let mut prev = toks.real_token();
        let mut result = None;

        // We keep track of the following two counts - the depth of nesting of
        // angle brackets, and the depth of nesting of square brackets. For the
        // angle bracket count, we only count tokens which occur outside of any
        // square brackets (i.e. bracket_count == 0). The intuition here is
        // that we want to count angle brackets in the type, but not any which
        // could be in expression context (because these could mean 'less than',
        // etc.).
        let mut angle_count = 0;
        let mut bracket_count = 0;
        loop {
            let next = toks.real_token();

            if (next.tok == token::Lt || next.tok == token::Colon) && angle_count == 0
                && bracket_count == 0 && prev.tok.is_ident()
            {
                result = Some(prev.sp);
            }

            if bracket_count == 0 {
                angle_count += match prev.tok {
                    token::Lt => 1,
                    token::Gt => -1,
                    token::BinOp(token::Shl) => 2,
                    token::BinOp(token::Shr) => -2,
                    _ => 0,
                };
            }

            bracket_count += match prev.tok {
                token::OpenDelim(token::Bracket) => 1,
                token::CloseDelim(token::Bracket) => -1,
                _ => 0,
            };

            if next.tok == token::Eof {
                break;
            }
            prev = next;
        }
        #[cfg(debug_assertions)] {
            if angle_count != 0 || bracket_count != 0 {
                let loc = self.sess.source_map().lookup_char_pos(span.lo());
                span_bug!(
                    span,
                    "Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}",
                    self.snippet(span),
                    loc.file.name,
                    loc.line
                );
            }
        }
        if result.is_none() && prev.tok.is_ident() {
            return Some(prev.sp);
        }
        result
    }

    pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        let mut prev = toks.real_token();
        loop {
            if prev.tok == token::Eof {
                return None;
            }
            let next = toks.real_token();
            if next.tok == tok {
                return Some(prev.sp);
            }
            prev = next;
        }
    }

    pub fn sub_span_of_token(&self, span: Span, tok: Token) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        loop {
            let next = toks.real_token();
            if next.tok == token::Eof {
                return None;
            }
            if next.tok == tok {
                return Some(next.sp);
            }
        }
    }

    pub fn sub_span_after_keyword(&self, span: Span, keyword: keywords::Keyword) -> Option<Span> {
        self.sub_span_after(span, |t| t.is_keyword(keyword))
    }

    fn sub_span_after<F: Fn(Token) -> bool>(&self, span: Span, f: F) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        loop {
            let ts = toks.real_token();
            if ts.tok == token::Eof {
                return None;
            }
            if f(ts.tok) {
                let ts = toks.real_token();
                if ts.tok == token::Eof {
                    return None;
                } else {
                    return Some(ts.sp);
                }
            }
        }
    }

    // // Return the name for a macro definition (identifier after first `!`)
    // pub fn span_for_macro_def_name(&self, span: Span) -> Option<Span> {
    //     let mut toks = self.retokenise_span(span);
    //     loop {
    //         let ts = toks.real_token();
    //         if ts.tok == token::Eof {
    //             return None;
    //         }
    //         if ts.tok == token::Not {
    //             let ts = toks.real_token();
    //             if ts.tok.is_ident() {
    //                 return Some(ts.sp);
    //             } else {
    //                 return None;
    //             }
    //         }
    //     }
    // }

    // // Return the name for a macro use (identifier before first `!`).
    // pub fn span_for_macro_use_name(&self, span:Span) -> Option<Span> {
    //     let mut toks = self.retokenise_span(span);
    //     let mut prev = toks.real_token();
    //     loop {
    //         if prev.tok == token::Eof {
    //             return None;
    //         }
    //         let ts = toks.real_token();
    //         if ts.tok == token::Not {
    //             if prev.tok.is_ident() {
    //                 return Some(prev.sp);
    //             } else {
    //                 return None;
    //             }
    //         }
    //         prev = ts;
    //     }
    // }

    /// Return true if the span is generated code, and
    /// it is not a subspan of the root callsite.
    ///
    /// Used to filter out spans of minimal value,
    /// such as references to macro internal variables.
    pub fn filter_generated(&self, sub_span: Option<Span>, parent: Span) -> bool {
        if !generated_code(parent) {
            // Edge case - this occurs on generated code with incorrect expansion info.
            return sub_span.is_none()
        }
        // If sub_span is none, filter out generated code.
        let sub_span = match sub_span {
            Some(ss) => ss,
            None => return true,
        };

        //If the span comes from a fake source_file, filter it.
        if !self.sess
            .source_map()
            .lookup_char_pos(parent.lo())
            .file
            .is_real_file()
        {
            return true;
        }

        // Otherwise, a generated span is deemed invalid if it is not a sub-span of the root
        // callsite. This filters out macro internal variables and most malformed spans.
        !parent.source_callsite().contains(sub_span)
    }
}

macro_rules! filter {
    ($util: expr, $span: expr, $parent: expr, None) => {
        if $util.filter_generated($span, $parent) {
            return None;
        }
    };
    ($util: expr, $span: ident, $parent: expr) => {
        if $util.filter_generated($span, $parent) {
            return;
        }
    };
}
<commit_msg>Also remap absolute source names in save-analysis<commit_after>// Copyright 2012-2014 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.

use rustc::session::Session;

use generated_code;

use std::cell::Cell;

use syntax::parse::lexer::{self, StringReader};
use syntax::parse::token::{self, Token};
use syntax::symbol::keywords;
use syntax_pos::*;

#[derive(Clone)]
pub struct SpanUtils<'a> {
    pub sess: &'a Session,
    // FIXME given that we clone SpanUtils all over the place, this err_count is
    // probably useless and any logic relying on it is bogus.
    pub err_count: Cell<isize>,
}

impl<'a> SpanUtils<'a> {
    pub fn new(sess: &'a Session) -> SpanUtils<'a> {
        SpanUtils {
            sess,
            err_count: Cell::new(0),
        }
    }

    pub fn make_filename_string(&self, file: &SourceFile) -> String {
        match &file.name {
            FileName::Real(path) if !file.name_was_remapped => {
                if path.is_absolute() {
                    self.sess.source_map().path_mapping()
                        .map_prefix(path.clone()).0
                        .display()
                        .to_string()
                } else {
                    self.sess.working_dir.0
                        .join(&path)
                        .display()
                        .to_string()
                }
            },
            // If the file name is already remapped, we assume the user
            // configured it the way they wanted to, so use that directly
            filename => filename.to_string()
        }
    }

    pub fn snippet(&self, span: Span) -> String {
        match self.sess.source_map().span_to_snippet(span) {
            Ok(s) => s,
            Err(_) => String::new(),
        }
    }

    pub fn retokenise_span(&self, span: Span) -> StringReader<'a> {
        lexer::StringReader::retokenize(&self.sess.parse_sess, span)
    }

    // Re-parses a path and returns the span for the last identifier in the path
    pub fn span_for_last_ident(&self, span: Span) -> Option<Span> {
        let mut result = None;

        let mut toks = self.retokenise_span(span);
        let mut bracket_count = 0;
        loop {
            let ts = toks.real_token();
            if ts.tok == token::Eof {
                return result;
            }
            if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) {
                result = Some(ts.sp);
            }

            bracket_count += match ts.tok {
                token::Lt => 1,
                token::Gt => -1,
                token::BinOp(token::Shr) => -2,
                _ => 0,
            }
        }
    }

    // Return the span for the first identifier in the path.
    pub fn span_for_first_ident(&self, span: Span) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        let mut bracket_count = 0;
        loop {
            let ts = toks.real_token();
            if ts.tok == token::Eof {
                return None;
            }
            if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) {
                return Some(ts.sp);
            }

            bracket_count += match ts.tok {
                token::Lt => 1,
                token::Gt => -1,
                token::BinOp(token::Shr) => -2,
                _ => 0,
            }
        }
    }

    // Return the span for the last ident before a `<` and outside any
    // angle brackets, or the last span.
    pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        let mut prev = toks.real_token();
        let mut result = None;

        // We keep track of the following two counts - the depth of nesting of
        // angle brackets, and the depth of nesting of square brackets. For the
        // angle bracket count, we only count tokens which occur outside of any
        // square brackets (i.e. bracket_count == 0). The intuition here is
        // that we want to count angle brackets in the type, but not any which
        // could be in expression context (because these could mean 'less than',
        // etc.).
        let mut angle_count = 0;
        let mut bracket_count = 0;
        loop {
            let next = toks.real_token();

            if (next.tok == token::Lt || next.tok == token::Colon) && angle_count == 0
                && bracket_count == 0 && prev.tok.is_ident()
            {
                result = Some(prev.sp);
            }

            if bracket_count == 0 {
                angle_count += match prev.tok {
                    token::Lt => 1,
                    token::Gt => -1,
                    token::BinOp(token::Shl) => 2,
                    token::BinOp(token::Shr) => -2,
                    _ => 0,
                };
            }

            bracket_count += match prev.tok {
                token::OpenDelim(token::Bracket) => 1,
                token::CloseDelim(token::Bracket) => -1,
                _ => 0,
            };

            if next.tok == token::Eof {
                break;
            }
            prev = next;
        }
        #[cfg(debug_assertions)] {
            if angle_count != 0 || bracket_count != 0 {
                let loc = self.sess.source_map().lookup_char_pos(span.lo());
                span_bug!(
                    span,
                    "Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}",
                    self.snippet(span),
                    loc.file.name,
                    loc.line
                );
            }
        }
        if result.is_none() && prev.tok.is_ident() {
            return Some(prev.sp);
        }
        result
    }

    pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        let mut prev = toks.real_token();
        loop {
            if prev.tok == token::Eof {
                return None;
            }
            let next = toks.real_token();
            if next.tok == tok {
                return Some(prev.sp);
            }
            prev = next;
        }
    }

    pub fn sub_span_of_token(&self, span: Span, tok: Token) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        loop {
            let next = toks.real_token();
            if next.tok == token::Eof {
                return None;
            }
            if next.tok == tok {
                return Some(next.sp);
            }
        }
    }

    pub fn sub_span_after_keyword(&self, span: Span, keyword: keywords::Keyword) -> Option<Span> {
        self.sub_span_after(span, |t| t.is_keyword(keyword))
    }

    fn sub_span_after<F: Fn(Token) -> bool>(&self, span: Span, f: F) -> Option<Span> {
        let mut toks = self.retokenise_span(span);
        loop {
            let ts = toks.real_token();
            if ts.tok == token::Eof {
                return None;
            }
            if f(ts.tok) {
                let ts = toks.real_token();
                if ts.tok == token::Eof {
                    return None;
                } else {
                    return Some(ts.sp);
                }
            }
        }
    }

    // // Return the name for a macro definition (identifier after first `!`)
    // pub fn span_for_macro_def_name(&self, span: Span) -> Option<Span> {
    //     let mut toks = self.retokenise_span(span);
    //     loop {
    //         let ts = toks.real_token();
    //         if ts.tok == token::Eof {
    //             return None;
    //         }
    //         if ts.tok == token::Not {
    //             let ts = toks.real_token();
    //             if ts.tok.is_ident() {
    //                 return Some(ts.sp);
    //             } else {
    //                 return None;
    //             }
    //         }
    //     }
    // }

    // // Return the name for a macro use (identifier before first `!`).
    // pub fn span_for_macro_use_name(&self, span:Span) -> Option<Span> {
    //     let mut toks = self.retokenise_span(span);
    //     let mut prev = toks.real_token();
    //     loop {
    //         if prev.tok == token::Eof {
    //             return None;
    //         }
    //         let ts = toks.real_token();
    //         if ts.tok == token::Not {
    //             if prev.tok.is_ident() {
    //                 return Some(prev.sp);
    //             } else {
    //                 return None;
    //             }
    //         }
    //         prev = ts;
    //     }
    // }

    /// Return true if the span is generated code, and
    /// it is not a subspan of the root callsite.
    ///
    /// Used to filter out spans of minimal value,
    /// such as references to macro internal variables.
    pub fn filter_generated(&self, sub_span: Option<Span>, parent: Span) -> bool {
        if !generated_code(parent) {
            // Edge case - this occurs on generated code with incorrect expansion info.
            return sub_span.is_none()
        }
        // If sub_span is none, filter out generated code.
        let sub_span = match sub_span {
            Some(ss) => ss,
            None => return true,
        };

        //If the span comes from a fake source_file, filter it.
        if !self.sess
            .source_map()
            .lookup_char_pos(parent.lo())
            .file
            .is_real_file()
        {
            return true;
        }

        // Otherwise, a generated span is deemed invalid if it is not a sub-span of the root
        // callsite. This filters out macro internal variables and most malformed spans.
        !parent.source_callsite().contains(sub_span)
    }
}

macro_rules! filter {
    ($util: expr, $span: expr, $parent: expr, None) => {
        if $util.filter_generated($span, $parent) {
            return None;
        }
    };
    ($util: expr, $span: ident, $parent: expr) => {
        if $util.filter_generated($span, $parent) {
            return;
        }
    };
}
<|endoftext|>