aboutsummaryrefslogtreecommitdiffstats
path: root/lib/concepts/Tuple.ml
blob: 943c1f668e738ca4e83f3cea61aa6a7234f0c9a9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
type t = {type_: string; attributes: Value.value BatMap.String.t}

let malformed_value () =
  Condition.condition "malformed-tuple-value" "A tuple field did not conform to what was expected"
    Condition.empty

let bencode_of_value = function
  | Value.String s -> Encoding.Bencode.Tagged ('s', Encoding.Bencode.String s)
  | Value.Integer n -> Encoding.Bencode.Tagged ('i', Encoding.Bencode.Int n)

let value_of_bencode = function
  | Encoding.Bencode.Tagged ('s', Encoding.Bencode.String s) -> Ok (Value.String s)
  | Encoding.Bencode.Tagged ('i', Encoding.Bencode.Int n) -> Ok (Value.Integer n)
  | _ -> Error (malformed_value ())

module rec Representation : (Encoding.Record.S with type t = t) = Encoding.Record.Make (Body)

and Body : Encoding.Record.BODY = struct
  type nonrec t = t

  let tag = 'T'
  let malformed = malformed_value

  let fields {type_; attributes} =
    [ "type", Encoding.Bencode.String type_;
      "attributes", Encoding.Bencode.of_map bencode_of_value attributes ]

  let of_fields data =
    let open Utilities.Result in
    let* type_ = Encoding.Bencode.field "type" data |>> Encoding.Bencode.as_string in
    let* attributes =
      Encoding.Bencode.field "attributes" data |>> Encoding.Bencode.to_map value_of_bencode
    in
    Ok {type_; attributes}
end

let hash tuple = Representation.to_blob tuple |> Hash.hash_of_blob

let to_string {attributes; _} =
  BatMap.String.bindings attributes
  |> List.map (fun (a, v) -> a ^ "=" ^ Value.to_string v)
  |> String.concat " "