public nogc ObjectPath.isValid function + ~ operator

This commit is contained in:
WebFreak001 2017-10-19 21:07:31 +02:00
parent 89c7736ccf
commit fd9b7ebdff

View file

@ -18,8 +18,8 @@ public import ddbus.exception : wrapErrors, DBusException;
struct ObjectPath { struct ObjectPath {
private string _value; private string _value;
this(string objPath) { this(string objPath) @safe {
enforce(_isValid(objPath)); enforce(isValid(objPath));
_value = objPath; _value = objPath;
} }
@ -27,17 +27,62 @@ struct ObjectPath {
return _value; return _value;
} }
size_t toHash() const pure nothrow @trusted { /// Returns the string representation of this ObjectPath.
string value() const pure @nogc nothrow @safe {
return _value;
}
size_t toHash() const pure @nogc nothrow @trusted {
return hashOf(_value); return hashOf(_value);
} }
bool opEquals(ref const typeof(this) b) const pure nothrow @safe { bool opEquals(ref const typeof(this) b) const pure @nogc nothrow @safe {
return _value == b._value; return _value == b._value;
} }
private static bool _isValid(string objPath) { ObjectPath opBinary(string op : "~")(string rhs) const pure @safe {
import std.regex : matchFirst, ctRegex; return opBinary!"~"(ObjectPath(rhs));
return cast(bool) objPath.matchFirst(ctRegex!("^((/[0-9A-Za-z_]+)+|/)$")); }
ObjectPath opBinary(string op : "~")(ObjectPath rhs) const pure @safe {
if (!_value.length || _value[$ - 1] != '/') {
ObjectPath ret;
// Is safe if both sides were safe and isValid enforces a starting /
ret._value = _value ~ rhs._value;
return ret;
} else {
ObjectPath ret;
ret._value = _value[0 .. $ - 1] ~ rhs._value;
return ret;
}
}
void opOpAssign(string op : "~")(string rhs) pure @safe {
_value = opBinary!"~"(rhs)._value;
}
void opOpAssign(string op : "~")(ObjectPath rhs) pure @safe {
_value = opBinary!"~"(rhs)._value;
}
/// Returns: false for empty strings or strings that don't match the pattern `(/[0-9A-Za-z_]+)+|/`
static bool isValid(string objPath) pure @nogc nothrow @safe {
import std.ascii : isAlphaNum;
if (!objPath.length)
return false;
if (objPath == "/")
return true;
if (objPath[0] != '/' || objPath[$ - 1] == '/')
return false;
// .representation to avoid unicode exceptions -> @nogc & nothrow
return objPath.representation.splitter('/').drop(1)
.all!(a =>
a.length &&
a.all!(c =>
c.isAlphaNum || c == '_'
)
);
} }
} }
@ -46,9 +91,10 @@ unittest {
ObjectPath("some.invalid/object_path").assertThrow(); ObjectPath("some.invalid/object_path").assertThrow();
ObjectPath("/path/with/TrailingSlash/").assertThrow(); ObjectPath("/path/with/TrailingSlash/").assertThrow();
ObjectPath("/path/without/TrailingSlash").assertNotThrown();
string path = "/org/freedesktop/DBus"; string path = "/org/freedesktop/DBus";
auto obj = ObjectPath(path); auto obj = ObjectPath(path);
obj.toString().assertEqual(path); obj.value.assertEqual(path);
obj.toHash().assertEqual(path.hashOf); obj.toHash().assertEqual(path.hashOf);
} }