Skip to content

Commit 8bd5d97

Browse files
Fix conversions from &_ to Val (#1502)
### What Add support for conversions from &Vec<T>, &Map<>, String, etc to Val. ### Why All SDK types should be convertible to `Val` either from an owned value, e.g. `Vec<T>`, or from a borrowed value, e.g. `&Vec<T>`. Close #1500
1 parent f951cf0 commit 8bd5d97

19 files changed

+524
-6
lines changed

soroban-sdk-macros/src/derive_enum.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,14 @@ pub fn derive_type_enum(
192192
}
193193
}
194194
}
195+
196+
impl #path::TryFromVal<#path::Env, &#enum_ident> for #path::Val {
197+
type Error = #path::ConversionError;
198+
#[inline(always)]
199+
fn try_from_val(env: &#path::Env, val: &&#enum_ident) -> Result<Self, #path::ConversionError> {
200+
<_ as #path::TryFromVal<#path::Env, #enum_ident>>::try_from_val(env, *val)
201+
}
202+
}
195203
};
196204

197205
// Additional output when testutils are enabled.

soroban-sdk-macros/src/derive_enum_int.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,14 @@ pub fn derive_type_enum_int(
117117
})
118118
}
119119
}
120+
121+
impl #path::TryFromVal<#path::Env, &#enum_ident> for #path::Val {
122+
type Error = #path::ConversionError;
123+
#[inline(always)]
124+
fn try_from_val(env: &#path::Env, val: &&#enum_ident) -> Result<Self, #path::ConversionError> {
125+
<_ as #path::TryFromVal<#path::Env, #enum_ident>>::try_from_val(env, *val)
126+
}
127+
}
120128
};
121129

122130
// Additional output when testutils are enabled.

soroban-sdk-macros/src/derive_error_enum_int.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,5 +188,13 @@ pub fn derive_type_error_enum_int(
188188
Ok(error.into())
189189
}
190190
}
191+
192+
impl #path::TryFromVal<#path::Env, &#enum_ident> for #path::Val {
193+
type Error = #path::ConversionError;
194+
#[inline(always)]
195+
fn try_from_val(env: &#path::Env, val: &&#enum_ident) -> Result<Self, #path::ConversionError> {
196+
<_ as #path::TryFromVal<#path::Env, #enum_ident>>::try_from_val(env, *val)
197+
}
198+
}
191199
}
192200
}

soroban-sdk-macros/src/derive_struct.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,14 @@ pub fn derive_type_struct(
129129
Ok(env.map_new_from_slices(&KEYS, &vals).map_err(|_| ConversionError)?.into())
130130
}
131131
}
132+
133+
impl #path::TryFromVal<#path::Env, &#ident> for #path::Val {
134+
type Error = #path::ConversionError;
135+
#[inline(always)]
136+
fn try_from_val(env: &#path::Env, val: &&#ident) -> Result<Self, #path::ConversionError> {
137+
<_ as #path::TryFromVal<#path::Env, #ident>>::try_from_val(env, *val)
138+
}
139+
}
132140
};
133141

134142
// Additional output when testutils are enabled.

soroban-sdk-macros/src/derive_struct_tuple.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,14 @@ pub fn derive_type_struct_tuple(
118118
Ok(env.vec_new_from_slice(&vals).map_err(|_| ConversionError)?.into())
119119
}
120120
}
121+
122+
impl #path::TryFromVal<#path::Env, &#ident> for #path::Val {
123+
type Error = #path::ConversionError;
124+
#[inline(always)]
125+
fn try_from_val(env: &#path::Env, val: &&#ident) -> Result<Self, #path::ConversionError> {
126+
<_ as #path::TryFromVal<#path::Env, #ident>>::try_from_val(env, *val)
127+
}
128+
}
121129
};
122130

123131
// Additional output when testutils are enabled.

soroban-sdk/src/bytes.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,14 @@ macro_rules! impl_bytesn_repr {
160160
}
161161
}
162162

163+
impl TryFromVal<Env, &$elem> for Val {
164+
type Error = ConversionError;
165+
166+
fn try_from_val(_env: &Env, elt: &&$elem) -> Result<Self, Self::Error> {
167+
Ok(elt.to_val())
168+
}
169+
}
170+
163171
#[cfg(not(target_family = "wasm"))]
164172
impl From<&$elem> for ScVal {
165173
fn from(v: &$elem) -> Self {

soroban-sdk/src/crypto/bls12_381.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,14 @@ impl TryFromVal<Env, Fr> for Val {
505505
}
506506
}
507507

508+
impl TryFromVal<Env, &Fr> for Val {
509+
type Error = ConversionError;
510+
511+
fn try_from_val(_env: &Env, fr: &&Fr) -> Result<Self, Self::Error> {
512+
Ok(fr.to_val())
513+
}
514+
}
515+
508516
#[cfg(not(target_family = "wasm"))]
509517
impl From<&Fr> for ScVal {
510518
fn from(v: &Fr) -> Self {
@@ -761,3 +769,74 @@ impl Bls12_381 {
761769
U256::try_from_val(env, &v).unwrap_infallible().into()
762770
}
763771
}
772+
773+
#[cfg(test)]
774+
mod test {
775+
use super::*;
776+
777+
#[test]
778+
fn test_g1affine_to_val() {
779+
let env = Env::default();
780+
781+
let g1 = G1Affine::from_bytes(BytesN::from_array(&env, &[1; 96]));
782+
let val: Val = g1.clone().into_val(&env);
783+
let rt: G1Affine = val.into_val(&env);
784+
785+
assert_eq!(g1, rt);
786+
}
787+
788+
#[test]
789+
fn test_ref_g1affine_to_val() {
790+
let env = Env::default();
791+
792+
let g1 = G1Affine::from_bytes(BytesN::from_array(&env, &[1; 96]));
793+
let val: Val = (&g1).into_val(&env);
794+
let rt: G1Affine = val.into_val(&env);
795+
796+
assert_eq!(g1, rt);
797+
}
798+
799+
#[test]
800+
fn test_doule_ref_g1affine_to_val() {
801+
let env = Env::default();
802+
803+
let g1 = G1Affine::from_bytes(BytesN::from_array(&env, &[1; 96]));
804+
let val: Val = (&&g1).into_val(&env);
805+
let rt: G1Affine = val.into_val(&env);
806+
807+
assert_eq!(g1, rt);
808+
}
809+
810+
#[test]
811+
fn test_fr_to_val() {
812+
let env = Env::default();
813+
814+
let fr = Fr::from_bytes(BytesN::from_array(&env, &[1; 32]));
815+
let val: Val = fr.clone().into_val(&env);
816+
let rt: Fr = val.into_val(&env);
817+
818+
assert_eq!(fr, rt);
819+
}
820+
821+
#[test]
822+
fn test_ref_fr_to_val() {
823+
let env = Env::default();
824+
825+
let fr = Fr::from_bytes(BytesN::from_array(&env, &[1; 32]));
826+
let val: Val = (&fr).into_val(&env);
827+
let rt: Fr = val.into_val(&env);
828+
829+
assert_eq!(fr, rt);
830+
}
831+
832+
#[test]
833+
fn test_double_ref_fr_to_val() {
834+
let env = Env::default();
835+
836+
let fr = Fr::from_bytes(BytesN::from_array(&env, &[1; 32]));
837+
let val: Val = (&&fr).into_val(&env);
838+
let rt: Fr = val.into_val(&env);
839+
840+
assert_eq!(fr, rt);
841+
}
842+
}

soroban-sdk/src/map.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,18 @@ where
216216
}
217217
}
218218

219+
impl<K, V> TryFromVal<Env, &Map<K, V>> for Val
220+
where
221+
K: IntoVal<Env, Val> + TryFromVal<Env, Val>,
222+
V: IntoVal<Env, Val> + TryFromVal<Env, Val>,
223+
{
224+
type Error = Infallible;
225+
226+
fn try_from_val(_env: &Env, v: &&Map<K, V>) -> Result<Self, Self::Error> {
227+
Ok(v.to_val())
228+
}
229+
}
230+
219231
impl<K, V> From<Map<K, V>> for Val
220232
where
221233
K: IntoVal<Env, Val> + TryFromVal<Env, Val>,
@@ -657,6 +669,39 @@ mod test {
657669
assert_eq!(map.len(), 0);
658670
}
659671

672+
#[test]
673+
fn test_map_to_val() {
674+
let env = Env::default();
675+
676+
let map = Map::<u32, ()>::from_array(&env, [(0, ()), (1, ()), (2, ()), (3, ())]);
677+
let val: Val = map.clone().into_val(&env);
678+
let rt: Map<u32, ()> = val.into_val(&env);
679+
680+
assert_eq!(map, rt);
681+
}
682+
683+
#[test]
684+
fn test_ref_map_to_val() {
685+
let env = Env::default();
686+
687+
let map = Map::<u32, ()>::from_array(&env, [(0, ()), (1, ()), (2, ()), (3, ())]);
688+
let val: Val = (&map).into_val(&env);
689+
let rt: Map<u32, ()> = val.into_val(&env);
690+
691+
assert_eq!(map, rt);
692+
}
693+
694+
#[test]
695+
fn test_double_ref_map_to_val() {
696+
let env = Env::default();
697+
698+
let map = Map::<u32, ()>::from_array(&env, [(0, ()), (1, ()), (2, ()), (3, ())]);
699+
let val: Val = (&&map).into_val(&env);
700+
let rt: Map<u32, ()> = val.into_val(&env);
701+
702+
assert_eq!(map, rt);
703+
}
704+
660705
#[test]
661706
fn test_raw_vals() {
662707
let env = Env::default();

soroban-sdk/src/string.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@ impl TryFromVal<Env, String> for Val {
111111
}
112112
}
113113

114+
impl TryFromVal<Env, &String> for Val {
115+
type Error = ConversionError;
116+
117+
fn try_from_val(_env: &Env, v: &&String) -> Result<Self, Self::Error> {
118+
Ok(v.to_val())
119+
}
120+
}
121+
114122
impl From<String> for Val {
115123
#[inline(always)]
116124
fn from(v: String) -> Self {
@@ -269,6 +277,7 @@ impl String {
269277
#[cfg(test)]
270278
mod test {
271279
use super::*;
280+
use crate::IntoVal;
272281

273282
#[test]
274283
fn string_from_and_to_slices() {
@@ -311,4 +320,37 @@ mod test {
311320
let mut out = [0u8; 10];
312321
s.copy_into_slice(&mut out);
313322
}
323+
324+
#[test]
325+
fn string_to_val() {
326+
let env = Env::default();
327+
328+
let s = String::from_str(&env, "abcdef");
329+
let val: Val = s.clone().into_val(&env);
330+
let rt: String = val.into_val(&env);
331+
332+
assert_eq!(s, rt);
333+
}
334+
335+
#[test]
336+
fn ref_string_to_val() {
337+
let env = Env::default();
338+
339+
let s = String::from_str(&env, "abcdef");
340+
let val: Val = (&s).into_val(&env);
341+
let rt: String = val.into_val(&env);
342+
343+
assert_eq!(s, rt);
344+
}
345+
346+
#[test]
347+
fn double_ref_string_to_val() {
348+
let env = Env::default();
349+
350+
let s = String::from_str(&env, "abcdef");
351+
let val: Val = (&&s).into_val(&env);
352+
let rt: String = val.into_val(&env);
353+
354+
assert_eq!(s, rt);
355+
}
314356
}

soroban-sdk/src/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ mod contract_store;
2121
mod contract_timepoint;
2222
mod contract_udt_enum;
2323
mod contract_udt_enum_error;
24+
mod contract_udt_enum_int;
2425
mod contract_udt_enum_option;
2526
mod contract_udt_option;
2627
mod contract_udt_struct;

0 commit comments

Comments
 (0)