-- |
-- Module      : Data.ASN1.Stream
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : experimental
-- Portability : unknown
--
module Data.ASN1.Stream
    ( ASN1Repr
    , getConstructedEnd
    , getConstructedEndRepr
    ) where

import Data.ASN1.Types
import Data.ASN1.Types.Lowlevel

{- associate a list of asn1 event with an ASN1 type.
 - it's sometimes required to know the exact byte sequence leading to an ASN1 type:
 - eg: cryptographic signature -}
type ASN1Repr = (ASN1, [ASN1Event])

getConstructedEnd :: Int -> [ASN1] -> ([ASN1],[ASN1])
getConstructedEnd :: Int -> [ASN1] -> ([ASN1], [ASN1])
getConstructedEnd Int
_ xs :: [ASN1]
xs@[]                = ([ASN1]
xs, [])
getConstructedEnd Int
i ((x :: ASN1
x@(Start ASN1ConstructionType
_)):[ASN1]
xs)   = let ([ASN1]
yz, [ASN1]
zs) = Int -> [ASN1] -> ([ASN1], [ASN1])
getConstructedEnd (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) [ASN1]
xs in (ASN1
xASN1 -> [ASN1] -> [ASN1]
forall a. a -> [a] -> [a]
:[ASN1]
yz,[ASN1]
zs)
getConstructedEnd Int
i ((x :: ASN1
x@(End ASN1ConstructionType
_)):[ASN1]
xs)
    | Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0    = ([], [ASN1]
xs)
    | Bool
otherwise = let ([ASN1]
ys, [ASN1]
zs) = Int -> [ASN1] -> ([ASN1], [ASN1])
getConstructedEnd (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) [ASN1]
xs in (ASN1
xASN1 -> [ASN1] -> [ASN1]
forall a. a -> [a] -> [a]
:[ASN1]
ys,[ASN1]
zs)
getConstructedEnd Int
i (ASN1
x:[ASN1]
xs)               = let ([ASN1]
ys, [ASN1]
zs) = Int -> [ASN1] -> ([ASN1], [ASN1])
getConstructedEnd Int
i [ASN1]
xs in (ASN1
xASN1 -> [ASN1] -> [ASN1]
forall a. a -> [a] -> [a]
:[ASN1]
ys,[ASN1]
zs)

getConstructedEndRepr :: [ASN1Repr] -> ([ASN1Repr],[ASN1Repr])
getConstructedEndRepr :: [ASN1Repr] -> ([ASN1Repr], [ASN1Repr])
getConstructedEndRepr = [ASN1Repr] -> ([ASN1Repr], [ASN1Repr])
g
    where g :: [ASN1Repr] -> ([ASN1Repr], [ASN1Repr])
g []                 = ([], [])
          g (x :: ASN1Repr
x@(Start ASN1ConstructionType
_,[ASN1Event]
_):[ASN1Repr]
xs) = let ([ASN1Repr]
ys, [ASN1Repr]
zs) = Int -> [ASN1Repr] -> ([ASN1Repr], [ASN1Repr])
getEnd Int
1 [ASN1Repr]
xs in (ASN1Repr
xASN1Repr -> [ASN1Repr] -> [ASN1Repr]
forall a. a -> [a] -> [a]
:[ASN1Repr]
ys, [ASN1Repr]
zs)
          g (ASN1Repr
x:[ASN1Repr]
xs)             = ([ASN1Repr
x],[ASN1Repr]
xs)

          getEnd :: Int -> [ASN1Repr] -> ([ASN1Repr],[ASN1Repr])
          getEnd :: Int -> [ASN1Repr] -> ([ASN1Repr], [ASN1Repr])
getEnd Int
_ []                    = ([], [])
          getEnd Int
0 [ASN1Repr]
xs                    = ([], [ASN1Repr]
xs)
          getEnd Int
i ((x :: ASN1Repr
x@(Start ASN1ConstructionType
_, [ASN1Event]
_)):[ASN1Repr]
xs) = let ([ASN1Repr]
ys, [ASN1Repr]
zs) = Int -> [ASN1Repr] -> ([ASN1Repr], [ASN1Repr])
getEnd (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) [ASN1Repr]
xs in (ASN1Repr
xASN1Repr -> [ASN1Repr] -> [ASN1Repr]
forall a. a -> [a] -> [a]
:[ASN1Repr]
ys,[ASN1Repr]
zs)
          getEnd Int
i ((x :: ASN1Repr
x@(End ASN1ConstructionType
_, [ASN1Event]
_)):[ASN1Repr]
xs)   = let ([ASN1Repr]
ys, [ASN1Repr]
zs) = Int -> [ASN1Repr] -> ([ASN1Repr], [ASN1Repr])
getEnd (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) [ASN1Repr]
xs in (ASN1Repr
xASN1Repr -> [ASN1Repr] -> [ASN1Repr]
forall a. a -> [a] -> [a]
:[ASN1Repr]
ys,[ASN1Repr]
zs)
          getEnd Int
i (ASN1Repr
x:[ASN1Repr]
xs)                = let ([ASN1Repr]
ys, [ASN1Repr]
zs) = Int -> [ASN1Repr] -> ([ASN1Repr], [ASN1Repr])
getEnd Int
i [ASN1Repr]
xs in (ASN1Repr
xASN1Repr -> [ASN1Repr] -> [ASN1Repr]
forall a. a -> [a] -> [a]
:[ASN1Repr]
ys,[ASN1Repr]
zs)