Persistent store with Git semantics: lazy reads, delayed writes, content-addressing
at inline-small-objects 107 lines 3.3 kB view raw
1(** Content-addressed hashes with phantom types for algorithm safety. 2 3 This module provides SHA-1 and SHA-256 hash types that are distinguished at 4 the type level, preventing accidental mixing of different hash algorithms. 5*) 6 7(** {1 Hash Algorithms} *) 8 9type algorithm = 10 | Sha1 (** SHA-1: 20 bytes, Git compatible *) 11 | Sha256 (** SHA-256: 32 bytes, ATProto compatible *) 12 13(** {1 Phantom-Typed Hashes} *) 14 15type 'a t 16(** ['a t] is a hash where ['a] is a phantom type indicating the algorithm. *) 17 18type sha1 = [ `Sha1 ] t 19(** SHA-1 hash: 20 bytes, used by Git. *) 20 21type sha256 = [ `Sha256 ] t 22(** SHA-256 hash: 32 bytes, used by ATProto MST. *) 23 24(** {1 Hash Construction} *) 25 26val sha1 : string -> sha1 27(** [sha1 data] computes the SHA-1 hash of [data]. *) 28 29val sha256 : string -> sha256 30(** [sha256 data] computes the SHA-256 hash of [data]. *) 31 32val sha1_of_bytes : string -> sha1 33(** [sha1_of_bytes raw] creates a SHA-1 hash from raw 20-byte digest. *) 34 35val sha256_of_bytes : string -> sha256 36(** [sha256_of_bytes raw] creates a SHA-256 hash from raw 32-byte digest. *) 37 38(** {1 Conversions} *) 39 40val to_bytes : _ t -> string 41(** [to_bytes h] returns the raw bytes of the hash digest. *) 42 43val to_hex : _ t -> string 44(** [to_hex h] returns the hexadecimal representation of the hash. *) 45 46type existential = 47 | Ex : _ t -> existential 48 (** Type-erased hash returned when algorithm is only known at runtime. *) 49 50val of_hex : algorithm -> string -> (existential, [> `Msg of string ]) result 51(** [of_hex algo hex] parses a hexadecimal hash string. *) 52 53val sha1_of_hex : string -> (sha1, [> `Msg of string ]) result 54(** [sha1_of_hex hex] parses a SHA-1 hex string. *) 55 56val sha256_of_hex : string -> (sha256, [> `Msg of string ]) result 57(** [sha256_of_hex hex] parses a SHA-256 hex string. *) 58 59(** {1 Comparison} *) 60 61val equal : 'a t -> 'a t -> bool 62(** [equal h1 h2] is [true] if [h1] and [h2] are the same hash. *) 63 64val compare : 'a t -> 'a t -> int 65(** [compare h1 h2] is a total ordering on hashes. *) 66 67(** {1 Algorithm Info} *) 68 69val length : _ t -> int 70(** [length h] returns the byte length of the hash (20 for SHA-1, 32 for 71 SHA-256). *) 72 73val algorithm_of : _ t -> algorithm 74(** [algorithm_of h] returns the algorithm used for [h]. *) 75 76val algorithm_length : algorithm -> int 77(** [algorithm_length algo] returns the byte length for [algo]. *) 78 79(** {1 MST Support} *) 80 81val mst_depth : sha256 -> int 82(** [mst_depth h] counts leading zeros in 2-bit chunks for ATProto MST. This 83 determines the tree depth for a given key hash. *) 84 85(** {1 Type-Erased Hashes} *) 86 87type any = Any : _ t -> any (** Type-erased hash for mixed-hash stores. *) 88 89val any_algorithm : any -> algorithm 90(** [any_algorithm (Any h)] returns the algorithm of the erased hash. *) 91 92val any_to_bytes : any -> string 93(** [any_to_bytes (Any h)] returns the raw bytes. *) 94 95val any_to_hex : any -> string 96(** [any_to_hex (Any h)] returns the hex representation. *) 97 98val equal_any : any -> any -> bool 99(** [equal_any a1 a2] compares two type-erased hashes. *) 100 101(** {1 Pretty Printing} *) 102 103val pp : Format.formatter -> _ t -> unit 104(** [pp fmt h] pretty-prints [h] as hex. *) 105 106val pp_short : Format.formatter -> _ t -> unit 107(** [pp_short fmt h] pretty-prints the first 7 characters of [h] (Git-style). *)