package fluxt
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Extensions of flux to provide basic streams (compression, hash, format)
Install
dune-project
Dependency
Authors
Maintainers
Sources
flux-0.0.1.beta2.tbz
sha256=dbfb198a16aab3f8987cc2ba31bc8da3720b9031d2b6b1a3313e6c1342cbf4b3
sha512=ec0ab77c2b1db2fd730581cefbb92f8391c3f8801cd02bb558609f46daff493e8c513e1d0978d1cdc613ce7ef1799e144d1f9740e0863169e45992df4c117ba4
doc/src/fluxt.zip/flux_zip.ml.html
Source file flux_zip.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 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215type entry = { filepath: string ; mtime: Ptime.t ; tz_offset_s: Ptime.tz_offset_s option ; src: string Flux.source ; level: int } let of_filepath ?tz_offset_s ?(mtime = Ptime.epoch) ?(level = 6) filepath src = if level < 0 || level > 9 then failwith "Invalid compression level (must be in 0 and 8 included)"; if String.length filepath >= 0x1000 then failwith "Too long filepath"; { filepath; mtime; tz_offset_s; src; level } let of_ptime ?tz_offset_s t = let (y, m, d), ((hh, mm, ss), _) = Ptime.to_date_time ?tz_offset_s t in let time = (ss lsr 1) + (mm lsl 5) + (hh lsl 11) in let date = d + (m lsl 5) + ((y - 1980) lsl 9) in (time, date) let to_sink : type a s. push:(s -> a -> s) -> ?full:(s -> bool) -> s -> (a, s) Flux.sink = fun ~push ?full acc -> let init () = acc and full = match full with Some full -> full | None -> Fun.const false and stop acc = acc in Flux.Sink { init; push; full; stop } let deflate ~level from into = let crc32 = ref Checkseum.Crc32.default in let csz = ref 0L in let usz = ref 0L in let on_source str = let len = String.length str in crc32 := Checkseum.Crc32.digest_string str 0 len !crc32; usz := Int64.add !usz (Int64.of_int len) in let on_deflated str = csz := Int64.add !csz (Int64.of_int (String.length str)) in match level with | 0 -> let via = let open Flux.Flow in tap on_source << tap on_deflated in let acc, src = Flux.Stream.run ~from ~via ~into in Option.iter Flux.Source.dispose src; (acc, !crc32, !csz, !usz) | level -> let cfg = Flux_de.config ~level () in let via = let open Flux.Flow in tap on_source << bstr ~len:0x1000 << Flux_de.deflate ~cfg << tap on_deflated in let acc, src = Flux.Stream.run ~from ~via ~into in Option.iter Flux.Source.dispose src; (acc, !crc32, !csz, !usz) type cdfh = { filepath: string ; meth: [ `Stored | `Deflated ] ; mtime: Ptime.t ; tz_offset_s: Ptime.tz_offset_s option ; crc32: Checkseum.Crc32.t ; csz: int64 ; usz: int64 ; offset: int64 } module S = Set.Make (String) let rev_uniq entries = let rec rev acc seen = function | [] -> acc | cdfh :: entries -> if S.mem cdfh.filepath seen then rev acc seen entries else rev (cdfh :: acc) (S.add cdfh.filepath seen) entries in rev [] S.empty entries let zip = let ( let* ) = Result.bind in let open Flux in let flow (Sink k) = let init () = Ok (k.init (), [], 0L) in let emit acc str = match k.full acc with | true -> Error (`Full acc) | false -> Ok (k.push acc str) in let push acc { filepath; mtime; tz_offset_s; level; src } = match acc with | Error _ as err -> err | Ok (acc, entries, offset) -> let filepath = if Sys.os_type = "Win32" then String.map (function '\\' -> '/' | chr -> chr) filepath else filepath in let time, date = of_ptime ?tz_offset_s mtime in let buf = Bytes.create 30 in Bytes.set_int32_le buf 0 0x04034b50l; Bytes.set_uint16_le buf 4 45; Bytes.set_uint16_le buf 6 0b1000; Bytes.set_uint16_le buf 8 (if level = 0 then 0 else 8); Bytes.set_uint16_le buf 10 time; Bytes.set_uint16_le buf 12 date; Bytes.set_int32_le buf 14 0l; Bytes.set_int32_le buf 18 0xffffffffl; Bytes.set_int32_le buf 22 0xffffffffl; Bytes.set_uint16_le buf 26 (String.length filepath); Bytes.set_uint16_le buf 28 20; let* acc = emit acc (Bytes.unsafe_to_string buf) in let* acc = emit acc filepath in let buf = Bytes.create 20 in Bytes.set_uint16_le buf 0 0x0001; Bytes.set_uint16_le buf 2 16; Bytes.set_int64_le buf 4 0xffffffffffffffffL; Bytes.set_int64_le buf 12 0xffffffffffffffffL; let* acc = emit acc (Bytes.unsafe_to_string buf) in let into = to_sink ~push:k.push ~full:k.full acc in let acc, crc32, csz, usz = deflate ~level src into in let buf = Bytes.create 24 in Bytes.set_int32_le buf 0 0x08074b50l; Bytes.set_int32_le buf 4 (Optint.to_unsigned_int32 crc32); Bytes.set_int64_le buf 8 csz; Bytes.set_int64_le buf 16 usz; let* acc = emit acc (Bytes.unsafe_to_string buf) in let meth = if level = 0 then `Stored else `Deflated in let cdfh = { filepath; meth; mtime; tz_offset_s; crc32; usz; csz; offset } in let len = Int64.of_int (30 + String.length filepath + 20 + 24) in let len = Int64.add len csz in Ok (acc, cdfh :: entries, Int64.add offset len) in let full = function Ok (acc, _, _) | Error (`Full acc) -> k.full acc in let stop state = let close (acc, entries, start_cd) = let entries = rev_uniq entries in let rec go acc start_ecd = function | [] -> Ok (acc, start_ecd) | { filepath; meth; mtime; tz_offset_s; crc32; csz; usz; offset } :: entries -> let buf = Bytes.create 46 in Bytes.set_int32_le buf 0 0x02014b50l; Bytes.set_uint16_le buf 4 45; Bytes.set_uint16_le buf 6 45; Bytes.set_uint16_le buf 8 0b1000; Bytes.set_uint16_le buf 10 (if meth = `Stored then 0 else 8); let time, date = of_ptime ?tz_offset_s mtime in Bytes.set_uint16_le buf 12 time; Bytes.set_uint16_le buf 14 date; Bytes.set_int32_le buf 16 (Optint.to_unsigned_int32 crc32); Bytes.set_int32_le buf 20 0xffffffffl; Bytes.set_int32_le buf 24 0xffffffffl; Bytes.set_uint16_le buf 28 (String.length filepath); Bytes.set_uint16_le buf 30 28; Bytes.set_uint16_le buf 32 0; Bytes.set_uint16_le buf 34 0; Bytes.set_uint16_le buf 36 0; Bytes.set_int32_le buf 38 0l; Bytes.set_int32_le buf 42 0xffffffffl; let* acc = emit acc (Bytes.unsafe_to_string buf) in let* acc = emit acc filepath in let buf = Bytes.create 28 in Bytes.set_uint16_le buf 0 0x0001; Bytes.set_uint16_le buf 2 24; Bytes.set_int64_le buf 4 usz; Bytes.set_int64_le buf 12 csz; Bytes.set_int64_le buf 20 offset; let* acc = emit acc (Bytes.unsafe_to_string buf) in let len = Int64.of_int (46 + String.length filepath + 28) in let start_ecd = Int64.add start_ecd len in go acc start_ecd entries in let* acc, start_ecd = go acc start_cd entries in let cd_size = Int64.sub start_ecd start_cd in let buf = Bytes.create 98 in Bytes.set_int32_le buf 0 0x06064b50l; Bytes.set_int64_le buf 4 44L; Bytes.set_uint16_le buf 12 45; Bytes.set_uint16_le buf 14 45; Bytes.set_int32_le buf 16 0l; Bytes.set_int32_le buf 20 0l; let num_entries = Int64.of_int (List.length entries) in Bytes.set_int64_le buf 24 num_entries; Bytes.set_int64_le buf 32 num_entries; Bytes.set_int64_le buf 40 cd_size; Bytes.set_int64_le buf 48 start_cd; Bytes.set_int32_le buf 56 0x07064b50l; Bytes.set_int32_le buf 60 0l; Bytes.set_int64_le buf 64 start_ecd; Bytes.set_int32_le buf 72 0l; Bytes.set_int32_le buf 76 0x06054b50l; Bytes.set_uint16_le buf 80 0xffff; Bytes.set_uint16_le buf 82 0xffff; Bytes.set_uint16_le buf 84 0xffff; Bytes.set_uint16_le buf 86 0xffff; Bytes.set_int32_le buf 88 0xffffffffl; Bytes.set_int32_le buf 92 0xffffffffl; Bytes.set_uint16_le buf 96 0; let* acc = emit acc (Bytes.unsafe_to_string buf) in Ok acc in match Result.bind state close with | Ok acc | Error (`Full acc) -> k.stop acc in Sink { init; push; full; stop } in { flow }
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>