/- Copyright (c) 2019 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon -/ prelude import Init.Core import Init.Data.UInt import Init.Data.ToString.Basic import Init.Data.String.Basic /- Imitate the structure of IOErrorType in Haskell: https://hackage.haskell.org/package/base-4.12.0.0/docs/System-IO-Error.html#t:IOErrorType -/ inductive IO.Error where | alreadyExists (filename : Option String) (osCode : UInt32) (details : String) -- EEXIST, EINPROGRESS, EISCONN | otherError (osCode : UInt32) (details : String) -- EFAULT, default | resourceBusy (osCode : UInt32) (details : String) -- EADDRINUSE, EBUSY, EDEADLK, ETXTBSY | resourceVanished (osCode : UInt32) (details : String) -- ECONNRESET, EIDRM, ENETDOWN, ENETRESET, -- ENOLINK, EPIPE | unsupportedOperation (osCode : UInt32) (details : String) -- EADDRNOTAVAIL, EAFNOSUPPORT, ENODEV, ENOPROTOOPT -- ENOSYS, EOPNOTSUPP, ERANGE, ESPIPE, EXDEV | hardwareFault (osCode : UInt32) (details : String) -- EIO | unsatisfiedConstraints (osCode : UInt32) (details : String) -- ENOTEMPTY | illegalOperation (osCode : UInt32) (details : String) -- ENOTTY | protocolError (osCode : UInt32) (details : String) -- EPROTO, EPROTONOSUPPORT, EPROTOTYPE | timeExpired (osCode : UInt32) (details : String) -- ETIME, ETIMEDOUT | interrupted (filename : String) (osCode : UInt32) (details : String) -- EINTR | noFileOrDirectory (filename : String) (osCode : UInt32) (details : String) -- ENOENT | invalidArgument (filename : Option String) (osCode : UInt32) (details : String) -- ELOOP, ENAMETOOLONG, EDESTADDRREQ, EILSEQ, EINVAL, EDOM, EBADF -- ENOEXEC, ENOSTR, ENOTCONN, ENOTSOCK | permissionDenied (filename : Option String) (osCode : UInt32) (details : String) -- EACCES, EROFS, ECONNABORTED, EFBIG, EPERM | resourceExhausted (filename : Option String) (osCode : UInt32) (details : String) -- EMFILE, ENFILE, ENOSPC, E2BIG, EAGAIN, EMLINK: -- EMSGSIZE, ENOBUFS, ENOLCK, ENOMEM, ENOSR: | inappropriateType (filename : Option String) (osCode : UInt32) (details : String) -- EISDIR, EBADMSG, ENOTDIR: | noSuchThing (filename : Option String) (osCode : UInt32) (details : String) -- ENXIO, EHOSTUNREACH, ENETUNREACH, ECHILD, ECONNREFUSED, -- ENODATA, ENOMSG, ESRCH | unexpectedEof | userError (msg : String) deriving Inhabited @[export lean_mk_io_user_error] def IO.userError (s : String) : IO.Error := IO.Error.userError s instance : Coe String IO.Error := ⟨IO.userError⟩ namespace IO.Error @[export lean_mk_io_error_already_exists_file] def mkAlreadyExistsFile : String → UInt32 → String → IO.Error := alreadyExists ∘ some @[export lean_mk_io_error_eof] def mkEofError : Unit → IO.Error := fun _ => unexpectedEof @[export lean_mk_io_error_inappropriate_type_file] def mkInappropriateTypeFile : String → UInt32 → String → IO.Error := inappropriateType ∘ some @[export lean_mk_io_error_interrupted] def mkInterrupted : String → UInt32 → String → IO.Error := interrupted @[export lean_mk_io_error_invalid_argument_file] def mkInvalidArgumentFile : String → UInt32 → String → IO.Error := invalidArgument ∘ some @[export lean_mk_io_error_no_file_or_directory] def mkNoFileOrDirectory : String → UInt32 → String → IO.Error := noFileOrDirectory @[export lean_mk_io_error_no_such_thing_file] def mkNoSuchThingFile : String → UInt32 → String → IO.Error := noSuchThing ∘ some @[export lean_mk_io_error_permission_denied_file] def mkPermissionDeniedFile : String → UInt32 → String → IO.Error := permissionDenied ∘ some @[export lean_mk_io_error_resource_exhausted_file] def mkResourceExhaustedFile : String → UInt32 → String → IO.Error := resourceExhausted ∘ some @[export lean_mk_io_error_unsupported_operation] def mkUnsupportedOperation : UInt32 → String → IO.Error := unsupportedOperation @[export lean_mk_io_error_resource_exhausted] def mkResourceExhausted : UInt32 → String → IO.Error := resourceExhausted none @[export lean_mk_io_error_already_exists] def mkAlreadyExists : UInt32 → String → IO.Error := alreadyExists none @[export lean_mk_io_error_inappropriate_type] def mkInappropriateType : UInt32 → String → IO.Error := inappropriateType none @[export lean_mk_io_error_no_such_thing] def mkNoSuchThing : UInt32 → String → IO.Error := noSuchThing none @[export lean_mk_io_error_resource_vanished] def mkResourceVanished : UInt32 → String → IO.Error := resourceVanished @[export lean_mk_io_error_resource_busy] def mkResourceBusy : UInt32 → String → IO.Error := resourceBusy @[export lean_mk_io_error_invalid_argument] def mkInvalidArgument : UInt32 → String → IO.Error := invalidArgument none @[export lean_mk_io_error_other_error] def mkOtherError : UInt32 → String → IO.Error := otherError @[export lean_mk_io_error_permission_denied] def mkPermissionDenied : UInt32 → String → IO.Error := permissionDenied none @[export lean_mk_io_error_hardware_fault] def mkHardwareFault : UInt32 → String → IO.Error := hardwareFault @[export lean_mk_io_error_unsatisfied_constraints] def mkUnsatisfiedConstraints : UInt32 → String → IO.Error := unsatisfiedConstraints @[export lean_mk_io_error_illegal_operation] def mkIllegalOperation : UInt32 → String → IO.Error := illegalOperation @[export lean_mk_io_error_protocol_error] def mkProtocolError : UInt32 → String → IO.Error := protocolError @[export lean_mk_io_error_time_expired] def mkTimeExpired : UInt32 → String → IO.Error := timeExpired private def downCaseFirst (s : String) : String := s.modify 0 Char.toLower def fopenErrorToString (gist fn : String) (code : UInt32) : Option String → String | some details => downCaseFirst gist ++ " (error code: " ++ toString code ++ ", " ++ downCaseFirst details ++ ")\n file: " ++ fn | none => downCaseFirst gist ++ " (error code: " ++ toString code ++ ")\n file: " ++ fn def otherErrorToString (gist : String) (code : UInt32) : Option String → String | some details => downCaseFirst gist ++ " (error code: " ++ toString code ++ ", " ++ downCaseFirst details ++ ")" | none => downCaseFirst gist ++ " (error code: " ++ toString code ++ ")" @[export lean_io_error_to_string] def toString : IO.Error → String | unexpectedEof => "end of file" | inappropriateType (some fn) code details => fopenErrorToString "inappropriate type" fn code details | inappropriateType none code details => otherErrorToString "inappropriate type" code details | interrupted fn code details => fopenErrorToString "interrupted system call" fn code details | invalidArgument (some fn) code details => fopenErrorToString "invalid argument" fn code details | invalidArgument none code details => otherErrorToString "invalid argument" code details | noFileOrDirectory fn code _ => fopenErrorToString "no such file or directory" fn code none | noSuchThing (some fn) code details => fopenErrorToString "no such thing" fn code details | noSuchThing none code details => otherErrorToString "no such thing" code details | permissionDenied (some fn) code details => fopenErrorToString details fn code none | permissionDenied none code details => otherErrorToString details code none | resourceExhausted (some fn) code details => fopenErrorToString "resource exhausted" fn code details | resourceExhausted none code details => otherErrorToString "resource exhausted" code details | alreadyExists none code details => otherErrorToString "already exists" code details | alreadyExists (some fn) code details => fopenErrorToString "already exists" fn code details | otherError code details => otherErrorToString details code none | resourceBusy code details => otherErrorToString "resource busy" code details | resourceVanished code details => otherErrorToString "resource vanished" code details | hardwareFault code _ => otherErrorToString "hardware fault" code none | illegalOperation code details => otherErrorToString "illegal operation" code details | protocolError code details => otherErrorToString "protocol error" code details | timeExpired code details => otherErrorToString "time expired" code details | unsatisfiedConstraints code _ => otherErrorToString "directory not empty" code none | unsupportedOperation code details => otherErrorToString "unsupported operation" code details | userError msg => msg instance : ToString IO.Error := ⟨ IO.Error.toString ⟩ end IO.Error