Skip to content

Commit

Permalink
Add compatibility for 32 bit platforms for timestamps
Browse files Browse the repository at this point in the history
  • Loading branch information
andersfugmann committed Apr 14, 2024
1 parent 387d7d1 commit b569450
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 9 deletions.
20 changes: 15 additions & 5 deletions src/ocaml_protoc_plugin/deserialize_json.ml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ let read_map: type a b. read_key:(string -> a) -> read_value:(Json.t -> b) -> Js
| json -> value_error "map_entry" json

(** What a strange encoding.
Durations less than one second are represented with a 0 seconds field and a positive or negative nanos field. For durations of one second or more, a non-zero value for the nanos field must be of the same sign as the seconds field.
Durations less than one second are represented with a 0 seconds
field and a positive or negative nanos field. For durations of one
second or more, a non-zero value for the nanos field must be of
the same sign as the seconds field.
*)
let duration_of_json json =
(* Capture the signedness of the duration, and apply to both seconds and nanos *)
Expand Down Expand Up @@ -116,16 +119,16 @@ let timestamp_of_json = function
| Ok (t, _, _) -> t
| Error _e -> value_error "google.protobuf.duration" (`String timestamp)
in
let seconds = Ptime.to_float_s t |> Float.to_int in
let nanos = Ptime.frac_s t |> Ptime.Span.to_float_s |> Float.mul 1_000_000_000.0 |> Float.to_int in
let seconds = Ptime.to_float_s t |> Int64.of_float in
let nanos = Ptime.frac_s t |> Ptime.Span.to_float_s |> Float.mul 1_000_000_000.0 |> Int64.of_float in
(seconds, nanos)
| json -> value_error "google.protobuf.timestamp" json

let%expect_test "google.protobuf.Timestamp" =
let test str =
try
let (s, n) = timestamp_of_json (`String str) in
Printf.printf "D: %s -> %d.%09ds\n" str s n
Printf.printf "D: %s -> %Ld.%09Lds\n" str s n
with
| Result.Error e -> Printf.printf "Error parsing %s: %s\n" str (Result.show_error e)
in
Expand Down Expand Up @@ -220,7 +223,14 @@ let map_message_json: name:string -> Json.t -> Json.t = fun ~name ->
| ".google.protobuf.Timestamp" ->
let convert json =
let (seconds, nanos) = timestamp_of_json json in
`Assoc [ "seconds", `Int seconds; "nanos", `Int nanos ]
match Sys.int_size < 63 with
| true ->
`Assoc [ "seconds", `String (Int64.to_string seconds);
"nanos", `String (Int64.to_string nanos) ]
| false ->
`Assoc [ "seconds", `Int (Int64.to_int seconds);
"nanos", `Int (Int64.to_int nanos) ]

in
convert
(* Wrapper types - google/protobuf/wrappers.proto *)
Expand Down
8 changes: 4 additions & 4 deletions src/ocaml_protoc_plugin/serialize_json.ml
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,10 @@ let%expect_test "duration_to_json" =
let timestamp_to_json json =
let open Stdlib in
let open StdLabels in
let seconds = get_key "seconds" ~f:Deserialize_json.to_int ~default:0 json in
let nanos = get_key "nanos" ~f:Deserialize_json.to_int ~default:0 json in
let s1 = Ptime.Span.of_int_s seconds in
let s2 = Ptime.Span.of_float_s (float nanos /. 1_000_000_000.0) |> Option.get in
let seconds = get_key "seconds" ~f:Deserialize_json.to_int64 ~default:0L json in
let nanos = get_key "nanos" ~f:Deserialize_json.to_int64 ~default:0L json in
let s1 = Ptime.Span.of_float_s (Int64.to_float seconds) |> Option.get in
let s2 = Ptime.Span.of_float_s (Int64.to_float nanos /. 1_000_000_000.0) |> Option.get in
let t =
Ptime.Span.add s1 s2
|> Ptime.of_span
Expand Down

0 comments on commit b569450

Please sign in to comment.