Skip to content

Clean up collections::EnumSet #19679

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 40 additions & 37 deletions src/libcollections/enum_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use core::num::Int;
pub struct EnumSet<E> {
// We must maintain the invariant that no bits are set
// for which no variant exists
bits: uint
bits: u32,
}

impl<E> Copy for EnumSet<E> {}
Expand All @@ -44,38 +44,39 @@ impl<E:CLike+fmt::Show> fmt::Show for EnumSet<E> {
}
}

/// An interface for casting C-like enum to uint and back.
/// An interface for casting C-like enum to u32 and back.
/// A typically implementation is as below.
///
/// ```{rust,ignore}
/// #[repr(uint)]
/// #[repr(u32)]
/// enum Foo {
/// A, B, C
/// }
///
/// impl CLike for Foo {
/// fn to_uint(&self) -> uint {
/// *self as uint
/// fn to_u32(&self) -> u32 {
/// *self as u32
/// }
///
/// fn from_uint(v: uint) -> Foo {
/// unsafe fn from_u32(v: u32) -> Foo {
/// unsafe { mem::transmute(v) }
/// }
/// }
/// ```
pub trait CLike {
/// Converts a C-like enum to a `uint`.
fn to_uint(&self) -> uint;
/// Converts a `uint` to a C-like enum.
fn from_uint(uint) -> Self;
/// Converts a C-like enum to a `u32`.
fn to_u32(&self) -> u32;
/// Converts a `u32` to a C-like enum. This method only needs to work
/// correctly for possible return values of `to_u32` of this trait.
unsafe fn from_u32(u32) -> Self;
}

fn bit<E:CLike>(e: &E) -> uint {
use core::uint;
let value = e.to_uint();
assert!(value < uint::BITS,
"EnumSet only supports up to {} variants.", uint::BITS - 1);
1 << value
fn bit<E:CLike>(e: &E) -> u32 {
use core::u32;
let value = e.to_u32();
assert!(value < u32::BITS as u32,
"EnumSet only supports up to {} variants.", u32::BITS - 1);
1 << value as uint
}

impl<E:CLike> EnumSet<E> {
Expand All @@ -88,7 +89,7 @@ impl<E:CLike> EnumSet<E> {
/// Returns an empty `EnumSet`.
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn new() -> EnumSet<E> {
EnumSet {bits: 0}
EnumSet { bits: 0 }
}

/// Returns the number of elements in the given `EnumSet`.
Expand Down Expand Up @@ -134,12 +135,12 @@ impl<E:CLike> EnumSet<E> {

/// Returns the union of both `EnumSets`.
pub fn union(&self, e: EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits | e.bits}
EnumSet { bits: self.bits | e.bits }
}

/// Returns the intersection of both `EnumSets`.
pub fn intersection(&self, e: EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits & e.bits}
EnumSet { bits: self.bits & e.bits }
}

/// Deprecated: Use `insert`.
Expand Down Expand Up @@ -185,36 +186,36 @@ impl<E:CLike> EnumSet<E> {

impl<E:CLike> Sub<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn sub(&self, e: &EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits & !e.bits}
EnumSet { bits: self.bits & !e.bits }
}
}

impl<E:CLike> BitOr<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn bitor(&self, e: &EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits | e.bits}
EnumSet { bits: self.bits | e.bits }
}
}

impl<E:CLike> BitAnd<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn bitand(&self, e: &EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits & e.bits}
EnumSet { bits: self.bits & e.bits }
}
}

impl<E:CLike> BitXor<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn bitxor(&self, e: &EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits ^ e.bits}
EnumSet { bits: self.bits ^ e.bits }
}
}

/// An iterator over an EnumSet
pub struct Items<E> {
index: uint,
bits: uint,
index: u32,
bits: u32,
}

impl<E:CLike> Items<E> {
fn new(bits: uint) -> Items<E> {
fn new(bits: u32) -> Items<E> {
Items { index: 0, bits: bits }
}
}
Expand All @@ -229,7 +230,9 @@ impl<E:CLike> Iterator<E> for Items<E> {
self.index += 1;
self.bits >>= 1;
}
let elem = CLike::from_uint(self.index);
// Safe because of the invariant that only valid bits are set (see
// comment on the `bit` member of this struct).
let elem = unsafe { CLike::from_u32(self.index) };
self.index += 1;
self.bits >>= 1;
Some(elem)
Expand Down Expand Up @@ -266,20 +269,20 @@ mod test {
use super::{EnumSet, CLike};

#[deriving(PartialEq, Show)]
#[repr(uint)]
#[repr(u32)]
enum Foo {
A, B, C
}

impl Copy for Foo {}

impl CLike for Foo {
fn to_uint(&self) -> uint {
*self as uint
fn to_u32(&self) -> u32 {
*self as u32
}

fn from_uint(v: uint) -> Foo {
unsafe { mem::transmute(v) }
unsafe fn from_u32(v: u32) -> Foo {
mem::transmute(v)
}
}

Expand Down Expand Up @@ -471,7 +474,7 @@ mod test {
#[should_fail]
fn test_overflow() {
#[allow(dead_code)]
#[repr(uint)]
#[repr(u32)]
enum Bar {
V00, V01, V02, V03, V04, V05, V06, V07, V08, V09,
V10, V11, V12, V13, V14, V15, V16, V17, V18, V19,
Expand All @@ -485,12 +488,12 @@ mod test {
impl Copy for Bar {}

impl CLike for Bar {
fn to_uint(&self) -> uint {
*self as uint
fn to_u32(&self) -> u32 {
*self as u32
}

fn from_uint(v: uint) -> Bar {
unsafe { mem::transmute(v) }
unsafe fn from_u32(v: u32) -> Bar {
mem::transmute(v)
}
}
let mut set = EnumSet::new();
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1436,7 +1436,7 @@ impl Copy for ExistentialBounds {}
pub type BuiltinBounds = EnumSet<BuiltinBound>;

#[deriving(Clone, Encodable, PartialEq, Eq, Decodable, Hash, Show)]
#[repr(uint)]
#[repr(u8)]
pub enum BuiltinBound {
BoundSend,
BoundSized,
Expand Down Expand Up @@ -1465,11 +1465,11 @@ pub fn region_existential_bound(r: ty::Region) -> ExistentialBounds {
}

impl CLike for BuiltinBound {
fn to_uint(&self) -> uint {
*self as uint
fn to_u32(&self) -> u32 {
*self as u32
}
fn from_uint(v: uint) -> BuiltinBound {
unsafe { mem::transmute(v) }
unsafe fn from_u32(v: u32) -> BuiltinBound {
mem::transmute(v as u8)
}
}

Expand Down
40 changes: 11 additions & 29 deletions src/libserialize/collection_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

//! Implementations of serialization for structures found in libcollections

use std::uint;
use std::default::Default;
use std::hash::{Hash, Hasher};

Expand Down Expand Up @@ -38,7 +37,7 @@ impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for DList<T> {
fn decode(d: &mut D) -> Result<DList<T>, E> {
d.read_seq(|d, len| {
let mut list = DList::new();
for i in range(0u, len) {
for i in range(0, len) {
list.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
Ok(list)
Expand All @@ -65,7 +64,7 @@ impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for RingBuf<T> {
fn decode(d: &mut D) -> Result<RingBuf<T>, E> {
d.read_seq(|d, len| {
let mut deque: RingBuf<T> = RingBuf::new();
for i in range(0u, len) {
for i in range(0, len) {
deque.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
Ok(deque)
Expand Down Expand Up @@ -101,7 +100,7 @@ impl<
fn decode(d: &mut D) -> Result<TreeMap<K, V>, E> {
d.read_map(|d, len| {
let mut map = TreeMap::new();
for i in range(0u, len) {
for i in range(0, len) {
let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
map.insert(key, val);
Expand Down Expand Up @@ -136,7 +135,7 @@ impl<
fn decode(d: &mut D) -> Result<TreeSet<T>, E> {
d.read_seq(|d, len| {
let mut set = TreeSet::new();
for i in range(0u, len) {
for i in range(0, len) {
set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
Ok(set)
Expand All @@ -152,26 +151,9 @@ impl<
fn encode(&self, s: &mut S) -> Result<(), E> {
let mut bits = 0;
for item in self.iter() {
bits |= item.to_uint();
bits |= item.to_u32();
}
s.emit_uint(bits)
}
}

impl<
E,
D: Decoder<E>,
T: Decodable<D, E> + CLike
> Decodable<D, E> for EnumSet<T> {
fn decode(d: &mut D) -> Result<EnumSet<T>, E> {
let bits = try!(d.read_uint());
let mut set = EnumSet::new();
for bit in range(0, uint::BITS) {
if bits & (1 << bit) != 0 {
set.insert(CLike::from_uint(1 << bit));
}
}
Ok(set)
s.emit_u32(bits)
}
}

Expand Down Expand Up @@ -208,7 +190,7 @@ impl<
d.read_map(|d, len| {
let hasher = Default::default();
let mut map = HashMap::with_capacity_and_hasher(len, hasher);
for i in range(0u, len) {
for i in range(0, len) {
let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
map.insert(key, val);
Expand Down Expand Up @@ -247,7 +229,7 @@ impl<
fn decode(d: &mut D) -> Result<HashSet<T, H>, E> {
d.read_seq(|d, len| {
let mut set = HashSet::with_capacity_and_hasher(len, Default::default());
for i in range(0u, len) {
for i in range(0, len) {
set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
Ok(set)
Expand Down Expand Up @@ -279,7 +261,7 @@ impl<
fn decode(d: &mut D) -> Result<TrieMap<V>, E> {
d.read_map(|d, len| {
let mut map = TrieMap::new();
for i in range(0u, len) {
for i in range(0, len) {
let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
map.insert(key, val);
Expand All @@ -304,7 +286,7 @@ impl<E, D: Decoder<E>> Decodable<D, E> for TrieSet {
fn decode(d: &mut D) -> Result<TrieSet, E> {
d.read_seq(|d, len| {
let mut set = TrieSet::new();
for i in range(0u, len) {
for i in range(0, len) {
set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
Ok(set)
Expand Down Expand Up @@ -336,7 +318,7 @@ impl<
fn decode(d: &mut D) -> Result<VecMap<V>, E> {
d.read_map(|d, len| {
let mut map = VecMap::new();
for i in range(0u, len) {
for i in range(0, len) {
let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
map.insert(key, val);
Expand Down