Parse for the main part of an IPv6 address
This commit is contained in:
parent
aa12aa9014
commit
131675d0a8
@ -385,3 +385,143 @@ if (isInputRange!R && is(Unqual!(ElementType!R) == ubyte))
|
|||||||
address1 = address2;
|
address1 = address2;
|
||||||
assert(address1 == address2);
|
assert(address1 == address2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IPv6 internet address.
|
||||||
|
*/
|
||||||
|
struct Address6
|
||||||
|
{
|
||||||
|
// Raw bytes
|
||||||
|
private ubyte[16] address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an $(D_PSYMBOL Address6) from an unsigned integer in host
|
||||||
|
* byte order.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* address = The address as an unsigned integer in host byte order.
|
||||||
|
*/
|
||||||
|
this(ulong address)
|
||||||
|
{
|
||||||
|
copy(NetworkOrder!8(address), this.address[]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void write2Bytes(R)(ref R range, ubyte[] address)
|
||||||
|
{
|
||||||
|
ushort group = readIntegral!ushort(range, 16);
|
||||||
|
address[0] = cast(ubyte) (group >> 8);
|
||||||
|
address[1] = group & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a string containing an IPv6 address.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* R = Input range type.
|
||||||
|
* range = Stringish range containing the address.
|
||||||
|
*
|
||||||
|
* Returns: $(D_PSYMBOL Option) containing the address if the parsing was
|
||||||
|
* successful, or nothing otherwise.
|
||||||
|
*/
|
||||||
|
Option!Address6 address6(R)(R range)
|
||||||
|
if (isInputRange!R && isSomeChar!(ElementType!R))
|
||||||
|
{
|
||||||
|
if (range.empty)
|
||||||
|
{
|
||||||
|
return typeof(return)();
|
||||||
|
}
|
||||||
|
Address6 result;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (range.front == ':')
|
||||||
|
{
|
||||||
|
range.popFront();
|
||||||
|
if (range.empty || range.front != ':')
|
||||||
|
{
|
||||||
|
return typeof(return)();
|
||||||
|
}
|
||||||
|
range.popFront();
|
||||||
|
goto ParseTail;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < 13; i += 2)
|
||||||
|
{
|
||||||
|
write2Bytes(range, result.address[i .. $]);
|
||||||
|
if (range.empty || range.front != ':')
|
||||||
|
{
|
||||||
|
return typeof(return)();
|
||||||
|
}
|
||||||
|
range.popFront();
|
||||||
|
if (range.empty)
|
||||||
|
{
|
||||||
|
return typeof(return)();
|
||||||
|
}
|
||||||
|
if (range.front == ':')
|
||||||
|
{
|
||||||
|
range.popFront();
|
||||||
|
goto ParseTail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write2Bytes(range, result.address[14 .. $]);
|
||||||
|
|
||||||
|
return range.empty ? typeof(return)(result) : typeof(return)();
|
||||||
|
|
||||||
|
ParseTail:
|
||||||
|
ubyte[12] tail;
|
||||||
|
size_t j;
|
||||||
|
|
||||||
|
for (; !range.empty; i += 2, j += 2, range.popFront())
|
||||||
|
{
|
||||||
|
if (i > 11 || range.front == ':')
|
||||||
|
{
|
||||||
|
return typeof(return)();
|
||||||
|
}
|
||||||
|
write2Bytes(range, tail[j .. $]);
|
||||||
|
|
||||||
|
if (range.empty)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (range.front != ':')
|
||||||
|
{
|
||||||
|
return typeof(return)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
copy(tail[0 .. j + 2], result.address[$ - j - 2 .. $]);
|
||||||
|
|
||||||
|
return typeof(return)(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
{
|
||||||
|
ubyte[16] expected = [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8];
|
||||||
|
auto actual = address6("1:2:3:4:5:6:7:8");
|
||||||
|
assert(actual.address == expected);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ubyte[16] expected;
|
||||||
|
auto actual = address6("::");
|
||||||
|
assert(actual.address == expected);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ubyte[16] expected = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
|
||||||
|
auto actual = address6("::1");
|
||||||
|
assert(actual.address == expected);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ubyte[16] expected = [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
auto actual = address6("1::");
|
||||||
|
assert(actual.address == expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rejects malformed addresses
|
||||||
|
@nogc nothrow pure @safe unittest
|
||||||
|
{
|
||||||
|
assert(address6("").isNothing);
|
||||||
|
assert(address6(":").isNothing);
|
||||||
|
assert(address6(":a").isNothing);
|
||||||
|
assert(address6("a:").isNothing);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user