let parse_optional_field_value s =
  match String.lsplit2 s ~on:':' with
  | None ->
    error "missing TYPE in optional field" s sexp_of_string
  | Some (typ,value) ->
    match typ with
    | "A" ->
      if String.length value = 1 then optional_field_value_A value.[0]
      else optional_field_value_err typ value
    | "i" ->
      (try
         if not (Re.execp opt_field_int_re value) then failwith "" ;
         Ok (optional_field_value_i (Int32.of_string value)) (* matching the regular expression is not enough: the number could not fit in 32 bits *)
       with _ -> optional_field_value_err typ value)
    | "f" ->
      (try
         if not (Re.execp opt_field_float_re value) then failwith "" ;
         Ok (optional_field_value_f (Float.of_string value)) (* matching the regular expression is not enough: the number could not fit in 32 bits *)
       with _ -> optional_field_value_err typ value)
    | "Z" -> optional_field_value_Z value
    | "H" -> optional_field_value_H value
    | "B" -> (
        match String.split ~on:',' value with
        | num_typ :: values ->
          if String.length num_typ = 1 then
            optional_field_value_B num_typ.[0] values
          else
            error "invalid array type" num_typ sexp_of_string
        | _ -> assert false (* [String.split] cannot return an empty list *)
      )
    | _ -> error "invalid type" typ sexp_of_string