91 Commits
Author SHA1 Message Date
pancake 0c3277646a Remove Travis badge - no longer used 2026-03-09 23:46:37 +01:00
pancake c504deaff8 Update the CI badge 2026-03-09 23:46:16 +01:00
pancake 7cd1560585 Add support for Windows 2026-03-09 23:41:26 +01:00
pancake ee36c46657 Use libload instead of dlopen for portability reasons 2026-02-20 16:00:28 +01:00
Jonathan Creekmore 1208b28183 Provide a proper Default impl for R2PipeSpawnOptions 2023-06-08 18:28:46 -04:00
RHL120 522a9f7a4f Fix docs link in README 2022-12-30 13:05:38 -05:00
meme 89db8759ce 0.7.0 2022-12-29 12:17:09 -05:00
RHL120 a66ddad123 Add support for radare as a shlib 2022-12-29 10:40:29 -05:00
RHL120 50c689f4bc Install radare2 in CI and add a simple test 2022-12-29 10:15:35 -05:00
RHL120 c0260db239 Fix an issue with Windows 2022-12-25 08:26:35 -05:00
RHL120 14079c97e9 Add call and callj methods 2022-12-17 12:09:35 -05:00
RHL120 43b68268ca Add default implementation for cmdj 2022-12-07 17:25:44 -05:00
RHL120 8cb8d248a8 Box pipe code 2022-12-07 17:25:01 -05:00
RHL120 e67a685a5b Clean up in_session code 2022-12-07 17:19:36 -05:00
RHL120 08335660d4 Clean up code in R2Pipe
* Remove some repeated code
* Add a default implementation for close
2022-11-14 13:55:19 -05:00
meme 32572abbb2 0.6.0 2021-12-04 19:57:07 -05:00
aemmitt-ns ee3fee9bb4 Merge pull request #42 from aemmitt-ns/reqwestless
replace single reqwest::get with tcpstream, remove dependency
2021-12-04 12:19:23 -05:00
aemmitt 4ee88ba031 use write_all, appease clippy 2021-12-04 11:44:17 -05:00
aemmitt 3796776e11 correct format 2021-12-04 11:39:38 -05:00
aemmitt a622e4926c replace single reqwest::get with tcpstream, remove dependency 2021-12-04 11:25:55 -05:00
Cyrill Leutwiler 9310015b18 Taking Pipe child process handle 2021-05-26 20:06:02 -04:00
Cyrill Leutwiler 8dae2fcb73 Wait for child on close (#40) 2021-05-22 08:51:13 -04:00
meme 15a83699ae Result and Error (#39)
* Result and Error

Instead of unwrapping or panicking haphazardly, instead use a unified
error type

* Update Error for reqwest

* Update examples to use Result
2021-05-21 10:03:02 -04:00
memeandmeme 3950fe4f0d Add clippy and fmt to CI (#38)
Co-authored-by: meme <[email protected]>
2021-05-16 12:06:11 -04:00
memeandmeme 591ac5c1b8 Move reqwest into an "http" feature (#37)
This is a very heavy dependency, and most may not need it. Instead it
should be a compile-time option.

Co-authored-by: meme <[email protected]>
2021-05-15 09:06:11 +02:00
Aswin C c2858b09d7 Bumb up some of the dependencies' versions (#36) 2021-01-01 16:21:49 +01:00
pancake eec57de9d6 Stick libc version 2020-06-13 18:19:36 +02:00
Cyrill Leutwiler 924eff860d Update README.md
Some more love for this crate
2020-06-13 01:20:53 +08:00
Anton Kochkov 08ab5a8f32 Add GitHub Actions 2020-06-12 13:15:36 +08:00
Anton Kochkov 5f1c34eb8d Better Travis CI configuration 2020-06-12 13:15:36 +08:00
Anton Kochkov 3b631b623e Fix formatting 2020-06-12 13:15:36 +08:00
Anton Kochkov 71f3fa40f0 Upgrade to Rust 2018 2020-06-12 13:15:36 +08:00
pancake b8a8c07ab6 Update dependencies #33 2020-06-11 20:57:01 +02:00
xermicus 76fa9f540b remove warnings in cargo test 2020-06-11 20:14:17 +02:00
xermicus a951524738 update deps and fix lints 2020-06-11 20:09:48 +02:00
Anton Kochkov 7c189bd4a7 Update reqwest dependency 2019-05-30 20:02:57 +08:00
Anton Kochkov f2fe7c74f9 Merge pull request #30 from xermicus/async
Add callback support in async api
2018-10-15 19:35:22 +08:00
0xrmc 6abb084735 add callback support in async api 2018-10-10 21:14:18 +02:00
0xrmc 43ad9657df add support for threads 2018-09-16 00:38:09 +02:00
kriw 61aa661f32 Update README.md 2018-08-10 18:40:23 +02:00
kriw 2494daf0ab Add example 2018-08-10 18:40:23 +02:00
kriw c1135945a6 Support Http interface 2018-08-10 18:40:23 +02:00
HMPerson1 07e22c8c01 Add appveyor.yml 2018-08-01 05:34:43 +01:00
HMPerson1 c75fd773da Fix build on windows 2018-08-01 05:34:43 +01:00
Michael Zhang c7476920c4 Update README.md 2018-07-28 09:09:05 +01:00
HMPerson1 5ddfda5a5d Add support TCP connections 2018-07-28 05:11:50 +01:00
HMPerson1 a2323b759f Remove clippy dependency
clippy now ships with rustup
2018-07-28 05:11:50 +01:00
Chinmay Deshpande 09622db2aa Removes higher level API functions from r2pipe.rs (#23)
* This aims to make the following changes:

* Remove all higher-level structs
* Remove certain functions used to interact with the r2 instance and
retrieve specific information

This functionality aims to be moved to r2pipe.rs-frontend repository.

* Removes outdated test, bumps version

* Removes init()
2017-07-15 22:15:43 +02:00
Joe Rozner 1972186180 Replace rustc_serialize with serde 2017-06-12 11:42:48 +02:00
Sushant 110dc301e2 Fixes local variable information
Closes #17
2016-12-30 19:12:47 -05:00
Chinmay Deshpande fdd1c5a329 Aims to fix the following issues: (#16)
* #15: which deals with usage of excess 'a' for r2 analysis call.
* If no function locals were found, a 'null' was written into the JSON
  which resulted in a parser error
* Unrequired usage of struct `Foo`
2016-12-28 10:04:41 +01:00
Sushant 23018f8320 Updates struct to reflect changes in r2 2016-07-14 21:35:07 +05:30
Sushant 3ee0bc88a6 Merge branch 'master' of github.com:radare/r2pipe.rs 2016-07-03 19:24:48 +05:30
Sushant c2aabb0daf Adds local vars information to functions 2016-07-03 19:24:33 +05:30
Sushant bed6e45e9c Uses specific version of dependencies 2016-06-29 14:05:01 +05:30
pancake 18d090c6ac Release 0.4.0 2016-06-29 10:24:21 +02:00
Sushant c5f5c0c614 Fixes FunctionInfo struct 2016-06-29 02:46:54 +05:30
Sushant 2bd48b5e64 Adds structs and helpers for strings 2016-06-20 13:52:25 +05:30
Sushant c972f48f8b Adds methods for fn_list and sections 2016-06-20 11:39:29 +05:30
Sushant d703d0448d Adds Function and SectionInfo 2016-06-20 09:26:32 +05:30
pancake b31c0ade0f Fix #11 - Add Travis badge in README 2016-06-08 10:35:23 +02:00
pancake 9ad7dbd790 Fix #4 - Trim all commands and results 2016-06-08 10:32:56 +02:00
pancake a816bc59b8 Support spawn path and args and bump to 0.3.0 2016-06-08 10:14:24 +02:00
pancake 9092dc8b91 in_windows_session returns the pipe path instead of bool 2016-06-06 13:23:56 +02:00
pancake 35963bdbfb Add in_windows_session() 2016-06-06 13:03:15 +02:00
pancake 21251d915b Use travis cache 2016-05-18 02:47:42 +02:00
pancake b86025045e Add .travis for r2pipe.rs 2016-05-18 02:45:23 +02:00
pancake 9f09bb40a4 Update indentation with latest rustfmt 2016-05-18 02:42:44 +02:00
Sushant de2a88d0f9 Fixes warnings from rust-clippy 2016-04-05 04:24:45 +05:30
Sushant 5c69423830 Adds rust-clippy as an optional dependency 2016-04-05 04:13:37 +05:30
Sushant 4bf320b8be Adds default implementation for r2::R2 2016-04-05 04:06:23 +05:30
Sushant 91771f18b1 Adds opcode-size field to LOpInfo 2016-02-04 11:14:06 +05:30
pancake d0a177df9b Use MIT/Apache-2.0 license 2016-01-22 10:12:35 +01:00
pancake 221496f7c6 Rustfmt all the examples 2015-12-10 10:40:41 +01:00
pancake b047dabba3 Avoid spurious panic in JSON unwrapping, add example program 2015-12-10 10:40:02 +01:00
Sushant 10f6b3362e Import r2 module from radeco-lib
- Adds rustfmt.toml to standardize styling
2015-11-12 19:31:05 +05:30
pancake 260bbf1bac Some advances in the async api 2015-10-13 00:33:28 +02:00
pancake 7cf052ae81 Chilling out a bit with the async r2pipe for rust 2015-10-12 18:42:37 +02:00
pancake 67727d8d35 Use libc::dup to avoid from_raw_fd ownership issues 2015-09-22 12:47:20 +02:00
pancake e1036a75e3 Add another example 2015-09-22 12:44:26 +02:00
pancake ecfb1112fc Better ignore-return-value thing 2015-09-21 12:09:02 +02:00
pancake 45885f32d4 cmd calls use Result now, support zero fdin/out for pipe 2015-09-21 11:58:13 +02:00
Sushant 29e6d7eaed Merge branch 'master' of github.com:radare/r2pipe.rs 2015-09-16 18:28:44 +05:30
Sushant 9e258cfe5b Updates open_pipe! macro to use Option
open_pipe! now uses Option<&str> rather than having two separate macro
matches for R2Pipe and R2PipeSpawn
2015-09-16 18:21:46 +05:30
David Kreuter b55306245c Use same read/write code for R2PipeSpawn and R2PipeLang 2015-08-07 04:38:53 +02:00
Sushant bbc6ddab62 Moves src/examples to examples/ 2015-08-06 23:36:53 +05:30
Sushant Dinesh 8f89f70075 Merge pull request #1 from dkreuter/master
Use rust's buffered reader
2015-08-06 23:30:47 +05:30
David Kreuter a8831ddb99 Use rust's buffered reader 2015-08-06 19:50:38 +02:00
Sushant c784cc4f8b Ready for release 2015-06-12 02:10:56 +05:30
Sushant 2d685c612e Getting ready for release 2015-06-12 01:40:07 +05:30
pancake f0bc663342 Import radare2-bindings/r2pipe/rust 2015-06-11 21:51:14 +02:00
51 changed files with 1447 additions and 3031 deletions

No files matched your search

+60
View File
@@ -0,0 +1,60 @@
name: ci
env:
R2V: 6.1.0
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build_and_test:
name: R2pipe.rs (Ubuntu)
runs-on: ubuntu-latest
steps:
- run: wget https://github.com/radareorg/radare2/releases/download/${{env.R2V}}/radare2_${{env.R2V}}_amd64.deb && sudo dpkg -i radare2*.deb
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- run: rustup component add rustfmt clippy
- uses: actions-rs/cargo@v1
name: Building
with:
command: build
args: --release --all-features
- uses: actions-rs/cargo@v1
name: Testing
with:
command: test
- uses: actions-rs/cargo@v1
name: Format
with:
command: fmt
args: --all -- --check
- uses: actions-rs/cargo@v1
name: Clippy
with:
command: clippy
args: -- -D warnings
build_and_test_windows:
name: R2pipe.rs (Windows)
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Install radare2
run: |
Invoke-WebRequest -Uri "https://github.com/radareorg/radare2/releases/download/${{env.R2V}}/radare2-${{env.R2V}}-w64.zip" -OutFile "radare2.zip"
Expand-Archive -Path "radare2.zip" -DestinationPath "C:\radare2"
$r2path = (Get-ChildItem -Path "C:\radare2" -Directory | Select-Object -First 1).FullName
echo "$r2path\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- uses: dtolnay/rust-toolchain@stable
- run: cargo build --release --all-features
- run: cargo test
+3
View File
@@ -0,0 +1,3 @@
target
Cargo.lock
*.swp
View File
Whitespace-only changes.
View File
Whitespace-only changes.
+30
View File
@@ -0,0 +1,30 @@
language: rust
jobs:
include:
- rust: 1.41.0
env:
- ALL=' '
- rust: stable
env:
- CHECKFMT=1
- rust: beta
- rust: nightly
- rust: nightly
env:
- BENCH=1
branches:
only:
- master
before_script:
- |
if [ "${CHECKFMT}" == "1"]; then
rustup component add rustfmt --toolchain stable
fi
script:
- |
cargo build --verbose --no-default-features &&
cargo test --verbose --no-default-features &&
if [ "${CHECKFMT}" == "1"]; then
cargo +stable fmt -- --check
fi
+7
View File
@@ -0,0 +1,7 @@
Short version for non-lawyers:
The R2Pipe Project is dual-licensed under Apache 2.0 and MIT terms.
Longer version:
Read `LICENSE-MIT` and `LICENSE-APACHE`.
+33
View File
@@ -0,0 +1,33 @@
[package]
name = "r2pipe"
version = "0.7.0"
authors = [
"pancake <[email protected]>",
"sushant94 <[email protected]>"
]
edition = "2018"
description = "Library to interact with radare2 using r2pipes."
# Repository
repository = "https://github.com/radare/r2pipe.rs"
documentation = "https://radare.github.io/r2pipe.rs/"
keywords = ["r2", "debugger", "hex" , "editor", "radare"]
# Readme link
readme = "README.md"
# License information
license = "MIT OR Apache-2.0"
[features]
docsrs = []
http = []
[dependencies]
libloading = "0.8"
libc = "0.2"
serde = "1.0.118"
serde_json = "1.0.60"
serde_derive = "1.0.118"
thiserror = "1"
Binary file not shown.
Binary file not shown.
Binary file not shown.
+202
View File
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+22
View File
@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 radare
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.
+12
View File
@@ -0,0 +1,12 @@
all:
cargo build
clean:
cargo clean
doc:
cargo doc --no-deps
run:
r2 -qc '#!pipe target/debug/r2pipe' /bin/ls
target/debug/r2pipe
+38
View File
@@ -0,0 +1,38 @@
[![ci](https://github.com/radareorg/r2pipe.rs/actions/workflows/main.yml/badge.svg)](https://github.com/radareorg/r2pipe.rs/actions/workflows/main.yml)
[![Documentation](https://docs.rs/r2pipe/badge.svg)](https://docs.rs/r2pipe)
[![Cargo](https://img.shields.io/crates/v/r2pipe.svg)](https://crates.io/crates/r2pipe)
[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](
https://github.com/radareorg/r2pipe.rs)
r2pipe.rs
=========
The Rust Crate to interact with radare2.
Please check [Documentation](https://docs.rs/r2pipe/latest/r2pipe/) to get
started.
**NOTICE**
Structures and API functions have been moved to [radare2-r2pipe-api](https://github.com/radare/radare2-r2pipe-api)
repository. Please make sure you update your dependencies and imports.
TODO
----
* Support futures API
* Add custom r2 start flags for spawn method
* Better error handling
## License
Licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+16
View File
@@ -0,0 +1,16 @@
clone_depth: 1
environment:
matrix:
- TARGET: i686-pc-windows-msvc
- TARGET: x86_64-pc-windows-msvc
install:
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
- rustup-init.exe -y --default-host %TARGET% --default-toolchain nightly
- set PATH=%PATH%;%USERPROFILE%\.cargo\bin
- rustc -Vv
- cargo -Vv
build_script:
- cargo build -vv
test_script:
- cargo test -vv
deploy: off
+19
View File
@@ -0,0 +1,19 @@
all: main quit brokenpipe
main:
rustc -L ../target/debug/ -L ../target/debug/deps main.rs
r2 -qc '#!pipe ./main' /bin/ls
brokenpipe:
rustc -L ../target/debug/ -L ../target/debug/deps brokenpipe.rs
async:
rustc -L ../target/debug/ -L ../target/debug/deps async.rs
# r2 -qc '#!pipe ./async' /bin/ls
quit:
rustc -L ../target/debug/ -L ../target/debug/deps quit.rs
r2 -qc '#!pipe ./quit' /bin/ls
.PHONY: main quit async brokenpipe
+98
View File
@@ -0,0 +1,98 @@
use r2pipe::R2Pipe;
use std::sync::mpsc::channel;
use std::sync::mpsc::Receiver;
use std::sync::mpsc::Sender;
use std::sync::Arc;
use std::thread;
const FILENAME: &'static str = "/bin/ls";
pub struct R2PipeAsync {
tx: Sender<String>,
rx: Receiver<String>,
tx2: Sender<String>,
rx2: Receiver<String>,
cbs: Vec<Arc<dyn Fn(String)>>,
}
impl R2PipeAsync {
pub fn open() -> R2PipeAsync {
let (tx, rx) = channel(); // query
let (tx2, rx2) = channel(); // result
R2PipeAsync {
tx: tx,
rx: rx,
tx2: tx2,
rx2: rx2,
cbs: Vec::new(),
}
}
pub fn cmd(&mut self, str: &'static str, cb: Arc<dyn Fn(String)>) {
self.cbs.insert(0, cb);
self.tx.send(str.to_string()).unwrap();
}
pub fn quit(&mut self) {
self.tx.send("q".to_string()).unwrap();
}
pub fn mainloop(mut self) {
let child_rx = self.rx;
let child_tx = self.tx2.clone();
let child = thread::spawn(move || {
let mut r2p = match R2Pipe::in_session() {
Some(_) => R2Pipe::open(),
None => R2Pipe::spawn(FILENAME.to_owned(), None),
}
.unwrap();
loop {
let msg = child_rx.recv().unwrap();
if msg == "q" {
// push a result without callback
child_tx.send("".to_owned()).unwrap();
drop(child_tx);
break;
}
let res = r2p.cmd(&msg).unwrap();
child_tx.send(res).unwrap();
}
r2p.close();
});
// main loop
loop {
let msg = self.rx2.recv();
if msg.is_ok() {
let res = msg.unwrap();
if let Some(cb) = self.cbs.pop() {
cb(res.trim().to_string());
} else {
break;
}
} else {
break;
}
}
child.join().unwrap();
}
}
fn main() {
let mut r2pa = R2PipeAsync::open();
r2pa.cmd(
"?e One",
Arc::new(|x| {
println!("One: {}", x);
}),
);
r2pa.cmd(
"?e Two",
Arc::new(|x| {
println!("Two: {}", x);
}),
);
r2pa.quit();
r2pa.mainloop();
}
+21
View File
@@ -0,0 +1,21 @@
use r2pipe::Result;
fn main() -> Result<()> {
#[cfg(feature = "http")]
{
use r2pipe::R2Pipe;
use serde_json;
let mut r2p = R2Pipe::http("http://localhost:9080")?;
let json = r2p.cmdj("ij")?;
println!("{}", serde_json::to_string_pretty(&json)?);
println!("ARCH {}", json["bin"]["arch"]);
println!("BITS {}", json["bin"]["bits"]);
println!("Disasm:\n{}", r2p.cmd("pd 20")?);
println!("Hexdump:\n{}", r2p.cmd("px 64")?);
r2p.close();
}
Ok(())
}
+38
View File
@@ -0,0 +1,38 @@
use serde_json;
use r2pipe::R2PipeSpawnOptions;
use r2pipe::{R2Pipe, Result};
fn test_trim() -> Result<()> {
let mut ns = R2Pipe::spawn("/bin/ls".to_owned(), None)?;
println!("(({}))", ns.cmd("\n\n?e hello world\n\n")?);
println!("(({}))", ns.cmd("\n\n?e hello world\n\n")?);
println!("(({}))", ns.cmd("\n\n?e hello world\n\n")?);
ns.close();
Ok(())
}
fn main() -> Result<()> {
test_trim()?;
let opts = R2PipeSpawnOptions {
exepath: "radare2".to_owned(),
..Default::default()
};
let mut r2p = match R2Pipe::in_session() {
Some(_) => R2Pipe::open()?,
None => R2Pipe::spawn("/bin/ls".to_owned(), Some(opts))?,
};
println!("{}", r2p.cmd("?e Hello World")?);
let json = r2p.cmdj("ij")?;
println!("{}", serde_json::to_string_pretty(&json)?);
println!("ARCH {}", json["bin"]["arch"]);
println!("BITS {}", json["bin"]["bits"]);
println!("Disasm:\n{}", r2p.cmd("pd 20")?);
println!("Hexdump:\n{}", r2p.cmd("px 64")?);
r2p.close();
Ok(())
}
+20
View File
@@ -0,0 +1,20 @@
use r2pipe::{R2Pipe, Result};
fn main() -> Result<()> {
let mut r2p = R2Pipe::spawn("/bin/ls".to_owned(), None)?;
println!("{}", r2p.cmd("?e Hello")?);
if let Err(_) = r2p.cmd("q") {
// !killall r2") {
println!("Quit happens!");
} else {
println!("Quit failed/ignored!");
if let Ok(msg) = r2p.cmd("?e World") {
println!("{}", msg);
r2p.close();
} else {
println!("FAIL");
}
}
println!("Byebye");
Ok(())
}
+19
View File
@@ -0,0 +1,19 @@
use serde_json;
use r2pipe::{R2Pipe, Result};
fn main() -> Result<()> {
let mut r2p = R2Pipe::tcp("localhost:9080")?;
println!("{}", r2p.cmd("?e Hello World")?);
let json = r2p.cmdj("ij")?;
println!("{}", serde_json::to_string_pretty(&json)?);
println!("ARCH {}", json["bin"]["arch"]);
println!("BITS {}", json["bin"]["bits"]);
println!("Disasm:\n{}", r2p.cmd("pd 20")?);
println!("Hexdump:\n{}", r2p.cmd("px 64")?);
r2p.close();
Ok(())
}
+42
View File
@@ -0,0 +1,42 @@
use r2pipe::{R2Pipe, Result};
fn main() -> Result<()> {
// Lets spawn some r2pipes to open some binaries
// First two arguments for R2Pipe::threads() are the same as for R2Pipe::spawn() but inside vectors
// Third and last argument is an option of a callback function
let pipes = match R2Pipe::threads(
vec!["/bin/ls", "/bin/id", "/bin/cat"],
vec![None, None, None],
None,
) {
Ok(p) => p,
Err(e) => {
println!("Error spawning Pipes: {}", e);
return Ok(());
}
};
// At this point we can iter through all of our r2pipes and send some commands
for p in pipes.iter() {
if let Ok(_) = p.send("ij".to_string()) {};
}
// do_other_stuff_here();
// Lets iter again and see what the pipes got
for p in pipes.iter() {
// this will block, do "p.recv(false)" for non-blocking receive inside a loop
if let Ok(msg) = p.recv(true) {
println!("Pipe #{} says: {}", p.id, msg);
}
}
// Finally properly close all pipes
// Note: For "join()" we need to borrow so pipes.iter() won't work for this
for p in pipes {
if let Ok(_) = p.send("q".to_string()) {};
p.handle.join().unwrap()?;
}
Ok(())
}
+42
View File
@@ -0,0 +1,42 @@
use r2pipe::{R2Pipe, Result};
use std::sync::Arc;
fn main() -> Result<()> {
// First we define a callback. It doesn't block and gets called after a thread receives output from r2pipe
// Note: First argument to the callback is the thread id, second one the r2pipe output
let callback = Arc::new(|id, result| {
println!("Pipe #{} says: {}", id, result);
});
// First two arguments for R2Pipe::threads() are the same as for R2Pipe::spawn() but inside vectors
// Third and last argument is an option to a callback function
// The callback function takes two Arguments: Thread ID and r2pipe output
let pipes = match R2Pipe::threads(
vec!["/bin/ls", "/bin/id", "/bin/cat"],
vec![None, None, None],
Some(callback),
) {
Ok(p) => p,
Err(e) => {
println!("Error spawning Pipes: {}", e);
return Ok(());
}
};
// At this point we can iter through all of our r2pipes and send some commands
for p in pipes.iter() {
if let Ok(_) = p.send("ij".to_string()) {};
}
// Meanwhile: Expecting callbacks
std::thread::sleep(std::time::Duration::from_millis(1000));
// Finally properly close all pipes
// Note: For "join()" we need to borrow so pipes.iter() won't work for this
for p in pipes {
if let Ok(_) = p.send("q".to_string()) {};
p.handle.join().unwrap()?;
}
Ok(())
}
-1
View File
@@ -1 +0,0 @@
<meta http-equiv=refresh content=0;url=r2pipe/index.html>
Vendored
-4
View File
@@ -1,4 +0,0 @@
/*! jQuery v2.1.0 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k="".trim,l={},m=a.document,n="2.1.0",o=function(a,b){return new o.fn.init(a,b)},p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};o.fn=o.prototype={jquery:n,constructor:o,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=o.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return o.each(this,a,b)},map:function(a){return this.pushStack(o.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},o.extend=o.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||o.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(o.isPlainObject(d)||(e=o.isArray(d)))?(e?(e=!1,f=c&&o.isArray(c)?c:[]):f=c&&o.isPlainObject(c)?c:{},g[b]=o.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},o.extend({expando:"jQuery"+(n+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===o.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return a-parseFloat(a)>=0},isPlainObject:function(a){if("object"!==o.type(a)||a.nodeType||o.isWindow(a))return!1;try{if(a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(b){return!1}return!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=o.trim(a),a&&(1===a.indexOf("use strict")?(b=m.createElement("script"),b.text=a,m.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":k.call(a)},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?o.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),o.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||o.guid++,f):void 0},now:Date.now,support:l}),o.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=o.type(a);return"function"===c||o.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s="sizzle"+-new Date,t=a.document,u=0,v=0,w=eb(),x=eb(),y=eb(),z=function(a,b){return a===b&&(j=!0),0},A="undefined",B=1<<31,C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=D.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",M=L.replace("w","w#"),N="\\["+K+"*("+L+")"+K+"*(?:([*^$|!~]?=)"+K+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+M+")|)|)"+K+"*\\]",O=":("+L+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+N.replace(3,8)+")*)|.*)\\)|)",P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*")Line truncated
while(c--)d=g[c].name,0===d.indexOf("data-")&&(d=o.camelCase(d.slice(5)),P(f,d,e[d]));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=o.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),o.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||o.isArray(c)?d=L.access(a,b,o.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=o.queue(a,b),d=c.length,e=c.shift(),f=o._queueHooks(a,b),g=function(){o.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:o.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),o.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?o.queue(this[0],a):void 0===b?this:this.each(function(){var c=o.queue(this,a,b);o._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&o.dequeue(this,a)})},dequeue:function(a){return this.each(function(){o.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=o.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=L.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var Q=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,R=["Top","Right","Bottom","Left"],S=function(a,b){return a=b||a,"none"===o.css(a,"display")||!o.contains(a.ownerDocument,a)},T=/^(?:checkbox|radio)$/i;!function(){var a=m.createDocumentFragment(),b=a.appendChild(m.createElement("div"));b.innerHTML="<input type='radio' checked='checked' name='t'/>",l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";l.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return m.activeElement}catch(a){}}o.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=o.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof o!==U&&o.event.triggered!==b.type?o.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],n=q=h[1],p=(h[2]||"").split(".").sort(),n&&(l=o.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=o.event.special[n]||{},k=o.extend({type:n,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&o.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(n,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),o.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],n=q=h[1],p=(h[2]||"").split(".").sort(),n){l=o.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||o.removeEvent(a,n,r.handle),delete i[n])}else for(n in i)o.event.remove(a,n+b[j],c,d,!0);o.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,p=[d||m],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||m,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+o.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[o.expando]?b:new o.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:o.makeArray(c,[b]),n=o.event.special[q]||{},e||!n.trigger||n.trigger.apply(d,c)!==!1)){if(!e&&!n.noBubble&&!o.isWindow(d)){for(i=n.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||m)&&p.push(h.deLine truncated
return d||(f=$b[b],$b[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,$b[b]=f),e}});var _b=/^(?:input|select|textarea|button)$/i;o.fn.extend({prop:function(a,b){return J(this,o.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[o.propFix[a]||a]})}}),o.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!o.isXMLDoc(a),f&&(b=o.propFix[b]||b,e=o.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){return a.hasAttribute("tabindex")||_b.test(a.nodeName)||a.href?a.tabIndex:-1}}}}),l.optSelected||(o.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null}}),o.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){o.propFix[this.toLowerCase()]=this});var ac=/[\t\r\n\f]/g;o.fn.extend({addClass:function(a){var b,c,d,e,f,g,h="string"==typeof a&&a,i=0,j=this.length;if(o.isFunction(a))return this.each(function(b){o(this).addClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=o.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0===arguments.length||"string"==typeof a&&a,i=0,j=this.length;if(o.isFunction(a))return this.each(function(b){o(this).removeClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?o.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(o.isFunction(a)?function(c){o(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=o(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===U||"boolean"===c)&&(this.className&&L.set(this,"__className__",this.className),this.className=this.className||a===!1?"":L.get(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(ac," ").indexOf(b)>=0)return!0;return!1}});var bc=/\r/g;o.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=o.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,o(this).val()):a,null==e?e="":"number"==typeof e?e+="":o.isArray(e)&&(e=o.map(e,function(a){return null==a?"":a+""})),b=o.valHooks[this.type]||o.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=o.valHooks[e.type]||o.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(bc,""):null==c?"":c)}}}),o.extend({valHooks:{select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(l.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&o.nodeName(c.parentNode,"optgroup"))){if(b=o(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=o.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=o.inArray(o(d).val(),f)>=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),o.each(["radio","checkbox"],function(){o.valHooks[this]={set:function(a,b){return o.isArray(b)?a.checked=o.inArray(o(a).val(),b)>=0:void 0}},l.checkOn||(o.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})}),o.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){o.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),o.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var cc=o.now(),dc=/\?/;o.parseJSON=function(a){return JSON.parse(a+"")},o.parseXML=function(a){var b,c;if(!a||"string"!=typeof a)return null;try{c=new DOMParser,b=c.parseFromString(a,"text/xml")}catch(d){b=void 0}return(!b||b.getElementsByTagName("parsererror").length)&&o.error("Invalid XML: "+a),b};var ec,fc,gc=/#.*$/,hc=/([?&])_=[^&]*/,ic=/^(.*?):[ \t]*(Line truncated
-655
View File
@@ -1,655 +0,0 @@
/**
* Copyright 2013 The Rust Project Developers. See the COPYRIGHT
* file at the top-level directory of this distribution and at
* http://rust-lang.org/COPYRIGHT.
*
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
* http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
* <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
* option. This file may not be copied, modified, or distributed
* except according to those terms.
*/
@font-face {
font-family: 'Fira Sans';
font-style: normal;
font-weight: 400;
src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff');
}
@font-face {
font-family: 'Fira Sans';
font-style: normal;
font-weight: 500;
src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff');
}
@font-face {
font-family: 'Source Serif Pro';
font-style: normal;
font-weight: 400;
src: local('Source Serif Pro'), url("SourceSerifPro-Regular.woff") format('woff');
}
@font-face {
font-family: 'Source Serif Pro';
font-style: italic;
font-weight: 400;
src: url("Heuristica-Italic.woff") format('woff');
}
@font-face {
font-family: 'Source Serif Pro';
font-style: normal;
font-weight: 700;
src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.woff") format('woff');
}
@font-face {
font-family: 'Source Code Pro';
font-style: normal;
font-weight: 400;
src: local('Source Code Pro'), url("SourceCodePro-Regular.woff") format('woff');
}
@font-face {
font-family: 'Source Code Pro';
font-style: normal;
font-weight: 600;
src: local('Source Code Pro Semibold'), url("SourceCodePro-Semibold.woff") format('woff');
}
@import "normalize.css";
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
/* General structure and fonts */
body {
color: #333;
font: 16px/1.4 "Source Serif Pro", Georgia, Times, "Times New Roman", serif;
margin: 0;
position: relative;
padding: 10px 15px 20px 15px;
-webkit-font-feature-settings: "kern", "liga";
-moz-font-feature-settings: "kern", "liga";
font-feature-settings: "kern", "liga";
}
h1 {
font-size: 1.5em;
}
h2 {
font-size: 1.4em;
}
h3 {
font-size: 1.3em;
}
h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
color: black;
font-weight: 500;
margin: 20px 0 15px 0;
padding-bottom: 6px;
}
h1.fqn {
border-bottom: 1px dashed #D5D5D5;
margin-top: 0;
}
h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
border-bottom: 1px solid #DDDDDD;
}
h3.impl, h3.method, h4.method, h3.type, h4.type {
font-weight: 600;
margin-top: 10px;
margin-bottom: 10px;
}
h3.impl, h3.method, h3.type {
margin-top: 15px;
}
h1, h2, h3, h4, section.sidebar, a.source, .search-input, .content table :not(code)>a, .collapse-toggle {
font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
ol, ul {
padding-left: 25px;
}
ul ul, ol ul, ul ol, ol ol {
margin-bottom: 0;
}
p {
margin: 0 0 .6em 0;
}
code, pre {
font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", Inconsolata, monospace;
white-space: pre-wrap;
}
.docblock code {
background-color: #F5F5F5;
border-radius: 3px;
padding: 0 0.2em;
}
pre {
background-color: #F5F5F5;
padding: 14px;
}
.source pre {
padding: 20px;
}
.content.source {
margin-top: 50px;
max-width: none;
overflow: visible;
margin-left: 0px;
min-width: 70em;
}
nav.sub {
font-size: 16px;
text-transform: uppercase;
}
.sidebar {
width: 200px;
position: absolute;
left: 0;
top: 0;
min-height: 100%;
}
.content, nav { max-width: 960px; }
/* Everything else */
.js-only, .hidden { display: none; }
.sidebar {
padding: 10px;
}
.sidebar img {
margin: 20px auto;
display: block;
}
.sidebar .location {
font-size: 17px;
margin: 30px 0 20px 0;
background: #e1e1e1;
text-align: center;
color: #333;
}
.location a:first-child { font-weight: 500; }
.block {
padding: 0 10px;
margin-bottom: 14px;
}
.block h2 {
margin-top: 0;
margin-bottom: 8px;
text-align: center;
}
.block a {
display: block;
text-overflow: ellipsis;
overflow: hidden;
line-height: 15px;
padding: 7px 5px;
font-size: 14px;
font-weight: 300;
transition: border 500ms ease-out;
}
.block a:hover {
background: #F5F5F5;
}
.content {
padding: 15px 0;
}
.content.source pre.rust {
white-space: pre;
overflow: auto;
padding-left: 0;
}
.content pre.line-numbers {
float: left;
border: none;
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.line-numbers span { color: #c67e2d; cursor: pointer; }
.line-numbers .line-highlighted {
background-color: #f6fdb0 !important;
}
.content .highlighted {
color: #000 !important;
background-color: #ccc;
}
.content .highlighted a, .content .highlighted span { color: #000 !important; }
.content .highlighted.trait { background-color: #fece7e; }
.content .highlighted.mod { background-color: #afc6e4; }
.content .highlighted.enum { background-color: #b4d1b9; }
.content .highlighted.struct { background-color: #e7b1a0; }
.content .highlighted.fn { background-color: #c6afb3; }
.content .highlighted.method { background-color: #c6afb3; }
.content .highlighted.tymethod { background-color: #c6afb3; }
.content .highlighted.type { background-color: #c6afb3; }
.docblock.short.nowrap {
display: block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.docblock.short p {
overflow: hidden;
text-overflow: ellipsis;
margin: 0;
}
.docblock.short code { white-space: nowrap; }
.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
border-bottom: 1px solid #DDD;
}
.docblock h1 { font-size: 1.3em; }
.docblock h2 { font-size: 1.15em; }
.docblock h3, .docblock h4, .docblock h5 { font-size: 1em; }
.content .out-of-band {
font-size: 23px;
width: 40%;
margin: 0px;
padding: 0px;
text-align: right;
display: inline-block;
}
.content .in-band {
width: 60%;
margin: 0px;
padding: 0px;
display: inline-block;
}
.content table {
border-spacing: 0 5px;
border-collapse: separate;
}
.content td { vertical-align: top; }
.content td:first-child { padding-right: 20px; }
.content td p:first-child { margin-top: 0; }
.content td h1, .content td h2 { margin-left: 0; font-size: 1.1em; }
.docblock table {
border: 1px solid #ddd;
margin: .5em 0;
border-collapse: collapse;
width: 100%;
}
.docblock table td {
padding: .5em;
border-top: 1px dashed #ddd;
border-bottom: 1px dashed #ddd;
}
.docblock table th {
padding: .5em;
text-align: left;
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
}
.content .item-list {
list-style-type: none;
padding: 0;
}
.content .item-list li { margin-bottom: 3px; }
.content .multi-column {
-moz-column-count: 5;
-moz-column-gap: 2.5em;
-webkit-column-count: 5;
-webkit-column-gap: 2.5em;
column-count: 5;
column-gap: 2.5em;
}
.content .multi-column li { width: 100%; display: inline-block; }
.content .method {
font-size: 1em;
position: relative;
}
/* Shift "where ..." part of method definition down a line */
.content .method .where { display: block; }
/* Bit of whitespace to indent it */
.content .method .where::before { content: ' '; }
.content .methods .docblock { margin-left: 40px; }
.content .impl-items .docblock { margin-left: 40px; }
nav {
border-bottom: 1px solid #e0e0e0;
padding-bottom: 10px;
margin-bottom: 10px;
}
nav.main {
padding: 20px 0;
text-align: center;
}
nav.main .current {
border-top: 1px solid #000;
border-bottom: 1px solid #000;
}
nav.main .separator {
border: 1px solid #000;
display: inline-block;
height: 23px;
margin: 0 20px;
}
nav.sum { text-align: right; }
nav.sub form { display: inline; }
nav, .content {
margin-left: 230px;
}
a {
text-decoration: none;
color: #000;
background: transparent;
}
.docblock a {
color: #4e8bca;
}
.docblock a:hover {
text-decoration: underline;
}
.content span.trait, .content a.trait, .block a.current.trait { color: #ed9603; }
.content span.mod, .content a.mod, block a.current.mod { color: #4d76ae; }
.content span.enum, .content a.enum, .block a.current.enum { color: #5e9766; }
.content span.struct, .content a.struct, .block a.current.struct { color: #e53700; }
.content span.fn, .content a.fn, .block a.current.fn { color: #8c6067; }
.content span.method, .content a.method, .block a.current.method { color: #8c6067; }
.content span.tymethod, .content a.tymethod, .block a.current.tymethod { color: #8c6067; }
.content .fnname { color: #8c6067; }
.search-input {
width: 100%;
/* Override Normalize.css: we have margins and do
not want to overflow - the `moz` attribute is necessary
until Firefox 29, too early to drop at this point */
-moz-box-sizing: border-box !important;
box-sizing: border-box !important;
outline: none;
border: none;
border-radius: 1px;
color: #555;
margin-top: 5px;
padding: 10px 16px;
font-size: 17px;
box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
transition: border-color 300ms ease;
transition: border-radius 300ms ease-in-out;
transition: box-shadow 300ms ease-in-out;
}
.search-input:focus {
border-color: #66afe9;
border-radius: 2px;
border: 0;
outline: 0;
box-shadow: 0 0 8px #078dd8;
}
.search-results .desc {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
display: block;
}
.search-results a {
display: block;
}
.content .search-results td:first-child { padding-right: 0; }
.content .search-results td:first-child a { padding-right: 10px; }
#help {
background: #e9e9e9;
border-radius: 4px;
box-shadow: 0 0 6px rgba(0,0,0,.2);
position: absolute;
top: 300px;
left: 50%;
margin-top: -125px;
margin-left: -275px;
width: 550px;
height: 300px;
border: 1px solid #bfbfbf;
}
#help dt {
float: left;
border-radius: 3px;
border: 1px solid #bfbfbf;
background: #fff;
width: 23px;
text-align: center;
clear: left;
display: block;
margin-top: -1px;
}
#help dd { margin: 5px 33px; }
#help .infos { padding-left: 0; }
#help h1 { margin-top: 0; }
#help div {
width: 50%;
float: left;
padding: 20px;
}
.stability {
border-left: 6px solid;
padding: 3px 6px;
border-radius: 3px;
}
h1 .stability {
text-transform: lowercase;
font-weight: 400;
margin-left: 14px;
padding: 4px 10px;
}
.impl-items .stability, .methods .stability {
margin-right: 20px;
}
.stability.Deprecated { border-color: #A071A8; color: #82478C; }
.stability.Experimental { border-color: #D46D6A; color: #AA3C39; }
.stability.Unstable { border-color: #D4B16A; color: #AA8439; }
.stability.Stable { border-color: #54A759; color: #2D8632; }
.stability.Frozen { border-color: #009431; color: #007726; }
.stability.Locked { border-color: #0084B6; color: #00668c; }
.stability.Unmarked { border-color: #BBBBBB; }
td.summary-column {
width: 100%;
}
.summary {
padding-right: 0px;
}
.summary.Deprecated { background-color: #A071A8; }
.summary.Experimental { background-color: #D46D6A; }
.summary.Unstable { background-color: #D4B16A; }
.summary.Stable { background-color: #54A759; }
.summary.Unmarked { background-color: #BBBBBB; }
:target { background: #FDFFD3; }
.line-numbers :target { background-color: transparent; }
/* Code highlighting */
pre.rust .kw { color: #8959A8; }
pre.rust .kw-2, pre.rust .prelude-ty { color: #4271AE; }
pre.rust .number, pre.rust .string { color: #718C00; }
pre.rust .self, pre.rust .boolval, pre.rust .prelude-val,
pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; }
pre.rust .comment { color: #8E908C; }
pre.rust .doccomment { color: #4D4D4C; }
pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
pre.rust .lifetime { color: #B76514; }
.rusttest { display: none; }
pre.rust { position: relative; }
.test-arrow {
display: inline-block;
position: absolute;
top: 0;
right: 10px;
font-size: 150%;
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
}
.methods .section-header {
/* Override parent class attributes. */
border-bottom: none !important;
font-size: 1.1em !important;
margin: 0 0 -5px;
padding: 0;
}
.section-header:hover a:after {
content: '\2002\00a7\2002';
}
.section-header:hover a {
text-decoration: none;
}
.section-header a {
color: inherit;
}
.collapse-toggle {
font-weight: 300;
position: absolute;
left: 13px;
color: #999;
margin-top: 2px;
}
.toggle-wrapper > .collapse-toggle {
left: -24px;
margin-top: 0px;
}
.toggle-wrapper {
position: relative;
}
.toggle-wrapper.collapsed {
height: 1em;
transition: height .2s;
}
.collapse-toggle > .inner {
display: inline-block;
width: 1ch;
text-align: center;
}
.toggle-label {
color: #999;
}
/* Media Queries */
@media (max-width: 700px) {
body {
padding-top: 0px;
}
.sidebar {
height: 40px;
min-height: 40px;
width: 100%;
margin: 0px;
padding: 0px;
position: static;
}
.sidebar .location {
float: left;
margin: 0px;
padding: 5px;
width: 60%;
background: inherit;
text-align: left;
font-size: 24px;
}
.sidebar img {
width: 35px;
margin-top: 5px;
margin-bottom: 0px;
float: left;
}
nav.sub {
margin: 0 auto;
}
.sidebar .block {
display: none;
}
.content {
margin-left: 0px;
}
.content .in-band {
width: 100%;
}
.content .out-of-band {
display: none;
}
.toggle-wrapper > .collapse-toggle {
left: 0px;
}
.toggle-wrapper {
height: 1.5em;
}
}
@media print {
nav.sub, .content .out-of-band, .collapse-toggle {
display: none;
}
}
-888
View File
@@ -1,888 +0,0 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*jslint browser: true, es5: true */
/*globals $: true, rootPath: true */
(function() {
"use strict";
var resizeTimeout, interval;
// This mapping table should match the discriminants of
// `rustdoc::html::item_type::ItemType` type in Rust.
var itemTypes = ["mod",
"externcrate",
"import",
"struct",
"enum",
"fn",
"type",
"static",
"trait",
"impl",
"tymethod",
"method",
"structfield",
"variant",
"macro",
"primitive",
"associatedtype",
"constant"];
$('.js-only').removeClass('js-only');
function getQueryStringParams() {
var params = {};
window.location.search.substring(1).split("&").
map(function(s) {
var pair = s.split("=");
params[decodeURIComponent(pair[0])] =
typeof pair[1] === "undefined" ?
null : decodeURIComponent(pair[1]);
});
return params;
}
function browserSupportsHistoryApi() {
return window.history && typeof window.history.pushState === "function";
}
function highlightSourceLines(ev) {
var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);
if (match) {
from = parseInt(match[1], 10);
to = Math.min(50000, parseInt(match[2] || match[1], 10));
from = Math.min(from, to);
if ($('#' + from).length === 0) {
return;
}
if (ev === null) $('#' + from)[0].scrollIntoView();
$('.line-numbers span').removeClass('line-highlighted');
for (i = from; i <= to; ++i) {
$('#' + i).addClass('line-highlighted');
}
}
}
highlightSourceLines(null);
$(window).on('hashchange', highlightSourceLines);
$(document).on('keyup', function(e) {
if (document.activeElement.tagName === 'INPUT') {
return;
}
if (e.which === 191) { // question mark
if (e.shiftKey && $('#help').hasClass('hidden')) {
e.preventDefault();
$('#help').removeClass('hidden');
}
} else if (e.which === 27) { // esc
if (!$('#help').hasClass('hidden')) {
e.preventDefault();
$('#help').addClass('hidden');
} else if (!$('#search').hasClass('hidden')) {
e.preventDefault();
$('#search').addClass('hidden');
$('#main').removeClass('hidden');
}
} else if (e.which === 83) { // S
e.preventDefault();
$('.search-input').focus();
}
}).on('click', function(e) {
if (!$(e.target).closest('#help').length) {
$('#help').addClass('hidden');
}
});
$('.version-selector').on('change', function() {
var i, match,
url = document.location.href,
stripped = '',
len = rootPath.match(/\.\.\//g).length + 1;
for (i = 0; i < len; ++i) {
match = url.match(/\/[^\/]*$/);
if (i < len - 1) {
stripped = match[0] + stripped;
}
url = url.substring(0, url.length - match[0].length);
}
url += '/' + $('.version-selector').val() + stripped;
document.location.href = url;
});
/**
* A function to compute the Levenshtein distance between two strings
* Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported
* Full License can be found at http://creativecommons.org/licenses/by-sa/3.0/legalcode
* This code is an unmodified version of the code written by Marco de Wit
* and was found at http://stackoverflow.com/a/18514751/745719
*/
var levenshtein = (function() {
var row2 = [];
return function(s1, s2) {
if (s1 === s2) {
return 0;
} else {
var s1_len = s1.length, s2_len = s2.length;
if (s1_len && s2_len) {
var i1 = 0, i2 = 0, a, b, c, c2, row = row2;
while (i1 < s1_len)
row[i1] = ++i1;
while (i2 < s2_len) {
c2 = s2.charCodeAt(i2);
a = i2;
++i2;
b = i2;
for (i1 = 0; i1 < s1_len; ++i1) {
c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
a = row[i1];
b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
row[i1] = b;
}
}
return b;
} else {
return s1_len + s2_len;
}
}
};
})();
function initSearch(rawSearchIndex) {
var currentResults, index, searchIndex;
var MAX_LEV_DISTANCE = 3;
var params = getQueryStringParams();
// Populate search bar with query string search term when provided,
// but only if the input bar is empty. This avoid the obnoxious issue
// where you start trying to do a search, and the index loads, and
// suddenly your search is gone!
if ($(".search-input")[0].value === "") {
$(".search-input")[0].value = params.search || '';
}
/**
* Executes the query and builds an index of results
* @param {[Object]} query [The user query]
* @param {[type]} max [The maximum results returned]
* @param {[type]} searchWords [The list of search words to query
* against]
* @return {[type]} [A search index of results]
*/
function execQuery(query, max, searchWords) {
var valLower = query.query.toLowerCase(),
val = valLower,
typeFilter = itemTypeFromName(query.type),
results = [],
split = valLower.split("::");
//remove empty keywords
for (var j = 0; j < split.length; ++j) {
split[j].toLowerCase();
if (split[j] === "") {
split.splice(j, 1);
}
}
// quoted values mean literal search
var nSearchWords = searchWords.length;
if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
val.charAt(val.length - 1) === val.charAt(0))
{
val = val.substr(1, val.length - 2);
for (var i = 0; i < nSearchWords; ++i) {
if (searchWords[i] === val) {
// filter type: ... queries
if (typeFilter < 0 || typeFilter === searchIndex[i].ty) {
results.push({id: i, index: -1});
}
}
if (results.length === max) {
break;
}
}
// searching by type
} else if (val.search("->") > -1) {
var trimmer = function (s) { return s.trim(); };
var parts = val.split("->").map(trimmer);
var input = parts[0];
// sort inputs so that order does not matter
var inputs = input.split(",").map(trimmer).sort();
var output = parts[1];
for (var i = 0; i < nSearchWords; ++i) {
var type = searchIndex[i].type;
if (!type) {
continue;
}
// sort index inputs so that order does not matter
var typeInputs = type.inputs.map(function (input) {
return input.name;
}).sort();
// allow searching for void (no output) functions as well
var typeOutput = type.output ? type.output.name : "";
if (inputs.toString() === typeInputs.toString() &&
output == typeOutput) {
results.push({id: i, index: -1, dontValidate: true});
}
}
} else {
// gather matching search results up to a certain maximum
val = val.replace(/\_/g, "");
for (var i = 0; i < split.length; ++i) {
for (var j = 0; j < nSearchWords; ++j) {
var lev_distance;
if (searchWords[j].indexOf(split[i]) > -1 ||
searchWords[j].indexOf(val) > -1 ||
searchWords[j].replace(/_/g, "").indexOf(val) > -1)
{
// filter type: ... queries
if (typeFilter < 0 || typeFilter === searchIndex[j].ty) {
results.push({
id: j,
index: searchWords[j].replace(/_/g, "").indexOf(val),
lev: 0,
});
}
} else if (
(lev_distance = levenshtein(searchWords[j], val)) <=
MAX_LEV_DISTANCE) {
if (typeFilter < 0 || typeFilter === searchIndex[j].ty) {
results.push({
id: j,
index: 0,
// we want lev results to go lower than others
lev: lev_distance,
});
}
}
if (results.length === max) {
break;
}
}
}
}
var nresults = results.length;
for (var i = 0; i < nresults; ++i) {
results[i].word = searchWords[results[i].id];
results[i].item = searchIndex[results[i].id] || {};
}
// if there are no results then return to default and fail
if (results.length === 0) {
return [];
}
results.sort(function(aaa, bbb) {
var a, b;
// Sort by non levenshtein results and then levenshtein results by the distance
// (less changes required to match means higher rankings)
a = (aaa.lev);
b = (bbb.lev);
if (a !== b) return a - b;
// sort by crate (non-current crate goes later)
a = (aaa.item.crate !== window.currentCrate);
b = (bbb.item.crate !== window.currentCrate);
if (a !== b) return a - b;
// sort by exact match (mismatch goes later)
a = (aaa.word !== valLower);
b = (bbb.word !== valLower);
if (a !== b) return a - b;
// sort by item name length (longer goes later)
a = aaa.word.length;
b = bbb.word.length;
if (a !== b) return a - b;
// sort by item name (lexicographically larger goes later)
a = aaa.word;
b = bbb.word;
if (a !== b) return (a > b ? +1 : -1);
// sort by index of keyword in item name (no literal occurrence goes later)
a = (aaa.index < 0);
b = (bbb.index < 0);
if (a !== b) return a - b;
// (later literal occurrence, if any, goes later)
a = aaa.index;
b = bbb.index;
if (a !== b) return a - b;
// sort by description (no description goes later)
a = (aaa.item.desc === '');
b = (bbb.item.desc === '');
if (a !== b) return a - b;
// sort by type (later occurrence in `itemTypes` goes later)
a = aaa.item.ty;
b = bbb.item.ty;
if (a !== b) return a - b;
// sort by path (lexicographically larger goes later)
a = aaa.item.path;
b = bbb.item.path;
if (a !== b) return (a > b ? +1 : -1);
// que sera, sera
return 0;
});
// remove duplicates, according to the data provided
for (var i = results.length - 1; i > 0; i -= 1) {
if (results[i].word === results[i - 1].word &&
results[i].item.ty === results[i - 1].item.ty &&
results[i].item.path === results[i - 1].item.path &&
(results[i].item.parent || {}).name === (results[i - 1].item.parent || {}).name)
{
results[i].id = -1;
}
}
for (var i = 0; i < results.length; ++i) {
var result = results[i],
name = result.item.name.toLowerCase(),
path = result.item.path.toLowerCase(),
parent = result.item.parent;
// this validation does not make sense when searching by types
if (result.dontValidate) {
continue;
}
var valid = validateResult(name, path, split, parent);
if (!valid) {
result.id = -1;
}
}
return results;
}
/**
* Validate performs the following boolean logic. For example:
* "File::open" will give IF A PARENT EXISTS => ("file" && "open")
* exists in (name || path || parent) OR => ("file" && "open") exists in
* (name || path )
*
* This could be written functionally, but I wanted to minimise
* functions on stack.
*
* @param {[string]} name [The name of the result]
* @param {[string]} path [The path of the result]
* @param {[string]} keys [The keys to be used (["file", "open"])]
* @param {[object]} parent [The parent of the result]
* @return {[boolean]} [Whether the result is valid or not]
*/
function validateResult(name, path, keys, parent) {
for (var i=0; i < keys.length; ++i) {
// each check is for validation so we negate the conditions and invalidate
if (!(
// check for an exact name match
name.toLowerCase().indexOf(keys[i]) > -1 ||
// then an exact path match
path.toLowerCase().indexOf(keys[i]) > -1 ||
// next if there is a parent, check for exact parent match
(parent !== undefined &&
parent.name.toLowerCase().indexOf(keys[i]) > -1) ||
// lastly check to see if the name was a levenshtein match
levenshtein(name.toLowerCase(), keys[i]) <=
MAX_LEV_DISTANCE)) {
return false;
}
}
return true;
}
function getQuery() {
var matches, type, query, raw = $('.search-input').val();
query = raw;
matches = query.match(/^(fn|mod|struct|enum|trait|t(ype)?d(ef)?)\s*:\s*/i);
if (matches) {
type = matches[1].replace(/^td$/, 'typedef')
.replace(/^tdef$/, 'typedef')
.replace(/^typed$/, 'typedef');
query = query.substring(matches[0].length);
}
return {
raw: raw,
query: query,
type: type,
id: query + type,
};
}
function initSearchNav() {
var hoverTimeout, $results = $('.search-results .result');
$results.on('click', function() {
var dst = $(this).find('a')[0];
if (window.location.pathname == dst.pathname) {
$('#search').addClass('hidden');
$('#main').removeClass('hidden');
document.location.href = dst.href;
}
}).on('mouseover', function() {
var $el = $(this);
clearTimeout(hoverTimeout);
hoverTimeout = setTimeout(function() {
$results.removeClass('highlighted');
$el.addClass('highlighted');
}, 20);
});
$(document).off('keydown.searchnav');
$(document).on('keydown.searchnav', function(e) {
var $active = $results.filter('.highlighted');
if (e.which === 38) { // up
e.preventDefault();
if (!$active.length || !$active.prev()) {
return;
}
$active.prev().addClass('highlighted');
$active.removeClass('highlighted');
} else if (e.which === 40) { // down
e.preventDefault();
if (!$active.length) {
$results.first().addClass('highlighted');
} else if ($active.next().length) {
$active.next().addClass('highlighted');
$active.removeClass('highlighted');
}
} else if (e.which === 13) { // return
e.preventDefault();
if ($active.length) {
document.location.href = $active.find('a').prop('href');
}
} else {
$active.removeClass('highlighted');
}
});
}
function escape(content) {
return $('<h1/>').text(content).html();
}
function showResults(results) {
var output, shown, query = getQuery();
currentResults = query.id;
output = '<h1>Results for ' + escape(query.query) +
(query.type ? ' (type: ' + escape(query.type) + ')' : '') + '</h1>';
output += '<table class="search-results">';
if (results.length > 0) {
shown = [];
results.forEach(function(item) {
var name, type, href, displayPath;
if (shown.indexOf(item) !== -1) {
return;
}
shown.push(item);
name = item.name;
type = itemTypes[item.ty];
if (type === 'mod') {
displayPath = item.path + '::';
href = rootPath + item.path.replace(/::/g, '/') + '/' +
name + '/index.html';
} else if (type === 'static' || type === 'reexport') {
displayPath = item.path + '::';
href = rootPath + item.path.replace(/::/g, '/') +
'/index.html';
} else if (item.parent !== undefined) {
var myparent = item.parent;
var anchor = '#' + type + '.' + name;
displayPath = item.path + '::' + myparent.name + '::';
href = rootPath + item.path.replace(/::/g, '/') +
'/' + itemTypes[myparent.ty] +
'.' + myparent.name +
'.html' + anchor;
} else {
displayPath = item.path + '::';
href = rootPath + item.path.replace(/::/g, '/') +
'/' + type + '.' + name + '.html';
}
output += '<tr class="' + type + ' result"><td>' +
'<a href="' + href + '">' +
displayPath + '<span class="' + type + '">' +
name + '</span></a></td><td>' +
'<a href="' + href + '">' +
'<span class="desc">' + item.desc +
'&nbsp;</span></a></td></tr>';
});
} else {
output += 'No results :( <a href="https://duckduckgo.com/?q=' +
encodeURIComponent('rust ' + query.query) +
'">Try on DuckDuckGo?</a>';
}
output += "</p>";
$('#main.content').addClass('hidden');
$('#search.content').removeClass('hidden').html(output);
$('#search .desc').width($('#search').width() - 40 -
$('#search td:first-child').first().width());
initSearchNav();
}
function search(e) {
var query,
filterdata = [],
obj, i, len,
results = [],
maxResults = 200,
resultIndex;
var params = getQueryStringParams();
query = getQuery();
if (e) {
e.preventDefault();
}
if (!query.query || query.id === currentResults) {
return;
}
// Because searching is incremental by character, only the most
// recent search query is added to the browser history.
if (browserSupportsHistoryApi()) {
if (!history.state && !params.search) {
history.pushState(query, "", "?search=" +
encodeURIComponent(query.raw));
} else {
history.replaceState(query, "", "?search=" +
encodeURIComponent(query.raw));
}
}
resultIndex = execQuery(query, 20000, index);
len = resultIndex.length;
for (i = 0; i < len; ++i) {
if (resultIndex[i].id > -1) {
obj = searchIndex[resultIndex[i].id];
filterdata.push([obj.name, obj.ty, obj.path, obj.desc]);
results.push(obj);
}
if (results.length >= maxResults) {
break;
}
}
showResults(results);
}
function itemTypeFromName(typename) {
for (var i = 0; i < itemTypes.length; ++i) {
if (itemTypes[i] === typename) return i;
}
return -1;
}
function buildIndex(rawSearchIndex) {
searchIndex = [];
var searchWords = [];
for (var crate in rawSearchIndex) {
if (!rawSearchIndex.hasOwnProperty(crate)) { continue }
// an array of [(Number) item type,
// (String) name,
// (String) full path or empty string for previous path,
// (String) description,
// (Number | null) the parent path index to `paths`]
// (Object | null) the type of the function (if any)
var items = rawSearchIndex[crate].items;
// an array of [(Number) item type,
// (String) name]
var paths = rawSearchIndex[crate].paths;
// convert `paths` into an object form
var len = paths.length;
for (var i = 0; i < len; ++i) {
paths[i] = {ty: paths[i][0], name: paths[i][1]};
}
// convert `items` into an object form, and construct word indices.
//
// before any analysis is performed lets gather the search terms to
// search against apart from the rest of the data. This is a quick
// operation that is cached for the life of the page state so that
// all other search operations have access to this cached data for
// faster analysis operations
var len = items.length;
var lastPath = "";
for (var i = 0; i < len; ++i) {
var rawRow = items[i];
var row = {crate: crate, ty: rawRow[0], name: rawRow[1],
path: rawRow[2] || lastPath, desc: rawRow[3],
parent: paths[rawRow[4]], type: rawRow[5]};
searchIndex.push(row);
if (typeof row.name === "string") {
var word = row.name.toLowerCase();
searchWords.push(word);
} else {
searchWords.push("");
}
lastPath = row.path;
}
}
return searchWords;
}
function startSearch() {
var keyUpTimeout;
$('.do-search').on('click', search);
$('.search-input').on('keyup', function() {
clearTimeout(keyUpTimeout);
keyUpTimeout = setTimeout(search, 500);
});
// Push and pop states are used to add search results to the browser
// history.
if (browserSupportsHistoryApi()) {
$(window).on('popstate', function(e) {
var params = getQueryStringParams();
// When browsing back from search results the main page
// visibility must be reset.
if (!params.search) {
$('#main.content').removeClass('hidden');
$('#search.content').addClass('hidden');
}
// When browsing forward to search results the previous
// search will be repeated, so the currentResults are
// cleared to ensure the search is successful.
currentResults = null;
// Synchronize search bar with query string state and
// perform the search. This will empty the bar if there's
// nothing there, which lets you really go back to a
// previous state with nothing in the bar.
$('.search-input').val(params.search);
// Some browsers fire 'onpopstate' for every page load
// (Chrome), while others fire the event only when actually
// popping a state (Firefox), which is why search() is
// called both here and at the end of the startSearch()
// function.
search();
});
}
search();
}
function plainSummaryLine(markdown) {
var str = markdown.replace(/\n/g, ' ')
str = str.replace(/'/g, "\'")
str = str.replace(/^#+? (.+?)/, "$1")
str = str.replace(/\[(.*?)\]\(.*?\)/g, "$1")
str = str.replace(/\[(.*?)\]\[.*?\]/g, "$1")
return str;
}
index = buildIndex(rawSearchIndex);
startSearch();
// Draw a convenient sidebar of known crates if we have a listing
if (rootPath == '../') {
var sidebar = $('.sidebar');
var div = $('<div>').attr('class', 'block crate');
div.append($('<h2>').text('Crates'));
var crates = [];
for (var crate in rawSearchIndex) {
if (!rawSearchIndex.hasOwnProperty(crate)) { continue }
crates.push(crate);
}
crates.sort();
for (var i = 0; i < crates.length; ++i) {
var klass = 'crate';
if (crates[i] == window.currentCrate) {
klass += ' current';
}
if (rawSearchIndex[crates[i]].items[0]) {
var desc = rawSearchIndex[crates[i]].items[0][3];
div.append($('<a>', {'href': '../' + crates[i] + '/index.html',
'title': plainSummaryLine(desc),
'class': klass}).text(crates[i]));
}
}
sidebar.append(div);
}
}
window.initSearch = initSearch;
// delayed sidebar rendering.
function initSidebarItems(items) {
var sidebar = $('.sidebar');
var current = window.sidebarCurrent;
function block(shortty, longty) {
var filtered = items[shortty];
if (!filtered) return;
var div = $('<div>').attr('class', 'block ' + shortty);
div.append($('<h2>').text(longty));
for (var i = 0; i < filtered.length; ++i) {
var item = filtered[i];
var name = item[0];
var desc = item[1]; // can be null
var klass = shortty;
if (name === current.name && shortty == current.ty) {
klass += ' current';
}
var path;
if (shortty === 'mod') {
path = name + '/index.html';
} else {
path = shortty + '.' + name + '.html';
}
div.append($('<a>', {'href': current.relpath + path,
'title': desc,
'class': klass}).text(name));
}
sidebar.append(div);
}
block("mod", "Modules");
block("struct", "Structs");
block("enum", "Enums");
block("trait", "Traits");
block("fn", "Functions");
block("macro", "Macros");
}
window.initSidebarItems = initSidebarItems;
window.register_implementors = function(imp) {
var list = $('#implementors-list');
var libs = Object.getOwnPropertyNames(imp);
for (var i = 0; i < libs.length; ++i) {
if (libs[i] == currentCrate) continue;
var structs = imp[libs[i]];
for (var j = 0; j < structs.length; ++j) {
var code = $('<code>').append(structs[j]);
$.each(code.find('a'), function(idx, a) {
var href = $(a).attr('href');
if (href && href.indexOf('http') !== 0) {
$(a).attr('href', rootPath + href);
}
});
var li = $('<li>').append(code);
list.append(li);
}
}
};
if (window.pending_implementors) {
window.register_implementors(window.pending_implementors);
}
// See documentation in html/render.rs for what this is doing.
var query = getQueryStringParams();
if (query['gotosrc']) {
window.location = $('#src-' + query['gotosrc']).attr('href');
}
$("#expand-all").on("click", function() {
$(".docblock").show();
$(".toggle-label").hide();
$(".toggle-wrapper").removeClass("collapsed");
$(".collapse-toggle").children(".inner").html("-");
});
$("#collapse-all").on("click", function() {
$(".docblock").hide();
$(".toggle-label").show();
$(".toggle-wrapper").addClass("collapsed");
$(".collapse-toggle").children(".inner").html("+");
});
$(document).on("click", ".collapse-toggle", function() {
var toggle = $(this);
var relatedDoc = toggle.parent().next();
if (relatedDoc.is(".docblock")) {
if (relatedDoc.is(":visible")) {
relatedDoc.slideUp({duration:'fast', easing:'linear'});
toggle.parent(".toggle-wrapper").addClass("collapsed");
toggle.children(".inner").html("+");
toggle.children(".toggle-label").fadeIn();
} else {
relatedDoc.slideDown({duration:'fast', easing:'linear'});
toggle.parent(".toggle-wrapper").removeClass("collapsed");
toggle.children(".inner").html("-");
toggle.children(".toggle-label").hide();
}
}
});
$(function() {
var toggle = $("<a/>", {'href': 'javascript:void(0)', 'class': 'collapse-toggle'})
.html("[<span class='inner'>-</span>]");
$(".method").each(function() {
if ($(this).next().is(".docblock")) {
$(this).children().first().after(toggle.clone());
}
});
var mainToggle =
$(toggle).append(
$('<span/>', {'class': 'toggle-label'})
.css('display', 'none')
.html('&nbsp;Expand&nbsp;description'));
var wrapper = $("<div class='toggle-wrapper'>").append(mainToggle);
$("#main > .docblock").before(wrapper);
});
$('pre.line-numbers').on('click', 'span', function() {
var prev_id = 0;
function set_fragment(name) {
if (history.replaceState) {
history.replaceState(null, null, '#' + name);
$(window).trigger('hashchange');
} else {
location.replace('#' + name);
}
}
return function(ev) {
var cur_id = parseInt(ev.target.id);
if (ev.shiftKey && prev_id) {
if (prev_id > cur_id) {
var tmp = prev_id;
prev_id = cur_id;
cur_id = tmp;
}
set_fragment(prev_id + '-' + cur_id);
} else {
prev_id = cur_id;
set_fragment(cur_id);
}
};
}());
}());
-1
View File
@@ -1 +0,0 @@
/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}
-27
View File
@@ -1,27 +0,0 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*jslint browser: true, es5: true */
/*globals $: true, rootPath: true */
(function() {
if (window.playgroundUrl) {
$('pre.rust').hover(function() {
var a = $('<a>').text('⇱').attr('class', 'test-arrow');
var code = $(this).prev(".rusttest").text();
a.attr('href', window.playgroundUrl + '?code=' +
encodeURIComponent(code));
a.attr('target', '_blank');
$(this).append(a);
}, function() {
$(this).find('a.test-arrow').remove();
});
}
}());
-148
View File
@@ -1,148 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="rustdoc">
<meta name="description" content="API documentation for the Rust `r2pipe` crate.">
<meta name="keywords" content="rust, rustlang, rust-lang, r2pipe">
<title>r2pipe - Rust</title>
<link rel="stylesheet" type="text/css" href="../main.css">
</head>
<body class="rustdoc">
<!--[if lte IE 8]>
<div class="warning">
This old browser is unsupported and will most likely display funky
things.
</div>
<![endif]-->
<section class="sidebar">
<p class='location'></p><script>window.sidebarCurrent = {name: 'r2pipe', ty: 'mod', relpath: '../'};</script>
</section>
<nav class="sub">
<form class="search-form js-only">
<div class="search-container">
<input class="search-input" name="search"
autocomplete="off"
placeholder="Click or press 'S' to search, '?' for more options..."
type="search">
</div>
</form>
</nav>
<section id='main' class="content mod">
<h1 class='fqn'><span class='in-band'>Crate <a class='mod' href=''>r2pipe</a><wbr></span><span class='out-of-band'><a href='stability.html'>[stability]</a> <span id='render-detail'>
<a id="collapse-all" href="#">[-]</a>&nbsp;<a id="expand-all" href="#">[+]</a>
</span><a id='src-0' href='../src/r2pipe/lib.rs.html#1-45'>[src]</a></span></h1>
<div class='docblock'><p>R2Pipe provides functions to interact with <a href="http://rada.re/r/">radare2</a></p>
<p>Hence this requires you to have radare2 installed on you system. For more information please
refer to the official <a href="https://github.com/radare/radare2">radare2 Repository</a>.
The module spawns an instance of r2 and communicates with it over pipes. Using commands which
produce a JSON output is recommended as it is easier to parse.</p>
<p>R2Pipes are available for a several of languages. For more information about r2pipes in general head over to the
<a href="https://github.com/radare/radare2/wiki/R2PipeAPI">wiki</a>.</p>
<h1 id="design" class='section-header'><a
href="#design">Design</a></h1>
<p>All the functionality for the crate are exposed through two structs: <code>R2PipeLang</code> and
<code>R2PipeSpawn</code>. Typically, there are two ways to invoke r2pipe. One by spawning a child-process
from inside r2 and second by making the program spawn a child r2process.
<code>enum R2Pipe</code> is provided to allow easier use of the library and abstract the difference between these two methods.
The <code>macro open_pipe!()</code> determines which of the two methods to use.</p>
<p><strong>Note:</strong> For the second method,
the path of the executable to be analyzed must be provided, while this is implicit in the first
method (executable loaded by r2).</p>
<h1 id="example" class='section-header'><a
href="#example">Example</a></h1><pre id='rust-example-rendered' class='rust '>
<span class='attribute'>#[<span class='ident'>macro_use</span>]</span>
<span class='kw'>extern</span> <span class='kw'>crate</span> <span class='ident'>r2pipe</span>;
<span class='kw'>use</span> <span class='ident'>r2pipe</span>::<span class='ident'>R2Pipe</span>;
<span class='kw'>fn</span> <span class='ident'>main</span>() {
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>r2p</span> <span class='op'>=</span> <span class='macro'>open_pipe</span><span class='macro'>!</span>(<span class='string'>&quot;/bin/ls&quot;</span>).<span class='ident'>unwrap</span>();
<span class='macro'>println</span><span class='macro'>!</span>(<span class='string'>&quot;{}&quot;</span>, <span class='ident'>r2p</span>.<span class='ident'>cmd</span>(<span class='string'>&quot;?e Hello World&quot;</span>));
<span class='kw'>let</span> <span class='ident'>json</span> <span class='op'>=</span> <span class='ident'>r2p</span>.<span class='ident'>cmdj</span>(<span class='string'>&quot;ij&quot;</span>);
<span class='macro'>println</span><span class='macro'>!</span>(<span class='string'>&quot;{}&quot;</span>, <span class='ident'>json</span>.<span class='ident'>pretty</span>());
<span class='macro'>println</span><span class='macro'>!</span>(<span class='string'>&quot;ARCH {}&quot;</span>, <span class='ident'>json</span>.<span class='ident'>find_path</span>(<span class='kw-2'>&amp;</span>[<span class='string'>&quot;bin&quot;</span>,<span class='string'>&quot;arch&quot;</span>]).<span class='ident'>unwrap</span>());
<span class='ident'>r2p</span>.<span class='ident'>close</span>();
}
</pre>
</div><h2 id='reexports' class='section-header'><a href="#reexports">Reexports</a></h2>
<table><tr><td><code>pub use self::<a class='mod'
href='./r2pipe/index.html'>r2pipe</a>::<a class='enum' href='../r2pipe/r2pipe/enum.R2Pipe.html' title='r2pipe::r2pipe::R2Pipe'>R2Pipe</a>;</code></td></tr></table><h2 id='modules' class='section-header'><a href="#modules">Modules</a></h2>
<table>
<tr>
<td><a class='stability Unmarked' title='No stability level'></a><a class='mod' href='r2pipe/index.html'
title='r2pipe::r2pipe'>r2pipe</a></td>
<td class='docblock short'><p>Provides functionality to connect with radare2.</p>
</td>
</tr>
</table><h2 id='macros' class='section-header'><a href="#macros">Macros</a></h2>
<table>
<tr>
<td><a class='stability Unmarked' title='No stability level'></a><a class='macro' href='macro.open_pipe!.html'
title='r2pipe::open_pipe!'>open_pipe!</a></td>
<td class='docblock short'></td>
</tr>
</table></section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../jquery.js"></script>
<script src="../main.js"></script>
<script async src="../search-index.js"></script>
</body>
</html>
-101
View File
@@ -1,101 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="rustdoc">
<meta name="description" content="API documentation for the Rust `open_pipe!` macro in crate `r2pipe`.">
<meta name="keywords" content="rust, rustlang, rust-lang, open_pipe!">
<title>r2pipe::open_pipe! - Rust</title>
<link rel="stylesheet" type="text/css" href="../main.css">
</head>
<body class="rustdoc">
<!--[if lte IE 8]>
<div class="warning">
This old browser is unsupported and will most likely display funky
things.
</div>
<![endif]-->
<section class="sidebar">
<p class='location'><a href='index.html'>r2pipe</a></p><script>window.sidebarCurrent = {name: 'open_pipe!', ty: 'macro', relpath: ''};</script><script defer src="sidebar-items.js"></script>
</section>
<nav class="sub">
<form class="search-form js-only">
<div class="search-container">
<input class="search-input" name="search"
autocomplete="off"
placeholder="Click or press 'S' to search, '?' for more options..."
type="search">
</div>
</form>
</nav>
<section id='main' class="content macro">
<h1 class='fqn'><span class='in-band'><a href='index.html'>r2pipe</a>::<wbr><a class='macro' href=''>open_pipe!</a><wbr></span><span class='out-of-band'><span id='render-detail'>
<a id="collapse-all" href="#">[-]</a>&nbsp;<a id="expand-all" href="#">[+]</a>
</span><a id='src-699' href='../src/r2pipe/r2pipe.rs.html#50-53'>[src]</a></span></h1>
<pre class='rust macro'>
<span class='macro'>macro_rules</span><span class='macro'>!</span> <span class='ident'>open_pipe</span> {
(<span class='macro-nonterminal'>$</span><span class='macro-nonterminal'>x</span>:<span class='ident'>expr</span>) <span class='op'>=&gt;</span> (<span class='ident'>R2Pipe</span>::<span class='ident'>spawn</span>(<span class='macro-nonterminal'>$</span><span class='macro-nonterminal'>x</span>));
() <span class='op'>=&gt;</span> (<span class='ident'>R2Pipe</span>::<span class='ident'>open</span>());
}
</pre>
</section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../jquery.js"></script>
<script src="../main.js"></script>
<script async src="../search-index.js"></script>
</body>
</html>
-107
View File
@@ -1,107 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="rustdoc">
<meta name="description" content="API documentation for the Rust `R2Pipe` enum in crate `r2pipe`.">
<meta name="keywords" content="rust, rustlang, rust-lang, R2Pipe">
<title>r2pipe::r2pipe::R2Pipe - Rust</title>
<link rel="stylesheet" type="text/css" href="../../main.css">
</head>
<body class="rustdoc">
<!--[if lte IE 8]>
<div class="warning">
This old browser is unsupported and will most likely display funky
things.
</div>
<![endif]-->
<section class="sidebar">
<p class='location'><a href='../index.html'>r2pipe</a>::<wbr><a href='index.html'>r2pipe</a></p><script>window.sidebarCurrent = {name: 'R2Pipe', ty: 'enum', relpath: ''};</script><script defer src="sidebar-items.js"></script>
</section>
<nav class="sub">
<form class="search-form js-only">
<div class="search-container">
<input class="search-input" name="search"
autocomplete="off"
placeholder="Click or press 'S' to search, '?' for more options..."
type="search">
</div>
</form>
</nav>
<section id='main' class="content enum">
<h1 class='fqn'><span class='in-band'>Enum <a href='../index.html'>r2pipe</a>::<wbr><a href='index.html'>r2pipe</a>::<wbr><a class='enum' href=''>R2Pipe</a><wbr></span><span class='out-of-band'><span id='render-detail'>
<a id="collapse-all" href="#">[-]</a>&nbsp;<a id="expand-all" href="#">[+]</a>
</span><a id='src-31' href='../../src/r2pipe/r2pipe.rs.html#30-33'>[src]</a></span></h1>
<pre class='rust enum'>pub enum R2Pipe {
Pipe(<a class='struct' href='../../r2pipe/r2pipe/struct.R2PipeSpawn.html' title='r2pipe::r2pipe::R2PipeSpawn'>R2PipeSpawn</a>),
Lang(<a class='struct' href='../../r2pipe/r2pipe/struct.R2PipeLang.html' title='r2pipe::r2pipe::R2PipeLang'>R2PipeLang</a>),
}</pre><div class='docblock'><p>Provides abstraction between the two invocation methods.</p>
</div><h2 class='variants'>Variants</h2>
<table><tr><td id='variant.Pipe'><a class='stability Unmarked' title='No stability level'></a><code>Pipe</code></td><td></td></tr><tr><td id='variant.Lang'><a class='stability Unmarked' title='No stability level'></a><code>Lang</code></td><td></td></tr></table><h2 id='methods'>Methods</h2><h3 class='impl'><a class='stability Unmarked' title='No stability level'></a><code>impl <a class='enum' href='../../r2pipe/r2pipe/enum.R2Pipe.html' title='r2pipe::r2pipe::R2Pipe'>R2Pipe</a></code></h3><div class='impl-items'><h4 id='method.open' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.open' class='fnname'>open</a>() -&gt; <a class='enum' href='http://doc.rust-lang.org/nightly/core/result/enum.Result.html' title='core::result::Result'>Result</a>&lt;<a class='enum' href='../../r2pipe/r2pipe/enum.R2Pipe.html' title='r2pipe::r2pipe::R2Pipe'>R2Pipe</a>, &amp;'static <a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>&gt;</code></h4>
<h4 id='method.cmd' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.cmd' class='fnname'>cmd</a>(&amp;mut self, cmd: &amp;<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -&gt; <a class='struct' href='http://doc.rust-lang.org/nightly/collections/string/struct.String.html' title='collections::string::String'>String</a></code></h4>
<h4 id='method.cmdj' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.cmdj' class='fnname'>cmdj</a>(&amp;mut self, cmd: &amp;<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -&gt; <a class='enum' href='http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/enum.Json.html' title='rustc_serialize::json::Json'>Json</a></code></h4>
<h4 id='method.close' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.close' class='fnname'>close</a>(&amp;mut self)</code></h4>
<h4 id='method.in_session' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.in_session' class='fnname'>in_session</a>() -&gt; <a class='enum' href='http://doc.rust-lang.org/nightly/core/option/enum.Option.html' title='core::option::Option'>Option</a>&lt;<a href='http://doc.rust-lang.org/nightly/std/primitive.tuple.html'>(<a href='http://doc.rust-lang.org/nightly/std/primitive.i32.html'>i32</a>, <a href='http://doc.rust-lang.org/nightly/std/primitive.i32.html'>i32</a>)</a>&gt;</code></h4>
<h4 id='method.spawn' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.spawn' class='fnname'>spawn</a>(_name: &amp;<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -&gt; <a class='enum' href='http://doc.rust-lang.org/nightly/core/result/enum.Result.html' title='core::result::Result'>Result</a>&lt;<a class='enum' href='../../r2pipe/r2pipe/enum.R2Pipe.html' title='r2pipe::r2pipe::R2Pipe'>R2Pipe</a>, &amp;'static <a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>&gt;</code></h4>
<div class='docblock'><p>Creates a new R2PipeSpawn.</p>
</div></div></section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../../jquery.js"></script>
<script src="../../main.js"></script>
<script async src="../../search-index.js"></script>
</body>
</html>
-121
View File
@@ -1,121 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="rustdoc">
<meta name="description" content="API documentation for the Rust `r2pipe` mod in crate `r2pipe`.">
<meta name="keywords" content="rust, rustlang, rust-lang, r2pipe">
<title>r2pipe::r2pipe - Rust</title>
<link rel="stylesheet" type="text/css" href="../../main.css">
</head>
<body class="rustdoc">
<!--[if lte IE 8]>
<div class="warning">
This old browser is unsupported and will most likely display funky
things.
</div>
<![endif]-->
<section class="sidebar">
<p class='location'><a href='../index.html'>r2pipe</a></p><script>window.sidebarCurrent = {name: 'r2pipe', ty: 'mod', relpath: '../'};</script><script defer src="../sidebar-items.js"></script>
</section>
<nav class="sub">
<form class="search-form js-only">
<div class="search-container">
<input class="search-input" name="search"
autocomplete="off"
placeholder="Click or press 'S' to search, '?' for more options..."
type="search">
</div>
</form>
</nav>
<section id='main' class="content mod">
<h1 class='fqn'><span class='in-band'>Module <a href='../index.html'>r2pipe</a>::<wbr><a class='mod' href=''>r2pipe</a><wbr></span><span class='out-of-band'><span id='render-detail'>
<a id="collapse-all" href="#">[-]</a>&nbsp;<a id="expand-all" href="#">[+]</a>
</span><a id='src-6' href='../../src/r2pipe/r2pipe.rs.html#1-196'>[src]</a></span></h1>
<div class='docblock'><p>Provides functionality to connect with radare2.</p>
<p>Please check crate level documentation for more details and example.</p>
</div><h2 id='structs' class='section-header'><a href="#structs">Structs</a></h2>
<table>
<tr>
<td><a class='stability Unmarked' title='No stability level'></a><a class='struct' href='struct.R2PipeLang.html'
title='r2pipe::r2pipe::R2PipeLang'>R2PipeLang</a></td>
<td class='docblock short'><p>File descriptors to the parent r2 process.</p>
</td>
</tr>
<tr>
<td><a class='stability Unmarked' title='No stability level'></a><a class='struct' href='struct.R2PipeSpawn.html'
title='r2pipe::r2pipe::R2PipeSpawn'>R2PipeSpawn</a></td>
<td class='docblock short'><p>Stores descriptors to the spawned r2 process.</p>
</td>
</tr>
</table><h2 id='enums' class='section-header'><a href="#enums">Enums</a></h2>
<table>
<tr>
<td><a class='stability Unmarked' title='No stability level'></a><a class='enum' href='enum.R2Pipe.html'
title='r2pipe::r2pipe::R2Pipe'>R2Pipe</a></td>
<td class='docblock short'><p>Provides abstraction between the two invocation methods.</p>
</td>
</tr>
</table></section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../../jquery.js"></script>
<script src="../../main.js"></script>
<script async src="../../search-index.js"></script>
</body>
</html>
-1
View File
@@ -1 +0,0 @@
initSidebarItems({"struct":[["R2PipeLang","File descriptors to the parent r2 process."],["R2PipeSpawn","Stores descriptors to the spawned r2 process."]],"enum":[["R2Pipe","Provides abstraction between the two invocation methods."]]});
-101
View File
@@ -1,101 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="rustdoc">
<meta name="description" content="API documentation for the Rust `R2PipeLang` struct in crate `r2pipe`.">
<meta name="keywords" content="rust, rustlang, rust-lang, R2PipeLang">
<title>r2pipe::r2pipe::R2PipeLang - Rust</title>
<link rel="stylesheet" type="text/css" href="../../main.css">
</head>
<body class="rustdoc">
<!--[if lte IE 8]>
<div class="warning">
This old browser is unsupported and will most likely display funky
things.
</div>
<![endif]-->
<section class="sidebar">
<p class='location'><a href='../index.html'>r2pipe</a>::<wbr><a href='index.html'>r2pipe</a></p><script>window.sidebarCurrent = {name: 'R2PipeLang', ty: 'struct', relpath: ''};</script><script defer src="sidebar-items.js"></script>
</section>
<nav class="sub">
<form class="search-form js-only">
<div class="search-container">
<input class="search-input" name="search"
autocomplete="off"
placeholder="Click or press 'S' to search, '?' for more options..."
type="search">
</div>
</form>
</nav>
<section id='main' class="content struct">
<h1 class='fqn'><span class='in-band'>Struct <a href='../index.html'>r2pipe</a>::<wbr><a href='index.html'>r2pipe</a>::<wbr><a class='struct' href=''>R2PipeLang</a><wbr></span><span class='out-of-band'><span id='render-detail'>
<a id="collapse-all" href="#">[-]</a>&nbsp;<a id="expand-all" href="#">[+]</a>
</span><a id='src-19' href='../../src/r2pipe/r2pipe.rs.html#18-21'>[src]</a></span></h1>
<pre class='rust struct'>pub struct R2PipeLang {
// some fields omitted
}</pre><div class='docblock'><p>File descriptors to the parent r2 process.</p>
</div><h2 id='methods'>Methods</h2><h3 class='impl'><a class='stability Unmarked' title='No stability level'></a><code>impl <a class='struct' href='../../r2pipe/r2pipe/struct.R2PipeLang.html' title='r2pipe::r2pipe::R2PipeLang'>R2PipeLang</a></code></h3><div class='impl-items'><h4 id='method.cmd' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.cmd' class='fnname'>cmd</a>(&amp;mut self, cmd: &amp;<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -&gt; <a class='struct' href='http://doc.rust-lang.org/nightly/collections/string/struct.String.html' title='collections::string::String'>String</a></code></h4>
<h4 id='method.cmdj' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.cmdj' class='fnname'>cmdj</a>(&amp;mut self, cmd: &amp;<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -&gt; <a class='enum' href='http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/enum.Json.html' title='rustc_serialize::json::Json'>Json</a></code></h4>
<h4 id='method.close' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.close' class='fnname'>close</a>(&amp;mut self)</code></h4>
</div></section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../../jquery.js"></script>
<script src="../../main.js"></script>
<script async src="../../search-index.js"></script>
</body>
</html>
-101
View File
@@ -1,101 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="rustdoc">
<meta name="description" content="API documentation for the Rust `R2PipeSpawn` struct in crate `r2pipe`.">
<meta name="keywords" content="rust, rustlang, rust-lang, R2PipeSpawn">
<title>r2pipe::r2pipe::R2PipeSpawn - Rust</title>
<link rel="stylesheet" type="text/css" href="../../main.css">
</head>
<body class="rustdoc">
<!--[if lte IE 8]>
<div class="warning">
This old browser is unsupported and will most likely display funky
things.
</div>
<![endif]-->
<section class="sidebar">
<p class='location'><a href='../index.html'>r2pipe</a>::<wbr><a href='index.html'>r2pipe</a></p><script>window.sidebarCurrent = {name: 'R2PipeSpawn', ty: 'struct', relpath: ''};</script><script defer src="sidebar-items.js"></script>
</section>
<nav class="sub">
<form class="search-form js-only">
<div class="search-container">
<input class="search-input" name="search"
autocomplete="off"
placeholder="Click or press 'S' to search, '?' for more options..."
type="search">
</div>
</form>
</nav>
<section id='main' class="content struct">
<h1 class='fqn'><span class='in-band'>Struct <a href='../index.html'>r2pipe</a>::<wbr><a href='index.html'>r2pipe</a>::<wbr><a class='struct' href=''>R2PipeSpawn</a><wbr></span><span class='out-of-band'><span id='render-detail'>
<a id="collapse-all" href="#">[-]</a>&nbsp;<a id="expand-all" href="#">[+]</a>
</span><a id='src-25' href='../../src/r2pipe/r2pipe.rs.html#24-27'>[src]</a></span></h1>
<pre class='rust struct'>pub struct R2PipeSpawn {
// some fields omitted
}</pre><div class='docblock'><p>Stores descriptors to the spawned r2 process.</p>
</div><h2 id='methods'>Methods</h2><h3 class='impl'><a class='stability Unmarked' title='No stability level'></a><code>impl <a class='struct' href='../../r2pipe/r2pipe/struct.R2PipeSpawn.html' title='r2pipe::r2pipe::R2PipeSpawn'>R2PipeSpawn</a></code></h3><div class='impl-items'><h4 id='method.cmd' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.cmd' class='fnname'>cmd</a>(&amp;mut self, cmd: &amp;<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -&gt; <a class='struct' href='http://doc.rust-lang.org/nightly/collections/string/struct.String.html' title='collections::string::String'>String</a></code></h4>
<h4 id='method.cmdj' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.cmdj' class='fnname'>cmdj</a>(&amp;mut self, cmd: &amp;<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -&gt; <a class='enum' href='http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/enum.Json.html' title='rustc_serialize::json::Json'>Json</a></code></h4>
<h4 id='method.close' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.close' class='fnname'>close</a>(&amp;mut self)</code></h4>
</div></section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../../jquery.js"></script>
<script src="../../main.js"></script>
<script async src="../../search-index.js"></script>
</body>
</html>
-1
View File
@@ -1 +0,0 @@
initSidebarItems({"macro":[["open_pipe!",""]],"mod":[["r2pipe","Provides functionality to connect with radare2."]]});
-102
View File
@@ -1,102 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="rustdoc">
<meta name="description" content="API stability overview for the Rust `r2pipe` crate.">
<meta name="keywords" content="rust, rustlang, rust-lang">
<title>r2pipe - Stability dashboard</title>
<link rel="stylesheet" type="text/css" href="../main.css">
</head>
<body class="rustdoc">
<!--[if lte IE 8]>
<div class="warning">
This old browser is unsupported and will most likely display funky
things.
</div>
<![endif]-->
<section class="sidebar">
<p class='location'></p><script>window.sidebarCurrent = {name: 'r2pipe', ty: 'mod', relpath: '../'};</script>
</section>
<nav class="sub">
<form class="search-form js-only">
<div class="search-container">
<input class="search-input" name="search"
autocomplete="off"
placeholder="Click or press 'S' to search, '?' for more options..."
type="search">
</div>
</form>
</nav>
<section id='main' class="content mod"><h1 class='fqn'>Stability dashboard: crate <a class='mod' href='index.html'>r2pipe</a></h1>
This dashboard summarizes the stability levels for all of the public modules of
the crate, according to the total number of items at each level in the module and
its children (percentages total for r2pipe):
<blockquote>
<a class='stability Stable'></a> stable (0%),<br/>
<a class='stability Unstable'></a> unstable (0%),<br/>
<a class='stability Deprecated'></a> deprecated (0%),<br/>
<a class='stability Unmarked'></a> unmarked (100%)
</blockquote>
The counts do not include methods or trait
implementations that are visible only through a re-exported type.<table><tr><td><a href='index.html'>r2pipe</a></td><td class='summary-column'><span class='summary Stable' style='width: 0.0000%; display: inline-block'>&nbsp</span><span class='summary Unstable' style='width: 0.0000%; display: inline-block'>&nbsp</span><span class='summary Deprecated' style='width: 0.0000%; display: inline-block'>&nbsp</span><span class='summary Unmarked' style='width: 100.0000%; display: inline-block'>&nbsp</span></td></tr><tr><td><a href='r2pipe/index.html'>r2pipe::r2pipe</a></td><td class='summary-column'><span class='summary Stable' style='width: 0.0000%; display: inline-block'>&nbsp</span><span class='summary Unstable' style='width: 0.0000%; display: inline-block'>&nbsp</span><span class='summary Deprecated' style='width: 0.0000%; display: inline-block'>&nbsp</span><span class='summary Unmarked' style='width: 100.0000%; display: inline-block'>&nbsp</span></td></tr></table></section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../jquery.js"></script>
<script src="../main.js"></script>
<script async src="../search-index.js"></script>
</body>
</html>
-1
View File
@@ -1 +0,0 @@
{"name":"r2pipe","counts":{"deprecated":0,"unstable":0,"stable":0,"unmarked":23},"submodules":[{"name":"r2pipe","counts":{"deprecated":0,"unstable":0,"stable":0,"unmarked":21},"submodules":[]}]}
-3
View File
@@ -1,3 +0,0 @@
var searchIndex = {};
searchIndex['r2pipe'] = {"items":[[0,"","r2pipe","R2Pipe provides functions to interact with [radare2](http://rada.re/r/)",null,null],[0,"r2pipe","","Provides functionality to connect with radare2.",null,null],[3,"R2PipeLang","r2pipe::r2pipe","File descriptors to the parent r2 process.",null,null],[3,"R2PipeSpawn","","Stores descriptors to the spawned r2 process.",null,null],[4,"R2Pipe","","Provides abstraction between the two invocation methods.",null,null],[13,"Pipe","","",0,null],[13,"Lang","","",0,null],[11,"open","","",0,{"inputs":[{"name":"r2pipe"}],"output":{"name":"result"}}],[11,"cmd","","",0,{"inputs":[{"name":"r2pipe"},{"name":"str"}],"output":{"name":"string"}}],[11,"cmdj","","",0,{"inputs":[{"name":"r2pipe"},{"name":"str"}],"output":{"name":"json"}}],[11,"close","","",0,{"inputs":[{"name":"r2pipe"}],"output":null}],[11,"in_session","","",0,{"inputs":[{"name":"r2pipe"}],"output":{"name":"option"}}],[11,"spawn","","Creates a new R2PipeSpawn.",0,{"inputs":[{"name":"r2pipe"},{"name":"str"}],"output":{"name":"result"}}],[11,"cmd","","",1,{"inputs":[{"name":"r2pipespawn"},{"name":"str"}],"output":{"name":"string"}}],[11,"cmdj","","",1,{"inputs":[{"name":"r2pipespawn"},{"name":"str"}],"output":{"name":"json"}}],[11,"close","","",1,{"inputs":[{"name":"r2pipespawn"}],"output":null}],[11,"cmd","","",2,{"inputs":[{"name":"r2pipelang"},{"name":"str"}],"output":{"name":"string"}}],[11,"cmdj","","",2,{"inputs":[{"name":"r2pipelang"},{"name":"str"}],"output":{"name":"json"}}],[11,"close","","",2,{"inputs":[{"name":"r2pipelang"}],"output":null}],[14,"open_pipe!","r2pipe","",null,null]],"paths":[[4,"R2Pipe"],[3,"R2PipeSpawn"],[3,"R2PipeLang"]]};
initSearch(searchIndex);
+81
View File
@@ -0,0 +1,81 @@
use crate::Result;
use libloading::{Library, Symbol};
use std::sync::Mutex;
/// Contains a handle to the dynamically loaded library.
pub struct LibHandle(Mutex<Library>);
impl LibHandle {
#[cfg(windows)]
fn load_library(path: &str) -> std::result::Result<Library, libloading::Error> {
use libloading::os::windows::{
Library as WindowsLibrary, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS,
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR,
};
if path.contains('\\') || path.contains('/') {
unsafe {
WindowsLibrary::load_with_flags(
path,
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS,
)
.map(Into::into)
}
} else {
unsafe { Library::new(path) }
}
}
#[cfg(not(windows))]
fn load_library(path: &str) -> std::result::Result<Library, libloading::Error> {
unsafe { Library::new(path) }
}
/// Load a shared library by name with platform-specific extension.
pub fn new(name: &str, end: Option<&str>) -> Result<LibHandle> {
let ext = if cfg!(windows) {
".dll"
} else if cfg!(target_os = "macos") {
".dylib"
} else {
".so"
};
let lib_name = format!("{}{}{}", name, ext, end.unwrap_or(""));
// Prepare list of paths to try
let mut lib_paths = vec![lib_name.clone()];
// On Windows, add common radare2 installation paths
if cfg!(windows) {
// CI installs to C:\radare2\<version>\bin, where version changes
// So we need to search for the latest version directory
lib_paths.push(format!("C:\\radare2\\bin\\{}", lib_name));
// Also try the versioned path pattern from CI
if let Ok(entries) = std::fs::read_dir("C:\\radare2") {
for entry in entries.flatten() {
if entry.file_type().is_ok_and(|ft| ft.is_dir()) {
let version_path = format!("{}\\bin\\{}", entry.path().display(), lib_name);
lib_paths.push(version_path);
}
}
}
}
// Try each path until we find one that works
for lib_path in &lib_paths {
if let Ok(lib) = Self::load_library(lib_path) {
return Ok(LibHandle(Mutex::new(lib)));
}
}
// If none worked, return the error from the first attempt
Err(Self::load_library(&lib_paths[0]).unwrap_err().into())
}
/// Load a symbol from the library and transmute it to the desired type.
pub unsafe fn load_sym<T>(&mut self, name: &str) -> Result<T> {
let lib = self.0.lock().unwrap();
let sym: Symbol<T> = lib.get(name.as_bytes())?;
Ok(std::mem::transmute_copy::<_, T>(&*sym))
}
}
+47
View File
@@ -0,0 +1,47 @@
use std::sync::mpsc::{RecvError, SendError, TryRecvError};
use std::{io, str};
use thiserror::Error;
/// Custom `Error` for r2pipe.rs.
#[derive(Error, Debug)]
pub enum Error {
/// An I/O error occurred.
#[error("I/O error")]
Io(#[from] io::Error),
/// No open radare2 session, perhaps path was not specified.
#[error("No open session")]
NoSession,
/// Response had invalid/missing JSON.
#[error("Empty response from JSON")]
EmptyResponse,
/// Incorrect number of arguments, or incorrect format.
#[error("Argument mismatch")]
ArgumentMismatch,
/// An error occurred inside of serde.
#[error("Serde deserialization error")]
SerdeError(#[from] serde_json::Error),
/// Error during UTF-8 decoding.
#[error("UTF-8 decoding error")]
Utf8(#[from] str::Utf8Error),
/// Error receiving data from channel.
#[error("Receive channel data error")]
ChannelReceiveError(#[from] RecvError),
/// Error trying to receive data from channel.
#[error("Trying receive channel data error")]
ChannelTryReceiveError(#[from] TryRecvError),
/// Error sending data through channel.
#[error("Send channel data error")]
ChannelSendError(#[from] SendError<String>),
/// Error loading radare2 shared library.
#[error("Shared library error: {0}")]
SharedLibraryError(#[from] libloading::Error),
}
+70
View File
@@ -0,0 +1,70 @@
//! `R2Pipe` provides functions to interact with [radare2](http://rada.re/r/).
//! This aims to be a raw API. For more higher-level functions and structs to abstract
//! over the generated output, see [r2pipe.rs-frontend]().
//!
//! Hence this requires you to have radare2 installed on you system. For more
//! information refer to the r2 [repository](https://github.com/radare/radare2).
//! The module spawns an instance of r2 and communicates with it over pipes.
//! Using commands which produce a JSON output is recommended and easier to
//! parse.
//!
//! `R2Pipe`s are available for a several of languages. For more information
//! about r2pipes in general head over to the
//! [wiki](https://github.com/radare/radare2/wiki/R2PipeAPI).
//!
//! # Design
//! All the functionality for the crate are exposed through two structs:
//! `R2PipeLang` and `R2PipeSpawn`.
//!
//! Typically, there are two ways to invoke r2pipe. One by spawning a
//! child-process
//! from inside r2 and second by making the program spawn a child r2process.
//! `enum R2Pipe` is provided to allow easier use of the library and abstract
//! the
//! difference between these two methods.
//!
//! The `macro open_pipe!()` determines which of the two methods to use.
//!
//! **Note:** For the second method,
//! the path of the executable to be analyzed must be provided, while this is
//! implicit in the first (pass `None`) method (executable loaded by r2).
//!
//! # Example
//! ```no_run
//! #[macro_use]
//! extern crate r2pipe;
//! extern crate serde_json;
//! use r2pipe::R2Pipe;
//! fn main() {
//! let path = Some("/bin/ls".to_owned());
//! let mut r2p = open_pipe!(path).unwrap();
//! println!("{}", r2p.cmd("?e Hello World").unwrap());
//! if let Ok(json) = r2p.cmdj("ij") {
//! println!("{}", serde_json::to_string_pretty(&json).unwrap());
//! println!("ARCH {}", json["bin"]["arch"]);
//! }
//! r2p.close();
//! }
//! ```
//!
//! The crate offers various methods to interact with r2pipe, eg. via process (multi-threadable), http or tcp.
//! Check the examples/ dir for more complete examples.
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc(html_root_url = "https://radare.github.io/r2pipe.rs/")]
#[macro_use]
pub mod r2pipe;
mod dlfcn;
pub mod r2;
mod error;
pub use error::*;
#[doc(hidden)]
pub type Result<T> = std::result::Result<T, error::Error>;
// Rexport to bring it out one module.
pub use self::r2::R2;
pub use self::r2pipe::R2Pipe;
pub use self::r2pipe::R2PipeSpawnOptions;
+84
View File
@@ -0,0 +1,84 @@
// Copyright (c) 2015, The Radare Project. All rights reserved.
// See the COPYING file at the top-level directory of this distribution.
// Licensed under the BSD 3-Clause License:
// <http://opensource.org/licenses/BSD-3-Clause>
// This file may not be copied, modified, or distributed
// except according to those terms.
//! Few functions for initialization, communication and termination of r2.
//!
//! If you wish to write wrappers for certain r2 functionalities,
//! contribute to the r2pipe.rs-frontend project. This aims to be a
//! barebones implementation of the pipe concept.
use crate::{r2pipe::R2Pipe, Error, Result};
use serde_json::Value;
pub struct R2 {
pipe: R2Pipe,
readin: String,
}
impl Default for R2 {
fn default() -> R2 {
R2::new::<&str>(None).expect("Unable to spawn r2 or find an open r2pipe")
}
}
// fn send and recv allow users to send their own commands,
// i.e. The ones that are not currently abstracted by the R2 API.
// Ideally, all commonly used commands must be supported for easier use.
impl R2 {
pub fn new<T: AsRef<str>>(path: Option<T>) -> Result<R2> {
if path.is_none() && !R2::in_session() {
return Err(Error::NoSession);
}
// This means that path is `Some` or we have an open session.
let pipe = open_pipe!(path.as_ref())?;
Ok(R2 {
pipe,
readin: String::new(),
})
}
pub fn in_session() -> bool {
R2Pipe::in_session().is_some()
}
pub fn from(r2p: R2Pipe) -> R2 {
R2 {
pipe: r2p,
readin: String::new(),
}
}
pub fn close(&mut self) -> Result<()> {
self.send("q!")?;
Ok(())
}
pub fn send(&mut self, cmd: &str) -> Result<()> {
self.readin = self.pipe.cmd(cmd)?;
Ok(())
}
pub fn recv(&mut self) -> String {
let res = self.readin.clone();
self.flush();
res
}
pub fn recv_json(&mut self) -> Result<Value> {
let mut res = self.recv().replace('\n', "");
if res.is_empty() {
res = "{}".to_owned();
}
Ok(serde_json::from_str(&res)?)
}
pub fn flush(&mut self) {
self.readin = String::from("");
}
}
+443
View File
@@ -0,0 +1,443 @@
//! Provides functionality to connect with radare2.
//!
//! Please check crate level documentation for more details and example.
use crate::dlfcn;
use crate::{Error, Result};
use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::net::{SocketAddr, TcpStream, ToSocketAddrs};
use std::path::Path;
use std::process;
use std::process::Command;
use std::process::Stdio;
use std::str;
use std::sync::mpsc;
use std::sync::Arc;
use std::thread;
use serde_json::Value;
/// File descriptors to the parent r2 process.
pub struct R2PipeLang {
read: BufReader<File>,
write: File,
}
/// Stores descriptors to the spawned r2 process.
pub struct R2PipeSpawn {
read: BufReader<process::ChildStdout>,
write: process::ChildStdin,
child: Option<process::Child>,
}
/// Stores the socket address of the r2 process.
pub struct R2PipeTcp {
socket_addr: SocketAddr,
}
pub struct R2PipeHttp {
host: String,
}
/// Stores thread metadata
/// It stores both a sending and receiving end to the thread, allowing convenient interaction
/// So we can send commands using R2PipeThread::send() and fetch outputs using R2PipeThread::recv()
pub struct R2PipeThread {
r2recv: mpsc::Receiver<String>,
r2send: mpsc::Sender<String>,
pub id: u16,
pub handle: thread::JoinHandle<Result<()>>,
}
#[derive(Clone)]
pub struct R2PipeSpawnOptions {
pub exepath: String,
pub args: Vec<&'static str>,
}
impl Default for R2PipeSpawnOptions {
fn default() -> Self {
let exepath = if cfg!(windows) { "radare2.exe" } else { "r2" };
R2PipeSpawnOptions {
exepath: exepath.to_string(),
args: Vec::default(),
}
}
}
/// Provides abstraction between the three invocation methods.
pub struct R2Pipe(Box<dyn Pipe>);
pub trait Pipe {
fn cmd(&mut self, cmd: &str) -> Result<String>;
fn cmdj(&mut self, cmd: &str) -> Result<Value> {
let result = self.cmd(cmd)?;
if result.is_empty() {
return Err(Error::EmptyResponse);
}
Ok(serde_json::from_str(&result)?)
}
/// Escape the command before executing, valid only as of r2 v.5.8.0 "icebucket"
fn call(&mut self, cmd: &str) -> Result<String> {
self.cmd(&format!("\"\"{}", cmd))
}
/// Escape the command before executing and convert it to a json value,
/// valid only as of r2 v.5.8.0 "icebucket"
fn callj(&mut self, cmd: &str) -> Result<Value> {
self.cmdj(&format!("\"\"{}", cmd))
}
fn close(&mut self) {}
}
fn getenv(k: &str) -> Option<i32> {
match env::var(k) {
Ok(val) => val.parse::<i32>().ok(),
Err(_) => None,
}
}
fn process_result(res: Vec<u8>) -> Result<String> {
let len = res.len();
if len == 0 {
Err(Error::EmptyResponse)
} else {
Ok(str::from_utf8(&res[..len - 1])?.to_string())
}
}
#[macro_export]
macro_rules! open_pipe {
() => {
R2Pipe::open(),
};
($x: expr) => {
match $x {
Some(path) => R2Pipe::load_native(&path.clone()).or_else(|_| R2Pipe::spawn(path, None)),
None => R2Pipe::open(),
}
};
($x: expr, $y: expr) => {
match $x $y {
Some(path, opts) => R2Pipe::spawn(path, opts),
(None, None) => R2Pipe::open(),
}
}
}
impl R2Pipe {
pub fn load_native<T: AsRef<str>>(path: T) -> Result<R2Pipe> {
Ok(R2Pipe(Box::new(R2PipeNative::open(path.as_ref())?)))
}
#[cfg(not(windows))]
pub fn open() -> Result<R2Pipe> {
use std::os::unix::io::FromRawFd;
let (f_in, f_out) = R2Pipe::in_session().ok_or(Error::NoSession)?;
let res = unsafe {
// dup file descriptors to avoid from_raw_fd ownership issue
let (d_in, d_out) = (libc::dup(f_in), libc::dup(f_out));
R2PipeLang {
read: BufReader::new(File::from_raw_fd(d_in)),
write: File::from_raw_fd(d_out),
}
};
Ok(R2Pipe(Box::new(res)))
}
#[cfg(windows)]
pub fn open() -> Result<R2Pipe> {
unimplemented!()
}
pub fn cmd(&mut self, cmd: &str) -> Result<String> {
self.0.cmd(cmd.trim())
}
pub fn cmdj(&mut self, cmd: &str) -> Result<Value> {
self.0.cmdj(cmd.trim())
}
pub fn close(&mut self) {
self.0.close();
}
/// Escape the command before executing, valid only as of r2 v.5.8.0 "icebucket"
pub fn call(&mut self, cmd: &str) -> Result<String> {
self.0.call(cmd)
}
/// Escape the command before executing and convert it to a json value,
/// valid only as of r2 v.5.8.0 "icebucket"
pub fn callj(&mut self, cmd: &str) -> Result<Value> {
self.0.callj(cmd)
}
pub fn in_session() -> Option<(i32, i32)> {
let f_in = getenv("R2PIPE_IN")?;
let f_out = getenv("R2PIPE_OUT")?;
Some((f_in, f_out))
}
#[cfg(windows)]
pub fn in_windows_session() -> Option<String> {
match env::var("R2PIPE_PATH") {
Ok(val) => Some(format!("\\\\.\\pipe\\{}", val)),
Err(_) => None,
}
}
/// Creates a new R2PipeSpawn.
pub fn spawn<T: AsRef<str>>(name: T, mut opts: Option<R2PipeSpawnOptions>) -> Result<R2Pipe> {
if name.as_ref() == "" && R2Pipe::in_session().is_some() {
return R2Pipe::open();
}
let R2PipeSpawnOptions { exepath, args } = opts.take().unwrap_or_default();
let path = Path::new(name.as_ref());
let mut child = Command::new(exepath)
.arg("-q0")
.args(&args)
.arg(path)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()?;
// If stdin/stdout is not available, hard error
let sin = child.stdin.take().unwrap();
let mut sout = child.stdout.take().unwrap();
// flush out the initial null byte.
let mut w = [0; 1];
sout.read_exact(&mut w)?;
let res = R2PipeSpawn {
read: BufReader::new(sout),
write: sin,
child: Some(child),
};
Ok(R2Pipe(Box::new(res)))
}
/// Creates a new R2PipeTcp
pub fn tcp<A: ToSocketAddrs>(addr: A) -> Result<R2Pipe> {
// use `connect` to figure out which socket address works
let stream = TcpStream::connect(addr)?;
let addr = stream.peer_addr()?;
Ok(R2Pipe(Box::new(R2PipeTcp { socket_addr: addr })))
}
/// Creates a new R2PipeHttp
pub fn http(host: &str) -> R2Pipe {
R2Pipe(Box::new(R2PipeHttp {
host: host.to_string(),
}))
}
/// Creates new pipe threads
/// First two arguments for R2Pipe::threads() are the same as for R2Pipe::spawn() but inside vectors
/// Third and last argument is an option to a callback function
/// The callback function takes two Arguments: Thread ID and r2pipe output
pub fn threads(
names: Vec<&'static str>,
opts: Vec<Option<R2PipeSpawnOptions>>,
callback: Option<Arc<dyn Fn(u16, String) + Sync + Send>>,
) -> Result<Vec<R2PipeThread>> {
if names.len() != opts.len() {
return Err(Error::ArgumentMismatch);
}
let mut pipes = Vec::new();
for n in 0..names.len() {
let (htx, rx) = mpsc::channel();
let (tx, hrx) = mpsc::channel();
let name = names[n];
let opt = opts[n].clone();
let cb = callback.clone();
let t = thread::spawn(move || -> Result<()> {
let mut r2 = R2Pipe::spawn(name, opt)?;
loop {
let cmd: String = hrx.recv()?;
if cmd == "q" {
break;
}
let res = r2.cmdj(&cmd)?.to_string();
htx.send(res.clone())?;
if let Some(cbs) = cb.clone() {
thread::spawn(move || {
cbs(n as u16, res);
});
};
}
Ok(())
});
pipes.push(R2PipeThread {
r2recv: rx,
r2send: tx,
id: n as u16,
handle: t,
});
}
Ok(pipes)
}
}
impl R2PipeThread {
pub fn send(&self, cmd: String) -> Result<()> {
Ok(self.r2send.send(cmd)?)
}
pub fn recv(&self, block: bool) -> Result<String> {
if block {
Ok(self.r2recv.recv()?)
} else {
Ok(self.r2recv.try_recv()?)
}
}
}
impl Pipe for R2PipeSpawn {
fn cmd(&mut self, cmd: &str) -> Result<String> {
let cmd = cmd.to_owned() + "\n";
self.write.write_all(cmd.as_bytes())?;
let mut res: Vec<u8> = Vec::new();
self.read.read_until(0u8, &mut res)?;
process_result(res)
}
fn close(&mut self) {
let _ = self.cmd("q!");
if let Some(child) = &mut self.child {
let _ = child.wait();
}
}
}
impl R2PipeSpawn {
/// Attempts to take the pipes underlying child process handle.
/// On success the handle is returned.
/// If `None` is returned the child handle was already taken previously.
/// By using this method you take over the responsibility to `wait()` the child process in order to free all of it's resources.
pub fn take_child(&mut self) -> Option<process::Child> {
self.child.take()
}
}
impl Pipe for R2PipeLang {
fn cmd(&mut self, cmd: &str) -> Result<String> {
self.write.write_all(cmd.as_bytes())?;
let mut res: Vec<u8> = Vec::new();
self.read.read_until(0u8, &mut res)?;
process_result(res)
}
}
impl Pipe for R2PipeHttp {
fn cmd(&mut self, cmd: &str) -> Result<String> {
let host = if self.host.starts_with("http://") {
&self.host[7..]
} else {
&self.host
};
let mut stream = TcpStream::connect(host)?;
let req = format!("GET /cmd/{} HTTP/1.1\r\n", cmd);
let mut resp = Vec::with_capacity(1024);
stream.write_all(req.as_bytes())?;
stream.read_to_end(&mut resp)?;
// index of the start of response body
let index = resp
.windows(4)
.position(|w| w == "\r\n\r\n".as_bytes())
.map(|i| i + 4)
.unwrap_or(0);
Ok(str::from_utf8(&resp[index..]).map(|s| s.to_string())?)
}
}
impl Pipe for R2PipeTcp {
fn cmd(&mut self, cmd: &str) -> Result<String> {
let mut stream = TcpStream::connect(self.socket_addr)?;
stream.write_all(cmd.as_bytes())?;
let mut res: Vec<u8> = Vec::new();
stream.read_to_end(&mut res)?;
res.push(0);
process_result(res)
}
}
pub struct R2PipeNative {
lib: dlfcn::LibHandle,
r_core: std::sync::Mutex<*mut libc::c_void>,
r_core_cmd_str_handle: fn(*mut libc::c_void, *const libc::c_char) -> *mut libc::c_char,
}
impl R2PipeNative {
pub fn open(file: &str) -> Result<R2PipeNative> {
let lib_name = if cfg!(windows) { "r_core" } else { "libr_core" };
let mut lib = dlfcn::LibHandle::new(lib_name, None)?;
let r_core_new: fn() -> *mut libc::c_void = unsafe { lib.load_sym("r_core_new")? };
let r_core_cmd_str_handle = unsafe { lib.load_sym("r_core_cmd_str")? };
let r_core = r_core_new();
if r_core.is_null() {
return Err(Error::EmptyResponse);
}
let mut ret = R2PipeNative {
lib,
r_core: std::sync::Mutex::new(r_core),
r_core_cmd_str_handle,
};
ret.cmd(&format!("o {}", file))?;
Ok(ret)
}
}
impl Pipe for R2PipeNative {
fn cmd(&mut self, cmd: &str) -> Result<String> {
let r_core = *self.r_core.lock().unwrap();
let cmd = std::ffi::CString::new(cmd).map_err(|_| Error::ArgumentMismatch)?;
let res = (self.r_core_cmd_str_handle)(r_core, cmd.as_ptr());
if res.is_null() {
Err(Error::EmptyResponse)
} else {
Ok(unsafe { std::ffi::CStr::from_ptr(res).to_str()?.to_string() })
}
}
}
impl Drop for R2PipeNative {
fn drop(&mut self) {
let r_core = *self.r_core.lock().unwrap();
if let Ok(r_core_free) =
unsafe { self.lib.load_sym::<fn(*mut libc::c_void)>("r_core_free") }
{
r_core_free(r_core);
}
}
}
#[cfg(test)]
mod test {
use super::Pipe;
use super::R2PipeNative;
#[cfg(not(windows))]
use crate::R2Pipe;
#[test]
#[cfg(not(windows))]
fn spawn_test() {
let mut pipe = R2Pipe::spawn("/bin/ls", None).unwrap();
assert_eq!(pipe.cmd("echo test").unwrap(), "test\n");
}
#[test]
fn native_test() {
let mut r2p = R2PipeNative::open("malloc://32").unwrap();
assert_eq!("a\n", r2p.cmd("echo a").unwrap());
}
}
-183
View File
@@ -1,183 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="rustdoc">
<meta name="description" content="Source to the Rust file `src/lib.rs`.">
<meta name="keywords" content="rust, rustlang, rust-lang">
<title>lib.rs.html -- source</title>
<link rel="stylesheet" type="text/css" href="../../main.css">
</head>
<body class="rustdoc">
<!--[if lte IE 8]>
<div class="warning">
This old browser is unsupported and will most likely display funky
things.
</div>
<![endif]-->
<section class="sidebar">
</section>
<nav class="sub">
<form class="search-form js-only">
<div class="search-container">
<input class="search-input" name="search"
autocomplete="off"
placeholder="Click or press 'S' to search, '?' for more options..."
type="search">
</div>
</form>
</nav>
<section id='main' class="content source"><pre class="line-numbers"><span id="1"> 1</span>
<span id="2"> 2</span>
<span id="3"> 3</span>
<span id="4"> 4</span>
<span id="5"> 5</span>
<span id="6"> 6</span>
<span id="7"> 7</span>
<span id="8"> 8</span>
<span id="9"> 9</span>
<span id="10">10</span>
<span id="11">11</span>
<span id="12">12</span>
<span id="13">13</span>
<span id="14">14</span>
<span id="15">15</span>
<span id="16">16</span>
<span id="17">17</span>
<span id="18">18</span>
<span id="19">19</span>
<span id="20">20</span>
<span id="21">21</span>
<span id="22">22</span>
<span id="23">23</span>
<span id="24">24</span>
<span id="25">25</span>
<span id="26">26</span>
<span id="27">27</span>
<span id="28">28</span>
<span id="29">29</span>
<span id="30">30</span>
<span id="31">31</span>
<span id="32">32</span>
<span id="33">33</span>
<span id="34">34</span>
<span id="35">35</span>
<span id="36">36</span>
<span id="37">37</span>
<span id="38">38</span>
<span id="39">39</span>
<span id="40">40</span>
<span id="41">41</span>
<span id="42">42</span>
<span id="43">43</span>
<span id="44">44</span>
<span id="45">45</span>
</pre><pre class='rust '>
<span class='doccomment'>//! R2Pipe provides functions to interact with [radare2](http://rada.re/r/)</span>
<span class='doccomment'>//!</span>
<span class='doccomment'>//! Hence this requires you to have radare2 installed on you system. For more information please</span>
<span class='doccomment'>//! refer to the official [radare2 Repository](https://github.com/radare/radare2).</span>
<span class='doccomment'>//! The module spawns an instance of r2 and communicates with it over pipes. Using commands which</span>
<span class='doccomment'>//! produce a JSON output is recommended as it is easier to parse.</span>
<span class='doccomment'>//!</span>
<span class='doccomment'>//! R2Pipes are available for a several of languages. For more information about r2pipes in general head over to the</span>
<span class='doccomment'>//! [wiki](https://github.com/radare/radare2/wiki/R2PipeAPI).</span>
<span class='doccomment'>//!</span>
<span class='doccomment'>//! # Design</span>
<span class='doccomment'>//! All the functionality for the crate are exposed through two structs: `R2PipeLang` and</span>
<span class='doccomment'>//! `R2PipeSpawn`. Typically, there are two ways to invoke r2pipe. One by spawning a child-process</span>
<span class='doccomment'>//! from inside r2 and second by making the program spawn a child r2process.</span>
<span class='doccomment'>//! `enum R2Pipe` is provided to allow easier use of the library and abstract the difference between these two methods.</span>
<span class='doccomment'>//! The `macro open_pipe!()` determines which of the two methods to use.</span>
<span class='doccomment'>//!</span>
<span class='doccomment'>//! **Note:** For the second method,</span>
<span class='doccomment'>//! the path of the executable to be analyzed must be provided, while this is implicit in the first</span>
<span class='doccomment'>//! method (executable loaded by r2).</span>
<span class='doccomment'>//!</span>
<span class='doccomment'>//! # Example</span>
<span class='doccomment'>//! ```no_run</span>
<span class='doccomment'>//! #[macro_use]</span>
<span class='doccomment'>//! extern crate r2pipe;</span>
<span class='doccomment'>//! use r2pipe::R2Pipe;</span>
<span class='doccomment'>//! fn main() {</span>
<span class='doccomment'>//! let mut r2p = open_pipe!(&quot;/bin/ls&quot;).unwrap();</span>
<span class='doccomment'>//! println!(&quot;{}&quot;, r2p.cmd(&quot;?e Hello World&quot;));</span>
<span class='doccomment'>//! let json = r2p.cmdj(&quot;ij&quot;);</span>
<span class='doccomment'>//! println!(&quot;{}&quot;, json.pretty());</span>
<span class='doccomment'>//! println!(&quot;ARCH {}&quot;, json.find_path(&amp;[&quot;bin&quot;,&quot;arch&quot;]).unwrap());</span>
<span class='doccomment'>//! r2p.close();</span>
<span class='doccomment'>//! }</span>
<span class='doccomment'>//! ```</span>
<span class='attribute'>#<span class='op'>!</span>[<span class='ident'>doc</span>(<span class='ident'>html_root_url</span> <span class='op'>=</span> <span class='string'>&quot;https://radare.github.io/r2pipe.rs/&quot;</span>)]</span>
<span class='kw'>extern</span> <span class='kw'>crate</span> <span class='ident'>libc</span>;
<span class='kw'>extern</span> <span class='kw'>crate</span> <span class='ident'>rustc_serialize</span>;
<span class='kw'>pub</span> <span class='kw'>mod</span> <span class='ident'>r2pipe</span>;
<span class='comment'>// Rexport to bring it out one module.</span>
<span class='kw'>pub</span> <span class='kw'>use</span> <span class='self'>self</span>::<span class='ident'>r2pipe</span>::<span class='ident'>R2Pipe</span>;
</pre>
</section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../../jquery.js"></script>
<script src="../../main.js"></script>
<script async src="../../search-index.js"></script>
</body>
</html>
-485
View File
@@ -1,485 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="rustdoc">
<meta name="description" content="Source to the Rust file `src/r2pipe.rs`.">
<meta name="keywords" content="rust, rustlang, rust-lang">
<title>r2pipe.rs.html -- source</title>
<link rel="stylesheet" type="text/css" href="../../main.css">
</head>
<body class="rustdoc">
<!--[if lte IE 8]>
<div class="warning">
This old browser is unsupported and will most likely display funky
things.
</div>
<![endif]-->
<section class="sidebar">
</section>
<nav class="sub">
<form class="search-form js-only">
<div class="search-container">
<input class="search-input" name="search"
autocomplete="off"
placeholder="Click or press 'S' to search, '?' for more options..."
type="search">
</div>
</form>
</nav>
<section id='main' class="content source"><pre class="line-numbers"><span id="1"> 1</span>
<span id="2"> 2</span>
<span id="3"> 3</span>
<span id="4"> 4</span>
<span id="5"> 5</span>
<span id="6"> 6</span>
<span id="7"> 7</span>
<span id="8"> 8</span>
<span id="9"> 9</span>
<span id="10"> 10</span>
<span id="11"> 11</span>
<span id="12"> 12</span>
<span id="13"> 13</span>
<span id="14"> 14</span>
<span id="15"> 15</span>
<span id="16"> 16</span>
<span id="17"> 17</span>
<span id="18"> 18</span>
<span id="19"> 19</span>
<span id="20"> 20</span>
<span id="21"> 21</span>
<span id="22"> 22</span>
<span id="23"> 23</span>
<span id="24"> 24</span>
<span id="25"> 25</span>
<span id="26"> 26</span>
<span id="27"> 27</span>
<span id="28"> 28</span>
<span id="29"> 29</span>
<span id="30"> 30</span>
<span id="31"> 31</span>
<span id="32"> 32</span>
<span id="33"> 33</span>
<span id="34"> 34</span>
<span id="35"> 35</span>
<span id="36"> 36</span>
<span id="37"> 37</span>
<span id="38"> 38</span>
<span id="39"> 39</span>
<span id="40"> 40</span>
<span id="41"> 41</span>
<span id="42"> 42</span>
<span id="43"> 43</span>
<span id="44"> 44</span>
<span id="45"> 45</span>
<span id="46"> 46</span>
<span id="47"> 47</span>
<span id="48"> 48</span>
<span id="49"> 49</span>
<span id="50"> 50</span>
<span id="51"> 51</span>
<span id="52"> 52</span>
<span id="53"> 53</span>
<span id="54"> 54</span>
<span id="55"> 55</span>
<span id="56"> 56</span>
<span id="57"> 57</span>
<span id="58"> 58</span>
<span id="59"> 59</span>
<span id="60"> 60</span>
<span id="61"> 61</span>
<span id="62"> 62</span>
<span id="63"> 63</span>
<span id="64"> 64</span>
<span id="65"> 65</span>
<span id="66"> 66</span>
<span id="67"> 67</span>
<span id="68"> 68</span>
<span id="69"> 69</span>
<span id="70"> 70</span>
<span id="71"> 71</span>
<span id="72"> 72</span>
<span id="73"> 73</span>
<span id="74"> 74</span>
<span id="75"> 75</span>
<span id="76"> 76</span>
<span id="77"> 77</span>
<span id="78"> 78</span>
<span id="79"> 79</span>
<span id="80"> 80</span>
<span id="81"> 81</span>
<span id="82"> 82</span>
<span id="83"> 83</span>
<span id="84"> 84</span>
<span id="85"> 85</span>
<span id="86"> 86</span>
<span id="87"> 87</span>
<span id="88"> 88</span>
<span id="89"> 89</span>
<span id="90"> 90</span>
<span id="91"> 91</span>
<span id="92"> 92</span>
<span id="93"> 93</span>
<span id="94"> 94</span>
<span id="95"> 95</span>
<span id="96"> 96</span>
<span id="97"> 97</span>
<span id="98"> 98</span>
<span id="99"> 99</span>
<span id="100">100</span>
<span id="101">101</span>
<span id="102">102</span>
<span id="103">103</span>
<span id="104">104</span>
<span id="105">105</span>
<span id="106">106</span>
<span id="107">107</span>
<span id="108">108</span>
<span id="109">109</span>
<span id="110">110</span>
<span id="111">111</span>
<span id="112">112</span>
<span id="113">113</span>
<span id="114">114</span>
<span id="115">115</span>
<span id="116">116</span>
<span id="117">117</span>
<span id="118">118</span>
<span id="119">119</span>
<span id="120">120</span>
<span id="121">121</span>
<span id="122">122</span>
<span id="123">123</span>
<span id="124">124</span>
<span id="125">125</span>
<span id="126">126</span>
<span id="127">127</span>
<span id="128">128</span>
<span id="129">129</span>
<span id="130">130</span>
<span id="131">131</span>
<span id="132">132</span>
<span id="133">133</span>
<span id="134">134</span>
<span id="135">135</span>
<span id="136">136</span>
<span id="137">137</span>
<span id="138">138</span>
<span id="139">139</span>
<span id="140">140</span>
<span id="141">141</span>
<span id="142">142</span>
<span id="143">143</span>
<span id="144">144</span>
<span id="145">145</span>
<span id="146">146</span>
<span id="147">147</span>
<span id="148">148</span>
<span id="149">149</span>
<span id="150">150</span>
<span id="151">151</span>
<span id="152">152</span>
<span id="153">153</span>
<span id="154">154</span>
<span id="155">155</span>
<span id="156">156</span>
<span id="157">157</span>
<span id="158">158</span>
<span id="159">159</span>
<span id="160">160</span>
<span id="161">161</span>
<span id="162">162</span>
<span id="163">163</span>
<span id="164">164</span>
<span id="165">165</span>
<span id="166">166</span>
<span id="167">167</span>
<span id="168">168</span>
<span id="169">169</span>
<span id="170">170</span>
<span id="171">171</span>
<span id="172">172</span>
<span id="173">173</span>
<span id="174">174</span>
<span id="175">175</span>
<span id="176">176</span>
<span id="177">177</span>
<span id="178">178</span>
<span id="179">179</span>
<span id="180">180</span>
<span id="181">181</span>
<span id="182">182</span>
<span id="183">183</span>
<span id="184">184</span>
<span id="185">185</span>
<span id="186">186</span>
<span id="187">187</span>
<span id="188">188</span>
<span id="189">189</span>
<span id="190">190</span>
<span id="191">191</span>
<span id="192">192</span>
<span id="193">193</span>
<span id="194">194</span>
<span id="195">195</span>
<span id="196">196</span>
</pre><pre class='rust '>
<span class='doccomment'>//! Provides functionality to connect with radare2.</span>
<span class='doccomment'>//!</span>
<span class='doccomment'>//! Please check crate level documentation for more details and example.</span>
<span class='kw'>extern</span> <span class='kw'>crate</span> <span class='ident'>libc</span>;
<span class='kw'>use</span> <span class='self'>self</span>::<span class='ident'>libc</span>::{ <span class='ident'>c_void</span> };
<span class='kw'>use</span> <span class='ident'>rustc_serialize</span>::<span class='ident'>json</span>::<span class='ident'>Json</span>;
<span class='kw'>use</span> <span class='ident'>std</span>::<span class='ident'>process</span>::<span class='ident'>Command</span>;
<span class='kw'>use</span> <span class='ident'>std</span>::<span class='ident'>process</span>::<span class='ident'>Stdio</span>;
<span class='kw'>use</span> <span class='ident'>std</span>::<span class='ident'>process</span>;
<span class='kw'>use</span> <span class='ident'>std</span>::<span class='ident'>env</span>;
<span class='kw'>use</span> <span class='ident'>std</span>::<span class='ident'>str</span>;
<span class='kw'>use</span> <span class='ident'>std</span>::<span class='ident'>path</span>::<span class='ident'>Path</span>;
<span class='kw'>use</span> <span class='ident'>std</span>::<span class='ident'>io</span>::<span class='ident'>prelude</span>::<span class='op'>*</span>;
<span class='doccomment'>/// File descriptors to the parent r2 process.</span>
<span class='kw'>pub</span> <span class='kw'>struct</span> <span class='ident'>R2PipeLang</span> {
<span class='ident'>fd_in</span>: <span class='ident'>i32</span>,
<span class='ident'>fd_out</span>: <span class='ident'>i32</span>
}
<span class='doccomment'>/// Stores descriptors to the spawned r2 process.</span>
<span class='kw'>pub</span> <span class='kw'>struct</span> <span class='ident'>R2PipeSpawn</span> {
<span class='ident'>read</span>: <span class='ident'>process</span>::<span class='ident'>ChildStdout</span>,
<span class='ident'>write</span>: <span class='ident'>process</span>::<span class='ident'>ChildStdin</span>,
}
<span class='doccomment'>/// Provides abstraction between the two invocation methods.</span>
<span class='kw'>pub</span> <span class='kw'>enum</span> <span class='ident'>R2Pipe</span> {
<span class='ident'>Pipe</span>(<span class='ident'>R2PipeSpawn</span>),
<span class='ident'>Lang</span>(<span class='ident'>R2PipeLang</span>),
}
<span class='kw'>fn</span> <span class='ident'>atoi</span>(<span class='ident'>k</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='ident'>i32</span> {
<span class='kw'>match</span> <span class='ident'>k</span>.<span class='ident'>parse</span>::<span class='op'>&lt;</span><span class='ident'>i32</span><span class='op'>&gt;</span>() {
<span class='prelude-val'>Ok</span>(<span class='ident'>val</span>) <span class='op'>=&gt;</span> <span class='ident'>val</span>,
<span class='prelude-val'>Err</span>(_) <span class='op'>=&gt;</span> <span class='number'>0</span>
}
}
<span class='kw'>fn</span> <span class='ident'>getenv</span>(<span class='ident'>k</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='ident'>i32</span> {
<span class='kw'>match</span> <span class='ident'>env</span>::<span class='ident'>var</span>(<span class='ident'>k</span>) {
<span class='prelude-val'>Ok</span>(<span class='ident'>val</span>) <span class='op'>=&gt;</span> <span class='ident'>atoi</span>(<span class='kw-2'>&amp;</span><span class='ident'>val</span>),
<span class='prelude-val'>Err</span>(_) <span class='op'>=&gt;</span> <span class='number'>0</span>,
}
}
<span class='attribute'>#[<span class='ident'>macro_export</span>]</span>
<span class='macro'>macro_rules</span><span class='macro'>!</span> <span class='ident'>open_pipe</span> {
(<span class='macro-nonterminal'>$</span><span class='macro-nonterminal'>x</span>:<span class='ident'>expr</span>) <span class='op'>=&gt;</span> (<span class='ident'>R2Pipe</span>::<span class='ident'>spawn</span>(<span class='macro-nonterminal'>$</span><span class='macro-nonterminal'>x</span>));
() <span class='op'>=&gt;</span> (<span class='ident'>R2Pipe</span>::<span class='ident'>open</span>());
}
<span class='kw'>impl</span> <span class='ident'>R2Pipe</span> {
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>open</span>() <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span><span class='op'>&lt;</span><span class='ident'>R2Pipe</span>, <span class='kw-2'>&amp;</span><span class='lifetime'>&#39;static</span> <span class='ident'>str</span><span class='op'>&gt;</span> {
<span class='kw'>let</span> (<span class='ident'>fin</span>, <span class='ident'>fout</span>) <span class='op'>=</span> <span class='kw'>match</span> <span class='ident'>R2Pipe</span>::<span class='ident'>in_session</span>() {
<span class='prelude-val'>Some</span>(<span class='ident'>x</span>) <span class='op'>=&gt;</span> <span class='ident'>x</span>,
<span class='prelude-val'>None</span> <span class='op'>=&gt;</span> <span class='kw'>return</span> <span class='prelude-val'>Err</span>(<span class='string'>&quot;Pipe not open. Please run from r2&quot;</span>),
};
<span class='kw'>let</span> <span class='ident'>_res</span> <span class='op'>=</span> <span class='ident'>R2PipeLang</span> { <span class='ident'>fd_in</span>: <span class='ident'>fin</span>, <span class='ident'>fd_out</span>: <span class='ident'>fout</span> };
<span class='prelude-val'>Ok</span>(<span class='ident'>R2Pipe</span>::<span class='ident'>Lang</span>(<span class='ident'>_res</span>))
}
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>cmd</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='ident'>String</span> {
<span class='kw'>match</span> <span class='op'>*</span><span class='self'>self</span> {
<span class='ident'>R2Pipe</span>::<span class='ident'>Pipe</span>(<span class='kw-2'>ref</span> <span class='kw-2'>mut</span> <span class='ident'>x</span>) <span class='op'>=&gt;</span> <span class='ident'>x</span>.<span class='ident'>cmd</span>(<span class='ident'>cmd</span>),
<span class='ident'>R2Pipe</span>::<span class='ident'>Lang</span>(<span class='kw-2'>ref</span> <span class='kw-2'>mut</span> <span class='ident'>x</span>) <span class='op'>=&gt;</span> <span class='ident'>x</span>.<span class='ident'>cmd</span>(<span class='ident'>cmd</span>),
}
}
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>cmdj</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='ident'>Json</span> {
<span class='kw'>match</span> <span class='op'>*</span><span class='self'>self</span> {
<span class='ident'>R2Pipe</span>::<span class='ident'>Pipe</span>(<span class='kw-2'>ref</span> <span class='kw-2'>mut</span> <span class='ident'>x</span>) <span class='op'>=&gt;</span> <span class='ident'>x</span>.<span class='ident'>cmdj</span>(<span class='ident'>cmd</span>),
<span class='ident'>R2Pipe</span>::<span class='ident'>Lang</span>(<span class='kw-2'>ref</span> <span class='kw-2'>mut</span> <span class='ident'>x</span>) <span class='op'>=&gt;</span> <span class='ident'>x</span>.<span class='ident'>cmdj</span>(<span class='ident'>cmd</span>),
}
}
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>close</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>) {
<span class='kw'>match</span> <span class='op'>*</span><span class='self'>self</span> {
<span class='ident'>R2Pipe</span>::<span class='ident'>Pipe</span>(<span class='kw-2'>ref</span> <span class='kw-2'>mut</span> <span class='ident'>x</span>) <span class='op'>=&gt;</span> <span class='ident'>x</span>.<span class='ident'>close</span>(),
<span class='ident'>R2Pipe</span>::<span class='ident'>Lang</span>(<span class='kw-2'>ref</span> <span class='kw-2'>mut</span> <span class='ident'>x</span>) <span class='op'>=&gt;</span> <span class='ident'>x</span>.<span class='ident'>close</span>(),
}
}
<span class='comment'>// XXX: must support windows</span>
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>in_session</span>() <span class='op'>-&gt;</span> <span class='prelude-ty'>Option</span><span class='op'>&lt;</span>(<span class='ident'>i32</span>, <span class='ident'>i32</span>)<span class='op'>&gt;</span> {
<span class='kw'>let</span> <span class='ident'>fin</span> <span class='op'>=</span> <span class='ident'>getenv</span>(<span class='string'>&quot;R2PIPE_IN&quot;</span>);
<span class='kw'>let</span> <span class='ident'>fout</span> <span class='op'>=</span> <span class='ident'>getenv</span>(<span class='string'>&quot;R2PIPE_OUT&quot;</span>);
<span class='kw'>if</span> <span class='ident'>fin</span> <span class='op'>==</span> <span class='number'>0</span> <span class='op'>||</span> <span class='ident'>fout</span> <span class='op'>==</span> <span class='number'>0</span> {
<span class='kw'>return</span> <span class='prelude-val'>None</span>;
}
<span class='kw'>return</span> <span class='prelude-val'>Some</span>((<span class='ident'>fin</span>, <span class='ident'>fout</span>));
}
<span class='doccomment'>/// Creates a new R2PipeSpawn.</span>
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>spawn</span>(<span class='ident'>_name</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span><span class='op'>&lt;</span><span class='ident'>R2Pipe</span>, <span class='kw-2'>&amp;</span><span class='lifetime'>&#39;static</span> <span class='ident'>str</span><span class='op'>&gt;</span> {
<span class='kw'>if</span> <span class='kw'>let</span> <span class='prelude-val'>Some</span>(_) <span class='op'>=</span> <span class='ident'>R2Pipe</span>::<span class='ident'>in_session</span>() {
<span class='kw'>return</span> <span class='ident'>R2Pipe</span>::<span class='ident'>open</span>();
}
<span class='kw'>let</span> <span class='ident'>name</span> <span class='op'>=</span> <span class='ident'>_name</span>.<span class='ident'>to_string</span>();
<span class='kw'>let</span> <span class='ident'>path</span> <span class='op'>=</span> <span class='ident'>Path</span>::<span class='ident'>new</span>(<span class='kw-2'>&amp;</span><span class='op'>*</span><span class='ident'>name</span>);
<span class='kw'>let</span> <span class='ident'>child</span> <span class='op'>=</span> <span class='kw'>match</span> <span class='ident'>Command</span>::<span class='ident'>new</span>(<span class='string'>&quot;r2&quot;</span>)
.<span class='ident'>arg</span>(<span class='string'>&quot;-q0&quot;</span>)
.<span class='ident'>arg</span>(<span class='ident'>path</span>)
.<span class='ident'>stdin</span>(<span class='ident'>Stdio</span>::<span class='ident'>piped</span>())
.<span class='ident'>stdout</span>(<span class='ident'>Stdio</span>::<span class='ident'>piped</span>())
.<span class='ident'>spawn</span>() {
<span class='prelude-val'>Ok</span>(<span class='ident'>c</span>) <span class='op'>=&gt;</span> <span class='ident'>c</span>,
<span class='prelude-val'>Err</span>(_) <span class='op'>=&gt;</span> <span class='kw'>return</span> <span class='prelude-val'>Err</span>(<span class='string'>&quot;Unable to spawn r2.&quot;</span>),
};
<span class='kw'>let</span> <span class='ident'>sin</span>: <span class='ident'>process</span>::<span class='ident'>ChildStdin</span>;
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>sout</span>: <span class='ident'>process</span>::<span class='ident'>ChildStdout</span>;
{
<span class='ident'>sin</span> <span class='op'>=</span> <span class='ident'>child</span>.<span class='ident'>stdin</span>.<span class='ident'>unwrap</span>();
<span class='ident'>sout</span> <span class='op'>=</span> <span class='ident'>child</span>.<span class='ident'>stdout</span>.<span class='ident'>unwrap</span>();
<span class='comment'>// flush out the initial null byte.</span>
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>w</span> <span class='op'>=</span> [<span class='number'>0</span>;<span class='number'>1</span>];
<span class='ident'>sout</span>.<span class='ident'>read</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='ident'>w</span>).<span class='ident'>unwrap</span>();
}
<span class='kw'>let</span> <span class='ident'>_res</span> <span class='op'>=</span> <span class='ident'>R2PipeSpawn</span> {
<span class='ident'>read</span>: <span class='ident'>sout</span>,
<span class='ident'>write</span>: <span class='ident'>sin</span>
};
<span class='prelude-val'>Ok</span>(<span class='ident'>R2Pipe</span>::<span class='ident'>Pipe</span>(<span class='ident'>_res</span>))
}
}
<span class='kw'>impl</span> <span class='ident'>R2PipeSpawn</span> {
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>cmd</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='ident'>String</span> {
<span class='kw'>let</span> <span class='ident'>cmd_</span> <span class='op'>=</span> <span class='ident'>cmd</span>.<span class='ident'>to_owned</span>() <span class='op'>+</span> <span class='string'>&quot;\n&quot;</span>;
<span class='kw'>if</span> <span class='kw'>let</span> <span class='prelude-val'>Err</span>(<span class='ident'>e</span>) <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>write</span>.<span class='ident'>write</span>(<span class='ident'>cmd_</span>.<span class='ident'>as_bytes</span>()) {
<span class='macro'>panic</span><span class='macro'>!</span>(<span class='string'>&quot;{}&quot;</span>, <span class='ident'>e</span>);
}
<span class='comment'>// Read in block size of 2048.</span>
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>s</span> <span class='op'>=</span> [<span class='number'>0</span>; <span class='number'>2048</span>];
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>res</span>: <span class='ident'>String</span> <span class='op'>=</span> <span class='ident'>String</span>::<span class='ident'>new</span>();
<span class='kw'>loop</span> {
<span class='kw'>let</span> <span class='ident'>count</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>read</span>.<span class='ident'>read</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='ident'>s</span>).<span class='ident'>unwrap</span>();
<span class='kw'>for</span> <span class='ident'>c</span> <span class='kw'>in</span> <span class='ident'>s</span>[..<span class='ident'>count</span>].<span class='ident'>iter</span>() {
<span class='ident'>res</span> <span class='op'>=</span> <span class='ident'>res</span> <span class='op'>+</span> <span class='kw-2'>&amp;</span><span class='op'>*</span><span class='macro'>format</span><span class='macro'>!</span>(<span class='string'>&quot;{}&quot;</span>, <span class='op'>*</span><span class='ident'>c</span> <span class='kw'>as</span> <span class='ident'>char</span>);
}
<span class='kw'>if</span> <span class='ident'>count</span> <span class='op'>&lt;</span> <span class='number'>2048</span> {
<span class='kw'>break</span>;
}
}
<span class='kw'>let</span> <span class='ident'>len</span> <span class='op'>=</span> <span class='ident'>res</span>.<span class='ident'>len</span>() <span class='op'>-</span> <span class='number'>1</span>;
<span class='ident'>res</span>.<span class='ident'>truncate</span>(<span class='ident'>len</span>);
<span class='ident'>res</span>
}
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>cmdj</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='ident'>Json</span> {
<span class='kw'>let</span> <span class='ident'>res</span> <span class='op'>=</span> <span class='kw-2'>&amp;</span><span class='self'>self</span>.<span class='ident'>cmd</span>(<span class='ident'>cmd</span>).<span class='ident'>replace</span>(<span class='string'>&quot;\n&quot;</span>,<span class='string'>&quot;&quot;</span>);
<span class='ident'>Json</span>::<span class='ident'>from_str</span>(<span class='ident'>res</span>).<span class='ident'>unwrap</span>()
}
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>close</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>) {
<span class='self'>self</span>.<span class='ident'>cmd</span>(<span class='string'>&quot;q!&quot;</span>);
}
}
<span class='kw'>impl</span> <span class='ident'>R2PipeLang</span> {
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>cmd</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='ident'>String</span> {
<span class='kw'>let</span> <span class='ident'>buf</span>: [<span class='ident'>u8</span>; <span class='number'>1024</span>] <span class='op'>=</span> [<span class='number'>0</span>;<span class='number'>1024</span>];
<span class='kw'>unsafe</span> {
<span class='ident'>libc</span>::<span class='ident'>write</span> (<span class='self'>self</span>.<span class='ident'>fd_out</span>, <span class='ident'>cmd</span>.<span class='ident'>as_ptr</span>() <span class='kw'>as</span> <span class='op'>*</span><span class='kw'>const</span> <span class='ident'>c_void</span>, <span class='ident'>cmd</span>.<span class='ident'>len</span>() <span class='kw'>as</span> <span class='ident'>u64</span>);
<span class='ident'>libc</span>::<span class='ident'>write</span> (<span class='self'>self</span>.<span class='ident'>fd_out</span>, <span class='string'>&quot;\x00&quot;</span>.<span class='ident'>as_ptr</span>() <span class='kw'>as</span> <span class='op'>*</span><span class='kw'>const</span> <span class='ident'>c_void</span>, <span class='number'>1</span>);
<span class='kw'>let</span> <span class='ident'>len</span> <span class='op'>=</span> <span class='ident'>libc</span>::<span class='ident'>read</span> (<span class='self'>self</span>.<span class='ident'>fd_in</span>, <span class='ident'>buf</span>.<span class='ident'>as_ptr</span>() <span class='kw'>as</span> <span class='op'>*</span><span class='kw-2'>mut</span> <span class='ident'>c_void</span>, <span class='ident'>buf</span>.<span class='ident'>len</span>() <span class='kw'>as</span> <span class='ident'>u64</span>) <span class='kw'>as</span> <span class='ident'>usize</span>;
<span class='kw'>let</span> <span class='ident'>buf2</span> : <span class='ident'>Box</span><span class='op'>&lt;</span><span class='kw-2'>&amp;</span>[<span class='ident'>u8</span>]<span class='op'>&gt;</span> <span class='op'>=</span> <span class='ident'>Box</span>::<span class='ident'>new</span>(<span class='kw-2'>&amp;</span><span class='ident'>buf</span>[<span class='number'>0</span>..<span class='ident'>len</span><span class='op'>-</span><span class='number'>1</span>]);
<span class='kw'>let</span> <span class='ident'>s</span> <span class='op'>=</span> <span class='ident'>str</span>::<span class='ident'>from_utf8</span>(<span class='kw-2'>&amp;</span><span class='ident'>buf2</span>).<span class='ident'>unwrap</span>();
<span class='ident'>s</span>.<span class='ident'>to_string</span>()
}
}
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>cmdj</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='ident'>Json</span> {
<span class='kw'>let</span> <span class='ident'>res</span> <span class='op'>=</span> <span class='kw-2'>&amp;</span><span class='self'>self</span>.<span class='ident'>cmd</span>(<span class='ident'>cmd</span>).<span class='ident'>replace</span>(<span class='string'>&quot;\n&quot;</span>,<span class='string'>&quot;&quot;</span>);
<span class='ident'>Json</span>::<span class='ident'>from_str</span>(<span class='ident'>res</span>).<span class='ident'>unwrap</span>()
}
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>close</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>) {
<span class='kw'>unsafe</span> {
<span class='ident'>libc</span>::<span class='ident'>close</span> (<span class='self'>self</span>.<span class='ident'>fd_in</span>);
<span class='ident'>libc</span>::<span class='ident'>close</span> (<span class='self'>self</span>.<span class='ident'>fd_out</span>);
}
}
}
</pre>
</section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../../jquery.js"></script>
<script src="../../main.js"></script>
<script async src="../../search-index.js"></script>
</body>
</html>