Subject: | Boolean support, TO_AMF hook |
Firstly, thank you so much for this module!
We are using booleans extensively for both JSON-RPC and AMF, so wanted a way to be able
to roundtrip booleans in AMF. We also missed the TO_JSON functionality from JSON::XS.
I made a patch to implement these, it's pretty rough but works for our internal use.
* Freezes 'boolean' perl objects to AMF boolean
* Freezes JSON::XS boolean objects to AMF boolean
* calls TO_AMF method on an object if present as a freeze hook (code based on JSON::XS)
* Thaws AMF boolean to JSON::XS boolean objects
The test suite now fails on two main points:
* 01 fails as booleans are not thawing to 1/0 as expected (they are JSON::XS booleans)
* 01, 46, 48 and 53 fail as they need to use JSON::XS.
I did not implement the changes for AMF3, only AMF0, and the creation of JSON::XS objects
on thaw should really be an option.
Hope this helps anyone using this wonderful module.
Subject: | AMF.xs.patch |
--- Storable-AMF-0.88/lib/Storable/AMF.xs 2010-11-27 20:02:57.000000000 +0000
+++ Storable-AMF-0.88_patch/lib/Storable/AMF.xs 2011-01-18 22:40:50.000000000 +0000
@@ -589,7 +589,31 @@
++io->RV_COUNT;
if (sv_isobject(one)) {
- if (SvTYPE(rv) == SVt_PVHV){
+ GV *to_amf = gv_fetchmethod_autoload (SvSTASH (rv), "TO_AMF", 0);
+ if ( to_amf ) {
+ dSP;
+
+ ENTER; SAVETMPS; PUSHMARK (SP);
+ XPUSHs (sv_bless (sv_2mortal (newRV_inc (rv)), SvSTASH (rv)));
+
+ // calling with G_SCALAR ensures that we always get a 1 return value
+ PUTBACK;
+ call_sv ((SV *)GvCV (to_amf), G_SCALAR);
+ SPAGAIN;
+
+ // catch this surprisingly common error
+ if (SvROK (TOPs) && SvRV (TOPs) == rv)
+ croak ("%s::TO_AMF method returned same object as was passed instead of a new one", HvNAME (SvSTASH (rv)));
+
+ rv = POPs;
+ PUTBACK;
+
+ //--io->RV_COUNT;
+ format_one( aTHX_ io, rv);
+
+ FREETMPS; LEAVE;
+ }
+ else if (SvTYPE(rv) == SVt_PVHV){
format_typed_object(aTHX_ io, (HV *) rv);
}
else if ( util_is_date( rv ) ) {
@@ -597,6 +621,14 @@
io_write_double(aTHX_ io, util_date_time( rv ));
io_write_s16(aTHX_ io, 0 );
}
+ else if (sv_isa(one, "boolean")) {
+ io_write_marker(aTHX_ io, MARKER0_BOOLEAN );
+ io_write_u8(aTHX_ io, SvIV(SvRV(one)));
+ }
+ else if (sv_isa(one, "JSON::XS::Boolean")) {
+ io_write_marker(aTHX_ io, MARKER0_BOOLEAN );
+ io_write_u8(aTHX_ io, SvIV(SvRV(one)));
+ }
else {
// may be i has to format as undef
io_register_error(io, ERR_BAD_OBJECT);
@@ -1285,7 +1317,33 @@
STATIC_INLINE SV* parse_boolean(pTHX_ struct io_struct * io){
char marker;
marker = io_read_marker(io);
- return newSViv(marker == '\000' ? 0 :1);
+
+ int count;
+ SV *value = 0;
+ SAVETMPS;
+
+ dSP;
+
+ ENTER; SAVETMPS; PUSHMARK (SP);
+ PUTBACK;
+ if ( marker == '\000' ) {
+ count = call_pv("JSON::XS::false", G_SCALAR);
+ }
+ else {
+ count = call_pv("JSON::XS::true", G_SCALAR);
+ }
+ SPAGAIN;
+ if (count == 1)
+ value = newSVsv(POPs);
+
+ if (count != 1 || !SvOK(value)) {
+ // fallback, return 0/1
+ value = newSViv( marker == '\000' ? 0 : 1 );
+ }
+
+ PUTBACK;
+ FREETMPS; LEAVE;
+ return value;
}
inline SV * amf3_parse_one(pTHX_ struct io_struct *io);