about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-05-06 12:41:55 -0700
committerbors <bors@rust-lang.org>2014-05-06 12:41:55 -0700
commitcf6857b9e9427f14d383ae2924555bedc251fa02 (patch)
tree045b617609058f5042495fd4172b2f2924179360 /src/libstd
parent1f6db7f4f6399628eaaca5d38cc5fb38e71b4c23 (diff)
parent8d1d7d9b5f3920d70b1edcc258a86106527e83f7 (diff)
downloadrust-cf6857b9e9427f14d383ae2924555bedc251fa02.tar.gz
rust-cf6857b9e9427f14d383ae2924555bedc251fa02.zip
auto merge of #13897 : aturon/rust/issue-6085, r=bjz
The `std::bitflags::bitflags!` macro did not provide support for
adding attributes to the generates structure, due to limitations in
the parser for macros. This patch works around the parser limitations
by requiring a `flags` keyword in the `bitflags!` invocations:

    bitflags!(
        #[deriving(Hash)]
        #[doc="Three flags"]
        flags Flags: u32 {
            FlagA       = 0x00000001,
            FlagB       = 0x00000010,
            FlagC       = 0x00000100
        }
    )

The intent of `std::bitflags` is to allow building type-safe wrappers
around C-style flags APIs. But in addition to construction these flags
from the Rust side, we need a way to convert them from the C
side. This patch adds a `from_bits` function, which is unsafe since
the bits in question may not represent a valid combination of flags.

Finally, this patch changes `std::io::FilePermissions` from an exposed
`u32` representation to a typesafe representation (that only allows valid
flag combinations) using the `std::bitflags`.

Closes #6085.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/bitflags.rs71
-rw-r--r--src/libstd/io/fs.rs6
-rw-r--r--src/libstd/io/mod.rs71
3 files changed, 87 insertions, 61 deletions
diff --git a/src/libstd/bitflags.rs b/src/libstd/bitflags.rs
index bf12dd2d94a..5737bc772df 100644
--- a/src/libstd/bitflags.rs
+++ b/src/libstd/bitflags.rs
@@ -17,14 +17,16 @@
 //! # Example
 //!
 //! ~~~rust
-//! bitflags!(Flags: u32 {
-//!     FlagA       = 0x00000001,
-//!     FlagB       = 0x00000010,
-//!     FlagC       = 0x00000100,
-//!     FlagABC     = FlagA.bits
-//!                 | FlagB.bits
-//!                 | FlagC.bits
-//! })
+//! bitflags!(
+//!     flags Flags: u32 {
+//!         static FlagA       = 0x00000001,
+//!         static FlagB       = 0x00000010,
+//!         static FlagC       = 0x00000100,
+//!         static FlagABC     = FlagA.bits
+//!                            | FlagB.bits
+//!                            | FlagC.bits
+//!     }
+//! )
 //!
 //! fn main() {
 //!     let e1 = FlagA | FlagC;
@@ -40,10 +42,12 @@
 //! ~~~rust
 //! use std::fmt;
 //!
-//! bitflags!(Flags: u32 {
-//!     FlagA   = 0x00000001,
-//!     FlagB   = 0x00000010
-//! })
+//! bitflags!(
+//!     flags Flags: u32 {
+//!         static FlagA   = 0x00000001,
+//!         static FlagB   = 0x00000010
+//!     }
+//! )
 //!
 //! impl Flags {
 //!     pub fn clear(&mut self) {
@@ -66,10 +70,16 @@
 //! }
 //! ~~~
 //!
+//! # Attributes
+//!
+//! Attributes can be attached to the generated `struct` by placing them
+//! before the `flags` keyword.
+//!
 //! # Derived traits
 //!
-//! The `Eq`, `TotalEq`, and `Clone` traits are automatically derived for the
-//! `struct` using the `deriving` attribute.
+//! The `Eq` and `Clone` traits are automatically derived for the `struct` using
+//! the `deriving` attribute. Additional traits can be derived by providing an
+//! explicit `deriving` attribute on `flags`.
 //!
 //! # Operators
 //!
@@ -91,17 +101,20 @@
 //! - `insert`: inserts the specified flags in-place
 //! - `remove`: removes the specified flags in-place
 
+#![macro_escape]
+
 #[macro_export]
 macro_rules! bitflags(
-    ($BitFlags:ident: $T:ty {
-        $($Flag:ident = $value:expr),+
+    ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
+        $($(#[$Flag_attr:meta])* static $Flag:ident = $value:expr),+
     }) => (
         #[deriving(Eq, TotalEq, Clone)]
+        $(#[$attr])*
         pub struct $BitFlags {
             bits: $T,
         }
 
-        $(pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+
+        $($(#[$Flag_attr])* pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+
 
         impl $BitFlags {
             /// Returns an empty set of flags.
@@ -114,6 +127,12 @@ macro_rules! bitflags(
                 self.bits
             }
 
+            /// Convert from underlying bit representation. Unsafe because the
+            /// bits are not guaranteed to represent valid flags.
+            pub unsafe fn from_bits(bits: $T) -> $BitFlags {
+                $BitFlags { bits: bits }
+            }
+
             /// Returns `true` if no flags are currently stored.
             pub fn is_empty(&self) -> bool {
                 *self == $BitFlags::empty()
@@ -170,14 +189,16 @@ macro_rules! bitflags(
 mod tests {
     use ops::{BitOr, BitAnd, Sub};
 
-    bitflags!(Flags: u32 {
-        FlagA       = 0x00000001,
-        FlagB       = 0x00000010,
-        FlagC       = 0x00000100,
-        FlagABC     = FlagA.bits
-                    | FlagB.bits
-                    | FlagC.bits
-    })
+    bitflags!(
+        flags Flags: u32 {
+            static FlagA       = 0x00000001,
+            static FlagB       = 0x00000010,
+            static FlagC       = 0x00000100,
+            static FlagABC     = FlagA.bits
+                               | FlagB.bits
+                               | FlagC.bits
+        }
+    )
 
     #[test]
     fn test_bits(){
diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs
index cd304250b19..6d48b9eee35 100644
--- a/src/libstd/io/fs.rs
+++ b/src/libstd/io/fs.rs
@@ -1119,7 +1119,7 @@ mod test {
         check!(File::create(&input));
         check!(chmod(&input, io::UserRead));
         check!(copy(&input, &out));
-        assert!(check!(out.stat()).perm & io::UserWrite == 0);
+        assert!(!check!(out.stat()).perm.intersects(io::UserWrite));
 
         check!(chmod(&input, io::UserFile));
         check!(chmod(&out, io::UserFile));
@@ -1193,9 +1193,9 @@ mod test {
         let file = tmpdir.join("in.txt");
 
         check!(File::create(&file));
-        assert!(check!(stat(&file)).perm & io::UserWrite == io::UserWrite);
+        assert!(check!(stat(&file)).perm.contains(io::UserWrite));
         check!(chmod(&file, io::UserRead));
-        assert!(check!(stat(&file)).perm & io::UserWrite == 0);
+        assert!(!check!(stat(&file)).perm.contains(io::UserWrite));
 
         match chmod(&tmpdir.join("foo"), io::UserRWX) {
             Ok(..) => fail!("wanted a failure"),
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index d948738ac56..ff276d02028 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -224,6 +224,7 @@ use fmt;
 use int;
 use iter::Iterator;
 use libc;
+use ops::{BitOr, BitAnd, Sub};
 use os;
 use option::{Option, Some, None};
 use path::Path;
@@ -1558,36 +1559,40 @@ pub struct UnstableFileStat {
     pub gen: u64,
 }
 
-/// A set of permissions for a file or directory is represented by a set of
-/// flags which are or'd together.
-pub type FilePermission = u32;
-
-// Each permission bit
-pub static UserRead: FilePermission     = 0x100;
-pub static UserWrite: FilePermission    = 0x080;
-pub static UserExecute: FilePermission  = 0x040;
-pub static GroupRead: FilePermission    = 0x020;
-pub static GroupWrite: FilePermission   = 0x010;
-pub static GroupExecute: FilePermission = 0x008;
-pub static OtherRead: FilePermission    = 0x004;
-pub static OtherWrite: FilePermission   = 0x002;
-pub static OtherExecute: FilePermission = 0x001;
-
-// Common combinations of these bits
-pub static UserRWX: FilePermission  = UserRead | UserWrite | UserExecute;
-pub static GroupRWX: FilePermission = GroupRead | GroupWrite | GroupExecute;
-pub static OtherRWX: FilePermission = OtherRead | OtherWrite | OtherExecute;
-
-/// A set of permissions for user owned files, this is equivalent to 0644 on
-/// unix-like systems.
-pub static UserFile: FilePermission = UserRead | UserWrite | GroupRead | OtherRead;
-/// A set of permissions for user owned directories, this is equivalent to 0755
-/// on unix-like systems.
-pub static UserDir: FilePermission = UserRWX | GroupRead | GroupExecute |
-                                     OtherRead | OtherExecute;
-/// A set of permissions for user owned executables, this is equivalent to 0755
-/// on unix-like systems.
-pub static UserExec: FilePermission = UserDir;
-
-/// A mask for all possible permission bits
-pub static AllPermissions: FilePermission = 0x1ff;
+bitflags!(
+    #[doc="A set of permissions for a file or directory is represented
+by a set of flags which are or'd together."]
+    #[deriving(Hash)]
+    #[deriving(Show)]
+    flags FilePermission: u32 {
+        static UserRead     = 0o400,
+        static UserWrite    = 0o200,
+        static UserExecute  = 0o100,
+        static GroupRead    = 0o040,
+        static GroupWrite   = 0o020,
+        static GroupExecute = 0o010,
+        static OtherRead    = 0o004,
+        static OtherWrite   = 0o002,
+        static OtherExecute = 0o001,
+
+        static UserRWX  = UserRead.bits | UserWrite.bits | UserExecute.bits,
+        static GroupRWX = GroupRead.bits | GroupWrite.bits | GroupExecute.bits,
+        static OtherRWX = OtherRead.bits | OtherWrite.bits | OtherExecute.bits,
+
+        #[doc="Permissions for user owned files, equivalent to 0644 on
+unix-like systems."]
+        static UserFile = UserRead.bits | UserWrite.bits | GroupRead.bits | OtherRead.bits,
+
+        #[doc="Permissions for user owned directories, equivalent to 0755 on
+unix-like systems."]
+        static UserDir  = UserRWX.bits | GroupRead.bits | GroupExecute.bits |
+                   OtherRead.bits | OtherExecute.bits,
+
+        #[doc="Permissions for user owned executables, equivalent to 0755
+on unix-like systems."]
+        static UserExec = UserDir.bits,
+
+        #[doc="All possible permissions enabled."]
+        static AllPermissions = UserRWX.bits | GroupRWX.bits | OtherRWX.bits
+    }
+)