3 Commits
Author SHA1 Message Date
Sushant 8d657dcffe Update documentation 2015-06-12 02:12:38 +05:50
Sushant 87af6e0391 Update documentation 2015-06-12 02:10:16 +05:50
Sushant 6596b93820 Update documentation 2015-06-12 02:05:41 +05:50
51 changed files with 3031 additions and 1447 deletions

No files matched your search

-60
View File
@@ -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
-3
View File
@@ -1,3 +0,0 @@
target
Cargo.lock
*.swp
View File
Whitespace-only changes.
View File
Whitespace-only changes.
-30
View File
@@ -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
-7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
-12
View File
@@ -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
-38
View File
@@ -1,38 +0,0 @@
[![ci](https://github.com/radareorg/r2pipe.rs/actions/workflows/main.yml/badge.svg)](https://github.com/radareorg/r2pipe.rs/actions/workflows/main.yml)
[![Documentation](https://docs.rs/r2pipe/badge.svg)](https://docs.rs/r2pipe)
[![Cargo](https://img.shields.io/crates/v/r2pipe.svg)](https://crates.io/crates/r2pipe)
[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](
https://github.com/radareorg/r2pipe.rs)
r2pipe.rs
=========
The Rust Crate to interact with radare2.
Please check [Documentation](https://docs.rs/r2pipe/latest/r2pipe/) to get
started.
**NOTICE**
Structures and API functions have been moved to [radare2-r2pipe-api](https://github.com/radare/radare2-r2pipe-api)
repository. Please make sure you update your dependencies and imports.
TODO
----
* Support futures API
* Add custom r2 start flags for spawn method
* Better error handling
## License
Licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-16
View File
@@ -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
-19
View File
@@ -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
-98
View File
@@ -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();
}
-21
View File
@@ -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(())
}
-38
View File
@@ -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(())
}
-20
View File
@@ -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(())
}
-19
View File
@@ -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(())
}
-42
View File
@@ -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(())
}
-42
View File
@@ -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(())
}
+1
View File
@@ -0,0 +1 @@
<meta http-equiv=refresh content=0;url=r2pipe/index.html>
Vendored
+4
View File
@@ -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
+655
View File
@@ -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;
}
}
+888
View File
@@ -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 +
'&nbsp;</span></a></td></tr>';
});
} else {
output += 'No results :( <a href="https://duckduckgo.com/?q=' +
encodeURIComponent('rust ' + query.query) +
'">Try on DuckDuckGo?</a>';
}
output += "</p>";
$('#main.content').addClass('hidden');
$('#search.content').removeClass('hidden').html(output);
$('#search .desc').width($('#search').width() - 40 -
$('#search td:first-child').first().width());
initSearchNav();
}
function search(e) {
var query,
filterdata = [],
obj, i, len,
results = [],
maxResults = 200,
resultIndex;
var params = getQueryStringParams();
query = getQuery();
if (e) {
e.preventDefault();
}
if (!query.query || query.id === currentResults) {
return;
}
// Because searching is incremental by character, only the most
// recent search query is added to the browser history.
if (browserSupportsHistoryApi()) {
if (!history.state && !params.search) {
history.pushState(query, "", "?search=" +
encodeURIComponent(query.raw));
} else {
history.replaceState(query, "", "?search=" +
encodeURIComponent(query.raw));
}
}
resultIndex = execQuery(query, 20000, index);
len = resultIndex.length;
for (i = 0; i < len; ++i) {
if (resultIndex[i].id > -1) {
obj = searchIndex[resultIndex[i].id];
filterdata.push([obj.name, obj.ty, obj.path, obj.desc]);
results.push(obj);
}
if (results.length >= maxResults) {
break;
}
}
showResults(results);
}
function itemTypeFromName(typename) {
for (var i = 0; i < itemTypes.length; ++i) {
if (itemTypes[i] === typename) return i;
}
return -1;
}
function buildIndex(rawSearchIndex) {
searchIndex = [];
var searchWords = [];
for (var crate in rawSearchIndex) {
if (!rawSearchIndex.hasOwnProperty(crate)) { continue }
// an array of [(Number) item type,
// (String) name,
// (String) full path or empty string for previous path,
// (String) description,
// (Number | null) the parent path index to `paths`]
// (Object | null) the type of the function (if any)
var items = rawSearchIndex[crate].items;
// an array of [(Number) item type,
// (String) name]
var paths = rawSearchIndex[crate].paths;
// convert `paths` into an object form
var len = paths.length;
for (var i = 0; i < len; ++i) {
paths[i] = {ty: paths[i][0], name: paths[i][1]};
}
// convert `items` into an object form, and construct word indices.
//
// before any analysis is performed lets gather the search terms to
// search against apart from the rest of the data. This is a quick
// operation that is cached for the life of the page state so that
// all other search operations have access to this cached data for
// faster analysis operations
var len = items.length;
var lastPath = "";
for (var i = 0; i < len; ++i) {
var rawRow = items[i];
var row = {crate: crate, ty: rawRow[0], name: rawRow[1],
path: rawRow[2] || lastPath, desc: rawRow[3],
parent: paths[rawRow[4]], type: rawRow[5]};
searchIndex.push(row);
if (typeof row.name === "string") {
var word = row.name.toLowerCase();
searchWords.push(word);
} else {
searchWords.push("");
}
lastPath = row.path;
}
}
return searchWords;
}
function startSearch() {
var keyUpTimeout;
$('.do-search').on('click', search);
$('.search-input').on('keyup', function() {
clearTimeout(keyUpTimeout);
keyUpTimeout = setTimeout(search, 500);
});
// Push and pop states are used to add search results to the browser
// history.
if (browserSupportsHistoryApi()) {
$(window).on('popstate', function(e) {
var params = getQueryStringParams();
// When browsing back from search results the main page
// visibility must be reset.
if (!params.search) {
$('#main.content').removeClass('hidden');
$('#search.content').addClass('hidden');
}
// When browsing forward to search results the previous
// search will be repeated, so the currentResults are
// cleared to ensure the search is successful.
currentResults = null;
// Synchronize search bar with query string state and
// perform the search. This will empty the bar if there's
// nothing there, which lets you really go back to a
// previous state with nothing in the bar.
$('.search-input').val(params.search);
// Some browsers fire 'onpopstate' for every page load
// (Chrome), while others fire the event only when actually
// popping a state (Firefox), which is why search() is
// called both here and at the end of the startSearch()
// function.
search();
});
}
search();
}
function plainSummaryLine(markdown) {
var str = markdown.replace(/\n/g, ' ')
str = str.replace(/'/g, "\'")
str = str.replace(/^#+? (.+?)/, "$1")
str = str.replace(/\[(.*?)\]\(.*?\)/g, "$1")
str = str.replace(/\[(.*?)\]\[.*?\]/g, "$1")
return str;
}
index = buildIndex(rawSearchIndex);
startSearch();
// Draw a convenient sidebar of known crates if we have a listing
if (rootPath == '../') {
var sidebar = $('.sidebar');
var div = $('<div>').attr('class', 'block crate');
div.append($('<h2>').text('Crates'));
var crates = [];
for (var crate in rawSearchIndex) {
if (!rawSearchIndex.hasOwnProperty(crate)) { continue }
crates.push(crate);
}
crates.sort();
for (var i = 0; i < crates.length; ++i) {
var klass = 'crate';
if (crates[i] == window.currentCrate) {
klass += ' current';
}
if (rawSearchIndex[crates[i]].items[0]) {
var desc = rawSearchIndex[crates[i]].items[0][3];
div.append($('<a>', {'href': '../' + crates[i] + '/index.html',
'title': plainSummaryLine(desc),
'class': klass}).text(crates[i]));
}
}
sidebar.append(div);
}
}
window.initSearch = initSearch;
// delayed sidebar rendering.
function initSidebarItems(items) {
var sidebar = $('.sidebar');
var current = window.sidebarCurrent;
function block(shortty, longty) {
var filtered = items[shortty];
if (!filtered) return;
var div = $('<div>').attr('class', 'block ' + shortty);
div.append($('<h2>').text(longty));
for (var i = 0; i < filtered.length; ++i) {
var item = filtered[i];
var name = item[0];
var desc = item[1]; // can be null
var klass = shortty;
if (name === current.name && shortty == current.ty) {
klass += ' current';
}
var path;
if (shortty === 'mod') {
path = name + '/index.html';
} else {
path = shortty + '.' + name + '.html';
}
div.append($('<a>', {'href': current.relpath + path,
'title': desc,
'class': klass}).text(name));
}
sidebar.append(div);
}
block("mod", "Modules");
block("struct", "Structs");
block("enum", "Enums");
block("trait", "Traits");
block("fn", "Functions");
block("macro", "Macros");
}
window.initSidebarItems = initSidebarItems;
window.register_implementors = function(imp) {
var list = $('#implementors-list');
var libs = Object.getOwnPropertyNames(imp);
for (var i = 0; i < libs.length; ++i) {
if (libs[i] == currentCrate) continue;
var structs = imp[libs[i]];
for (var j = 0; j < structs.length; ++j) {
var code = $('<code>').append(structs[j]);
$.each(code.find('a'), function(idx, a) {
var href = $(a).attr('href');
if (href && href.indexOf('http') !== 0) {
$(a).attr('href', rootPath + href);
}
});
var li = $('<li>').append(code);
list.append(li);
}
}
};
if (window.pending_implementors) {
window.register_implementors(window.pending_implementors);
}
// See documentation in html/render.rs for what this is doing.
var query = getQueryStringParams();
if (query['gotosrc']) {
window.location = $('#src-' + query['gotosrc']).attr('href');
}
$("#expand-all").on("click", function() {
$(".docblock").show();
$(".toggle-label").hide();
$(".toggle-wrapper").removeClass("collapsed");
$(".collapse-toggle").children(".inner").html("-");
});
$("#collapse-all").on("click", function() {
$(".docblock").hide();
$(".toggle-label").show();
$(".toggle-wrapper").addClass("collapsed");
$(".collapse-toggle").children(".inner").html("+");
});
$(document).on("click", ".collapse-toggle", function() {
var toggle = $(this);
var relatedDoc = toggle.parent().next();
if (relatedDoc.is(".docblock")) {
if (relatedDoc.is(":visible")) {
relatedDoc.slideUp({duration:'fast', easing:'linear'});
toggle.parent(".toggle-wrapper").addClass("collapsed");
toggle.children(".inner").html("+");
toggle.children(".toggle-label").fadeIn();
} else {
relatedDoc.slideDown({duration:'fast', easing:'linear'});
toggle.parent(".toggle-wrapper").removeClass("collapsed");
toggle.children(".inner").html("-");
toggle.children(".toggle-label").hide();
}
}
});
$(function() {
var toggle = $("<a/>", {'href': 'javascript:void(0)', 'class': 'collapse-toggle'})
.html("[<span class='inner'>-</span>]");
$(".method").each(function() {
if ($(this).next().is(".docblock")) {
$(this).children().first().after(toggle.clone());
}
});
var mainToggle =
$(toggle).append(
$('<span/>', {'class': 'toggle-label'})
.css('display', 'none')
.html('&nbsp;Expand&nbsp;description'));
var wrapper = $("<div class='toggle-wrapper'>").append(mainToggle);
$("#main > .docblock").before(wrapper);
});
$('pre.line-numbers').on('click', 'span', function() {
var prev_id = 0;
function set_fragment(name) {
if (history.replaceState) {
history.replaceState(null, null, '#' + name);
$(window).trigger('hashchange');
} else {
location.replace('#' + name);
}
}
return function(ev) {
var cur_id = parseInt(ev.target.id);
if (ev.shiftKey && prev_id) {
if (prev_id > cur_id) {
var tmp = prev_id;
prev_id = cur_id;
cur_id = tmp;
}
set_fragment(prev_id + '-' + cur_id);
} else {
prev_id = cur_id;
set_fragment(cur_id);
}
};
}());
}());
+1
View File
@@ -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
View File
@@ -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();
});
}
}());
+148
View File
@@ -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>&nbsp;<a id="expand-all" href="#">[+]</a>
</span><a id='src-0' href='../src/r2pipe/lib.rs.html#1-45'>[src]</a></span></h1>
<div class='docblock'><p>R2Pipe provides functions to interact with <a href="http://rada.re/r/">radare2</a></p>
<p>Hence this requires you to have radare2 installed on you system. For more information please
refer to the official <a href="https://github.com/radare/radare2">radare2 Repository</a>.
The module spawns an instance of r2 and communicates with it over pipes. Using commands which
produce a JSON output is recommended as it is easier to parse.</p>
<p>R2Pipes are available for a several of languages. For more information about r2pipes in general head over to the
<a href="https://github.com/radare/radare2/wiki/R2PipeAPI">wiki</a>.</p>
<h1 id="design" class='section-header'><a
href="#design">Design</a></h1>
<p>All the functionality for the crate are exposed through two structs: <code>R2PipeLang</code> and
<code>R2PipeSpawn</code>. Typically, there are two ways to invoke r2pipe. One by spawning a child-process
from inside r2 and second by making the program spawn a child r2process.
<code>enum R2Pipe</code> is provided to allow easier use of the library and abstract the difference between these two methods.
The <code>macro open_pipe!()</code> determines which of the two methods to use.</p>
<p><strong>Note:</strong> For the second method,
the path of the executable to be analyzed must be provided, while this is implicit in the first
method (executable loaded by r2).</p>
<h1 id="example" class='section-header'><a
href="#example">Example</a></h1><pre id='rust-example-rendered' class='rust '>
<span class='attribute'>#[<span class='ident'>macro_use</span>]</span>
<span class='kw'>extern</span> <span class='kw'>crate</span> <span class='ident'>r2pipe</span>;
<span class='kw'>use</span> <span class='ident'>r2pipe</span>::<span class='ident'>R2Pipe</span>;
<span class='kw'>fn</span> <span class='ident'>main</span>() {
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>r2p</span> <span class='op'>=</span> <span class='macro'>open_pipe</span><span class='macro'>!</span>(<span class='string'>&quot;/bin/ls&quot;</span>).<span class='ident'>unwrap</span>();
<span class='macro'>println</span><span class='macro'>!</span>(<span class='string'>&quot;{}&quot;</span>, <span class='ident'>r2p</span>.<span class='ident'>cmd</span>(<span class='string'>&quot;?e Hello World&quot;</span>));
<span class='kw'>let</span> <span class='ident'>json</span> <span class='op'>=</span> <span class='ident'>r2p</span>.<span class='ident'>cmdj</span>(<span class='string'>&quot;ij&quot;</span>);
<span class='macro'>println</span><span class='macro'>!</span>(<span class='string'>&quot;{}&quot;</span>, <span class='ident'>json</span>.<span class='ident'>pretty</span>());
<span class='macro'>println</span><span class='macro'>!</span>(<span class='string'>&quot;ARCH {}&quot;</span>, <span class='ident'>json</span>.<span class='ident'>find_path</span>(<span class='kw-2'>&amp;</span>[<span class='string'>&quot;bin&quot;</span>,<span class='string'>&quot;arch&quot;</span>]).<span class='ident'>unwrap</span>());
<span class='ident'>r2p</span>.<span class='ident'>close</span>();
}
</pre>
</div><h2 id='reexports' class='section-header'><a href="#reexports">Reexports</a></h2>
<table><tr><td><code>pub use self::<a class='mod'
href='./r2pipe/index.html'>r2pipe</a>::<a class='enum' href='../r2pipe/r2pipe/enum.R2Pipe.html' title='r2pipe::r2pipe::R2Pipe'>R2Pipe</a>;</code></td></tr></table><h2 id='modules' class='section-header'><a href="#modules">Modules</a></h2>
<table>
<tr>
<td><a class='stability Unmarked' title='No stability level'></a><a class='mod' href='r2pipe/index.html'
title='r2pipe::r2pipe'>r2pipe</a></td>
<td class='docblock short'><p>Provides functionality to connect with radare2.</p>
</td>
</tr>
</table><h2 id='macros' class='section-header'><a href="#macros">Macros</a></h2>
<table>
<tr>
<td><a class='stability Unmarked' title='No stability level'></a><a class='macro' href='macro.open_pipe!.html'
title='r2pipe::open_pipe!'>open_pipe!</a></td>
<td class='docblock short'></td>
</tr>
</table></section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../jquery.js"></script>
<script src="../main.js"></script>
<script async src="../search-index.js"></script>
</body>
</html>
+101
View File
@@ -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>&nbsp;<a id="expand-all" href="#">[+]</a>
</span><a id='src-699' href='../src/r2pipe/r2pipe.rs.html#50-53'>[src]</a></span></h1>
<pre class='rust macro'>
<span class='macro'>macro_rules</span><span class='macro'>!</span> <span class='ident'>open_pipe</span> {
(<span class='macro-nonterminal'>$</span><span class='macro-nonterminal'>x</span>:<span class='ident'>expr</span>) <span class='op'>=&gt;</span> (<span class='ident'>R2Pipe</span>::<span class='ident'>spawn</span>(<span class='macro-nonterminal'>$</span><span class='macro-nonterminal'>x</span>));
() <span class='op'>=&gt;</span> (<span class='ident'>R2Pipe</span>::<span class='ident'>open</span>());
}
</pre>
</section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../jquery.js"></script>
<script src="../main.js"></script>
<script async src="../search-index.js"></script>
</body>
</html>
+107
View File
@@ -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>&nbsp;<a id="expand-all" href="#">[+]</a>
</span><a id='src-31' href='../../src/r2pipe/r2pipe.rs.html#30-33'>[src]</a></span></h1>
<pre class='rust enum'>pub enum R2Pipe {
Pipe(<a class='struct' href='../../r2pipe/r2pipe/struct.R2PipeSpawn.html' title='r2pipe::r2pipe::R2PipeSpawn'>R2PipeSpawn</a>),
Lang(<a class='struct' href='../../r2pipe/r2pipe/struct.R2PipeLang.html' title='r2pipe::r2pipe::R2PipeLang'>R2PipeLang</a>),
}</pre><div class='docblock'><p>Provides abstraction between the two invocation methods.</p>
</div><h2 class='variants'>Variants</h2>
<table><tr><td id='variant.Pipe'><a class='stability Unmarked' title='No stability level'></a><code>Pipe</code></td><td></td></tr><tr><td id='variant.Lang'><a class='stability Unmarked' title='No stability level'></a><code>Lang</code></td><td></td></tr></table><h2 id='methods'>Methods</h2><h3 class='impl'><a class='stability Unmarked' title='No stability level'></a><code>impl <a class='enum' href='../../r2pipe/r2pipe/enum.R2Pipe.html' title='r2pipe::r2pipe::R2Pipe'>R2Pipe</a></code></h3><div class='impl-items'><h4 id='method.open' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.open' class='fnname'>open</a>() -&gt; <a class='enum' href='http://doc.rust-lang.org/nightly/core/result/enum.Result.html' title='core::result::Result'>Result</a>&lt;<a class='enum' href='../../r2pipe/r2pipe/enum.R2Pipe.html' title='r2pipe::r2pipe::R2Pipe'>R2Pipe</a>, &amp;'static <a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>&gt;</code></h4>
<h4 id='method.cmd' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.cmd' class='fnname'>cmd</a>(&amp;mut self, cmd: &amp;<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -&gt; <a class='struct' href='http://doc.rust-lang.org/nightly/collections/string/struct.String.html' title='collections::string::String'>String</a></code></h4>
<h4 id='method.cmdj' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.cmdj' class='fnname'>cmdj</a>(&amp;mut self, cmd: &amp;<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -&gt; <a class='enum' href='http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/enum.Json.html' title='rustc_serialize::json::Json'>Json</a></code></h4>
<h4 id='method.close' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.close' class='fnname'>close</a>(&amp;mut self)</code></h4>
<h4 id='method.in_session' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.in_session' class='fnname'>in_session</a>() -&gt; <a class='enum' href='http://doc.rust-lang.org/nightly/core/option/enum.Option.html' title='core::option::Option'>Option</a>&lt;<a href='http://doc.rust-lang.org/nightly/std/primitive.tuple.html'>(<a href='http://doc.rust-lang.org/nightly/std/primitive.i32.html'>i32</a>, <a href='http://doc.rust-lang.org/nightly/std/primitive.i32.html'>i32</a>)</a>&gt;</code></h4>
<h4 id='method.spawn' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.spawn' class='fnname'>spawn</a>(_name: &amp;<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -&gt; <a class='enum' href='http://doc.rust-lang.org/nightly/core/result/enum.Result.html' title='core::result::Result'>Result</a>&lt;<a class='enum' href='../../r2pipe/r2pipe/enum.R2Pipe.html' title='r2pipe::r2pipe::R2Pipe'>R2Pipe</a>, &amp;'static <a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>&gt;</code></h4>
<div class='docblock'><p>Creates a new R2PipeSpawn.</p>
</div></div></section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../../jquery.js"></script>
<script src="../../main.js"></script>
<script async src="../../search-index.js"></script>
</body>
</html>
+121
View File
@@ -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>&nbsp;<a id="expand-all" href="#">[+]</a>
</span><a id='src-6' href='../../src/r2pipe/r2pipe.rs.html#1-196'>[src]</a></span></h1>
<div class='docblock'><p>Provides functionality to connect with radare2.</p>
<p>Please check crate level documentation for more details and example.</p>
</div><h2 id='structs' class='section-header'><a href="#structs">Structs</a></h2>
<table>
<tr>
<td><a class='stability Unmarked' title='No stability level'></a><a class='struct' href='struct.R2PipeLang.html'
title='r2pipe::r2pipe::R2PipeLang'>R2PipeLang</a></td>
<td class='docblock short'><p>File descriptors to the parent r2 process.</p>
</td>
</tr>
<tr>
<td><a class='stability Unmarked' title='No stability level'></a><a class='struct' href='struct.R2PipeSpawn.html'
title='r2pipe::r2pipe::R2PipeSpawn'>R2PipeSpawn</a></td>
<td class='docblock short'><p>Stores descriptors to the spawned r2 process.</p>
</td>
</tr>
</table><h2 id='enums' class='section-header'><a href="#enums">Enums</a></h2>
<table>
<tr>
<td><a class='stability Unmarked' title='No stability level'></a><a class='enum' href='enum.R2Pipe.html'
title='r2pipe::r2pipe::R2Pipe'>R2Pipe</a></td>
<td class='docblock short'><p>Provides abstraction between the two invocation methods.</p>
</td>
</tr>
</table></section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../../jquery.js"></script>
<script src="../../main.js"></script>
<script async src="../../search-index.js"></script>
</body>
</html>
+1
View File
@@ -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."]]});
+101
View File
@@ -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>&nbsp;<a id="expand-all" href="#">[+]</a>
</span><a id='src-19' href='../../src/r2pipe/r2pipe.rs.html#18-21'>[src]</a></span></h1>
<pre class='rust struct'>pub struct R2PipeLang {
// some fields omitted
}</pre><div class='docblock'><p>File descriptors to the parent r2 process.</p>
</div><h2 id='methods'>Methods</h2><h3 class='impl'><a class='stability Unmarked' title='No stability level'></a><code>impl <a class='struct' href='../../r2pipe/r2pipe/struct.R2PipeLang.html' title='r2pipe::r2pipe::R2PipeLang'>R2PipeLang</a></code></h3><div class='impl-items'><h4 id='method.cmd' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.cmd' class='fnname'>cmd</a>(&amp;mut self, cmd: &amp;<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -&gt; <a class='struct' href='http://doc.rust-lang.org/nightly/collections/string/struct.String.html' title='collections::string::String'>String</a></code></h4>
<h4 id='method.cmdj' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.cmdj' class='fnname'>cmdj</a>(&amp;mut self, cmd: &amp;<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -&gt; <a class='enum' href='http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/enum.Json.html' title='rustc_serialize::json::Json'>Json</a></code></h4>
<h4 id='method.close' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.close' class='fnname'>close</a>(&amp;mut self)</code></h4>
</div></section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../../jquery.js"></script>
<script src="../../main.js"></script>
<script async src="../../search-index.js"></script>
</body>
</html>
+101
View File
@@ -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>&nbsp;<a id="expand-all" href="#">[+]</a>
</span><a id='src-25' href='../../src/r2pipe/r2pipe.rs.html#24-27'>[src]</a></span></h1>
<pre class='rust struct'>pub struct R2PipeSpawn {
// some fields omitted
}</pre><div class='docblock'><p>Stores descriptors to the spawned r2 process.</p>
</div><h2 id='methods'>Methods</h2><h3 class='impl'><a class='stability Unmarked' title='No stability level'></a><code>impl <a class='struct' href='../../r2pipe/r2pipe/struct.R2PipeSpawn.html' title='r2pipe::r2pipe::R2PipeSpawn'>R2PipeSpawn</a></code></h3><div class='impl-items'><h4 id='method.cmd' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.cmd' class='fnname'>cmd</a>(&amp;mut self, cmd: &amp;<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -&gt; <a class='struct' href='http://doc.rust-lang.org/nightly/collections/string/struct.String.html' title='collections::string::String'>String</a></code></h4>
<h4 id='method.cmdj' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.cmdj' class='fnname'>cmdj</a>(&amp;mut self, cmd: &amp;<a href='http://doc.rust-lang.org/nightly/std/primitive.str.html'>str</a>) -&gt; <a class='enum' href='http://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/enum.Json.html' title='rustc_serialize::json::Json'>Json</a></code></h4>
<h4 id='method.close' class='method'><a class='stability Unmarked' title='No stability level'></a><code>fn <a href='#method.close' class='fnname'>close</a>(&amp;mut self)</code></h4>
</div></section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../../jquery.js"></script>
<script src="../../main.js"></script>
<script async src="../../search-index.js"></script>
</body>
</html>
+1
View File
@@ -0,0 +1 @@
initSidebarItems({"macro":[["open_pipe!",""]],"mod":[["r2pipe","Provides functionality to connect with radare2."]]});
+102
View File
@@ -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'>&nbsp</span><span class='summary Unstable' style='width: 0.0000%; display: inline-block'>&nbsp</span><span class='summary Deprecated' style='width: 0.0000%; display: inline-block'>&nbsp</span><span class='summary Unmarked' style='width: 100.0000%; display: inline-block'>&nbsp</span></td></tr><tr><td><a href='r2pipe/index.html'>r2pipe::r2pipe</a></td><td class='summary-column'><span class='summary Stable' style='width: 0.0000%; display: inline-block'>&nbsp</span><span class='summary Unstable' style='width: 0.0000%; display: inline-block'>&nbsp</span><span class='summary Deprecated' style='width: 0.0000%; display: inline-block'>&nbsp</span><span class='summary Unmarked' style='width: 100.0000%; display: inline-block'>&nbsp</span></td></tr></table></section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../jquery.js"></script>
<script src="../main.js"></script>
<script async src="../search-index.js"></script>
</body>
</html>
+1
View File
@@ -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":[]}]}
+3
View File
@@ -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);
-81
View File
@@ -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))
}
}
-47
View File
@@ -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
View File
@@ -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;
-84
View File
@@ -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
View File
@@ -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());
}
}
+183
View File
@@ -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!(&quot;/bin/ls&quot;).unwrap();</span>
<span class='doccomment'>//! println!(&quot;{}&quot;, r2p.cmd(&quot;?e Hello World&quot;));</span>
<span class='doccomment'>//! let json = r2p.cmdj(&quot;ij&quot;);</span>
<span class='doccomment'>//! println!(&quot;{}&quot;, json.pretty());</span>
<span class='doccomment'>//! println!(&quot;ARCH {}&quot;, json.find_path(&amp;[&quot;bin&quot;,&quot;arch&quot;]).unwrap());</span>
<span class='doccomment'>//! r2p.close();</span>
<span class='doccomment'>//! }</span>
<span class='doccomment'>//! ```</span>
<span class='attribute'>#<span class='op'>!</span>[<span class='ident'>doc</span>(<span class='ident'>html_root_url</span> <span class='op'>=</span> <span class='string'>&quot;https://radare.github.io/r2pipe.rs/&quot;</span>)]</span>
<span class='kw'>extern</span> <span class='kw'>crate</span> <span class='ident'>libc</span>;
<span class='kw'>extern</span> <span class='kw'>crate</span> <span class='ident'>rustc_serialize</span>;
<span class='kw'>pub</span> <span class='kw'>mod</span> <span class='ident'>r2pipe</span>;
<span class='comment'>// Rexport to bring it out one module.</span>
<span class='kw'>pub</span> <span class='kw'>use</span> <span class='self'>self</span>::<span class='ident'>r2pipe</span>::<span class='ident'>R2Pipe</span>;
</pre>
</section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../../jquery.js"></script>
<script src="../../main.js"></script>
<script async src="../../search-index.js"></script>
</body>
</html>
+485
View File
@@ -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'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='ident'>i32</span> {
<span class='kw'>match</span> <span class='ident'>k</span>.<span class='ident'>parse</span>::<span class='op'>&lt;</span><span class='ident'>i32</span><span class='op'>&gt;</span>() {
<span class='prelude-val'>Ok</span>(<span class='ident'>val</span>) <span class='op'>=&gt;</span> <span class='ident'>val</span>,
<span class='prelude-val'>Err</span>(_) <span class='op'>=&gt;</span> <span class='number'>0</span>
}
}
<span class='kw'>fn</span> <span class='ident'>getenv</span>(<span class='ident'>k</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='ident'>i32</span> {
<span class='kw'>match</span> <span class='ident'>env</span>::<span class='ident'>var</span>(<span class='ident'>k</span>) {
<span class='prelude-val'>Ok</span>(<span class='ident'>val</span>) <span class='op'>=&gt;</span> <span class='ident'>atoi</span>(<span class='kw-2'>&amp;</span><span class='ident'>val</span>),
<span class='prelude-val'>Err</span>(_) <span class='op'>=&gt;</span> <span class='number'>0</span>,
}
}
<span class='attribute'>#[<span class='ident'>macro_export</span>]</span>
<span class='macro'>macro_rules</span><span class='macro'>!</span> <span class='ident'>open_pipe</span> {
(<span class='macro-nonterminal'>$</span><span class='macro-nonterminal'>x</span>:<span class='ident'>expr</span>) <span class='op'>=&gt;</span> (<span class='ident'>R2Pipe</span>::<span class='ident'>spawn</span>(<span class='macro-nonterminal'>$</span><span class='macro-nonterminal'>x</span>));
() <span class='op'>=&gt;</span> (<span class='ident'>R2Pipe</span>::<span class='ident'>open</span>());
}
<span class='kw'>impl</span> <span class='ident'>R2Pipe</span> {
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>open</span>() <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span><span class='op'>&lt;</span><span class='ident'>R2Pipe</span>, <span class='kw-2'>&amp;</span><span class='lifetime'>&#39;static</span> <span class='ident'>str</span><span class='op'>&gt;</span> {
<span class='kw'>let</span> (<span class='ident'>fin</span>, <span class='ident'>fout</span>) <span class='op'>=</span> <span class='kw'>match</span> <span class='ident'>R2Pipe</span>::<span class='ident'>in_session</span>() {
<span class='prelude-val'>Some</span>(<span class='ident'>x</span>) <span class='op'>=&gt;</span> <span class='ident'>x</span>,
<span class='prelude-val'>None</span> <span class='op'>=&gt;</span> <span class='kw'>return</span> <span class='prelude-val'>Err</span>(<span class='string'>&quot;Pipe not open. Please run from r2&quot;</span>),
};
<span class='kw'>let</span> <span class='ident'>_res</span> <span class='op'>=</span> <span class='ident'>R2PipeLang</span> { <span class='ident'>fd_in</span>: <span class='ident'>fin</span>, <span class='ident'>fd_out</span>: <span class='ident'>fout</span> };
<span class='prelude-val'>Ok</span>(<span class='ident'>R2Pipe</span>::<span class='ident'>Lang</span>(<span class='ident'>_res</span>))
}
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>cmd</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='ident'>String</span> {
<span class='kw'>match</span> <span class='op'>*</span><span class='self'>self</span> {
<span class='ident'>R2Pipe</span>::<span class='ident'>Pipe</span>(<span class='kw-2'>ref</span> <span class='kw-2'>mut</span> <span class='ident'>x</span>) <span class='op'>=&gt;</span> <span class='ident'>x</span>.<span class='ident'>cmd</span>(<span class='ident'>cmd</span>),
<span class='ident'>R2Pipe</span>::<span class='ident'>Lang</span>(<span class='kw-2'>ref</span> <span class='kw-2'>mut</span> <span class='ident'>x</span>) <span class='op'>=&gt;</span> <span class='ident'>x</span>.<span class='ident'>cmd</span>(<span class='ident'>cmd</span>),
}
}
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>cmdj</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='ident'>Json</span> {
<span class='kw'>match</span> <span class='op'>*</span><span class='self'>self</span> {
<span class='ident'>R2Pipe</span>::<span class='ident'>Pipe</span>(<span class='kw-2'>ref</span> <span class='kw-2'>mut</span> <span class='ident'>x</span>) <span class='op'>=&gt;</span> <span class='ident'>x</span>.<span class='ident'>cmdj</span>(<span class='ident'>cmd</span>),
<span class='ident'>R2Pipe</span>::<span class='ident'>Lang</span>(<span class='kw-2'>ref</span> <span class='kw-2'>mut</span> <span class='ident'>x</span>) <span class='op'>=&gt;</span> <span class='ident'>x</span>.<span class='ident'>cmdj</span>(<span class='ident'>cmd</span>),
}
}
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>close</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>) {
<span class='kw'>match</span> <span class='op'>*</span><span class='self'>self</span> {
<span class='ident'>R2Pipe</span>::<span class='ident'>Pipe</span>(<span class='kw-2'>ref</span> <span class='kw-2'>mut</span> <span class='ident'>x</span>) <span class='op'>=&gt;</span> <span class='ident'>x</span>.<span class='ident'>close</span>(),
<span class='ident'>R2Pipe</span>::<span class='ident'>Lang</span>(<span class='kw-2'>ref</span> <span class='kw-2'>mut</span> <span class='ident'>x</span>) <span class='op'>=&gt;</span> <span class='ident'>x</span>.<span class='ident'>close</span>(),
}
}
<span class='comment'>// XXX: must support windows</span>
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>in_session</span>() <span class='op'>-&gt;</span> <span class='prelude-ty'>Option</span><span class='op'>&lt;</span>(<span class='ident'>i32</span>, <span class='ident'>i32</span>)<span class='op'>&gt;</span> {
<span class='kw'>let</span> <span class='ident'>fin</span> <span class='op'>=</span> <span class='ident'>getenv</span>(<span class='string'>&quot;R2PIPE_IN&quot;</span>);
<span class='kw'>let</span> <span class='ident'>fout</span> <span class='op'>=</span> <span class='ident'>getenv</span>(<span class='string'>&quot;R2PIPE_OUT&quot;</span>);
<span class='kw'>if</span> <span class='ident'>fin</span> <span class='op'>==</span> <span class='number'>0</span> <span class='op'>||</span> <span class='ident'>fout</span> <span class='op'>==</span> <span class='number'>0</span> {
<span class='kw'>return</span> <span class='prelude-val'>None</span>;
}
<span class='kw'>return</span> <span class='prelude-val'>Some</span>((<span class='ident'>fin</span>, <span class='ident'>fout</span>));
}
<span class='doccomment'>/// Creates a new R2PipeSpawn.</span>
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>spawn</span>(<span class='ident'>_name</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span><span class='op'>&lt;</span><span class='ident'>R2Pipe</span>, <span class='kw-2'>&amp;</span><span class='lifetime'>&#39;static</span> <span class='ident'>str</span><span class='op'>&gt;</span> {
<span class='kw'>if</span> <span class='kw'>let</span> <span class='prelude-val'>Some</span>(_) <span class='op'>=</span> <span class='ident'>R2Pipe</span>::<span class='ident'>in_session</span>() {
<span class='kw'>return</span> <span class='ident'>R2Pipe</span>::<span class='ident'>open</span>();
}
<span class='kw'>let</span> <span class='ident'>name</span> <span class='op'>=</span> <span class='ident'>_name</span>.<span class='ident'>to_string</span>();
<span class='kw'>let</span> <span class='ident'>path</span> <span class='op'>=</span> <span class='ident'>Path</span>::<span class='ident'>new</span>(<span class='kw-2'>&amp;</span><span class='op'>*</span><span class='ident'>name</span>);
<span class='kw'>let</span> <span class='ident'>child</span> <span class='op'>=</span> <span class='kw'>match</span> <span class='ident'>Command</span>::<span class='ident'>new</span>(<span class='string'>&quot;r2&quot;</span>)
.<span class='ident'>arg</span>(<span class='string'>&quot;-q0&quot;</span>)
.<span class='ident'>arg</span>(<span class='ident'>path</span>)
.<span class='ident'>stdin</span>(<span class='ident'>Stdio</span>::<span class='ident'>piped</span>())
.<span class='ident'>stdout</span>(<span class='ident'>Stdio</span>::<span class='ident'>piped</span>())
.<span class='ident'>spawn</span>() {
<span class='prelude-val'>Ok</span>(<span class='ident'>c</span>) <span class='op'>=&gt;</span> <span class='ident'>c</span>,
<span class='prelude-val'>Err</span>(_) <span class='op'>=&gt;</span> <span class='kw'>return</span> <span class='prelude-val'>Err</span>(<span class='string'>&quot;Unable to spawn r2.&quot;</span>),
};
<span class='kw'>let</span> <span class='ident'>sin</span>: <span class='ident'>process</span>::<span class='ident'>ChildStdin</span>;
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>sout</span>: <span class='ident'>process</span>::<span class='ident'>ChildStdout</span>;
{
<span class='ident'>sin</span> <span class='op'>=</span> <span class='ident'>child</span>.<span class='ident'>stdin</span>.<span class='ident'>unwrap</span>();
<span class='ident'>sout</span> <span class='op'>=</span> <span class='ident'>child</span>.<span class='ident'>stdout</span>.<span class='ident'>unwrap</span>();
<span class='comment'>// flush out the initial null byte.</span>
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>w</span> <span class='op'>=</span> [<span class='number'>0</span>;<span class='number'>1</span>];
<span class='ident'>sout</span>.<span class='ident'>read</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='ident'>w</span>).<span class='ident'>unwrap</span>();
}
<span class='kw'>let</span> <span class='ident'>_res</span> <span class='op'>=</span> <span class='ident'>R2PipeSpawn</span> {
<span class='ident'>read</span>: <span class='ident'>sout</span>,
<span class='ident'>write</span>: <span class='ident'>sin</span>
};
<span class='prelude-val'>Ok</span>(<span class='ident'>R2Pipe</span>::<span class='ident'>Pipe</span>(<span class='ident'>_res</span>))
}
}
<span class='kw'>impl</span> <span class='ident'>R2PipeSpawn</span> {
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>cmd</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='ident'>String</span> {
<span class='kw'>let</span> <span class='ident'>cmd_</span> <span class='op'>=</span> <span class='ident'>cmd</span>.<span class='ident'>to_owned</span>() <span class='op'>+</span> <span class='string'>&quot;\n&quot;</span>;
<span class='kw'>if</span> <span class='kw'>let</span> <span class='prelude-val'>Err</span>(<span class='ident'>e</span>) <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>write</span>.<span class='ident'>write</span>(<span class='ident'>cmd_</span>.<span class='ident'>as_bytes</span>()) {
<span class='macro'>panic</span><span class='macro'>!</span>(<span class='string'>&quot;{}&quot;</span>, <span class='ident'>e</span>);
}
<span class='comment'>// Read in block size of 2048.</span>
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>s</span> <span class='op'>=</span> [<span class='number'>0</span>; <span class='number'>2048</span>];
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>res</span>: <span class='ident'>String</span> <span class='op'>=</span> <span class='ident'>String</span>::<span class='ident'>new</span>();
<span class='kw'>loop</span> {
<span class='kw'>let</span> <span class='ident'>count</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>read</span>.<span class='ident'>read</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='ident'>s</span>).<span class='ident'>unwrap</span>();
<span class='kw'>for</span> <span class='ident'>c</span> <span class='kw'>in</span> <span class='ident'>s</span>[..<span class='ident'>count</span>].<span class='ident'>iter</span>() {
<span class='ident'>res</span> <span class='op'>=</span> <span class='ident'>res</span> <span class='op'>+</span> <span class='kw-2'>&amp;</span><span class='op'>*</span><span class='macro'>format</span><span class='macro'>!</span>(<span class='string'>&quot;{}&quot;</span>, <span class='op'>*</span><span class='ident'>c</span> <span class='kw'>as</span> <span class='ident'>char</span>);
}
<span class='kw'>if</span> <span class='ident'>count</span> <span class='op'>&lt;</span> <span class='number'>2048</span> {
<span class='kw'>break</span>;
}
}
<span class='kw'>let</span> <span class='ident'>len</span> <span class='op'>=</span> <span class='ident'>res</span>.<span class='ident'>len</span>() <span class='op'>-</span> <span class='number'>1</span>;
<span class='ident'>res</span>.<span class='ident'>truncate</span>(<span class='ident'>len</span>);
<span class='ident'>res</span>
}
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>cmdj</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='ident'>Json</span> {
<span class='kw'>let</span> <span class='ident'>res</span> <span class='op'>=</span> <span class='kw-2'>&amp;</span><span class='self'>self</span>.<span class='ident'>cmd</span>(<span class='ident'>cmd</span>).<span class='ident'>replace</span>(<span class='string'>&quot;\n&quot;</span>,<span class='string'>&quot;&quot;</span>);
<span class='ident'>Json</span>::<span class='ident'>from_str</span>(<span class='ident'>res</span>).<span class='ident'>unwrap</span>()
}
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>close</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>) {
<span class='self'>self</span>.<span class='ident'>cmd</span>(<span class='string'>&quot;q!&quot;</span>);
}
}
<span class='kw'>impl</span> <span class='ident'>R2PipeLang</span> {
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>cmd</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='ident'>String</span> {
<span class='kw'>let</span> <span class='ident'>buf</span>: [<span class='ident'>u8</span>; <span class='number'>1024</span>] <span class='op'>=</span> [<span class='number'>0</span>;<span class='number'>1024</span>];
<span class='kw'>unsafe</span> {
<span class='ident'>libc</span>::<span class='ident'>write</span> (<span class='self'>self</span>.<span class='ident'>fd_out</span>, <span class='ident'>cmd</span>.<span class='ident'>as_ptr</span>() <span class='kw'>as</span> <span class='op'>*</span><span class='kw'>const</span> <span class='ident'>c_void</span>, <span class='ident'>cmd</span>.<span class='ident'>len</span>() <span class='kw'>as</span> <span class='ident'>u64</span>);
<span class='ident'>libc</span>::<span class='ident'>write</span> (<span class='self'>self</span>.<span class='ident'>fd_out</span>, <span class='string'>&quot;\x00&quot;</span>.<span class='ident'>as_ptr</span>() <span class='kw'>as</span> <span class='op'>*</span><span class='kw'>const</span> <span class='ident'>c_void</span>, <span class='number'>1</span>);
<span class='kw'>let</span> <span class='ident'>len</span> <span class='op'>=</span> <span class='ident'>libc</span>::<span class='ident'>read</span> (<span class='self'>self</span>.<span class='ident'>fd_in</span>, <span class='ident'>buf</span>.<span class='ident'>as_ptr</span>() <span class='kw'>as</span> <span class='op'>*</span><span class='kw-2'>mut</span> <span class='ident'>c_void</span>, <span class='ident'>buf</span>.<span class='ident'>len</span>() <span class='kw'>as</span> <span class='ident'>u64</span>) <span class='kw'>as</span> <span class='ident'>usize</span>;
<span class='kw'>let</span> <span class='ident'>buf2</span> : <span class='ident'>Box</span><span class='op'>&lt;</span><span class='kw-2'>&amp;</span>[<span class='ident'>u8</span>]<span class='op'>&gt;</span> <span class='op'>=</span> <span class='ident'>Box</span>::<span class='ident'>new</span>(<span class='kw-2'>&amp;</span><span class='ident'>buf</span>[<span class='number'>0</span>..<span class='ident'>len</span><span class='op'>-</span><span class='number'>1</span>]);
<span class='kw'>let</span> <span class='ident'>s</span> <span class='op'>=</span> <span class='ident'>str</span>::<span class='ident'>from_utf8</span>(<span class='kw-2'>&amp;</span><span class='ident'>buf2</span>).<span class='ident'>unwrap</span>();
<span class='ident'>s</span>.<span class='ident'>to_string</span>()
}
}
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>cmdj</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>cmd</span>: <span class='kw-2'>&amp;</span><span class='ident'>str</span>) <span class='op'>-&gt;</span> <span class='ident'>Json</span> {
<span class='kw'>let</span> <span class='ident'>res</span> <span class='op'>=</span> <span class='kw-2'>&amp;</span><span class='self'>self</span>.<span class='ident'>cmd</span>(<span class='ident'>cmd</span>).<span class='ident'>replace</span>(<span class='string'>&quot;\n&quot;</span>,<span class='string'>&quot;&quot;</span>);
<span class='ident'>Json</span>::<span class='ident'>from_str</span>(<span class='ident'>res</span>).<span class='ident'>unwrap</span>()
}
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>close</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>) {
<span class='kw'>unsafe</span> {
<span class='ident'>libc</span>::<span class='ident'>close</span> (<span class='self'>self</span>.<span class='ident'>fd_in</span>);
<span class='ident'>libc</span>::<span class='ident'>close</span> (<span class='self'>self</span>.<span class='ident'>fd_out</span>);
}
}
}
</pre>
</section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<div id="help" class="hidden">
<div class="shortcuts">
<h1>Keyboard shortcuts</h1>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h1>Search tricks</h1>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>typedef</code> (or
<code>tdef</code>).
</p>
</div>
</div>
<script>
window.rootPath = "../../";
window.currentCrate = "r2pipe";
window.playgroundUrl = "";
</script>
<script src="../../jquery.js"></script>
<script src="../../main.js"></script>
<script async src="../../search-index.js"></script>
</body>
</html>