Class: Oj::Rails::Encoder

Inherits:
Object
  • Object
show all
Defined in:
ext/oj/rails.c,
ext/oj/rails.c

Overview

The Oj ActiveSupport compliant encoder.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.new(*args) ⇒ Object



754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
# File 'ext/oj/rails.c', line 754

static VALUE encoder_new(int argc, VALUE *argv, VALUE self) {
    Encoder e = OJ_R_ALLOC(struct _encoder);

    e->ropts.len   = 0;
    e->ropts.alen  = 0;
    e->ropts.table = NULL;
    e->own_ropts   = false;

    if (1 <= argc && Qnil != *argv) {
        e->arg = *argv;
    } else {
        e->arg = rb_hash_new();
    }
    // An encoder given no options of its own reads oj_default_options at encode
    // time rather than copying it here. ActiveSupport keeps such an encoder for
    // the life of the process, so a copy taken now would freeze every later
    // Oj.default_options and ActiveSupport::JSON::Encoding change out of it -
    // including the time_precision that set_encoder itself writes after
    // ActiveSupport has already built and cached that encoder.
    //
    // A hash counts as options only if at least one key names an option Oj
    // knows. Non-empty is not enough: ActiveSupport 8.1 caches a second encoder
    // built with {escape: false}, a key Oj has never had.
    e->own_opts = T_HASH == rb_type(e->arg) && 0 < RHASH_SIZE(e->arg);
    if (e->own_opts) {
        e->opts = oj_default_options;
        // Detach from the match_string regexps owned by the defaults before the
        // options are parsed so that a :match_string option builds a chain of
        // its own that is freed with the encoder.
        e->opts.str_rx.head = NULL;
        e->opts.str_rx.tail = NULL;
        e->own_opts         = oj_parse_options_consumed(e->arg, &e->opts);
    }
    if (e->own_opts) {
        oj_options_take_ownership(&e->opts);
    } else {
        // Nothing to free: every option that allocates is reached through a
        // recognized key, and ownership is not taken until after that check.
        memset(&e->opts, 0, sizeof(e->opts));
    }

    return TypedData_Wrap_Struct(encoder_class, &oj_encoder_type, e);
}

Instance Method Details

#deoptimize(*args) ⇒ Object



943
944
945
946
947
948
949
950
# File 'ext/oj/rails.c', line 943

static VALUE encoder_deoptimize(int argc, VALUE *argv, VALUE self) {
    Encoder e;
    TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);

    optimize(argc, argv, encoder_own_ropts(e), false);

    return Qnil;
}

#encode(obj) ⇒ Object



1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
# File 'ext/oj/rails.c', line 1082

static VALUE encoder_encode(VALUE self, VALUE obj) {
    Encoder e;
    TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);

    if (Qnil != e->arg) {
        // as_json is allowed to write into the options hash it is handed, and
        // the ActiveSupport suite has a test that does exactly that. Handing
        // out the encoder's own hash lets one such call poison every later
        // encode by the same encoder, which on ActiveSupport 8.1 is every
        // option-less to_json in the process because json_encoder= caches one
        // encoder and keeps it. Rails never exposes a hash it will reuse:
        // JSONGemEncoder#encode passes options.dup, and only when there are
        // options at all, so with none as_json writes into its own default.
        // The copy is not frozen the way Rails 8.0 and later freeze theirs,
        // because Oj hands as_json the hash even when it is empty and that is
        // exactly the case Rails leaves writable.
        VALUE argv[1] = {T_HASH == rb_type(e->arg) ? rb_hash_dup(e->arg) : e->arg};

        return encode(obj, encoder_ropts(e), encoder_opts(e), 1, argv);
    }
    return encode(obj, encoder_ropts(e), encoder_opts(e), 0, NULL);
}

#optimize(*args) ⇒ Object



886
887
888
889
890
891
892
893
# File 'ext/oj/rails.c', line 886

static VALUE encoder_optimize(int argc, VALUE *argv, VALUE self) {
    Encoder e;
    TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);

    optimize(argc, argv, encoder_own_ropts(e), true);

    return Qnil;
}

#optimized?(clas) ⇒ Object



973
974
975
976
977
978
979
980
981
982
983
984
# File 'ext/oj/rails.c', line 973

static VALUE encoder_optimized(VALUE self, VALUE clas) {
    Encoder e;
    ROpt    ro;

    TypedData_Get_Struct(self, struct _encoder, &oj_encoder_type, e);
    ro = oj_rails_get_opt(encoder_ropts(e), clas);

    if (NULL == ro) {
        return Qfalse;
    }
    return (ro->on) ? Qtrue : Qfalse;
}