| 
 | 1 | +open Kcas  | 
 | 2 | + | 
 | 3 | +type 'a t = { capacity : int; length : int; list : 'a list; limit : int }  | 
 | 4 | + | 
 | 5 | +let empty_unlimited =  | 
 | 6 | +  { capacity = Int.max_int; length = 0; list = []; limit = Int.max_int }  | 
 | 7 | + | 
 | 8 | +let make_empty ~capacity =  | 
 | 9 | +  if capacity = Int.max_int then empty_unlimited  | 
 | 10 | +  else { capacity; length = 0; list = []; limit = capacity }  | 
 | 11 | +  [@@inline]  | 
 | 12 | + | 
 | 13 | +let make ~capacity ~length ~list ~limit = { capacity; length; list; limit }  | 
 | 14 | +  [@@inline]  | 
 | 15 | + | 
 | 16 | +let to_rev_elems t = Elems.of_list_rev t.list [@@inline]  | 
 | 17 | +let is_empty t = t.length = 0 [@@inline]  | 
 | 18 | +let length t = t.length [@@inline]  | 
 | 19 | +let capacity t = t.capacity [@@inline]  | 
 | 20 | +let limit t = t.limit [@@inline]  | 
 | 21 | +let list t = t.list [@@inline]  | 
 | 22 | + | 
 | 23 | +let tl_safe = function  | 
 | 24 | +  | { list = []; _ } as t -> t  | 
 | 25 | +  | { capacity; length; list = _ :: list; _ } as t ->  | 
 | 26 | +      let limit = if capacity = Int.max_int then capacity else t.limit in  | 
 | 27 | +      { capacity; length = length - 1; list; limit }  | 
 | 28 | +  [@@inline]  | 
 | 29 | + | 
 | 30 | +let tl_or_retry = function  | 
 | 31 | +  | { list = []; _ } -> Retry.later ()  | 
 | 32 | +  | { capacity; length; list = _ :: list; _ } as t ->  | 
 | 33 | +      let limit = if capacity = Int.max_int then capacity else t.limit in  | 
 | 34 | +      { capacity; length = length - 1; list; limit }  | 
 | 35 | +  [@@inline]  | 
 | 36 | + | 
 | 37 | +let hd_opt t = match t.list with [] -> None | x :: _ -> Some x [@@inline]  | 
 | 38 | + | 
 | 39 | +let hd_or_retry t = match t.list with [] -> Retry.later () | x :: _ -> x  | 
 | 40 | +  [@@inline]  | 
 | 41 | + | 
 | 42 | +let hd_unsafe t = List.hd t.list [@@inline]  | 
 | 43 | + | 
 | 44 | +let cons_safe x ({ capacity; _ } as t) =  | 
 | 45 | +  if capacity = Int.max_int then  | 
 | 46 | +    let { length; list; _ } = t in  | 
 | 47 | +    { capacity; length = length + 1; list = x :: list; limit = capacity }  | 
 | 48 | +  else  | 
 | 49 | +    let { length; limit; _ } = t in  | 
 | 50 | +    if length < limit then  | 
 | 51 | +      let { list; _ } = t in  | 
 | 52 | +      { capacity; length = length + 1; list = x :: list; limit }  | 
 | 53 | +    else t  | 
 | 54 | +  [@@inline]  | 
 | 55 | + | 
 | 56 | +let cons_or_retry x ({ capacity; _ } as t) =  | 
 | 57 | +  if capacity = Int.max_int then  | 
 | 58 | +    let { length; list; _ } = t in  | 
 | 59 | +    { capacity; length = length + 1; list = x :: list; limit = capacity }  | 
 | 60 | +  else  | 
 | 61 | +    let { length; limit; _ } = t in  | 
 | 62 | +    if length < limit then  | 
 | 63 | +      let { list; _ } = t in  | 
 | 64 | +      { capacity; length = length + 1; list = x :: list; limit }  | 
 | 65 | +    else Retry.later ()  | 
 | 66 | +  [@@inline]  | 
 | 67 | + | 
 | 68 | +let move ({ capacity; _ } as t) =  | 
 | 69 | +  if capacity = Int.max_int then empty_unlimited  | 
 | 70 | +  else  | 
 | 71 | +    let { length; _ } = t in  | 
 | 72 | +    if length = 0 then t  | 
 | 73 | +    else  | 
 | 74 | +      let { limit; _ } = t in  | 
 | 75 | +      { capacity; length = 0; list = []; limit = limit - length }  | 
 | 76 | +  [@@inline]  | 
 | 77 | + | 
 | 78 | +let move_last ({ capacity; _ } as t) =  | 
 | 79 | +  if capacity = Int.max_int then empty_unlimited  | 
 | 80 | +  else  | 
 | 81 | +    let { length; _ } = t in  | 
 | 82 | +    let limit = capacity - length in  | 
 | 83 | +    if length = 0 && t.limit = limit then t  | 
 | 84 | +    else { capacity; length = 0; list = []; limit }  | 
 | 85 | + | 
 | 86 | +let clear ({ capacity; _ } as t) =  | 
 | 87 | +  if capacity = Int.max_int then empty_unlimited  | 
 | 88 | +  else if t.length = 0 && t.limit = capacity then t  | 
 | 89 | +  else make_empty ~capacity  | 
 | 90 | +  [@@inline]  | 
 | 91 | + | 
 | 92 | +let rec prepend_to_seq xs tl =  | 
 | 93 | +  match xs with  | 
 | 94 | +  | [] -> tl  | 
 | 95 | +  | x :: xs -> fun () -> Seq.Cons (x, prepend_to_seq xs tl)  | 
 | 96 | + | 
 | 97 | +let to_seq { list; _ } = prepend_to_seq list Seq.empty  | 
 | 98 | + | 
 | 99 | +let rev_prepend_to_seq { length; list; _ } tl =  | 
 | 100 | +  if length <= 1 then prepend_to_seq list tl  | 
 | 101 | +  else  | 
 | 102 | +    let t = ref (`Original list) in  | 
 | 103 | +    fun () ->  | 
 | 104 | +      let t =  | 
 | 105 | +        match !t with  | 
 | 106 | +        | `Original t' ->  | 
 | 107 | +            (* This is domain safe as the result is always equivalent. *)  | 
 | 108 | +            let t' = List.rev t' in  | 
 | 109 | +            t := `Reversed t';  | 
 | 110 | +            t'  | 
 | 111 | +        | `Reversed t' -> t'  | 
 | 112 | +      in  | 
 | 113 | +      prepend_to_seq t tl ()  | 
 | 114 | + | 
 | 115 | +let of_list ?(capacity = Int.max_int) list =  | 
 | 116 | +  let length = List.length list in  | 
 | 117 | +  let limit = Int.min 0 (capacity - length) in  | 
 | 118 | +  { capacity; length; list; limit }  | 
 | 119 | + | 
 | 120 | +let of_seq_rev ?capacity xs =  | 
 | 121 | +  of_list ?capacity (Seq.fold_left (fun xs x -> x :: xs) [] xs)  | 
0 commit comments