struct
  type target = t [@@deriving yojson]

  module V0 = struct
    type t = [
      | `Target of target
      | `Pointer of Target_pointer.t
    ] [@@deriving yojson]
  end
  include Json.Versioned.Of_v0(V0)
  type t = V0.t

  let deserialize s : (t, _) Result.t =
    let open Result in
    begin
      try return (deserialize_exn s)
    with e -> fail (`Target (`Deserilization (Printexc.to_string e)))
    end

  let get_target = function
  | `Target t -> `Target t
  | `Pointer { Target_pointer. pointer; _} -> `Pointer pointer

  let of_target t = `Target t

  let id = function
  | `Target t -> t.id
  | `Pointer { Target_pointer. original } -> original.id

  let make_pointer ~from ~pointing_to =
    `Pointer { Target_pointer.
               original = from;
               pointer = pointing_to.id }
end