Skip to content
This repository was archived by the owner on Jun 10, 2024. It is now read-only.

Commit 1f525a4

Browse files
committed
integer_to_list/2
Part of #143
1 parent a0da70d commit 1f525a4

8 files changed

+194
-47
lines changed

lumen_runtime/src/otp/erlang.rs

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ pub mod insert_element_3;
5959
pub mod integer_to_binary_1;
6060
pub mod integer_to_binary_2;
6161
pub mod integer_to_list_1;
62+
pub mod integer_to_list_2;
6263
mod integer_to_string;
6364
pub mod is_alive_0;
6465
pub mod is_atom_1;

lumen_runtime/src/otp/erlang/integer_to_binary_1.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ use liblumen_alloc::erts::term::Term;
1111

1212
use lumen_runtime_macros::native_implemented_function;
1313

14-
use crate::otp::erlang::integer_to_string::integer_to_string;
14+
use crate::otp::erlang::integer_to_string::decimal_integer_to_string;
1515

1616
#[native_implemented_function(integer_to_binary/1)]
1717
pub fn native(process: &Process, integer: Term) -> exception::Result {
18-
integer_to_string(integer).and_then(|string| {
18+
decimal_integer_to_string(integer).and_then(|string| {
1919
process
2020
.binary_from_str(&string)
2121
.map_err(|alloc| alloc.into())

lumen_runtime/src/otp/erlang/integer_to_binary_2.rs

+6-42
Original file line numberDiff line numberDiff line change
@@ -5,55 +5,19 @@
55
#[cfg(all(not(target_arch = "wasm32"), test))]
66
mod test;
77

8-
use std::convert::TryInto;
9-
10-
use num_bigint::BigInt;
11-
12-
use radix_fmt::radix;
13-
14-
use liblumen_alloc::badarg;
158
use liblumen_alloc::erts::exception;
169
use liblumen_alloc::erts::process::Process;
17-
use liblumen_alloc::erts::term::{Term, TypedTerm};
10+
use liblumen_alloc::erts::term::Term;
1811

1912
use lumen_runtime_macros::native_implemented_function;
2013

21-
use crate::otp::erlang::base::Base;
14+
use crate::otp::erlang::integer_to_string::base_integer_to_string;
2215

2316
#[native_implemented_function(integer_to_binary/2)]
2417
pub fn native(process: &Process, integer: Term, base: Term) -> exception::Result {
25-
let base: Base = base.try_into()?;
26-
27-
let option_string: Option<String> = match integer.to_typed_term().unwrap() {
28-
TypedTerm::SmallInteger(small_integer) => {
29-
let integer_isize: isize = small_integer.into();
30-
31-
let (sign, radix) = if integer_isize < 0 {
32-
let radix = radix(-1 * integer_isize, base.base());
33-
34-
("-", radix)
35-
} else {
36-
let radix = radix(integer_isize, base.base());
37-
("", radix)
38-
};
39-
40-
Some(format!("{}{}", sign, radix))
41-
}
42-
TypedTerm::Boxed(boxed) => match boxed.to_typed_term().unwrap() {
43-
TypedTerm::BigInteger(big_integer) => {
44-
let big_int: &BigInt = big_integer.as_ref().into();
45-
46-
Some(big_int.to_str_radix(base.radix()))
47-
}
48-
_ => None,
49-
},
50-
_ => None,
51-
};
52-
53-
match option_string {
54-
Some(string) => process
18+
base_integer_to_string(base, integer).and_then(|string| {
19+
process
5520
.binary_from_str(&string)
56-
.map_err(|alloc| alloc.into()),
57-
None => Err(badarg!().into()),
58-
}
21+
.map_err(|alloc| alloc.into())
22+
})
5923
}

lumen_runtime/src/otp/erlang/integer_to_list_1.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ use liblumen_alloc::erts::term::Term;
1111

1212
use lumen_runtime_macros::native_implemented_function;
1313

14-
use crate::otp::erlang::integer_to_string::integer_to_string;
14+
use crate::otp::erlang::integer_to_string::decimal_integer_to_string;
1515

1616
#[native_implemented_function(integer_to_list/1)]
1717
pub fn native(process: &Process, integer: Term) -> exception::Result {
18-
integer_to_string(integer).and_then(|string| {
18+
decimal_integer_to_string(integer).and_then(|string| {
1919
process
2020
.list_from_chars(string.chars())
2121
.map_err(|alloc| alloc.into())
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// wasm32 proptest cannot be compiled at the same time as non-wasm32 proptest, so disable tests that
2+
// use proptest completely for wasm32
3+
//
4+
// See https://github.com/rust-lang/cargo/issues/4866
5+
#[cfg(all(not(target_arch = "wasm32"), test))]
6+
mod test;
7+
8+
use liblumen_alloc::erts::exception;
9+
use liblumen_alloc::erts::process::Process;
10+
use liblumen_alloc::erts::term::Term;
11+
12+
use lumen_runtime_macros::native_implemented_function;
13+
14+
use crate::otp::erlang::integer_to_string::base_integer_to_string;
15+
16+
#[native_implemented_function(integer_to_binary/2)]
17+
pub fn native(process: &Process, integer: Term, base: Term) -> exception::Result {
18+
base_integer_to_string(base, integer).and_then(|string| {
19+
process
20+
.charlist_from_str(&string)
21+
.map_err(|alloc| alloc.into())
22+
})
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
mod with_integer_integer;
2+
3+
use proptest::test_runner::{Config, TestRunner};
4+
use proptest::{prop_assert, prop_assert_eq};
5+
6+
use liblumen_alloc::badarg;
7+
8+
use crate::otp::erlang::integer_to_list_2::native;
9+
use crate::scheduler::with_process_arc;
10+
use crate::test::strategy;
11+
12+
#[test]
13+
fn without_integer_integer_errors_badarg() {
14+
with_process_arc(|arc_process| {
15+
TestRunner::new(Config::with_source_file(file!()))
16+
.run(
17+
&(
18+
strategy::term::is_not_integer(arc_process.clone()),
19+
strategy::term::is_base(arc_process.clone()),
20+
),
21+
|(integer, base)| {
22+
prop_assert_eq!(native(&arc_process, integer, base), Err(badarg!().into()));
23+
24+
Ok(())
25+
},
26+
)
27+
.unwrap();
28+
});
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
use super::*;
2+
3+
use std::convert::TryInto;
4+
5+
use proptest::arbitrary::any;
6+
use proptest::strategy::{Just, Strategy};
7+
8+
#[test]
9+
fn without_base_base_errors_badarg() {
10+
with_process_arc(|arc_process| {
11+
TestRunner::new(Config::with_source_file(file!()))
12+
.run(
13+
&(
14+
strategy::term::is_integer(arc_process.clone()),
15+
strategy::term::is_not_base(arc_process.clone()),
16+
),
17+
|(integer, base)| {
18+
prop_assert_eq!(native(&arc_process, integer, base), Err(badarg!().into()));
19+
20+
Ok(())
21+
},
22+
)
23+
.unwrap();
24+
});
25+
}
26+
27+
#[test]
28+
fn with_base_base_returns_list() {
29+
with_process_arc(|arc_process| {
30+
TestRunner::new(Config::with_source_file(file!()))
31+
.run(
32+
&(any::<isize>(), strategy::base::base()),
33+
|(integer_isize, base_u8)| {
34+
let integer = arc_process.integer(integer_isize).unwrap();
35+
let base = arc_process.integer(base_u8).unwrap();
36+
37+
let result = native(&arc_process, integer, base);
38+
39+
prop_assert!(result.is_ok());
40+
41+
let list = result.unwrap();
42+
43+
prop_assert!(list.is_list());
44+
45+
Ok(())
46+
},
47+
)
48+
.unwrap();
49+
});
50+
}
51+
52+
#[test]
53+
fn with_negative_integer_returns_list_in_base_with_negative_sign_in_front_of_non_negative_list() {
54+
TestRunner::new(Config::with_source_file(file!()))
55+
.run(
56+
&((std::isize::MIN..=-1_isize), strategy::base::base()).prop_flat_map(
57+
|(negative_isize, base_u8)| {
58+
(Just(negative_isize), Just(base_u8), strategy::process())
59+
},
60+
),
61+
|(negative_isize, base_u8, arc_process)| {
62+
let base = arc_process.integer(base_u8).unwrap();
63+
64+
let positive_isize = -1 * negative_isize;
65+
let positive_integer = arc_process.integer(positive_isize).unwrap();
66+
let positive_list = native(&arc_process, positive_integer, base).unwrap();
67+
let positive_string: String = positive_list.try_into().unwrap();
68+
let expected_negative_string = format!("-{}", positive_string);
69+
let expected_negative_list = arc_process
70+
.charlist_from_str(&expected_negative_string)
71+
.unwrap();
72+
73+
let negative_integer = arc_process.integer(negative_isize).unwrap();
74+
75+
let result = native(&arc_process, negative_integer, base);
76+
77+
prop_assert!(result.is_ok());
78+
79+
let list = result.unwrap();
80+
81+
prop_assert_eq!(list, expected_negative_list);
82+
83+
Ok(())
84+
},
85+
)
86+
.unwrap();
87+
}

lumen_runtime/src/otp/erlang/integer_to_string.rs

+44-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,51 @@
1+
use std::convert::TryInto;
2+
3+
use num_bigint::BigInt;
4+
5+
use radix_fmt::radix;
6+
17
use liblumen_alloc::badarg;
28
use liblumen_alloc::erts::exception::Exception;
39
use liblumen_alloc::erts::term::{Term, TypedTerm};
410

5-
pub fn integer_to_string(integer: Term) -> Result<String, Exception> {
11+
use crate::otp::erlang::base::Base;
12+
13+
pub fn base_integer_to_string(base: Term, integer: Term) -> Result<String, Exception> {
14+
let base: Base = base.try_into()?;
15+
16+
let option_string: Option<String> = match integer.to_typed_term().unwrap() {
17+
TypedTerm::SmallInteger(small_integer) => {
18+
let integer_isize: isize = small_integer.into();
19+
20+
let (sign, radix) = if integer_isize < 0 {
21+
let radix = radix(-1 * integer_isize, base.base());
22+
23+
("-", radix)
24+
} else {
25+
let radix = radix(integer_isize, base.base());
26+
("", radix)
27+
};
28+
29+
Some(format!("{}{}", sign, radix))
30+
}
31+
TypedTerm::Boxed(boxed) => match boxed.to_typed_term().unwrap() {
32+
TypedTerm::BigInteger(big_integer) => {
33+
let big_int: &BigInt = big_integer.as_ref().into();
34+
35+
Some(big_int.to_str_radix(base.radix()))
36+
}
37+
_ => None,
38+
},
39+
_ => None,
40+
};
41+
42+
match option_string {
43+
Some(string) => Ok(string),
44+
None => Err(badarg!().into()),
45+
}
46+
}
47+
48+
pub fn decimal_integer_to_string(integer: Term) -> Result<String, Exception> {
649
let option_string: Option<String> = match integer.to_typed_term().unwrap() {
750
TypedTerm::SmallInteger(small_integer) => Some(small_integer.to_string()),
851
TypedTerm::Boxed(boxed) => match boxed.to_typed_term().unwrap() {

0 commit comments

Comments
 (0)