aboutsummaryrefslogblamecommitdiffstats
path: root/lib/kernel/Prototype.ml
blob: b159e003096604281461ebe589c48e906d83bad2 (plain) (tree)
1
2
3
4
5
6
7
8
9
10





                                                                                            

                                                 

                      


                                                       









                                                                                                                               











                                                                        
                           














                                                         























                                                                                             
                         
                           








                                                                                                                
                                              




                                          

                                                                                       





                                                                                       
let mixture ps = Protocols.Handle.make @@
                   object
                     inherit Lifecycle.null
                     inherit Identity.of_id (* Should we allow the user to override this? *)

                     method protocols = ps

                     method to_string = "mixture"
                   end

let rec mixture_of value f =
  mixture (f (fun value' -> mixture_of value' f) value)

module Error = struct
  open Concepts.Condition

  let invalid_property key = condition "invalid-property" "The specified key does not correspond to any property of the object"
                               ("key" |=| Concepts.Value.String key)

  let deletion_not_supported () = condition "deletion-not-supported" "Attempting to delete an object property"
                                    empty
end

module Addressable = struct
  module OfTree (S : Abstract.Storage.STORAGE) (K : Merkle.KEY) = struct
    module Tree = Merkle.Make (S) (K)

    let make ~node =
      Protocols.Addressable.make @@
        object
          method address = Tree.hash_of node
        end
  end
end

module Associative = struct
  let of_properties props =
    Protocols.Associative.make @@
      object
        val props = BatList.to_seq props |> BatMap.of_seq

        method update key value =
          match BatMap.find_opt key props with
          | None -> Error (Error.invalid_property key)
          | Some f -> f value
      end

  let update_only f = function
    | None -> Error (Error.deletion_not_supported ())
    | Some x -> f x

  module OfTree (S : Abstract.Storage.STORAGE) (K : Merkle.KEY with type t = string) = struct
    module Tree = Merkle.Make (S) (K)
    module SI = Storage.Make (S)

    let make ~storage ~constructor ~node =
      Protocols.Associative.make @@
        object
          method update key value =
            (* TODO: read-only transactions *)
            SI.with_transaction storage (fun tx ->
                let open Utilities.Result in
                let open Protocols in
                let* node' = match value with
                  | None -> Tree.remove tx key node
                  | Some h ->
                     let* addressable = Handle.require Addressable.from h in
                     let addr = Addressable.address addressable in
                     Tree.insert tx key addr node
                in
                constructor node')
        end
  end
end

module Directory = struct
  let of_properties props =
    Protocols.Directory.make @@
      object
        val props = BatList.to_seq props |> BatMap.of_seq

        method list = Ok (BatMap.keys props |> BatFingerTree.of_enum)
        method find k = Ok (BatMap.find_opt k props)
      end

  module OfTree (S : Abstract.Storage.STORAGE) (K : Merkle.KEY with type t = string) (V : Merkle.VALUE) = struct
    module Tree = Merkle.Interface (S) (K) (V)
    module SI = Storage.Make (S)

    let make ~storage ~constructor ~node =
      Protocols.Directory.make @@
        object
          method list = SI.with_transaction storage (Fun.flip Tree.keys node)
          method find k = SI.with_transaction storage (fun tx -> Tree.lookup tx k node)
                          |> Utilities.Result.fmap (function
                                 | None -> Ok None
                                 | Some x -> constructor x |> Result.map (Option.some))
        end
  end
end