Skip to content

Commit

Permalink
feat: implement derive macro for all access types
Browse files Browse the repository at this point in the history
Signed-off-by: Martin Kröning <[email protected]>
  • Loading branch information
mkroening committed Apr 26, 2024
1 parent a731e72 commit bd31299
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 19 deletions.
30 changes: 23 additions & 7 deletions volatile-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ mod volatile;
///
/// // A real device might have changed the value, though.
/// assert_eq!(volatile_ptr.feature().read(), 0);
///
/// // You can also use shared references.
/// let volatile_ptr = volatile_ref.as_ptr();
/// assert_eq!(volatile_ptr.feature_select().read(), 42);
/// // This does not compile, because `volatile_ptr` is `ReadOnly`.
/// // volatile_ptr.feature_select().write(42);
/// ```
///
/// # Details
Expand All @@ -65,21 +71,31 @@ mod volatile;
/// # feature_select: u32,
/// # feature: u32,
/// # }
/// use volatile::access::{ReadOnly, ReadWrite};
/// use volatile::access::{ReadOnly, ReadWrite, RestrictAccess};
/// use volatile::{map_field, VolatilePtr};
///
/// pub trait DeviceConfigVolatileFieldAccess<'a> {
/// fn feature_select(self) -> VolatilePtr<'a, u32, ReadWrite>;
/// pub trait DeviceConfigVolatileFieldAccess<'a, A> {
/// fn feature_select(self) -> VolatilePtr<'a, u32, A::Restricted>
/// where
/// A: RestrictAccess<ReadWrite>;
///
/// fn feature(self) -> VolatilePtr<'a, u32, ReadOnly>;
/// fn feature(self) -> VolatilePtr<'a, u32, A::Restricted>
/// where
/// A: RestrictAccess<ReadOnly>;
/// }
///
/// impl<'a> DeviceConfigVolatileFieldAccess<'a> for VolatilePtr<'a, DeviceConfig, ReadWrite> {
/// fn feature_select(self) -> VolatilePtr<'a, u32, ReadWrite> {
/// impl<'a, A> DeviceConfigVolatileFieldAccess<'a, A> for VolatilePtr<'a, DeviceConfig, A> {
/// fn feature_select(self) -> VolatilePtr<'a, u32, A::Restricted>
/// where
/// A: RestrictAccess<ReadWrite>
/// {
/// map_field!(self.feature_select).restrict()
/// }
///
/// fn feature(self) -> VolatilePtr<'a, u32, ReadOnly> {
/// fn feature(self) -> VolatilePtr<'a, u32, A::Restricted>
/// where
/// A: RestrictAccess<ReadOnly>
/// {
/// map_field!(self.feature).restrict()
/// }
/// }
Expand Down
37 changes: 25 additions & 12 deletions volatile-macro/src/volatile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ fn parse_input(input: &ItemStruct) -> Result<ParsedInput> {
}

let sig = parse_quote! {
fn #ident(self) -> ::volatile::VolatilePtr<'a, #ty, #access>
fn #ident(self) -> ::volatile::VolatilePtr<'a, #ty, A::Restricted>
where
A: ::volatile::access::RestrictAccess<#access>
};
sigs.push(sig);
}
Expand Down Expand Up @@ -112,7 +114,7 @@ fn emit_trait(
parse_quote! {
#(#attrs)*
#[allow(non_camel_case_types)]
#vis trait #trait_ident <'a> {
#vis trait #trait_ident <'a, A> {
#(
#(#method_attrs)*
#sigs;
Expand All @@ -133,9 +135,10 @@ fn emit_impl(

parse_quote! {
#[automatically_derived]
impl<'a> #trait_ident<'a> for ::volatile::VolatilePtr<'a, #struct_ident, ::volatile::access::ReadWrite> {
impl<'a, A> #trait_ident<'a, A> for ::volatile::VolatilePtr<'a, #struct_ident, A> {
#(
#sigs {
#sigs,
{
::volatile::map_field!(self.#fields).restrict()
}
)*
Expand Down Expand Up @@ -183,24 +186,34 @@ mod tests {
///
/// This is a wonderful struct.
#[allow(non_camel_case_types)]
pub trait DeviceConfigVolatileFieldAccess<'a> {
fn feature_select(self) -> ::volatile::VolatilePtr<'a, u32, ::volatile::access::ReadWrite>;
pub trait DeviceConfigVolatileFieldAccess<'a, A> {
fn feature_select(self) -> ::volatile::VolatilePtr<'a, u32, A::Restricted>
where
A: ::volatile::access::RestrictAccess<::volatile::access::ReadWrite>;

/// Feature.
///
/// This is a good field.
fn feature(self) -> ::volatile::VolatilePtr<'a, u32, ReadOnly>;
fn feature(self) -> ::volatile::VolatilePtr<'a, u32, A::Restricted>
where
A: ::volatile::access::RestrictAccess<ReadOnly>;
}
};

let expected_impl = quote! {
#[automatically_derived]
impl<'a> DeviceConfigVolatileFieldAccess<'a> for ::volatile::VolatilePtr<'a, DeviceConfig, ::volatile::access::ReadWrite> {
fn feature_select(self) -> ::volatile::VolatilePtr<'a, u32, ::volatile::access::ReadWrite> {
impl<'a, A> DeviceConfigVolatileFieldAccess<'a, A> for ::volatile::VolatilePtr<'a, DeviceConfig, A> {
fn feature_select(self) -> ::volatile::VolatilePtr<'a, u32, A::Restricted>
where
A: ::volatile::access::RestrictAccess<::volatile::access::ReadWrite>,
{
::volatile::map_field!(self.feature_select).restrict()
}

fn feature(self) -> ::volatile::VolatilePtr<'a, u32, ReadOnly> {
fn feature(self) -> ::volatile::VolatilePtr<'a, u32, A::Restricted>
where
A: ::volatile::access::RestrictAccess<ReadOnly>,
{
::volatile::map_field!(self.feature).restrict()
}
}
Expand Down Expand Up @@ -230,12 +243,12 @@ mod tests {

let expected_trait = quote! {
#[allow(non_camel_case_types)]
pub trait DeviceConfigVolatileFieldAccess<'a> {}
pub trait DeviceConfigVolatileFieldAccess<'a, A> {}
};

let expected_impl = quote! {
#[automatically_derived]
impl<'a> DeviceConfigVolatileFieldAccess<'a> for ::volatile::VolatilePtr<'a, DeviceConfig, ::volatile::access::ReadWrite> {}
impl<'a, A> DeviceConfigVolatileFieldAccess<'a, A> for ::volatile::VolatilePtr<'a, DeviceConfig, A> {}
};

assert_eq!(
Expand Down

0 comments on commit bd31299

Please sign in to comment.