Starting using SPan
diff --git a/dev/core_generator/lib/src/field_types/bytes_field_type.dart b/dev/core_generator/lib/src/field_types/bytes_field_type.dart
index 8c2b57c..883ebc4 100644
--- a/dev/core_generator/lib/src/field_types/bytes_field_type.dart
+++ b/dev/core_generator/lib/src/field_types/bytes_field_type.dart
@@ -5,15 +5,15 @@
       : super(
           'Bytes',
           'CoreBytesType',
-          cppName: 'std::vector<uint8_t>',
-          include: '<vector>',
+          cppName: 'Span<uint8_t>',
+          include: 'rive/span.hpp',
         );
 
   @override
-  String get defaultValue => 'std::vector<uint8_t>()';
+  String get defaultValue => 'Span<uint8_t>(nullptr, 0)';
 
   @override
-  String get cppGetterName => 'const std::vector<uint8_t>&';
+  String get cppGetterName => 'const Span<uint8_t>&';
 
   @override
   String convertCpp(String value) {
diff --git a/dev/defs/assets/file_asset_contents.json b/dev/defs/assets/file_asset_contents.json
index 511d858..626b2e0 100644
--- a/dev/defs/assets/file_asset_contents.json
+++ b/dev/defs/assets/file_asset_contents.json
@@ -18,6 +18,7 @@
     },
     "bytes": {
       "type": "Bytes",
+      "encoded": true,
       "key": {
         "int": 212,
         "string": "bytes"
diff --git a/include/rive/assets/file_asset_contents.hpp b/include/rive/assets/file_asset_contents.hpp
index 7a237a9..7cdfd3d 100644
--- a/include/rive/assets/file_asset_contents.hpp
+++ b/include/rive/assets/file_asset_contents.hpp
@@ -1,11 +1,18 @@
 #ifndef _RIVE_FILE_ASSET_CONTENTS_HPP_
 #define _RIVE_FILE_ASSET_CONTENTS_HPP_
 #include "rive/generated/assets/file_asset_contents_base.hpp"
+#include <cstdint>
 
 namespace rive {
     class FileAssetContents : public FileAssetContentsBase {
+    private:
+        std::vector<uint8_t> m_Bytes;
+
     public:
+        const std::vector<uint8_t>& bytes() const;
         StatusCode import(ImportStack& importStack) override;
+        void decodeBytes(Span<uint8_t> value) override;
+        void copyBytes(const FileAssetContentsBase& object) override;
     };
 } // namespace rive
 
diff --git a/include/rive/core/binary_reader.hpp b/include/rive/core/binary_reader.hpp
index c8e6a8c..9cc6c2b 100644
--- a/include/rive/core/binary_reader.hpp
+++ b/include/rive/core/binary_reader.hpp
@@ -4,6 +4,7 @@
 
 #include <string>
 #include <vector>
+#include "rive/span.hpp"
 
 namespace rive {
     class BinaryReader {
@@ -23,7 +24,7 @@
         size_t lengthInBytes() const;
 
         std::string readString();
-        std::vector<uint8_t> readBytes();
+        Span<uint8_t> readBytes();
         double readFloat64();
         float readFloat32();
         uint8_t readByte();
diff --git a/include/rive/core/field_types/core_bytes_type.hpp b/include/rive/core/field_types/core_bytes_type.hpp
index 2530cf5..834acb8 100644
--- a/include/rive/core/field_types/core_bytes_type.hpp
+++ b/include/rive/core/field_types/core_bytes_type.hpp
@@ -1,7 +1,7 @@
 #ifndef _RIVE_CORE_BYTES_TYPE_HPP_
 #define _RIVE_CORE_BYTES_TYPE_HPP_
 
-#include <vector>
+#include "rive/span.hpp"
 #include <cstdint>
 
 namespace rive {
@@ -9,7 +9,7 @@
     class CoreBytesType {
     public:
         static const int id = 1;
-        static std::vector<uint8_t> deserialize(BinaryReader& reader);
+        static Span<uint8_t> deserialize(BinaryReader& reader);
     };
 } // namespace rive
 #endif
\ No newline at end of file
diff --git a/include/rive/generated/assets/file_asset_contents_base.hpp b/include/rive/generated/assets/file_asset_contents_base.hpp
index 89565d2..10456cb 100644
--- a/include/rive/generated/assets/file_asset_contents_base.hpp
+++ b/include/rive/generated/assets/file_asset_contents_base.hpp
@@ -1,8 +1,8 @@
 #ifndef _RIVE_FILE_ASSET_CONTENTS_BASE_HPP_
 #define _RIVE_FILE_ASSET_CONTENTS_BASE_HPP_
-#include <vector>
 #include "rive/core.hpp"
 #include "rive/core/field_types/core_bytes_type.hpp"
+#include "rive/span.hpp"
 namespace rive {
     class FileAssetContentsBase : public Core {
     protected:
@@ -26,28 +26,17 @@
 
         static const uint16_t bytesPropertyKey = 212;
 
-    private:
-        std::vector<uint8_t> m_Bytes;
-
     public:
-        inline const std::vector<uint8_t>& bytes() const { return m_Bytes; }
-        void bytes(std::vector<uint8_t> value) {
-            if (m_Bytes == value) {
-                return;
-            }
-            m_Bytes = value;
-            bytesChanged();
-        }
+        virtual void decodeBytes(Span<uint8_t> value) = 0;
+        virtual void copyBytes(const FileAssetContentsBase& object) = 0;
 
         Core* clone() const override;
-        void copy(const FileAssetContentsBase& object) {
-            m_Bytes = object.m_Bytes;
-        }
+        void copy(const FileAssetContentsBase& object) { copyBytes(object); }
 
         bool deserialize(uint16_t propertyKey, BinaryReader& reader) override {
             switch (propertyKey) {
                 case bytesPropertyKey:
-                    m_Bytes = CoreBytesType::deserialize(reader);
+                    decodeBytes(CoreBytesType::deserialize(reader));
                     return true;
             }
             return false;
diff --git a/include/rive/generated/core_registry.hpp b/include/rive/generated/core_registry.hpp
index d7d46a3..dbe63f3 100644
--- a/include/rive/generated/core_registry.hpp
+++ b/include/rive/generated/core_registry.hpp
@@ -781,14 +781,6 @@
                     break;
             }
         }
-        static void
-        setBytes(Core* object, int propertyKey, std::vector<uint8_t> value) {
-            switch (propertyKey) {
-                case FileAssetContentsBase::bytesPropertyKey:
-                    object->as<FileAssetContentsBase>()->bytes(value);
-                    break;
-            }
-        }
         static std::string getString(Core* object, int propertyKey) {
             switch (propertyKey) {
                 case ComponentBase::namePropertyKey:
@@ -1157,13 +1149,6 @@
             }
             return 0;
         }
-        static std::vector<uint8_t> getBytes(Core* object, int propertyKey) {
-            switch (propertyKey) {
-                case FileAssetContentsBase::bytesPropertyKey:
-                    return object->as<FileAssetContentsBase>()->bytes();
-            }
-            return std::vector<uint8_t>();
-        }
         static int propertyFieldId(int propertyKey) {
             switch (propertyKey) {
                 case ComponentBase::namePropertyKey:
diff --git a/include/rive/generated/shapes/mesh_base.hpp b/include/rive/generated/shapes/mesh_base.hpp
index ff9b93d..736c86c 100644
--- a/include/rive/generated/shapes/mesh_base.hpp
+++ b/include/rive/generated/shapes/mesh_base.hpp
@@ -1,8 +1,8 @@
 #ifndef _RIVE_MESH_BASE_HPP_
 #define _RIVE_MESH_BASE_HPP_
-#include <vector>
 #include "rive/container_component.hpp"
 #include "rive/core/field_types/core_bytes_type.hpp"
+#include "rive/span.hpp"
 namespace rive {
     class MeshBase : public ContainerComponent {
     protected:
@@ -29,7 +29,7 @@
         static const uint16_t triangleIndexBytesPropertyKey = 223;
 
     public:
-        virtual void decodeTriangleIndexBytes(std::vector<uint8_t> value) = 0;
+        virtual void decodeTriangleIndexBytes(Span<uint8_t> value) = 0;
         virtual void copyTriangleIndexBytes(const MeshBase& object) = 0;
 
         Core* clone() const override;
diff --git a/include/rive/shapes/mesh.hpp b/include/rive/shapes/mesh.hpp
index 1b531e5..3484fe4 100644
--- a/include/rive/shapes/mesh.hpp
+++ b/include/rive/shapes/mesh.hpp
@@ -1,6 +1,7 @@
 #ifndef _RIVE_MESH_HPP_
 #define _RIVE_MESH_HPP_
 #include "rive/generated/shapes/mesh_base.hpp"
+#include "rive/span.hpp"
 
 namespace rive {
     class MeshVertex;
@@ -12,7 +13,7 @@
         StatusCode onAddedDirty(CoreContext* context) override;
         void markDrawableDirty();
         void addVertex(MeshVertex* vertex);
-        void decodeTriangleIndexBytes(std::vector<uint8_t> value) override;
+        void decodeTriangleIndexBytes(Span<uint8_t> value) override;
         void copyTriangleIndexBytes(const MeshBase& object) override;
 #ifdef TESTING
         std::vector<MeshVertex*>& vertices() { return m_Vertices; }
diff --git a/src/assets/file_asset_contents.cpp b/src/assets/file_asset_contents.cpp
index 1f552f6..2ba8602 100644
--- a/src/assets/file_asset_contents.cpp
+++ b/src/assets/file_asset_contents.cpp
@@ -13,4 +13,15 @@
     fileAssetImporter->loadContents(*this);
 
     return Super::import(importStack);
-}
\ No newline at end of file
+}
+
+void FileAssetContents::decodeBytes(Span<uint8_t> value) {
+    m_Bytes = std::vector(value.begin(), value.end());
+}
+
+void FileAssetContents::copyBytes(const FileAssetContentsBase& object) {
+    // Should never be called.
+    assert(false);
+}
+
+const std::vector<uint8_t>& FileAssetContents::bytes() const { return m_Bytes; }
\ No newline at end of file
diff --git a/src/core/binary_reader.cpp b/src/core/binary_reader.cpp
index c5e31e4..59004ec 100644
--- a/src/core/binary_reader.cpp
+++ b/src/core/binary_reader.cpp
@@ -1,5 +1,6 @@
 #include "rive/core/binary_reader.hpp"
 #include "rive/core/reader.h"
+#include "rive/span.hpp"
 #include <vector>
 
 using namespace rive;
@@ -50,15 +51,15 @@
     return std::string(rawValue.data(), length);
 }
 
-std::vector<uint8_t> BinaryReader::readBytes() {
+Span<uint8_t> BinaryReader::readBytes() {
     uint64_t length = readVarUint64();
     if (didOverflow()) {
-        return std::vector<uint8_t>();
+        return Span<uint8_t>(m_Position, 0);
     }
 
     uint8_t* start = m_Position;
     m_Position += length;
-    return std::vector<uint8_t>(start, start + length);
+    return Span<uint8_t>(start, length);
 }
 
 double BinaryReader::readFloat64() {
diff --git a/src/core/field_types/core_bytes_type.cpp b/src/core/field_types/core_bytes_type.cpp
index 68f7d8b..9a78bd2 100644
--- a/src/core/field_types/core_bytes_type.cpp
+++ b/src/core/field_types/core_bytes_type.cpp
@@ -3,6 +3,6 @@
 
 using namespace rive;
 
-std::vector<uint8_t> CoreBytesType::deserialize(BinaryReader& reader) {
+Span<uint8_t> CoreBytesType::deserialize(BinaryReader& reader) {
     return reader.readBytes();
 }
\ No newline at end of file
diff --git a/src/shapes/mesh.cpp b/src/shapes/mesh.cpp
index e84b27e..76e90a0 100644
--- a/src/shapes/mesh.cpp
+++ b/src/shapes/mesh.cpp
@@ -23,7 +23,7 @@
     return StatusCode::Ok;
 }
 
-void Mesh::decodeTriangleIndexBytes(std::vector<uint8_t> value) {
+void Mesh::decodeTriangleIndexBytes(Span<uint8_t> value) {
     // decode the triangle index bytes
 }