Skip to content

Commit

Permalink
Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
hal3e committed Jan 7, 2025
1 parent 1fb0acb commit 9f34af8
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 161 deletions.
67 changes: 65 additions & 2 deletions e2e/tests/configurables.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use fuels::{
core::codec::EncoderConfig,
core::{codec::EncoderConfig, ConfigurablesReader},
prelude::*,
types::{Bits256, SizedAsciiString, U256},
types::{AsciiString, Bits256, SizedAsciiString, U256},
};
use test_case::test_case;

Expand Down Expand Up @@ -392,3 +392,66 @@ async fn configurable_encoder_config_is_applied() {
.contains("token limit `1` reached while encoding. Try increasing it"),)
}
}

#[tokio::test]
async fn contract_configurables_reader() -> Result<()> {
abigen!(Contract(
name = "MyContract",
abi = "e2e/sway/contracts/dyn_configurables/out/release/dyn_configurables-abi.json"
));

let configurables_reader = MyContractConfigurablesReader::load_from(
"sway/contracts/dyn_configurables/out/release/dyn_configurables.bin",
)?;

let some_bool = configurables_reader.BOOL()?;
let some_u8 = configurables_reader.U8()?;
let some_str = configurables_reader.STR()?;
let some_str2 = configurables_reader.STR_2()?;
let some_str3 = configurables_reader.STR_3()?;
let some_last_u8 = configurables_reader.LAST_U8()?;

assert!(some_bool);
assert_eq!(some_u8, 8);
assert_eq!(some_str, "sway");
assert_eq!(some_str2, "forc");
assert_eq!(some_str3, "fuel");
assert_eq!(some_last_u8, 16);

// let offset = 2555;
// let some_u8: u8 = fuels::core::ConfigurablesReader::load_from(
// "sway/contracts/dyn_configurables/out/release/dyn_configurables.bin",
// )?
// .decode_direct(offset)?;

// let offset = 2555;
// let some_str: fuels::types::AsciiString = fuels::core::ConfigurablesReader::load_from(
// "sway/contracts/dyn_configurables/out/release/dyn_configurables.bin",
// )?
// .decode_indirect(offset)?;

Ok(())
}

#[tokio::test]
async fn contract_configurables_reader_manual() -> Result<()> {
let configurables_reader = ConfigurablesReader::load_from(
"sway/contracts/dyn_configurables/out/release/dyn_configurables.bin",
)?;

let some_bool: bool = configurables_reader.decode_direct(3264)?;
let some_u8: u8 = configurables_reader.decode_direct(3304)?;
let some_str: AsciiString = configurables_reader.decode_indirect(3280)?;
let some_str2: AsciiString = configurables_reader.decode_indirect(3288)?;
let some_str3: AsciiString = configurables_reader.decode_indirect(3296)?;
let some_last_u8: u8 = configurables_reader.decode_direct(3272)?;

assert!(some_bool);
assert_eq!(some_u8, 8);
assert_eq!(some_str, "sway");
assert_eq!(some_str2, "forc");
assert_eq!(some_str3, "fuel");
assert_eq!(some_last_u8, 16);

Ok(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
abigen::{
bindings::function_generator::FunctionGenerator,
configurables::{
generate_code_for_configurable_constants, generate_code_for_configurable_constants2,
generate_code_for_configurable_constants, generate_code_for_configurable_reader,
},
logs::log_formatters_instantiation_code,
},
Expand Down Expand Up @@ -38,9 +38,9 @@ pub(crate) fn contract_bindings(
let constant_configuration_code =
generate_code_for_configurable_constants(&configuration_struct_name, &abi.configurables)?;

let configuration_struct_name2 = ident(&format!("{name}Configurables2"));
let configuration_struct_name2 = ident(&format!("{name}ConfigurablesReader"));
let constant_configuration_code2 =
generate_code_for_configurable_constants2(&configuration_struct_name2, &abi.configurables)?;
generate_code_for_configurable_reader(&configuration_struct_name2, &abi.configurables)?;

let code = quote! {
#[derive(Debug, Clone)]
Expand Down
138 changes: 22 additions & 116 deletions packages/fuels-code-gen/src/program_bindings/abigen/configurables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ fn generate_from_impl(configurable_struct_name: &Ident) -> TokenStream {
}
}

pub(crate) fn generate_code_for_configurable_constants2(
pub(crate) fn generate_code_for_configurable_reader(
configurable_struct_name: &Ident,
configurables: &[FullConfigurable],
) -> Result<TokenStream> {
Expand All @@ -156,147 +156,67 @@ pub(crate) fn generate_code_for_configurable_constants2(
.map(ResolvedConfigurable::new)
.collect::<Result<Vec<_>>>()?;

let struct_decl = generate_struct_decl2(configurable_struct_name);
let struct_impl = generate_struct_impl2(configurable_struct_name, &resolved_configurables);
let struct_decl = generate_struct_decl_reader(configurable_struct_name);
let struct_impl =
generate_struct_impl_reader(configurable_struct_name, &resolved_configurables);

Ok(quote! {
#struct_decl
#struct_impl
})
}

fn generate_struct_decl2(configurable_struct_name: &Ident) -> TokenStream {
fn generate_struct_decl_reader(configurable_struct_name: &Ident) -> TokenStream {
quote! {
#[derive(Clone, Debug, Default)]
#[derive(Clone, Debug)]
pub struct #configurable_struct_name {
configurables: ::std::collections::HashMap<u64, ::fuels::core::Configurable>,
encoder: ::fuels::core::codec::ABIEncoder,
decoder: ::fuels::core::codec::ABIDecoder,
reader: ::fuels::core::ConfigurablesReader,
}
}
}

fn generate_struct_impl2(
fn generate_struct_impl_reader(
configurable_struct_name: &Ident,
resolved_configurables: &[ResolvedConfigurable],
) -> TokenStream {
let methods = generate_methods2(resolved_configurables);

let code_to_load_configurables = resolved_configurables.iter().map(
|ResolvedConfigurable {
ttype,
offset,
indirect,
..
}| {
let decoder_code = generate_decoder_code2(ttype, *offset as usize);
quote! {
let configurable = if #indirect {
let offset_from_data_section = Self::extract_usize_at_offset(&binary, #offset as usize)?;
::std::dbg!(&offset_from_data_section);
let data_offset = data_section_offset + offset_from_data_section;

let token = self.decoder.decode(&<#ttype as ::fuels::core::traits::Parameterize>::param_type(), &binary[data_offset..])?;
let encoded = self.encoder.encode(&[token])?; //TODO: @hal3e remove the encoding

::fuels::core::Configurable::Indirect{
offset: #offset,
data_offset: data_offset as u64,
data: encoded,
}
}
else {
let token = #decoder_code?;
let encoded = self.encoder.encode(&[token])?; //TODO: @hal3e remove the encoding
//and get the num of loaded bytes
::fuels::core::Configurable::Direct{
offset: #offset,
data: encoded,
}
};

configurables.insert(#offset, configurable);
}
},
);
let methods = generate_methods_reader(resolved_configurables);

quote! {
impl #configurable_struct_name {
pub fn load_from(mut self,
pub fn load_from(
binary_filepath: impl ::std::convert::AsRef<::std::path::Path>,
) -> ::fuels::prelude::Result<Self> {
let binary_filepath = binary_filepath.as_ref();

let binary = ::std::fs::read(binary_filepath).map_err(|e| {
::std::io::Error::new(
e.kind(),
format!("failed to read binary: {binary_filepath:?}: {e}"),
)
})?;

let mut configurables = ::std::collections::HashMap::new();
let data_section_offset = Self::extract_usize_at_offset(&binary, 8)?;
::std::dbg!(&data_section_offset);
let reader = ::fuels::core::ConfigurablesReader::load_from(binary_filepath)?;


#(#code_to_load_configurables)*

self.configurables = configurables;

::fuels::prelude::Result::Ok(self)
}

fn extract_usize_at_offset(binary: &[u8], offset: usize) -> ::fuels::prelude::Result<usize> {
if binary.len() < (offset + 8) {
return ::std::result::Result::Err(::fuels::types::errors::error!(
Other,
"given binary is too short to contain a data offset, len: {}",
binary.len()
));
}
let data_offset =
<&[u8] as ::std::convert::TryInto<[u8; 8]>>::try_into(&binary[offset..(offset + 8)]).expect("checked above");


::fuels::prelude::Result::Ok(u64::from_be_bytes(data_offset) as usize)
::fuels::prelude::Result::Ok(Self{reader})
}

#methods
}
}
}

fn generate_methods2(resolved_configurables: &[ResolvedConfigurable]) -> TokenStream {
fn generate_methods_reader(resolved_configurables: &[ResolvedConfigurable]) -> TokenStream {
let methods = resolved_configurables.iter().map(
|ResolvedConfigurable {
name,
ttype,
offset,
..
indirect,
}| {
let encoder_code = generate_encoder_code2(ttype);
let name = safe_ident(name);
let with_name = safe_ident(&format!("with_{}", name));
quote! {
// Generate the `with_XXX` methods for setting the configurables
#[allow(non_snake_case)]
pub fn #with_name(mut self, value: #ttype) -> ::fuels::prelude::Result<Self> {
let encoded = #encoder_code?;
let mut configurable = self.configurables.get(&#offset).expect("is there").clone();
configurable.set_data(encoded);
self.configurables.insert(#offset, configurable);

::fuels::prelude::Result::Ok(self)
}
let reader_code = if *indirect {
quote! { self.reader.decode_indirect(#offset as usize) }
} else {
quote! { self.reader.decode_direct(#offset as usize) }
};

quote! {
// Generate the `XXX` methods for getting the configurables
#[allow(non_snake_case)]
pub fn #name(&self) -> #ttype {
let configurable = self.configurables.get(&#offset).expect("is there");

let token = self.decoder.decode(&<#ttype as ::fuels::core::traits::Parameterize>::param_type(), configurable.data()).expect("is ok");

<#ttype as ::fuels::core::traits::Tokenizable>::from_token(token).expect("is ok")
pub fn #name(&self) -> ::fuels::prelude::Result<#ttype> {
#reader_code
}

}
Expand All @@ -307,17 +227,3 @@ fn generate_methods2(resolved_configurables: &[ResolvedConfigurable]) -> TokenSt
#(#methods)*
}
}

fn generate_encoder_code2(ttype: &ResolvedType) -> TokenStream {
quote! {
self.encoder.encode(&[
<#ttype as ::fuels::core::traits::Tokenizable>::into_token(value)
])
}
}

fn generate_decoder_code2(ttype: &ResolvedType, offset: usize) -> TokenStream {
quote! {
self.decoder.decode(&<#ttype as ::fuels::core::traits::Parameterize>::param_type(), &binary[#offset..])
}
}
Loading

0 comments on commit 9f34af8

Please sign in to comment.