combine crates to workspace

This commit is contained in:
Florian Stecker committed 2024-02-28 00:57:20 -05:00
1 parent e853f8bc46
commit bc852d6b6a
18 files changed
+243 -42

No files matched your search

+7 -9
View File
@@ -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
View 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"
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+12
View 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
View 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
View 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()
}
+11 -27
View File
@@ -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;
}