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

Commit 40e8291

Browse files
authored
Merge pull request #315 from lumen/integer_to_list/1
integer_to_list/1
2 parents 7abf964 + a0da70d commit 40e8291

File tree

8 files changed

+150
-16
lines changed

8 files changed

+150
-16
lines changed

liblumen_alloc/src/erts/term/list.rs

+18
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use core::mem;
77
use core::ptr;
88

99
use crate::borrow::CloneToProcess;
10+
use crate::erts::exception::runtime;
1011
use crate::erts::exception::system::Alloc;
1112
use crate::erts::term::{AsTerm, Boxed, Term, TypeError, TypedTerm};
1213
use crate::erts::{to_word_size, HeapAlloc, StackAlloc};
@@ -331,6 +332,23 @@ impl TryFrom<TypedTerm> for Boxed<Cons> {
331332
}
332333
}
333334

335+
impl TryInto<String> for Boxed<Cons> {
336+
type Error = runtime::Exception;
337+
338+
fn try_into(self) -> Result<String, Self::Error> {
339+
self.into_iter()
340+
.map(|result| match result {
341+
Ok(element) => {
342+
let result_char: Result<char, _> = element.try_into().map_err(|_| badarg!());
343+
344+
result_char
345+
}
346+
Err(_) => Err(badarg!()),
347+
})
348+
.collect()
349+
}
350+
}
351+
334352
pub struct ListBuilder<'a, A: HeapAlloc> {
335353
heap: &'a mut A,
336354
element: Option<Term>,

liblumen_alloc/src/erts/term/typed_term.rs

+2
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,8 @@ impl TryInto<String> for TypedTerm {
969969
TypedTerm::SubBinary(subbinary) => subbinary.try_into(),
970970
TypedTerm::ProcBin(process_binary) => process_binary.try_into(),
971971
TypedTerm::MatchContext(match_context) => match_context.try_into(),
972+
TypedTerm::Nil => Ok("".to_string()),
973+
TypedTerm::List(boxed_cons) => boxed_cons.try_into(),
972974
_ => Err(badarg!()),
973975
}
974976
}

lumen_runtime/src/otp/erlang.rs

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ pub mod hd_1;
5858
pub mod insert_element_3;
5959
pub mod integer_to_binary_1;
6060
pub mod integer_to_binary_2;
61+
pub mod integer_to_list_1;
62+
mod integer_to_string;
6163
pub mod is_alive_0;
6264
pub mod is_atom_1;
6365
pub mod is_binary_1;

lumen_runtime/src/otp/erlang/integer_to_binary_1.rs

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

8-
use liblumen_alloc::badarg;
98
use liblumen_alloc::erts::exception;
109
use liblumen_alloc::erts::process::Process;
11-
use liblumen_alloc::erts::term::{Term, TypedTerm};
10+
use liblumen_alloc::erts::term::Term;
1211

1312
use lumen_runtime_macros::native_implemented_function;
1413

14+
use crate::otp::erlang::integer_to_string::integer_to_string;
15+
1516
#[native_implemented_function(integer_to_binary/1)]
1617
pub fn native(process: &Process, integer: Term) -> exception::Result {
17-
let option_string: Option<String> = match integer.to_typed_term().unwrap() {
18-
TypedTerm::SmallInteger(small_integer) => Some(small_integer.to_string()),
19-
TypedTerm::Boxed(boxed) => match boxed.to_typed_term().unwrap() {
20-
TypedTerm::BigInteger(big_integer) => Some(big_integer.to_string()),
21-
_ => None,
22-
},
23-
_ => None,
24-
};
25-
26-
match option_string {
27-
Some(string) => process
18+
integer_to_string(integer).and_then(|string| {
19+
process
2820
.binary_from_str(&string)
29-
.map_err(|alloc| alloc.into()),
30-
None => Err(badarg!().into()),
31-
}
21+
.map_err(|alloc| alloc.into())
22+
})
3223
}
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::integer_to_string;
15+
16+
#[native_implemented_function(integer_to_list/1)]
17+
pub fn native(process: &Process, integer: Term) -> exception::Result {
18+
integer_to_string(integer).and_then(|string| {
19+
process
20+
.list_from_chars(string.chars())
21+
.map_err(|alloc| alloc.into())
22+
})
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
mod with_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_1::native;
9+
use crate::scheduler::with_process_arc;
10+
use crate::test::strategy;
11+
12+
#[test]
13+
fn without_integer_errors_badarg() {
14+
with_process_arc(|arc_process| {
15+
TestRunner::new(Config::with_source_file(file!()))
16+
.run(
17+
&strategy::term::is_not_integer(arc_process.clone()),
18+
|binary| {
19+
prop_assert_eq!(native(&arc_process, binary), Err(badarg!().into()));
20+
21+
Ok(())
22+
},
23+
)
24+
.unwrap();
25+
});
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use super::*;
2+
3+
use std::convert::TryInto;
4+
5+
#[test]
6+
fn with_small_integer_returns_list() {
7+
with_process_arc(|arc_process| {
8+
TestRunner::new(Config::with_source_file(file!()))
9+
.run(&strategy::term::integer::small::isize(), |integer_isize| {
10+
let integer = arc_process.integer(integer_isize).unwrap();
11+
12+
let result = native(&arc_process, integer);
13+
14+
prop_assert!(result.is_ok());
15+
16+
let term = result.unwrap();
17+
18+
prop_assert!(term.is_list());
19+
20+
let string: String = term.try_into().unwrap();
21+
22+
prop_assert_eq!(string, integer_isize.to_string());
23+
24+
Ok(())
25+
})
26+
.unwrap();
27+
});
28+
}
29+
30+
#[test]
31+
fn with_big_integer_returns_list() {
32+
with_process_arc(|arc_process| {
33+
TestRunner::new(Config::with_source_file(file!()))
34+
.run(&strategy::term::integer::big::isize(), |integer_isize| {
35+
let integer = arc_process.integer(integer_isize).unwrap();
36+
37+
let result = native(&arc_process, integer);
38+
39+
prop_assert!(result.is_ok());
40+
41+
let term = result.unwrap();
42+
43+
prop_assert!(term.is_list());
44+
45+
let string: String = term.try_into().unwrap();
46+
47+
prop_assert_eq!(string, integer_isize.to_string());
48+
49+
Ok(())
50+
})
51+
.unwrap();
52+
});
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use liblumen_alloc::badarg;
2+
use liblumen_alloc::erts::exception::Exception;
3+
use liblumen_alloc::erts::term::{Term, TypedTerm};
4+
5+
pub fn integer_to_string(integer: Term) -> Result<String, Exception> {
6+
let option_string: Option<String> = match integer.to_typed_term().unwrap() {
7+
TypedTerm::SmallInteger(small_integer) => Some(small_integer.to_string()),
8+
TypedTerm::Boxed(boxed) => match boxed.to_typed_term().unwrap() {
9+
TypedTerm::BigInteger(big_integer) => Some(big_integer.to_string()),
10+
_ => None,
11+
},
12+
_ => None,
13+
};
14+
15+
match option_string {
16+
Some(string) => Ok(string),
17+
None => Err(badarg!().into()),
18+
}
19+
}

0 commit comments

Comments
 (0)