Options is picklable, _skip_single_line does not drop exceptions
diff --git a/src/_decoder.pyx b/src/_decoder.pyx
index ee2708a..c519380 100644
--- a/src/_decoder.pyx
+++ b/src/_decoder.pyx
@@ -2,13 +2,15 @@
     NO_EXTRA_DATA = 0x0011_0000
 
 
-cdef void _skip_single_line(ReaderRef reader):
+cdef boolean _skip_single_line(ReaderRef reader) except False:
     cdef uint32_t c0
     while _reader_good(reader):
         c0 = _reader_get(reader)
         if _is_line_terminator(c0):
             break
 
+    return True
+
 
 cdef boolean _skip_multiline_comment(ReaderRef reader) except False:
     cdef uint32_t c0
diff --git a/src/_encoder.pyx b/src/_encoder.pyx
index 7e074aa..96eabb0 100644
--- a/src/_encoder.pyx
+++ b/src/_encoder.pyx
@@ -289,14 +289,10 @@
     if expect(formatter_string is None, False):
         _raise_unstringifiable(data)
 
-    formatter_string = formatter_string % data
-    if PyUnicode_IS_ASCII(formatter_string):
-        string = <const char*> PyUnicode_1BYTE_DATA(formatter_string)
-        length = PyUnicode_GET_LENGTH(formatter_string)
-    else:
-        string = PyUnicode_AsUTF8AndSize(formatter_string, &length)
-
+    formatter_string = PyUnicode_Format(formatter_string, data)
+    string = PyUnicode_AsUTF8AndSize(formatter_string, &length)
     writer.append_s(writer, string, length)
+
     return True
 
 
diff --git a/src/_encoder_options.pyx b/src/_encoder_options.pyx
index daff41e..b96b599 100644
--- a/src/_encoder_options.pyx
+++ b/src/_encoder_options.pyx
@@ -24,6 +24,14 @@
     return datum
 
 
+cdef object _options_reduce_arg(object key, object value, object default):
+    if value != default:
+        if value is not None:
+            return key, value
+        else:
+            return key, False
+
+
 cdef object _option_from_ascii(object name, object value, object default):
     if value == default:
         return
@@ -47,6 +55,8 @@
 
 
 @final
+@no_gc
+@freelist(8)
 @auto_pickle(False)
 cdef class Options:
     '''
@@ -130,16 +140,17 @@
     '''
 
     def __reduce__(self):
-        '''
-        Pickling is not supported (yet).
-        '''
-        raise NotImplementedError
-
-    def __reduce_ex__(self, protocol):
-        '''
-        Pickling is not supported (yet).
-        '''
-        raise NotImplementedError
+        cdef object args = tuple(filter(bool, (
+            _options_reduce_arg('quotationmark', self.quotationmark, DEFAULT_QUOTATIONMARK),
+            _options_reduce_arg('tojson', self.tojson, None),
+            _options_reduce_arg('posinfinity', self.posinfinity, DEFAULT_POSINFINITY),
+            _options_reduce_arg('neginfinity', self.neginfinity, DEFAULT_NEGINFINITY),
+            _options_reduce_arg('intformat', self.intformat, DEFAULT_INTFORMAT),
+            _options_reduce_arg('floatformat', self.floatformat, DEFAULT_FLOATFORMAT),
+            _options_reduce_arg('decimalformat', self.decimalformat, DEFAULT_DECIMALFORMAT),
+            _options_reduce_arg('nan', self.nan, DEFAULT_NAN),
+        )))
+        return (_UnpickleOptions if args else Options), args
 
     def __repr__(self):
         cdef object repr_options = _options_from_ascii(self)
@@ -198,19 +209,19 @@
 
         if intformat is not None:
             try:
-                intformat % TEST_INT
+                PyUnicode_Format(intformat, TEST_INT)
             except Exception as ex:
                 raise ValueError('intformat is not a valid format string') from ex
 
         if floatformat is not None:
             try:
-                floatformat % TEST_FLOAT
+                PyUnicode_Format(floatformat, TEST_FLOAT)
             except Exception as ex:
                 raise ValueError('floatformat is not a valid format string') from ex
 
         if decimalformat is not None:
             try:
-                decimalformat % TEST_DECIMAL
+                PyUnicode_Format(decimalformat, TEST_DECIMAL)
             except Exception as ex:
                 raise ValueError('decimalformat is not a valid format string') from ex
 
@@ -223,16 +234,26 @@
                     raise TypeError('mappingtypes must be a sequence of types '
                                     'or False')
 
-    def update(self, **kw):
+    def update(self, *args, **kw):
         '''
         Creates a new Options instance by modifying some members.
         '''
-        return _to_options(self, kw)
+        if kw:
+            return _to_options(self, kw)
+        else:
+            return self
 
 
 cdef Options DEFAULT_OPTIONS_OBJECT = Options()
 
 
+def _UnpickleOptions(*args):
+    if args:
+        return _to_options(None, dict(args))
+    else:
+        return DEFAULT_OPTIONS_OBJECT
+
+
 cdef object _to_options(Options arg, dict kw):
     if arg is None:
         if not kw:
diff --git a/src/_imports.pyx b/src/_imports.pyx
index c70ea17..6c6571c 100644
--- a/src/_imports.pyx
+++ b/src/_imports.pyx
@@ -1,4 +1,4 @@
-from cython import final, no_gc, auto_pickle
+from cython import final, no_gc, auto_pickle, freelist
 from cpython cimport dict, int, list, long, tuple, type
 from cpython.bool cimport PyBool_Check
 from cpython.buffer cimport (
@@ -15,7 +15,7 @@
 from cpython.long cimport PyLong_FromString, PyLong_Check
 from cpython.object cimport PyObject
 from cpython.type cimport PyType_Check
-from cpython.unicode cimport PyUnicode_Check, PyUnicode_FromEncodedObject
+from cpython.unicode cimport PyUnicode_Check, PyUnicode_FromEncodedObject, PyUnicode_Format
 from libcpp cimport bool as boolean
 
 
diff --git a/src/_legacy.pyx b/src/_legacy.pyx
index 218ff83..337dc84 100644
--- a/src/_legacy.pyx
+++ b/src/_legacy.pyx
@@ -24,7 +24,7 @@
         see ``decode(...)``
     '''
     if not isinstance(s, unicode):
-        s = unicode(s, encoding, 'strict')
+        s = PyUnicode_FromEncodedObject(s, encoding, 'strict')
     return decode(s)