Add non-template get_xxx/is_xxx methods to element
This fixes #781, adding to both element and result<element>:

- get_array, get_object, get_string, get_c_str, get_int64_t, get_uint64_t, get_double, get_bool
- is_array, is_object, is_string, is_c_str, is_int64_t, is_uint64_t, is_double, is_bool

I'm unsure about the naming of get_double, get_int64_t and get_uint64_t. I could see get_float, get_integer and get_unsigned as well, but went with this because then I don't have to introduce concepts.

To accomplish this, I also had to move `internal::tape_ref` out of the way: it has some methods with the same name, and that was causing C++ confusion. Instead of being a base class of element, internal::tape_ref is now a member. I did the same for array and object and their iterators as well, for consistency. This is nice in part because now there isn't a distracting private base class for these classes in the documentation. It's all hidden exactly as it should be.

I also refactored the casting tests some so that I could easily add tests for this functionality.
{"label": "simdjson:master", "ref": "master", "sha": "2cc84b6e51df1b71dd08df1f2f3435df2bc47783"}
Comment from @pps83 in another PR....

> I've used a few json libraries. I strongly believe that templated is<T>(), get<T> are wrong (for publicly faced api at least). It's not completely clear what T has to be for a json string (in simdjson, std::string isn't even there, right?). One may try to do.is<MyClas>() which makes no sense in json context. Json has clear set of types, and I'd rather prefer clear names for these. When I type jobj. and get .is one of intellisense offers, I have no clue what I need to do: I need to go to the source code to see how it works.


Add get_string, get_number... methods to the API as well as is_string, is_number...  (don't force templates)
diff --git a/include/simdjson/dom/array.h b/include/simdjson/dom/array.h
index 62a48c9e66..55d3ec8a87 100644
--- a/include/simdjson/dom/array.h
+++ b/include/simdjson/dom/array.h
@@ -16,12 +16,12 @@ class element;
 /**
  * JSON array.
  */
-class array : protected internal::tape_ref {
+class array {
 public:
   /** Create a new, invalid array */
   really_inline array() noexcept;
 
-  class iterator : protected internal::tape_ref {
+  class iterator {
   public:
     /**
      * Get the actual value
@@ -41,7 +41,8 @@ class array : protected internal::tape_ref {
      */
     inline bool operator!=(const iterator& other) const noexcept;
   private:
-    really_inline iterator(const document *doc, size_t json_index) noexcept;
+    really_inline iterator(const internal::tape_ref &tape) noexcept;
+    internal::tape_ref tape;
     friend class array;
   };
 
@@ -98,7 +99,8 @@ class array : protected internal::tape_ref {
   inline simdjson_result<element> at(size_t index) const noexcept;
 
 private:
-  really_inline array(const document *doc, size_t json_index) noexcept;
+  really_inline array(const internal::tape_ref &tape) noexcept;
+  internal::tape_ref tape;
   friend class element;
   friend struct simdjson_result<element>;
   template<typename T>
diff --git a/include/simdjson/dom/element.h b/include/simdjson/dom/element.h
index 80b6a39584..cee2920eb8 100644
--- a/include/simdjson/dom/element.h
+++ b/include/simdjson/dom/element.h
@@ -35,7 +35,7 @@ enum class element_type {
  * References an element in a JSON document, representing a JSON null, boolean, string, number,
  * array or object.
  */
-class element : protected internal::tape_ref {
+class element {
 public:
   /** Create a new, invalid element. */
   really_inline element() noexcept;
@@ -43,8 +43,135 @@ class element : protected internal::tape_ref {
   /** The type of this element. */
   really_inline element_type type() const noexcept;
 
-  /** Whether this element is a json `null`. */
-  really_inline bool is_null() const noexcept;
+  /**
+   * Cast this element to an array.
+   *
+   * Equivalent to get<array>().
+   *
+   * @returns An object that can be used to iterate the array, or:
+   *          INCORRECT_TYPE if the JSON element is not an array.
+   */
+  inline simdjson_result<array> get_array() const noexcept;
+  /**
+   * Cast this element to an object.
+   *
+   * Equivalent to get<object>().
+   *
+   * @returns An object that can be used to look up or iterate the object's fields, or:
+   *          INCORRECT_TYPE if the JSON element is not an object.
+   */
+  inline simdjson_result<object> get_object() const noexcept;
+  /**
+   * Cast this element to a string.
+   *
+   * Equivalent to get<const char *>().
+   *
+   * @returns An pointer to a null-terminated string. This string is stored in the parser and will
+   *          be invalidated the next time it parses a document or when it is destroyed.
+   *          Returns INCORRECT_TYPE if the JSON element is not a string.
+   */
+  inline simdjson_result<const char *> get_c_str() const noexcept;
+  /**
+   * Cast this element to a string.
+   *
+   * Equivalent to get<std::string_view>().
+   *
+   * @returns A string. The string is stored in the parser and will be invalidated the next time it
+   *          parses a document or when it is destroyed.
+   *          Returns INCORRECT_TYPE if the JSON element is not a string.
+   */
+  inline simdjson_result<std::string_view> get_string() const noexcept;
+  /**
+   * Cast this element to a signed integer.
+   *
+   * Equivalent to get<int64_t>().
+   *
+   * @returns A signed 64-bit integer.
+   *          Returns INCORRECT_TYPE if the JSON element is not an integer, or NUMBER_OUT_OF_RANGE
+   *          if it is negative.
+   */
+  inline simdjson_result<int64_t> get_int64_t() const noexcept;
+  /**
+   * Cast this element to an unsigned integer.
+   *
+   * Equivalent to get<uint64_t>().
+   *
+   * @returns An unsigned 64-bit integer.
+   *          Returns INCORRECT_TYPE if the JSON element is not an integer, or NUMBER_OUT_OF_RANGE
+   *          if it is too large.
+   */
+  inline simdjson_result<uint64_t> get_uint64_t() const noexcept;
+  /**
+   * Cast this element to an double floating-point.
+   *
+   * Equivalent to get<double>().
+   *
+   * @returns A double value.
+   *          Returns INCORRECT_TYPE if the JSON element is not a number.
+   */
+  inline simdjson_result<double> get_double() const noexcept;
+  /**
+   * Cast this element to a bool.
+   *
+   * Equivalent to get<bool>().
+   *
+   * @returns A bool value.
+   *          Returns INCORRECT_TYPE if the JSON element is not a boolean.
+   */
+  inline simdjson_result<bool> get_bool() const noexcept;
+
+  /**
+   * Whether this element is a json array.
+   *
+   * Equivalent to is<array>().
+   */
+  inline bool is_array() const noexcept;
+  /**
+   * Whether this element is a json object.
+   *
+   * Equivalent to is<object>().
+   */
+  inline bool is_object() const noexcept;
+  /**
+   * Whether this element is a json string.
+   *
+   * Equivalent to is<std::string_view>() or is<const char *>().
+   */
+  inline bool is_string() const noexcept;
+  /**
+   * Whether this element is a json number that fits in a signed 64-bit integer.
+   *
+   * Equivalent to is<int64_t>().
+   */
+  inline bool is_int64_t() const noexcept;
+  /**
+   * Whether this element is a json number that fits in an unsigned 64-bit integer.
+   *
+   * Equivalent to is<uint64_t>().
+   */
+  inline bool is_uint64_t() const noexcept;
+  /**
+   * Whether this element is a json number that fits in a double.
+   *
+   * Equivalent to is<double>().
+   */
+  inline bool is_double() const noexcept;
+  /**
+   * Whether this element is a json number.
+   *
+   * Both integers and floating points will return true.
+   */
+  inline bool is_number() const noexcept;
+  /**
+   * Whether this element is a json `true` or `false`.
+   *
+   * Equivalent to is<bool>().
+   */
+  inline bool is_bool() const noexcept;
+  /**
+   * Whether this element is a json `null`.
+   */
+  inline bool is_null() const noexcept;
 
   /**
    * Tell whether the value can be cast to provided type (T).
@@ -249,7 +376,8 @@ class element : protected internal::tape_ref {
   inline bool dump_raw_tape(std::ostream &out) const noexcept;
 
 private:
-  really_inline element(const document *doc, size_t json_index) noexcept;
+  really_inline element(const internal::tape_ref &tape) noexcept;
+  internal::tape_ref tape;
   friend class document;
   friend class object;
   friend class array;
@@ -289,12 +417,29 @@ struct simdjson_result<dom::element> : public internal::simdjson_result_base<dom
   really_inline simdjson_result(error_code error) noexcept; ///< @private
 
   inline simdjson_result<dom::element_type> type() const noexcept;
-  inline simdjson_result<bool> is_null() const noexcept;
   template<typename T>
   inline simdjson_result<bool> is() const noexcept;
   template<typename T>
   inline simdjson_result<T> get() const noexcept;
 
+  inline simdjson_result<dom::array> get_array() const noexcept;
+  inline simdjson_result<dom::object> get_object() const noexcept;
+  inline simdjson_result<const char *> get_c_str() const noexcept;
+  inline simdjson_result<std::string_view> get_string() const noexcept;
+  inline simdjson_result<int64_t> get_int64_t() const noexcept;
+  inline simdjson_result<uint64_t> get_uint64_t() const noexcept;
+  inline simdjson_result<double> get_double() const noexcept;
+  inline simdjson_result<bool> get_bool() const noexcept;
+
+  inline simdjson_result<bool> is_array() const noexcept;
+  inline simdjson_result<bool> is_object() const noexcept;
+  inline simdjson_result<bool> is_string() const noexcept;
+  inline simdjson_result<bool> is_int64_t() const noexcept;
+  inline simdjson_result<bool> is_uint64_t() const noexcept;
+  inline simdjson_result<bool> is_double() const noexcept;
+  inline simdjson_result<bool> is_bool() const noexcept;
+  inline simdjson_result<bool> is_null() const noexcept;
+
   inline simdjson_result<dom::element> operator[](const std::string_view &key) const noexcept;
   inline simdjson_result<dom::element> operator[](const char *key) const noexcept;
   inline simdjson_result<dom::element> at(const std::string_view &json_pointer) const noexcept;
diff --git a/include/simdjson/dom/object.h b/include/simdjson/dom/object.h
index 03f3aaa9b5..9316914d9a 100644
--- a/include/simdjson/dom/object.h
+++ b/include/simdjson/dom/object.h
@@ -17,12 +17,12 @@ class key_value_pair;
 /**
  * JSON object.
  */
-class object : protected internal::tape_ref {
+class object {
 public:
   /** Create a new, invalid object */
   really_inline object() noexcept;
 
-  class iterator : protected internal::tape_ref {
+  class iterator {
   public:
     /**
      * Get the actual key/value pair
@@ -70,7 +70,10 @@ class object : protected internal::tape_ref {
      */
     inline element value() const noexcept;
   private:
-    really_inline iterator(const document *doc, size_t json_index) noexcept;
+    really_inline iterator(const internal::tape_ref &tape) noexcept;
+
+    internal::tape_ref tape;
+
     friend class object;
   };
 
@@ -172,7 +175,10 @@ class object : protected internal::tape_ref {
   inline simdjson_result<element> at_key_case_insensitive(const std::string_view &key) const noexcept;
 
 private:
-  really_inline object(const document *doc, size_t json_index) noexcept;
+  really_inline object(const internal::tape_ref &tape) noexcept;
+
+  internal::tape_ref tape;
+
   friend class element;
   friend struct simdjson_result<element>;
   template<typename T>
diff --git a/include/simdjson/inline/array.h b/include/simdjson/inline/array.h
index da50814254..790977dde1 100644
--- a/include/simdjson/inline/array.h
+++ b/include/simdjson/inline/array.h
@@ -50,16 +50,16 @@ namespace dom {
 //
 // array inline implementation
 //
-really_inline array::array() noexcept : internal::tape_ref() {}
-really_inline array::array(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) {}
+really_inline array::array() noexcept : tape{} {}
+really_inline array::array(const internal::tape_ref &_tape) noexcept : tape{_tape} {}
 inline array::iterator array::begin() const noexcept {
-  return iterator(doc, json_index + 1);
+  return internal::tape_ref(tape.doc, tape.json_index + 1);
 }
 inline array::iterator array::end() const noexcept {
-  return iterator(doc, after_element() - 1);
+  return internal::tape_ref(tape.doc, tape.after_element() - 1);
 }
 inline size_t array::size() const noexcept {
-  return scope_count();
+  return tape.scope_count();
 }
 inline simdjson_result<element> array::at(const std::string_view &json_pointer) const noexcept {
   // - means "the append position" or "the element after the end of the array"
@@ -83,7 +83,7 @@ inline simdjson_result<element> array::at(const std::string_view &json_pointer)
   if (i == 0) { return INVALID_JSON_POINTER; } // "Empty string in JSON pointer array index"
 
   // Get the child
-  auto child = array(doc, json_index).at(array_index);
+  auto child = array(tape).at(array_index);
   // If there is a /, we're not done yet, call recursively.
   if (i < json_pointer.length()) {
     child = child.at(json_pointer.substr(i+1));
@@ -102,15 +102,15 @@ inline simdjson_result<element> array::at(size_t index) const noexcept {
 //
 // array::iterator inline implementation
 //
-really_inline array::iterator::iterator(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) { }
+really_inline array::iterator::iterator(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
 inline element array::iterator::operator*() const noexcept {
-  return element(doc, json_index);
+  return element(tape);
 }
 inline bool array::iterator::operator!=(const array::iterator& other) const noexcept {
-  return json_index != other.json_index;
+  return tape.json_index != other.tape.json_index;
 }
 inline array::iterator& array::iterator::operator++() noexcept {
-  json_index = after_element();
+  tape.json_index = tape.after_element();
   return *this;
 }
 
diff --git a/include/simdjson/inline/document.h b/include/simdjson/inline/document.h
index 028aac7760..f78eba022a 100644
--- a/include/simdjson/inline/document.h
+++ b/include/simdjson/inline/document.h
@@ -17,7 +17,7 @@ namespace dom {
 // document inline implementation
 //
 inline element document::root() const noexcept {
-  return element(this, 1);
+  return element(internal::tape_ref(this, 1));
 }
 
 WARN_UNUSED
diff --git a/include/simdjson/inline/element.h b/include/simdjson/inline/element.h
index c77be566b7..f2cc95882d 100644
--- a/include/simdjson/inline/element.h
+++ b/include/simdjson/inline/element.h
@@ -22,10 +22,7 @@ inline simdjson_result<dom::element_type> simdjson_result<dom::element>::type()
   if (error()) { return error(); }
   return first.type();
 }
-inline simdjson_result<bool> simdjson_result<dom::element>::is_null() const noexcept {
-  if (error()) { return error(); }
-  return first.is_null();
-}
+
 template<typename T>
 inline simdjson_result<bool> simdjson_result<dom::element>::is() const noexcept {
   if (error()) { return error(); }
@@ -37,6 +34,73 @@ inline simdjson_result<T> simdjson_result<dom::element>::get() const noexcept {
   return first.get<T>();
 }
 
+inline simdjson_result<dom::array> simdjson_result<dom::element>::get_array() const noexcept {
+  if (error()) { return error(); }
+  return first.get_array();
+}
+inline simdjson_result<dom::object> simdjson_result<dom::element>::get_object() const noexcept {
+  if (error()) { return error(); }
+  return first.get_object();
+}
+inline simdjson_result<const char *> simdjson_result<dom::element>::get_c_str() const noexcept {
+  if (error()) { return error(); }
+  return first.get_c_str();
+}
+inline simdjson_result<std::string_view> simdjson_result<dom::element>::get_string() const noexcept {
+  if (error()) { return error(); }
+  return first.get_string();
+}
+inline simdjson_result<int64_t> simdjson_result<dom::element>::get_int64_t() const noexcept {
+  if (error()) { return error(); }
+  return first.get_int64_t();
+}
+inline simdjson_result<uint64_t> simdjson_result<dom::element>::get_uint64_t() const noexcept {
+  if (error()) { return error(); }
+  return first.get_uint64_t();
+}
+inline simdjson_result<double> simdjson_result<dom::element>::get_double() const noexcept {
+  if (error()) { return error(); }
+  return first.get_double();
+}
+inline simdjson_result<bool> simdjson_result<dom::element>::get_bool() const noexcept {
+  if (error()) { return error(); }
+  return first.get_bool();
+}
+
+inline simdjson_result<bool> simdjson_result<dom::element>::is_array() const noexcept {
+  if (error()) { return error(); }
+  return first.is_array();
+}
+inline simdjson_result<bool> simdjson_result<dom::element>::is_object() const noexcept {
+  if (error()) { return error(); }
+  return first.is_object();
+}
+inline simdjson_result<bool> simdjson_result<dom::element>::is_string() const noexcept {
+  if (error()) { return error(); }
+  return first.is_string();
+}
+inline simdjson_result<bool> simdjson_result<dom::element>::is_int64_t() const noexcept {
+  if (error()) { return error(); }
+  return first.is_int64_t();
+}
+inline simdjson_result<bool> simdjson_result<dom::element>::is_uint64_t() const noexcept {
+  if (error()) { return error(); }
+  return first.is_uint64_t();
+}
+inline simdjson_result<bool> simdjson_result<dom::element>::is_double() const noexcept {
+  if (error()) { return error(); }
+  return first.is_double();
+}
+inline simdjson_result<bool> simdjson_result<dom::element>::is_bool() const noexcept {
+  if (error()) { return error(); }
+  return first.is_bool();
+}
+
+inline simdjson_result<bool> simdjson_result<dom::element>::is_null() const noexcept {
+  if (error()) { return error(); }
+  return first.is_null();
+}
+
 inline simdjson_result<dom::element> simdjson_result<dom::element>::operator[](const std::string_view &key) const noexcept {
   if (error()) { return error(); }
   return first[key];
@@ -105,50 +169,43 @@ namespace dom {
 //
 // element inline implementation
 //
-really_inline element::element() noexcept : internal::tape_ref() {}
-really_inline element::element(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) { }
+really_inline element::element() noexcept : tape{} {}
+really_inline element::element(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
 
 inline element_type element::type() const noexcept {
-  auto tape_type = tape_ref_type();
+  auto tape_type = tape.tape_ref_type();
   return tape_type == internal::tape_type::FALSE_VALUE ? element_type::BOOL : static_cast<element_type>(tape_type);
 }
-really_inline bool element::is_null() const noexcept {
-  return is_null_on_tape();
-}
 
-template<>
-inline simdjson_result<bool> element::get<bool>() const noexcept {
-  if(is_true()) {
+inline simdjson_result<bool> element::get_bool() const noexcept {
+  if(tape.is_true()) {
     return true;
-  } else if(is_false()) {
+  } else if(tape.is_false()) {
     return false;
   }
   return INCORRECT_TYPE;
 }
-template<>
-inline simdjson_result<const char *> element::get<const char *>() const noexcept {
-  switch (tape_ref_type()) {
+inline simdjson_result<const char *> element::get_c_str() const noexcept {
+  switch (tape.tape_ref_type()) {
     case internal::tape_type::STRING: {
-      return get_c_str();
+      return tape.get_c_str();
     }
     default:
       return INCORRECT_TYPE;
   }
 }
-template<>
-inline simdjson_result<std::string_view> element::get<std::string_view>() const noexcept {
-  switch (tape_ref_type()) {
+inline simdjson_result<std::string_view> element::get_string() const noexcept {
+  switch (tape.tape_ref_type()) {
     case internal::tape_type::STRING:
-      return get_string_view();
+      return tape.get_string_view();
     default:
       return INCORRECT_TYPE;
   }
 }
-template<>
-inline simdjson_result<uint64_t> element::get<uint64_t>() const noexcept {
-  if(unlikely(!is_uint64())) { // branch rarely taken
-    if(is_int64()) {
-      int64_t result = next_tape_value<int64_t>();
+inline simdjson_result<uint64_t> element::get_uint64_t() const noexcept {
+  if(unlikely(!tape.is_uint64())) { // branch rarely taken
+    if(tape.is_int64()) {
+      int64_t result = tape.next_tape_value<int64_t>();
       if (result < 0) {
         return NUMBER_OUT_OF_RANGE;
       }
@@ -156,13 +213,12 @@ inline simdjson_result<uint64_t> element::get<uint64_t>() const noexcept {
     }
     return INCORRECT_TYPE;
   }
-  return next_tape_value<int64_t>();
+  return tape.next_tape_value<int64_t>();
 }
-template<>
-inline simdjson_result<int64_t> element::get<int64_t>() const noexcept {
-  if(unlikely(!is_int64())) { // branch rarely taken
-    if(is_uint64()) {
-      uint64_t result = next_tape_value<uint64_t>();
+inline simdjson_result<int64_t> element::get_int64_t() const noexcept {
+  if(unlikely(!tape.is_int64())) { // branch rarely taken
+    if(tape.is_uint64()) {
+      uint64_t result = tape.next_tape_value<uint64_t>();
       // Wrapping max in parens to handle Windows issue: https://stackoverflow.com/questions/11544073/how-do-i-deal-with-the-max-macro-in-windows-h-colliding-with-max-in-std
       if (result > uint64_t((std::numeric_limits<int64_t>::max)())) {
         return NUMBER_OUT_OF_RANGE;
@@ -171,10 +227,9 @@ inline simdjson_result<int64_t> element::get<int64_t>() const noexcept {
     }
     return INCORRECT_TYPE;
   }
-  return next_tape_value<int64_t>();
+  return tape.next_tape_value<int64_t>();
 }
-template<>
-inline simdjson_result<double> element::get<double>() const noexcept {
+inline simdjson_result<double> element::get_double() const noexcept {
   // Performance considerations:
   // 1. Querying tape_ref_type() implies doing a shift, it is fast to just do a straight
   //   comparison.
@@ -184,42 +239,61 @@ inline simdjson_result<double> element::get<double>() const noexcept {
   // We can expect get<double> to refer to a double type almost all the time.
   // It is important to craft the code accordingly so that the compiler can use this
   // information. (This could also be solved with profile-guided optimization.)
-  if(unlikely(!is_double())) { // branch rarely taken
-    if(is_uint64()) {
-      return double(next_tape_value<uint64_t>());
-    } else if(is_int64()) {
-      return double(next_tape_value<int64_t>());
+  if(unlikely(!tape.is_double())) { // branch rarely taken
+    if(tape.is_uint64()) {
+      return double(tape.next_tape_value<uint64_t>());
+    } else if(tape.is_int64()) {
+      return double(tape.next_tape_value<int64_t>());
     }
     return INCORRECT_TYPE;
   }
   // this is common:
-  return next_tape_value<double>();
+  return tape.next_tape_value<double>();
 }
-template<>
-inline simdjson_result<array> element::get<array>() const noexcept {
-  switch (tape_ref_type()) {
+inline simdjson_result<array> element::get_array() const noexcept {
+  switch (tape.tape_ref_type()) {
     case internal::tape_type::START_ARRAY:
-      return array(doc, json_index);
+      return array(tape);
     default:
       return INCORRECT_TYPE;
   }
 }
-template<>
-inline simdjson_result<object> element::get<object>() const noexcept {
-  switch (tape_ref_type()) {
+inline simdjson_result<object> element::get_object() const noexcept {
+  switch (tape.tape_ref_type()) {
     case internal::tape_type::START_OBJECT:
-      return object(doc, json_index);
+      return object(tape);
     default:
       return INCORRECT_TYPE;
   }
 }
 
 template<typename T>
-really_inline bool element::is() const noexcept {
+inline bool element::is() const noexcept {
   auto result = get<T>();
   return !result.error();
 }
 
+template<> inline simdjson_result<array> element::get<array>() const noexcept { return get_array(); }
+template<> inline simdjson_result<object> element::get<object>() const noexcept { return get_object(); }
+template<> inline simdjson_result<const char *> element::get<const char *>() const noexcept { return get_c_str(); }
+template<> inline simdjson_result<std::string_view> element::get<std::string_view>() const noexcept { return get_string(); }
+template<> inline simdjson_result<int64_t> element::get<int64_t>() const noexcept { return get_int64_t(); }
+template<> inline simdjson_result<uint64_t> element::get<uint64_t>() const noexcept { return get_uint64_t(); }
+template<> inline simdjson_result<double> element::get<double>() const noexcept { return get_double(); }
+template<> inline simdjson_result<bool> element::get<bool>() const noexcept { return get_bool(); }
+
+inline bool element::is_array() const noexcept { return is<array>(); }
+inline bool element::is_object() const noexcept { return is<object>(); }
+inline bool element::is_string() const noexcept { return is<std::string_view>(); }
+inline bool element::is_int64_t() const noexcept { return is<int64_t>(); }
+inline bool element::is_uint64_t() const noexcept { return is<uint64_t>(); }
+inline bool element::is_double() const noexcept { return is<double>(); }
+inline bool element::is_bool() const noexcept { return is<bool>(); }
+
+inline bool element::is_null() const noexcept {
+  return tape.is_null_on_tape();
+}
+
 #if SIMDJSON_EXCEPTIONS
 
 inline element::operator bool() const noexcept(false) { return get<bool>(); }
@@ -247,11 +321,11 @@ inline simdjson_result<element> element::operator[](const char *key) const noexc
   return at_key(key);
 }
 inline simdjson_result<element> element::at(const std::string_view &json_pointer) const noexcept {
-  switch (tape_ref_type()) {
+  switch (tape.tape_ref_type()) {
     case internal::tape_type::START_OBJECT:
-      return object(doc, json_index).at(json_pointer);
+      return object(tape).at(json_pointer);
     case internal::tape_type::START_ARRAY:
-      return array(doc, json_index).at(json_pointer);
+      return array(tape).at(json_pointer);
     default:
       return INCORRECT_TYPE;
   }
@@ -267,7 +341,7 @@ inline simdjson_result<element> element::at_key_case_insensitive(const std::stri
 }
 
 inline bool element::dump_raw_tape(std::ostream &out) const noexcept {
-  return doc->dump_raw_tape(out);
+  return tape.doc->dump_raw_tape(out);
 }
 
 inline std::ostream& operator<<(std::ostream& out, const element &value) {
@@ -308,7 +382,7 @@ inline std::ostream& minifier<dom::element>::print(std::ostream& out) {
   is_object[0] = false;
   bool after_value = false;
 
-  internal::tape_ref iter(value);
+  internal::tape_ref iter(value.tape);
   do {
     // print commas after each value
     if (after_value) {
@@ -326,7 +400,7 @@ inline std::ostream& minifier<dom::element>::print(std::ostream& out) {
       // If we're too deep, we need to recurse to go deeper.
       depth++;
       if (unlikely(depth >= MAX_DEPTH)) {
-        out << minify<dom::array>(dom::array(iter.doc, iter.json_index));
+        out << minify<dom::array>(dom::array(iter));
         iter.json_index = iter.matching_brace_index() - 1; // Jump to the ]
         depth--;
         break;
@@ -353,7 +427,7 @@ inline std::ostream& minifier<dom::element>::print(std::ostream& out) {
       // If we're too deep, we need to recurse to go deeper.
       depth++;
       if (unlikely(depth >= MAX_DEPTH)) {
-        out << minify<dom::object>(dom::object(iter.doc, iter.json_index));
+        out << minify<dom::object>(dom::object(iter));
         iter.json_index = iter.matching_brace_index() - 1; // Jump to the }
         depth--;
         break;
diff --git a/include/simdjson/inline/object.h b/include/simdjson/inline/object.h
index bbd69818c3..f12a5252bd 100644
--- a/include/simdjson/inline/object.h
+++ b/include/simdjson/inline/object.h
@@ -62,16 +62,16 @@ namespace dom {
 //
 // object inline implementation
 //
-really_inline object::object() noexcept : internal::tape_ref() {}
-really_inline object::object(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) { }
+really_inline object::object() noexcept : tape{} {}
+really_inline object::object(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
 inline object::iterator object::begin() const noexcept {
-  return iterator(doc, json_index + 1);
+  return internal::tape_ref(tape.doc, tape.json_index + 1);
 }
 inline object::iterator object::end() const noexcept {
-  return iterator(doc, after_element() - 1);
+  return internal::tape_ref(tape.doc, tape.after_element() - 1);
 }
 inline size_t object::size() const noexcept {
-  return scope_count();
+  return tape.scope_count();
 }
 
 inline simdjson_result<element> object::operator[](const std::string_view &key) const noexcept {
@@ -142,29 +142,29 @@ inline simdjson_result<element> object::at_key_case_insensitive(const std::strin
 //
 // object::iterator inline implementation
 //
-really_inline object::iterator::iterator(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) { }
+really_inline object::iterator::iterator(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
 inline const key_value_pair object::iterator::operator*() const noexcept {
   return key_value_pair(key(), value());
 }
 inline bool object::iterator::operator!=(const object::iterator& other) const noexcept {
-  return json_index != other.json_index;
+  return tape.json_index != other.tape.json_index;
 }
 inline object::iterator& object::iterator::operator++() noexcept {
-  json_index++;
-  json_index = after_element();
+  tape.json_index++;
+  tape.json_index = tape.after_element();
   return *this;
 }
 inline std::string_view object::iterator::key() const noexcept {
-  return get_string_view();
+  return tape.get_string_view();
 }
 inline uint32_t object::iterator::key_length() const noexcept {
-  return get_string_length();
+  return tape.get_string_length();
 }
 inline const char* object::iterator::key_c_str() const noexcept {
-  return reinterpret_cast<const char *>(&doc->string_buf[size_t(tape_value()) + sizeof(uint32_t)]);
+  return reinterpret_cast<const char *>(&tape.doc->string_buf[size_t(tape.tape_value()) + sizeof(uint32_t)]);
 }
 inline element object::iterator::value() const noexcept {
-  return element(doc, json_index + 1);
+  return element(internal::tape_ref(tape.doc, tape.json_index + 1));
 }
 
 /**

diff --git a/tests/basictests.cpp b/tests/basictests.cpp
index 697e4261a6..b464ee966e 100644
--- a/tests/basictests.cpp
+++ b/tests/basictests.cpp
@@ -14,37 +14,8 @@
 #include <unistd.h>
 
 #include "simdjson.h"
-
-#ifndef SIMDJSON_BENCHMARK_DATA_DIR
-#define SIMDJSON_BENCHMARK_DATA_DIR "jsonexamples/"
-#endif
-const char *TWITTER_JSON = SIMDJSON_BENCHMARK_DATA_DIR "twitter.json";
-const char *TWITTER_TIMELINE_JSON = SIMDJSON_BENCHMARK_DATA_DIR "twitter_timeline.json";
-const char *REPEAT_JSON = SIMDJSON_BENCHMARK_DATA_DIR "repeat.json";
-const char *AMAZON_CELLPHONES_NDJSON = SIMDJSON_BENCHMARK_DATA_DIR "amazon_cellphones.ndjson";
-
-#define SIMDJSON_BENCHMARK_SMALLDATA_DIR SIMDJSON_BENCHMARK_DATA_DIR "small/"
-
-const char *ADVERSARIAL_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR  "adversarial.json";
-const char *FLATADVERSARIAL_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR  "flatadversarial.json";
-const char *DEMO_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR  "demo.json";
-const char *SMALLDEMO_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR  "smalldemo.json";
-const char *TRUENULL_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR  "truenull.json";
-
-
-
-template<typename T>
-bool equals_expected(T actual, T expected) {
-  return actual == expected;
-}
-template<>
-bool equals_expected<const char *>(const char *actual, const char *expected) {
-  return !strcmp(actual, expected);
-}
-
-#define ASSERT_EQUAL(ACTUAL, EXPECTED) if (!equals_expected(ACTUAL, EXPECTED)) { std::cerr << "Expected " << #ACTUAL << " to be " << (EXPECTED) << ", got " << (ACTUAL) << " instead!" << std::endl; return false; }
-#define ASSERT(RESULT, MESSAGE) if (!(RESULT)) { std::cerr << MESSAGE << std::endl; return false; }
-#define ASSERT_SUCCESS(ERROR) if (ERROR) { std::cerr << (ERROR) << std::endl; return false; }
+#include "cast_tester.h"
+#include "test_macros.h"
 
 namespace number_tests {
 
@@ -1367,222 +1338,73 @@ namespace type_tests {
     }
   )"_padded;
 
-  // test_implicit_cast<T>::with(value, [](T value) { return true; })
-  // Makes it so we test implicit casts for anything that supports them, but *don't* test them
-  // for const char *
-  template<typename T>
-  class test_implicit_cast {
-  public:
-    template<typename A, typename F>
-    static bool with(A input, F const & test);
-    template<typename A>
-    static bool error_with(A input, simdjson::error_code expected_error);
-  };
-
-  template<typename T>
-  template<typename A, typename F>
-  bool test_implicit_cast<T>::with(A input, F const & test) {
-    T actual;
-    actual = input;
-    return test(actual);
-  }
-
-  template<>
-  template<typename A, typename F>
-  bool test_implicit_cast<const char *>::with(A, F const &) {
-    return true;
-  }
-
-  template<typename T>
-  template<typename A>
-  bool test_implicit_cast<T>::error_with(A input, simdjson::error_code expected_error) {
-    try {
-      UNUSED T actual;
-      actual = input;
-      return false;
-    } catch(simdjson_error &e) {
-      ASSERT_EQUAL(e.error(), expected_error);
-      return true;
-    }
-  }
-
-  template<>
-  template<typename A>
-  bool test_implicit_cast<const char *>::error_with(A, simdjson::error_code) {
-    return true;
-  }
-
   template<typename T>
   bool test_cast(simdjson_result<dom::element> result, T expected) {
+    cast_tester<T> tester;
     std::cout << "  test_cast<" << typeid(T).name() << "> expecting " << expected << std::endl;
     // Grab the element out and check success
     dom::element element = result.first;
 
-    // get<T>() == expected
-    T actual;
-    simdjson::error_code error;
-    result.get<T>().tie(actual, error);
-    ASSERT_SUCCESS(error);
-    ASSERT_EQUAL(actual, expected);
-
-    element.get<T>().tie(actual, error);
-    ASSERT_SUCCESS(error);
-    ASSERT_EQUAL(actual, expected);
-
-    // is<T>()
-    bool actual_is;
-    result.is<T>().tie(actual_is, error);
-    ASSERT_SUCCESS(error);
-    ASSERT_EQUAL(actual_is, true);
-
-    actual_is = element.is<T>();
-    ASSERT_EQUAL(actual_is, true);
-
+    RUN_TEST( tester.test_get(element, expected ) );
+    RUN_TEST( tester.test_get(result, expected) );
+    // RUN_TEST( tester.test_named_get(element, expected) );
+    // RUN_TEST( tester.test_named_get(result, expected) );
+    RUN_TEST( tester.test_is(element, true) );
+    RUN_TEST( tester.test_is(result, true) );
+    // RUN_TEST( tester.test_named_is(element, true) );
+    // RUN_TEST( tester.test_named_is(result, true) );
 #if SIMDJSON_EXCEPTIONS
-    try {
-
-      // T() == expected
-      actual = T(result);
-      ASSERT_EQUAL(actual, expected);
-      actual = T(element);
-      ASSERT_EQUAL(actual, expected);
-
-      test_implicit_cast<T>::with(result, [&](T a) { ASSERT_EQUAL(a, expected); return false; });
-
-      test_implicit_cast<T>::with(element, [&](T a) { ASSERT_EQUAL(a, expected); return false; });
-
-      // get<T>() == expected
-      actual = result.get<T>();
-      ASSERT_EQUAL(actual, expected);
-
-      actual = element.get<T>();
-      ASSERT_EQUAL(actual, expected);
-
-      // is<T>()
-      actual_is = result.is<T>();
-      ASSERT_EQUAL(actual_is, true);
-
-    } catch(simdjson_error &e) {
-      std::cerr << e.error() << std::endl;
-      return false;
-    }
-
+    RUN_TEST( tester.test_implicit_cast(element, expected) );
+    RUN_TEST( tester.test_implicit_cast(result, expected) );
 #endif
 
     return true;
   }
 
-
   template<typename T>
   bool test_cast(simdjson_result<dom::element> result) {
-    std::cout << "  test_cast<" << typeid(T).name() << "> expecting success" << std::endl;
+    cast_tester<T> tester;
+    std::cout << "  test_cast<" << typeid(T).name() << ">" << std::endl;
     // Grab the element out and check success
     dom::element element = result.first;
 
-    // get<T>() == expected
-    T actual;
-    simdjson::error_code error;
-    result.get<T>().tie(actual, error);
-    ASSERT_SUCCESS(error);
-
-    element.get<T>().tie(actual, error);
-    ASSERT_SUCCESS(error);
-
-    // is<T>()
-    bool actual_is;
-    result.is<T>().tie(actual_is, error);
-    ASSERT_SUCCESS(error);
-    ASSERT_EQUAL(actual_is, true);
-
-    actual_is = element.is<T>();
-    ASSERT_EQUAL(actual_is, true);
-
+    RUN_TEST( tester.test_get(element) );
+    RUN_TEST( tester.test_get(result) );
+    RUN_TEST( tester.test_named_get(element) );
+    RUN_TEST( tester.test_named_get(result) );
+    RUN_TEST( tester.test_is(element, true) );
+    RUN_TEST( tester.test_is(result, true) );
+    RUN_TEST( tester.test_named_is(element, true) );
+    RUN_TEST( tester.test_named_is(result, true) );
 #if SIMDJSON_EXCEPTIONS
-
-    try {
-
-      // T()
-      actual = T(result);
-
-      actual = T(element);
-
-      test_implicit_cast<T>::with(result, [&](T) { return true; });
-
-      test_implicit_cast<T>::with(element, [&](T) { return true; });
-
-      // get<T>() == expected
-      actual = result.get<T>();
-
-      actual = element.get<T>();
-
-      // is<T>()
-      actual_is = result.is<T>();
-      ASSERT_EQUAL(actual_is, true);
-
-    } catch(simdjson_error &e) {
-      std::cerr << e.error() << std::endl;
-      return false;
-    }
-
+    RUN_TEST( tester.test_implicit_cast(element) );
+    RUN_TEST( tester.test_implicit_cast(result) );
 #endif
 
     return true;
   }
 
+  //
+  // Test that we get errors when we cast to the wrong type
+  //
   template<typename T>
-  bool test_cast(simdjson_result<dom::element> result, simdjson::error_code expected_error) {
-    std::cout << "  test_cast<" << typeid(T).name() << "> expecting error '" << expected_error << "'" << std::endl;
+  bool test_cast_error(simdjson_result<dom::element> result, simdjson::error_code expected_error) {
+    std::cout << "  test_cast_error<" << typeid(T).name() << "> expecting error '" << expected_error << "'" << std::endl;
     dom::element element = result.first;
-    // get<T>() == expected
-    T actual;
-    simdjson::error_code error;
-    result.get<T>().tie(actual, error);
-    ASSERT_EQUAL(error, expected_error);
 
-    element.get<T>().tie(actual, error);
-    ASSERT_EQUAL(error, expected_error);
-
-    // is<T>()
-    bool actual_is;
-    result.is<T>().tie(actual_is, error);
-    ASSERT_SUCCESS(error);
-    ASSERT_EQUAL(actual_is, false);
-
-    actual_is = element.is<T>();
-    ASSERT_EQUAL(actual_is, false);
+    cast_tester<T> tester;
 
+    RUN_TEST( tester.test_get_error(element, expected_error) );
+    RUN_TEST( tester.test_get_error(result, expected_error) );
+    RUN_TEST( tester.test_named_get_error(element, expected_error) );
+    RUN_TEST( tester.test_named_get_error(result, expected_error) );
+    RUN_TEST( tester.test_is(element, false) );
+    RUN_TEST( tester.test_is(result, false) );
+    RUN_TEST( tester.test_named_is(element, false) );
+    RUN_TEST( tester.test_named_is(result, false) );
 #if SIMDJSON_EXCEPTIONS
-
-    // T()
-    try {
-      actual = T(result);
-      return false;
-    } catch(simdjson_error &e) {
-      ASSERT_EQUAL(e.error(), expected_error);
-    }
-
-    try {
-      actual = T(element);
-      return false;
-    } catch(simdjson_error &e) {
-      ASSERT_EQUAL(e.error(), expected_error);
-    }
-
-    if (!test_implicit_cast<T>::error_with(result, expected_error)) { return false; }
-
-    if (!test_implicit_cast<T>::error_with(result, expected_error)) { return true; }
-
-    try {
-
-      // is<T>()
-      actual_is = result.is<T>();
-      ASSERT_EQUAL(actual_is, false);
-
-    } catch(simdjson_error &e) {
-      std::cerr << e.error() << std::endl;
-      return false;
-    }
-
+    RUN_TEST( tester.test_implicit_cast_error(element, expected_error) );
+    RUN_TEST( tester.test_implicit_cast_error(result, expected_error) );
 #endif
 
     return true;
@@ -1657,13 +1479,13 @@ namespace type_tests {
     return true
       && test_type(result, dom::element_type::ARRAY)
       && test_cast<dom::array>(result)
-      && test_cast<dom::object>(result, INCORRECT_TYPE)
-      && test_cast<std::string_view>(result, INCORRECT_TYPE)
-      && test_cast<const char *>(result, INCORRECT_TYPE)
-      && test_cast<int64_t>(result, INCORRECT_TYPE)
-      && test_cast<uint64_t>(result, INCORRECT_TYPE)
-      && test_cast<double>(result, INCORRECT_TYPE)
-      && test_cast<bool>(result, INCORRECT_TYPE)
+      && test_cast_error<dom::object>(result, INCORRECT_TYPE)
+      && test_cast_error<std::string_view>(result, INCORRECT_TYPE)
+      && test_cast_error<const char *>(result, INCORRECT_TYPE)
+      && test_cast_error<int64_t>(result, INCORRECT_TYPE)
+      && test_cast_error<uint64_t>(result, INCORRECT_TYPE)
+      && test_cast_error<double>(result, INCORRECT_TYPE)
+      && test_cast_error<bool>(result, INCORRECT_TYPE)
       && test_is_null(result, false);
   }
 
@@ -1675,14 +1497,14 @@ namespace type_tests {
 
     return true
       && test_type(result, dom::element_type::OBJECT)
-      && test_cast<dom::array>(result, INCORRECT_TYPE)
+      && test_cast_error<dom::array>(result, INCORRECT_TYPE)
       && test_cast<dom::object>(result)
-      && test_cast<std::string_view>(result, INCORRECT_TYPE)
-      && test_cast<const char *>(result, INCORRECT_TYPE)
-      && test_cast<int64_t>(result, INCORRECT_TYPE)
-      && test_cast<uint64_t>(result, INCORRECT_TYPE)
-      && test_cast<double>(result, INCORRECT_TYPE)
-      && test_cast<bool>(result, INCORRECT_TYPE)
+      && test_cast_error<std::string_view>(result, INCORRECT_TYPE)
+      && test_cast_error<const char *>(result, INCORRECT_TYPE)
+      && test_cast_error<int64_t>(result, INCORRECT_TYPE)
+      && test_cast_error<uint64_t>(result, INCORRECT_TYPE)
+      && test_cast_error<double>(result, INCORRECT_TYPE)
+      && test_cast_error<bool>(result, INCORRECT_TYPE)
       && test_is_null(result, false);
   }
 
@@ -1694,14 +1516,14 @@ namespace type_tests {
 
     return true
       && test_type(result, dom::element_type::STRING)
-      && test_cast<dom::array>(result, INCORRECT_TYPE)
-      && test_cast<dom::object>(result, INCORRECT_TYPE)
+      && test_cast_error<dom::array>(result, INCORRECT_TYPE)
+      && test_cast_error<dom::object>(result, INCORRECT_TYPE)
       && test_cast<std::string_view>(result, "foo")
       && test_cast<const char *>(result, "foo")
-      && test_cast<int64_t>(result, INCORRECT_TYPE)
-      && test_cast<uint64_t>(result, INCORRECT_TYPE)
-      && test_cast<double>(result, INCORRECT_TYPE)
-      && test_cast<bool>(result, INCORRECT_TYPE)
+      && test_cast_error<int64_t>(result, INCORRECT_TYPE)
+      && test_cast_error<uint64_t>(result, INCORRECT_TYPE)
+      && test_cast_error<double>(result, INCORRECT_TYPE)
+      && test_cast_error<bool>(result, INCORRECT_TYPE)
       && test_is_null(result, false);
   }
 
@@ -1712,16 +1534,16 @@ namespace type_tests {
     simdjson_result<dom::element> result = parser.parse(ALL_TYPES_JSON)[key];
     return true
       && test_type(result, dom::element_type::INT64)
-      && test_cast<dom::array>(result, INCORRECT_TYPE)
-      && test_cast<dom::object>(result, INCORRECT_TYPE)
-      && test_cast<std::string_view>(result, INCORRECT_TYPE)
-      && test_cast<const char *>(result, INCORRECT_TYPE)
+      && test_cast_error<dom::array>(result, INCORRECT_TYPE)
+      && test_cast_error<dom::object>(result, INCORRECT_TYPE)
+      && test_cast_error<std::string_view>(result, INCORRECT_TYPE)
+      && test_cast_error<const char *>(result, INCORRECT_TYPE)
       && test_cast<int64_t>(result, expected_value)
       && (expected_value >= 0 ?
           test_cast<uint64_t>(result, expected_value) :
-          test_cast<uint64_t>(result, NUMBER_OUT_OF_RANGE))
+          test_cast_error<uint64_t>(result, NUMBER_OUT_OF_RANGE))
       && test_cast<double>(result, static_cast<double>(expected_value))
-      && test_cast<bool>(result, INCORRECT_TYPE)
+      && test_cast_error<bool>(result, INCORRECT_TYPE)
       && test_is_null(result, false);
   }
 
@@ -1733,14 +1555,14 @@ namespace type_tests {
 
     return true
       && test_type(result, dom::element_type::UINT64)
-      && test_cast<dom::array>(result, INCORRECT_TYPE)
-      && test_cast<dom::object>(result, INCORRECT_TYPE)
-      && test_cast<std::string_view>(result, INCORRECT_TYPE)
-      && test_cast<const char *>(result, INCORRECT_TYPE)
-      && test_cast<int64_t>(result, NUMBER_OUT_OF_RANGE)
+      && test_cast_error<dom::array>(result, INCORRECT_TYPE)
+      && test_cast_error<dom::object>(result, INCORRECT_TYPE)
+      && test_cast_error<std::string_view>(result, INCORRECT_TYPE)
+      && test_cast_error<const char *>(result, INCORRECT_TYPE)
+      && test_cast_error<int64_t>(result, NUMBER_OUT_OF_RANGE)
       && test_cast<uint64_t>(result, expected_value)
       && test_cast<double>(result, static_cast<double>(expected_value))
-      && test_cast<bool>(result, INCORRECT_TYPE)
+      && test_cast_error<bool>(result, INCORRECT_TYPE)
       && test_is_null(result, false);
   }
 
@@ -1751,14 +1573,14 @@ namespace type_tests {
     simdjson_result<dom::element> result = parser.parse(ALL_TYPES_JSON)[key];
     return true
       && test_type(result, dom::element_type::DOUBLE)
-      && test_cast<dom::array>(result, INCORRECT_TYPE)
-      && test_cast<dom::object>(result, INCORRECT_TYPE)
-      && test_cast<std::string_view>(result, INCORRECT_TYPE)
-      && test_cast<const char *>(result, INCORRECT_TYPE)
-      && test_cast<int64_t>(result, INCORRECT_TYPE)
-      && test_cast<uint64_t>(result, INCORRECT_TYPE)
+      && test_cast_error<dom::array>(result, INCORRECT_TYPE)
+      && test_cast_error<dom::object>(result, INCORRECT_TYPE)
+      && test_cast_error<std::string_view>(result, INCORRECT_TYPE)
+      && test_cast_error<const char *>(result, INCORRECT_TYPE)
+      && test_cast_error<int64_t>(result, INCORRECT_TYPE)
+      && test_cast_error<uint64_t>(result, INCORRECT_TYPE)
       && test_cast<double>(result, expected_value)
-      && test_cast<bool>(result, INCORRECT_TYPE)
+      && test_cast_error<bool>(result, INCORRECT_TYPE)
       && test_is_null(result, false);
   }
 
@@ -1770,13 +1592,13 @@ namespace type_tests {
 
     return true
       && test_type(result, dom::element_type::BOOL)
-      && test_cast<dom::array>(result, INCORRECT_TYPE)
-      && test_cast<dom::object>(result, INCORRECT_TYPE)
-      && test_cast<std::string_view>(result, INCORRECT_TYPE)
-      && test_cast<const char *>(result, INCORRECT_TYPE)
-      && test_cast<int64_t>(result, INCORRECT_TYPE)
-      && test_cast<uint64_t>(result, INCORRECT_TYPE)
-      && test_cast<double>(result, INCORRECT_TYPE)
+      && test_cast_error<dom::array>(result, INCORRECT_TYPE)
+      && test_cast_error<dom::object>(result, INCORRECT_TYPE)
+      && test_cast_error<std::string_view>(result, INCORRECT_TYPE)
+      && test_cast_error<const char *>(result, INCORRECT_TYPE)
+      && test_cast_error<int64_t>(result, INCORRECT_TYPE)
+      && test_cast_error<uint64_t>(result, INCORRECT_TYPE)
+      && test_cast_error<double>(result, INCORRECT_TYPE)
       && test_cast<bool>(result, expected_value)
       && test_is_null(result, false);
   }
@@ -1788,14 +1610,14 @@ namespace type_tests {
     simdjson_result<dom::element> result = parser.parse(ALL_TYPES_JSON)["null"];
     return true
       && test_type(result, dom::element_type::NULL_VALUE)
-      && test_cast<dom::array>(result, INCORRECT_TYPE)
-      && test_cast<dom::object>(result, INCORRECT_TYPE)
-      && test_cast<std::string_view>(result, INCORRECT_TYPE)
-      && test_cast<const char *>(result, INCORRECT_TYPE)
-      && test_cast<int64_t>(result, INCORRECT_TYPE)
-      && test_cast<uint64_t>(result, INCORRECT_TYPE)
-      && test_cast<double>(result, INCORRECT_TYPE)
-      && test_cast<bool>(result, INCORRECT_TYPE)
+      && test_cast_error<dom::array>(result, INCORRECT_TYPE)
+      && test_cast_error<dom::object>(result, INCORRECT_TYPE)
+      && test_cast_error<std::string_view>(result, INCORRECT_TYPE)
+      && test_cast_error<const char *>(result, INCORRECT_TYPE)
+      && test_cast_error<int64_t>(result, INCORRECT_TYPE)
+      && test_cast_error<uint64_t>(result, INCORRECT_TYPE)
+      && test_cast_error<double>(result, INCORRECT_TYPE)
+      && test_cast_error<bool>(result, INCORRECT_TYPE)
       && test_is_null(result, true);
   }
 
diff --git a/tests/cast_tester.h b/tests/cast_tester.h
new file mode 100644
index 0000000000..37d443b346
--- /dev/null
+++ b/tests/cast_tester.h
@@ -0,0 +1,284 @@
+#ifndef CAST_TESTER_H
+#define CAST_TESTER_H
+
+#include "simdjson.h"
+#include "test_macros.h"
+
+namespace {
+  using simdjson::error_code;
+  using simdjson::simdjson_error;
+  using simdjson::simdjson_result;
+  using simdjson::dom::array;
+  using simdjson::dom::element;
+  using simdjson::dom::object;
+}
+
+// cast_tester<T> tester;
+// tester.test_implicit(value, [](T value) { return true; })
+// tester.test_implicit_error(value, error)
+// Used to test casts to a type. In the case of const char * in particular, we don't test
+// implicit casts at all, so that method always returns true.
+template<typename T>
+class cast_tester {
+public:
+  bool test_get(element element, T expected = {});
+  bool test_get(simdjson_result<element> element, T expected = {});
+  bool test_get_error(element element, error_code expected_error);
+  bool test_get_error(simdjson_result<element> element, error_code expected_error);
+
+#if SIMDJSON_EXCEPTIONS
+  bool test_implicit_cast(element element, T expected = {});
+  bool test_implicit_cast(simdjson_result<element> element, T expected = {});
+  bool test_implicit_cast_error(element element, error_code expected_error);
+  bool test_implicit_cast_error(simdjson_result<element> element, error_code expected_error);
+#endif // SIMDJSON_EXCEPTIONS
+
+  bool test_is(element element, bool expected);
+  bool test_is(simdjson_result<element> element, bool expected);
+  bool test_is_error(simdjson_result<element> element, error_code expected_error);
+
+  bool test_named_get(element element, T expected = {});
+  bool test_named_get(simdjson_result<element> element, T expected = {});
+  bool test_named_get_error(element element, error_code expected_error);
+  bool test_named_get_error(simdjson_result<element> element, error_code expected_error);
+
+  bool test_named_is(element element, bool expected);
+  bool test_named_is(simdjson_result<element> element, bool expected);
+  bool test_named_is_error(simdjson_result<element> element, error_code expected_error);
+
+private:
+  simdjson_result<T> named_get(element element);
+  simdjson_result<T> named_get(simdjson_result<element> element);
+  bool named_is(element element);
+  simdjson_result<bool> named_is(simdjson_result<element> element);
+  bool assert_equal(const T& expected, const T& actual);
+};
+
+template<typename T>
+bool cast_tester<T>::test_get(element element, T expected) {
+  T actual;
+  error_code error;
+  element.get<T>().tie(actual, error);
+  ASSERT_SUCCESS(error);
+  return assert_equal(actual, expected);
+}
+
+template<typename T>
+bool cast_tester<T>::test_get(simdjson_result<element> element, T expected) {
+  T actual;
+  error_code error;
+  element.get<T>().tie(actual, error);
+  ASSERT_SUCCESS(error);
+  return assert_equal(actual, expected);
+}
+
+template<typename T>
+bool cast_tester<T>::test_get_error(element element, error_code expected_error) {
+  T actual;
+  error_code error;
+  element.get<T>().tie(actual, error);
+  ASSERT_EQUAL(error, expected_error);
+  return true;
+}
+
+template<typename T>
+bool cast_tester<T>::test_get_error(simdjson_result<element> element, error_code expected_error) {
+  T actual;
+  error_code error;
+  element.get<T>().tie(actual, error);
+  ASSERT_EQUAL(error, expected_error);
+  return true;
+}
+
+template<typename T>
+bool cast_tester<T>::test_named_get(element element, T expected) {
+  T actual;
+  error_code error;
+  named_get(element).tie(actual, error);
+  ASSERT_SUCCESS(error);
+  return assert_equal(actual, expected);
+}
+
+template<typename T>
+bool cast_tester<T>::test_named_get(simdjson_result<element> element, T expected) {
+  T actual;
+  error_code error;
+  named_get(element).tie(actual, error);
+  ASSERT_SUCCESS(error);
+  return assert_equal(actual, expected);
+}
+
+template<typename T>
+bool cast_tester<T>::test_named_get_error(element element, error_code expected_error) {
+  T actual;
+  error_code error;
+  named_get(element).tie(actual, error);
+  ASSERT_EQUAL(error, expected_error);
+  return true;
+}
+
+template<typename T>
+bool cast_tester<T>::test_named_get_error(simdjson_result<element> element, error_code expected_error) {
+  T actual;
+  error_code error;
+  named_get(element).tie(actual, error);
+  ASSERT_EQUAL(error, expected_error);
+  return true;
+}
+
+#if SIMDJSON_EXCEPTIONS
+
+template<typename T>
+bool cast_tester<T>::test_implicit_cast(element element, T expected) {
+  T actual;
+  try {
+    actual = element;
+  } catch(simdjson_error &e) {
+    std::cerr << e.error() << std::endl;
+    return false;
+  }
+  return assert_equal(actual, expected);
+}
+
+template<typename T>
+bool cast_tester<T>::test_implicit_cast(simdjson_result<element> element, T expected) {
+  T actual;
+  try {
+    actual = element;
+  } catch(simdjson_error &e) {
+    std::cerr << e.error() << std::endl;
+    return false;
+  }
+  return assert_equal(actual, expected);
+}
+
+template<typename T>
+bool cast_tester<T>::test_implicit_cast_error(element element, error_code expected_error) {
+  try {
+    UNUSED T actual;
+    actual = element;
+    return false;
+  } catch(simdjson_error &e) {
+    ASSERT_EQUAL(e.error(), expected_error);
+    return true;
+  }
+}
+
+template<typename T>
+bool cast_tester<T>::test_implicit_cast_error(simdjson_result<element> element, error_code expected_error) {
+  try {
+    UNUSED T actual;
+    actual = element;
+    return false;
+  } catch(simdjson_error &e) {
+    ASSERT_EQUAL(e.error(), expected_error);
+    return true;
+  }
+}
+
+template<> bool cast_tester<const char *>::test_implicit_cast(element, const char *) { return true; }
+template<> bool cast_tester<const char *>::test_implicit_cast(simdjson_result<element>, const char *) { return true; }
+template<> bool cast_tester<const char *>::test_implicit_cast_error(element, error_code) { return true; }
+template<> bool cast_tester<const char *>::test_implicit_cast_error(simdjson_result<element>, error_code) { return true; }
+
+#endif // SIMDJSON_EXCEPTIONS
+
+template<typename T>
+bool cast_tester<T>::test_is(element element, bool expected) {
+  ASSERT_EQUAL(element.is<T>(), expected);
+  return true;
+}
+
+template<typename T>
+bool cast_tester<T>::test_is(simdjson_result<element> element, bool expected) {
+  bool actual;
+  error_code error;
+  element.is<T>().tie(actual, error);
+  ASSERT_SUCCESS(error);
+  ASSERT_EQUAL(actual, expected);
+  return true;
+}
+
+template<typename T>
+bool cast_tester<T>::test_is_error(simdjson_result<element> element, error_code expected_error) {
+  UNUSED bool actual;
+  error_code error;
+  element.is<T>().tie(actual, error);
+  ASSERT_EQUAL(error, expected_error);
+  return true;
+}
+
+template<typename T>
+bool cast_tester<T>::test_named_is(element element, bool expected) {
+  ASSERT_EQUAL(named_is(element), expected);
+  return true;
+}
+
+template<typename T>
+bool cast_tester<T>::test_named_is(simdjson_result<element> element, bool expected) {
+  bool actual;
+  error_code error;
+  named_is(element).tie(actual, error);
+  ASSERT_SUCCESS(error);
+  ASSERT_EQUAL(actual, expected);
+  return true;
+}
+
+template<typename T>
+bool cast_tester<T>::test_named_is_error(simdjson_result<element> element, error_code expected_error) {
+  bool actual;
+  error_code error;
+  named_is(element, error).tie(actual, error);
+  ASSERT_EQUAL(error, expected_error);
+  return true;
+}
+
+template<> simdjson_result<array> cast_tester<array>::named_get(element element) { return element.get_array(); }
+template<> simdjson_result<object> cast_tester<object>::named_get(element element) { return element.get_object(); }
+template<> simdjson_result<const char *> cast_tester<const char *>::named_get(element element) { return element.get_c_str(); }
+template<> simdjson_result<std::string_view> cast_tester<std::string_view>::named_get(element element) { return element.get_string(); }
+template<> simdjson_result<uint64_t> cast_tester<uint64_t>::named_get(element element) { return element.get_uint64_t(); }
+template<> simdjson_result<int64_t> cast_tester<int64_t>::named_get(element element) { return element.get_int64_t(); }
+template<> simdjson_result<double> cast_tester<double>::named_get(element element) { return element.get_double(); }
+template<> simdjson_result<bool> cast_tester<bool>::named_get(element element) { return element.get_bool(); }
+
+template<> simdjson_result<array> cast_tester<array>::named_get(simdjson_result<element> element) { return element.get_array(); }
+template<> simdjson_result<object> cast_tester<object>::named_get(simdjson_result<element> element) { return element.get_object(); }
+template<> simdjson_result<const char *> cast_tester<const char *>::named_get(simdjson_result<element> element) { return element.get_c_str(); }
+template<> simdjson_result<std::string_view> cast_tester<std::string_view>::named_get(simdjson_result<element> element) { return element.get_string(); }
+template<> simdjson_result<uint64_t> cast_tester<uint64_t>::named_get(simdjson_result<element> element) { return element.get_uint64_t(); }
+template<> simdjson_result<int64_t> cast_tester<int64_t>::named_get(simdjson_result<element> element) { return element.get_int64_t(); }
+template<> simdjson_result<double> cast_tester<double>::named_get(simdjson_result<element> element) { return element.get_double(); }
+template<> simdjson_result<bool> cast_tester<bool>::named_get(simdjson_result<element> element) { return element.get_bool(); }
+
+template<> bool cast_tester<array>::named_is(element element) { return element.is_array(); }
+template<> bool cast_tester<object>::named_is(element element) { return element.is_object(); }
+template<> bool cast_tester<const char *>::named_is(element element) { return element.is_string(); }
+template<> bool cast_tester<std::string_view>::named_is(element element) { return element.is_string(); }
+template<> bool cast_tester<uint64_t>::named_is(element element) { return element.is_uint64_t(); }
+template<> bool cast_tester<int64_t>::named_is(element element) { return element.is_int64_t(); }
+template<> bool cast_tester<double>::named_is(element element) { return element.is_double(); }
+template<> bool cast_tester<bool>::named_is(element element) { return element.is_bool(); }
+
+template<> simdjson_result<bool> cast_tester<array>::named_is(simdjson_result<element> element) { return element.is_array(); }
+template<> simdjson_result<bool> cast_tester<object>::named_is(simdjson_result<element> element) { return element.is_object(); }
+template<> simdjson_result<bool> cast_tester<const char *>::named_is(simdjson_result<element> element) { return element.is_string(); }
+template<> simdjson_result<bool> cast_tester<std::string_view>::named_is(simdjson_result<element> element) { return element.is_string(); }
+template<> simdjson_result<bool> cast_tester<uint64_t>::named_is(simdjson_result<element> element) { return element.is_uint64_t(); }
+template<> simdjson_result<bool> cast_tester<int64_t>::named_is(simdjson_result<element> element) { return element.is_int64_t(); }
+template<> simdjson_result<bool> cast_tester<double>::named_is(simdjson_result<element> element) { return element.is_double(); }
+template<> simdjson_result<bool> cast_tester<bool>::named_is(simdjson_result<element> element) { return element.is_bool(); }
+
+template<typename T> bool cast_tester<T>::assert_equal(const T& expected, const T& actual) {
+  ASSERT_EQUAL(expected, actual);
+  return true;
+}
+// We don't actually check equality for objects and arrays, just check that they actually cast
+template<> bool cast_tester<array>::assert_equal(const array&, const array&) {
+  return true;
+}
+template<> bool cast_tester<object>::assert_equal(const object&, const object&) {
+  return true;
+}
+
+#endif
\ No newline at end of file
diff --git a/tests/test_macros.h b/tests/test_macros.h
new file mode 100644
index 0000000000..909deb10ea
--- /dev/null
+++ b/tests/test_macros.h
@@ -0,0 +1,34 @@
+#ifndef TEST_MACROS_H
+#define TEST_MACROS_H
+
+#ifndef SIMDJSON_BENCHMARK_DATA_DIR
+#define SIMDJSON_BENCHMARK_DATA_DIR "jsonexamples/"
+#endif
+const char *TWITTER_JSON = SIMDJSON_BENCHMARK_DATA_DIR "twitter.json";
+const char *TWITTER_TIMELINE_JSON = SIMDJSON_BENCHMARK_DATA_DIR "twitter_timeline.json";
+const char *REPEAT_JSON = SIMDJSON_BENCHMARK_DATA_DIR "repeat.json";
+const char *AMAZON_CELLPHONES_NDJSON = SIMDJSON_BENCHMARK_DATA_DIR "amazon_cellphones.ndjson";
+
+#define SIMDJSON_BENCHMARK_SMALLDATA_DIR SIMDJSON_BENCHMARK_DATA_DIR "small/"
+
+const char *ADVERSARIAL_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR  "adversarial.json";
+const char *FLATADVERSARIAL_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR  "flatadversarial.json";
+const char *DEMO_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR  "demo.json";
+const char *SMALLDEMO_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR  "smalldemo.json";
+const char *TRUENULL_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR  "truenull.json";
+
+// For the ASSERT_EQUAL macro
+template<typename T>
+bool equals_expected(T actual, T expected) {
+  return actual == expected;
+}
+template<>
+bool equals_expected<const char *>(const char *actual, const char *expected) {
+  return !strcmp(actual, expected);
+}
+#define ASSERT_EQUAL(ACTUAL, EXPECTED) if (!equals_expected(ACTUAL, EXPECTED)) { std::cerr << "Expected " << #ACTUAL << " to be " << (EXPECTED) << ", got " << (ACTUAL) << " instead!" << std::endl; return false; }
+#define ASSERT(RESULT, MESSAGE) if (!(RESULT)) { std::cerr << MESSAGE << std::endl; return false; }
+#define RUN_TEST(RESULT) if (!RESULT) { return false; }
+#define ASSERT_SUCCESS(ERROR) if (ERROR) { std::cerr << (ERROR) << std::endl; return false; }
+
+#endif // TEST_MACROS_H
\ No newline at end of file

{"avoid_stdout": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "readme_examples11": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "example_compiletest_should_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_parse_uchar_should_not_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "jsoncheck": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "avoid_stderr": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "extracting_values_example": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "fuzz_dump": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_parse_stdstring_should_not_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "pointercheck": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "integer_tests": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "readme_examples_will_fail_with_exceptions_off": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "fuzz_parser": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "simdjson_force_implementation": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "quickstart11": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "quickstart": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "testjson2json": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_parse_uint8_should_not_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "example_compiletest_should_not_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "readme_examples": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "checkimplementation": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_load_should_not_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "json2json": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "fuzz_dump_raw_tape": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "stringparsingcheck": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "basictests": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "fuzz_print_json": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_parse_padstring_should_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "avoid_abort": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "errortests": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_load_should_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "quickstart14": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "numberparsingcheck": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "readme_examples_noexceptions11": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_parse_uchar_should_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "quickstart_noexceptions": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "amalgamate_demo_direct_from_repository": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_parse_stdstring_should_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "amalgamate_demo": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "readme_examples_noexceptions": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "simdjson_force_implementation_error": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "parse_many_test": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_parse_padstring_should_not_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_parse_uint8_should_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "fuzz_minify": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "quickstart_noexceptions11": {"run": "PASS", "test": "NONE", "fix": "PASS"}}
{"avoid_stdout": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "readme_examples11": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "example_compiletest_should_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_parse_uchar_should_not_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "jsoncheck": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "avoid_stderr": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "extracting_values_example": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "fuzz_dump": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_parse_stdstring_should_not_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "pointercheck": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "integer_tests": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "readme_examples_will_fail_with_exceptions_off": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "fuzz_parser": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "simdjson_force_implementation": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "quickstart11": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "quickstart": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "testjson2json": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_parse_uint8_should_not_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "example_compiletest_should_not_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "readme_examples": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "checkimplementation": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_load_should_not_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "json2json": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "fuzz_dump_raw_tape": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "stringparsingcheck": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "basictests": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "fuzz_print_json": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_parse_padstring_should_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "avoid_abort": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "errortests": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_load_should_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "quickstart14": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "numberparsingcheck": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "readme_examples_noexceptions11": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_parse_uchar_should_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "quickstart_noexceptions": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "amalgamate_demo_direct_from_repository": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_parse_stdstring_should_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "amalgamate_demo": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "readme_examples_noexceptions": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "simdjson_force_implementation_error": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "parse_many_test": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_parse_padstring_should_not_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "dangling_parser_parse_uint8_should_compile": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "fuzz_minify": {"run": "PASS", "test": "NONE", "fix": "PASS"}, "quickstart_noexceptions11": {"run": "PASS", "test": "NONE", "fix": "PASS"}}
{"passed_count": 46, "failed_count": 0, "skipped_count": 0, "passed_tests": ["avoid_stdout", "readme_examples11", "example_compiletest_should_compile", "dangling_parser_parse_uchar_should_not_compile", "jsoncheck", "avoid_stderr", "extracting_values_example", "fuzz_dump", "dangling_parser_parse_stdstring_should_not_compile", "pointercheck", "integer_tests", "readme_examples_will_fail_with_exceptions_off", "fuzz_parser", "simdjson_force_implementation", "quickstart11", "quickstart", "testjson2json", "dangling_parser_parse_uint8_should_not_compile", "example_compiletest_should_not_compile", "fuzz_minify", "readme_examples", "dangling_parser_load_should_not_compile", "json2json", "fuzz_dump_raw_tape", "stringparsingcheck", "basictests", "fuzz_print_json", "dangling_parser_parse_padstring_should_compile", "avoid_abort", "errortests", "dangling_parser_load_should_compile", "quickstart14", "numberparsingcheck", "readme_examples_noexceptions11", "dangling_parser_parse_uchar_should_compile", "quickstart_noexceptions", "amalgamate_demo_direct_from_repository", "dangling_parser_parse_stdstring_should_compile", "amalgamate_demo", "readme_examples_noexceptions", "simdjson_force_implementation_error", "parse_many_test", "dangling_parser_parse_padstring_should_not_compile", "dangling_parser_parse_uint8_should_compile", "checkimplementation", "quickstart_noexceptions11"], "failed_tests": [], "skipped_tests": []}
{"passed_count": 0, "failed_count": 0, "skipped_count": 0, "passed_tests": [], "failed_tests": [], "skipped_tests": []}
{"passed_count": 46, "failed_count": 0, "skipped_count": 0, "passed_tests": ["avoid_stdout", "readme_examples11", "example_compiletest_should_compile", "dangling_parser_parse_uchar_should_not_compile", "jsoncheck", "avoid_stderr", "extracting_values_example", "fuzz_dump", "dangling_parser_parse_stdstring_should_not_compile", "pointercheck", "integer_tests", "readme_examples_will_fail_with_exceptions_off", "fuzz_parser", "simdjson_force_implementation", "quickstart11", "quickstart", "testjson2json", "dangling_parser_parse_uint8_should_not_compile", "example_compiletest_should_not_compile", "fuzz_minify", "readme_examples", "dangling_parser_load_should_not_compile", "json2json", "fuzz_dump_raw_tape", "stringparsingcheck", "basictests", "fuzz_print_json", "dangling_parser_parse_padstring_should_compile", "avoid_abort", "errortests", "dangling_parser_load_should_compile", "quickstart14", "numberparsingcheck", "readme_examples_noexceptions11", "dangling_parser_parse_uchar_should_compile", "quickstart_noexceptions", "amalgamate_demo_direct_from_repository", "dangling_parser_parse_stdstring_should_compile", "amalgamate_demo", "readme_examples_noexceptions", "simdjson_force_implementation_error", "parse_many_test", "dangling_parser_parse_padstring_should_not_compile", "dangling_parser_parse_uint8_should_compile", "checkimplementation", "quickstart_noexceptions11"], "failed_tests": [], "skipped_tests": []}