nak,compiler: Move AsSlice to common code
Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30443>
This commit is contained in:
committed by
Marge Bot
parent
3ca448a549
commit
ab72be6c5e
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright © 2024 Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
use std::ops::Index;
|
||||||
|
|
||||||
|
pub enum AttrList<T: 'static> {
|
||||||
|
Array(&'static [T]),
|
||||||
|
Uniform(T),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: 'static> Index<usize> for AttrList<T> {
|
||||||
|
type Output = T;
|
||||||
|
|
||||||
|
fn index(&self, idx: usize) -> &T {
|
||||||
|
match self {
|
||||||
|
AttrList::Array(arr) => &arr[idx],
|
||||||
|
AttrList::Uniform(typ) => typ,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait AsSlice<T> {
|
||||||
|
type Attr;
|
||||||
|
|
||||||
|
fn as_slice(&self) -> &[T];
|
||||||
|
fn as_mut_slice(&mut self) -> &mut [T];
|
||||||
|
fn attrs(&self) -> AttrList<Self::Attr>;
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright © 2024 Igalia S.L.
|
// Copyright © 2024 Igalia S.L.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
pub mod as_slice;
|
||||||
pub mod bindings;
|
pub mod bindings;
|
||||||
pub mod bitset;
|
pub mod bitset;
|
||||||
pub mod cfg;
|
pub mod cfg;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
_compiler_rs_sources = [
|
_compiler_rs_sources = [
|
||||||
|
'as_slice.rs',
|
||||||
'bitset.rs',
|
'bitset.rs',
|
||||||
'cfg.rs',
|
'cfg.rs',
|
||||||
'nir.rs',
|
'nir.rs',
|
||||||
@@ -94,3 +95,21 @@ _libcompiler_rs = static_library(
|
|||||||
idep_compiler_rs = declare_dependency(
|
idep_compiler_rs = declare_dependency(
|
||||||
link_with : _libcompiler_rs,
|
link_with : _libcompiler_rs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
dep_syn = dependency('syn',
|
||||||
|
version : '>= 2.0.15',
|
||||||
|
fallback : ['syn', 'dep_syn'],
|
||||||
|
required : true,
|
||||||
|
)
|
||||||
|
|
||||||
|
_libcompiler_proc_rs = static_library(
|
||||||
|
'compiler_proc',
|
||||||
|
'proc/lib.rs',
|
||||||
|
gnu_symbol_visibility : 'hidden',
|
||||||
|
dependencies : [dep_syn],
|
||||||
|
rust_abi : 'rust',
|
||||||
|
)
|
||||||
|
|
||||||
|
idep_compiler_proc_rs = declare_dependency(
|
||||||
|
link_with : _libcompiler_proc_rs,
|
||||||
|
)
|
||||||
|
|||||||
@@ -0,0 +1,220 @@
|
|||||||
|
// Copyright © 2023 Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
use proc_macro2::{Span, TokenStream as TokenStream2};
|
||||||
|
use syn::*;
|
||||||
|
|
||||||
|
fn expr_as_usize(expr: &syn::Expr) -> usize {
|
||||||
|
let lit = match expr {
|
||||||
|
syn::Expr::Lit(lit) => lit,
|
||||||
|
_ => panic!("Expected a literal, found an expression"),
|
||||||
|
};
|
||||||
|
let lit_int = match &lit.lit {
|
||||||
|
syn::Lit::Int(i) => i,
|
||||||
|
_ => panic!("Expected a literal integer"),
|
||||||
|
};
|
||||||
|
assert!(lit.attrs.is_empty());
|
||||||
|
lit_int
|
||||||
|
.base10_parse()
|
||||||
|
.expect("Failed to parse integer literal")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count_type(ty: &Type, slice_type: &str) -> usize {
|
||||||
|
match ty {
|
||||||
|
syn::Type::Array(a) => {
|
||||||
|
let elems = count_type(a.elem.as_ref(), slice_type);
|
||||||
|
if elems > 0 {
|
||||||
|
elems * expr_as_usize(&a.len)
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
syn::Type::Path(p) => {
|
||||||
|
if p.qself.is_none() && p.path.is_ident(slice_type) {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_attr(field: &Field, attr_name: &str) -> Option<String> {
|
||||||
|
for attr in &field.attrs {
|
||||||
|
if let Meta::List(ml) = &attr.meta {
|
||||||
|
if ml.path.is_ident(attr_name) {
|
||||||
|
return Some(format!("{}", ml.tokens));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn derive_as_slice(
|
||||||
|
input: TokenStream,
|
||||||
|
slice_type: &str,
|
||||||
|
attr_name: &str,
|
||||||
|
attr_type: &str,
|
||||||
|
) -> TokenStream {
|
||||||
|
let DeriveInput {
|
||||||
|
attrs, ident, data, ..
|
||||||
|
} = parse_macro_input!(input);
|
||||||
|
|
||||||
|
match data {
|
||||||
|
Data::Struct(s) => {
|
||||||
|
let mut has_repr_c = false;
|
||||||
|
for attr in attrs {
|
||||||
|
match attr.meta {
|
||||||
|
Meta::List(ml) => {
|
||||||
|
if ml.path.is_ident("repr")
|
||||||
|
&& format!("{}", ml.tokens) == "C"
|
||||||
|
{
|
||||||
|
has_repr_c = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert!(has_repr_c, "Struct must be declared #[repr(C)]");
|
||||||
|
|
||||||
|
let mut first = None;
|
||||||
|
let mut count = 0_usize;
|
||||||
|
let mut found_last = false;
|
||||||
|
let mut attrs = TokenStream2::new();
|
||||||
|
|
||||||
|
if let Fields::Named(named) = s.fields {
|
||||||
|
for f in named.named {
|
||||||
|
let f_count = count_type(&f.ty, slice_type);
|
||||||
|
let f_attr = get_attr(&f, &attr_name);
|
||||||
|
|
||||||
|
if f_count > 0 {
|
||||||
|
assert!(
|
||||||
|
!found_last,
|
||||||
|
"All fields of type {slice_type} must be consecutive",
|
||||||
|
);
|
||||||
|
|
||||||
|
let attr_type =
|
||||||
|
Ident::new(attr_type, Span::call_site());
|
||||||
|
let f_attr = if let Some(s) = f_attr {
|
||||||
|
let s = syn::parse_str::<Ident>(&s).unwrap();
|
||||||
|
quote! { #attr_type::#s, }
|
||||||
|
} else {
|
||||||
|
quote! { #attr_type::DEFAULT, }
|
||||||
|
};
|
||||||
|
|
||||||
|
first.get_or_insert(f.ident);
|
||||||
|
for _ in 0..f_count {
|
||||||
|
attrs.extend(f_attr.clone());
|
||||||
|
}
|
||||||
|
count += f_count;
|
||||||
|
} else {
|
||||||
|
assert!(
|
||||||
|
f_attr.is_none(),
|
||||||
|
"{attr_name} attribute is only allowed on {slice_type}"
|
||||||
|
);
|
||||||
|
if !first.is_none() {
|
||||||
|
found_last = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("Fields are not named");
|
||||||
|
}
|
||||||
|
|
||||||
|
let slice_type = Ident::new(slice_type, Span::call_site());
|
||||||
|
let attr_type = Ident::new(attr_type, Span::call_site());
|
||||||
|
if let Some(first) = first {
|
||||||
|
quote! {
|
||||||
|
impl compiler::as_slice::AsSlice<#slice_type> for #ident {
|
||||||
|
type Attr = #attr_type;
|
||||||
|
|
||||||
|
fn as_slice(&self) -> &[#slice_type] {
|
||||||
|
unsafe {
|
||||||
|
let first = &self.#first as *const #slice_type;
|
||||||
|
std::slice::from_raw_parts(first, #count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_mut_slice(&mut self) -> &mut [#slice_type] {
|
||||||
|
unsafe {
|
||||||
|
let first =
|
||||||
|
&mut self.#first as *mut #slice_type;
|
||||||
|
std::slice::from_raw_parts_mut(first, #count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn attrs(&self) -> AttrList<Self::Attr> {
|
||||||
|
static ATTRS: [#attr_type; #count] = [#attrs];
|
||||||
|
AttrList::Array(&ATTRS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
impl compiler::as_slice::AsSlice<#slice_type> for #ident {
|
||||||
|
type Attr = #attr_type;
|
||||||
|
|
||||||
|
fn as_slice(&self) -> &[#slice_type] {
|
||||||
|
&[]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_mut_slice(&mut self) -> &mut [#slice_type] {
|
||||||
|
&mut []
|
||||||
|
}
|
||||||
|
|
||||||
|
fn attrs(&self) -> AttrList<Self::Attr> {
|
||||||
|
AttrList::Uniform(#attr_type::DEFAULT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
Data::Enum(e) => {
|
||||||
|
let mut as_slice_cases = TokenStream2::new();
|
||||||
|
let mut as_mut_slice_cases = TokenStream2::new();
|
||||||
|
let mut types_cases = TokenStream2::new();
|
||||||
|
let slice_type = Ident::new(slice_type, Span::call_site());
|
||||||
|
let attr_type = Ident::new(attr_type, Span::call_site());
|
||||||
|
for v in e.variants {
|
||||||
|
let case = v.ident;
|
||||||
|
as_slice_cases.extend(quote! {
|
||||||
|
#ident::#case(x) => compiler::as_slice::AsSlice::<#slice_type>::as_slice(x),
|
||||||
|
});
|
||||||
|
as_mut_slice_cases.extend(quote! {
|
||||||
|
#ident::#case(x) => compiler::as_slice::AsSlice::<#slice_type>::as_mut_slice(x),
|
||||||
|
});
|
||||||
|
types_cases.extend(quote! {
|
||||||
|
#ident::#case(x) => compiler::as_slice::AsSlice::<#slice_type>::attrs(x),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
quote! {
|
||||||
|
impl compiler::as_slice::AsSlice<#slice_type> for #ident {
|
||||||
|
type Attr = #attr_type;
|
||||||
|
|
||||||
|
fn as_slice(&self) -> &[#slice_type] {
|
||||||
|
match self {
|
||||||
|
#as_slice_cases
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_mut_slice(&mut self) -> &mut [#slice_type] {
|
||||||
|
match self {
|
||||||
|
#as_mut_slice_cases
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn attrs(&self) -> AttrList<Self::Attr> {
|
||||||
|
match self {
|
||||||
|
#types_cases
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
_ => panic!("Not a struct type"),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// Copyright © 2024 Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
extern crate proc_macro;
|
||||||
|
extern crate proc_macro2;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate quote;
|
||||||
|
extern crate syn;
|
||||||
|
|
||||||
|
pub mod as_slice;
|
||||||
@@ -16,12 +16,6 @@ nak_rust_args = [
|
|||||||
'-Anon_snake_case',
|
'-Anon_snake_case',
|
||||||
]
|
]
|
||||||
|
|
||||||
dep_syn = dependency('syn',
|
|
||||||
version : '>= 2.0.15',
|
|
||||||
fallback : ['syn', 'dep_syn'],
|
|
||||||
required : true,
|
|
||||||
)
|
|
||||||
|
|
||||||
dep_paste = dependency('paste',
|
dep_paste = dependency('paste',
|
||||||
version : '>= 1.0.14',
|
version : '>= 1.0.14',
|
||||||
fallback : ['paste', 'dep_paste'],
|
fallback : ['paste', 'dep_paste'],
|
||||||
@@ -114,7 +108,7 @@ _libnak_bindings_rs = static_library(
|
|||||||
_libnak_ir_proc_rs = rust.proc_macro(
|
_libnak_ir_proc_rs = rust.proc_macro(
|
||||||
'nak_ir_proc',
|
'nak_ir_proc',
|
||||||
files('nak/ir_proc.rs'),
|
files('nak/ir_proc.rs'),
|
||||||
dependencies : [dep_syn],
|
dependencies : [idep_compiler_proc_rs],
|
||||||
)
|
)
|
||||||
|
|
||||||
_libnak_rs = static_library(
|
_libnak_rs = static_library(
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use nak_bindings::*;
|
|||||||
pub use crate::builder::{Builder, InstrBuilder, SSABuilder, SSAInstrBuilder};
|
pub use crate::builder::{Builder, InstrBuilder, SSABuilder, SSAInstrBuilder};
|
||||||
use crate::legalize::LegalizeBuilder;
|
use crate::legalize::LegalizeBuilder;
|
||||||
use crate::sph::{OutputTopology, PixelImap};
|
use crate::sph::{OutputTopology, PixelImap};
|
||||||
|
use compiler::as_slice::*;
|
||||||
use compiler::cfg::CFG;
|
use compiler::cfg::CFG;
|
||||||
use nak_ir_proc::*;
|
use nak_ir_proc::*;
|
||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
@@ -1398,30 +1399,6 @@ impl fmt::Display for Src {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum AttrList<T: 'static> {
|
|
||||||
Array(&'static [T]),
|
|
||||||
Uniform(T),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: 'static> Index<usize> for AttrList<T> {
|
|
||||||
type Output = T;
|
|
||||||
|
|
||||||
fn index(&self, idx: usize) -> &T {
|
|
||||||
match self {
|
|
||||||
AttrList::Array(arr) => &arr[idx],
|
|
||||||
AttrList::Uniform(typ) => typ,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait AsSlice<T> {
|
|
||||||
type Attr;
|
|
||||||
|
|
||||||
fn as_slice(&self) -> &[T];
|
|
||||||
fn as_mut_slice(&mut self) -> &mut [T];
|
|
||||||
fn attrs(&self) -> AttrList<Self::Attr>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
pub enum SrcType {
|
pub enum SrcType {
|
||||||
|
|||||||
@@ -7,224 +7,11 @@ extern crate proc_macro2;
|
|||||||
extern crate quote;
|
extern crate quote;
|
||||||
extern crate syn;
|
extern crate syn;
|
||||||
|
|
||||||
|
use compiler_proc::as_slice::*;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::{Span, TokenStream as TokenStream2};
|
use proc_macro2::{TokenStream as TokenStream2};
|
||||||
use syn::*;
|
use syn::*;
|
||||||
|
|
||||||
fn expr_as_usize(expr: &syn::Expr) -> usize {
|
|
||||||
let lit = match expr {
|
|
||||||
syn::Expr::Lit(lit) => lit,
|
|
||||||
_ => panic!("Expected a literal, found an expression"),
|
|
||||||
};
|
|
||||||
let lit_int = match &lit.lit {
|
|
||||||
syn::Lit::Int(i) => i,
|
|
||||||
_ => panic!("Expected a literal integer"),
|
|
||||||
};
|
|
||||||
assert!(lit.attrs.is_empty());
|
|
||||||
lit_int
|
|
||||||
.base10_parse()
|
|
||||||
.expect("Failed to parse integer literal")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn count_type(ty: &Type, slice_type: &str) -> usize {
|
|
||||||
match ty {
|
|
||||||
syn::Type::Array(a) => {
|
|
||||||
let elems = count_type(a.elem.as_ref(), slice_type);
|
|
||||||
if elems > 0 {
|
|
||||||
elems * expr_as_usize(&a.len)
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
syn::Type::Path(p) => {
|
|
||||||
if p.qself.is_none() && p.path.is_ident(slice_type) {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_attr(field: &Field, attr_name: &str) -> Option<String> {
|
|
||||||
for attr in &field.attrs {
|
|
||||||
if let Meta::List(ml) = &attr.meta {
|
|
||||||
if ml.path.is_ident(attr_name) {
|
|
||||||
return Some(format!("{}", ml.tokens));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn derive_as_slice(
|
|
||||||
input: TokenStream,
|
|
||||||
slice_type: &str,
|
|
||||||
attr_name: &str,
|
|
||||||
attr_type: &str,
|
|
||||||
) -> TokenStream {
|
|
||||||
let DeriveInput {
|
|
||||||
attrs, ident, data, ..
|
|
||||||
} = parse_macro_input!(input);
|
|
||||||
|
|
||||||
match data {
|
|
||||||
Data::Struct(s) => {
|
|
||||||
let mut has_repr_c = false;
|
|
||||||
for attr in attrs {
|
|
||||||
match attr.meta {
|
|
||||||
Meta::List(ml) => {
|
|
||||||
if ml.path.is_ident("repr")
|
|
||||||
&& format!("{}", ml.tokens) == "C"
|
|
||||||
{
|
|
||||||
has_repr_c = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert!(has_repr_c, "Struct must be declared #[repr(C)]");
|
|
||||||
|
|
||||||
let mut first = None;
|
|
||||||
let mut count = 0_usize;
|
|
||||||
let mut found_last = false;
|
|
||||||
let mut attrs = TokenStream2::new();
|
|
||||||
|
|
||||||
if let Fields::Named(named) = s.fields {
|
|
||||||
for f in named.named {
|
|
||||||
let f_count = count_type(&f.ty, slice_type);
|
|
||||||
let f_attr = get_attr(&f, &attr_name);
|
|
||||||
|
|
||||||
if f_count > 0 {
|
|
||||||
assert!(
|
|
||||||
!found_last,
|
|
||||||
"All fields of type {slice_type} must be consecutive",
|
|
||||||
);
|
|
||||||
|
|
||||||
let attr_type =
|
|
||||||
Ident::new(attr_type, Span::call_site());
|
|
||||||
let f_attr = if let Some(s) = f_attr {
|
|
||||||
let s = syn::parse_str::<Ident>(&s).unwrap();
|
|
||||||
quote! { #attr_type::#s, }
|
|
||||||
} else {
|
|
||||||
quote! { #attr_type::DEFAULT, }
|
|
||||||
};
|
|
||||||
|
|
||||||
first.get_or_insert(f.ident);
|
|
||||||
for _ in 0..f_count {
|
|
||||||
attrs.extend(f_attr.clone());
|
|
||||||
}
|
|
||||||
count += f_count;
|
|
||||||
} else {
|
|
||||||
assert!(
|
|
||||||
f_attr.is_none(),
|
|
||||||
"{attr_name} attribute is only allowed on {slice_type}"
|
|
||||||
);
|
|
||||||
if !first.is_none() {
|
|
||||||
found_last = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic!("Fields are not named");
|
|
||||||
}
|
|
||||||
|
|
||||||
let slice_type = Ident::new(slice_type, Span::call_site());
|
|
||||||
let attr_type = Ident::new(attr_type, Span::call_site());
|
|
||||||
if let Some(first) = first {
|
|
||||||
quote! {
|
|
||||||
impl AsSlice<#slice_type> for #ident {
|
|
||||||
type Attr = #attr_type;
|
|
||||||
|
|
||||||
fn as_slice(&self) -> &[#slice_type] {
|
|
||||||
unsafe {
|
|
||||||
let first = &self.#first as *const #slice_type;
|
|
||||||
std::slice::from_raw_parts(first, #count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_mut_slice(&mut self) -> &mut [#slice_type] {
|
|
||||||
unsafe {
|
|
||||||
let first =
|
|
||||||
&mut self.#first as *mut #slice_type;
|
|
||||||
std::slice::from_raw_parts_mut(first, #count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn attrs(&self) -> AttrList<Self::Attr> {
|
|
||||||
static ATTRS: [#attr_type; #count] = [#attrs];
|
|
||||||
AttrList::Array(&ATTRS)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
quote! {
|
|
||||||
impl AsSlice<#slice_type> for #ident {
|
|
||||||
type Attr = #attr_type;
|
|
||||||
|
|
||||||
fn as_slice(&self) -> &[#slice_type] {
|
|
||||||
&[]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_mut_slice(&mut self) -> &mut [#slice_type] {
|
|
||||||
&mut []
|
|
||||||
}
|
|
||||||
|
|
||||||
fn attrs(&self) -> AttrList<Self::Attr> {
|
|
||||||
AttrList::Uniform(#attr_type::DEFAULT)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
Data::Enum(e) => {
|
|
||||||
let mut as_slice_cases = TokenStream2::new();
|
|
||||||
let mut as_mut_slice_cases = TokenStream2::new();
|
|
||||||
let mut types_cases = TokenStream2::new();
|
|
||||||
let slice_type = Ident::new(slice_type, Span::call_site());
|
|
||||||
let attr_type = Ident::new(attr_type, Span::call_site());
|
|
||||||
for v in e.variants {
|
|
||||||
let case = v.ident;
|
|
||||||
as_slice_cases.extend(quote! {
|
|
||||||
#ident::#case(x) => AsSlice::<#slice_type>::as_slice(x),
|
|
||||||
});
|
|
||||||
as_mut_slice_cases.extend(quote! {
|
|
||||||
#ident::#case(x) => AsSlice::<#slice_type>::as_mut_slice(x),
|
|
||||||
});
|
|
||||||
types_cases.extend(quote! {
|
|
||||||
#ident::#case(x) => AsSlice::<#slice_type>::attrs(x),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
quote! {
|
|
||||||
impl AsSlice<#slice_type> for #ident {
|
|
||||||
type Attr = #attr_type;
|
|
||||||
|
|
||||||
fn as_slice(&self) -> &[#slice_type] {
|
|
||||||
match self {
|
|
||||||
#as_slice_cases
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_mut_slice(&mut self) -> &mut [#slice_type] {
|
|
||||||
match self {
|
|
||||||
#as_mut_slice_cases
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn attrs(&self) -> AttrList<Self::Attr> {
|
|
||||||
match self {
|
|
||||||
#types_cases
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
_ => panic!("Not a struct type"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[proc_macro_derive(SrcsAsSlice, attributes(src_type))]
|
#[proc_macro_derive(SrcsAsSlice, attributes(src_type))]
|
||||||
pub fn derive_srcs_as_slice(input: TokenStream) -> TokenStream {
|
pub fn derive_srcs_as_slice(input: TokenStream) -> TokenStream {
|
||||||
derive_as_slice(input, "Src", "src_type", "SrcType")
|
derive_as_slice(input, "Src", "src_type", "SrcType")
|
||||||
|
|||||||
Reference in New Issue
Block a user