зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to mozilla-central. a=merge
This commit is contained in:
Коммит
bdc12b755f
|
@ -156,17 +156,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.33.2"
|
||||
version = "0.37.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clang-sys 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -293,7 +294,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "0.22.0"
|
||||
version = "0.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -463,7 +464,7 @@ version = "0.3.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -547,7 +548,7 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ident_case 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -977,7 +978,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
name = "js"
|
||||
version = "0.1.4"
|
||||
dependencies = [
|
||||
"bindgen 0.33.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1592,7 +1593,7 @@ version = "0.0.1"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.3.6"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1641,7 +1642,7 @@ name = "quote"
|
|||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1936,7 +1937,7 @@ dependencies = [
|
|||
"app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bindgen 0.33.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2029,7 +2030,7 @@ name = "syn"
|
|||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -2049,7 +2050,7 @@ name = "synstructure"
|
|||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2533,7 +2534,7 @@ dependencies = [
|
|||
"checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9"
|
||||
"checksum binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88ceb0d16c4fd0e42876e298d7d3ce3780dd9ebdcbe4199816a32c77e08597ff"
|
||||
"checksum bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bda13183df33055cbb84b847becce220d392df502ebe7a4a78d7021771ed94d0"
|
||||
"checksum bindgen 0.33.2 (registry+https://github.com/rust-lang/crates.io-index)" = "603ed8d8392ace9581e834e26bd09799bf1e989a79bd1aedbb893e72962bdc6e"
|
||||
"checksum bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1b25ab82877ea8fe6ce1ce1f8ac54361f0218bad900af9eb11803994bf67c221"
|
||||
"checksum binjs_meta 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9fcfc86eecb125147e907529a5f1ac7978f6f26d20a52b82a7e053da5faefbc3"
|
||||
"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
|
||||
"checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f"
|
||||
|
@ -2550,7 +2551,7 @@ dependencies = [
|
|||
"checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00"
|
||||
"checksum clang-sys 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "939a1a34310b120d26eba35c29475933128b0ec58e24b43327f8dbe6036fc538"
|
||||
"checksum clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7f7c04e52c35222fffcc3a115b5daf5f7e2bfb71c13c4e2321afe1fc71859c2"
|
||||
"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
|
||||
"checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
|
||||
"checksum cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "746858cae4eae40fff37e1998320068df317bc247dc91a67c6cfa053afdc2abb"
|
||||
|
@ -2673,7 +2674,7 @@ dependencies = [
|
|||
"checksum plane-split 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7079b8485b4f9d9560dee7a69ca8f6ca781f9f284ff9d2bf27255d440b03e4af"
|
||||
"checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0"
|
||||
"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
"checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118"
|
||||
"checksum proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4"
|
||||
"checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6"
|
||||
"checksum procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f566249236c6ca4340f7ca78968271f0ed2b0f234007a61b66f9ecd0af09260"
|
||||
"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
|
||||
|
|
|
@ -562,35 +562,6 @@ class SameOriginCheckerImpl final : public nsIChannelEventSink,
|
|||
|
||||
} // namespace
|
||||
|
||||
class nsContentUtils::nsContentUtilsReporter final : public nsIMemoryReporter
|
||||
{
|
||||
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf);
|
||||
|
||||
~nsContentUtilsReporter() = default;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD
|
||||
CollectReports(nsIHandleReportCallback* aHandleReport,
|
||||
nsISupports* aData, bool aAnonymize) override
|
||||
{
|
||||
int64_t amt = 0;
|
||||
for (int32_t i = 0; i < PropertiesFile_COUNT; ++i) {
|
||||
if (sStringBundles[i]) {
|
||||
amt += sStringBundles[i]->SizeOfIncludingThisIfUnshared(MallocSizeOf);
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_COLLECT_REPORT("explicit/dom/content-utils-string-bundles", KIND_HEAP, UNITS_BYTES,
|
||||
amt, "string-bundles in ContentUtils");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsContentUtils::nsContentUtilsReporter, nsIMemoryReporter)
|
||||
|
||||
/**
|
||||
* This class is used to determine whether or not the user is currently
|
||||
* interacting with the browser. It listens to observer events to toggle the
|
||||
|
@ -691,7 +662,6 @@ nsContentUtils::Init()
|
|||
new PLDHashTable(&hash_table_ops, sizeof(EventListenerManagerMapEntry));
|
||||
|
||||
RegisterStrongMemoryReporter(new DOMEventListenerManagersHashReporter());
|
||||
RegisterStrongMemoryReporter(new nsContentUtilsReporter());
|
||||
}
|
||||
|
||||
sBlockedScriptRunners = new AutoTArray<nsCOMPtr<nsIRunnable>, 8>;
|
||||
|
@ -3920,6 +3890,8 @@ nsContentUtils::GetEventArgNames(int32_t aNameSpaceID,
|
|||
}
|
||||
}
|
||||
|
||||
// Note: The list of content bundles in nsStringBundle.cpp should be updated
|
||||
// whenever entries are added or removed from this list.
|
||||
static const char gPropertiesFiles[nsContentUtils::PropertiesFile_COUNT][56] = {
|
||||
// Must line up with the enum values in |PropertiesFile| enum.
|
||||
"chrome://global/locale/css.properties",
|
||||
|
@ -3960,6 +3932,18 @@ nsContentUtils::EnsureStringBundle(PropertiesFile aFile)
|
|||
void
|
||||
nsContentUtils::AsyncPrecreateStringBundles()
|
||||
{
|
||||
// We only ever want to pre-create bundles in the parent process.
|
||||
//
|
||||
// All nsContentUtils bundles are shared between the parent and child
|
||||
// precesses, and the shared memory regions that back them *must* be created
|
||||
// in the parent, and then sent to all children.
|
||||
//
|
||||
// If we attempt to create a bundle in the child before its memory region is
|
||||
// available, we need to create a temporary non-shared bundle, and later
|
||||
// replace that with the shared memory copy. So attempting to pre-load in the
|
||||
// child is wasteful and unnecessary.
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
for (uint32_t bundleIndex = 0; bundleIndex < PropertiesFile_COUNT; ++bundleIndex) {
|
||||
nsresult rv = NS_IdleDispatchToCurrentThread(
|
||||
NS_NewRunnableFunction("AsyncPrecreateStringBundles",
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
#include "GMPServiceChild.h"
|
||||
#include "NullPrincipal.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIWorkerDebuggerManager.h"
|
||||
|
||||
#if !defined(XP_WIN)
|
||||
|
@ -2262,11 +2263,6 @@ ContentChild::RecvRegisterChrome(InfallibleTArray<ChromePackage>&& packages,
|
|||
static_cast<nsChromeRegistryContent*>(registrySvc.get());
|
||||
chromeRegistry->RegisterRemoteChrome(packages, resources, overrides,
|
||||
locale, reset);
|
||||
static bool preloadDone = false;
|
||||
if (!preloadDone) {
|
||||
preloadDone = true;
|
||||
nsContentUtils::AsyncPrecreateStringBundles();
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -2536,6 +2532,20 @@ ContentChild::RecvAsyncMessage(const nsString& aMsg,
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvRegisterStringBundles(nsTArray<mozilla::dom::StringBundleDescriptor>&& aDescriptors)
|
||||
{
|
||||
nsCOMPtr<nsIStringBundleService> stringBundleService =
|
||||
services::GetStringBundleService();
|
||||
|
||||
for (auto& descriptor : aDescriptors) {
|
||||
stringBundleService->RegisterContentBundle(descriptor.bundleURL(), descriptor.mapFile(),
|
||||
descriptor.mapSize());
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvGeolocationUpdate(nsIDOMGeoPosition* aPosition)
|
||||
{
|
||||
|
|
|
@ -394,6 +394,8 @@ public:
|
|||
const IPC::Principal& aPrincipal,
|
||||
const ClonedMessageData& aData) override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvRegisterStringBundles(nsTArray<StringBundleDescriptor>&& stringBundles) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvGeolocationUpdate(nsIDOMGeoPosition* aPosition) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvGeolocationError(const uint16_t& errorCode) override;
|
||||
|
|
|
@ -146,6 +146,7 @@
|
|||
#include "nsISiteSecurityService.h"
|
||||
#include "nsISound.h"
|
||||
#include "nsISpellChecker.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIURIFixup.h"
|
||||
|
@ -1277,6 +1278,17 @@ ContentParent::GetAllEvenIfDead(nsTArray<ContentParent*>& aArray)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::BroadcastStringBundle(const StringBundleDescriptor& aBundle)
|
||||
{
|
||||
AutoTArray<StringBundleDescriptor, 1> array;
|
||||
array.AppendElement(aBundle);
|
||||
|
||||
for (auto* cp : AllProcesses(eLive)) {
|
||||
Unused << cp->SendRegisterStringBundles(array);
|
||||
}
|
||||
}
|
||||
|
||||
const nsAString&
|
||||
ContentParent::GetRemoteType() const
|
||||
{
|
||||
|
@ -2317,6 +2329,10 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority)
|
|||
static_cast<nsChromeRegistryChrome*>(registrySvc.get());
|
||||
chromeRegistry->SendRegisteredChrome(this);
|
||||
|
||||
nsCOMPtr<nsIStringBundleService> stringBundleService =
|
||||
services::GetStringBundleService();
|
||||
stringBundleService->SendContentBundles(this);
|
||||
|
||||
if (gAppData) {
|
||||
nsCString version(gAppData->version);
|
||||
nsCString buildID(gAppData->buildID);
|
||||
|
|
|
@ -204,6 +204,8 @@ public:
|
|||
|
||||
static void GetAllEvenIfDead(nsTArray<ContentParent*>& aArray);
|
||||
|
||||
static void BroadcastStringBundle(const StringBundleDescriptor&);
|
||||
|
||||
const nsAString& GetRemoteType() const;
|
||||
|
||||
virtual void DoGetRemoteType(nsAString& aRemoteType, ErrorResult& aError) const override
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=4 et sw=4 tw=99: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MemMapSnapshot.h"
|
||||
|
||||
#include "base/eintr_wrapper.h"
|
||||
#include "base/file_util.h"
|
||||
#include "mozilla/ResultExtensions.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/ipc/FileDescriptorUtils.h"
|
||||
#include "nsIFile.h"
|
||||
|
||||
#ifdef XP_UNIX
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using loader::AutoMemMap;
|
||||
|
||||
namespace ipc {
|
||||
|
||||
Result<Ok, nsresult>
|
||||
MemMapSnapshot::Init(size_t aSize)
|
||||
{
|
||||
MOZ_ASSERT(!mInitialized);
|
||||
|
||||
MOZ_TRY(Create(aSize));
|
||||
|
||||
mInitialized = true;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
Result<Ok, nsresult>
|
||||
MemMapSnapshot::Finalize(AutoMemMap& aMem)
|
||||
{
|
||||
MOZ_ASSERT(mInitialized);
|
||||
|
||||
MOZ_TRY(Freeze(aMem));
|
||||
|
||||
mInitialized = false;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
Result<Ok, nsresult>
|
||||
MemMapSnapshot::Create(size_t aSize)
|
||||
{
|
||||
HANDLE handle = CreateFileMapping(
|
||||
INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE,
|
||||
0, DWORD(aSize), nullptr);
|
||||
|
||||
if (!handle) {
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
mFile.emplace(handle);
|
||||
return mMem.initWithHandle(mFile.ref(), aSize, PR_PROT_READWRITE);
|
||||
}
|
||||
|
||||
Result<Ok, nsresult>
|
||||
MemMapSnapshot::Freeze(AutoMemMap& aMem)
|
||||
{
|
||||
auto orig = mFile.ref().ClonePlatformHandle();
|
||||
mFile.reset();
|
||||
|
||||
HANDLE handle;
|
||||
if (!::DuplicateHandle(GetCurrentProcess(), orig.release(), GetCurrentProcess(),
|
||||
&handle, GENERIC_READ | FILE_MAP_READ,
|
||||
false, DUPLICATE_CLOSE_SOURCE)) {
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
return aMem.initWithHandle(FileDescriptor(handle), mMem.size());
|
||||
}
|
||||
|
||||
#elif defined(XP_UNIX)
|
||||
|
||||
Result<Ok, nsresult>
|
||||
MemMapSnapshot::Create(size_t aSize)
|
||||
{
|
||||
FilePath path;
|
||||
ScopedCloseFile fd(file_util::CreateAndOpenTemporaryShmemFile(&path));
|
||||
if (!fd) {
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
if (HANDLE_EINTR(ftruncate(fileno(fd), aSize)) != 0) {
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
MOZ_TRY(mMem.init(FILEToFileDescriptor(fd), PR_PROT_READWRITE));
|
||||
|
||||
mPath.Assign(path.value().data(), path.value().length());
|
||||
return Ok();
|
||||
}
|
||||
|
||||
Result<Ok, nsresult>
|
||||
MemMapSnapshot::Freeze(AutoMemMap& aMem)
|
||||
{
|
||||
// Delete the shm file after we're done here, whether we succeed or not. The
|
||||
// open file descriptor will keep it alive until all remaining references
|
||||
// are closed, at which point it will be automatically freed.
|
||||
auto cleanup = MakeScopeExit([&]() {
|
||||
PR_Delete(mPath.get());
|
||||
});
|
||||
|
||||
// Make the shm file readonly. This doesn't make a difference in practice,
|
||||
// since we open and share a read-only file descriptor, and then delete the
|
||||
// file. But it doesn't hurt, either.
|
||||
chmod(mPath.get(), 0400);
|
||||
|
||||
nsCOMPtr<nsIFile> file;
|
||||
MOZ_TRY(NS_NewNativeLocalFile(mPath, /* followLinks = */ false,
|
||||
getter_AddRefs(file)));
|
||||
|
||||
return aMem.init(file);
|
||||
}
|
||||
|
||||
#else
|
||||
# error "Unsupported build configuration"
|
||||
#endif
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,64 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=4 et sw=4 tw=99: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef dom_ipc_MemMapSnapshot_h
|
||||
#define dom_ipc_MemMapSnapshot_h
|
||||
|
||||
#include "AutoMemMap.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/RangedPtr.h"
|
||||
#include "mozilla/Result.h"
|
||||
#ifdef XP_WIN
|
||||
# include "mozilla/ipc/FileDescriptor.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
/**
|
||||
* A helper class for creating a read-only snapshot of memory-mapped data.
|
||||
*
|
||||
* The Init() method initializes a read-write memory mapped region of the given
|
||||
* size, which can be initialized with arbitrary data. The Finalize() method
|
||||
* remaps that region as read-only (and backs it with a read-only file
|
||||
* descriptor), and initializes an AutoMemMap with the new contents.
|
||||
*
|
||||
* The file descriptor for the resulting AutoMemMap can be shared among
|
||||
* processes, to safely access a shared, read-only copy of the data snapshot.
|
||||
*/
|
||||
class MOZ_RAII MemMapSnapshot
|
||||
{
|
||||
public:
|
||||
Result<Ok, nsresult> Init(size_t aSize);
|
||||
Result<Ok, nsresult> Finalize(loader::AutoMemMap& aMap);
|
||||
|
||||
template<typename T = void>
|
||||
RangedPtr<T> Get()
|
||||
{
|
||||
MOZ_ASSERT(mInitialized);
|
||||
return mMem.get<T>();
|
||||
}
|
||||
|
||||
private:
|
||||
Result<Ok, nsresult> Create(size_t aSize);
|
||||
Result<Ok, nsresult> Freeze(loader::AutoMemMap& aMem);
|
||||
|
||||
loader::AutoMemMap mMem;
|
||||
|
||||
bool mInitialized = false;
|
||||
|
||||
#ifdef XP_WIN
|
||||
Maybe<FileDescriptor> mFile;
|
||||
#else
|
||||
nsCString mPath;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // ipc
|
||||
} // mozilla
|
||||
|
||||
#endif // dom_ipc_MemMapSnapshot_h
|
|
@ -289,6 +289,13 @@ struct XPCOMInitData
|
|||
DynamicScalarDefinition[] dynamicScalarDefs;
|
||||
};
|
||||
|
||||
struct StringBundleDescriptor
|
||||
{
|
||||
nsCString bundleURL;
|
||||
FileDescriptor mapFile;
|
||||
uint32_t mapSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* The PContent protocol is a top-level protocol between the UI process
|
||||
* and a content process. There is exactly one PContentParent/PContentChild pair
|
||||
|
@ -457,6 +464,8 @@ child:
|
|||
|
||||
async ClearSiteDataReloadNeeded(nsString origin);
|
||||
|
||||
async RegisterStringBundles(StringBundleDescriptor[] stringBundles);
|
||||
|
||||
// nsIPermissionManager messages
|
||||
async AddPermission(Permission permission);
|
||||
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=4 et sw=4 tw=99: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "SharedStringMap.h"
|
||||
|
||||
#include "MemMapSnapshot.h"
|
||||
#include "ScriptPreloader-inl.h"
|
||||
|
||||
#include "mozilla/BinarySearch.h"
|
||||
#include "mozilla/ipc/FileDescriptor.h"
|
||||
|
||||
using namespace mozilla::loader;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace ipc;
|
||||
|
||||
namespace dom {
|
||||
namespace ipc {
|
||||
|
||||
static inline size_t
|
||||
GetAlignmentOffset(size_t aOffset, size_t aAlign)
|
||||
{
|
||||
auto mod = aOffset % aAlign;
|
||||
return mod ? aAlign - mod : 0;
|
||||
}
|
||||
|
||||
|
||||
SharedStringMap::SharedStringMap(const FileDescriptor& aMapFile, size_t aMapSize)
|
||||
{
|
||||
auto result = mMap.initWithHandle(aMapFile, aMapSize);
|
||||
MOZ_RELEASE_ASSERT(result.isOk());
|
||||
// We return literal nsStrings and nsCStrings pointing to the mapped data,
|
||||
// which means that we may still have references to the mapped data even
|
||||
// after this instance is destroyed. That means that we need to keep the
|
||||
// mapping alive until process shutdown, in order to be safe.
|
||||
mMap.setPersistent();
|
||||
}
|
||||
|
||||
SharedStringMap::SharedStringMap(SharedStringMapBuilder&& aBuilder)
|
||||
{
|
||||
auto result = aBuilder.Finalize(mMap);
|
||||
MOZ_RELEASE_ASSERT(result.isOk());
|
||||
mMap.setPersistent();
|
||||
}
|
||||
|
||||
mozilla::ipc::FileDescriptor
|
||||
SharedStringMap::CloneFileDescriptor() const
|
||||
{
|
||||
return mMap.cloneHandle();
|
||||
}
|
||||
|
||||
bool
|
||||
SharedStringMap::Has(const nsCString& aKey)
|
||||
{
|
||||
size_t index;
|
||||
return Find(aKey, &index);
|
||||
}
|
||||
|
||||
bool
|
||||
SharedStringMap::Get(const nsCString& aKey, nsAString& aValue)
|
||||
{
|
||||
const auto& entries = Entries();
|
||||
|
||||
size_t index;
|
||||
if (!Find(aKey, &index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aValue.Assign(ValueTable().Get(entries[index].mValue));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SharedStringMap::Find(const nsCString& aKey, size_t* aIndex)
|
||||
{
|
||||
const auto& keys = KeyTable();
|
||||
|
||||
return BinarySearchIf(Entries(), 0, EntryCount(),
|
||||
[&] (const Entry& aEntry) {
|
||||
return aKey.Compare(keys.GetBare(aEntry.mKey));
|
||||
},
|
||||
aIndex);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SharedStringMapBuilder::Add(const nsCString& aKey, const nsString& aValue)
|
||||
{
|
||||
mEntries.Put(aKey, {{mKeyTable.Add(aKey), aKey.Length()},
|
||||
{mValueTable.Add(aValue), aValue.Length()}});
|
||||
}
|
||||
|
||||
Result<Ok, nsresult>
|
||||
SharedStringMapBuilder::Finalize(loader::AutoMemMap& aMap)
|
||||
{
|
||||
using Header = SharedStringMap::Header;
|
||||
|
||||
MOZ_ASSERT(mEntries.Count() == mKeyTable.Count());
|
||||
|
||||
nsTArray<nsCString> keys(mEntries.Count());
|
||||
for (auto iter = mEntries.Iter(); !iter.Done(); iter.Next()) {
|
||||
keys.AppendElement(iter.Key());
|
||||
}
|
||||
keys.Sort();
|
||||
|
||||
|
||||
Header header = {uint32_t(keys.Length())};
|
||||
|
||||
size_t offset = sizeof(header);
|
||||
offset += GetAlignmentOffset(offset, alignof(Header));
|
||||
|
||||
offset += keys.Length() * sizeof(SharedStringMap::Entry);
|
||||
|
||||
header.mKeyStringsOffset = offset;
|
||||
header.mKeyStringsSize = mKeyTable.Size();
|
||||
|
||||
offset += header.mKeyStringsSize;
|
||||
offset += GetAlignmentOffset(offset, alignof(decltype(mValueTable)::ElemType));
|
||||
|
||||
header.mValueStringsOffset = offset;
|
||||
header.mValueStringsSize = mValueTable.Size();
|
||||
|
||||
offset += header.mValueStringsSize;
|
||||
|
||||
|
||||
MemMapSnapshot mem;
|
||||
MOZ_TRY(mem.Init(offset));
|
||||
|
||||
auto headerPtr = mem.Get<Header>();
|
||||
headerPtr[0] = header;
|
||||
|
||||
auto* entry = reinterpret_cast<Entry*>(&headerPtr[1]);
|
||||
for (auto& key : keys) {
|
||||
*entry++ = mEntries.Get(key);
|
||||
}
|
||||
|
||||
auto ptr = mem.Get<uint8_t>();
|
||||
|
||||
mKeyTable.Write({ &ptr[header.mKeyStringsOffset],
|
||||
header.mKeyStringsSize });
|
||||
|
||||
mValueTable.Write({ &ptr[header.mValueStringsOffset],
|
||||
header.mValueStringsSize });
|
||||
|
||||
mKeyTable.Clear();
|
||||
mValueTable.Clear();
|
||||
mEntries.Clear();
|
||||
|
||||
return mem.Finalize(aMap);
|
||||
}
|
||||
|
||||
} // ipc
|
||||
} // dom
|
||||
} // mozilla
|
|
@ -0,0 +1,324 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=4 et sw=4 tw=99: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef dom_ipc_SharedStringMap_h
|
||||
#define dom_ipc_SharedStringMap_h
|
||||
|
||||
#include "mozilla/AutoMemMap.h"
|
||||
#include "mozilla/Result.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace ipc {
|
||||
|
||||
class SharedStringMapBuilder;
|
||||
|
||||
/**
|
||||
* This class provides a simple, read-only key-value string store, with all
|
||||
* data packed into a single segment of memory, which can be shared between
|
||||
* processes.
|
||||
*
|
||||
* Look-ups are performed by binary search of a static table in the mapped
|
||||
* memory region, and all returned strings are literals which reference the
|
||||
* mapped data. No copies are performed on instantiation or look-up.
|
||||
*
|
||||
* Important: The mapped memory created by this class is persistent. Once an
|
||||
* instance has been initialized, the memory that it allocates can never be
|
||||
* freed before process shutdown. Do not use it for short-lived mappings.
|
||||
*/
|
||||
class SharedStringMap
|
||||
{
|
||||
using FileDescriptor = mozilla::ipc::FileDescriptor;
|
||||
|
||||
public:
|
||||
/**
|
||||
* The header at the beginning of the shared memory region describing its
|
||||
* layout. The layout of the shared memory is as follows:
|
||||
*
|
||||
* - Header:
|
||||
* A Header struct describing the contents of the rest of the memory region.
|
||||
*
|
||||
* - Optional alignment padding for Header[].
|
||||
*
|
||||
* - Entry[header.mEntryCount]:
|
||||
* An array of Entry structs, one for each entry in the map. Entries are
|
||||
* lexocographically sorted by key.
|
||||
*
|
||||
* - StringTable<nsCString>:
|
||||
* A region of flat, null-terminated C strings. Entry key strings are
|
||||
* encoded as character offsets into this region.
|
||||
*
|
||||
* - Optional alignment padding for char16_t[]
|
||||
*
|
||||
* - StringTable<nsString>:
|
||||
* A region of flat, null-terminated UTF-16 strings. Entry value strings are
|
||||
* encoded as character (*not* byte) offsets into this region.
|
||||
*/
|
||||
struct Header {
|
||||
// The number of entries in this map.
|
||||
uint32_t mEntryCount;
|
||||
|
||||
// The raw byte offset of the beginning of the key string table, from the
|
||||
// start of the shared memory region, and its size in bytes.
|
||||
size_t mKeyStringsOffset;
|
||||
size_t mKeyStringsSize;
|
||||
|
||||
// The raw byte offset of the beginning of the value string table, from the
|
||||
// start of the shared memory region, and its size in bytes (*not*
|
||||
// characters).
|
||||
size_t mValueStringsOffset;
|
||||
size_t mValueStringsSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Contains the character offset and character length of an entry in a string
|
||||
* table. This may be used for either 8-bit or 16-bit strings, and is required
|
||||
* to retrieve an entry from a string table.
|
||||
*/
|
||||
struct StringEntry {
|
||||
uint32_t mOffset;
|
||||
uint32_t mLength;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes a value in the string map, as offsets into the key and value
|
||||
* string tables.
|
||||
*/
|
||||
struct Entry {
|
||||
// The offset and size of the entry's UTF-8 key in the key string table.
|
||||
StringEntry mKey;
|
||||
// The offset and size of the entry's UTF-16 value in the value string table.
|
||||
StringEntry mValue;
|
||||
};
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(SharedStringMap)
|
||||
|
||||
// Note: These constructors are infallible on the premise that this class
|
||||
// is used primarily in cases where it is critical to platform
|
||||
// functionality.
|
||||
explicit SharedStringMap(const FileDescriptor&, size_t);
|
||||
explicit SharedStringMap(SharedStringMapBuilder&&);
|
||||
|
||||
/**
|
||||
* Searches for the given value in the map, and returns true if it exists.
|
||||
*/
|
||||
bool Has(const nsCString& aKey);
|
||||
|
||||
/**
|
||||
* Searches for the given value in the map, and, if it exists, returns true
|
||||
* and places its value in aValue.
|
||||
*
|
||||
* The returned value is a literal string which references the mapped memory
|
||||
* region.
|
||||
*/
|
||||
bool Get(const nsCString& aKey, nsAString& aValue);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Searches for an entry for the given key. If found, returns true, and
|
||||
* places its index in the entry array in aIndex.
|
||||
*/
|
||||
bool Find(const nsCString& aKey, size_t* aIndex);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns the number of entries in the map.
|
||||
*/
|
||||
uint32_t Count() const { return EntryCount(); }
|
||||
|
||||
/**
|
||||
* Returns the string entry at the given index. Keys are guaranteed to be
|
||||
* sorted lexographically.
|
||||
*
|
||||
* The given index *must* be less than the value returned by Count().
|
||||
*
|
||||
* The returned value is a literal string which references the mapped memory
|
||||
* region.
|
||||
*/
|
||||
nsCString GetKeyAt(uint32_t aIndex) const
|
||||
{
|
||||
MOZ_ASSERT(aIndex < Count());
|
||||
return KeyTable().Get(Entries()[aIndex].mKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string value for the entry at the given index.
|
||||
*
|
||||
* The given index *must* be less than the value returned by Count().
|
||||
*
|
||||
* The returned value is a literal string which references the mapped memory
|
||||
* region.
|
||||
*/
|
||||
nsString GetValueAt(uint32_t aIndex) const
|
||||
{
|
||||
MOZ_ASSERT(aIndex < Count());
|
||||
return ValueTable().Get(Entries()[aIndex].mValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the read-only file descriptor which backs the shared
|
||||
* memory region for this map. The file descriptor may be passed between
|
||||
* processes, and used to construct new instances of SharedStringMap with
|
||||
* the same data as this instance.
|
||||
*/
|
||||
FileDescriptor CloneFileDescriptor() const;
|
||||
|
||||
size_t MapSize() const { return mMap.size(); }
|
||||
|
||||
protected:
|
||||
~SharedStringMap() = default;
|
||||
|
||||
private:
|
||||
template <typename StringType>
|
||||
class StringTable
|
||||
{
|
||||
using ElemType = decltype(DeclVal<StringType>()[0]);
|
||||
|
||||
public:
|
||||
MOZ_IMPLICIT StringTable(const RangedPtr<uint8_t>& aBuffer)
|
||||
: mBuffer(aBuffer.ReinterpretCast<ElemType>())
|
||||
{
|
||||
MOZ_ASSERT(uintptr_t(aBuffer.get()) % alignof(ElemType) == 0,
|
||||
"Got misalinged buffer");
|
||||
}
|
||||
|
||||
StringType Get(const StringEntry& aEntry) const
|
||||
{
|
||||
StringType res;
|
||||
res.AssignLiteral(GetBare(aEntry), aEntry.mLength);
|
||||
return res;
|
||||
}
|
||||
|
||||
const ElemType* GetBare(const StringEntry& aEntry) const
|
||||
{
|
||||
return &mBuffer[aEntry.mOffset];
|
||||
}
|
||||
|
||||
private:
|
||||
RangedPtr<ElemType> mBuffer;
|
||||
};
|
||||
|
||||
|
||||
// Type-safe getters for values in the shared memory region:
|
||||
const Header& GetHeader() const
|
||||
{
|
||||
return mMap.get<Header>()[0];
|
||||
}
|
||||
|
||||
RangedPtr<const Entry> Entries() const
|
||||
{
|
||||
return { reinterpret_cast<const Entry*>(&GetHeader() + 1),
|
||||
EntryCount() };
|
||||
}
|
||||
|
||||
uint32_t EntryCount() const
|
||||
{
|
||||
return GetHeader().mEntryCount;
|
||||
}
|
||||
|
||||
StringTable<nsCString> KeyTable() const
|
||||
{
|
||||
auto& header = GetHeader();
|
||||
return { { &mMap.get<uint8_t>()[header.mKeyStringsOffset],
|
||||
header.mKeyStringsSize } };
|
||||
}
|
||||
|
||||
StringTable<nsString> ValueTable() const
|
||||
{
|
||||
auto& header = GetHeader();
|
||||
return { { &mMap.get<uint8_t>()[header.mValueStringsOffset],
|
||||
header.mValueStringsSize } };
|
||||
}
|
||||
|
||||
|
||||
loader::AutoMemMap mMap;
|
||||
};
|
||||
|
||||
/**
|
||||
* A helper class which builds the contiguous look-up table used by
|
||||
* SharedStringMap. Each key-value pair in the final map is added to the
|
||||
* builder, before it is finalized and transformed into a snapshot.
|
||||
*/
|
||||
class MOZ_RAII SharedStringMapBuilder
|
||||
{
|
||||
public:
|
||||
SharedStringMapBuilder() = default;
|
||||
|
||||
/**
|
||||
* Adds a key-value pair to the map.
|
||||
*/
|
||||
void Add(const nsCString& aKey, const nsString& aValue);
|
||||
|
||||
/**
|
||||
* Finalizes the binary representation of the map, writes it to a shared
|
||||
* memory region, and then initializes the given AutoMemMap with a reference
|
||||
* to the read-only copy of it.
|
||||
*/
|
||||
Result<Ok, nsresult> Finalize(loader::AutoMemMap& aMap);
|
||||
|
||||
private:
|
||||
template <typename KeyType, typename StringType>
|
||||
class StringTableBuilder
|
||||
{
|
||||
public:
|
||||
using ElemType = typename StringType::char_type;
|
||||
|
||||
uint32_t Add(const StringType& aKey)
|
||||
{
|
||||
auto entry = mEntries.LookupForAdd(aKey).OrInsert([&] () {
|
||||
Entry newEntry { mSize, aKey };
|
||||
mSize += aKey.Length() + 1;
|
||||
|
||||
return newEntry;
|
||||
});
|
||||
|
||||
return entry.mOffset;
|
||||
}
|
||||
|
||||
void Write(const RangedPtr<uint8_t>& aBuffer)
|
||||
{
|
||||
auto buffer = aBuffer.ReinterpretCast<ElemType>();
|
||||
|
||||
for (auto iter = mEntries.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto& entry = iter.Data();
|
||||
memcpy(&buffer[entry.mOffset], entry.mValue.BeginReading(),
|
||||
sizeof(ElemType) * (entry.mValue.Length() + 1));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Count() const { return mEntries.Count(); }
|
||||
|
||||
uint32_t Size() const { return mSize * sizeof(ElemType); }
|
||||
|
||||
void Clear() { mEntries.Clear(); }
|
||||
|
||||
private:
|
||||
struct Entry
|
||||
{
|
||||
uint32_t mOffset;
|
||||
StringType mValue;
|
||||
};
|
||||
|
||||
nsDataHashtable<KeyType, Entry> mEntries;
|
||||
uint32_t mSize = 0;
|
||||
};
|
||||
|
||||
using Entry = SharedStringMap::Entry;
|
||||
|
||||
StringTableBuilder<nsCStringHashKey, nsCString> mKeyTable;
|
||||
StringTableBuilder<nsStringHashKey, nsString> mValueTable;
|
||||
|
||||
nsDataHashtable<nsCStringHashKey, Entry> mEntries;
|
||||
};
|
||||
|
||||
} // ipc
|
||||
} // dom
|
||||
} // mozilla
|
||||
|
||||
#endif // dom_ipc_SharedStringMap_h
|
||||
|
|
@ -12,8 +12,10 @@
|
|||
#include "ipc/IPCMessageUtils.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/BlobBinding.h"
|
||||
#include "mozilla/dom/IPCBlobUtils.h"
|
||||
#include "mozilla/dom/DOMTypes.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/IPCBlobUtils.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/ipc/IPCStreamUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
|
@ -21,6 +23,8 @@
|
|||
#include "StructuredCloneTags.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace ipc {
|
||||
|
|
|
@ -15,6 +15,7 @@ XPIDL_MODULE = 'dom'
|
|||
|
||||
EXPORTS.mozilla.dom.ipc += [
|
||||
'IdType.h',
|
||||
'SharedStringMap.h',
|
||||
'StructuredCloneData.h',
|
||||
]
|
||||
|
||||
|
@ -61,12 +62,14 @@ UNIFIED_SOURCES += [
|
|||
'ContentProcessHost.cpp',
|
||||
'ContentProcessManager.cpp',
|
||||
'FilePickerParent.cpp',
|
||||
'MemMapSnapshot.cpp',
|
||||
'MemoryReportRequest.cpp',
|
||||
'nsIContentChild.cpp',
|
||||
'nsIContentParent.cpp',
|
||||
'PermissionMessageUtils.cpp',
|
||||
'PreallocatedProcessManager.cpp',
|
||||
'ProcessPriorityManager.cpp',
|
||||
'SharedStringMap.cpp',
|
||||
'StructuredCloneData.cpp',
|
||||
'TabChild.cpp',
|
||||
'TabContext.cpp',
|
||||
|
@ -132,6 +135,7 @@ LOCAL_INCLUDES += [
|
|||
'/extensions/spellcheck/src',
|
||||
'/gfx/2d',
|
||||
'/hal/sandbox',
|
||||
'/js/xpconnect/loader',
|
||||
'/layout/base',
|
||||
'/media/webrtc',
|
||||
'/netwerk/base',
|
||||
|
|
|
@ -48,8 +48,8 @@ SVGAngle::SetValue(float aValue, ErrorResult& rv)
|
|||
return;
|
||||
}
|
||||
bool isBaseVal = mType == BaseValue;
|
||||
mVal->SetBaseValue(aValue, isBaseVal ? mSVGElement.get() : nullptr,
|
||||
isBaseVal);
|
||||
mVal->SetBaseValue(aValue, mVal->mBaseValUnit,
|
||||
isBaseVal ? mSVGElement.get() : nullptr, isBaseVal);
|
||||
}
|
||||
|
||||
float
|
||||
|
|
|
@ -182,7 +182,7 @@ SVGMarkerElement::SetOrientToAngle(SVGAngle& angle, ErrorResult& rv)
|
|||
return;
|
||||
}
|
||||
mOrientType.SetBaseValue(SVG_MARKER_ORIENT_ANGLE);
|
||||
mAngleAttributes[ORIENT].SetBaseValue(f, this, true);
|
||||
mAngleAttributes[ORIENT].SetBaseValue(f, angle.UnitType(), this, true);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -222,14 +222,16 @@ SVGMarkerElement::ParseAttribute(int32_t aNameSpaceID, nsAtom* aName,
|
|||
if (aValue.EqualsLiteral("auto")) {
|
||||
mOrientType.SetBaseValue(SVG_MARKER_ORIENT_AUTO);
|
||||
aResult.SetTo(aValue);
|
||||
mAngleAttributes[ORIENT].SetBaseValue(0.f, this, false);
|
||||
mAngleAttributes[ORIENT].SetBaseValue(0.f, SVG_ANGLETYPE_UNSPECIFIED,
|
||||
this, false);
|
||||
return true;
|
||||
}
|
||||
if (aValue.EqualsLiteral("auto-start-reverse") &&
|
||||
MarkerImprovementsPrefEnabled()) {
|
||||
mOrientType.SetBaseValue(SVG_MARKER_ORIENT_AUTO_START_REVERSE);
|
||||
aResult.SetTo(aValue);
|
||||
mAngleAttributes[ORIENT].SetBaseValue(0.f, this, false);
|
||||
mAngleAttributes[ORIENT].SetBaseValue(0.f, SVG_ANGLETYPE_UNSPECIFIED,
|
||||
this, false);
|
||||
return true;
|
||||
}
|
||||
mOrientType.SetBaseValue(SVG_MARKER_ORIENT_ANGLE);
|
||||
|
|
|
@ -163,10 +163,9 @@ nsSVGAngle::ConvertToSpecifiedUnits(uint16_t unitType,
|
|||
}
|
||||
|
||||
float valueInUserUnits = mBaseVal * GetDegreesPerUnit(mBaseValUnit);
|
||||
mBaseValUnit = uint8_t(unitType);
|
||||
// Setting aDoSetAttr to false here will ensure we don't call
|
||||
// Will/DidChangeAngle a second time (and dispatch duplicate notifications).
|
||||
SetBaseValue(valueInUserUnits, aSVGElement, false);
|
||||
SetBaseValue(valueInUserUnits, unitType, aSVGElement, false);
|
||||
|
||||
if (aSVGElement) {
|
||||
aSVGElement->DidChangeAngle(mAttrEnum, emptyOrOldValue);
|
||||
|
@ -294,10 +293,11 @@ nsSVGAngle::GetAnimValueString(nsAString & aValueAsString) const
|
|||
}
|
||||
|
||||
void
|
||||
nsSVGAngle::SetBaseValue(float aValue, nsSVGElement *aSVGElement,
|
||||
bool aDoSetAttr)
|
||||
nsSVGAngle::SetBaseValue(float aValue, uint8_t aUnit,
|
||||
nsSVGElement *aSVGElement, bool aDoSetAttr)
|
||||
{
|
||||
if (mBaseVal == aValue * GetDegreesPerUnit(mBaseValUnit)) {
|
||||
float valueInSpecifiedUnits = aValue / GetDegreesPerUnit(aUnit);
|
||||
if (aUnit == mBaseValUnit && mBaseVal == valueInSpecifiedUnits) {
|
||||
return;
|
||||
}
|
||||
nsAttrValue emptyOrOldValue;
|
||||
|
@ -305,7 +305,8 @@ nsSVGAngle::SetBaseValue(float aValue, nsSVGElement *aSVGElement,
|
|||
emptyOrOldValue = aSVGElement->WillChangeAngle(mAttrEnum);
|
||||
}
|
||||
|
||||
mBaseVal = aValue / GetDegreesPerUnit(mBaseValUnit);
|
||||
mBaseValUnit = aUnit;
|
||||
mBaseVal = valueInSpecifiedUnits;
|
||||
if (!mIsAnimated) {
|
||||
mAnimVal = mBaseVal;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,8 @@ public:
|
|||
float GetAnimValue() const
|
||||
{ return mAnimVal * GetDegreesPerUnit(mAnimValUnit); }
|
||||
|
||||
void SetBaseValue(float aValue, nsSVGElement *aSVGElement, bool aDoSetAttr);
|
||||
void SetBaseValue(float aValue, uint8_t aUnit, nsSVGElement *aSVGElement,
|
||||
bool aDoSetAttr);
|
||||
void SetAnimValue(float aValue, uint8_t aUnit, nsSVGElement *aSVGElement);
|
||||
|
||||
uint8_t GetBaseValueUnit() const { return mBaseValUnit; }
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
// string bundles (intl)
|
||||
#include "nsStringBundleService.h"
|
||||
#include "nsStringBundleTextOverride.h"
|
||||
|
||||
// locale
|
||||
#include "nsLocaleConstructors.h"
|
||||
|
@ -15,12 +14,10 @@
|
|||
// uconv
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStringBundleService, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStringBundleTextOverride, Init)
|
||||
|
||||
NS_DEFINE_NAMED_CID(MOZ_LOCALESERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(MOZ_OSPREFERENCES_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_STRINGBUNDLESERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_STRINGBUNDLETEXTOVERRIDE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_COLLATIONFACTORY_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_COLLATION_CID);
|
||||
|
||||
|
@ -28,7 +25,6 @@ static const mozilla::Module::CIDEntry kIntlCIDs[] = {
|
|||
{ &kMOZ_LOCALESERVICE_CID, false, nullptr, mozilla::intl::LocaleServiceConstructor },
|
||||
{ &kMOZ_OSPREFERENCES_CID, false, nullptr, mozilla::intl::OSPreferencesConstructor },
|
||||
{ &kNS_STRINGBUNDLESERVICE_CID, false, nullptr, nsStringBundleServiceConstructor },
|
||||
{ &kNS_STRINGBUNDLETEXTOVERRIDE_CID, false, nullptr, nsStringBundleTextOverrideConstructor },
|
||||
{ &kNS_COLLATIONFACTORY_CID, false, nullptr, nsCollationFactoryConstructor },
|
||||
{ &kNS_COLLATION_CID, false, nullptr, nsCollationConstructor },
|
||||
{ nullptr }
|
||||
|
@ -38,7 +34,6 @@ static const mozilla::Module::ContractIDEntry kIntlContracts[] = {
|
|||
{ MOZ_LOCALESERVICE_CONTRACTID, &kMOZ_LOCALESERVICE_CID },
|
||||
{ MOZ_OSPREFERENCES_CONTRACTID, &kMOZ_OSPREFERENCES_CID },
|
||||
{ NS_STRINGBUNDLE_CONTRACTID, &kNS_STRINGBUNDLESERVICE_CID },
|
||||
{ NS_STRINGBUNDLETEXTOVERRIDE_CONTRACTID, &kNS_STRINGBUNDLETEXTOVERRIDE_CID },
|
||||
{ NS_COLLATIONFACTORY_CONTRACTID, &kNS_COLLATIONFACTORY_CID },
|
||||
{ NS_COLLATION_CONTRACTID, &kNS_COLLATION_CID },
|
||||
{ nullptr }
|
||||
|
|
|
@ -8,16 +8,20 @@ XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
|
|||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIStringBundle.idl',
|
||||
'nsIStringBundleOverride.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'intl'
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'nsStringBundle.cpp',
|
||||
'nsStringBundleTextOverride.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/xpcom/ds',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
|
|
|
@ -9,6 +9,15 @@
|
|||
%{C++
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class ContentParent;
|
||||
}
|
||||
namespace ipc {
|
||||
class FileDescriptor;
|
||||
}
|
||||
}
|
||||
|
||||
// Define Contractid and CID
|
||||
// {D85A17C1-AA7C-11d2-9B8C-00805F8A16D9}
|
||||
#define NS_STRINGBUNDLESERVICE_CID \
|
||||
|
@ -74,7 +83,6 @@ interface nsIStringBundle : nsISupports
|
|||
interface nsIStringBundleService : nsISupports
|
||||
{
|
||||
nsIStringBundle createBundle(in string aURLSpec);
|
||||
nsIStringBundle createExtensibleBundle(in string aRegistryKey);
|
||||
|
||||
/**
|
||||
* Formats a message string from a status code and status arguments.
|
||||
|
@ -99,5 +107,11 @@ interface nsIStringBundleService : nsISupports
|
|||
|
||||
%{C++
|
||||
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const = 0;
|
||||
|
||||
virtual void SendContentBundles(mozilla::dom::ContentParent* aContentParent) const = 0;
|
||||
|
||||
virtual void RegisterContentBundle(const nsCString& aBundleURL,
|
||||
const mozilla::ipc::FileDescriptor& aMapFile,
|
||||
size_t aMapSize) = 0;
|
||||
%}
|
||||
};
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsISimpleEnumerator;
|
||||
|
||||
%{C++
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
%}
|
||||
|
||||
// to be implemented by an embeddor that wants to override some strings
|
||||
[scriptable, uuid(965eb278-5678-456b-82a7-20a0c86a803c)]
|
||||
interface nsIStringBundleOverride : nsISupports
|
||||
{
|
||||
/**
|
||||
* get the override value for a particular key in a particular
|
||||
* string bundle
|
||||
*/
|
||||
AString getStringFromName(in AUTF8String url,
|
||||
in ACString key);
|
||||
|
||||
/**
|
||||
* get all override keys for a given string bundle
|
||||
*/
|
||||
nsISimpleEnumerator enumerateKeysInBundle(in AUTF8String url);
|
||||
|
||||
%{C++
|
||||
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const = 0;
|
||||
%}
|
||||
};
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -8,73 +8,87 @@
|
|||
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
class nsIPersistentProperties;
|
||||
class nsIStringBundleOverride;
|
||||
|
||||
class nsStringBundle : public nsIStringBundle
|
||||
|
||||
class nsStringBundleBase : public nsIStringBundle
|
||||
, public nsIMemoryReporter
|
||||
{
|
||||
public:
|
||||
// init version
|
||||
nsStringBundle(const char* aURLSpec, nsIStringBundleOverride*);
|
||||
nsresult LoadProperties();
|
||||
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
|
||||
|
||||
nsresult ParseProperties(nsIPersistentProperties**);
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSISTRINGBUNDLE
|
||||
NS_DECL_NSIMEMORYREPORTER
|
||||
|
||||
nsCOMPtr<nsIPersistentProperties> mProps;
|
||||
virtual nsresult LoadProperties() = 0;
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
|
||||
size_t SizeOfIncludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf) const override;
|
||||
const nsCString& BundleURL() const { return mPropertiesURL; }
|
||||
|
||||
// Returns true if this bundle has more than one reference. If it has only
|
||||
// a single reference, it is assumed to be held alive by the bundle cache.
|
||||
bool IsShared() const { return mRefCnt > 1; }
|
||||
|
||||
static nsStringBundleBase* Cast(nsIStringBundle* aBundle)
|
||||
{
|
||||
return static_cast<nsStringBundleBase*>(aBundle);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
static already_AddRefed<T> Create(Args... args);
|
||||
|
||||
protected:
|
||||
virtual ~nsStringBundle();
|
||||
nsStringBundleBase(const char* aURLSpec);
|
||||
|
||||
virtual ~nsStringBundleBase();
|
||||
|
||||
virtual nsresult GetStringImpl(const nsACString& aName, nsAString& aResult) = 0;
|
||||
|
||||
virtual nsresult GetSimpleEnumerationImpl(nsISimpleEnumerator** elements) = 0;
|
||||
|
||||
void RegisterMemoryReporter();
|
||||
|
||||
nsresult GetCombinedEnumeration(nsIStringBundleOverride* aOverrideString,
|
||||
nsISimpleEnumerator** aResult);
|
||||
private:
|
||||
nsCString mPropertiesURL;
|
||||
nsCOMPtr<nsIStringBundleOverride> mOverrideStrings;
|
||||
mozilla::ReentrantMonitor mReentrantMonitor;
|
||||
bool mAttemptedLoad;
|
||||
bool mLoaded;
|
||||
|
||||
size_t SizeOfIncludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
public:
|
||||
static nsresult FormatString(const char16_t *formatStr,
|
||||
const char16_t **aParams, uint32_t aLength,
|
||||
nsAString& aResult);
|
||||
};
|
||||
|
||||
class nsExtensibleStringBundle;
|
||||
|
||||
/**
|
||||
* An extensible implementation of the StringBundle interface.
|
||||
*
|
||||
* @created 28/Dec/1999
|
||||
* @author Catalin Rotaru [CATA]
|
||||
*/
|
||||
class nsExtensibleStringBundle final : public nsIStringBundle
|
||||
class nsStringBundle : public nsStringBundleBase
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTRINGBUNDLE
|
||||
|
||||
nsresult Init(const char * aCategory, nsIStringBundleService *);
|
||||
|
||||
public:
|
||||
nsExtensibleStringBundle();
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
|
||||
size_t SizeOfIncludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf) const override;
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
private:
|
||||
virtual ~nsExtensibleStringBundle();
|
||||
nsCOMPtr<nsIPersistentProperties> mProps;
|
||||
|
||||
nsCOMArray<nsIStringBundle> mBundles;
|
||||
bool mLoaded;
|
||||
nsresult LoadProperties() override;
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
protected:
|
||||
friend class nsStringBundleBase;
|
||||
|
||||
explicit nsStringBundle(const char* aURLSpec);
|
||||
|
||||
virtual ~nsStringBundle();
|
||||
|
||||
nsresult GetStringImpl(const nsACString& aName, nsAString& aResult) override;
|
||||
|
||||
nsresult GetSimpleEnumerationImpl(nsISimpleEnumerator** elements) override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
#include "nsIObserver.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsIErrorService.h"
|
||||
#include "nsIStringBundleOverride.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
struct bundleCacheEntry_t;
|
||||
|
||||
|
@ -43,14 +43,20 @@ public:
|
|||
size_t amt = SizeOfIncludingThis(MallocSizeOf);
|
||||
|
||||
MOZ_COLLECT_REPORT(
|
||||
"explicit/string-bundle-service", KIND_HEAP, UNITS_BYTES,
|
||||
"explicit/string-bundles/service", KIND_HEAP, UNITS_BYTES,
|
||||
amt,
|
||||
"Memory used for StringBundleService bundles");
|
||||
"Memory used for StringBundleService overhead");
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
void SendContentBundles(mozilla::dom::ContentParent* aContentParent) const override;
|
||||
|
||||
void RegisterContentBundle(const nsCString& aBundleURL,
|
||||
const mozilla::ipc::FileDescriptor& aMapFile,
|
||||
size_t aMapSize) override;
|
||||
|
||||
private:
|
||||
virtual ~nsStringBundleService();
|
||||
|
||||
|
@ -59,16 +65,20 @@ private:
|
|||
uint32_t argCount, char16_t** argArray,
|
||||
nsAString& result);
|
||||
|
||||
void flushBundleCache();
|
||||
void flushBundleCache(bool ignoreShared = true);
|
||||
|
||||
bundleCacheEntry_t *insertIntoCache(already_AddRefed<nsIStringBundle> aBundle,
|
||||
nsCString &aHashKey);
|
||||
mozilla::UniquePtr<bundleCacheEntry_t> evictOneEntry();
|
||||
|
||||
bundleCacheEntry_t* insertIntoCache(already_AddRefed<nsIStringBundle> aBundle,
|
||||
const nsACString &aHashKey);
|
||||
|
||||
nsDataHashtable<nsCStringHashKey, bundleCacheEntry_t*> mBundleMap;
|
||||
// LRU list of cached entries, with the least-recently-used entry first.
|
||||
mozilla::LinkedList<bundleCacheEntry_t> mBundleCache;
|
||||
// List of cached shared-memory string bundles, in arbitrary order.
|
||||
mozilla::AutoCleanLinkedList<bundleCacheEntry_t> mSharedBundles;
|
||||
|
||||
nsCOMPtr<nsIErrorService> mErrorService;
|
||||
nsCOMPtr<nsIStringBundleOverride> mOverrideStrings;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,292 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#include "nsStringBundleTextOverride.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
|
||||
// first we need a simple class which wraps a nsIPropertyElement and
|
||||
// cuts out the leading URL from the key
|
||||
class URLPropertyElement : public nsIPropertyElement
|
||||
{
|
||||
public:
|
||||
URLPropertyElement(nsIPropertyElement *aRealElement, uint32_t aURLLength) :
|
||||
mRealElement(aRealElement),
|
||||
mURLLength(aURLLength)
|
||||
{ }
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPROPERTYELEMENT
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIPropertyElement> mRealElement;
|
||||
uint32_t mURLLength;
|
||||
|
||||
virtual ~URLPropertyElement() {}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(URLPropertyElement, nsIPropertyElement)
|
||||
|
||||
// we'll tweak the key on the way through, and remove the url prefix
|
||||
NS_IMETHODIMP
|
||||
URLPropertyElement::GetKey(nsACString& aKey)
|
||||
{
|
||||
nsresult rv = mRealElement->GetKey(aKey);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// chop off the url
|
||||
aKey.Cut(0, mURLLength);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// values are unaffected
|
||||
NS_IMETHODIMP
|
||||
URLPropertyElement::GetValue(nsAString& aValue)
|
||||
{
|
||||
return mRealElement->GetValue(aValue);
|
||||
}
|
||||
|
||||
// setters are kind of strange, hopefully we'll never be called
|
||||
NS_IMETHODIMP
|
||||
URLPropertyElement::SetKey(const nsACString& aKey)
|
||||
{
|
||||
// this is just wrong - ideally you'd take the key, append it to
|
||||
// the url, and set that as the key. However, that would require
|
||||
// us to hold onto a copy of the string, and that's a waste,
|
||||
// considering nobody should ever be calling this.
|
||||
NS_ERROR("This makes no sense!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
URLPropertyElement::SetValue(const nsAString& aValue)
|
||||
{
|
||||
return mRealElement->SetValue(aValue);
|
||||
}
|
||||
|
||||
|
||||
// this is a special enumerator which returns only the elements which
|
||||
// are prefixed with a particular url
|
||||
class nsPropertyEnumeratorByURL : public nsISimpleEnumerator
|
||||
{
|
||||
public:
|
||||
nsPropertyEnumeratorByURL(const nsACString& aURL,
|
||||
nsISimpleEnumerator* aOuter) :
|
||||
mOuter(aOuter),
|
||||
mURL(aURL)
|
||||
{
|
||||
// prepare the url once so we can use its value later
|
||||
// persistent properties uses ":" as a delimiter, so escape
|
||||
// that character
|
||||
mURL.ReplaceSubstring(":", "%3A");
|
||||
// there is always a # between the url and the real key
|
||||
mURL.Append('#');
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
private:
|
||||
|
||||
// actual enumerator of all strings from nsIProperties
|
||||
nsCOMPtr<nsISimpleEnumerator> mOuter;
|
||||
|
||||
// the current element that is valid for this url
|
||||
nsCOMPtr<nsIPropertyElement> mCurrent;
|
||||
|
||||
// the url in question, pre-escaped and with the # already in it
|
||||
nsCString mURL;
|
||||
|
||||
virtual ~nsPropertyEnumeratorByURL() {}
|
||||
};
|
||||
|
||||
//
|
||||
// nsStringBundleTextOverride implementation
|
||||
//
|
||||
NS_IMPL_ISUPPORTS(nsStringBundleTextOverride,
|
||||
nsIStringBundleOverride)
|
||||
|
||||
nsresult
|
||||
nsStringBundleTextOverride::Init()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// check for existence of custom-strings.txt
|
||||
|
||||
nsCOMPtr<nsIFile> customStringsFile;
|
||||
rv = NS_GetSpecialDirectory(NS_APP_CHROME_DIR,
|
||||
getter_AddRefs(customStringsFile));
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// bail if not found - this will cause the service creation to
|
||||
// bail as well, and cause this object to go away
|
||||
|
||||
customStringsFile->AppendNative(NS_LITERAL_CSTRING("custom-strings.txt"));
|
||||
|
||||
bool exists;
|
||||
rv = customStringsFile->Exists(&exists);
|
||||
if (NS_FAILED(rv) || !exists)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_WARNING("Using custom-strings.txt to override string bundles.");
|
||||
// read in the custom bundle. Keys are in the form
|
||||
// chrome://package/locale/foo.properties:keyname
|
||||
|
||||
nsAutoCString customStringsURLSpec;
|
||||
rv = NS_GetURLSpecFromFile(customStringsFile, customStringsURLSpec);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), customStringsURLSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = NS_NewChannel(getter_AddRefs(channel),
|
||||
uri,
|
||||
nsContentUtils::GetSystemPrincipal(),
|
||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
||||
nsIContentPolicy::TYPE_OTHER);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIInputStream> in;
|
||||
rv = channel->Open2(getter_AddRefs(in));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
static NS_DEFINE_CID(kPersistentPropertiesCID, NS_IPERSISTENTPROPERTIES_CID);
|
||||
mValues = do_CreateInstance(kPersistentPropertiesCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mValues->Load(in);
|
||||
|
||||
// turn this on to see the contents of custom-strings.txt
|
||||
#ifdef DEBUG_alecf
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
mValues->Enumerate(getter_AddRefs(enumerator));
|
||||
NS_ASSERTION(enumerator, "no enumerator!\n");
|
||||
|
||||
printf("custom-strings.txt contains:\n");
|
||||
printf("----------------------------\n");
|
||||
|
||||
bool hasMore;
|
||||
enumerator->HasMoreElements(&hasMore);
|
||||
do {
|
||||
nsCOMPtr<nsISupports> sup;
|
||||
enumerator->GetNext(getter_AddRefs(sup));
|
||||
|
||||
nsCOMPtr<nsIPropertyElement> prop = do_QueryInterface(sup);
|
||||
|
||||
nsAutoCString key;
|
||||
nsAutoString value;
|
||||
prop->GetKey(key);
|
||||
prop->GetValue(value);
|
||||
|
||||
printf("%s = '%s'\n", key.get(), NS_ConvertUTF16toUTF8(value).get());
|
||||
|
||||
enumerator->HasMoreElements(&hasMore);
|
||||
} while (hasMore);
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStringBundleTextOverride::GetStringFromName(const nsACString& aURL,
|
||||
const nsACString& key,
|
||||
nsAString& aResult)
|
||||
{
|
||||
// concatenate url#key to get the key to read
|
||||
nsAutoCString combinedURL(aURL + NS_LITERAL_CSTRING("#") + key);
|
||||
|
||||
// persistent properties uses ":" as a delimiter, so escape that character
|
||||
combinedURL.ReplaceSubstring(":", "%3A");
|
||||
|
||||
return mValues->GetStringProperty(combinedURL, aResult);
|
||||
}
|
||||
|
||||
size_t
|
||||
nsStringBundleTextOverride::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return aMallocSizeOf(this) + (mValues ? mValues->SizeOfIncludingThis(aMallocSizeOf) : 0);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStringBundleTextOverride::EnumerateKeysInBundle(const nsACString& aURL,
|
||||
nsISimpleEnumerator** aResult)
|
||||
{
|
||||
// enumerate all strings, and let the enumerator know
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
mValues->Enumerate(getter_AddRefs(enumerator));
|
||||
|
||||
// make the enumerator wrapper and pass it off
|
||||
nsPropertyEnumeratorByURL* propEnum =
|
||||
new nsPropertyEnumeratorByURL(aURL, enumerator);
|
||||
|
||||
if (!propEnum) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aResult = propEnum);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// nsPropertyEnumeratorByURL implementation
|
||||
//
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsPropertyEnumeratorByURL, nsISimpleEnumerator)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPropertyEnumeratorByURL::GetNext(nsISupports **aResult)
|
||||
{
|
||||
if (!mCurrent) return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// wrap mCurrent instead of returning it
|
||||
*aResult = new URLPropertyElement(mCurrent, mURL.Length());
|
||||
NS_ADDREF(*aResult);
|
||||
|
||||
// release it so we don't return it twice
|
||||
mCurrent = nullptr;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPropertyEnumeratorByURL::HasMoreElements(bool * aResult)
|
||||
{
|
||||
bool hasMore;
|
||||
mOuter->HasMoreElements(&hasMore);
|
||||
while (hasMore) {
|
||||
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
mOuter->GetNext(getter_AddRefs(supports));
|
||||
|
||||
mCurrent = do_QueryInterface(supports);
|
||||
|
||||
if (mCurrent) {
|
||||
nsAutoCString curKey;
|
||||
mCurrent->GetKey(curKey);
|
||||
|
||||
if (StringBeginsWith(curKey, mURL))
|
||||
break;
|
||||
}
|
||||
|
||||
mOuter->HasMoreElements(&hasMore);
|
||||
}
|
||||
|
||||
if (!hasMore)
|
||||
mCurrent = nullptr;
|
||||
|
||||
*aResult = mCurrent ? true : false;
|
||||
|
||||
return NS_OK;
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#ifndef nsStringBundleTextOverride_h__
|
||||
#define nsStringBundleTextOverride_h__
|
||||
|
||||
#include "nsIStringBundleOverride.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIPersistentProperties2.h"
|
||||
|
||||
// {6316C6CE-12D3-479e-8F53-E289351412B8}
|
||||
#define NS_STRINGBUNDLETEXTOVERRIDE_CID \
|
||||
{ 0x6316c6ce, 0x12d3, 0x479e, \
|
||||
{ 0x8f, 0x53, 0xe2, 0x89, 0x35, 0x14, 0x12, 0xb8 } }
|
||||
|
||||
|
||||
#define NS_STRINGBUNDLETEXTOVERRIDE_CONTRACTID \
|
||||
"@mozilla.org/intl/stringbundle/text-override;1"
|
||||
|
||||
// an implementation which does overrides from a text file
|
||||
|
||||
class nsStringBundleTextOverride : public nsIStringBundleOverride
|
||||
{
|
||||
public:
|
||||
nsStringBundleTextOverride() { }
|
||||
|
||||
nsresult Init();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTRINGBUNDLEOVERRIDE
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIPersistentProperties> mValues;
|
||||
|
||||
virtual ~nsStringBundleTextOverride() {}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -7,7 +7,7 @@ license = "MPL-2.0"
|
|||
|
||||
[build-dependencies]
|
||||
env_logger = {version = "0.5", default-features = false} # disable `regex` to reduce code size
|
||||
bindgen = {version = "0.33.1", default-features = false} # disable `logging` to reduce code size
|
||||
bindgen = {version = "0.37", default-features = false} # disable `logging` to reduce code size
|
||||
cmake = "0.1"
|
||||
glob = "0.2.11"
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,8 @@
|
|||
#!/bin/sh
|
||||
|
||||
cargo run -- \
|
||||
../BinSource.webidl_ \
|
||||
../BinSource.yaml \
|
||||
--out-class ../BinSource-auto.h \
|
||||
--out-impl ../BinSource-auto.cpp \
|
||||
--out-token ../BinToken.h
|
|
@ -19,6 +19,22 @@ use clap::{ App, Arg };
|
|||
|
||||
use itertools::Itertools;
|
||||
|
||||
/// A string or string-like construction that can be appended newline.
|
||||
trait NewLineIfNotEmpty {
|
||||
/// Append newline if the string is not empty.
|
||||
fn newline_if_not_empty(&self) -> String;
|
||||
}
|
||||
impl<T> NewLineIfNotEmpty for T where T: ToStr {
|
||||
fn newline_if_not_empty(&self) -> String {
|
||||
let str = self.to_str();
|
||||
if str.len() == 0 {
|
||||
"".to_string()
|
||||
} else {
|
||||
format!("{}\n", str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Rules for generating the code for parsing a single field
|
||||
/// of a node.
|
||||
///
|
||||
|
@ -735,18 +751,18 @@ impl CPPExporter {
|
|||
buffer_cases.push_str(&format!("
|
||||
case BinKind::{variant_name}:
|
||||
MOZ_TRY_VAR(result, parseInterface{class_name}(start, kind, fields));
|
||||
{arm_after}
|
||||
break;",
|
||||
{arm_after} break;",
|
||||
class_name = node.to_class_cases(),
|
||||
variant_name = node.to_cpp_enum_case(),
|
||||
arm_after = rules_for_this_sum.by_sum.get(&node)
|
||||
.cloned()
|
||||
.unwrap_or_default().after_arm.reindent(" ")));
|
||||
.unwrap_or_default().after_arm.reindent(" ")
|
||||
.newline_if_not_empty()));
|
||||
}
|
||||
buffer.push_str(&format!("\n{first_line}
|
||||
{{
|
||||
{type_ok} result;
|
||||
switch(kind) {{{cases}
|
||||
switch (kind) {{{cases}
|
||||
default:
|
||||
return raiseInvalidKind(\"{kind}\", kind);
|
||||
}}
|
||||
|
@ -888,9 +904,11 @@ impl CPPExporter {
|
|||
{type_ok} result;
|
||||
if (kind == BinKind::{null}) {{
|
||||
result = {default_value};
|
||||
}} else {{
|
||||
}} else if (kind == BinKind::{kind}) {{
|
||||
const auto start = tokenizer_->offset();
|
||||
MOZ_TRY_VAR(result, parseInterface{contents}(start, kind, fields));
|
||||
}} else {{
|
||||
return raiseInvalidKind(\"{kind}\", kind);
|
||||
}}
|
||||
MOZ_TRY(guard.done());
|
||||
|
||||
|
@ -903,6 +921,7 @@ impl CPPExporter {
|
|||
contents = parser.elements.to_class_cases(),
|
||||
type_ok = type_ok,
|
||||
default_value = default_value,
|
||||
kind = parser.elements.to_cpp_enum_case(),
|
||||
));
|
||||
}
|
||||
NamedType::Typedef(ref type_) => {
|
||||
|
@ -988,7 +1007,6 @@ impl CPPExporter {
|
|||
buffer.push_str(&comment);
|
||||
|
||||
// Generate public method
|
||||
let kind = name.to_class_cases();
|
||||
buffer.push_str(&format!("{first_line}
|
||||
{{
|
||||
BinKind kind;
|
||||
|
@ -996,9 +1014,11 @@ impl CPPExporter {
|
|||
AutoTaggedTuple guard(*tokenizer_);
|
||||
|
||||
MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
|
||||
if (kind != BinKind::{kind}) {{
|
||||
return raiseInvalidKind(\"{kind}\", kind);
|
||||
}}
|
||||
const auto start = tokenizer_->offset();
|
||||
|
||||
BINJS_MOZ_TRY_DECL(result, parseInterface{kind}(start, kind, fields));
|
||||
BINJS_MOZ_TRY_DECL(result, parseInterface{class_name}(start, kind, fields));
|
||||
MOZ_TRY(guard.done());
|
||||
|
||||
return result;
|
||||
|
@ -1006,7 +1026,8 @@ impl CPPExporter {
|
|||
|
||||
",
|
||||
first_line = self.get_method_definition_start(name, "ParseNode*", "", ""),
|
||||
kind = kind
|
||||
kind = name.to_cpp_enum_case(),
|
||||
class_name = name.to_class_cases(),
|
||||
));
|
||||
|
||||
// Generate aux method
|
||||
|
@ -1115,32 +1136,24 @@ impl CPPExporter {
|
|||
};
|
||||
if needs_block {
|
||||
let parse_var = parse_var.reindent(" ");
|
||||
format!("{before_field}
|
||||
{decl_var}
|
||||
{{
|
||||
{block_before_field}
|
||||
{parse_var}
|
||||
{block_after_field}
|
||||
format!("{before_field}{decl_var} {{
|
||||
{block_before_field}{parse_var}{block_after_field}
|
||||
}}
|
||||
{after_field}",
|
||||
before_field = before_field.reindent(" "),
|
||||
decl_var = decl_var.reindent(" "),
|
||||
parse_var = parse_var.reindent(" "),
|
||||
after_field = after_field.reindent(" "),
|
||||
block_before_field = rules_for_this_field.block_before_field.reindent(" "),
|
||||
block_after_field = rules_for_this_field.block_after_field.reindent(" "))
|
||||
before_field = before_field.reindent(" ").newline_if_not_empty(),
|
||||
decl_var = decl_var.reindent(" ").newline_if_not_empty(),
|
||||
block_before_field = rules_for_this_field.block_before_field.reindent(" ").newline_if_not_empty(),
|
||||
parse_var = parse_var.reindent(" ").newline_if_not_empty(),
|
||||
block_after_field = rules_for_this_field.block_after_field.reindent(" "),
|
||||
after_field = after_field.reindent(" "))
|
||||
} else {
|
||||
// We have a before_field and an after_field. This will create newlines
|
||||
// for them.
|
||||
format!("
|
||||
{before_field}
|
||||
{decl_var}
|
||||
{parse_var}
|
||||
{after_field}
|
||||
",
|
||||
before_field = before_field.reindent(" "),
|
||||
decl_var = decl_var.reindent(" "),
|
||||
parse_var = parse_var.reindent(" "),
|
||||
{before_field}{decl_var}{parse_var}{after_field}",
|
||||
before_field = before_field.reindent(" ").newline_if_not_empty(),
|
||||
decl_var = decl_var.reindent(" ").newline_if_not_empty(),
|
||||
parse_var = parse_var.reindent(" ").newline_if_not_empty(),
|
||||
after_field = after_field.reindent(" "))
|
||||
}
|
||||
}
|
||||
|
@ -1154,11 +1167,11 @@ impl CPPExporter {
|
|||
if build_result == "" {
|
||||
buffer.push_str(&format!("{first_line}
|
||||
{{
|
||||
return raiseError(\"FIXME: Not implemented yet ({})\");
|
||||
return raiseError(\"FIXME: Not implemented yet ({class_name})\");
|
||||
}}
|
||||
|
||||
",
|
||||
kind = kind.to_str(),
|
||||
class_name = name.to_class_cases(),
|
||||
first_line = first_line,
|
||||
));
|
||||
} else {
|
||||
|
@ -1170,8 +1183,7 @@ impl CPPExporter {
|
|||
#if defined(DEBUG)
|
||||
const BinField expected_fields[{number_of_fields}] = {fields_type_list};
|
||||
MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
|
||||
#endif // defined(DEBUG)
|
||||
",
|
||||
#endif // defined(DEBUG)",
|
||||
fields_type_list = fields_type_list,
|
||||
number_of_fields = number_of_fields)
|
||||
};
|
||||
|
@ -1179,18 +1191,16 @@ impl CPPExporter {
|
|||
{{
|
||||
MOZ_ASSERT(kind == BinKind::{kind});
|
||||
BINJS_TRY(CheckRecursionLimit(cx_));
|
||||
|
||||
{check_fields}
|
||||
{pre}{fields_implem}
|
||||
{post}
|
||||
return result;
|
||||
{post} return result;
|
||||
}}
|
||||
|
||||
",
|
||||
check_fields = check_fields,
|
||||
fields_implem = fields_implem,
|
||||
pre = init,
|
||||
post = build_result,
|
||||
pre = init.newline_if_not_empty(),
|
||||
post = build_result.newline_if_not_empty(),
|
||||
kind = name.to_cpp_enum_case(),
|
||||
first_line = first_line,
|
||||
));
|
||||
|
|
|
@ -19,19 +19,11 @@ using namespace mozilla::ipc;
|
|||
|
||||
AutoMemMap::~AutoMemMap()
|
||||
{
|
||||
if (fileMap) {
|
||||
if (addr) {
|
||||
Unused << NS_WARN_IF(PR_MemUnmap(addr, size()) != PR_SUCCESS);
|
||||
addr = nullptr;
|
||||
}
|
||||
|
||||
Unused << NS_WARN_IF(PR_CloseFileMap(fileMap) != PR_SUCCESS);
|
||||
fileMap = nullptr;
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
FileDescriptor
|
||||
AutoMemMap::cloneFileDescriptor()
|
||||
AutoMemMap::cloneFileDescriptor() const
|
||||
{
|
||||
if (fd.get()) {
|
||||
auto handle = FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(fd.get()));
|
||||
|
@ -51,7 +43,8 @@ AutoMemMap::init(nsIFile* file, int flags, int mode, PRFileMapProtect prot)
|
|||
}
|
||||
|
||||
Result<Ok, nsresult>
|
||||
AutoMemMap::init(const FileDescriptor& file)
|
||||
AutoMemMap::init(const FileDescriptor& file, PRFileMapProtect prot,
|
||||
size_t expectedSize)
|
||||
{
|
||||
MOZ_ASSERT(!fd);
|
||||
if (!file.IsValid()) {
|
||||
|
@ -66,11 +59,11 @@ AutoMemMap::init(const FileDescriptor& file)
|
|||
}
|
||||
Unused << handle.release();
|
||||
|
||||
return initInternal();
|
||||
return initInternal(prot, expectedSize);
|
||||
}
|
||||
|
||||
Result<Ok, nsresult>
|
||||
AutoMemMap::initInternal(PRFileMapProtect prot)
|
||||
AutoMemMap::initInternal(PRFileMapProtect prot, size_t expectedSize)
|
||||
{
|
||||
MOZ_ASSERT(!fileMap);
|
||||
MOZ_ASSERT(!addr);
|
||||
|
@ -86,6 +79,12 @@ AutoMemMap::initInternal(PRFileMapProtect prot)
|
|||
return Err(NS_ERROR_FAILURE);
|
||||
|
||||
size_ = fileInfo.size;
|
||||
// The memory region size passed in certain IPC messages isn't necessary on
|
||||
// Unix-like systems, since we can always stat the file descriptor to
|
||||
// determine it accurately. But since we have it, anyway, sanity check that
|
||||
// it matches the size returned by the stat.
|
||||
MOZ_ASSERT_IF(expectedSize > 0, size_ == expectedSize);
|
||||
|
||||
addr = PR_MemMap(fileMap, 0, size_);
|
||||
if (!addr)
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
|
@ -93,5 +92,73 @@ AutoMemMap::initInternal(PRFileMapProtect prot)
|
|||
return Ok();
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
||||
Result<Ok, nsresult>
|
||||
AutoMemMap::initWithHandle(const FileDescriptor& file, size_t size, PRFileMapProtect prot)
|
||||
{
|
||||
MOZ_ASSERT(!fd);
|
||||
MOZ_ASSERT(!handle_);
|
||||
if (!file.IsValid()) {
|
||||
return Err(NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
|
||||
handle_ = file.ClonePlatformHandle().release();
|
||||
|
||||
MOZ_ASSERT(!addr);
|
||||
|
||||
size_ = size;
|
||||
|
||||
addr = MapViewOfFile(
|
||||
handle_,
|
||||
prot == PR_PROT_READONLY ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS,
|
||||
0, 0, size);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
FileDescriptor
|
||||
AutoMemMap::cloneHandle() const
|
||||
{
|
||||
return FileDescriptor(handle_);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
Result<Ok, nsresult>
|
||||
AutoMemMap::initWithHandle(const FileDescriptor& file, size_t size, PRFileMapProtect prot)
|
||||
{
|
||||
return init(file, prot);
|
||||
}
|
||||
|
||||
FileDescriptor
|
||||
AutoMemMap::cloneHandle() const
|
||||
{
|
||||
return cloneFileDescriptor();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
AutoMemMap::reset()
|
||||
{
|
||||
if (fileMap) {
|
||||
if (addr && !persistent_) {
|
||||
Unused << NS_WARN_IF(PR_MemUnmap(addr, size()) != PR_SUCCESS);
|
||||
addr = nullptr;
|
||||
}
|
||||
|
||||
Unused << NS_WARN_IF(PR_CloseFileMap(fileMap) != PR_SUCCESS);
|
||||
fileMap = nullptr;
|
||||
}
|
||||
#ifdef XP_WIN
|
||||
if (handle_) {
|
||||
CloseHandle(handle_);
|
||||
handle_ = nullptr;
|
||||
}
|
||||
#endif
|
||||
fd.dispose();
|
||||
}
|
||||
|
||||
} // namespace loader
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -34,14 +34,26 @@ class AutoMemMap
|
|||
PRFileMapProtect prot = PR_PROT_READONLY);
|
||||
|
||||
Result<Ok, nsresult>
|
||||
init(const ipc::FileDescriptor& file);
|
||||
init(const ipc::FileDescriptor& file,
|
||||
PRFileMapProtect prot = PR_PROT_READONLY,
|
||||
size_t expectedSize = 0);
|
||||
|
||||
// Initializes the mapped memory with a shared memory handle. On
|
||||
// Unix-like systems, this is identical to the above init() method. On
|
||||
// Windows, the FileDescriptor must be a handle for a file mapping,
|
||||
// rather than a file descriptor.
|
||||
Result<Ok, nsresult>
|
||||
initWithHandle(const ipc::FileDescriptor& file, size_t size,
|
||||
PRFileMapProtect prot = PR_PROT_READONLY);
|
||||
|
||||
void reset();
|
||||
|
||||
bool initialized() { return addr; }
|
||||
|
||||
uint32_t size() const { MOZ_ASSERT(fd); return size_; }
|
||||
uint32_t size() const { return size_; }
|
||||
|
||||
template<typename T = void>
|
||||
const RangedPtr<T> get()
|
||||
RangedPtr<T> get()
|
||||
{
|
||||
MOZ_ASSERT(addr);
|
||||
return { static_cast<T*>(addr), size_ };
|
||||
|
@ -56,17 +68,32 @@ class AutoMemMap
|
|||
|
||||
size_t nonHeapSizeOfExcludingThis() { return size_; }
|
||||
|
||||
FileDescriptor cloneFileDescriptor();
|
||||
FileDescriptor cloneFileDescriptor() const;
|
||||
FileDescriptor cloneHandle() const;
|
||||
|
||||
// Makes this mapping persistent. After calling this, the mapped memory
|
||||
// will remained mapped, even after this instance is destroyed.
|
||||
void setPersistent() { persistent_ = true; }
|
||||
|
||||
private:
|
||||
Result<Ok, nsresult> initInternal(PRFileMapProtect prot = PR_PROT_READONLY);
|
||||
Result<Ok, nsresult> initInternal(PRFileMapProtect prot = PR_PROT_READONLY,
|
||||
size_t expectedSize = 0);
|
||||
|
||||
AutoFDClose fd;
|
||||
PRFileMap* fileMap = nullptr;
|
||||
|
||||
#ifdef XP_WIN
|
||||
// We can't include windows.h in this header, since it gets included
|
||||
// by some binding headers (which are explicitly incompatible with
|
||||
// windows.h). So we can't use the HANDLE type here.
|
||||
void* handle_ = nullptr;
|
||||
#endif
|
||||
|
||||
uint32_t size_ = 0;
|
||||
void* addr = nullptr;
|
||||
|
||||
bool persistent_ = 0;
|
||||
|
||||
AutoMemMap(const AutoMemMap&) = delete;
|
||||
void operator=(const AutoMemMap&) = delete;
|
||||
};
|
||||
|
|
|
@ -25,6 +25,7 @@ IPDL_SOURCES += [
|
|||
]
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
'AutoMemMap.h',
|
||||
'ScriptPreloader.h',
|
||||
'URLPreloader.h',
|
||||
]
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html style="width: 1px;">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body onload="x.style.color='red';">
|
||||
<div id="x" style="overflow: scroll;"><input type="image" style="display: contents;"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -641,6 +641,7 @@ load text-overflow-form-elements.html
|
|||
load text-overflow-iframe.html
|
||||
asserts(1-4) load 1225005.html # bug 682647 and bug 448083
|
||||
load 1233191.html
|
||||
load 1233607.html
|
||||
load 1234701-1.html
|
||||
load 1234701-2.html
|
||||
load 1271765.html
|
||||
|
|
|
@ -123,6 +123,19 @@ public:
|
|||
MOZ_ASSERT(mRangeEnd == aOther.mRangeEnd);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
RangedPtr<U>
|
||||
ReinterpretCast() const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
return { reinterpret_cast<U*>(mPtr),
|
||||
reinterpret_cast<U*>(mRangeStart),
|
||||
reinterpret_cast<U*>(mRangeEnd) };
|
||||
#else
|
||||
return { reinterpret_cast<U*>(mPtr), nullptr, nullptr };
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* You can only assign one RangedPtr into another if the two pointers have
|
||||
* the same valid range:
|
||||
|
|
|
@ -807,8 +807,6 @@ malloc_size_of_is_0!(webrender_api::NormalBorder);
|
|||
#[cfg(feature = "webrender_api")]
|
||||
malloc_size_of_is_0!(webrender_api::RepeatMode);
|
||||
#[cfg(feature = "webrender_api")]
|
||||
malloc_size_of_is_0!(webrender_api::ScrollPolicy);
|
||||
#[cfg(feature = "webrender_api")]
|
||||
malloc_size_of_is_0!(webrender_api::ScrollSensitivity);
|
||||
#[cfg(feature = "webrender_api")]
|
||||
malloc_size_of_is_0!(webrender_api::StickyOffsetBounds);
|
||||
|
|
|
@ -78,7 +78,7 @@ kernel32-sys = "0.2"
|
|||
[build-dependencies]
|
||||
lazy_static = "1"
|
||||
log = "0.4"
|
||||
bindgen = { version = "0.33.2", optional = true, default-features = false }
|
||||
bindgen = { version = "0.37", optional = true, default-features = false }
|
||||
regex = {version = "0.2", optional = true}
|
||||
walkdir = "2.1.4"
|
||||
toml = {version = "0.4.5", optional = true, default-features = false}
|
||||
|
|
|
@ -71,7 +71,7 @@ bitflags! {
|
|||
const IN_OPTIONAL_STATE = 1 << 22;
|
||||
/// <https://html.spec.whatwg.org/multipage/#selector-read-write>
|
||||
const IN_READ_WRITE_STATE = 1 << 22;
|
||||
/// <https://html.spec.whatwg.org/multipage/semantics-other.html#selector-defined>
|
||||
/// <https://html.spec.whatwg.org/multipage/#selector-defined>
|
||||
const IN_DEFINED_STATE = 1 << 23;
|
||||
/// <https://html.spec.whatwg.org/multipage/#selector-visited>
|
||||
const IN_VISITED_STATE = 1 << 24;
|
||||
|
|
|
@ -6,17 +6,16 @@
|
|||
//!
|
||||
//! https://drafts.csswg.org/mediaqueries-4/#typedef-media-condition
|
||||
|
||||
use cssparser::{Parser, Token};
|
||||
use context::QuirksMode;
|
||||
use cssparser::{Parser, Token};
|
||||
use parser::ParserContext;
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||
|
||||
use super::{Device, MediaFeatureExpression};
|
||||
|
||||
|
||||
/// A binary `and` or `or` operator.
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Parse, ToCss)]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum Operator {
|
||||
And,
|
||||
|
@ -24,7 +23,7 @@ pub enum Operator {
|
|||
}
|
||||
|
||||
/// Whether to allow an `or` condition or not during parsing.
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Parse, ToCss)]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss)]
|
||||
enum AllowOr {
|
||||
Yes,
|
||||
No,
|
||||
|
|
|
@ -216,7 +216,7 @@ impl MediaFeatureExpression {
|
|||
"width" => {
|
||||
ExpressionKind::Width(Range::Eq(specified::Length::parse_non_negative(context, input)?))
|
||||
},
|
||||
_ => return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name)))
|
||||
_ => return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone())))
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
|
@ -27,12 +27,10 @@ mod attr;
|
|||
mod custom_properties;
|
||||
mod keyframes;
|
||||
mod logical_geometry;
|
||||
mod media_queries;
|
||||
mod parsing;
|
||||
mod properties;
|
||||
mod rule_tree;
|
||||
mod size_of;
|
||||
#[path = "../../../ports/geckolib/tests/specified_values.rs"]
|
||||
mod specified_values;
|
||||
mod str;
|
||||
mod stylesheets;
|
||||
|
|
|
@ -7,7 +7,7 @@ use style::computed_values::display::T as Display;
|
|||
use style::properties::{PropertyDeclaration, Importance};
|
||||
use style::properties::declaration_block::PropertyDeclarationBlock;
|
||||
use style::properties::parse_property_declaration_list;
|
||||
use style::values::{CustomIdent, RGBA};
|
||||
use style::values::RGBA;
|
||||
use style::values::specified::{BorderStyle, BorderSideWidth, Color};
|
||||
use style::values::specified::{Length, LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||
use style::values::specified::NoCalcLength;
|
||||
|
@ -75,39 +75,6 @@ mod shorthand_serialization {
|
|||
block.to_css_string()
|
||||
}
|
||||
|
||||
// Add Test to show error if a longhand property is missing!!!!!!
|
||||
|
||||
mod overflow {
|
||||
pub use super::*;
|
||||
use style::properties::longhands::overflow_x::SpecifiedValue as OverflowValue;
|
||||
|
||||
#[test]
|
||||
fn equal_overflow_properties_should_serialize_to_single_value() {
|
||||
let mut properties = Vec::new();
|
||||
|
||||
let overflow = OverflowValue::Auto;
|
||||
properties.push(PropertyDeclaration::OverflowX(overflow));
|
||||
properties.push(PropertyDeclaration::OverflowY(overflow));
|
||||
|
||||
let serialization = shorthand_properties_to_string(properties);
|
||||
assert_eq!(serialization, "overflow: auto;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn different_overflow_properties_should_serialize_to_two_values() {
|
||||
let mut properties = Vec::new();
|
||||
|
||||
let overflow_x = OverflowValue::Scroll;
|
||||
properties.push(PropertyDeclaration::OverflowX(overflow_x));
|
||||
|
||||
let overflow_y = OverflowValue::Auto;
|
||||
properties.push(PropertyDeclaration::OverflowY(overflow_y));
|
||||
|
||||
let serialization = shorthand_properties_to_string(properties);
|
||||
assert_eq!(serialization, "overflow-x: scroll; overflow-y: auto;");
|
||||
}
|
||||
}
|
||||
|
||||
mod four_sides_shorthands {
|
||||
pub use super::*;
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"d2d15d8518f87e50143184b13e14139095b0a6aa627d4d5d3a2d12893e765f50","build.rs":"032a1c51963894a421b0535f9227796d88768ac5f665a81d2edced69dc6d106a","src/callbacks.rs":"49f382ebdb94c8f0aba5496f5283ae3cdcf6666a5c41c604e6356e674f9a072b","src/clang.rs":"33d94fa699f052b52a2804b85f49fa5de3a2404ae05801ef9eae16016bc841f1","src/codegen/bitfield_unit.rs":"bd1a19701f1766d0bae3bcb97d7c3cb3881d4b182c56b8f4dfd24b7cc87b5338","src/codegen/bitfield_unit_tests.rs":"2073ac6a36e0bc9afaef5b1207966817c8fb7a1a9f6368c3b1b8f79822efbfba","src/codegen/error.rs":"2613af1d833377fd4a70719f4a09951d9d45dc9227827b9a2a938a1bcaaea2dd","src/codegen/helpers.rs":"bcb951f320fd0948e341d8eabdb58567296d77bf1ae5040c05d967e6435a15d5","src/codegen/impl_debug.rs":"e2ffd5b6ed936698aa4b9e7e3459d353383792707ad51f829a18a822f69cab0e","src/codegen/impl_partialeq.rs":"e86050b98f57fa4496dbde0beea319a89e46290309d274f626361779549b95bd","src/codegen/mod.rs":"74e818d857fb5147f623e9287632d23c4bd0cf87de840034809992b74ff88bdc","src/codegen/struct_layout.rs":"698ed7340242d1cbedd38d400c7c83c32e2fa043c35dbc9a2eea4022251ffdb0","src/extra_assertions.rs":"449549c4a7a50c3f0b06332452b2fb6c9b23f31ca8e5e1656fe6c7f21e8ef7fa","src/features.rs":"8c2148a6f922ca9cb0de2dd3ad77c4dd5734c4c219a5bea9d6b22c4367acb187","src/ir/analysis/derive_copy.rs":"14b53c53b337be00d59424371c07c6712d7cfc9a6735f9d913cda043fddce797","src/ir/analysis/derive_debug.rs":"1d6621c0fa5d899310cc175cb99703606ed34fd7f7ad77bb60f012f25ba504af","src/ir/analysis/derive_default.rs":"4fac04fc3019562cd213586680ecdcf8a3b3544ca3a5c5117f68e5c26e7ee0d9","src/ir/analysis/derive_hash.rs":"a50e849b4388115264c2d6afef5ab07e309d2469f4c3342fb683c799451e9e19","src/ir/analysis/derive_partialeq_or_partialord.rs":"46611c7f3caa0fe78243187742c4a36003dbc266de4c4390642e136bb889c43f","src/ir/analysis/has_destructor.rs":"d9aaaceba580b48eb0df4e5537b34b417c51ccdfeb8f6b72484f3bf4992317fe","src/ir/analysis/has_float.rs":"2a0465503d2c8247eaf916bd6a03594f3dc0370533d9a7c58cc5afb86693816c","src/ir/analysis/has_type_param_in_array.rs":"fcb1c78b6000f1f5eb8d8147e2afdaba9eb0e3a81b61e72537048dfdbeea7bcd","src/ir/analysis/has_vtable.rs":"37765e954ef792e369a58ccfe1d827a00fe9bce680466da1d6523671b94b6c92","src/ir/analysis/mod.rs":"ea5ace45c77e855674bb565ba0fef556f60e3293b0ddcf11d3a5a6ec15ab0648","src/ir/analysis/sizedness.rs":"3d3c8bde40604d53bb64273a3cbd8c55936a7dfe1de9b2ba92fc2c45572624b4","src/ir/analysis/template_params.rs":"5c6ee7a251a321ef5733e2e7ac3264621b4181268babcc008b69dbfc37691fb1","src/ir/annotations.rs":"ef106afcbe6084c18bd13a37ee3c1cdc9596bfb055db8c773d81f8f15fec3208","src/ir/comment.rs":"36f2a1d3970fdbf3d72c1f094043902747cde395215bdf7e9103926d9df011fd","src/ir/comp.rs":"b24e6ab76235b46bb5a262e3a3f2fc685c26bd7482aea113231a942eeffd0cf5","src/ir/context.rs":"ccd99c814f1a8ba1f3a30667a8d90db13a50adc26620be08f907283d1c5f08a3","src/ir/derive.rs":"1fd6ad621e3c60b950acbd51fbe386d1f0fadb7c1889c723245afff45e42e143","src/ir/dot.rs":"d01f1621ab67e368d854a82bd6bb0b8dd52f3c2c733de8eaf81aece9543818cb","src/ir/enum_ty.rs":"98a4aa58e598b31e4dc2c052c90029f37b53b5c5cfcbd216d4b0e8c73454813f","src/ir/function.rs":"cce97e7cd6ffb7d5ae40e6be1b82e7ae899d9ea9cf7c8f97380486ac7cc120e6","src/ir/int.rs":"1f61a472288afe489d9320bc8b13920333ece57891ae8570b4c4f25ab50688e6","src/ir/item.rs":"03477f4f4abfebc92ce4c9a202e33c86615dfffe3e6d1e0a201d2e85eecb9917","src/ir/item_kind.rs":"dbeae8c4fd0e5c9485d325aea040e056a1f2cd6d43fc927dee8fe1c0c59a7197","src/ir/layout.rs":"e3d1adf1ad2fa5bd96530cdd5097db3d9cc7b44d33ec23a04fcfccecd9cf4469","src/ir/mod.rs":"2eae90f207fad2e45957ec9287064992a419e3fc916aba84faff2ea25cbeb5ee","src/ir/module.rs":"c4d90bf38fe3672e01923734ccbdb7951ea929949d5f413a9c2aee12395a5094","src/ir/objc.rs":"05068c4fbf42429c4ac2a233c874f18ffcf7dc1744398e400a5a48d0e7a972f2","src/ir/template.rs":"bcd750450a4df0200a6e7958f9c96a09b91e3ccd29c60712f2b9d3458f1234aa","src/ir/traversal.rs":"da73d3fafa594fb12c13136f5c9d6e6ee0d6c7fa4b6e57863638d4ba5ef55dfa","src/ir/ty.rs":"7d16711a053f1b4e9d11d3c5665062a58278a869b196a24b7b2a62227eb3a38f","src/ir/var.rs":"57c8aa9f834c6f06418f7d471b1771bbb915821ef0d194b383be60092edca5f7","src/lib.rs":"99ed57a26e794ce724e434af0bf4f72b199bd0e1c42833324beb939acda9af33","src/log_stubs.rs":"6dfdd908b7c6453da416cf232893768f9480e551ca4add0858ef88bf71ee6ceb","src/main.rs":"e519053bcdde6bc88f60f955246a02d53b3db1cc5ccd1612e6675b790b7460b0","src/options.rs":"3df0214f428c221604420f8eb511b1c1e6d9326d1c6d3d2dea48278f833f9b77","src/parse.rs":"be7d13cc84fae79ec7b3aa9e77063fa475a48d74a854423e2c72d75006a25202","src/regex_set.rs":"a55241f2117f15729d174790f386e255fcb224b692325bbe6716dbb1d6874881","src/time.rs":"a02befb48d10dcc31e3f9571b2fa1c40f97fafe6f6ae7d7fc4f8fd01f1a169ba"},"package":"603ed8d8392ace9581e834e26bd09799bf1e989a79bd1aedbb893e72962bdc6e"}
|
||||
{"files":{"Cargo.toml":"3080fa2631c58e35cb1b32642139d8c303a609f8b554bfe69cd659a5374f18b9","LICENSE":"1d2e4bdb9d94ab020e9550136cae9ec73fc699c3c96a9d98078c542e9b93d294","README.md":"630d1a1d123c131bad0fec23173e263ba8ecc064b5cd8446d4cab7ffd197db45","build.rs":"032a1c51963894a421b0535f9227796d88768ac5f665a81d2edced69dc6d106a","src/callbacks.rs":"9d41b7848cea37e8741fa7bc947ba58a83647824b1a0bbe7ff75012c412eab13","src/clang.rs":"5ce27d0772e66f9f2f94a55afd18c98d4a57aed4c1d57da53b025fbbbb81a287","src/codegen/bitfield_unit.rs":"88b0604322dc449fc9284850eadc1f5d14b42fa747d4258bae0b6b9535f52dfd","src/codegen/bitfield_unit_tests.rs":"2073ac6a36e0bc9afaef5b1207966817c8fb7a1a9f6368c3b1b8f79822efbfba","src/codegen/error.rs":"2613af1d833377fd4a70719f4a09951d9d45dc9227827b9a2a938a1bcaaea2dd","src/codegen/helpers.rs":"8badd4b5ba38b83477c3ee3fc6f9ca79059b5650f5b489b2723c335037e27d92","src/codegen/impl_debug.rs":"e2ffd5b6ed936698aa4b9e7e3459d353383792707ad51f829a18a822f69cab0e","src/codegen/impl_partialeq.rs":"d69e2a9cdf2fdea74a60532109c0a1a75791f5a5ef931b28c5d447fa2915e5d3","src/codegen/mod.rs":"c923594d8d27dede9192dd1081acdedf97d67430f780e3dc4db39b8928a55d71","src/codegen/struct_layout.rs":"9bd0e3455e55e2a1faa4f332a327c2529a21bdfdd0fcb3a45bc5cdd7801d288f","src/extra_assertions.rs":"449549c4a7a50c3f0b06332452b2fb6c9b23f31ca8e5e1656fe6c7f21e8ef7fa","src/features.rs":"a437e6f736c8fba81ff74d90e7ddd142192ae5ffb9240d8c885eb84be6f2fe45","src/ir/analysis/derive_copy.rs":"59c21e299af3a36c6c82d4d16454700238269abd5929ec2d67c8414aebf82c3b","src/ir/analysis/derive_debug.rs":"3530e27ab0e260ec013cee3ad78a81497970c656a8eed589b755cce8caf53040","src/ir/analysis/derive_default.rs":"20e9dac151fadc59a7926ed9276ee8ced47e59c3f0c43f69fdafb75706045aca","src/ir/analysis/derive_hash.rs":"85c73c5660dc311ab6c15a21b69c4c5d2aa380d740decaf59ad594a6728cbe1f","src/ir/analysis/derive_partialeq_or_partialord.rs":"fb9540c324fdfcc9b0ae816e7713af000b11f5e2768c512c22a3082f263bb6bc","src/ir/analysis/has_destructor.rs":"d9aaaceba580b48eb0df4e5537b34b417c51ccdfeb8f6b72484f3bf4992317fe","src/ir/analysis/has_float.rs":"2a0465503d2c8247eaf916bd6a03594f3dc0370533d9a7c58cc5afb86693816c","src/ir/analysis/has_type_param_in_array.rs":"fcb1c78b6000f1f5eb8d8147e2afdaba9eb0e3a81b61e72537048dfdbeea7bcd","src/ir/analysis/has_vtable.rs":"37765e954ef792e369a58ccfe1d827a00fe9bce680466da1d6523671b94b6c92","src/ir/analysis/mod.rs":"ea5ace45c77e855674bb565ba0fef556f60e3293b0ddcf11d3a5a6ec15ab0648","src/ir/analysis/sizedness.rs":"3d3c8bde40604d53bb64273a3cbd8c55936a7dfe1de9b2ba92fc2c45572624b4","src/ir/analysis/template_params.rs":"6554dd1240142ec0e7299e678b696725f5cba99243d1c3d1cbf58d4764082fd6","src/ir/annotations.rs":"ef106afcbe6084c18bd13a37ee3c1cdc9596bfb055db8c773d81f8f15fec3208","src/ir/comment.rs":"000481754e5433d7c0886b9ce8b93b64c7ab1ae52867d211c73c7c4b336649a2","src/ir/comp.rs":"7b22f3ff19ca45a6fbfe7ea015109d43f4ddf65b33b47b1c37829fcb87cdff9b","src/ir/context.rs":"80679859b4efa52d74b0c7501bb5951b58c9705a97b96c9fc05134d1abe401c6","src/ir/derive.rs":"9550d01731ca66be28124c91fd0211a618743a065bec7b00e27c934afff82a84","src/ir/dot.rs":"d01f1621ab67e368d854a82bd6bb0b8dd52f3c2c733de8eaf81aece9543818cb","src/ir/enum_ty.rs":"3611100df8ddf01b010d2eae1d26a67df022e47b6236b0ed9d1b9b42340ebafd","src/ir/function.rs":"b86e665c6659c32bce39194240e7da6221c5a2ec51b362ad9f6e34f1bc396a6f","src/ir/int.rs":"1f61a472288afe489d9320bc8b13920333ece57891ae8570b4c4f25ab50688e6","src/ir/item.rs":"6f0d13615c6883b5e64c75f6d18d79b978b47aa3599ae1f4c196903d2d2cda68","src/ir/item_kind.rs":"dbeae8c4fd0e5c9485d325aea040e056a1f2cd6d43fc927dee8fe1c0c59a7197","src/ir/layout.rs":"17daab0a80564006de1f6b6190e7d9e6c5eb96990242fe707f8dc676f7110c18","src/ir/mod.rs":"2eae90f207fad2e45957ec9287064992a419e3fc916aba84faff2ea25cbeb5ee","src/ir/module.rs":"c4d90bf38fe3672e01923734ccbdb7951ea929949d5f413a9c2aee12395a5094","src/ir/objc.rs":"828a890acdc8b10c44e69e2ed4a4f5d8c0e734606d3a8cc71658dcf43a49acf4","src/ir/template.rs":"21ba4cbacafce39b4a8013bc97e8054a906a8bc2f45a51aeef3b007caadde221","src/ir/traversal.rs":"eaca9aa6deb3eea9b8d7adc696781c70038796ff43e536bda47e90f84fe87d61","src/ir/ty.rs":"daa95f757288e4bfe84f9724c5f5df127b6f3a4452330691a24a94369db7d993","src/ir/var.rs":"57c8aa9f834c6f06418f7d471b1771bbb915821ef0d194b383be60092edca5f7","src/lib.rs":"d4217ac878659794c5990b1612f1de12f94f975257ea14307fb7dc63ac3a76da","src/log_stubs.rs":"6dfdd908b7c6453da416cf232893768f9480e551ca4add0858ef88bf71ee6ceb","src/main.rs":"e519053bcdde6bc88f60f955246a02d53b3db1cc5ccd1612e6675b790b7460b0","src/options.rs":"f1be872e418a96582b048c095ceeeba012b92ffed8a9658cd1fd9ae0e192372d","src/parse.rs":"be7d13cc84fae79ec7b3aa9e77063fa475a48d74a854423e2c72d75006a25202","src/regex_set.rs":"a55241f2117f15729d174790f386e255fcb224b692325bbe6716dbb1d6874881","src/time.rs":"3b763e6fee51d0eb01228dfe28bc28a9f692aff73b2a7b90a030902e0238fca6"},"package":"1b25ab82877ea8fe6ce1ce1f8ac54361f0218bad900af9eb11803994bf67c221"}
|
|
@ -12,11 +12,12 @@
|
|||
|
||||
[package]
|
||||
name = "bindgen"
|
||||
version = "0.33.2"
|
||||
version = "0.37.4"
|
||||
authors = ["Jyun-Yan You <jyyou.tw@gmail.com>", "Emilio Cobos Álvarez <emilio@crisal.io>", "Nick Fitzgerald <fitzgen@gmail.com>", "The Servo project developers"]
|
||||
build = "build.rs"
|
||||
include = ["Cargo.toml", "build.rs", "src/*.rs", "src/**/*.rs"]
|
||||
include = ["LICENSE", "README.md", "Cargo.toml", "build.rs", "src/*.rs", "src/**/*.rs"]
|
||||
description = "Automatically generates Rust FFI bindings to C and C++ libraries."
|
||||
homepage = "https://rust-lang-nursery.github.io/rust-bindgen/"
|
||||
documentation = "https://docs.rs/bindgen"
|
||||
readme = "README.md"
|
||||
keywords = ["bindings", "ffi", "code-generation"]
|
||||
|
@ -38,8 +39,8 @@ version = "0.2"
|
|||
version = "0.1.0"
|
||||
|
||||
[dependencies.clang-sys]
|
||||
version = "0.22.0"
|
||||
features = ["runtime", "clang_3_9"]
|
||||
version = "0.23"
|
||||
features = ["runtime", "clang_6_0"]
|
||||
|
||||
[dependencies.clap]
|
||||
version = "2"
|
||||
|
@ -58,11 +59,16 @@ optional = true
|
|||
[dependencies.peeking_take_while]
|
||||
version = "0.1.2"
|
||||
|
||||
[dependencies.proc-macro2]
|
||||
version = "0.3.2, < 0.3.6"
|
||||
default-features = false
|
||||
|
||||
[dependencies.quote]
|
||||
version = "0.3.15"
|
||||
version = "0.5"
|
||||
default-features = false
|
||||
|
||||
[dependencies.regex]
|
||||
version = "0.2"
|
||||
version = "1.0"
|
||||
|
||||
[dependencies.which]
|
||||
version = "1.0.2"
|
||||
|
@ -84,5 +90,6 @@ testing_only_extra_assertions = []
|
|||
testing_only_libclang_3_8 = []
|
||||
testing_only_libclang_3_9 = []
|
||||
testing_only_libclang_4 = []
|
||||
testing_only_libclang_5 = []
|
||||
[badges.travis-ci]
|
||||
repository = "rust-lang-nursery/rust-bindgen"
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
Copyright (c) 2013, Jyun-Yan You
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the author nor the names of his contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
|
@ -0,0 +1,45 @@
|
|||
# `bindgen`
|
||||
|
||||
[`impl period`](https://blog.rust-lang.org/2017/09/18/impl-future-for-rust.html) has been started! Join us at [Gitter.im](https://gitter.im/rust-impl-period/WG-dev-tools-bindgen).
|
||||
|
||||
**`bindgen` automatically generates Rust FFI bindings to C (and some C++) libraries.**
|
||||
|
||||
For example, given the C header `doggo.h`:
|
||||
|
||||
```c
|
||||
typedef struct Doggo {
|
||||
int many;
|
||||
char wow;
|
||||
} Doggo;
|
||||
|
||||
void eleven_out_of_ten_majestic_af(Doggo* pupper);
|
||||
```
|
||||
|
||||
`bindgen` produces Rust FFI code allowing you to call into the `doggo` library's
|
||||
functions and use its types:
|
||||
|
||||
```rust
|
||||
/* automatically generated by rust-bindgen */
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Doggo {
|
||||
pub many: ::std::os::raw::c_int,
|
||||
pub wow: ::std::os::raw::c_char,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn eleven_out_of_ten_majestic_af(pupper: *mut Doggo);
|
||||
}
|
||||
```
|
||||
|
||||
## Users Guide
|
||||
|
||||
[📚 Read the `bindgen` users guide here! 📚](https://rust-lang-nursery.github.io/rust-bindgen)
|
||||
|
||||
## API Reference
|
||||
|
||||
[API reference documentation is on docs.rs](https://docs.rs/bindgen)
|
||||
|
||||
## Contributing
|
||||
|
||||
[See `CONTRIBUTING.md` for hacking on `bindgen`!](./CONTRIBUTING.md)
|
|
@ -35,7 +35,7 @@ pub trait ParseCallbacks: fmt::Debug + UnwindSafe {
|
|||
None
|
||||
}
|
||||
|
||||
/// This function should return whether, given the a given enum variant
|
||||
/// This function should return whether, given an enum variant
|
||||
/// name, and value, this enum variant will forcibly be a constant.
|
||||
fn enum_variant_behavior(
|
||||
&self,
|
||||
|
|
|
@ -911,6 +911,13 @@ impl Type {
|
|||
/// Get the number of template arguments this type has, or `None` if it is
|
||||
/// not some kind of template.
|
||||
pub fn num_template_args(&self) -> Option<u32> {
|
||||
// If an old libclang is loaded, we have no hope of answering this
|
||||
// question correctly. However, that's no reason to panic when
|
||||
// generating bindings for simple C headers with an old libclang.
|
||||
if !clang_Type_getNumTemplateArguments::is_loaded() {
|
||||
return None
|
||||
}
|
||||
|
||||
let n = unsafe { clang_Type_getNumTemplateArguments(self.x) };
|
||||
if n >= 0 {
|
||||
Some(n as u32)
|
||||
|
@ -975,7 +982,7 @@ impl Type {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the canonical version of this type. This sees through `typdef`s and
|
||||
/// Get the canonical version of this type. This sees through `typedef`s and
|
||||
/// aliases to get the underlying, canonical type.
|
||||
pub fn canonical_type(&self) -> Type {
|
||||
unsafe {
|
||||
|
@ -1639,8 +1646,11 @@ pub fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult {
|
|||
depth,
|
||||
format!(" {}spelling = \"{}\"", prefix, ty.spelling()),
|
||||
);
|
||||
let num_template_args =
|
||||
unsafe { clang_Type_getNumTemplateArguments(ty.x) };
|
||||
let num_template_args = if clang_Type_getNumTemplateArguments::is_loaded() {
|
||||
unsafe { clang_Type_getNumTemplateArguments(ty.x) }
|
||||
} else {
|
||||
-1
|
||||
};
|
||||
if num_template_args >= 0 {
|
||||
print_indent(
|
||||
depth,
|
||||
|
@ -1812,3 +1822,35 @@ impl Drop for EvalResult {
|
|||
unsafe { clang_EvalResult_dispose(self.x) };
|
||||
}
|
||||
}
|
||||
|
||||
/// Target information obtained from libclang.
|
||||
#[derive(Debug)]
|
||||
pub struct TargetInfo {
|
||||
/// The target triple.
|
||||
pub triple: String,
|
||||
/// The width of the pointer _in bits_.
|
||||
pub pointer_width: usize,
|
||||
}
|
||||
|
||||
impl TargetInfo {
|
||||
/// Tries to obtain target information from libclang.
|
||||
pub fn new(tu: &TranslationUnit) -> Option<Self> {
|
||||
if !clang_getTranslationUnitTargetInfo::is_loaded() {
|
||||
return None;
|
||||
}
|
||||
let triple;
|
||||
let pointer_width;
|
||||
unsafe {
|
||||
let ti = clang_getTranslationUnitTargetInfo(tu.x);
|
||||
triple = cxstring_into_string(clang_TargetInfo_getTriple(ti));
|
||||
pointer_width = clang_TargetInfo_getPointerWidth(ti);
|
||||
clang_TargetInfo_dispose(ti);
|
||||
}
|
||||
assert!(pointer_width > 0);
|
||||
assert_eq!(pointer_width % 8, 0);
|
||||
Some(TargetInfo {
|
||||
triple,
|
||||
pointer_width: pointer_width as usize,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,13 @@ where
|
|||
let byte_index = index / 8;
|
||||
let byte = self.storage.as_ref()[byte_index];
|
||||
|
||||
let bit_index = index % 8;
|
||||
let bit_index =
|
||||
if cfg!(target_endian = "big") {
|
||||
7 - (index % 8)
|
||||
} else {
|
||||
index % 8
|
||||
};
|
||||
|
||||
let mask = 1 << bit_index;
|
||||
|
||||
byte & mask == mask
|
||||
|
@ -40,9 +46,14 @@ where
|
|||
let byte_index = index / 8;
|
||||
let byte = &mut self.storage.as_mut()[byte_index];
|
||||
|
||||
let bit_index = index % 8;
|
||||
let mask = 1 << bit_index;
|
||||
let bit_index =
|
||||
if cfg!(target_endian = "big") {
|
||||
7 - (index % 8)
|
||||
} else {
|
||||
index % 8
|
||||
};
|
||||
|
||||
let mask = 1 << bit_index;
|
||||
if val {
|
||||
*byte |= mask;
|
||||
} else {
|
||||
|
@ -60,7 +71,13 @@ where
|
|||
|
||||
for i in 0..(bit_width as usize) {
|
||||
if self.get_bit(i + bit_offset) {
|
||||
val |= 1 << i;
|
||||
let index =
|
||||
if cfg!(target_endian = "big") {
|
||||
bit_width as usize - 1 - i
|
||||
} else {
|
||||
i
|
||||
};
|
||||
val |= 1 << index;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,7 +93,13 @@ where
|
|||
for i in 0..(bit_width as usize) {
|
||||
let mask = 1 << i;
|
||||
let val_bit_is_set = val & mask == mask;
|
||||
self.set_bit(i + bit_offset, val_bit_is_set);
|
||||
let index =
|
||||
if cfg!(target_endian = "big") {
|
||||
bit_width as usize - 1 - i
|
||||
} else {
|
||||
i
|
||||
};
|
||||
self.set_bit(index + bit_offset, val_bit_is_set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,26 +4,28 @@ use ir::context::BindgenContext;
|
|||
use ir::layout::Layout;
|
||||
use quote;
|
||||
use std::mem;
|
||||
use proc_macro2::{Term, Span};
|
||||
|
||||
pub mod attributes {
|
||||
use quote;
|
||||
use proc_macro2::{Term, Span};
|
||||
|
||||
pub fn repr(which: &str) -> quote::Tokens {
|
||||
let which = quote::Ident::new(which);
|
||||
let which = Term::new(which, Span::call_site());
|
||||
quote! {
|
||||
#[repr( #which )]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn repr_list(which_ones: &[&str]) -> quote::Tokens {
|
||||
let which_ones = which_ones.iter().cloned().map(quote::Ident::new);
|
||||
let which_ones = which_ones.iter().cloned().map(|one| Term::new(one, Span::call_site()));
|
||||
quote! {
|
||||
#[repr( #( #which_ones ),* )]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn derives(which_ones: &[&str]) -> quote::Tokens {
|
||||
let which_ones = which_ones.iter().cloned().map(quote::Ident::new);
|
||||
let which_ones = which_ones.iter().cloned().map(|one| Term::new(one, Span::call_site()));
|
||||
quote! {
|
||||
#[derive( #( #which_ones ),* )]
|
||||
}
|
||||
|
@ -40,9 +42,9 @@ pub mod attributes {
|
|||
// time they get here. Just make sure that we have newlines around it so
|
||||
// that nothing else gets wrapped into the comment.
|
||||
let mut tokens = quote! {};
|
||||
tokens.append("\n");
|
||||
tokens.append(comment);
|
||||
tokens.append("\n");
|
||||
tokens.append(Term::new("\n", Span::call_site()));
|
||||
tokens.append(Term::new(&comment, Span::call_site()));
|
||||
tokens.append(Term::new("\n", Span::call_site()));
|
||||
tokens
|
||||
}
|
||||
|
||||
|
@ -73,7 +75,7 @@ pub fn blob(layout: Layout) -> quote::Tokens {
|
|||
}
|
||||
};
|
||||
|
||||
let ty_name = quote::Ident::new(ty_name);
|
||||
let ty_name = Term::new(ty_name, Span::call_site());
|
||||
|
||||
let data_len = opaque.array_size().unwrap_or(layout.size);
|
||||
|
||||
|
@ -103,7 +105,7 @@ pub fn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> quote::Tokens {
|
|||
let mut tokens = quote! {};
|
||||
|
||||
if ctx.options().enable_cxx_namespaces {
|
||||
tokens.append(quote! { root:: });
|
||||
tokens.append_all(quote! { root:: });
|
||||
}
|
||||
|
||||
let align = match layout.align {
|
||||
|
@ -114,7 +116,7 @@ pub fn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> quote::Tokens {
|
|||
};
|
||||
|
||||
let size = layout.size;
|
||||
tokens.append(quote! {
|
||||
tokens.append_all(quote! {
|
||||
__BindgenBitfieldUnit<[u8; #size], #align>
|
||||
});
|
||||
|
||||
|
@ -126,6 +128,7 @@ pub mod ast_ty {
|
|||
use ir::function::FunctionSig;
|
||||
use ir::ty::FloatKind;
|
||||
use quote;
|
||||
use proc_macro2;
|
||||
|
||||
pub fn raw_type(ctx: &BindgenContext, name: &str) -> quote::Tokens {
|
||||
let ident = ctx.rust_ident_raw(name);
|
||||
|
@ -166,29 +169,25 @@ pub mod ast_ty {
|
|||
|
||||
pub fn int_expr(val: i64) -> quote::Tokens {
|
||||
// Don't use quote! { #val } because that adds the type suffix.
|
||||
let mut tokens = quote! {};
|
||||
tokens.append(val.to_string());
|
||||
tokens
|
||||
let val = proc_macro2::Literal::i64_unsuffixed(val);
|
||||
quote!(#val)
|
||||
}
|
||||
|
||||
pub fn uint_expr(val: u64) -> quote::Tokens {
|
||||
// Don't use quote! { #val } because that adds the type suffix.
|
||||
let mut tokens = quote! {};
|
||||
tokens.append(val.to_string());
|
||||
tokens
|
||||
let val = proc_macro2::Literal::u64_unsuffixed(val);
|
||||
quote!(#val)
|
||||
}
|
||||
|
||||
pub fn byte_array_expr(bytes: &[u8]) -> quote::Tokens {
|
||||
let mut bytes: Vec<_> = bytes.iter().cloned().collect();
|
||||
bytes.push(0);
|
||||
quote! {
|
||||
#bytes
|
||||
}
|
||||
quote! { [ #(#bytes),* ] }
|
||||
}
|
||||
|
||||
pub fn cstr_expr(mut string: String) -> quote::Tokens {
|
||||
string.push('\0');
|
||||
let b = quote::ByteStr(&string);
|
||||
let b = proc_macro2::Literal::byte_string(&string.as_bytes());
|
||||
quote! {
|
||||
#b
|
||||
}
|
||||
|
@ -199,16 +198,9 @@ pub mod ast_ty {
|
|||
f: f64,
|
||||
) -> Result<quote::Tokens, ()> {
|
||||
if f.is_finite() {
|
||||
let mut string = f.to_string();
|
||||
let val = proc_macro2::Literal::f64_unsuffixed(f);
|
||||
|
||||
// So it gets properly recognised as a floating point constant.
|
||||
if !string.contains('.') {
|
||||
string.push('.');
|
||||
}
|
||||
|
||||
let mut tokens = quote! {};
|
||||
tokens.append(string);
|
||||
return Ok(tokens);
|
||||
return Ok(quote!(#val));
|
||||
}
|
||||
|
||||
let prefix = ctx.trait_prefix();
|
||||
|
|
|
@ -4,6 +4,7 @@ use ir::context::BindgenContext;
|
|||
use ir::item::{IsOpaque, Item};
|
||||
use ir::ty::{TypeKind, RUST_DERIVE_IN_ARRAY_LIMIT};
|
||||
use quote;
|
||||
use proc_macro2;
|
||||
|
||||
/// Generate a manual implementation of `PartialEq` trait for the
|
||||
/// specified compound type.
|
||||
|
@ -20,7 +21,7 @@ pub fn gen_partialeq_impl(
|
|||
&self._bindgen_opaque_blob[..] == &other._bindgen_opaque_blob[..]
|
||||
});
|
||||
} else if comp_info.kind() == CompKind::Union {
|
||||
assert!(!ctx.options().rust_features().untagged_union());
|
||||
assert!(!ctx.options().rust_features().untagged_union);
|
||||
tokens.push(quote! {
|
||||
&self.bindgen_union_field[..] == &other.bindgen_union_field[..]
|
||||
});
|
||||
|
@ -71,7 +72,7 @@ pub fn gen_partialeq_impl(
|
|||
}
|
||||
|
||||
fn gen_field(ctx: &BindgenContext, ty_item: &Item, name: &str) -> quote::Tokens {
|
||||
fn quote_equals(name_ident: quote::Ident) -> quote::Tokens {
|
||||
fn quote_equals(name_ident: proc_macro2::Term) -> quote::Tokens {
|
||||
quote! { self.#name_ident == other.#name_ident }
|
||||
}
|
||||
|
||||
|
|
|
@ -38,14 +38,15 @@ use ir::ty::{Type, TypeKind};
|
|||
use ir::var::Var;
|
||||
|
||||
use quote;
|
||||
use proc_macro2::{self, Term, Span};
|
||||
|
||||
use std;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::Cell;
|
||||
use std::collections::{HashSet, VecDeque};
|
||||
use std::collections::hash_map::{Entry, HashMap};
|
||||
use std::fmt::Write;
|
||||
use std::iter;
|
||||
use std::mem;
|
||||
use std::ops;
|
||||
|
||||
// Name of type defined in constified enum module
|
||||
|
@ -75,7 +76,7 @@ fn root_import(ctx: &BindgenContext, module: &Item) -> quote::Tokens {
|
|||
|
||||
|
||||
let mut tokens = quote! {};
|
||||
tokens.append_separated(path, "::");
|
||||
tokens.append_separated(path, Term::new("::", Span::call_site()));
|
||||
|
||||
quote! {
|
||||
#[allow(unused_imports)]
|
||||
|
@ -299,17 +300,12 @@ impl AppendImplicitTemplateParams for quote::Tokens {
|
|||
_ => {},
|
||||
}
|
||||
|
||||
if let Some(params) = item.used_template_params(ctx) {
|
||||
if params.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let params = params.into_iter().map(|p| {
|
||||
p.try_to_rust_ty(ctx, &())
|
||||
.expect("template params cannot fail to be a rust type")
|
||||
});
|
||||
|
||||
self.append(quote! {
|
||||
let params: Vec<_> = item.used_template_params(ctx).iter().map(|p| {
|
||||
p.try_to_rust_ty(ctx, &())
|
||||
.expect("template params cannot fail to be a rust type")
|
||||
}).collect();
|
||||
if !params.is_empty() {
|
||||
self.append_all(quote! {
|
||||
< #( #params ),* >
|
||||
});
|
||||
}
|
||||
|
@ -404,7 +400,7 @@ impl CodeGenerator for Module {
|
|||
if result.saw_incomplete_array {
|
||||
utils::prepend_incomplete_array_types(ctx, &mut *result);
|
||||
}
|
||||
if ctx.need_bindegen_complex_type() {
|
||||
if ctx.need_bindgen_complex_type() {
|
||||
utils::prepend_complex_type(&mut *result);
|
||||
}
|
||||
if result.saw_objc {
|
||||
|
@ -427,6 +423,18 @@ impl CodeGenerator for Module {
|
|||
let mut found_any = false;
|
||||
let inner_items = result.inner(|result| {
|
||||
result.push(root_import(ctx, item));
|
||||
|
||||
let path = item.namespace_aware_canonical_path(ctx).join("::");
|
||||
if let Some(raw_lines) = ctx.options().module_lines.get(&path) {
|
||||
for raw_line in raw_lines {
|
||||
found_any = true;
|
||||
// FIXME(emilio): The use of `Term` is an abuse, but we abuse it
|
||||
// in a bunch more places.
|
||||
let line = Term::new(raw_line, Span::call_site());
|
||||
result.push(quote! { #line });
|
||||
}
|
||||
}
|
||||
|
||||
codegen_self(result, &mut found_any);
|
||||
});
|
||||
|
||||
|
@ -436,16 +444,15 @@ impl CodeGenerator for Module {
|
|||
}
|
||||
|
||||
let name = item.canonical_name(ctx);
|
||||
|
||||
result.push(if name == "root" {
|
||||
let ident = ctx.rust_ident(name);
|
||||
result.push(if item.id() == ctx.root_module() {
|
||||
quote! {
|
||||
#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
|
||||
pub mod root {
|
||||
pub mod #ident {
|
||||
#( #inner_items )*
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let ident = ctx.rust_ident(name);
|
||||
quote! {
|
||||
pub mod #ident {
|
||||
#( #inner_items )*
|
||||
|
@ -479,11 +486,8 @@ impl CodeGenerator for Var {
|
|||
// We can't generate bindings to static variables of templates. The
|
||||
// number of actual variables for a single declaration are open ended
|
||||
// and we don't know what instantiations do or don't exist.
|
||||
let type_params = item.all_template_params(ctx);
|
||||
if let Some(params) = type_params {
|
||||
if !params.is_empty() {
|
||||
return;
|
||||
}
|
||||
if !item.all_template_params(ctx).is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let ty = self.ty().to_rust_ty_or_opaque(ctx, &());
|
||||
|
@ -636,15 +640,10 @@ impl CodeGenerator for Type {
|
|||
return;
|
||||
}
|
||||
|
||||
let mut outer_params = item.used_template_params(ctx)
|
||||
.and_then(|ps| if ps.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(ps)
|
||||
});
|
||||
let mut outer_params = item.used_template_params(ctx);
|
||||
|
||||
let inner_rust_type = if item.is_opaque(ctx, &()) {
|
||||
outer_params = None;
|
||||
outer_params = vec![];
|
||||
self.to_opaque(ctx, item)
|
||||
} else {
|
||||
// Its possible that we have better layout information than
|
||||
|
@ -691,7 +690,7 @@ impl CodeGenerator for Type {
|
|||
|
||||
// We prefer using `pub use` over `pub type` because of:
|
||||
// https://github.com/rust-lang/rust/issues/26264
|
||||
if inner_rust_type.as_str()
|
||||
if inner_rust_type.to_string()
|
||||
.chars()
|
||||
.all(|c| match c {
|
||||
// These are the only characters allowed in simple
|
||||
|
@ -699,50 +698,48 @@ impl CodeGenerator for Type {
|
|||
'A'...'Z' | 'a'...'z' | '0'...'9' | ':' | '_' | ' ' => true,
|
||||
_ => false,
|
||||
}) &&
|
||||
outer_params.is_none() &&
|
||||
outer_params.is_empty() &&
|
||||
inner_item.expect_type().canonical_type(ctx).is_enum()
|
||||
{
|
||||
tokens.append(quote! {
|
||||
tokens.append_all(quote! {
|
||||
pub use
|
||||
});
|
||||
let path = top_level_path(ctx, item);
|
||||
tokens.append_separated(path, "::");
|
||||
tokens.append(quote! {
|
||||
tokens.append_separated(path, Term::new("::", Span::call_site()));
|
||||
tokens.append_all(quote! {
|
||||
:: #inner_rust_type as #rust_name ;
|
||||
});
|
||||
result.push(tokens);
|
||||
return;
|
||||
}
|
||||
|
||||
tokens.append(quote! {
|
||||
tokens.append_all(quote! {
|
||||
pub type #rust_name
|
||||
});
|
||||
|
||||
if let Some(params) = outer_params {
|
||||
let params: Vec<_> = params.into_iter()
|
||||
.filter_map(|p| p.as_template_param(ctx, &()))
|
||||
.collect();
|
||||
if params.iter().any(|p| ctx.resolve_type(*p).is_invalid_type_param()) {
|
||||
warn!(
|
||||
"Item contained invalid template \
|
||||
parameter: {:?}",
|
||||
item
|
||||
);
|
||||
return;
|
||||
}
|
||||
let params: Vec<_> = outer_params.into_iter()
|
||||
.filter_map(|p| p.as_template_param(ctx, &()))
|
||||
.collect();
|
||||
if params.iter().any(|p| ctx.resolve_type(*p).is_invalid_type_param()) {
|
||||
warn!(
|
||||
"Item contained invalid template \
|
||||
parameter: {:?}",
|
||||
item
|
||||
);
|
||||
return;
|
||||
}
|
||||
let params: Vec<_> = params.iter().map(|p| {
|
||||
p.try_to_rust_ty(ctx, &())
|
||||
.expect("type parameters can always convert to rust ty OK")
|
||||
}).collect();
|
||||
|
||||
let params = params.iter()
|
||||
.map(|p| {
|
||||
p.try_to_rust_ty(ctx, &())
|
||||
.expect("type parameters can always convert to rust ty OK")
|
||||
});
|
||||
|
||||
tokens.append(quote! {
|
||||
if !params.is_empty() {
|
||||
tokens.append_all(quote! {
|
||||
< #( #params ),* >
|
||||
});
|
||||
}
|
||||
|
||||
tokens.append(quote! {
|
||||
tokens.append_all(quote! {
|
||||
= #inner_rust_type ;
|
||||
});
|
||||
|
||||
|
@ -1059,11 +1056,11 @@ impl<'a> FieldCodegen<'a> for FieldData {
|
|||
self.annotations().accessor_kind().unwrap_or(accessor_kind);
|
||||
|
||||
if is_private {
|
||||
field.append(quote! {
|
||||
field.append_all(quote! {
|
||||
#field_ident : #ty ,
|
||||
});
|
||||
} else {
|
||||
field.append(quote! {
|
||||
field.append_all(quote! {
|
||||
pub #field_ident : #ty ,
|
||||
});
|
||||
}
|
||||
|
@ -1123,7 +1120,7 @@ impl<'a> FieldCodegen<'a> for FieldData {
|
|||
impl BitfieldUnit {
|
||||
/// Get the constructor name for this bitfield unit.
|
||||
fn ctor_name(&self) -> quote::Tokens {
|
||||
let ctor_name = quote::Ident::new(format!("new_bitfield_{}", self.nth()));
|
||||
let ctor_name = Term::new(&format!("new_bitfield_{}", self.nth()), Span::call_site());
|
||||
quote! {
|
||||
#ctor_name
|
||||
}
|
||||
|
@ -1154,7 +1151,7 @@ impl Bitfield {
|
|||
let width = self.width() as u8;
|
||||
let prefix = ctx.trait_prefix();
|
||||
|
||||
ctor_impl.append(quote! {
|
||||
ctor_impl.append_all(quote! {
|
||||
__bindgen_bitfield_unit.set(
|
||||
#offset,
|
||||
#width,
|
||||
|
@ -1322,7 +1319,7 @@ impl<'a> FieldCodegen<'a> for Bitfield {
|
|||
let prefix = ctx.trait_prefix();
|
||||
let getter_name = bitfield_getter_name(ctx, self);
|
||||
let setter_name = bitfield_setter_name(ctx, self);
|
||||
let unit_field_ident = quote::Ident::new(unit_field_name);
|
||||
let unit_field_ident = Term::new(unit_field_name, Span::call_site());
|
||||
|
||||
let bitfield_ty_item = ctx.resolve_item(self.ty());
|
||||
let bitfield_ty = bitfield_ty_item.expect_type();
|
||||
|
@ -1418,8 +1415,6 @@ impl CodeGenerator for CompInfo {
|
|||
return;
|
||||
}
|
||||
|
||||
let used_template_params = item.used_template_params(ctx);
|
||||
|
||||
let ty = item.expect_type();
|
||||
let layout = ty.layout(ctx);
|
||||
let mut packed = self.is_packed(ctx, &layout);
|
||||
|
@ -1527,6 +1522,7 @@ impl CodeGenerator for CompInfo {
|
|||
});
|
||||
}
|
||||
|
||||
let mut explicit_align = None;
|
||||
if is_opaque {
|
||||
// Opaque item should not have generated methods, fields.
|
||||
debug_assert!(fields.is_empty());
|
||||
|
@ -1534,6 +1530,8 @@ impl CodeGenerator for CompInfo {
|
|||
|
||||
match layout {
|
||||
Some(l) => {
|
||||
explicit_align = Some(l.align);
|
||||
|
||||
let ty = helpers::blob(l);
|
||||
fields.push(quote! {
|
||||
pub _bindgen_opaque_blob: #ty ,
|
||||
|
@ -1555,6 +1553,7 @@ impl CodeGenerator for CompInfo {
|
|||
if layout.align == 1 {
|
||||
packed = true;
|
||||
} else {
|
||||
explicit_align = Some(layout.align);
|
||||
let ty = helpers::blob(Layout::new(0, layout.align));
|
||||
fields.push(quote! {
|
||||
pub __bindgen_align: #ty ,
|
||||
|
@ -1597,21 +1596,19 @@ impl CodeGenerator for CompInfo {
|
|||
|
||||
let mut generic_param_names = vec![];
|
||||
|
||||
if let Some(ref params) = used_template_params {
|
||||
for (idx, ty) in params.iter().enumerate() {
|
||||
let param = ctx.resolve_type(*ty);
|
||||
let name = param.name().unwrap();
|
||||
let ident = ctx.rust_ident(name);
|
||||
generic_param_names.push(ident.clone());
|
||||
for (idx, ty) in item.used_template_params(ctx).iter().enumerate() {
|
||||
let param = ctx.resolve_type(*ty);
|
||||
let name = param.name().unwrap();
|
||||
let ident = ctx.rust_ident(name);
|
||||
generic_param_names.push(ident.clone());
|
||||
|
||||
let prefix = ctx.trait_prefix();
|
||||
let field_name = ctx.rust_ident(format!("_phantom_{}", idx));
|
||||
fields.push(quote! {
|
||||
pub #field_name : ::#prefix::marker::PhantomData<
|
||||
::#prefix::cell::UnsafeCell<#ident>
|
||||
> ,
|
||||
});
|
||||
}
|
||||
let prefix = ctx.trait_prefix();
|
||||
let field_name = ctx.rust_ident(format!("_phantom_{}", idx));
|
||||
fields.push(quote! {
|
||||
pub #field_name : ::#prefix::marker::PhantomData<
|
||||
::#prefix::cell::UnsafeCell<#ident>
|
||||
> ,
|
||||
});
|
||||
}
|
||||
|
||||
let generics = if !generic_param_names.is_empty() {
|
||||
|
@ -1637,6 +1634,18 @@ impl CodeGenerator for CompInfo {
|
|||
attributes.push(attributes::repr("C"));
|
||||
}
|
||||
|
||||
if ctx.options().rust_features().repr_align {
|
||||
if let Some(explicit) = explicit_align {
|
||||
// Ensure that the struct has the correct alignment even in
|
||||
// presence of alignas.
|
||||
let explicit = helpers::ast_ty::int_expr(explicit as i64);
|
||||
attributes.push(quote! {
|
||||
#[repr(align(#explicit))]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let mut derives = vec![];
|
||||
if item.can_derive_debug(ctx) {
|
||||
derives.push("Debug");
|
||||
|
@ -1652,11 +1661,13 @@ impl CodeGenerator for CompInfo {
|
|||
ctx.options().derive_default && !self.is_forward_declaration();
|
||||
}
|
||||
|
||||
let all_template_params = item.all_template_params(ctx);
|
||||
|
||||
if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() {
|
||||
derives.push("Copy");
|
||||
|
||||
if ctx.options().rust_features().builtin_clone_impls() ||
|
||||
used_template_params.is_some()
|
||||
if ctx.options().rust_features().builtin_clone_impls ||
|
||||
!all_template_params.is_empty()
|
||||
{
|
||||
// FIXME: This requires extra logic if you have a big array in a
|
||||
// templated struct. The reason for this is that the magic:
|
||||
|
@ -1711,7 +1722,7 @@ impl CodeGenerator for CompInfo {
|
|||
}
|
||||
};
|
||||
|
||||
tokens.append(quote! {
|
||||
tokens.append_all(quote! {
|
||||
#generics {
|
||||
#( #fields )*
|
||||
}
|
||||
|
@ -1734,11 +1745,11 @@ impl CodeGenerator for CompInfo {
|
|||
if self.found_unknown_attr() {
|
||||
warn!(
|
||||
"Type {} has an unkown attribute that may affect layout",
|
||||
canonical_ident
|
||||
canonical_ident.as_str()
|
||||
);
|
||||
}
|
||||
|
||||
if used_template_params.is_none() {
|
||||
if all_template_params.is_empty() {
|
||||
if !is_opaque {
|
||||
for var in self.inner_vars() {
|
||||
ctx.resolve_item(*var).codegen(ctx, result, &());
|
||||
|
@ -1748,7 +1759,7 @@ impl CodeGenerator for CompInfo {
|
|||
if ctx.options().layout_tests && !self.is_forward_declaration() {
|
||||
if let Some(layout) = layout {
|
||||
let fn_name =
|
||||
format!("bindgen_test_layout_{}", canonical_ident);
|
||||
format!("bindgen_test_layout_{}", canonical_ident.as_str());
|
||||
let fn_name = ctx.rust_ident_raw(fn_name);
|
||||
let prefix = ctx.trait_prefix();
|
||||
let size_of_expr = quote! {
|
||||
|
@ -1761,8 +1772,9 @@ impl CodeGenerator for CompInfo {
|
|||
let align = layout.align;
|
||||
|
||||
let check_struct_align =
|
||||
if align > mem::size_of::<*mut ()>() {
|
||||
// FIXME when [RFC 1358](https://github.com/rust-lang/rust/issues/33626) ready
|
||||
if align > ctx.target_pointer_size() &&
|
||||
!ctx.options().rust_features().repr_align
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some(quote! {
|
||||
|
@ -1996,7 +2008,7 @@ impl MethodCodegen for Method {
|
|||
_ => panic!("How in the world?"),
|
||||
};
|
||||
|
||||
if let (Abi::ThisCall, false) = (signature.abi(), ctx.options().rust_features().thiscall_abi()) {
|
||||
if let (Abi::ThisCall, false) = (signature.abi(), ctx.options().rust_features().thiscall_abi) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2092,11 +2104,15 @@ impl MethodCodegen for Method {
|
|||
}
|
||||
|
||||
/// A helper type that represents different enum variations.
|
||||
#[derive(Copy, Clone)]
|
||||
enum EnumVariation {
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub enum EnumVariation {
|
||||
/// The code for this enum will use a Rust enum
|
||||
Rust,
|
||||
/// The code for this enum will use a bitfield
|
||||
Bitfield,
|
||||
/// The code for this enum will use consts
|
||||
Consts,
|
||||
/// The code for this enum will use a module containing consts
|
||||
ModuleConsts
|
||||
}
|
||||
|
||||
|
@ -2110,7 +2126,7 @@ impl EnumVariation {
|
|||
|
||||
fn is_bitfield(&self) -> bool {
|
||||
match *self {
|
||||
EnumVariation::Bitfield => true,
|
||||
EnumVariation::Bitfield {..} => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
@ -2125,12 +2141,37 @@ impl EnumVariation {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for EnumVariation {
|
||||
fn default() -> EnumVariation {
|
||||
EnumVariation::Consts
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for EnumVariation {
|
||||
type Err = std::io::Error;
|
||||
|
||||
/// Create a `EnumVariation` from a string.
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"rust" => Ok(EnumVariation::Rust),
|
||||
"bitfield" => Ok(EnumVariation::Bitfield),
|
||||
"consts" => Ok(EnumVariation::Consts),
|
||||
"moduleconsts" => Ok(EnumVariation::ModuleConsts),
|
||||
_ => Err(std::io::Error::new(std::io::ErrorKind::InvalidInput,
|
||||
concat!("Got an invalid EnumVariation. Accepted values ",
|
||||
"are 'rust', 'bitfield', 'consts', and ",
|
||||
"'moduleconsts'."))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A helper type to construct different enum variations.
|
||||
enum EnumBuilder<'a> {
|
||||
Rust {
|
||||
codegen_depth: usize,
|
||||
attrs: Vec<quote::Tokens>,
|
||||
ident: quote::Ident,
|
||||
ident: Term,
|
||||
tokens: quote::Tokens,
|
||||
emitted_any_variants: bool,
|
||||
},
|
||||
|
@ -2170,7 +2211,7 @@ impl<'a> EnumBuilder<'a> {
|
|||
enum_variation: EnumVariation,
|
||||
enum_codegen_depth: usize,
|
||||
) -> Self {
|
||||
let ident = quote::Ident::new(name);
|
||||
let ident = Term::new(name, Span::call_site());
|
||||
|
||||
match enum_variation {
|
||||
EnumVariation::Bitfield => {
|
||||
|
@ -2185,7 +2226,7 @@ impl<'a> EnumBuilder<'a> {
|
|||
}
|
||||
|
||||
EnumVariation::Rust => {
|
||||
let tokens = quote!{};
|
||||
let tokens = quote!();
|
||||
EnumBuilder::Rust {
|
||||
codegen_depth: enum_codegen_depth + 1,
|
||||
attrs,
|
||||
|
@ -2208,7 +2249,7 @@ impl<'a> EnumBuilder<'a> {
|
|||
}
|
||||
|
||||
EnumVariation::ModuleConsts => {
|
||||
let ident = quote::Ident::new(CONSTIFIED_ENUM_MODULE_REPR_NAME);
|
||||
let ident = Term::new(CONSTIFIED_ENUM_MODULE_REPR_NAME, Span::call_site());
|
||||
let type_definition = quote! {
|
||||
#( #attrs )*
|
||||
pub type #ident = #repr;
|
||||
|
@ -2231,6 +2272,7 @@ impl<'a> EnumBuilder<'a> {
|
|||
mangling_prefix: Option<&str>,
|
||||
rust_ty: quote::Tokens,
|
||||
result: &mut CodegenResult<'b>,
|
||||
is_ty_named: bool,
|
||||
) -> Self {
|
||||
let variant_name = ctx.rust_mangle(variant.name());
|
||||
let expr = match variant.val() {
|
||||
|
@ -2262,19 +2304,28 @@ impl<'a> EnumBuilder<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
EnumBuilder::Bitfield { .. } => {
|
||||
let constant_name = match mangling_prefix {
|
||||
Some(prefix) => {
|
||||
Cow::Owned(format!("{}_{}", prefix, variant_name))
|
||||
}
|
||||
None => variant_name,
|
||||
};
|
||||
|
||||
let ident = ctx.rust_ident(constant_name);
|
||||
result.push(quote! {
|
||||
#doc
|
||||
pub const #ident : #rust_ty = #rust_ty ( #expr );
|
||||
});
|
||||
EnumBuilder::Bitfield { canonical_name, .. } => {
|
||||
if ctx.options().rust_features().associated_const && is_ty_named {
|
||||
let enum_ident = ctx.rust_ident(canonical_name);
|
||||
let variant_ident = ctx.rust_ident(variant_name);
|
||||
result.push(quote! {
|
||||
impl #enum_ident {
|
||||
#doc
|
||||
pub const #variant_ident : #rust_ty = #rust_ty ( #expr );
|
||||
}
|
||||
});
|
||||
} else {
|
||||
let ident = ctx.rust_ident(match mangling_prefix {
|
||||
Some(prefix) => {
|
||||
Cow::Owned(format!("{}_{}", prefix, variant_name))
|
||||
}
|
||||
None => variant_name,
|
||||
});
|
||||
result.push(quote! {
|
||||
#doc
|
||||
pub const #ident : #rust_ty = #rust_ty ( #expr );
|
||||
});
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
@ -2461,15 +2512,18 @@ impl CodeGenerator for Enum {
|
|||
}
|
||||
};
|
||||
|
||||
let variation = if self.is_bitfield(ctx, item) {
|
||||
// ModuleConsts has higher precedence before Rust in order to avoid problems with
|
||||
// overlapping match patterns
|
||||
let variation = if self.is_constified_enum_module(ctx, item) {
|
||||
EnumVariation::ModuleConsts
|
||||
} else if self.is_bitfield(ctx, item) {
|
||||
EnumVariation::Bitfield
|
||||
} else if self.is_rustified_enum(ctx, item) {
|
||||
EnumVariation::Rust
|
||||
} else if self.is_constified_enum_module(ctx, item) {
|
||||
EnumVariation::ModuleConsts
|
||||
} else {
|
||||
// We generate consts by default
|
||||
} else if self.is_constified_enum(ctx, item) {
|
||||
EnumVariation::Consts
|
||||
} else {
|
||||
ctx.options().default_enum_style
|
||||
};
|
||||
|
||||
let mut attrs = vec![];
|
||||
|
@ -2495,18 +2549,18 @@ impl CodeGenerator for Enum {
|
|||
ctx: &BindgenContext,
|
||||
enum_: &Type,
|
||||
// Only to avoid recomputing every time.
|
||||
enum_canonical_name: "e::Ident,
|
||||
enum_canonical_name: &Term,
|
||||
// May be the same as "variant" if it's because the
|
||||
// enum is unnamed and we still haven't seen the
|
||||
// value.
|
||||
variant_name: &str,
|
||||
referenced_name: "e::Ident,
|
||||
referenced_name: &Term,
|
||||
enum_rust_ty: quote::Tokens,
|
||||
result: &mut CodegenResult<'a>,
|
||||
) {
|
||||
let constant_name = if enum_.name().is_some() {
|
||||
if ctx.options().prepend_enum_name {
|
||||
format!("{}_{}", enum_canonical_name, variant_name)
|
||||
format!("{}_{}", enum_canonical_name.as_str(), variant_name)
|
||||
} else {
|
||||
variant_name.into()
|
||||
}
|
||||
|
@ -2535,7 +2589,7 @@ impl CodeGenerator for Enum {
|
|||
);
|
||||
|
||||
// A map where we keep a value -> variant relation.
|
||||
let mut seen_values = HashMap::<_, quote::Ident>::new();
|
||||
let mut seen_values = HashMap::<_, Term>::new();
|
||||
let enum_rust_ty = item.to_rust_ty_or_opaque(ctx, &());
|
||||
let is_toplevel = item.is_toplevel(ctx);
|
||||
|
||||
|
@ -2607,6 +2661,7 @@ impl CodeGenerator for Enum {
|
|||
constant_mangling_prefix,
|
||||
enum_rust_ty.clone(),
|
||||
result,
|
||||
enum_ty.name().is_some(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2617,6 +2672,7 @@ impl CodeGenerator for Enum {
|
|||
constant_mangling_prefix,
|
||||
enum_rust_ty.clone(),
|
||||
result,
|
||||
enum_ty.name().is_some(),
|
||||
);
|
||||
|
||||
let variant_name = ctx.rust_ident(variant.name());
|
||||
|
@ -2633,12 +2689,13 @@ impl CodeGenerator for Enum {
|
|||
let parent_name =
|
||||
parent_canonical_name.as_ref().unwrap();
|
||||
|
||||
quote::Ident::new(
|
||||
format!(
|
||||
Term::new(
|
||||
&format!(
|
||||
"{}_{}",
|
||||
parent_name,
|
||||
variant_name
|
||||
)
|
||||
variant_name.as_str()
|
||||
),
|
||||
Span::call_site()
|
||||
)
|
||||
};
|
||||
|
||||
|
@ -2646,14 +2703,14 @@ impl CodeGenerator for Enum {
|
|||
ctx,
|
||||
enum_ty,
|
||||
&ident,
|
||||
mangled_name.as_ref(),
|
||||
mangled_name.as_str(),
|
||||
&variant_name,
|
||||
enum_rust_ty.clone(),
|
||||
result,
|
||||
);
|
||||
}
|
||||
|
||||
entry.insert(quote::Ident::new(variant_name));
|
||||
entry.insert(variant_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2702,9 +2759,8 @@ trait TryToOpaque {
|
|||
/// leverage the blanket impl for this trait.
|
||||
trait ToOpaque: TryToOpaque {
|
||||
fn get_layout(&self, ctx: &BindgenContext, extra: &Self::Extra) -> Layout {
|
||||
self.try_get_layout(ctx, extra).unwrap_or_else(
|
||||
|_| Layout::for_size(1),
|
||||
)
|
||||
self.try_get_layout(ctx, extra)
|
||||
.unwrap_or_else(|_| Layout::for_size(ctx, 1))
|
||||
}
|
||||
|
||||
fn to_opaque(
|
||||
|
@ -2951,7 +3007,7 @@ impl TryToRustTy for Type {
|
|||
TypeKind::Complex(fk) => {
|
||||
let float_path = float_kind_rust_type(ctx, fk);
|
||||
|
||||
ctx.generated_bindegen_complex();
|
||||
ctx.generated_bindgen_complex();
|
||||
Ok(if ctx.options().enable_cxx_namespaces {
|
||||
quote! {
|
||||
root::__BindgenComplex<#float_path>
|
||||
|
@ -2981,10 +3037,9 @@ impl TryToRustTy for Type {
|
|||
})
|
||||
}
|
||||
TypeKind::Enum(..) => {
|
||||
let mut tokens = quote! {};
|
||||
let path = item.namespace_aware_canonical_path(ctx);
|
||||
tokens.append_separated(path.into_iter().map(quote::Ident::new), "::");
|
||||
Ok(tokens)
|
||||
let path = Term::new(&path.join("::"), Span::call_site());
|
||||
Ok(quote!(#path))
|
||||
}
|
||||
TypeKind::TemplateInstantiation(ref inst) => {
|
||||
inst.try_to_rust_ty(ctx, item)
|
||||
|
@ -2993,7 +3048,6 @@ impl TryToRustTy for Type {
|
|||
TypeKind::TemplateAlias(..) |
|
||||
TypeKind::Alias(..) => {
|
||||
let template_params = item.used_template_params(ctx)
|
||||
.unwrap_or(vec![])
|
||||
.into_iter()
|
||||
.filter(|param| param.is_template_param(ctx, &()))
|
||||
.collect::<Vec<_>>();
|
||||
|
@ -3012,9 +3066,9 @@ impl TryToRustTy for Type {
|
|||
}
|
||||
}
|
||||
TypeKind::Comp(ref info) => {
|
||||
let template_params = item.used_template_params(ctx);
|
||||
let template_params = item.all_template_params(ctx);
|
||||
if info.has_non_type_template_params() ||
|
||||
(item.is_opaque(ctx, &()) && template_params.is_some())
|
||||
(item.is_opaque(ctx, &()) && !template_params.is_empty())
|
||||
{
|
||||
return self.try_to_opaque(ctx, item);
|
||||
}
|
||||
|
@ -3031,7 +3085,7 @@ impl TryToRustTy for Type {
|
|||
}
|
||||
TypeKind::Pointer(inner) |
|
||||
TypeKind::Reference(inner) => {
|
||||
let is_const = self.is_const() || ctx.resolve_type(inner).is_const();
|
||||
let is_const = ctx.resolve_type(inner).is_const();
|
||||
|
||||
let inner = inner.into_resolver().through_type_refs().resolve(ctx);
|
||||
let inner_ty = inner.expect_type();
|
||||
|
@ -3106,20 +3160,18 @@ impl TryToRustTy for TemplateInstantiation {
|
|||
|
||||
let mut ty = quote! {};
|
||||
let def_path = def.namespace_aware_canonical_path(ctx);
|
||||
ty.append_separated(def_path.into_iter().map(|p| ctx.rust_ident(p)), "::");
|
||||
ty.append_separated(def_path.into_iter().map(|p| ctx.rust_ident(p)), Term::new("::", Span::call_site()));
|
||||
|
||||
let def_params = match def.self_template_params(ctx) {
|
||||
Some(params) => params,
|
||||
None => {
|
||||
// This can happen if we generated an opaque type for a partial
|
||||
// template specialization, and we've hit an instantiation of
|
||||
// that partial specialization.
|
||||
extra_assert!(
|
||||
def.is_opaque(ctx, &())
|
||||
);
|
||||
return Err(error::Error::InstantiationOfOpaqueType);
|
||||
}
|
||||
};
|
||||
let def_params = def.self_template_params(ctx);
|
||||
if def_params.is_empty() {
|
||||
// This can happen if we generated an opaque type for a partial
|
||||
// template specialization, and we've hit an instantiation of
|
||||
// that partial specialization.
|
||||
extra_assert!(
|
||||
def.is_opaque(ctx, &())
|
||||
);
|
||||
return Err(error::Error::InstantiationOfOpaqueType);
|
||||
}
|
||||
|
||||
// TODO: If the definition type is a template class/struct
|
||||
// definition's member template definition, it could rely on
|
||||
|
@ -3167,7 +3219,7 @@ impl TryToRustTy for FunctionSig {
|
|||
let abi = self.abi();
|
||||
|
||||
match abi {
|
||||
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi() => {
|
||||
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi => {
|
||||
warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target");
|
||||
Ok(quote::Tokens::new())
|
||||
}
|
||||
|
@ -3212,11 +3264,8 @@ impl CodeGenerator for Function {
|
|||
// generate bindings to template functions, because the set of
|
||||
// instantiations is open ended and we have no way of knowing which
|
||||
// monomorphizations actually exist.
|
||||
let type_params = item.all_template_params(ctx);
|
||||
if let Some(params) = type_params {
|
||||
if !params.is_empty() {
|
||||
return;
|
||||
}
|
||||
if !item.all_template_params(ctx).is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let name = self.name();
|
||||
|
@ -3264,7 +3313,7 @@ impl CodeGenerator for Function {
|
|||
}
|
||||
|
||||
let abi = match signature.abi() {
|
||||
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi() => {
|
||||
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi => {
|
||||
warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target");
|
||||
return;
|
||||
}
|
||||
|
@ -3319,7 +3368,7 @@ fn objc_method_codegen(
|
|||
let class_name = class_name
|
||||
.expect("Generating a class method without class name?")
|
||||
.to_owned();
|
||||
let expect_msg = format!("Couldn't find {}", class_name);
|
||||
let expect_msg = proc_macro2::Literal::string(&format!("Couldn't find {}", class_name));
|
||||
quote! {
|
||||
msg_send!(objc::runtime::Class::get(#class_name).expect(#expect_msg), #methods_and_args)
|
||||
}
|
||||
|
@ -3445,11 +3494,12 @@ mod utils {
|
|||
use ir::item::{Item, ItemCanonicalPath};
|
||||
use ir::ty::TypeKind;
|
||||
use quote;
|
||||
use proc_macro2::{Term, Span};
|
||||
use std::mem;
|
||||
|
||||
pub fn prepend_bitfield_unit_type(result: &mut Vec<quote::Tokens>) {
|
||||
let mut bitfield_unit_type = quote! {};
|
||||
bitfield_unit_type.append(include_str!("./bitfield_unit.rs"));
|
||||
let bitfield_unit_type = Term::new(include_str!("./bitfield_unit.rs"), Span::call_site());
|
||||
let bitfield_unit_type = quote!(#bitfield_unit_type);
|
||||
|
||||
let items = vec![bitfield_unit_type];
|
||||
let old_items = mem::replace(result, items);
|
||||
|
@ -3675,10 +3725,12 @@ mod utils {
|
|||
item: &Item,
|
||||
ctx: &BindgenContext,
|
||||
) -> error::Result<quote::Tokens> {
|
||||
let path = item.namespace_aware_canonical_path(ctx);
|
||||
use proc_macro2::{Term, Span};
|
||||
|
||||
let mut tokens = quote! {};
|
||||
tokens.append_separated(path.into_iter().map(quote::Ident::new), "::");
|
||||
let path = item.namespace_aware_canonical_path(ctx);
|
||||
let path = Term::new(&path.join("::"), Span::call_site());
|
||||
let tokens = quote! {#path};
|
||||
//tokens.append_separated(path, "::");
|
||||
|
||||
Ok(tokens)
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ use ir::context::BindgenContext;
|
|||
use ir::layout::Layout;
|
||||
use ir::ty::{Type, TypeKind};
|
||||
use quote;
|
||||
use proc_macro2::{Term, Span};
|
||||
use std::cmp;
|
||||
use std::mem;
|
||||
|
||||
/// Trace the layout of struct.
|
||||
#[derive(Debug)]
|
||||
|
@ -101,7 +101,7 @@ impl<'a> StructLayoutTracker<'a> {
|
|||
pub fn saw_vtable(&mut self) {
|
||||
debug!("saw vtable for {}", self.name);
|
||||
|
||||
let ptr_size = mem::size_of::<*mut ()>();
|
||||
let ptr_size = self.ctx.target_pointer_size();
|
||||
self.latest_offset += ptr_size;
|
||||
self.latest_field_layout = Some(Layout::new(ptr_size, ptr_size));
|
||||
self.max_field_align = ptr_size;
|
||||
|
@ -165,15 +165,13 @@ impl<'a> StructLayoutTracker<'a> {
|
|||
// can support.
|
||||
//
|
||||
// This means that the structs in the array are super-unsafe to
|
||||
// access, since they won't be properly aligned, but *shrug*.
|
||||
if let Some(layout) = self.ctx.resolve_type(inner).layout(
|
||||
self.ctx,
|
||||
)
|
||||
{
|
||||
if layout.align > mem::size_of::<*mut ()>() {
|
||||
field_layout.size = align_to(layout.size, layout.align) *
|
||||
len;
|
||||
field_layout.align = mem::size_of::<*mut ()>();
|
||||
// access, since they won't be properly aligned, but there's not too
|
||||
// much we can do about it.
|
||||
if let Some(layout) = self.ctx.resolve_type(inner).layout(self.ctx) {
|
||||
if layout.align > self.ctx.target_pointer_size() {
|
||||
field_layout.size =
|
||||
align_to(layout.size, layout.align) * len;
|
||||
field_layout.align = self.ctx.target_pointer_size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +191,7 @@ impl<'a> StructLayoutTracker<'a> {
|
|||
|
||||
// Otherwise the padding is useless.
|
||||
let need_padding = padding_bytes >= field_layout.align ||
|
||||
field_layout.align > mem::size_of::<*mut ()>();
|
||||
field_layout.align > self.ctx.target_pointer_size();
|
||||
|
||||
self.latest_offset += padding_bytes;
|
||||
|
||||
|
@ -215,7 +213,7 @@ impl<'a> StructLayoutTracker<'a> {
|
|||
if need_padding && padding_bytes != 0 {
|
||||
Some(Layout::new(
|
||||
padding_bytes,
|
||||
cmp::min(field_layout.align, mem::size_of::<*mut ()>()),
|
||||
cmp::min(field_layout.align, self.ctx.target_pointer_size())
|
||||
))
|
||||
} else {
|
||||
None
|
||||
|
@ -267,15 +265,15 @@ impl<'a> StructLayoutTracker<'a> {
|
|||
(self.last_field_was_bitfield &&
|
||||
padding_bytes >=
|
||||
self.latest_field_layout.unwrap().align) ||
|
||||
layout.align > mem::size_of::<*mut ()>())
|
||||
layout.align > self.ctx.target_pointer_size())
|
||||
{
|
||||
let layout = if self.is_packed {
|
||||
Layout::new(padding_bytes, 1)
|
||||
} else if self.last_field_was_bitfield ||
|
||||
layout.align > mem::size_of::<*mut ()>()
|
||||
layout.align > self.ctx.target_pointer_size()
|
||||
{
|
||||
// We've already given up on alignment here.
|
||||
Layout::for_size(padding_bytes)
|
||||
Layout::for_size(self.ctx, padding_bytes)
|
||||
} else {
|
||||
Layout::new(padding_bytes, layout.align)
|
||||
};
|
||||
|
@ -289,8 +287,18 @@ impl<'a> StructLayoutTracker<'a> {
|
|||
}
|
||||
|
||||
pub fn requires_explicit_align(&self, layout: Layout) -> bool {
|
||||
self.max_field_align < layout.align &&
|
||||
layout.align <= mem::size_of::<*mut ()>()
|
||||
if self.max_field_align >= layout.align {
|
||||
return false;
|
||||
}
|
||||
// At this point we require explicit alignment, but we may not be able
|
||||
// to generate the right bits, let's double check.
|
||||
if self.ctx.options().rust_features().repr_align {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We can only generate up-to a word of alignment unless we support
|
||||
// repr(align).
|
||||
layout.align <= self.ctx.target_pointer_size()
|
||||
}
|
||||
|
||||
fn padding_bytes(&self, layout: Layout) -> usize {
|
||||
|
@ -303,7 +311,7 @@ impl<'a> StructLayoutTracker<'a> {
|
|||
|
||||
self.padding_count += 1;
|
||||
|
||||
let padding_field_name = quote::Ident::new(format!("__bindgen_padding_{}", padding_count));
|
||||
let padding_field_name = Term::new(&format!("__bindgen_padding_{}", padding_count), Span::call_site());
|
||||
|
||||
self.max_field_align = cmp::max(self.max_field_align, layout.align);
|
||||
|
||||
|
|
|
@ -90,8 +90,12 @@ macro_rules! rust_target_base {
|
|||
=> Stable_1_0 => 1.0;
|
||||
/// Rust stable 1.19
|
||||
=> Stable_1_19 => 1.19;
|
||||
/// Rust stable 1.20
|
||||
=> Stable_1_20 => 1.20;
|
||||
/// Rust stable 1.21
|
||||
=> Stable_1_21 => 1.21;
|
||||
/// Rust stable 1.25
|
||||
=> Stable_1_25 => 1.25;
|
||||
/// Nightly rust
|
||||
=> Nightly => nightly;
|
||||
);
|
||||
|
@ -111,7 +115,10 @@ macro_rules! rust_feature_def {
|
|||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct RustFeatures {
|
||||
$(
|
||||
$feature: bool,
|
||||
$(
|
||||
#[$attr]
|
||||
)*
|
||||
pub $feature: bool,
|
||||
)*
|
||||
}
|
||||
|
||||
|
@ -124,15 +131,6 @@ macro_rules! rust_feature_def {
|
|||
)*
|
||||
}
|
||||
}
|
||||
|
||||
$(
|
||||
$(
|
||||
#[$attr]
|
||||
)*
|
||||
pub fn $feature(&self) -> bool {
|
||||
self.$feature
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,6 +142,10 @@ rust_feature_def!(
|
|||
=> thiscall_abi;
|
||||
/// builtin impls for `Clone` ([PR](https://github.com/rust-lang/rust/pull/43690))
|
||||
=> builtin_clone_impls;
|
||||
/// repr(align) https://github.com/rust-lang/rust/pull/47006
|
||||
=> repr_align;
|
||||
/// associated constants https://github.com/rust-lang/rust/issues/29646
|
||||
=> associated_const;
|
||||
);
|
||||
|
||||
impl From<RustTarget> for RustFeatures {
|
||||
|
@ -154,10 +156,18 @@ impl From<RustTarget> for RustFeatures {
|
|||
features.untagged_union = true;
|
||||
}
|
||||
|
||||
if rust_target >= RustTarget::Stable_1_20 {
|
||||
features.associated_const = true;
|
||||
}
|
||||
|
||||
if rust_target >= RustTarget::Stable_1_21 {
|
||||
features.builtin_clone_impls = true;
|
||||
}
|
||||
|
||||
if rust_target >= RustTarget::Stable_1_25 {
|
||||
features.repr_align = true;
|
||||
}
|
||||
|
||||
if rust_target >= RustTarget::Nightly {
|
||||
features.thiscall_abi = true;
|
||||
}
|
||||
|
@ -189,6 +199,7 @@ mod test {
|
|||
test_target("1.0", RustTarget::Stable_1_0);
|
||||
test_target("1.19", RustTarget::Stable_1_19);
|
||||
test_target("1.21", RustTarget::Stable_1_21);
|
||||
test_target("1.25", RustTarget::Stable_1_25);
|
||||
test_target("nightly", RustTarget::Nightly);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -234,7 +234,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> {
|
|||
}
|
||||
|
||||
if info.kind() == CompKind::Union {
|
||||
if !self.ctx.options().rust_features().untagged_union() {
|
||||
if !self.ctx.options().rust_features().untagged_union {
|
||||
// NOTE: If there's no template parameters we can derive
|
||||
// copy unconditionally, since arrays are magical for
|
||||
// rustc, and __BindgenUnionField always implements
|
||||
|
@ -246,8 +246,8 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> {
|
|||
}
|
||||
|
||||
// https://github.com/rust-lang/rust/issues/36640
|
||||
if info.self_template_params(self.ctx).is_some() ||
|
||||
item.used_template_params(self.ctx).is_some()
|
||||
if !info.self_template_params(self.ctx).is_empty() ||
|
||||
!item.all_template_params(self.ctx).is_empty()
|
||||
{
|
||||
trace!(
|
||||
" comp cannot derive copy because issue 36640"
|
||||
|
|
|
@ -150,7 +150,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
|
|||
});
|
||||
return if layout_can_derive &&
|
||||
!(ty.is_union() &&
|
||||
self.ctx.options().rust_features().untagged_union()) {
|
||||
self.ctx.options().rust_features().untagged_union) {
|
||||
trace!(" we can trivially derive Debug for the layout");
|
||||
ConstrainResult::Same
|
||||
} else {
|
||||
|
@ -235,7 +235,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
|
|||
);
|
||||
|
||||
if info.kind() == CompKind::Union {
|
||||
if self.ctx.options().rust_features().untagged_union() {
|
||||
if self.ctx.options().rust_features().untagged_union {
|
||||
trace!(" cannot derive Debug for Rust unions");
|
||||
return self.insert(id);
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
|
|||
});
|
||||
return if layout_can_derive &&
|
||||
!(ty.is_union() &&
|
||||
self.ctx.options().rust_features().untagged_union()) {
|
||||
self.ctx.options().rust_features().untagged_union) {
|
||||
trace!(" we can trivially derive Default for the layout");
|
||||
ConstrainResult::Same
|
||||
} else {
|
||||
|
@ -271,7 +271,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
|
|||
}
|
||||
|
||||
if info.kind() == CompKind::Union {
|
||||
if self.ctx.options().rust_features().untagged_union() {
|
||||
if self.ctx.options().rust_features().untagged_union {
|
||||
trace!(" cannot derive Default for Rust unions");
|
||||
return self.insert(id);
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
|
|||
});
|
||||
return if layout_can_derive &&
|
||||
!(ty.is_union() &&
|
||||
self.ctx.options().rust_features().untagged_union()) {
|
||||
self.ctx.options().rust_features().untagged_union) {
|
||||
trace!(" we can trivially derive Hash for the layout");
|
||||
ConstrainResult::Same
|
||||
} else {
|
||||
|
@ -257,7 +257,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
|
|||
}
|
||||
|
||||
if info.kind() == CompKind::Union {
|
||||
if self.ctx.options().rust_features().untagged_union() {
|
||||
if self.ctx.options().rust_features().untagged_union {
|
||||
trace!(" cannot derive Hash for Rust unions");
|
||||
return self.insert(id);
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
|
|||
trace!("ty: {:?}", ty);
|
||||
if item.is_opaque(self.ctx, &()) {
|
||||
if ty.is_union()
|
||||
&& self.ctx.options().rust_features().untagged_union()
|
||||
&& self.ctx.options().rust_features().untagged_union
|
||||
{
|
||||
trace!(
|
||||
" cannot derive `PartialEq`/`PartialOrd` for Rust unions"
|
||||
|
@ -242,7 +242,7 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
|
|||
}
|
||||
|
||||
if info.kind() == CompKind::Union {
|
||||
if self.ctx.options().rust_features().untagged_union() {
|
||||
if self.ctx.options().rust_features().untagged_union {
|
||||
trace!(
|
||||
" cannot derive `PartialEq`/`PartialOrd` for Rust unions"
|
||||
);
|
||||
|
|
|
@ -275,7 +275,7 @@ impl<'ctx> UsedTemplateParameters<'ctx> {
|
|||
let decl = self.ctx.resolve_type(instantiation.template_definition());
|
||||
let args = instantiation.template_arguments();
|
||||
|
||||
let params = decl.self_template_params(self.ctx).unwrap_or(vec![]);
|
||||
let params = decl.self_template_params(self.ctx);
|
||||
|
||||
debug_assert!(this_id != instantiation.template_definition());
|
||||
let used_by_def = self.used
|
||||
|
@ -419,7 +419,7 @@ impl<'ctx> MonotoneFramework for UsedTemplateParameters<'ctx> {
|
|||
// template parameters, there is a single exception:
|
||||
// opaque templates. Hence the unwrap_or.
|
||||
let params =
|
||||
decl.self_template_params(ctx).unwrap_or(vec![]);
|
||||
decl.self_template_params(ctx);
|
||||
|
||||
for (arg, param) in args.iter().zip(params.iter()) {
|
||||
let arg = arg.into_resolver()
|
||||
|
|
|
@ -39,7 +39,7 @@ fn make_indent(indent: usize) -> String {
|
|||
iter::repeat(' ').take(indent * RUST_INDENTATION).collect()
|
||||
}
|
||||
|
||||
/// Preprocesses mulitple single line comments.
|
||||
/// Preprocesses multiple single line comments.
|
||||
///
|
||||
/// Handles lines starting with both `//` and `///`.
|
||||
fn preprocess_single_lines(comment: &str, indent: usize) -> String {
|
||||
|
|
|
@ -1290,9 +1290,10 @@ impl CompInfo {
|
|||
return CXChildVisit_Continue;
|
||||
}
|
||||
|
||||
// Even if this is a definition, we may not be the semantic
|
||||
// parent, see #1281.
|
||||
let inner = Item::parse(cur, Some(potential_id), ctx)
|
||||
.expect("Inner ClassDecl");
|
||||
assert_eq!(ctx.resolve_item(inner).parent_id(), potential_id);
|
||||
|
||||
let inner = inner.expect_type_id(ctx);
|
||||
|
||||
|
@ -1355,7 +1356,7 @@ impl CompInfo {
|
|||
// to be inserted in the map two times.
|
||||
//
|
||||
// I couldn't make a reduced test case, but anyway...
|
||||
// Methods of template functions not only use to be inlined,
|
||||
// Methods of template functions not only used to be inlined,
|
||||
// but also instantiated, and we wouldn't be able to call
|
||||
// them, so just bail out.
|
||||
if !ci.template_params.is_empty() {
|
||||
|
@ -1543,7 +1544,7 @@ impl CompInfo {
|
|||
/// 1. Current RustTarget allows for `untagged_union`
|
||||
/// 2. Each field can derive `Copy`
|
||||
pub fn can_be_rust_union(&self, ctx: &BindgenContext) -> bool {
|
||||
if !ctx.options().rust_features().untagged_union() {
|
||||
if !ctx.options().rust_features().untagged_union {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1668,12 +1669,8 @@ impl TemplateParameters for CompInfo {
|
|||
fn self_template_params(
|
||||
&self,
|
||||
_ctx: &BindgenContext,
|
||||
) -> Option<Vec<TypeId>> {
|
||||
if self.template_params.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(self.template_params.clone())
|
||||
}
|
||||
) -> Vec<TypeId> {
|
||||
self.template_params.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1684,8 +1681,7 @@ impl Trace for CompInfo {
|
|||
where
|
||||
T: Tracer,
|
||||
{
|
||||
let params = item.all_template_params(context).unwrap_or(vec![]);
|
||||
for p in params {
|
||||
for p in item.all_template_params(context) {
|
||||
tracer.visit_kind(p.into(), EdgeKind::TemplateParameterDefinition);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ use cexpr;
|
|||
use clang::{self, Cursor};
|
||||
use clang_sys;
|
||||
use parse::ClangItemParser;
|
||||
use quote;
|
||||
use proc_macro2::{Term, Span};
|
||||
use std::borrow::Cow;
|
||||
use std::cell::Cell;
|
||||
use std::collections::{HashMap, HashSet, hash_map};
|
||||
|
@ -366,11 +366,14 @@ pub struct BindgenContext {
|
|||
/// The translation unit for parsing.
|
||||
translation_unit: clang::TranslationUnit,
|
||||
|
||||
/// Target information that can be useful for some stuff.
|
||||
target_info: Option<clang::TargetInfo>,
|
||||
|
||||
/// The options given by the user via cli or other medium.
|
||||
options: BindgenOptions,
|
||||
|
||||
/// Whether a bindgen complex was generated
|
||||
generated_bindegen_complex: Cell<bool>,
|
||||
generated_bindgen_complex: Cell<bool>,
|
||||
|
||||
/// The set of `ItemId`s that are whitelisted. This the very first thing
|
||||
/// computed after parsing our IR, and before running any of our analyses.
|
||||
|
@ -503,6 +506,9 @@ impl<'ctx> WhitelistedItemsTraversal<'ctx> {
|
|||
}
|
||||
}
|
||||
|
||||
const HOST_TARGET: &'static str =
|
||||
include_str!(concat!(env!("OUT_DIR"), "/host-target.txt"));
|
||||
|
||||
/// Returns the effective target, and whether it was explicitly specified on the
|
||||
/// clang flags.
|
||||
fn find_effective_target(clang_args: &[String]) -> (String, bool) {
|
||||
|
@ -521,8 +527,6 @@ fn find_effective_target(clang_args: &[String]) -> (String, bool) {
|
|||
return (t, false)
|
||||
}
|
||||
|
||||
const HOST_TARGET: &'static str =
|
||||
include_str!(concat!(env!("OUT_DIR"), "/host-target.txt"));
|
||||
(HOST_TARGET.to_owned(), false)
|
||||
}
|
||||
|
||||
|
@ -561,6 +565,17 @@ impl BindgenContext {
|
|||
).expect("TranslationUnit::parse failed")
|
||||
};
|
||||
|
||||
let target_info = clang::TargetInfo::new(&translation_unit);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
if let Some(ref ti) = target_info {
|
||||
if effective_target == HOST_TARGET {
|
||||
assert_eq!(ti.pointer_width / 8, mem::size_of::<*mut ()>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let root_module = Self::build_root_module(ItemId(0));
|
||||
let root_module_id = root_module.id().as_module_id_unchecked();
|
||||
|
||||
|
@ -578,10 +593,11 @@ impl BindgenContext {
|
|||
replacements: Default::default(),
|
||||
collected_typerefs: false,
|
||||
in_codegen: false,
|
||||
index: index,
|
||||
translation_unit: translation_unit,
|
||||
options: options,
|
||||
generated_bindegen_complex: Cell::new(false),
|
||||
index,
|
||||
translation_unit,
|
||||
target_info,
|
||||
options,
|
||||
generated_bindgen_complex: Cell::new(false),
|
||||
whitelisted: None,
|
||||
codegen_items: None,
|
||||
used_template_parameters: None,
|
||||
|
@ -611,6 +627,15 @@ impl BindgenContext {
|
|||
Timer::new(name).with_output(self.options.time_phases)
|
||||
}
|
||||
|
||||
/// Returns the pointer width to use for the target for the current
|
||||
/// translation.
|
||||
pub fn target_pointer_size(&self) -> usize {
|
||||
if let Some(ref ti) = self.target_info {
|
||||
return ti.pointer_width / 8;
|
||||
}
|
||||
mem::size_of::<*mut ()>()
|
||||
}
|
||||
|
||||
/// Get the stack of partially parsed types that we are in the middle of
|
||||
/// parsing.
|
||||
pub fn currently_parsed_types(&self) -> &[PartialType] {
|
||||
|
@ -880,7 +905,7 @@ impl BindgenContext {
|
|||
}
|
||||
|
||||
/// Returns a mangled name as a rust identifier.
|
||||
pub fn rust_ident<S>(&self, name: S) -> quote::Ident
|
||||
pub fn rust_ident<S>(&self, name: S) -> Term
|
||||
where
|
||||
S: AsRef<str>
|
||||
{
|
||||
|
@ -888,11 +913,11 @@ impl BindgenContext {
|
|||
}
|
||||
|
||||
/// Returns a mangled name as a rust identifier.
|
||||
pub fn rust_ident_raw<T>(&self, name: T) -> quote::Ident
|
||||
pub fn rust_ident_raw<T>(&self, name: T) -> Term
|
||||
where
|
||||
T: Into<quote::Ident>
|
||||
T: AsRef<str>
|
||||
{
|
||||
name.into()
|
||||
Term::new(name.as_ref(), Span::call_site())
|
||||
}
|
||||
|
||||
/// Iterate over all items that have been defined.
|
||||
|
@ -1341,10 +1366,7 @@ impl BindgenContext {
|
|||
let mut used_params = HashMap::new();
|
||||
for &id in self.whitelisted_items() {
|
||||
used_params.entry(id).or_insert(
|
||||
id.self_template_params(self).map_or(
|
||||
Default::default(),
|
||||
|params| params.into_iter().map(|p| p.into()).collect(),
|
||||
),
|
||||
id.self_template_params(self).into_iter().map(|p| p.into()).collect()
|
||||
);
|
||||
}
|
||||
self.used_template_parameters = Some(used_params);
|
||||
|
@ -1516,7 +1538,7 @@ impl BindgenContext {
|
|||
///
|
||||
/// Note that `declaration_id` is not guaranteed to be in the context's item
|
||||
/// set! It is possible that it is a partial type that we are still in the
|
||||
/// middle of parsign.
|
||||
/// middle of parsing.
|
||||
fn get_declaration_info_for_template_instantiation(
|
||||
&self,
|
||||
instantiation: &Cursor,
|
||||
|
@ -1527,15 +1549,16 @@ impl BindgenContext {
|
|||
.and_then(|canon_decl| {
|
||||
self.get_resolved_type(&canon_decl).and_then(
|
||||
|template_decl_id| {
|
||||
template_decl_id.num_self_template_params(self).map(
|
||||
|num_params| {
|
||||
(
|
||||
*canon_decl.cursor(),
|
||||
template_decl_id.into(),
|
||||
num_params,
|
||||
)
|
||||
},
|
||||
)
|
||||
let num_params = template_decl_id.num_self_template_params(self);
|
||||
if num_params == 0 {
|
||||
None
|
||||
} else {
|
||||
Some((
|
||||
*canon_decl.cursor(),
|
||||
template_decl_id.into(),
|
||||
num_params,
|
||||
))
|
||||
}
|
||||
},
|
||||
)
|
||||
})
|
||||
|
@ -1556,15 +1579,16 @@ impl BindgenContext {
|
|||
.cloned()
|
||||
})
|
||||
.and_then(|template_decl| {
|
||||
template_decl.num_self_template_params(self).map(
|
||||
|num_template_params| {
|
||||
(
|
||||
*template_decl.decl(),
|
||||
template_decl.id(),
|
||||
num_template_params,
|
||||
)
|
||||
},
|
||||
)
|
||||
let num_template_params = template_decl.num_self_template_params(self);
|
||||
if num_template_params == 0 {
|
||||
None
|
||||
} else {
|
||||
Some((
|
||||
*template_decl.decl(),
|
||||
template_decl.id(),
|
||||
num_template_params,
|
||||
))
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -1611,17 +1635,14 @@ impl BindgenContext {
|
|||
) -> Option<TypeId> {
|
||||
use clang_sys;
|
||||
|
||||
let num_expected_args = match self.resolve_type(template)
|
||||
.num_self_template_params(self) {
|
||||
Some(n) => n,
|
||||
None => {
|
||||
warn!(
|
||||
"Tried to instantiate a template for which we could not \
|
||||
determine any template parameters"
|
||||
);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
let num_expected_args = self.resolve_type(template).num_self_template_params(self);
|
||||
if num_expected_args == 0 {
|
||||
warn!(
|
||||
"Tried to instantiate a template for which we could not \
|
||||
determine any template parameters"
|
||||
);
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut args = vec![];
|
||||
let mut found_const_arg = false;
|
||||
|
@ -1893,7 +1914,7 @@ impl BindgenContext {
|
|||
/// Make a new item that is a resolved type reference to the `wrapped_id`.
|
||||
///
|
||||
/// This is unfortunately a lot of bloat, but is needed to properly track
|
||||
/// constness et. al.
|
||||
/// constness et al.
|
||||
///
|
||||
/// We should probably make the constness tracking separate, so it doesn't
|
||||
/// bloat that much, but hey, we already bloat the heck out of builtin
|
||||
|
@ -1904,9 +1925,44 @@ impl BindgenContext {
|
|||
wrapped_id: TypeId,
|
||||
parent_id: Option<ItemId>,
|
||||
ty: &clang::Type,
|
||||
) -> TypeId {
|
||||
self.build_wrapper(
|
||||
with_id,
|
||||
wrapped_id,
|
||||
parent_id,
|
||||
ty,
|
||||
ty.is_const(),
|
||||
)
|
||||
}
|
||||
|
||||
/// A wrapper over a type that adds a const qualifier explicitly.
|
||||
///
|
||||
/// Needed to handle const methods in C++, wrapping the type .
|
||||
pub fn build_const_wrapper(
|
||||
&mut self,
|
||||
with_id: ItemId,
|
||||
wrapped_id: TypeId,
|
||||
parent_id: Option<ItemId>,
|
||||
ty: &clang::Type,
|
||||
) -> TypeId {
|
||||
self.build_wrapper(
|
||||
with_id,
|
||||
wrapped_id,
|
||||
parent_id,
|
||||
ty,
|
||||
/* is_const = */ true,
|
||||
)
|
||||
}
|
||||
|
||||
fn build_wrapper(
|
||||
&mut self,
|
||||
with_id: ItemId,
|
||||
wrapped_id: TypeId,
|
||||
parent_id: Option<ItemId>,
|
||||
ty: &clang::Type,
|
||||
is_const: bool,
|
||||
) -> TypeId {
|
||||
let spelling = ty.spelling();
|
||||
let is_const = ty.is_const();
|
||||
let layout = ty.fallible_layout().ok();
|
||||
let type_kind = TypeKind::ResolvedTypeRef(wrapped_id);
|
||||
let ty = Type::new(Some(spelling), layout, type_kind, is_const);
|
||||
|
@ -2291,7 +2347,11 @@ impl BindgenContext {
|
|||
if self.options().whitelist_recursively {
|
||||
traversal::all_edges
|
||||
} else {
|
||||
traversal::no_edges
|
||||
// Only follow InnerType edges from the whitelisted roots.
|
||||
// Such inner types (e.g. anonymous structs/unions) are
|
||||
// always emitted by codegen, and they need to be whitelisted
|
||||
// to make sure they are processed by e.g. the derive analysis.
|
||||
traversal::only_inner_type_edges
|
||||
};
|
||||
|
||||
let whitelisted = WhitelistedItemsTraversal::new(
|
||||
|
@ -2316,7 +2376,7 @@ impl BindgenContext {
|
|||
|
||||
/// Convenient method for getting the prefix to use for most traits in
|
||||
/// codegen depending on the `use_core` option.
|
||||
pub fn trait_prefix(&self) -> quote::Ident {
|
||||
pub fn trait_prefix(&self) -> Term {
|
||||
if self.options().use_core {
|
||||
self.rust_ident_raw("core")
|
||||
} else {
|
||||
|
@ -2324,14 +2384,14 @@ impl BindgenContext {
|
|||
}
|
||||
}
|
||||
|
||||
/// Call if a binden complex is generated
|
||||
pub fn generated_bindegen_complex(&self) {
|
||||
self.generated_bindegen_complex.set(true)
|
||||
/// Call if a bindgen complex is generated
|
||||
pub fn generated_bindgen_complex(&self) {
|
||||
self.generated_bindgen_complex.set(true)
|
||||
}
|
||||
|
||||
/// Whether we need to generate the binden complex type
|
||||
pub fn need_bindegen_complex_type(&self) -> bool {
|
||||
self.generated_bindegen_complex.get()
|
||||
/// Whether we need to generate the bindgen complex type
|
||||
pub fn need_bindgen_complex_type(&self) -> bool {
|
||||
self.generated_bindgen_complex.get()
|
||||
}
|
||||
|
||||
/// Compute whether we can derive debug.
|
||||
|
@ -2503,7 +2563,7 @@ impl BindgenContext {
|
|||
self.options().no_copy_types.matches(&name)
|
||||
}
|
||||
|
||||
/// Chech if `--no-hash` flag is enabled for this item.
|
||||
/// Check if `--no-hash` flag is enabled for this item.
|
||||
pub fn no_hash_by_name(&self, item: &Item) -> bool {
|
||||
let name = item.canonical_path(self)[1..].join("::");
|
||||
self.options().no_hash_types.matches(&name)
|
||||
|
@ -2618,13 +2678,13 @@ impl TemplateParameters for PartialType {
|
|||
fn self_template_params(
|
||||
&self,
|
||||
_ctx: &BindgenContext,
|
||||
) -> Option<Vec<TypeId>> {
|
||||
) -> Vec<TypeId> {
|
||||
// Maybe at some point we will eagerly parse named types, but for now we
|
||||
// don't and this information is unavailable.
|
||||
None
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn num_self_template_params(&self, _ctx: &BindgenContext) -> Option<usize> {
|
||||
fn num_self_template_params(&self, _ctx: &BindgenContext) -> usize {
|
||||
// Wouldn't it be nice if libclang would reliably give us this
|
||||
// information‽
|
||||
match self.decl().kind() {
|
||||
|
@ -2643,9 +2703,9 @@ impl TemplateParameters for PartialType {
|
|||
};
|
||||
clang_sys::CXChildVisit_Continue
|
||||
});
|
||||
Some(num_params)
|
||||
num_params
|
||||
}
|
||||
_ => None,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ pub trait CanDeriveCopy<'a> {
|
|||
|
||||
/// A trait that encapsulates the logic for whether or not we can trivially
|
||||
/// derive `Copy` without looking at any other types or results of fix point
|
||||
/// analsyses. This is a helper trait for fix point analysis.
|
||||
/// analyses. This is a helper trait for fix point analysis.
|
||||
pub trait CanTriviallyDeriveCopy {
|
||||
/// Return `true` if `Copy` can be trivially derived for this thing, `false`
|
||||
/// otherwise.
|
||||
|
|
|
@ -7,6 +7,7 @@ use clang;
|
|||
use ir::annotations::Annotations;
|
||||
use ir::item::ItemCanonicalPath;
|
||||
use parse::{ClangItemParser, ParseError};
|
||||
use regex_set::RegexSet;
|
||||
|
||||
/// An enum representing custom handling that can be given to a variant.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
|
@ -137,44 +138,36 @@ impl Enum {
|
|||
Ok(Enum::new(repr, variants))
|
||||
}
|
||||
|
||||
/// Whether the enum should be a bitfield
|
||||
pub fn is_bitfield(&self, ctx: &BindgenContext, item: &Item) -> bool {
|
||||
fn is_matching_enum(&self, ctx: &BindgenContext, enums: &RegexSet, item: &Item) -> bool {
|
||||
let path = item.canonical_path(ctx);
|
||||
let enum_ty = item.expect_type();
|
||||
|
||||
ctx.options().bitfield_enums.matches(&path[1..].join("::")) ||
|
||||
(enum_ty.name().is_none() &&
|
||||
self.variants().iter().any(|v| {
|
||||
ctx.options().bitfield_enums.matches(&v.name())
|
||||
}))
|
||||
let path_matches = enums.matches(&path[1..].join("::"));
|
||||
let enum_is_anon = enum_ty.name().is_none();
|
||||
let a_variant_matches = self.variants().iter().any(|v| {
|
||||
enums.matches(&v.name())
|
||||
});
|
||||
path_matches || (enum_is_anon && a_variant_matches)
|
||||
}
|
||||
|
||||
/// Whether the enum should be a bitfield
|
||||
pub fn is_bitfield(&self, ctx: &BindgenContext, item: &Item) -> bool {
|
||||
self.is_matching_enum(ctx, &ctx.options().bitfield_enums, item)
|
||||
}
|
||||
|
||||
/// Whether the enum should be an constified enum module
|
||||
pub fn is_constified_enum_module(
|
||||
&self,
|
||||
ctx: &BindgenContext,
|
||||
item: &Item,
|
||||
) -> bool {
|
||||
let path = item.canonical_path(ctx);
|
||||
let enum_ty = item.expect_type();
|
||||
pub fn is_constified_enum_module(&self, ctx: &BindgenContext, item: &Item) -> bool {
|
||||
self.is_matching_enum(ctx, &ctx.options().constified_enum_modules, item)
|
||||
}
|
||||
|
||||
ctx.options().constified_enum_modules.matches(&path[1..].join("::")) ||
|
||||
(enum_ty.name().is_none() &&
|
||||
self.variants().iter().any(|v| {
|
||||
ctx.options().constified_enum_modules.matches(&v.name())
|
||||
}))
|
||||
/// Whether the enum should be an set of constants
|
||||
pub fn is_constified_enum(&self, ctx: &BindgenContext, item: &Item) -> bool {
|
||||
self.is_matching_enum(ctx, &ctx.options().constified_enums, item)
|
||||
}
|
||||
|
||||
/// Whether the enum should be a Rust enum
|
||||
pub fn is_rustified_enum(&self, ctx: &BindgenContext, item: &Item) -> bool {
|
||||
let path = item.canonical_path(ctx);
|
||||
let enum_ty = item.expect_type();
|
||||
|
||||
ctx.options().rustified_enums.matches(&path[1..].join("::")) ||
|
||||
(enum_ty.name().is_none() &&
|
||||
self.variants().iter().any(|v| {
|
||||
ctx.options().rustified_enums.matches(&v.name())
|
||||
}))
|
||||
self.is_matching_enum(ctx, &ctx.options().rustified_enums, item)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -193,7 +193,7 @@ impl Abi {
|
|||
|
||||
impl quote::ToTokens for Abi {
|
||||
fn to_tokens(&self, tokens: &mut quote::Tokens) {
|
||||
tokens.append(match *self {
|
||||
tokens.append_all(match *self {
|
||||
Abi::C => quote! { "C" },
|
||||
Abi::Stdcall => quote! { "stdcall" },
|
||||
Abi::Fastcall => quote! { "fastcall" },
|
||||
|
@ -402,14 +402,27 @@ impl FunctionSig {
|
|||
let is_virtual = is_method && cursor.method_is_virtual();
|
||||
let is_static = is_method && cursor.method_is_static();
|
||||
if !is_static && !is_virtual {
|
||||
let class = Item::parse(cursor.semantic_parent(), None, ctx)
|
||||
let parent = cursor.semantic_parent();
|
||||
let class = Item::parse(parent, None, ctx)
|
||||
.expect("Expected to parse the class");
|
||||
// The `class` most likely is not finished parsing yet, so use
|
||||
// the unchecked variant.
|
||||
let class = class.as_type_id_unchecked();
|
||||
|
||||
let class = if is_const {
|
||||
let const_class_id = ctx.next_item_id();
|
||||
ctx.build_const_wrapper(
|
||||
const_class_id,
|
||||
class,
|
||||
None,
|
||||
&parent.cur_type(),
|
||||
)
|
||||
} else {
|
||||
class
|
||||
};
|
||||
|
||||
let ptr =
|
||||
Item::builtin_type(TypeKind::Pointer(class), is_const, ctx);
|
||||
Item::builtin_type(TypeKind::Pointer(class), false, ctx);
|
||||
args.insert(0, (Some("this".into()), ptr));
|
||||
} else if is_virtual {
|
||||
let void = Item::builtin_type(TypeKind::Void, false, ctx);
|
||||
|
|
|
@ -1112,8 +1112,8 @@ where
|
|||
fn self_template_params(
|
||||
&self,
|
||||
ctx: &BindgenContext,
|
||||
) -> Option<Vec<TypeId>> {
|
||||
ctx.resolve_item_fallible(*self).and_then(|item| {
|
||||
) -> Vec<TypeId> {
|
||||
ctx.resolve_item_fallible(*self).map_or(vec![], |item| {
|
||||
item.self_template_params(ctx)
|
||||
})
|
||||
}
|
||||
|
@ -1123,7 +1123,7 @@ impl TemplateParameters for Item {
|
|||
fn self_template_params(
|
||||
&self,
|
||||
ctx: &BindgenContext,
|
||||
) -> Option<Vec<TypeId>> {
|
||||
) -> Vec<TypeId> {
|
||||
self.kind.self_template_params(ctx)
|
||||
}
|
||||
}
|
||||
|
@ -1132,7 +1132,7 @@ impl TemplateParameters for ItemKind {
|
|||
fn self_template_params(
|
||||
&self,
|
||||
ctx: &BindgenContext,
|
||||
) -> Option<Vec<TypeId>> {
|
||||
) -> Vec<TypeId> {
|
||||
match *self {
|
||||
ItemKind::Type(ref ty) => ty.self_template_params(ctx),
|
||||
// If we start emitting bindings to explicitly instantiated
|
||||
|
@ -1140,7 +1140,7 @@ impl TemplateParameters for ItemKind {
|
|||
// template params.
|
||||
ItemKind::Function(_) |
|
||||
ItemKind::Module(_) |
|
||||
ItemKind::Var(_) => None,
|
||||
ItemKind::Var(_) => vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1449,8 +1449,8 @@ impl ClangItemParser for Item {
|
|||
return Ok(Item::new_opaque_type(id, ty, ctx));
|
||||
}
|
||||
|
||||
if let Some(id) = Item::type_param(Some(id), location, ctx) {
|
||||
return Ok(id);
|
||||
if let Some(param_id) = Item::type_param(None, location, ctx) {
|
||||
return Ok(ctx.build_ty_wrapper(id, param_id, None, ty));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,9 @@ use super::derive::{CanTriviallyDeriveCopy, CanTriviallyDeriveDebug,
|
|||
CanTriviallyDeriveDefault, CanTriviallyDeriveHash,
|
||||
CanTriviallyDerivePartialEqOrPartialOrd, CanDerive};
|
||||
use super::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, Type, TypeKind};
|
||||
use ir::context::BindgenContext;
|
||||
use clang;
|
||||
use std::{cmp, mem};
|
||||
use std::cmp;
|
||||
|
||||
/// A type that represents the struct layout of a type.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
|
@ -20,10 +21,15 @@ pub struct Layout {
|
|||
|
||||
#[test]
|
||||
fn test_layout_for_size() {
|
||||
use std::mem;
|
||||
|
||||
let ptr_size = mem::size_of::<*mut ()>();
|
||||
assert_eq!(Layout::for_size(ptr_size), Layout::new(ptr_size, ptr_size));
|
||||
assert_eq!(
|
||||
Layout::for_size(3 * ptr_size),
|
||||
Layout::for_size_internal(ptr_size, ptr_size),
|
||||
Layout::new(ptr_size, ptr_size)
|
||||
);
|
||||
assert_eq!(
|
||||
Layout::for_size_internal(ptr_size, 3 * ptr_size),
|
||||
Layout::new(3 * ptr_size, ptr_size)
|
||||
);
|
||||
}
|
||||
|
@ -39,13 +45,9 @@ impl Layout {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a non-packed layout for a given size, trying to use the maximum
|
||||
/// alignment possible.
|
||||
pub fn for_size(size: usize) -> Self {
|
||||
fn for_size_internal(ptr_size: usize, size: usize) -> Self {
|
||||
let mut next_align = 2;
|
||||
while size % next_align == 0 &&
|
||||
next_align <= mem::size_of::<*mut ()>()
|
||||
{
|
||||
while size % next_align == 0 && next_align <= ptr_size {
|
||||
next_align *= 2;
|
||||
}
|
||||
Layout {
|
||||
|
@ -55,6 +57,12 @@ impl Layout {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a non-packed layout for a given size, trying to use the maximum
|
||||
/// alignment possible.
|
||||
pub fn for_size(ctx: &BindgenContext, size: usize) -> Self {
|
||||
Self::for_size_internal(ctx.target_pointer_size(), size)
|
||||
}
|
||||
|
||||
/// Is this a zero-sized layout?
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.size == 0 && self.align == 0
|
||||
|
@ -80,7 +88,8 @@ impl Opaque {
|
|||
pub fn from_clang_ty(ty: &clang::Type) -> Type {
|
||||
let layout = Layout::new(ty.size(), ty.align());
|
||||
let ty_kind = TypeKind::Opaque;
|
||||
Type::new(None, Some(layout), ty_kind, false)
|
||||
let is_const = ty.is_const();
|
||||
Type::new(None, Some(layout), ty_kind, is_const)
|
||||
}
|
||||
|
||||
/// Return the known rust type we should use to create a correctly-aligned
|
||||
|
|
|
@ -13,6 +13,7 @@ use clang_sys::CXCursor_ObjCInstanceMethodDecl;
|
|||
use clang_sys::CXCursor_ObjCProtocolDecl;
|
||||
use clang_sys::CXCursor_ObjCProtocolRef;
|
||||
use quote;
|
||||
use proc_macro2::{Term, Span};
|
||||
|
||||
/// Objective C interface as used in TypeKind
|
||||
///
|
||||
|
@ -216,7 +217,7 @@ impl ObjCMethod {
|
|||
let split_name: Vec<_> = self.name
|
||||
.split(':')
|
||||
.filter(|p| !p.is_empty())
|
||||
.map(quote::Ident::new)
|
||||
.map(|name| Term::new(name, Span::call_site()))
|
||||
.collect();
|
||||
|
||||
// No arguments
|
||||
|
@ -239,9 +240,10 @@ impl ObjCMethod {
|
|||
// Get arguments without type signatures to pass to `msg_send!`
|
||||
let mut args_without_types = vec![];
|
||||
for arg in args.iter() {
|
||||
let name_and_sig: Vec<&str> = arg.as_str().split(' ').collect();
|
||||
let arg = arg.to_string();
|
||||
let name_and_sig: Vec<&str> = arg.split(' ').collect();
|
||||
let name = name_and_sig[0];
|
||||
args_without_types.push(quote::Ident::new(name))
|
||||
args_without_types.push(Term::new(name, Span::call_site()))
|
||||
};
|
||||
|
||||
let args = split_name
|
||||
|
|
|
@ -81,23 +81,23 @@ use parse::ClangItemParser;
|
|||
/// +------+----------------------+--------------------------+------------------------+----
|
||||
/// |Decl. | self_template_params | num_self_template_params | all_template_parameters| ...
|
||||
/// +------+----------------------+--------------------------+------------------------+----
|
||||
/// |Foo | Some([T, U]) | Some(2) | Some([T, U]) | ...
|
||||
/// |Bar | Some([V]) | Some(1) | Some([T, U, V]) | ...
|
||||
/// |Inner | None | None | Some([T, U]) | ...
|
||||
/// |Lol | Some([W]) | Some(1) | Some([T, U, W]) | ...
|
||||
/// |Wtf | Some([X]) | Some(1) | Some([T, U, X]) | ...
|
||||
/// |Qux | None | None | None | ...
|
||||
/// |Foo | [T, U] | 2 | [T, U] | ...
|
||||
/// |Bar | [V] | 1 | [T, U, V] | ...
|
||||
/// |Inner | [] | 0 | [T, U] | ...
|
||||
/// |Lol | [W] | 1 | [T, U, W] | ...
|
||||
/// |Wtf | [X] | 1 | [T, U, X] | ...
|
||||
/// |Qux | [] | 0 | [] | ...
|
||||
/// +------+----------------------+--------------------------+------------------------+----
|
||||
///
|
||||
/// ----+------+-----+----------------------+
|
||||
/// ... |Decl. | ... | used_template_params |
|
||||
/// ----+------+-----+----------------------+
|
||||
/// ... |Foo | ... | Some([T, U]) |
|
||||
/// ... |Bar | ... | Some([V]) |
|
||||
/// ... |Inner | ... | None |
|
||||
/// ... |Lol | ... | Some([T]) |
|
||||
/// ... |Wtf | ... | Some([T]) |
|
||||
/// ... |Qux | ... | None |
|
||||
/// ... |Foo | ... | [T, U] |
|
||||
/// ... |Bar | ... | [V] |
|
||||
/// ... |Inner | ... | [] |
|
||||
/// ... |Lol | ... | [T] |
|
||||
/// ... |Wtf | ... | [T] |
|
||||
/// ... |Qux | ... | [] |
|
||||
/// ----+------+-----+----------------------+
|
||||
pub trait TemplateParameters {
|
||||
/// Get the set of `ItemId`s that make up this template declaration's free
|
||||
|
@ -109,17 +109,12 @@ pub trait TemplateParameters {
|
|||
/// anything but types, so we must treat them as opaque, and avoid
|
||||
/// instantiating them.
|
||||
fn self_template_params(&self, ctx: &BindgenContext)
|
||||
-> Option<Vec<TypeId>>;
|
||||
-> Vec<TypeId>;
|
||||
|
||||
/// Get the number of free template parameters this template declaration
|
||||
/// has.
|
||||
///
|
||||
/// Implementations *may* return `Some` from this method when
|
||||
/// `template_params` returns `None`. This is useful when we only have
|
||||
/// partial information about the template declaration, such as when we are
|
||||
/// in the middle of parsing it.
|
||||
fn num_self_template_params(&self, ctx: &BindgenContext) -> Option<usize> {
|
||||
self.self_template_params(ctx).map(|params| params.len())
|
||||
fn num_self_template_params(&self, ctx: &BindgenContext) -> usize {
|
||||
self.self_template_params(ctx).len()
|
||||
}
|
||||
|
||||
/// Get the complete set of template parameters that can affect this
|
||||
|
@ -136,30 +131,20 @@ pub trait TemplateParameters {
|
|||
/// how we would fully reference such a member type in C++:
|
||||
/// `Foo<int,char>::Inner`. `Foo` *must* be instantiated with template
|
||||
/// arguments before we can gain access to the `Inner` member type.
|
||||
fn all_template_params(&self, ctx: &BindgenContext) -> Option<Vec<TypeId>>
|
||||
fn all_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>
|
||||
where
|
||||
Self: ItemAncestors,
|
||||
{
|
||||
let each_self_params: Vec<Vec<_>> = self.ancestors(ctx)
|
||||
.filter_map(|id| id.self_template_params(ctx))
|
||||
.collect();
|
||||
if each_self_params.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
each_self_params
|
||||
.into_iter()
|
||||
.rev()
|
||||
.flat_map(|params| params)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
let ancestors: Vec<_> = self.ancestors(ctx).collect();
|
||||
ancestors.into_iter().rev().flat_map(|id| {
|
||||
id.self_template_params(ctx).into_iter()
|
||||
}).collect()
|
||||
}
|
||||
|
||||
/// Get only the set of template parameters that this item uses. This is a
|
||||
/// subset of `all_template_params` and does not necessarily contain any of
|
||||
/// `self_template_params`.
|
||||
fn used_template_params(&self, ctx: &BindgenContext) -> Option<Vec<TypeId>>
|
||||
fn used_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>
|
||||
where
|
||||
Self: AsRef<ItemId>,
|
||||
{
|
||||
|
@ -169,14 +154,10 @@ pub trait TemplateParameters {
|
|||
);
|
||||
|
||||
let id = *self.as_ref();
|
||||
ctx.resolve_item(id).all_template_params(ctx).map(
|
||||
|all_params| {
|
||||
all_params
|
||||
ctx.resolve_item(id).all_template_params(ctx)
|
||||
.into_iter()
|
||||
.filter(|p| ctx.uses_template_parameter(id, *p))
|
||||
.collect()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -201,11 +201,13 @@ pub fn all_edges(_: &BindgenContext, _: Edge) -> bool {
|
|||
true
|
||||
}
|
||||
|
||||
/// A `TraversalPredicate` implementation that never follows any edges, and
|
||||
/// therefore traversals using this predicate will only visit the traversal's
|
||||
/// roots.
|
||||
pub fn no_edges(_: &BindgenContext, _: Edge) -> bool {
|
||||
false
|
||||
/// A `TraversalPredicate` implementation that only follows
|
||||
/// `EdgeKind::InnerType` edges, and therefore traversals using this predicate
|
||||
/// will only visit the traversal's roots and their inner types. This is used
|
||||
/// in no-recursive-whitelist mode, where inner types such as anonymous
|
||||
/// structs/unions still need to be processed.
|
||||
pub fn only_inner_type_edges(_: &BindgenContext, edge: Edge) -> bool {
|
||||
edge.kind == EdgeKind::InnerType
|
||||
}
|
||||
|
||||
/// A `TraversalPredicate` implementation that only follows edges to items that
|
||||
|
|
|
@ -16,7 +16,6 @@ use clang::{self, Cursor};
|
|||
use parse::{ClangItemParser, ParseError, ParseResult};
|
||||
use std::borrow::Cow;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
|
||||
/// The base representation of a type in bindgen.
|
||||
///
|
||||
|
@ -232,8 +231,6 @@ impl Type {
|
|||
|
||||
/// What is the layout of this type?
|
||||
pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
|
||||
use std::mem;
|
||||
|
||||
self.layout.or_else(|| {
|
||||
match self.kind {
|
||||
TypeKind::Comp(ref ci) => ci.layout(ctx),
|
||||
|
@ -242,8 +239,8 @@ impl Type {
|
|||
TypeKind::Pointer(..) |
|
||||
TypeKind::BlockPointer => {
|
||||
Some(Layout::new(
|
||||
mem::size_of::<*mut ()>(),
|
||||
mem::align_of::<*mut ()>(),
|
||||
ctx.target_pointer_size(),
|
||||
ctx.target_pointer_size(),
|
||||
))
|
||||
}
|
||||
TypeKind::ResolvedTypeRef(inner) => {
|
||||
|
@ -543,7 +540,7 @@ impl TemplateParameters for Type {
|
|||
fn self_template_params(
|
||||
&self,
|
||||
ctx: &BindgenContext,
|
||||
) -> Option<Vec<TypeId>> {
|
||||
) -> Vec<TypeId> {
|
||||
self.kind.self_template_params(ctx)
|
||||
}
|
||||
}
|
||||
|
@ -552,13 +549,13 @@ impl TemplateParameters for TypeKind {
|
|||
fn self_template_params(
|
||||
&self,
|
||||
ctx: &BindgenContext,
|
||||
) -> Option<Vec<TypeId>> {
|
||||
) -> Vec<TypeId> {
|
||||
match *self {
|
||||
TypeKind::ResolvedTypeRef(id) => {
|
||||
ctx.resolve_type(id).self_template_params(ctx)
|
||||
}
|
||||
TypeKind::Comp(ref comp) => comp.self_template_params(ctx),
|
||||
TypeKind::TemplateAlias(_, ref args) => Some(args.clone()),
|
||||
TypeKind::TemplateAlias(_, ref args) => args.clone(),
|
||||
|
||||
TypeKind::Opaque |
|
||||
TypeKind::TemplateInstantiation(..) |
|
||||
|
@ -578,7 +575,7 @@ impl TemplateParameters for TypeKind {
|
|||
TypeKind::Alias(_) |
|
||||
TypeKind::ObjCId |
|
||||
TypeKind::ObjCSel |
|
||||
TypeKind::ObjCInterface(_) => None,
|
||||
TypeKind::ObjCInterface(_) => vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -596,17 +593,6 @@ pub enum FloatKind {
|
|||
Float128,
|
||||
}
|
||||
|
||||
impl FloatKind {
|
||||
/// If this type has a known size, return it (in bytes).
|
||||
pub fn known_size(&self) -> usize {
|
||||
match *self {
|
||||
FloatKind::Float => mem::size_of::<f32>(),
|
||||
FloatKind::Double | FloatKind::LongDouble => mem::size_of::<f64>(),
|
||||
FloatKind::Float128 => mem::size_of::<f64>() * 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The different kinds of types that we can parse.
|
||||
#[derive(Debug)]
|
||||
pub enum TypeKind {
|
||||
|
@ -1208,6 +1194,7 @@ impl Type {
|
|||
};
|
||||
|
||||
let name = if name.is_empty() { None } else { Some(name) };
|
||||
|
||||
let is_const = ty.is_const();
|
||||
|
||||
let ty = Type::new(name, layout, kind, is_const);
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
//! functions and use types defined in the header.
|
||||
//!
|
||||
//! See the [`Builder`](./struct.Builder.html) struct for usage.
|
||||
//!
|
||||
//! See the [Users Guide](https://rust-lang-nursery.github.io/rust-bindgen/) for
|
||||
//! additional documentation.
|
||||
#![deny(missing_docs)]
|
||||
#![deny(warnings)]
|
||||
#![deny(unused_extern_crates)]
|
||||
|
@ -23,6 +26,7 @@ extern crate lazy_static;
|
|||
extern crate peeking_take_while;
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
extern crate proc_macro2;
|
||||
extern crate regex;
|
||||
extern crate which;
|
||||
|
||||
|
@ -79,8 +83,10 @@ use ir::context::{BindgenContext, ItemId};
|
|||
use ir::item::Item;
|
||||
use parse::{ClangItemParser, ParseError};
|
||||
use regex_set::RegexSet;
|
||||
pub use codegen::EnumVariation;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::{self, Write};
|
||||
use std::iter;
|
||||
|
@ -155,6 +161,23 @@ impl Default for CodegenConfig {
|
|||
/// // Write the generated bindings to an output file.
|
||||
/// bindings.write_to_file("path/to/output.rs")?;
|
||||
/// ```
|
||||
///
|
||||
/// # Enums
|
||||
///
|
||||
/// Bindgen can map C/C++ enums into Rust in different ways. The way bindgen maps enums depends on
|
||||
/// the pattern passed to several methods:
|
||||
///
|
||||
/// 1. [`constified_enum_module()`](#method.constified_enum_module)
|
||||
/// 2. [`bitfield_enum()`](#method.bitfield_enum)
|
||||
/// 3. [`rustified_enum()`](#method.rustified_enum)
|
||||
///
|
||||
/// For each C enum, bindgen tries to match the pattern in the following order:
|
||||
///
|
||||
/// 1. Constified enum module
|
||||
/// 2. Bitfield enum
|
||||
/// 3. Rustified enum
|
||||
///
|
||||
/// If none of the above patterns match, then bindgen will generate a set of Rust constants.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Builder {
|
||||
options: BindgenOptions,
|
||||
|
@ -181,6 +204,16 @@ impl Builder {
|
|||
output_vector.push("--rust-target".into());
|
||||
output_vector.push(self.options.rust_target.into());
|
||||
|
||||
if self.options.default_enum_style != Default::default() {
|
||||
output_vector.push("--default-enum-variant=".into());
|
||||
output_vector.push(match self.options.default_enum_style {
|
||||
codegen::EnumVariation::Rust => "rust",
|
||||
codegen::EnumVariation::Bitfield => "bitfield",
|
||||
codegen::EnumVariation::Consts => "consts",
|
||||
codegen::EnumVariation::ModuleConsts => "moduleconsts",
|
||||
}.into())
|
||||
}
|
||||
|
||||
self.options
|
||||
.bitfield_enums
|
||||
.get_items()
|
||||
|
@ -223,6 +256,20 @@ impl Builder {
|
|||
})
|
||||
.count();
|
||||
|
||||
self.options
|
||||
.constified_enums
|
||||
.get_items()
|
||||
.iter()
|
||||
.map(|item| {
|
||||
output_vector.push("--constified-enum".into());
|
||||
output_vector.push(
|
||||
item.trim_left_matches("^")
|
||||
.trim_right_matches("$")
|
||||
.into(),
|
||||
);
|
||||
})
|
||||
.count();
|
||||
|
||||
self.options
|
||||
.blacklisted_types
|
||||
.get_items()
|
||||
|
@ -326,19 +373,6 @@ impl Builder {
|
|||
output_vector.push("--disable-name-namespacing".into());
|
||||
}
|
||||
|
||||
self.options
|
||||
.links
|
||||
.iter()
|
||||
.map(|&(ref item, _)| {
|
||||
output_vector.push("--framework".into());
|
||||
output_vector.push(
|
||||
item.trim_left_matches("^")
|
||||
.trim_right_matches("$")
|
||||
.into(),
|
||||
);
|
||||
})
|
||||
.count();
|
||||
|
||||
if !self.options.codegen_config.functions {
|
||||
output_vector.push("--ignore-functions".into());
|
||||
}
|
||||
|
@ -372,19 +406,6 @@ impl Builder {
|
|||
output_vector.push("--ignore-methods".into());
|
||||
}
|
||||
|
||||
self.options
|
||||
.links
|
||||
.iter()
|
||||
.map(|&(ref item, _)| {
|
||||
output_vector.push("--clang-args".into());
|
||||
output_vector.push(
|
||||
item.trim_left_matches("^")
|
||||
.trim_right_matches("$")
|
||||
.into(),
|
||||
);
|
||||
})
|
||||
.count();
|
||||
|
||||
if !self.options.convert_floats {
|
||||
output_vector.push("--no-convert-floats".into());
|
||||
}
|
||||
|
@ -420,19 +441,6 @@ impl Builder {
|
|||
})
|
||||
.count();
|
||||
|
||||
self.options
|
||||
.links
|
||||
.iter()
|
||||
.map(|&(ref item, _)| {
|
||||
output_vector.push("--static".into());
|
||||
output_vector.push(
|
||||
item.trim_left_matches("^")
|
||||
.trim_right_matches("$")
|
||||
.into(),
|
||||
);
|
||||
})
|
||||
.count();
|
||||
|
||||
if self.options.use_core {
|
||||
output_vector.push("--use-core".into());
|
||||
}
|
||||
|
@ -600,6 +608,12 @@ impl Builder {
|
|||
self
|
||||
}
|
||||
|
||||
/// Disable support for native Rust unions, if supported.
|
||||
pub fn disable_untagged_union(mut self) -> Self {
|
||||
self.options.rust_features.untagged_union = false;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the output graphviz file.
|
||||
pub fn emit_ir_graphviz<T: Into<String>>(mut self, path: T) -> Builder {
|
||||
let path = path.into();
|
||||
|
@ -642,7 +656,7 @@ impl Builder {
|
|||
///
|
||||
/// **Disabling this feature will almost certainly cause `bindgen` to emit
|
||||
/// bindings that will not compile!** If you disable this feature, then it
|
||||
/// is *your* responsiblity to provide definitions for every type that is
|
||||
/// is *your* responsibility to provide definitions for every type that is
|
||||
/// referenced from an explicitly whitelisted item. One way to provide the
|
||||
/// definitions is by using the [`Builder::raw_line`](#method.raw_line)
|
||||
/// method, another would be to define them in Rust and then `include!(...)`
|
||||
|
@ -740,6 +754,11 @@ impl Builder {
|
|||
self.whitelist_var(arg)
|
||||
}
|
||||
|
||||
/// Set the default style of code to generate for enums
|
||||
pub fn default_enum_style(mut self, arg: codegen::EnumVariation) -> Builder {
|
||||
self.options.default_enum_style = arg;
|
||||
self
|
||||
}
|
||||
|
||||
/// Mark the given enum (or set of enums, if using a pattern) as being
|
||||
/// bitfield-like. Regular expressions are supported.
|
||||
|
@ -766,6 +785,13 @@ impl Builder {
|
|||
self
|
||||
}
|
||||
|
||||
/// Mark the given enum (or set of enums, if using a pattern) as a set of
|
||||
/// constants that are not to be put into a module.
|
||||
pub fn constified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
|
||||
self.options.constified_enums.insert(arg);
|
||||
self
|
||||
}
|
||||
|
||||
/// Mark the given enum (or set of enums, if using a pattern) as a set of
|
||||
/// constants that should be put into a module.
|
||||
///
|
||||
|
@ -778,11 +804,40 @@ impl Builder {
|
|||
|
||||
/// Add a string to prepend to the generated bindings. The string is passed
|
||||
/// through without any modification.
|
||||
pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Builder {
|
||||
pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Self {
|
||||
self.options.raw_lines.push(arg.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a given line to the beginning of module `mod`.
|
||||
pub fn module_raw_line<T, U>(mut self, mod_: T, line: U) -> Self
|
||||
where
|
||||
T: Into<String>,
|
||||
U: Into<String>,
|
||||
{
|
||||
self.options
|
||||
.module_lines
|
||||
.entry(mod_.into())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(line.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a given set of lines to the beginning of module `mod`.
|
||||
pub fn module_raw_lines<T, I>(mut self, mod_: T, lines: I) -> Self
|
||||
where
|
||||
T: Into<String>,
|
||||
I: IntoIterator,
|
||||
I::Item: Into<String>,
|
||||
{
|
||||
self.options
|
||||
.module_lines
|
||||
.entry(mod_.into())
|
||||
.or_insert_with(Vec::new)
|
||||
.extend(lines.into_iter().map(Into::into));
|
||||
self
|
||||
}
|
||||
|
||||
/// Add an argument to be passed straight through to clang.
|
||||
pub fn clang_arg<T: Into<String>>(mut self, arg: T) -> Builder {
|
||||
self.options.clang_args.push(arg.into());
|
||||
|
@ -801,26 +856,6 @@ impl Builder {
|
|||
self
|
||||
}
|
||||
|
||||
/// Make the generated bindings link the given shared library.
|
||||
pub fn link<T: Into<String>>(mut self, library: T) -> Builder {
|
||||
self.options.links.push((library.into(), LinkType::Default));
|
||||
self
|
||||
}
|
||||
|
||||
/// Make the generated bindings link the given static library.
|
||||
pub fn link_static<T: Into<String>>(mut self, library: T) -> Builder {
|
||||
self.options.links.push((library.into(), LinkType::Static));
|
||||
self
|
||||
}
|
||||
|
||||
/// Make the generated bindings link the given framework.
|
||||
pub fn link_framework<T: Into<String>>(mut self, library: T) -> Builder {
|
||||
self.options.links.push(
|
||||
(library.into(), LinkType::Framework),
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
/// Emit bindings for builtin definitions (for example `__builtin_va_list`)
|
||||
/// in the generated Rust.
|
||||
pub fn emit_builtins(mut self) -> Builder {
|
||||
|
@ -1242,6 +1277,9 @@ struct BindgenOptions {
|
|||
/// Whitelisted variables. See docs for `whitelisted_types` for more.
|
||||
whitelisted_vars: RegexSet,
|
||||
|
||||
/// The default style of code to generate for enums
|
||||
default_enum_style: codegen::EnumVariation,
|
||||
|
||||
/// The enum patterns to mark an enum as bitfield.
|
||||
bitfield_enums: RegexSet,
|
||||
|
||||
|
@ -1251,12 +1289,12 @@ struct BindgenOptions {
|
|||
/// The enum patterns to mark an enum as a module of constants.
|
||||
constified_enum_modules: RegexSet,
|
||||
|
||||
/// The enum patterns to mark an enum as a set of constants.
|
||||
constified_enums: RegexSet,
|
||||
|
||||
/// Whether we should generate builtins or not.
|
||||
builtins: bool,
|
||||
|
||||
/// The set of libraries we should link in the generated Rust code.
|
||||
links: Vec<(String, LinkType)>,
|
||||
|
||||
/// True if we should dump the Clang AST for debugging purposes.
|
||||
emit_ast: bool,
|
||||
|
||||
|
@ -1281,7 +1319,7 @@ struct BindgenOptions {
|
|||
impl_debug: bool,
|
||||
|
||||
/// True if we should implement the PartialEq trait for C/C++ structures and types
|
||||
/// that do not support autoamically deriving PartialEq.
|
||||
/// that do not support automatically deriving PartialEq.
|
||||
impl_partialeq: bool,
|
||||
|
||||
/// True if we should derive Copy trait implementations for C/C++ structures
|
||||
|
@ -1335,9 +1373,15 @@ struct BindgenOptions {
|
|||
/// Whether we should convert float types to f32/f64 types.
|
||||
convert_floats: bool,
|
||||
|
||||
/// The set of raw lines to prepend to the generated Rust code.
|
||||
/// The set of raw lines to prepend to the top-level module of generated
|
||||
/// Rust code.
|
||||
raw_lines: Vec<String>,
|
||||
|
||||
/// The set of raw lines to prepend to each of the modules.
|
||||
///
|
||||
/// This only makes sense if the `enable_cxx_namespaces` option is set.
|
||||
module_lines: HashMap<String, Vec<String>>,
|
||||
|
||||
/// The set of arguments to pass straight through to Clang.
|
||||
clang_args: Vec<String>,
|
||||
|
||||
|
@ -1360,17 +1404,17 @@ struct BindgenOptions {
|
|||
/// See the builder method description for more details.
|
||||
conservative_inline_namespaces: bool,
|
||||
|
||||
/// Wether to keep documentation comments in the generated output. See the
|
||||
/// Whether to keep documentation comments in the generated output. See the
|
||||
/// documentation for more details.
|
||||
generate_comments: bool,
|
||||
|
||||
/// Whether to generate inline functions. Defaults to false.
|
||||
generate_inline_functions: bool,
|
||||
|
||||
/// Wether to whitelist types recursively. Defaults to true.
|
||||
/// Whether to whitelist types recursively. Defaults to true.
|
||||
whitelist_recursively: bool,
|
||||
|
||||
/// Intead of emitting 'use objc;' to files generated from objective c files,
|
||||
/// Instead of emitting 'use objc;' to files generated from objective c files,
|
||||
/// generate '#[macro_use] extern crate objc;'
|
||||
objc_extern_crate: bool,
|
||||
|
||||
|
@ -1423,6 +1467,7 @@ impl BindgenOptions {
|
|||
self.blacklisted_types.build();
|
||||
self.opaque_types.build();
|
||||
self.bitfield_enums.build();
|
||||
self.constified_enums.build();
|
||||
self.constified_enum_modules.build();
|
||||
self.rustified_enums.build();
|
||||
self.no_partialeq_types.build();
|
||||
|
@ -1457,11 +1502,12 @@ impl Default for BindgenOptions {
|
|||
whitelisted_types: Default::default(),
|
||||
whitelisted_functions: Default::default(),
|
||||
whitelisted_vars: Default::default(),
|
||||
default_enum_style: Default::default(),
|
||||
bitfield_enums: Default::default(),
|
||||
rustified_enums: Default::default(),
|
||||
constified_enums: Default::default(),
|
||||
constified_enum_modules: Default::default(),
|
||||
builtins: false,
|
||||
links: vec![],
|
||||
emit_ast: false,
|
||||
emit_ir: false,
|
||||
emit_ir_graphviz: None,
|
||||
|
@ -1484,6 +1530,7 @@ impl Default for BindgenOptions {
|
|||
msvc_mangling: false,
|
||||
convert_floats: true,
|
||||
raw_lines: vec![],
|
||||
module_lines: HashMap::default(),
|
||||
clang_args: vec![],
|
||||
input_header: None,
|
||||
input_unsaved_files: vec![],
|
||||
|
@ -1506,19 +1553,6 @@ impl Default for BindgenOptions {
|
|||
}
|
||||
}
|
||||
|
||||
/// The linking type to use with a given library.
|
||||
///
|
||||
/// TODO: #104: This is ignored at the moment, but shouldn't be.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum LinkType {
|
||||
/// Use shared library linking. This is the default.
|
||||
Default,
|
||||
/// Use static linking.
|
||||
Static,
|
||||
/// The library is an OSX framework.
|
||||
Framework,
|
||||
}
|
||||
|
||||
fn ensure_libclang_is_loaded() {
|
||||
if clang_sys::is_loaded() {
|
||||
return;
|
||||
|
@ -1696,7 +1730,7 @@ impl Bindings {
|
|||
writer.write("\n".as_bytes())?;
|
||||
}
|
||||
|
||||
let bindings = self.module.as_str().to_string();
|
||||
let bindings = self.module.to_string();
|
||||
|
||||
match self.rustfmt_generated_string(&bindings) {
|
||||
Ok(rustfmt_bindings) => {
|
||||
|
@ -1704,7 +1738,7 @@ impl Bindings {
|
|||
},
|
||||
Err(err) => {
|
||||
eprintln!("{:?}", err);
|
||||
writer.write(bindings.as_str().as_bytes())?;
|
||||
writer.write(bindings.as_bytes())?;
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
|
@ -1865,13 +1899,13 @@ fn parse(context: &mut BindgenContext) -> Result<(), ()> {
|
|||
/// Extracted Clang version data
|
||||
#[derive(Debug)]
|
||||
pub struct ClangVersion {
|
||||
/// Major and minor semvar, if parsing was successful
|
||||
/// Major and minor semver, if parsing was successful
|
||||
pub parsed: Option<(u32, u32)>,
|
||||
/// full version string
|
||||
pub full: String,
|
||||
}
|
||||
|
||||
/// Get the major and the minor semvar numbers of Clang's version
|
||||
/// Get the major and the minor semver numbers of Clang's version
|
||||
pub fn clang_version() -> ClangVersion {
|
||||
if !clang_sys::is_loaded() {
|
||||
// TODO(emilio): Return meaningful error (breaking).
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use bindgen::{Builder, CodegenConfig, RUST_TARGET_STRINGS, RustTarget, builder};
|
||||
use bindgen::{Builder, CodegenConfig, RUST_TARGET_STRINGS, RustTarget, builder, EnumVariation};
|
||||
use clap::{App, Arg};
|
||||
use std::fs::File;
|
||||
use std::io::{self, Error, ErrorKind, Write, stderr};
|
||||
|
@ -26,18 +26,32 @@ where
|
|||
Arg::with_name("header")
|
||||
.help("C or C++ header file")
|
||||
.required(true),
|
||||
Arg::with_name("default-enum-style")
|
||||
.long("default-enum-style")
|
||||
.help("The default style of code used to generate enums.")
|
||||
.value_name("variant")
|
||||
.default_value("consts")
|
||||
.possible_values(&["consts", "moduleconsts", "bitfield", "rust"])
|
||||
.multiple(false),
|
||||
Arg::with_name("bitfield-enum")
|
||||
.long("bitfield-enum")
|
||||
.help("Mark any enum whose name matches <regex> as a set of \
|
||||
bitfield flags instead of an enumeration.")
|
||||
bitfield flags.")
|
||||
.value_name("regex")
|
||||
.takes_value(true)
|
||||
.multiple(true)
|
||||
.number_of_values(1),
|
||||
Arg::with_name("rustified-enum")
|
||||
.long("rustified-enum")
|
||||
.help("Mark any enum whose name matches <regex> as a Rust enum \
|
||||
instead of a set of constants.")
|
||||
.help("Mark any enum whose name matches <regex> as a Rust enum.")
|
||||
.value_name("regex")
|
||||
.takes_value(true)
|
||||
.multiple(true)
|
||||
.number_of_values(1),
|
||||
Arg::with_name("constified-enum")
|
||||
.long("constified-enum")
|
||||
.help("Mark any enum whose name matches <regex> as a series of \
|
||||
constants.")
|
||||
.value_name("regex")
|
||||
.takes_value(true)
|
||||
.multiple(true)
|
||||
|
@ -45,7 +59,7 @@ where
|
|||
Arg::with_name("constified-enum-module")
|
||||
.long("constified-enum-module")
|
||||
.help("Mark any enum whose name matches <regex> as a module of \
|
||||
constants instead of just constants.")
|
||||
constants.")
|
||||
.value_name("regex")
|
||||
.takes_value(true)
|
||||
.multiple(true)
|
||||
|
@ -149,12 +163,6 @@ where
|
|||
.help("Disable namespacing via mangling, causing bindgen to \
|
||||
generate names like \"Baz\" instead of \"foo_bar_Baz\" \
|
||||
for an input name \"foo::bar::Baz\"."),
|
||||
Arg::with_name("framework")
|
||||
.long("framework-link")
|
||||
.help("Link to framework.")
|
||||
.takes_value(true)
|
||||
.multiple(true)
|
||||
.number_of_values(1),
|
||||
Arg::with_name("ignore-functions")
|
||||
.long("ignore-functions")
|
||||
.help("Do not generate bindings for functions or methods. This \
|
||||
|
@ -168,13 +176,6 @@ where
|
|||
Arg::with_name("ignore-methods")
|
||||
.long("ignore-methods")
|
||||
.help("Do not generate bindings for methods."),
|
||||
Arg::with_name("dynamic")
|
||||
.short("l")
|
||||
.long("link")
|
||||
.help("Link to dynamic library.")
|
||||
.takes_value(true)
|
||||
.multiple(true)
|
||||
.number_of_values(1),
|
||||
Arg::with_name("no-convert-floats")
|
||||
.long("no-convert-floats")
|
||||
.help("Do not automatically convert floats to f32/f64."),
|
||||
|
@ -207,12 +208,6 @@ where
|
|||
.long("rust-target")
|
||||
.help(&rust_target_help)
|
||||
.takes_value(true),
|
||||
Arg::with_name("static")
|
||||
.long("static-link")
|
||||
.help("Link to static library.")
|
||||
.takes_value(true)
|
||||
.multiple(true)
|
||||
.number_of_values(1),
|
||||
Arg::with_name("use-core")
|
||||
.long("use-core")
|
||||
.help("Use types from Rust core instead of std."),
|
||||
|
@ -322,6 +317,10 @@ where
|
|||
builder = builder.rust_target(RustTarget::from_str(rust_target)?);
|
||||
}
|
||||
|
||||
if let Some(variant) = matches.value_of("default-enum-style") {
|
||||
builder = builder.default_enum_style(EnumVariation::from_str(variant)?)
|
||||
}
|
||||
|
||||
if let Some(bitfields) = matches.values_of("bitfield-enum") {
|
||||
for regex in bitfields {
|
||||
builder = builder.bitfield_enum(regex);
|
||||
|
@ -334,6 +333,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(bitfields) = matches.values_of("constified-enum") {
|
||||
for regex in bitfields {
|
||||
builder = builder.constified_enum(regex);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(constified_mods) = matches.values_of("constified-enum-module") {
|
||||
for regex in constified_mods {
|
||||
builder = builder.constified_enum_module(regex);
|
||||
|
@ -409,12 +414,6 @@ where
|
|||
builder = builder.ctypes_prefix(prefix);
|
||||
}
|
||||
|
||||
if let Some(links) = matches.values_of("dynamic") {
|
||||
for library in links {
|
||||
builder = builder.link(library);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(what_to_generate) = matches.value_of("generate") {
|
||||
let mut config = CodegenConfig::nothing();
|
||||
for what in what_to_generate.split(",") {
|
||||
|
@ -456,12 +455,6 @@ where
|
|||
builder = builder.disable_name_namespacing();
|
||||
}
|
||||
|
||||
if let Some(links) = matches.values_of("framework") {
|
||||
for framework in links {
|
||||
builder = builder.link_framework(framework);
|
||||
}
|
||||
}
|
||||
|
||||
if matches.is_present("ignore-functions") {
|
||||
builder = builder.ignore_functions();
|
||||
}
|
||||
|
@ -498,12 +491,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(links) = matches.values_of("static") {
|
||||
for library in links {
|
||||
builder = builder.link_static(library);
|
||||
}
|
||||
}
|
||||
|
||||
if matches.is_present("use-core") {
|
||||
builder = builder.use_core();
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ impl<'a> Timer<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Sets whether or not the Timer will print a mesage
|
||||
/// Sets whether or not the Timer will print a message
|
||||
/// when it is dropped.
|
||||
pub fn with_output(mut self, output: bool) -> Self {
|
||||
self.output = output;
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{".travis.yml":"d5c89494c836e00ec8c3c02c9e228bf5dc34aabff203c37662a248e2da4bda05","CHANGELOG.md":"2d6ade5cd80d388392915d24f4712e8fd604579c7b26d48aa99908499e08817d","CONTRIBUTING.md":"4e2a45992604f07a37030bb1fc598c6f54a1785747c4f37a15a37481bbdecce8","Cargo.toml":"c2256b278d66bf80e6b62e58efa62a5fb98665c8c23dec68829b2c9fc2191962","LICENSE.txt":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","README.md":"dff1b472fe1edbc6059ff5a96e595fa8dab9e9e133d10fd761cf5dfdcc80f4c6","appveyor.yml":"c9ab8ab1ab028b27d2be176e994a0d6a255cf8bcc36e15868472b6b8abf33fac","build.rs":"e6cf2ec64466b21f3e6eb8aaf7327ccdfcc77a2067e0e19ee5e2a6f57117c09b","ci/before_install.sh":"711c9d0539fa0372980c3a288d9482a0e46d3ba0fb8f7c7c110d6488a8ec4de5","ci/install.bat":"fb636c3511ba038ccf805755ef6542237cc595e905edcd61d56abd7163321f76","ci/script.sh":"1bb1cd29bd9635cc126cdcbd6c02f3500620a231a86726bf2165a4b74baaf433","ci/test_script.bat":"73462f51aaa9a1c14ce9f55c41dc3672df64faa9789725384ae4f28d8ba3c90b","clippy.toml":"acef14b9acffa18d1069ae08a4e8fe824a614f91b0bc71a6b1c68e4d885397e6","src/lib.rs":"a0410d2e23f808ba441e7bebe84785e85582c8130613e49c7b3b98e0aaf55b66","src/link.rs":"7323c3ddcd8038b899c21f7087666628f88e9cb430900549855ea78717824e6f","src/support.rs":"ecd0489662caad0a13ea468cbbbec3ca62ba9796a6e24aabb392978a3455ebfd","tests/header.h":"b1cf564b21d76db78529d1934e1481a5f0452fdedc6e32954608293c310498b6","tests/lib.rs":"e5e8a60bcaec3b5d043fde4a993d397adb56454d0b2a6adaa15df0535246f909"},"package":"939a1a34310b120d26eba35c29475933128b0ec58e24b43327f8dbe6036fc538"}
|
||||
{"files":{".travis.yml":"d5c89494c836e00ec8c3c02c9e228bf5dc34aabff203c37662a248e2da4bda05","CHANGELOG.md":"62fd8ba43afbc4da3dba40d448a5af482794aaaa99071d40dc7abf8fc1a2195b","Cargo.toml":"1ada60cd29713d4386050d2b61a9eed430827885520816b0412ed0380fa3fa8f","LICENSE.txt":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","README.md":"dff1b472fe1edbc6059ff5a96e595fa8dab9e9e133d10fd761cf5dfdcc80f4c6","appveyor.yml":"c9ab8ab1ab028b27d2be176e994a0d6a255cf8bcc36e15868472b6b8abf33fac","build.rs":"50be9c247e528ab0a354a7652fa9516906f79bbb4d128d54db7f5a9ee1ed2a86","ci/before_install.sh":"711c9d0539fa0372980c3a288d9482a0e46d3ba0fb8f7c7c110d6488a8ec4de5","ci/install.bat":"fb636c3511ba038ccf805755ef6542237cc595e905edcd61d56abd7163321f76","ci/script.sh":"1bb1cd29bd9635cc126cdcbd6c02f3500620a231a86726bf2165a4b74baaf433","ci/test_script.bat":"73462f51aaa9a1c14ce9f55c41dc3672df64faa9789725384ae4f28d8ba3c90b","clippy.toml":"acef14b9acffa18d1069ae08a4e8fe824a614f91b0bc71a6b1c68e4d885397e6","src/lib.rs":"d0a11284694f4f77448e72480addca613572d19c07fa92157e0fa717ed504abd","src/link.rs":"a0208e6b8e4840f1162b3b799b5e12dd559cc6f31a330b0eb1ba4ebe2385296d","src/support.rs":"70e77ea4337f740b13c394034c5705e962af6ee7ac4843fc7c9c7fe22ec2d074","tests/header.h":"b1cf564b21d76db78529d1934e1481a5f0452fdedc6e32954608293c310498b6","tests/lib.rs":"e5e8a60bcaec3b5d043fde4a993d397adb56454d0b2a6adaa15df0535246f909"},"package":"d7f7c04e52c35222fffcc3a115b5daf5f7e2bfb71c13c4e2321afe1fc71859c2"}
|
|
@ -1,3 +1,8 @@
|
|||
## [0.23.0] - 2018-06-16
|
||||
|
||||
### Changed
|
||||
- Changed `Clang::find` to skip dynamic libraries for an incorrect architecture on Windows
|
||||
|
||||
## [0.22.0] - 2018-03-11
|
||||
|
||||
### Added
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
# Contributing to clang-sys
|
||||
|
||||
## Pull Requests
|
||||
|
||||
If you are intending to make a pull request, please make your changes in a branch that originated
|
||||
from the `development` branch, not the `master` branch. Then, make your pull request against the
|
||||
`development` branch.
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
[package]
|
||||
name = "clang-sys"
|
||||
version = "0.22.0"
|
||||
version = "0.23.0"
|
||||
authors = ["Kyle Mayes <kyle@mayeses.com>"]
|
||||
build = "build.rs"
|
||||
links = "clang"
|
||||
|
@ -21,10 +21,6 @@ documentation = "https://kylemayes.github.io/clang-sys/3_5/clang_sys"
|
|||
readme = "README.md"
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/KyleMayes/clang-sys"
|
||||
[dependencies.clippy]
|
||||
version = "0.0.*"
|
||||
optional = true
|
||||
|
||||
[dependencies.glob]
|
||||
version = "0.2.11"
|
||||
|
||||
|
@ -34,10 +30,6 @@ version = "0.2.39"
|
|||
[dependencies.libloading]
|
||||
version = "0.5.0"
|
||||
optional = true
|
||||
[build-dependencies.clippy]
|
||||
version = "0.0.*"
|
||||
optional = true
|
||||
|
||||
[build-dependencies.glob]
|
||||
version = "0.2.11"
|
||||
|
||||
|
|
|
@ -25,15 +25,11 @@
|
|||
|
||||
#![allow(unused_attributes)]
|
||||
|
||||
#![cfg_attr(feature="clippy", feature(plugin))]
|
||||
#![cfg_attr(feature="clippy", plugin(clippy))]
|
||||
#![cfg_attr(feature="clippy", warn(clippy))]
|
||||
|
||||
extern crate glob;
|
||||
|
||||
use std::env;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{Read};
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command};
|
||||
|
||||
|
@ -128,6 +124,41 @@ const SEARCH_WINDOWS: &[&str] = &[
|
|||
"C:\\MSYS*\\MinGW*\\lib",
|
||||
];
|
||||
|
||||
/// Returns the ELF class from the ELF header in the supplied file.
|
||||
fn parse_elf_header(file: &PathBuf) -> Result<u8, String> {
|
||||
let mut file = try!(File::open(file).map_err(|e| e.to_string()));
|
||||
let mut elf = [0; 5];
|
||||
try!(file.read_exact(&mut elf).map_err(|e| e.to_string()));
|
||||
if elf[..4] == [127, 69, 76, 70] {
|
||||
Ok(elf[4])
|
||||
} else {
|
||||
Err("invalid ELF header".into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the magic number from the PE header in the supplied file.
|
||||
fn parse_pe_header(file: &PathBuf) -> Result<u16, String> {
|
||||
let mut file = try!(File::open(file).map_err(|e| e.to_string()));
|
||||
let mut pe = [0; 4];
|
||||
|
||||
// Determine the header offset.
|
||||
try!(file.seek(SeekFrom::Start(0x3C)).map_err(|e| e.to_string()));
|
||||
try!(file.read_exact(&mut pe).map_err(|e| e.to_string()));
|
||||
let offset = i32::from(pe[0]) + (i32::from(pe[1]) << 8) + (i32::from(pe[2]) << 16) + (i32::from(pe[3]) << 24);
|
||||
|
||||
// Determine the validity of the header.
|
||||
try!(file.seek(SeekFrom::Start(offset as u64)).map_err(|e| e.to_string()));
|
||||
try!(file.read_exact(&mut pe).map_err(|e| e.to_string()));
|
||||
if pe != [80, 69, 0, 0] {
|
||||
return Err("invalid PE header".into());
|
||||
}
|
||||
|
||||
// Find the magic number.
|
||||
try!(file.seek(SeekFrom::Current(20)).map_err(|e| e.to_string()));
|
||||
try!(file.read_exact(&mut pe).map_err(|e| e.to_string()));
|
||||
Ok(u16::from(pe[0]) + (u16::from(pe[1]) << 8))
|
||||
}
|
||||
|
||||
/// Indicates the type of library being searched for.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
enum Library {
|
||||
|
@ -142,19 +173,26 @@ impl Library {
|
|||
if *self == Library::Static {
|
||||
return Ok(());
|
||||
}
|
||||
let mut file = try!(File::open(file).map_err(|e| e.to_string()));
|
||||
let mut elf = [0; 5];
|
||||
try!(file.read_exact(&mut elf).map_err(|e| e.to_string()));
|
||||
if elf[..4] != [127, 69, 76, 70] {
|
||||
return Err("invalid ELF header".into());
|
||||
}
|
||||
if cfg!(target_pointer_width="32") && elf[4] != 1 {
|
||||
let class = try!(parse_elf_header(file));
|
||||
if cfg!(target_pointer_width="32") && class != 1 {
|
||||
return Err("invalid ELF class (64-bit)".into());
|
||||
}
|
||||
if cfg!(target_pointer_width="64") && elf[4] != 2 {
|
||||
if cfg!(target_pointer_width="64") && class != 2 {
|
||||
return Err("invalid ELF class (32-bit)".into());
|
||||
}
|
||||
Ok(())
|
||||
} else if cfg!(target_os="windows") {
|
||||
if *self == Library::Static {
|
||||
return Ok(());
|
||||
}
|
||||
let magic = try!(parse_pe_header(file));
|
||||
if cfg!(target_pointer_width="32") && magic != 267 {
|
||||
return Err("invalid DLL (64-bit)".into());
|
||||
}
|
||||
if cfg!(target_pointer_width="64") && magic != 523 {
|
||||
return Err("invalid DLL (32-bit)".into());
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -216,7 +254,7 @@ fn find(library: Library, files: &[String], env: &str) -> Result<PathBuf, String
|
|||
|
||||
// Search the `LD_LIBRARY_PATH` directories.
|
||||
if let Ok(path) = env::var("LD_LIBRARY_PATH") {
|
||||
for directory in path.split(":").map(Path::new) {
|
||||
for directory in path.split(':').map(Path::new) {
|
||||
search_directory!(directory);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,10 +27,7 @@
|
|||
|
||||
#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]
|
||||
|
||||
#![cfg_attr(feature="clippy", feature(plugin))]
|
||||
#![cfg_attr(feature="clippy", plugin(clippy))]
|
||||
#![cfg_attr(feature="clippy", warn(clippy))]
|
||||
#![cfg_attr(feature="clippy", allow(unreadable_literal))]
|
||||
#![cfg_attr(feature="cargo-clippy", allow(unreadable_literal))]
|
||||
|
||||
extern crate glob;
|
||||
extern crate libc;
|
||||
|
|
|
@ -80,7 +80,7 @@ macro_rules! link {
|
|||
}
|
||||
|
||||
$(
|
||||
#[cfg_attr(feature="clippy", allow(too_many_arguments))]
|
||||
#[cfg_attr(feature="cargo-clippy", allow(too_many_arguments))]
|
||||
$(#[cfg($cfg)])*
|
||||
pub unsafe fn $name($($pname: $pty), *) $(-> $ret)* {
|
||||
let f = with_library(|l| {
|
||||
|
|
|
@ -63,12 +63,7 @@ impl Clang {
|
|||
let version = parse_version(&path);
|
||||
let c_search_paths = parse_search_paths(&path, "c", args);
|
||||
let cpp_search_paths = parse_search_paths(&path, "c++", args);
|
||||
Clang {
|
||||
path: path,
|
||||
version: version,
|
||||
c_search_paths: c_search_paths,
|
||||
cpp_search_paths: cpp_search_paths,
|
||||
}
|
||||
Clang { path, version, c_search_paths, cpp_search_paths }
|
||||
}
|
||||
|
||||
/// Returns a `clang` executable if one can be found.
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{"files":{".travis.yml":"872a0d195dcb1e84f28aa994f301c7139f70360bb42dee3954df5ee965efea15","Cargo.toml":"e71f764696d6998512da00a9ac309f2717d103707aeef81164f906c1588ede63","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"ce05336717e1e90724491a2f54487c41c752fa2d32396639439f7c6d0f1e6776","src/lib.rs":"3280d7e0b6043d8472f418aa5c8458c97aa2b5a572f9156a251b5672828468c2","src/stable.rs":"4b5a65bd5dc174dd027b9ee951844c3765450f9d45961a8d6cd7d5f85b4c25c8","src/strnom.rs":"129fe22f0b50e5a64fca82e731c959135381c910e19f3305ef35420e0aadde08","src/unstable.rs":"b43c713ac16d9de0ba0fa1b9bebe390122b4ad60ef2fc75408f721305fdcd46b","tests/test.rs":"b06713fd8bd93ab9f0156bd25152e08f68a71b35e064c53b584f7f7dbb9b60b8"},"package":"77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4"}
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
[package]
|
||||
name = "proc-macro2"
|
||||
version = "0.3.6"
|
||||
version = "0.3.5"
|
||||
authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
||||
description = "A stable implementation of the upcoming new `proc_macro` API. Comes with an\noption, off by default, to also reimplement itself in terms of the upstream\nunstable API.\n"
|
||||
homepage = "https://github.com/alexcrichton/proc-macro2"
|
|
@ -24,7 +24,7 @@
|
|||
//! [ts]: https://doc.rust-lang.org/proc_macro/struct.TokenStream.html
|
||||
|
||||
// Proc-macro2 types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/proc-macro2/0.3.6")]
|
||||
#![doc(html_root_url = "https://docs.rs/proc-macro2/0.3.5")]
|
||||
#![cfg_attr(feature = "nightly", feature(proc_macro))]
|
||||
|
||||
#[cfg(feature = "proc-macro")]
|
|
@ -403,8 +403,6 @@ thread_local!(static SYMBOLS: RefCell<Interner> = RefCell::new(Interner::new()))
|
|||
|
||||
impl Term {
|
||||
pub fn new(string: &str, span: Span) -> Term {
|
||||
validate_term(string);
|
||||
|
||||
Term {
|
||||
intern: SYMBOLS.with(|s| s.borrow_mut().intern(string)),
|
||||
span: span,
|
||||
|
@ -428,42 +426,6 @@ impl Term {
|
|||
}
|
||||
}
|
||||
|
||||
fn validate_term(string: &str) {
|
||||
let validate = if string.starts_with('\'') {
|
||||
&string[1..]
|
||||
} else if string.starts_with("r#") {
|
||||
&string[2..]
|
||||
} else {
|
||||
string
|
||||
};
|
||||
|
||||
if validate.is_empty() {
|
||||
panic!("Term is not allowed to be empty; use Option<Term>");
|
||||
}
|
||||
|
||||
if validate.bytes().all(|digit| digit >= b'0' && digit <= b'9') {
|
||||
panic!("Term cannot be a number; use Literal instead");
|
||||
}
|
||||
|
||||
fn xid_ok(string: &str) -> bool {
|
||||
let mut chars = string.chars();
|
||||
let first = chars.next().unwrap();
|
||||
if !(UnicodeXID::is_xid_start(first) || first == '_') {
|
||||
return false;
|
||||
}
|
||||
for ch in chars {
|
||||
if !UnicodeXID::is_xid_continue(ch) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
if !xid_ok(validate) {
|
||||
panic!("{:?} is not a valid Term", string);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Term {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("Term").field(&self.as_str()).finish()
|
|
@ -5,78 +5,9 @@ use std::str::{self, FromStr};
|
|||
use proc_macro2::{Literal, Span, Term, TokenStream, TokenTree};
|
||||
|
||||
#[test]
|
||||
fn terms() {
|
||||
assert_eq!(Term::new("String", Span::call_site()).as_str(), "String");
|
||||
assert_eq!(Term::new("fn", Span::call_site()).as_str(), "fn");
|
||||
assert_eq!(Term::new("_", Span::call_site()).as_str(), "_");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn raw_terms() {
|
||||
assert_eq!(Term::new("r#String", Span::call_site()).as_str(), "r#String");
|
||||
assert_eq!(Term::new("r#fn", Span::call_site()).as_str(), "r#fn");
|
||||
assert_eq!(Term::new("r#_", Span::call_site()).as_str(), "r#_");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lifetimes() {
|
||||
assert_eq!(Term::new("'a", Span::call_site()).as_str(), "'a");
|
||||
assert_eq!(Term::new("'static", Span::call_site()).as_str(), "'static");
|
||||
assert_eq!(Term::new("'_", Span::call_site()).as_str(), "'_");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Term is not allowed to be empty; use Option<Term>")]
|
||||
fn term_empty() {
|
||||
Term::new("", Span::call_site());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Term cannot be a number; use Literal instead")]
|
||||
fn term_number() {
|
||||
Term::new("255", Span::call_site());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "\"a#\" is not a valid Term")]
|
||||
fn term_invalid() {
|
||||
Term::new("a#", Span::call_site());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Term is not allowed to be empty; use Option<Term>")]
|
||||
fn raw_term_empty() {
|
||||
Term::new("r#", Span::call_site());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Term cannot be a number; use Literal instead")]
|
||||
fn raw_term_number() {
|
||||
Term::new("r#255", Span::call_site());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "\"r#a#\" is not a valid Term")]
|
||||
fn raw_term_invalid() {
|
||||
Term::new("r#a#", Span::call_site());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Term is not allowed to be empty; use Option<Term>")]
|
||||
fn lifetime_empty() {
|
||||
Term::new("'", Span::call_site());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Term cannot be a number; use Literal instead")]
|
||||
fn lifetime_number() {
|
||||
Term::new("'255", Span::call_site());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = r#""\'a#" is not a valid Term"#)]
|
||||
fn lifetime_invalid() {
|
||||
Term::new("'a#", Span::call_site());
|
||||
fn symbols() {
|
||||
assert_eq!(Term::new("foo", Span::call_site()).as_str(), "foo");
|
||||
assert_eq!(Term::new("bar", Span::call_site()).as_str(), "bar");
|
||||
}
|
||||
|
||||
#[test]
|
|
@ -1 +0,0 @@
|
|||
{"files":{".travis.yml":"872a0d195dcb1e84f28aa994f301c7139f70360bb42dee3954df5ee965efea15","Cargo.toml":"6ed5d7b9bf8805abd76f9e2a9be99b98e2cb70d9b97980b8aa09b6082d26a94d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"ce05336717e1e90724491a2f54487c41c752fa2d32396639439f7c6d0f1e6776","src/lib.rs":"e99fedcb4b410c626fe1a3ab722c8b4f98baed2c64c2dff28c4eb62da354f2e2","src/stable.rs":"fd8d86f7542d211030056a7cdcc58b86131180d54f461910a4a067269eee9d4a","src/strnom.rs":"129fe22f0b50e5a64fca82e731c959135381c910e19f3305ef35420e0aadde08","src/unstable.rs":"b43c713ac16d9de0ba0fa1b9bebe390122b4ad60ef2fc75408f721305fdcd46b","tests/test.rs":"a8229931093cd6b39f759c60ef097e59bc43c98f1b0e5eea06ecc8d5d0879853"},"package":"49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118"}
|
Загрузка…
Ссылка в новой задаче