Skip to content

Commit e208591

Browse files
committed
Error handling in array deserialization
1 parent 36a75bb commit e208591

File tree

4 files changed

+34
-21
lines changed

4 files changed

+34
-21
lines changed

src/Data/ArrayBuffer/DataView.purs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ function whole(b) {
1717

1818
foreign import sliceImpl
1919
"""
20-
function sliceImpl(s, l, b) {
21-
return new DataView(b, s, l);
20+
function sliceImpl(just, nothing, s, l, b) {
21+
return s + l <= b.byteLength? just(new DataView(b, s, l)) : nothing;
2222
}
23-
""" :: forall e. Fn3 ByteOffset ByteLength ArrayBuffer DataView
24-
slice :: forall e. ByteOffset -> ByteLength -> ArrayBuffer -> DataView
25-
slice = runFn3 sliceImpl
23+
""" :: forall e. Fn5 (DataView -> Maybe DataView) (Maybe DataView) ByteOffset ByteLength ArrayBuffer (Maybe DataView)
24+
slice :: forall e. ByteOffset -> ByteLength -> ArrayBuffer -> Maybe DataView
25+
slice = runFn5 sliceImpl Just Nothing
2626

2727
foreign import buffer
2828
"""

src/Data/ArrayBuffer/Deserializer.purs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,31 +47,42 @@ instance isDeserializableFloat32 :: IsDeserializable Float32 where
4747
instance isDeserializableFloat64 :: IsDeserializable Float64 where
4848
get = getFloat64
4949

50-
getDataView :: forall e. Deserializer -> ByteLength -> Eff (reader :: DV.Reader | e) DV.DataView
50+
getDataView :: forall e. Deserializer -> ByteLength -> Eff (reader :: DV.Reader | e) (Either String DV.DataView)
5151
getDataView d n = do
5252
o <- advance n d
53-
return $ DV.slice o n (DV.buffer d.dv)
53+
return $ case DV.slice o n (DV.buffer d.dv) of
54+
(Just dv) -> Right dv
55+
otherwise -> Left "short read"
56+
57+
type AD t = forall e. Deserializer -> Number -> Eff (reader :: DV.Reader | e) (Either String t)
58+
59+
60+
getTypedArray :: forall e t. Deserializer -> Number -> (DV.DataView -> t) -> Eff (reader :: DV.Reader | e) (Either String t)
61+
getTypedArray d sz conv = do
62+
edv <- getDataView d sz
63+
return $ case edv of
64+
Right dv -> Right $ conv dv
65+
Left err -> Left err
5466

55-
type AD t = forall e. Deserializer -> Number -> Eff (reader :: DV.Reader | e) t
5667

5768
getInt8Array :: AD TA.Int8Array
58-
getInt8Array d n = getDataView d n >>= return <<< TA.asInt8Array
69+
getInt8Array d n = getTypedArray d n TA.asInt8Array
5970
getInt16Array :: AD TA.Int16Array
60-
getInt16Array d n = getDataView d (n * 2) >>= return <<< TA.asInt16Array
71+
getInt16Array d n = getTypedArray d (n * 2) TA.asInt16Array
6172
getInt32Array :: AD TA.Int32Array
62-
getInt32Array d n = getDataView d (n * 4) >>= return <<< TA.asInt32Array
73+
getInt32Array d n = getTypedArray d (n * 4) TA.asInt32Array
6374
getUint8Array :: AD TA.Uint8Array
64-
getUint8Array d n = getDataView d n >>= return <<< TA.asUint8Array
75+
getUint8Array d n = getTypedArray d n TA.asUint8Array
6576
getUint16Array :: AD TA.Uint16Array
66-
getUint16Array d n = getDataView d (n * 2) >>= return <<< TA.asUint16Array
77+
getUint16Array d n = getTypedArray d (n * 2) TA.asUint16Array
6778
getUint32Array :: AD TA.Uint32Array
68-
getUint32Array d n = getDataView d (n * 4) >>= return <<< TA.asUint32Array
79+
getUint32Array d n = getTypedArray d (n * 4) TA.asUint32Array
6980
getUint8ClampedArray :: AD TA.Uint8ClampedArray
70-
getUint8ClampedArray d n = getDataView d n >>= return <<< TA.asUint8ClampedArray
81+
getUint8ClampedArray d n = getTypedArray d n TA.asUint8ClampedArray
7182
getFloat32Array :: AD TA.Float32Array
72-
getFloat32Array d n = getDataView d (n * 4) >>= return <<< TA.asFloat32Array
83+
getFloat32Array d n = getTypedArray d (n * 4) TA.asFloat32Array
7384
getFloat64Array :: AD TA.Float64Array
74-
getFloat64Array d n = getDataView d (n * 8) >>= return <<< TA.asFloat64Array
85+
getFloat64Array d n = getTypedArray d (n * 8) TA.asFloat64Array
7586

7687
deserializer :: forall e. AB.ArrayBuffer -> Eff (reader :: DV.Reader | e) Deserializer
7788
deserializer ab = return $ { dv : DV.whole ab, off : 0 }

src/Data/ArrayBuffer/Serializer.purs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import qualified Data.ArrayBuffer as AB
55
import qualified Data.ArrayBuffer.DataView as DV
66
import Data.ArrayBuffer.Advancer
77
import Data.Function
8+
import Data.Maybe
89
import Control.Monad.Eff
910

1011
type Serializer = Advancer
@@ -29,7 +30,7 @@ instance isSerializableFloat32 :: IsSerializable Float32 where
2930
instance isSerializableFloat64 :: IsSerializable Float64 where
3031
put s v = advance 8 s >>= DV.setFloat64 s.dv v
3132

32-
mapDataView :: forall e. Serializer -> ByteLength -> Eff (writer :: DV.Writer | e) DV.DataView
33+
mapDataView :: forall e. Serializer -> ByteLength -> Eff (writer :: DV.Writer | e) (Maybe DV.DataView)
3334
mapDataView s n = do
3435
o <- advance n s
3536
return $ DV.slice o n (DV.buffer s.dv)

test/Main.purs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ main = do
114114
assert $ AB.byteLength (AB.slice 2 4 ab) == 2
115115
assert $ AB.byteLength (AB.slice (-2) (-2) ab) == 0
116116
assert $ AB.byteLength (AB.slice (-2) (-1) ab) == 1
117-
assert $ DV.byteLength (DV.slice 0 2 ab) == 2
118-
assert $ DV.byteLength (DV.slice 2 2 ab) == 2
117+
assert $ (DV.byteLength <$> (DV.slice 0 2 ab)) == Just 2
118+
assert $ (DV.byteLength <$> (DV.slice 2 2 ab)) == Just 2
119119
let aab = AB.fromArray [1, 2, 3, 4]
120120
assert $ AB.byteLength aab == 4
121121
let sab = AB.fromString "hola"
@@ -127,7 +127,8 @@ main = do
127127

128128
assert $ AB.byteLength (DV.buffer $ TA.dataView (TA.asInt8Array dv)) == 8
129129

130-
assert $ DV.byteLength (DV.slice 0 4 nab) == 4
130+
assert $ (DV.byteLength <$> DV.slice 0 4 nab) == Just 4
131+
assert $ (DV.byteLength <$> DV.slice 0 40 nab) == Nothing
131132

132133
assert $ do
133134
let ab = AB.fromArray [1,2,3,4]

0 commit comments

Comments
 (0)