diff options
Diffstat (limited to '')
| -rw-r--r-- | lib/protocols/Cursor.ml | 36 | ||||
| -rw-r--r-- | lib/protocols/Cursor.mli | 21 |
2 files changed, 57 insertions, 0 deletions
diff --git a/lib/protocols/Cursor.ml b/lib/protocols/Cursor.ml new file mode 100644 index 0000000..36db97d --- /dev/null +++ b/lib/protocols/Cursor.ml @@ -0,0 +1,36 @@ +module Error = struct + open Concepts.Condition + + let not_a_cursor () = + condition "not-a-cursor" "A handle was expected to carry the cursor protocol and did not" empty +end + +type batch = {tuples: Concepts.Tuple.t BatFingerTree.t; exhausted: bool} + +class type implementation = object + method fetch : int -> (batch, Concepts.Condition.condition) result +end + +type Handle.protocol += Cursor of implementation +type t = implementation + +let make impl = Cursor (impl :> implementation) +let from handle = Handle.into handle (function Cursor impl -> Some impl | _ -> None) +let require handle = from handle |> Option.to_result ~none:(Error.not_a_cursor ()) +let fetch i limit = Handle.invoke i (fun o -> o#fetch limit) + +let rec next i = + let open Utilities.Result in + let* batch = fetch i 1 in + match BatFingerTree.front batch.tuples with + | Some (_, tuple) -> Ok (Some tuple) + | None -> if batch.exhausted then Ok None else next i + +let drain i ?(limit = 256) () = + let open Utilities.Result in + let rec loop tuples = + let* batch = fetch i limit in + let tuples = BatFingerTree.append tuples batch.tuples in + if batch.exhausted then Ok tuples else loop tuples + in + loop BatFingerTree.empty diff --git a/lib/protocols/Cursor.mli b/lib/protocols/Cursor.mli new file mode 100644 index 0000000..08c7628 --- /dev/null +++ b/lib/protocols/Cursor.mli @@ -0,0 +1,21 @@ +type batch = + {tuples: Concepts.Tuple.t BatFingerTree.t; exhausted: bool} + +type t + +class type implementation = object + method fetch : int -> (batch, Concepts.Condition.condition) result +end + +val make : #implementation -> Handle.protocol +val from : Handle.t -> t Handle.interface option +val require : Handle.t -> (t Handle.interface, Concepts.Condition.condition) result +val fetch : t Handle.interface -> int -> (batch, Concepts.Condition.condition) result + +val next : t Handle.interface -> (Concepts.Tuple.t option, Concepts.Condition.condition) result + +val drain : + t Handle.interface -> + ?limit:int -> + unit -> + (Concepts.Tuple.t BatFingerTree.t, Concepts.Condition.condition) result |
