11module Node.FS.Perms
2- ( permsFromString
3- , permsToString
4- , permsToInt
2+ ( Perm ()
53 , none
6- , r
7- , w
8- , x
4+ , read
5+ , write
6+ , execute
97 , all
10- , mkPerms
118 , Perms ()
12- , Perm ()
9+ , mkPerms
10+ , permsFromString
11+ , permsToString
12+ , permsToInt
1313 ) where
1414
1515import Global (readInt )
16+ import Data.Array () -- for Semigroup and Functor instances
1617import Data.Maybe (Maybe (..))
17- import Data.Char (Char (), charString )
18- import Data.String (toCharArray )
18+ import Data.Char (Char (), charString , fromCharCode )
19+ import Data.String (toCharArray , joinWith , drop , charAt )
1920import Data.Int (Int (), fromNumber , toNumber )
2021
2122-- | A `Perm` value specifies what is allowed to be done with a particular
2223-- | file by a particular class of user — that is, whether it is
2324-- | readable, writable, and/or executable. It has a semigroup instance, which
24- -- | allows you to combine permissions; for example, `r <> w ` means "readable
25- -- | and writable".
25+ -- | allows you to combine permissions; for example, `read <> write ` means
26+ -- | "readable and writable".
2627newtype Perm = Perm { r :: Boolean , w :: Boolean , x :: Boolean }
2728
28- -- | A `Perms` value includes all the permissions information about a
29- -- | particular file or directory, by storing a `Perm` value for each of the
30- -- | file owner, the group, and others.
31- newtype Perms = Perms { u :: Perm , g :: Perm , o :: Perm }
29+ instance eqPerm :: Eq Perm where
30+ (==) (Perm { r = r1, w = w1, x = x1 }) (Perm { r = r2, w = w2, x = x2 }) =
31+ r1 == r2 && w1 == w2 && x1 == x2
32+ (/=) x y = not (x == y)
33+
34+ instance ordPerm :: Ord Perm where
35+ compare (Perm { r = r1, w = w1, x = x1 }) (Perm { r = r2, w = w2, x = x2 }) =
36+ compare [r1, w1, x1] [r2, w2, x2]
37+
38+ instance showPerm :: Show Perm where
39+ show p | p == none = " none"
40+ show p | p == all = " all"
41+ show (Perm { r = r, w = w, x = x }) =
42+ joinWith " <> " ps
43+ where
44+ ps =
45+ (if r then [" read" ] else [] ) <>
46+ (if w then [" write" ] else [] ) <>
47+ (if x then [" execute" ] else [] )
48+
49+ instance semigroupPerm :: Semigroup Perm where
50+ (<>) (Perm { r = r0, w = w0, x = x0 }) (Perm { r = r1, w = w1, x = x1 }) =
51+ Perm { r: r0 || r1, w: w0 || w1, x: x0 || x1 }
52+
53+ -- | Create a `Perm` value. The arguments represent the readable, writable, and
54+ -- | executable permissions, in that order.
55+ mkPerm :: Boolean -> Boolean -> Boolean -> Perm
56+ mkPerm r w x = Perm { r: r, w: w, x: x }
3257
3358-- | No permissions. This is the identity of the `Semigroup` operation `(<>)`
3459-- | for `Perm`.
3560none :: Perm
3661none = Perm { r: false , w: false , x: false }
3762
3863-- | The "readable" permission.
39- r :: Perm
40- r = Perm { r: true , w: false , x: false }
64+ read :: Perm
65+ read = Perm { r: true , w: false , x: false }
4166
4267-- | The "writable" permission.
43- w :: Perm
44- w = Perm { r: false , w: true , x: false }
68+ write :: Perm
69+ write = Perm { r: false , w: true , x: false }
4570
4671-- | The "executable" permission.
47- x :: Perm
48- x = Perm { r: false , w: false , x: true }
72+ execute :: Perm
73+ execute = Perm { r: false , w: false , x: true }
4974
5075-- | All permissions: readable, writable, and executable.
5176all :: Perm
52- all = r <> w <> x
77+ all = read <> write <> execute
5378
54- instance semigroupPerm :: Semigroup Perm where
55- (<>) (Perm { r = r0, w = w0, x = x0 }) (Perm { r = r1, w = w1, x = x1 }) =
56- Perm { r: r0 || r1, w: w0 || w1, x: x0 || x1 }
79+ -- | A `Perms` value includes all the permissions information about a
80+ -- | particular file or directory, by storing a `Perm` value for each of the
81+ -- | file owner, the group, and any other users.
82+ newtype Perms = Perms { u :: Perm , g :: Perm , o :: Perm }
83+
84+ instance eqPerms :: Eq Perms where
85+ (==) (Perms { u = u1, g = g1, o = o1 }) (Perms { u = u2, g = g2, o = o2 }) =
86+ u1 == u2 && g1 == g2 && o1 == o2
87+ (/=) x y = not (x == y)
88+
89+ instance ordPerms :: Ord Perms where
90+ compare (Perms { u = u1, g = g1, o = o1 }) (Perms { u = u2, g = g2, o = o2 }) =
91+ compare [u1, g1, o1] [u2, g2, o2]
92+
93+ instance showPerms :: Show Perms where
94+ show (Perms { u = u, g = g, o = o }) =
95+ " mkPerms " <> joinWith " " (f <$> [u, g, o])
96+ where
97+ f perm = " (" <> show perm <> " )"
5798
5899-- | Attempt to parse a `Perms` value from a `String` containing an octal
59100-- | integer. For example,
60- -- | `permsFromString "644 " == Just (mkPerms (r <> w) r r )`.
101+ -- | `permsFromString "0644 " == Just (mkPerms (read <> write) read read )`.
61102permsFromString :: String -> Maybe Perms
62- permsFromString = _perms <<< toCharArray
103+ permsFromString = _perms <<< toCharArray <<< dropPrefix zeroChar
63104 where
105+ zeroChar = fromCharCode 48
106+
107+ dropPrefix x xs
108+ | charAt 0 xs == Just x = drop 1 xs
109+ | otherwise = xs
110+
64111 _perms [u, g, o] =
65112 mkPerms <$> permFromChar u
66113 <*> permFromChar g
@@ -71,22 +118,17 @@ permFromChar :: Char -> Maybe Perm
71118permFromChar = _perm <<< charString
72119 where
73120 _perm " 0" = Just $ none
74- _perm " 1" = Just $ x
75- _perm " 2" = Just $ w
76- _perm " 3" = Just $ w <> x
77- _perm " 4" = Just $ r
78- _perm " 5" = Just $ r <> x
79- _perm " 6" = Just $ r <> w
80- _perm " 7" = Just $ r <> w <> x
121+ _perm " 1" = Just $ execute
122+ _perm " 2" = Just $ write
123+ _perm " 3" = Just $ write <> execute
124+ _perm " 4" = Just $ read
125+ _perm " 5" = Just $ read <> execute
126+ _perm " 6" = Just $ read <> write
127+ _perm " 7" = Just $ read <> write <> execute
81128 _perm _ = Nothing
82129
83- -- | Create a `Perm` value. The arguments represent the readable, writable, and
84- -- | executable permissions, in that order.
85- mkPerm :: Boolean -> Boolean -> Boolean -> Perm
86- mkPerm r w x = Perm { r: r, w: w, x: x }
87-
88- -- | Create a `Perms` value. The arguments represent the user's, group's, and
89- -- | others' permission sets, respectively.
130+ -- | Create a `Perms` value. The arguments represent the owner's, group's, and
131+ -- | other users' permission sets, respectively.
90132mkPerms :: Perm -> Perm -> Perm -> Perms
91133mkPerms u g o = Perms { u: u, g: g, o: o }
92134
@@ -96,10 +138,11 @@ mkPerms u g o = Perms { u: u, g: g, o: o }
96138-- | * `permToInt w == 2`
97139-- | * `permToInt (r <> w) == 6`
98140permToInt :: Perm -> Int
99- permToInt (Perm { r = r, w = w, x = x }) = fromNumber $
100- (if r then 4 else 0 )
101- + (if w then 2 else 0 )
102- + (if x then 1 else 0 )
141+ permToInt (Perm { r = r, w = w, x = x }) =
142+ fromNumber $
143+ (if r then 4 else 0 )
144+ + (if w then 2 else 0 )
145+ + (if x then 1 else 0 )
103146
104147-- | Convert a `Perm` to an octal string, via `permToInt`.
105148permToString :: Perm -> String
@@ -116,14 +159,6 @@ permsToString (Perms { u = u, g = g, o = o }) =
116159 ++ permToString g
117160 ++ permToString o
118161
162+ -- | Convert a `Perms` value to an `Int`, via `permsToString`.
119163permsToInt :: Perms -> Int
120- permsToInt p = fromNumber $ readInt 8 $ permsToString p
121-
122- instance showPerm :: Show Perm where
123- show (Perm { r = r, w = w, x = x }) =
124- (if r then " r" else " -" )
125- ++ (if w then " w" else " -" )
126- ++ (if x then " x" else " -" )
127-
128- instance showPerms :: Show Perms where
129- show (Perms { u = u, g = g, o = o }) = show u ++ show g ++ show o
164+ permsToInt = fromNumber <<< readInt 8 <<< permsToString
0 commit comments