Skip to content

Commit e012152

Browse files
AlexaDeWitjacereda
authored andcommitted
Initial prototype with text encoding backend for arraybuffer morphisms
with string
1 parent 1249576 commit e012152

File tree

7 files changed

+56
-38
lines changed

7 files changed

+56
-38
lines changed

Diff for: .gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ bower_components/
44
node_modules/
55
.psci
66
.psci_modules/
7+
yarn-error.log
8+
yarn.lock

Diff for: README.md

+4
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@ ArrayBuffer bindings for PureScript.
1313

1414
Module documentation is [published on Pursuit](http://pursuit.purescript.org/packages/purescript-arraybuffer).
1515

16+
17+
## Important Usage Notes
18+
19+
- Usage of the ArrayBuffer<->String conversion functions requires the import of the NPM package 'text-encoding'.

Diff for: bower.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
"purescript-arraybuffer-types": "^2.0.0",
1717
"purescript-maybe": "^4.0.0",
1818
"purescript-effect": "^2.0.0",
19-
"purescript-uint": "^4.0.0"
19+
"purescript-uint": "^4.0.0",
20+
"purescript-text-encoding": "^0.0.7"
2021
},
2122
"devDependencies": {
2223
"purescript-debug": "^4.0.0",

Diff for: package.json

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "purescript-arraybuffer",
3+
"version": "7.0.0",
4+
"main": "index.js",
5+
"repository": "git@github.com:jacereda/purescript-arraybuffer.git",
6+
"author": "https://github.com/jacereda",
7+
"license": "MIT",
8+
"devDependencies": {
9+
"text-encoding": "^0.6.4"
10+
}
11+
12+
}

Diff for: src/Data/ArrayBuffer/ArrayBuffer.js

-18
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,3 @@ exports.fromArray = function(s) {
2525
exports.fromIntArray = function(s) {
2626
return (new Uint8Array(s)).buffer;
2727
};
28-
29-
exports.fromString = function(s) {
30-
var buf = new ArrayBuffer(s.length*2);
31-
var bufView = new Uint16Array(buf);
32-
for (var i=0, strLen=s.length; i<strLen; i++) {
33-
bufView[i] = s.charCodeAt(i);
34-
}
35-
return buf;
36-
};
37-
38-
exports.decodeToStringImpl = function(just, nothing, buffer) {
39-
try {
40-
return just(String.fromCharCode.apply(null, new Uint16Array(buffer)));
41-
}
42-
catch (e) {
43-
return nothing;
44-
}
45-
};

Diff for: src/Data/ArrayBuffer/ArrayBuffer.purs

+23-13
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,17 @@ module Data.ArrayBuffer.ArrayBuffer ( create
77
, decodeToString
88
) where
99

10-
import Effect (Effect)
11-
import Data.Maybe (Maybe(..))
12-
import Data.Function.Uncurried (Fn3, runFn3)
10+
import Data.ArrayBuffer.DataView (whole, buffer)
11+
import Data.ArrayBuffer.Typed (asUint8Array, dataView)
1312
import Data.ArrayBuffer.Types (ArrayBuffer, ByteOffset, ByteLength)
13+
import Data.Either (Either)
14+
import Data.Function.Uncurried (Fn3, runFn3)
15+
import Data.TextDecoder (decodeUtf8)
16+
import Data.TextEncoder (encodeUtf8)
17+
import Effect (Effect)
18+
import Effect.Exception (Error)
19+
import Prelude ((<<<))
20+
1421

1522
-- | Create an `ArrayBuffer` with the given capacity.
1623
foreign import create :: ByteLength -> Effect ArrayBuffer
@@ -30,13 +37,16 @@ foreign import fromArray :: Array Number -> ArrayBuffer
3037
-- | Convert an array into an `ArrayBuffer` representation.
3138
foreign import fromIntArray :: Array Int -> ArrayBuffer
3239

33-
-- | Convert a string into an `ArrayBuffer` representation.
34-
foreign import fromString :: String -> ArrayBuffer
35-
36-
foreign import decodeToStringImpl :: Fn3 (String -> Maybe String) (Maybe String) ArrayBuffer (Maybe String)
37-
38-
-- | Convert an ArrayBuffer into a string. Uses fromCharCode and thus does not support full utf-16
39-
-- | Is currently only defined for ArrayBuffers with even numbers of bytes, as it assumes the ArrayBuffer encodes string data.
40-
-- | For more general string-encoding forms of data, use a base64 or other encoding scheme.
41-
decodeToString :: ArrayBuffer -> Maybe String
42-
decodeToString = runFn3 decodeToStringImpl Just Nothing
40+
-- | Convert a UTF-8 encoded `ArrayBuffer` into a `String`.
41+
-- | Serves as a quick utility function for a common use-case. For more use-cases,
42+
-- | see: [purescript-text-encoding](https://pursuit.purescript.org/packages/purescript-text-encoding/0.0.7)
43+
-- | Requires the TextDecoder class available. A polyfill can be found in the npm package "text-encoding"
44+
decodeToString :: ArrayBuffer -> Either Error String
45+
decodeToString = decodeUtf8 <<< asUint8Array <<< whole
46+
47+
-- | Convert a `String` into a UTF-8 encoded `ArrayBuffer`.
48+
-- | Serves as a quick utility function for a common use-case. For more use-cases,
49+
-- | see: [purescript-text-encoding](https://pursuit.purescript.org/packages/purescript-text-encoding/0.0.7)
50+
-- | Requires the TextDecoder class available. A polyfill can be found in the npm package "text-encoding"
51+
fromString :: String -> ArrayBuffer
52+
fromString = buffer <<< dataView <<< encodeUtf8

Diff for: test/Main.purs

+13-6
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ import Effect (Effect)
66
import Data.ArrayBuffer.ArrayBuffer as AB
77
import Data.ArrayBuffer.DataView as DV
88
import Data.ArrayBuffer.Typed as TA
9+
import Data.Either (fromRight)
910
import Data.Maybe (Maybe(..), isNothing)
1011
import Data.UInt (fromInt, pow)
12+
import Partial.Unsafe (unsafePartial)
1113
import Test.QuickCheck (quickCheck', (<?>), quickCheck)
1214

1315
assertEffEquals :: forall a. Eq a => Show a => a -> Effect a -> Effect Unit
@@ -35,9 +37,9 @@ main = do
3537
assertEquals (Just 2) $ DV.byteLength <$> DV.slice 2 2 ab4
3638
assertEquals 4 $ AB.byteLength $ AB.fromArray [1.0, 2.0, 3.0, 4.0]
3739
assertEquals 4 $ AB.byteLength $ AB.fromIntArray [1, 2, 3, 4]
38-
assertEquals 8 $ AB.byteLength $ AB.fromString "hola"
39-
assertEquals 8 $ AB.byteLength $ AB.fromString "hóla"
40-
assertEquals 10 $ AB.byteLength $ AB.fromString "hóla¡"
40+
assertEquals 4 $ AB.byteLength $ AB.fromString "hola"
41+
assertEquals 5 $ AB.byteLength $ AB.fromString "hóla"
42+
assertEquals 7 $ AB.byteLength $ AB.fromString "hóla¡"
4143
assertEquals 8 $ AB.byteLength $ DV.buffer $ DV.whole ab8
4244
assertEquals 8 $ AB.byteLength $ DV.buffer $ TA.dataView $ TA.asInt8Array $ DV.whole ab8
4345

@@ -51,9 +53,14 @@ main = do
5153

5254
quickCheck
5355
\(s) ->
54-
Just s == (AB.decodeToString $ AB.fromString s)
55-
<?> "Isormorphic arraybuffer conversion with string failed for input "
56-
<> s
56+
let
57+
result = (unsafePartial $ fromRight $ AB.decodeToString $ AB.fromString s)
58+
in
59+
s == result
60+
<?> "Isormorphic arraybuffer conversion with string failed for input\n"
61+
<> s
62+
<> " which, after the round trip, result in\n"
63+
<> result
5764

5865
assertEquals [1.0, 2.0, 3.0] $ TA.toArray <<< TA.asInt8Array <<< DV.whole $ AB.fromArray [1.0, 2.0, 3.0]
5966

0 commit comments

Comments
 (0)