mirror of
https://github.com/radareorg/r2pipe.rs.git
synced 2026-11-08 17:42:45 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d657dcffe | ||
|
|
87af6e0391 | ||
|
|
6596b93820 |
No files matched your search
@@ -1,60 +0,0 @@
|
||||
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
|
||||
@@ -1,3 +0,0 @@
|
||||
target
|
||||
Cargo.lock
|
||||
*.swp
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
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
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
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
@@ -1,33 +0,0 @@
|
||||
[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
@@ -1,202 +0,0 @@
|
||||
|
||||
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
@@ -1,22 +0,0 @@
|
||||
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.
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
all:
|
||||
cargo build
|
||||
|
||||
clean:
|
||||
cargo clean
|
||||
|
||||
doc:
|
||||
cargo doc --no-deps
|
||||
|
||||
run:
|
||||
r2 -qc '#!pipe target/debug/r2pipe' /bin/ls
|
||||
target/debug/r2pipe
|
||||
@@ -1,38 +0,0 @@
|
||||
[](https://github.com/radareorg/r2pipe.rs/actions/workflows/main.yml)
|
||||
[](https://docs.rs/r2pipe)
|
||||
[](https://crates.io/crates/r2pipe)
|
||||
[](
|
||||
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.
@@ -1,16 +0,0 @@
|
||||
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
|
||||
@@ -1,19 +0,0 @@
|
||||
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
|
||||
@@ -1,98 +0,0 @@
|
||||
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();
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
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(())
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
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(())
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
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(())
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
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(())
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
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(())
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
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(())
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<meta http-equiv=refresh content=0;url=r2pipe/index.html>
|
||||
@@ -0,0 +1,4 @@
|
||||
/*! 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
|
||||
@@ -0,0 +1,655 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,888 @@
|
||||
// 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 +
|
||||
' </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(' Expand 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);
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
||||
}());
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
/*! 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
@@ -0,0 +1,27 @@
|
||||
// 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();
|
||||
});
|
||||
}
|
||||
}());
|
||||
@@ -0,0 +1,148 @@
|
||||
<!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> <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'>"/bin/ls"</span>).<span class='ident'>unwrap</span>();
|
||||
<span class='macro'>println</span><span class='macro'>!</span>(<span class='string'>"{}"</span>, <span class='ident'>r2p</span>.<span class='ident'>cmd</span>(<span class='string'>"?e Hello World"</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'>"ij"</span>);
|
||||
<span class='macro'>println</span><span class='macro'>!</span>(<span class='string'>"{}"</span>, <span class='ident'>json</span>.<span class='ident'>pretty</span>());
|
||||
<span class='macro'>println</span><span class='macro'>!</span>(<span class='string'>"ARCH {}"</span>, <span class='ident'>json</span>.<span class='ident'>find_path</span>(<span class='kw-2'>&</span>[<span class='string'>"bin"</span>,<span class='string'>"arch"</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>⇤</dt>
|
||||
<dd>Move up in search results</dd>
|
||||
<dt>⇥</dt>
|
||||
<dd>Move down in search results</dd>
|
||||
<dt>⏎</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>
|
||||
@@ -0,0 +1,101 @@
|
||||
<!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> <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'>=></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'>=></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>⇤</dt>
|
||||
<dd>Move up in search results</dd>
|
||||
<dt>⇥</dt>
|
||||
<dd>Move down in search results</dd>
|
||||
<dt>⏎</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>
|
||||
@@ -0,0 +1,107 @@
|
||||
<!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> <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>() -> <a class='enum' href='http://doc.rust-lang.org/nightly/core/result/enum.Result.html' title='core::result::Result'>Result</a><<a class='enum' href='../../r2pipe/r2pipe/enum.R2Pipe.html' title='r2pipe::r2pipe::R2Pipe'>R2Pipe</a>, &'static <a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>></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>(&mut self, cmd: &<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -> <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>(&mut self, cmd: &<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -> <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>(&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>() -> <a class='enum' href='http://doc.rust-lang.org/nightly/core/option/enum.Option.html' title='core::option::Option'>Option</a><<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>></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: &<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -> <a class='enum' href='http://doc.rust-lang.org/nightly/core/result/enum.Result.html' title='core::result::Result'>Result</a><<a class='enum' href='../../r2pipe/r2pipe/enum.R2Pipe.html' title='r2pipe::r2pipe::R2Pipe'>R2Pipe</a>, &'static <a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>></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>⇤</dt>
|
||||
<dd>Move up in search results</dd>
|
||||
<dt>⇥</dt>
|
||||
<dd>Move down in search results</dd>
|
||||
<dt>⏎</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>
|
||||
@@ -0,0 +1,121 @@
|
||||
<!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> <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>⇤</dt>
|
||||
<dd>Move up in search results</dd>
|
||||
<dt>⇥</dt>
|
||||
<dd>Move down in search results</dd>
|
||||
<dt>⏎</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>
|
||||
@@ -0,0 +1 @@
|
||||
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."]]});
|
||||
@@ -0,0 +1,101 @@
|
||||
<!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> <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>(&mut self, cmd: &<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -> <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>(&mut self, cmd: &<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -> <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>(&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>⇤</dt>
|
||||
<dd>Move up in search results</dd>
|
||||
<dt>⇥</dt>
|
||||
<dd>Move down in search results</dd>
|
||||
<dt>⏎</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>
|
||||
@@ -0,0 +1,101 @@
|
||||
<!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> <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>(&mut self, cmd: &<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -> <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>(&mut self, cmd: &<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -> <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>(&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>⇤</dt>
|
||||
<dd>Move up in search results</dd>
|
||||
<dt>⇥</dt>
|
||||
<dd>Move down in search results</dd>
|
||||
<dt>⏎</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>
|
||||
@@ -0,0 +1 @@
|
||||
initSidebarItems({"macro":[["open_pipe!",""]],"mod":[["r2pipe","Provides functionality to connect with radare2."]]});
|
||||
@@ -0,0 +1,102 @@
|
||||
<!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'> </span><span class='summary Unstable' style='width: 0.0000%; display: inline-block'> </span><span class='summary Deprecated' style='width: 0.0000%; display: inline-block'> </span><span class='summary Unmarked' style='width: 100.0000%; display: inline-block'> </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'> </span><span class='summary Unstable' style='width: 0.0000%; display: inline-block'> </span><span class='summary Deprecated' style='width: 0.0000%; display: inline-block'> </span><span class='summary Unmarked' style='width: 100.0000%; display: inline-block'> </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>⇤</dt>
|
||||
<dd>Move up in search results</dd>
|
||||
<dt>⇥</dt>
|
||||
<dd>Move down in search results</dd>
|
||||
<dt>⏎</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>
|
||||
@@ -0,0 +1 @@
|
||||
{"name":"r2pipe","counts":{"deprecated":0,"unstable":0,"stable":0,"unmarked":23},"submodules":[{"name":"r2pipe","counts":{"deprecated":0,"unstable":0,"stable":0,"unmarked":21},"submodules":[]}]}
|
||||
@@ -0,0 +1,3 @@
|
||||
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);
|
||||
@@ -1,81 +0,0 @@
|
||||
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))
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
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
@@ -1,70 +0,0 @@
|
||||
//! `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;
|
||||
@@ -1,84 +0,0 @@
|
||||
// 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
@@ -1,443 +0,0 @@
|
||||
//! 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());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
<!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!("/bin/ls").unwrap();</span>
|
||||
<span class='doccomment'>//! println!("{}", r2p.cmd("?e Hello World"));</span>
|
||||
<span class='doccomment'>//! let json = r2p.cmdj("ij");</span>
|
||||
<span class='doccomment'>//! println!("{}", json.pretty());</span>
|
||||
<span class='doccomment'>//! println!("ARCH {}", json.find_path(&["bin","arch"]).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'>"https://radare.github.io/r2pipe.rs/"</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>⇤</dt>
|
||||
<dd>Move up in search results</dd>
|
||||
<dt>⇥</dt>
|
||||
<dd>Move down in search results</dd>
|
||||
<dt>⏎</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>
|
||||
@@ -0,0 +1,485 @@
|
||||
<!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'>&</span><span class='ident'>str</span>) <span class='op'>-></span> <span class='ident'>i32</span> {
|
||||
<span class='kw'>match</span> <span class='ident'>k</span>.<span class='ident'>parse</span>::<span class='op'><</span><span class='ident'>i32</span><span class='op'>></span>() {
|
||||
<span class='prelude-val'>Ok</span>(<span class='ident'>val</span>) <span class='op'>=></span> <span class='ident'>val</span>,
|
||||
<span class='prelude-val'>Err</span>(_) <span class='op'>=></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'>&</span><span class='ident'>str</span>) <span class='op'>-></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'>=></span> <span class='ident'>atoi</span>(<span class='kw-2'>&</span><span class='ident'>val</span>),
|
||||
<span class='prelude-val'>Err</span>(_) <span class='op'>=></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'>=></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'>=></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'>-></span> <span class='prelude-ty'>Result</span><span class='op'><</span><span class='ident'>R2Pipe</span>, <span class='kw-2'>&</span><span class='lifetime'>'static</span> <span class='ident'>str</span><span class='op'>></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'>=></span> <span class='ident'>x</span>,
|
||||
<span class='prelude-val'>None</span> <span class='op'>=></span> <span class='kw'>return</span> <span class='prelude-val'>Err</span>(<span class='string'>"Pipe not open. Please run from r2"</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'>&</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&</span><span class='ident'>str</span>) <span class='op'>-></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'>=></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'>=></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'>&</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&</span><span class='ident'>str</span>) <span class='op'>-></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'>=></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'>=></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'>&</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'>=></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'>=></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'>-></span> <span class='prelude-ty'>Option</span><span class='op'><</span>(<span class='ident'>i32</span>, <span class='ident'>i32</span>)<span class='op'>></span> {
|
||||
<span class='kw'>let</span> <span class='ident'>fin</span> <span class='op'>=</span> <span class='ident'>getenv</span>(<span class='string'>"R2PIPE_IN"</span>);
|
||||
<span class='kw'>let</span> <span class='ident'>fout</span> <span class='op'>=</span> <span class='ident'>getenv</span>(<span class='string'>"R2PIPE_OUT"</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'>&</span><span class='ident'>str</span>) <span class='op'>-></span> <span class='prelude-ty'>Result</span><span class='op'><</span><span class='ident'>R2Pipe</span>, <span class='kw-2'>&</span><span class='lifetime'>'static</span> <span class='ident'>str</span><span class='op'>></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'>&</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'>"r2"</span>)
|
||||
.<span class='ident'>arg</span>(<span class='string'>"-q0"</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'>=></span> <span class='ident'>c</span>,
|
||||
<span class='prelude-val'>Err</span>(_) <span class='op'>=></span> <span class='kw'>return</span> <span class='prelude-val'>Err</span>(<span class='string'>"Unable to spawn r2."</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'>&</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'>&</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&</span><span class='ident'>str</span>) <span class='op'>-></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'>"\n"</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'>"{}"</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'>&</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'>&</span><span class='op'>*</span><span class='macro'>format</span><span class='macro'>!</span>(<span class='string'>"{}"</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'><</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'>&</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&</span><span class='ident'>str</span>) <span class='op'>-></span> <span class='ident'>Json</span> {
|
||||
<span class='kw'>let</span> <span class='ident'>res</span> <span class='op'>=</span> <span class='kw-2'>&</span><span class='self'>self</span>.<span class='ident'>cmd</span>(<span class='ident'>cmd</span>).<span class='ident'>replace</span>(<span class='string'>"\n"</span>,<span class='string'>""</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'>&</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'>"q!"</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'>&</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&</span><span class='ident'>str</span>) <span class='op'>-></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'>"\x00"</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'><</span><span class='kw-2'>&</span>[<span class='ident'>u8</span>]<span class='op'>></span> <span class='op'>=</span> <span class='ident'>Box</span>::<span class='ident'>new</span>(<span class='kw-2'>&</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'>&</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'>&</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&</span><span class='ident'>str</span>) <span class='op'>-></span> <span class='ident'>Json</span> {
|
||||
<span class='kw'>let</span> <span class='ident'>res</span> <span class='op'>=</span> <span class='kw-2'>&</span><span class='self'>self</span>.<span class='ident'>cmd</span>(<span class='ident'>cmd</span>).<span class='ident'>replace</span>(<span class='string'>"\n"</span>,<span class='string'>""</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'>&</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>⇤</dt>
|
||||
<dd>Move up in search results</dd>
|
||||
<dt>⇥</dt>
|
||||
<dd>Move down in search results</dd>
|
||||
<dt>⏎</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>
|
||||
Reference in new issue
Block a user