summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2014-08-11 09:07:25 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2014-08-23 11:16:14 -0700
commit5d35f31762750169569eb5ae9ce51b9af8a91793 (patch)
tree1f23d0cd156fc05791bc16d9d105868477c189b2
parent3759f4e96d3800260e3d942dd225867c13e78b33 (diff)
downloadffi-yajl-5d35f31762750169569eb5ae9ce51b9af8a91793.tar.gz
add datetime encoding
necessary for ohai json_gem spec complies with JSON gem format. this also arguably fixes issues with yajl-ruby where it does not encode date objects correctly.
-rw-r--r--ext/ffi_yajl/ext/encoder/encoder.c29
-rw-r--r--lib/ffi_yajl/ffi/encoder.rb28
-rw-r--r--lib/ffi_yajl/json_gem.rb19
-rw-r--r--spec/ffi_yajl/encoder_spec.rb15
-rw-r--r--spec/ffi_yajl/json_gem_spec.rb14
5 files changed, 92 insertions, 13 deletions
diff --git a/ext/ffi_yajl/ext/encoder/encoder.c b/ext/ffi_yajl/ext/encoder/encoder.c
index 26ae368..371752b 100644
--- a/ext/ffi_yajl/ext/encoder/encoder.c
+++ b/ext/ffi_yajl/ext/encoder/encoder.c
@@ -2,6 +2,7 @@
#include <yajl/yajl_gen.h>
static VALUE mFFI_Yajl, mExt, mEncoder, mEncoder2, cEncodeError;
+static VALUE cDate, cTime, cDateTime;
static VALUE cYajl_Gen;
/* FIXME: the json gem does a whole bunch of indirection around monkeypatching... not sure if we need to as well... */
@@ -62,7 +63,6 @@ int rb_cHash_ffi_yajl_callback(VALUE key, VALUE val, VALUE extra) {
VALUE state = rb_hash_aref(extra, rb_str_new2("state"));
VALUE rb_yajl_gen = rb_hash_aref(extra, rb_str_new2("yajl_gen"));
-
rb_hash_aset(state, rb_str_new2("processing_key"), Qtrue);
rb_funcall(key, sym_ffi_yajl, 2, rb_yajl_gen, state);
rb_hash_aset(state, rb_str_new2("processing_key"), Qfalse);
@@ -227,7 +227,8 @@ static VALUE rb_cString_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
return Qnil;
}
-static VALUE rb_cSymbol_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
+/* calls #to_s on an object to encode it */
+static VALUE object_to_s_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
yajl_gen_status status;
ID sym_to_s = rb_intern("to_s");
VALUE str = rb_funcall(self, sym_to_s, 0);
@@ -241,6 +242,22 @@ static VALUE rb_cSymbol_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
return Qnil;
}
+static VALUE rb_cSymbol_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
+ return object_to_s_ffi_yajl(self, rb_yajl_gen, state);
+}
+
+static VALUE rb_cDate_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
+ return object_to_s_ffi_yajl(self, rb_yajl_gen, state);
+}
+
+static VALUE rb_cTime_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
+ return object_to_s_ffi_yajl(self, rb_yajl_gen, state);
+}
+
+static VALUE rb_cDateTime_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
+ return object_to_s_ffi_yajl(self, rb_yajl_gen, state);
+}
+
static VALUE rb_cObject_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) {
yajl_gen_status status;
ID sym_to_json = rb_intern("to_json");
@@ -265,6 +282,10 @@ void Init_encoder() {
cYajl_Gen = rb_define_class_under(mEncoder, "YajlGen", rb_cObject);
rb_define_method(mEncoder, "do_yajl_encode", mEncoder_do_yajl_encode, 3);
+ cDate = rb_define_class("Date", rb_cObject);
+ cTime = rb_define_class("Time", rb_cObject);
+ cDateTime = rb_define_class("DateTime", cDate);
+
rb_define_method(rb_cHash, "ffi_yajl", rb_cHash_ffi_yajl, 2);
rb_define_method(rb_cArray, "ffi_yajl", rb_cArray_ffi_yajl, 2);
rb_define_method(rb_cNilClass, "ffi_yajl", rb_cNilClass_ffi_yajl, 2);
@@ -275,6 +296,8 @@ void Init_encoder() {
rb_define_method(rb_cFloat, "ffi_yajl", rb_cFloat_ffi_yajl, 2);
rb_define_method(rb_cString, "ffi_yajl", rb_cString_ffi_yajl, 2);
rb_define_method(rb_cSymbol, "ffi_yajl", rb_cSymbol_ffi_yajl, 2);
+ rb_define_method(cDate, "ffi_yajl", rb_cDate_ffi_yajl, 2);
+ rb_define_method(cTime, "ffi_yajl", rb_cTime_ffi_yajl, 2);
+ rb_define_method(cDateTime, "ffi_yajl", rb_cDateTime_ffi_yajl, 2);
rb_define_method(rb_cObject, "ffi_yajl", rb_cObject_ffi_yajl, 2);
}
-
diff --git a/lib/ffi_yajl/ffi/encoder.rb b/lib/ffi_yajl/ffi/encoder.rb
index 3bad69f..b82c0fe 100644
--- a/lib/ffi_yajl/ffi/encoder.rb
+++ b/lib/ffi_yajl/ffi/encoder.rb
@@ -171,6 +171,33 @@ class String
end
end
+class Date
+ def ffi_yajl(yajl_gen, state)
+ str = self.to_s
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
+ FFI_Yajl::Encoder.raise_error_for_status(status)
+ end
+ end
+end
+
+class Time
+ def ffi_yajl(yajl_gen, state)
+ str = self.to_s
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
+ FFI_Yajl::Encoder.raise_error_for_status(status)
+ end
+ end
+end
+
+class DateTime
+ def ffi_yajl(yajl_gen, state)
+ str = self.to_s
+ if ( status = FFI_Yajl.yajl_gen_string(yajl_gen, str, str.bytesize) ) != 0
+ FFI_Yajl::Encoder.raise_error_for_status(status)
+ end
+ end
+end
+
# I feel dirty
class Object
def ffi_yajl(yajl_gen, state)
@@ -180,4 +207,3 @@ class Object
end
end
end
-
diff --git a/lib/ffi_yajl/json_gem.rb b/lib/ffi_yajl/json_gem.rb
index 6a3b139..47586b6 100644
--- a/lib/ffi_yajl/json_gem.rb
+++ b/lib/ffi_yajl/json_gem.rb
@@ -101,6 +101,24 @@ class NilClass
end
end
+class Date
+ def to_json(*opts, &block)
+ FFI_Yajl::Encoder.encode(self, *opts)
+ end
+end
+
+class Time
+ def to_json(*opts, &block)
+ FFI_Yajl::Encoder.encode(self, *opts)
+ end
+end
+
+class DateTime
+ def to_json(*opts, &block)
+ FFI_Yajl::Encoder.encode(self, *opts)
+ end
+end
+
module ::Kernel
def JSON(object, opts = {})
if object.respond_to? :to_s
@@ -118,4 +136,3 @@ class Object
end
end
end
-
diff --git a/spec/ffi_yajl/encoder_spec.rb b/spec/ffi_yajl/encoder_spec.rb
index 67945e0..969481a 100644
--- a/spec/ffi_yajl/encoder_spec.rb
+++ b/spec/ffi_yajl/encoder_spec.rb
@@ -60,4 +60,19 @@ describe "FFI_Yajl::Encoder" do
end
end
+ it "can encode Date objects" do
+ ruby = Date.parse('2001-02-03')
+ expect(encoder.encode(ruby)).to eq( %q{"2001-02-03"} )
+ end
+
+ it "can encode Time objects" do
+ ruby = DateTime.parse('2001-02-03T04:05:06.1+07:00').to_time
+ expect(encoder.encode(ruby)).to eq( %q{"2001-02-02 13:05:06 -0800"} )
+ end
+
+ it "can encode DateTime objects" do
+ ruby = DateTime.parse('2001-02-03T04:05:06.1+07:00')
+ expect(encoder.encode(ruby)).to eq( %q{"2001-02-03T04:05:06+07:00"} )
+ end
+
end
diff --git a/spec/ffi_yajl/json_gem_spec.rb b/spec/ffi_yajl/json_gem_spec.rb
index 36233eb..bfb9e2b 100644
--- a/spec/ffi_yajl/json_gem_spec.rb
+++ b/spec/ffi_yajl/json_gem_spec.rb
@@ -149,18 +149,18 @@ describe "JSON Gem Compat API" do
end
it "encodes Time values correctly" do
- t = Time.new
- expect(t.to_json).to eq( %Q{"#{t.to_s}"} )
+ t = DateTime.parse('2001-02-03T04:05:06.1+07:00').to_time
+ expect(t.to_json).to eq( %Q{"2001-02-02 13:05:06 -0800"} )
end
it "encodes Date values correctly" do
- da = Date.new
- expect(da.to_json).to eq( %Q{"#{da.to_s}"} )
+ da = Date.parse('2001-02-03')
+ expect(da.to_json).to eq( %Q{"2001-02-03"} )
end
it "encodes DateTime values correctly" do
- dt = DateTime.new
- expect(dt.to_json).to eq( %Q{"#{dt.to_s}"} )
+ dt = DateTime.parse('2001-02-03T04:05:06.1+07:00')
+ expect(dt.to_json).to eq( %Q{"2001-02-03T04:05:06+07:00"} )
end
end
@@ -230,7 +230,6 @@ describe "JSON Gem Compat API" do
it_behaves_like "handles encoding and parsing correctly"
end
-
context "when dealing with common UTF-8 symbols" do
let(:ruby) { [ "© ≠ €! \01" ] }
let(:json) { "[\"© ≠ €! \\u0001\"]" }
@@ -277,7 +276,6 @@ describe "JSON Gem Compat API" do
end
end
-
context "when encoding basic types with #to_json" do
it "Array#to_json should work" do
expect([ "a", "b", "c" ].to_json).to eq(%Q{["a","b","c"]})