Backed out 5 changesets (bug 1277338) for a microscopic speck of flake8 lint

Backed out changeset a8ae266cd61e (bug 1277338)
Backed out changeset b00ca2e7bda4 (bug 1277338)
Backed out changeset 40d0eefb1b5a (bug 1277338)
Backed out changeset ec92904a27cf (bug 1277338)
Backed out changeset 8ee31bf579fc (bug 1277338)

MozReview-Commit-ID: DLI8N9xhSxq

--HG--
rename : third_party/rust/bindgen-0.29.0/.github/ISSUE_TEMPLATE.md => third_party/rust/bindgen/.github/ISSUE_TEMPLATE.md
rename : third_party/rust/bindgen-0.29.0/.travis.yml => third_party/rust/bindgen/.travis.yml
rename : third_party/rust/bindgen-0.29.0/CONTRIBUTING.md => third_party/rust/bindgen/CONTRIBUTING.md
rename : third_party/rust/bindgen-0.29.0/LICENSE => third_party/rust/bindgen/LICENSE
rename : third_party/rust/bindgen-0.29.0/README.md => third_party/rust/bindgen/README.md
rename : third_party/rust/bindgen-0.29.0/appveyor.yml => third_party/rust/bindgen/appveyor.yml
rename : third_party/rust/bindgen-0.29.0/book/book.toml => third_party/rust/bindgen/book/book.toml
rename : third_party/rust/bindgen-0.29.0/book/src/SUMMARY.md => third_party/rust/bindgen/book/src/SUMMARY.md
rename : third_party/rust/bindgen-0.29.0/book/src/blacklisting.md => third_party/rust/bindgen/book/src/blacklisting.md
rename : third_party/rust/bindgen-0.29.0/book/src/chapter_1.md => third_party/rust/bindgen/book/src/chapter_1.md
rename : third_party/rust/bindgen-0.29.0/book/src/command-line-usage.md => third_party/rust/bindgen/book/src/command-line-usage.md
rename : third_party/rust/bindgen-0.29.0/book/src/cpp.md => third_party/rust/bindgen/book/src/cpp.md
rename : third_party/rust/bindgen-0.29.0/book/src/customizing-generated-bindings.md => third_party/rust/bindgen/book/src/customizing-generated-bindings.md
rename : third_party/rust/bindgen-0.29.0/book/src/introduction.md => third_party/rust/bindgen/book/src/introduction.md
rename : third_party/rust/bindgen-0.29.0/book/src/library-usage.md => third_party/rust/bindgen/book/src/library-usage.md
rename : third_party/rust/bindgen-0.29.0/book/src/nocopy.md => third_party/rust/bindgen/book/src/nocopy.md
rename : third_party/rust/bindgen-0.29.0/book/src/opaque.md => third_party/rust/bindgen/book/src/opaque.md
rename : third_party/rust/bindgen-0.29.0/book/src/replacing-types.md => third_party/rust/bindgen/book/src/replacing-types.md
rename : third_party/rust/bindgen-0.29.0/book/src/requirements.md => third_party/rust/bindgen/book/src/requirements.md
rename : third_party/rust/bindgen-0.29.0/book/src/tutorial-0.md => third_party/rust/bindgen/book/src/tutorial-0.md
rename : third_party/rust/bindgen-0.29.0/book/src/tutorial-1.md => third_party/rust/bindgen/book/src/tutorial-1.md
rename : third_party/rust/bindgen-0.29.0/book/src/tutorial-2.md => third_party/rust/bindgen/book/src/tutorial-2.md
rename : third_party/rust/bindgen-0.29.0/book/src/tutorial-3.md => third_party/rust/bindgen/book/src/tutorial-3.md
rename : third_party/rust/bindgen-0.29.0/book/src/tutorial-4.md => third_party/rust/bindgen/book/src/tutorial-4.md
rename : third_party/rust/bindgen-0.29.0/book/src/tutorial-5.md => third_party/rust/bindgen/book/src/tutorial-5.md
rename : third_party/rust/bindgen-0.29.0/book/src/tutorial-6.md => third_party/rust/bindgen/book/src/tutorial-6.md
rename : third_party/rust/bindgen-0.29.0/book/src/using-unions.md => third_party/rust/bindgen/book/src/using-unions.md
rename : third_party/rust/bindgen-0.29.0/book/src/whitelisting.md => third_party/rust/bindgen/book/src/whitelisting.md
rename : third_party/rust/bindgen-0.29.0/ci/assert-docs.sh => third_party/rust/bindgen/ci/assert-docs.sh
rename : third_party/rust/bindgen-0.29.0/ci/assert-no-diff.bat => third_party/rust/bindgen/ci/assert-no-diff.bat
rename : third_party/rust/bindgen-0.29.0/ci/assert-no-diff.sh => third_party/rust/bindgen/ci/assert-no-diff.sh
rename : third_party/rust/bindgen-0.29.0/ci/assert-rustfmt.sh => third_party/rust/bindgen/ci/assert-rustfmt.sh
rename : third_party/rust/bindgen-0.29.0/ci/before_install.sh => third_party/rust/bindgen/ci/before_install.sh
rename : third_party/rust/bindgen-0.29.0/ci/deploy-book.sh => third_party/rust/bindgen/ci/deploy-book.sh
rename : third_party/rust/bindgen-0.29.0/ci/no-includes.sh => third_party/rust/bindgen/ci/no-includes.sh
rename : third_party/rust/bindgen-0.29.0/ci/test-book.sh => third_party/rust/bindgen/ci/test-book.sh
rename : third_party/rust/bindgen-0.29.0/ci/test.bat => third_party/rust/bindgen/ci/test.bat
rename : third_party/rust/bindgen-0.29.0/ci/test.sh => third_party/rust/bindgen/ci/test.sh
rename : third_party/rust/bindgen-0.29.0/example-graphviz-ir.png => third_party/rust/bindgen/example-graphviz-ir.png
rename : third_party/rust/bindgen-0.29.0/rustfmt.toml => third_party/rust/bindgen/rustfmt.toml
rename : third_party/rust/bindgen-0.29.0/src/uses.rs => third_party/rust/bindgen/src/uses.rs
rename : third_party/rust/clap-2.24.2/appveyor.yml => third_party/rust/clap/appveyor.yml
rename : third_party/rust/thread-id/license-apache => third_party/rust/thread-id/license
This commit is contained in:
Phil Ringnalda 2017-09-01 22:32:40 -07:00
Родитель 72a1482137
Коммит 086c3155bc
568 изменённых файлов: 4189 добавлений и 112598 удалений

1
js/rust/.gitignore поставляемый
Просмотреть файл

@ -1 +0,0 @@
target/

Просмотреть файл

@ -1,35 +0,0 @@
project(rust-mozjs)
cmake_minimum_required(VERSION 2.6)
set(DUMMY ${CMAKE_BUILD_TYPE})
set(SOURCES
src/jsglue.cpp
)
include_directories($ENV{DEP_MOZJS_OUTDIR}/dist/include)
if(MSVC)
if(NOT "$ENV{CARGO_FEATURE_DEBUGMOZJS}" STREQUAL "")
add_definitions(-MDd -Od -DDEBUG -D_DEBUG)
else()
add_definitions(-MD)
endif()
add_definitions(-FI$ENV{DEP_MOZJS_OUTDIR}/js/src/js-confdefs.h)
add_definitions(-DWIN32)
add_definitions(-Zi -GR-)
else()
if(NOT "$ENV{CARGO_FEATURE_DEBUGMOZJS}" STREQUAL "")
add_definitions(-g -O0 -DDEBUG -D_DEBUG)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_definitions(-Wno-c++0x-extensions -Wno-return-type-c-linkage -Wno-invalid-offsetof)
endif()
add_definitions(-fPIC -fno-rtti)
add_definitions(-std=c++11 -DJS_NO_JSVAL_JSID_STRUCT_TYPES)
add_definitions(-include $ENV{DEP_MOZJS_OUTDIR}/js/src/js-confdefs.h)
endif()
add_library(jsglue STATIC ${SOURCES})
install(TARGETS jsglue ARCHIVE DESTINATION lib)

494
js/rust/Cargo.lock сгенерированный
Просмотреть файл

@ -1,494 +0,0 @@
[root]
name = "js"
version = "0.1.4"
dependencies = [
"bindgen 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mozjs_sys 0.0.0",
"num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "aho-corasick"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ansi_term"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "aster"
version = "0.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "atty"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bindgen"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"clang-sys 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
"quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
"which 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cexpr"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cfg-if"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clang-sys"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
"libloading 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clap"
version = "2.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"textwrap 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cmake"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "env_logger"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gcc"
version = "0.3.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "glob"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "heapsize"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libloading"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libz-sys"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mozjs_sys"
version = "0.0.0"
dependencies = [
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "nom"
version = "1.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num-traits"
version = "0.1.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num_cpus"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "pkg-config"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quasi"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quasi_codegen"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-serialize"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "strsim"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syntex"
version = "0.58.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syntex_errors"
version = "0.58.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
"term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syntex_pos"
version = "0.58.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syntex_syntax"
version = "0.58.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "term"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "term_size"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "textwrap"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread-id"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-segmentation"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-width"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unreachable"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "utf8-ranges"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vcpkg"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vec_map"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "which"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
"checksum aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfdf7355d9db158df68f976ed030ab0f6578af811f5a7bb6dcf221ec24e0e0"
"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
"checksum bindgen 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "33024f55a754d920637461adf87fb485702a69bdf7ac1d307b7e18da93bae505"
"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4"
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
"checksum cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c47d456a36ebf0536a6705c83c1cbbcb9255fbc1d905a6ded104f479268a29"
"checksum clang-sys 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "611ec2e3a7623afd8a8c0d027887b6b55759d894abbf5fe11b9dc11b50d5b49a"
"checksum clap 2.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "867a885995b4184be051b70a592d4d70e32d7a188db6e8dff626af286a962771"
"checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f"
"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
"checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a"
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
"checksum heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c7593b1522161003928c959c20a2ca421c68e940d63d75573316a009e48a6d4"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
"checksum libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)" = "38f5c2b18a287cf78b4097db62e20f43cace381dc76ae5c0a3073067f78b7ddc"
"checksum libloading 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "be99f814beb3e9503a786a592c909692bb6d4fc5a695f6ed7987223acfbd5194"
"checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8"
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
"checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
"checksum num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "1708c0628602a98b52fad936cf3edb9a107af06e52e49fdf0707e884456a6af6"
"checksum num_cpus 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83df569ffd47dbf87f36bead512632f89e90882b8e7a14286d0471daf6b72de9"
"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
"checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3"
"checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4"
"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
"checksum syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a8f5e3aaa79319573d19938ea38d068056b826db9883a5d47f86c1cecc688f0e"
"checksum syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "867cc5c2d7140ae7eaad2ae9e8bf39cb18a67ca651b7834f88d46ca98faadb9c"
"checksum syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13ad4762fe52abc9f4008e85c4fb1b1fe3aa91ccb99ff4826a439c7c598e1047"
"checksum syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e0e4dbae163dd98989464c23dd503161b338790640e11537686f2ef0f25c791"
"checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989"
"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
"checksum textwrap 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f86300c3e7416ee233abd7cda890c492007a3980f941f79185c753a701257167"
"checksum thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df7875b676fddfadffd96deea3b1124e5ede707d4884248931077518cf1f773"
"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"
"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
"checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b"
"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum which 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d238435618c0f298d2d75596c2d4fa7d4ea469c0c1c3ff824737ed50ad5ab61c"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

Просмотреть файл

@ -1,50 +0,0 @@
[package]
name = "js"
version = "0.1.4"
authors = ["The Servo Project Developers"]
build = "build.rs"
license = "MPL-2.0"
[build-dependencies]
env_logger = "0.4"
log = "0.3"
bindgen = "0.30.0"
cmake = "0.1"
glob = "0.2.11"
[[test]]
name = "callback"
[[test]]
name = "enumerate"
[[test]]
name = "evaluate"
[[test]]
name = "panic"
[[test]]
name = "rooting"
[[test]]
name = "runtime"
[[test]]
name = "typedarray"
[[test]]
name = "stack_limit"
[[test]]
name = "vec_conversion"
[lib]
doctest = false
[features]
debugmozjs = ['mozjs_sys/debugmozjs']
promises = ['mozjs_sys/promises']
nonzero = []
[dependencies.mozjs_sys]
path = "../src"
[dependencies]
lazy_static = "0.2.1"
libc = "0.2"
log = "0.3"
heapsize = "0.4"
num-traits = "0.1.32"

Просмотреть файл

@ -1,46 +0,0 @@
# The `js` Crate: Rust Bindings to SpiderMonkey
[User Documentation](http://doc.servo.org/js/)
## Building
To build a release version of SpiderMonkey and the Rust code with optimizations
enabled:
```
$ cargo build --release
```
To build with SpiderMonkey's DEBUG checks and assertions:
```
$ cargo build --features debugmozjs
```
Raw FFI bindings to JSAPI are machine generated with
[`rust-lang-nursery/rust-bindgen`][bindgen], and requires libclang >= 3.9. See
`./build.rs` for details.
[bindgen]: https://github.com/rust-lang-nursery/rust-bindgen
## Cargo Features
* `debugmozjs`: Create a DEBUG build of SpiderMonkey with many extra assertions
enabled. This is decoupled from whether the crate and its Rust code is built
in debug or release mode.
* `promises`: Enable SpiderMonkey native promises.
* `nonzero`: Leverage the unstable `NonZero` type. Requires nightly Rust.
## Testing
Make sure to test both with and without the `debugmozjs` feature because various
structures have different sizes and get passed through functions differently at
the ABI level! At minimum, you should test with `debugmozjs` to get extra
assertions and checking.
```
$ cargo test
$ cargo test --features debugmozjs
```

Просмотреть файл

@ -1,468 +0,0 @@
/* 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/. */
extern crate bindgen;
extern crate cmake;
extern crate glob;
extern crate log;
extern crate env_logger;
use std::env;
use std::path;
fn main() {
log::set_logger(|max_log_level| {
use env_logger::Logger;
let env_logger = Logger::new();
max_log_level.set(env_logger.filter());
Box::new(env_logger)
}).expect("Failed to set logger.");
build_jsapi_bindings();
build_jsglue_cpp();
}
/// Build the ./src/jsglue.cpp file containing C++ glue methods built on top of
/// JSAPI.
fn build_jsglue_cpp() {
let dst = cmake::Config::new(".").build();
println!("cargo:rustc-link-search=native={}/lib", dst.display());
println!("cargo:rustc-link-lib=static=jsglue");
println!("cargo:rerun-if-changed=src/jsglue.cpp");
}
/// Find the public include directory within our mozjs-sys crate dependency.
fn get_mozjs_include_dir() -> path::PathBuf {
let out_dir = env::var("OUT_DIR")
.expect("cargo should invoke us with the OUT_DIR env var set");
let mut target_build_dir = path::PathBuf::from(out_dir);
target_build_dir.push("../../");
let mut include_dir_glob = target_build_dir.display().to_string();
include_dir_glob.push_str("mozjs_sys-*/out/dist/include");
let entries = glob::glob(&include_dir_glob)
.expect("Should find entries for mozjs-sys include dir");
for entry in entries {
if let Ok(path) = entry {
return path.canonicalize()
.expect("Should canonicalize include path");
}
}
panic!("Should have found either a mozjs_sys in target/debug or in target/release");
}
/// Invoke bindgen on the JSAPI headers to produce raw FFI bindings for use from
/// Rust.
///
/// To add or remove which functions, types, and variables get bindings
/// generated, see the `const` configuration variables below.
fn build_jsapi_bindings() {
let mut builder = bindgen::builder()
.rust_target(bindgen::RustTarget::Stable_1_19)
.header("./etc/wrapper.hpp")
.raw_line("pub use self::root::*;")
.enable_cxx_namespaces();
if cfg!(feature = "debugmozjs") {
builder = builder
.clang_arg("-DJS_GC_ZEAL")
.clang_arg("-DDEBUG")
.clang_arg("-DJS_DEBUG");
}
let include_dir = get_mozjs_include_dir();
let include_dir = include_dir.to_str()
.expect("Path to mozjs include dir should be utf-8");
builder = builder.clang_arg("-I");
builder = builder.clang_arg(include_dir);
for ty in UNSAFE_IMPL_SYNC_TYPES {
builder = builder.raw_line(format!("unsafe impl Sync for {} {{}}", ty));
}
for extra in EXTRA_CLANG_FLAGS {
builder = builder.clang_arg(*extra);
}
for ty in WHITELIST_TYPES {
builder = builder.whitelisted_type(ty);
}
for var in WHITELIST_VARS {
builder = builder.whitelisted_var(var);
}
for func in WHITELIST_FUNCTIONS {
builder = builder.whitelisted_function(func);
}
for ty in OPAQUE_TYPES {
builder = builder.opaque_type(ty);
}
for ty in BLACKLIST_TYPES {
builder = builder.hide_type(ty);
}
let bindings = builder.generate()
.expect("Should generate JSAPI bindings OK");
let out = path::PathBuf::from(env::var("OUT_DIR").unwrap());
if cfg!(feature = "debugmozjs") {
bindings.write_to_file(out.join("jsapi_debug.rs"))
.expect("Should write bindings to file OK");
} else {
bindings.write_to_file(out.join("jsapi.rs"))
.expect("Should write bindings to file OK");
}
println!("cargo:rerun-if-changed=etc/wrapper.hpp");
}
/// JSAPI types for which we should implement `Sync`.
const UNSAFE_IMPL_SYNC_TYPES: &'static [&'static str] = &[
"JSClass",
"JSFunctionSpec",
"JSNativeWrapper",
"JSPropertySpec",
"JSTypedMethodJitInfo",
];
/// Flags passed through bindgen directly to Clang.
const EXTRA_CLANG_FLAGS: &'static [&'static str] = &[
"-x", "c++",
"-std=c++14",
"-DRUST_BINDGEN",
];
/// Types which we want to generate bindings for (and every other type they
/// transitively use).
const WHITELIST_TYPES: &'static [&'static str] = &[
"JS::AutoCheckCannotGC",
"JS::AutoIdVector",
"JS::AutoObjectVector",
"JS::CallArgs",
"js::Class",
"JS::CompartmentOptions",
"JS::ContextOptions",
"js::DOMCallbacks",
"js::DOMProxyShadowsResult",
"js::ESClass",
"JS::ForOfIterator",
"JS::Handle",
"JS::HandleId",
"JS::HandleObject",
"JS::HandleString",
"JS::HandleValue",
"JS::HandleValueArray",
"JS::IsAcceptableThis",
"JSAutoCompartment",
"JSAutoStructuredCloneBuffer",
"JSClass",
"JSClassOps",
"JSContext",
"JSErrNum",
"JSErrorCallback",
"JSErrorFormatString",
"JSErrorReport",
"JSExnType",
"JSFlatString",
"JSFunction",
"JSFunctionSpec",
"JS::GCDescription",
"JSGCInvocationKind",
"JSGCMode",
"JSGCParamKey",
"JS::GCProgress",
"JSGCStatus",
"JSJitCompilerOption",
"JSJitGetterCallArgs",
"JSJitMethodCallArgs",
"JSJitSetterCallArgs",
"JSNativeWrapper",
"JSPropertySpec",
"JSProtoKey",
"JSObject",
"JSString",
"JSStructuredCloneReader",
"JSStructuredCloneWriter",
"JSScript",
"JSType",
"JSTypedMethodJitInfo",
"JSValueTag",
"JSValueType",
"JSVersion",
"JSWrapObjectCallbacks",
"jsid",
"JS::Latin1Char",
"JS::detail::MaybeWrapped",
"JS::MutableHandle",
"JS::MutableHandleObject",
"JS::MutableHandleValue",
"JS::NativeImpl",
"js::ObjectOps",
"JS::ObjectOpResult",
"JS::PromiseState",
"JS::PropertyDescriptor",
"JS::Rooted",
"JS::RootedObject",
"JS::RootingContext",
"JS::RootKind",
"js::Scalar::Type",
"JS::ServoSizes",
"js::shadow::Object",
"js::shadow::ObjectGroup",
"JS::SourceBufferHolder",
"JSStructuredCloneCallbacks",
"JS::Symbol",
"JS::SymbolCode",
"JS::TraceKind",
"JS::TransferableOwnership",
"JS::Value",
"JS::WarningReporter",
"JS::shadow::Zone",
"JS::Zone",
];
/// Global variables we want to generate bindings to.
const WHITELIST_VARS: &'static [&'static str] = &[
"JS_STRUCTURED_CLONE_VERSION",
"JSCLASS_.*",
"JSFUN_.*",
"JSID_VOID",
"JSITER_.*",
"JSPROP_.*",
"JS::FalseHandleValue",
"JS::NullHandleValue",
"JS::TrueHandleValue",
"JS::UndefinedHandleValue",
];
/// Functions we want to generate bindings to.
const WHITELIST_FUNCTIONS: &'static [&'static str] = &[
"INTERNED_STRING_TO_JSID",
"JS_AddExtraGCRootsTracer",
"JS_AddInterruptCallback",
"JS::AddPromiseReactions",
"js::AddRawValueRoot",
"JS_AlreadyHasOwnPropertyById",
"JS_AtomizeAndPinString",
"js::AssertSameCompartment",
"JS::Call",
"JS_CallFunctionValue",
"JS::CallOriginalPromiseThen",
"JS::CallOriginalPromiseResolve",
"JS::CallOriginalPromiseReject",
"JS::CompileFunction",
"JS::Construct",
"JS::ContextOptionsRef",
"JS_CopyPropertiesFrom",
"JS::CurrentGlobalOrNull",
"JS_DeletePropertyById",
"js::detail::IsWindowSlow",
"JS::Evaluate",
"JS_ForwardGetPropertyTo",
"JS_ForwardSetPropertyTo",
"JS::GCTraceKindToAscii",
"js::GetArrayBufferLengthAndData",
"js::GetArrayBufferViewLengthAndData",
"JS_GetErrorPrototype",
"js::GetFunctionNativeReserved",
"JS_GetFunctionPrototype",
"js::GetGlobalForObjectCrossCompartment",
"JS_GetIteratorPrototype",
"js::GetObjectProto",
"JS_GetObjectPrototype",
"JS_GetObjectRuntime",
"JS_GetOwnPropertyDescriptorById",
"JS::GetPromiseState",
"JS_GetPropertyDescriptorById",
"js::GetPropertyKeys",
"JS_GetPrototype",
"JS_GetRuntime",
"js::GetStaticPrototype",
"JS_HasOwnPropertyById",
"JS_HasProperty",
"JS_HasPropertyById",
"JS::HeapObjectPostBarrier",
"JS::HeapValuePostBarrier",
"JS_InitializePropertiesFromCompatibleNativeObject",
"JS::InitSelfHostedCode",
"JS::IsConstructor",
"JS::IsPromiseObject",
"JS_BeginRequest",
"JS_ClearPendingException",
"JS_DefineElement",
"JS_DefineFunction",
"JS_DefineFunctions",
"JS_DefineProperties",
"JS_DefineProperty",
"JS_DefinePropertyById",
"JS_DefineUCProperty",
"JS::detail::InitWithFailureDiagnostic",
"JS_DestroyContext",
"JS::DisableIncrementalGC",
"js::Dump.*",
"JS_EncodeStringToUTF8",
"JS_EndRequest",
"JS_EnterCompartment",
"JS_EnumerateStandardClasses",
"JS_ErrorFromException",
"JS_FireOnNewGlobalObject",
"JS_GC",
"JS_GetArrayBufferData",
"JS_GetArrayBufferViewType",
"JS_GetFloat32ArrayData",
"JS_GetFloat64ArrayData",
"JS_GetFunctionObject",
"JS_GetGCParameter",
"JS_GetInt16ArrayData",
"JS_GetInt32ArrayData",
"JS_GetInt8ArrayData",
"JS_GetLatin1StringCharsAndLength",
"JS_GetParentRuntime",
"JS_GetPendingException",
"JS_GetProperty",
"JS_GetPropertyById",
"js::GetPropertyKeys",
"JS_GetPrototype",
"JS_GetReservedSlot",
"JS::GetScriptedCallerGlobal",
"JS_GetTwoByteStringCharsAndLength",
"JS_GetUint16ArrayData",
"JS_GetUint32ArrayData",
"JS_GetUint8ArrayData",
"JS_GetUint8ClampedArrayData",
"JS::GetWellKnownSymbol",
"JS_GlobalObjectTraceHook",
"JS::HideScriptedCaller",
"JS_InitStandardClasses",
"JS_IsArrayObject",
"JS_IsExceptionPending",
"JS_IsGlobalObject",
"JS::IsCallable",
"JS_LeaveCompartment",
"JS_LinkConstructorAndPrototype",
"JS_MayResolveStandardClass",
"JS_NewArrayBuffer",
"JS_NewArrayObject",
"JS_NewContext",
"JS_NewFloat32Array",
"JS_NewFloat64Array",
"JS_NewFunction",
"js::NewFunctionWithReserved",
"JS_NewGlobalObject",
"JS_NewInt16Array",
"JS_NewInt32Array",
"JS_NewInt8Array",
"JS_NewObject",
"JS_NewObjectWithGivenProto",
"JS_NewObjectWithoutMetadata",
"JS_NewObjectWithUniqueType",
"JS_NewPlainObject",
"JS::NewPromiseObject",
"JS_NewStringCopyN",
"JS_NewUCStringCopyN",
"JS_NewUint16Array",
"JS_NewUint32Array",
"JS_NewUint8Array",
"JS_NewUint8ClampedArray",
"js::ObjectClassName",
"JS_ObjectIsDate",
"JS_ParseJSON",
"JS_ReadBytes",
"JS_ReadStructuredClone",
"JS_ReadUint32Pair",
"js::RemoveRawValueRoot",
"JS_ReportErrorASCII",
"JS_ReportErrorNumberUTF8",
"JS_RequestInterruptCallback",
"JS_ResolveStandardClass",
"JS_SameValue",
"js::SetDOMCallbacks",
"js::SetDOMProxyInformation",
"JS::SetEnqueuePromiseJobCallback",
"js::SetFunctionNativeReserved",
"JS_SetGCCallback",
"JS::SetGCSliceCallback",
"JS_SetGCParameter",
"JS_SetGCZeal",
"JS::SetGetIncumbentGlobalCallback",
"JS_SetGlobalJitCompilerOption",
"JS_SetImmutablePrototype",
"JS_SetNativeStackQuota",
"JS_SetOffthreadIonCompilationEnabled",
"JS_SetParallelParsingEnabled",
"JS_SetPendingException",
"js::SetPreserveWrapperCallback",
"JS_SetPrototype",
"js::SetWindowProxy",
"js::SetWindowProxyClass",
"JS_SetProperty",
"JS_SetReservedSlot",
"JS_SetWrapObjectCallbacks",
"JS_ShutDown",
"JS_SplicePrototype",
"JS_StrictPropertyStub",
"JS_StringEqualsAscii",
"JS_StringHasLatin1Chars",
"JS_WrapObject",
"JS_WrapValue",
"JS_WriteBytes",
"JS_WriteStructuredClone",
"JS_WriteUint32Pair",
"JS::ResolvePromise",
"JS::RejectPromise",
"JS::SetWarningReporter",
"js::ToBooleanSlow",
"js::ToInt32Slow",
"js::ToInt64Slow",
"js::ToNumberSlow",
"js::ToStringSlow",
"js::ToUint16Slow",
"js::ToUint32Slow",
"js::ToUint64Slow",
"JS_TransplantObject",
"js::detail::ToWindowProxyIfWindowSlow",
"JS::UnhideScriptedCaller",
"js::UnwrapArrayBuffer",
"js::UnwrapArrayBufferView",
"js::UnwrapFloat32Array",
"js::UnwrapFloat64Array",
"js::UnwrapInt16Array",
"js::UnwrapInt32Array",
"js::UnwrapInt8Array",
"js::UnwrapUint16Array",
"js::UnwrapUint32Array",
"js::UnwrapUint8Array",
"js::UnwrapUint8ClampedArray",
];
/// Types that should be treated as an opaque blob of bytes whenever they show
/// up within a whitelisted type.
///
/// These are types which are too tricky for bindgen to handle, and/or use C++
/// features that don't have an equivalent in rust, such as partial template
/// specialization.
const OPAQUE_TYPES: &'static [&'static str] = &[
"JS::ReadOnlyCompileOptions",
"mozilla::BufferList",
"mozilla::UniquePtr.*",
"JS::Rooted<JS::Auto.*Vector.*>",
];
/// Types for which we should NEVER generate bindings, even if it is used within
/// a type or function signature that we are generating bindings for.
const BLACKLIST_TYPES: &'static [&'static str] = &[
// We provide our own definition because we need to express trait bounds in
// the definition of the struct to make our Drop implementation correct.
"JS::Heap",
];

Просмотреть файл

@ -1,23 +0,0 @@
/* -*- 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 <stdint.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
typedef uint32_t HashNumber;
#include "jsfriendapi.h"
#include "js/Conversions.h"
#include "js/Initialization.h"
#include "js/MemoryMetrics.h"
// Replacements for types that are too difficult for rust-bindgen.
/// <div rustbindgen replaces="JS::detail::MaybeWrapped" />
template <typename T>
using replaces_MaybeWrapped = T;

Просмотреть файл

@ -1,56 +0,0 @@
use jsapi::root::*;
#[cfg(feature = "debugmozjs")]
use std::ptr;
#[derive(Debug)]
pub struct AutoCompartment(JSAutoCompartment);
impl AutoCompartment {
#[cfg(feature = "debugmozjs")]
pub unsafe fn with_obj(cx: *mut JSContext,
target: *mut JSObject)
-> AutoCompartment
{
let mut notifier = mozilla::detail::GuardObjectNotifier {
mStatementDone: ptr::null_mut(),
};
AutoCompartment(
JSAutoCompartment::new(
cx,
target,
&mut notifier as *mut _))
}
#[cfg(not(feature = "debugmozjs"))]
pub unsafe fn with_obj(cx: *mut JSContext,
target: *mut JSObject)
-> AutoCompartment
{
AutoCompartment(JSAutoCompartment::new(cx, target))
}
#[cfg(feature = "debugmozjs")]
pub unsafe fn with_script(cx: *mut JSContext,
target: *mut JSScript)
-> AutoCompartment
{
let mut notifier = mozilla::detail::GuardObjectNotifier {
mStatementDone: ptr::null_mut(),
};
AutoCompartment(
JSAutoCompartment::new1(
cx,
target,
&mut notifier as *mut _))
}
#[cfg(not(feature = "debugmozjs"))]
pub unsafe fn with_script(cx: *mut JSContext,
target: *mut JSScript)
-> AutoCompartment
{
AutoCompartment(JSAutoCompartment::new1(cx, target))
}
}

Просмотреть файл

@ -1,679 +0,0 @@
/* 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/. */
//! Conversions of Rust values to and from `JSVal`.
//!
//! | IDL type | Type |
//! |-------------------------|----------------------------------|
//! | any | `JSVal` |
//! | boolean | `bool` |
//! | byte | `i8` |
//! | octet | `u8` |
//! | short | `i16` |
//! | unsigned short | `u16` |
//! | long | `i32` |
//! | unsigned long | `u32` |
//! | long long | `i64` |
//! | unsigned long long | `u64` |
//! | unrestricted float | `f32` |
//! | float | `Finite<f32>` |
//! | unrestricted double | `f64` |
//! | double | `Finite<f64>` |
//! | USVString | `String` |
//! | object | `*mut JSObject` |
//! | nullable types | `Option<T>` |
//! | sequences | `Vec<T>` |
#![deny(missing_docs)]
#[cfg(feature = "nonzero")]
use core::nonzero::NonZero;
use error::throw_type_error;
use glue::RUST_JS_NumberValue;
use heap::Heap;
use jsapi::root::*;
use jsval::{BooleanValue, Int32Value, NullValue, UInt32Value, UndefinedValue};
use jsval::{ObjectValue, ObjectOrNullValue, StringValue};
use rust::{ToBoolean, ToInt32, ToInt64, ToNumber, ToUint16, ToUint32, ToUint64};
use rust::{ToString, maybe_wrap_object_or_null_value, maybe_wrap_value};
use libc;
use num_traits::{Bounded, Zero};
use std::borrow::Cow;
use std::rc::Rc;
use std::{ptr, slice};
trait As<O>: Copy {
fn cast(self) -> O;
}
macro_rules! impl_as {
($I:ty, $O:ty) => (
impl As<$O> for $I {
fn cast(self) -> $O {
self as $O
}
}
)
}
impl_as!(f64, u8);
impl_as!(f64, u16);
impl_as!(f64, u32);
impl_as!(f64, u64);
impl_as!(f64, i8);
impl_as!(f64, i16);
impl_as!(f64, i32);
impl_as!(f64, i64);
impl_as!(u8, f64);
impl_as!(u16, f64);
impl_as!(u32, f64);
impl_as!(u64, f64);
impl_as!(i8, f64);
impl_as!(i16, f64);
impl_as!(i32, f64);
impl_as!(i64, f64);
impl_as!(i32, i8);
impl_as!(i32, u8);
impl_as!(i32, i16);
impl_as!(u16, u16);
impl_as!(i32, i32);
impl_as!(u32, u32);
impl_as!(i64, i64);
impl_as!(u64, u64);
/// A trait to convert Rust types to `JSVal`s.
pub trait ToJSValConvertible {
/// Convert `self` to a `JSVal`. JSAPI failure causes a panic.
#[inline]
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue);
}
/// An enum to better support enums through FromJSValConvertible::from_jsval.
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum ConversionResult<T> {
/// Everything went fine.
Success(T),
/// Conversion failed, without a pending exception.
Failure(Cow<'static, str>),
}
impl<T> ConversionResult<T> {
/// Returns Some(value) if it is `ConversionResult::Success`.
pub fn get_success_value(&self) -> Option<&T> {
match *self {
ConversionResult::Success(ref v) => Some(v),
_ => None,
}
}
}
/// A trait to convert `JSVal`s to Rust types.
pub trait FromJSValConvertible: Sized {
/// Optional configurable behaviour switch; use () for no configuration.
type Config;
/// Convert `val` to type `Self`.
/// Optional configuration of type `T` can be passed as the `option`
/// argument.
/// If it returns `Err(())`, a JSAPI exception is pending.
/// If it returns `Ok(Failure(reason))`, there is no pending JSAPI exception.
unsafe fn from_jsval(cx: *mut JSContext,
val: JS::HandleValue,
option: Self::Config)
-> Result<ConversionResult<Self>, ()>;
}
/// Behavior for converting out-of-range integers.
#[derive(PartialEq, Eq, Clone)]
pub enum ConversionBehavior {
/// Wrap into the integer's range.
Default,
/// Throw an exception.
EnforceRange,
/// Clamp into the integer's range.
Clamp,
}
/// Try to cast the number to a smaller type, but
/// if it doesn't fit, it will return an error.
unsafe fn enforce_range<D>(cx: *mut JSContext, d: f64) -> Result<ConversionResult<D>, ()>
where D: Bounded + As<f64>,
f64: As<D>
{
if d.is_infinite() {
throw_type_error(cx, "value out of range in an EnforceRange argument");
return Err(());
}
let rounded = d.round();
if D::min_value().cast() <= rounded && rounded <= D::max_value().cast() {
Ok(ConversionResult::Success(rounded.cast()))
} else {
throw_type_error(cx, "value out of range in an EnforceRange argument");
Err(())
}
}
/// Try to cast the number to a smaller type, but if it doesn't fit,
/// round it to the MAX or MIN of the source type before casting it to
/// the destination type.
fn clamp_to<D>(d: f64) -> D
where D: Bounded + As<f64> + Zero,
f64: As<D>
{
if d.is_nan() {
D::zero()
} else if d > D::max_value().cast() {
D::max_value()
} else if d < D::min_value().cast() {
D::min_value()
} else {
d.cast()
}
}
// https://heycam.github.io/webidl/#es-void
impl ToJSValConvertible for () {
#[inline]
unsafe fn to_jsval(&self, _cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(UndefinedValue());
}
}
impl FromJSValConvertible for JS::HandleValue {
type Config = ();
#[inline]
unsafe fn from_jsval(cx: *mut JSContext,
value: JS::HandleValue,
_option: ())
-> Result<ConversionResult<JS::HandleValue>, ()> {
if value.is_object() {
js::AssertSameCompartment(cx, value.to_object());
}
Ok(ConversionResult::Success(value))
}
}
impl FromJSValConvertible for JS::Value {
type Config = ();
unsafe fn from_jsval(_cx: *mut JSContext,
value: JS::HandleValue,
_option: ())
-> Result<ConversionResult<JS::Value>, ()> {
Ok(ConversionResult::Success(value.get()))
}
}
impl FromJSValConvertible for Heap<JS::Value> {
type Config = ();
unsafe fn from_jsval(_cx: *mut JSContext,
value: JS::HandleValue,
_option: ())
-> Result<ConversionResult<Self>, ()> {
Ok(ConversionResult::Success(Heap::<JS::Value>::new(value.get())))
}
}
impl ToJSValConvertible for JS::Value {
#[inline]
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(*self);
maybe_wrap_value(cx, rval);
}
}
impl ToJSValConvertible for JS::HandleValue {
#[inline]
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(self.get());
maybe_wrap_value(cx, rval);
}
}
impl ToJSValConvertible for Heap<JS::Value> {
#[inline]
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(self.get());
maybe_wrap_value(cx, rval);
}
}
#[inline]
unsafe fn convert_int_from_jsval<T, M>(cx: *mut JSContext, value: JS::HandleValue,
option: ConversionBehavior,
convert_fn: unsafe fn(*mut JSContext, JS::HandleValue) -> Result<M, ()>)
-> Result<ConversionResult<T>, ()>
where T: Bounded + Zero + As<f64>,
M: Zero + As<T>,
f64: As<T>
{
match option {
ConversionBehavior::Default => Ok(ConversionResult::Success(try!(convert_fn(cx, value)).cast())),
ConversionBehavior::EnforceRange => enforce_range(cx, try!(ToNumber(cx, value))),
ConversionBehavior::Clamp => Ok(ConversionResult::Success(clamp_to(try!(ToNumber(cx, value))))),
}
}
// https://heycam.github.io/webidl/#es-boolean
impl ToJSValConvertible for bool {
#[inline]
unsafe fn to_jsval(&self, _cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(BooleanValue(*self));
}
}
// https://heycam.github.io/webidl/#es-boolean
impl FromJSValConvertible for bool {
type Config = ();
unsafe fn from_jsval(_cx: *mut JSContext, val: JS::HandleValue, _option: ()) -> Result<ConversionResult<bool>, ()> {
Ok(ToBoolean(val)).map(ConversionResult::Success)
}
}
// https://heycam.github.io/webidl/#es-byte
impl ToJSValConvertible for i8 {
#[inline]
unsafe fn to_jsval(&self, _cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(Int32Value(*self as i32));
}
}
// https://heycam.github.io/webidl/#es-byte
impl FromJSValConvertible for i8 {
type Config = ConversionBehavior;
unsafe fn from_jsval(cx: *mut JSContext,
val: JS::HandleValue,
option: ConversionBehavior)
-> Result<ConversionResult<i8>, ()> {
convert_int_from_jsval(cx, val, option, ToInt32)
}
}
// https://heycam.github.io/webidl/#es-octet
impl ToJSValConvertible for u8 {
#[inline]
unsafe fn to_jsval(&self, _cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(Int32Value(*self as i32));
}
}
// https://heycam.github.io/webidl/#es-octet
impl FromJSValConvertible for u8 {
type Config = ConversionBehavior;
unsafe fn from_jsval(cx: *mut JSContext,
val: JS::HandleValue,
option: ConversionBehavior)
-> Result<ConversionResult<u8>, ()> {
convert_int_from_jsval(cx, val, option, ToInt32)
}
}
// https://heycam.github.io/webidl/#es-short
impl ToJSValConvertible for i16 {
#[inline]
unsafe fn to_jsval(&self, _cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(Int32Value(*self as i32));
}
}
// https://heycam.github.io/webidl/#es-short
impl FromJSValConvertible for i16 {
type Config = ConversionBehavior;
unsafe fn from_jsval(cx: *mut JSContext,
val: JS::HandleValue,
option: ConversionBehavior)
-> Result<ConversionResult<i16>, ()> {
convert_int_from_jsval(cx, val, option, ToInt32)
}
}
// https://heycam.github.io/webidl/#es-unsigned-short
impl ToJSValConvertible for u16 {
#[inline]
unsafe fn to_jsval(&self, _cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(Int32Value(*self as i32));
}
}
// https://heycam.github.io/webidl/#es-unsigned-short
impl FromJSValConvertible for u16 {
type Config = ConversionBehavior;
unsafe fn from_jsval(cx: *mut JSContext,
val: JS::HandleValue,
option: ConversionBehavior)
-> Result<ConversionResult<u16>, ()> {
convert_int_from_jsval(cx, val, option, ToUint16)
}
}
// https://heycam.github.io/webidl/#es-long
impl ToJSValConvertible for i32 {
#[inline]
unsafe fn to_jsval(&self, _cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(Int32Value(*self));
}
}
// https://heycam.github.io/webidl/#es-long
impl FromJSValConvertible for i32 {
type Config = ConversionBehavior;
unsafe fn from_jsval(cx: *mut JSContext,
val: JS::HandleValue,
option: ConversionBehavior)
-> Result<ConversionResult<i32>, ()> {
convert_int_from_jsval(cx, val, option, ToInt32)
}
}
// https://heycam.github.io/webidl/#es-unsigned-long
impl ToJSValConvertible for u32 {
#[inline]
unsafe fn to_jsval(&self, _cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(UInt32Value(*self));
}
}
// https://heycam.github.io/webidl/#es-unsigned-long
impl FromJSValConvertible for u32 {
type Config = ConversionBehavior;
unsafe fn from_jsval(cx: *mut JSContext,
val: JS::HandleValue,
option: ConversionBehavior)
-> Result<ConversionResult<u32>, ()> {
convert_int_from_jsval(cx, val, option, ToUint32)
}
}
// https://heycam.github.io/webidl/#es-long-long
impl ToJSValConvertible for i64 {
#[inline]
unsafe fn to_jsval(&self, _cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(RUST_JS_NumberValue(*self as f64));
}
}
// https://heycam.github.io/webidl/#es-long-long
impl FromJSValConvertible for i64 {
type Config = ConversionBehavior;
unsafe fn from_jsval(cx: *mut JSContext,
val: JS::HandleValue,
option: ConversionBehavior)
-> Result<ConversionResult<i64>, ()> {
convert_int_from_jsval(cx, val, option, ToInt64)
}
}
// https://heycam.github.io/webidl/#es-unsigned-long-long
impl ToJSValConvertible for u64 {
#[inline]
unsafe fn to_jsval(&self, _cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(RUST_JS_NumberValue(*self as f64));
}
}
// https://heycam.github.io/webidl/#es-unsigned-long-long
impl FromJSValConvertible for u64 {
type Config = ConversionBehavior;
unsafe fn from_jsval(cx: *mut JSContext,
val: JS::HandleValue,
option: ConversionBehavior)
-> Result<ConversionResult<u64>, ()> {
convert_int_from_jsval(cx, val, option, ToUint64)
}
}
// https://heycam.github.io/webidl/#es-float
impl ToJSValConvertible for f32 {
#[inline]
unsafe fn to_jsval(&self, _cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(RUST_JS_NumberValue(*self as f64));
}
}
// https://heycam.github.io/webidl/#es-float
impl FromJSValConvertible for f32 {
type Config = ();
unsafe fn from_jsval(cx: *mut JSContext, val: JS::HandleValue, _option: ()) -> Result<ConversionResult<f32>, ()> {
let result = ToNumber(cx, val);
result.map(|f| f as f32).map(ConversionResult::Success)
}
}
// https://heycam.github.io/webidl/#es-double
impl ToJSValConvertible for f64 {
#[inline]
unsafe fn to_jsval(&self, _cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(RUST_JS_NumberValue(*self));
}
}
// https://heycam.github.io/webidl/#es-double
impl FromJSValConvertible for f64 {
type Config = ();
unsafe fn from_jsval(cx: *mut JSContext, val: JS::HandleValue, _option: ()) -> Result<ConversionResult<f64>, ()> {
ToNumber(cx, val).map(ConversionResult::Success)
}
}
/// Converts a `JSString`, encoded in "Latin1" (i.e. U+0000-U+00FF encoded as 0x00-0xFF) into a
/// `String`.
pub unsafe fn latin1_to_string(cx: *mut JSContext, s: *mut JSString) -> String {
assert!(JS_StringHasLatin1Chars(s));
let mut length = 0;
let chars = JS_GetLatin1StringCharsAndLength(cx, ptr::null(), s, &mut length);
assert!(!chars.is_null());
let chars = slice::from_raw_parts(chars, length as usize);
let mut s = String::with_capacity(length as usize);
s.extend(chars.iter().map(|&c| c as char));
s
}
// https://heycam.github.io/webidl/#es-USVString
impl ToJSValConvertible for str {
#[inline]
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
let mut string_utf16: Vec<u16> = Vec::with_capacity(self.len());
string_utf16.extend(self.encode_utf16());
let jsstr = JS_NewUCStringCopyN(cx,
string_utf16.as_ptr(),
string_utf16.len() as libc::size_t);
if jsstr.is_null() {
panic!("JS_NewUCStringCopyN failed");
}
rval.set(StringValue(&*jsstr));
}
}
// https://heycam.github.io/webidl/#es-USVString
impl ToJSValConvertible for String {
#[inline]
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
(**self).to_jsval(cx, rval);
}
}
// https://heycam.github.io/webidl/#es-USVString
impl FromJSValConvertible for String {
type Config = ();
unsafe fn from_jsval(cx: *mut JSContext, value: JS::HandleValue, _: ()) -> Result<ConversionResult<String>, ()> {
let jsstr = ToString(cx, value);
if jsstr.is_null() {
debug!("ToString failed");
return Err(());
}
if JS_StringHasLatin1Chars(jsstr) {
return Ok(latin1_to_string(cx, jsstr)).map(ConversionResult::Success);
}
let mut length = 0;
let chars = JS_GetTwoByteStringCharsAndLength(cx, ptr::null(), jsstr, &mut length);
assert!(!chars.is_null());
let char_vec = slice::from_raw_parts(chars, length as usize);
Ok(String::from_utf16_lossy(char_vec)).map(ConversionResult::Success)
}
}
impl<T: ToJSValConvertible> ToJSValConvertible for Option<T> {
#[inline]
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
match self {
&Some(ref value) => value.to_jsval(cx, rval),
&None => rval.set(NullValue()),
}
}
}
impl<T: ToJSValConvertible> ToJSValConvertible for Rc<T> {
#[inline]
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
(**self).to_jsval(cx, rval)
}
}
impl<T: FromJSValConvertible> FromJSValConvertible for Option<T> {
type Config = T::Config;
unsafe fn from_jsval(cx: *mut JSContext,
value: JS::HandleValue,
option: T::Config)
-> Result<ConversionResult<Option<T>>, ()> {
if value.get().is_null_or_undefined() {
Ok(ConversionResult::Success(None))
} else {
Ok(match try!(FromJSValConvertible::from_jsval(cx, value, option)) {
ConversionResult::Success(v) => ConversionResult::Success(Some(v)),
ConversionResult::Failure(v) => ConversionResult::Failure(v),
})
}
}
}
// https://heycam.github.io/webidl/#es-sequence
impl<T: ToJSValConvertible> ToJSValConvertible for Vec<T> {
#[inline]
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
rooted!(in(cx) let js_array = JS_NewArrayObject1(cx, self.len() as libc::size_t));
assert!(!js_array.handle().is_null());
rooted!(in(cx) let mut val = UndefinedValue());
for (index, obj) in self.iter().enumerate() {
obj.to_jsval(cx, val.handle_mut());
assert!(JS_DefineElement(
cx,
js_array.handle(),
index as u32,
val.handle(),
JSPROP_ENUMERATE as _
));
}
rval.set(ObjectValue(js_array.handle().get()));
}
}
/// Rooting guard for the iterator field of ForOfIterator.
/// Behaves like RootedGuard (roots on creation, unroots on drop),
/// but borrows and allows access to the whole ForOfIterator, so
/// that methods on ForOfIterator can still be used through it.
struct ForOfIteratorGuard<'a> {
root: &'a mut JS::ForOfIterator
}
impl<'a> ForOfIteratorGuard<'a> {
fn new(cx: *mut JSContext, root: &'a mut JS::ForOfIterator) -> Self {
unsafe {
root.iterator.register_with_root_lists(cx);
}
ForOfIteratorGuard {
root: root
}
}
}
impl<'a> Drop for ForOfIteratorGuard<'a> {
fn drop(&mut self) {
unsafe {
self.root.iterator.remove_from_root_stack();
}
}
}
impl<C: Clone, T: FromJSValConvertible<Config=C>> FromJSValConvertible for Vec<T> {
type Config = C;
unsafe fn from_jsval(cx: *mut JSContext,
value: JS::HandleValue,
option: C)
-> Result<ConversionResult<Vec<T>>, ()> {
let mut iterator = JS::ForOfIterator {
cx_: cx,
iterator: JS::RootedObject::new_unrooted(),
index: ::std::u32::MAX, // NOT_ARRAY
};
let iterator = ForOfIteratorGuard::new(cx, &mut iterator);
let iterator = &mut *iterator.root;
if !iterator.init(value, JS::ForOfIterator_NonIterableBehavior::AllowNonIterable) {
return Err(())
}
if iterator.iterator.ptr.is_null() {
return Ok(ConversionResult::Failure("Value is not iterable".into()));
}
let mut ret = vec![];
loop {
let mut done = false;
rooted!(in(cx) let mut val = UndefinedValue());
if !iterator.next(val.handle_mut(), &mut done) {
return Err(())
}
if done {
break;
}
ret.push(match try!(T::from_jsval(cx, val.handle(), option.clone())) {
ConversionResult::Success(v) => v,
ConversionResult::Failure(e) => return Ok(ConversionResult::Failure(e)),
});
}
Ok(ret).map(ConversionResult::Success)
}
}
// https://heycam.github.io/webidl/#es-object
impl ToJSValConvertible for *mut JSObject {
#[inline]
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(ObjectOrNullValue(*self));
maybe_wrap_object_or_null_value(cx, rval);
}
}
// https://heycam.github.io/webidl/#es-object
#[cfg(feature = "nonzero")]
impl ToJSValConvertible for NonZero<*mut JSObject> {
#[inline]
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
use rust::maybe_wrap_object_value;
rval.set(ObjectValue(self.get()));
maybe_wrap_object_value(cx, rval);
}
}
// https://heycam.github.io/webidl/#es-object
impl ToJSValConvertible for Heap<*mut JSObject> {
#[inline]
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: JS::MutableHandleValue) {
rval.set(ObjectOrNullValue(self.get()));
maybe_wrap_object_or_null_value(cx, rval);
}
}

Просмотреть файл

@ -1,73 +0,0 @@
/* 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/. */
//! Functions to throw JavaScript exceptions from Rust.
#![deny(missing_docs)]
use jsapi::root::*;
use libc;
use std::ffi::CString;
use std::{mem, os, ptr};
/// Format string used to throw javascript errors.
static ERROR_FORMAT_STRING_STRING: [libc::c_char; 4] = [
'{' as libc::c_char,
'0' as libc::c_char,
'}' as libc::c_char,
0 as libc::c_char,
];
/// Format string struct used to throw `TypeError`s.
static mut TYPE_ERROR_FORMAT_STRING: JSErrorFormatString = JSErrorFormatString {
name: b"RUSTMSG_TYPE_ERROR\0" as *const _ as *const libc::c_char,
format: &ERROR_FORMAT_STRING_STRING as *const libc::c_char,
argCount: 1,
exnType: JSExnType::JSEXN_TYPEERR as i16,
};
/// Format string struct used to throw `RangeError`s.
static mut RANGE_ERROR_FORMAT_STRING: JSErrorFormatString = JSErrorFormatString {
name: b"RUSTMSG_RANGE_ERROR\0" as *const _ as *const libc::c_char,
format: &ERROR_FORMAT_STRING_STRING as *const libc::c_char,
argCount: 1,
exnType: JSExnType::JSEXN_RANGEERR as i16,
};
/// Callback used to throw javascript errors.
/// See throw_js_error for info about error_number.
unsafe extern "C" fn get_error_message(_user_ref: *mut os::raw::c_void,
error_number: libc::c_uint)
-> *const JSErrorFormatString {
let num: JSExnType = mem::transmute(error_number);
match num {
JSExnType::JSEXN_TYPEERR => &TYPE_ERROR_FORMAT_STRING as *const JSErrorFormatString,
JSExnType::JSEXN_RANGEERR => &RANGE_ERROR_FORMAT_STRING as *const JSErrorFormatString,
_ => panic!("Bad js error number given to get_error_message: {}",
error_number),
}
}
/// Helper fn to throw a javascript error with the given message and number.
/// Reuse the jsapi error codes to distinguish the error_number
/// passed back to the get_error_message callback.
/// c_uint is u32, so this cast is safe, as is casting to/from i32 from there.
unsafe fn throw_js_error(cx: *mut JSContext, error: &str, error_number: u32) {
let error = CString::new(error).unwrap();
JS_ReportErrorNumberUTF8(cx,
Some(get_error_message),
ptr::null_mut(),
error_number,
error.as_ptr());
}
/// Throw a `TypeError` with the given message.
pub unsafe fn throw_type_error(cx: *mut JSContext, error: &str) {
throw_js_error(cx, error, JSExnType::JSEXN_TYPEERR as u32);
}
/// Throw a `RangeError` with the given message.
pub unsafe fn throw_range_error(cx: *mut JSContext, error: &str) {
throw_js_error(cx, error, JSExnType::JSEXN_RANGEERR as u32);
}

Просмотреть файл

@ -1,348 +0,0 @@
use jsapi::root::*;
use heap::Heap;
use std::os::raw::c_void;
pub enum Action { }
unsafe impl Sync for ProxyTraps {}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct ProxyTraps {
pub enter: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
id: JS::HandleId,
action: Action,
bp: *mut bool)
-> bool>,
pub getOwnPropertyDescriptor:
::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
id: JS::HandleId,
desc: JS::MutableHandle<JS::PropertyDescriptor>)
-> bool>,
pub defineProperty:
::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
id: JS::HandleId,
desc: JS::Handle<JS::PropertyDescriptor>,
result: *mut JS::ObjectOpResult)
-> bool>,
pub ownPropertyKeys: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
props: *mut JS::AutoIdVector)
-> bool>,
pub delete_: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
id: JS::HandleId,
result: *mut JS::ObjectOpResult)
-> bool>,
pub enumerate: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
objp: JS::MutableHandleObject)
-> bool>,
pub getPrototypeIfOrdinary:
::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
isOrdinary: *mut bool,
protop: JS::MutableHandleObject)
-> bool>,
pub preventExtensions:
::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
result: *mut JS::ObjectOpResult)
-> bool>,
pub isExtensible: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
succeeded: *mut bool)
-> bool>,
pub has: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
id: JS::HandleId,
bp: *mut bool)
-> bool>,
pub get: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
receiver: JS::HandleValue,
id: JS::HandleId,
vp: JS::MutableHandleValue)
-> bool>,
pub set: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
id: JS::HandleId,
v: JS::HandleValue,
receiver: JS::HandleValue,
result: *mut JS::ObjectOpResult)
-> bool>,
pub call: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
args: *const JS::CallArgs)
-> bool>,
pub construct: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
args: *const JS::CallArgs)
-> bool>,
pub getPropertyDescriptor:
::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
id: JS::HandleId,
desc: JS::MutableHandle<JS::PropertyDescriptor>)
-> bool>,
pub hasOwn: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
id: JS::HandleId,
bp: *mut bool)
-> bool>,
pub getOwnEnumerablePropertyKeys:
::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
props: *mut JS::AutoIdVector)
-> bool>,
pub nativeCall: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
test: JS::IsAcceptableThis,
_impl: JS::NativeImpl,
args: JS::CallArgs)
-> bool>,
pub hasInstance: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
v: JS::MutableHandleValue,
bp: *mut bool)
-> bool>,
pub objectClassIs: ::std::option::Option<unsafe extern "C" fn(obj: JS::HandleObject,
classValue: js::ESClass,
cx: *mut JSContext)
-> bool>,
pub className: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject)
-> *const i8>,
pub fun_toString: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
indent: u32)
-> *mut JSString>,
pub boxedValue_unbox: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
proxy: JS::HandleObject,
vp: JS::MutableHandleValue)
-> bool>,
pub defaultValue: ::std::option::Option<unsafe extern "C" fn(cx: *mut JSContext,
obj: JS::HandleObject,
hint: JSType,
vp: JS::MutableHandleValue)
-> bool>,
pub trace:
::std::option::Option<unsafe extern "C" fn(trc: *mut JSTracer, proxy: *mut JSObject)>,
pub finalize:
::std::option::Option<unsafe extern "C" fn(fop: *mut JSFreeOp, proxy: *mut JSObject)>,
pub objectMoved:
::std::option::Option<unsafe extern "C" fn(proxy: *mut JSObject, old: *const JSObject)>,
pub isCallable: ::std::option::Option<unsafe extern "C" fn(obj: *mut JSObject) -> bool>,
pub isConstructor: ::std::option::Option<unsafe extern "C" fn(obj: *mut JSObject) -> bool>,
}
impl ::std::default::Default for ProxyTraps {
fn default() -> ProxyTraps {
unsafe { ::std::mem::zeroed() }
}
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct WrapperProxyHandler {
pub mTraps: ProxyTraps,
}
impl ::std::default::Default for WrapperProxyHandler {
fn default() -> WrapperProxyHandler {
unsafe { ::std::mem::zeroed() }
}
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct ForwardingProxyHandler {
pub mTraps: ProxyTraps,
pub mExtra: *const ::libc::c_void,
}
impl ::std::default::Default for ForwardingProxyHandler {
fn default() -> ForwardingProxyHandler {
unsafe { ::std::mem::zeroed() }
}
}
extern "C" {
pub fn InvokeGetOwnPropertyDescriptor(handler: *const ::libc::c_void,
cx: *mut JSContext,
proxy: JS::HandleObject,
id: JS::HandleId,
desc: JS::MutableHandle<JS::PropertyDescriptor>)
-> bool;
pub fn InvokeHasOwn(handler: *const ::libc::c_void,
cx: *mut JSContext,
proxy: JS::HandleObject,
id: JS::HandleId,
bp: *mut bool)
-> bool;
pub fn RUST_JS_NumberValue(d: f64) -> JS::Value;
pub fn RUST_FUNCTION_VALUE_TO_JITINFO(v: JS::Value) -> *const JSJitInfo;
pub fn CreateCallArgsFromVp(argc: u32, v: *mut JS::Value) -> JS::CallArgs;
pub fn CallJitGetterOp(info: *const JSJitInfo,
cx: *mut JSContext,
thisObj: JS::HandleObject,
specializedThis: *mut ::libc::c_void,
argc: u32,
vp: *mut JS::Value)
-> bool;
pub fn CallJitSetterOp(info: *const JSJitInfo,
cx: *mut JSContext,
thisObj: JS::HandleObject,
specializedThis: *mut ::libc::c_void,
argc: u32,
vp: *mut JS::Value)
-> bool;
pub fn CallJitMethodOp(info: *const JSJitInfo,
cx: *mut JSContext,
thisObj: JS::HandleObject,
specializedThis: *mut ::libc::c_void,
argc: u32,
vp: *mut JS::Value)
-> bool;
pub fn CreateProxyHandler(aTraps: *const ProxyTraps,
aExtra: *const ::libc::c_void)
-> *const ::libc::c_void;
pub fn CreateWrapperProxyHandler(aTraps: *const ProxyTraps) -> *const ::libc::c_void;
pub fn CreateRustJSPrincipal(origin: *const ::libc::c_void,
destroy: Option<unsafe extern "C" fn
(principal: *mut JSPrincipals)>,
write: Option<unsafe extern "C" fn
(cx: *mut JSContext,
writer: *mut JSStructuredCloneWriter)
-> bool>)
-> *mut JSPrincipals;
pub fn GetPrincipalOrigin(principal: *const JSPrincipals) -> *const ::libc::c_void;
pub fn GetCrossCompartmentWrapper() -> *const ::libc::c_void;
pub fn GetSecurityWrapper() -> *const ::libc::c_void;
pub fn NewCompileOptions(aCx: *mut JSContext,
aFile: *const ::libc::c_char,
aLine: u32)
-> *mut JS::ReadOnlyCompileOptions;
pub fn DeleteCompileOptions(aOpts: *mut JS::ReadOnlyCompileOptions);
pub fn NewProxyObject(aCx: *mut JSContext,
aHandler: *const ::libc::c_void,
aPriv: JS::HandleValue,
proto: *mut JSObject,
parent: *mut JSObject,
call: *mut JSObject,
construct: *mut JSObject)
-> *mut JSObject;
pub fn WrapperNew(aCx: *mut JSContext,
aObj: JS::HandleObject,
aHandler: *const ::libc::c_void,
aClass: *const JSClass,
aSingleton: bool)
-> *mut JSObject;
pub fn NewWindowProxy(aCx: *mut JSContext,
aObj: JS::HandleObject,
aHandler: *const ::libc::c_void)
-> *mut JSObject;
pub fn GetWindowProxyClass() -> *const js::Class;
pub fn GetProxyPrivate(obj: *mut JSObject) -> JS::Value;
pub fn SetProxyPrivate(obj: *mut JSObject, private: *const JS::Value);
pub fn GetProxyReservedSlot(obj: *mut JSObject, slot: u32) -> JS::Value;
pub fn SetProxyReservedSlot(obj: *mut JSObject, slot: u32, val: *const JS::Value);
pub fn RUST_JSID_IS_INT(id: JS::HandleId) -> bool;
pub fn RUST_JSID_TO_INT(id: JS::HandleId) -> i32;
pub fn int_to_jsid(i: i32) -> jsid;
pub fn RUST_JSID_IS_STRING(id: JS::HandleId) -> bool;
pub fn RUST_JSID_TO_STRING(id: JS::HandleId) -> *mut JSString;
pub fn RUST_SYMBOL_TO_JSID(sym: *mut JS::Symbol) -> jsid;
pub fn RUST_SET_JITINFO(func: *mut JSFunction, info: *const JSJitInfo);
pub fn RUST_INTERNED_STRING_TO_JSID(cx: *mut JSContext, str: *mut JSString) -> jsid;
pub fn RUST_js_GetErrorMessage(userRef: *mut ::libc::c_void,
errorNumber: u32)
-> *const JSErrorFormatString;
pub fn IsProxyHandlerFamily(obj: *mut JSObject) -> u8;
pub fn GetProxyHandlerExtra(obj: *mut JSObject) -> *const ::libc::c_void;
pub fn GetProxyHandler(obj: *mut JSObject) -> *const ::libc::c_void;
pub fn ReportError(aCx: *mut JSContext, aError: *const i8);
pub fn IsWrapper(obj: *mut JSObject) -> bool;
pub fn UnwrapObject(obj: *mut JSObject, stopAtOuter: u8) -> *mut JSObject;
pub fn UncheckedUnwrapObject(obj: *mut JSObject, stopAtOuter: u8) -> *mut JSObject;
pub fn CreateAutoIdVector(cx: *mut JSContext) -> *mut JS::AutoIdVector;
pub fn AppendToAutoIdVector(v: *mut JS::AutoIdVector, id: jsid) -> bool;
pub fn SliceAutoIdVector(v: *const JS::AutoIdVector, length: *mut usize) -> *const jsid;
pub fn DestroyAutoIdVector(v: *mut JS::AutoIdVector);
pub fn CreateAutoObjectVector(aCx: *mut JSContext) -> *mut JS::AutoObjectVector;
pub fn AppendToAutoObjectVector(v: *mut JS::AutoObjectVector, obj: *mut JSObject) -> bool;
pub fn DeleteAutoObjectVector(v: *mut JS::AutoObjectVector);
pub fn CollectServoSizes(rt: *mut JSRuntime, sizes: *mut JS::ServoSizes) -> bool;
pub fn CallIdTracer(trc: *mut JSTracer, idp: *mut Heap<jsid>, name: *const ::libc::c_char);
pub fn CallValueTracer(trc: *mut JSTracer,
valuep: *mut Heap<JS::Value>,
name: *const ::libc::c_char);
pub fn CallObjectTracer(trc: *mut JSTracer,
objp: *mut Heap<*mut JSObject>,
name: *const ::libc::c_char);
pub fn CallStringTracer(trc: *mut JSTracer,
strp: *mut Heap<*mut JSString>,
name: *const ::libc::c_char);
pub fn CallScriptTracer(trc: *mut JSTracer,
scriptp: *mut Heap<*mut JSScript>,
name: *const ::libc::c_char);
pub fn CallFunctionTracer(trc: *mut JSTracer,
funp: *mut Heap<*mut JSFunction>,
name: *const ::libc::c_char);
pub fn CallUnbarrieredObjectTracer(trc: *mut JSTracer,
objp: *mut *mut JSObject,
name: *const ::libc::c_char);
pub fn GetProxyHandlerFamily() -> *const c_void;
pub fn GetInt8ArrayLengthAndData(obj: *mut JSObject,
length: *mut u32,
isSharedMemory: *mut bool,
data: *mut *mut i8);
pub fn GetUint8ArrayLengthAndData(obj: *mut JSObject,
length: *mut u32,
isSharedMemory: *mut bool,
data: *mut *mut u8);
pub fn GetUint8ClampedArrayLengthAndData(obj: *mut JSObject,
length: *mut u32,
isSharedMemory: *mut bool,
data: *mut *mut u8);
pub fn GetInt16ArrayLengthAndData(obj: *mut JSObject,
length: *mut u32,
isSharedMemory: *mut bool,
data: *mut *mut i16);
pub fn GetUint16ArrayLengthAndData(obj: *mut JSObject,
length: *mut u32,
isSharedMemory: *mut bool,
data: *mut *mut u16);
pub fn GetInt32ArrayLengthAndData(obj: *mut JSObject,
length: *mut u32,
isSharedMemory: *mut bool,
data: *mut *mut i32);
pub fn GetUint32ArrayLengthAndData(obj: *mut JSObject,
length: *mut u32,
isSharedMemory: *mut bool,
data: *mut *mut u32);
pub fn GetFloat32ArrayLengthAndData(obj: *mut JSObject,
length: *mut u32,
isSharedMemory: *mut bool,
data: *mut *mut f32);
pub fn GetFloat64ArrayLengthAndData(obj: *mut JSObject,
length: *mut u32,
isSharedMemory: *mut bool,
data: *mut *mut f64);
pub fn NewJSAutoStructuredCloneBuffer(scope: JS::StructuredCloneScope,
callbacks: *const JSStructuredCloneCallbacks)
-> *mut JSAutoStructuredCloneBuffer;
pub fn DeleteJSAutoStructuredCloneBuffer(buf: *mut JSAutoStructuredCloneBuffer);
pub fn GetLengthOfJSStructuredCloneData(data: *mut JSStructuredCloneData) -> usize;
pub fn CopyJSStructuredCloneData(src: *mut JSStructuredCloneData, dest: *mut u8);
pub fn WriteBytesToJSStructuredCloneData(src: *const u8,
len: usize,
dest: *mut JSStructuredCloneData)
-> bool;
pub fn IsDebugBuild() -> bool;
}
#[test]
fn jsglue_cpp_configured_correctly() {
assert_eq!(cfg!(feature = "debugmozjs"), unsafe { IsDebugBuild() });
}

Просмотреть файл

@ -1,172 +0,0 @@
use glue;
use heapsize::HeapSizeOf;
use jsapi::root::*;
use rust::GCMethods;
use std::cell::UnsafeCell;
use std::ptr;
/// Types that can be traced.
///
/// This trait is unsafe; if it is implemented incorrectly, the GC may end up
/// collecting objects that are still reachable.
pub unsafe trait Trace {
unsafe fn trace(&self, trc: *mut JSTracer);
}
/**
* The Heap<T> class is a heap-stored reference to a JS GC thing. All members of
* heap classes that refer to GC things should use Heap<T> (or possibly
* TenuredHeap<T>, described below).
*
* Heap<T> is an abstraction that hides some of the complexity required to
* maintain GC invariants for the contained reference. It uses operator
* overloading to provide a normal pointer interface, but notifies the GC every
* time the value it contains is updated. This is necessary for generational GC,
* which keeps track of all pointers into the nursery.
*
* Heap<T> instances must be traced when their containing object is traced to
* keep the pointed-to GC thing alive.
*
* Heap<T> objects should only be used on the heap. GC references stored on the
* C/C++ stack must use Rooted/Handle/MutableHandle instead.
*
* Type T must be a public GC pointer type.
*/
#[repr(C)]
#[derive(Debug)]
pub struct Heap<T: GCMethods + Copy> {
ptr: UnsafeCell<T>,
}
impl<T: GCMethods + Copy> Heap<T> {
pub fn new(v: T) -> Heap<T>
where Heap<T>: Default
{
let ptr = Heap::default();
ptr.set(v);
ptr
}
pub fn set(&self, v: T) {
unsafe {
let ptr = self.ptr.get();
let prev = *ptr;
*ptr = v;
T::post_barrier(ptr, prev, v);
}
}
pub fn get(&self) -> T {
unsafe {
*self.ptr.get()
}
}
pub unsafe fn get_unsafe(&self) -> *mut T {
self.ptr.get()
}
pub fn handle(&self) -> JS::Handle<T> {
unsafe {
JS::Handle::from_marked_location(self.ptr.get() as *const _)
}
}
pub fn handle_mut(&self) -> JS::MutableHandle<T> {
unsafe {
JS::MutableHandle::from_marked_location(self.ptr.get())
}
}
}
impl<T: GCMethods + Copy> Clone for Heap<T>
where Heap<T>: Default
{
fn clone(&self) -> Self {
Heap::new(self.get())
}
}
impl<T: GCMethods + Copy + PartialEq> PartialEq for Heap<T> {
fn eq(&self, other: &Self) -> bool {
self.get() == other.get()
}
}
impl<T> Default for Heap<*mut T>
where *mut T: GCMethods + Copy
{
fn default() -> Heap<*mut T> {
Heap {
ptr: UnsafeCell::new(ptr::null_mut())
}
}
}
impl Default for Heap<JS::Value> {
fn default() -> Heap<JS::Value> {
Heap {
ptr: UnsafeCell::new(JS::Value::default())
}
}
}
impl<T: GCMethods + Copy> Drop for Heap<T> {
fn drop(&mut self) {
unsafe {
let prev = self.ptr.get();
T::post_barrier(prev, *prev, T::initial());
}
}
}
// Creates a C string literal `$str`.
macro_rules! c_str {
($str:expr) => {
concat!($str, "\0").as_ptr() as *const ::std::os::raw::c_char
}
}
unsafe impl Trace for Heap<*mut JSFunction> {
unsafe fn trace(&self, trc: *mut JSTracer) {
glue::CallFunctionTracer(trc, self as *const _ as *mut Self, c_str!("function"));
}
}
unsafe impl Trace for Heap<*mut JSObject> {
unsafe fn trace(&self, trc: *mut JSTracer) {
glue::CallObjectTracer(trc, self as *const _ as *mut Self, c_str!("object"));
}
}
unsafe impl Trace for Heap<*mut JSScript> {
unsafe fn trace(&self, trc: *mut JSTracer) {
glue::CallScriptTracer(trc, self as *const _ as *mut Self, c_str!("script"));
}
}
unsafe impl Trace for Heap<*mut JSString> {
unsafe fn trace(&self, trc: *mut JSTracer) {
glue::CallStringTracer(trc, self as *const _ as *mut Self, c_str!("string"));
}
}
unsafe impl Trace for Heap<JS::Value> {
unsafe fn trace(&self, trc: *mut JSTracer) {
glue::CallValueTracer(trc, self as *const _ as *mut Self, c_str!("value"));
}
}
unsafe impl Trace for Heap<jsid> {
unsafe fn trace(&self, trc: *mut JSTracer) {
glue::CallIdTracer(trc, self as *const _ as *mut Self, c_str!("id"));
}
}
// This is measured properly by the heap measurement implemented in
// SpiderMonkey.
impl<T: Copy + GCMethods> HeapSizeOf for Heap<T> {
fn heap_size_of_children(&self) -> usize {
0
}
}

Просмотреть файл

@ -1,5 +0,0 @@
#[cfg(feature = "debugmozjs")]
include!(concat!(env!("OUT_DIR"), "/jsapi_debug.rs"));
#[cfg(not(feature = "debugmozjs"))]
include!(concat!(env!("OUT_DIR"), "/jsapi.rs"));

Просмотреть файл

@ -1,940 +0,0 @@
/* 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/. */
#define __STDC_LIMIT_MACROS
#include <stdint.h>
#include "js-config.h"
#ifdef JS_DEBUG
// A hack for MFBT. Guard objects need this to work.
#define DEBUG 1
#endif
#include "jsapi.h"
#include "jsfriendapi.h"
#include "js/Proxy.h"
#include "js/Class.h"
#include "jswrapper.h"
#include "js/MemoryMetrics.h"
#include "js/Principals.h"
#include "assert.h"
struct ProxyTraps {
bool (*enter)(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
js::BaseProxyHandler::Action action, bool *bp);
bool (*getOwnPropertyDescriptor)(JSContext *cx, JS::HandleObject proxy,
JS::HandleId id,
JS::MutableHandle<JS::PropertyDescriptor> desc);
bool (*defineProperty)(JSContext *cx, JS::HandleObject proxy,
JS::HandleId id,
JS::Handle<JS::PropertyDescriptor> desc,
JS::ObjectOpResult &result);
bool (*ownPropertyKeys)(JSContext *cx, JS::HandleObject proxy,
JS::AutoIdVector &props);
bool (*delete_)(JSContext *cx, JS::HandleObject proxy,
JS::HandleId id, JS::ObjectOpResult &result);
JSObject* (*enumerate)(JSContext *cx, JS::HandleObject proxy);
bool (*getPrototypeIfOrdinary)(JSContext *cx, JS::HandleObject proxy,
bool *isOrdinary, JS::MutableHandleObject protop);
// getPrototype
// setPrototype
// setImmutablePrototype
bool (*preventExtensions)(JSContext *cx, JS::HandleObject proxy,
JS::ObjectOpResult &result);
bool (*isExtensible)(JSContext *cx, JS::HandleObject proxy, bool *succeeded);
bool (*has)(JSContext *cx, JS::HandleObject proxy,
JS::HandleId id, bool *bp);
bool (*get)(JSContext *cx, JS::HandleObject proxy, JS::HandleValue receiver,
JS::HandleId id, JS::MutableHandleValue vp);
bool (*set)(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
JS::HandleValue v, JS::HandleValue receiver,
JS::ObjectOpResult &result);
bool (*call)(JSContext *cx, JS::HandleObject proxy,
const JS::CallArgs &args);
bool (*construct)(JSContext *cx, JS::HandleObject proxy,
const JS::CallArgs &args);
bool (*getPropertyDescriptor)(JSContext *cx, JS::HandleObject proxy,
JS::HandleId id,
JS::MutableHandle<JS::PropertyDescriptor> desc);
bool (*hasOwn)(JSContext *cx, JS::HandleObject proxy,
JS::HandleId id, bool *bp);
bool (*getOwnEnumerablePropertyKeys)(JSContext *cx, JS::HandleObject proxy,
JS::AutoIdVector &props);
bool (*nativeCall)(JSContext *cx, JS::IsAcceptableThis test,
JS::NativeImpl impl, JS::CallArgs args);
bool (*hasInstance)(JSContext *cx, JS::HandleObject proxy,
JS::MutableHandleValue v, bool *bp);
bool (*objectClassIs)(JS::HandleObject obj, js::ESClass classValue,
JSContext *cx);
const char *(*className)(JSContext *cx, JS::HandleObject proxy);
JSString* (*fun_toString)(JSContext *cx, JS::HandleObject proxy,
bool isToString);
//bool (*regexp_toShared)(JSContext *cx, JS::HandleObject proxy, RegExpGuard *g);
bool (*boxedValue_unbox)(JSContext *cx, JS::HandleObject proxy,
JS::MutableHandleValue vp);
bool (*defaultValue)(JSContext *cx, JS::HandleObject obj, JSType hint, JS::MutableHandleValue vp);
void (*trace)(JSTracer *trc, JSObject *proxy);
void (*finalize)(JSFreeOp *fop, JSObject *proxy);
void (*objectMoved)(JSObject *proxy, const JSObject *old);
bool (*isCallable)(JSObject *obj);
bool (*isConstructor)(JSObject *obj);
// watch
// unwatch
// getElements
// weakmapKeyDelegate
// isScripted
};
static int HandlerFamily;
#define DEFER_TO_TRAP_OR_BASE_CLASS(_base) \
\
/* Standard internal methods. */ \
virtual JSObject* enumerate(JSContext *cx, \
JS::HandleObject proxy) const override \
{ \
return mTraps.enumerate \
? mTraps.enumerate(cx, proxy) \
: _base::enumerate(cx, proxy); \
} \
\
virtual bool has(JSContext* cx, JS::HandleObject proxy, \
JS::HandleId id, bool *bp) const override \
{ \
return mTraps.has \
? mTraps.has(cx, proxy, id, bp) \
: _base::has(cx, proxy, id, bp); \
} \
\
virtual bool get(JSContext* cx, JS::HandleObject proxy, \
JS::HandleValue receiver, \
JS::HandleId id, JS::MutableHandleValue vp) const override \
{ \
return mTraps.get \
? mTraps.get(cx, proxy, receiver, id, vp) \
: _base::get(cx, proxy, receiver, id, vp); \
} \
\
virtual bool set(JSContext* cx, JS::HandleObject proxy, \
JS::HandleId id, JS::HandleValue v, \
JS::HandleValue receiver, \
JS::ObjectOpResult &result) const override \
{ \
return mTraps.set \
? mTraps.set(cx, proxy, id, v, receiver, result) \
: _base::set(cx, proxy, id, v, receiver, result); \
} \
\
virtual bool call(JSContext* cx, JS::HandleObject proxy, \
const JS::CallArgs &args) const override \
{ \
return mTraps.call \
? mTraps.call(cx, proxy, args) \
: _base::call(cx, proxy, args); \
} \
\
virtual bool construct(JSContext* cx, JS::HandleObject proxy, \
const JS::CallArgs &args) const override \
{ \
return mTraps.construct \
? mTraps.construct(cx, proxy, args) \
: _base::construct(cx, proxy, args); \
} \
\
/* Spidermonkey extensions. */ \
virtual bool hasOwn(JSContext* cx, JS::HandleObject proxy, JS::HandleId id, \
bool* bp) const override \
{ \
return mTraps.hasOwn \
? mTraps.hasOwn(cx, proxy, id, bp) \
: _base::hasOwn(cx, proxy, id, bp); \
} \
\
virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, \
JS::HandleObject proxy, \
JS::AutoIdVector &props) const override \
{ \
return mTraps.getOwnEnumerablePropertyKeys \
? mTraps.getOwnEnumerablePropertyKeys(cx, proxy, props) \
: _base::getOwnEnumerablePropertyKeys(cx, proxy, props); \
} \
\
virtual bool nativeCall(JSContext* cx, JS::IsAcceptableThis test, \
JS::NativeImpl impl, \
const JS::CallArgs& args) const override \
{ \
return mTraps.nativeCall \
? mTraps.nativeCall(cx, test, impl, args) \
: _base::nativeCall(cx, test, impl, args); \
} \
\
virtual bool hasInstance(JSContext* cx, JS::HandleObject proxy, \
JS::MutableHandleValue v, bool* bp) const override \
{ \
return mTraps.hasInstance \
? mTraps.hasInstance(cx, proxy, v, bp) \
: _base::hasInstance(cx, proxy, v, bp); \
} \
\
virtual const char *className(JSContext *cx, JS::HandleObject proxy) const override\
{ \
return mTraps.className \
? mTraps.className(cx, proxy) \
: _base::className(cx, proxy); \
} \
\
virtual JSString* fun_toString(JSContext* cx, JS::HandleObject proxy, \
bool isToString) const override \
{ \
return mTraps.fun_toString \
? mTraps.fun_toString(cx, proxy, isToString) \
: _base::fun_toString(cx, proxy, isToString); \
} \
\
virtual bool boxedValue_unbox(JSContext* cx, JS::HandleObject proxy, \
JS::MutableHandleValue vp) const override \
{ \
return mTraps.boxedValue_unbox \
? mTraps.boxedValue_unbox(cx, proxy, vp) \
: _base::boxedValue_unbox(cx, proxy, vp); \
} \
\
virtual void trace(JSTracer* trc, JSObject* proxy) const override \
{ \
mTraps.trace \
? mTraps.trace(trc, proxy) \
: _base::trace(trc, proxy); \
} \
\
virtual void finalize(JSFreeOp* fop, JSObject* proxy) const override \
{ \
mTraps.finalize \
? mTraps.finalize(fop, proxy) \
: _base::finalize(fop, proxy); \
} \
\
virtual void objectMoved(JSObject* proxy, \
const JSObject *old) const override \
{ \
mTraps.objectMoved \
? mTraps.objectMoved(proxy, old) \
: _base::objectMoved(proxy, old); \
} \
\
virtual bool isCallable(JSObject* obj) const override \
{ \
return mTraps.isCallable \
? mTraps.isCallable(obj) \
: _base::isCallable(obj); \
} \
\
virtual bool isConstructor(JSObject* obj) const override \
{ \
return mTraps.isConstructor \
? mTraps.isConstructor(obj) \
: _base::isConstructor(obj); \
}
class WrapperProxyHandler : public js::Wrapper
{
ProxyTraps mTraps;
public:
WrapperProxyHandler(const ProxyTraps& aTraps)
: js::Wrapper(0), mTraps(aTraps) {}
virtual bool finalizeInBackground(const JS::Value& priv) const override
{
return false;
}
DEFER_TO_TRAP_OR_BASE_CLASS(js::Wrapper)
virtual bool getOwnPropertyDescriptor(JSContext *cx, JS::HandleObject proxy,
JS::HandleId id,
JS::MutableHandle<JS::PropertyDescriptor> desc) const override
{
return mTraps.getOwnPropertyDescriptor
? mTraps.getOwnPropertyDescriptor(cx, proxy, id, desc)
: js::Wrapper::getOwnPropertyDescriptor(cx, proxy, id, desc);
}
virtual bool defineProperty(JSContext *cx,
JS::HandleObject proxy, JS::HandleId id,
JS::Handle<JS::PropertyDescriptor> desc,
JS::ObjectOpResult &result) const override
{
return mTraps.defineProperty
? mTraps.defineProperty(cx, proxy, id, desc, result)
: js::Wrapper::defineProperty(cx, proxy, id, desc, result);
}
virtual bool ownPropertyKeys(JSContext *cx, JS::HandleObject proxy,
JS::AutoIdVector &props) const override
{
return mTraps.ownPropertyKeys
? mTraps.ownPropertyKeys(cx, proxy, props)
: js::Wrapper::ownPropertyKeys(cx, proxy, props);
}
virtual bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
JS::ObjectOpResult &result) const override
{
return mTraps.delete_
? mTraps.delete_(cx, proxy, id, result)
: js::Wrapper::delete_(cx, proxy, id, result);
}
virtual bool preventExtensions(JSContext *cx, JS::HandleObject proxy,
JS::ObjectOpResult &result) const override
{
return mTraps.preventExtensions
? mTraps.preventExtensions(cx, proxy, result)
: js::Wrapper::preventExtensions(cx, proxy, result);
}
virtual bool isExtensible(JSContext *cx, JS::HandleObject proxy,
bool *succeeded) const override
{
return mTraps.isExtensible
? mTraps.isExtensible(cx, proxy, succeeded)
: js::Wrapper::isExtensible(cx, proxy, succeeded);
}
virtual bool getPropertyDescriptor(JSContext *cx, JS::HandleObject proxy,
JS::HandleId id,
JS::MutableHandle<JS::PropertyDescriptor> desc) const override
{
return mTraps.getPropertyDescriptor
? mTraps.getPropertyDescriptor(cx, proxy, id, desc)
: js::Wrapper::getPropertyDescriptor(cx, proxy, id, desc);
}
};
class RustJSPrincipal : public JSPrincipals
{
const void* origin; //box with origin in it
void (*destroyCallback)(JSPrincipals *principal);
bool (*writeCallback)(JSContext* cx, JSStructuredCloneWriter* writer);
public:
RustJSPrincipal(const void* origin,
void (*destroy)(JSPrincipals *principal),
bool (*write)(JSContext* cx, JSStructuredCloneWriter* writer))
: JSPrincipals() {
this->origin = origin;
this->destroyCallback = destroy;
this->writeCallback = write;
}
virtual const void* getOrigin() {
return origin;
}
virtual void destroy() {
if(this->destroyCallback)
this->destroyCallback(this);
}
bool write(JSContext* cx, JSStructuredCloneWriter* writer) {
return this->writeCallback
? this->writeCallback(cx, writer)
: false;
}
};
class ForwardingProxyHandler : public js::BaseProxyHandler
{
ProxyTraps mTraps;
const void* mExtra;
public:
ForwardingProxyHandler(const ProxyTraps& aTraps, const void* aExtra)
: js::BaseProxyHandler(&HandlerFamily), mTraps(aTraps), mExtra(aExtra) {}
const void* getExtra() const {
return mExtra;
}
virtual bool finalizeInBackground(const JS::Value& priv) const override
{
return false;
}
DEFER_TO_TRAP_OR_BASE_CLASS(BaseProxyHandler)
virtual bool getOwnPropertyDescriptor(JSContext *cx, JS::HandleObject proxy,
JS::HandleId id,
JS::MutableHandle<JS::PropertyDescriptor> desc) const override
{
return mTraps.getOwnPropertyDescriptor(cx, proxy, id, desc);
}
virtual bool defineProperty(JSContext *cx,
JS::HandleObject proxy, JS::HandleId id,
JS::Handle<JS::PropertyDescriptor> desc,
JS::ObjectOpResult &result) const override
{
return mTraps.defineProperty(cx, proxy, id, desc, result);
}
virtual bool ownPropertyKeys(JSContext *cx, JS::HandleObject proxy,
JS::AutoIdVector &props) const override
{
return mTraps.ownPropertyKeys(cx, proxy, props);
}
virtual bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
JS::ObjectOpResult &result) const override
{
return mTraps.delete_(cx, proxy, id, result);
}
virtual bool getPrototypeIfOrdinary(JSContext* cx, JS::HandleObject proxy,
bool* isOrdinary,
JS::MutableHandleObject protop) const override
{
return mTraps.getPrototypeIfOrdinary(cx, proxy, isOrdinary, protop);
}
virtual bool preventExtensions(JSContext *cx, JS::HandleObject proxy,
JS::ObjectOpResult &result) const override
{
return mTraps.preventExtensions(cx, proxy, result);
}
virtual bool isExtensible(JSContext *cx, JS::HandleObject proxy,
bool *succeeded) const override
{
return mTraps.isExtensible(cx, proxy, succeeded);
}
virtual bool getPropertyDescriptor(JSContext *cx, JS::HandleObject proxy,
JS::HandleId id,
JS::MutableHandle<JS::PropertyDescriptor> desc) const override
{
return mTraps.getPropertyDescriptor(cx, proxy, id, desc);
}
};
extern "C" {
JSPrincipals*
CreateRustJSPrincipal(const void* origin,
void (*destroy)(JSPrincipals *principal),
bool (*write)(JSContext* cx, JSStructuredCloneWriter *writer)){
return new RustJSPrincipal(origin, destroy, write);
}
const void*
GetPrincipalOrigin(JSPrincipals* principal) {
return static_cast<RustJSPrincipal*>(principal)->getOrigin();
}
bool
InvokeGetOwnPropertyDescriptor(
const void *handler,
JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
JS::MutableHandle<JS::PropertyDescriptor> desc)
{
return static_cast<const ForwardingProxyHandler*>(handler)->
getOwnPropertyDescriptor(cx, proxy, id, desc);
}
bool
InvokeHasOwn(
const void *handler,
JSContext *cx, JS::HandleObject proxy,
JS::HandleId id, bool *bp)
{
return static_cast<const js::BaseProxyHandler*>(handler)->
hasOwn(cx, proxy, id, bp);
}
JS::Value
RUST_JS_NumberValue(double d)
{
return JS_NumberValue(d);
}
const JSJitInfo*
RUST_FUNCTION_VALUE_TO_JITINFO(JS::Value v)
{
return FUNCTION_VALUE_TO_JITINFO(v);
}
JS::CallArgs
CreateCallArgsFromVp(unsigned argc, JS::Value* vp)
{
return JS::CallArgsFromVp(argc, vp);
}
bool
CallJitGetterOp(const JSJitInfo* info, JSContext* cx,
JS::HandleObject thisObj, void* specializedThis,
unsigned argc, JS::Value* vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
return info->getter(cx, thisObj, specializedThis, JSJitGetterCallArgs(args));
}
bool
CallJitSetterOp(const JSJitInfo* info, JSContext* cx,
JS::HandleObject thisObj, void* specializedThis,
unsigned argc, JS::Value* vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
return info->setter(cx, thisObj, specializedThis, JSJitSetterCallArgs(args));
}
bool
CallJitMethodOp(const JSJitInfo* info, JSContext* cx,
JS::HandleObject thisObj, void* specializedThis,
uint32_t argc, JS::Value* vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
return info->method(cx, thisObj, specializedThis, JSJitMethodCallArgs(args));
}
const void*
CreateProxyHandler(const ProxyTraps* aTraps, const void* aExtra)
{
return new ForwardingProxyHandler(*aTraps, aExtra);
}
const void*
CreateWrapperProxyHandler(const ProxyTraps* aTraps)
{
return new WrapperProxyHandler(*aTraps);
}
const void*
GetCrossCompartmentWrapper()
{
return &js::CrossCompartmentWrapper::singleton;
}
const void*
GetSecurityWrapper()
{
return &js::CrossCompartmentSecurityWrapper::singleton;
}
JS::ReadOnlyCompileOptions*
NewCompileOptions(JSContext* aCx, const char* aFile, unsigned aLine)
{
JS::OwningCompileOptions *opts = new JS::OwningCompileOptions(aCx);
opts->setFileAndLine(aCx, aFile, aLine);
opts->setVersion(JSVERSION_DEFAULT);
return opts;
}
void
DeleteCompileOptions(JS::ReadOnlyCompileOptions *aOpts)
{
delete static_cast<JS::OwningCompileOptions *>(aOpts);
}
JSObject*
NewProxyObject(JSContext* aCx, const void* aHandler, JS::HandleValue aPriv,
JSObject* proto, JSObject* parent, JSObject* call,
JSObject* construct)
{
js::ProxyOptions options;
return js::NewProxyObject(aCx, (js::BaseProxyHandler*)aHandler, aPriv, proto,
options);
}
JSObject*
WrapperNew(JSContext* aCx, JS::HandleObject aObj, const void* aHandler,
const JSClass* aClass, bool aSingleton)
{
js::WrapperOptions options;
if (aClass) {
options.setClass(js::Valueify(aClass));
}
options.setSingleton(aSingleton);
return js::Wrapper::New(aCx, aObj, (const js::Wrapper*)aHandler, options);
}
void WindowProxyObjectMoved(JSObject*, const JSObject*)
{
abort();
}
static const js::ClassExtension WindowProxyClassExtension = PROXY_MAKE_EXT(
WindowProxyObjectMoved
);
const js::Class WindowProxyClass = PROXY_CLASS_WITH_EXT(
"Proxy",
JSCLASS_HAS_RESERVED_SLOTS(1), /* additional class flags */
&WindowProxyClassExtension);
const js::Class*
GetWindowProxyClass()
{
return &WindowProxyClass;
}
JS::Value
GetProxyReservedSlot(JSObject* obj, uint32_t slot)
{
return js::GetProxyReservedSlot(obj, slot);
}
void
SetProxyReservedSlot(JSObject* obj, uint32_t slot, const JS::Value* val)
{
js::SetProxyReservedSlot(obj, slot, *val);
}
JSObject*
NewWindowProxy(JSContext* aCx, JS::HandleObject aObj, const void* aHandler)
{
return WrapperNew(aCx, aObj, aHandler, Jsvalify(&WindowProxyClass), true);
}
JS::Value
GetProxyPrivate(JSObject* obj)
{
return js::GetProxyPrivate(obj);
}
void
SetProxyPrivate(JSObject* obj, const JS::Value* expando)
{
js::SetProxyPrivate(obj, *expando);
}
bool
RUST_JSID_IS_INT(JS::HandleId id)
{
return JSID_IS_INT(id);
}
jsid
int_to_jsid(int32_t i)
{
return INT_TO_JSID(i);
}
int32_t
RUST_JSID_TO_INT(JS::HandleId id)
{
return JSID_TO_INT(id);
}
bool
RUST_JSID_IS_STRING(JS::HandleId id)
{
return JSID_IS_STRING(id);
}
JSString*
RUST_JSID_TO_STRING(JS::HandleId id)
{
return JSID_TO_STRING(id);
}
jsid
RUST_SYMBOL_TO_JSID(JS::Symbol* sym)
{
return SYMBOL_TO_JSID(sym);
}
void
RUST_SET_JITINFO(JSFunction* func, const JSJitInfo* info) {
SET_JITINFO(func, info);
}
jsid
RUST_INTERNED_STRING_TO_JSID(JSContext* cx, JSString* str) {
return INTERNED_STRING_TO_JSID(cx, str);
}
const JSErrorFormatString*
RUST_js_GetErrorMessage(void* userRef, uint32_t errorNumber)
{
return js::GetErrorMessage(userRef, errorNumber);
}
bool
IsProxyHandlerFamily(JSObject* obj)
{
auto family = js::GetProxyHandler(obj)->family();
return family == &HandlerFamily;
}
const void*
GetProxyHandlerFamily()
{
return &HandlerFamily;
}
const void*
GetProxyHandlerExtra(JSObject* obj)
{
const js::BaseProxyHandler* handler = js::GetProxyHandler(obj);
assert(handler->family() == &HandlerFamily);
return static_cast<const ForwardingProxyHandler*>(handler)->getExtra();
}
const void*
GetProxyHandler(JSObject* obj)
{
const js::BaseProxyHandler* handler = js::GetProxyHandler(obj);
assert(handler->family() == &HandlerFamily);
return handler;
}
void
ReportError(JSContext* aCx, const char* aError)
{
#ifdef DEBUG
for (const char* p = aError; *p; ++p) {
assert(*p != '%');
}
#endif
JS_ReportErrorASCII(aCx, "%s", aError);
}
bool
IsWrapper(JSObject* obj)
{
return js::IsWrapper(obj);
}
JSObject*
UnwrapObject(JSObject* obj, bool stopAtOuter)
{
return js::CheckedUnwrap(obj, stopAtOuter);
}
JSObject*
UncheckedUnwrapObject(JSObject* obj, bool stopAtOuter)
{
return js::UncheckedUnwrap(obj, stopAtOuter);
}
JS::AutoIdVector*
CreateAutoIdVector(JSContext* cx)
{
return new JS::AutoIdVector(cx);
}
bool
AppendToAutoIdVector(JS::AutoIdVector* v, jsid id)
{
return v->append(id);
}
const jsid*
SliceAutoIdVector(const JS::AutoIdVector* v, size_t* length)
{
*length = v->length();
return v->begin();
}
void
DestroyAutoIdVector(JS::AutoIdVector* v)
{
delete v;
}
JS::AutoObjectVector*
CreateAutoObjectVector(JSContext* aCx)
{
JS::AutoObjectVector* vec = new JS::AutoObjectVector(aCx);
return vec;
}
bool
AppendToAutoObjectVector(JS::AutoObjectVector* v, JSObject* obj)
{
return v->append(obj);
}
void
DeleteAutoObjectVector(JS::AutoObjectVector* v)
{
delete v;
}
#if defined(__linux__)
#include <malloc.h>
#elif defined(__APPLE__)
#include <malloc/malloc.h>
#elif defined(__MINGW32__) || defined(__MINGW64__)
// nothing needed here
#elif defined(_MSC_VER)
// nothing needed here
#else
#error "unsupported platform"
#endif
// SpiderMonkey-in-Rust currently uses system malloc, not jemalloc.
static size_t MallocSizeOf(const void* aPtr)
{
#if defined(__linux__)
return malloc_usable_size((void*)aPtr);
#elif defined(__APPLE__)
return malloc_size((void*)aPtr);
#elif defined(__MINGW32__) || defined(__MINGW64__)
return _msize((void*)aPtr);
#elif defined(_MSC_VER)
return _msize((void*)aPtr);
#else
#error "unsupported platform"
#endif
}
bool
CollectServoSizes(JSContext* cx, JS::ServoSizes *sizes)
{
mozilla::PodZero(sizes);
return JS::AddServoSizeOf(cx, MallocSizeOf,
/* ObjectPrivateVisitor = */ nullptr, sizes);
}
void
CallValueTracer(JSTracer* trc, JS::Heap<JS::Value>* valuep, const char* name)
{
JS::TraceEdge(trc, valuep, name);
}
void
CallIdTracer(JSTracer* trc, JS::Heap<jsid>* idp, const char* name)
{
JS::TraceEdge(trc, idp, name);
}
void
CallObjectTracer(JSTracer* trc, JS::Heap<JSObject*>* objp, const char* name)
{
JS::TraceEdge(trc, objp, name);
}
void
CallStringTracer(JSTracer* trc, JS::Heap<JSString*>* strp, const char* name)
{
JS::TraceEdge(trc, strp, name);
}
void
CallScriptTracer(JSTracer* trc, JS::Heap<JSScript*>* scriptp, const char* name)
{
JS::TraceEdge(trc, scriptp, name);
}
void
CallFunctionTracer(JSTracer* trc, JS::Heap<JSFunction*>* funp, const char* name)
{
JS::TraceEdge(trc, funp, name);
}
void
CallUnbarrieredObjectTracer(JSTracer* trc, JSObject** objp, const char* name)
{
js::UnsafeTraceManuallyBarrieredEdge(trc, objp, name);
}
bool
IsDebugBuild()
{
#ifdef JS_DEBUG
return true;
#else
return false;
#endif
}
#define JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Type, type) \
void \
Get ## Type ## ArrayLengthAndData(JSObject* obj, uint32_t* length, \
bool* isSharedMemory, type** data) \
{ \
js::Get ## Type ## ArrayLengthAndData(obj, length, isSharedMemory, \
data); \
}
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int8, int8_t)
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8, uint8_t)
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint8Clamped, uint8_t)
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int16, int16_t)
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint16, uint16_t)
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int32, int32_t)
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Uint32, uint32_t)
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float32, float)
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Float64, double)
#undef JS_DEFINE_DATA_AND_LENGTH_ACCESSOR
JSAutoStructuredCloneBuffer*
NewJSAutoStructuredCloneBuffer(JS::StructuredCloneScope scope,
const JSStructuredCloneCallbacks* callbacks)
{
return js_new<JSAutoStructuredCloneBuffer>(scope, callbacks, nullptr);
}
JSStructuredCloneData*
DeleteJSAutoStructuredCloneBuffer(JSAutoStructuredCloneBuffer* buf)
{
js_delete(buf);
}
size_t
GetLengthOfJSStructuredCloneData(JSStructuredCloneData* data)
{
assert(data != nullptr);
size_t len = 0;
auto iter = data->Iter();
while (!iter.Done()) {
size_t len_of_this_segment = iter.RemainingInSegment();
len += len_of_this_segment;
iter.Advance(*data, len_of_this_segment);
}
return len;
}
void
CopyJSStructuredCloneData(JSStructuredCloneData* src, uint8_t* dest)
{
assert(src != nullptr);
assert(dest != nullptr);
size_t bytes_copied = 0;
auto iter = src->Iter();
while (!iter.Done()) {
size_t len_of_this_segment = iter.RemainingInSegment();
memcpy(dest + bytes_copied, iter.Data(), len_of_this_segment);
bytes_copied += len_of_this_segment;
iter.Advance(*src, len_of_this_segment);
}
}
bool
WriteBytesToJSStructuredCloneData(const uint8_t* src, size_t len, JSStructuredCloneData* dest)
{
assert(src != nullptr);
assert(dest != nullptr);
return dest->WriteBytes(reinterpret_cast<const char*>(src), len);
}
} // extern "C"

Просмотреть файл

@ -1,549 +0,0 @@
/* 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/. */
use jsapi::root::*;
use libc::c_void;
use std::mem;
#[cfg(target_pointer_width = "64")]
const JSVAL_TAG_SHIFT: usize = 47;
#[cfg(target_pointer_width = "64")]
const JSVAL_TAG_MAX_DOUBLE: u32 = 0x1FFF0u32;
#[cfg(target_pointer_width = "32")]
const JSVAL_TAG_CLEAR: u32 = 0xFFFFFF80;
#[cfg(target_pointer_width = "64")]
#[repr(u32)]
#[allow(dead_code)]
#[derive(Clone, Copy, Debug)]
enum ValueTag {
INT32 = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_INT32 as u32),
UNDEFINED = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_UNDEFINED as u32),
STRING = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_STRING as u32),
SYMBOL = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_SYMBOL as u32),
BOOLEAN = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_BOOLEAN as u32),
MAGIC = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_MAGIC as u32),
NULL = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_NULL as u32),
OBJECT = JSVAL_TAG_MAX_DOUBLE | (JSValueType::JSVAL_TYPE_OBJECT as u32),
}
#[cfg(target_pointer_width = "32")]
#[repr(u32)]
#[allow(dead_code)]
#[derive(Clone, Copy, Debug)]
enum ValueTag {
PRIVATE = 0,
INT32 = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_INT32 as u32),
UNDEFINED = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_UNDEFINED as u32),
STRING = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_STRING as u32),
SYMBOL = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_SYMBOL as u32),
BOOLEAN = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_BOOLEAN as u32),
MAGIC = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_MAGIC as u32),
NULL = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_NULL as u32),
OBJECT = JSVAL_TAG_CLEAR as u32 | (JSValueType::JSVAL_TYPE_OBJECT as u32),
}
#[cfg(target_pointer_width = "64")]
#[repr(u64)]
#[allow(dead_code)]
#[derive(Clone, Copy, Debug)]
enum ValueShiftedTag {
MAX_DOUBLE = (((JSVAL_TAG_MAX_DOUBLE as u64) << JSVAL_TAG_SHIFT) | 0xFFFFFFFFu64),
INT32 = ((ValueTag::INT32 as u64) << JSVAL_TAG_SHIFT),
UNDEFINED = ((ValueTag::UNDEFINED as u64) << JSVAL_TAG_SHIFT),
STRING = ((ValueTag::STRING as u64) << JSVAL_TAG_SHIFT),
SYMBOL = ((ValueTag::SYMBOL as u64) << JSVAL_TAG_SHIFT),
BOOLEAN = ((ValueTag::BOOLEAN as u64) << JSVAL_TAG_SHIFT),
MAGIC = ((ValueTag::MAGIC as u64) << JSVAL_TAG_SHIFT),
NULL = ((ValueTag::NULL as u64) << JSVAL_TAG_SHIFT),
OBJECT = ((ValueTag::OBJECT as u64) << JSVAL_TAG_SHIFT),
}
#[cfg(target_pointer_width = "64")]
const JSVAL_PAYLOAD_MASK: u64 = 0x00007FFFFFFFFFFF;
#[inline(always)]
fn AsJSVal(val: u64) -> JS::Value {
JS::Value {
data: JS::Value_layout {
asBits: val,
}
}
}
#[cfg(target_pointer_width = "64")]
#[inline(always)]
fn BuildJSVal(tag: ValueTag, payload: u64) -> JS::Value {
AsJSVal(((tag as u32 as u64) << JSVAL_TAG_SHIFT) | payload)
}
#[cfg(target_pointer_width = "32")]
#[inline(always)]
fn BuildJSVal(tag: ValueTag, payload: u64) -> JS::Value {
AsJSVal(((tag as u32 as u64) << 32) | payload)
}
#[inline(always)]
pub fn NullValue() -> JS::Value {
BuildJSVal(ValueTag::NULL, 0)
}
#[inline(always)]
pub fn UndefinedValue() -> JS::Value {
BuildJSVal(ValueTag::UNDEFINED, 0)
}
#[inline(always)]
pub fn Int32Value(i: i32) -> JS::Value {
BuildJSVal(ValueTag::INT32, i as u32 as u64)
}
#[cfg(target_pointer_width = "64")]
#[inline(always)]
pub fn DoubleValue(f: f64) -> JS::Value {
let bits: u64 = unsafe { mem::transmute(f) };
assert!(bits <= ValueShiftedTag::MAX_DOUBLE as u64);
AsJSVal(bits)
}
#[cfg(target_pointer_width = "32")]
#[inline(always)]
pub fn DoubleValue(f: f64) -> JS::Value {
let bits: u64 = unsafe { mem::transmute(f) };
let val = AsJSVal(bits);
assert!(val.is_double());
val
}
#[inline(always)]
pub fn UInt32Value(ui: u32) -> JS::Value {
if ui > 0x7fffffff {
DoubleValue(ui as f64)
} else {
Int32Value(ui as i32)
}
}
#[cfg(target_pointer_width = "64")]
#[inline(always)]
pub fn StringValue(s: &JSString) -> JS::Value {
let bits = s as *const JSString as usize as u64;
assert!((bits >> JSVAL_TAG_SHIFT) == 0);
BuildJSVal(ValueTag::STRING, bits)
}
#[cfg(target_pointer_width = "32")]
#[inline(always)]
pub fn StringValue(s: &JSString) -> JS::Value {
let bits = s as *const JSString as usize as u64;
BuildJSVal(ValueTag::STRING, bits)
}
#[inline(always)]
pub fn BooleanValue(b: bool) -> JS::Value {
BuildJSVal(ValueTag::BOOLEAN, b as u64)
}
#[cfg(target_pointer_width = "64")]
#[inline(always)]
pub fn ObjectValue(o: *mut JSObject) -> JS::Value {
let bits = o as usize as u64;
assert!((bits >> JSVAL_TAG_SHIFT) == 0);
BuildJSVal(ValueTag::OBJECT, bits)
}
#[cfg(target_pointer_width = "32")]
#[inline(always)]
pub fn ObjectValue(o: *mut JSObject) -> JS::Value {
let bits = o as usize as u64;
BuildJSVal(ValueTag::OBJECT, bits)
}
#[inline(always)]
pub fn ObjectOrNullValue(o: *mut JSObject) -> JS::Value {
if o.is_null() {
NullValue()
} else {
ObjectValue(o)
}
}
#[cfg(target_pointer_width = "64")]
#[inline(always)]
pub fn PrivateValue(o: *const c_void) -> JS::Value {
let ptrBits = o as usize as u64;
assert!((ptrBits & 1) == 0);
AsJSVal(ptrBits >> 1)
}
#[cfg(target_pointer_width = "32")]
#[inline(always)]
pub fn PrivateValue(o: *const c_void) -> JS::Value {
let ptrBits = o as usize as u64;
assert!((ptrBits & 1) == 0);
BuildJSVal(ValueTag::PRIVATE, ptrBits)
}
impl JS::Value {
#[inline(always)]
unsafe fn asBits(&self) -> u64 {
self.data.asBits
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn is_undefined(&self) -> bool {
unsafe {
self.asBits() == ValueShiftedTag::UNDEFINED as u64
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn is_undefined(&self) -> bool {
unsafe {
(self.asBits() >> 32) == ValueTag::UNDEFINED as u64
}
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn is_null(&self) -> bool {
unsafe {
self.asBits() == ValueShiftedTag::NULL as u64
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn is_null(&self) -> bool {
unsafe {
(self.asBits() >> 32) == ValueTag::NULL as u64
}
}
#[inline(always)]
pub fn is_null_or_undefined(&self) -> bool {
self.is_null() || self.is_undefined()
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn is_boolean(&self) -> bool {
unsafe {
(self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::BOOLEAN as u64
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn is_boolean(&self) -> bool {
unsafe {
(self.asBits() >> 32) == ValueTag::BOOLEAN as u64
}
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn is_int32(&self) -> bool {
unsafe {
(self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::INT32 as u64
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn is_int32(&self) -> bool {
unsafe {
(self.asBits() >> 32) == ValueTag::INT32 as u64
}
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn is_double(&self) -> bool {
unsafe {
self.asBits() <= ValueShiftedTag::MAX_DOUBLE as u64
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn is_double(&self) -> bool {
unsafe {
(self.asBits() >> 32) <= JSVAL_TAG_CLEAR as u64
}
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn is_number(&self) -> bool {
const JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET: u64 = ValueShiftedTag::UNDEFINED as u64;
unsafe {
self.asBits() < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn is_number(&self) -> bool {
const JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET: u64 = ValueTag::INT32 as u64;
unsafe {
(self.asBits() >> 32) <= JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET
}
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn is_primitive(&self) -> bool {
const JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET: u64 = ValueShiftedTag::OBJECT as u64;
unsafe {
self.asBits() < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn is_primitive(&self) -> bool {
const JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET: u64 = ValueTag::OBJECT as u64;
unsafe {
(self.asBits() >> 32) < JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET
}
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn is_string(&self) -> bool {
unsafe {
(self.asBits() >> JSVAL_TAG_SHIFT) == ValueTag::STRING as u64
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn is_string(&self) -> bool {
unsafe {
(self.asBits() >> 32) == ValueTag::STRING as u64
}
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn is_object(&self) -> bool {
unsafe {
assert!((self.asBits() >> JSVAL_TAG_SHIFT) <= ValueTag::OBJECT as u64);
self.asBits() >= ValueShiftedTag::OBJECT as u64
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn is_object(&self) -> bool {
unsafe {
(self.asBits() >> 32) == ValueTag::OBJECT as u64
}
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn is_symbol(&self) -> bool {
unsafe {
self.asBits() == ValueShiftedTag::SYMBOL as u64
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn is_symbol(&self) -> bool {
unsafe {
(self.asBits() >> 32) == ValueTag::SYMBOL as u64
}
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn to_boolean(&self) -> bool {
assert!(self.is_boolean());
unsafe {
(self.asBits() & JSVAL_PAYLOAD_MASK) != 0
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn to_boolean(&self) -> bool {
assert!(self.is_boolean());
unsafe {
(self.asBits() & 0x00000000FFFFFFFF) != 0
}
}
#[inline(always)]
pub fn to_int32(&self) -> i32 {
assert!(self.is_int32());
unsafe {
(self.asBits() & 0x00000000FFFFFFFF) as i32
}
}
#[inline(always)]
pub fn to_double(&self) -> f64 {
assert!(self.is_double());
unsafe { mem::transmute(self.asBits()) }
}
#[inline(always)]
pub fn to_number(&self) -> f64 {
assert!(self.is_number());
if self.is_double() {
self.to_double()
} else {
self.to_int32() as f64
}
}
#[inline(always)]
pub fn to_object(&self) -> *mut JSObject {
assert!(self.is_object());
self.to_object_or_null()
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn to_string(&self) -> *mut JSString {
assert!(self.is_string());
unsafe {
let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK;
ptrBits as usize as *mut JSString
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn to_string(&self) -> *mut JSString {
assert!(self.is_string());
unsafe {
let ptrBits: u32 = (self.asBits() & 0x00000000FFFFFFFF) as u32;
ptrBits as *mut JSString
}
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn is_object_or_null(&self) -> bool {
const JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET: u64 = ValueShiftedTag::NULL as u64;
unsafe {
assert!((self.asBits() >> JSVAL_TAG_SHIFT) <= ValueTag::OBJECT as u64);
self.asBits() >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn is_object_or_null(&self) -> bool {
const JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET: u64 = ValueTag::NULL as u64;
unsafe {
assert!((self.asBits() >> 32) <= ValueTag::OBJECT as u64);
(self.asBits() >> 32) >= JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET
}
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn to_object_or_null(&self) -> *mut JSObject {
assert!(self.is_object_or_null());
unsafe {
let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK;
assert!((ptrBits & 0x7) == 0);
ptrBits as usize as *mut JSObject
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn to_object_or_null(&self) -> *mut JSObject {
assert!(self.is_object_or_null());
unsafe {
let ptrBits: u32 = (self.asBits() & 0x00000000FFFFFFFF) as u32;
ptrBits as *mut JSObject
}
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn to_private(&self) -> *const c_void {
assert!(self.is_double());
unsafe {
assert!((self.asBits() & 0x8000000000000000u64) == 0);
(self.asBits() << 1) as usize as *const c_void
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn to_private(&self) -> *const c_void {
unsafe {
let ptrBits: u32 = (self.asBits() & 0x00000000FFFFFFFF) as u32;
ptrBits as *const c_void
}
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn is_gcthing(&self) -> bool {
const JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET: u64 = ValueShiftedTag::STRING as u64;
unsafe {
self.asBits() >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn is_gcthing(&self) -> bool {
const JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET: u64 = ValueTag::STRING as u64;
unsafe {
(self.asBits() >> 32) >= JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET
}
}
#[inline(always)]
#[cfg(target_pointer_width = "64")]
pub fn to_gcthing(&self) -> *mut c_void {
assert!(self.is_gcthing());
unsafe {
let ptrBits = self.asBits() & JSVAL_PAYLOAD_MASK;
assert!((ptrBits & 0x7) == 0);
ptrBits as *mut c_void
}
}
#[inline(always)]
#[cfg(target_pointer_width = "32")]
pub fn to_gcthing(&self) -> *mut c_void {
assert!(self.is_gcthing());
unsafe {
let ptrBits: u32 = (self.asBits() & 0x00000000FFFFFFFF) as u32;
ptrBits as *mut c_void
}
}
#[inline(always)]
pub fn is_markable(&self) -> bool {
self.is_gcthing() && !self.is_null()
}
#[inline(always)]
pub fn trace_kind(&self) -> JS::TraceKind {
assert!(self.is_markable());
if self.is_object() {
JS::TraceKind::Object
} else {
JS::TraceKind::String
}
}
}

Просмотреть файл

@ -1,54 +0,0 @@
/* 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/. */
#![crate_name = "js"]
#![crate_type = "rlib"]
#![cfg_attr(feature = "nonzero", feature(nonzero))]
#![allow(non_upper_case_globals, non_camel_case_types, non_snake_case, improper_ctypes)]
#[cfg(feature = "nonzero")]
extern crate core;
#[macro_use]
extern crate heapsize;
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
#[allow(unused_extern_crates)]
extern crate mozjs_sys;
extern crate num_traits;
#[macro_use]
pub mod rust;
pub mod ac;
pub mod conversions;
pub mod error;
pub mod glue;
pub mod heap;
pub mod jsval;
pub mod panic;
pub mod sc;
pub mod typedarray;
pub mod jsapi;
use self::jsapi::root::*;
#[inline(always)]
pub unsafe fn JS_ARGV(_cx: *mut JSContext, vp: *mut JS::Value) -> *mut JS::Value {
vp.offset(2)
}
known_heap_size!(0, JS::Value);
impl JS::ObjectOpResult {
/// Set this ObjectOpResult to true and return true.
pub fn succeed(&mut self) -> bool {
self.code_ = JS::ObjectOpResult_SpecialCodes::OkCode as usize;
true
}
}

Просмотреть файл

@ -1,33 +0,0 @@
/* 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/. */
use std::any::Any;
use std::cell::RefCell;
use std::panic::{UnwindSafe, catch_unwind, resume_unwind};
thread_local!(static PANIC_RESULT: RefCell<Option<Box<Any + Send>>> = RefCell::new(None));
/// If there is a pending panic, resume unwinding.
pub fn maybe_resume_unwind() {
if let Some(error) = PANIC_RESULT.with(|result| result.borrow_mut().take()) {
resume_unwind(error);
}
}
/// Generic wrapper for JS engine callbacks panic-catching
pub fn wrap_panic<F, R>(function: F, generic_return_type: R) -> R
where F: FnOnce() -> R + UnwindSafe
{
let result = catch_unwind(function);
match result {
Ok(result) => result,
Err(error) => {
PANIC_RESULT.with(|result| {
assert!(result.borrow().is_none());
*result.borrow_mut() = Some(error);
});
generic_return_type
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,102 +0,0 @@
/* 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/. */
//! Nicer, Rust-y APIs for structured cloning.
use glue;
use jsapi;
use rust::Runtime;
use std::ptr;
/// An RAII owned buffer for structured cloning into and out of.
pub struct StructuredCloneBuffer {
raw: *mut jsapi::JSAutoStructuredCloneBuffer,
}
impl StructuredCloneBuffer {
/// Construct a new `StructuredCloneBuffer`.
///
/// # Panics
///
/// Panics if the underlying JSAPI calls fail.
pub fn new(scope: jsapi::JS::StructuredCloneScope,
callbacks: &jsapi::JSStructuredCloneCallbacks)
-> StructuredCloneBuffer {
let raw = unsafe {
glue::NewJSAutoStructuredCloneBuffer(scope, callbacks)
};
assert!(!raw.is_null());
StructuredCloneBuffer {
raw: raw,
}
}
/// Get the raw `*mut JSStructuredCloneData` owned by this buffer.
pub fn data(&self) -> *mut jsapi::JSStructuredCloneData {
unsafe {
&mut (*self.raw).data_
}
}
/// Copy this buffer's data into a vec.
pub fn copy_to_vec(&self) -> Vec<u8> {
let len = unsafe {
glue::GetLengthOfJSStructuredCloneData(self.data())
};
let mut vec = Vec::with_capacity(len);
unsafe {
glue::CopyJSStructuredCloneData(self.data(), vec.as_mut_ptr());
}
vec
}
/// Read a JS value out of this buffer.
pub fn read(&mut self,
vp: jsapi::JS::MutableHandleValue,
callbacks: &jsapi::JSStructuredCloneCallbacks)
-> Result<(), ()> {
if unsafe {
(*self.raw).read(Runtime::get(), vp, callbacks, ptr::null_mut())
} {
Ok(())
} else {
Err(())
}
}
/// Write a JS value into this buffer.
pub fn write(&mut self,
v: jsapi::JS::HandleValue,
callbacks: &jsapi::JSStructuredCloneCallbacks)
-> Result<(), ()> {
if unsafe {
(*self.raw).write(Runtime::get(), v, callbacks, ptr::null_mut())
} {
Ok(())
} else {
Err(())
}
}
/// Copy the given slice into this buffer.
pub fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), ()> {
let len = bytes.len();
let src = bytes.as_ptr();
if unsafe {
glue::WriteBytesToJSStructuredCloneData(src, len, self.data())
} {
Ok(())
} else {
Err(())
}
}
}
impl Drop for StructuredCloneBuffer {
fn drop(&mut self) {
unsafe {
glue::DeleteJSAutoStructuredCloneBuffer(self.raw);
}
}
}

Просмотреть файл

@ -1,301 +0,0 @@
/* 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/. */
//! High-level, safe bindings for JS typed array APIs. Allows creating new
//! typed arrays or wrapping existing JS reflectors, and prevents reinterpreting
//! existing buffers as different types except in well-defined cases.
use glue::GetFloat32ArrayLengthAndData;
use glue::GetFloat64ArrayLengthAndData;
use glue::GetInt16ArrayLengthAndData;
use glue::GetInt32ArrayLengthAndData;
use glue::GetInt8ArrayLengthAndData;
use glue::GetUint16ArrayLengthAndData;
use glue::GetUint32ArrayLengthAndData;
use glue::GetUint8ArrayLengthAndData;
use glue::GetUint8ClampedArrayLengthAndData;
use jsapi::*;
use jsapi::js::*;
use jsapi::JS::*;
use rust::RootedGuard;
use std::ptr;
use std::slice;
pub enum CreateWith<'a, T: 'a> {
Length(u32),
Slice(&'a [T]),
}
/// A rooted typed array.
pub struct TypedArray<'a, T: 'a + TypedArrayElement> {
object: RootedGuard<'a, *mut JSObject>,
computed: Option<(*mut T::Element, u32)>,
}
impl<'a, T: TypedArrayElement> TypedArray<'a, T> {
/// Create a typed array representation that wraps an existing JS reflector.
/// This operation will fail if attempted on a JS object that does not match
/// the expected typed array details.
pub fn from(cx: *mut JSContext,
root: &'a mut Rooted<*mut JSObject>,
object: *mut JSObject)
-> Result<Self, ()> {
if object.is_null() {
return Err(());
}
unsafe {
let mut guard = RootedGuard::new(cx, root, object);
let unwrapped = T::unwrap_array(*guard);
if unwrapped.is_null() {
return Err(());
}
*guard = unwrapped;
Ok(TypedArray {
object: guard,
computed: None,
})
}
}
fn data(&mut self) -> (*mut T::Element, u32) {
if let Some(data) = self.computed {
return data;
}
let data = unsafe { T::length_and_data(*self.object) };
self.computed = Some(data);
data
}
/// # Unsafety
///
/// The returned slice can be invalidated if the underlying typed array
/// is neutered.
pub unsafe fn as_slice(&mut self) -> &[T::Element] {
let (pointer, length) = self.data();
slice::from_raw_parts(pointer as *const T::Element, length as usize)
}
/// # Unsafety
///
/// The returned slice can be invalidated if the underlying typed array
/// is neutered.
///
/// The underlying `JSObject` can be aliased, which can lead to
/// Undefined Behavior due to mutable aliasing.
pub unsafe fn as_mut_slice(&mut self) -> &mut [T::Element] {
let (pointer, length) = self.data();
slice::from_raw_parts_mut(pointer, length as usize)
}
}
impl<'a, T: TypedArrayElementCreator + TypedArrayElement> TypedArray<'a, T> {
/// Create a new JS typed array, optionally providing initial data that will
/// be copied into the newly-allocated buffer. Returns the new JS reflector.
pub unsafe fn create(cx: *mut JSContext,
with: CreateWith<T::Element>,
result: MutableHandleObject)
-> Result<(), ()> {
let length = match with {
CreateWith::Length(len) => len,
CreateWith::Slice(slice) => slice.len() as u32,
};
result.set(T::create_new(cx, length));
if result.get().is_null() {
return Err(());
}
if let CreateWith::Slice(data) = with {
TypedArray::<T>::update_raw(data, result.handle());
}
Ok(())
}
/// Update an existed JS typed array
pub unsafe fn update(&mut self, data: &[T::Element]) {
TypedArray::<T>::update_raw(data, self.object.handle());
}
unsafe fn update_raw(data: &[T::Element], result: HandleObject) {
let (buf, length) = T::length_and_data(result.get());
assert!(data.len() <= length as usize);
ptr::copy_nonoverlapping(data.as_ptr(), buf, data.len());
}
}
/// Internal trait used to associate an element type with an underlying representation
/// and various functions required to manipulate typed arrays of that element type.
pub trait TypedArrayElement {
/// Underlying primitive representation of this element type.
type Element;
/// Unwrap a typed array JS reflector for this element type.
unsafe fn unwrap_array(obj: *mut JSObject) -> *mut JSObject;
/// Retrieve the length and data of a typed array's buffer for this element type.
unsafe fn length_and_data(obj: *mut JSObject) -> (*mut Self::Element, u32);
}
/// Internal trait for creating new typed arrays.
pub trait TypedArrayElementCreator: TypedArrayElement {
/// Create a new typed array.
unsafe fn create_new(cx: *mut JSContext, length: u32) -> *mut JSObject;
/// Get the data.
unsafe fn get_data(obj: *mut JSObject) -> *mut Self::Element;
}
macro_rules! typed_array_element {
($t: ident,
$element: ty,
$unwrap: ident,
$length_and_data: ident) => (
/// A kind of typed array.
pub struct $t;
impl TypedArrayElement for $t {
type Element = $element;
unsafe fn unwrap_array(obj: *mut JSObject) -> *mut JSObject {
$unwrap(obj)
}
unsafe fn length_and_data(obj: *mut JSObject) -> (*mut Self::Element, u32) {
let mut len = 0;
let mut shared = false;
let mut data = ptr::null_mut();
$length_and_data(obj, &mut len, &mut shared, &mut data);
assert!(!shared);
(data, len)
}
}
);
($t: ident,
$element: ty,
$unwrap: ident,
$length_and_data: ident,
$create_new: ident,
$get_data: ident) => (
typed_array_element!($t, $element, $unwrap, $length_and_data);
impl TypedArrayElementCreator for $t {
unsafe fn create_new(cx: *mut JSContext, length: u32) -> *mut JSObject {
$create_new(cx, length)
}
unsafe fn get_data(obj: *mut JSObject) -> *mut Self::Element {
let mut shared = false;
let data = $get_data(obj, &mut shared, ptr::null_mut());
assert!(!shared);
data
}
}
);
}
typed_array_element!(Uint8,
u8,
UnwrapUint8Array,
GetUint8ArrayLengthAndData,
JS_NewUint8Array,
JS_GetUint8ArrayData);
typed_array_element!(Uint16,
u16,
UnwrapUint16Array,
GetUint16ArrayLengthAndData,
JS_NewUint16Array,
JS_GetUint16ArrayData);
typed_array_element!(Uint32,
u32,
UnwrapUint32Array,
GetUint32ArrayLengthAndData,
JS_NewUint32Array,
JS_GetUint32ArrayData);
typed_array_element!(Int8,
i8,
UnwrapInt8Array,
GetInt8ArrayLengthAndData,
JS_NewInt8Array,
JS_GetInt8ArrayData);
typed_array_element!(Int16,
i16,
UnwrapInt16Array,
GetInt16ArrayLengthAndData,
JS_NewInt16Array,
JS_GetInt16ArrayData);
typed_array_element!(Int32,
i32,
UnwrapInt32Array,
GetInt32ArrayLengthAndData,
JS_NewInt32Array,
JS_GetInt32ArrayData);
typed_array_element!(Float32,
f32,
UnwrapFloat32Array,
GetFloat32ArrayLengthAndData,
JS_NewFloat32Array,
JS_GetFloat32ArrayData);
typed_array_element!(Float64,
f64,
UnwrapFloat64Array,
GetFloat64ArrayLengthAndData,
JS_NewFloat64Array,
JS_GetFloat64ArrayData);
typed_array_element!(ClampedU8,
u8,
UnwrapUint8ClampedArray,
GetUint8ClampedArrayLengthAndData,
JS_NewUint8ClampedArray,
JS_GetUint8ClampedArrayData);
typed_array_element!(ArrayBufferU8,
u8,
UnwrapArrayBuffer,
GetArrayBufferLengthAndData,
JS_NewArrayBuffer,
JS_GetArrayBufferData);
typed_array_element!(ArrayBufferViewU8,
u8,
UnwrapArrayBufferView,
GetArrayBufferViewLengthAndData);
/// The Uint8ClampedArray type.
pub type Uint8ClampedArray<'a> = TypedArray<'a, ClampedU8>;
/// The Uint8Array type.
pub type Uint8Array<'a> = TypedArray<'a, Uint8>;
/// The Int8Array type.
pub type Int8Array<'a> = TypedArray<'a, Int8>;
/// The Uint16Array type.
pub type Uint16Array<'a> = TypedArray<'a, Uint16>;
/// The Int16Array type.
pub type Int16Array<'a> = TypedArray<'a, Int16>;
/// The Uint32Array type.
pub type Uint32Array<'a> = TypedArray<'a, Uint32>;
/// The Int32Array type.
pub type Int32Array<'a> = TypedArray<'a, Int32>;
/// The Float32Array type.
pub type Float32Array<'a> = TypedArray<'a, Float32>;
/// The Float64Array type.
pub type Float64Array<'a> = TypedArray<'a, Float64>;
/// The ArrayBuffer type.
pub type ArrayBuffer<'a> = TypedArray<'a, ArrayBufferU8>;
/// The ArrayBufferView type
pub type ArrayBufferView<'a> = TypedArray<'a, ArrayBufferViewU8>;
impl<'a> ArrayBufferView<'a> {
pub fn get_array_type(&self) -> Scalar::Type {
unsafe { JS_GetArrayBufferViewType(self.object.get()) }
}
}
#[macro_export]
macro_rules! typedarray {
(in($cx:expr) let $name:ident : $ty:ident = $init:expr) => {
let mut __root = $crate::jsapi::JS::Rooted::new_unrooted();
let $name = $crate::typedarray::$ty::from($cx, &mut __root, $init);
};
(in($cx:expr) let mut $name:ident : $ty:ident = $init:expr) => {
let mut __root = $crate::jsapi::JS::Rooted::new_unrooted();
let mut $name = $crate::typedarray::$ty::from($cx, &mut __root, $init);
}
}

Просмотреть файл

@ -1,64 +0,0 @@
/* 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/. */
#[macro_use]
extern crate js;
extern crate libc;
use js::ac::AutoCompartment;
use js::jsapi::root::JS::CallArgs;
use js::jsapi::root::JS::CompartmentOptions;
use js::jsapi::root::JSContext;
use js::jsapi::root::JS_DefineFunction;
use js::jsapi::root::JS_EncodeStringToUTF8;
use js::jsapi::root::JS_NewGlobalObject;
use js::jsapi::root::JS_ReportErrorASCII;
use js::jsapi::root::JS::OnNewGlobalHookOption;
use js::jsapi::root::JS::Value;
use js::jsval::UndefinedValue;
use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS};
use std::ffi::CStr;
use std::ptr;
use std::str;
#[test]
fn callback() {
let runtime = Runtime::new().unwrap();
let context = runtime.cx();
let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook;
let c_option = CompartmentOptions::default();
unsafe {
let global = JS_NewGlobalObject(context, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(), h_option, &c_option);
rooted!(in(context) let global_root = global);
let global = global_root.handle();
let _ac = AutoCompartment::with_obj(context, global.get());
let function = JS_DefineFunction(context, global, b"puts\0".as_ptr() as *const libc::c_char,
Some(puts), 1, 0);
assert!(!function.is_null());
let javascript = "puts('Test Iñtërnâtiônàlizætiøn ┬─┬ノ( º _ ºノ) ');";
rooted!(in(context) let mut rval = UndefinedValue());
let _ = runtime.evaluate_script(global, javascript, "test.js", 0, rval.handle_mut());
}
}
unsafe extern "C" fn puts(context: *mut JSContext, argc: u32, vp: *mut Value) -> bool {
let args = CallArgs::from_vp(vp, argc);
if args._base.argc_ != 1 {
JS_ReportErrorASCII(context, b"puts() requires exactly 1 argument\0".as_ptr() as *const libc::c_char);
return false;
}
let arg = args.get(0);
let js = js::rust::ToString(context, arg);
rooted!(in(context) let message_root = js);
let message = JS_EncodeStringToUTF8(context, message_root.handle());
let message = CStr::from_ptr(message);
println!("{}", str::from_utf8(message.to_bytes()).unwrap());
args.rval().set(UndefinedValue());
return true;
}

Просмотреть файл

@ -1,56 +0,0 @@
/* 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/. */
#[macro_use]
extern crate js;
use js::glue::RUST_JSID_IS_STRING;
use js::glue::RUST_JSID_TO_STRING;
use js::jsapi::root::JS::CompartmentOptions;
use js::jsapi::root::js::GetPropertyKeys;
use js::jsapi::root::JSITER_OWNONLY;
use js::jsapi::root::JS_NewGlobalObject;
use js::jsapi::root::JS_StringEqualsAscii;
use js::jsapi::root::JS::OnNewGlobalHookOption;
use js::jsval::UndefinedValue;
use js::rust::IdVector;
use js::rust::Runtime;
use js::rust::SIMPLE_GLOBAL_CLASS;
use std::ptr;
#[test]
fn enumerate() {
let rt = Runtime::new().unwrap();
let cx = rt.cx();
unsafe {
rooted!(in(cx) let global =
JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
OnNewGlobalHookOption::FireOnNewGlobalHook,
&CompartmentOptions::default())
);
rooted!(in(cx) let mut rval = UndefinedValue());
assert!(rt.evaluate_script(global.handle(), "({ 'a': 7 })",
"test", 1, rval.handle_mut()).is_ok());
assert!(rval.is_object());
rooted!(in(cx) let object = rval.to_object());
let ids = IdVector::new(cx);
assert!(GetPropertyKeys(cx, object.handle(), JSITER_OWNONLY, ids.get()));
assert_eq!(ids.len(), 1);
rooted!(in(cx) let id = ids[0]);
assert!(RUST_JSID_IS_STRING(id.handle()));
rooted!(in(cx) let id = RUST_JSID_TO_STRING(id.handle()));
let mut matches = false;
assert!(JS_StringEqualsAscii(cx,
id.get(),
b"a\0" as *const _ as *const _,
&mut matches));
assert!(matches);
}
}

Просмотреть файл

@ -1,32 +0,0 @@
/* 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/. */
#[macro_use]
extern crate js;
use js::jsapi::root::JS::CompartmentOptions;
use js::jsapi::root::JS_NewGlobalObject;
use js::jsapi::root::JS::OnNewGlobalHookOption;
use js::jsval::UndefinedValue;
use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS};
use std::ptr;
#[test]
fn evaluate() {
let rt = Runtime::new().unwrap();
let cx = rt.cx();
unsafe {
rooted!(in(cx) let global =
JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
OnNewGlobalHookOption::FireOnNewGlobalHook,
&CompartmentOptions::default())
);
rooted!(in(cx) let mut rval = UndefinedValue());
assert!(rt.evaluate_script(global.handle(), "1 + 1",
"test", 1, rval.handle_mut()).is_ok());
}
}

Просмотреть файл

@ -1,43 +0,0 @@
/* 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/. */
#[macro_use]
extern crate js;
use js::jsapi::*;
use js::jsval::UndefinedValue;
use js::panic::wrap_panic;
use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS};
use std::ptr;
use std::str;
#[test]
#[should_panic]
fn panic() {
let runtime = Runtime::new().unwrap();
let context = runtime.cx();
let h_option = JS::OnNewGlobalHookOption::FireOnNewGlobalHook;
let c_option = JS::CompartmentOptions::default();
unsafe {
let global = JS_NewGlobalObject(context, &SIMPLE_GLOBAL_CLASS,
ptr::null_mut(), h_option, &c_option);
rooted!(in(context) let global_root = global);
let global = global_root.handle();
let _ac = js::ac::AutoCompartment::with_obj(context, global.get());
let function = JS_DefineFunction(context, global,
b"test\0".as_ptr() as *const _,
Some(test), 0, 0);
assert!(!function.is_null());
rooted!(in(context) let mut rval = UndefinedValue());
let _ = runtime.evaluate_script(global, "test();", "test.js", 0,
rval.handle_mut());
}
}
unsafe extern "C" fn test(_cx: *mut JSContext, _argc: u32, _vp: *mut JS::Value) -> bool {
wrap_panic(|| {
panic!()
}, false)
}

Просмотреть файл

@ -1,83 +0,0 @@
/* 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/. */
#![cfg(feature = "debugmozjs")]
#[macro_use]
extern crate js;
#[macro_use]
extern crate lazy_static;
extern crate libc;
use js::jsapi::*;
use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS, define_methods};
use std::ptr;
#[test]
fn rooting() {
unsafe {
let runtime = Runtime::new().unwrap();
JS_SetGCZeal(runtime.cx(), 2, 1);
let cx = runtime.cx();
let h_option = JS::OnNewGlobalHookOption::FireOnNewGlobalHook;
let c_option = JS::CompartmentOptions::default();
rooted!(in(cx) let global = JS_NewGlobalObject(cx,
&SIMPLE_GLOBAL_CLASS,
ptr::null_mut(),
h_option,
&c_option));
let _ac = js::ac::AutoCompartment::with_obj(cx, global.get());
rooted!(in(cx) let prototype_proto = JS_GetObjectPrototype(cx, global.handle()));
rooted!(in(cx) let proto = JS_NewObjectWithUniqueType(cx,
&CLASS as *const _,
prototype_proto.handle()));
define_methods(cx, proto.handle(), &METHODS[..]).unwrap();
}
}
unsafe extern "C" fn generic_method(_: *mut JSContext, _: u32, _: *mut JS::Value) -> bool {
true
}
lazy_static! {
static ref METHODS: [JSFunctionSpec; 4] = [
JSFunctionSpec {
name: b"addEventListener\0" as *const u8 as *const libc::c_char,
call: JSNativeWrapper { op: Some(generic_method), info: ptr::null() },
nargs: 2,
flags: JSPROP_ENUMERATE as u16,
selfHostedName: 0 as *const libc::c_char
},
JSFunctionSpec {
name: b"removeEventListener\0" as *const u8 as *const libc::c_char,
call: JSNativeWrapper { op: Some(generic_method), info: ptr::null() },
nargs: 2,
flags: JSPROP_ENUMERATE as u16,
selfHostedName: 0 as *const libc::c_char
},
JSFunctionSpec {
name: b"dispatchEvent\0" as *const u8 as *const libc::c_char,
call: JSNativeWrapper { op: Some(generic_method), info: ptr::null() },
nargs: 1,
flags: JSPROP_ENUMERATE as u16,
selfHostedName: 0 as *const libc::c_char
},
JSFunctionSpec {
name: ptr::null(),
call: JSNativeWrapper { op: None, info: ptr::null() },
nargs: 0,
flags: 0,
selfHostedName: ptr::null()
}
];
}
static CLASS: JSClass = JSClass {
name: b"EventTargetPrototype\0" as *const u8 as *const libc::c_char,
flags: 0,
cOps: 0 as *const _,
reserved: [0 as *mut _; 3]
};

Просмотреть файл

@ -1,57 +0,0 @@
/* 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/. */
#[macro_use]
extern crate js;
extern crate libc;
use js::jsapi::*;
use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS};
use std::ptr;
#[test]
fn runtime() {
unsafe {
let runtime = Runtime::new().unwrap();
let cx = runtime.cx();
let h_option = JS::OnNewGlobalHookOption::FireOnNewGlobalHook;
let c_option = JS::CompartmentOptions::default();
rooted!(in(cx) let global = JS_NewGlobalObject(cx,
&SIMPLE_GLOBAL_CLASS,
ptr::null_mut(),
h_option,
&c_option));
let _ac = js::ac::AutoCompartment::with_obj(cx, global.get());
rooted!(in(cx) let _object = JS_NewObject(cx, &CLASS as *const _));
}
assert!(Runtime::new().is_err());
}
unsafe extern fn finalize(_fop: *mut JSFreeOp, _object: *mut JSObject) {
assert!(!Runtime::get().is_null());
}
static CLASS_OPS: JSClassOps = JSClassOps {
addProperty: None,
delProperty: None,
enumerate: None,
newEnumerate: None,
resolve: None,
mayResolve: None,
finalize: Some(finalize),
call: None,
hasInstance: None,
construct: None,
trace: None,
};
static CLASS: JSClass = JSClass {
name: b"EventTargetPrototype\0" as *const u8 as *const libc::c_char,
flags: 0 | JSCLASS_FOREGROUND_FINALIZE,
cOps: &CLASS_OPS as *const JSClassOps,
reserved: [0 as *mut _; 3]
};

Просмотреть файл

@ -1,32 +0,0 @@
/* 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/. */
#[macro_use]
extern crate js;
use js::jsapi::root::JS::CompartmentOptions;
use js::jsapi::root::JS_NewGlobalObject;
use js::jsapi::root::JS::OnNewGlobalHookOption;
use js::jsval::UndefinedValue;
use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS};
use std::ptr;
#[test]
fn stack_limit() {
let rt = Runtime::new().unwrap();
let cx = rt.cx();
unsafe {
let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook;
let c_option = CompartmentOptions::default();
let global = JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS,
ptr::null_mut(), h_option, &c_option);
rooted!(in(cx) let global_root = global);
let global = global_root.handle();
rooted!(in(cx) let mut rval = UndefinedValue());
assert!(rt.evaluate_script(global, "function f() { f.apply() } f()",
"test", 1, rval.handle_mut()).is_err());
}
}

Просмотреть файл

@ -1,91 +0,0 @@
/* 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/. */
#[macro_use]
extern crate js;
use js::jsapi::*;
use js::jsval::UndefinedValue;
use js::rust::Runtime as Runtime_;
use js::rust::SIMPLE_GLOBAL_CLASS;
use js::typedarray::{CreateWith, Uint32Array};
use std::ptr;
#[test]
fn typedarray() {
let rt = Runtime_::new().unwrap();
let cx = rt.cx();
unsafe {
rooted!(in(cx) let global =
JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
JS::OnNewGlobalHookOption::FireOnNewGlobalHook,
&JS::CompartmentOptions::default())
);
let _ac = js::ac::AutoCompartment::with_obj(cx, global.get());
rooted!(in(cx) let mut rval = UndefinedValue());
assert!(rt.evaluate_script(global.handle(), "new Uint8Array([0, 2, 4])",
"test", 1, rval.handle_mut()).is_ok());
assert!(rval.is_object());
typedarray!(in(cx) let array: Uint8Array = rval.to_object());
assert_eq!(array.unwrap().as_slice(), &[0, 2, 4][..]);
typedarray!(in(cx) let array: Uint16Array = rval.to_object());
assert!(array.is_err());
typedarray!(in(cx) let view: ArrayBufferView = rval.to_object());
assert_eq!(view.unwrap().get_array_type(), js::jsapi::js::Scalar::Type::Uint8);
rooted!(in(cx) let mut rval = ptr::null_mut());
assert!(Uint32Array::create(cx, CreateWith::Slice(&[1, 3, 5]), rval.handle_mut()).is_ok());
typedarray!(in(cx) let array: Uint32Array = rval.get());
assert_eq!(array.unwrap().as_slice(), &[1, 3, 5][..]);
typedarray!(in(cx) let mut array: Uint32Array = rval.get());
array.as_mut().unwrap().update(&[2, 4, 6]);
assert_eq!(array.unwrap().as_slice(), &[2, 4, 6][..]);
rooted!(in(cx) let rval = ptr::null_mut());
typedarray!(in(cx) let array: Uint8Array = rval.get());
assert!(array.is_err());
rooted!(in(cx) let mut rval = ptr::null_mut());
assert!(Uint32Array::create(cx, CreateWith::Length(5), rval.handle_mut()).is_ok());
typedarray!(in(cx) let array: Uint32Array = rval.get());
assert_eq!(array.unwrap().as_slice(), &[0, 0, 0, 0, 0]);
typedarray!(in(cx) let mut array: Uint32Array = rval.get());
array.as_mut().unwrap().update(&[0, 1, 2, 3]);
assert_eq!(array.unwrap().as_slice(), &[0, 1, 2, 3, 0]);
typedarray!(in(cx) let view: ArrayBufferView = rval.get());
assert_eq!(view.unwrap().get_array_type(), js::jsapi::js::Scalar::Type::Uint32);
}
}
#[test]
#[should_panic]
fn typedarray_update_panic() {
let rt = Runtime_::new().unwrap();
let cx = rt.cx();
unsafe {
rooted!(in(cx) let global =
JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(),
JS::OnNewGlobalHookOption::FireOnNewGlobalHook,
&JS::CompartmentOptions::default())
);
let _ac = js::ac::AutoCompartment::with_obj(cx, global.get());
rooted!(in(cx) let mut rval = ptr::null_mut());
let _ = Uint32Array::create(cx, CreateWith::Slice(&[1, 2, 3, 4, 5]), rval.handle_mut());
typedarray!(in(cx) let mut array: Uint32Array = rval.get());
array.as_mut().unwrap().update(&[0, 2, 4, 6, 8, 10]);
}
}

Просмотреть файл

@ -1,80 +0,0 @@
/* 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/. */
#[macro_use]
extern crate js;
use js::ac::AutoCompartment;
use js::conversions::ConversionBehavior;
use js::conversions::ConversionResult;
use js::conversions::FromJSValConvertible;
use js::conversions::ToJSValConvertible;
use js::jsapi::root::JS::CompartmentOptions;
use js::jsapi::root::JS_InitStandardClasses;
use js::jsapi::root::JS_NewGlobalObject;
use js::jsapi::root::JS::OnNewGlobalHookOption;
use js::jsval::UndefinedValue;
use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS};
use std::ptr;
fn assert_is_array(cx: *mut js::jsapi::root::JSContext,
val: js::jsapi::root::JS::HandleValue) {
let mut is_array = false;
assert!(unsafe {
js::jsapi::root::JS_IsArrayObject(cx, val, &mut is_array as *mut _)
});
assert!(is_array);
}
#[test]
fn vec_conversion() {
let rt = Runtime::new().unwrap();
let cx = rt.cx();
let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook;
let c_option = CompartmentOptions::default();
unsafe {
let global = JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS,
ptr::null_mut(), h_option, &c_option);
rooted!(in(cx) let global_root = global);
let global = global_root.handle();
let _ac = AutoCompartment::with_obj(cx, global.get());
assert!(JS_InitStandardClasses(cx, global));
rooted!(in(cx) let mut rval = UndefinedValue());
let orig_vec: Vec<f32> = vec![1.0, 2.9, 3.0];
orig_vec.to_jsval(cx, rval.handle_mut());
assert_is_array(cx, rval.handle());
let converted = Vec::<f32>::from_jsval(cx, rval.handle(), ()).unwrap();
assert_eq!(&orig_vec, converted.get_success_value().unwrap());
let orig_vec: Vec<i32> = vec![1, 2, 3];
orig_vec.to_jsval(cx, rval.handle_mut());
assert_is_array(cx, rval.handle());
let converted = Vec::<i32>::from_jsval(cx, rval.handle(),
ConversionBehavior::Default).unwrap();
assert_eq!(&orig_vec, converted.get_success_value().unwrap());
rt.evaluate_script(global, "new Set([1, 2, 3])",
"test", 1, rval.handle_mut()).unwrap();
let converted =
Vec::<i32>::from_jsval(cx, rval.handle(),
ConversionBehavior::Default).unwrap();
assert_eq!(&orig_vec, converted.get_success_value().unwrap());
rt.evaluate_script(global, "({})", "test", 1, rval.handle_mut()).unwrap();
let converted = Vec::<i32>::from_jsval(cx, rval.handle(),
ConversionBehavior::Default);
assert!(match converted {
Ok(ConversionResult::Failure(_)) => true,
_ => false,
});
}
}

13
js/src/Cargo.lock сгенерированный
Просмотреть файл

@ -3,7 +3,7 @@ name = "mozjs_sys"
version = "0.0.0"
dependencies = [
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -19,13 +19,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libz-sys"
version = "1.0.16"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -41,15 +40,9 @@ name = "pkg-config"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vcpkg"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum gcc 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)" = "291055c78f59ca3d84c99026c9501c469413d386bb46be1e1cf1d285cd1db3b0"
"checksum libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)" = "38f5c2b18a287cf78b4097db62e20f43cace381dc76ae5c0a3073067f78b7ddc"
"checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8"
"checksum libz-sys 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "7616099a575493da60cddc1174b686fcfb00ece89dc6f61f31ff47c35f07bbe8"
"checksum num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a225d1e2717567599c24f88e49f00856c6e825a12125181ee42c4257e3688d39"
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
"checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b"

Просмотреть файл

@ -18,4 +18,4 @@ num_cpus = "1.1.0"
[dependencies]
libc = "0.2"
libz-sys = "1.0.16"
libz-sys = "1.0"

Просмотреть файл

@ -110,7 +110,6 @@ case $cmd in
cp -pPR ${TOPSRCDIR}/mfbt ${tgtpath}
cp -p ${SRCDIR}/../moz.configure ${tgtpath}/js
cp -pPR ${SRCDIR}/../public ${tgtpath}/js
cp -pPR ${SRCDIR}/../rust ${tgtpath}/js
cp -pPR ${SRCDIR}/../examples ${tgtpath}/js
find ${SRCDIR} -mindepth 1 -maxdepth 1 -not -path ${STAGING} -a -not -name ${pkg} \
-exec cp -pPR {} ${tgtpath}/js/src \;

Просмотреть файл

@ -270,7 +270,7 @@ license file's hash.
crates_and_roots = (
('gkrust', 'toolkit/library/rust'),
('gkrust-gtest', 'toolkit/library/gtest/rust'),
('js', 'js/rust'),
('mozjs_sys', 'js/src'),
('geckodriver', 'testing/geckodriver'),
)

Просмотреть файл

@ -35,7 +35,6 @@ job-defaults:
- intl/icu/**
- js/moz.configure
- js/public/**
- js/rust/**
- js/src/**
- layout/tools/reftest/reftest/**
- Makefile.in
@ -96,23 +95,6 @@ jobs:
spidermonkey-variant: plain
run-on-projects: ['integration', 'release', 'try']
sm-rust-bindings/debug:
description: "Build and test the Rust bindings for SpiderMonkey"
index:
job-name: sm-rust-bindings-debug
treeherder:
symbol: SM-tc(rust)
tier: 2
worker:
max-run-time: 36000
docker-image: {in-tree: desktop-build}
env:
TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/linux64/releng.manifest"
run:
using: spidermonkey-rust-bindings
spidermonkey-variant: plain
run-on-projects: ['integration', 'release', 'try']
sm-plain/debug:
description: "Spidermonkey Plain"
index:

Просмотреть файл

@ -142,7 +142,7 @@ following ``run-using`` are available
* ``mozharness``
* ``mozharness-test``
* ``run-task``
* ``spidermonkey`` or ``spidermonkey-package`` or ``spidermonkey-mozjs-crate`` or ``spidermonkey-rust-bindings``
* ``spidermonkey`` or ``spidermonkey-package`` or ``spidermonkey-mozjs-crate``
* ``toolchain-script``

Просмотреть файл

@ -1,18 +0,0 @@
#!/usr/bin/env bash
set -xe
source $(dirname $0)/sm-tooltool-config.sh
# Ensure that we have a .config/cargo that points us to our vendored crates
# rather than to crates.io.
cd "$SRCDIR/.cargo"
sed -e "s|@top_srcdir@|$SRCDIR|" < config.in | tee config
cd "$SRCDIR/js/rust"
# Enable backtraces if we panic.
export RUST_BACKTRACE=1
cargo test --verbose --frozen --features debugmozjs
cargo test --verbose --frozen

Просмотреть файл

@ -47,8 +47,3 @@ BROWSER_PLATFORM=$PLATFORM_OS$BITS
export TOOLTOOL_CHECKOUT
(cd $TOOLTOOL_CHECKOUT && ${SRCDIR}/mach artifact toolchain -v --tooltool-url $TOOLTOOL_SERVER --tooltool-manifest $SRCDIR/$TOOLTOOL_MANIFEST ${TOOLTOOL_CACHE:+ --cache-dir $TOOLTOOL_CACHE}${MOZ_TOOLCHAINS:+ ${MOZ_TOOLCHAINS}})
# Add all the tooltool binaries to our $PATH.
for bin in ls $TOOLTOOL_CHECKOUT/*/bin; do
export PATH="$bin:$PATH"
done

Просмотреть файл

@ -88,7 +88,6 @@ JOB_NAME_WHITELIST = set([
'sm-plaindebug-debug',
'sm-win-plaindebug-debug',
'sm-rootanalysis-debug',
'sm-rust-bindings-debug',
'sm-tsan-opt',
'win32-add-on-devel',
'win32-clang-tidy',

Просмотреть файл

@ -20,7 +20,7 @@ from taskgraph.transforms.job.common import (
)
sm_run_schema = Schema({
Required('using'): Any('spidermonkey', 'spidermonkey-package', 'spidermonkey-mozjs-crate', 'spidermonkey-rust-bindings'),
Required('using'): Any('spidermonkey', 'spidermonkey-package', 'spidermonkey-mozjs-crate'),
# The SPIDERMONKEY_VARIANT
Required('spidermonkey-variant'): basestring,
@ -31,8 +31,6 @@ sm_run_schema = Schema({
@run_job_using("docker-worker", "spidermonkey-package", schema=sm_run_schema)
@run_job_using("docker-worker", "spidermonkey-mozjs-crate",
schema=sm_run_schema)
@run_job_using("docker-worker", "spidermonkey-rust-bindings",
schema=sm_run_schema)
def docker_worker_spidermonkey(config, job, taskdesc):
run = job['run']
@ -64,8 +62,6 @@ def docker_worker_spidermonkey(config, job, taskdesc):
script = "build-sm-package.sh"
elif run['using'] == 'spidermonkey-mozjs-crate':
script = "build-sm-mozjs-crate.sh"
elif run['using'] == 'spidermonkey-rust-bindings':
script = "build-sm-rust-bindings.sh"
worker['command'] = [
'/builds/worker/bin/run-task',
@ -108,11 +104,7 @@ def generic_worker_spidermonkey(config, job, taskdesc):
elif run['using'] == 'spidermonkey-mozjs-crate':
script = "build-sm-mozjs-crate.sh"
# Don't allow untested configurations yet
raise Exception("spidermonkey-mozjs-crate is not a supported configuration")
elif run['using'] == 'spidermonkey-rust-bindings':
script = "build-sm-rust-bindings.sh"
# Don't allow untested configurations yet
raise Exception("spidermonkey-rust-bindings is not a supported configuration")
raise Exception("spidermonkey-mozhs-crate is not a supported configuration")
hg_command = ['"c:\\Program Files\\Mercurial\\hg.exe"']
hg_command.append('robustcheckout')

Просмотреть файл

@ -167,7 +167,6 @@ RIDEALONG_BUILDS = {
'sm-mozjs-sys',
'sm-msan',
'sm-fuzzing',
'sm-rust-bindings',
],
}

Просмотреть файл

@ -1 +0,0 @@
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".travis.yml":"e17babe5ba0bdd19ec59a37b4a099fd4313bff58be63a2ff506075f9a97dc172","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"367c53caf576e1c811c77b5234f4d00ee23f5b1052d5e11bdc0c3153a8d9ae82","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","Makefile":"a45a128685a2ae7d4fa39d310786674417ee113055ef290a11f88002285865fc","README.md":"9bc60d2cec222b50f87c85cf9475349bb228a36f89796c5d6481c52560ddde3a","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"acf4844efadeafc7bc396c2b16f2a184e140b6c17d1084dbaf454196de2090cd","benches/random.txt":"9386fb3efedc7ffbd09fb49088347f1056bc2d90a861009fa2f804cdb714efcb","ctags.rust":"3d128d3cc59f702e68953ba2fe6c3f46bc6991fc575308db060482d5da0c79f3","examples/dict-search.rs":"30eb44b1a0b599507db4c23a90f74199faabc64a8ae1d603ecdf3bba7428eb1e","session.vim":"95cb1d7caf0ff7fbe76ec911988d908ddd883381c925ba64b537695bc9f021c4","src/autiter.rs":"dc8817af24825c356842c814d771868fb07b6965addf4780e8b9dea9718344a0","src/full.rs":"b83a9c8ff3ef611c316b68650915df2d7f361a49b59dab103dc2c5476f2d8303","src/lib.rs":"68bf2ed02d58bebee6f7f7579038f1e4b60a2c4acc334263cb837bcbe15ffe94","src/main.rs":"fc867cb5f0b02d0f49ecab06b72c05a247cbcf3bf9228c235de8e787bda7bef5"},"package":"0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2"}

Просмотреть файл

Просмотреть файл

@ -1,13 +0,0 @@
language: rust
rust:
- 1.12.0
- stable
- beta
- nightly
script:
- cargo build --verbose
- cargo test --verbose
- cargo doc
- if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then
cargo bench --verbose;
fi

3
third_party/rust/aho-corasick-0.6.2/COPYING поставляемый
Просмотреть файл

@ -1,3 +0,0 @@
This project is dual-licensed under the Unlicense and MIT licenses.
You may use this code under the terms of either license.

Просмотреть файл

@ -1,47 +0,0 @@
[package]
name = "aho-corasick"
version = "0.6.2" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = "Fast multiple substring searching with finite state machines."
documentation = "http://burntsushi.net/rustdoc/aho_corasick/"
homepage = "https://github.com/BurntSushi/aho-corasick"
repository = "https://github.com/BurntSushi/aho-corasick"
readme = "README.md"
keywords = ["string", "search", "text", "aho", "corasick"]
license = "Unlicense/MIT"
exclude = ["benches/sherlock.txt"]
[lib]
name = "aho_corasick"
[[bin]]
name = "aho-corasick-dot"
test = false
doc = false
bench = false
[dependencies]
memchr = "1"
[dev-dependencies]
csv = "0.15"
docopt = "0.7"
memmap = "0.5"
quickcheck = { version = "0.4", default-features = false }
rand = "0.3"
rustc-serialize = "0.3"
[[bench]]
name = "bench"
path = "benches/bench.rs"
test = false
bench = true
[profile.test]
debug = true
[profile.bench]
debug = true
[profile.release]
debug = true

Просмотреть файл

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2015 Andrew Gallant
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

14
third_party/rust/aho-corasick-0.6.2/Makefile поставляемый
Просмотреть файл

@ -1,14 +0,0 @@
all:
echo Nothing to do...
ctags:
ctags --recurse --options=ctags.rust --languages=Rust
docs:
cargo doc
in-dir ./target/doc fix-perms
rscp ./target/doc/* gopher:~/www/burntsushi.net/rustdoc/
push:
git push origin master
git push github master

55
third_party/rust/aho-corasick-0.6.2/README.md поставляемый
Просмотреть файл

@ -1,55 +0,0 @@
This crate provides an implementation of the
[Aho-Corasick](http://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm)
algorithm. Its intended use case is for fast substring matching, particularly
when matching multiple substrings in a search text. This is achieved by
compiling the substrings into a finite state machine.
This implementation provides optimal algorithmic time complexity. Construction
of the finite state machine is `O(p)` where `p` is the length of the substrings
concatenated. Matching against search text is `O(n + p + m)`, where `n` is
the length of the search text and `m` is the number of matches.
[![Build status](https://api.travis-ci.org/BurntSushi/aho-corasick.png)](https://travis-ci.org/BurntSushi/aho-corasick)
[![](http://meritbadge.herokuapp.com/aho-corasick)](https://crates.io/crates/aho-corasick)
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
### Documentation
[http://burntsushi.net/rustdoc/aho_corasick/](http://burntsushi.net/rustdoc/aho_corasick/).
### Example
The documentation contains several examples, and there is a more complete
example as a full program in `examples/dict-search.rs`.
Here is a quick example showing simple substring matching:
```rust
use aho_corasick::{Automaton, AcAutomaton, Match};
let aut = AcAutomaton::new(vec!["apple", "maple"]);
let mut it = aut.find("I like maple apples.");
assert_eq!(it.next(), Some(Match {
pati: 1,
start: 7,
end: 12,
}));
assert_eq!(it.next(), Some(Match {
pati: 0,
start: 13,
end: 18,
}));
assert_eq!(it.next(), None);
```
### Alternatives
Aho-Corasick is useful for matching multiple substrings against many long
strings. If your long string is fixed, then you might consider building a
[suffix array](https://github.com/BurntSushi/suffix)
of the search text (which takes `O(n)` time). Matches can then be found in
`O(plogn)` time.

24
third_party/rust/aho-corasick-0.6.2/UNLICENSE поставляемый
Просмотреть файл

@ -1,24 +0,0 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>

Просмотреть файл

@ -1,339 +0,0 @@
#![feature(test)]
extern crate aho_corasick;
extern crate test;
use std::iter;
use aho_corasick::{Automaton, AcAutomaton, Transitions};
use test::Bencher;
const HAYSTACK_RANDOM: &'static str = include_str!("random.txt");
const HAYSTACK_SHERLOCK: &'static str = include_str!("sherlock.txt");
fn bench_aut_no_match<P: AsRef<[u8]>, T: Transitions>(
b: &mut Bencher,
aut: AcAutomaton<P, T>,
haystack: &str,
) {
b.bytes = haystack.len() as u64;
b.iter(|| assert!(aut.find(haystack).next().is_none()));
}
fn bench_box_aut_no_match<P: AsRef<[u8]>, T: Transitions>(
b: &mut Bencher,
aut: AcAutomaton<P, T>,
haystack: &str,
) {
b.bytes = haystack.len() as u64;
let aut: &Automaton<P> = &aut;
b.iter(|| assert!(Automaton::find(&aut, haystack).next().is_none()));
}
fn bench_full_aut_no_match<P: AsRef<[u8]>, T: Transitions>(
b: &mut Bencher,
aut: AcAutomaton<P, T>,
haystack: &str,
) {
let aut = aut.into_full();
b.bytes = haystack.len() as u64;
b.iter(|| assert!(aut.find(haystack).next().is_none()));
}
fn bench_full_aut_overlapping_no_match<P: AsRef<[u8]>, T: Transitions>(
b: &mut Bencher,
aut: AcAutomaton<P, T>,
haystack: &str,
) {
let aut = aut.into_full();
b.bytes = haystack.len() as u64;
b.iter(|| assert!(aut.find_overlapping(haystack).count() == 0));
}
fn bench_naive_no_match<S>(b: &mut Bencher, needles: Vec<S>, haystack: &str)
where S: Into<String> {
b.bytes = haystack.len() as u64;
let needles: Vec<String> = needles.into_iter().map(Into::into).collect();
b.iter(|| assert!(!naive_find(&needles, haystack)));
}
fn haystack_same(letter: char) -> String {
iter::repeat(letter).take(10000).collect()
}
macro_rules! aut_benches {
($prefix:ident, $aut:expr, $bench:expr) => {
mod $prefix {
#![allow(unused_imports)]
use aho_corasick::{Automaton, AcAutomaton, Sparse};
use test::Bencher;
use super::{
HAYSTACK_RANDOM, haystack_same,
bench_aut_no_match, bench_box_aut_no_match,
bench_full_aut_no_match, bench_full_aut_overlapping_no_match,
};
#[bench]
fn ac_one_byte(b: &mut Bencher) {
let aut = $aut(vec!["a"]);
$bench(b, aut, &haystack_same('z'));
}
#[bench]
fn ac_one_prefix_byte_no_match(b: &mut Bencher) {
let aut = $aut(vec!["zbc"]);
$bench(b, aut, &haystack_same('y'));
}
#[bench]
fn ac_one_prefix_byte_every_match(b: &mut Bencher) {
// We lose the benefit of `memchr` because the first byte matches
// in every position in the haystack.
let aut = $aut(vec!["zbc"]);
$bench(b, aut, &haystack_same('z'));
}
#[bench]
fn ac_one_prefix_byte_random(b: &mut Bencher) {
let aut = $aut(vec!["zbc\x00"]);
$bench(b, aut, HAYSTACK_RANDOM);
}
#[bench]
fn ac_two_bytes(b: &mut Bencher) {
let aut = $aut(vec!["a", "b"]);
$bench(b, aut, &haystack_same('z'));
}
#[bench]
fn ac_two_diff_prefix(b: &mut Bencher) {
let aut = $aut(vec!["abcdef", "bmnopq"]);
$bench(b, aut, &haystack_same('z'));
}
#[bench]
fn ac_two_one_prefix_byte_every_match(b: &mut Bencher) {
let aut = $aut(vec!["zbcdef", "zmnopq"]);
$bench(b, aut, &haystack_same('z'));
}
#[bench]
fn ac_two_one_prefix_byte_no_match(b: &mut Bencher) {
let aut = $aut(vec!["zbcdef", "zmnopq"]);
$bench(b, aut, &haystack_same('y'));
}
#[bench]
fn ac_two_one_prefix_byte_random(b: &mut Bencher) {
let aut = $aut(vec!["zbcdef\x00", "zmnopq\x00"]);
$bench(b, aut, HAYSTACK_RANDOM);
}
#[bench]
fn ac_ten_bytes(b: &mut Bencher) {
let aut = $aut(vec!["a", "b", "c", "d", "e",
"f", "g", "h", "i", "j"]);
$bench(b, aut, &haystack_same('z'));
}
#[bench]
fn ac_ten_diff_prefix(b: &mut Bencher) {
let aut = $aut(vec!["abcdef", "bbcdef", "cbcdef", "dbcdef",
"ebcdef", "fbcdef", "gbcdef", "hbcdef",
"ibcdef", "jbcdef"]);
$bench(b, aut, &haystack_same('z'));
}
#[bench]
fn ac_ten_one_prefix_byte_every_match(b: &mut Bencher) {
let aut = $aut(vec!["zacdef", "zbcdef", "zccdef", "zdcdef",
"zecdef", "zfcdef", "zgcdef", "zhcdef",
"zicdef", "zjcdef"]);
$bench(b, aut, &haystack_same('z'));
}
#[bench]
fn ac_ten_one_prefix_byte_no_match(b: &mut Bencher) {
let aut = $aut(vec!["zacdef", "zbcdef", "zccdef", "zdcdef",
"zecdef", "zfcdef", "zgcdef", "zhcdef",
"zicdef", "zjcdef"]);
$bench(b, aut, &haystack_same('y'));
}
#[bench]
fn ac_ten_one_prefix_byte_random(b: &mut Bencher) {
let aut = $aut(vec!["zacdef\x00", "zbcdef\x00", "zccdef\x00",
"zdcdef\x00", "zecdef\x00", "zfcdef\x00",
"zgcdef\x00", "zhcdef\x00", "zicdef\x00",
"zjcdef\x00"]);
$bench(b, aut, HAYSTACK_RANDOM);
}
}
}
}
aut_benches!(dense, AcAutomaton::new, bench_aut_no_match);
aut_benches!(dense_boxed, AcAutomaton::new, bench_box_aut_no_match);
aut_benches!(sparse, AcAutomaton::<&str, Sparse>::with_transitions,
bench_aut_no_match);
aut_benches!(full, AcAutomaton::new, bench_full_aut_no_match);
aut_benches!(full_overlap, AcAutomaton::new, bench_full_aut_overlapping_no_match);
// A naive multi-pattern search.
// We use this to benchmark *throughput*, so it should never match anything.
fn naive_find(needles: &[String], haystack: &str) -> bool {
for hi in 0..haystack.len() {
let rest = &haystack.as_bytes()[hi..];
for needle in needles {
let needle = needle.as_bytes();
if needle.len() > rest.len() {
continue;
}
if needle == &rest[..needle.len()] {
// should never happen in throughput benchmarks.
return true;
}
}
}
false
}
#[bench]
fn naive_one_byte(b: &mut Bencher) {
bench_naive_no_match(b, vec!["a"], &haystack_same('z'));
}
#[bench]
fn naive_one_prefix_byte_no_match(b: &mut Bencher) {
bench_naive_no_match(b, vec!["zbc"], &haystack_same('y'));
}
#[bench]
fn naive_one_prefix_byte_every_match(b: &mut Bencher) {
bench_naive_no_match(b, vec!["zbc"], &haystack_same('z'));
}
#[bench]
fn naive_one_prefix_byte_random(b: &mut Bencher) {
bench_naive_no_match(b, vec!["zbc\x00"], HAYSTACK_RANDOM);
}
#[bench]
fn naive_two_bytes(b: &mut Bencher) {
bench_naive_no_match(b, vec!["a", "b"], &haystack_same('z'));
}
#[bench]
fn naive_two_diff_prefix(b: &mut Bencher) {
bench_naive_no_match(b, vec!["abcdef", "bmnopq"], &haystack_same('z'));
}
#[bench]
fn naive_two_one_prefix_byte_every_match(b: &mut Bencher) {
bench_naive_no_match(b, vec!["zbcdef", "zmnopq"], &haystack_same('z'));
}
#[bench]
fn naive_two_one_prefix_byte_no_match(b: &mut Bencher) {
bench_naive_no_match(b, vec!["zbcdef", "zmnopq"], &haystack_same('y'));
}
#[bench]
fn naive_two_one_prefix_byte_random(b: &mut Bencher) {
bench_naive_no_match(b, vec!["zbcdef\x00", "zmnopq\x00"], HAYSTACK_RANDOM);
}
#[bench]
fn naive_ten_bytes(b: &mut Bencher) {
let needles = vec!["a", "b", "c", "d", "e",
"f", "g", "h", "i", "j"];
bench_naive_no_match(b, needles, &haystack_same('z'));
}
#[bench]
fn naive_ten_diff_prefix(b: &mut Bencher) {
let needles = vec!["abcdef", "bbcdef", "cbcdef", "dbcdef",
"ebcdef", "fbcdef", "gbcdef", "hbcdef",
"ibcdef", "jbcdef"];
bench_naive_no_match(b, needles, &haystack_same('z'));
}
#[bench]
fn naive_ten_one_prefix_byte_every_match(b: &mut Bencher) {
let needles = vec!["zacdef", "zbcdef", "zccdef", "zdcdef",
"zecdef", "zfcdef", "zgcdef", "zhcdef",
"zicdef", "zjcdef"];
bench_naive_no_match(b, needles, &haystack_same('z'));
}
#[bench]
fn naive_ten_one_prefix_byte_no_match(b: &mut Bencher) {
let needles = vec!["zacdef", "zbcdef", "zccdef", "zdcdef",
"zecdef", "zfcdef", "zgcdef", "zhcdef",
"zicdef", "zjcdef"];
bench_naive_no_match(b, needles, &haystack_same('y'));
}
#[bench]
fn naive_ten_one_prefix_byte_random(b: &mut Bencher) {
let needles = vec!["zacdef\x00", "zbcdef\x00", "zccdef\x00",
"zdcdef\x00", "zecdef\x00", "zfcdef\x00",
"zgcdef\x00", "zhcdef\x00", "zicdef\x00",
"zjcdef\x00"];
bench_naive_no_match(b, needles, HAYSTACK_RANDOM);
}
// The organization above is just awful. Let's start over...
mod sherlock {
use aho_corasick::{Automaton, AcAutomaton};
use test::Bencher;
use super::HAYSTACK_SHERLOCK;
macro_rules! sherlock {
($name:ident, $count:expr, $pats:expr) => {
#[bench]
fn $name(b: &mut Bencher) {
let haystack = HAYSTACK_SHERLOCK;
let aut = AcAutomaton::new($pats).into_full();
b.bytes = haystack.len() as u64;
b.iter(|| assert_eq!($count, aut.find(haystack).count()));
}
}
}
sherlock!(name_alt1, 158, vec!["Sherlock", "Street"]);
sherlock!(name_alt2, 558, vec!["Sherlock", "Holmes"]);
sherlock!(name_alt3, 740, vec![
"Sherlock", "Holmes", "Watson", "Irene", "Adler", "John", "Baker",
]);
sherlock!(name_alt3_nocase, 1764, vec![
"ADL", "ADl", "AdL", "Adl", "BAK", "BAk", "BA", "BaK", "Bak", "Ba",
"HOL", "HOl", "HoL", "Hol", "IRE", "IRe", "IrE", "Ire", "JOH", "JOh",
"JoH", "Joh", "SHE", "SHe", "ShE", "She", "WAT", "WAt", "WaT", "Wat",
"aDL", "aDl", "adL", "adl", "bAK", "bAk", "bA", "baK", "bak", "ba",
"hOL", "hOl", "hoL", "hol", "iRE", "iRe", "irE", "ire", "jOH", "jOh",
"joH", "joh", "sHE", "sHe", "shE", "she", "wAT", "wAt", "waT", "wat",
"ſHE", "ſHe", "ſhE", "ſhe",
]);
sherlock!(name_alt4, 582, vec!["Sher", "Hol"]);
sherlock!(name_alt4_nocase, 1307, vec![
"HOL", "HOl", "HoL", "Hol", "SHE", "SHe", "ShE", "She", "hOL", "hOl",
"hoL", "hol", "sHE", "sHe", "shE", "she", "ſHE", "ſHe", "ſhE", "ſhe",
]);
sherlock!(name_alt5, 639, vec!["Sherlock", "Holmes", "Watson"]);
sherlock!(name_alt5_nocase, 1442, vec![
"HOL", "HOl", "HoL", "Hol", "SHE", "SHe", "ShE", "She", "WAT", "WAt",
"WaT", "Wat", "hOL", "hOl", "hoL", "hol", "sHE", "sHe", "shE", "she",
"wAT", "wAt", "waT", "wat", "ſHE", "ſHe", "ſhE", "ſhe",
]);
}

Просмотреть файл

@ -1,513 +0,0 @@
mnxnsynfvuugtbxsxbfxwreuspglnplefzwsp
tacfqcwnmodnmgnyiuvqoco
z
qjuozfkexn
zoaxzncje
sldhqtmgxzyurfyzwazmmu
bbeuv
mzsrihycwcb
xzfqozfmlnpmrzpxxxytqs
xrg
mcplby
nmslhfgjowhzfxsvyddydnsyehdskbydbjksqtpet
indvfw
bvjvvw
pddufodyqtyixbndtumndyz
xjjhtuvmsxhuwqulqtjhqrdqrmtbcphvyuqllocrnkpfv
zemshhz
wss
xewlrxfmgxnwgphcgefa
mbgsgbzrtthxweimcqzcaaheurdmd
osqefupespvh
z
tvvlakwzwjbrgjzfgubsmmonav
pjdskxcfgapsm
zqktqgkrcdrlskx
zwwfebhguskho
zlvvw
czwm
gojnpmboehlsazbexjjnuscqftrfufngygjdxcydib
d
afigycivicnknfxl
ljuwuopctiftfwctxecwipjnljyef
jonwbkodomzhqvlf
jdkizhognqsdogunwedjsmsdzho
zxvni
oynfjf
muvokjuqz
azuwrwtuxzfopwrcex
ixrjinlvxjmn
blaegnmbhsgsbmebwazaeguugtkowexgnqtbfkldadddv
tzabyoftyov
ctbtqbzscxzviuvcigwuwusrdro
ljynr
gnnnyyxslrhsbj
hhzlw
hijalf
rxlfqk
mhaofforwznvmcgplinludpgkucpa
gvvxsqqfmu
xxqhoyosixjfhjuxpv
faadjpvamjekreepizurntvwdynozfawsfawyms
lcbutr
aqyxvpozkjrecrkl
lfmochahrr
ptqyomjlwo
vcmslulznx
lmlsskcihrmxauztuarydlp
beiqsrfnmvmlmybmwpektjbikvpggthpabqsgmjhnthvysuhwbigillugjsp
dfsuegseffwcsnvsrqedytblbpzbfeyfsq
kypvqctrkuds
ylqeduokzgdqaxelhftxnxbidu
bprzyayfopxdsmfhhfqowa
ymiutdtlfaaxpbtaeslv
ggago
owpbicekdeykzfgcbgzobdvvrtetvcv
xsrlgingstiez
gyncqvq
xasohmeiwyscpehctmzmsnjklg
xsudghakxlw
dzqlfptjogzpkvwuticcyugnyopypuqqc
wlxshxbhdvuherumoppcc
znyaptivzncvkpeyeipynqefjxjjcsgfqbnezeebtowdrbjaqjlbxwvyikrmxjwoxngqgvfpbniftnmszuxg
umwpwwyvufy
pallkjtnrmtauqxauewgygwkjjwebbkabhtxticxmxfujpxlrpzlrozfslkzfdsswlmmsbdgjwmjnummk
dhsxylejzityahtqqzmohrpzjprrsraztpnuagtyzfjdekthvdogfidksrdppr
ybc
fyukknoqfnkllkwflwempjijxgo
dltvlau
rhvrvlwsribfctuzodfqkdczfzxnetqqzflnhiyl
goxmcasmq
wljbhwkpahdotqhhrbhqzijv
lszewkgdmkezvgmbmllhpksdkoiwgkvqjmurshrptlctqsosuurndcuzjfwherotv
dudxxihygxblhgchbgzyzffb
eht
fvwxvqoltdcsd
rkuig
e
axhsacsmnicugul
rubtdlhjqndxdzzwfnkuzy
swxteuyxxsktkjgv
hzwwodlqaq
vxgecev
qnwla
vdxjuzpyoqhpmuunyffptopmeauhycs
dkzo
awrfzatzohslgvqlaezepmli
qgxatixvpkkhvkumbwmwcagtgyfljdok
amdnzstpvcqj
xsrvwvhjirzfgkessve
qezwbfltfbikbmoasvoflozsjhrljnszqiciuqmflrlqowwkoevuumh
babskcvavmtvsxqsewirucwzajjcfcqwsydydqo
ywfurpsl
edacsjjkjjewkxfoh
dcgkfpcjezurnuhiatrczcp
xsatnimwbcciu
grzmbrsvvcyigcbmcqfwiiknrohveubhyijxeyzfm
kqyewccgcqrrrznwxmoztlyseagbpyho
najju
nis
awgzdvfjkzlrsjcqfeacx
oisuflfigrjaex
desbdulyuwqxuxianyypybxwlql
ekmqgspvqpftpwswayh
egbyj
fznzprhvnnwcxgcc
wfdsueieosmugirxbymbpmfrspvrktjzguxm
qkjrufshwnfwwpbhukdjlaqvljlgubmqmhnha
hwqpudgnblhlxppbrmbznotteivuzguuwlhtkytky
w
yofkyzbpg
cenolnfnllkvhikrpttcxgqxmufvorekjruyjxmr
hyexmpjijgzumawp
cdbevdilgopbzlo
fivelagckslkugdxprjxkylizewcptwxfhomzuituujixchadmnjoktnqa
csojvlinzmmkkfzqueamnuwkanzdzsavgohposbuoamoevehqrmcxdsuyelvvctoejzoertqormhaaxwofvjzekwt
sbkghhnhutrvwtyjaxndzyjamrhx
jjyqy
majwbnrhveuhrsbbbjrwpwuplifeseylqh
wyvutpxnkrnkuxxetjkkifpqb
dyzucmbcvgnjeecm
hz
uhnuipthxrzkqluosvk
lwqqzsdwiwvwaqfwlvubadlyizlo
jbd
oyzjeu
kydjkbsqxnbfiuesc
smeubjqrcxdvhsabzceyglqjzbfmoacmwvwjbhhxbr
uabipgecujfdfxpmdzrscdyvefizabgspqjrrkmgjt
xgvdgzryz
lw
uimob
ifhn
bqph
ole
g
wt
k
yslzrkwkundxfdibwqvucemepqxlmlpyngabbeciuzhptpjdetyngrtxrdtzmvq
ccwapidp
bwvrgvmtshevrophy
ni
fdkplu
mdykey
i
rhsrenoetdggpjb
djmkplpeabsholx
judxtub
fooakqwvocvpcrvxqhvtmpvhkrecy
uuxscjillynilbkrgt
evtinrmilniguarqritpeipwochmdw
sxaqzjybydyvnmmjtdcgkjnqfcklbfpkdfyewgcukqoiegyfp
kg
ovrwieqhy
jcxqtkerzjwhs
xeonglszbgypafhmqcaseimzjgebkvigbqwsayrnrprtuvhsxyitfqygohgorcdnufbcyvevvgzmjrgjqqquwkszplogx
zdketqqv
yebckucwayckeezfvtnavglpjh
zorkfrwk
pad
xqaquxudybwtgixbfktinctfirjfdayh
rieknj
ebk
qzbcfywfdmhsdruhopovemafijbscagllkmhmof
asbsnbddlobwoqatfhkbhhsymzqxjuixwreheugvngmgcuqpkjhhfwpbarqaxrwgwnjbanljlds
etevdvlc
lqyjrnmenhn
k
tsf
zczgeavcexh
jlpuxywtsrvnvluruqhecjca
ir
rikrgkmhwaosodkxgcnrexfmdrszhnmutpvwztg
bffjqovvkemctnsgeh
weysbhzixiipfithjfsk
usyzvaiyuhmksfluoirfbnsu
o
cgawpdakaszeafdtbdkqtlzkrpnoqomqvuaqcfmzgvfegovtfaonelpv
izmrcjlk
xmzemniyrzy
knqexaafsdlimdamcrprlshq
qkmqw
dntgjwsibclvposdwjuklvtejjjdjibgpyynqpgprvvaetshhmvfkcpb
otvazkrkklrxfotpopyjte
fghkcnpi
rulyaihsowvcgbzeiblhuhhfbmncqsuuqcxvseorn
exirzfmojnxcoqom
zsgpgtokun
zvamxfocorganbtlafifwdqmqtsnktbwwtewborq
cxlnaspjqvsitjyzyriqsuorjsrvzqenisprttudxntsbqrpjtdkxnwcwgjyxmgtqljcrmrbrmyvosojzlumcmjcgfjsdehec
mvx
mt
mckr
teulvroifk
laaicc
koufy
bexmwsvyarnznebdfy
ripvviosbqijsxnjilwddaqaqemzsdarnxmfooxghoypizwtbueo
ljycycuqwfnzbambibqdixmkkvwtubepla
cis
kcg
vmbbiuuoamenzepuagpfujevfstqtndjxjchdvycfrrrowochtjdmkklgnhf
pmorrwguxkvdxpluatagaziin
uwvzbmkmykjkmknzppklx
pnzxuvsrjunqxercsnvayhykcazdeclomdsasgkpqpiufyfqsxhj
yceizkddwojgweegcllaagpvrpo
ek
kuxxgbezqyxvfaxdwnqdgqsmneijunxzlwxkrs
ldldbrxmvtjlqxifngmactzqcygkvuteffcmvphevilabgukatqakamjlridznodcvblvlogulmcixxfimh
iuzjootuywjqklolzzhpeaynydjwtufjavbozxnzckuzdodkvkjfmhinelv
swlfkcufscfcovmghqwcrtxjukwafoeogrkgubbqgwzm
gjcylkwgzroubdssuqeykqjcmguso
fzq
srfvysoxtlylctp
pbfeiuzwoyixews
ocvvunfsjnrtklmuuzjojw
xdjcnrpqhmpmpcwacpcdtmbsczvhllkqapzjuaf
nfnuvjz
fwnuiyqpn
wshxxxpzzxp
hibrxcfeqca
wqhlllarl
bukcbojv
plrytapy
xm
vlgfqoyzdczqbbaxjwbjjevjhxgopuqvqcrj
vpjqfbdnsdxlbuuiqocvrhap
mgumjbvnnzgnrdru
gcgzugazxdcamrhczfzhtmdjj
uislwq
vooai
zjuqfmebuzsqngzekyajujkopvayxtdzvugwwucvlsbrnhitfotmhhmgddlzlvqrkcponictrfweuilfjiuoabkfdvpjiqjrrgi
aptjfhmrnxaq
hbs
w
mwmoxqvucwygunplzvxtxpk
fgmqmtlorfzytjdzffsosfccnfwugrsrynuej
rpmpenrhsxoefnblyumjqwvuyszyppnttuyvazjdug
zdzxraxkroknkmqgvuoqeqdtvclsvvuwmdwzfugcpteohlogxubyoebvrzbqzklvehfcqadtdrkpubfhmokzwyosogepwragcpwxo
ax
dz
de
thvkdmnbdws
ejmubw
umvwkaubzurf
wyxtxeluaoox
wwbioobtgmkebxo
miglgnafmdarzkeblyjctuayzyoeqnfnbtrcbymdzkzg
loavxq
kzhllgsenxlbgdbfzwbg
yxflogzsohlcycbyzegeubfflouvtuatixhjvicjegltjiy
jigqfjppafdiarc
mcnmwtachgearonfcymvjbrnljjxmlzkudvzqsarnfysmxlfrtlvjxwvpdbhvwysnvcdozfcruhjwnucdzakkilmlfgjiolcatpfusm
n
pdjunfcz
dc
edxkkxabsbvmvifiinnoccki
bc
gwtwsvorwzfqpz
exidmexstfflkhi
s
s
c
wtcjfywlayhpbqktcepoybowtkrmnumqsg
ozclkgjdmdk
jmegtbunyexurvfexhqptnqzie
tkoenpagzwqfawlxvzaijsjqhmg
swodqfjpdqcbkc
ujokogocyaygdibgpglecis
shlmdmgonvpuaxlhrymkxtiytmv
brhk
jmsyiuomiywxhegilycjprkyfgojdo
wzdzrgpdiosdsvkcw
odlnmsfnjrcsnflviwvawybpczdkzvdocpwrmavz
p
ubowamlskcqhdxuckrxa
fawhntiwhmdwkddnahmtajqqazpdygttqivhdiodkcpcwv
gmxujmmaufmbipaiulhurzkfdg
eixjhmbaeoybiwk
kumntgrgiofcmujlzbcopuobambsw
mnjkqiyb
iktwnsnv
hfuzcl
tqiyqvagbqgtowpjbedgjot
dfemvamelxadkztogliizdtsddoboafawficudlefo
raecmxiiibljryswntpfed
mbwrtsebkeegw
x
epp
he
vnztrswhiusokqdkmsnpuswucvfhcthjbtam
baxlwidsgbdpzvnlj
tcbjjoadrzo
aiidahyllzzsg
igebuubweicbssgddpmqxunrawavuglmpxrtkqsvjjtscibqiejjfgfnovokodmqcqitlteiakooupvzkwucucrfdzjvjbqbkgutoybmpfvhbutigdxhfiqfplyciz
cnrhbjdnjftwfwlwzrdkwhajgsizsi
qfntnt
okqyfnbresp
asyg
mjqdkdyggdxzwuzglays
h
ifaqcazoy
fol
vvsusbnugduxsceozmsarbp
epjwtorx
bwiuxxiyc
cw
bwogruhctwkfvbexjnwircykxyzjmats
kygiochfwlpsvmxcgmtjrgvfdptd
q
qmpqe
z
jghffhqfoecmszunhxmzmzhlmbrvjabhrkihgjmvckhkfpaygjkg
kfiyfgounmhlvhupswqdgws
ezzdpyqucqoocsdcjtruqpokldfkmjhqzoynirybsifyaxnaxppthjoqy
nwetlgzwrhkhtuubbkbepuhbllxspvagxrqokwnrhkbwdwtp
hlazomrhqogoaxypqaszwfxxmutvbpuuvpdffuqskcbzlwyzcssnflkwiydoveyxjnzllzhyozbsa
hwnitkwbxcyibbqsluuqywbk
ozpfjsdrc
yoepefuy
lvmspzepnetra
genbrcrmuqfvkaouvuymoxhcxotjjhk
pcshyqgbmqdubsdajnyfqvxkqvywffzn
ukhcbyzwslqeq
otfrmcbnhbyffxqregqoufdxucjunwdhlqqeiiawbxlpqeyzzopfungrryqdykgizrhqodirvazm
dhpfhzyq
cloz
eduupqifolfekve
qiec
ishnjukvomntmdthlkajxpiwk
y
axl
tmyskjqkjsvumizlal
wvvolwewsfxhhdieuagdcuhwsgqvswpbkdkpxskloalmr
ryfmhe
z
mmbpgsyrfvzdatbjrjhuipwt
llzwizmmuulgwocowwmugtaoewkhnqxparvtynlffffdfcocdbba
pyczkzbmcgrdnxnmezsx
gsqe
mcocxcolcynhpecstsn
opnpplkccobjuhtbhirpzfxuktmpsiwbvsgiaavvdge
wpaldxzasnrbvtugjwytvtfttrh
zxecurevkjiyxy
wtnovebcmglkktic
fdpwfgvlvovxrwh
bmwgdullzy
uzwhagxinwqifxjbcntqzqoxkmpqxhe
jrfizsnwxwnnhb
inapddlahrp
ndtvkceobe
buskgghihdjmjlwfc
j
rkvffxwtmzoeruhlsurwtnuh
cbvkhfepkdishfpqvijzrpleuy
jzdpxjhcgqnybssfegvrnpgyehdqpgjwudbwrjbavp
xzzvgqdrdwajmdmj
vfatwsxvwfdbdhnijdujoyotwvwjipuuetichcfmvgrsnjpqaaezjtkvc
lbfoqgfshrtwgdqufwnfuitdrjydqctqixlzufkdbp
zgau
qefdpmtkecvtj
kuphldkvnzdtpd
dti
fpd
gfrliyegxsb
i
qsddsrmkyfgzrjeqnitmnypbcakh
vfbvbrpuogzhzrbmklvhji
nkz
xlufbaoblbmeub
alwuzxzmobwdukvwnkiwmuqhuxfhevogdnqtmxjptqznrk
cngpoty
ms
qvenfg
dmeaffm
jycfgnanbmoamhmarkmjcagbp
ysqmbhopgx
jczbzgwedsp
zxzwjrxcwdtleizjlvifjwgxiibezwxhtzywqdi
mtgnlu
xboxirdchurkfnklnpkapnqfxnhrxyseiujrznjm
zm
atddskbghcahlhql
szshwzmmvu
befdtpouamwhiisyybispkchpjhownatawjfbx
ennkzbrlygd
zbt
upphzpdwzmlhhhbqvjsfmbnrar
ddcs
ipbxgzyudjyongtcyygncojdufnufqpdppgvq
gc
isu
foa
wf
jdlvqxgfbowhohhyyngbcs
zjuwjyucdwblatsnywaaoftlcamfbcnw
lzrioesuhoeevczuwrnltmkahfwiu
uicggfbddqltnjyxfltbnaekncnyxsit
zkxsqkqrwrzrxgxbsgxatybfr
ptvmfyxdcglbfipcguqthjygzqnpqssscukzawynidtchjrrxwuxifoe
w
ohu
vg
zagpowezvbniybgold
lhqseqcxteiqtgnpanpvrmvvlltxh
mtfnxn
wyodtg
rawpbgtpbaktqzmmpzxmrlwpvvmdsl
widcfbirvswraukbmkhf
vplrueuxomjkqrtjgyxjdkexttzyozawyq
hrpbahllznvmjudzxpbbv
tlavfrxygjfipkupwnbacltcfepeg
icu
otxcu
aewazy
hl
fmrp
qaacthwzohenzjr
xbyebba
rvkph
mkhhmh
swme
zjmdoypaktglcyzobquunvthcdwegtbywpijxd
jvkuhnxqc
gibhqgjojsxt
bodbktzomiqujtbstqiyquwvqgufphqstenxvddkvtdh
bpusrxkfi
zgp
pmxvgamydyakituvvsucsuidrlznupcsinltmrahulhepxmhoqtfvpjkxzhrrinncuh
jzgkjjhjqykzelaszvcwvvwbnzsxdeaerfnaravk
ynanrqyrxo
zsmuxofullob
brklgrcqefdyoczy
qkpls
snhqumae
iqdtzjadzzvnqvdvjfsaf
nfqfdqiramueblxkaqxbbkxwywzgdbndjjiqk
tc
kp
cpuckbjsxhtxmomfesgxdpz
oseif
ybhxbvyxrpkrexrhjzoaxxohrhsniewsrktjnaztn
ggelspdzhzbchruhbjbjidgjwdlhdycetqaswh
jkgivsngygkbqtlmoj
dwpnanfvitxg
ospxbwxp
wgvmvrnjescemdoiralbkvemalifxnyhrbdgodml
hjtsnkzknkplbzsiwmneefdkihnhsamjsrxggclyjqgpqltizi
sykgbuypwwhweab
nvdkkkskmtiwpoerkon
sx
sbyflwwiqylbskdlxesmylpaz
dnwcjenaluwesyywfaezznwkdwpoesxpu
kie
dslccwfryol
gfhomgfn
zprjtfqvkotktzidmoyrivall
bunvsqkysdelozemnjoeqfolruulpbipm
ullyzfahpkhkja
hwd
kvyqtprpuulgsk
zotbkcadnxmfvqmtlbxalhughceyfcibtzzj
vvpjbgxygl
hpic
mhrqd
dv
thehuzdbaacoidjoljbysnqwrrxxplrdznmgiukkvjqbopb
moszjt
rmtbunktkywqirveeqfa
kse
wbfflnatgzobjrxghjgvcsyxoruenxhyomutbptswjajawqjpqafpdcstkiyjuilimecgejpqmyciolgcmdpcstzdozbmnza

Просмотреть файл

@ -1,11 +0,0 @@
--langdef=Rust
--langmap=Rust:.rs
--regex-Rust=/^[ \t]*(#\[[^\]]\][ \t]*)*(pub[ \t]+)?(extern[ \t]+)?("[^"]+"[ \t]+)?(unsafe[ \t]+)?fn[ \t]+([a-zA-Z0-9_]+)/\6/f,functions,function definitions/
--regex-Rust=/^[ \t]*(pub[ \t]+)?type[ \t]+([a-zA-Z0-9_]+)/\2/T,types,type definitions/
--regex-Rust=/^[ \t]*(pub[ \t]+)?enum[ \t]+([a-zA-Z0-9_]+)/\2/g,enum,enumeration names/
--regex-Rust=/^[ \t]*(pub[ \t]+)?struct[ \t]+([a-zA-Z0-9_]+)/\2/s,structure names/
--regex-Rust=/^[ \t]*(pub[ \t]+)?mod[ \t]+([a-zA-Z0-9_]+)/\2/m,modules,module names/
--regex-Rust=/^[ \t]*(pub[ \t]+)?static[ \t]+([a-zA-Z0-9_]+)/\2/c,consts,static constants/
--regex-Rust=/^[ \t]*(pub[ \t]+)?trait[ \t]+([a-zA-Z0-9_]+)/\2/t,traits,traits/
--regex-Rust=/^[ \t]*(pub[ \t]+)?impl([ \t\n]+<.*>)?[ \t]+([a-zA-Z0-9_]+)/\3/i,impls,trait implementations/
--regex-Rust=/^[ \t]*macro_rules![ \t]+([a-zA-Z0-9_]+)/\1/d,macros,macro definitions/

Просмотреть файл

@ -1,151 +0,0 @@
// This example demonstrates how to use the Aho-Corasick algorithm to rapidly
// scan text for matches in a large dictionary of keywords. This example by
// default reads your system's dictionary (~120,000 words).
extern crate aho_corasick;
extern crate csv;
extern crate docopt;
extern crate memmap;
extern crate rustc_serialize;
use std::error::Error;
use std::fs::File;
use std::io::{self, BufRead, Write};
use std::process;
use aho_corasick::{Automaton, AcAutomaton, Match};
use docopt::Docopt;
use memmap::{Mmap, Protection};
static USAGE: &'static str = "
Usage: dict-search [options] <input>
dict-search --help
Options:
-d <path>, --dict <path> Path to dictionary of keywords to search.
[default: /usr/share/dict/words]
-m <len>, --min-len <len> The minimum length for a keyword in UTF-8
encoded bytes. [default: 5]
--overlapping Report overlapping matches.
-c, --count Show only the numebr of matches.
--memory-usage Show memory usage of automaton.
--full Use fully expanded transition matrix.
Warning: may use lots of memory.
-h, --help Show this usage message.
";
#[derive(Clone, Debug, RustcDecodable)]
struct Args {
arg_input: String,
flag_dict: String,
flag_min_len: usize,
flag_overlapping: bool,
flag_memory_usage: bool,
flag_full: bool,
flag_count: bool,
}
fn main() {
let args: Args = Docopt::new(USAGE)
.and_then(|d| d.decode())
.unwrap_or_else(|e| e.exit());
match run(&args) {
Ok(()) => {}
Err(err) => {
writeln!(&mut io::stderr(), "{}", err).unwrap();
process::exit(1);
}
}
}
fn run(args: &Args) -> Result<(), Box<Error>> {
let aut = try!(build_automaton(&args.flag_dict, args.flag_min_len));
if args.flag_memory_usage {
let (bytes, states) = if args.flag_full {
let aut = aut.into_full();
(aut.heap_bytes(), aut.num_states())
} else {
(aut.heap_bytes(), aut.num_states())
};
println!("{} bytes, {} states", bytes, states);
return Ok(());
}
if args.flag_full {
let aut = aut.into_full();
if args.flag_overlapping {
if args.flag_count {
let mmap = Mmap::open_path(
&args.arg_input, Protection::Read).unwrap();
let text = unsafe { mmap.as_slice() };
println!("{}", aut.find_overlapping(text).count());
} else {
let rdr = try!(File::open(&args.arg_input));
try!(write_matches(&aut, aut.stream_find_overlapping(rdr)));
}
} else {
if args.flag_count {
let mmap = Mmap::open_path(
&args.arg_input, Protection::Read).unwrap();
let text = unsafe { mmap.as_slice() };
println!("{}", aut.find(text).count());
} else {
let rdr = try!(File::open(&args.arg_input));
try!(write_matches(&aut, aut.stream_find(rdr)));
}
}
} else {
if args.flag_overlapping {
if args.flag_count {
let mmap = Mmap::open_path(
&args.arg_input, Protection::Read).unwrap();
let text = unsafe { mmap.as_slice() };
println!("{}", aut.find_overlapping(text).count());
} else {
let rdr = try!(File::open(&args.arg_input));
try!(write_matches(&aut, aut.stream_find_overlapping(rdr)));
}
} else {
if args.flag_count {
let mmap = Mmap::open_path(
&args.arg_input, Protection::Read).unwrap();
let text = unsafe { mmap.as_slice() };
println!("{}", aut.find(text).count());
} else {
let rdr = try!(File::open(&args.arg_input));
try!(write_matches(&aut, aut.stream_find(rdr)));
}
}
}
Ok(())
}
fn write_matches<A, I>(aut: &A, it: I) -> Result<(), Box<Error>>
where A: Automaton<String>, I: Iterator<Item=io::Result<Match>> {
let mut wtr = csv::Writer::from_writer(io::stdout());
try!(wtr.write(["pattern", "start", "end"].iter()));
for m in it {
let m = try!(m);
try!(wtr.write([
aut.pattern(m.pati),
&m.start.to_string(),
&m.end.to_string(),
].iter()));
}
try!(wtr.flush());
Ok(())
}
fn build_automaton(
dict_path: &str,
min_len: usize,
) -> Result<AcAutomaton<String>, Box<Error>> {
let buf = io::BufReader::new(try!(File::open(dict_path)));
let mut lines = Vec::with_capacity(1 << 10);
for line in buf.lines() {
let line = try!(line);
if line.len() >= min_len {
lines.push(line);
}
}
Ok(AcAutomaton::with_transitions(lines))
}

Просмотреть файл

@ -1 +0,0 @@
au BufWritePost *.rs silent!make ctags > /dev/null 2>&1

Просмотреть файл

@ -1,503 +0,0 @@
use std::io::{self, BufRead};
use std::marker::PhantomData;
use memchr::{memchr, memchr2, memchr3};
use super::{ROOT_STATE, StateIdx};
/// An abstraction over automatons and their corresponding iterators.
/// The type parameter `P` is the type of the pattern that was used to
/// construct this Automaton.
pub trait Automaton<P> {
/// Return the next state given the current state and next character.
fn next_state(&self, si: StateIdx, b: u8) -> StateIdx;
/// Return true if and only if the given state and current pattern index
/// indicate a match.
fn has_match(&self, si: StateIdx, outi: usize) -> bool;
/// Build a match given the current state, pattern index and input index.
fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match;
/// Return the set of bytes that have transitions in the root state.
fn start_bytes(&self) -> &[u8];
/// Returns all of the patterns matched by this automaton.
///
/// The order of the patterns is the order in which they were added.
fn patterns(&self) -> &[P];
/// Returns the pattern indexed at `i`.
///
/// The index corresponds to the position at which the pattern was added
/// to the automaton, starting at `0`.
fn pattern(&self, i: usize) -> &P;
/// Return the number of patterns in the automaton.
#[inline]
fn len(&self) -> usize {
self.patterns().len()
}
/// Returns true if the automaton has no patterns.
#[inline]
fn is_empty(&self) -> bool {
self.len() == 0
}
/// Returns an iterator of non-overlapping matches in `s`.
fn find<'a, 's, Q: ?Sized + AsRef<[u8]>>(
&'a self,
s: &'s Q,
) -> Matches<'a, 's, P, Self>
where Self: Sized {
Matches {
aut: self,
text: s.as_ref(),
texti: 0,
si: ROOT_STATE,
_m: PhantomData,
}
}
/// Returns an iterator of overlapping matches in `s`.
fn find_overlapping<'a, 's, Q: ?Sized + AsRef<[u8]>>(
&'a self,
s: &'s Q,
) -> MatchesOverlapping<'a, 's, P, Self>
where Self: Sized {
MatchesOverlapping {
aut: self,
text: s.as_ref(),
texti: 0,
si: ROOT_STATE,
outi: 0,
_m: PhantomData,
}
}
/// Returns an iterator of non-overlapping matches in the given reader.
fn stream_find<'a, R: io::Read>(
&'a self,
rdr: R,
) -> StreamMatches<'a, R, P, Self>
where Self: Sized {
StreamMatches {
aut: self,
buf: io::BufReader::new(rdr),
texti: 0,
si: ROOT_STATE,
_m: PhantomData,
}
}
/// Returns an iterator of overlapping matches in the given reader.
fn stream_find_overlapping<'a, R: io::Read>(
&'a self,
rdr: R,
) -> StreamMatchesOverlapping<'a, R, P, Self>
where Self: Sized {
StreamMatchesOverlapping {
aut: self,
buf: io::BufReader::new(rdr),
texti: 0,
si: ROOT_STATE,
outi: 0,
_m: PhantomData,
}
}
}
impl<'a, P: AsRef<[u8]>, A: 'a + Automaton<P> + ?Sized>
Automaton<P> for &'a A {
fn next_state(&self, si: StateIdx, b: u8) -> StateIdx {
(**self).next_state(si, b)
}
fn has_match(&self, si: StateIdx, outi: usize) -> bool {
(**self).has_match(si, outi)
}
fn start_bytes(&self) -> &[u8] {
(**self).start_bytes()
}
fn patterns(&self) -> &[P] {
(**self).patterns()
}
fn pattern(&self, i: usize) -> &P {
(**self).pattern(i)
}
fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match {
(**self).get_match(si, outi, texti)
}
}
/// Records a match in the search text.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct Match {
/// The pattern index.
///
/// This corresponds to the ordering in which the matched pattern was
/// added to the automaton, starting at `0`.
pub pati: usize,
/// The starting byte offset of the match in the search text.
pub start: usize,
/// The ending byte offset of the match in the search text.
///
/// (This can be re-captiulated with `pati` and adding the pattern's
/// length to `start`, but it is convenient to have it here.)
pub end: usize,
}
/// An iterator of non-overlapping matches for in-memory text.
///
/// This iterator yields `Match` values.
///
/// `'a` is the lifetime of the automaton, `'s` is the lifetime of the
/// search text, and `P` is the type of the Automaton's pattern.
#[derive(Debug)]
pub struct Matches<'a, 's, P, A: 'a + Automaton<P> + ?Sized> {
aut: &'a A,
text: &'s [u8],
texti: usize,
si: StateIdx,
_m: PhantomData<P>,
}
// When there's an initial lone start byte, it is usually worth it
// to use `memchr` to skip along the input. The problem is that
// the skipping function is called in the inner match loop, which
// can be quite costly if the skipping condition is never met.
// Therefore, we lift the case analysis outside of the inner loop at
// the cost of repeating code.
//
// `step_to_match` is the version of the inner loop without skipping,
// and `skip_to_match` is the version with skipping.
#[inline(never)]
fn step_to_match<P, A: Automaton<P> + ?Sized>(
aut: &A,
text: &[u8],
mut texti: usize,
mut si: StateIdx
) -> Option<(usize, StateIdx)> {
while texti < text.len() {
si = aut.next_state(si, text[texti]);
if aut.has_match(si, 0) {
return Some((texti, si));
}
texti += 1;
if texti + 4 < text.len() {
si = aut.next_state(si, text[texti]);
if aut.has_match(si, 0) {
return Some((texti, si));
}
texti += 1;
si = aut.next_state(si, text[texti]);
if aut.has_match(si, 0) {
return Some((texti, si));
}
texti += 1;
si = aut.next_state(si, text[texti]);
if aut.has_match(si, 0) {
return Some((texti, si));
}
texti += 1;
si = aut.next_state(si, text[texti]);
if aut.has_match(si, 0) {
return Some((texti, si));
}
texti += 1;
si = aut.next_state(si, text[texti]);
if aut.has_match(si, 0) {
return Some((texti, si));
}
texti += 1;
}
}
None
}
fn skip_to_match<P, A: Automaton<P> + ?Sized, F: Fn(&A, &[u8], usize) -> usize>(
aut: &A,
text: &[u8],
mut texti: usize,
mut si: StateIdx,
skip: F,
) -> Option<(usize, StateIdx)> {
if si == ROOT_STATE {
texti = skip(aut, text, texti);
}
while texti < text.len() {
si = aut.next_state(si, text[texti]);
if aut.has_match(si, 0) {
return Some((texti, si));
}
if si == ROOT_STATE {
texti = skip(aut, text, texti + 1);
} else {
texti += 1;
}
}
None
}
#[inline]
fn skip1<P, A: Automaton<P> + ?Sized>(
aut: &A,
text: &[u8],
at: usize,
) -> usize {
debug_assert!(aut.start_bytes().len() == 1);
let b = aut.start_bytes()[0];
match memchr(b, &text[at..]) {
None => text.len(),
Some(i) => at + i,
}
}
#[inline]
fn skip2<P, A: Automaton<P> + ?Sized>(
aut: &A,
text: &[u8],
at: usize,
) -> usize {
debug_assert!(aut.start_bytes().len() == 2);
let (b1, b2) = (aut.start_bytes()[0], aut.start_bytes()[1]);
match memchr2(b1, b2, &text[at..]) {
None => text.len(),
Some(i) => at + i,
}
}
#[inline]
fn skip3<P, A: Automaton<P> + ?Sized>(
aut: &A,
text: &[u8],
at: usize,
) -> usize {
debug_assert!(aut.start_bytes().len() == 3);
let (b1, b2, b3) = (
aut.start_bytes()[0], aut.start_bytes()[1], aut.start_bytes()[2],
);
match memchr3(b1, b2, b3, &text[at..]) {
None => text.len(),
Some(i) => at + i,
}
}
impl<'a, 's, P, A: Automaton<P> + ?Sized> Iterator for Matches<'a, 's, P, A> {
type Item = Match;
fn next(&mut self) -> Option<Match> {
if self.aut.start_bytes().len() == 1 {
let skip = skip_to_match(
self.aut, self.text, self.texti, self.si, skip1);
if let Some((texti, si)) = skip {
self.texti = texti + 1;
self.si = ROOT_STATE;
return Some(self.aut.get_match(si, 0, texti));
}
} else if self.aut.start_bytes().len() == 2 {
let skip = skip_to_match(
self.aut, self.text, self.texti, self.si, skip2);
if let Some((texti, si)) = skip {
self.texti = texti + 1;
self.si = ROOT_STATE;
return Some(self.aut.get_match(si, 0, texti));
}
} else if self.aut.start_bytes().len() == 3 {
let skip = skip_to_match(
self.aut, self.text, self.texti, self.si, skip3);
if let Some((texti, si)) = skip {
self.texti = texti + 1;
self.si = ROOT_STATE;
return Some(self.aut.get_match(si, 0, texti));
}
} else {
let step = step_to_match(self.aut, self.text, self.texti, self.si);
if let Some((texti, si)) = step {
self.texti = texti + 1;
self.si = ROOT_STATE;
return Some(self.aut.get_match(si, 0, texti));
}
}
None
}
}
/// An iterator of non-overlapping matches for streaming text.
///
/// This iterator yields `io::Result<Match>` values.
///
/// `'a` is the lifetime of the automaton, `R` is the type of the underlying
/// `io::Read`er, and P is the type of the Automaton's pattern.
#[derive(Debug)]
pub struct StreamMatches<'a, R, P, A: 'a + Automaton<P> + ?Sized> {
aut: &'a A,
buf: io::BufReader<R>,
texti: usize,
si: StateIdx,
_m: PhantomData<P>,
}
impl<'a, R: io::Read, P, A: Automaton<P>>
Iterator for StreamMatches<'a, R, P, A> {
type Item = io::Result<Match>;
fn next(&mut self) -> Option<io::Result<Match>> {
let mut m = None;
let mut consumed = 0;
'LOOP: loop {
self.buf.consume(consumed);
let bs = match self.buf.fill_buf() {
Err(err) => return Some(Err(err)),
Ok(bs) if bs.len() == 0 => break,
Ok(bs) => bs,
};
consumed = bs.len(); // is shortened if we find a match
for (i, &b) in bs.iter().enumerate() {
self.si = self.aut.next_state(self.si, b);
if self.aut.has_match(self.si, 0) {
m = Some(Ok(self.aut.get_match(self.si, 0, self.texti)));
consumed = i + 1;
self.texti += 1;
self.si = ROOT_STATE;
break 'LOOP;
}
self.texti += 1;
}
}
self.buf.consume(consumed);
m
}
}
/// An iterator of overlapping matches for in-memory text.
///
/// This iterator yields `Match` values.
///
/// `'a` is the lifetime of the automaton, `'s` is the lifetime of the
/// search text, and `P` is the type of the Automaton's pattern.
#[derive(Debug)]
pub struct MatchesOverlapping<'a, 's, P, A: 'a + Automaton<P> + ?Sized> {
aut: &'a A,
text: &'s [u8],
texti: usize,
si: StateIdx,
outi: usize,
_m: PhantomData<P>,
}
impl<'a, 's, P, A: Automaton<P> + ?Sized>
Iterator for MatchesOverlapping<'a, 's, P, A> {
type Item = Match;
fn next(&mut self) -> Option<Match> {
if self.aut.has_match(self.si, self.outi) {
let m = self.aut.get_match(self.si, self.outi, self.texti);
self.outi += 1;
if !self.aut.has_match(self.si, self.outi) {
self.texti += 1;
}
return Some(m);
}
self.outi = 0;
if self.aut.start_bytes().len() == 1 {
let skip = skip_to_match(
self.aut, self.text, self.texti, self.si, skip1);
if let Some((texti, si)) = skip {
self.texti = texti;
self.si = si;
return self.next();
}
} else if self.aut.start_bytes().len() == 2 {
let skip = skip_to_match(
self.aut, self.text, self.texti, self.si, skip2);
if let Some((texti, si)) = skip {
self.texti = texti;
self.si = si;
return self.next();
}
} else if self.aut.start_bytes().len() == 3 {
let skip = skip_to_match(
self.aut, self.text, self.texti, self.si, skip3);
if let Some((texti, si)) = skip {
self.texti = texti;
self.si = si;
return self.next();
}
} else {
let step = step_to_match(self.aut, self.text, self.texti, self.si);
if let Some((texti, si)) = step {
self.texti = texti;
self.si = si;
return self.next();
}
}
None
}
}
/// An iterator of overlapping matches for streaming text.
///
/// This iterator yields `io::Result<Match>` values.
///
/// `'a` is the lifetime of the automaton, `R` is the type of the underlying
/// `io::Read`er, and P is the type of the Automaton's pattern.
#[derive(Debug)]
pub struct StreamMatchesOverlapping<'a, R, P, A: 'a + Automaton<P> + ?Sized> {
aut: &'a A,
buf: io::BufReader<R>,
texti: usize,
si: StateIdx,
outi: usize,
_m: PhantomData<P>,
}
impl<'a, R: io::Read, P, A: Automaton<P> + ?Sized>
Iterator for StreamMatchesOverlapping<'a, R, P, A> {
type Item = io::Result<Match>;
fn next(&mut self) -> Option<io::Result<Match>> {
if self.aut.has_match(self.si, self.outi) {
let m = self.aut.get_match(self.si, self.outi, self.texti);
self.outi += 1;
if !self.aut.has_match(self.si, self.outi) {
self.texti += 1;
}
return Some(Ok(m));
}
let mut m = None;
let mut consumed = 0;
self.outi = 0;
'LOOP: loop {
self.buf.consume(consumed);
let bs = match self.buf.fill_buf() {
Err(err) => return Some(Err(err)),
Ok(bs) if bs.len() == 0 => break,
Ok(bs) => bs,
};
consumed = bs.len(); // is shortened if we find a match
for (i, &b) in bs.iter().enumerate() {
self.si = self.aut.next_state(self.si, b);
if self.aut.has_match(self.si, self.outi) {
m = Some(Ok(self.aut.get_match(
self.si, self.outi, self.texti)));
consumed = i + 1;
self.outi += 1;
if !self.aut.has_match(self.si, self.outi) {
self.texti += 1;
}
break 'LOOP;
}
self.texti += 1;
}
}
self.buf.consume(consumed);
m
}
}

Просмотреть файл

@ -1,136 +0,0 @@
use std::fmt;
use std::mem;
use super::{
FAIL_STATE,
StateIdx, AcAutomaton, Transitions, Match,
usize_bytes, vec_bytes,
};
use super::autiter::Automaton;
/// A complete Aho-Corasick automaton.
///
/// This uses a single transition matrix that permits each input character
/// to move to the next state with a single lookup in the matrix.
///
/// This is as fast as it gets, but it is guaranteed to use a lot of memory.
/// Namely, it will use at least `4 * 256 * #states`, where the number of
/// states is capped at length of all patterns concatenated.
#[derive(Clone)]
pub struct FullAcAutomaton<P> {
pats: Vec<P>,
trans: Vec<StateIdx>, // row-major, where states are rows
out: Vec<Vec<usize>>, // indexed by StateIdx
start_bytes: Vec<u8>,
}
impl<P: AsRef<[u8]>> FullAcAutomaton<P> {
/// Build a new expanded Aho-Corasick automaton from an existing
/// Aho-Corasick automaton.
pub fn new<T: Transitions>(ac: AcAutomaton<P, T>) -> FullAcAutomaton<P> {
let mut fac = FullAcAutomaton {
pats: vec![],
trans: vec![FAIL_STATE; 256 * ac.states.len()],
out: vec![vec![]; ac.states.len()],
start_bytes: vec![],
};
fac.build_matrix(&ac);
fac.pats = ac.pats;
fac.start_bytes = ac.start_bytes;
fac
}
#[doc(hidden)]
pub fn memory_usage(&self) -> usize {
self.pats.iter()
.map(|p| vec_bytes() + p.as_ref().len())
.fold(0, |a, b| a + b)
+ (4 * self.trans.len())
+ self.out.iter()
.map(|v| vec_bytes() + (usize_bytes() * v.len()))
.fold(0, |a, b| a + b)
+ self.start_bytes.len()
}
#[doc(hidden)]
pub fn heap_bytes(&self) -> usize {
self.pats.iter()
.map(|p| mem::size_of::<P>() + p.as_ref().len())
.fold(0, |a, b| a + b)
+ (4 * self.trans.len())
+ self.out.iter()
.map(|v| vec_bytes() + (usize_bytes() * v.len()))
.fold(0, |a, b| a + b)
+ self.start_bytes.len()
}
fn set(&mut self, si: StateIdx, i: u8, goto: StateIdx) {
let ns = self.num_states();
self.trans[i as usize * ns + si as usize] = goto;
}
#[doc(hidden)]
#[inline]
pub fn num_states(&self) -> usize {
self.out.len()
}
}
impl<P: AsRef<[u8]>> Automaton<P> for FullAcAutomaton<P> {
#[inline]
fn next_state(&self, si: StateIdx, i: u8) -> StateIdx {
let at = i as usize * self.num_states() + si as usize;
unsafe { *self.trans.get_unchecked(at) }
}
#[inline]
fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match {
let pati = self.out[si as usize][outi];
let patlen = self.pats[pati].as_ref().len();
let start = texti + 1 - patlen;
Match {
pati: pati,
start: start,
end: start + patlen,
}
}
#[inline]
fn has_match(&self, si: StateIdx, outi: usize) -> bool {
unsafe { outi < self.out.get_unchecked(si as usize).len() }
}
#[inline]
fn start_bytes(&self) -> &[u8] {
&self.start_bytes
}
#[inline]
fn patterns(&self) -> &[P] {
&self.pats
}
#[inline]
fn pattern(&self, i: usize) -> &P {
&self.pats[i]
}
}
impl<P: AsRef<[u8]>> FullAcAutomaton<P> {
fn build_matrix<T: Transitions>(&mut self, ac: &AcAutomaton<P, T>) {
for (si, s) in ac.states.iter().enumerate().skip(1) {
for b in (0..256).map(|b| b as u8) {
self.set(si as StateIdx, b, ac.next_state(si as StateIdx, b));
}
for &pati in &s.out {
self.out[si].push(pati);
}
}
}
}
impl<P: AsRef<[u8]> + fmt::Debug> fmt::Debug for FullAcAutomaton<P> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "FullAcAutomaton({:?})", self.pats)
}
}

925
third_party/rust/aho-corasick-0.6.2/src/lib.rs поставляемый
Просмотреть файл

@ -1,925 +0,0 @@
/*!
An implementation of the
[Aho-Corasick string search algorithm](https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm).
The Aho-Corasick algorithm is principally useful when you need to search many
large texts for a fixed (possibly large) set of keywords. In particular, the
Aho-Corasick algorithm preprocesses the set of keywords by constructing a
finite state machine. The search phase is then a quick linear scan through the
text. Each character in the search text causes a state transition in the
automaton. Matches are reported when the automaton enters a match state.
# Examples
The main type exposed by this crate is `AcAutomaton`, which can be constructed
from an iterator of pattern strings:
```rust
use aho_corasick::{Automaton, AcAutomaton};
let aut = AcAutomaton::new(vec!["apple", "maple"]);
// AcAutomaton also implements `FromIterator`:
let aut: AcAutomaton<&str> = ["apple", "maple"].iter().cloned().collect();
```
Finding matches can be done with `find`:
```rust
use aho_corasick::{Automaton, AcAutomaton, Match};
let aut = AcAutomaton::new(vec!["apple", "maple"]);
let mut it = aut.find("I like maple apples.");
assert_eq!(it.next(), Some(Match {
pati: 1,
start: 7,
end: 12,
}));
assert_eq!(it.next(), Some(Match {
pati: 0,
start: 13,
end: 18,
}));
assert_eq!(it.next(), None);
```
Use `find_overlapping` if you want to report all matches, even if they
overlap with each other.
```rust
use aho_corasick::{Automaton, AcAutomaton, Match};
let aut = AcAutomaton::new(vec!["abc", "a"]);
let matches: Vec<_> = aut.find_overlapping("abc").collect();
assert_eq!(matches, vec![
Match { pati: 1, start: 0, end: 1}, Match { pati: 0, start: 0, end: 3 },
]);
// Regular `find` will report only one match:
let matches: Vec<_> = aut.find("abc").collect();
assert_eq!(matches, vec![Match { pati: 1, start: 0, end: 1}]);
```
Finally, there are also methods for finding matches on *streams*. Namely, the
search text does not have to live in memory. It's useful to run this on files
that can't fit into memory:
```no_run
use std::fs::File;
use aho_corasick::{Automaton, AcAutomaton};
let aut = AcAutomaton::new(vec!["foo", "bar", "baz"]);
let rdr = File::open("search.txt").unwrap();
for m in aut.stream_find(rdr) {
let m = m.unwrap(); // could be an IO error
println!("Pattern '{}' matched at: ({}, {})",
aut.pattern(m.pati), m.start, m.end);
}
```
There is also `stream_find_overlapping`, which is just like `find_overlapping`,
but it operates on streams.
Please see `dict-search.rs` in this crate's `examples` directory for a more
complete example. It creates a large automaton from a dictionary and can do a
streaming match over arbitrarily large data.
# Memory usage
A key aspect of an Aho-Corasick implementation is how the state transitions
are represented. The easiest way to make the automaton fast is to store a
sparse 256-slot map in each state. It maps an input byte to a state index.
This makes the matching loop extremely fast, since it translates to a simple
pointer read.
The problem is that as the automaton accumulates more states, you end up paying
a `256 * 4` (`4` is for the `u32` state index) byte penalty for every state
regardless of how many transitions it has.
To solve this, only states near the root of the automaton have this sparse
map representation. States near the leaves of the automaton use a dense mapping
that requires a linear scan.
(The specific limit currently set is `3`, so that states with a depth less than
or equal to `3` are less memory efficient. The result is that the memory usage
of the automaton stops growing rapidly past ~60MB, even for automatons with
thousands of patterns.)
If you'd like to opt for the less-memory-efficient-but-faster version, then
you can construct an `AcAutomaton` with a `Sparse` transition strategy:
```rust
use aho_corasick::{Automaton, AcAutomaton, Match, Sparse};
let aut = AcAutomaton::<&str, Sparse>::with_transitions(vec!["abc", "a"]);
let matches: Vec<_> = aut.find("abc").collect();
assert_eq!(matches, vec![Match { pati: 1, start: 0, end: 1}]);
```
*/
#![deny(missing_docs)]
extern crate memchr;
#[cfg(test)] extern crate quickcheck;
#[cfg(test)] extern crate rand;
use std::collections::VecDeque;
use std::fmt;
use std::iter::FromIterator;
use std::mem;
pub use self::autiter::{
Automaton, Match,
Matches, MatchesOverlapping, StreamMatches, StreamMatchesOverlapping,
};
pub use self::full::FullAcAutomaton;
// We're specifying paths explicitly so that we can use
// these modules simultaneously from `main.rs`.
// Should probably make just make `main.rs` a separate crate.
#[path = "autiter.rs"]
mod autiter;
#[path = "full.rs"]
mod full;
/// The integer type used for the state index.
///
/// Limiting this to 32 bit integers can have a big impact on memory usage
/// when using the `Sparse` transition representation.
pub type StateIdx = u32;
// Constants for special state indexes.
const FAIL_STATE: u32 = 0;
const ROOT_STATE: u32 = 1;
// Limit the depth at which we use a sparse alphabet map. Once the limit is
// reached, a dense set is used (and lookup becomes O(n)).
//
// This does have a performance hit, but the (straight forward) alternative
// is to have a `256 * 4` byte overhead for every state.
// Given that Aho-Corasick is typically used for dictionary searching, this
// can lead to dramatic memory bloat.
//
// This limit should only be increased at your peril. Namely, in the worst
// case, `256^DENSE_DEPTH_THRESHOLD * 4` corresponds to the memory usage in
// bytes. A value of `1` gives us a good balance. This is also a happy point
// in the benchmarks. A value of `0` gives considerably worse times on certain
// benchmarks (e.g., `ac_ten_one_prefix_byte_every_match`) than even a value
// of `1`. A value of `2` is slightly better than `1` and it looks like gains
// level off at that point with not much observable difference when set to
// `3`.
//
// Why not make this user configurable? Well, it doesn't make much sense
// because we pay for it with case analysis in the matching loop. Increasing it
// doesn't have much impact on performance (outside of pathological cases?).
//
// N.B. Someone else seems to have discovered an alternative, but I haven't
// grokked it yet: https://github.com/mischasan/aho-corasick
const DENSE_DEPTH_THRESHOLD: u32 = 1;
/// An Aho-Corasick finite automaton.
///
/// The type parameter `P` is the type of the pattern that was used to
/// construct this AcAutomaton.
#[derive(Clone)]
pub struct AcAutomaton<P, T=Dense> {
pats: Vec<P>,
states: Vec<State<T>>,
start_bytes: Vec<u8>,
}
#[derive(Clone)]
struct State<T> {
out: Vec<usize>,
fail: StateIdx,
goto: T,
depth: u32,
}
impl<P: AsRef<[u8]>> AcAutomaton<P> {
/// Create a new automaton from an iterator of patterns.
///
/// The patterns must be convertible to bytes (`&[u8]`) via the `AsRef`
/// trait.
pub fn new<I>(pats: I) -> AcAutomaton<P, Dense>
where I: IntoIterator<Item=P> {
AcAutomaton::with_transitions(pats)
}
}
impl<P: AsRef<[u8]>, T: Transitions> AcAutomaton<P, T> {
/// Create a new automaton from an iterator of patterns.
///
/// This constructor allows one to choose the transition representation.
///
/// The patterns must be convertible to bytes (`&[u8]`) via the `AsRef`
/// trait.
pub fn with_transitions<I>(pats: I) -> AcAutomaton<P, T>
where I: IntoIterator<Item=P> {
AcAutomaton {
pats: vec![], // filled in later, avoid wrath of borrow checker
states: vec![State::new(0), State::new(0)], // empty and root
start_bytes: vec![], // also filled in later
}.build(pats.into_iter().collect())
}
/// Build out the entire automaton into a single matrix.
///
/// This will make searching as fast as possible at the expense of using
/// at least `4 * 256 * #states` bytes of memory.
pub fn into_full(self) -> FullAcAutomaton<P> {
FullAcAutomaton::new(self)
}
#[doc(hidden)]
pub fn num_states(&self) -> usize {
self.states.len()
}
#[doc(hidden)]
pub fn heap_bytes(&self) -> usize {
self.pats.iter()
.map(|p| mem::size_of::<P>() + p.as_ref().len())
.fold(0, |a, b| a + b)
+ self.states.iter()
.map(|s| mem::size_of::<State<T>>() + s.heap_bytes())
.fold(0, |a, b| a + b)
+ self.start_bytes.len()
}
}
impl<P: AsRef<[u8]>, T: Transitions> Automaton<P> for AcAutomaton<P, T> {
#[inline]
fn next_state(&self, mut si: StateIdx, b: u8) -> StateIdx {
loop {
let maybe_si = self.states[si as usize].goto(b);
if maybe_si != FAIL_STATE {
si = maybe_si;
break;
} else {
si = self.states[si as usize].fail;
}
}
si
}
#[inline]
fn get_match(&self, si: StateIdx, outi: usize, texti: usize) -> Match {
let pati = self.states[si as usize].out[outi];
let patlen = self.pats[pati].as_ref().len();
let start = texti + 1 - patlen;
Match {
pati: pati,
start: start,
end: start + patlen,
}
}
#[inline]
fn has_match(&self, si: StateIdx, outi: usize) -> bool {
outi < self.states[si as usize].out.len()
}
#[inline]
fn start_bytes(&self) -> &[u8] {
&self.start_bytes
}
#[inline]
fn patterns(&self) -> &[P] {
&self.pats
}
#[inline]
fn pattern(&self, i: usize) -> &P {
&self.pats[i]
}
}
// Below contains code for *building* the automaton. It's a reasonably faithful
// translation of the description/psuedo-code from:
// http://www.cs.uku.fi/~kilpelai/BSA05/lectures/slides04.pdf
impl<P: AsRef<[u8]>, T: Transitions> AcAutomaton<P, T> {
// This is the first phase and builds the initial keyword tree.
fn build(mut self, pats: Vec<P>) -> AcAutomaton<P, T> {
for (pati, pat) in pats.iter().enumerate() {
if pat.as_ref().is_empty() {
continue;
}
let mut previ = ROOT_STATE;
for &b in pat.as_ref() {
if self.states[previ as usize].goto(b) != FAIL_STATE {
previ = self.states[previ as usize].goto(b);
} else {
let depth = self.states[previ as usize].depth + 1;
let nexti = self.add_state(State::new(depth));
self.states[previ as usize].set_goto(b, nexti);
previ = nexti;
}
}
self.states[previ as usize].out.push(pati);
}
for c in (0..256).into_iter().map(|c| c as u8) {
if self.states[ROOT_STATE as usize].goto(c) == FAIL_STATE {
self.states[ROOT_STATE as usize].set_goto(c, ROOT_STATE);
} else {
self.start_bytes.push(c);
}
}
// If any of the start bytes are non-ASCII, then remove them all,
// because we don't want to be calling memchr on non-ASCII bytes.
// (Well, we could, but it requires being more clever. Simply using
// the prefix byte isn't good enough.)
if self.start_bytes.iter().any(|&b| b > 0x7F) {
self.start_bytes.clear();
}
self.pats = pats;
self.fill()
}
// The second phase that fills in the back links.
fn fill(mut self) -> AcAutomaton<P, T> {
// Fill up the queue with all non-root transitions out of the root
// node. Then proceed by breadth first traversal.
let mut q = VecDeque::new();
for c in (0..256).into_iter().map(|c| c as u8) {
let si = self.states[ROOT_STATE as usize].goto(c);
if si != ROOT_STATE {
q.push_front(si);
}
}
while let Some(si) = q.pop_back() {
for c in (0..256).into_iter().map(|c| c as u8) {
let u = self.states[si as usize].goto(c);
if u != FAIL_STATE {
q.push_front(u);
let mut v = self.states[si as usize].fail;
while self.states[v as usize].goto(c) == FAIL_STATE {
v = self.states[v as usize].fail;
}
let ufail = self.states[v as usize].goto(c);
self.states[u as usize].fail = ufail;
let ufail_out = self.states[ufail as usize].out.clone();
self.states[u as usize].out.extend(ufail_out);
}
}
}
self
}
fn add_state(&mut self, state: State<T>) -> StateIdx {
let i = self.states.len();
self.states.push(state);
i as StateIdx
}
}
impl<T: Transitions> State<T> {
fn new(depth: u32) -> State<T> {
State {
out: vec![],
fail: 1,
goto: Transitions::new(depth),
depth: depth,
}
}
fn goto(&self, b: u8) -> StateIdx {
self.goto.goto(b)
}
fn set_goto(&mut self, b: u8, si: StateIdx) {
self.goto.set_goto(b, si);
}
fn heap_bytes(&self) -> usize {
(self.out.len() * usize_bytes())
+ self.goto.heap_bytes()
}
}
/// An abstraction over state transition strategies.
///
/// This is an attempt to let the caller choose the space/time trade offs
/// used for state transitions.
///
/// (It's possible that this interface is merely good enough for just the two
/// implementations in this crate.)
pub trait Transitions {
/// Return a new state at the given depth.
fn new(depth: u32) -> Self;
/// Return the next state index given the next character.
fn goto(&self, alpha: u8) -> StateIdx;
/// Set the next state index for the character given.
fn set_goto(&mut self, alpha: u8, si: StateIdx);
/// The memory use in bytes (on the heap) of this set of transitions.
fn heap_bytes(&self) -> usize;
}
/// State transitions that can be stored either sparsely or densely.
///
/// This uses less space but at the expense of slower matching.
#[derive(Clone, Debug)]
pub struct Dense(DenseChoice);
#[derive(Clone, Debug)]
enum DenseChoice {
Sparse(Vec<StateIdx>), // indexed by alphabet
Dense(Vec<(u8, StateIdx)>),
}
impl Transitions for Dense {
fn new(depth: u32) -> Dense {
if depth <= DENSE_DEPTH_THRESHOLD {
Dense(DenseChoice::Sparse(vec![0; 256]))
} else {
Dense(DenseChoice::Dense(vec![]))
}
}
fn goto(&self, b1: u8) -> StateIdx {
match self.0 {
DenseChoice::Sparse(ref m) => m[b1 as usize],
DenseChoice::Dense(ref m) => {
for &(b2, si) in m {
if b1 == b2 {
return si;
}
}
FAIL_STATE
}
}
}
fn set_goto(&mut self, b: u8, si: StateIdx) {
match self.0 {
DenseChoice::Sparse(ref mut m) => m[b as usize] = si,
DenseChoice::Dense(ref mut m) => m.push((b, si)),
}
}
fn heap_bytes(&self) -> usize {
match self.0 {
DenseChoice::Sparse(ref m) => m.len() * 4,
DenseChoice::Dense(ref m) => m.len() * (1 + 4),
}
}
}
/// State transitions that are always sparse.
///
/// This can use enormous amounts of memory when there are many patterns,
/// but matching is very fast.
#[derive(Clone, Debug)]
pub struct Sparse(Vec<StateIdx>);
impl Transitions for Sparse {
fn new(_: u32) -> Sparse {
Sparse(vec![0; 256])
}
#[inline]
fn goto(&self, b: u8) -> StateIdx {
self.0[b as usize]
}
fn set_goto(&mut self, b: u8, si: StateIdx) {
self.0[b as usize] = si;
}
fn heap_bytes(&self) -> usize {
self.0.len() * 4
}
}
impl<S: AsRef<[u8]>> FromIterator<S> for AcAutomaton<S> {
/// Create an automaton from an iterator of strings.
fn from_iter<T>(it: T) -> AcAutomaton<S> where T: IntoIterator<Item=S> {
AcAutomaton::new(it)
}
}
// Provide some question debug impls for viewing automatons.
// The custom impls mostly exist for special showing of sparse maps.
impl<P: AsRef<[u8]> + fmt::Debug, T: Transitions>
fmt::Debug for AcAutomaton<P, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use std::iter::repeat;
try!(writeln!(f, "{}", repeat('-').take(79).collect::<String>()));
try!(writeln!(f, "Patterns: {:?}", self.pats));
for (i, state) in self.states.iter().enumerate().skip(1) {
try!(writeln!(f, "{:3}: {}", i, state.debug(i == 1)));
}
write!(f, "{}", repeat('-').take(79).collect::<String>())
}
}
impl<T: Transitions> State<T> {
fn debug(&self, root: bool) -> String {
format!("State {{ depth: {:?}, out: {:?}, fail: {:?}, goto: {{{}}} }}",
self.depth, self.out, self.fail, self.goto_string(root))
}
fn goto_string(&self, root: bool) -> String {
use std::char::from_u32;
let mut goto = vec![];
for b in (0..256).map(|b| b as u8) {
let si = self.goto(b);
if (!root && si == FAIL_STATE) || (root && si == ROOT_STATE) {
continue;
}
goto.push(format!("{} => {}", from_u32(b as u32).unwrap(), si));
}
goto.join(", ")
}
}
impl<T: Transitions> fmt::Debug for State<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.debug(false))
}
}
impl<T: Transitions> AcAutomaton<String, T> {
#[doc(hidden)]
pub fn dot(&self) -> String {
use std::fmt::Write;
let mut out = String::new();
macro_rules! w {
($w:expr, $($tt:tt)*) => { {write!($w, $($tt)*)}.unwrap() }
}
w!(out, r#"
digraph automaton {{
label=<<FONT POINT-SIZE="20">{}</FONT>>;
labelloc="l";
labeljust="l";
rankdir="LR";
"#, self.pats.join(", "));
for (i, s) in self.states.iter().enumerate().skip(1) {
let i = i as u32;
if s.out.len() == 0 {
w!(out, " {};\n", i);
} else {
w!(out, " {} [peripheries=2];\n", i);
}
w!(out, " {} -> {} [style=dashed];\n", i, s.fail);
for b in (0..256).map(|b| b as u8) {
let si = s.goto(b);
if si == FAIL_STATE || (i == ROOT_STATE && si == ROOT_STATE) {
continue;
}
w!(out, " {} -> {} [label={}];\n", i, si, b as char);
}
}
w!(out, "}}");
out
}
}
fn vec_bytes() -> usize {
usize_bytes() * 3
}
fn usize_bytes() -> usize {
let bits = usize::max_value().count_ones() as usize;
bits / 8
}
#[cfg(test)]
mod tests {
use std::collections::HashSet;
use std::io;
use quickcheck::{Arbitrary, Gen, quickcheck};
use super::{Automaton, AcAutomaton, Match};
fn aut_find<S>(xs: &[S], haystack: &str) -> Vec<Match>
where S: Clone + AsRef<[u8]> {
AcAutomaton::new(xs.to_vec()).find(&haystack).collect()
}
fn aut_finds<S>(xs: &[S], haystack: &str) -> Vec<Match>
where S: Clone + AsRef<[u8]> {
let cur = io::Cursor::new(haystack.as_bytes());
AcAutomaton::new(xs.to_vec())
.stream_find(cur).map(|r| r.unwrap()).collect()
}
fn aut_findf<S>(xs: &[S], haystack: &str) -> Vec<Match>
where S: Clone + AsRef<[u8]> {
AcAutomaton::new(xs.to_vec()).into_full().find(haystack).collect()
}
fn aut_findfs<S>(xs: &[S], haystack: &str) -> Vec<Match>
where S: Clone + AsRef<[u8]> {
let cur = io::Cursor::new(haystack.as_bytes());
AcAutomaton::new(xs.to_vec())
.into_full()
.stream_find(cur).map(|r| r.unwrap()).collect()
}
fn aut_findo<S>(xs: &[S], haystack: &str) -> Vec<Match>
where S: Clone + AsRef<[u8]> {
AcAutomaton::new(xs.to_vec()).find_overlapping(haystack).collect()
}
fn aut_findos<S>(xs: &[S], haystack: &str) -> Vec<Match>
where S: Clone + AsRef<[u8]> {
let cur = io::Cursor::new(haystack.as_bytes());
AcAutomaton::new(xs.to_vec())
.stream_find_overlapping(cur).map(|r| r.unwrap()).collect()
}
fn aut_findfo<S>(xs: &[S], haystack: &str) -> Vec<Match>
where S: Clone + AsRef<[u8]> {
AcAutomaton::new(xs.to_vec())
.into_full().find_overlapping(haystack).collect()
}
fn aut_findfos<S>(xs: &[S], haystack: &str) -> Vec<Match>
where S: Clone + AsRef<[u8]> {
let cur = io::Cursor::new(haystack.as_bytes());
AcAutomaton::new(xs.to_vec())
.into_full()
.stream_find_overlapping(cur).map(|r| r.unwrap()).collect()
}
#[test]
fn one_pattern_one_match() {
let ns = vec!["a"];
let hay = "za";
let matches = vec![
Match { pati: 0, start: 1, end: 2 },
];
assert_eq!(&aut_find(&ns, hay), &matches);
assert_eq!(&aut_finds(&ns, hay), &matches);
assert_eq!(&aut_findf(&ns, hay), &matches);
assert_eq!(&aut_findfs(&ns, hay), &matches);
}
#[test]
fn one_pattern_many_match() {
let ns = vec!["a"];
let hay = "zazazzzza";
let matches = vec![
Match { pati: 0, start: 1, end: 2 },
Match { pati: 0, start: 3, end: 4 },
Match { pati: 0, start: 8, end: 9 },
];
assert_eq!(&aut_find(&ns, hay), &matches);
assert_eq!(&aut_finds(&ns, hay), &matches);
assert_eq!(&aut_findf(&ns, hay), &matches);
assert_eq!(&aut_findfs(&ns, hay), &matches);
}
#[test]
fn one_longer_pattern_one_match() {
let ns = vec!["abc"];
let hay = "zazabcz";
let matches = vec![ Match { pati: 0, start: 3, end: 6 } ];
assert_eq!(&aut_find(&ns, hay), &matches);
assert_eq!(&aut_finds(&ns, hay), &matches);
assert_eq!(&aut_findf(&ns, hay), &matches);
assert_eq!(&aut_findfs(&ns, hay), &matches);
}
#[test]
fn one_longer_pattern_many_match() {
let ns = vec!["abc"];
let hay = "zazabczzzzazzzabc";
let matches = vec![
Match { pati: 0, start: 3, end: 6 },
Match { pati: 0, start: 14, end: 17 },
];
assert_eq!(&aut_find(&ns, hay), &matches);
assert_eq!(&aut_finds(&ns, hay), &matches);
assert_eq!(&aut_findf(&ns, hay), &matches);
assert_eq!(&aut_findfs(&ns, hay), &matches);
}
#[test]
fn many_pattern_one_match() {
let ns = vec!["a", "b"];
let hay = "zb";
let matches = vec![ Match { pati: 1, start: 1, end: 2 } ];
assert_eq!(&aut_find(&ns, hay), &matches);
assert_eq!(&aut_finds(&ns, hay), &matches);
assert_eq!(&aut_findf(&ns, hay), &matches);
assert_eq!(&aut_findfs(&ns, hay), &matches);
}
#[test]
fn many_pattern_many_match() {
let ns = vec!["a", "b"];
let hay = "zbzazzzzb";
let matches = vec![
Match { pati: 1, start: 1, end: 2 },
Match { pati: 0, start: 3, end: 4 },
Match { pati: 1, start: 8, end: 9 },
];
assert_eq!(&aut_find(&ns, hay), &matches);
assert_eq!(&aut_finds(&ns, hay), &matches);
assert_eq!(&aut_findf(&ns, hay), &matches);
assert_eq!(&aut_findfs(&ns, hay), &matches);
}
#[test]
fn many_longer_pattern_one_match() {
let ns = vec!["abc", "xyz"];
let hay = "zazxyzz";
let matches = vec![ Match { pati: 1, start: 3, end: 6 } ];
assert_eq!(&aut_find(&ns, hay), &matches);
assert_eq!(&aut_finds(&ns, hay), &matches);
assert_eq!(&aut_findf(&ns, hay), &matches);
assert_eq!(&aut_findfs(&ns, hay), &matches);
}
#[test]
fn many_longer_pattern_many_match() {
let ns = vec!["abc", "xyz"];
let hay = "zazxyzzzzzazzzabcxyz";
let matches = vec![
Match { pati: 1, start: 3, end: 6 },
Match { pati: 0, start: 14, end: 17 },
Match { pati: 1, start: 17, end: 20 },
];
assert_eq!(&aut_find(&ns, hay), &matches);
assert_eq!(&aut_finds(&ns, hay), &matches);
assert_eq!(&aut_findf(&ns, hay), &matches);
assert_eq!(&aut_findfs(&ns, hay), &matches);
}
#[test]
fn many_longer_pattern_overlap_one_match() {
let ns = vec!["abc", "bc"];
let hay = "zazabcz";
let matches = vec![
Match { pati: 0, start: 3, end: 6 },
Match { pati: 1, start: 4, end: 6 },
];
assert_eq!(&aut_findo(&ns, hay), &matches);
assert_eq!(&aut_findos(&ns, hay), &matches);
assert_eq!(&aut_findfo(&ns, hay), &matches);
assert_eq!(&aut_findfos(&ns, hay), &matches);
}
#[test]
fn many_longer_pattern_overlap_one_match_reverse() {
let ns = vec!["abc", "bc"];
let hay = "xbc";
let matches = vec![ Match { pati: 1, start: 1, end: 3 } ];
assert_eq!(&aut_findo(&ns, hay), &matches);
assert_eq!(&aut_findos(&ns, hay), &matches);
assert_eq!(&aut_findfo(&ns, hay), &matches);
assert_eq!(&aut_findfos(&ns, hay), &matches);
}
#[test]
fn many_longer_pattern_overlap_many_match() {
let ns = vec!["abc", "bc", "c"];
let hay = "zzzabczzzbczzzc";
let matches = vec![
Match { pati: 0, start: 3, end: 6 },
Match { pati: 1, start: 4, end: 6 },
Match { pati: 2, start: 5, end: 6 },
Match { pati: 1, start: 9, end: 11 },
Match { pati: 2, start: 10, end: 11 },
Match { pati: 2, start: 14, end: 15 },
];
assert_eq!(&aut_findo(&ns, hay), &matches);
assert_eq!(&aut_findos(&ns, hay), &matches);
assert_eq!(&aut_findfo(&ns, hay), &matches);
assert_eq!(&aut_findfos(&ns, hay), &matches);
}
#[test]
fn many_longer_pattern_overlap_many_match_reverse() {
let ns = vec!["abc", "bc", "c"];
let hay = "zzzczzzbczzzabc";
let matches = vec![
Match { pati: 2, start: 3, end: 4 },
Match { pati: 1, start: 7, end: 9 },
Match { pati: 2, start: 8, end: 9 },
Match { pati: 0, start: 12, end: 15 },
Match { pati: 1, start: 13, end: 15 },
Match { pati: 2, start: 14, end: 15 },
];
assert_eq!(&aut_findo(&ns, hay), &matches);
assert_eq!(&aut_findos(&ns, hay), &matches);
assert_eq!(&aut_findfo(&ns, hay), &matches);
assert_eq!(&aut_findfos(&ns, hay), &matches);
}
#[test]
fn pattern_returns_original_type() {
let aut = AcAutomaton::new(vec!["apple", "maple"]);
// Explicitly given this type to assert that the thing returned
// from the function is our original type.
let pat: &str = aut.pattern(0);
assert_eq!(pat, "apple");
// Also check the return type of the `patterns` function.
let pats: &[&str] = aut.patterns();
assert_eq!(pats, &["apple", "maple"]);
}
// Quickcheck time.
// This generates very small ascii strings, which makes them more likely
// to interact in interesting ways with larger haystack strings.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct SmallAscii(String);
impl Arbitrary for SmallAscii {
fn arbitrary<G: Gen>(g: &mut G) -> SmallAscii {
use std::char::from_u32;
SmallAscii((0..2)
.map(|_| from_u32(g.gen_range(97, 123)).unwrap())
.collect())
}
fn shrink(&self) -> Box<Iterator<Item=SmallAscii>> {
Box::new(self.0.shrink().map(SmallAscii))
}
}
impl From<SmallAscii> for String {
fn from(s: SmallAscii) -> String { s.0 }
}
impl AsRef<[u8]> for SmallAscii {
fn as_ref(&self) -> &[u8] { self.0.as_ref() }
}
// This is the same arbitrary impl as `String`, except it has a bias toward
// ASCII characters.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct BiasAscii(String);
impl Arbitrary for BiasAscii {
fn arbitrary<G: Gen>(g: &mut G) -> BiasAscii {
use std::char::from_u32;
let size = { let s = g.size(); g.gen_range(0, s) };
let mut s = String::with_capacity(size);
for _ in 0..size {
if g.gen_weighted_bool(3) {
s.push(char::arbitrary(g));
} else {
for _ in 0..5 {
s.push(from_u32(g.gen_range(97, 123)).unwrap());
}
}
}
BiasAscii(s)
}
fn shrink(&self) -> Box<Iterator<Item=BiasAscii>> {
Box::new(self.0.shrink().map(BiasAscii))
}
}
fn naive_find<S>(xs: &[S], haystack: &str) -> Vec<Match>
where S: Clone + Into<String> {
let needles: Vec<String> =
xs.to_vec().into_iter().map(Into::into).collect();
let mut matches = vec![];
for hi in 0..haystack.len() {
for (pati, needle) in needles.iter().enumerate() {
let needle = needle.as_bytes();
if needle.len() == 0 || needle.len() > haystack.len() - hi {
continue;
}
if needle == &haystack.as_bytes()[hi..hi+needle.len()] {
matches.push(Match {
pati: pati,
start: hi,
end: hi + needle.len(),
});
}
}
}
matches
}
#[test]
fn qc_ac_equals_naive() {
fn prop(needles: Vec<SmallAscii>, haystack: BiasAscii) -> bool {
let aut_matches = aut_findo(&needles, &haystack.0);
let naive_matches = naive_find(&needles, &haystack.0);
// Ordering isn't always the same. I don't think we care, so do
// an unordered comparison.
let aset: HashSet<Match> = aut_matches.iter().cloned().collect();
let nset: HashSet<Match> = naive_matches.iter().cloned().collect();
aset == nset
}
quickcheck(prop as fn(Vec<SmallAscii>, BiasAscii) -> bool);
}
}

Просмотреть файл

@ -1,13 +0,0 @@
extern crate memchr;
use std::env;
use lib::AcAutomaton;
#[allow(dead_code)]
mod lib;
fn main() {
let aut = AcAutomaton::new(env::args().skip(1));
println!("{}", aut.dot().trim());
}

Просмотреть файл

@ -1 +1 @@
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".travis.yml":"e17babe5ba0bdd19ec59a37b4a099fd4313bff58be63a2ff506075f9a97dc172","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"b3fa06c2147a4749cd984ded69024ddcc8b7d578ab763b60227b3ba474c3ec70","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","Makefile":"a45a128685a2ae7d4fa39d310786674417ee113055ef290a11f88002285865fc","README.md":"9bc60d2cec222b50f87c85cf9475349bb228a36f89796c5d6481c52560ddde3a","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"acf4844efadeafc7bc396c2b16f2a184e140b6c17d1084dbaf454196de2090cd","benches/random.txt":"9386fb3efedc7ffbd09fb49088347f1056bc2d90a861009fa2f804cdb714efcb","ctags.rust":"3d128d3cc59f702e68953ba2fe6c3f46bc6991fc575308db060482d5da0c79f3","examples/dict-search.rs":"30eb44b1a0b599507db4c23a90f74199faabc64a8ae1d603ecdf3bba7428eb1e","session.vim":"95cb1d7caf0ff7fbe76ec911988d908ddd883381c925ba64b537695bc9f021c4","src/autiter.rs":"98c31a7fbe21cfacaa858f90409f0d86edd46dda1b7651f4e800d929a50afb7b","src/full.rs":"b83a9c8ff3ef611c316b68650915df2d7f361a49b59dab103dc2c5476f2d8303","src/lib.rs":"68bf2ed02d58bebee6f7f7579038f1e4b60a2c4acc334263cb837bcbe15ffe94","src/main.rs":"fc867cb5f0b02d0f49ecab06b72c05a247cbcf3bf9228c235de8e787bda7bef5"},"package":"500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"}
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".travis.yml":"e17babe5ba0bdd19ec59a37b4a099fd4313bff58be63a2ff506075f9a97dc172","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"367c53caf576e1c811c77b5234f4d00ee23f5b1052d5e11bdc0c3153a8d9ae82","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","Makefile":"a45a128685a2ae7d4fa39d310786674417ee113055ef290a11f88002285865fc","README.md":"9bc60d2cec222b50f87c85cf9475349bb228a36f89796c5d6481c52560ddde3a","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"acf4844efadeafc7bc396c2b16f2a184e140b6c17d1084dbaf454196de2090cd","benches/random.txt":"9386fb3efedc7ffbd09fb49088347f1056bc2d90a861009fa2f804cdb714efcb","ctags.rust":"3d128d3cc59f702e68953ba2fe6c3f46bc6991fc575308db060482d5da0c79f3","examples/dict-search.rs":"30eb44b1a0b599507db4c23a90f74199faabc64a8ae1d603ecdf3bba7428eb1e","session.vim":"95cb1d7caf0ff7fbe76ec911988d908ddd883381c925ba64b537695bc9f021c4","src/autiter.rs":"dc8817af24825c356842c814d771868fb07b6965addf4780e8b9dea9718344a0","src/full.rs":"b83a9c8ff3ef611c316b68650915df2d7f361a49b59dab103dc2c5476f2d8303","src/lib.rs":"68bf2ed02d58bebee6f7f7579038f1e4b60a2c4acc334263cb837bcbe15ffe94","src/main.rs":"fc867cb5f0b02d0f49ecab06b72c05a247cbcf3bf9228c235de8e787bda7bef5"},"package":"0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2"}

2
third_party/rust/aho-corasick/Cargo.toml поставляемый
Просмотреть файл

@ -1,6 +1,6 @@
[package]
name = "aho-corasick"
version = "0.6.3" #:version
version = "0.6.2" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = "Fast multiple substring searching with finite state machines."
documentation = "http://burntsushi.net/rustdoc/aho_corasick/"

27
third_party/rust/aho-corasick/src/autiter.rs поставляемый
Просмотреть файл

@ -239,33 +239,6 @@ fn skip_to_match<P, A: Automaton<P> + ?Sized, F: Fn(&A, &[u8], usize) -> usize>(
texti = skip(aut, text, texti + 1);
} else {
texti += 1;
if texti + 4 < text.len() {
si = aut.next_state(si, text[texti]);
if aut.has_match(si, 0) {
return Some((texti, si));
}
texti += 1;
si = aut.next_state(si, text[texti]);
if aut.has_match(si, 0) {
return Some((texti, si));
}
texti += 1;
si = aut.next_state(si, text[texti]);
if aut.has_match(si, 0) {
return Some((texti, si));
}
texti += 1;
si = aut.next_state(si, text[texti]);
if aut.has_match(si, 0) {
return Some((texti, si));
}
texti += 1;
si = aut.next_state(si, text[texti]);
if aut.has_match(si, 0) {
return Some((texti, si));
}
texti += 1;
}
}
}
None

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

0
third_party/rust/bindgen-0.29.0/.cargo-ok поставляемый
Просмотреть файл

95
third_party/rust/bindgen-0.29.0/Cargo.toml поставляемый
Просмотреть файл

@ -1,95 +0,0 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g. crates.io) dependencies
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
[package]
name = "bindgen"
version = "0.29.0"
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"
exclude = ["bindgen-integration", "ci", "tests/**", "*.orig"]
description = "Automatically generates Rust FFI bindings to C and C++ libraries."
documentation = "https://docs.rs/bindgen"
readme = "README.md"
keywords = ["bindings", "ffi", "code-generation"]
categories = ["external-ffi-bindings", "development-tools::ffi"]
license = "BSD-3-Clause"
repository = "https://github.com/rust-lang-nursery/rust-bindgen"
[lib]
path = "src/lib.rs"
[[bin]]
name = "bindgen"
path = "src/main.rs"
doc = false
[dependencies.clap]
version = "2"
[dependencies.peeking_take_while]
version = "0.1.2"
[dependencies.cfg-if]
version = "0.1.0"
[dependencies.regex]
version = "0.2"
[dependencies.clang-sys]
version = "0.19.0"
features = ["runtime", "clang_3_9"]
[dependencies.lazy_static]
version = "0.2.1"
[dependencies.syntex_syntax]
version = "0.58"
[dependencies.aster]
version = "0.41"
features = ["with-syntex"]
[dependencies.log]
version = "0.3"
optional = true
[dependencies.quasi]
version = "0.32"
features = ["with-syntex"]
[dependencies.cexpr]
version = "0.2"
[dependencies.env_logger]
version = "0.4"
optional = true
[dev-dependencies.diff]
version = "0.1"
[dev-dependencies.clap]
version = "2"
[dev-dependencies.shlex]
version = "0.1"
[build-dependencies.quasi_codegen]
version = "0.32"
[features]
testing_only_extra_assertions = []
testing_only_libclang_4 = []
testing_only_docs = []
logging = ["env_logger", "log"]
default = ["logging"]
testing_only_libclang_3_8 = []
testing_only_libclang_3_9 = []
static = []
[badges.travis-ci]
repository = "rust-lang-nursery/rust-bindgen"

72
third_party/rust/bindgen-0.29.0/build.rs поставляемый
Просмотреть файл

@ -1,72 +0,0 @@
mod codegen {
extern crate quasi_codegen;
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
pub fn main() {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let src = Path::new("src/codegen/mod.rs");
let dst = Path::new(&out_dir).join("codegen.rs");
quasi_codegen::expand(&src, &dst).unwrap();
println!("cargo:rerun-if-changed=src/codegen/mod.rs");
println!("cargo:rerun-if-changed=src/codegen/error.rs");
println!("cargo:rerun-if-changed=src/codegen/helpers.rs");
println!("cargo:rerun-if-changed=src/codegen/struct_layout.rs");
let mut dst =
File::create(Path::new(&out_dir).join("host-target.txt")).unwrap();
dst.write_all(env::var("TARGET").unwrap().as_bytes()).unwrap();
}
}
mod testgen {
use std::char;
use std::env;
use std::ffi::OsStr;
use std::fs::{self, File};
use std::io::Write;
use std::path::{Path, PathBuf};
pub fn main() {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let mut dst = File::create(Path::new(&out_dir).join("tests.rs")).unwrap();
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let headers_dir = manifest_dir.join("tests").join("headers");
let headers = match fs::read_dir(headers_dir) {
Ok(dir) => dir,
// We may not have headers directory after packaging.
Err(..) => return,
};
let entries =
headers.map(|result| result.expect("Couldn't read header file"));
println!("cargo:rerun-if-changed=tests/headers");
for entry in entries {
match entry.path().extension().and_then(OsStr::to_str) {
Some("h") | Some("hpp") => {
let func = entry.file_name().to_str().unwrap()
.replace(|c| !char::is_alphanumeric(c), "_")
.replace("__", "_")
.to_lowercase();
writeln!(dst, "test_header!(header_{}, {:?});",
func, entry.path()).unwrap();
}
_ => {}
}
}
dst.flush().unwrap();
}
}
fn main() {
codegen::main();
testgen::main();
}

Просмотреть файл

@ -1,31 +0,0 @@
//! A public API for more fine-grained customization of bindgen behavior.
pub use ir::enum_ty::{EnumVariantCustomBehavior, EnumVariantValue};
pub use ir::int::IntKind;
use std::fmt;
use std::panic::UnwindSafe;
/// A trait to allow configuring different kinds of types in different
/// situations.
pub trait ParseCallbacks: fmt::Debug + UnwindSafe {
/// This function will be run on every macro that is identified
fn parsed_macro(&self, _name: &str) {}
/// The integer kind an integer macro should have, given a name and the
/// value of that macro, or `None` if you want the default to be chosen.
fn int_macro(&self, _name: &str, _value: i64) -> Option<IntKind> {
None
}
/// This function should return whether, given the a given enum variant
/// name, and value, returns whether this enum variant will forcibly be a
/// constant.
fn enum_variant_behavior(&self,
_enum_name: Option<&str>,
_variant_name: &str,
_variant_value: EnumVariantValue)
-> Option<EnumVariantCustomBehavior> {
None
}
}

1760
third_party/rust/bindgen-0.29.0/src/clang.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,41 +0,0 @@
use std::error;
use std::fmt;
/// Errors that can occur during code generation.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Error {
/// Tried to generate an opaque blob for a type that did not have a layout.
NoLayoutForOpaqueBlob,
/// Tried to instantiate an opaque template definition, or a template
/// definition that is too difficult for us to understand (like a partial
/// template specialization).
InstantiationOfOpaqueType,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", error::Error::description(self))
}
}
impl error::Error for Error {
fn cause(&self) -> Option<&error::Error> {
None
}
fn description(&self) -> &'static str {
match *self {
Error::NoLayoutForOpaqueBlob => {
"Tried to generate an opaque blob, but had no layout"
}
Error::InstantiationOfOpaqueType => {
"Instantiation of opaque template type or partial template \
specialization"
}
}
}
}
/// A `Result` of `T` or an error of `bindgen::codegen::error::Error`.
pub type Result<T> = ::std::result::Result<T, Error>;

Просмотреть файл

@ -1,215 +0,0 @@
//! Helpers for code generation that don't need macro expansion.
use aster;
use ir::layout::Layout;
use syntax::ast;
use syntax::ptr::P;
pub mod attributes {
use aster;
use syntax::ast;
pub fn allow(which_ones: &[&str]) -> ast::Attribute {
aster::AstBuilder::new().attr().list("allow").words(which_ones).build()
}
pub fn repr(which: &str) -> ast::Attribute {
aster::AstBuilder::new().attr().list("repr").words(&[which]).build()
}
pub fn repr_list(which_ones: &[&str]) -> ast::Attribute {
aster::AstBuilder::new().attr().list("repr").words(which_ones).build()
}
pub fn derives(which_ones: &[&str]) -> ast::Attribute {
aster::AstBuilder::new().attr().list("derive").words(which_ones).build()
}
pub fn inline() -> ast::Attribute {
aster::AstBuilder::new().attr().word("inline")
}
pub fn doc(comment: String) -> ast::Attribute {
aster::AstBuilder::new().attr().doc(&*comment)
}
pub fn link_name(name: &str) -> ast::Attribute {
aster::AstBuilder::new().attr().name_value("link_name").str(name)
}
}
/// Generates a proper type for a field or type with a given `Layout`, that is,
/// a type with the correct size and alignment restrictions.
pub struct BlobTyBuilder {
layout: Layout,
}
impl BlobTyBuilder {
pub fn new(layout: Layout) -> Self {
BlobTyBuilder {
layout: layout,
}
}
pub fn build(self) -> P<ast::Ty> {
let opaque = self.layout.opaque();
// FIXME(emilio, #412): We fall back to byte alignment, but there are
// some things that legitimately are more than 8-byte aligned.
//
// Eventually we should be able to `unwrap` here, but...
let ty_name = match opaque.known_rust_type_for_array() {
Some(ty) => ty,
None => {
warn!("Found unknown alignment on code generation!");
"u8"
}
};
let data_len = opaque.array_size().unwrap_or(self.layout.size);
let inner_ty = aster::AstBuilder::new().ty().path().id(ty_name).build();
if data_len == 1 {
inner_ty
} else {
aster::ty::TyBuilder::new().array(data_len).build(inner_ty)
}
}
}
pub mod ast_ty {
use aster;
use ir::context::BindgenContext;
use ir::function::FunctionSig;
use ir::ty::FloatKind;
use syntax::ast;
use syntax::ptr::P;
pub fn raw_type(ctx: &BindgenContext, name: &str) -> P<ast::Ty> {
let ident = ctx.rust_ident_raw(&name);
match ctx.options().ctypes_prefix {
Some(ref prefix) => {
let prefix = ctx.rust_ident_raw(prefix);
quote_ty!(ctx.ext_cx(), $prefix::$ident)
}
None => quote_ty!(ctx.ext_cx(), ::std::os::raw::$ident),
}
}
pub fn float_kind_rust_type(ctx: &BindgenContext,
fk: FloatKind)
-> P<ast::Ty> {
// TODO: we probably should just take the type layout into
// account?
//
// Also, maybe this one shouldn't be the default?
//
// FIXME: `c_longdouble` doesn't seem to be defined in some
// systems, so we use `c_double` directly.
match (fk, ctx.options().convert_floats) {
(FloatKind::Float, true) => aster::ty::TyBuilder::new().f32(),
(FloatKind::Double, true) |
(FloatKind::LongDouble, true) => aster::ty::TyBuilder::new().f64(),
(FloatKind::Float, false) => raw_type(ctx, "c_float"),
(FloatKind::Double, false) |
(FloatKind::LongDouble, false) => raw_type(ctx, "c_double"),
(FloatKind::Float128, _) => {
aster::ty::TyBuilder::new().array(16).u8()
}
}
}
pub fn int_expr(val: i64) -> P<ast::Expr> {
use std::i64;
let expr = aster::AstBuilder::new().expr();
// This is not representable as an i64 if it's negative, so we
// special-case it.
//
// Fix in aster incoming.
if val == i64::MIN {
expr.neg().uint(1u64 << 63)
} else {
expr.int(val)
}
}
pub fn bool_expr(val: bool) -> P<ast::Expr> {
aster::AstBuilder::new().expr().bool(val)
}
pub fn byte_array_expr(bytes: &[u8]) -> P<ast::Expr> {
let mut vec = Vec::with_capacity(bytes.len() + 1);
for byte in bytes {
vec.push(int_expr(*byte as i64));
}
vec.push(int_expr(0));
let kind = ast::ExprKind::Array(vec);
aster::AstBuilder::new().expr().build_expr_kind(kind)
}
pub fn cstr_expr(mut string: String) -> P<ast::Expr> {
string.push('\0');
aster::AstBuilder::new()
.expr()
.build_lit(aster::AstBuilder::new().lit().byte_str(string))
}
pub fn float_expr(ctx: &BindgenContext,
f: f64)
-> Result<P<ast::Expr>, ()> {
use aster::symbol::ToSymbol;
if f.is_finite() {
let mut string = f.to_string();
// So it gets properly recognised as a floating point constant.
if !string.contains('.') {
string.push('.');
}
let kind = ast::LitKind::FloatUnsuffixed(string.as_str().to_symbol());
return Ok(aster::AstBuilder::new().expr().lit().build_lit(kind))
}
let prefix = ctx.trait_prefix();
if f.is_nan() {
return Ok(quote_expr!(ctx.ext_cx(), ::$prefix::f64::NAN));
}
if f.is_infinite() {
return Ok(if f.is_sign_positive() {
quote_expr!(ctx.ext_cx(), ::$prefix::f64::INFINITY)
} else {
quote_expr!(ctx.ext_cx(), ::$prefix::f64::NEG_INFINITY)
});
}
warn!("Unknown non-finite float number: {:?}", f);
return Err(());
}
pub fn arguments_from_signature(signature: &FunctionSig,
ctx: &BindgenContext)
-> Vec<P<ast::Expr>> {
// TODO: We need to keep in sync the argument names, so we should unify
// this with the other loop that decides them.
let mut unnamed_arguments = 0;
signature.argument_types()
.iter()
.map(|&(ref name, _ty)| {
let arg_name = match *name {
Some(ref name) => ctx.rust_mangle(name).into_owned(),
None => {
unnamed_arguments += 1;
format!("arg{}", unnamed_arguments)
}
};
aster::expr::ExprBuilder::new().id(arg_name)
})
.collect::<Vec<_>>()
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,334 +0,0 @@
//! Helpers for code generation that need struct layout
use super::helpers::BlobTyBuilder;
use aster::struct_field::StructFieldBuilder;
use ir::comp::CompInfo;
use ir::context::BindgenContext;
use ir::layout::Layout;
use ir::ty::{Type, TypeKind};
use std::cmp;
use std::mem;
use syntax::ast;
/// Trace the layout of struct.
#[derive(Debug)]
pub struct StructLayoutTracker<'a, 'ctx: 'a> {
name: &'a str,
ctx: &'a BindgenContext<'ctx>,
comp: &'a CompInfo,
latest_offset: usize,
padding_count: usize,
latest_field_layout: Option<Layout>,
max_field_align: usize,
last_field_was_bitfield: bool,
}
/// Returns a size aligned to a given value.
pub fn align_to(size: usize, align: usize) -> usize {
if align == 0 {
return size;
}
let rem = size % align;
if rem == 0 {
return size;
}
size + align - rem
}
/// Returns the lower power of two byte count that can hold at most n bits.
pub fn bytes_from_bits_pow2(mut n: usize) -> usize {
if n == 0 {
return 0;
}
if n <= 8 {
return 1;
}
if !n.is_power_of_two() {
n = n.next_power_of_two();
}
n / 8
}
#[test]
fn test_align_to() {
assert_eq!(align_to(1, 1), 1);
assert_eq!(align_to(1, 2), 2);
assert_eq!(align_to(1, 4), 4);
assert_eq!(align_to(5, 1), 5);
assert_eq!(align_to(17, 4), 20);
}
#[test]
fn test_bytes_from_bits_pow2() {
assert_eq!(bytes_from_bits_pow2(0), 0);
for i in 1..9 {
assert_eq!(bytes_from_bits_pow2(i), 1);
}
for i in 9..17 {
assert_eq!(bytes_from_bits_pow2(i), 2);
}
for i in 17..33 {
assert_eq!(bytes_from_bits_pow2(i), 4);
}
}
impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> {
pub fn new(ctx: &'a BindgenContext<'ctx>, comp: &'a CompInfo, name: &'a str) -> Self {
StructLayoutTracker {
name: name,
ctx: ctx,
comp: comp,
latest_offset: 0,
padding_count: 0,
latest_field_layout: None,
max_field_align: 0,
last_field_was_bitfield: false,
}
}
pub fn saw_vtable(&mut self) {
debug!("saw vtable for {}", self.name);
let ptr_size = mem::size_of::<*mut ()>();
self.latest_offset += ptr_size;
self.latest_field_layout = Some(Layout::new(ptr_size, ptr_size));
self.max_field_align = ptr_size;
}
pub fn saw_base(&mut self, base_ty: &Type) {
debug!("saw base for {}", self.name);
if let Some(layout) = base_ty.layout(self.ctx) {
self.align_to_latest_field(layout);
self.latest_offset += self.padding_bytes(layout) + layout.size;
self.latest_field_layout = Some(layout);
self.max_field_align = cmp::max(self.max_field_align, layout.align);
}
}
pub fn saw_bitfield_unit(&mut self, layout: Layout) {
debug!("saw bitfield unit for {}: {:?}", self.name, layout);
self.align_to_latest_field(layout);
self.latest_offset += layout.size;
debug!("Offset: <bitfield>: {} -> {}",
self.latest_offset - layout.size,
self.latest_offset);
self.latest_field_layout = Some(layout);
self.last_field_was_bitfield = true;
// NB: We intentionally don't update the max_field_align here, since our
// bitfields code doesn't necessarily guarantee it, so we need to
// actually generate the dummy alignment.
}
pub fn saw_union(&mut self, layout: Layout) {
debug!("saw union for {}: {:?}", self.name, layout);
self.align_to_latest_field(layout);
self.latest_offset += self.padding_bytes(layout) + layout.size;
self.latest_field_layout = Some(layout);
self.max_field_align = cmp::max(self.max_field_align, layout.align);
}
/// Add a padding field if necessary for a given new field _before_ adding
/// that field.
pub fn pad_field(&mut self,
field_name: &str,
field_ty: &Type,
field_offset: Option<usize>)
-> Option<ast::StructField> {
let mut field_layout = match field_ty.layout(self.ctx) {
Some(l) => l,
None => return None,
};
if let TypeKind::Array(inner, len) =
*field_ty.canonical_type(self.ctx).kind() {
// FIXME(emilio): As an _ultra_ hack, we correct the layout returned
// by arrays of structs that have a bigger alignment than what we
// 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 ()>();
}
}
}
let will_merge_with_bitfield = self.align_to_latest_field(field_layout);
let padding_layout = if self.comp.packed() {
None
} else {
let padding_bytes = match field_offset {
Some(offset) if offset / 8 > self.latest_offset => {
offset / 8 - self.latest_offset
}
_ if will_merge_with_bitfield || field_layout.align == 0 => 0,
_ => self.padding_bytes(field_layout),
};
// Otherwise the padding is useless.
let need_padding = padding_bytes >= field_layout.align ||
field_layout.align > mem::size_of::<*mut ()>();
self.latest_offset += padding_bytes;
debug!("Offset: <padding>: {} -> {}",
self.latest_offset - padding_bytes,
self.latest_offset);
debug!("align field {} to {}/{} with {} padding bytes {:?}",
field_name,
self.latest_offset,
field_offset.unwrap_or(0) / 8,
padding_bytes,
field_layout);
if need_padding && padding_bytes != 0 {
Some(Layout::new(padding_bytes,
cmp::min(field_layout.align,
mem::size_of::<*mut ()>())))
} else {
None
}
};
self.latest_offset += field_layout.size;
self.latest_field_layout = Some(field_layout);
self.max_field_align = cmp::max(self.max_field_align,
field_layout.align);
self.last_field_was_bitfield = false;
debug!("Offset: {}: {} -> {}",
field_name,
self.latest_offset - field_layout.size,
self.latest_offset);
padding_layout.map(|layout| self.padding_field(layout))
}
pub fn pad_struct(&mut self, layout: Layout) -> Option<ast::StructField> {
debug!("pad_struct:\n\tself = {:#?}\n\tlayout = {:#?}", self, layout);
if layout.size < self.latest_offset {
error!("Calculated wrong layout for {}, too more {} bytes",
self.name,
self.latest_offset - layout.size);
return None;
}
let padding_bytes = layout.size - self.latest_offset;
// We always pad to get to the correct size if the struct is one of
// those we can't align properly.
//
// Note that if the last field we saw was a bitfield, we may need to pad
// regardless, because bitfields don't respect alignment as strictly as
// other fields.
if padding_bytes > 0 &&
(padding_bytes >= layout.align ||
(self.last_field_was_bitfield &&
padding_bytes >= self.latest_field_layout.unwrap().align) ||
layout.align > mem::size_of::<*mut ()>()) {
let layout = if self.comp.packed() {
Layout::new(padding_bytes, 1)
} else if self.last_field_was_bitfield ||
layout.align > mem::size_of::<*mut ()>() {
// We've already given up on alignment here.
Layout::for_size(padding_bytes)
} else {
Layout::new(padding_bytes, layout.align)
};
debug!("pad bytes to struct {}, {:?}", self.name, layout);
Some(self.padding_field(layout))
} else {
None
}
}
pub fn align_struct(&self, layout: Layout) -> Option<ast::StructField> {
if self.max_field_align < layout.align &&
layout.align <= mem::size_of::<*mut ()>() {
let ty = BlobTyBuilder::new(Layout::new(0, layout.align)).build();
Some(StructFieldBuilder::named("__bindgen_align")
.pub_()
.build_ty(ty))
} else {
None
}
}
fn padding_bytes(&self, layout: Layout) -> usize {
align_to(self.latest_offset, layout.align) - self.latest_offset
}
fn padding_field(&mut self, layout: Layout) -> ast::StructField {
let ty = BlobTyBuilder::new(layout).build();
let padding_count = self.padding_count;
self.padding_count += 1;
let padding_field_name = format!("__bindgen_padding_{}", padding_count);
self.max_field_align = cmp::max(self.max_field_align, layout.align);
StructFieldBuilder::named(padding_field_name).pub_().build_ty(ty)
}
/// Returns whether the new field is known to merge with a bitfield.
///
/// This is just to avoid doing the same check also in pad_field.
fn align_to_latest_field(&mut self, new_field_layout: Layout) -> bool {
if self.comp.packed() {
// Skip to align fields when packed.
return false;
}
let layout = match self.latest_field_layout {
Some(l) => l,
None => return false,
};
// If it was, we may or may not need to align, depending on what the
// current field alignment and the bitfield size and alignment are.
debug!("align_to_bitfield? {}: {:?} {:?}",
self.last_field_was_bitfield,
layout,
new_field_layout);
if self.last_field_was_bitfield &&
new_field_layout.align <= layout.size % layout.align &&
new_field_layout.size <= layout.size % layout.align {
// The new field will be coalesced into some of the remaining bits.
//
// FIXME(emilio): I think this may not catch everything?
debug!("Will merge with bitfield");
return true;
}
// Else, just align the obvious way.
self.latest_offset += self.padding_bytes(layout);
return false;
}
}

Просмотреть файл

@ -1,30 +0,0 @@
//! Macros for defining extra assertions that should only be checked in testing
//! and/or CI when the `testing_only_extra_assertions` feature is enabled.
#[macro_export]
macro_rules! extra_assert {
( $cond:expr ) => {
if cfg!(feature = "testing_only_extra_assertions") {
assert!($cond);
}
};
( $cond:expr , $( $arg:tt )+ ) => {
if cfg!(feature = "testing_only_extra_assertions") {
assert!($cond, $( $arg )* )
}
};
}
#[macro_export]
macro_rules! extra_assert_eq {
( $lhs:expr , $rhs:expr ) => {
if cfg!(feature = "testing_only_extra_assertions") {
assert_eq!($lhs, $rhs);
}
};
( $lhs:expr , $rhs:expr , $( $arg:tt )+ ) => {
if cfg!(feature = "testing_only_extra_assertions") {
assert!($lhs, $rhs, $( $arg )* );
}
};
}

Просмотреть файл

@ -1,322 +0,0 @@
//! Determining which types for which we can emit `#[derive(Debug)]`.
use super::{ConstrainResult, MonotoneFramework, generate_dependencies};
use std::collections::HashSet;
use std::collections::HashMap;
use ir::context::{BindgenContext, ItemId};
use ir::item::IsOpaque;
use ir::traversal::EdgeKind;
use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
use ir::ty::TypeKind;
use ir::comp::Field;
use ir::comp::FieldMethods;
use ir::derive::CanTriviallyDeriveDebug;
use ir::comp::CompKind;
/// An analysis that finds for each IR item whether debug cannot be derived.
///
/// We use the monotone constraint function `cannot_derive_debug`, defined as
/// follows:
///
/// * If T is Opaque and layout of the type is known, get this layout as opaque
/// type and check whether it can be derived using trivial checks.
/// * If T is Array type, debug cannot be derived if the length of the array is
/// larger than the limit or the type of data the array contains cannot derive
/// debug.
/// * If T is a type alias, a templated alias or an indirection to another type,
/// debug cannot be derived if the type T refers to cannot be derived debug.
/// * If T is a compound type, debug cannot be derived if any of its base member
/// or field cannot be derived debug.
/// * If T is a pointer, T cannot be derived debug if T is a function pointer
/// and the function signature cannot be derived debug.
/// * If T is an instantiation of an abstract template definition, T cannot be
/// derived debug if any of the template arguments or template definition
/// cannot derive debug.
#[derive(Debug, Clone)]
pub struct CannotDeriveDebug<'ctx, 'gen>
where 'gen: 'ctx
{
ctx: &'ctx BindgenContext<'gen>,
// The incremental result of this analysis's computation. Everything in this
// set cannot derive debug.
cannot_derive_debug: HashSet<ItemId>,
// Dependencies saying that if a key ItemId has been inserted into the
// `cannot_derive_debug` set, then each of the ids in Vec<ItemId> need to be
// considered again.
//
// This is a subset of the natural IR graph with reversed edges, where we
// only include the edges from the IR graph that can affect whether a type
// can derive debug or not.
dependencies: HashMap<ItemId, Vec<ItemId>>,
}
impl<'ctx, 'gen> CannotDeriveDebug<'ctx, 'gen> {
fn consider_edge(kind: EdgeKind) -> bool {
match kind {
// These are the only edges that can affect whether a type can derive
// debug or not.
EdgeKind::BaseMember |
EdgeKind::Field |
EdgeKind::TypeReference |
EdgeKind::VarType |
EdgeKind::TemplateArgument |
EdgeKind::TemplateDeclaration |
EdgeKind::TemplateParameterDefinition => true,
EdgeKind::Constructor |
EdgeKind::Destructor |
EdgeKind::FunctionReturn |
EdgeKind::FunctionParameter |
EdgeKind::InnerType |
EdgeKind::InnerVar |
EdgeKind::Method => false,
EdgeKind::Generic => false,
}
}
fn insert(&mut self, id: ItemId) -> ConstrainResult {
trace!("inserting {:?} into the cannot_derive_debug set", id);
let was_not_already_in_set = self.cannot_derive_debug.insert(id);
assert!(
was_not_already_in_set,
"We shouldn't try and insert {:?} twice because if it was \
already in the set, `constrain` should have exited early.",
id
);
ConstrainResult::Changed
}
}
impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> {
type Node = ItemId;
type Extra = &'ctx BindgenContext<'gen>;
type Output = HashSet<ItemId>;
fn new(ctx: &'ctx BindgenContext<'gen>) -> CannotDeriveDebug<'ctx, 'gen> {
let cannot_derive_debug = HashSet::new();
let dependencies = generate_dependencies(ctx, Self::consider_edge);
CannotDeriveDebug {
ctx,
cannot_derive_debug,
dependencies,
}
}
fn initial_worklist(&self) -> Vec<ItemId> {
self.ctx.whitelisted_items().iter().cloned().collect()
}
fn constrain(&mut self, id: ItemId) -> ConstrainResult {
trace!("constrain: {:?}", id);
if self.cannot_derive_debug.contains(&id) {
trace!(" already know it cannot derive Debug");
return ConstrainResult::Same;
}
let item = self.ctx.resolve_item(id);
let ty = match item.as_type() {
Some(ty) => ty,
None => {
trace!(" not a type; ignoring");
return ConstrainResult::Same;
}
};
if ty.is_opaque(self.ctx, item) {
let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
l.opaque().can_trivially_derive_debug(self.ctx, ())
});
return if layout_can_derive {
trace!(" we can trivially derive Debug for the layout");
ConstrainResult::Same
} else {
trace!(" we cannot derive Debug for the layout");
self.insert(id)
};
}
if ty.layout(self.ctx).map_or(false, |l| l.align > RUST_DERIVE_IN_ARRAY_LIMIT) {
// We have to be conservative: the struct *could* have enough
// padding that we emit an array that is longer than
// `RUST_DERIVE_IN_ARRAY_LIMIT`. If we moved padding calculations
// into the IR and computed them before this analysis, then we could
// be precise rather than conservative here.
return self.insert(id);
}
match *ty.kind() {
// Handle the simple cases. These can derive debug without further
// information.
TypeKind::Void |
TypeKind::NullPtr |
TypeKind::Int(..) |
TypeKind::Float(..) |
TypeKind::Complex(..) |
TypeKind::Function(..) |
TypeKind::Enum(..) |
TypeKind::Reference(..) |
TypeKind::BlockPointer |
TypeKind::Named |
TypeKind::UnresolvedTypeRef(..) |
TypeKind::ObjCInterface(..) |
TypeKind::ObjCId |
TypeKind::ObjCSel => {
trace!(" simple type that can always derive Debug");
ConstrainResult::Same
}
TypeKind::Array(t, len) => {
if self.cannot_derive_debug.contains(&t) {
trace!(" arrays of T for which we cannot derive Debug \
also cannot derive Debug");
return self.insert(id);
}
if len <= RUST_DERIVE_IN_ARRAY_LIMIT {
trace!(" array is small enough to derive Debug");
ConstrainResult::Same
} else {
trace!(" array is too large to derive Debug");
self.insert(id)
}
}
TypeKind::ResolvedTypeRef(t) |
TypeKind::TemplateAlias(t, _) |
TypeKind::Alias(t) => {
if self.cannot_derive_debug.contains(&t) {
trace!(" aliases and type refs to T which cannot derive \
Debug also cannot derive Debug");
self.insert(id)
} else {
trace!(" aliases and type refs to T which can derive \
Debug can also derive Debug");
ConstrainResult::Same
}
}
TypeKind::Comp(ref info) => {
assert!(
!info.has_non_type_template_params(),
"The early ty.is_opaque check should have handled this case"
);
if info.kind() == CompKind::Union {
if self.ctx.options().unstable_rust {
trace!(" cannot derive Debug for Rust unions");
return self.insert(id);
}
if ty.layout(self.ctx)
.map_or(true,
|l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
trace!(" union layout can trivially derive Debug");
return ConstrainResult::Same;
} else {
trace!(" union layout cannot derive Debug");
return self.insert(id);
}
}
let bases_cannot_derive = info.base_members()
.iter()
.any(|base| self.cannot_derive_debug.contains(&base.ty));
if bases_cannot_derive {
trace!(" base members cannot derive Debug, so we can't \
either");
return self.insert(id);
}
let fields_cannot_derive = info.fields()
.iter()
.any(|f| {
match *f {
Field::DataMember(ref data) => {
self.cannot_derive_debug.contains(&data.ty())
}
Field::Bitfields(ref bfu) => {
bfu.bitfields()
.iter().any(|b| {
self.cannot_derive_debug.contains(&b.ty())
})
}
}
});
if fields_cannot_derive {
trace!(" fields cannot derive Debug, so we can't either");
return self.insert(id);
}
trace!(" comp can derive Debug");
ConstrainResult::Same
}
TypeKind::Pointer(inner) => {
let inner_type = self.ctx.resolve_type(inner).canonical_type(self.ctx);
if let TypeKind::Function(ref sig) = *inner_type.kind() {
if !sig.can_trivially_derive_debug(&self.ctx, ()) {
trace!(" function pointer that can't trivially derive Debug");
return self.insert(id);
}
}
trace!(" pointers can derive Debug");
ConstrainResult::Same
}
TypeKind::TemplateInstantiation(ref template) => {
let args_cannot_derive = template.template_arguments()
.iter()
.any(|arg| self.cannot_derive_debug.contains(&arg));
if args_cannot_derive {
trace!(" template args cannot derive Debug, so \
insantiation can't either");
return self.insert(id);
}
assert!(
!template.template_definition().is_opaque(self.ctx, &()),
"The early ty.is_opaque check should have handled this case"
);
let def_cannot_derive = self.cannot_derive_debug
.contains(&template.template_definition());
if def_cannot_derive {
trace!(" template definition cannot derive Debug, so \
insantiation can't either");
return self.insert(id);
}
trace!(" template instantiation can derive Debug");
ConstrainResult::Same
}
TypeKind::Opaque => {
unreachable!(
"The early ty.is_opaque check should have handled this case"
)
}
}
}
fn each_depending_on<F>(&self, id: ItemId, mut f: F)
where F: FnMut(ItemId),
{
if let Some(edges) = self.dependencies.get(&id) {
for item in edges {
trace!("enqueue {:?} into worklist", item);
f(*item);
}
}
}
}
impl<'ctx, 'gen> From<CannotDeriveDebug<'ctx, 'gen>> for HashSet<ItemId> {
fn from(analysis: CannotDeriveDebug<'ctx, 'gen>) -> Self {
analysis.cannot_derive_debug
}
}

Просмотреть файл

@ -1,162 +0,0 @@
//! Determining which types has vtable
use super::{ConstrainResult, MonotoneFramework, generate_dependencies};
use std::collections::HashSet;
use std::collections::HashMap;
use ir::context::{BindgenContext, ItemId};
use ir::traversal::EdgeKind;
use ir::ty::TypeKind;
/// An analysis that finds for each IR item whether it has vtable or not
///
/// We use the monotone function `has vtable`, defined as follows:
///
/// * If T is a type alias, a templated alias, an indirection to another type,
/// or a reference of a type, T has vtable if the type T refers to has vtable.
/// * If T is a compound type, T has vtable if we saw a virtual function when
/// parsing it or any of its base member has vtable.
/// * If T is an instantiation of an abstract template definition, T has
/// vtable if template definition has vtable
#[derive(Debug, Clone)]
pub struct HasVtableAnalysis<'ctx, 'gen>
where 'gen: 'ctx
{
ctx: &'ctx BindgenContext<'gen>,
// The incremental result of this analysis's computation. Everything in this
// set definitely has a vtable.
have_vtable: HashSet<ItemId>,
// Dependencies saying that if a key ItemId has been inserted into the
// `have_vtable` set, then each of the ids in Vec<ItemId> need to be
// considered again.
//
// This is a subset of the natural IR graph with reversed edges, where we
// only include the edges from the IR graph that can affect whether a type
// has a vtable or not.
dependencies: HashMap<ItemId, Vec<ItemId>>,
}
impl<'ctx, 'gen> HasVtableAnalysis<'ctx, 'gen> {
fn consider_edge(kind: EdgeKind) -> bool {
match kind {
// These are the only edges that can affect whether a type has a
// vtable or not.
EdgeKind::TypeReference |
EdgeKind::BaseMember |
EdgeKind::TemplateDeclaration => true,
_ => false,
}
}
fn insert(&mut self, id: ItemId) -> ConstrainResult {
let was_not_already_in_set = self.have_vtable.insert(id);
assert!(
was_not_already_in_set,
"We shouldn't try and insert {:?} twice because if it was \
already in the set, `constrain` should have exited early.",
id
);
ConstrainResult::Changed
}
}
impl<'ctx, 'gen> MonotoneFramework for HasVtableAnalysis<'ctx, 'gen> {
type Node = ItemId;
type Extra = &'ctx BindgenContext<'gen>;
type Output = HashSet<ItemId>;
fn new(ctx: &'ctx BindgenContext<'gen>) -> HasVtableAnalysis<'ctx, 'gen> {
let have_vtable = HashSet::new();
let dependencies = generate_dependencies(ctx, Self::consider_edge);
HasVtableAnalysis {
ctx,
have_vtable,
dependencies,
}
}
fn initial_worklist(&self) -> Vec<ItemId> {
self.ctx.whitelisted_items().iter().cloned().collect()
}
fn constrain(&mut self, id: ItemId) -> ConstrainResult {
if self.have_vtable.contains(&id) {
// We've already computed that this type has a vtable and that can't
// change.
return ConstrainResult::Same;
}
let item = self.ctx.resolve_item(id);
let ty = match item.as_type() {
None => return ConstrainResult::Same,
Some(ty) => ty
};
// TODO #851: figure out a way to handle deriving from template type parameters.
match *ty.kind() {
TypeKind::TemplateAlias(t, _) |
TypeKind::Alias(t) |
TypeKind::ResolvedTypeRef(t) |
TypeKind::Reference(t) => {
if self.have_vtable.contains(&t) {
self.insert(id)
} else {
ConstrainResult::Same
}
},
TypeKind::Comp(ref info) => {
if info.has_own_virtual_method() {
return self.insert(id);
}
let bases_has_vtable = info.base_members().iter().any(|base| {
self.have_vtable.contains(&base.ty)
});
if bases_has_vtable {
self.insert(id)
} else {
ConstrainResult::Same
}
},
TypeKind::TemplateInstantiation(ref inst) => {
if self.have_vtable.contains(&inst.template_definition()) {
self.insert(id)
} else {
ConstrainResult::Same
}
},
_ => ConstrainResult::Same,
}
}
fn each_depending_on<F>(&self, id: ItemId, mut f: F)
where F: FnMut(ItemId),
{
if let Some(edges) = self.dependencies.get(&id) {
for item in edges {
trace!("enqueue {:?} into worklist", item);
f(*item);
}
}
}
}
impl<'ctx, 'gen> From<HasVtableAnalysis<'ctx, 'gen>> for HashSet<ItemId> {
fn from(analysis: HasVtableAnalysis<'ctx, 'gen>) -> Self {
analysis.have_vtable
}
}
/// A convenience trait for the things for which we might wonder if they have a
/// vtable during codegen.
///
/// This is not for _computing_ whether the thing has a vtable, it is for
/// looking up the results of the HasVtableAnalysis's computations for a
/// specific thing.
pub trait HasVtable {
/// Return `true` if this thing has vtable, `false` otherwise.
fn has_vtable(&self, ctx: &BindgenContext) -> bool;
}

Просмотреть файл

@ -1,345 +0,0 @@
//! Fix-point analyses on the IR using the "monotone framework".
//!
//! A lattice is a set with a partial ordering between elements, where there is
//! a single least upper bound and a single greatest least bound for every
//! subset. We are dealing with finite lattices, which means that it has a
//! finite number of elements, and it follows that there exists a single top and
//! a single bottom member of the lattice. For example, the power set of a
//! finite set forms a finite lattice where partial ordering is defined by set
//! inclusion, that is `a <= b` if `a` is a subset of `b`. Here is the finite
//! lattice constructed from the set {0,1,2}:
//!
//! ```text
//! .----- Top = {0,1,2} -----.
//! / | \
//! / | \
//! / | \
//! {0,1} -------. {0,2} .--------- {1,2}
//! | \ / \ / |
//! | / \ |
//! | / \ / \ |
//! {0} --------' {1} `---------- {2}
//! \ | /
//! \ | /
//! \ | /
//! `------ Bottom = {} ------'
//! ```
//!
//! A monotone function `f` is a function where if `x <= y`, then it holds that
//! `f(x) <= f(y)`. It should be clear that running a monotone function to a
//! fix-point on a finite lattice will always terminate: `f` can only "move"
//! along the lattice in a single direction, and therefore can only either find
//! a fix-point in the middle of the lattice or continue to the top or bottom
//! depending if it is ascending or descending the lattice respectively.
//!
//! For a deeper introduction to the general form of this kind of analysis, see
//! [Static Program Analysis by Anders Møller and Michael I. Schwartzbach][spa].
//!
//! [spa]: https://cs.au.dk/~amoeller/spa/spa.pdf
// Re-export individual analyses.
mod template_params;
pub use self::template_params::UsedTemplateParameters;
mod derive_debug;
pub use self::derive_debug::CannotDeriveDebug;
mod has_vtable;
pub use self::has_vtable::HasVtableAnalysis;
pub use self::has_vtable::HasVtable;
use ir::context::{BindgenContext, ItemId};
use ir::traversal::{EdgeKind, Trace};
use std::collections::HashMap;
use std::fmt;
/// An analysis in the monotone framework.
///
/// Implementors of this trait must maintain the following two invariants:
///
/// 1. The concrete data must be a member of a finite-height lattice.
/// 2. The concrete `constrain` method must be monotone: that is,
/// if `x <= y`, then `constrain(x) <= constrain(y)`.
///
/// If these invariants do not hold, iteration to a fix-point might never
/// complete.
///
/// For a simple example analysis, see the `ReachableFrom` type in the `tests`
/// module below.
pub trait MonotoneFramework: Sized + fmt::Debug {
/// The type of node in our dependency graph.
///
/// This is just generic (and not `ItemId`) so that we can easily unit test
/// without constructing real `Item`s and their `ItemId`s.
type Node: Copy;
/// Any extra data that is needed during computation.
///
/// Again, this is just generic (and not `&BindgenContext`) so that we can
/// easily unit test without constructing real `BindgenContext`s full of
/// real `Item`s and real `ItemId`s.
type Extra: Sized;
/// The final output of this analysis. Once we have reached a fix-point, we
/// convert `self` into this type, and return it as the final result of the
/// analysis.
type Output: From<Self> + fmt::Debug;
/// Construct a new instance of this analysis.
fn new(extra: Self::Extra) -> Self;
/// Get the initial set of nodes from which to start the analysis. Unless
/// you are sure of some domain-specific knowledge, this should be the
/// complete set of nodes.
fn initial_worklist(&self) -> Vec<Self::Node>;
/// Update the analysis for the given node.
///
/// If this results in changing our internal state (ie, we discovered that
/// we have not reached a fix-point and iteration should continue), return
/// `ConstrainResult::Changed`. Otherwise, return `ConstrainResult::Same`.
/// When `constrain` returns `ConstrainResult::Same` for all nodes in the
/// set, we have reached a fix-point and the analysis is complete.
fn constrain(&mut self, node: Self::Node) -> ConstrainResult;
/// For each node `d` that depends on the given `node`'s current answer when
/// running `constrain(d)`, call `f(d)`. This informs us which new nodes to
/// queue up in the worklist when `constrain(node)` reports updated
/// information.
fn each_depending_on<F>(&self, node: Self::Node, f: F)
where F: FnMut(Self::Node);
}
/// Whether an analysis's `constrain` function modified the incremental results
/// or not.
pub enum ConstrainResult {
/// The incremental results were updated, and the fix-point computation
/// should continue.
Changed,
/// The incremental results were not updated.
Same,
}
/// Run an analysis in the monotone framework.
pub fn analyze<Analysis>(extra: Analysis::Extra) -> Analysis::Output
where Analysis: MonotoneFramework,
{
let mut analysis = Analysis::new(extra);
let mut worklist = analysis.initial_worklist();
while let Some(node) = worklist.pop() {
if let ConstrainResult::Changed = analysis.constrain(node) {
analysis.each_depending_on(node, |needs_work| {
worklist.push(needs_work);
});
}
}
analysis.into()
}
/// Generate the dependency map for analysis
pub fn generate_dependencies<F>(ctx: &BindgenContext, consider_edge: F) -> HashMap<ItemId, Vec<ItemId>>
where F: Fn(EdgeKind) -> bool {
let mut dependencies = HashMap::new();
for &item in ctx.whitelisted_items() {
dependencies.entry(item).or_insert(vec![]);
{
// We reverse our natural IR graph edges to find dependencies
// between nodes.
item.trace(ctx, &mut |sub_item: ItemId, edge_kind| {
if ctx.whitelisted_items().contains(&sub_item) &&
consider_edge(edge_kind) {
dependencies.entry(sub_item)
.or_insert(vec![])
.push(item);
}
}, &());
}
}
dependencies
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::{HashMap, HashSet};
// Here we find the set of nodes that are reachable from any given
// node. This is a lattice mapping nodes to subsets of all nodes. Our join
// function is set union.
//
// This is our test graph:
//
// +---+ +---+
// | | | |
// | 1 | .----| 2 |
// | | | | |
// +---+ | +---+
// | | ^
// | | |
// | +---+ '------'
// '----->| |
// | 3 |
// .------| |------.
// | +---+ |
// | ^ |
// v | v
// +---+ | +---+ +---+
// | | | | | | |
// | 4 | | | 5 |--->| 6 |
// | | | | | | |
// +---+ | +---+ +---+
// | | | |
// | | | v
// | +---+ | +---+
// | | | | | |
// '----->| 7 |<-----' | 8 |
// | | | |
// +---+ +---+
//
// And here is the mapping from a node to the set of nodes that are
// reachable from it within the test graph:
//
// 1: {3,4,5,6,7,8}
// 2: {2}
// 3: {3,4,5,6,7,8}
// 4: {3,4,5,6,7,8}
// 5: {3,4,5,6,7,8}
// 6: {8}
// 7: {3,4,5,6,7,8}
// 8: {}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
struct Node(usize);
#[derive(Clone, Debug, Default, PartialEq, Eq)]
struct Graph(HashMap<Node, Vec<Node>>);
impl Graph {
fn make_test_graph() -> Graph {
let mut g = Graph::default();
g.0.insert(Node(1), vec![Node(3)]);
g.0.insert(Node(2), vec![Node(2)]);
g.0.insert(Node(3), vec![Node(4), Node(5)]);
g.0.insert(Node(4), vec![Node(7)]);
g.0.insert(Node(5), vec![Node(6), Node(7)]);
g.0.insert(Node(6), vec![Node(8)]);
g.0.insert(Node(7), vec![Node(3)]);
g.0.insert(Node(8), vec![]);
g
}
fn reverse(&self) -> Graph {
let mut reversed = Graph::default();
for (node, edges) in self.0.iter() {
reversed.0.entry(*node).or_insert(vec![]);
for referent in edges.iter() {
reversed.0.entry(*referent).or_insert(vec![]).push(*node);
}
}
reversed
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
struct ReachableFrom<'a> {
reachable: HashMap<Node, HashSet<Node>>,
graph: &'a Graph,
reversed: Graph,
}
impl<'a> MonotoneFramework for ReachableFrom<'a> {
type Node = Node;
type Extra = &'a Graph;
type Output = HashMap<Node, HashSet<Node>>;
fn new(graph: &'a Graph) -> ReachableFrom {
let reversed = graph.reverse();
ReachableFrom {
reachable: Default::default(),
graph: graph,
reversed: reversed,
}
}
fn initial_worklist(&self) -> Vec<Node> {
self.graph.0.keys().cloned().collect()
}
fn constrain(&mut self, node: Node) -> ConstrainResult {
// The set of nodes reachable from a node `x` is
//
// reachable(x) = s_0 U s_1 U ... U reachable(s_0) U reachable(s_1) U ...
//
// where there exist edges from `x` to each of `s_0, s_1, ...`.
//
// Yes, what follows is a **terribly** inefficient set union
// implementation. Don't copy this code outside of this test!
let original_size =
self.reachable.entry(node).or_insert(HashSet::new()).len();
for sub_node in self.graph.0[&node].iter() {
self.reachable.get_mut(&node).unwrap().insert(*sub_node);
let sub_reachable = self.reachable
.entry(*sub_node)
.or_insert(HashSet::new())
.clone();
for transitive in sub_reachable {
self.reachable.get_mut(&node).unwrap().insert(transitive);
}
}
let new_size = self.reachable[&node].len();
if original_size != new_size {
ConstrainResult::Changed
} else {
ConstrainResult::Same
}
}
fn each_depending_on<F>(&self, node: Node, mut f: F)
where F: FnMut(Node),
{
for dep in self.reversed.0[&node].iter() {
f(*dep);
}
}
}
impl<'a> From<ReachableFrom<'a>> for HashMap<Node, HashSet<Node>> {
fn from(reachable: ReachableFrom<'a>) -> Self {
reachable.reachable
}
}
#[test]
fn monotone() {
let g = Graph::make_test_graph();
let reachable = analyze::<ReachableFrom>(&g);
println!("reachable = {:#?}", reachable);
fn nodes<A>(nodes: A) -> HashSet<Node>
where A: AsRef<[usize]>,
{
nodes.as_ref().iter().cloned().map(Node).collect()
}
let mut expected = HashMap::new();
expected.insert(Node(1), nodes([3, 4, 5, 6, 7, 8]));
expected.insert(Node(2), nodes([2]));
expected.insert(Node(3), nodes([3, 4, 5, 6, 7, 8]));
expected.insert(Node(4), nodes([3, 4, 5, 6, 7, 8]));
expected.insert(Node(5), nodes([3, 4, 5, 6, 7, 8]));
expected.insert(Node(6), nodes([8]));
expected.insert(Node(7), nodes([3, 4, 5, 6, 7, 8]));
expected.insert(Node(8), nodes([]));
println!("expected = {:#?}", expected);
assert_eq!(reachable, expected);
}
}

Просмотреть файл

@ -1,550 +0,0 @@
//! Discover which template type parameters are actually used.
//!
//! ### Why do we care?
//!
//! C++ allows ignoring template parameters, while Rust does not. Usually we can
//! blindly stick a `PhantomData<T>` inside a generic Rust struct to make up for
//! this. That doesn't work for templated type aliases, however:
//!
//! ```C++
//! template <typename T>
//! using Fml = int;
//! ```
//!
//! If we generate the naive Rust code for this alias, we get:
//!
//! ```ignore
//! pub type Fml<T> = ::std::os::raw::int;
//! ```
//!
//! And this is rejected by `rustc` due to the unused type parameter.
//!
//! (Aside: in these simple cases, `libclang` will often just give us the
//! aliased type directly, and we will never even know we were dealing with
//! aliases, let alone templated aliases. It's the more convoluted scenarios
//! where we get to have some fun...)
//!
//! For such problematic template aliases, we could generate a tuple whose
//! second member is a `PhantomData<T>`. Or, if we wanted to go the extra mile,
//! we could even generate some smarter wrapper that implements `Deref`,
//! `DerefMut`, `From`, `Into`, `AsRef`, and `AsMut` to the actually aliased
//! type. However, this is still lackluster:
//!
//! 1. Even with a billion conversion-trait implementations, using the generated
//! bindings is rather un-ergonomic.
//! 2. With either of these solutions, we need to keep track of which aliases
//! we've transformed like this in order to generate correct uses of the
//! wrapped type.
//!
//! Given that we have to properly track which template parameters ended up used
//! for (2), we might as well leverage that information to make ergonomic
//! bindings that don't contain any unused type parameters at all, and
//! completely avoid the pain of (1).
//!
//! ### How do we determine which template parameters are used?
//!
//! Determining which template parameters are actually used is a trickier
//! problem than it might seem at a glance. On the one hand, trivial uses are
//! easy to detect:
//!
//! ```C++
//! template <typename T>
//! class Foo {
//! T trivial_use_of_t;
//! };
//! ```
//!
//! It gets harder when determining if one template parameter is used depends on
//! determining if another template parameter is used. In this example, whether
//! `U` is used depends on whether `T` is used.
//!
//! ```C++
//! template <typename T>
//! class DoesntUseT {
//! int x;
//! };
//!
//! template <typename U>
//! class Fml {
//! DoesntUseT<U> lololol;
//! };
//! ```
//!
//! We can express the set of used template parameters as a constraint solving
//! problem (where the set of template parameters used by a given IR item is the
//! union of its sub-item's used template parameters) and iterate to a
//! fixed-point.
//!
//! We use the `ir::analysis::MonotoneFramework` infrastructure for this
//! fix-point analysis, where our lattice is the mapping from each IR item to
//! the powerset of the template parameters that appear in the input C++ header,
//! our join function is set union. The set of template parameters appearing in
//! the program is finite, as is the number of IR items. We start at our
//! lattice's bottom element: every item mapping to an empty set of template
//! parameters. Our analysis only adds members to each item's set of used
//! template parameters, never removes them, so it is monotone. Because our
//! lattice is finite and our constraint function is monotone, iteration to a
//! fix-point will terminate.
//!
//! See `src/ir/analysis.rs` for more.
use super::{ConstrainResult, MonotoneFramework};
use ir::context::{BindgenContext, ItemId};
use ir::item::{Item, ItemSet};
use ir::template::{TemplateInstantiation, TemplateParameters};
use ir::traversal::{EdgeKind, Trace};
use ir::ty::TypeKind;
use std::collections::{HashMap, HashSet};
/// An analysis that finds for each IR item its set of template parameters that
/// it uses.
///
/// We use the monotone constraint function `template_param_usage`, defined as
/// follows:
///
/// * If `T` is a named template type parameter, it trivially uses itself:
///
/// ```ignore
/// template_param_usage(T) = { T }
/// ```
///
/// * If `inst` is a template instantiation, `inst.args` are the template
/// instantiation's template arguments, `inst.def` is the template definition
/// being instantiated, and `inst.def.params` is the template definition's
/// template parameters, then the instantiation's usage is the union of each
/// of its arguments' usages *if* the corresponding template parameter is in
/// turn used by the template definition:
///
/// ```ignore
/// template_param_usage(inst) = union(
/// template_param_usage(inst.args[i])
/// for i in 0..length(inst.args.length)
/// if inst.def.params[i] in template_param_usage(inst.def)
/// )
/// ```
///
/// * Finally, for all other IR item kinds, we use our lattice's `join`
/// operation: set union with each successor of the given item's template
/// parameter usage:
///
/// ```ignore
/// template_param_usage(v) =
/// union(template_param_usage(w) for w in successors(v))
/// ```
///
/// Note that we ignore certain edges in the graph, such as edges from a
/// template declaration to its template parameters' definitions for this
/// analysis. If we didn't, then we would mistakenly determine that ever
/// template parameter is always used.
///
/// The final wrinkle is handling of blacklisted types. Normally, we say that
/// the set of whitelisted items is the transitive closure of items explicitly
/// called out for whitelisting, *without* any items explicitly called out as
/// blacklisted. However, for the purposes of this analysis's correctness, we
/// simplify and consider run the analysis on the full transitive closure of
/// whitelisted items. We do, however, treat instantiations of blacklisted items
/// specially; see `constrain_instantiation_of_blacklisted_template` and its
/// documentation for details.
#[derive(Debug, Clone)]
pub struct UsedTemplateParameters<'ctx, 'gen>
where 'gen: 'ctx,
{
ctx: &'ctx BindgenContext<'gen>,
// The Option is only there for temporary moves out of the hash map. See the
// comments in `UsedTemplateParameters::constrain` below.
used: HashMap<ItemId, Option<ItemSet>>,
dependencies: HashMap<ItemId, Vec<ItemId>>,
// The set of whitelisted items, without any blacklisted items reachable
// from the whitelisted items which would otherwise be considered
// whitelisted as well.
whitelisted_items: HashSet<ItemId>,
}
impl<'ctx, 'gen> UsedTemplateParameters<'ctx, 'gen> {
fn consider_edge(kind: EdgeKind) -> bool {
match kind {
// For each of these kinds of edges, if the referent uses a template
// parameter, then it should be considered that the origin of the
// edge also uses the template parameter.
EdgeKind::TemplateArgument |
EdgeKind::BaseMember |
EdgeKind::Field |
EdgeKind::Constructor |
EdgeKind::Destructor |
EdgeKind::VarType |
EdgeKind::FunctionReturn |
EdgeKind::FunctionParameter |
EdgeKind::TypeReference => true,
// An inner var or type using a template parameter is orthogonal
// from whether we use it. See template-param-usage-{6,11}.hpp.
EdgeKind::InnerVar | EdgeKind::InnerType => false,
// We can't emit machine code for new monomorphizations of class
// templates' methods (and don't detect explicit instantiations) so
// we must ignore template parameters that are only used by
// methods. This doesn't apply to a function type's return or
// parameter types, however, because of type aliases of function
// pointers that use template parameters, eg
// tests/headers/struct_with_typedef_template_arg.hpp
EdgeKind::Method => false,
// If we considered these edges, we would end up mistakenly claiming
// that every template parameter always used.
EdgeKind::TemplateDeclaration |
EdgeKind::TemplateParameterDefinition => false,
// Since we have to be careful about which edges we consider for
// this analysis to be correct, we ignore generic edges. We also
// avoid a `_` wild card to force authors of new edge kinds to
// determine whether they need to be considered by this analysis.
EdgeKind::Generic => false,
}
}
fn take_this_id_usage_set(&mut self, this_id: ItemId) -> ItemSet {
self.used
.get_mut(&this_id)
.expect("Should have a set of used template params for every item \
id")
.take()
.expect("Should maintain the invariant that all used template param \
sets are `Some` upon entry of `constrain`")
}
/// We say that blacklisted items use all of their template parameters. The
/// blacklisted type is most likely implemented explicitly by the user,
/// since it won't be in the generated bindings, and we don't know exactly
/// what they'll to with template parameters, but we can push the issue down
/// the line to them.
fn constrain_instantiation_of_blacklisted_template(&self,
this_id: ItemId,
used_by_this_id: &mut ItemSet,
instantiation: &TemplateInstantiation) {
trace!(" instantiation of blacklisted template, uses all template \
arguments");
let args = instantiation.template_arguments()
.into_iter()
.map(|a| {
a.into_resolver()
.through_type_refs()
.through_type_aliases()
.resolve(self.ctx)
.id()
})
.filter(|a| *a != this_id)
.flat_map(|a| {
self.used.get(&a)
.expect("Should have a used entry for the template arg")
.as_ref()
.expect("Because a != this_id, and all used template \
param sets other than this_id's are `Some`, \
a's used template param set should be `Some`")
.iter()
.cloned()
});
used_by_this_id.extend(args);
}
/// A template instantiation's concrete template argument is only used if
/// the template definition uses the corresponding template parameter.
fn constrain_instantiation(&self,
this_id: ItemId,
used_by_this_id: &mut ItemSet,
instantiation: &TemplateInstantiation) {
trace!(" template instantiation");
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![]);
debug_assert!(this_id != instantiation.template_definition());
let used_by_def = self.used
.get(&instantiation.template_definition())
.expect("Should have a used entry for instantiation's template definition")
.as_ref()
.expect("And it should be Some because only this_id's set is None, and an \
instantiation's template definition should never be the \
instantiation itself");
for (arg, param) in args.iter().zip(params.iter()) {
trace!(" instantiation's argument {:?} is used if definition's \
parameter {:?} is used",
arg,
param);
if used_by_def.contains(param) {
trace!(" param is used by template definition");
let arg = arg.into_resolver()
.through_type_refs()
.through_type_aliases()
.resolve(self.ctx)
.id();
if arg == this_id {
continue;
}
let used_by_arg = self.used
.get(&arg)
.expect("Should have a used entry for the template arg")
.as_ref()
.expect("Because arg != this_id, and all used template \
param sets other than this_id's are `Some`, \
arg's used template param set should be \
`Some`")
.iter()
.cloned();
used_by_this_id.extend(used_by_arg);
}
}
}
/// The join operation on our lattice: the set union of all of this id's
/// successors.
fn constrain_join(&self, used_by_this_id: &mut ItemSet, item: &Item) {
trace!(" other item: join with successors' usage");
item.trace(self.ctx, &mut |sub_id, edge_kind| {
// Ignore ourselves, since union with ourself is a
// no-op. Ignore edges that aren't relevant to the
// analysis.
if sub_id == item.id() || !Self::consider_edge(edge_kind) {
return;
}
let used_by_sub_id = self.used
.get(&sub_id)
.expect("Should have a used set for the sub_id successor")
.as_ref()
.expect("Because sub_id != id, and all used template \
param sets other than id's are `Some`, \
sub_id's used template param set should be \
`Some`")
.iter()
.cloned();
trace!(" union with {:?}'s usage: {:?}",
sub_id,
used_by_sub_id.clone().collect::<Vec<_>>());
used_by_this_id.extend(used_by_sub_id);
}, &());
}
}
impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> {
type Node = ItemId;
type Extra = &'ctx BindgenContext<'gen>;
type Output = HashMap<ItemId, ItemSet>;
fn new(ctx: &'ctx BindgenContext<'gen>)
-> UsedTemplateParameters<'ctx, 'gen> {
let mut used = HashMap::new();
let mut dependencies = HashMap::new();
let whitelisted_items: HashSet<_> = ctx.whitelisted_items()
.iter()
.cloned()
.collect();
let whitelisted_and_blacklisted_items: ItemSet = whitelisted_items.iter()
.cloned()
.flat_map(|i| {
let mut reachable = vec![i];
i.trace(ctx, &mut |s, _| {
reachable.push(s);
}, &());
reachable
})
.collect();
for item in whitelisted_and_blacklisted_items {
dependencies.entry(item).or_insert(vec![]);
used.entry(item).or_insert(Some(ItemSet::new()));
{
// We reverse our natural IR graph edges to find dependencies
// between nodes.
item.trace(ctx, &mut |sub_item: ItemId, _| {
used.entry(sub_item).or_insert(Some(ItemSet::new()));
dependencies.entry(sub_item)
.or_insert(vec![])
.push(item);
}, &());
}
// Additionally, whether a template instantiation's template
// arguments are used depends on whether the template declaration's
// generic template parameters are used.
ctx.resolve_item(item)
.as_type()
.map(|ty| match ty.kind() {
&TypeKind::TemplateInstantiation(ref inst) => {
let decl = ctx.resolve_type(inst.template_definition());
let args = inst.template_arguments();
// Although template definitions should always have
// template parameters, there is a single exception:
// opaque templates. Hence the unwrap_or.
let params = decl.self_template_params(ctx)
.unwrap_or(vec![]);
for (arg, param) in args.iter().zip(params.iter()) {
let arg = arg.into_resolver()
.through_type_aliases()
.through_type_refs()
.resolve(ctx)
.id();
let param = param.into_resolver()
.through_type_aliases()
.through_type_refs()
.resolve(ctx)
.id();
used.entry(arg).or_insert(Some(ItemSet::new()));
used.entry(param).or_insert(Some(ItemSet::new()));
dependencies.entry(arg)
.or_insert(vec![])
.push(param);
}
}
_ => {}
});
}
if cfg!(feature = "testing_only_extra_assertions") {
// Invariant: The `used` map has an entry for every whitelisted
// item, as well as all explicitly blacklisted items that are
// reachable from whitelisted items.
//
// Invariant: the `dependencies` map has an entry for every
// whitelisted item.
//
// (This is so that every item we call `constrain` on is guaranteed
// to have a set of template parameters, and we can allow
// blacklisted templates to use all of their parameters).
for item in whitelisted_items.iter() {
extra_assert!(used.contains_key(item));
extra_assert!(dependencies.contains_key(item));
item.trace(ctx, &mut |sub_item, _| {
extra_assert!(used.contains_key(&sub_item));
extra_assert!(dependencies.contains_key(&sub_item));
}, &())
}
}
UsedTemplateParameters {
ctx: ctx,
used: used,
dependencies: dependencies,
whitelisted_items: whitelisted_items,
}
}
fn initial_worklist(&self) -> Vec<ItemId> {
// The transitive closure of all whitelisted items, including explicitly
// blacklisted items.
self.ctx
.whitelisted_items()
.iter()
.cloned()
.flat_map(|i| {
let mut reachable = vec![i];
i.trace(self.ctx, &mut |s, _| {
reachable.push(s);
}, &());
reachable
})
.collect()
}
fn constrain(&mut self, id: ItemId) -> ConstrainResult {
// Invariant: all hash map entries' values are `Some` upon entering and
// exiting this method.
extra_assert!(self.used.values().all(|v| v.is_some()));
// Take the set for this id out of the hash map while we mutate it based
// on other hash map entries. We *must* put it back into the hash map at
// the end of this method. This allows us to side-step HashMap's lack of
// an analog to slice::split_at_mut.
let mut used_by_this_id = self.take_this_id_usage_set(id);
trace!("constrain {:?}", id);
trace!(" initially, used set is {:?}", used_by_this_id);
let original_len = used_by_this_id.len();
let item = self.ctx.resolve_item(id);
let ty_kind = item.as_type().map(|ty| ty.kind());
match ty_kind {
// Named template type parameters trivially use themselves.
Some(&TypeKind::Named) => {
trace!(" named type, trivially uses itself");
used_by_this_id.insert(id);
}
// Template instantiations only use their template arguments if the
// template definition uses the corresponding template parameter.
Some(&TypeKind::TemplateInstantiation(ref inst)) => {
if self.whitelisted_items.contains(&inst.template_definition()) {
self.constrain_instantiation(id, &mut used_by_this_id, inst);
} else {
self.constrain_instantiation_of_blacklisted_template(id,
&mut used_by_this_id,
inst);
}
}
// Otherwise, add the union of each of its referent item's template
// parameter usage.
_ => self.constrain_join(&mut used_by_this_id, item),
}
trace!(" finally, used set is {:?}", used_by_this_id);
let new_len = used_by_this_id.len();
assert!(new_len >= original_len,
"This is the property that ensures this function is monotone -- \
if it doesn't hold, the analysis might never terminate!");
// Put the set back in the hash map and restore our invariant.
debug_assert!(self.used[&id].is_none());
self.used.insert(id, Some(used_by_this_id));
extra_assert!(self.used.values().all(|v| v.is_some()));
if new_len != original_len {
ConstrainResult::Changed
} else {
ConstrainResult::Same
}
}
fn each_depending_on<F>(&self, item: ItemId, mut f: F)
where F: FnMut(ItemId),
{
if let Some(edges) = self.dependencies.get(&item) {
for item in edges {
trace!("enqueue {:?} into worklist", item);
f(*item);
}
}
}
}
impl<'ctx, 'gen> From<UsedTemplateParameters<'ctx, 'gen>>
for HashMap<ItemId, ItemSet> {
fn from(used_templ_params: UsedTemplateParameters<'ctx, 'gen>) -> Self {
used_templ_params.used
.into_iter()
.map(|(k, v)| (k, v.unwrap()))
.collect()
}
}

Просмотреть файл

@ -1,188 +0,0 @@
//! Types and functions related to bindgen annotation comments.
//!
//! Users can add annotations in doc comments to types that they would like to
//! replace other types with, mark as opaque, etc. This module deals with all of
//! that stuff.
use clang;
/// What kind of accessor should we provide for a field?
#[derive(Copy, PartialEq, Clone, Debug)]
pub enum FieldAccessorKind {
/// No accessor.
None,
/// Plain accessor.
Regular,
/// Unsafe accessor.
Unsafe,
/// Immutable accessor.
Immutable,
}
/// Annotations for a given item, or a field.
///
/// You can see the kind of comments that are accepted in the Doxygen
/// documentation:
///
/// http://www.stack.nl/~dimitri/doxygen/manual/docblocks.html
#[derive(Clone, PartialEq, Debug)]
pub struct Annotations {
/// Whether this item is marked as opaque. Only applies to types.
opaque: bool,
/// Whether this item should be hidden from the output. Only applies to
/// types, or enum variants.
hide: bool,
/// Whether this type should be replaced by another. The name is a
/// namespace-aware path.
use_instead_of: Option<Vec<String>>,
/// Manually disable deriving copy/clone on this type. Only applies to
/// struct or union types.
disallow_copy: bool,
/// Whether fields should be marked as private or not. You can set this on
/// structs (it will apply to all the fields), or individual fields.
private_fields: Option<bool>,
/// The kind of accessor this field will have. Also can be applied to
/// structs so all the fields inside share it by default.
accessor_kind: Option<FieldAccessorKind>,
/// Whether this enum variant should be constified.
///
/// This is controlled by the `constant` attribute, this way:
///
/// ```cpp
/// enum Foo {
/// Bar = 0, /**< <div rustbindgen constant></div> */
/// Baz = 0,
/// };
/// ```
///
/// In that case, bindgen will generate a constant for `Bar` instead of
/// `Baz`.
constify_enum_variant: bool,
}
fn parse_accessor(s: &str) -> FieldAccessorKind {
match s {
"false" => FieldAccessorKind::None,
"unsafe" => FieldAccessorKind::Unsafe,
"immutable" => FieldAccessorKind::Immutable,
_ => FieldAccessorKind::Regular,
}
}
impl Default for Annotations {
fn default() -> Self {
Annotations {
opaque: false,
hide: false,
use_instead_of: None,
disallow_copy: false,
private_fields: None,
accessor_kind: None,
constify_enum_variant: false,
}
}
}
impl Annotations {
/// Construct new annotations for the given cursor and its bindgen comments
/// (if any).
pub fn new(cursor: &clang::Cursor) -> Option<Annotations> {
let mut anno = Annotations::default();
let mut matched_one = false;
anno.parse(&cursor.comment(), &mut matched_one);
if matched_one { Some(anno) } else { None }
}
/// Should this type be hidden?
pub fn hide(&self) -> bool {
self.hide
}
/// Should this type be opaque?
pub fn opaque(&self) -> bool {
self.opaque
}
/// For a given type, indicates the type it should replace.
///
/// For example, in the following code:
///
/// ```cpp
///
/// /** <div rustbindgen replaces="Bar"></div> */
/// struct Foo { int x; };
///
/// struct Bar { char foo; };
/// ```
///
/// the generated code would look something like:
///
/// ```
/// /** <div rustbindgen replaces="Bar"></div> */
/// struct Bar {
/// x: ::std::os::raw::c_int,
/// };
/// ```
///
/// That is, code for `Foo` is used to generate `Bar`.
pub fn use_instead_of(&self) -> Option<&[String]> {
self.use_instead_of.as_ref().map(|s| &**s)
}
/// Should we avoid implementing the `Copy` trait?
pub fn disallow_copy(&self) -> bool {
self.disallow_copy
}
/// Should the fields be private?
pub fn private_fields(&self) -> Option<bool> {
self.private_fields
}
/// What kind of accessors should we provide for this type's fields?
pub fn accessor_kind(&self) -> Option<FieldAccessorKind> {
self.accessor_kind
}
fn parse(&mut self, comment: &clang::Comment, matched: &mut bool) {
use clang_sys::CXComment_HTMLStartTag;
if comment.kind() == CXComment_HTMLStartTag &&
comment.get_tag_name() == "div" &&
comment.get_tag_attrs()
.next()
.map_or(false, |attr| attr.name == "rustbindgen") {
*matched = true;
for attr in comment.get_tag_attrs() {
match attr.name.as_str() {
"opaque" => self.opaque = true,
"hide" => self.hide = true,
"nocopy" => self.disallow_copy = true,
"replaces" => {
self.use_instead_of = Some(attr.value
.split("::")
.map(Into::into)
.collect())
}
"private" => {
self.private_fields = Some(attr.value != "false")
}
"accessor" => {
self.accessor_kind = Some(parse_accessor(&attr.value))
}
"constant" => self.constify_enum_variant = true,
_ => {}
}
}
}
for child in comment.get_children() {
self.parse(&child, matched);
}
}
/// Returns whether we've parsed a "constant" attribute.
pub fn constify_enum_variant(&self) -> bool {
self.constify_enum_variant
}
}

Просмотреть файл

@ -1,118 +0,0 @@
//! Utilities for manipulating C/C++ comments.
use std::iter;
/// The type of a comment.
#[derive(Debug, PartialEq, Eq)]
enum Kind {
/// A `///` comment, or something of the like.
/// All lines in a comment should start with the same symbol.
SingleLines,
/// A `/**` comment, where each other line can start with `*` and the
/// entire block ends with `*/`.
MultiLine,
}
/// Preprocesses a C/C++ comment so that it is a valid Rust comment.
pub fn preprocess(comment: &str, indent: usize) -> String {
match self::kind(&comment) {
Some(Kind::SingleLines) => preprocess_single_lines(comment, indent),
Some(Kind::MultiLine) => preprocess_multi_line(comment, indent),
None => comment.to_owned(),
}
}
/// Gets the kind of the doc comment, if it is one.
fn kind(comment: &str) -> Option<Kind> {
if comment.starts_with("/*") {
Some(Kind::MultiLine)
} else if comment.starts_with("//") {
Some(Kind::SingleLines)
} else {
None
}
}
fn make_indent(indent: usize) -> String {
const RUST_INDENTATION: usize = 4;
iter::repeat(' ').take(indent * RUST_INDENTATION).collect()
}
/// Preprocesses mulitple single line comments.
///
/// Handles lines starting with both `//` and `///`.
fn preprocess_single_lines(comment: &str, indent: usize) -> String {
debug_assert!(comment.starts_with("//"), "comment is not single line");
let indent = make_indent(indent);
let mut is_first = true;
let lines: Vec<_> = comment.lines()
.map(|l| l.trim_left_matches('/').trim())
.map(|l| {
let indent = if is_first { "" } else { &*indent };
is_first = false;
let maybe_space = if l.is_empty() { "" } else { " " };
format!("{}///{}{}", indent, maybe_space, l)
})
.collect();
lines.join("\n")
}
fn preprocess_multi_line(comment: &str, indent: usize) -> String {
let comment = comment.trim_left_matches('/')
.trim_left_matches('*')
.trim_left_matches('!')
.trim_right_matches('/')
.trim_right_matches('*')
.trim();
let indent = make_indent(indent);
// Strip any potential `*` characters preceding each line.
let mut is_first = true;
let mut lines: Vec<_> = comment.lines()
.map(|line| line.trim().trim_left_matches('*').trim())
.skip_while(|line| line.is_empty()) // Skip the first empty lines.
.map(|line| {
let indent = if is_first { "" } else { &*indent };
is_first = false;
let maybe_space = if line.is_empty() { "" } else { " " };
format!("{}///{}{}", indent, maybe_space, line)
})
.collect();
// Remove the trailing line corresponding to the `*/`.
let last_line_is_empty = lines.last().map_or(false, |l| l.is_empty());
if last_line_is_empty {
lines.pop();
}
lines.join("\n")
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn picks_up_single_and_multi_line_doc_comments() {
assert_eq!(kind("/// hello"), Some(Kind::SingleLines));
assert_eq!(kind("/** world */"), Some(Kind::MultiLine));
}
#[test]
fn processes_single_lines_correctly() {
assert_eq!(preprocess("/// hello", 0), "/// hello");
assert_eq!(preprocess("// hello", 0), "/// hello");
}
#[test]
fn processes_multi_lines_correctly() {
assert_eq!(preprocess("/** hello \n * world \n * foo \n */", 0),
"/// hello\n/// world\n/// foo");
assert_eq!(preprocess("/**\nhello\n*world\n*foo\n*/", 0),
"/// hello\n/// world\n/// foo");
}
}

1562
third_party/rust/bindgen-0.29.0/src/ir/comp.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,97 +0,0 @@
//! Traits for determining whether we can derive traits for a thing or not.
use super::context::BindgenContext;
/// A trait that encapsulates the logic for whether or not we can derive `Debug`
/// for a given thing.
///
/// This should ideally be a no-op that just returns `true`, but instead needs
/// to be a recursive method that checks whether all the proper members can
/// derive debug or not, because of the limit rust has on 32 items as max in the
/// array.
pub trait CanDeriveDebug {
/// Return `true` if `Debug` can be derived for this thing, `false`
/// otherwise.
fn can_derive_debug(&self, ctx: &BindgenContext) -> bool;
}
/// A trait that encapsulates the logic for whether or not we can derive `Debug`.
/// The difference between this trait and the CanDeriveDebug is that the type
/// implementing this trait cannot use recursion or lookup result from fix point
/// analysis. It's a helper trait for fix point analysis.
pub trait CanTriviallyDeriveDebug {
/// Serve the same purpose as the Extra in CanDeriveDebug.
type Extra;
/// Return `true` if `Debug` can be derived for this thing, `false`
/// otherwise.
fn can_trivially_derive_debug(&self,
ctx: &BindgenContext,
extra: Self::Extra)
-> bool;
}
/// A trait that encapsulates the logic for whether or not we can derive `Copy`
/// for a given thing.
pub trait CanDeriveCopy<'a> {
/// Implementations can define this type to get access to any extra
/// information required to determine whether they can derive `Copy`. If
/// extra information is unneeded, then this should simply be the unit type.
type Extra;
/// Return `true` if `Copy` can be derived for this thing, `false`
/// otherwise.
fn can_derive_copy(&'a self,
ctx: &'a BindgenContext,
extra: Self::Extra)
-> bool;
/// For some reason, deriving copies of an array of a type that is not known
/// to be `Copy` is a compile error. e.g.:
///
/// ```rust
/// #[derive(Copy, Clone)]
/// struct A<T> {
/// member: T,
/// }
/// ```
///
/// is fine, while:
///
/// ```rust,ignore
/// #[derive(Copy, Clone)]
/// struct A<T> {
/// member: [T; 1],
/// }
/// ```
///
/// is an error.
///
/// That's the whole point of the existence of `can_derive_copy_in_array`.
fn can_derive_copy_in_array(&'a self,
ctx: &'a BindgenContext,
extra: Self::Extra)
-> bool;
}
/// A trait that encapsulates the logic for whether or not we can derive `Default`
/// for a given thing.
///
/// This should ideally be a no-op that just returns `true`, but instead needs
/// to be a recursive method that checks whether all the proper members can
/// derive default or not, because of the limit rust has on 32 items as max in the
/// array.
pub trait CanDeriveDefault<'a> {
/// Implementations can define this type to get access to any extra
/// information required to determine whether they can derive `Default`. If
/// extra information is unneeded, then this should simply be the unit type.
type Extra;
/// Return `true` if `Default` can be derived for this thing, `false`
/// otherwise.
fn can_derive_default(&self,
ctx: &BindgenContext,
extra: Self::Extra)
-> bool;
}

71
third_party/rust/bindgen-0.29.0/src/ir/dot.rs поставляемый
Просмотреть файл

@ -1,71 +0,0 @@
//! Generating Graphviz `dot` files from our IR.
use super::context::{BindgenContext, ItemId};
use super::traversal::Trace;
use std::fs::File;
use std::io::{self, Write};
use std::path::Path;
/// A trait for anything that can write attributes as `<table>` rows to a dot
/// file.
pub trait DotAttributes {
/// Write this thing's attributes to the given output. Each attribute must
/// be its own `<tr>...</tr>`.
fn dot_attributes<W>(&self,
ctx: &BindgenContext,
out: &mut W)
-> io::Result<()>
where W: io::Write;
}
/// Write a graphviz dot file containing our IR.
pub fn write_dot_file<P>(ctx: &BindgenContext, path: P) -> io::Result<()>
where P: AsRef<Path>,
{
let file = try!(File::create(path));
let mut dot_file = io::BufWriter::new(file);
try!(writeln!(&mut dot_file, "digraph {{"));
let mut err: Option<io::Result<_>> = None;
for (id, item) in ctx.items() {
try!(writeln!(&mut dot_file,
r#"{} [fontname="courier", label=< <table border="0" align="left">"#,
id.as_usize()));
try!(item.dot_attributes(ctx, &mut dot_file));
try!(writeln!(&mut dot_file, r#"</table> >];"#));
item.trace(ctx,
&mut |sub_id: ItemId, edge_kind| {
if err.is_some() {
return;
}
match writeln!(&mut dot_file,
"{} -> {} [label={:?}];",
id.as_usize(),
sub_id.as_usize(),
edge_kind) {
Ok(_) => {}
Err(e) => err = Some(Err(e)),
}
},
&());
if let Some(err) = err {
return err;
}
if let Some(module) = item.as_module() {
for child in module.children() {
try!(writeln!(&mut dot_file,
"{} -> {} [style=dotted]",
item.id().as_usize(),
child.as_usize()));
}
}
}
try!(writeln!(&mut dot_file, "}}"));
Ok(())
}

Просмотреть файл

@ -1,205 +0,0 @@
//! Intermediate representation for C/C++ enumerations.
use super::context::{BindgenContext, ItemId};
use super::item::Item;
use super::ty::TypeKind;
use clang;
use ir::annotations::Annotations;
use ir::item::ItemCanonicalName;
use parse::{ClangItemParser, ParseError};
/// An enum representing custom handling that can be given to a variant.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum EnumVariantCustomBehavior {
/// This variant will be a module containing constants.
ModuleConstify,
/// This variant will be constified, that is, forced to generate a constant.
Constify,
/// This variant will be hidden entirely from the resulting enum.
Hide,
}
/// A C/C++ enumeration.
#[derive(Debug)]
pub struct Enum {
/// The representation used for this enum; it should be an `IntKind` type or
/// an alias to one.
///
/// It's `None` if the enum is a forward declaration and isn't defined
/// anywhere else, see `tests/headers/func_ptr_in_struct.h`.
repr: Option<ItemId>,
/// The different variants, with explicit values.
variants: Vec<EnumVariant>,
}
impl Enum {
/// Construct a new `Enum` with the given representation and variants.
pub fn new(repr: Option<ItemId>, variants: Vec<EnumVariant>) -> Self {
Enum {
repr: repr,
variants: variants,
}
}
/// Get this enumeration's representation.
pub fn repr(&self) -> Option<ItemId> {
self.repr
}
/// Get this enumeration's variants.
pub fn variants(&self) -> &[EnumVariant] {
&self.variants
}
/// Construct an enumeration from the given Clang type.
pub fn from_ty(ty: &clang::Type,
ctx: &mut BindgenContext)
-> Result<Self, ParseError> {
use clang_sys::*;
debug!("Enum::from_ty {:?}", ty);
if ty.kind() != CXType_Enum {
return Err(ParseError::Continue);
}
let declaration = ty.declaration().canonical();
let repr = declaration.enum_type()
.and_then(|et| Item::from_ty(&et, declaration, None, ctx).ok());
let mut variants = vec![];
// Assume signedness since the default type by the C standard is an int.
let is_signed =
repr.and_then(|r| ctx.resolve_type(r).safe_canonical_type(ctx))
.map_or(true, |ty| match *ty.kind() {
TypeKind::Int(ref int_kind) => int_kind.is_signed(),
ref other => {
panic!("Since when enums can be non-integers? {:?}",
other)
}
});
let type_name = ty.spelling();
let type_name = if type_name.is_empty() {
None
} else {
Some(type_name)
};
let type_name = type_name.as_ref().map(String::as_str);
let definition = declaration.definition().unwrap_or(declaration);
definition.visit(|cursor| {
if cursor.kind() == CXCursor_EnumConstantDecl {
let value = if is_signed {
cursor.enum_val_signed().map(EnumVariantValue::Signed)
} else {
cursor.enum_val_unsigned().map(EnumVariantValue::Unsigned)
};
if let Some(val) = value {
let name = cursor.spelling();
let custom_behavior = ctx.parse_callbacks()
.and_then(|t| {
t.enum_variant_behavior(type_name, &name, val)
})
.or_else(|| {
Annotations::new(&cursor)
.and_then(|anno| if anno.hide() {
Some(EnumVariantCustomBehavior::Hide)
} else if
anno.constify_enum_variant() {
Some(EnumVariantCustomBehavior::Constify)
} else {
None
})
});
let comment = cursor.raw_comment();
variants.push(EnumVariant::new(name,
comment,
val,
custom_behavior));
}
}
CXChildVisit_Continue
});
Ok(Enum::new(repr, variants))
}
/// Whether the enum should be an constified enum module
pub fn is_constified_enum_module(&self, ctx: &BindgenContext, item: &Item) -> bool {
let name = item.canonical_name(ctx);
let enum_ty = item.expect_type();
ctx.options().constified_enum_modules.matches(&name) ||
(enum_ty.name().is_none() &&
self.variants()
.iter()
.any(|v| ctx.options().constified_enum_modules.matches(&v.name())))
}
}
/// A single enum variant, to be contained only in an enum.
#[derive(Debug)]
pub struct EnumVariant {
/// The name of the variant.
name: String,
/// An optional doc comment.
comment: Option<String>,
/// The integer value of the variant.
val: EnumVariantValue,
/// The custom behavior this variant may have, if any.
custom_behavior: Option<EnumVariantCustomBehavior>,
}
/// A constant value assigned to an enumeration variant.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum EnumVariantValue {
/// A signed constant.
Signed(i64),
/// An unsigned constant.
Unsigned(u64),
}
impl EnumVariant {
/// Construct a new enumeration variant from the given parts.
pub fn new(name: String,
comment: Option<String>,
val: EnumVariantValue,
custom_behavior: Option<EnumVariantCustomBehavior>)
-> Self {
EnumVariant {
name: name,
comment: comment,
val: val,
custom_behavior: custom_behavior,
}
}
/// Get this variant's name.
pub fn name(&self) -> &str {
&self.name
}
/// Get this variant's value.
pub fn val(&self) -> EnumVariantValue {
self.val
}
/// Returns whether this variant should be enforced to be a constant by code
/// generation.
pub fn force_constification(&self) -> bool {
self.custom_behavior
.map_or(false, |b| b == EnumVariantCustomBehavior::Constify)
}
/// Returns whether the current variant should be hidden completely from the
/// resulting rust enum.
pub fn hidden(&self) -> bool {
self.custom_behavior
.map_or(false, |b| b == EnumVariantCustomBehavior::Hide)
}
}

Просмотреть файл

@ -1,497 +0,0 @@
//! Intermediate representation for C/C++ functions and methods.
use super::comp::MethodKind;
use super::context::{BindgenContext, ItemId};
use super::dot::DotAttributes;
use super::item::Item;
use super::traversal::{EdgeKind, Trace, Tracer};
use super::ty::TypeKind;
use clang;
use clang_sys::{self, CXCallingConv};
use ir::derive::CanTriviallyDeriveDebug;
use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
use std::io;
use syntax::abi;
/// What kind of a function are we looking at?
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum FunctionKind {
/// A plain, free function.
Function,
/// A method of some kind.
Method(MethodKind),
}
impl FunctionKind {
fn from_cursor(cursor: &clang::Cursor) -> Option<FunctionKind> {
Some(match cursor.kind() {
clang_sys::CXCursor_FunctionDecl => FunctionKind::Function,
clang_sys::CXCursor_Constructor => FunctionKind::Method(MethodKind::Constructor),
clang_sys::CXCursor_Destructor => FunctionKind::Method(MethodKind::Destructor),
clang_sys::CXCursor_CXXMethod => {
if cursor.method_is_virtual() {
FunctionKind::Method(MethodKind::Virtual)
} else if cursor.method_is_static() {
FunctionKind::Method(MethodKind::Static)
} else {
FunctionKind::Method(MethodKind::Normal)
}
}
_ => return None,
})
}
}
/// A function declaration, with a signature, arguments, and argument names.
///
/// The argument names vector must be the same length as the ones in the
/// signature.
#[derive(Debug)]
pub struct Function {
/// The name of this function.
name: String,
/// The mangled name, that is, the symbol.
mangled_name: Option<String>,
/// The id pointing to the current function signature.
signature: ItemId,
/// The doc comment on the function, if any.
comment: Option<String>,
/// The kind of function this is.
kind: FunctionKind,
}
impl Function {
/// Construct a new function.
pub fn new(name: String,
mangled_name: Option<String>,
sig: ItemId,
comment: Option<String>,
kind: FunctionKind)
-> Self {
Function {
name: name,
mangled_name: mangled_name,
signature: sig,
comment: comment,
kind: kind,
}
}
/// Get this function's name.
pub fn name(&self) -> &str {
&self.name
}
/// Get this function's name.
pub fn mangled_name(&self) -> Option<&str> {
self.mangled_name.as_ref().map(|n| &**n)
}
/// Get this function's signature.
pub fn signature(&self) -> ItemId {
self.signature
}
/// Get this function's kind.
pub fn kind(&self) -> FunctionKind {
self.kind
}
}
impl DotAttributes for Function {
fn dot_attributes<W>(&self,
_ctx: &BindgenContext,
out: &mut W)
-> io::Result<()>
where W: io::Write,
{
if let Some(ref mangled) = self.mangled_name {
let mangled: String = mangled.chars().flat_map(|c| c.escape_default()).collect();
try!(writeln!(out,
"<tr><td>mangled name</td><td>{}</td></tr>",
mangled));
}
Ok(())
}
}
/// An ABI extracted from a clang cursor.
#[derive(Debug, Copy, Clone)]
pub enum Abi {
/// A known ABI, that rust also understand.
Known(abi::Abi),
/// An unknown or invalid ABI.
Unknown(CXCallingConv),
}
impl Abi {
/// Returns whether this Abi is known or not.
fn is_unknown(&self) -> bool {
match *self {
Abi::Unknown(..) => true,
_ => false,
}
}
}
/// A function signature.
#[derive(Debug)]
pub struct FunctionSig {
/// The return type of the function.
return_type: ItemId,
/// The type of the arguments, optionally with the name of the argument when
/// declared.
argument_types: Vec<(Option<String>, ItemId)>,
/// Whether this function is variadic.
is_variadic: bool,
/// The ABI of this function.
abi: Abi,
}
fn get_abi(cc: CXCallingConv) -> Abi {
use clang_sys::*;
Abi::Known(match cc {
CXCallingConv_Default => abi::Abi::C,
CXCallingConv_C => abi::Abi::C,
CXCallingConv_X86StdCall => abi::Abi::Stdcall,
CXCallingConv_X86FastCall => abi::Abi::Fastcall,
CXCallingConv_AAPCS => abi::Abi::Aapcs,
CXCallingConv_X86_64Win64 => abi::Abi::Win64,
other => return Abi::Unknown(other),
})
}
fn mangling_hack_if_needed(ctx: &BindgenContext, symbol: &mut String) {
if ctx.needs_mangling_hack() {
match symbol.chars().next().unwrap() {
// Stripping leading underscore for all names on Darwin and
// C linkage functions on Win32.
'_' => { symbol.remove(0); }
// Stop Rust from prepending underscore for variables on Win32.
'?' => { symbol.insert(0, '\x01'); }
_ => {}
}
}
}
/// Get the mangled name for the cursor's referent.
pub fn cursor_mangling(ctx: &BindgenContext,
cursor: &clang::Cursor)
-> Option<String> {
use clang_sys;
if !ctx.options().enable_mangling {
return None;
}
// We early return here because libclang may crash in some case
// if we pass in a variable inside a partial specialized template.
// See rust-lang-nursery/rust-bindgen#67, and rust-lang-nursery/rust-bindgen#462.
if cursor.is_in_non_fully_specialized_template() {
return None;
}
if let Ok(mut manglings) = cursor.cxx_manglings() {
if let Some(mut m) = manglings.pop() {
mangling_hack_if_needed(ctx, &mut m);
return Some(m);
}
}
let mut mangling = cursor.mangling();
if mangling.is_empty() {
return None;
}
mangling_hack_if_needed(ctx, &mut mangling);
if cursor.kind() == clang_sys::CXCursor_Destructor {
// With old (3.8-) libclang versions, and the Itanium ABI, clang returns
// the "destructor group 0" symbol, which means that it'll try to free
// memory, which definitely isn't what we want.
//
// Explicitly force the destructor group 1 symbol.
//
// See http://refspecs.linuxbase.org/cxxabi-1.83.html#mangling-special
// for the reference, and http://stackoverflow.com/a/6614369/1091587 for
// a more friendly explanation.
//
// We don't need to do this for constructors since clang seems to always
// have returned the C1 constructor.
//
// FIXME(emilio): Can a legit symbol in other ABIs end with this string?
// I don't think so, but if it can this would become a linker error
// anyway, not an invalid free at runtime.
//
// TODO(emilio, #611): Use cpp_demangle if this becomes nastier with
// time.
if mangling.ends_with("D0Ev") {
let new_len = mangling.len() - 4;
mangling.truncate(new_len);
mangling.push_str("D1Ev");
}
}
Some(mangling)
}
impl FunctionSig {
/// Construct a new function signature.
pub fn new(return_type: ItemId,
arguments: Vec<(Option<String>, ItemId)>,
is_variadic: bool,
abi: Abi)
-> Self {
FunctionSig {
return_type: return_type,
argument_types: arguments,
is_variadic: is_variadic,
abi: abi,
}
}
/// Construct a new function signature from the given Clang type.
pub fn from_ty(ty: &clang::Type,
cursor: &clang::Cursor,
ctx: &mut BindgenContext)
-> Result<Self, ParseError> {
use clang_sys::*;
debug!("FunctionSig::from_ty {:?} {:?}", ty, cursor);
// Skip function templates
if cursor.kind() == CXCursor_FunctionTemplate {
return Err(ParseError::Continue);
}
// Don't parse operatorxx functions in C++
let spelling = cursor.spelling();
if spelling.starts_with("operator") {
return Err(ParseError::Continue);
}
let cursor = if cursor.is_valid() {
*cursor
} else {
ty.declaration()
};
let mut args: Vec<_> = match cursor.kind() {
CXCursor_FunctionDecl |
CXCursor_Constructor |
CXCursor_CXXMethod |
CXCursor_ObjCInstanceMethodDecl |
CXCursor_ObjCClassMethodDecl => {
// For CXCursor_FunctionDecl, cursor.args() is the reliable way
// to get parameter names and types.
cursor.args()
.unwrap()
.iter()
.map(|arg| {
let arg_ty = arg.cur_type();
let name = arg.spelling();
let name =
if name.is_empty() { None } else { Some(name) };
let ty = Item::from_ty_or_ref(arg_ty, *arg, None, ctx);
(name, ty)
})
.collect()
}
_ => {
// For non-CXCursor_FunctionDecl, visiting the cursor's children
// is the only reliable way to get parameter names.
let mut args = vec![];
cursor.visit(|c| {
if c.kind() == CXCursor_ParmDecl {
let ty =
Item::from_ty_or_ref(c.cur_type(), c, None, ctx);
let name = c.spelling();
let name =
if name.is_empty() { None } else { Some(name) };
args.push((name, ty));
}
CXChildVisit_Continue
});
args
}
};
let is_method = cursor.kind() == CXCursor_CXXMethod;
let is_constructor = cursor.kind() == CXCursor_Constructor;
let is_destructor = cursor.kind() == CXCursor_Destructor;
if (is_constructor || is_destructor || is_method) &&
cursor.lexical_parent() != cursor.semantic_parent() {
// Only parse constructors once.
return Err(ParseError::Continue);
}
if is_method || is_constructor || is_destructor {
let is_const = is_method && cursor.method_is_const();
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)
.expect("Expected to parse the class");
let ptr =
Item::builtin_type(TypeKind::Pointer(class), is_const, ctx);
args.insert(0, (Some("this".into()), ptr));
} else if is_virtual {
let void = Item::builtin_type(TypeKind::Void, false, ctx);
let ptr =
Item::builtin_type(TypeKind::Pointer(void), false, ctx);
args.insert(0, (Some("this".into()), ptr));
}
}
let ty_ret_type = if cursor.kind() == CXCursor_ObjCInstanceMethodDecl ||
cursor.kind() == CXCursor_ObjCClassMethodDecl {
try!(ty.ret_type()
.or_else(|| cursor.ret_type())
.ok_or(ParseError::Continue))
} else {
try!(ty.ret_type().ok_or(ParseError::Continue))
};
let ret = Item::from_ty_or_ref(ty_ret_type, cursor, None, ctx);
let call_conv = ty.call_conv();
let abi = get_abi(call_conv);
if abi.is_unknown() {
warn!("Unknown calling convention: {:?}", call_conv);
}
Ok(Self::new(ret, args, ty.is_variadic(), abi))
}
/// Get this function signature's return type.
pub fn return_type(&self) -> ItemId {
self.return_type
}
/// Get this function signature's argument (name, type) pairs.
pub fn argument_types(&self) -> &[(Option<String>, ItemId)] {
&self.argument_types
}
/// Get this function signature's ABI.
pub fn abi(&self) -> Abi {
self.abi
}
/// Is this function signature variadic?
pub fn is_variadic(&self) -> bool {
// Clang reports some functions as variadic when they *might* be
// variadic. We do the argument check because rust doesn't codegen well
// variadic functions without an initial argument.
self.is_variadic && !self.argument_types.is_empty()
}
}
impl ClangSubItemParser for Function {
fn parse(cursor: clang::Cursor,
context: &mut BindgenContext)
-> Result<ParseResult<Self>, ParseError> {
use clang_sys::*;
let kind = match FunctionKind::from_cursor(&cursor) {
None => return Err(ParseError::Continue),
Some(k) => k,
};
debug!("Function::parse({:?}, {:?})", cursor, cursor.cur_type());
let visibility = cursor.visibility();
if visibility != CXVisibility_Default {
return Err(ParseError::Continue);
}
if cursor.access_specifier() == CX_CXXPrivate {
return Err(ParseError::Continue);
}
if !context.options().generate_inline_functions &&
cursor.is_inlined_function() {
return Err(ParseError::Continue);
}
let linkage = cursor.linkage();
if linkage != CXLinkage_External &&
linkage != CXLinkage_UniqueExternal {
return Err(ParseError::Continue);
}
// Grab the signature using Item::from_ty.
let sig =
try!(Item::from_ty(&cursor.cur_type(), cursor, None, context));
let mut name = cursor.spelling();
assert!(!name.is_empty(), "Empty function name?");
if cursor.kind() == CXCursor_Destructor {
// Remove the leading `~`. The alternative to this is special-casing
// code-generation for destructor functions, which seems less than
// ideal.
if name.starts_with('~') {
name.remove(0);
}
// Add a suffix to avoid colliding with constructors. This would be
// technically fine (since we handle duplicated functions/methods),
// but seems easy enough to handle it here.
name.push_str("_destructor");
}
let mut mangled_name = cursor_mangling(context, &cursor);
if mangled_name.as_ref() == Some(&name) {
mangled_name = None;
}
let comment = cursor.raw_comment();
let function = Self::new(name, mangled_name, sig, comment, kind);
Ok(ParseResult::New(function, Some(cursor)))
}
}
impl Trace for FunctionSig {
type Extra = ();
fn trace<T>(&self, _: &BindgenContext, tracer: &mut T, _: &())
where T: Tracer,
{
tracer.visit_kind(self.return_type(), EdgeKind::FunctionReturn);
for &(_, ty) in self.argument_types() {
tracer.visit_kind(ty, EdgeKind::FunctionParameter);
}
}
}
// Function pointers follow special rules, see:
//
// https://github.com/rust-lang-nursery/rust-bindgen/issues/547,
// https://github.com/rust-lang/rust/issues/38848,
// and https://github.com/rust-lang/rust/issues/40158
//
// Note that copy is always derived, so we don't need to implement it.
impl CanTriviallyDeriveDebug for FunctionSig {
type Extra = ();
fn can_trivially_derive_debug(&self, _ctx: &BindgenContext, _: ()) -> bool {
const RUST_DERIVE_FUNPTR_LIMIT: usize = 12;
if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT {
return false;
}
match self.abi {
Abi::Known(abi::Abi::C) |
Abi::Unknown(..) => true,
_ => false,
}
}
}

121
third_party/rust/bindgen-0.29.0/src/ir/int.rs поставляемый
Просмотреть файл

@ -1,121 +0,0 @@
//! Intermediate representation for integral types.
/// Which integral type are we dealing with?
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum IntKind {
/// A `bool`.
Bool,
/// A `signed char`.
SChar,
/// An `unsigned char`.
UChar,
/// A platform-dependent `char` type, with the signedness support.
Char {
/// Whether the char is signed for the target platform.
is_signed: bool,
},
/// A `short`.
Short,
/// An `unsigned short`.
UShort,
/// An `int`.
Int,
/// An `unsigned int`.
UInt,
/// A `long`.
Long,
/// An `unsigned long`.
ULong,
/// A `long long`.
LongLong,
/// An `unsigned long long`.
ULongLong,
/// A 8-bit signed integer.
I8,
/// A 8-bit unsigned integer.
U8,
/// A 16-bit signed integer.
I16,
/// Either a `char16_t` or a `wchar_t`.
U16,
/// A 32-bit signed integer.
I32,
/// A 32-bit unsigned integer.
U32,
/// A 64-bit signed integer.
I64,
/// A 64-bit unsigned integer.
U64,
/// An `int128_t`
I128,
/// A `uint128_t`.
U128,
/// A custom integer type, used to allow custom macro types depending on
/// range.
Custom {
/// The name of the type, which would be used without modification.
name: &'static str,
/// Whether the type is signed or not.
is_signed: bool,
},
}
impl IntKind {
/// Is this integral type signed?
pub fn is_signed(&self) -> bool {
use self::IntKind::*;
match *self {
Bool | UChar | UShort | UInt | ULong | ULongLong | U8 | U16 |
U32 | U64 | U128 => false,
SChar | Short | Int | Long | LongLong | I8 | I16 | I32 | I64 |
I128 => true,
Char { is_signed } => is_signed,
Custom { is_signed, .. } => is_signed,
}
}
/// If this type has a known size, return it (in bytes). This is to
/// alleviate libclang sometimes not giving us a layout (like in the case
/// when an enum is defined inside a class with template parameters).
pub fn known_size(&self) -> Option<usize> {
use self::IntKind::*;
Some(match *self {
Bool | UChar | SChar | U8 | I8 | Char { .. } => 1,
U16 | I16 => 2,
U32 | I32 => 4,
U64 | I64 => 8,
I128 | U128 => 16,
_ => return None,
})
}
/// Whether this type's signedness matches the value.
pub fn signedness_matches(&self, val: i64) -> bool {
val >= 0 || self.is_signed()
}
}

1661
third_party/rust/bindgen-0.29.0/src/ir/item.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,147 +0,0 @@
//! Different variants of an `Item` in our intermediate representation.
use super::context::BindgenContext;
use super::dot::DotAttributes;
use super::function::Function;
use super::module::Module;
use super::ty::Type;
use super::var::Var;
use std::io;
/// A item we parse and translate.
#[derive(Debug)]
pub enum ItemKind {
/// A module, created implicitly once (the root module), or via C++
/// namespaces.
Module(Module),
/// A type declared in any of the multiple ways it can be declared.
Type(Type),
/// A function or method declaration.
Function(Function),
/// A variable declaration, most likely a static.
Var(Var),
}
impl ItemKind {
/// Get a reference to this `ItemKind`'s underying `Module`, or `None` if it
/// is some other kind.
pub fn as_module(&self) -> Option<&Module> {
match *self {
ItemKind::Module(ref module) => Some(module),
_ => None,
}
}
/// Transform our `ItemKind` into a string.
pub fn kind_name(&self) -> &'static str {
match *self {
ItemKind::Module(..) => "Module",
ItemKind::Type(..) => "Type",
ItemKind::Function(..) => "Function",
ItemKind::Var(..) => "Var",
}
}
/// Is this a module?
pub fn is_module(&self) -> bool {
self.as_module().is_some()
}
/// Get a reference to this `ItemKind`'s underying `Module`, or panic if it
/// is some other kind.
pub fn expect_module(&self) -> &Module {
self.as_module().expect("Not a module")
}
/// Get a reference to this `ItemKind`'s underying `Function`, or `None` if
/// it is some other kind.
pub fn as_function(&self) -> Option<&Function> {
match *self {
ItemKind::Function(ref func) => Some(func),
_ => None,
}
}
/// Is this a function?
pub fn is_function(&self) -> bool {
self.as_function().is_some()
}
/// Get a reference to this `ItemKind`'s underying `Function`, or panic if
/// it is some other kind.
pub fn expect_function(&self) -> &Function {
self.as_function().expect("Not a function")
}
/// Get a reference to this `ItemKind`'s underying `Type`, or `None` if
/// it is some other kind.
pub fn as_type(&self) -> Option<&Type> {
match *self {
ItemKind::Type(ref ty) => Some(ty),
_ => None,
}
}
/// Get a mutable reference to this `ItemKind`'s underying `Type`, or `None`
/// if it is some other kind.
pub fn as_type_mut(&mut self) -> Option<&mut Type> {
match *self {
ItemKind::Type(ref mut ty) => Some(ty),
_ => None,
}
}
/// Is this a type?
pub fn is_type(&self) -> bool {
self.as_type().is_some()
}
/// Get a reference to this `ItemKind`'s underying `Type`, or panic if it is
/// some other kind.
pub fn expect_type(&self) -> &Type {
self.as_type().expect("Not a type")
}
/// Get a reference to this `ItemKind`'s underying `Var`, or `None` if it is
/// some other kind.
pub fn as_var(&self) -> Option<&Var> {
match *self {
ItemKind::Var(ref v) => Some(v),
_ => None,
}
}
/// Is this a variable?
pub fn is_var(&self) -> bool {
self.as_var().is_some()
}
/// Get a reference to this `ItemKind`'s underying `Var`, or panic if it is
/// some other kind.
pub fn expect_var(&self) -> &Var {
self.as_var().expect("Not a var")
}
}
impl DotAttributes for ItemKind {
fn dot_attributes<W>(&self,
ctx: &BindgenContext,
out: &mut W)
-> io::Result<()>
where W: io::Write,
{
try!(writeln!(out,
"<tr><td>kind</td><td>{}</td></tr>",
self.kind_name()));
match *self {
ItemKind::Module(ref module) => module.dot_attributes(ctx, out),
ItemKind::Type(ref ty) => ty.dot_attributes(ctx, out),
ItemKind::Function(ref func) => func.dot_attributes(ctx, out),
ItemKind::Var(ref var) => var.dot_attributes(ctx, out),
}
}
}

Просмотреть файл

@ -1,134 +0,0 @@
//! Intermediate representation for the physical layout of some type.
use super::context::BindgenContext;
use super::derive::{CanDeriveCopy, CanTriviallyDeriveDebug, CanDeriveDefault};
use super::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, Type, TypeKind};
use clang;
use std::{cmp, mem};
/// A type that represents the struct layout of a type.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Layout {
/// The size (in bytes) of this layout.
pub size: usize,
/// The alignment (in bytes) of this layout.
pub align: usize,
/// Whether this layout's members are packed or not.
pub packed: bool,
}
#[test]
fn test_layout_for_size() {
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::new(3 * ptr_size, ptr_size));
}
impl Layout {
/// Construct a new `Layout` with the given `size` and `align`. It is not
/// packed.
pub fn new(size: usize, align: usize) -> Self {
Layout {
size: size,
align: align,
packed: false,
}
}
/// Creates a non-packed layout for a given size, trying to use the maximum
/// alignment possible.
pub fn for_size(size: usize) -> Self {
let mut next_align = 2;
while size % next_align == 0 &&
next_align <= mem::size_of::<*mut ()>() {
next_align *= 2;
}
Layout {
size: size,
align: next_align / 2,
packed: false,
}
}
/// Is this a zero-sized layout?
pub fn is_zero(&self) -> bool {
self.size == 0 && self.align == 0
}
/// Construct a zero-sized layout.
pub fn zero() -> Self {
Self::new(0, 0)
}
/// Get this layout as an opaque type.
pub fn opaque(&self) -> Opaque {
Opaque(*self)
}
}
/// When we are treating a type as opaque, it is just a blob with a `Layout`.
#[derive(Clone, Debug, PartialEq)]
pub struct Opaque(pub Layout);
impl Opaque {
/// Construct a new opaque type from the given clang type.
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)
}
/// Return the known rust type we should use to create a correctly-aligned
/// field with this layout.
pub fn known_rust_type_for_array(&self) -> Option<&'static str> {
Some(match self.0.align {
8 => "u64",
4 => "u32",
2 => "u16",
1 => "u8",
_ => return None,
})
}
/// Return the array size that an opaque type for this layout should have if
/// we know the correct type for it, or `None` otherwise.
pub fn array_size(&self) -> Option<usize> {
if self.known_rust_type_for_array().is_some() {
Some(self.0.size / cmp::max(self.0.align, 1))
} else {
None
}
}
}
impl CanTriviallyDeriveDebug for Opaque {
type Extra = ();
fn can_trivially_derive_debug(&self, _: &BindgenContext, _: ()) -> bool {
self.array_size()
.map_or(false, |size| size <= RUST_DERIVE_IN_ARRAY_LIMIT)
}
}
impl<'a> CanDeriveDefault<'a> for Opaque {
type Extra = ();
fn can_derive_default(&self, _: &BindgenContext, _: ()) -> bool {
self.array_size()
.map_or(false, |size| size <= RUST_DERIVE_IN_ARRAY_LIMIT)
}
}
impl<'a> CanDeriveCopy<'a> for Opaque {
type Extra = ();
fn can_derive_copy(&self, _: &BindgenContext, _: ()) -> bool {
self.array_size()
.map_or(false, |size| size <= RUST_DERIVE_IN_ARRAY_LIMIT)
}
fn can_derive_copy_in_array(&self, ctx: &BindgenContext, _: ()) -> bool {
self.can_derive_copy(ctx, ())
}
}

24
third_party/rust/bindgen-0.29.0/src/ir/mod.rs поставляемый
Просмотреть файл

@ -1,24 +0,0 @@
//! The ir module defines bindgen's intermediate representation.
//!
//! Parsing C/C++ generates the IR, while code generation outputs Rust code from
//! the IR.
pub mod annotations;
pub mod analysis;
pub mod comp;
pub mod comment;
pub mod context;
pub mod derive;
pub mod dot;
pub mod enum_ty;
pub mod function;
pub mod int;
pub mod item;
pub mod item_kind;
pub mod layout;
pub mod module;
pub mod template;
pub mod traversal;
pub mod ty;
pub mod var;
pub mod objc;

Просмотреть файл

@ -1,92 +0,0 @@
//! Intermediate representation for modules (AKA C++ namespaces).
use super::context::BindgenContext;
use super::dot::DotAttributes;
use super::item::ItemSet;
use clang;
use parse::{ClangSubItemParser, ParseError, ParseResult};
use parse_one;
use std::io;
/// Whether this module is inline or not.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ModuleKind {
/// This module is not inline.
Normal,
/// This module is inline, as in `inline namespace foo {}`.
Inline,
}
/// A module, as in, a C++ namespace.
#[derive(Clone, Debug)]
pub struct Module {
/// The name of the module, or none if it's anonymous.
name: Option<String>,
/// The kind of module this is.
kind: ModuleKind,
/// The children of this module, just here for convenience.
children: ItemSet,
}
impl Module {
/// Construct a new `Module`.
pub fn new(name: Option<String>, kind: ModuleKind) -> Self {
Module {
name: name,
kind: kind,
children: ItemSet::new(),
}
}
/// Get this module's name.
pub fn name(&self) -> Option<&str> {
self.name.as_ref().map(|n| &**n)
}
/// Get a mutable reference to this module's children.
pub fn children_mut(&mut self) -> &mut ItemSet {
&mut self.children
}
/// Get this module's children.
pub fn children(&self) -> &ItemSet {
&self.children
}
/// Whether this namespace is inline.
pub fn is_inline(&self) -> bool {
self.kind == ModuleKind::Inline
}
}
impl DotAttributes for Module {
fn dot_attributes<W>(&self,
_ctx: &BindgenContext,
out: &mut W)
-> io::Result<()>
where W: io::Write,
{
writeln!(out, "<tr><td>ModuleKind</td><td>{:?}</td></tr>", self.kind)
}
}
impl ClangSubItemParser for Module {
fn parse(cursor: clang::Cursor,
ctx: &mut BindgenContext)
-> Result<ParseResult<Self>, ParseError> {
use clang_sys::*;
match cursor.kind() {
CXCursor_Namespace => {
let module_id = ctx.module(cursor);
ctx.with_module(module_id, |ctx| {
cursor.visit(|cursor| {
parse_one(ctx, cursor, Some(module_id))
})
});
Ok(ParseResult::AlreadyResolved(module_id))
}
_ => Err(ParseError::Continue),
}
}
}

254
third_party/rust/bindgen-0.29.0/src/ir/objc.rs поставляемый
Просмотреть файл

@ -1,254 +0,0 @@
//! Objective C types
use super::context::{BindgenContext, ItemId};
use super::function::FunctionSig;
use super::traversal::{Trace, Tracer};
use super::ty::TypeKind;
use clang;
use clang_sys::CXChildVisit_Continue;
use clang_sys::CXCursor_ObjCCategoryDecl;
use clang_sys::CXCursor_ObjCClassMethodDecl;
use clang_sys::CXCursor_ObjCClassRef;
use clang_sys::CXCursor_ObjCInstanceMethodDecl;
use clang_sys::CXCursor_ObjCProtocolDecl;
use clang_sys::CXCursor_ObjCProtocolRef;
/// Objective C interface as used in TypeKind
///
/// Also protocols and categories are parsed as this type
#[derive(Debug)]
pub struct ObjCInterface {
/// The name
/// like, NSObject
name: String,
category: Option<String>,
is_protocol: bool,
conforms_to: Vec<ItemId>,
/// List of the methods defined in this interfae
methods: Vec<ObjCMethod>,
class_methods: Vec<ObjCMethod>,
}
/// The objective c methods
#[derive(Debug)]
pub struct ObjCMethod {
/// The original method selector name
/// like, dataWithBytes:length:
name: String,
/// Method name as converted to rust
/// like, dataWithBytes_length_
rust_name: String,
signature: FunctionSig,
/// Is class method?
is_class_method: bool,
}
impl ObjCInterface {
fn new(name: &str) -> ObjCInterface {
ObjCInterface {
name: name.to_owned(),
category: None,
is_protocol: false,
conforms_to: Vec::new(),
methods: Vec::new(),
class_methods: Vec::new(),
}
}
/// The name
/// like, NSObject
pub fn name(&self) -> &str {
self.name.as_ref()
}
/// Formats the name for rust
/// Can be like NSObject, but with categories might be like NSObject_NSCoderMethods
/// and protocols are like protocol_NSObject
pub fn rust_name(&self) -> String {
if let Some(ref cat) = self.category {
format!("{}_{}", self.name(), cat)
} else {
if self.is_protocol {
format!("protocol_{}", self.name())
} else {
self.name().to_owned()
}
}
}
/// List of the methods defined in this interface
pub fn methods(&self) -> &Vec<ObjCMethod> {
&self.methods
}
/// List of the class methods defined in this interface
pub fn class_methods(&self) -> &Vec<ObjCMethod> {
&self.class_methods
}
/// Parses the Objective C interface from the cursor
pub fn from_ty(cursor: &clang::Cursor,
ctx: &mut BindgenContext)
-> Option<Self> {
let name = cursor.spelling();
let mut interface = Self::new(&name);
if cursor.kind() == CXCursor_ObjCProtocolDecl {
interface.is_protocol = true;
}
cursor.visit(|c| {
match c.kind() {
CXCursor_ObjCClassRef => {
if cursor.kind() == CXCursor_ObjCCategoryDecl {
// We are actually a category extension, and we found the reference
// to the original interface, so name this interface approriately
interface.name = c.spelling();
interface.category = Some(cursor.spelling());
}
}
CXCursor_ObjCProtocolRef => {
// Gather protocols this interface conforms to
let needle = format!("protocol_{}", c.spelling());
let items_map = ctx.items();
debug!("Interface {} conforms to {}, find the item", interface.name, needle);
for (id, item) in items_map
{
if let Some(ty) = item.as_type() {
match *ty.kind() {
TypeKind::ObjCInterface(ref protocol) => {
if protocol.is_protocol
{
debug!("Checking protocol {}, ty.name {:?}", protocol.name, ty.name());
if Some(needle.as_ref()) == ty.name()
{
debug!("Found conforming protocol {:?}", item);
interface.conforms_to.push(*id);
break;
}
}
}
_ => {}
}
}
}
}
CXCursor_ObjCInstanceMethodDecl |
CXCursor_ObjCClassMethodDecl => {
let name = c.spelling();
let signature =
FunctionSig::from_ty(&c.cur_type(), &c, ctx)
.expect("Invalid function sig");
let is_class_method = c.kind() == CXCursor_ObjCClassMethodDecl;
let method = ObjCMethod::new(&name, signature, is_class_method);
interface.add_method(method);
}
_ => {}
}
CXChildVisit_Continue
});
Some(interface)
}
fn add_method(&mut self, method: ObjCMethod) {
if method.is_class_method {
self.class_methods.push(method);
} else {
self.methods.push(method);
}
}
}
impl ObjCMethod {
fn new(name: &str,
signature: FunctionSig,
is_class_method: bool)
-> ObjCMethod {
let split_name: Vec<&str> = name.split(':').collect();
let rust_name = split_name.join("_");
ObjCMethod {
name: name.to_owned(),
rust_name: rust_name.to_owned(),
signature: signature,
is_class_method: is_class_method,
}
}
/// The original method selector name
/// like, dataWithBytes:length:
pub fn name(&self) -> &str {
self.name.as_ref()
}
/// Method name as converted to rust
/// like, dataWithBytes_length_
pub fn rust_name(&self) -> &str {
self.rust_name.as_ref()
}
/// Returns the methods signature as FunctionSig
pub fn signature(&self) -> &FunctionSig {
&self.signature
}
/// Is this a class method?
pub fn is_class_method(&self) -> bool {
self.is_class_method
}
/// Formats the method call
pub fn format_method_call(&self, args: &[String]) -> String {
let split_name: Vec<&str> =
self.name.split(':').filter(|p| !p.is_empty()).collect();
// No arguments
if args.len() == 0 && split_name.len() == 1 {
return split_name[0].to_string();
}
// Check right amount of arguments
if args.len() != split_name.len() {
panic!("Incorrect method name or arguments for objc method, {:?} vs {:?}",
args,
split_name);
}
split_name.iter()
.zip(args.iter())
.map(|parts| format!("{}:{} ", parts.0, parts.1))
.collect::<Vec<_>>()
.join("")
}
}
impl Trace for ObjCInterface {
type Extra = ();
fn trace<T>(&self, context: &BindgenContext, tracer: &mut T, _: &())
where T: Tracer,
{
for method in &self.methods {
method.signature.trace(context, tracer, &());
}
for class_method in &self.class_methods {
class_method.signature.trace(context, tracer, &());
}
for protocol in &self.conforms_to {
tracer.visit(*protocol);
}
}
}

Просмотреть файл

@ -1,361 +0,0 @@
//! Template declaration and instantiation related things.
//!
//! The nomenclature surrounding templates is often confusing, so here are a few
//! brief definitions:
//!
//! * "Template definition": a class/struct/alias/function definition that takes
//! generic template parameters. For example:
//!
//! ```c++
//! template<typename T>
//! class List<T> {
//! // ...
//! };
//! ```
//!
//! * "Template instantiation": an instantiation is a use of a template with
//! concrete template arguments. For example, `List<int>`.
//!
//! * "Template specialization": an alternative template definition providing a
//! custom definition for instantiations with the matching template
//! arguments. This C++ feature is unsupported by bindgen. For example:
//!
//! ```c++
//! template<>
//! class List<int> {
//! // Special layout for int lists...
//! };
//! ```
use super::context::{BindgenContext, ItemId};
use super::derive::{CanDeriveCopy};
use super::item::{IsOpaque, Item, ItemAncestors, ItemCanonicalPath};
use super::traversal::{EdgeKind, Trace, Tracer};
use clang;
use parse::ClangItemParser;
/// Template declaration (and such declaration's template parameters) related
/// methods.
///
/// This trait's methods distinguish between `None` and `Some([])` for
/// declarations that are not templates and template declarations with zero
/// parameters, in general.
///
/// Consider this example:
///
/// ```c++
/// template <typename T, typename U>
/// class Foo {
/// T use_of_t;
/// U use_of_u;
///
/// template <typename V>
/// using Bar = V*;
///
/// class Inner {
/// T x;
/// U y;
/// Bar<int> z;
/// };
///
/// template <typename W>
/// class Lol {
/// // No use of W, but here's a use of T.
/// T t;
/// };
///
/// template <typename X>
/// class Wtf {
/// // X is not used because W is not used.
/// Lol<X> lololol;
/// };
/// };
///
/// class Qux {
/// int y;
/// };
/// ```
///
/// The following table depicts the results of each trait method when invoked on
/// each of the declarations above:
///
/// +------+----------------------+--------------------------+------------------------+----
/// |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 | ...
/// +------+----------------------+--------------------------+------------------------+----
///
/// ----+------+-----+----------------------+
/// ... |Decl. | ... | used_template_params |
/// ----+------+-----+----------------------+
/// ... |Foo | ... | Some([T, U]) |
/// ... |Bar | ... | Some([V]) |
/// ... |Inner | ... | None |
/// ... |Lol | ... | Some([T]) |
/// ... |Wtf | ... | Some([T]) |
/// ... |Qux | ... | None |
/// ----+------+-----+----------------------+
pub trait TemplateParameters {
/// Get the set of `ItemId`s that make up this template declaration's free
/// template parameters.
///
/// Note that these might *not* all be named types: C++ allows
/// constant-value template parameters as well as template-template
/// parameters. Of course, Rust does not allow generic parameters to be
/// anything but types, so we must treat them as opaque, and avoid
/// instantiating them.
fn self_template_params(&self,
ctx: &BindgenContext)
-> Option<Vec<ItemId>>;
/// 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())
}
/// Get the complete set of template parameters that can affect this
/// declaration.
///
/// Note that this item doesn't need to be a template declaration itself for
/// `Some` to be returned here (in contrast to `self_template_params`). If
/// this item is a member of a template declaration, then the parent's
/// template parameters are included here.
///
/// In the example above, `Inner` depends on both of the `T` and `U` type
/// parameters, even though it is not itself a template declaration and
/// therefore has no type parameters itself. Perhaps it helps to think about
/// 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<ItemId>>
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())
}
}
/// 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<ItemId>>
where Self: AsRef<ItemId>,
{
assert!(ctx.in_codegen_phase(),
"template parameter usage is not computed until codegen");
let id = *self.as_ref();
ctx.resolve_item(id)
.all_template_params(ctx)
.map(|all_params| {
all_params.into_iter()
.filter(|p| ctx.uses_template_parameter(id, *p))
.collect()
})
}
}
/// A trait for things which may or may not be a named template type parameter.
pub trait AsTemplateParam {
/// Any extra information the implementor might need to make this decision.
type Extra;
/// Convert this thing to the item id of a named template type parameter.
fn as_template_param(&self,
ctx: &BindgenContext,
extra: &Self::Extra)
-> Option<ItemId>;
/// Is this a named template type parameter?
fn is_template_param(&self, ctx: &BindgenContext, extra: &Self::Extra) -> bool {
self.as_template_param(ctx, extra).is_some()
}
}
/// A concrete instantiation of a generic template.
#[derive(Clone, Debug)]
pub struct TemplateInstantiation {
/// The template definition which this is instantiating.
definition: ItemId,
/// The concrete template arguments, which will be substituted in the
/// definition for the generic template parameters.
args: Vec<ItemId>,
}
impl TemplateInstantiation {
/// Construct a new template instantiation from the given parts.
pub fn new<I>(template_definition: ItemId,
template_args: I)
-> TemplateInstantiation
where I: IntoIterator<Item = ItemId>,
{
TemplateInstantiation {
definition: template_definition,
args: template_args.into_iter().collect(),
}
}
/// Get the template definition for this instantiation.
pub fn template_definition(&self) -> ItemId {
self.definition
}
/// Get the concrete template arguments used in this instantiation.
pub fn template_arguments(&self) -> &[ItemId] {
&self.args[..]
}
/// Parse a `TemplateInstantiation` from a clang `Type`.
pub fn from_ty(ty: &clang::Type,
ctx: &mut BindgenContext)
-> Option<TemplateInstantiation> {
use clang_sys::*;
let template_args = ty.template_args()
.map_or(vec![], |args| {
match ty.canonical_type().template_args() {
Some(canonical_args) => {
let arg_count = args.len();
args.chain(canonical_args.skip(arg_count))
.filter(|t| t.kind() != CXType_Invalid)
.map(|t| {
Item::from_ty_or_ref(t, t.declaration(), None, ctx)
}).collect()
}
None => {
args.filter(|t| t.kind() != CXType_Invalid)
.map(|t| {
Item::from_ty_or_ref(t, t.declaration(), None, ctx)
}).collect()
}
}
});
let declaration = ty.declaration();
let definition = if declaration.kind() == CXCursor_TypeAliasTemplateDecl {
Some(declaration)
} else {
declaration
.specialized()
.or_else(|| {
let mut template_ref = None;
ty.declaration().visit(|child| {
if child.kind() == CXCursor_TemplateRef {
template_ref = Some(child);
return CXVisit_Break;
}
// Instantiations of template aliases might have the
// TemplateRef to the template alias definition arbitrarily
// deep, so we need to recurse here and not only visit
// direct children.
CXChildVisit_Recurse
});
template_ref.and_then(|cur| cur.referenced())
})
};
let definition = match definition {
Some(def) => def,
None => {
if !ty.declaration().is_builtin() {
warn!("Could not find template definition for template \
instantiation");
}
return None
}
};
let template_definition =
Item::from_ty_or_ref(definition.cur_type(), definition, None, ctx);
Some(TemplateInstantiation::new(template_definition, template_args))
}
/// Does this instantiation have a destructor?
pub fn has_destructor(&self, ctx: &BindgenContext) -> bool {
ctx.resolve_type(self.definition).has_destructor(ctx) ||
self.args.iter().any(|arg| ctx.resolve_type(*arg).has_destructor(ctx))
}
}
impl IsOpaque for TemplateInstantiation {
type Extra = Item;
/// Is this an opaque template instantiation?
fn is_opaque(&self, ctx: &BindgenContext, item: &Item) -> bool {
if self.template_definition().is_opaque(ctx, &()) {
return true;
}
// TODO(#774): This doesn't properly handle opaque instantiations where
// an argument is itself an instantiation because `canonical_name` does
// not insert the template arguments into the name, ie it for nested
// template arguments it creates "Foo" instead of "Foo<int>". The fully
// correct fix is to make `canonical_{name,path}` include template
// arguments properly.
let mut path = item.canonical_path(ctx);
let args: Vec<_> = self.template_arguments()
.iter()
.map(|arg| {
let arg_path = arg.canonical_path(ctx);
arg_path[1..].join("::")
}).collect();
{
let mut last = path.last_mut().unwrap();
last.push('<');
last.push_str(&args.join(", "));
last.push('>');
}
ctx.opaque_by_name(&path)
}
}
impl<'a> CanDeriveCopy<'a> for TemplateInstantiation {
type Extra = ();
fn can_derive_copy(&self, ctx: &BindgenContext, _: ()) -> bool {
self.definition.can_derive_copy(ctx, ()) &&
self.args.iter().all(|arg| arg.can_derive_copy(ctx, ()))
}
fn can_derive_copy_in_array(&self, ctx: &BindgenContext, _: ()) -> bool {
self.definition.can_derive_copy_in_array(ctx, ()) &&
self.args.iter().all(|arg| arg.can_derive_copy_in_array(ctx, ()))
}
}
impl Trace for TemplateInstantiation {
type Extra = ();
fn trace<T>(&self, _ctx: &BindgenContext, tracer: &mut T, _: &())
where T: Tracer,
{
tracer.visit_kind(self.definition, EdgeKind::TemplateDeclaration);
for &item in self.template_arguments() {
tracer.visit_kind(item, EdgeKind::TemplateArgument);
}
}
}

Просмотреть файл

@ -1,507 +0,0 @@
//! Traversal of the graph of IR items and types.
use super::context::{BindgenContext, ItemId};
use super::item::ItemSet;
use std::collections::{BTreeMap, VecDeque};
/// An outgoing edge in the IR graph is a reference from some item to another
/// item:
///
/// from --> to
///
/// The `from` is left implicit: it is the concrete `Trace` implementer which
/// yielded this outgoing edge.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Edge {
to: ItemId,
kind: EdgeKind,
}
impl Edge {
/// Construct a new edge whose referent is `to` and is of the given `kind`.
pub fn new(to: ItemId, kind: EdgeKind) -> Edge {
Edge {
to: to,
kind: kind,
}
}
}
impl Into<ItemId> for Edge {
fn into(self) -> ItemId {
self.to
}
}
/// The kind of edge reference. This is useful when we wish to only consider
/// certain kinds of edges for a particular traversal or analysis.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum EdgeKind {
/// A generic, catch-all edge.
Generic,
/// An edge from a template declaration, to the definition of a named type
/// parameter. For example, the edge from `Foo<T>` to `T` in the following
/// snippet:
///
/// ```C++
/// template<typename T>
/// class Foo { };
/// ```
TemplateParameterDefinition,
/// An edge from a template instantiation to the template declaration that
/// is being instantiated. For example, the edge from `Foo<int>` to
/// to `Foo<T>`:
///
/// ```C++
/// template<typename T>
/// class Foo { };
///
/// using Bar = Foo<ant>;
/// ```
TemplateDeclaration,
/// An edge from a template instantiation to its template argument. For
/// example, `Foo<Bar>` to `Bar`:
///
/// ```C++
/// template<typename T>
/// class Foo { };
///
/// class Bar { };
///
/// using FooBar = Foo<Bar>;
/// ```
TemplateArgument,
/// An edge from a compound type to one of its base member types. For
/// example, the edge from `Bar` to `Foo`:
///
/// ```C++
/// class Foo { };
///
/// class Bar : public Foo { };
/// ```
BaseMember,
/// An edge from a compound type to the types of one of its fields. For
/// example, the edge from `Foo` to `int`:
///
/// ```C++
/// class Foo {
/// int x;
/// };
/// ```
Field,
/// An edge from an class or struct type to an inner type member. For
/// example, the edge from `Foo` to `Foo::Bar` here:
///
/// ```C++
/// class Foo {
/// struct Bar { };
/// };
/// ```
InnerType,
/// An edge from an class or struct type to an inner static variable. For
/// example, the edge from `Foo` to `Foo::BAR` here:
///
/// ```C++
/// class Foo {
/// static const char* BAR;
/// };
/// ```
InnerVar,
/// An edge from a class or struct type to one of its method functions. For
/// example, the edge from `Foo` to `Foo::bar`:
///
/// ```C++
/// class Foo {
/// bool bar(int x, int y);
/// };
/// ```
Method,
/// An edge from a class or struct type to one of its constructor
/// functions. For example, the edge from `Foo` to `Foo::Foo(int x, int y)`:
///
/// ```C++
/// class Foo {
/// int my_x;
/// int my_y;
///
/// public:
/// Foo(int x, int y);
/// };
/// ```
Constructor,
/// An edge from a class or struct type to its destructor function. For
/// example, the edge from `Doggo` to `Doggo::~Doggo()`:
///
/// ```C++
/// struct Doggo {
/// char* wow;
///
/// public:
/// ~Doggo();
/// };
/// ```
Destructor,
/// An edge from a function declaration to its return type. For example, the
/// edge from `foo` to `int`:
///
/// ```C++
/// int foo(char* string);
/// ```
FunctionReturn,
/// An edge from a function declaration to one of its parameter types. For
/// example, the edge from `foo` to `char*`:
///
/// ```C++
/// int foo(char* string);
/// ```
FunctionParameter,
/// An edge from a static variable to its type. For example, the edge from
/// `FOO` to `const char*`:
///
/// ```C++
/// static const char* FOO;
/// ```
VarType,
/// An edge from a non-templated alias or typedef to the referenced type.
TypeReference,
}
/// A predicate to allow visiting only sub-sets of the whole IR graph by
/// excluding certain edges from being followed by the traversal.
pub trait TraversalPredicate {
/// Should the traversal follow this edge, and visit everything that is
/// reachable through it?
fn should_follow(&self, ctx: &BindgenContext, edge: Edge) -> bool;
}
impl TraversalPredicate for for<'a> fn(&'a BindgenContext, Edge) -> bool {
fn should_follow(&self, ctx: &BindgenContext, edge: Edge) -> bool {
(*self)(ctx, edge)
}
}
/// A `TraversalPredicate` implementation that follows all edges, and therefore
/// traversals using this predicate will see the whole IR graph reachable from
/// the traversal's roots.
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 edges to items that
/// are enabled for code generation. This lets us skip considering items for
/// which are not reachable from code generation.
pub fn codegen_edges(ctx: &BindgenContext, edge: Edge) -> bool {
let cc = &ctx.options().codegen_config;
match edge.kind {
EdgeKind::Generic => ctx.resolve_item(edge.to).is_enabled_for_codegen(ctx),
// We statically know the kind of item that non-generic edges can point
// to, so we don't need to actually resolve the item and check
// `Item::is_enabled_for_codegen`.
EdgeKind::TemplateParameterDefinition |
EdgeKind::TemplateArgument |
EdgeKind::TemplateDeclaration |
EdgeKind::BaseMember |
EdgeKind::Field |
EdgeKind::InnerType |
EdgeKind::FunctionReturn |
EdgeKind::FunctionParameter |
EdgeKind::VarType |
EdgeKind::TypeReference => cc.types,
EdgeKind::InnerVar => cc.vars,
EdgeKind::Method => cc.methods,
EdgeKind::Constructor => cc.constructors,
EdgeKind::Destructor => cc.destructors,
}
}
/// The storage for the set of items that have been seen (although their
/// outgoing edges might not have been fully traversed yet) in an active
/// traversal.
pub trait TraversalStorage<'ctx, 'gen> {
/// Construct a new instance of this TraversalStorage, for a new traversal.
fn new(ctx: &'ctx BindgenContext<'gen>) -> Self;
/// Add the given item to the storage. If the item has never been seen
/// before, return `true`. Otherwise, return `false`.
///
/// The `from` item is the item from which we discovered this item, or is
/// `None` if this item is a root.
fn add(&mut self, from: Option<ItemId>, item: ItemId) -> bool;
}
impl<'ctx, 'gen> TraversalStorage<'ctx, 'gen> for ItemSet {
fn new(_: &'ctx BindgenContext<'gen>) -> Self {
ItemSet::new()
}
fn add(&mut self, _: Option<ItemId>, item: ItemId) -> bool {
self.insert(item)
}
}
/// A `TraversalStorage` implementation that keeps track of how we first reached
/// each item. This is useful for providing debug assertions with meaningful
/// diagnostic messages about dangling items.
#[derive(Debug)]
pub struct Paths<'ctx, 'gen>(BTreeMap<ItemId, ItemId>,
&'ctx BindgenContext<'gen>)
where 'gen: 'ctx;
impl<'ctx, 'gen> TraversalStorage<'ctx, 'gen> for Paths<'ctx, 'gen>
where 'gen: 'ctx,
{
fn new(ctx: &'ctx BindgenContext<'gen>) -> Self {
Paths(BTreeMap::new(), ctx)
}
fn add(&mut self, from: Option<ItemId>, item: ItemId) -> bool {
let newly_discovered =
self.0.insert(item, from.unwrap_or(item)).is_none();
if self.1.resolve_item_fallible(item).is_none() {
let mut path = vec![];
let mut current = item;
loop {
let predecessor = *self.0
.get(&current)
.expect("We know we found this item id, so it must have a \
predecessor");
if predecessor == current {
break;
}
path.push(predecessor);
current = predecessor;
}
path.reverse();
panic!("Found reference to dangling id = {:?}\nvia path = {:?}",
item,
path);
}
newly_discovered
}
}
/// The queue of seen-but-not-yet-traversed items.
///
/// Using a FIFO queue with a traversal will yield a breadth-first traversal,
/// while using a LIFO queue will result in a depth-first traversal of the IR
/// graph.
pub trait TraversalQueue: Default {
/// Add a newly discovered item to the queue.
fn push(&mut self, item: ItemId);
/// Pop the next item to traverse, if any.
fn next(&mut self) -> Option<ItemId>;
}
impl TraversalQueue for Vec<ItemId> {
fn push(&mut self, item: ItemId) {
self.push(item);
}
fn next(&mut self) -> Option<ItemId> {
self.pop()
}
}
impl TraversalQueue for VecDeque<ItemId> {
fn push(&mut self, item: ItemId) {
self.push_back(item);
}
fn next(&mut self) -> Option<ItemId> {
self.pop_front()
}
}
/// Something that can receive edges from a `Trace` implementation.
pub trait Tracer {
/// Note an edge between items. Called from within a `Trace` implementation.
fn visit_kind(&mut self, item: ItemId, kind: EdgeKind);
/// A synonym for `tracer.visit_kind(item, EdgeKind::Generic)`.
fn visit(&mut self, item: ItemId) {
self.visit_kind(item, EdgeKind::Generic);
}
}
impl<F> Tracer for F
where F: FnMut(ItemId, EdgeKind),
{
fn visit_kind(&mut self, item: ItemId, kind: EdgeKind) {
(*self)(item, kind)
}
}
/// Trace all of the outgoing edges to other items. Implementations should call
/// one of `tracer.visit(edge)` or `tracer.visit_kind(edge, EdgeKind::Whatever)`
/// for each of their outgoing edges.
pub trait Trace {
/// If a particular type needs extra information beyond what it has in
/// `self` and `context` to find its referenced items, its implementation
/// can define this associated type, forcing callers to pass the needed
/// information through.
type Extra;
/// Trace all of this item's outgoing edges to other items.
fn trace<T>(&self,
context: &BindgenContext,
tracer: &mut T,
extra: &Self::Extra)
where T: Tracer;
}
/// An graph traversal of the transitive closure of references between items.
///
/// See `BindgenContext::whitelisted_items` for more information.
pub struct ItemTraversal<'ctx, 'gen, Storage, Queue, Predicate>
where 'gen: 'ctx,
Storage: TraversalStorage<'ctx, 'gen>,
Queue: TraversalQueue,
Predicate: TraversalPredicate,
{
ctx: &'ctx BindgenContext<'gen>,
/// The set of items we have seen thus far in this traversal.
seen: Storage,
/// The set of items that we have seen, but have yet to traverse.
queue: Queue,
/// The predicate that determines which edges this traversal will follow.
predicate: Predicate,
/// The item we are currently traversing.
currently_traversing: Option<ItemId>,
}
impl<'ctx, 'gen, Storage, Queue, Predicate> ItemTraversal<'ctx,
'gen,
Storage,
Queue,
Predicate>
where 'gen: 'ctx,
Storage: TraversalStorage<'ctx, 'gen>,
Queue: TraversalQueue,
Predicate: TraversalPredicate,
{
/// Begin a new traversal, starting from the given roots.
pub fn new<R>(ctx: &'ctx BindgenContext<'gen>,
roots: R,
predicate: Predicate)
-> ItemTraversal<'ctx, 'gen, Storage, Queue, Predicate>
where R: IntoIterator<Item = ItemId>,
{
let mut seen = Storage::new(ctx);
let mut queue = Queue::default();
for id in roots {
seen.add(None, id);
queue.push(id);
}
ItemTraversal {
ctx: ctx,
seen: seen,
queue: queue,
predicate: predicate,
currently_traversing: None,
}
}
}
impl<'ctx, 'gen, Storage, Queue, Predicate> Tracer
for ItemTraversal<'ctx, 'gen, Storage, Queue, Predicate>
where 'gen: 'ctx,
Storage: TraversalStorage<'ctx, 'gen>,
Queue: TraversalQueue,
Predicate: TraversalPredicate,
{
fn visit_kind(&mut self, item: ItemId, kind: EdgeKind) {
let edge = Edge::new(item, kind);
if !self.predicate.should_follow(self.ctx, edge) {
return;
}
let is_newly_discovered = self.seen
.add(self.currently_traversing, item);
if is_newly_discovered {
self.queue.push(item)
}
}
}
impl<'ctx, 'gen, Storage, Queue, Predicate> Iterator
for ItemTraversal<'ctx, 'gen, Storage, Queue, Predicate>
where 'gen: 'ctx,
Storage: TraversalStorage<'ctx, 'gen>,
Queue: TraversalQueue,
Predicate: TraversalPredicate,
{
type Item = ItemId;
fn next(&mut self) -> Option<Self::Item> {
let id = match self.queue.next() {
None => return None,
Some(id) => id,
};
let newly_discovered = self.seen.add(None, id);
debug_assert!(!newly_discovered,
"should have already seen anything we get out of our queue");
debug_assert!(self.ctx.resolve_item_fallible(id).is_some(),
"should only get IDs of actual items in our context during traversal");
self.currently_traversing = Some(id);
id.trace(self.ctx, self, &());
self.currently_traversing = None;
Some(id)
}
}
/// An iterator to find any dangling items.
///
/// See `BindgenContext::assert_no_dangling_item_traversal` for more
/// information.
pub type AssertNoDanglingItemsTraversal<'ctx, 'gen> =
ItemTraversal<'ctx,
'gen,
Paths<'ctx, 'gen>,
VecDeque<ItemId>,
for<'a> fn(&'a BindgenContext, Edge) -> bool>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[allow(dead_code)]
fn traversal_predicate_is_object_safe() {
// This should compile only if TraversalPredicate is object safe.
fn takes_by_trait_object(_: &TraversalPredicate) {}
}
}

1294
third_party/rust/bindgen-0.29.0/src/ir/ty.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

360
third_party/rust/bindgen-0.29.0/src/ir/var.rs поставляемый
Просмотреть файл

@ -1,360 +0,0 @@
//! Intermediate representation of variables.
use super::context::{BindgenContext, ItemId};
use super::dot::DotAttributes;
use super::function::cursor_mangling;
use super::int::IntKind;
use super::item::Item;
use super::ty::{FloatKind, TypeKind};
use cexpr;
use clang;
use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
use std::io;
use std::num::Wrapping;
/// The type for a constant variable.
#[derive(Debug)]
pub enum VarType {
/// A boolean.
Bool(bool),
/// An integer.
Int(i64),
/// A floating point number.
Float(f64),
/// A character.
Char(u8),
/// A string, not necessarily well-formed utf-8.
String(Vec<u8>),
}
/// A `Var` is our intermediate representation of a variable.
#[derive(Debug)]
pub struct Var {
/// The name of the variable.
name: String,
/// The mangled name of the variable.
mangled_name: Option<String>,
/// The type of the variable.
ty: ItemId,
/// The value of the variable, that needs to be suitable for `ty`.
val: Option<VarType>,
/// Whether this variable is const.
is_const: bool,
}
impl Var {
/// Construct a new `Var`.
pub fn new(name: String,
mangled: Option<String>,
ty: ItemId,
val: Option<VarType>,
is_const: bool)
-> Var {
assert!(!name.is_empty());
Var {
name: name,
mangled_name: mangled,
ty: ty,
val: val,
is_const: is_const,
}
}
/// Is this variable `const` qualified?
pub fn is_const(&self) -> bool {
self.is_const
}
/// The value of this constant variable, if any.
pub fn val(&self) -> Option<&VarType> {
self.val.as_ref()
}
/// Get this variable's type.
pub fn ty(&self) -> ItemId {
self.ty
}
/// Get this variable's name.
pub fn name(&self) -> &str {
&self.name
}
/// Get this variable's mangled name.
pub fn mangled_name(&self) -> Option<&str> {
self.mangled_name.as_ref().map(|n| &**n)
}
}
impl DotAttributes for Var {
fn dot_attributes<W>(&self,
_ctx: &BindgenContext,
out: &mut W)
-> io::Result<()>
where W: io::Write,
{
if self.is_const {
try!(writeln!(out, "<tr><td>const</td><td>true</td></tr>"));
}
if let Some(ref mangled) = self.mangled_name {
try!(writeln!(out,
"<tr><td>mangled name</td><td>{}</td></tr>",
mangled));
}
Ok(())
}
}
impl ClangSubItemParser for Var {
fn parse(cursor: clang::Cursor,
ctx: &mut BindgenContext)
-> Result<ParseResult<Self>, ParseError> {
use clang_sys::*;
use cexpr::expr::EvalResult;
use cexpr::literal::CChar;
match cursor.kind() {
CXCursor_MacroDefinition => {
if let Some(visitor) = ctx.parse_callbacks() {
visitor.parsed_macro(&cursor.spelling());
}
let value = parse_macro(ctx, &cursor, ctx.translation_unit());
let (id, value) = match value {
Some(v) => v,
None => return Err(ParseError::Continue),
};
assert!(!id.is_empty(), "Empty macro name?");
let previously_defined = ctx.parsed_macro(&id);
// NB: It's important to "note" the macro even if the result is
// not an integer, otherwise we might loose other kind of
// derived macros.
ctx.note_parsed_macro(id.clone(), value.clone());
if previously_defined {
let name = String::from_utf8(id).unwrap();
warn!("Duplicated macro definition: {}", name);
return Err(ParseError::Continue);
}
// NOTE: Unwrapping, here and above, is safe, because the
// identifier of a token comes straight from clang, and we
// enforce utf8 there, so we should have already panicked at
// this point.
let name = String::from_utf8(id).unwrap();
let (type_kind, val) = match value {
EvalResult::Invalid => return Err(ParseError::Continue),
EvalResult::Float(f) => {
(TypeKind::Float(FloatKind::Double), VarType::Float(f))
}
EvalResult::Char(c) => {
let c = match c {
CChar::Char(c) => {
assert_eq!(c.len_utf8(), 1);
c as u8
}
CChar::Raw(c) => {
assert!(c <= ::std::u8::MAX as u64);
c as u8
}
};
(TypeKind::Int(IntKind::U8), VarType::Char(c))
}
EvalResult::Str(val) => {
let char_ty =
Item::builtin_type(TypeKind::Int(IntKind::U8),
true,
ctx);
(TypeKind::Pointer(char_ty), VarType::String(val))
}
EvalResult::Int(Wrapping(value)) => {
let kind = ctx.parse_callbacks()
.and_then(|c| c.int_macro(&name, value))
.unwrap_or_else(|| if value < 0 {
if value < i32::min_value() as i64 {
IntKind::LongLong
} else {
IntKind::Int
}
} else if value > u32::max_value() as i64 {
IntKind::ULongLong
} else {
IntKind::UInt
});
(TypeKind::Int(kind), VarType::Int(value))
}
};
let ty = Item::builtin_type(type_kind, true, ctx);
Ok(ParseResult::New(Var::new(name, None, ty, Some(val), true),
Some(cursor)))
}
CXCursor_VarDecl => {
let name = cursor.spelling();
if name.is_empty() {
warn!("Empty constant name?");
return Err(ParseError::Continue);
}
let ty = cursor.cur_type();
// XXX this is redundant, remove!
let is_const = ty.is_const();
let ty = match Item::from_ty(&ty, cursor, None, ctx) {
Ok(ty) => ty,
Err(e) => {
assert_eq!(ty.kind(),
CXType_Auto,
"Couldn't resolve constant type, and it \
wasn't an nondeductible auto type!");
return Err(e);
}
};
// Note: Ty might not be totally resolved yet, see
// tests/headers/inner_const.hpp
//
// That's fine because in that case we know it's not a literal.
let canonical_ty = ctx.safe_resolve_type(ty)
.and_then(|t| t.safe_canonical_type(ctx));
let is_integer = canonical_ty.map_or(false, |t| t.is_integer());
let is_float = canonical_ty.map_or(false, |t| t.is_float());
// TODO: We could handle `char` more gracefully.
// TODO: Strings, though the lookup is a bit more hard (we need
// to look at the canonical type of the pointee too, and check
// is char, u8, or i8 I guess).
let value = if is_integer {
let kind = match *canonical_ty.unwrap().kind() {
TypeKind::Int(kind) => kind,
_ => unreachable!(),
};
let mut val = cursor.evaluate()
.and_then(|v| v.as_int())
.map(|val| val as i64);
if val.is_none() || !kind.signedness_matches(val.unwrap()) {
let tu = ctx.translation_unit();
val = get_integer_literal_from_cursor(&cursor, tu);
}
val.map(|val| if kind == IntKind::Bool {
VarType::Bool(val != 0)
} else {
VarType::Int(val)
})
} else if is_float {
cursor.evaluate()
.and_then(|v| v.as_double())
.map(VarType::Float)
} else {
cursor.evaluate()
.and_then(|v| v.as_literal_string())
.map(VarType::String)
};
let mangling = cursor_mangling(ctx, &cursor);
let var = Var::new(name, mangling, ty, value, is_const);
Ok(ParseResult::New(var, Some(cursor)))
}
_ => {
/* TODO */
Err(ParseError::Continue)
}
}
}
}
/// Try and parse a macro using all the macros parsed until now.
fn parse_macro(ctx: &BindgenContext,
cursor: &clang::Cursor,
unit: &clang::TranslationUnit)
-> Option<(Vec<u8>, cexpr::expr::EvalResult)> {
use cexpr::{expr, nom};
let mut cexpr_tokens = match unit.cexpr_tokens(cursor) {
None => return None,
Some(tokens) => tokens,
};
let parser = expr::IdentifierParser::new(ctx.parsed_macros());
match parser.macro_definition(&cexpr_tokens) {
nom::IResult::Done(_, (id, val)) => {
return Some((id.into(), val));
}
_ => {}
}
// Try without the last token, to workaround a libclang bug in versions
// previous to 4.0.
//
// See:
// https://bugs.llvm.org//show_bug.cgi?id=9069
// https://reviews.llvm.org/D26446
if cexpr_tokens.pop().is_none() {
return None;
}
match parser.macro_definition(&cexpr_tokens) {
nom::IResult::Done(_, (id, val)) => {
Some((id.into(), val))
}
_ => None
}
}
fn parse_int_literal_tokens(cursor: &clang::Cursor,
unit: &clang::TranslationUnit)
-> Option<i64> {
use cexpr::{expr, nom};
use cexpr::expr::EvalResult;
let cexpr_tokens = match unit.cexpr_tokens(cursor) {
None => return None,
Some(tokens) => tokens,
};
// TODO(emilio): We can try to parse other kinds of literals.
match expr::expr(&cexpr_tokens) {
nom::IResult::Done(_, EvalResult::Int(Wrapping(val))) => Some(val),
_ => None,
}
}
fn get_integer_literal_from_cursor(cursor: &clang::Cursor,
unit: &clang::TranslationUnit)
-> Option<i64> {
use clang_sys::*;
let mut value = None;
cursor.visit(|c| {
match c.kind() {
CXCursor_IntegerLiteral |
CXCursor_UnaryOperator => {
value = parse_int_literal_tokens(&c, unit);
}
CXCursor_UnexposedExpr => {
value = get_integer_literal_from_cursor(&c, unit);
}
_ => (),
}
if value.is_some() {
CXChildVisit_Break
} else {
CXChildVisit_Continue
}
});
value
}

1448
third_party/rust/bindgen-0.29.0/src/lib.rs поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,30 +0,0 @@
macro_rules! log {
(target: $target:expr, $lvl:expr, $($arg:tt)+) => {
let _ = $target;
let _ = log!($lvl, $($arg)+);
};
($lvl:expr, $($arg:tt)+) => {{
let _ = $lvl;
let _ = format_args!($($arg)+);
}};
}
macro_rules! error {
(target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); };
($($arg:tt)*) => { log!("", $($arg)*); };
}
macro_rules! warn {
(target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); };
($($arg:tt)*) => { log!("", $($arg)*); };
}
macro_rules! info {
(target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); };
($($arg:tt)*) => { log!("", $($arg)*); };
}
macro_rules! debug {
(target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); };
($($arg:tt)*) => { log!("", $($arg)*); };
}
macro_rules! trace {
(target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); };
($($arg:tt)*) => { log!("", $($arg)*); };
}

88
third_party/rust/bindgen-0.29.0/src/main.rs поставляемый
Просмотреть файл

@ -1,88 +0,0 @@
extern crate bindgen;
#[cfg(feature="logging")]
extern crate env_logger;
#[macro_use]
#[cfg(feature="logging")]
extern crate log;
extern crate clang_sys;
extern crate clap;
use bindgen::clang_version;
use std::env;
use std::panic;
#[macro_use]
#[cfg(not(feature="logging"))]
mod log_stubs;
mod options;
use options::builder_from_flags;
pub fn main() {
#[cfg(feature="logging")]
log::set_logger(|max_log_level| {
use env_logger::Logger;
let env_logger = Logger::new();
max_log_level.set(env_logger.filter());
Box::new(env_logger)
})
.expect("Failed to set logger.");
let bind_args: Vec<_> = env::args().collect();
let version = clang_version();
let expected_version = if cfg!(feature = "testing_only_libclang_4") {
(4, 0)
} else if cfg!(feature = "testing_only_libclang_3_8") {
(3, 8)
} else {
// Default to 3.9.
(3, 9)
};
info!("Clang Version: {}", version.full);
match version.parsed {
None => warn!("Couldn't parse libclang version"),
Some(version) if version != expected_version => {
warn!("Using clang {:?}, expected {:?}", version, expected_version);
}
_ => {}
}
match builder_from_flags(bind_args.into_iter()) {
Ok((builder, output, verbose)) => {
let builder_result = panic::catch_unwind(|| {
builder.generate().expect("Unable to generate bindings")
});
if builder_result.is_err() {
if verbose {
print_verbose_err();
}
std::process::exit(1);
}
let mut bindings = builder_result.unwrap();
bindings.write(output)
.expect("Unable to write output");
bindings.write_dummy_uses()
.expect("Unable to write dummy uses to file.");
}
Err(error) => {
println!("{}", error);
std::process::exit(1);
}
};
}
fn print_verbose_err() {
println!("Bindgen unexpectedly panicked");
println!("This may be caused by one of the known-unsupported \
things (https://github.com/rust-lang-nursery/rust-bindgen#c), \
please modify the bindgen flags to work around it as \
described in https://github.com/rust-lang-nursery/rust-bindgen#c");
println!("Otherwise, please file an issue at \
https://github.com/rust-lang-nursery/rust-bindgen/issues/new");
}

441
third_party/rust/bindgen-0.29.0/src/options.rs поставляемый
Просмотреть файл

@ -1,441 +0,0 @@
use bindgen::{Builder, CodegenConfig, builder};
use clap::{App, Arg};
use std::fs::File;
use std::io::{self, Error, ErrorKind};
/// Construct a new [`Builder`](./struct.Builder.html) from command line flags.
pub fn builder_from_flags<I>
(args: I)
-> Result<(Builder, Box<io::Write>, bool), io::Error>
where I: Iterator<Item = String>,
{
let matches = App::new("bindgen")
.version(env!("CARGO_PKG_VERSION"))
.about("Generates Rust bindings from C/C++ headers.")
.usage("bindgen [FLAGS] [OPTIONS] <header> -- <clang-args>...")
.args(&[
Arg::with_name("header")
.help("C or C++ header file")
.required(true),
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.")
.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 set of \
constants instead of an enumeration.")
.value_name("regex")
.takes_value(true)
.multiple(true)
.number_of_values(1),
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 an enumeration. This option \
implies \"--constified-enum.\"")
.value_name("regex")
.takes_value(true)
.multiple(true)
.number_of_values(1),
Arg::with_name("blacklist-type")
.long("blacklist-type")
.help("Mark <type> as hidden.")
.value_name("type")
.takes_value(true)
.multiple(true)
.number_of_values(1),
Arg::with_name("no-layout-tests")
.long("no-layout-tests")
.help("Avoid generating layout tests for any type."),
Arg::with_name("no-derive-debug")
.long("no-derive-debug")
.help("Avoid deriving Debug on any type."),
Arg::with_name("no-derive-default")
.long("no-derive-default")
.hidden(true)
.help("Avoid deriving Default on any type."),
Arg::with_name("with-derive-default")
.long("with-derive-default")
.help("Derive Default on any type."),
Arg::with_name("no-doc-comments")
.long("no-doc-comments")
.help("Avoid including doc comments in the output, see: \
https://github.com/rust-lang-nursery/rust-bindgen/issues/426"),
Arg::with_name("no-recursive-whitelist")
.long("no-recursive-whitelist")
.help("Avoid whitelisting types recursively."),
Arg::with_name("objc-extern-crate")
.long("objc-extern-crate")
.help("Use extern crate instead of use for objc."),
Arg::with_name("distrust-clang-mangling")
.long("distrust-clang-mangling")
.help("Do not trust the libclang-provided mangling"),
Arg::with_name("builtins")
.long("builtins")
.help("Output bindings for builtin definitions, e.g. \
__builtin_va_list."),
Arg::with_name("ctypes-prefix")
.long("ctypes-prefix")
.help("Use the given prefix before raw types instead of \
::std::os::raw.")
.value_name("prefix")
.takes_value(true),
// All positional arguments after the end of options marker, `--`
Arg::with_name("clang-args")
.multiple(true),
Arg::with_name("dummy-uses")
.long("dummy-uses")
.help("For testing purposes, generate a C/C++ file containing \
dummy uses of all types defined in the input header.")
.takes_value(true),
Arg::with_name("emit-clang-ast")
.long("emit-clang-ast")
.help("Output the Clang AST for debugging purposes."),
Arg::with_name("emit-ir")
.long("emit-ir")
.help("Output our internal IR for debugging purposes."),
Arg::with_name("emit-ir-graphviz")
.long("emit-ir-graphviz")
.help("Dump graphviz dot file.")
.value_name("path")
.takes_value(true),
Arg::with_name("enable-cxx-namespaces")
.long("enable-cxx-namespaces")
.help("Enable support for C++ namespaces."),
Arg::with_name("disable-name-namespacing")
.long("disable-name-namespacing")
.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 \
is useful when you only care about struct layouts."),
Arg::with_name("generate")
.long("generate")
.help("Generate only given items, split by commas. \
Valid values are \"functions\",\"types\", \"vars\", \
\"methods\", \"constructors\" and \"destructors\".")
.takes_value(true),
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."),
Arg::with_name("no-prepend-enum-name")
.long("no-prepend-enum-name")
.help("Do not prepend the enum name to bitfield or constant variants."),
Arg::with_name("unstable-rust")
.long("unstable-rust")
.help("Generate unstable Rust code.")
.multiple(true), // FIXME: Pass legacy test suite
Arg::with_name("opaque-type")
.long("opaque-type")
.help("Mark <type> as opaque.")
.value_name("type")
.takes_value(true)
.multiple(true)
.number_of_values(1),
Arg::with_name("output")
.short("o")
.long("output")
.help("Write Rust bindings to <output>.")
.takes_value(true),
Arg::with_name("raw-line")
.long("raw-line")
.help("Add a raw line of Rust code at the beginning of output.")
.takes_value(true)
.multiple(true)
.number_of_values(1),
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."),
Arg::with_name("conservative-inline-namespaces")
.long("conservative-inline-namespaces")
.help("Conservatively generate inline namespaces to avoid name \
conflicts."),
Arg::with_name("use-msvc-mangling")
.long("use-msvc-mangling")
.help("MSVC C++ ABI mangling. DEPRECATED: Has no effect."),
Arg::with_name("whitelist-function")
.long("whitelist-function")
.help("Whitelist all the free-standing functions matching \
<regex>. Other non-whitelisted functions will not be \
generated.")
.value_name("regex")
.takes_value(true)
.multiple(true)
.number_of_values(1),
Arg::with_name("generate-inline-functions")
.long("generate-inline-functions")
.help("Generate inline functions."),
Arg::with_name("whitelist-type")
.long("whitelist-type")
.help("Whitelist the type. Other non-whitelisted types will \
not be generated.")
.value_name("type")
.takes_value(true)
.multiple(true)
.number_of_values(1),
Arg::with_name("whitelist-var")
.long("whitelist-var")
.help("Whitelist all the free-standing variables matching \
<regex>. Other non-whitelisted variables will not be \
generated.")
.value_name("regex")
.takes_value(true)
.multiple(true)
.number_of_values(1),
Arg::with_name("verbose")
.long("verbose")
.help("Print verbose error messages."),
Arg::with_name("dump-preprocessed-input")
.long("dump-preprocessed-input")
.help("Preprocess and dump the input header files to disk. \
Useful when debugging bindgen, using C-Reduce, or when \
filing issues. The resulting file will be named \
something like `__bindgen.i` or `__bindgen.ii`.")
]) // .args()
.get_matches_from(args);
let mut builder = builder();
if let Some(header) = matches.value_of("header") {
builder = builder.header(header);
} else {
return Err(Error::new(ErrorKind::Other, "Header not found"));
}
if let Some(bitfields) = matches.values_of("bitfield-enum") {
for regex in bitfields {
builder = builder.bitfield_enum(regex);
}
}
if let Some(constifieds) = matches.values_of("constified-enum") {
for regex in constifieds {
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);
}
}
if let Some(hidden_types) = matches.values_of("blacklist-type") {
for ty in hidden_types {
builder = builder.hide_type(ty);
}
}
if matches.is_present("builtins") {
builder = builder.emit_builtins();
}
if matches.is_present("no-layout-tests") {
builder = builder.layout_tests(false);
}
if matches.is_present("no-derive-debug") {
builder = builder.derive_debug(false);
}
if matches.is_present("with-derive-default") {
builder = builder.derive_default(true);
}
if matches.is_present("no-derive-default") {
builder = builder.derive_default(false);
}
if matches.is_present("no-prepend-enum-name") {
builder = builder.prepend_enum_name(false);
}
if let Some(prefix) = matches.value_of("ctypes-prefix") {
builder = builder.ctypes_prefix(prefix);
}
if let Some(dummy) = matches.value_of("dummy-uses") {
builder = builder.dummy_uses(dummy);
}
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(",") {
match what {
"functions" => config.functions = true,
"types" => config.types = true,
"vars" => config.vars = true,
"methods" => config.methods = true,
"constructors" => config.constructors = true,
"destructors" => config.destructors = true,
otherwise => {
return Err(Error::new(ErrorKind::Other,
format!("Unknown generate item: {}",
otherwise)));
}
}
}
builder = builder.with_codegen_config(config);
}
if matches.is_present("emit-clang-ast") {
builder = builder.emit_clang_ast();
}
if matches.is_present("emit-ir") {
builder = builder.emit_ir();
}
if let Some(path) = matches.value_of("emit-ir-graphviz") {
builder = builder.emit_ir_graphviz(path);
}
if matches.is_present("enable-cxx-namespaces") {
builder = builder.enable_cxx_namespaces();
}
if matches.is_present("disable-name-namespacing") {
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();
}
if matches.is_present("ignore-methods") {
builder = builder.ignore_methods();
}
if matches.is_present("unstable-rust") {
builder = builder.unstable_rust(true);
}
if matches.is_present("no-convert-floats") {
builder = builder.no_convert_floats();
}
if matches.is_present("no-doc-comments") {
builder = builder.generate_comments(false);
}
if matches.is_present("no-recursive-whitelist") {
builder = builder.whitelist_recursively(false);
}
if matches.is_present("objc-extern-crate") {
builder = builder.objc_extern_crate(true);
}
if let Some(opaque_types) = matches.values_of("opaque-type") {
for ty in opaque_types {
builder = builder.opaque_type(ty);
}
}
if let Some(lines) = matches.values_of("raw-line") {
for line in lines {
builder = builder.raw_line(line);
}
}
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();
}
if matches.is_present("distrust-clang-mangling") {
builder = builder.trust_clang_mangling(false);
}
if matches.is_present("conservative-inline-namespaces") {
builder = builder.conservative_inline_namespaces();
}
if matches.is_present("generate-inline-functions") {
builder = builder.generate_inline_functions(true);
}
if let Some(whitelist) = matches.values_of("whitelist-function") {
for regex in whitelist {
builder = builder.whitelisted_function(regex);
}
}
if let Some(whitelist) = matches.values_of("whitelist-type") {
for regex in whitelist {
builder = builder.whitelisted_type(regex);
}
}
if let Some(whitelist) = matches.values_of("whitelist-var") {
for regex in whitelist {
builder = builder.whitelisted_var(regex);
}
}
if let Some(args) = matches.values_of("clang-args") {
for arg in args {
builder = builder.clang_arg(arg);
}
}
let output = if let Some(path) = matches.value_of("output") {
let file = try!(File::create(path));
Box::new(io::BufWriter::new(file)) as Box<io::Write>
} else {
Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>
};
if matches.is_present("dump-preprocessed-input") {
builder.dump_preprocessed_input()?;
}
let verbose = matches.is_present("verbose");
Ok((builder, output, verbose))
}

94
third_party/rust/bindgen-0.29.0/src/parse.rs поставляемый
Просмотреть файл

@ -1,94 +0,0 @@
//! Common traits and types related to parsing our IR from Clang cursors.
use clang;
use ir::context::{BindgenContext, ItemId};
use ir::ty::TypeKind;
/// Not so much an error in the traditional sense, but a control flow message
/// when walking over Clang's AST with a cursor.
#[derive(Debug)]
pub enum ParseError {
/// Recurse down the current AST node's children.
Recurse,
/// Continue on to the next sibling AST node, or back up to the parent's
/// siblings if we've exhausted all of this node's siblings (and so on).
Continue,
}
/// The result of parsing a Clang AST node.
#[derive(Debug)]
pub enum ParseResult<T> {
/// We've already resolved this item before, here is the extant `ItemId` for
/// it.
AlreadyResolved(ItemId),
/// This is a newly parsed item. If the cursor is `Some`, it points to the
/// AST node where the new `T` was declared.
New(T, Option<clang::Cursor>),
}
/// An intermediate representation "sub-item" (i.e. one of the types contained
/// inside an `ItemKind` variant) that can be parsed from a Clang cursor.
pub trait ClangSubItemParser: Sized {
/// Attempt to parse this type from the given cursor.
///
/// The fact that is a reference guarantees it's held by the context, and
/// allow returning already existing types.
fn parse(cursor: clang::Cursor,
context: &mut BindgenContext)
-> Result<ParseResult<Self>, ParseError>;
}
/// An intermediate representation item that can be parsed from a Clang cursor.
pub trait ClangItemParser: Sized {
/// Parse this item from the given Clang cursor.
fn parse(cursor: clang::Cursor,
parent: Option<ItemId>,
context: &mut BindgenContext)
-> Result<ItemId, ParseError>;
/// Parse this item from the given Clang type.
fn from_ty(ty: &clang::Type,
location: clang::Cursor,
parent: Option<ItemId>,
ctx: &mut BindgenContext)
-> Result<ItemId, ParseError>;
/// Identical to `from_ty`, but use the given `id` as the `ItemId` for the
/// newly parsed item.
fn from_ty_with_id(id: ItemId,
ty: &clang::Type,
location: clang::Cursor,
parent: Option<ItemId>,
ctx: &mut BindgenContext)
-> Result<ItemId, ParseError>;
/// Parse this item from the given Clang type, or if we haven't resolved all
/// the other items this one depends on, an unresolved reference.
fn from_ty_or_ref(ty: clang::Type,
location: clang::Cursor,
parent_id: Option<ItemId>,
context: &mut BindgenContext)
-> ItemId;
/// Identical to `from_ty_or_ref`, but use the given `potential_id` as the
/// `ItemId` for the newly parsed item.
fn from_ty_or_ref_with_id(potential_id: ItemId,
ty: clang::Type,
location: clang::Cursor,
parent_id: Option<ItemId>,
context: &mut BindgenContext)
-> ItemId;
/// Create a named template type.
fn named_type(with_id: Option<ItemId>,
location: clang::Cursor,
ctx: &mut BindgenContext)
-> Option<ItemId>;
/// Create a builtin type.
fn builtin_type(kind: TypeKind,
is_const: bool,
context: &mut BindgenContext)
-> ItemId;
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше