Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ version = "=28.0.0"
#rev = "a749b69b3471aec0c20ec431b0297f3414d66421"
default-features = false

#[patch.crates-io]
[patch.crates-io]
# Pending https://github.com/stellar/rs-stellar-xdr/pull/562, which adds the
# borrowing `*View` types and their const XDR serializers that the contract spec
# generation in soroban-sdk-macros builds on.
stellar-xdr = { git = "https://github.com/stellar/rs-stellar-xdr", rev = "595950c5dfd2dab0333922ebb26fab27dac3188a" }
#soroban-env-common = { path = "../rs-soroban-env/soroban-env-common" }
#soroban-env-guest = { path = "../rs-soroban-env/soroban-env-guest" }
#soroban-env-host = { path = "../rs-soroban-env/soroban-env-host" }
Expand Down
1 change: 0 additions & 1 deletion soroban-sdk-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ proc-macro = true
doctest = false

[dependencies]
soroban-spec = { workspace = true }
soroban-spec-rust = { workspace = true }
soroban-env-common = { workspace = true }
stellar-xdr = { workspace = true, features = ["std"] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,12 @@ fn derive(args: &Args) -> Result<TokenStream2, Error> {
Some(trait_ident),
&args.client_name,
));
output.extend(derive_fns_spec(&args.spec_name, &fns, spec_export));
output.extend(derive_fns_spec(
&args.crate_path,
&args.spec_name,
&fns,
spec_export,
));
output.extend(derive_client_impl(
&args.crate_path,
&args.client_name,
Expand Down
64 changes: 50 additions & 14 deletions soroban-sdk-macros/src/derive_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ use syn::{
};

use stellar_xdr::{
Error as XdrError, ScSpecEntry, ScSpecTypeDef, ScSpecUdtUnionCaseTupleV0, ScSpecUdtUnionCaseV0,
ScSpecUdtUnionCaseVoidV0, ScSpecUdtUnionV0, StringM, VecM, WriteXdr, SCSYMBOL_LIMIT,
Error as XdrError, ScSpecTypeDef, ScSpecUdtUnionCaseTupleV0, ScSpecUdtUnionCaseV0,
ScSpecUdtUnionCaseVoidV0, ScSpecUdtUnionV0, StringM, VecM, SCSYMBOL_LIMIT,
};

use crate::{doc::docs_from_attrs, map_type::map_type, shaking, DEFAULT_XDR_RW_LIMITS};
use crate::{
doc::docs_from_attrs,
map_type::{const_view_string, const_view_type_def, map_type},
shaking,
};

pub fn derive_type_enum(
path: &Path,
Expand Down Expand Up @@ -144,30 +148,62 @@ pub fn derive_type_enum(
return quote! { #(#compile_errors)* };
}

// Compute spec XDR once.
let spec_entry = ScSpecEntry::UdtUnionV0(ScSpecUdtUnionV0 {
// Build the spec entry once.
let spec = ScSpecUdtUnionV0 {
doc: docs_from_attrs(attrs),
lib: lib.as_deref().unwrap_or_default().try_into().unwrap(),
name: enum_ident.unraw().to_string().try_into().unwrap(),
cases: spec_cases.try_into().unwrap(),
});
let spec_xdr = spec_entry.to_xdr(DEFAULT_XDR_RW_LIMITS).unwrap();
};

// Generated code spec.
// Generated code spec. The spec entry is rendered as the equivalent const
// ScSpecEntryView, which the contract crate encodes to XDR at compile time.
let spec_gen = {
let spec_xdr_lit = proc_macro2::Literal::byte_string(spec_xdr.as_slice());
let spec_xdr_len = spec_xdr.len();
let doc = const_view_string(path, &spec.doc);
let lib = const_view_string(path, &spec.lib);
let name = const_view_string(path, &spec.name);
let cases = spec.cases.iter().map(|c| match c {
ScSpecUdtUnionCaseV0::VoidV0(c) => {
let doc = const_view_string(path, &c.doc);
let name = const_view_string(path, &c.name);
quote!(#path::xdr::ScSpecUdtUnionCaseV0View::VoidV0(
#path::xdr::ScSpecUdtUnionCaseVoidV0View { doc: #doc, name: #name }
))
}
ScSpecUdtUnionCaseV0::TupleV0(c) => {
let doc = const_view_string(path, &c.doc);
let name = const_view_string(path, &c.name);
let type_ = c.type_.iter().map(|t| const_view_type_def(path, t));
quote!(#path::xdr::ScSpecUdtUnionCaseV0View::TupleV0(
#path::xdr::ScSpecUdtUnionCaseTupleV0View {
doc: #doc,
name: #name,
type_: #path::xdr::VecMView::new(&[#(#type_),*]),
}
))
}
});
let spec_view = quote! {
#path::xdr::ScSpecEntryView::UdtUnionV0(#path::xdr::ScSpecUdtUnionV0View {
doc: #doc,
lib: #lib,
name: #name,
cases: #path::xdr::VecMView::new(&[#(#cases),*]),
})
};
let spec_ident = format_ident!(
"__SPEC_XDR_TYPE_{}",
enum_ident.unraw().to_string().to_uppercase()
);
quote! {
#[cfg_attr(target_family = "wasm", link_section = "contractspecv0")]
pub static #spec_ident: [u8; #spec_xdr_len] = #enum_ident::spec_xdr();
pub static #spec_ident: [u8; #enum_ident::__SPEC_XDR_VIEW.const_xdr_len()] = #enum_ident::spec_xdr();

impl #enum_ident {
pub const fn spec_xdr() -> [u8; #spec_xdr_len] {
*#spec_xdr_lit
const __SPEC_XDR_VIEW: #path::xdr::ScSpecEntryView<'static> = #spec_view;

pub const fn spec_xdr() -> [u8; #enum_ident::__SPEC_XDR_VIEW.const_xdr_len()] {
#enum_ident::__SPEC_XDR_VIEW.const_to_xdr()
}
}
}
Expand All @@ -184,7 +220,7 @@ pub fn derive_type_enum(
shaking::generate_marker_impl(
path,
quote!(#enum_ident),
&spec_xdr,
quote!(#enum_ident::spec_xdr()),
all_field_types.cloned(),
None,
None,
Expand Down
43 changes: 30 additions & 13 deletions soroban-sdk-macros/src/derive_enum_int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use syn::{
Visibility,
};

use stellar_xdr::{ScSpecEntry, ScSpecUdtEnumCaseV0, WriteXdr};
use stellar_xdr::ScSpecUdtEnumCaseV0;

use crate::{doc::docs_from_attrs, shaking, DEFAULT_XDR_RW_LIMITS};
use crate::{doc::docs_from_attrs, map_type::const_view_string, shaking};

// TODO: Add conversions to/from ScVal types.

Expand Down Expand Up @@ -66,30 +66,47 @@ pub fn derive_type_enum_int(
return quote! { #(#compile_errors)* };
}

// Compute spec XDR once.
let spec_entry = ScSpecEntry::UdtEnumV0(ScSpecUdtEnumV0 {
// Build the spec entry once.
let spec = ScSpecUdtEnumV0 {
doc: docs_from_attrs(attrs),
lib: lib.as_deref().unwrap_or_default().try_into().unwrap(),
name: enum_ident.unraw().to_string().try_into().unwrap(),
cases: spec_cases.try_into().unwrap(),
});
let spec_xdr = spec_entry.to_xdr(DEFAULT_XDR_RW_LIMITS).unwrap();
};

// Generated code spec.
// Generated code spec. The spec entry is rendered as the equivalent const
// ScSpecEntryView, which the contract crate encodes to XDR at compile time.
let spec_gen = {
let spec_xdr_lit = proc_macro2::Literal::byte_string(spec_xdr.as_slice());
let spec_xdr_len = spec_xdr.len();
let doc = const_view_string(path, &spec.doc);
let lib = const_view_string(path, &spec.lib);
let name = const_view_string(path, &spec.name);
let cases = spec.cases.iter().map(|c| {
let doc = const_view_string(path, &c.doc);
let name = const_view_string(path, &c.name);
let value = c.value;
quote!(#path::xdr::ScSpecUdtEnumCaseV0View { doc: #doc, name: #name, value: #value })
});
let spec_view = quote! {
#path::xdr::ScSpecEntryView::UdtEnumV0(#path::xdr::ScSpecUdtEnumV0View {
doc: #doc,
lib: #lib,
name: #name,
cases: #path::xdr::VecMView::new(&[#(#cases),*]),
})
};
let spec_ident = format_ident!(
"__SPEC_XDR_TYPE_{}",
enum_ident.unraw().to_string().to_uppercase()
);
quote! {
#[cfg_attr(target_family = "wasm", link_section = "contractspecv0")]
pub static #spec_ident: [u8; #spec_xdr_len] = #enum_ident::spec_xdr();
pub static #spec_ident: [u8; #enum_ident::__SPEC_XDR_VIEW.const_xdr_len()] = #enum_ident::spec_xdr();

impl #enum_ident {
pub const fn spec_xdr() -> [u8; #spec_xdr_len] {
*#spec_xdr_lit
const __SPEC_XDR_VIEW: #path::xdr::ScSpecEntryView<'static> = #spec_view;

pub const fn spec_xdr() -> [u8; #enum_ident::__SPEC_XDR_VIEW.const_xdr_len()] {
#enum_ident::__SPEC_XDR_VIEW.const_to_xdr()
}
}
}
Expand All @@ -99,7 +116,7 @@ pub fn derive_type_enum_int(
let spec_shaking_impl = shaking::generate_marker_impl(
path,
quote!(#enum_ident),
&spec_xdr,
quote!(#enum_ident::spec_xdr()),
std::iter::empty(),
None,
None,
Expand Down
43 changes: 30 additions & 13 deletions soroban-sdk-macros/src/derive_error_enum_int.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use itertools::MultiUnzip;
use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote};
use stellar_xdr::{ScSpecEntry, ScSpecUdtErrorEnumCaseV0, ScSpecUdtErrorEnumV0, StringM, WriteXdr};
use stellar_xdr::{ScSpecUdtErrorEnumCaseV0, ScSpecUdtErrorEnumV0, StringM};
use syn::{
ext::IdentExt as _, spanned::Spanned, Attribute, DataEnum, Error, ExprLit, Ident, Lit, Path,
};

use crate::{doc::docs_from_attrs, shaking, DEFAULT_XDR_RW_LIMITS};
use crate::{doc::docs_from_attrs, map_type::const_view_string, shaking};

pub fn derive_type_error_enum_int(
path: &Path,
Expand Down Expand Up @@ -63,30 +63,47 @@ pub fn derive_type_error_enum_int(
return quote! { #(#compile_errors)* };
}

// Compute spec XDR once.
let spec_entry = ScSpecEntry::UdtErrorEnumV0(ScSpecUdtErrorEnumV0 {
// Build the spec entry once.
let spec = ScSpecUdtErrorEnumV0 {
doc: docs_from_attrs(attrs),
lib: lib.as_deref().unwrap_or_default().try_into().unwrap(),
name: enum_ident.unraw().to_string().try_into().unwrap(),
cases: spec_cases.try_into().unwrap(),
});
let spec_xdr = spec_entry.to_xdr(DEFAULT_XDR_RW_LIMITS).unwrap();
};

// Generated code spec.
// Generated code spec. The spec entry is rendered as the equivalent const
// ScSpecEntryView, which the contract crate encodes to XDR at compile time.
let spec_gen = {
let spec_xdr_lit = proc_macro2::Literal::byte_string(spec_xdr.as_slice());
let spec_xdr_len = spec_xdr.len();
let doc = const_view_string(path, &spec.doc);
let lib = const_view_string(path, &spec.lib);
let name = const_view_string(path, &spec.name);
let cases = spec.cases.iter().map(|c| {
let doc = const_view_string(path, &c.doc);
let name = const_view_string(path, &c.name);
let value = c.value;
quote!(#path::xdr::ScSpecUdtErrorEnumCaseV0View { doc: #doc, name: #name, value: #value })
});
let spec_view = quote! {
#path::xdr::ScSpecEntryView::UdtErrorEnumV0(#path::xdr::ScSpecUdtErrorEnumV0View {
doc: #doc,
lib: #lib,
name: #name,
cases: #path::xdr::VecMView::new(&[#(#cases),*]),
})
};
let spec_ident = format_ident!(
"__SPEC_XDR_TYPE_{}",
enum_ident.unraw().to_string().to_uppercase()
);
quote! {
#[cfg_attr(target_family = "wasm", link_section = "contractspecv0")]
pub static #spec_ident: [u8; #spec_xdr_len] = #enum_ident::spec_xdr();
pub static #spec_ident: [u8; #enum_ident::__SPEC_XDR_VIEW.const_xdr_len()] = #enum_ident::spec_xdr();

impl #enum_ident {
pub const fn spec_xdr() -> [u8; #spec_xdr_len] {
*#spec_xdr_lit
const __SPEC_XDR_VIEW: #path::xdr::ScSpecEntryView<'static> = #spec_view;

pub const fn spec_xdr() -> [u8; #enum_ident::__SPEC_XDR_VIEW.const_xdr_len()] {
#enum_ident::__SPEC_XDR_VIEW.const_to_xdr()
}
}
}
Expand All @@ -96,7 +113,7 @@ pub fn derive_type_error_enum_int(
let spec_shaking_impl = shaking::generate_marker_impl(
path,
quote!(#enum_ident),
&spec_xdr,
quote!(#enum_ident::spec_xdr()),
std::iter::empty(),
None,
None,
Expand Down
Loading
Loading