Skip to content

Commit c81554a

Browse files
committed
Add onDataEither
Useful in the case where `setEncoding` has been called, although this is a bad idea in most cases.
1 parent c659700 commit c81554a

File tree

4 files changed

+91
-42
lines changed

4 files changed

+91
-42
lines changed

bower.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
"dependencies": {
2121
"purescript-eff": "~0.1.1",
2222
"purescript-node-buffer": "~0.2.0",
23-
"purescript-prelude": "~0.1.2"
23+
"purescript-prelude": "~0.1.2",
24+
"purescript-either": "~0.2.3",
25+
"purescript-exceptions": "~0.3.3"
2426
}
2527
}

docs/Node/Stream.md

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,34 +55,47 @@ type Duplex = Stream (read :: Read, write :: Write)
5555

5656
A duplex (readable _and_ writable stream)
5757

58-
#### `setEncoding`
58+
#### `onData`
5959

6060
``` purescript
61-
setEncoding :: forall w eff. Readable w eff -> Encoding -> Eff eff Unit
61+
onData :: forall w eff. Readable w (err :: EXCEPTION | eff) -> (Buffer -> Eff (err :: EXCEPTION | eff) Unit) -> Eff (err :: EXCEPTION | eff) Unit
6262
```
6363

64-
Set the encoding used to read chunks as strings from the stream. This
65-
function is useful when you are passing a readable stream to some other
66-
JavaScript library, which already expects an encoding to be set. It
67-
has no effect on the behaviour of the `onDataString` function (because
68-
that function ensures that the encoding is always supplied explicitly).
64+
Listen for `data` events, returning data in a Buffer. Note that this will fail
65+
if `setEncoding` has been called on the stream.
6966

70-
#### `onData`
67+
#### `onDataString`
7168

7269
``` purescript
73-
onData :: forall w eff. Readable w eff -> (Buffer -> Eff eff Unit) -> Eff eff Unit
70+
onDataString :: forall w eff. Readable w (err :: EXCEPTION | eff) -> Encoding -> (String -> Eff (err :: EXCEPTION | eff) Unit) -> Eff (err :: EXCEPTION | eff) Unit
7471
```
7572

76-
Listen for `data` events, returning data in a Buffer.
73+
Listen for `data` events, returning data in a String, which will be
74+
decoded using the given encoding. Note that this will fail if `setEncoding`
75+
has been called on the stream.
7776

78-
#### `onDataString`
77+
#### `onDataEither`
7978

8079
``` purescript
81-
onDataString :: forall w eff. Readable w eff -> Encoding -> (String -> Eff eff Unit) -> Eff eff Unit
80+
onDataEither :: forall w eff. Readable w eff -> (Either String Buffer -> Eff eff Unit) -> Eff eff Unit
8281
```
8382

84-
Listen for `data` events, returning data in a String, which will be
85-
decoded using the given encoding.
83+
Listen for `data` events, returning data in an `Either String Buffer`. This
84+
function is provided for the (hopefully rare) case that `setEncoding` has
85+
been called on the stream.
86+
87+
#### `setEncoding`
88+
89+
``` purescript
90+
setEncoding :: forall w eff. Readable w eff -> Encoding -> Eff eff Unit
91+
```
92+
93+
Set the encoding used to read chunks as strings from the stream. This
94+
function may be useful when you are passing a readable stream to some other
95+
JavaScript library, which already expects an encoding to be set.
96+
97+
Where possible, you should try to use `onDataString` instead of this
98+
function.
8699

87100
#### `onEnd`
88101

src/Node/Stream.js

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/* global exports */
2+
/* global Buffer */
23
"use strict";
34

45
// module Node.Stream
@@ -11,15 +12,27 @@ exports.setEncodingImpl = function(s) {
1112
};
1213
};
1314

14-
exports.onDataImpl = function(s) {
15-
return function(f) {
16-
return function() {
17-
s.on('data', function(chunk) {
18-
if (!(chunk instanceof Buffer)) {
19-
throw new Error("Node.Stream.onDataImpl: stream encoding should not be set");
20-
}
21-
f(chunk)();
22-
});
15+
exports.onDataEitherImpl = function(left){
16+
return function(right){
17+
return function(s) {
18+
return function(f) {
19+
return function() {
20+
s.on('data', function(chunk) {
21+
if (chunk instanceof Buffer) {
22+
f(right(chunk))();
23+
}
24+
else if (chunk instanceof String) {
25+
f(left(chunk))();
26+
}
27+
else {
28+
throw new Error(
29+
"Node.Stream.onDataEitherImpl: Unrecognised" +
30+
"chunk type; expected String or Buffer, got:" +
31+
chunk);
32+
}
33+
});
34+
};
35+
};
2336
};
2437
};
2538
};

src/Node/Stream.purs

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ module Node.Stream
77
, Write()
88
, Writable()
99
, Duplex()
10-
, setEncoding
1110
, onData
1211
, onDataString
12+
, onDataEither
13+
, setEncoding
1314
, onEnd
1415
, onClose
1516
, onError
@@ -27,11 +28,14 @@ module Node.Stream
2728

2829
import Prelude
2930

31+
import Control.Bind ((<=<))
32+
import Data.Either (Either(..))
3033
import Node.Encoding
3134
import Node.Buffer (Buffer())
3235
import Node.Buffer as Buffer
3336

3437
import Control.Monad.Eff
38+
import Control.Monad.Eff.Exception (throw, EXCEPTION())
3539
import Control.Monad.Eff.Unsafe (unsafeInterleaveEff)
3640

3741
-- | A stream.
@@ -57,29 +61,46 @@ type Writable r = Stream (write :: Write | r)
5761
-- | A duplex (readable _and_ writable stream)
5862
type Duplex = Stream (read :: Read, write :: Write)
5963

60-
foreign import setEncodingImpl :: forall w eff. Readable w eff -> String -> Eff eff Unit
61-
62-
-- | Set the encoding used to read chunks as strings from the stream. This
63-
-- | function is useful when you are passing a readable stream to some other
64-
-- | JavaScript library, which already expects an encoding to be set. It
65-
-- | has no effect on the behaviour of the `onDataString` function (because
66-
-- | that function ensures that the encoding is always supplied explicitly).
67-
setEncoding :: forall w eff. Readable w eff -> Encoding -> Eff eff Unit
68-
setEncoding r enc = setEncodingImpl r (show enc)
69-
70-
foreign import onDataImpl :: forall w eff a. Readable w eff -> (a -> Eff eff Unit) -> Eff eff Unit
71-
72-
-- | Listen for `data` events, returning data in a Buffer.
73-
onData :: forall w eff. Readable w eff -> (Buffer -> Eff eff Unit) -> Eff eff Unit
74-
onData = onDataImpl
64+
-- | Listen for `data` events, returning data in a Buffer. Note that this will fail
65+
-- | if `setEncoding` has been called on the stream.
66+
onData :: forall w eff. Readable w (err :: EXCEPTION | eff) -> (Buffer -> Eff (err :: EXCEPTION | eff) Unit) -> Eff (err :: EXCEPTION | eff) Unit
67+
onData r cb =
68+
onDataEither r (cb <=< fromEither)
69+
where
70+
fromEither x =
71+
case x of
72+
Left _ ->
73+
throw "Node.Stream.onData: Stream encoding should not be set"
74+
Right buf ->
75+
pure buf
7576

7677
-- | Listen for `data` events, returning data in a String, which will be
77-
-- | decoded using the given encoding.
78-
onDataString :: forall w eff. Readable w eff -> Encoding -> (String -> Eff eff Unit) -> Eff eff Unit
78+
-- | decoded using the given encoding. Note that this will fail if `setEncoding`
79+
-- | has been called on the stream.
80+
onDataString :: forall w eff. Readable w (err :: EXCEPTION | eff) -> Encoding -> (String -> Eff (err :: EXCEPTION | eff) Unit) -> Eff (err :: EXCEPTION | eff) Unit
7981
onDataString r enc cb = onData r $ \buf -> do
8082
str <- unsafeInterleaveEff (Buffer.toString enc buf)
8183
cb str
8284

85+
foreign import onDataEitherImpl :: forall w eff. (forall l r. l -> Either l r) -> (forall l r. r -> Either l r) -> Readable w eff -> (Either String Buffer -> Eff eff Unit) -> Eff eff Unit
86+
87+
-- | Listen for `data` events, returning data in an `Either String Buffer`. This
88+
-- | function is provided for the (hopefully rare) case that `setEncoding` has
89+
-- | been called on the stream.
90+
onDataEither :: forall w eff. Readable w eff -> (Either String Buffer -> Eff eff Unit) -> Eff eff Unit
91+
onDataEither = onDataEitherImpl Left Right
92+
93+
foreign import setEncodingImpl :: forall w eff. Readable w eff -> String -> Eff eff Unit
94+
95+
-- | Set the encoding used to read chunks as strings from the stream. This
96+
-- | function may be useful when you are passing a readable stream to some other
97+
-- | JavaScript library, which already expects an encoding to be set.
98+
-- |
99+
-- | Where possible, you should try to use `onDataString` instead of this
100+
-- | function.
101+
setEncoding :: forall w eff. Readable w eff -> Encoding -> Eff eff Unit
102+
setEncoding r enc = setEncodingImpl r (show enc)
103+
83104
-- | Listen for `end` events.
84105
foreign import onEnd :: forall w eff. Readable w eff -> Eff eff Unit -> Eff eff Unit
85106

0 commit comments

Comments
 (0)