summaryrefslogtreecommitdiff
path: root/byte_encode_derive
diff options
context:
space:
mode:
authorDylan <boss@tehbox.org>2026-08-26 23:58:16 +1200
committerDylan <boss@tehbox.org>2026-08-26 23:58:16 +1200
commit7c640bfeaf2a0fbc8c3550b4c19790a800a7f6a2 (patch)
tree60ef598fa415b6a01bed7b1c1f62c1c696111c8f /byte_encode_derive
parentf8ffb92f2857677e4a9986ef154800ddb2e233fd (diff)
downloadtehimage-rs-master.tar.gz
tehimage-rs-master.zip
feat: Added a bunch of stuffHEADmaster
Added derive macro for byte encode Added start for PNG reading Added BMP writing
Diffstat (limited to 'byte_encode_derive')
-rw-r--r--byte_encode_derive/Cargo.lock46
-rw-r--r--byte_encode_derive/Cargo.toml12
-rw-r--r--byte_encode_derive/src/lib.rs128
3 files changed, 186 insertions, 0 deletions
diff --git a/byte_encode_derive/Cargo.lock b/byte_encode_derive/Cargo.lock
new file mode 100644
index 0000000..2616932
--- /dev/null
+++ b/byte_encode_derive/Cargo.lock
@@ -0,0 +1,46 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "byte_encode_derive"
+version = "0.1.0"
+dependencies = [
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.46"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.118"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
diff --git a/byte_encode_derive/Cargo.toml b/byte_encode_derive/Cargo.toml
new file mode 100644
index 0000000..832dadd
--- /dev/null
+++ b/byte_encode_derive/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "byte_encode_derive"
+version = "0.1.0"
+edition = "2024"
+
+[lib]
+proc-macro = true
+
+[dependencies]
+
+syn = { version = "2", features = ["full", "parsing"] }
+quote = "1" \ No newline at end of file
diff --git a/byte_encode_derive/src/lib.rs b/byte_encode_derive/src/lib.rs
new file mode 100644
index 0000000..5970c66
--- /dev/null
+++ b/byte_encode_derive/src/lib.rs
@@ -0,0 +1,128 @@
+// Code mostly made by gemini somehow
+
+use proc_macro::TokenStream;
+use quote::quote;
+use syn::{parse_macro_input, Data, DeriveInput, Fields};
+
+#[proc_macro_derive(ByteEncode)]
+pub fn derive_byte_encode(input: TokenStream) -> TokenStream {
+ let input = parse_macro_input!(input as DeriveInput);
+ let name = input.ident;
+
+ // We only support structs with named fields for this example
+ let fields = match input.data {
+ Data::Struct(data) => match data.fields {
+ Fields::Named(fields) => fields.named,
+ _ => panic!("Only named fields are supported"),
+ },
+ _ => panic!("Only structs are supported"),
+ };
+
+ // --- 1. Generate from_le_bytes parsing logic ---
+ let mut current_offset = quote! { 0 };
+ let from_le_bytes_initializers = fields.iter().map(|f| {
+ let field_name = &f.ident;
+ let field_type = &f.ty;
+
+ // Calculate start and end bounds for the current field slice
+ let start = quote! { #current_offset };
+ let end = quote! { #start + <#field_type>::SIZE };
+
+ // Update the offset tracking for the next iteration loop
+ current_offset = quote! { #end };
+
+ quote! {
+ #field_name: <#field_type as ByteEncode<{<#field_type>::SIZE}>>::from_le_bytes(
+ buffer[#start..#end].try_into().unwrap()
+ )
+ }
+ });
+ let mut current_offset = quote! { 0 };
+ let from_be_bytes_initializers = fields.iter().map(|f| {
+ let field_name = &f.ident;
+ let field_type = &f.ty;
+
+ // Calculate start and end bounds for the current field slice
+ let start = quote! { #current_offset };
+ let end = quote! { #start + <#field_type>::SIZE };
+
+ // Update the offset tracking for the next iteration loop
+ current_offset = quote! { #end };
+
+ quote! {
+ #field_name: <#field_type as ByteEncode<{<#field_type>::SIZE}>>::from_be_bytes(
+ &mut buffer[#start..#end].try_into().unwrap()
+ )
+ }
+ });
+
+
+ // --- 2. Generate to_le_bytes serialization logic ---
+ let mut current_offset = quote! { 0 };
+ let to_le_bytes_writers = fields.iter().map(|f| {
+ let field_name = &f.ident;
+ let field_type = &f.ty;
+
+ let start = quote! { #current_offset };
+ let end = quote! { #start + <#field_type>::SIZE };
+
+ current_offset = quote! { #end };
+
+ quote! {
+ res[#start..#end].copy_from_slice(&self.#field_name.to_le_bytes());
+ }
+ });
+ let mut current_offset = quote! { 0 };
+ let to_be_bytes_writers = fields.iter().map(|f| {
+ let field_name = &f.ident;
+ let field_type = &f.ty;
+
+ let start = quote! { #current_offset };
+ let end = quote! { #start + <#field_type>::SIZE };
+
+ current_offset = quote! { #end };
+
+ quote! {
+ res[#start..#end].copy_from_slice(&self.#field_name.to_be_bytes());
+ }
+ });
+
+
+ // --- 3. Construct final token stream ---
+ // This dynamically sums up sizes like: 0 + Field1::SIZE + Field2::SIZE ...
+ let total_size_expr = fields.iter().fold(quote! { 0 }, |acc, f| {
+ let field_type = &f.ty;
+ quote! { #acc + <#field_type>::SIZE }
+ });
+
+ let expanded = quote! {
+ impl ByteEncode<{ #total_size_expr }> for #name {
+ fn from_le_bytes(buffer: &[u8; { #total_size_expr }]) -> Self {
+ Self {
+ #( #from_le_bytes_initializers, )*
+ }
+ }
+
+ fn to_le_bytes(&self) -> [u8; { #total_size_expr }] {
+ let mut res = [0u8; { #total_size_expr }];
+ #( #to_le_bytes_writers )*
+ res
+ }
+
+
+ fn from_be_bytes(buffer: &mut [u8; { #total_size_expr }]) -> Self {
+ Self {
+ #( #from_be_bytes_initializers, )*
+ }
+ }
+
+ fn to_be_bytes(&self) -> [u8; { #total_size_expr }] {
+ let mut res = [0u8; { #total_size_expr }];
+ #( #to_be_bytes_writers )*
+ res
+ }
+ }
+ };
+
+ TokenStream::from(expanded)
+}