123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148open!Importtype'at=intmoduletypeS=Syscall_result_intf.Swithtype'asyscall_result:='atmoduletypeArg=Syscall_result_intf.ArgmoduleUnix=UnixLabelsletcreate_errorerr=-(Unix_error.to_errnoerr)letis_okt=Int.O.(t>=0)letis_errort=Int.O.(t<0)leterror_code_exnt=ifis_oktthenfailwiths~here:[%here]"Syscall_result.error_code_exn received success value"t[%sexp_of:int]else-t;;leterror_exnt=Unix_error.of_errno(error_code_exnt)moduleMake(M:Arg)()=struct(* The only reason to have one of these per functor invocation is to make it trivial to
get the type right. *)letpreallocated_errnos:(_,Unix_error.t)Result.tarray=Array.init64~f:(funi->Error(Unix_error.of_errnoi));;(* Since we return [-errno] from C, we implicitly rely on there not being a 0 [errno].
However, we have 0 in [preallocated_errnos], partly so we can index directly by
[errno]. *)let%test"no 0 errno"=preallocated_errnos.(0)=Error(Unix_error.EUNKNOWNERR0)letnum_preallocated_errnos=Array.lengthpreallocated_errnostypenonrect=M.ttletcompare=Int.compareletequal=Int.equalletpreallocated_ms=letrecloopirev_acc=(* Preallocate at most a handful of Ms. 2048 is the first round binary number after
1500, the likely maximum result for many network functions that use
[Syscall_result.Int]. *)ifi=2048thenArray.of_list_revrev_accelsematchM.of_int_exniwith|exception_->Array.of_list_revrev_acc|m->loop(i+1)(Okm::rev_acc)inloop0[];;letnum_preallocated_ms=Array.lengthpreallocated_msletcreate_okx=lett=M.to_intxinift<0thenfailwithf"Syscall_result.create_ok received negative value (%d)"t()elset;;letcreate_error=create_errorletis_ok=is_okletis_error=is_errorletto_resultt=ifis_oktthenift<num_preallocated_msthenArray.unsafe_getpreallocated_mstelseOk(M.of_int_exnt)else(leterrno=-tiniferrno<num_preallocated_errnosthenArray.unsafe_getpreallocated_errnoserrnoelseError(Unix_error.of_errnoerrno));;letsexp_of_tt=[%sexp_of:(M.t,Unix_error.t)Result.t](to_resultt)letok_exnt=ifis_oktthenM.of_int_exntelsefailwiths~here:[%here]"Syscall_result.ok_exn received error value"tsexp_of_t;;leterror_code_exnt=ifis_oktthenfailwiths~here:[%here]"Syscall_result.error_code_exn received success value"tsexp_of_telse-t;;leterror_exnt=Unix_error.of_errno(error_code_exnt)letreinterpret_error_exnt=ifis_oktthenfailwiths~here:[%here]"Syscall_result.cast_error_exn received success value"tsexp_of_telset;;letok_or_unix_error_exnt~syscall_name=ifis_oktthenM.of_int_exntelseraise(Unix.Unix_error(Unix_error.of_errno(-t),syscall_name,""));;letok_or_unix_error_with_args_exnt~syscall_namexsexp_of_x=ifis_oktthenM.of_int_exntelseraise(Unix.Unix_error(Unix_error.of_errno(-t),syscall_name,Sexp.to_string(sexp_of_xx)));;letis_nonet=is_errortletunchecked_valuet=M.of_int_exntmoduleOptional_syntax=structmoduleOptional_syntax=structletis_none=is_noneletunsafe_value=unchecked_valueendendmodulePrivate=structletof_intt=tletlength_preallocated_errnos=Array.lengthpreallocated_errnosletlength_preallocated_ms=Array.lengthpreallocated_msendendmoduleInt=Make(Int)()moduleUnit=Make(structtypet=unit[@@derivingsexp_of,compare]letof_int_exnn=assert(n=0)letto_int()=0end)()letunit=Unit.create_ok()letignore_ok_valuet=Core_kernel.Int.mint0