Implement Error.text()

Error.text() returns an error description.
This commit is contained in:
Eugen Wissner 2018-03-02 06:48:03 +01:00
parent 9bf8754711
commit 16c5fa12df
1 changed files with 121 additions and 41 deletions

View File

@ -5,7 +5,7 @@
/** /**
* This module provides a portable way of using operating system error codes. * This module provides a portable way of using operating system error codes.
* *
* Copyright: Eugene Wissner 2017. * Copyright: Eugene Wissner 2017-2018.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
@ -14,6 +14,8 @@
*/ */
module tanya.os.error; module tanya.os.error;
import tanya.meta.trait;
// Socket API error. // Socket API error.
private template SAError(int posix, int wsa = posix) private template SAError(int posix, int wsa = posix)
{ {
@ -120,7 +122,7 @@ struct ErrorCode
/// Protocol not available. /// Protocol not available.
noProtocolOption = SAError!(92, 42), noProtocolOption = SAError!(92, 42),
/// The protocol is not implemented orR has not been configured. /// The protocol is not implemented or has not been configured.
protocolNotSupported = SAError!(93, 43), protocolNotSupported = SAError!(93, 43),
/// The support for the specified socket type does not exist in this /// The support for the specified socket type does not exist in this
@ -186,19 +188,66 @@ struct ErrorCode
cancelled = SAError!(125, 103), cancelled = SAError!(125, 103),
} }
/**
* Error descriptions.
*/
private enum ErrorStr : string
{
success = "The operation completed successfully",
noPermission = "Operation not permitted",
interrupted = "Interrupted system call",
badDescriptor = "Bad file descriptor",
wouldBlock = "An operation on a non-blocking socket would block",
noMemory = "Out of memory",
accessDenied = "Access denied",
fault = "An invalid pointer address detected",
noSuchDevice = "No such device",
invalidArgument = "An invalid argument was supplied",
tooManyDescriptors = "The limit on the number of open file descriptors",
noDescriptors = "The limit on the number of open file descriptors",
brokenPipe = "Broken pipe",
nameTooLong = "The name was too long",
notSocket = "A socket operation was attempted on a non-socket",
protocolError = "Protocol error",
messageTooLong = "Message too long",
wrongProtocolType = "Wrong protocol type for socket",
noProtocolOption = "Protocol not available",
protocolNotSupported = "The protocol is not implemented or has not been configured",
socketNotSupported = "Socket type not supported",
operationNotSupported = "The address family is no supported by the protocol family",
addressFamilyNotSupported = "Address family specified is not supported",
addressInUse = "Address already in use",
networkDown = "The network is not available",
networkUnreachable = "No route to host",
networkReset = "Network dropped connection because of reset",
connectionAborted = "The connection has been aborted",
connectionReset = "Connection reset by peer",
noBufferSpace = "No free buffer space is available for a socket operation",
alreadyConnected = "Transport endpoint is already connected",
notConnected = "Transport endpoint is not connected",
shutdown = "Cannot send after transport endpoint shutdown",
timedOut = "Operation timed out",
connectionRefused = "Connection refused",
hostDown = "Host is down",
hostUnreachable = "No route to host",
alreadyStarted = "Operation already in progress",
inProgress = "Operation now in progress",
cancelled = "Operation cancelled",
}
/** /**
* Constructor. * Constructor.
* *
* Params: * Params:
* value = Numeric error code. * value = Numeric error code.
*/ */
this(const ErrorNo value) pure nothrow @safe @nogc this(const ErrorNo value) @nogc nothrow pure @safe
{ {
this.value_ = value; this.value_ = value;
} }
/// ///
pure nothrow @safe @nogc unittest @nogc nothrow pure @safe unittest
{ {
ErrorCode ec; ErrorCode ec;
assert(ec == ErrorCode.success); assert(ec == ErrorCode.success);
@ -211,13 +260,13 @@ struct ErrorCode
* Resets this $(D_PSYMBOL ErrorCode) to default * Resets this $(D_PSYMBOL ErrorCode) to default
* ($(D_PSYMBOL ErrorCode.success)). * ($(D_PSYMBOL ErrorCode.success)).
*/ */
void reset() pure nothrow @safe @nogc void reset() @nogc nothrow pure @safe
{ {
this.value_ = ErrorNo.success; this.value_ = ErrorNo.success;
} }
/// ///
pure nothrow @safe @nogc unittest @nogc nothrow pure @safe unittest
{ {
auto ec = ErrorCode(ErrorCode.fault); auto ec = ErrorCode(ErrorCode.fault);
assert(ec == ErrorCode.fault); assert(ec == ErrorCode.fault);
@ -241,7 +290,7 @@ struct ErrorCode
} }
/// ///
pure nothrow @safe @nogc unittest @nogc nothrow pure @safe unittest
{ {
ErrorCode ec = ErrorCode.fault; ErrorCode ec = ErrorCode.fault;
auto errorNo = cast(ErrorCode.ErrorNo) ec; auto errorNo = cast(ErrorCode.ErrorNo) ec;
@ -258,38 +307,38 @@ struct ErrorCode
* *
* Returns: $(D_KEYWORD this). * Returns: $(D_KEYWORD this).
*/ */
ref ErrorCode opAssign(const ErrorNo that) pure nothrow @safe @nogc ref ErrorCode opAssign(const ErrorNo that) @nogc nothrow pure @safe
{ {
this.value_ = that; this.value_ = that;
return this; return this;
} }
/// ditto /// ditto
ref ErrorCode opAssign()(auto ref const ErrorCode that) ref ErrorCode opAssign(const ErrorCode that) @nogc nothrow pure @safe
pure nothrow @safe @nogc
{ {
this.value_ = that.value_; this.value_ = that.value_;
return this; return this;
} }
/// ///
pure nothrow @safe @nogc unittest @nogc nothrow pure @safe unittest
{ {
{ ErrorCode ec;
ErrorCode ec; assert(ec == ErrorCode.success);
assert(ec == ErrorCode.success);
ec = ErrorCode.fault; ec = ErrorCode.fault;
assert(ec == ErrorCode.fault); assert(ec == ErrorCode.fault);
} }
{
auto ec1 = ErrorCode(ErrorCode.fault);
ErrorCode ec2;
assert(ec2 == ErrorCode.success);
ec2 = ec1; ///
assert(ec1 == ec2); @nogc nothrow pure @safe unittest
} {
auto ec1 = ErrorCode(ErrorCode.fault);
ErrorCode ec2;
assert(ec2 == ErrorCode.success);
ec2 = ec1;
assert(ec1 == ec2);
} }
/** /**
@ -300,37 +349,68 @@ struct ErrorCode
* *
* Returns: Whether $(D_KEYWORD this) and $(D_PARAM that) are equal. * Returns: Whether $(D_KEYWORD this) and $(D_PARAM that) are equal.
*/ */
bool opEquals(const ErrorNo that) const pure nothrow @safe @nogc bool opEquals(const ErrorNo that) const @nogc nothrow pure @safe
{ {
return this.value_ == that; return this.value_ == that;
} }
/// ditto /// ditto
bool opEquals()(auto ref const ErrorCode that) bool opEquals(const ErrorCode that) const @nogc nothrow pure @safe
const pure nothrow @safe @nogc
{ {
return this.value_ == that.value_; return this.value_ == that.value_;
} }
/// ///
pure nothrow @safe @nogc unittest @nogc nothrow pure @safe unittest
{ {
{ ErrorCode ec1 = ErrorCode.fault;
ErrorCode ec1 = ErrorCode.fault; ErrorCode ec2 = ErrorCode.accessDenied;
ErrorCode ec2 = ErrorCode.accessDenied;
assert(ec1 != ec2); assert(ec1 != ec2);
assert(ec1 != ErrorCode.accessDenied); assert(ec1 != ErrorCode.accessDenied);
assert(ErrorCode.fault != ec2); assert(ErrorCode.fault != ec2);
} }
{
ErrorCode ec1 = ErrorCode.fault;
ErrorCode ec2 = ErrorCode.fault;
assert(ec1 == ec2); ///
assert(ec1 == ErrorCode.fault); @nogc nothrow pure @safe unittest
assert(ErrorCode.fault == ec2); {
ErrorCode ec1 = ErrorCode.fault;
ErrorCode ec2 = ErrorCode.fault;
assert(ec1 == ec2);
assert(ec1 == ErrorCode.fault);
assert(ErrorCode.fault == ec2);
}
/**
* Returns string describing the error number. If a description for a
* specific error number is not available, returns $(D_KEYWORD null).
*
* Returns: String describing the error number.
*/
string text() const @nogc nothrow pure @safe
{
foreach (e; __traits(allMembers, ErrorNo))
{
if (__traits(getMember, ErrorNo, e) == this.value_)
{
return __traits(getMember, ErrorStr, e);
}
} }
return null;
}
///
@nogc nothrow pure @safe unittest
{
ErrorCode ec = ErrorCode.fault;
assert(ec.text == "An invalid pointer address detected");
}
@nogc nothrow pure @safe unittest
{
ErrorCode ec = cast(ErrorCode.ErrorNo) -1;
assert(ec.text is null);
} }
private ErrorNo value_ = ErrorNo.success; private ErrorNo value_ = ErrorNo.success;