package errno type ErrorT uint16 const ( NULL ErrorT = iota /**************** * Posix Errors * ****************/ // Argument list too long. E2BIG // Permission denied. EACCES // Address in use. EADDRINUSE // Address not available. EADDRNOTAVAIL // Address family not supported. EAFNOSUPPORT // Resource unavailable, try again. EAGAIN // Connection already in progress. EALREADY // Bad file descriptor. EBADF // Bad message. EBADMSG // Device or resource busy. EBUSY // Operation canceled. ECANCELED // No child processes. ECHILD // Connection aborted. ECONNABORTED // Connection refused. ECONNREFUSED // Connection reset. ECONNRESET // Resource deadlock would occur. EDEADLK // Destination address required. EDESTADDRREQ // Mathematics argument out of domain of function. EDOM // Reserved. EDQUOT // File exists. EEXIST // Bad address. EFAULT // File too large. EFBIG // Host is unreachable. EHOSTUNREACH // Identifier removed. EIDRM // Illegal byte sequence. EILSEQ // Operation in progress. EINPROGRESS // Interrupted function. EINTR // Invalid argument. EINVAL // I/O error. EIO // Socket is connected. EISCONN // Is a directory. EISDIR // Too many levels of symbolic links. ELOOP // File descriptor value too large. EMFILE // Too many links. EMLINK // Message too large. EMSGSIZE // Reserved. EMULTIHOP // Filename too long. ENAMETOOLONG // Network is down. ENETDOWN // Connection aborted by network. ENETRESET // Network unreachable. ENETUNREACH // Too many files open in system. ENFILE // No buffer space available. ENOBUFS // No message is available on the STREAM head read queue. ENODATA // No such device. ENODEV // No such file or directory. ENOENT // Executable file format error. ENOEXEC // No locks available. ENOLCK // Reserved. ENOLINK // Not enough space. ENOMEM // No message of the desired type. ENOMSG // Protocol not available. ENOPROTOOPT // No space left on device. ENOSPC // No STREAM resources. ENOSR // Not a STREAM. ENOSTR // Functionality not supported. ENOSYS // The socket is not connected. ENOTCONN // Not a directory or a symbolic link to a directory. ENOTDIR // Directory not empty. ENOTEMPTY // State not recoverable. ENOTRECOVERABLE // Not a socket. ENOTSOCK // Not supported. ENOTSUP // Inappropriate I/O control operation. ENOTTY // No such device or address. ENXIO // Operation not supported on socket. EOPNOTSUPP // Value too large to be stored in data type. EOVERFLOW // Previous owner died. EOWNERDEAD // Operation not permitted. EPERM // Broken pipe. EPIPE // Protocol error. EPROTO // Protocol not supported. EPROTONOSUPPORT // Protocol wrong type for socket. EPROTOTYPE // Result too large. ERANGE // Read-only file system. EROFS // Invalid seek. ESPIPE // No such process. ESRCH // Reserved. ESTALE // Stream ioctl() timeout. ETIME // Connection timed out. ETIMEDOUT // Text file busy. ETXTBSY // Operation would block. EWOULDBLOCK // Cross-device link. EXDEV /************************* * ErrGo Specific Errors * *************************/ // Generic error. EOTHER ErrorT = 16384 + iota // ID is already in use. EIDINUSE // Already set. EALREADYSET // Not found. ENOTFOUND ) var errorTable = map[ErrorT]string{ /**************** * Posix Errors * ****************/ E2BIG: "Argument list too long", EACCES: "Permission denied", EADDRINUSE: "Address in use", EADDRNOTAVAIL: "Address not available", EAFNOSUPPORT: "Address family not supported", EAGAIN: "Resource unavailable, try again", EALREADY: "Connection already in progress", EBADF: "Bad file descriptor", EBADMSG: "Bad message", EBUSY: "Device or resource busy", ECANCELED: "Operation canceled", ECHILD: "No child processes", ECONNABORTED: "Connection aborted", ECONNREFUSED: "Connection refused", ECONNRESET: "Connection reset", EDEADLK: "Resource deadlock would occur", EDESTADDRREQ: "Destination address required", EDOM: "Mathematics argument out of domain of function", EDQUOT: "Reserved", EEXIST: "File exists", EFAULT: "Bad address", EFBIG: "File too large", EHOSTUNREACH: "Host is unreachable", EIDRM: "Identifier removed", EILSEQ: "Illegal byte sequence", EINPROGRESS: "Operation in progress", EINTR: "Interrupted function", EINVAL: "Invalid argument", EIO: "I/O error", EISCONN: "Socket is connected", EISDIR: "Is a directory", ELOOP: "Too many levels of symbolic links", EMFILE: "File descriptor value too large", EMLINK: "Too many links", EMSGSIZE: "Message too large", EMULTIHOP: "Reserved", ENAMETOOLONG: "Filename too long", ENETDOWN: "Network is down", ENETRESET: "Connection aborted by network", ENETUNREACH: "Network unreachable", ENFILE: "Too many files open in system", ENOBUFS: "No buffer space available", ENODATA: "No message is available on the STREAM head read queue", ENODEV: "No such device", ENOENT: "No such file or directory", ENOEXEC: "Executable file format error", ENOLCK: "No locks available", ENOLINK: "Reserved", ENOMEM: "Not enough space", ENOMSG: "No message of the desired type", ENOPROTOOPT: "Protocol not available", ENOSPC: "No space left on device", ENOSR: "No STREAM resources", ENOSTR: "Not a STREAM", ENOSYS: "Functionality not supported", ENOTCONN: "The socket is not connected", ENOTDIR: "Not a directory or a symbolic link to a directory", ENOTEMPTY: "Directory not empty", ENOTRECOVERABLE: "State not recoverable", ENOTSOCK: "Not a socket", ENOTSUP: "Not supported", ENOTTY: "Inappropriate I/O control operation", ENXIO: "No such device or address", EOPNOTSUPP: "Operation not supported on socket", EOVERFLOW: "Value too large to be stored in data type", EOWNERDEAD: "Previous owner died", EPERM: "Operation not permitted", EPIPE: "Broken pipe", EPROTO: "Protocol error", EPROTONOSUPPORT: "Protocol not supported", EPROTOTYPE: "Protocol wrong type for socket", ERANGE: "Result too large", EROFS: "Read-only file system", ESPIPE: "Invalid seek", ESRCH: "No such process", ESTALE: "Reserved", ETIME: "Stream ioctl() timeout", ETIMEDOUT: "Connection timed out", ETXTBSY: "Text file busy", EWOULDBLOCK: "Operation would block", EXDEV: "Cross-device link", /************************* * ErrGo Specific Errors * *************************/ EOTHER: "Generic error", EIDINUSE: "ID is already in use", EALREADYSET: "Already set", ENOTFOUND: "Not found", } const userErrorIDSpaceStart = uint16(1) << 15 var highestUserErrorID uint16 = userErrorIDSpaceStart // Error is required to satisfy the Go error interface. func (err ErrorT) Error() string { return errorTable[err] } // RegisterMsg allows you to set the error message on manually created ErrorT's. func (err ErrorT) RegisterMsg(msg string) error { if _, nok := errorTable[err]; nok { return EALREADYSET } return nil } // MustRegisterMsg is identical to RegisterMsg but will panic on errors. func (err ErrorT) MustRegisterMsg(msg string) { if e := err.RegisterMsg(msg); e != nil { panic(e) } } // ID is shorthand for uint16(err), when err is an ErrorT. func (err ErrorT) ID() uint16 { return uint16(err) } // NewErrorT is a factory for ErrorT. // In the event that an invalid id is provided it will return an empty ErrorT in the first value // and one of the following in the second: // // EINVAL When the id provided is not >32767 // EIDINUSE When the ID is already in use. func NewErrorT(id uint16, msg string) (ErrorT, error) { if id < userErrorIDSpaceStart { return ErrorT(0), EINVAL } err := ErrorT(id) if _, nok := errorTable[err]; nok { return ErrorT(0), EIDINUSE } err.MustRegisterMsg(msg) return err, nil } // MustNewErrorT is identical to NewErrorT but will panic on errors. func MustNewErrorT(id uint16, msg string) ErrorT { err, e := NewErrorT(id, msg) if e != nil { panic(e) } return err } // NewNextErrorT is a factory for ErrorT which attempt to auto assign an ID >32767 and <65536. // In the event that 32768 errors have already been created in this way, it will return an empty // ErrorT in the first value and EOVERFLOW in the second. func NewNextErrorT(msg string) (ErrorT, error) { if highestUserErrorID == ^uint16(0) { return ErrorT(0), EOVERFLOW } id := highestUserErrorID highestUserErrorID++ err := ErrorT(id) err.MustRegisterMsg(msg) return err, nil } // MustNewNextErrorT is identical to NewNextErrorT but will panic on errors. func MustNewNextErrorT(msg string) ErrorT { err, e := NewNextErrorT(msg) if e != nil { panic(e) } return err } // Lookup takes an id and attempts to find an ErrorT which matches it. func Lookup(id uint16) (err ErrorT, msg string, e error) { for err, msg := range errorTable { if uint16(err) == id { return err, msg, nil } } return ErrorT(0), "", ENOTFOUND } // Assert will perform a type assertion on a given error to ErrorT. func Assert(e error) (ErrorT, error) { err, ok := e.(ErrorT) if !ok { return ErrorT(0), EINVAL } return err, nil } // MustAssert is identical to Assert but will panic on errors. func MustAssert(e error) ErrorT { err, e := Assert(e) if e != nil { panic(e) } return err }