123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330(* Conversions between units of measure based on bytes. *)open!ImportopenStd_internalmoduleRepr=Int63moduleT=Byte_units0include(T:moduletypeofTwithmoduleRepr:=Repr)includeComparable.Make_plain(T)includeHashable.Make_plain(T)moduleInfix=structlet(-)ab=of_repr(Repr.(-)(to_repra)(to_reprb))let(+)ab=of_repr(Repr.(+)(to_repra)(to_reprb))let(//)ab=Repr.(//)(to_repra)(to_reprb)let(/)ts=of_repr(Repr.of_float(Repr.to_float(to_reprt)/.s))let(*)ts=of_repr(Repr.of_float(Repr.to_float(to_reprt)*.s))endincludeInfixletzero=of_reprRepr.zeroletmin_value=of_reprRepr.min_valueletmax_value=of_reprRepr.max_valueletscale=Infix.(*)letiscalets=of_repr(Repr.(*)(to_reprt)(Repr.of_ints))letbytes_int_exn=T.bytes_int_exnletbytes_int63=to_reprletbytes_int64t=Repr.to_int64(to_reprt)letbytes_floatt=Repr.to_float(to_reprt)letof_bytes_intb=of_repr(Repr.of_intb)letof_bytes_int63=of_reprletof_bytes_int64_exnb=of_repr(Repr.of_int64_exnb)letof_bytes_float_exnb=of_repr(Repr.of_floatb)let[@deprecated"[since 2019-01] Use [bytes_int_exn], [bytes_int63], [bytes_int64] or [bytes_float] \
as appropriate."]bytes=bytes_float;;let[@deprecated"[since 2019-01] Use [of_bytes_int], [of_bytes_int63], [of_bytes_int64_exn] or \
[of_bytes_float_exn] as appropriate."]of_bytes=of_bytes_float_exn;;letkilobyte:t=of_bytes_int1024letmegabyte=iscalekilobyte1024letgigabyte=iscalemegabyte1024letterabyte=iscalegigabyte1024letpetabyte=iscaleterabyte1024letexabyte=iscalepetabyte1024letword=letmoduleW=Word_sizeinmatchW.word_sizewith|W.W32->of_bytes_int4|W.W64->of_bytes_int8;;letkilobytest:float=Infix.(//)tkilobyteletmegabytest=Infix.(//)tmegabyteletgigabytest=Infix.(//)tgigabyteletterabytest=Infix.(//)tterabyteletpetabytest=Infix.(//)tpetabyteletexabytest=Infix.(//)texabyteletwords_int_exnt=Repr.to_int_exn(Repr.(/)(to_reprt)(to_reprword))letwords_floatt=Infix.(//)twordletof_kilobytest:t=Infix.(*)kilobytetletof_megabytest=Infix.(*)megabytetletof_gigabytest=Infix.(*)gigabytetletof_terabytest=Infix.(*)terabytetletof_petabytest=Infix.(*)petabytetletof_exabytest=Infix.(*)exabytetletof_words_intt=iscalewordtletof_words_float_exnt=Infix.(*)wordtlet[@deprecated"[since 2019-01] Use [words_int_exn] or [words_float]"]words=words_float;;let[@deprecated"[since 2019-01] Use [of_words_int] or [of_words_float_exn]"]of_words=of_words_float_exn;;letof_strings=letlength=String.lengthsinifInt.(<)length2theninvalid_argf"'%s' passed to Byte_units.of_string - too short"s();letbase_str=String.subs~pos:0~len:(Int.(-)length1)inletext_char=Char.lowercases.[Int.(-)length1]inletbase=tryFloat.of_stringbase_strwith|_->invalid_argf"'%s' passed to Byte_units.of_string - %s cannot be converted to float "sbase_str()inmatchext_charwith|'b'->of_bytes_float_exnbase|'k'->of_kilobytesbase|'m'->of_megabytesbase|'g'->of_gigabytesbase|'t'->of_terabytesbase|'p'->of_petabytesbase|'e'->of_exabytesbase|'w'->of_wordsbase|ext->invalid_argf"'%s' passed to Byte_units.of_string - illegal extension %c"sext();;letarg_type=Command.Arg_type.createof_stringletlargest_measuret=lett_abs=of_repr(Repr.abs(to_reprt))inift_abs>=exabytethen`Exabyteselseift_abs>=petabytethen`Petabyteselseift_abs>=terabytethen`Terabyteselseift_abs>=gigabytethen`Gigabyteselseift_abs>=megabytethen`Megabyteselseift_abs>=kilobytethen`Kilobyteselse`Bytes;;moduleStable=struct(* Share the common [of_sexp] code for [V1] and [V2]. *)moduleOf_sexp_v1_v2:sigvalt_of_sexp:Sexp.t->tend=structletno_match()=failwith"Not a recognized [Byte_units.t] representation"letof_value_sexp_and_unit_nameval_sexp=function|"Bytes"->(tryof_bytes_int63(Int63.t_of_sexpval_sexp)with|_->of_bytes_float_exn(Float.t_of_sexpval_sexp))|"Kilobytes"->of_kilobytes(float_of_sexpval_sexp)|"Megabytes"->of_megabytes(float_of_sexpval_sexp)|"Gigabytes"->of_gigabytes(float_of_sexpval_sexp)|"Terabytes"->of_terabytes(float_of_sexpval_sexp)|"Petabytes"->of_petabytes(float_of_sexpval_sexp)|"Exabytes"->of_exabytes(float_of_sexpval_sexp)|"Words"->of_words_float_exn(float_of_sexpval_sexp)|_->no_match();;lett_of_sexp=function|Sexp.Atomstr->of_stringstr|Sexp.List[Sexp.Atomunit_name;value]->of_value_sexp_and_unit_namevalueunit_name|_->no_match();;lett_of_sexpsexp=tryt_of_sexpsexpwith|exn->raise(Sexp.Of_sexp_error(exn,sexp));;endmoduleV1=structtypenonrect=t[@@derivingcompare,hash]includeBinable0.Of_binable_without_uuid[@alert"-legacy"](Float)(structtypenonrect=tletto_binable=bytes_floatletof_binable=of_bytes_float_exnend)includeOf_sexp_v1_v2letsexp_of_tt=(* V1 only goes up to gigabytes *)matchlargest_measuretwith|`Bytes->[%sexp`Bytes(bytes_floatt:float)]|`Kilobytes->[%sexp`Kilobytes(kilobytest:float)]|`Megabytes->[%sexp`Megabytes(megabytest:float)]|`Gigabytes|`Terabytes|`Petabytes|`Exabytes->[%sexp`Gigabytes(gigabytest:float)];;letto_stringt=String.lowercase(to_stringt)letof_string=of_string(* This test documents the original to-string representation and fails under javascript
due to differences in the rounding. *)let%expect_test(_[@tags"no-js"])=printf!"%{}"(of_bytes_int1000);[%expect{| 1000b |}];printf!"%{}"(of_bytes_int1023);[%expect{| 1023b |}];printf!"%{}"(of_bytes_int1024);[%expect{| 1k |}];printf!"%{}"(of_bytes_int1025);[%expect{| 1.00098k |}];printf!"%{}"(of_bytes_int1500);[%expect{| 1.46484k |}];printf!"%{}"(of_bytes_int10000);[%expect{| 9.76562k |}];printf!"%{}"(of_bytes_int100000);[%expect{| 97.6562k |}];printf!"%{}"(of_bytes_int1000000);[%expect{| 976.562k |}];printf!"%{}"(of_bytes_int10000000);[%expect{| 9.53674m |}];;lett_of_sexpsexp=matchsexpwith|Sexp.Atoms->(tryof_stringswith|Invalid_argumentmsg->of_sexp_errormsgsexp)|Sexp.List_->t_of_sexpsexp;;endmoduleV2=structtypenonrect=t[@@derivingcompare,hash]includeBinable0.Of_binable_without_uuid[@alert"-legacy"](Int63)(structtypenonrect=tletto_binable=bytes_int63letof_binable=of_bytes_int63end)includeOf_sexp_v1_v2letsexp_of_tt=[%sexp`Bytes(bytes_int63t:Int63.t)]endendletto_string_hum=T.to_stringmoduleShort=structtypenonrect=tletto_stringt=letto_units_strto_unitext=letf=to_unittinletf_abs=Float.absfinifFloat.Robustly_comparable.(>=.)f_abs100.thensprintf"%.0f%c"fextelseifFloat.Robustly_comparable.(>=.)f_abs10.thensprintf"%.1f%c"fextelsesprintf"%.2f%c"fextinmatchlargest_measuretwith|`Bytes->sprintf"%dB"(bytes_int_exnt)|`Kilobytes->to_units_strkilobytes'K'|`Megabytes->to_units_strmegabytes'M'|`Gigabytes->to_units_strgigabytes'G'|`Terabytes->to_units_strterabytes'T'|`Petabytes->to_units_strpetabytes'P'|`Exabytes->to_units_strexabytes'E';;letsexp_of_tt=Sexp.Atom(to_stringt)let%expect_test_=printf!"%{}"(of_bytes_int1000);[%expect{| 1000B |}];printf!"%{}"(of_bytes_int1023);[%expect{| 1023B |}];printf!"%{}"(of_bytes_int1024);[%expect{| 1.00K |}];printf!"%{}"(of_bytes_int1025);[%expect{| 1.00K |}];printf!"%{}"(of_bytes_int10000);[%expect{| 9.77K |}];printf!"%{}"(of_bytes_int100000);[%expect{| 97.7K |}];printf!"%{}"(of_bytes_int1000000);[%expect{| 977K |}];printf!"%{}"(of_bytes_int10000000);[%expect{| 9.54M |}];printf!"%{}"(of_bytes10000000000.);[%expect{| 9.31G |}];printf!"%{}"(of_bytes1000000000000.);[%expect{| 931G |}];printf!"%{}"(of_bytes100000000000000.);[%expect{| 90.9T |}];printf!"%{}"(of_bytes100000000000000000.);[%expect{| 88.8P |}];printf!"%{}"(of_bytes3000000000000000000.);[%expect{| 2.60E |}];();;endletto_string_short=Short.to_stringlet[@deprecated"[since 2019-01] Use [of_bytes], [of_kilobytes], [of_megabytes], etc as appropriate."]createunitsvalue=matchunitswith|`Bytes->of_bytes_float_exnvalue|`Kilobytes->of_kilobytesvalue|`Megabytes->of_megabytesvalue|`Gigabytes->of_gigabytesvalue|`Words->of_words_float_exnvalue;;includeQuickcheckable.Of_quickcheckable(Repr)(structtypenonrect=tletof_quickcheckable=of_reprletto_quickcheckable=to_reprend)