let parse_optional_content raw =
    let error e = fail (`wrong_optional (raw, e)) in
    let char tag typ raw = 
      if String.length raw <> 1 then error (`not_a_char raw)
      else return (tag, typ, `char raw.[0]) in
    let int tag typ raw =
      try let i = Int.of_string raw in return (tag, typ, `int i)
      with e -> error (`not_an_int raw) in
    let float tag typ raw =
      try let i = Float.of_string raw in return (tag, typ, `float i)
      with e -> error (`not_a_float raw) in
    let parse_cCsSiIf tag typ raw =
      begin match typ with
      | 'i' | 's' | 'I' | 'S' -> int tag typ raw
      | 'A' | 'c' | 'C' -> char tag typ raw
      | 'f' -> float tag typ raw
      | _ -> error (`unknown_type typ)
      end in
    while_ok raw (fun _ (tag, typ, raw_v) ->
      begin match typ with
      | 'Z' -> return (tag, typ, `string raw_v)
      | 'H' -> return (tag, typ, `string raw_v)
      | 'B' -> 
        begin match String.split ~on:',' raw_v with
        | [] ->  error (`wrong_array (`wrong_type raw_v))
        | f :: _ when String.length f <> 1 ->
          error (`wrong_array (`wrong_type raw_v))
        | typs :: l ->
          let array = Array.create List.(length l) (`string "no"in
          let rec loop i = function
            | [] -> return array
            | h :: t ->
              begin match parse_cCsSiIf "" typs.[0] h with
              | Ok (_, _, v) -> array.(i) <- v; loop (i + 1) t
              | Error (`wrong_optional (_, e)) -> error (`wrong_array e)
              end
          in
          loop 0 l
          >>= fun a ->
          return (tag, typ, `array (typs.[0], a))
        end
      | c -> parse_cCsSiIf tag typ raw_v
      end)