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
| true, true ->`end_of_stream
| true, false -> `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