Skip to content

Commit 36a75bb

Browse files
committed
Adding error handling to deserializer
1 parent a29346f commit 36a75bb

File tree

3 files changed

+74
-43
lines changed

3 files changed

+74
-43
lines changed

src/Data/ArrayBuffer/DataView.purs

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module Data.ArrayBuffer.DataView where
33
import Data.ArrayBuffer(ArrayBuffer())
44
import Data.ArrayBuffer.Types
55
import Data.Function
6+
import Data.Maybe
67
import Control.Monad.Eff
78

89
foreign import data DataView :: *
@@ -47,21 +48,19 @@ function byteLength(v) {
4748

4849
foreign import data Reader :: !
4950

50-
foreign import getter
51+
foreign import getterImpl
5152
"""
52-
function getter(s) {
53-
return function(v) {
54-
var f = v[s];
55-
return function(o) {
56-
return function() {
57-
return f.call(v,o);
58-
};
59-
};
53+
function getterImpl(just, nothing, s, l, v, o) {
54+
return function() {
55+
return (o + l) <= v.byteLength? just(v[s].call(v,o)) : nothing;
6056
};
6157
}
62-
""" :: forall e r. String -> DataView -> ByteOffset -> Eff (reader :: Reader | e) r
58+
""" :: forall e r. Fn6 (r -> Maybe r) (Maybe r) String ByteLength DataView ByteOffset (Eff (reader :: Reader | e) (Maybe r))
59+
60+
getter :: forall e r. String -> ByteLength -> DataView -> ByteOffset -> Eff (reader :: Reader | e) (Maybe r)
61+
getter = runFn6 getterImpl Just Nothing
6362

64-
type Getter r = forall e. DataView -> ByteOffset -> Eff (reader :: Reader | e) r
63+
type Getter r = forall e. DataView -> ByteOffset -> Eff (reader :: Reader | e) (Maybe r)
6564

6665
foreign import data Writer :: !
6766

@@ -85,31 +84,31 @@ type Setter r = forall e. DataView -> r -> ByteOffset -> Eff (writer :: Writer |
8584

8685

8786
getInt8 :: Getter Int8
88-
getInt8 = getter "getInt8"
87+
getInt8 = getter "getInt8" 1
8988

9089
getInt16 :: Getter Int16
91-
getInt16 = getter "getInt16"
90+
getInt16 = getter "getInt16" 2
9291

9392
getInt32 :: Getter Int32
94-
getInt32 = getter "getInt32"
93+
getInt32 = getter "getInt32" 4
9594

9695
getUint8 :: Getter Uint8
97-
getUint8 = getter "getUint8"
96+
getUint8 = getter "getUint8" 1
9897

9998
getUint16 :: Getter Uint16
100-
getUint16 = getter "getUint16"
99+
getUint16 = getter "getUint16" 2
101100

102101
getUint32 :: Getter Uint32
103-
getUint32 = getter "getUint32"
102+
getUint32 = getter "getUint32" 4
104103

105104
getUint8Clamped :: Getter Uint8Clamped
106-
getUint8Clamped = getter "getUint8Clamped"
105+
getUint8Clamped = getter "getUint8Clamped" 1
107106

108107
getFloat32 :: Getter Float32
109-
getFloat32 = getter "getFloat32"
108+
getFloat32 = getter "getFloat32" 4
110109

111110
getFloat64 :: Getter Float64
112-
getFloat64 = getter "getFloat64"
111+
getFloat64 = getter "getFloat64" 8
113112

114113

115114
setInt8 :: Setter Int8

src/Data/ArrayBuffer/Deserializer.purs

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module Data.ArrayBuffer.Deserializer where
22

3-
import Data.Function
3+
import Data.Either
4+
import Data.Maybe
45
import Control.Monad.Eff
56
import Data.ArrayBuffer.Advancer
67
import Data.ArrayBuffer.Types
@@ -11,24 +12,40 @@ import qualified Data.ArrayBuffer.DataView as DV
1112
type Deserializer = Advancer
1213

1314
class IsDeserializable a where
14-
get :: forall e. Deserializer -> Eff (reader :: DV.Reader | e) a
15+
get :: forall e. Deserializer -> Eff (reader :: DV.Reader | e) (Either String a)
16+
17+
chkErr :: forall a e. Maybe a -> Either String a
18+
chkErr x = case x of
19+
(Just v) -> Right v
20+
otherwise -> Left "Short read"
21+
22+
23+
getInt8 :: forall e. Deserializer -> Eff (reader :: DV.Reader | e) (Either String Int8)
24+
getInt8 d = chkErr <$> (advance 1 d >>= DV.getInt8 d.dv)
25+
getInt16 d = chkErr <$> (advance 2 d >>= DV.getInt16 d.dv)
26+
getInt32 d = chkErr <$> (advance 4 d >>= DV.getInt32 d.dv)
27+
getUint8 d = chkErr <$> (advance 1 d >>= DV.getUint8 d.dv)
28+
getUint16 d = chkErr <$> (advance 2 d >>= DV.getUint16 d.dv)
29+
getUint32 d = chkErr <$> (advance 4 d >>= DV.getUint32 d.dv)
30+
getFloat32 d = chkErr <$> (advance 4 d >>= DV.getFloat32 d.dv)
31+
getFloat64 d = chkErr <$> (advance 8 d >>= DV.getFloat64 d.dv)
1532

1633
instance isDeserializableInt8 :: IsDeserializable Int8 where
17-
get d = advance 1 d >>= DV.getInt8 d.dv
34+
get = getInt8
1835
instance isDeserializableInt16 :: IsDeserializable Int16 where
19-
get d = advance 2 d >>= DV.getInt16 d.dv
36+
get = getInt16
2037
instance isDeserializableInt32 :: IsDeserializable Int32 where
21-
get d = advance 4 d >>= DV.getInt32 d.dv
38+
get = getInt32
2239
instance isDeserializableUint8 :: IsDeserializable Uint8 where
23-
get d = advance 1 d >>= DV.getUint8 d.dv
40+
get = getUint8
2441
instance isDeserializableUint16 :: IsDeserializable Uint16 where
25-
get d = advance 2 d >>= DV.getUint16 d.dv
42+
get = getUint16
2643
instance isDeserializableUint32 :: IsDeserializable Uint32 where
27-
get d = advance 4 d >>= DV.getUint32 d.dv
44+
get = getUint32
2845
instance isDeserializableFloat32 :: IsDeserializable Float32 where
29-
get d = advance 4 d >>= DV.getFloat32 d.dv
46+
get = getFloat32
3047
instance isDeserializableFloat64 :: IsDeserializable Float64 where
31-
get d = advance 8 d >>= DV.getFloat64 d.dv
48+
get = getFloat64
3249

3350
getDataView :: forall e. Deserializer -> ByteLength -> Eff (reader :: DV.Reader | e) DV.DataView
3451
getDataView d n = do

test/Main.purs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module Test.Main where
22

33
import Debug.Trace
4+
import Data.Either
45
import Data.Maybe
56
import Test.QuickCheck
67
import Data.ArrayBuffer.Types
@@ -22,8 +23,10 @@ instance isSerializableComp :: S.IsSerializable Comp where
2223

2324
instance isDeserializableComp :: D.IsDeserializable Comp where
2425
get d = do
25-
(Int8 v) <- D.get d
26-
return $ Comp v
26+
v <- D.getInt8 d
27+
return $ case v of
28+
(Right (Int8 vv)) -> Right $ Comp vv
29+
(Left err) -> Left err
2730

2831
instance eqComp :: Eq Comp where
2932
(==) (Comp v0) (Comp v1) = v0 == v1
@@ -59,13 +62,13 @@ instance v4IsSerializable :: S.IsSerializable V4 where
5962

6063
instance v4IsDeserializable :: D.IsDeserializable V4 where
6164
get d = do
62-
let i8 = D.get d
63-
x <- i8
64-
y <- i8
65-
z <- i8
66-
t <- i8
67-
return $ V4 x y z t
68-
65+
let comp = D.get d
66+
x <- comp
67+
y <- comp
68+
z <- comp
69+
t <- comp
70+
return $ V4 <$> x <*> y <*> z <*> t
71+
6972
data M4 = M4 V4 V4 V4 V4
7073

7174
instance eqM4 :: Eq M4 where
@@ -94,7 +97,7 @@ instance m4IsDeserializable :: D.IsDeserializable M4 where
9497
y <- v4
9598
z <- v4
9699
t <- v4
97-
return $ M4 x y z t
100+
return $ M4 <$> x <*> y <*> z <*> t
98101

99102
foreign import ut """
100103
function ut(a) {
@@ -134,9 +137,9 @@ main = do
134137

135138
assert $ [1,2,3] == (TA.toArray $ TA.asInt8Array $ DV.whole $ AB.fromArray [1,2,3])
136139

137-
140+
quickCheck short
138141

139-
quickCheck' 5000 serdes
142+
quickCheck serdes
140143

141144
serdes :: M4 -> M4 -> M4 -> M4 -> Boolean
142145
serdes m0 m1 m2 m3 = forcePure $ do
@@ -152,7 +155,19 @@ serdes m0 m1 m2 m3 = forcePure $ do
152155
m1' <- g
153156
m2' <- g
154157
m3' <- g
155-
return $ m0 == m0' && m1 == m1' && m2 == m2' && m3 == m3'
158+
return $ (Right m0) == m0' && (Right m1) == m1' && (Right m2) == m2' && (Right m3) == m3'
159+
160+
short :: M4 -> M4 -> Boolean
161+
short m0 m1 = forcePure $ do
162+
a <- S.serialized 256 $ \s -> do
163+
let p = S.put s
164+
p m0
165+
d <- D.deserializer a
166+
let g = D.get d
167+
m0' <- g
168+
m1' <- g
169+
return $ m0' == (Right m0) && m1' /= (Right m1) && m1' == (Left "Short read")
170+
156171

157172

158173
assert :: Boolean -> QC Unit

0 commit comments

Comments
 (0)