summaryrefslogtreecommitdiffstats
path: root/third_party/rust/scroll_derive/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/scroll_derive/src
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/scroll_derive/src')
-rw-r--r--third_party/rust/scroll_derive/src/lib.rs332
1 files changed, 332 insertions, 0 deletions
diff --git a/third_party/rust/scroll_derive/src/lib.rs b/third_party/rust/scroll_derive/src/lib.rs
new file mode 100644
index 0000000000..24a08fd26c
--- /dev/null
+++ b/third_party/rust/scroll_derive/src/lib.rs
@@ -0,0 +1,332 @@
+#![recursion_limit="1024"]
+
+extern crate proc_macro;
+use proc_macro2;
+use quote::quote;
+
+use proc_macro::TokenStream;
+
+fn impl_struct(name: &syn::Ident, fields: &syn::FieldsNamed) -> proc_macro2::TokenStream {
+ let items: Vec<_> = fields.named.iter().map(|f| {
+ let ident = &f.ident;
+ let ty = &f.ty;
+ match *ty {
+ syn::Type::Array(ref array) => {
+ match array.len {
+ syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Int(ref int), ..}) => {
+ let size = int.base10_parse::<usize>().unwrap();
+ quote! {
+ #ident: { let mut __tmp: #ty = [0; #size]; src.gread_inout_with(offset, &mut __tmp, ctx)?; __tmp }
+ }
+ },
+ _ => panic!("Pread derive with bad array constexpr")
+ }
+ },
+ _ => {
+ quote! {
+ #ident: src.gread_with::<#ty>(offset, ctx)?
+ }
+ }
+ }
+ }).collect();
+
+ quote! {
+ impl<'a> ::scroll::ctx::TryFromCtx<'a, ::scroll::Endian> for #name where #name: 'a {
+ type Error = ::scroll::Error;
+ #[inline]
+ fn try_from_ctx(src: &'a [u8], ctx: ::scroll::Endian) -> ::scroll::export::result::Result<(Self, usize), Self::Error> {
+ use ::scroll::Pread;
+ let offset = &mut 0;
+ let data = #name { #(#items,)* };
+ Ok((data, *offset))
+ }
+ }
+ }
+}
+
+fn impl_try_from_ctx(ast: &syn::DeriveInput) -> proc_macro2::TokenStream {
+ let name = &ast.ident;
+ match ast.data {
+ syn::Data::Struct(ref data) => {
+ match data.fields {
+ syn::Fields::Named(ref fields) => {
+ impl_struct(name, fields)
+ },
+ _ => {
+ panic!("Pread can only be derived for a regular struct with public fields")
+ }
+ }
+ },
+ _ => panic!("Pread can only be derived for structs")
+ }
+}
+
+#[proc_macro_derive(Pread)]
+pub fn derive_pread(input: TokenStream) -> TokenStream {
+ let ast: syn::DeriveInput = syn::parse(input).unwrap();
+ let gen = impl_try_from_ctx(&ast);
+ gen.into()
+}
+
+fn impl_try_into_ctx(name: &syn::Ident, fields: &syn::FieldsNamed) -> proc_macro2::TokenStream {
+ let items: Vec<_> = fields.named.iter().map(|f| {
+ let ident = &f.ident;
+ let ty = &f.ty;
+ match *ty {
+ syn::Type::Array(_) => {
+ quote! {
+ for i in 0..self.#ident.len() {
+ dst.gwrite_with(&self.#ident[i], offset, ctx)?;
+ }
+ }
+ },
+ _ => {
+ quote! {
+ dst.gwrite_with(&self.#ident, offset, ctx)?
+ }
+ }
+ }
+ }).collect();
+
+ quote! {
+ impl<'a> ::scroll::ctx::TryIntoCtx<::scroll::Endian> for &'a #name {
+ type Error = ::scroll::Error;
+ #[inline]
+ fn try_into_ctx(self, dst: &mut [u8], ctx: ::scroll::Endian) -> ::scroll::export::result::Result<usize, Self::Error> {
+ use ::scroll::Pwrite;
+ let offset = &mut 0;
+ #(#items;)*;
+ Ok(*offset)
+ }
+ }
+
+ impl ::scroll::ctx::TryIntoCtx<::scroll::Endian> for #name {
+ type Error = ::scroll::Error;
+ #[inline]
+ fn try_into_ctx(self, dst: &mut [u8], ctx: ::scroll::Endian) -> ::scroll::export::result::Result<usize, Self::Error> {
+ (&self).try_into_ctx(dst, ctx)
+ }
+ }
+ }
+}
+
+fn impl_pwrite(ast: &syn::DeriveInput) -> proc_macro2::TokenStream {
+ let name = &ast.ident;
+ match ast.data {
+ syn::Data::Struct(ref data) => {
+ match data.fields {
+ syn::Fields::Named(ref fields) => {
+ impl_try_into_ctx(name, fields)
+ },
+ _ => {
+ panic!("Pwrite can only be derived for a regular struct with public fields")
+ }
+ }
+ },
+ _ => panic!("Pwrite can only be derived for structs")
+ }
+}
+
+#[proc_macro_derive(Pwrite)]
+pub fn derive_pwrite(input: TokenStream) -> TokenStream {
+ let ast: syn::DeriveInput = syn::parse(input).unwrap();
+ let gen = impl_pwrite(&ast);
+ gen.into()
+}
+
+fn size_with(name: &syn::Ident, fields: &syn::FieldsNamed) -> proc_macro2::TokenStream {
+ let items: Vec<_> = fields.named.iter().map(|f| {
+ let ty = &f.ty;
+ match *ty {
+ syn::Type::Array(ref array) => {
+ let elem = &array.elem;
+ match array.len {
+ syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Int(ref int), ..}) => {
+ let size = int.base10_parse::<usize>().unwrap();
+ quote! {
+ (#size * <#elem>::size_with(ctx))
+ }
+ },
+ _ => panic!("Pread derive with bad array constexpr")
+ }
+ },
+ _ => {
+ quote! {
+ <#ty>::size_with(ctx)
+ }
+ }
+ }
+ }).collect();
+ quote! {
+ impl ::scroll::ctx::SizeWith<::scroll::Endian> for #name {
+ #[inline]
+ fn size_with(ctx: &::scroll::Endian) -> usize {
+ 0 #(+ #items)*
+ }
+ }
+ }
+}
+
+fn impl_size_with(ast: &syn::DeriveInput) -> proc_macro2::TokenStream {
+ let name = &ast.ident;
+ match ast.data {
+ syn::Data::Struct(ref data) => {
+ match data.fields {
+ syn::Fields::Named(ref fields) => {
+ size_with(name, fields)
+ },
+ _ => {
+ panic!("SizeWith can only be derived for a regular struct with public fields")
+ }
+ }
+ },
+ _ => panic!("SizeWith can only be derived for structs")
+ }
+}
+
+#[proc_macro_derive(SizeWith)]
+pub fn derive_sizewith(input: TokenStream) -> TokenStream {
+ let ast: syn::DeriveInput = syn::parse(input).unwrap();
+ let gen = impl_size_with(&ast);
+ gen.into()
+}
+
+fn impl_cread_struct(name: &syn::Ident, fields: &syn::FieldsNamed) -> proc_macro2::TokenStream {
+ let items: Vec<_> = fields.named.iter().map(|f| {
+ let ident = &f.ident;
+ let ty = &f.ty;
+ match *ty {
+ syn::Type::Array(ref array) => {
+ let arrty = &array.elem;
+ match array.len {
+ syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Int(ref int), ..}) => {
+ let size = int.base10_parse::<usize>().unwrap();
+ let incr = quote! { ::scroll::export::mem::size_of::<#arrty>() };
+ quote! {
+ #ident: {
+ let mut __tmp: #ty = [0; #size];
+ for i in 0..__tmp.len() {
+ __tmp[i] = src.cread_with(*offset, ctx);
+ *offset += #incr;
+ }
+ __tmp
+ }
+ }
+ },
+ _ => panic!("IOread derive with bad array constexpr")
+ }
+ },
+ _ => {
+ let size = quote! { ::scroll::export::mem::size_of::<#ty>() };
+ quote! {
+ #ident: { let res = src.cread_with::<#ty>(*offset, ctx); *offset += #size; res }
+ }
+ }
+ }
+ }).collect();
+
+ quote! {
+ impl ::scroll::ctx::FromCtx<::scroll::Endian> for #name {
+ #[inline]
+ fn from_ctx(src: &[u8], ctx: ::scroll::Endian) -> Self {
+ use ::scroll::Cread;
+ let offset = &mut 0;
+ let data = #name { #(#items,)* };
+ data
+ }
+ }
+ }
+}
+
+fn impl_from_ctx(ast: &syn::DeriveInput) -> proc_macro2::TokenStream {
+ let name = &ast.ident;
+ match ast.data {
+ syn::Data::Struct(ref data) => {
+ match data.fields {
+ syn::Fields::Named(ref fields) => {
+ impl_cread_struct(name, fields)
+ },
+ _ => {
+ panic!("IOread can only be derived for a regular struct with public fields")
+ }
+ }
+ },
+ _ => panic!("IOread can only be derived for structs")
+ }
+}
+
+#[proc_macro_derive(IOread)]
+pub fn derive_ioread(input: TokenStream) -> TokenStream {
+ let ast: syn::DeriveInput = syn::parse(input).unwrap();
+ let gen = impl_from_ctx(&ast);
+ gen.into()
+}
+
+fn impl_into_ctx(name: &syn::Ident, fields: &syn::FieldsNamed) -> proc_macro2::TokenStream {
+ let items: Vec<_> = fields.named.iter().map(|f| {
+ let ident = &f.ident;
+ let ty = &f.ty;
+ let size = quote! { ::scroll::export::mem::size_of::<#ty>() };
+ match *ty {
+ syn::Type::Array(ref array) => {
+ let arrty = &array.elem;
+ quote! {
+ let size = ::scroll::export::mem::size_of::<#arrty>();
+ for i in 0..self.#ident.len() {
+ dst.cwrite_with(self.#ident[i], *offset, ctx);
+ *offset += size;
+ }
+ }
+ },
+ _ => {
+ quote! {
+ dst.cwrite_with(self.#ident, *offset, ctx);
+ *offset += #size;
+ }
+ }
+ }
+ }).collect();
+
+ quote! {
+ impl<'a> ::scroll::ctx::IntoCtx<::scroll::Endian> for &'a #name {
+ #[inline]
+ fn into_ctx(self, dst: &mut [u8], ctx: ::scroll::Endian) {
+ use ::scroll::Cwrite;
+ let offset = &mut 0;
+ #(#items;)*;
+ ()
+ }
+ }
+
+ impl ::scroll::ctx::IntoCtx<::scroll::Endian> for #name {
+ #[inline]
+ fn into_ctx(self, dst: &mut [u8], ctx: ::scroll::Endian) {
+ (&self).into_ctx(dst, ctx)
+ }
+ }
+ }
+}
+
+fn impl_iowrite(ast: &syn::DeriveInput) -> proc_macro2::TokenStream {
+ let name = &ast.ident;
+ match ast.data {
+ syn::Data::Struct(ref data) => {
+ match data.fields {
+ syn::Fields::Named(ref fields) => {
+ impl_into_ctx(name, fields)
+ },
+ _ => {
+ panic!("IOwrite can only be derived for a regular struct with public fields")
+ }
+ }
+ },
+ _ => panic!("IOwrite can only be derived for structs")
+ }
+}
+
+#[proc_macro_derive(IOwrite)]
+pub fn derive_iowrite(input: TokenStream) -> TokenStream {
+ let ast: syn::DeriveInput = syn::parse(input).unwrap();
+ let gen = impl_iowrite(&ast);
+ gen.into()
+}