ASN1-0.0.1: BERTest.hs
module Main(main) where
import Data.Char
import Data.Maybe
import Control.Monad.Error
import Control.Monad.State
import Language.ASN1.BER
import Language.ASN1
import Test.HUnit
{-
Some of the ASN.1 definitions are taken from various standards and
these are annotated with references. The other ASN.1 definitions
have been created specifically to check decoding. These have been
checked using the on-line tool, Asnp, available at
http://asn1.elibel.tm.fr/en/tools/asnp/index.htm
Notes: Definitions using ANY DEFINED BY have to be checked with -1990
option. Asnp was developed in Objective Caml.
-}
expectSuccess testName asnType berValue expectedAbsValue =
TestCase $
do (w,x) <- typeCheck asnType berValue
let (_ ::= c) = w
d = decode c (Just x)
(Just y) = d
assertEqual testName expectedAbsValue y
expectFailure testName asnType berValue expectedError =
TestCase $
do x <- (do y <- typeCheck asnType berValue
return "Unexpected successful typechecking")
`catchError` (\e -> return $ show e)
assertEqual testName x expectedError
{-
Some tagged value tests. See 8.14.3 of X.690 (ISO 8825-1).
Type1 ::= VisibleString
Type2 ::= [APPLICATION 3] IMPLICIT Type1
Type3 ::= [2] Type2
Type4 ::= [APPLICATION 7] IMPLICIT Type3
Type5 ::= [2] IMPLICIT Type2
-}
type1' = modName "Type1" absVisibleString
type Type1 = VisibleString
jones1 = Primitive Universal 26 5 [0x4a,0x6f,0x6e,0x65,0x73]
decodedJones1 = VisibleString "Jones"
tagTest1 = expectSuccess "Type1" type1' jones1 decodedJones1
type2 = "Type2" ::= AbsRef Application 3 Implicit type1'
data Type2 = Type2 VisibleString
deriving (Eq,Show)
instance Encode Type2 where
decode a b =
do x <- decode a b
return $ Type2 x
jones2 = Primitive Application 3 5 [0x4a,0x6f,0x6e,0x65,0x73]
decodedJones2 = Type2 decodedJones1
tagTest2 = expectSuccess "Type2" type2 jones2 decodedJones2
type3 = "Type3" ::= AbsRef Context 2 Explicit type2
data Type3 = Type3 Type2
deriving (Eq,Show)
instance Encode Type3 where
decode a b =
do y <- b
let a' = absRefedType a
b' = (encodedDefComps y)!!0
x <- decode a' b'
return $ Type3 x
jones3 = Constructed Context 2 7 [jones2]
decodedJones3 = Type3 decodedJones2
tagTest3 = expectSuccess "Type3" type3 jones3 decodedJones3
type4 = "Type4" ::= AbsRef Application 7 Implicit type3
jones4 = Constructed Application 7 7 [jones2]
data Type4 = Type4 Type3
deriving (Eq,Show)
instance Encode Type4 where
decode a b =
do x <- decode a b
return $ Type4 x
decodedJones4 = Type4 decodedJones3
tagTest4 = expectSuccess "Type4" type4 jones4 decodedJones4
{-
Some tests for OPTIONAL components.
-}
{-
Journey ::=
SEQUENCE {
origin IA5String,
stop1 [0] IA5String OPTIONAL,
stop2 [1] IA5String OPTIONAL,
destination IA5String
}
-}
journey =
"Journey" ::=
AbsSeq Universal 16 Implicit [
Regular (Just "origin" :>: (Nothing :@: absIA5String)),
Optional (Just "stop1" :>: (Just 0 :@: absIA5String)),
Optional (Just "stop2" :>: (Just 1 :@: absIA5String)),
Regular (Just "destination" :>: (Nothing :@: absIA5String))
]
j1 =
Constructed Universal 16 24 [
Primitive Universal 22 3 [97,97,98],
Primitive Context 0 3 [99,100,101],
Primitive Context 1 3 [102,103,104],
Primitive Universal 22 3 [97,97,98]
]
j2 =
Constructed Universal 16 24 [
Primitive Universal 22 3 [97,97,98],
Primitive Context 1 3 [102,103,104],
Primitive Universal 22 3 [97,97,98]
]
data Journey =
Journey {
origin :: IA5String,
stop1 :: Maybe IA5String,
stop2 :: Maybe IA5String,
destination :: IA5String
}
deriving (Eq,Show)
instance Encode Journey where
decode a b =
do x <- b
let as = absSeqComponents a
bs = encodedDefComps x
return $
Journey {
origin = fromJust (decode (as!!0) (bs!!0)),
stop1 = do decode (as!!1) (bs!!1),
stop2 = do decode (as!!2) (bs!!2),
destination = fromJust (decode (as!!3) (bs!!3))
}
decodedJ1 =
Journey {
origin = IA5String "aab",
stop1 = Just $ IA5String "cde",
stop2 = Just $ IA5String "fgh",
destination = IA5String "aab"
}
decodedJ2 =
Journey {
origin = IA5String "aab",
stop1 = Nothing,
stop2 = Just $ IA5String "fgh",
destination = IA5String "aab"
}
journeyTest1 =
expectSuccess "Journey1" journey j1 decodedJ1
journeyTest2 =
expectSuccess "Journey2" journey j2 decodedJ2
{-
Odyssey ::= SEQUENCE {
start Journey,
trip1 [0] Journey OPTIONAL,
trip2 [1] Journey OPTIONAL,
trip3 [2] Journey OPTIONAL,
end Journey
}
-}
odyssey =
"Odyssey" ::=
AbsSeq Universal 16 Implicit [
Regular (Just "start" :>: (Nothing :@: journey)),
Optional (Just "trip1" :>: (Just 0 :@: journey)),
Optional (Just "trip2" :>: (Just 1 :@: journey)),
Optional (Just "trip3" :>: (Just 2 :@: journey)),
Regular (Just "end" :>: (Nothing :@: journey))
]
prej1 = [
Primitive Universal 22 3 [97,97,98],
Primitive Context 0 3 [99,100,101],
Primitive Context 1 3 [102,103,104],
Primitive Universal 22 3 [97,97,98]
]
o1 =
Constructed Universal 16 130 [
j1,
Constructed Context 0 26 prej1,
Constructed Context 1 26 prej1,
Constructed Context 2 26 prej1,
j1
]
o2 =
Constructed Universal 16 52 [
j1,
j1
]
data Odyssey =
Odyssey {
start :: Journey,
trip1 :: Maybe Journey,
trip2 :: Maybe Journey,
trip3 :: Maybe Journey,
end :: Journey
}
deriving (Eq,Show)
instance Encode Odyssey where
decode a b =
do x <- b
let as = absSeqComponents a
bs = encodedDefComps x
return $
Odyssey {
start = fromJust (decode (as!!0) (bs!!0)),
trip1 = do decode (as!!1) (bs!!1),
trip2 = do decode (as!!2) (bs!!2),
trip3 = do decode (as!!3) (bs!!3),
end = fromJust (decode (as!!4) (bs!!4))
}
decodedO1 =
Odyssey {
start = decodedJ1,
trip1 = Just decodedJ1,
trip2 = Just decodedJ1,
trip3 = Just decodedJ1,
end = decodedJ1
}
decodedO2 =
Odyssey {
start = decodedJ1,
trip1 = Nothing,
trip2 = Nothing,
trip3 = Nothing,
end = decodedJ1
}
odysseyTest1 =
expectSuccess "Odyssey1" odyssey o1 decodedO1
odysseyTest2 =
expectSuccess "Odyssey2" odyssey o2 decodedO2
{-
FunnyOptional ::=
SEQUENCE {
perhaps [0] IA5String OPTIONAL
}
-}
funnyOptional =
"FunnyOptional" ::=
AbsSeq Universal 16 Implicit [
Optional (Just "perhaps" :>: (Just 0 :@: absIA5String))
]
fo1 =
Constructed Universal 16 7 [
Primitive Context 0 3 [97,97,98]
]
fo2 = Constructed Universal 16 0 []
data FunnyOptional =
FunnyOptional {
perhaps :: Maybe IA5String
}
deriving (Eq,Show)
instance Encode FunnyOptional where
decode a b =
do x <- b
let as = absSeqComponents a
bs = encodedDefComps x
return $
FunnyOptional {
perhaps = do decode (as!!0) (bs!!0)
}
decodedFO1 =
FunnyOptional {
perhaps = Just $ IA5String "aab"
}
funnyOptionalTest1 =
expectSuccess "FunnyOptional1" funnyOptional fo1 decodedFO1
decodedFO2 =
FunnyOptional {
perhaps = Nothing
}
funnyOptionalTest2 =
expectSuccess "FunnyOptional2" funnyOptional fo2 decodedFO2
{-
Some ANY DEFINED BY tests. See the former versions of the ASN.1
standards, X.208 and X.209, sometimes referred to as ASN.1:1988 or
ASN.1:1990. This was used in some definitions of X.509 certificates,
for example:
AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL }
-- contains a value of the type
-- registered for use with the
-- algorithm object identifier value
-}
{-
TextBook = SEQUENCE
{
author PrintableString,
citationType OID,
reference ANY DEFINED BY CitationType
}
-}
textBook =
"TextBook" ::=
AbsSeq Universal 16 Implicit
[Regular (Just "author" :>: (Nothing :@: absPrintableString)),
Regular (Just "citationType" :>: (Nothing :@: absOID)),
AnyDefBy 1]
data TextBook =
TextBook {
author :: PrintableString,
citationType :: OID,
reference :: PrintableString
}
deriving (Eq,Show)
instance Encode TextBook where
decode a b =
do x <- b
let as = absSeqComponents a
bs = encodedDefComps x
return $
TextBook {
author = fromJust $ decode (as!!0) (bs!!0),
citationType = fromJust $ decode (as!!1) (bs!!1),
reference = fromJust $ decode (as!!2) (bs!!2)
}
encodedPrintableString1 =
Primitive Universal 19 5 [104,101,108,108,111]
encodedPrintableString2 =
Primitive Universal 19 5 [105,101,108,108,111]
encodedPrintableString3 =
Primitive Universal 19 5 [106,101,108,108,111]
encodedPrintableString4 =
Primitive Universal 19 5 [107,101,108,108,111]
encodedOID1 = Primitive Universal 6 3 [85,4,7]
encodedTextBook1 =
Constructed Universal 16 13 [
encodedPrintableString1,
encodedOID1
]
decodedTextBook1 =
"user error (Checking AnyDefBy 1: insufficient components)"
encodedTextBook2 =
Constructed Universal 16 13 [
encodedPrintableString1,
encodedOID1,
encodedPrintableString2
]
decodedTextBook2 =
TextBook {
author = PrintableString "hello",
citationType = OID [2,5,4,7],
reference = PrintableString "iello"
}
encodedTextBook3 =
Constructed Universal 16 13 [
encodedPrintableString3,
encodedOID1,
encodedPrintableString4
]
decodedTextBook3 =
TextBook {
author = PrintableString "jello",
citationType = OID [2,5,4,7],
reference = PrintableString "kello"
}
textBookTest1 =
expectFailure "TextBook1" textBook encodedTextBook1 decodedTextBook1
textBookTest2 =
expectSuccess "TextBook2" textBook encodedTextBook2 decodedTextBook2
textBookTest3 =
expectSuccess "TextBook3" textBook encodedTextBook3 decodedTextBook3
library =
"Library" ::=
AbsSeq Universal 16 Implicit
[Regular (Just "first" :>: (Nothing :@: textBook)),
Regular (Just "second" :>: (Nothing :@: textBook))]
data Library =
Library {
first :: TextBook,
second :: TextBook
}
deriving (Eq,Show)
instance Encode Library where
decode a b =
do x <- b
let as = absSeqComponents a
bs = encodedDefComps x
return $
Library {
first = fromJust $ decode (as!!0) (bs!!0),
second = fromJust $ decode (as!!1) (bs!!1)
}
encodedLibrary =
Constructed Universal 16 28 [encodedTextBook2,encodedTextBook3]
decodedLibrary =
Library {
first = decodedTextBook2,
second = decodedTextBook3
}
libraryTest =
expectSuccess "Library1" library encodedLibrary decodedLibrary
v1 = Primitive Universal 26 5 [104,101,108,108,111] -- Valid
v2 = Primitive Universal 26 5 [103,101,108,108,111] -- Valid
v3 = Primitive Universal 26 5 [31,101,108,108,111] -- Not valid VisibleString
expectedv1 = VisibleString "hello"
expectedv2 = VisibleString "gello"
expectedv3 =
"user error (Checking \"VisibleString\": type not compatible " ++
"with values [31,101,108,108,111])"
visibleStringTest1 =
expectSuccess "VisibleString1" absVisibleString v1 expectedv1
visibleStringTest2 =
expectSuccess "VisibleString2" absVisibleString v2 expectedv2
visibleStringTest3 =
expectFailure "VisibleString3" absVisibleString v3 expectedv3
{-
A modified version of the example in Annex A of X.690 (ISO 8825-1).
-}
{-
Name ::= [APPLICATION 1] IMPLICIT SEQUENCE
{givenName VisibleString,
initial VisibleString,
familyName VisibleString}
-}
name =
"Name" ::=
AbsSeq Application 1 Implicit [
Regular (Just "givenName" :>: (Nothing :@: absVisibleString)),
Regular (Just "initial" :>: (Nothing :@: absVisibleString)),
Regular (Just "familyName" :>: (Nothing :@: absVisibleString))
]
data Name = Name {givenName :: VisibleString,
initial :: VisibleString,
familyName :: VisibleString}
deriving (Eq,Show)
instance Encode Name where
decode a b =
do x <- b
let as = absSeqComponents a
bs = encodedDefComps x
return $
Name {
givenName = fromJust $ decode (as!!0) (bs!!0),
initial = fromJust $ decode (as!!1) (bs!!1),
familyName = fromJust $ decode (as!!2) (bs!!2)
}
n1 = Constructed Application 1 14 [v1,v2] -- Invalid number
-- of components
n2 = Constructed Application 1 14 [v1] -- Invalid number
-- of components
n3 = Constructed Application 1 14 [] -- Invalid number
-- of components
n4 = Constructed Application 1 14 [v1,v2,v1] -- Valid
n5 = Constructed Application 1 14 [v1,v2,v3] -- Invalid component
expectedn1 =
"user error (Checking Regular (Just \"familyName\" :>: " ++
"(Nothing :@: (\"VisibleString\" ::= " ++
"AbsBasePrim Universal 26 AbsVisibleString))): " ++
"insufficient components)"
nameTest1 =
expectFailure "Name1" name n1 expectedn1
expectedn2 =
"user error (Checking Regular (Just \"initial\" :>: " ++
"(Nothing :@: (\"VisibleString\" ::= " ++
"AbsBasePrim Universal 26 AbsVisibleString))): " ++
"insufficient components)"
nameTest2 =
expectFailure "Name2" name n2 expectedn2
expectedn3 =
"user error (Checking Regular (Just \"givenName\" :>: " ++
"(Nothing :@: (\"VisibleString\" ::= " ++
"AbsBasePrim Universal 26 AbsVisibleString))): " ++
"insufficient components)"
nameTest3 =
expectFailure "Name3" name n3 expectedn3
expectedn4 =
Name {
givenName = VisibleString "hello",
initial = VisibleString "gello",
familyName = VisibleString "hello"
}
nameTest4 =
expectSuccess "Name4" name n4 expectedn4
expectedn5 =
"user error (Checking \"VisibleString\": " ++
"type not compatible with values [31,101,108,108,111])"
nameTest5 =
expectFailure "Name5" name n5 expectedn5
{-
EmployeeNumber ::= [APPLICATION 2] IMPLICIT INTEGER
-}
employeeNumber =
"EmployeeNumber" ::= AbsRef Application 2 Implicit absInteger
data EmployeeNumber = EmployeeNumber Integer
deriving (Eq,Show)
instance Encode EmployeeNumber where
decode a b =
do x <- decode a b
return $ EmployeeNumber x
en1 = Primitive Application 2 1 [0x33]
decodedEN1 = EmployeeNumber 51
enTest1 =
expectSuccess "EmployeeNumber1" employeeNumber en1 decodedEN1
{-
Date ::= [APPLICATION 3] IMPLICIT VisibleString -- YYYYMMDD
-}
date = "Date" ::=
AbsRef Application 3 Implicit absVisibleString
data Date = Date VisibleString
deriving (Eq,Show)
instance Encode Date where
decode a b =
do x <- decode a b
return $ Date x
b = "30/03/2003 19:37:34 GMT"
a = "30/03/2004 19:37:34 GMT"
nb = map (fromIntegral . ord) b
na = map (fromIntegral . ord) a
d1 = Constructed Application 3 7 [Primitive Universal 23 23 na] -- Invalid
d2 = Primitive Application 3 6 nb -- Valid
expectedD1 =
"user error (Checking \"Date\": " ++
"expected PRIMITIVE Tag found CONSTRUCTED Tag\n" ++
"\"Date\" ::= AbsBasePrim Application 3 AbsVisibleString\n" ++
show d1 ++ ")"
decodedD2 = Date $ VisibleString b
dateTest1 =
expectFailure "Date1" date d1 expectedD1
dateTest2 =
expectSuccess "Date2" date d2 decodedD2
{-
ChildInformation ::= SEQUENCE
{ name Name,
dateOfBirth [0] Date}
-}
childInformation =
"ChildInformation" ::=
AbsSeq Universal 16 Implicit [
Regular (Just "name" :>: (Nothing :@: name)),
Regular (Just "dateOfBirth" :>: (Just 0 :@: date))
]
data ChildInformation =
ChildInformation { name1 :: Name,
dateOfBirth :: Date }
deriving (Eq,Show)
instance Encode ChildInformation where
decode a b =
do x <- b
let as = absSeqComponents a
bs = encodedDefComps x
return $
ChildInformation {
name1 = fromJust $ decode (as!!0) (bs!!0),
dateOfBirth = fromJust $ decode (as!!1) (bs!!1)
}
ci1 = Constructed Universal 16 28
[n4,Primitive Context 0 6 nb]
expectedCI1 =
ChildInformation {
name1 = expectedn4,
dateOfBirth = decodedD2
}
ciTest1 =
expectSuccess "ChildInformation1" childInformation ci1 expectedCI1
{-
PersonnelRecord ::= [APPLICATION 0] IMPLICIT SEQUENCE {
name Name,
title [0] VisibleString,
number EmployeeNumber,
dateOfHire [1] Date,
nameOfSpouse [2] Name,
children [3] IMPLICIT
SEQUENCE OF ChildInformation DEFAULT {} }
-}
personnelRecord =
"PersonnelRecord" ::=
AbsSeq Application 0 Implicit [
Regular (Just "name" :>: (Nothing :@: name)),
Regular (Just "title" :>: (Just 0 :@: absVisibleString)),
Regular (Just "number" :>: (Nothing :@: employeeNumber)),
Regular (Just "dateOfHire" :>: (Just 1 :@: date)),
Regular (Just "nameOfSpouse" :>: (Just 2 :@: name)),
Regular (
Just "children" :>: (
Just 3 :@: (
"SEQUENCE OF ChildInformation" ::=
AbsSeqOf Universal 16 Implicit childInformation
)
)
)
]
data PersonnelRecord =
PersonnelRecord {name2 :: Name,
title :: VisibleString,
number :: EmployeeNumber,
dateOfHire :: Date,
nameOfSpouse :: Name,
children :: [ChildInformation]}
deriving (Eq,Show)
instance Encode PersonnelRecord where
decode a b =
do x <- b
let as = absSeqComponents a
bs = encodedDefComps x
return $
PersonnelRecord {
name2 = fromJust $ decode (as!!0) (bs!!0),
title = fromJust $ decode (as!!1) (bs!!1),
number = fromJust $ decode (as!!2) (bs!!2),
dateOfHire = fromJust $ decode (as!!3) (bs!!3),
nameOfSpouse = fromJust $ decode (as!!4) (bs!!4),
children = fromJust $ decode (as!!5) (bs!!5)}
pr1 =
Constructed Application 0 23 [
n4,
Primitive Context 0 5 [104,101,108,108,111],
en1,
Primitive Context 1 6 nb,
Constructed Context 2 14 [v1,v2,v1],
Constructed Context 3 30 [ci1]
-- Constructed Context 3 18 [Constructed Universal 16 16 [ci1]]
]
decodedpr1 =
PersonnelRecord {
name2 = expectedn4,
title = expectedv1,
number = decodedEN1,
dateOfHire = decodedD2,
nameOfSpouse = expectedn4,
children = [expectedCI1]
}
prTest1 =
expectSuccess "PersonnelRecord1" personnelRecord pr1 decodedpr1
taggedRecord =
"PersonnelRecord" ::=
AbsSeq Application 0 Implicit [
Regular (Just "name" :>: (Nothing :@: name)),
Regular (Just "nameOfSpouse" :>: (Just 2 :@: name))
]
tr1 =
Constructed Application 0 23 [
n4,
Constructed Context 2 14 [v1,v2,v1]
]
taggedRecord1 =
"PersonnelRecord" ::=
AbsSeq Application 0 Implicit [
Regular (Just "name" :>: (Nothing :@: name)),
Regular (Just "title" :>: (Just 0 :@: absVisibleString)),
Regular (Just "number" :>: (Nothing :@: employeeNumber)),
Regular (Just "dateOfHire" :>: (Just 1 :@: date)),
Regular (Just "nameOfSpouse" :>: (Just 2 :@: name)),
Regular (Just "another" :>: (Just 3 :@: name))
]
tr2 =
Constructed Application 0 23 [
n4,
Primitive Context 0 5 [104,101,108,108,111],
en1,
Primitive Context 1 6 nb,
Constructed Context 2 14 [v1,v2,v1],
Constructed Context 3 14 [v1,v2,v1]
]
taggedRecord2 =
"PersonnelRecord" ::=
AbsSeq Application 0 Implicit [
Regular (Just "name" :>: (Nothing :@: name)),
Regular (
Just "children" :>: (
Just 3 :@: (
"SEQUENCE OF ChildInformation" ::=
AbsSeqOf Universal 16 Implicit childInformation
)
)
)
]
tr3 =
Constructed Application 0 23 [
n4,
Constructed Context 3 18 [Constructed Universal 16 16 [ci1]]
]
taggedRecord3 =
"TaggedRecord3" ::=
AbsSeq Application 0 Implicit [
Regular (
Just "children" :>: (
Just 3 :@: (
"SEQUENCE OF ChildInformation" ::=
AbsSeqOf Universal 16 Implicit childInformation
)
)
)
]
tr4 =
Constructed Application 0 23 [
Constructed Context 3 18 [Constructed Universal 16 16 [ci1]]
]
sequenceOfChildInformation =
"SEQUENCE OF ChildInformation" ::=
AbsSeqOf Universal 16 Implicit childInformation
soci1 = Constructed Universal 16 30 [ci1]
tr5 =
Constructed Application 0 32 [
Constructed Context 3 30 [ci1]
]
taggedRecord4 =
"TaggedRecord3" ::=
AbsSeq Application 0 Implicit [
Regular (Just "children" :>: (Just 3 :@: sequenceOfChildInformation))
]
{-
Choice1 ::= CHOICE {
z1 [0] EmployeeNumber,
z2 [1] EmployeeNumber,
z3 [2] EmployeeNumber
}
A ::= CHOICE {
b B,
c C
}
B ::= CHOICE {
d [0] NULL,
e [1] NULL
}
C ::= CHOICE {
f [2] NULL,
g [3] NULL
}
-}
choice1 =
"Choice1" ::=
AbsChoice [
(Implicit, Just "z1" :>: (Just 0 :@: employeeNumber)),
(Implicit, Just "z2" :>: (Just 1 :@: employeeNumber)),
(Implicit, Just "z3" :>: (Just 2 :@: employeeNumber))
]
c1 = Primitive Context 0 1 [0x33]
c2 = Primitive Context 1 1 [0x33]
c3 = Primitive Context 2 1 [0x33]
c4 = Primitive Context 3 1 [0x33]
decodedC1 = Z1 (EmployeeNumber' 51)
decodedC2 = Z2 (EmployeeNumber' 51)
decodedC3 = Z3 (EmployeeNumber' 51)
data Choice1 =
Z1 EmployeeNumber' |
Z2 EmployeeNumber' |
Z3 EmployeeNumber'
deriving (Eq,Show)
instance Encode Choice1 where
decode a b =
do x <- b
let t = defaultedTagValue x
case t of
0 -> do foo <- decode a b
return $ Z1 foo
1 -> do foo <- decode a b
return $ Z2 foo
2 -> do foo <- decode a b
return $ Z3 foo
{-
EmployeeNumber ::= [APPLICATION 2] IMPLICIT INTEGER
-}
employeeNumber' =
"EmployeeNumber" ::= AbsRef Application 2 Implicit absInteger
data EmployeeNumber' = EmployeeNumber' Integer
deriving (Eq,Show)
instance Encode EmployeeNumber' where
decode a b =
do x <- decode a b
return $ EmployeeNumber' x
tChoice11 =
expectSuccess "Choice1" choice1 c1 decodedC1
choice2 =
"A" ::=
AbsChoice [
(Implicit, Just "b" :>: (Nothing :@: choice3)),
(Implicit, Just "c" :>: (Nothing :@: choice4))
]
data Choice2 =
B Choice3 |
C Choice4
deriving (Eq,Show)
instance Encode Choice2 where
decode a b =
do x <- b
let t = defaultedTagValue x
f t
| t `elem` [0,1] =
do foo <- decode a b
return $ B foo
| t `elem` [2,3] =
do foo <- decode a b
return $ C foo
f t
decodedCBD = B decodedCD
decodedCBE = B decodedCE
tChoice21 =
expectSuccess "Choice2BD" choice2 c1 decodedCBD
tChoice22 =
expectSuccess "Choice2BE" choice2 c2 decodedCBE
choice3 =
"B" ::=
AbsChoice [
(Implicit, Just "d" :>: (Just 0 :@: employeeNumber)),
(Implicit, Just "e" :>: (Just 1 :@: employeeNumber))
]
decodedCD = D (EmployeeNumber' 51)
decodedCE = E (EmployeeNumber' 51)
data Choice3 =
D EmployeeNumber' |
E EmployeeNumber'
deriving (Eq,Show)
instance Encode Choice3 where
decode a b =
do x <- b
let t = defaultedTagValue x
case t of
0 -> do foo <- decode a b
return $ D foo
1 -> do foo <- decode a b
return $ E foo
tChoice31 =
expectSuccess "Choice3D" choice3 c1 decodedCD
tChoice32 =
expectSuccess "Choice3E" choice3 c2 decodedCE
choice4 =
"C" ::=
AbsChoice [
(Implicit, Just "f" :>: (Just 2 :@: employeeNumber)),
(Implicit, Just "g" :>: (Just 3 :@: employeeNumber))
]
decodedCF = F (EmployeeNumber' 51)
decodedCG = G (EmployeeNumber' 51)
data Choice4 =
F EmployeeNumber' |
G EmployeeNumber'
deriving (Eq,Show)
instance Encode Choice4 where
decode a b =
do x <- b
let t = defaultedTagValue x
case t of
2 -> do foo <- decode a b
return $ F foo
3 -> do foo <- decode a b
return $ G foo
tChoice43 =
expectSuccess "Choice4F" choice4 c3 decodedCF
tChoice44 =
expectSuccess "Choice4G" choice2 c4 decodedCG
{-
NoTags ::= CHOICE {
myInt INTEGER,
myIA5 IA5String
}
-}
noTags =
"NoTags" ::=
AbsChoice [
(Implicit, Just "myInt" :>: (Nothing :@: absInteger)),
(Implicit, Just "myIA5" :>: (Nothing :@: absIA5String))
]
nt1 = Primitive Universal 2 1 [0x33]
nt2 = Primitive Universal 22 1 [0x33]
nt3 = Primitive Universal 3 1 [0x33]
nt4 = Primitive Universal 23 1 [0x33]
decodedNT1 = MyInt 51
decodedNT2 = MyIA5 (IA5String "3")
data NoTags =
MyInt Integer |
MyIA5 IA5String
deriving (Eq,Show)
instance Encode NoTags where
decode a b =
do x <- b
let t = defaultedTagValue x
f t
| t `elem` [2] =
do foo <- decode a b
return $ MyInt foo
| t `elem` [22] =
do foo <- decode a b
return $ MyIA5 foo
f t
tNoTags1 =
expectSuccess "NoTags1" noTags nt1 decodedNT1
tNoTags2 =
expectSuccess "NoTags2" noTags nt2 decodedNT2
{-
ExplicitChoice ::= CHOICE {
x1 [0] EXPLICIT EmployeeNumber,
x2 [1] EXPLICIT EmployeeNumber,
x3 [2] EXPLICIT EmployeeNumber
}
-}
explicitChoice =
"ExplicitChoice" ::=
AbsChoice [
(Explicit, Just "z1" :>: (Just 0 :@: employeeNumber)),
(Explicit, Just "z2" :>: (Just 1 :@: employeeNumber)),
(Explicit, Just "z3" :>: (Just 2 :@: employeeNumber))
]
ec1 = Constructed Context 0 3 [en1]
ec2 = Constructed Context 1 3 [en1]
ec3 = Constructed Context 2 3 [en1]
ec4 = Constructed Context 3 3 [en1]
foo e =
do (w,x) <- typeCheck explicitChoice e
putStrLn (show x)
putStrLn (show w)
let (_ ::= c) = w
d = decode c (Just x)
(Just y) = d::(Maybe ExplicitChoice)
putStrLn (show y)
data ExplicitChoice =
X1 EmployeeNumber |
X2 EmployeeNumber |
X3 EmployeeNumber
deriving (Eq,Show)
instance Encode ExplicitChoice where
decode a b =
do x <- b
let t = defaultedTagValue x
a' = absRefedType a
b' = (encodedDefComps x)!!0
foo <- decode a' b'
case t of
0 -> return (X1 foo)
1 -> return (X2 foo)
2 -> return (X3 foo)
{-
We can't put this in a test yet as w does not return something
that can be decoded mechanically. It needs more investigation but
is probably because EXPLICIT doesn't get handled correctly either
for CHOICE or SEQUENCE.
-}
version = modName "Version" absInteger
type Version = Integer
certificateVersion =
"version" ::= AbsRef Context 0 Explicit version
data CertificateVersion =
CertificateVersion Version
deriving (Eq,Show)
instance Encode CertificateVersion where
decode a b =
do y <- b
let a' = absRefedType a
b' = (encodedDefComps y)!!0
x <- decode a' b'
return $ CertificateVersion x
ver1 =
Constructed Universal 16 17 [
Constructed Context 0 3 [
Primitive Universal 2 1 [2]
],
Primitive Universal 2 10 [25,139,17,209,63,154,143,254,105,160]
]
ver2 =
Constructed Context 0 3 [
Primitive Universal 2 1 [2]
]
decodedVer2 = CertificateVersion 2
bar =
do (w,x) <- typeCheck certificateVersion ver2
putStrLn (show x)
putStrLn (show w)
let (_ ::= c) = w
d = decode c (Just x)
(Just y) = d::(Maybe CertificateVersion)
putStrLn (show y)
tVer1 = expectSuccess "Version1" certificateVersion ver2 decodedVer2
tests =
TestList [
tagTest1, tagTest2, tagTest3, tagTest4,
textBookTest1, textBookTest2, textBookTest3, libraryTest,
visibleStringTest1, visibleStringTest2, visibleStringTest3,
nameTest1, nameTest2, nameTest3, nameTest4, nameTest5,
enTest1, dateTest1, dateTest2, ciTest1,
prTest1, journeyTest1, journeyTest2, odysseyTest1,
odysseyTest2, funnyOptionalTest1, funnyOptionalTest2,
tChoice11, tChoice31, tChoice32, tChoice43, tChoice44,
tChoice21, tChoice22, tNoTags1, tNoTags2, tVer1
]
main = runTestTT tests
{-
051217083900
Three (at least) things to think about.
1. Real errors in choice. At the moment, all errors get treated
as a trigger to try the next alternative.
2. Typechecking a reference returns the abstract BER representation
of the referenced element. Should this be the whole element?
3. SEQUENCE elements can be IMPLICIT or EXPLICIT. Currently all are
treated as IMPLICIT because of
k (Regular (mn :>: (tv :@: td)):as) (bv:bvs) =
do foo <- lift $ case tv of
Nothing ->
tc td bv
Just v ->
case mn of
Nothing ->
tc ("" ::= AbsRef Context v Implicit td) bv
Just name ->
tc (name ::= AbsRef Context v Implicit td) bv
-}