combine crates to workspace
This commit is contained in:
parent
e853f8bc46
commit
bc852d6b6a
16
Cargo.toml
16
Cargo.toml
@ -1,10 +1,8 @@
|
||||
[package]
|
||||
name = "parsebtrfs"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
|
||||
[dependencies]
|
||||
binparse_derive = { path = "../binparse_derive" }
|
||||
maud = "0.26.0"
|
||||
memmap2 = "0.7.1"
|
||||
rouille = "3.6.2"
|
||||
members = [
|
||||
"btrfs_explorer_bin",
|
||||
"btrfs_parse_derive",
|
||||
"btrfs_explorer",
|
||||
]
|
||||
|
9
btrfs_explorer/Cargo.toml
Normal file
9
btrfs_explorer/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "btrfs_explorer"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
btrfs_parse_derive = { path = "../btrfs_parse_derive" }
|
||||
maud = "0.26.0"
|
||||
rouille = "3.6.2"
|
12
btrfs_explorer_bin/Cargo.toml
Normal file
12
btrfs_explorer_bin/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "btrfs_explorer_bin"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
btrfs_explorer = { path = "../btrfs_explorer" }
|
||||
memmap2 = "0.7.1"
|
||||
maud = "0.26.0"
|
||||
rouille = "3.6.2"
|
@ -3,7 +3,7 @@ use std::{
|
||||
};
|
||||
use memmap2::{Mmap, MmapOptions};
|
||||
use rouille::{Request, Response, router};
|
||||
use parsebtrfs::{
|
||||
use btrfs_explorer::{
|
||||
btrfs_structs::{TreeID, Value::Extent, Value::BlockGroup, NODE_SIZE, ItemType},
|
||||
btrfs_lookup::Tree,
|
||||
addrmap::AddressMap,
|
||||
@ -41,15 +41,15 @@ fn main() -> Result<(), MainError> {
|
||||
(GET) ["/"] =>
|
||||
http_main_boxes(&image, request),
|
||||
(GET) ["/root"] =>
|
||||
parsebtrfs::http_tree::http_root(&image, None, request),
|
||||
btrfs_explorer::http_tree::http_root(&image, None, request),
|
||||
(GET) ["/tree/{tree}", tree: String] =>
|
||||
parsebtrfs::http_tree::http_tree(&image, &tree, None, request.get_param("key").as_deref(), request).unwrap(),
|
||||
btrfs_explorer::http_tree::http_tree(&image, &tree, None, request.get_param("key").as_deref(), request).unwrap(),
|
||||
(GET) ["/tree/{tree}/{key}", tree: String, key: String] =>
|
||||
parsebtrfs::http_tree::http_tree(&image, &tree, None, Some(&key), request).unwrap(),
|
||||
btrfs_explorer::http_tree::http_tree(&image, &tree, None, Some(&key), request).unwrap(),
|
||||
(GET) ["/tree/{tree}?key={key}", tree: String, key: String] =>
|
||||
parsebtrfs::http_tree::http_tree(&image, &tree, None, Some(&key), request).unwrap(),
|
||||
btrfs_explorer::http_tree::http_tree(&image, &tree, None, Some(&key), request).unwrap(),
|
||||
(GET) ["/tree/{tree}/{method}/{key}", tree: String, method: String, key: String] =>
|
||||
parsebtrfs::http_tree::http_tree(&image, &tree, Some(&method), Some(&key), request).unwrap(),
|
||||
btrfs_explorer::http_tree::http_tree(&image, &tree, Some(&method), Some(&key), request).unwrap(),
|
||||
(GET) ["/favicon.ico"] => Response::empty_404(),
|
||||
(GET) ["/style.css"] => Response::from_file("text/css", File::open("style.css").unwrap()),
|
||||
(GET) ["/htmx.min.js"] => Response::from_file("text/css", File::open("htmx.min.js").unwrap()),
|
14
btrfs_parse_derive/Cargo.toml
Normal file
14
btrfs_parse_derive/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "btrfs_parse_derive"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0.66"
|
||||
quote = "1.0.32"
|
||||
syn = "2.0.27"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
184
btrfs_parse_derive/src/lib.rs
Normal file
184
btrfs_parse_derive/src/lib.rs
Normal file
@ -0,0 +1,184 @@
|
||||
extern crate proc_macro;
|
||||
extern crate syn;
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
extern crate proc_macro2;
|
||||
|
||||
use proc_macro2::Span;
|
||||
use proc_macro::TokenStream;
|
||||
use syn::{DeriveInput, Data::Enum, parse_macro_input};
|
||||
|
||||
#[proc_macro_derive(AllVariants)]
|
||||
pub fn derive_all_variants(input: TokenStream) -> TokenStream {
|
||||
let syn_item: DeriveInput = parse_macro_input!(input);
|
||||
|
||||
let variants = match syn_item.data {
|
||||
Enum(enum_item) => {
|
||||
enum_item.variants.into_iter().map(|v|v.ident)
|
||||
},
|
||||
_ => panic!("AllVariants only works on enums!"),
|
||||
};
|
||||
let enum_name = syn_item.ident;
|
||||
|
||||
let expanded = quote! {
|
||||
impl #enum_name {
|
||||
fn all_variants() -> &'static[#enum_name] {
|
||||
&[ #(#enum_name::#variants),* ]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
expanded.into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(ParseBin, attributes(skip_bytes, len))]
|
||||
pub fn derive_parse_bin(input: TokenStream) -> TokenStream {
|
||||
let syn_item: DeriveInput = parse_macro_input!(input);
|
||||
let name = syn_item.ident;
|
||||
|
||||
match syn_item.data {
|
||||
syn::Data::Struct(struct_item) => {
|
||||
match struct_item.fields {
|
||||
syn::Fields::Named(fields_named) => {
|
||||
return derive_parse_bin_struct(&name, &fields_named.named);
|
||||
},
|
||||
syn::Fields::Unnamed(fields_unnamed) => {
|
||||
if fields_unnamed.unnamed.len() != 1 {
|
||||
panic!("ParseBin does not support tuple structs!");
|
||||
}
|
||||
|
||||
let inner_type = fields_unnamed.unnamed.into_iter().next().unwrap().ty;
|
||||
return derive_parse_bin_alias(name, inner_type);
|
||||
},
|
||||
_ => panic!("ParseBin on unit structs makes no sense!"),
|
||||
}
|
||||
},
|
||||
_ => panic!("ParseBin only works on structs so far!"),
|
||||
};
|
||||
}
|
||||
|
||||
fn derive_parse_bin_alias(name: syn::Ident, ty: syn::Type) -> TokenStream {
|
||||
quote! {
|
||||
impl ParseBin for #name {
|
||||
fn parse_len(bytes: &[u8]) -> Result<(Self, usize), ParseError> {
|
||||
let (result, size) = <#ty>::parse_len(bytes)?;
|
||||
Ok((#name(result), size))
|
||||
}
|
||||
}
|
||||
}.into()
|
||||
}
|
||||
|
||||
fn derive_parse_bin_struct<'a, T>(name: &syn::Ident, fields: T) -> TokenStream
|
||||
where T: IntoIterator<Item = &'a syn::Field>
|
||||
{
|
||||
let mut parsing_statements = Vec::new();
|
||||
let mut combining_expressions = Vec::new();
|
||||
|
||||
for field in fields {
|
||||
let field_name = field.ident.as_ref().unwrap();
|
||||
let field_type = &field.ty;
|
||||
let mut skip: Option<usize> = None;
|
||||
let mut veclen: Option<String> = None;
|
||||
|
||||
// look for attributes
|
||||
for at in &field.attrs {
|
||||
if let syn::Meta::NameValue(nv) = &at.meta {
|
||||
if nv.path.segments.len() == 1 {
|
||||
let attr_name = nv.path.segments[0].ident.to_string();
|
||||
if attr_name == "skip_bytes" {
|
||||
if let syn::Expr::Lit(expr) = &nv.value {
|
||||
if let syn::Lit::Int(nbytes) = &expr.lit {
|
||||
// println!("reserved = {}", nbytes);
|
||||
skip = nbytes.base10_parse::<usize>().ok()
|
||||
}
|
||||
}
|
||||
} else if attr_name == "len" {
|
||||
if let syn::Expr::Lit(expr) = &nv.value {
|
||||
if let syn::Lit::Str(litstr) = &expr.lit {
|
||||
// println!("len = {}", litstr.value());
|
||||
veclen = Some(litstr.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(offset) = skip {
|
||||
parsing_statements.push(quote!{
|
||||
__parse_bin_derive_size += #offset;
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(varname) = veclen {
|
||||
let field_name_item = format_ident!("{}_item", field_name);
|
||||
|
||||
let field_type_item: &syn::Type = match &field_type {
|
||||
syn::Type::Path(tp) => {
|
||||
match tp.path.segments.iter().next() {
|
||||
Some(single) => {
|
||||
if &single.ident.to_string() == "Vec" {
|
||||
match &single.arguments {
|
||||
syn::PathArguments::AngleBracketed(args) => {
|
||||
match args.args.iter().next() {
|
||||
Some(firstarg) => {
|
||||
match firstarg {
|
||||
syn::GenericArgument::Type(ty) => {
|
||||
Some(ty)
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
}.expect("The len attribute is only allowed on type Vec<_>");
|
||||
|
||||
let varname_ident = syn::Ident::new(&varname, Span::call_site());
|
||||
|
||||
parsing_statements.push(quote!{
|
||||
let mut #field_name = Vec::new();
|
||||
for i in 0 .. #varname_ident.0 as usize {
|
||||
let #field_name_item = <#field_type_item>::parse_len(&bytes[__parse_bin_derive_size..])?;
|
||||
__parse_bin_derive_size += #field_name_item.1;
|
||||
#field_name.push(#field_name_item.0);
|
||||
}
|
||||
});
|
||||
|
||||
combining_expressions.push(quote!(#field_name: #field_name));
|
||||
} else {
|
||||
parsing_statements.push(quote!{
|
||||
let #field_name = <#field_type>::parse_len(&bytes[__parse_bin_derive_size..])?;
|
||||
__parse_bin_derive_size += #field_name.1;
|
||||
});
|
||||
|
||||
combining_expressions.push(quote!(#field_name: #field_name.0));
|
||||
}
|
||||
}
|
||||
|
||||
quote! {
|
||||
impl ParseBin for #name {
|
||||
fn parse_len(bytes: &[u8]) -> Result<(Self, usize), ParseError> {
|
||||
let mut __parse_bin_derive_size: usize = 0;
|
||||
|
||||
#(#parsing_statements)*
|
||||
|
||||
let result = #name {
|
||||
#(#combining_expressions),*
|
||||
};
|
||||
|
||||
Ok((result, __parse_bin_derive_size))
|
||||
}
|
||||
}
|
||||
}.into()
|
||||
}
|
38
style.css
38
style.css
@ -10,9 +10,6 @@ table td {
|
||||
padding: 0.1em 0.2em;
|
||||
}
|
||||
|
||||
table tr:nth-child(even) {
|
||||
}
|
||||
|
||||
table th {
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #ccc;
|
||||
@ -42,23 +39,10 @@ table > tbody > tr.fold.open {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
/*
|
||||
table > tbody > tr.view td:first-child:before {
|
||||
color: #999;
|
||||
content: "x";
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
table > tbody > tr.view.open td:first-child:before {
|
||||
transform: rotate(-180deg);
|
||||
color: #333;
|
||||
}
|
||||
*/
|
||||
|
||||
div.nav {
|
||||
padding: 5px;
|
||||
background-color: #dde;
|
||||
border-radius: 5px;
|
||||
border-radius: 4px;
|
||||
margin: 5px 0;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
@ -69,10 +53,10 @@ a.nav {
|
||||
}
|
||||
|
||||
details.item {
|
||||
padding: 5px;
|
||||
padding: 3px;
|
||||
background-color: #dde;
|
||||
border-radius: 5px;
|
||||
margin: 5px 0;
|
||||
border-radius: 4px;
|
||||
margin: 3px 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@ -81,15 +65,15 @@ a {
|
||||
}
|
||||
|
||||
details.highlight {
|
||||
background-color: #abc;
|
||||
background-color: #bbc;
|
||||
}
|
||||
|
||||
details .details {
|
||||
color: white;
|
||||
background-color: #222;
|
||||
color: black;
|
||||
// background-color: #222;
|
||||
padding: 10px;
|
||||
margin-top: 5px;
|
||||
border-radius: 5px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
details .itemvalue {
|
||||
@ -103,7 +87,7 @@ details .itemvalue {
|
||||
details .key {
|
||||
color: white;
|
||||
background-color: #999;
|
||||
border-radius: 5px;
|
||||
border-radius: 4px;
|
||||
padding: 3px;
|
||||
margin: 1px 2px;
|
||||
display: inline-block;
|
||||
@ -155,11 +139,11 @@ span.key_type.root {
|
||||
}
|
||||
|
||||
.details td {
|
||||
border: 1px solid white;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.details td:first-child {
|
||||
border: 1px solid white;
|
||||
border: 1px solid black;
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user