    -- |
    -- 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)