Skip to content

Commit

Permalink
Improve docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcondiro committed Jul 8, 2024
1 parent 179da1b commit e7f5f28
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 8 deletions.
36 changes: 32 additions & 4 deletions libafl_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,44 @@ pub fn libafl_serdeany_derive(input: TokenStream) -> TokenStream {
/// Options: Some => inner type display None => "".
/// Vec: inner type display space separated concatenation.
/// Generics and other more or less exotic stuff are not supported.
///
/// # Examples
///
/// ```rust
/// use libafl_derive;
///
/// #[derive(libafl_derive::Display)]
/// struct MyStruct {
/// foo: String,
/// bar: Option<u32>,
/// }
/// ```
///
/// The above code will expand to:
///
/// ```rust
/// struct MyStruct {
/// foo: String,
/// bar: Option<u32>,
/// }
///
/// impl core::fmt::Display for MyStruct {
/// fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
/// f.write_fmt(format_args!(" {0}", self.foo))?;
/// if let Some(opt) = &self.bar {
/// f.write_fmt(format_args!(" {0}", opt))?;
/// }
/// Ok(())
/// }
/// }
/// ```
#[proc_macro_derive(Display)]
pub fn libafl_display(input: TokenStream) -> TokenStream {
let DeriveInput { ident, data, .. } = parse_macro_input!(input as DeriveInput);

if let Struct(s) = data {
if let Named(fields) = s.fields {
let fields_fmt = fields
.named
.iter()
.map(libafl_display_field_by_type);
let fields_fmt = fields.named.iter().map(libafl_display_field_by_type);

return quote! {
impl core::fmt::Display for #ident {
Expand Down
5 changes: 2 additions & 3 deletions libafl_qemu/src/qemu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -572,10 +572,9 @@ impl From<u8> for HookData {

#[allow(clippy::unused_self)]
impl Qemu {
/// For more details about the parameters check
/// [the QEMU documentation](https://www.qemu.org/docs/master/about/).
pub fn builder() -> QemuConfigBuilder {
// Since Qemu is a zero sized struct, this is not a completely standard builder pattern.
// The Qemu configuration is not stored in the Qemu struct after build().
// Therefore, to use the derived builder and avoid boilerplate a builder for QemuConfig is derived.
QemuConfig::builder()
}

Expand Down
18 changes: 17 additions & 1 deletion libafl_qemu/src/qemu/qemu_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ pub enum Monitor {
}

/// Set the directory for the BIOS, VGA BIOS and keymaps.
/// Corresponds to the `-L` option of QEMU.
#[derive(Debug, Clone)]
pub struct Bios {
path: PathBuf,
Expand Down Expand Up @@ -197,6 +198,7 @@ impl From<bool> for Snapshot {
}
}

/// When set to DISABLE, corresponds to the `-S` option of QEMU.
#[derive(Debug, Clone, strum_macros::Display)]
pub enum StartCPU {
#[strum(serialize = "")]
Expand Down Expand Up @@ -300,7 +302,11 @@ impl<R: AsRef<Path>> From<R> for Program {
}

#[derive(Debug, Clone, libafl_derive::Display, TypedBuilder)]
#[builder(build_method(into = Result<Qemu, QemuInitError>), builder_method(vis = "pub(crate)"))]
#[builder(build_method(into = Result<Qemu, QemuInitError>), builder_method(vis = "pub(crate)",
doc = "Since Qemu is a zero sized struct, this is not a completely standard builder pattern. \
The Qemu configuration is not stored in the Qemu struct after build() but in QEMU_CONFIG \
Therefore, to use the derived builder and avoid boilerplate a builder for QemuConfig is \
derived."))]
pub struct QemuConfig {
#[cfg(emulation_mode = "systemmode")]
#[builder(default, setter(strip_option))]
Expand Down Expand Up @@ -337,6 +343,16 @@ pub struct QemuConfig {
} // Adding something here? Please leave Program as the last field

impl From<QemuConfig> for Result<Qemu, QemuInitError> {
/// This method is necessary to make the API resemble a typical builder pattern, i.e.
/// `Qemu::builder().foo(bar).build()`, while still leveraging TypedBuilder for this
/// non-standard use case where `Qemu` doesn't store the configuration.
/// Internally, TypedBuilder is used to generate a builder for `QemuConfig`.
/// This `QemuConfig.into()` method is used by the derived `QemuConfigBuilder.build()`
/// to go from `QemuConfigBuilder` to `QemuConfig`, and finally to `Qemu` in one fn.
///
/// # Errors
/// returns `QemuInitError` if the Qemu initialization fails, including if Qemu has been
/// initialized already.
fn from(config: QemuConfig) -> Self {
let args = config
.to_string()
Expand Down

0 comments on commit e7f5f28

Please sign in to comment.