let item_to_raw () :
      (Sam.item, (raw_item, _) Result.t) Biocaml_transform.t =
    let name = "bam_item_downgrader" in
    let queue = Dequeue.create () in
    let items_count = ref 0 in
    let ref_dict = ref [| |] in
    let ref_dict_done = ref false in
    let header = Buffer.create 256 in
    let rec next stopped =
      dbg "  queue: %d  items_count: %d"
        (Dequeue.length queue) !items_count;
      begin match Dequeue.is_empty queue, stopped with
      | truetrue ->`end_of_stream
      | truefalse -> `not_ready
      | false, _ ->
        incr items_count;
        begin match Dequeue.dequeue_exn queue `front with
        | `comment c ->
          Buffer.add_string header "@CO\t";
          Buffer.add_string header c;
          Buffer.add_string header "\n";
          next stopped
        | `header_line (version, ordering, rest) ->
          if Buffer.contents header <> "" then
            `output (Error (`header_item_not_first (Buffer.contents header)))
          else begin
            ksprintf (Buffer.add_string header) "@HD\tVN:%s\tSO:%s%s\n"
              version
              (match ordering with
              | `unknown -> "unknown"
              | `unsorted -> "unsorted"
              | `queryname -> "queryname"
              | `coordinate -> "coordinate")
              (List.map rest (fun (t, v) -> sprintf "\t%s:%s" t v)
               |> String.concat ~sep:"");
            next stopped
          end
        | `header (pretag, l) ->
          ksprintf (Buffer.add_string header) "@%s" pretag;
          List.iter l (fun (t, v) ->
            ksprintf (Buffer.add_string header) "\t%s:%s" t v;
          );
          Buffer.add_string header "\n";
          next stopped
        | `reference_sequence_dictionary r ->
          ref_dict := r;
          `output (Ok (`header (Buffer.contents header)))
        | `alignment al ->
          if not !ref_dict_done
          then begin
            dbg "reference_information: %d" Array.(length !ref_dict);
            ref_dict_done := true;
            Dequeue.enqueue queue `front (`alignment al);
            `output (Ok (`reference_information (Array.map !ref_dict ~f:(fun rs ->
              let open Sam in
              (rs.ref_name, rs.ref_length)))))
          end
          else begin
            match downgrade_alignement al !ref_dict with
            | Ok o -> `output (Ok (`alignment o))
            | Error e -> `output (Error e)
          end
        end
      end
    in
    Biocaml_transform.make ~name ~feed:(Dequeue.enqueue queue `back) ()
      ~next