Skip to content

Commit

Permalink
Use EffectFnX (#70)
Browse files Browse the repository at this point in the history
* Use EffectFnX

* Update CHANGELOG

* Make JSCallback an EffectFn2, remove handleCallbackImpl FFI, implement handleCallback in PureScript
  • Loading branch information
Colin Wahl authored Oct 22, 2022
1 parent 2629cb3 commit b631e2c
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 154 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ New features:
Bugfixes:

Other improvements:
- Use `EffectFn` throughout instead of unsafe `mkEffect` utility (#70 by @colinwahl)

## [v8.1.0](https://github.com/purescript-node/purescript-node-fs/releases/tag/v8.1.0) - 2022-06-10

Expand Down
10 changes: 0 additions & 10 deletions src/Node/FS/Async.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,3 @@ export {
write as writeImpl,
close as closeImpl
} from "fs";

export function handleCallbackImpl(left, right, f) {
return function (err, value) {
if (err) {
f(left(err))();
} else {
f(right(value))();
}
};
}
120 changes: 57 additions & 63 deletions src/Node/FS/Async.purs
Original file line number Diff line number Diff line change
Expand Up @@ -39,67 +39,61 @@ import Prelude
import Data.DateTime (DateTime)
import Data.DateTime.Instant (fromDateTime, unInstant)
import Data.Either (Either(..))
import Data.Function.Uncurried (Fn2, Fn6, Fn4, Fn3, runFn2, runFn6, runFn4, runFn3)
import Data.Int (round)
import Data.Maybe (Maybe(..))
import Data.Nullable (Nullable, toNullable)
import Data.Nullable (Nullable, toMaybe, toNullable)
import Data.Time.Duration (Milliseconds(..))
import Effect (Effect)
import Effect.Exception (Error)
import Effect.Uncurried (EffectFn2, EffectFn3, EffectFn4, EffectFn6, mkEffectFn2, runEffectFn2, runEffectFn3, runEffectFn4, runEffectFn6)
import Node.Buffer (Buffer, size)
import Node.Encoding (Encoding)
import Node.FS (FileDescriptor, ByteCount, FilePosition, BufferLength, BufferOffset, FileMode, FileFlags, SymlinkType, fileFlagsToNode, symlinkTypeToNode)
import Node.FS.Internal (mkEffect)
import Node.FS.Perms (Perms, permsToString, all, mkPerms)
import Node.FS.Stats (StatsObj, Stats(..))
import Node.Path (FilePath)

type JSCallback a = Fn2 (Nullable Error) a Unit

foreign import handleCallbackImpl ::
forall a. Fn3 (Error -> Either Error a)
(a -> Either Error a)
(Callback a)
(JSCallback a)

handleCallback :: forall a. (Callback a) -> JSCallback a
handleCallback cb = runFn3 handleCallbackImpl Left Right cb
type JSCallback a = EffectFn2 (Nullable Error) a Unit

handleCallback :: forall a. Callback a -> JSCallback a
handleCallback cb = mkEffectFn2 \err a -> case toMaybe err of
Nothing -> cb (Right a)
Just err' -> cb (Left err')

-- | Type synonym for callback functions.
type Callback a = Either Error a -> Effect Unit

foreign import renameImpl :: Fn3 FilePath FilePath (JSCallback Unit) Unit
foreign import truncateImpl :: Fn3 FilePath Int (JSCallback Unit) Unit
foreign import chownImpl :: Fn4 FilePath Int Int (JSCallback Unit) Unit
foreign import chmodImpl :: Fn3 FilePath String (JSCallback Unit) Unit
foreign import statImpl :: Fn2 FilePath (JSCallback StatsObj) Unit
foreign import lstatImpl :: Fn2 FilePath (JSCallback StatsObj) Unit
foreign import linkImpl :: Fn3 FilePath FilePath (JSCallback Unit) Unit
foreign import symlinkImpl :: Fn4 FilePath FilePath String (JSCallback Unit) Unit
foreign import readlinkImpl :: Fn2 FilePath (JSCallback FilePath) Unit
foreign import realpathImpl :: forall cache. Fn3 FilePath { | cache } (JSCallback FilePath) Unit
foreign import unlinkImpl :: Fn2 FilePath (JSCallback Unit) Unit
foreign import rmdirImpl :: Fn3 FilePath { maxRetries :: Int, retryDelay :: Int } (JSCallback Unit) Unit
foreign import rmImpl :: Fn3 FilePath { force :: Boolean, maxRetries :: Int, recursive :: Boolean, retryDelay :: Int } (JSCallback Unit) Unit
foreign import mkdirImpl :: Fn3 FilePath { recursive :: Boolean, mode :: String } (JSCallback Unit) Unit
foreign import readdirImpl :: Fn2 FilePath (JSCallback (Array FilePath)) Unit
foreign import utimesImpl :: Fn4 FilePath Int Int (JSCallback Unit) Unit
foreign import readFileImpl :: forall a opts. Fn3 FilePath { | opts } (JSCallback a) Unit
foreign import writeFileImpl :: forall a opts. Fn4 FilePath a { | opts } (JSCallback Unit) Unit
foreign import appendFileImpl :: forall a opts. Fn4 FilePath a { | opts } (JSCallback Unit) Unit
foreign import openImpl :: Fn4 FilePath String (Nullable FileMode) (JSCallback FileDescriptor) Unit
foreign import readImpl :: Fn6 FileDescriptor Buffer BufferOffset BufferLength (Nullable FilePosition) (JSCallback ByteCount) Unit
foreign import writeImpl :: Fn6 FileDescriptor Buffer BufferOffset BufferLength (Nullable FilePosition) (JSCallback ByteCount) Unit
foreign import closeImpl :: Fn2 FileDescriptor (JSCallback Unit) Unit
foreign import renameImpl :: EffectFn3 FilePath FilePath (JSCallback Unit) Unit
foreign import truncateImpl :: EffectFn3 FilePath Int (JSCallback Unit) Unit
foreign import chownImpl :: EffectFn4 FilePath Int Int (JSCallback Unit) Unit
foreign import chmodImpl :: EffectFn3 FilePath String (JSCallback Unit) Unit
foreign import statImpl :: EffectFn2 FilePath (JSCallback StatsObj) Unit
foreign import lstatImpl :: EffectFn2 FilePath (JSCallback StatsObj) Unit
foreign import linkImpl :: EffectFn3 FilePath FilePath (JSCallback Unit) Unit
foreign import symlinkImpl :: EffectFn4 FilePath FilePath String (JSCallback Unit) Unit
foreign import readlinkImpl :: EffectFn2 FilePath (JSCallback FilePath) Unit
foreign import realpathImpl :: forall cache. EffectFn3 FilePath { | cache } (JSCallback FilePath) Unit
foreign import unlinkImpl :: EffectFn2 FilePath (JSCallback Unit) Unit
foreign import rmdirImpl :: EffectFn3 FilePath { maxRetries :: Int, retryDelay :: Int } (JSCallback Unit) Unit
foreign import rmImpl :: EffectFn3 FilePath { force :: Boolean, maxRetries :: Int, recursive :: Boolean, retryDelay :: Int } (JSCallback Unit) Unit
foreign import mkdirImpl :: EffectFn3 FilePath { recursive :: Boolean, mode :: String } (JSCallback Unit) Unit
foreign import readdirImpl :: EffectFn2 FilePath (JSCallback (Array FilePath)) Unit
foreign import utimesImpl :: EffectFn4 FilePath Int Int (JSCallback Unit) Unit
foreign import readFileImpl :: forall a opts. EffectFn3 FilePath { | opts } (JSCallback a) Unit
foreign import writeFileImpl :: forall a opts. EffectFn4 FilePath a { | opts } (JSCallback Unit) Unit
foreign import appendFileImpl :: forall a opts. EffectFn4 FilePath a { | opts } (JSCallback Unit) Unit
foreign import openImpl :: EffectFn4 FilePath String (Nullable FileMode) (JSCallback FileDescriptor) Unit
foreign import readImpl :: EffectFn6 FileDescriptor Buffer BufferOffset BufferLength (Nullable FilePosition) (JSCallback ByteCount) Unit
foreign import writeImpl :: EffectFn6 FileDescriptor Buffer BufferOffset BufferLength (Nullable FilePosition) (JSCallback ByteCount) Unit
foreign import closeImpl :: EffectFn2 FileDescriptor (JSCallback Unit) Unit


-- | Renames a file.
rename :: FilePath
-> FilePath
-> Callback Unit
-> Effect Unit
rename oldFile newFile cb = mkEffect $ \_ -> runFn3
rename oldFile newFile cb = runEffectFn3
renameImpl oldFile newFile (handleCallback cb)

-- | Truncates a file to the specified length.
Expand All @@ -108,7 +102,7 @@ truncate :: FilePath
-> Callback Unit
-> Effect Unit

truncate file len cb = mkEffect $ \_ -> runFn3
truncate file len cb = runEffectFn3
truncateImpl file len (handleCallback cb)

-- | Changes the ownership of a file.
Expand All @@ -118,7 +112,7 @@ chown :: FilePath
-> Callback Unit
-> Effect Unit

chown file uid gid cb = mkEffect $ \_ -> runFn4
chown file uid gid cb = runEffectFn4
chownImpl file uid gid (handleCallback cb)

-- | Changes the permissions of a file.
Expand All @@ -127,15 +121,15 @@ chmod :: FilePath
-> Callback Unit
-> Effect Unit

chmod file perms cb = mkEffect $ \_ -> runFn3
chmod file perms cb = runEffectFn3
chmodImpl file (permsToString perms) (handleCallback cb)

-- | Gets file statistics.
stat :: FilePath
-> Callback Stats
-> Effect Unit

stat file cb = mkEffect $ \_ -> runFn2
stat file cb = runEffectFn2
statImpl file (handleCallback $ cb <<< map Stats)

-- | Gets file or symlink statistics. `lstat` is identical to `stat`, except
Expand All @@ -144,7 +138,7 @@ stat file cb = mkEffect $ \_ -> runFn2
lstat :: FilePath
-> Callback Stats
-> Effect Unit
lstat file cb = mkEffect $ \_ -> runFn2
lstat file cb = runEffectFn2
lstatImpl file (handleCallback $ cb <<< map Stats)

-- | Creates a link to an existing file.
Expand All @@ -153,7 +147,7 @@ link :: FilePath
-> Callback Unit
-> Effect Unit

link src dst cb = mkEffect $ \_ -> runFn3
link src dst cb = runEffectFn3
linkImpl src dst (handleCallback cb)

-- | Creates a symlink.
Expand All @@ -163,23 +157,23 @@ symlink :: FilePath
-> Callback Unit
-> Effect Unit

symlink src dest ty cb = mkEffect $ \_ -> runFn4
symlink src dest ty cb = runEffectFn4
symlinkImpl src dest (symlinkTypeToNode ty) (handleCallback cb)

-- | Reads the value of a symlink.
readlink :: FilePath
-> Callback FilePath
-> Effect Unit

readlink path cb = mkEffect $ \_ -> runFn2
readlink path cb = runEffectFn2
readlinkImpl path (handleCallback cb)

-- | Find the canonicalized absolute location for a path.
realpath :: FilePath
-> Callback FilePath
-> Effect Unit

realpath path cb = mkEffect $ \_ -> runFn3
realpath path cb = runEffectFn3
realpathImpl path {} (handleCallback cb)

-- | Find the canonicalized absolute location for a path using a cache object
Expand All @@ -189,15 +183,15 @@ realpath' :: forall cache. FilePath
-> Callback FilePath
-> Effect Unit

realpath' path cache cb = mkEffect $ \_ -> runFn3
realpath' path cache cb = runEffectFn3
realpathImpl path cache (handleCallback cb)

-- | Deletes a file.
unlink :: FilePath
-> Callback Unit
-> Effect Unit

unlink file cb = mkEffect $ \_ -> runFn2
unlink file cb = runEffectFn2
unlinkImpl file (handleCallback cb)

-- | Deletes a directory.
Expand All @@ -211,7 +205,7 @@ rmdir' :: FilePath
-> { maxRetries :: Int, retryDelay :: Int }
-> Callback Unit
-> Effect Unit
rmdir' path opts cb = mkEffect $ \_ -> runFn3
rmdir' path opts cb = runEffectFn3
rmdirImpl path opts (handleCallback cb)

-- | Deletes a file or directory.
Expand All @@ -225,7 +219,7 @@ rm' :: FilePath
-> { force :: Boolean, maxRetries :: Int, recursive :: Boolean, retryDelay :: Int }
-> Callback Unit
-> Effect Unit
rm' path opts cb = mkEffect $ \_ -> runFn3
rm' path opts cb = runEffectFn3
rmImpl path opts (handleCallback cb)


Expand All @@ -241,15 +235,15 @@ mkdir'
-> { recursive :: Boolean, mode :: Perms }
-> Callback Unit
-> Effect Unit
mkdir' file { recursive, mode: perms } cb = mkEffect $ \_ -> runFn3
mkdir' file { recursive, mode: perms } cb = runEffectFn3
mkdirImpl file { recursive, mode: permsToString perms } (handleCallback cb)

-- | Reads the contents of a directory.
readdir :: FilePath
-> Callback (Array FilePath)
-> Effect Unit

readdir file cb = mkEffect $ \_ -> runFn2
readdir file cb = runEffectFn2
readdirImpl file (handleCallback cb)

-- | Sets the accessed and modified times for the specified file.
Expand All @@ -259,7 +253,7 @@ utimes :: FilePath
-> Callback Unit
-> Effect Unit

utimes file atime mtime cb = mkEffect $ \_ -> runFn4
utimes file atime mtime cb = runEffectFn4
utimesImpl file
(fromDate atime)
(fromDate mtime)
Expand All @@ -274,7 +268,7 @@ readFile :: FilePath
-> Callback Buffer
-> Effect Unit

readFile file cb = mkEffect $ \_ -> runFn3
readFile file cb = runEffectFn3
readFileImpl file {} (handleCallback cb)

-- | Reads the entire contents of a text file with the specified encoding.
Expand All @@ -283,7 +277,7 @@ readTextFile :: Encoding
-> Callback String
-> Effect Unit

readTextFile encoding file cb = mkEffect $ \_ -> runFn3
readTextFile encoding file cb = runEffectFn3
readFileImpl file { encoding: show encoding } (handleCallback cb)

-- | Writes a buffer to a file.
Expand All @@ -292,7 +286,7 @@ writeFile :: FilePath
-> Callback Unit
-> Effect Unit

writeFile file buff cb = mkEffect $ \_ -> runFn4
writeFile file buff cb = runEffectFn4
writeFileImpl file buff {} (handleCallback cb)

-- | Writes text to a file using the specified encoding.
Expand All @@ -302,7 +296,7 @@ writeTextFile :: Encoding
-> Callback Unit
-> Effect Unit

writeTextFile encoding file buff cb = mkEffect $ \_ -> runFn4
writeTextFile encoding file buff cb = runEffectFn4
writeFileImpl file buff { encoding: show encoding } (handleCallback cb)

-- | Appends the contents of a buffer to a file.
Expand All @@ -311,7 +305,7 @@ appendFile :: FilePath
-> Callback Unit
-> Effect Unit

appendFile file buff cb = mkEffect $ \_ -> runFn4
appendFile file buff cb = runEffectFn4
appendFileImpl file buff {} (handleCallback cb)

-- | Appends text to a file using the specified encoding.
Expand All @@ -321,7 +315,7 @@ appendTextFile :: Encoding
-> Callback Unit
-> Effect Unit

appendTextFile encoding file buff cb = mkEffect $ \_ -> runFn4
appendTextFile encoding file buff cb = runEffectFn4
appendFileImpl file buff { encoding: show encoding } (handleCallback cb)


Expand All @@ -332,7 +326,7 @@ fdOpen :: FilePath
-> Maybe FileMode
-> Callback FileDescriptor
-> Effect Unit
fdOpen file flags mode cb = mkEffect $ \_ -> runFn4 openImpl file (fileFlagsToNode flags) (toNullable mode) (handleCallback cb)
fdOpen file flags mode cb = runEffectFn4 openImpl file (fileFlagsToNode flags) (toNullable mode) (handleCallback cb)

-- | Read from a file asynchronously. See the [Node Documentation](https://nodejs.org/api/fs.html#fs_fs_read_fd_buffer_offset_length_position_callback)
-- | for details.
Expand All @@ -343,7 +337,7 @@ fdRead :: FileDescriptor
-> Maybe FilePosition
-> Callback ByteCount
-> Effect Unit
fdRead fd buff off len pos cb = mkEffect $ \_ -> runFn6 readImpl fd buff off len (toNullable pos) (handleCallback cb)
fdRead fd buff off len pos cb = runEffectFn6 readImpl fd buff off len (toNullable pos) (handleCallback cb)

-- | Convenience function to fill the whole buffer from the current
-- | file position.
Expand All @@ -364,7 +358,7 @@ fdWrite :: FileDescriptor
-> Maybe FilePosition
-> Callback ByteCount
-> Effect Unit
fdWrite fd buff off len pos cb = mkEffect $ \_ -> runFn6 writeImpl fd buff off len (toNullable pos) (handleCallback cb)
fdWrite fd buff off len pos cb = runEffectFn6 writeImpl fd buff off len (toNullable pos) (handleCallback cb)

-- | Convenience function to append the whole buffer to the current
-- | file position.
Expand All @@ -381,4 +375,4 @@ fdAppend fd buff cb = do
fdClose :: FileDescriptor
-> Callback Unit
-> Effect Unit
fdClose fd cb = mkEffect $ \_ -> runFn2 closeImpl fd (handleCallback cb)
fdClose fd cb = runEffectFn2 closeImpl fd (handleCallback cb)
10 changes: 0 additions & 10 deletions src/Node/FS/Internal.purs

This file was deleted.

Loading

0 comments on commit b631e2c

Please sign in to comment.