--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -30,17 +30,19 @@
using mozilla::dom::EncodingUtils;
using namespace mozilla::ipc;
namespace mozilla {
namespace net {
static NS_DEFINE_CID(kThisImplCID, NS_THIS_STANDARDURL_IMPL_CID);
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
-
+#ifdef MOZ_RUST_URLPARSE
+static bool sUseRust = false;
+#endif
nsIIDNService *nsStandardURL::gIDN = nullptr;
bool nsStandardURL::gInitialized = false;
bool nsStandardURL::gEscapeUTF8 = true;
bool nsStandardURL::gAlwaysEncodeInUTF8 = true;
char nsStandardURL::gHostLimitDigits[] = { '/', '\\', '?', '#', 0 };
//
// setenv MOZ_LOG nsStandardURL:5
@@ -60,16 +62,29 @@ static LazyLogModule gStandardURLLog("ns
if (!mMutable) { \
NS_WARNING("attempt to modify an immutable nsStandardURL"); \
return NS_ERROR_ABORT; \
} \
PR_END_MACRO
//----------------------------------------------------------------------------
+#ifdef MOZ_RUST_URLPARSE
+extern "C" int32_t c_fn_set_size(void * container, size_t size)
+{
+ ((nsACString *) container)->SetLength(size);
+ return 0;
+}
+
+extern "C" char * c_fn_get_buffer(void * container)
+{
+ return ((nsACString *) container)->BeginWriting();
+}
+#endif
+
static nsresult
EncodeString(nsIUnicodeEncoder *encoder, const nsAFlatString &str, nsACString &result)
{
nsresult rv;
int32_t len = str.Length();
int32_t maxlen;
rv = encoder->GetMaxLength(str.get(), len, &maxlen);
@@ -321,16 +336,20 @@ nsStandardURL::InitGlobalObjects()
if (prefBranch) {
nsCOMPtr<nsIObserver> obs( new nsPrefObserver() );
prefBranch->AddObserver(NS_NET_PREF_ESCAPEUTF8, obs.get(), false);
prefBranch->AddObserver(NS_NET_PREF_ALWAYSENCODEINUTF8, obs.get(), false);
PrefsChanged(prefBranch, nullptr);
}
+#ifdef MOZ_RUST_URLPARSE
+ Preferences::AddBoolVarCache(&sUseRust, "network.standard-url.use-rust", false);
+#endif
+
#ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN
PR_INIT_CLIST(&gAllURLs);
#endif
}
void
nsStandardURL::ShutdownGlobalObjects()
{
@@ -1191,24 +1210,75 @@ NS_INTERFACE_MAP_BEGIN(nsStandardURL)
foundInterface = static_cast<nsIURI *>(this);
else
NS_INTERFACE_MAP_ENTRY(nsISizeOf)
NS_INTERFACE_MAP_END
//----------------------------------------------------------------------------
// nsStandardURL::nsIURI
//----------------------------------------------------------------------------
+
+#ifdef MOZ_RUST_URLPARSE
+static void CheckDifference(const char * method, nsACString & standardResult, nsACString & rustResult)
+{
+ if (standardResult != rustResult) {
+ printf("[RUST] Difference occured in ::%s\n", method);
+ printf("\t c++ : %s\n", standardResult.BeginReading());
+ printf("\t rust : %s\n", rustResult.BeginReading());
+ }
+
+ if (sUseRust) {
+ standardResult.Assign(rustResult);
+ }
+}
+
+static void CheckDifference(const char * method, int32_t & standardResult, int32_t & rustResult)
+{
+ if (standardResult != rustResult) {
+ printf("[RUST] Difference occured in ::%s\n", method);
+ printf("\t c++ : %d\n", standardResult);
+ printf("\t rust : %d\n", rustResult);
+ }
+
+ if (sUseRust) {
+ standardResult = rustResult;
+ }
+}
+
+
+static void CheckDifference(const char * method, bool & standardResult, bool & rustResult)
+{
+ if (standardResult != rustResult) {
+ printf("[RUST] Difference occured in ::%s\n", method);
+ printf("\t c++ : %d\n", standardResult);
+ printf("\t rust : %d\n", rustResult);
+ }
+
+ if (sUseRust) {
+ standardResult = rustResult;
+ }
+}
+#endif
+
// result may contain unescaped UTF-8 characters
NS_IMETHODIMP
nsStandardURL::GetSpec(nsACString &result)
{
MOZ_ASSERT(mSpec.Length() <= (uint32_t) net_GetURLMaxLength(),
"The spec should never be this long, we missed a check.");
result = mSpec;
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+ rusturl_get_spec(mURL, &rustResult);
+
+ CheckDifference(__FUNCTION__, result, rustResult);
+#endif
+
return NS_OK;
}
// result may contain unescaped UTF-8 characters
NS_IMETHODIMP
nsStandardURL::GetSensitiveInfoHiddenSpec(nsACString &result)
{
result = mSpec;
@@ -1225,87 +1295,224 @@ nsStandardURL::GetSpecIgnoringRef(nsACSt
// URI without ref is 0 to one char before ref
if (mRef.mLen >= 0) {
URLSegment noRef(0, mRef.mPos - 1);
result = Segment(noRef);
} else {
result = mSpec;
}
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+
+ rusturl_get_spec(mURL, &rustResult);
+ int32_t hashPos = rustResult.FindChar('#');
+ if (hashPos != kNotFound) {
+ rustResult.SetLength(hashPos);
+ }
+
+ CheckDifference(__FUNCTION__, result, rustResult);
+#endif
return NS_OK;
}
// result may contain unescaped UTF-8 characters
NS_IMETHODIMP
nsStandardURL::GetPrePath(nsACString &result)
{
result = Prepath();
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+
+ nsAutoCString part;
+
+ rusturl_get_scheme(mURL, &part);
+ rustResult.Append(part);
+ rustResult += "://";
+ part = "";
+
+ rusturl_get_username(mURL, &part);
+ if (!part.IsEmpty()) {
+ rustResult += part;
+ }
+
+ rusturl_get_password(mURL, &part);
+ if (!part.IsEmpty()) {
+ rustResult += ":";
+ rustResult += part;
+ }
+
+ if (!part.IsEmpty()) {
+ rustResult += "@";
+ }
+
+ GetHostPort(part);
+ rustResult += part;
+
+ CheckDifference(__FUNCTION__, result, rustResult);
+#endif
+
return NS_OK;
}
// result is strictly US-ASCII
NS_IMETHODIMP
nsStandardURL::GetScheme(nsACString &result)
{
result = Scheme();
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+ rusturl_get_scheme(mURL, &rustResult);
+
+ CheckDifference(__FUNCTION__, result, rustResult);
+#endif
+
return NS_OK;
}
// result may contain unescaped UTF-8 characters
NS_IMETHODIMP
nsStandardURL::GetUserPass(nsACString &result)
{
result = Userpass();
+
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+ nsresult rv = GetUsername(rustResult);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ nsAutoCString password;
+ rv = GetPassword(password);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ if (password.Length()) {
+ rustResult.Append(':');
+ rustResult.Append(password);
+ }
+
+ CheckDifference(__FUNCTION__, result, rustResult);
+#endif
+
return NS_OK;
}
// result may contain unescaped UTF-8 characters
NS_IMETHODIMP
nsStandardURL::GetUsername(nsACString &result)
{
result = Username();
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+ rusturl_get_username(mURL, &rustResult);
+
+ CheckDifference(__FUNCTION__, result, rustResult);
+#endif
return NS_OK;
}
// result may contain unescaped UTF-8 characters
NS_IMETHODIMP
nsStandardURL::GetPassword(nsACString &result)
{
result = Password();
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::GetHostPort(nsACString &result)
{
result = Hostport();
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+ rusturl_get_host(mURL, &rustResult);
+
+ int32_t port;
+ nsresult rv = GetPort(&port);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ if (port>=0) {
+ rustResult.Append(':');
+ rustResult.AppendInt(port);
+ }
+
+ CheckDifference(__FUNCTION__, result, rustResult);
+#endif
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::GetHost(nsACString &result)
{
result = Host();
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+ rusturl_get_host(mURL, &rustResult);
+ if (rustResult.Length() > 0 && rustResult[0] == '[' && rustResult[rustResult.Length()-1] == ']')
+ rustResult = Substring(rustResult, 1, rustResult.Length()-2);
+
+ CheckDifference(__FUNCTION__, result, rustResult);
+#endif
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::GetPort(int32_t *result)
{
// should never be more than 16 bit
MOZ_ASSERT(mPort <= std::numeric_limits<uint16_t>::max());
*result = mPort;
+
+#ifdef MOZ_RUST_URLPARSE
+ int32_t rustResult = rusturl_get_port(mURL);
+
+ CheckDifference(__FUNCTION__, *result, rustResult);
+#endif
return NS_OK;
}
// result may contain unescaped UTF-8 characters
NS_IMETHODIMP
nsStandardURL::GetPath(nsACString &result)
{
result = Path();
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+ rusturl_get_path(mURL, &rustResult);
+
+ nsAutoCString query;
+ rusturl_get_query(mURL, &query);
+
+ nsAutoCString ref;
+ rusturl_get_fragment(mURL, &ref);
+
+ if (!query.IsEmpty()) {
+ rustResult.Append('?');
+ rustResult.Append(query);
+ }
+
+ if (!ref.IsEmpty()) {
+ rustResult.Append('#');
+ rustResult.Append(ref);
+ }
+
+ CheckDifference(__FUNCTION__, result, rustResult);
+#endif
return NS_OK;
}
// result is ASCII
NS_IMETHODIMP
nsStandardURL::GetAsciiSpec(nsACString &result)
{
if (mSpecEncoding == eEncoding_Unknown) {
@@ -1351,16 +1558,18 @@ nsStandardURL::GetAsciiHostPort(nsACStri
// the our host is not ipv6, and we can avoid looking at it.
MOZ_ASSERT(result.FindChar(':') == -1, "The host must not be ipv6");
// hostport = "hostA" + ":port"
uint32_t pos = mHost.mPos + mHost.mLen;
if (pos < mPath.mPos)
result += Substring(mSpec, pos, mPath.mPos - pos);
+ // TODO
+
return NS_OK;
}
// result is ASCII
NS_IMETHODIMP
nsStandardURL::GetAsciiHost(nsACString &result)
{
if (mHostEncoding == eEncoding_ASCII) {
@@ -1381,16 +1590,18 @@ nsStandardURL::GetAsciiHost(nsACString &
mHostA = ToNewCString(result);
return NS_OK;
}
NS_WARNING("nsIDNService::ConvertUTF8toACE failed");
}
// something went wrong... guess all we can do is URL escape :-/
NS_EscapeURL(Host(), esc_OnlyNonASCII | esc_AlwaysCopy, result);
+
+ // TODO
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::GetOriginCharset(nsACString &result)
{
if (mOriginCharset.IsEmpty())
result.AssignLiteral("UTF-8");
@@ -1437,16 +1648,20 @@ nsStandardURL::SetSpec(const nsACString
// filter out unexpected chars "\r\n\t" if necessary
nsAutoCString filteredURI;
net_FilterURIString(flat, filteredURI);
if (filteredURI.Length() == 0) {
return NS_ERROR_MALFORMED_URI;
}
+#ifdef MOZ_RUST_URLPARSE
+ mURL.Init(input);
+#endif
+
// Make a backup of the curent URL
nsStandardURL prevURL(false,false);
prevURL.CopyMembers(this, eHonorRef, EmptyCString());
Clear();
if (IsSpecialProtocol(filteredURI)) {
// Bug 652186: Replace all backslashes with slashes when parsing paths
// Stop when we reach the query or the hash.
@@ -1500,23 +1715,33 @@ nsStandardURL::SetSpec(const nsACString
LOG((" path = (%u,%d)\n", mPath.mPos, mPath.mLen));
LOG((" filepath = (%u,%d)\n", mFilepath.mPos, mFilepath.mLen));
LOG((" directory = (%u,%d)\n", mDirectory.mPos, mDirectory.mLen));
LOG((" basename = (%u,%d)\n", mBasename.mPos, mBasename.mLen));
LOG((" extension = (%u,%d)\n", mExtension.mPos, mExtension.mLen));
LOG((" query = (%u,%d)\n", mQuery.mPos, mQuery.mLen));
LOG((" ref = (%u,%d)\n", mRef.mPos, mRef.mLen));
}
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustSpec;
+ rusturl_get_spec(mURL, &rustSpec);
+ nsAutoCString cSpec(mSpec);
+ CheckDifference(__FUNCTION__, cSpec, rustSpec);
+#endif
+
return rv;
}
NS_IMETHODIMP
nsStandardURL::SetScheme(const nsACString &input)
{
ENSURE_MUTABLE();
+#ifdef MOZ_RUST_URLPARSE
+ rusturl_set_scheme(mURL, input.BeginReading(), input.Length());
+#endif
const nsPromiseFlatCString &scheme = PromiseFlatCString(input);
LOG(("nsStandardURL::SetScheme [scheme=%s]\n", scheme.get()));
if (scheme.IsEmpty()) {
NS_WARNING("cannot remove the scheme from an url");
return NS_ERROR_UNEXPECTED;
@@ -1544,23 +1769,41 @@ nsStandardURL::SetScheme(const nsACStrin
ShiftFromAuthority(shift);
}
// ensure new scheme is lowercase
//
// XXX the string code unfortunately doesn't provide a ToLowerCase
// that operates on a substring.
net_ToLowerCase((char *) mSpec.get(), mScheme.mLen);
+
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::SetUserPass(const nsACString &input)
{
ENSURE_MUTABLE();
+#ifdef MOZ_RUST_URLPARSE
+ {
+ int32_t colonPos = input.FindChar(':');
+ nsAutoCString user;
+ nsAutoCString pass;
+ if (colonPos == kNotFound) {
+ user = input;
+ } else {
+ user = Substring(input, 0, colonPos);
+ pass = Substring(input, colonPos + 1, input.Length());
+ }
+
+ rusturl_set_username(mURL, user.BeginReading(), user.Length());
+ rusturl_set_password(mURL, pass.BeginReading(), pass.Length());
+ }
+#endif
+
const nsPromiseFlatCString &userpass = PromiseFlatCString(input);
LOG(("nsStandardURL::SetUserPass [userpass=%s]\n", userpass.get()));
if (mURLType == URLTYPE_NO_AUTHORITY) {
if (userpass.IsEmpty())
return NS_OK;
@@ -1649,23 +1892,27 @@ nsStandardURL::SetUserPass(const nsACStr
ShiftFromHost(shift);
mAuthority.mLen += shift;
}
// update positions and lengths
mUsername.mLen = usernameLen;
mPassword.mLen = passwordLen;
if (passwordLen)
mPassword.mPos = mUsername.mPos + mUsername.mLen + 1;
+
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::SetUsername(const nsACString &input)
{
ENSURE_MUTABLE();
+#ifdef MOZ_RUST_URLPARSE
+ rusturl_set_username(mURL, input.BeginReading(), input.Length());
+#endif
const nsPromiseFlatCString &username = PromiseFlatCString(input);
LOG(("nsStandardURL::SetUsername [username=%s]\n", username.get()));
if (mURLType == URLTYPE_NO_AUTHORITY) {
if (username.IsEmpty())
return NS_OK;
@@ -1698,23 +1945,27 @@ nsStandardURL::SetUsername(const nsACStr
else
shift = ReplaceSegment(mUsername.mPos, mUsername.mLen, escUsername);
if (shift) {
mUsername.mLen = escUsername.Length();
mAuthority.mLen += shift;
ShiftFromPassword(shift);
}
+
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::SetPassword(const nsACString &input)
{
ENSURE_MUTABLE();
+#ifdef MOZ_RUST_URLPARSE
+ rusturl_set_password(mURL, input.BeginReading(), input.Length());
+#endif
const nsPromiseFlatCString &password = PromiseFlatCString(input);
LOG(("nsStandardURL::SetPassword [password=%s]\n", password.get()));
if (mURLType == URLTYPE_NO_AUTHORITY) {
if (password.IsEmpty())
return NS_OK;
@@ -1759,16 +2010,17 @@ nsStandardURL::SetPassword(const nsACStr
else
shift = ReplaceSegment(mPassword.mPos, mPassword.mLen, escPassword);
if (shift) {
mPassword.mLen = escPassword.Length();
mAuthority.mLen += shift;
ShiftFromHost(shift);
}
+
return NS_OK;
}
void
nsStandardURL::FindHostLimit(nsACString::const_iterator& aStart,
nsACString::const_iterator& aEnd)
{
for (int32_t i = 0; gHostLimitDigits[i]; ++i) {
@@ -1780,16 +2032,19 @@ nsStandardURL::FindHostLimit(nsACString:
}
// If aValue only has a host part and no port number, the port
// will not be reset!!!
NS_IMETHODIMP
nsStandardURL::SetHostPort(const nsACString &aValue)
{
ENSURE_MUTABLE();
+#ifdef MOZ_RUST_URLPARSE
+ rusturl_set_host_and_port(mURL, aValue.BeginReading(), aValue.Length());
+#endif
// We cannot simply call nsIURI::SetHost because that would treat the name as
// an IPv6 address (like http:://[server:443]/). We also cannot call
// nsIURI::SetHostPort because that isn't implemented. Sadfaces.
nsACString::const_iterator start, end;
aValue.BeginReading(start);
aValue.EndReading(end);
@@ -1923,16 +2178,20 @@ nsStandardURL::SetHost(const nsACString
// NormalizeIDN always copies if the call was successful
host = hostBuf.get();
len = hostBuf.Length();
if (!ValidIPv6orHostname(host, len)) {
return NS_ERROR_MALFORMED_URI;
}
+#ifdef MOZ_RUST_URLPARSE
+ rusturl_set_host(mURL, host, len);
+#endif
+
if (mHost.mLen < 0) {
int port_length = 0;
if (mPort != -1) {
nsAutoCString buf;
buf.Assign(':');
buf.AppendInt(mPort);
port_length = buf.Length();
}
@@ -1958,16 +2217,19 @@ nsStandardURL::SetHost(const nsACString
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::SetPort(int32_t port)
{
ENSURE_MUTABLE();
+#ifdef MOZ_RUST_URLPARSE
+ rusturl_set_port_no(mURL, port);
+#endif
LOG(("nsStandardURL::SetPort [port=%d]\n", port));
if ((port == mPort) || (mPort == -1 && port == mDefaultPort))
return NS_OK;
// ports must be >= 0 and 16 bit
// -1 == use default
@@ -2049,27 +2311,32 @@ nsStandardURL::SetPath(const nsACString
spec.Assign(mSpec.get(), mPath.mPos);
if (path.First() != '/')
spec.Append('/');
spec.Append(path);
return SetSpec(spec);
}
else if (mPath.mLen >= 1) {
+#ifdef MOZ_RUST_URLPARSE
+ rusturl_set_path(mURL, input.BeginReading(), input.Length());
+#endif
+
mSpec.Cut(mPath.mPos + 1, mPath.mLen - 1);
// these contain only a '/'
mPath.mLen = 1;
mDirectory.mLen = 1;
mFilepath.mLen = 1;
// these are no longer defined
mBasename.mLen = -1;
mExtension.mLen = -1;
mQuery.mLen = -1;
mRef.mLen = -1;
}
+
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::Equals(nsIURI *unknownOther, bool *result)
{
return EqualsInternal(unknownOther, eHonorRef, result);
}
@@ -2098,43 +2365,68 @@ nsStandardURL::EqualsInternal(nsIURI *un
// First, check whether one URIs is an nsIFileURL while the other
// is not. If that's the case, they're different.
if (mSupportsFileURL != other->mSupportsFileURL) {
*result = false;
return NS_OK;
}
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString spec1;
+ GetSpecIgnoringRef(spec1);
+ nsAutoCString spec2;
+ other->GetSpecIgnoringRef(spec2);
+ bool rustResult = spec1 == spec2;
+#endif
+
// Next check parts of a URI that, if different, automatically make the
// URIs different
if (!SegmentIs(mScheme, other->mSpec.get(), other->mScheme) ||
// Check for host manually, since conversion to file will
// ignore the host!
!SegmentIs(mHost, other->mSpec.get(), other->mHost) ||
!SegmentIs(mQuery, other->mSpec.get(), other->mQuery) ||
!SegmentIs(mUsername, other->mSpec.get(), other->mUsername) ||
!SegmentIs(mPassword, other->mSpec.get(), other->mPassword) ||
Port() != other->Port()) {
// No need to compare files or other URI parts -- these are different
// beasties
*result = false;
+#ifdef MOZ_RUST_URLPARSE
+ CheckDifference(__FUNCTION__, *result, rustResult);
+#endif
return NS_OK;
}
+#ifdef MOZ_RUST_URLPARSE
+ if (refHandlingMode == eHonorRef) {
+ GetRef(spec1);
+ other->GetRef(spec2);
+ rustResult = spec1 == spec2;
+ }
+#endif
+
if (refHandlingMode == eHonorRef &&
!SegmentIs(mRef, other->mSpec.get(), other->mRef)) {
*result = false;
+#ifdef MOZ_RUST_URLPARSE
+ CheckDifference(__FUNCTION__, *result, rustResult);
+#endif
return NS_OK;
}
-
+
// Then check for exact identity of URIs. If we have it, they're equal
if (SegmentIs(mDirectory, other->mSpec.get(), other->mDirectory) &&
SegmentIs(mBasename, other->mSpec.get(), other->mBasename) &&
SegmentIs(mExtension, other->mSpec.get(), other->mExtension)) {
*result = true;
+#ifdef MOZ_RUST_URLPARSE
+ CheckDifference(__FUNCTION__, *result, rustResult);
+#endif
return NS_OK;
}
// At this point, the URIs are not identical, but they only differ in the
// directory/filename/extension. If these are file URLs, then get the
// corresponding file objects and compare those, since two filenames that
// differ, eg, only in case could still be equal.
if (mSupportsFileURL) {
@@ -2262,16 +2554,20 @@ nsresult nsStandardURL::CopyMembers(nsSt
}
if (refHandlingMode == eIgnoreRef) {
SetRef(EmptyCString());
} else if (refHandlingMode == eReplaceRef) {
SetRef(newRef);
}
+#ifdef MOZ_RUST_URLPARSE
+ mURL.Init(mSpec);
+#endif
+
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::Resolve(const nsACString &in, nsACString &out)
{
const nsPromiseFlatCString &flat = PromiseFlatCString(in);
// filter out unexpected chars "\r\n\t" if necessary
@@ -2292,16 +2588,21 @@ nsStandardURL::Resolve(const nsACString
// output. normalization will occur when the result is used to
// initialize a nsStandardURL object.
if (mScheme.mLen < 0) {
NS_WARNING("unable to Resolve URL: this URL not initialized");
return NS_ERROR_NOT_INITIALIZED;
}
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+ rusturl_resolve(mURL, relpath, relpathLen, &rustResult);
+#endif
+
nsresult rv;
URLSegment scheme;
char *resultPath = nullptr;
bool relative = false;
uint32_t offset = 0;
netCoalesceFlags coalesceFlag = NET_COALESCE_NORMAL;
// relative urls should never contain a host, so we always want to use
@@ -2444,16 +2745,26 @@ nsStandardURL::Resolve(const nsACString
resultPath = PL_strstr(result, "://");
if (resultPath) {
resultPath = PL_strchr(resultPath + 3, '/');
if (resultPath)
net_CoalesceDirs(coalesceFlag,resultPath);
}
}
out.Adopt(result);
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString outTest(out);
+ CheckDifference(__FUNCTION__, outTest, rustResult);
+
+ nsAutoCString rustSpec;
+ rusturl_get_spec(mURL, &rustSpec);
+ nsAutoCString cSpec(mSpec);
+ CheckDifference("Resolve-Spec", cSpec, rustSpec);
+#endif
+
return NS_OK;
}
// result may contain unescaped UTF-8 characters
NS_IMETHODIMP
nsStandardURL::GetCommonBaseSpec(nsIURI *uri2, nsACString &aResult)
{
NS_ENSURE_ARG_POINTER(uri2);
@@ -2463,26 +2774,36 @@ nsStandardURL::GetCommonBaseSpec(nsIURI
if (NS_SUCCEEDED(Equals(uri2, &isEquals)) && isEquals)
return GetSpec(aResult);
aResult.Truncate();
// check pre-path; if they don't match, then return empty string
nsStandardURL *stdurl2;
nsresult rv = uri2->QueryInterface(kThisImplCID, (void **) &stdurl2);
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+ if (stdurl2)
+ rusturl_common_base_spec(mURL, stdurl2->mURL, &rustResult);
+#endif
+
isEquals = NS_SUCCEEDED(rv)
&& SegmentIs(mScheme, stdurl2->mSpec.get(), stdurl2->mScheme)
&& SegmentIs(mHost, stdurl2->mSpec.get(), stdurl2->mHost)
&& SegmentIs(mUsername, stdurl2->mSpec.get(), stdurl2->mUsername)
&& SegmentIs(mPassword, stdurl2->mSpec.get(), stdurl2->mPassword)
&& (Port() == stdurl2->Port());
if (!isEquals)
{
if (NS_SUCCEEDED(rv))
NS_RELEASE(stdurl2);
+#ifdef MOZ_RUST_URLPARSE
+ CheckDifference(__FUNCTION__, aResult, rustResult);
+#endif
return NS_OK;
}
// scan for first mismatched character
const char *thisIndex, *thatIndex, *startCharPos;
startCharPos = mSpec.get() + mDirectory.mPos;
thisIndex = startCharPos;
thatIndex = stdurl2->mSpec.get() + mDirectory.mPos;
@@ -2497,16 +2818,20 @@ nsStandardURL::GetCommonBaseSpec(nsIURI
// todo: also check for file matches which include '?' and '#'
while ((thisIndex != startCharPos) && (*(thisIndex-1) != '/'))
thisIndex--;
// grab spec from beginning to thisIndex
aResult = Substring(mSpec, mScheme.mPos, thisIndex - mSpec.get());
NS_RELEASE(stdurl2);
+#ifdef MOZ_RUST_URLPARSE
+ CheckDifference(__FUNCTION__, aResult, rustResult);
+#endif
+
return rv;
}
NS_IMETHODIMP
nsStandardURL::GetRelativeSpec(nsIURI *uri2, nsACString &aResult)
{
NS_ENSURE_ARG_POINTER(uri2);
@@ -2514,28 +2839,41 @@ nsStandardURL::GetRelativeSpec(nsIURI *u
// if uri's are equal, then return empty string
bool isEquals = false;
if (NS_SUCCEEDED(Equals(uri2, &isEquals)) && isEquals)
return NS_OK;
nsStandardURL *stdurl2;
nsresult rv = uri2->QueryInterface(kThisImplCID, (void **) &stdurl2);
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+ if (stdurl2)
+ rusturl_relative_spec(mURL, stdurl2->mURL, &rustResult);
+#endif
+
isEquals = NS_SUCCEEDED(rv)
&& SegmentIs(mScheme, stdurl2->mSpec.get(), stdurl2->mScheme)
&& SegmentIs(mHost, stdurl2->mSpec.get(), stdurl2->mHost)
&& SegmentIs(mUsername, stdurl2->mSpec.get(), stdurl2->mUsername)
&& SegmentIs(mPassword, stdurl2->mSpec.get(), stdurl2->mPassword)
&& (Port() == stdurl2->Port());
if (!isEquals)
{
if (NS_SUCCEEDED(rv))
NS_RELEASE(stdurl2);
+#ifdef MOZ_RUST_URLPARSE
+ uri2->GetSpec(aResult);
+ CheckDifference(__FUNCTION__, aResult, rustResult);
+ return NS_OK;
+#else
return uri2->GetSpec(aResult);
+#endif
}
// scan for first mismatched character
const char *thisIndex, *thatIndex, *startCharPos;
startCharPos = mSpec.get() + mDirectory.mPos;
thisIndex = startCharPos;
thatIndex = stdurl2->mSpec.get() + mDirectory.mPos;
@@ -2589,90 +2927,187 @@ nsStandardURL::GetRelativeSpec(nsIURI *u
}
// grab spec from thisIndex to end
uint32_t startPos = stdurl2->mScheme.mPos + thatIndex - stdurl2->mSpec.get();
aResult.Append(Substring(stdurl2->mSpec, startPos,
stdurl2->mSpec.Length() - startPos));
NS_RELEASE(stdurl2);
+
+#ifdef MOZ_RUST_URLPARSE
+ CheckDifference(__FUNCTION__, aResult, rustResult);
+#endif
return rv;
}
//----------------------------------------------------------------------------
// nsStandardURL::nsIURL
//----------------------------------------------------------------------------
// result may contain unescaped UTF-8 characters
NS_IMETHODIMP
nsStandardURL::GetFilePath(nsACString &result)
{
result = Filepath();
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+ rusturl_get_path(mURL, &rustResult);
+ CheckDifference(__FUNCTION__, result, rustResult);
+#endif
+
return NS_OK;
}
// result may contain unescaped UTF-8 characters
NS_IMETHODIMP
nsStandardURL::GetQuery(nsACString &result)
{
result = Query();
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+ rusturl_get_query(mURL, &rustResult);
+ CheckDifference(__FUNCTION__, result, rustResult);
+
+ nsAutoCString rustSpec;
+ rusturl_get_spec(mURL, &rustSpec);
+ nsAutoCString cSpec(mSpec);
+ CheckDifference("GetQuery-Spec", cSpec, rustSpec);
+#endif
+
return NS_OK;
}
// result may contain unescaped UTF-8 characters
NS_IMETHODIMP
nsStandardURL::GetRef(nsACString &result)
{
result = Ref();
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+ rusturl_get_fragment(mURL, &rustResult);
+ CheckDifference(__FUNCTION__, result, rustResult);
+#endif
+
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::GetHasRef(bool *result)
{
*result = (mRef.mLen >= 0);
+
+#ifdef MOZ_RUST_URLPARSE
+ int32_t rustResult = rusturl_has_fragment(mURL);
+
+ if (rustResult != *result) {
+ printf("[RUST] Difference occured in ::%s\n", __FUNCTION__);
+ printf("\t c++ : %d\n", *result);
+ printf("\t rust : %d\n", rustResult);
+ }
+
+ if (sUseRust) {
+ *result = rustResult;
+ }
+#endif
+
return NS_OK;
}
// result may contain unescaped UTF-8 characters
NS_IMETHODIMP
nsStandardURL::GetDirectory(nsACString &result)
{
result = Directory();
+#ifdef MOZ_RUST_URLPARSE
+
+ nsAutoCString rustResult;
+ GetFilePath(rustResult);
+
+ int32_t slashPos = rustResult.RFindChar('/');
+ if (slashPos != kNotFound)
+ rustResult.SetLength(slashPos+1);
+ CheckDifference(__FUNCTION__, result, rustResult);
+#endif
+
return NS_OK;
}
// result may contain unescaped UTF-8 characters
NS_IMETHODIMP
nsStandardURL::GetFileName(nsACString &result)
{
result = Filename();
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+ GetFilePath(rustResult);
+
+ int32_t slashPos = rustResult.RFindChar('/');
+ if (slashPos != kNotFound)
+ rustResult = Substring(rustResult, slashPos+1);
+
+ CheckDifference(__FUNCTION__, result, rustResult);
+#endif
+
return NS_OK;
}
// result may contain unescaped UTF-8 characters
NS_IMETHODIMP
nsStandardURL::GetFileBaseName(nsACString &result)
{
result = Basename();
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+ GetFileName(rustResult);
+
+ int32_t dotPos = rustResult.RFindChar('.');
+ if (dotPos != kNotFound)
+ rustResult.SetLength(dotPos);
+
+ CheckDifference(__FUNCTION__, result, rustResult);
+#endif
+
return NS_OK;
}
// result may contain unescaped UTF-8 characters
NS_IMETHODIMP
nsStandardURL::GetFileExtension(nsACString &result)
{
result = Extension();
+
+#ifdef MOZ_RUST_URLPARSE
+ nsAutoCString rustResult;
+ GetFileName(rustResult);
+
+ int32_t dotPos = rustResult.RFindChar('.');
+ if (dotPos != kNotFound)
+ rustResult = Substring(rustResult, dotPos + 1);
+ else
+ rustResult.SetLength(0);
+
+ CheckDifference(__FUNCTION__, result, rustResult);
+#endif
+
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::SetFilePath(const nsACString &input)
{
ENSURE_MUTABLE();
+#ifdef MOZ_RUST_URLPARSE
+ rusturl_set_path(mURL, input.BeginReading(), input.Length());
+#endif
const nsPromiseFlatCString &flat = PromiseFlatCString(input);
const char *filepath = flat.get();
LOG(("nsStandardURL::SetFilePath [filepath=%s]\n", filepath));
// if there isn't a filepath, then there can't be anything
// after the path either. this url is likely uninitialized.
@@ -2734,16 +3169,17 @@ nsStandardURL::SetFilePath(const nsACStr
// these contain only a '/'
mPath.mLen = 1;
mDirectory.mLen = 1;
mFilepath.mLen = 1;
// these are no longer defined
mBasename.mLen = -1;
mExtension.mLen = -1;
}
+
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::SetQuery(const nsACString &input)
{
ENSURE_MUTABLE();
@@ -2758,16 +3194,19 @@ nsStandardURL::SetQuery(const nsACString
if (mSpec.Length() + input.Length() - Query().Length() > (uint32_t) net_GetURLMaxLength()) {
return NS_ERROR_MALFORMED_URI;
}
InvalidateCache();
if (!query || !*query) {
// remove existing query
+#ifdef MOZ_RUST_URLPARSE
+ rusturl_set_query(mURL, input.BeginReading(), input.Length());
+#endif
if (mQuery.mLen >= 0) {
// remove query and leading '?'
mSpec.Cut(mQuery.mPos - 1, mQuery.mLen + 1);
ShiftFromRef(-(mQuery.mLen + 1));
mPath.mLen -= (mQuery.mLen + 1);
mQuery.mPos = 0;
mQuery.mLen = -1;
}
@@ -2806,31 +3245,38 @@ nsStandardURL::SetQuery(const nsACString
int32_t shift = ReplaceSegment(mQuery.mPos, mQuery.mLen, query, queryLen);
if (shift) {
mQuery.mLen = queryLen;
mPath.mLen += shift;
ShiftFromRef(shift);
}
+#ifdef MOZ_RUST_URLPARSE
+ rusturl_set_query(mURL, input.BeginReading(), input.Length());
+#endif
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::SetRef(const nsACString &input)
{
ENSURE_MUTABLE();
+#ifdef MOZ_RUST_URLPARSE
+ rusturl_set_fragment(mURL, input.BeginReading(), input.Length());
+#endif
const nsPromiseFlatCString &flat = PromiseFlatCString(input);
const char *ref = flat.get();
LOG(("nsStandardURL::SetRef [ref=%s]\n", ref));
- if (mPath.mLen < 0)
+ if (mPath.mLen < 0) {
return SetPath(flat);
+ }
if (mSpec.Length() + input.Length() - Ref().Length() > (uint32_t) net_GetURLMaxLength()) {
return NS_ERROR_MALFORMED_URI;
}
InvalidateCache();
if (!ref || !*ref) {
@@ -2871,16 +3317,17 @@ nsStandardURL::SetRef(const nsACString &
ref = buf.get();
refLen = buf.Length();
}
}
int32_t shift = ReplaceSegment(mRef.mPos, mRef.mLen, ref, refLen);
mPath.mLen += shift;
mRef.mLen = refLen;
+
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::SetDirectory(const nsACString &input)
{
NS_NOTYETIMPLEMENTED("");
return NS_ERROR_NOT_IMPLEMENTED;
@@ -3321,17 +3768,21 @@ nsStandardURL::Read(nsIObjectInputStream
// file and start of the query - mPath should include the param,
// query and ref already. Bump the mFilePath and
// directory/basename/extension components to include this.
mFilepath.Merge(mSpec, ';', old_param);
mDirectory.Merge(mSpec, ';', old_param);
mBasename.Merge(mSpec, ';', old_param);
mExtension.Merge(mSpec, ';', old_param);
}
-
+
+#ifdef MOZ_RUST_URLPARSE
+ mURL.Init(mSpec);
+#endif
+
return NS_OK;
}
NS_IMETHODIMP
nsStandardURL::Write(nsIObjectOutputStream *stream)
{
MOZ_ASSERT(mSpec.Length() <= (uint32_t) net_GetURLMaxLength(),
"The spec should never be this long, we missed a check.");
@@ -3512,16 +3963,19 @@ nsStandardURL::Deserialize(const URIPara
mExtension = FromIPCSegment(params.extension());
mQuery = FromIPCSegment(params.query());
mRef = FromIPCSegment(params.ref());
mOriginCharset = params.originCharset();
mMutable = params.isMutable();
mSupportsFileURL = params.supportsFileURL();
mHostEncoding = params.hostEncoding();
+#ifdef MOZ_RUST_URLPARSE
+ mURL.Init(mSpec);
+#endif
// mSpecEncoding and mHostA are just caches that can be recovered as needed.
return true;
}
//----------------------------------------------------------------------------
// nsStandardURL::nsIClassInfo
//----------------------------------------------------------------------------