let raw_to_item () :
      (raw_item, (item, [> Error.raw_to_item]) Result.t) Biocaml_transform.t =
    let name = "sam_item_parser" in
    let raw_queue = Dequeue.create () in
    let raw_items_count = ref 0 in
    let refseq_line, refseq_end = reference_sequence_aggregator () in
    let header_finished = ref false in
    let ref_dictionary = ref None in
    let rec next stopped =
      if Dequeue.is_empty raw_queue
      then (if stopped then `end_of_stream else `not_ready)
      else begin
        incr raw_items_count;
        begin match Dequeue.dequeue_exn raw_queue `front with
        | `comment c when !header_finished ->
          `output (Error (`comment_after_end_of_header (!raw_items_count, c)))
        | `header c when !header_finished ->
          `output (Error (`header_after_end_of_header (!raw_items_count, c)))
        | `comment c ->  `output (Ok (`comment c))
        | `header ("HD", l) ->
          if !raw_items_count <> 1
          then `output (Error (`header_line_not_first !raw_items_count))
          else `output (expand_header_line l)
        | `header ("SQ", l) ->
          begin match refseq_line l with
          | Error e -> `output (Error e)
          | Ok () ->  next stopped
          end
        | `header _ as other -> `output (Ok other)
        | `alignment a ->
          if !header_finished then (
            expand_alignment a !ref_dictionary
            >>| (fun a -> `alignment a)
                          |> (fun x -> `output x)
          ) else begin
            header_finished := true;
            Dequeue.enqueue raw_queue `front (`alignment a);
            begin match refseq_end () with
            | Ok rd ->
              ref_dictionary := Some rd;
              `output (Ok (`reference_sequence_dictionary rd))
            | Error e -> `output (Error e)
            end
          end
        end
      end
    in
    Biocaml_transform.make ~name ~feed:(Dequeue.enqueue raw_queue `back) ()
      ~next