   fileprivate func read<T: ByteTreeObjectDecodable>(
     _ objectType: T.Type
   ) -> T {
-    let numFields = readFieldLength()
+    let numFields = readObjectLength()
     let objectReader = ByteTreeObjectReader(reader: self,
                                             numFields: numFields)
     return T.read(from: objectReader, numFields: numFields, userInfo: userInfo)


  /// Discard the next scalar field, advancing the pointer to the next field
  fileprivate func discardField() {
    // FIXME: This can currently only discard scalar fields. Object fields
    // should also be discardable
    let fieldSize = readFieldLength()
    pointer = pointer.advanced(by: fieldSize)
  }
}


    return result
  }

  private func readFieldLength() -> (isObject: Bool, length: Int) {
    let raw = UInt32(littleEndian: readRaw(UInt32.self))
    let isObject = (raw & (UInt32(1) << 31)) != 0
    let length = Int(raw & ~(UInt32(1) << 31))
    return (isObject, length)
  }


  /// Read the number of fields in an object.
  ///
  /// - Returns: The number of fields in the following object
  private func readObjectLength() -> Int {
    let (isObject, length) = readFieldLength()
    assert(isObject)
    return length
  }

  /// Read the size of a scalar in bytes
  ///
  /// - Returns: The size of the following scalar in bytes
  private func readScalarLength() -> Int {
    let (isObject, length) = readFieldLength()
    assert(!isObject)
    return length
  }

  /// Read the protocol version and validate that it can be read using the given
