Source file decode.ml

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
open Decoders

module Bencode_decodeable : Decode.Decodeable with type value = Bencode.t = struct
  type value = Bencode.t

  let pp fmt t = Format.fprintf fmt "@[%s@]" (Bencode.pretty_print t)

  let of_string (input : string) : (value, string) result =
    try Ok (Bencode.decode (`String input)) with
    | _ -> Error "invalid bencode"

  let of_file (file : string) : (value, string) result =
    try
      let v = Decoders_util.with_file_in file (fun ic -> Bencode.decode (`Channel ic)) in
      Ok v
    with
    | e -> Error (Printexc.to_string e)

  let get_string = function
    | Bencode.String str -> Some str
    | _ -> None

  let get_int = function
    | Bencode.Integer int -> Some (Int64.to_int int)
    | Bencode.String s -> (try Some (int_of_string s) with _ -> None)
    | _ -> None

  let get_float = function
    | Bencode.String s -> (try Some (float_of_string s) with _ -> None)
    | _ -> None

  let get_null = function
    | Bencode.Integer 0L | Bencode.List [] -> Some ()
    | _ -> None

  let get_bool = function
    | Bencode.Integer 1L | Bencode.String "true" -> Some true
    | Bencode.Integer 0L | Bencode.String "false" -> Some false
    | _ -> None

  let get_list = function
    | Bencode.List a -> Some a
    | _ -> None

  let get_key_value_pairs = function
    | Bencode.Dict assoc ->
      Some (List.rev_map (fun (s,v) -> Bencode.String s, v) assoc)
    | _ -> None

  let to_list vs = Bencode.List vs
end

include Decode.Make(Bencode_decodeable)

let int64 : int64 decoder =
  { run =
      fun t ->
        match t with
        | Bencode.Integer value -> Ok value
        | _ -> (fail "Expected an int64").run t
  }