-- |
-- 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 _ xs :: [ASN1]
xs@[]                = ([ASN1]
xs, [])
getConstructedEnd i :: Int
i ((x :: ASN1
x@(Start _)):xs :: [ASN1]
xs)   = let (yz :: [ASN1]
yz, zs :: [ASN1]
zs) = Int -> [ASN1] -> ([ASN1], [ASN1])
getConstructedEnd (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) [ASN1]
xs in (ASN1
xASN1 -> [ASN1] -> [ASN1]
forall a. a -> [a] -> [a]
:[ASN1]
yz,[ASN1]
zs)
getConstructedEnd i :: Int
i ((x :: ASN1
x@(End _)):xs :: [ASN1]
xs)
    | Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 0    = ([], [ASN1]
xs)
    | Bool
otherwise = let (ys :: [ASN1]
ys, zs :: [ASN1]
zs) = Int -> [ASN1] -> ([ASN1], [ASN1])
getConstructedEnd (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-1) [ASN1]
xs in (ASN1
xASN1 -> [ASN1] -> [ASN1]
forall a. a -> [a] -> [a]
:[ASN1]
ys,[ASN1]
zs)
getConstructedEnd i :: Int
i (x :: ASN1
x:xs :: [ASN1]
xs)               = let (ys :: [ASN1]
ys, zs :: [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 _,_):xs :: [ASN1Repr]
xs) = let (ys :: [ASN1Repr]
ys, zs :: [ASN1Repr]
zs) = Int -> [ASN1Repr] -> ([ASN1Repr], [ASN1Repr])
getEnd 1 [ASN1Repr]
xs in (ASN1Repr
xASN1Repr -> [ASN1Repr] -> [ASN1Repr]
forall a. a -> [a] -> [a]
:[ASN1Repr]
ys, [ASN1Repr]
zs)
          g (x :: ASN1Repr
x:xs :: [ASN1Repr]
xs)             = ([ASN1Repr
x],[ASN1Repr]
xs)

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