vfs: auto-implement Vnode using macros
This commit is contained in:
parent
058bfddd58
commit
901f311856
@ -7,4 +7,5 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" }
|
||||
macros = { path = "macros" }
|
||||
bitflags = "2.3.3"
|
||||
|
16
lib/vfs/macros/Cargo.toml
Normal file
16
lib/vfs/macros/Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "macros"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
lazy_static = "1.4.0"
|
||||
proc-macro-crate = "1.3.1"
|
||||
proc-macro2 = "1.0.66"
|
||||
quote = "1.0.31"
|
||||
syn = { version = "2.0.26", features = ["full"] }
|
53
lib/vfs/macros/src/lib.rs
Normal file
53
lib/vfs/macros/src/lib.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::Ident;
|
||||
use proc_macro_crate::{crate_name, FoundCrate};
|
||||
use quote::{quote, ToTokens};
|
||||
use syn::{parse_macro_input, ImplItem, ItemImpl};
|
||||
|
||||
mod vnode_impl;
|
||||
use vnode_impl::IMPLS;
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn auto_vnode_impl(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let current_crate = crate_name("vfs").unwrap();
|
||||
|
||||
let vfs_crate = match current_crate {
|
||||
FoundCrate::Itself => quote!(crate),
|
||||
FoundCrate::Name(name) => quote!( #name ),
|
||||
};
|
||||
let mut impl_item = parse_macro_input!(input as ItemImpl);
|
||||
let behavior = if attr.is_empty() {
|
||||
"unimplemented".to_string()
|
||||
} else {
|
||||
parse_macro_input!(attr as Ident).to_string()
|
||||
};
|
||||
let behavior = match behavior.as_str() {
|
||||
"unimplemented" => quote! { unimplemented!() },
|
||||
"panic" => quote! { panic!() },
|
||||
"error" => quote! { Err(yggdrasil_abi::error::Error::NotImplemented) },
|
||||
_ => panic!("Unknown #[auto_vnode_impl] behavior: {:?}", behavior),
|
||||
};
|
||||
|
||||
let mut missing_impls: HashSet<&str> = HashSet::from_iter(IMPLS.keys().copied());
|
||||
|
||||
for item in &impl_item.items {
|
||||
match item {
|
||||
ImplItem::Fn(f) => {
|
||||
let name = &f.sig.ident.to_string();
|
||||
missing_impls.remove(name.as_str());
|
||||
}
|
||||
_ => panic!("Unexpected item in Vnode impl"),
|
||||
}
|
||||
}
|
||||
|
||||
for &item in &missing_impls {
|
||||
let f = IMPLS.get(item).unwrap();
|
||||
let fn_impl = f(&vfs_crate, &behavior);
|
||||
|
||||
impl_item.items.push(ImplItem::Verbatim(fn_impl));
|
||||
}
|
||||
|
||||
impl_item.to_token_stream().into()
|
||||
}
|
60
lib/vfs/macros/src/vnode_impl.rs
Normal file
60
lib/vfs/macros/src/vnode_impl.rs
Normal file
@ -0,0 +1,60 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use proc_macro2::TokenStream as TS2;
|
||||
use quote::quote;
|
||||
|
||||
fn impl_open(vfs: &TS2, behavior: &TS2) -> TS2 {
|
||||
quote! {
|
||||
fn open(&mut self, _node: &#vfs::VnodeRef, _opts: yggdrasil_abi::io::OpenFlags)
|
||||
-> Result<usize, yggdrasil_abi::error::Error> {
|
||||
#behavior
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_close(vfs: &TS2, behavior: &TS2) -> TS2 {
|
||||
quote! {
|
||||
fn close(&mut self, _node: &#vfs::VnodeRef) -> Result<(), Error> {
|
||||
#behavior
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_create(vfs: &TS2, behavior: &TS2) -> TS2 {
|
||||
quote! {
|
||||
fn create(&mut self, _at: &#vfs::VnodeRef, _name: &str, _kind: #vfs::VnodeKind)
|
||||
-> Result<#vfs::VnodeRef, yggdrasil_abi::error::Error> {
|
||||
#behavior
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_write(vfs: &TS2, behavior: &TS2) -> TS2 {
|
||||
quote! {
|
||||
fn write(&mut self, _node: &#vfs::VnodeRef, _pos: usize, _data: &[u8])
|
||||
-> Result<usize, yggdrasil_abi::error::Error> {
|
||||
#behavior
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_read(vfs: &TS2, behavior: &TS2) -> TS2 {
|
||||
quote! {
|
||||
fn read(&mut self, _node: &#vfs::VnodeRef, _pos: usize, _data: &mut [u8])
|
||||
-> Result<usize, yggdrasil_abi::error::Error> {
|
||||
#behavior
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref IMPLS: HashMap<&'static str, fn(&TS2, &TS2) -> TS2> = {
|
||||
let mut m = HashMap::new();
|
||||
m.insert("open".into(), impl_open as _);
|
||||
m.insert("close".into(), impl_close as _);
|
||||
m.insert("create".into(), impl_create as _);
|
||||
m.insert("write".into(), impl_write as _);
|
||||
m.insert("read".into(), impl_read as _);
|
||||
m
|
||||
};
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
use yggdrasil_abi::error::Error;
|
||||
use macros::auto_vnode_impl;
|
||||
use yggdrasil_abi::{error::Error, io::OpenFlags};
|
||||
|
||||
use crate::node::{VnodeImpl, VnodeRef};
|
||||
use crate::{node::VnodeImpl, VnodeRef};
|
||||
|
||||
pub trait CharDevice {
|
||||
fn read(&'static self, blocking: bool, data: &mut [u8]) -> Result<usize, Error>;
|
||||
@ -17,12 +18,9 @@ impl CharDeviceWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
#[auto_vnode_impl(error)]
|
||||
impl VnodeImpl for CharDeviceWrapper {
|
||||
fn open(
|
||||
&mut self,
|
||||
_node: &VnodeRef,
|
||||
_opts: yggdrasil_abi::io::OpenFlags,
|
||||
) -> Result<usize, Error> {
|
||||
fn open(&mut self, _node: &VnodeRef, _opts: OpenFlags) -> Result<usize, Error> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
@ -37,13 +35,4 @@ impl VnodeImpl for CharDeviceWrapper {
|
||||
fn write(&mut self, _node: &VnodeRef, _pos: usize, data: &[u8]) -> Result<usize, Error> {
|
||||
self.device.write(true, data)
|
||||
}
|
||||
|
||||
fn create(
|
||||
&mut self,
|
||||
_at: &VnodeRef,
|
||||
_name: &str,
|
||||
_kind: crate::node::VnodeKind,
|
||||
) -> Result<VnodeRef, Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use core::time::Duration;
|
||||
use abi::{
|
||||
error::{Error, IntoSyscallResult},
|
||||
io::{OpenFlags, RawFd},
|
||||
SyscallFunction,
|
||||
syscall::SyscallFunction,
|
||||
};
|
||||
use vfs::{Read, Write};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user