#!/usr/bin/env python
import struct
import sys


SIGNATURE_WEB = "UnityWeb"
SIGNATURE_RAW = "UnityRaw"


class BinaryReader:
	def __init__(self, buf):
		self.buf = buf

	def read_string(self, encoding="utf-8"):
		ret = []
		c = b""
		while c != b"\0":
			ret.append(c)
			c = self.buf.read(1)
			if not c:
				raise ValueError("Unterminated string: %r" % (ret))
		return b"".join(ret).decode(encoding)

	def read_int(self):
		return struct.unpack(">i", self.buf.read(4))[0]

	def read_uint(self):
		return struct.unpack(">I", self.buf.read(4))[0]


class AssetBundle:
	@classmethod
	def from_path(cls, path):
		ret = cls()
		ret.load_file(path)
		return ret

	def __init__(self):
		self.file = None

	def __del__(self):
		if self.file:
			self.file.close()

	@property
	def files(self):
		return []

	def load_file(self, path):
		file = open(path, "rb")
		self.file = file
		self.read_header()

	def read_header(self):
		buf = BinaryReader(self.file)
		self.signature = buf.read_string()
		self.format_version = buf.read_int()
		self.unity_version = buf.read_string()
		self.generator_version = buf.read_string()
		self.file_size = buf.read_uint()
		self.header_size = buf.read_int()

		self.file_count = buf.read_int()
		self.bundle_count = buf.read_int()

		if self.format_version >= 2:
			self.complete_file_size = buf.read_uint()

			if self.format_version >= 3:
				self.data_header_size = buf.read_uint()

		buf.buf.read(1)


def main():
	files = sys.argv[1:]
	for file in files:
		bundle = AssetBundle.from_path(file)
		print(bundle.files)


if __name__ == "__main__":
	main()

@@ -40,16 +40,39 @@
 ort sys%0A
+from io import BytesIO%0A
 %0A%0ASIGNAT
@@ -293,28 +293,24 @@
 %09%09%09c = self.
-buf.
 read(1)%0A%09%09%09i
@@ -415,16 +415,169 @@
 oding)%0A%0A
+%09def read(self, *args):%0A%09%09return self.buf.read(*args)%0A%0A%09def seek(self, *args):%0A%09%09return self.buf.seek(*args)%0A%0A%09def tell(self):%0A%09%09return self.buf.tell()%0A%0A
 %09def rea
@@ -615,36 +615,32 @@
 pack(%22%3Ei%22, self.
-buf.
 read(4))%5B0%5D%0A%0A%09de
@@ -688,28 +688,24 @@
 (%22%3EI%22, self.
-buf.
 read(4))%5B0%5D%0A
@@ -703,16 +703,519 @@
 d(4))%5B0%5D
+%0A%0A%0Aclass Asset:%0A%09def __repr__(self):%0A%09%09return %22%3CAsset %25s%3E%22 %25 (self.name)%0A%0A%09def read_header(self, buf):%0A%09%09offset = buf.tell()%0A%09%09self.name = buf.read_string()%0A%09%09self.header_size = buf.read_uint()%0A%09%09self.size = buf.read_uint()%0A%0A%09%09buf.seek(offset + self.header_size)%0A%09%09self.file_size = buf.read_uint()%0A%09%09self.format = buf.read_uint()%0A%09%09self.data_offset = buf.read_uint()%0A%09%09self.endianness = buf.read_uint()%0A%0A%09%09assert self.endianness == 0%0A%09%09assert self.format %3E= 9%0A%0A%09%09self.data = BytesIO(buf.read(self.size))
 %0A%0A%0Aclass
@@ -1358,16 +1358,35 @@
 e = None
+%0A%09%09self.assets = %5B%5D
 %0A%0A%09def _
@@ -2097,22 +2097,362 @@
 %0A%0A%09%09
-buf.buf.read(1
+if self.header_size %3E= 60:%0A%09%09%09self.uncompressed_file_size = buf.read_uint()%0A%09%09%09self.bundle_header_size = buf.read_uint()%0A%0A%09%09assert self.signature == SIGNATURE_RAW%0A%0A%09%09# Preload assets%0A%09%09buf.seek(self.header_size)%0A%09%09self.num_assets = buf.read_int()%0A%09%09for i in range(self.num_assets):%0A%09%09%09asset = Asset()%0A%09%09%09asset.read_header(buf)%0A%09%09%09self.assets.append(asset
 )%0A%0A%0A

Implement reading asset metadata