Skip to content

Commit

Permalink
Merge pull request #1258 from herwinw/io_pipe_encoding
Browse files Browse the repository at this point in the history
Set encoding in IO.pipe when arguments are given
  • Loading branch information
seven1m authored Sep 26, 2023
2 parents 168aea4 + a253d00 commit c110b81
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 52 deletions.
2 changes: 1 addition & 1 deletion include/natalie/io_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class IoObject : public Object {
bool is_closed() const { return m_closed; }
bool is_eof(Env *);
bool isatty(Env *) const;
static Value pipe(Env *, Args, Block *, ClassObject *);
static Value pipe(Env *, Value, Value, Block *, ClassObject *);
int pos(Env *);
Value pread(Env *, Value, Value, Value = nullptr);
Value puts(Env *, Args);
Expand Down
2 changes: 1 addition & 1 deletion lib/natalie/compiler/binding_gen.rb
Original file line number Diff line number Diff line change
Expand Up @@ -843,7 +843,7 @@ def generate_name
gen.binding('Integer', 'zero?', 'IntegerObject', 'is_zero', argc: 0, pass_env: false, pass_block: false, return_type: :bool, optimized: true)

gen.static_binding('IO', 'binread', 'IoObject', 'binread', argc: 1..3, pass_env: true, pass_block: false, return_type: :Object)
gen.static_binding('IO', 'pipe', 'IoObject', 'pipe', argc: :any, pass_env: true, pass_block: true, pass_klass: true, return_type: :Object)
gen.static_binding('IO', 'pipe', 'IoObject', 'pipe', argc: 0..2, pass_env: true, pass_block: true, pass_klass: true, return_type: :Object)
gen.static_binding('IO', 'read', 'IoObject', 'read_file', argc: :any, pass_env: true, pass_block: false, return_type: :Object)
gen.static_binding('IO', 'sysopen', 'IoObject', 'sysopen', argc: 1..3, pass_env: true, pass_block: false, return_type: :Object)
gen.static_binding('IO', 'try_convert', 'IoObject', 'try_convert', argc: 1, pass_env: true, pass_block: false, return_type: :Object)
Expand Down
80 changes: 34 additions & 46 deletions spec/core/io/pipe_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,34 +131,28 @@
end

it "sets the external encoding of the read end when passed an Encoding argument" do
NATFIXME 'Encoding arguments', exception: SpecFailedException do
IO.pipe(Encoding::UTF_8) do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should be_nil
end
IO.pipe(Encoding::UTF_8) do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should be_nil
end
end

it "sets the external and internal encodings of the read end when passed two Encoding arguments" do
NATFIXME 'Encoding arguments', exception: SpecFailedException do
IO.pipe(Encoding::UTF_8, Encoding::UTF_16BE) do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should == Encoding::UTF_16BE
end
IO.pipe(Encoding::UTF_8, Encoding::UTF_16BE) do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should == Encoding::UTF_16BE
end
end

it "sets the external encoding of the read end when passed the name of an Encoding" do
NATFIXME 'Encoding arguments', exception: SpecFailedException do
IO.pipe("UTF-8") do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should be_nil
end
IO.pipe("UTF-8") do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should be_nil
end
end

it "accepts 'bom|' prefix for external encoding" do
NATFIXME 'Encoding arguments', exception: SpecFailedException do
NATFIXME 'BOM UTF-8 encoding', exception: ArgumentError, message: 'unknown encoding name - "BOM|UTF-8"' do
IO.pipe("BOM|UTF-8") do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should be_nil
Expand All @@ -167,16 +161,14 @@
end

it "sets the external and internal encodings specified as a String and separated with a colon" do
NATFIXME 'Encoding arguments', exception: SpecFailedException do
IO.pipe("UTF-8:ISO-8859-1") do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should == Encoding::ISO_8859_1
end
IO.pipe("UTF-8:ISO-8859-1") do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should == Encoding::ISO_8859_1
end
end

it "accepts 'bom|' prefix for external encoding when specifying 'external:internal'" do
NATFIXME 'Encoding arguments', exception: SpecFailedException do
NATFIXME 'BOM UTF-8 encoding', exception: ArgumentError, message: 'unknown encoding name - "BOM|UTF-8"' do
IO.pipe("BOM|UTF-8:ISO-8859-1") do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should == Encoding::ISO_8859_1
Expand All @@ -185,16 +177,14 @@
end

it "sets the external and internal encoding when passed two String arguments" do
NATFIXME 'Encoding arguments', exception: SpecFailedException do
IO.pipe("UTF-8", "UTF-16BE") do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should == Encoding::UTF_16BE
end
IO.pipe("UTF-8", "UTF-16BE") do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should == Encoding::UTF_16BE
end
end

it "accepts an options Hash with one String encoding argument" do
NATFIXME 'Encoding arguments', exception: SpecFailedException do
NATFIXME 'keyword arguments', exception: ArgumentError, message: 'unknown encoding name - "BOM|UTF-8:ISO-8859-1"' do
IO.pipe("BOM|UTF-8:ISO-8859-1", invalid: :replace) do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should == Encoding::ISO_8859_1
Expand All @@ -203,7 +193,7 @@
end

it "accepts an options Hash with two String encoding arguments" do
NATFIXME 'Encoding arguments', exception: SpecFailedException do
NATFIXME 'keyword arguments', exception: ArgumentError, message: 'wrong number of arguments (given 3, expected 0..2)' do
IO.pipe("UTF-8", "ISO-8859-1", invalid: :replace) do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should == Encoding::ISO_8859_1
Expand All @@ -212,30 +202,28 @@
end

it "calls #to_hash to convert an options argument" do
options = mock("io pipe encoding options")
options.should_receive(:to_hash).and_return({ invalid: :replace })
IO.pipe("UTF-8", "ISO-8859-1", **options) { |r, w| }
NATFIXME 'keyword arguments', exception: ArgumentError, message: 'wrong number of arguments (given 3, expected 0..2)' do
options = mock("io pipe encoding options")
options.should_receive(:to_hash).and_return({ invalid: :replace })
IO.pipe("UTF-8", "ISO-8859-1", **options) { |r, w| }
end
end

it "calls #to_str to convert the first argument to a String" do
NATFIXME 'Encoding arguments', exception: SpecFailedException do
obj = mock("io_pipe_encoding")
obj.should_receive(:to_str).and_return("UTF-8:UTF-16BE")
IO.pipe(obj) do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should == Encoding::UTF_16BE
end
obj = mock("io_pipe_encoding")
obj.should_receive(:to_str).and_return("UTF-8:UTF-16BE")
IO.pipe(obj) do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should == Encoding::UTF_16BE
end
end

it "calls #to_str to convert the second argument to a String" do
NATFIXME 'Encoding arguments', exception: SpecFailedException do
obj = mock("io_pipe_encoding")
obj.should_receive(:to_str).at_least(1).times.and_return("UTF-16BE")
IO.pipe(Encoding::UTF_8, obj) do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should == Encoding::UTF_16BE
end
obj = mock("io_pipe_encoding")
obj.should_receive(:to_str).at_least(1).times.and_return("UTF-16BE")
IO.pipe(Encoding::UTF_8, obj) do |r, w|
r.external_encoding.should == Encoding::UTF_8
r.internal_encoding.should == Encoding::UTF_16BE
end
end

Expand Down
6 changes: 2 additions & 4 deletions src/io_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -812,10 +812,7 @@ int IoObject::set_pos(Env *env, Value position) {
return result;
}

Value IoObject::pipe(Env *env, Args args, Block *block, ClassObject *klass) {
/* auto kwargs = */ args.pop_keyword_hash();
args.ensure_argc_between(env, 0, 2);

Value IoObject::pipe(Env *env, Value external_encoding, Value internal_encoding, Block *block, ClassObject *klass) {
int pipefd[2];
#ifdef __APPLE__
// No pipe2, use pipe and set permissions afterwards
Expand All @@ -838,6 +835,7 @@ Value IoObject::pipe(Env *env, Args args, Block *block, ClassObject *klass) {

auto io_read = _new(env, klass, { IntegerObject::create(pipefd[0]) }, nullptr);
auto io_write = _new(env, klass, { IntegerObject::create(pipefd[1]) }, nullptr);
io_read->as_io()->set_encoding(env, external_encoding, internal_encoding);
auto pipes = new ArrayObject { io_read, io_write };

if (!block)
Expand Down

0 comments on commit c110b81

Please sign in to comment.