-- | Turn a 'Builder' into its initial 'BufferWriter' action.
--
runBuilder :: Builder -> BufferWriter
runBuilder = run . I.runBuilder
  where
    run :: I.BuildStep () -> BufferWriter
    run step = \buf len -> do
      sig <- step (I.BufferRange buf (buf `plusPtr` len))
      case sig of
        I.Done endPtr () ->
          let !wc  = bytesWritten buf endPtr
              next = Done
           in return (wc, next)

        I.BufferFull minReq endPtr step' ->
          let !wc  = bytesWritten buf endPtr
              next = More minReq (run step')
           in return (wc, next)

        I.InsertChunks endPtr _ lbsc step' ->
          let !wc  = bytesWritten buf endPtr
              next = case lbsc L.Empty of
                       L.Empty      -> More  (len - wc) (run step')
                       L.Chunk c cs -> Chunk c          (yieldChunks step' cs)
           in return (wc, next)

    yieldChunks :: I.BuildStep () -> L.ByteString -> BufferWriter
    yieldChunks step' cs = \buf len ->
      case cs of
        L.Empty       -> run step' buf len
        L.Chunk c cs' ->
          let wc   = 0
              next = Chunk c (yieldChunks step' cs')
           in return (wc, next)

    bytesWritten startPtr endPtr = endPtr `minusPtr` startPtr


------------------------------------------------------------------------------
-- Host-specific encodings
------------------------------------------------------------------------------

-- | Encode a single native machine 'Int'. The 'Int' is encoded in host order,
-- host endian form, for the machine you're on. On a 64 bit machine the 'Int'
-- is an 8 byte value, on a 32 bit machine, 4 bytes. Values encoded this way
-- are not portable to different endian or int sized machines, without
-- conversion.
--

runBuilder :: Builder -> BufferWriter
runBuilder = run . I.runBuilder
  where
    run :: I.BuildStep () -> BufferWriter
    run step = \buf len -> do
      sig <- step (I.BufferRange buf (buf `plusPtr` len))
      case sig of
        I.Done endPtr () ->
          let !wc  = bytesWritten buf endPtr
              next = Done
           in return (wc, next)

        I.BufferFull minReq endPtr step' ->
          let !wc  = bytesWritten buf endPtr
              next = More minReq (run step')
           in return (wc, next)

        I.InsertChunks endPtr _ lbsc step' ->
          let !wc  = bytesWritten buf endPtr
              next = case lbsc L.Empty of
                       L.Empty      -> More  (len - wc) (run step')
                       L.Chunk c cs -> Chunk c          (yieldChunks step' cs)
           in return (wc, next)

    yieldChunks :: I.BuildStep () -> L.ByteString -> BufferWriter
    yieldChunks step' cs = \buf len ->
      case cs of
        L.Empty       -> run step' buf len
        L.Chunk c cs' ->
          let wc   = 0
              next = Chunk c (yieldChunks step' cs')
           in return (wc, next)

    bytesWritten startPtr endPtr = endPtr `minusPtr` startPtr


------------------------------------------------------------------------------
-- Host-specific encodings
------------------------------------------------------------------------------

-- | Encode a single native machine 'Int'. The 'Int' is encoded in host order,
-- host endian form, for the machine you're on. On a 64 bit machine the 'Int'
-- is an 8 byte value, on a 32 bit machine, 4 bytes. Values encoded this way
-- are not portable to different endian or int sized machines, without
-- conversion.
--

runBuilder = run . I.runBuilder
  where
    run :: I.BuildStep () -> BufferWriter
    run step = \buf len -> do
      sig <- step (I.BufferRange buf (buf `plusPtr` len))
      case sig of
        I.Done endPtr () ->
          let !wc  = bytesWritten buf endPtr
              next = Done
           in return (wc, next)

        I.BufferFull minReq endPtr step' ->
          let !wc  = bytesWritten buf endPtr
              next = More minReq (run step')
           in return (wc, next)

        I.InsertChunks endPtr _ lbsc step' ->
          let !wc  = bytesWritten buf endPtr
              next = case lbsc L.Empty of
                       L.Empty      -> More  (len - wc) (run step')
                       L.Chunk c cs -> Chunk c          (yieldChunks step' cs)
           in return (wc, next)

    yieldChunks :: I.BuildStep () -> L.ByteString -> BufferWriter
    yieldChunks step' cs = \buf len ->
      case cs of
        L.Empty       -> run step' buf len
        L.Chunk c cs' ->
          let wc   = 0
              next = Chunk c (yieldChunks step' cs')
           in return (wc, next)

    bytesWritten startPtr endPtr = endPtr `minusPtr` startPtr


------------------------------------------------------------------------------
-- Host-specific encodings
------------------------------------------------------------------------------

-- | Encode a single native machine 'Int'. The 'Int' is encoded in host order,
-- host endian form, for the machine you're on. On a 64 bit machine the 'Int'
-- is an 8 byte value, on a 32 bit machine, 4 bytes. Values encoded this way
-- are not portable to different endian or int sized machines, without
-- conversion.
--
