{"id":29871604,"url":"https://github.com/mr-k-bear/enhance-data-view","last_synced_at":"2025-07-30T20:02:32.824Z","repository":{"id":303955803,"uuid":"1013647214","full_name":"Mr-k-bear/enhance-data-view","owner":"Mr-k-bear","description":"Reactive DataView extension with chainable API for type-safe binary data manipulation.","archived":false,"fork":false,"pushed_at":"2025-07-29T02:44:03.000Z","size":174,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-07-29T04:39:09.254Z","etag":null,"topics":["arraybuffer","binary","buffer","dataview","reactive","typescript","typescript-library","wasm","webassembly"],"latest_commit_sha":null,"homepage":"https://github.com/Mr-k-bear/enhance-data-view","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Mr-k-bear.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-04T08:34:38.000Z","updated_at":"2025-07-29T02:44:07.000Z","dependencies_parsed_at":"2025-07-29T04:22:23.574Z","dependency_job_id":"769312f5-cbcb-47a1-a10e-83d1f30eb4eb","html_url":"https://github.com/Mr-k-bear/enhance-data-view","commit_stats":null,"previous_names":["mr-k-bear/enhance-data-view"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Mr-k-bear/enhance-data-view","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mr-k-bear%2Fenhance-data-view","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mr-k-bear%2Fenhance-data-view/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mr-k-bear%2Fenhance-data-view/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mr-k-bear%2Fenhance-data-view/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Mr-k-bear","download_url":"https://codeload.github.com/Mr-k-bear/enhance-data-view/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mr-k-bear%2Fenhance-data-view/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267930533,"owners_count":24167472,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-30T02:00:09.044Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arraybuffer","binary","buffer","dataview","reactive","typescript","typescript-library","wasm","webassembly"],"created_at":"2025-07-30T20:01:08.040Z","updated_at":"2025-07-30T20:02:32.800Z","avatar_url":"https://github.com/Mr-k-bear.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DataView Enhanced (EDataView)\n\nEnhanced DataView(EDataView) is a lightweight binary data manipulation library, rigorously written in TypeScript, providing a chained API for type definition and reactive data manipulation.\n\n[![EDataView on npm](https://img.shields.io/npm/v/enhance-data-view.svg)](https://www.npmjs.com/package/enhance-data-view)\n![MIT](https://img.shields.io/badge/License-MIT-yellow.svg)\n\n## Core Features\n\n- **Declarative Type System:** Define complex data structures through a concise chained API, abstracting underlying binary operations\n- **Automatic Memory Layout Calculation:** Intelligently handles memory alignment requirements, compatible with WASM modules compiled from static languages\n- **Reactive Data Manipulation:** Based on Proxy implementation, supports partial modification of complex data structures\n- **Precise Type Inference:** Type definitions automatically map to the TypeScript type system\n- **Highly Extensible Architecture:** Interface-based API design supports flexible functionality extensions\n\n## Installation\n\n```bash\nnpm install enhanced-data-view\n```\n\nUsing EDataView from CDN (jsdelivr)\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/enhance-data-view/dist/index.umd.mini.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\nconst { defineArray, defineString, defineStruct, types, reactive, toRaw } = window.EDataView;\n\u003c/script\u003e\n```\n\n## Quick Start\n\n```typescript\nimport { defineArray, defineString, defineStruct, types, reactive, toRaw } from \"enhance-data-view\";\n\n// Define type\nconst StructPerson = defineStruct({\n    id: types.UINT_32,\n    name: defineString(10, 0).freeze(),\n    friends: defineArray(types.UINT_32, 4).freeze()\n}).freeze();\n\n// Use 'StructPerson.size' to get the byte size of the type\nconst dataView = new DataView(new ArrayBuffer(StructPerson.size));\n// Make dataView reactive ✨\nconst person = reactive(dataView, StructPerson, 0, true);\n// TypeScript automatically infers the type of person as follows:\n// const person: {\n//     id: number;\n//     name: string;\n//     friends: number[];\n// }\n\n// Write data to DataView\nperson.id = 1;\nperson.name = \"MrKBear\";\nperson.friends = [2, 3, 4, 5];\nperson.friends[1] = 0xff;\n\n// Read data from dataView\nconsole.log(dataView.buffer);\n// \u003c01 00 00 00 \n//  4d 72 4b 42 65 61 72 00 00 00 00 00\n//  02 00 00 00 ff 00 00 00 04 00 00 00 05 00 00 00\u003e\nconsole.log(person.id); // 1\nconsole.log(person.name); // MrKBear\nconsole.log(toRaw(person.friends)); // [2, 255, 4, 5]\n```\n\n## Design Philosophy\n\nEDataView is designed around two core issues:\n\n- **Type Definition:** How to describe binary data structures\n- **Data Manipulation:** How to perform binary read/write based on type definitions\n\n## Type Definition\n\n### Primitive Types\n\nEDataView predefines various common types, supporting on-demand import or batch import:\n\n```typescript\n// Introduce all primitive types at once\nimport { types } from \"enhance-data-view\";\ntypes.UINT_8;\ntypes.FLOAT_32;\n\n// Selective import\nimport { UINT_8, FLOAT_32 } from \"enhance-data-view\";\n```\n\n### Struct Types\n\nCreate structs through the `defineStruct` function:\n\n```typescript\nimport { defineStruct, types } from \"enhance-data-view\";\n\n// Chained declaration syntax\nconst MyStruct = defineStruct()\n    .addProperty(\"foo\", types.UINT_8)\n    .addProperty(\"bar\", types.FLOAT_32)\n    .freeze(); // Freeze definition to improve performance and prevent subsequent erroneous modifications\n\n// Configuration object syntax\nconst MyStruct = defineStruct({\n    foo: types.UINT_8,\n    bar: types.FLOAT_32\n}).freeze();\n```\n\nWe recommend the chained declaration syntax, as it is more flexible and secure.\n\n### Array Types\n\nDefine array types through the `defineArray` function:\n\n```typescript\nimport { defineArray, types } from \"enhance-data-view\";\n\n// Array of FLOAT_32 with length 4\nconst MyArray = defineArray(types.FLOAT_32, 4).freeze();\n// Array of structs with length 16\nconst MyStructArray = defineArray(MyStruct, 16).freeze();\n// Two-dimensional array\nconst My2DArray = defineArray(MyArray, 2).freeze();\n```\n\n### String Types\n\nDefine string types through the `defineString` function:\n\n```typescript\nimport { defineString } from \"enhance-data-view\";\n\n// Define a string of length 10, unused space filled with 0 (NULL)\nconst MyString = defineString(10, 0).freeze();\n```\n\n## Binary Operations\n\n### Reactive Read/Write\n\nThe core capability of EDataView is providing reactive data access to `ArrayBuffer`. Through the powerful `reactive`/`ref` functions, you can map any data type in DataView to a JavaScript Proxy object.\n\nAll operations on the Proxy object will be reactively synchronized to the original `ArrayBuffer`. This feature is particularly suitable for handling dynamic data in WebAssembly (WASM) memory.\n\n```typescript\nimport { defineStruct, reactive, types } from \"enhance-data-view\";\n\n// Define struct type using chained API\nconst MyStruct = defineStruct()\n    .addProperty(\"foo\", types.UINT_8)\n    .addProperty(\"bar\", types.FLOAT_32)\n    .freeze();\n\nconst dataView = new DataView(new ArrayBuffer(MyStruct.size));\n// Convert DataView to reactive proxy object\nconst data = reactive(dataView, MyStruct, 0);\n// Modifications are directly written to DataView\ndata.bar = 1;\n// Property read operations retrieve the latest value from DataView in real-time\nconsole.log(data.bar);\n```\n\nWhen handling primitive value types (such as number/boolean), using reactive directly will fail because JavaScript's proxy mechanism cannot intercept direct assignment operations on primitive values. \n\nIn this case, the ref function must be used.\n\n```typescript\nimport { reactive, ref, types } from \"enhance-data-view\";\nconst dataView = new DataView(types.FLOAT_32.size);\n\n// ❌ Value type trap: reactive only applies to objects\nlet data = reactive(dataView, types.FLOAT_32, 0);\n// This operation will not synchronize to DataView\ndata = 1;\n\n// ✅ Value type solution: use ref wrapper\nlet refData = ref(dataView, types.FLOAT_32, 0);\n// Automatically writes to DataView\nrefData.value = 1;\n```\n\n### Bulk Read/Write\n\nWhen reading/writing data structures in bulk, the property-by-property access pattern of reactive operations incurs significant performance overhead. In such cases, the get/set functions should be used for efficient single operations.\n\n```typescript\nimport { defineArray, defineStruct, reactive, get, types } from \"enhance-data-view\";\n\nconst MyStruct = defineStruct()\n    .addProperty(\"foo\", types.UINT_8)\n    .addProperty(\"bar\", types.FLOAT_32)\n    .freeze();\nconst MyArray = defineArray(MyStruct, 1000).freeze();\n// Struct array with length 1000\nconst dataView = new DataView(new ArrayBuffer(MyArray.size));\n\n// ❌ Inefficient operation: traversing large amounts of data through reactive proxy\nconst reactiveData = reactive(dataView, MyArray, 0);\nfor (let i = 0; i \u003c reactiveData.length; i++) {\n    console.log(reactiveData[i].foo);\n    console.log(reactiveData[i].bar);\n}\n\n// ✅ Efficient solution: use get for batch reading\nconst allData = get(dataView, MyArray, 0);\nfor (let i = 0; i \u003c allData.length; i++) {\n    console.log(allData[i].foo);\n    console.log(allData[i].bar);\n}\n```\n\nEDataView also provides the `toRaw` function for efficiently extracting raw data objects from reactive proxies, supporting full deep copy reads.\n\n```typescript\nimport { defineArray, defineStruct, reactive, toRaw, types } from \"enhance-data-view\";\n\nconst MyStruct = defineStruct()\n    .addProperty(\"foo\", types.UINT_8)\n    .addProperty(\"bar\", defineStruct()\n        .addProperty(\"apple\", types.UINT_8)\n        .addProperty(\"banana\", types.FLOAT_32)\n        .freeze()\n    ).freeze();\nconst dataView = new DataView(new ArrayBuffer(MyStruct.size));、\n// Reactive proxy of nested struct\nconst data = reactive(dataView, MyStruct, 0);\n// Use toRaw to efficiently extract nested struct data\n// Advantage: avoids proxy layer overhead, directly obtains deep copy object\nconst bar = toRaw(data.bar);\n```\n\n## Advanced Section\n\n### Comparison of Two Struct Declaration Methods\n\nAlthough the configuration object syntax is intuitive and clear, the enumeration order of JavaScript object properties may be inconsistent with the declaration order (underlying dependency on `Object.entries` order), while memory layout strictly depends on field order.\n\nTo ensure order determinism, you can use `defineProperty` to explicitly specify the order parameter.\n\n```typescript\nimport { defineStruct, defineProperty, types } from \"enhance-data-view\";\n\nconst MyStruct = defineStruct({\n    foo: defineProperty(types.UINT_8, { order: 0 }),\n    bar: defineProperty(types.FLOAT_32, { order: 1 })\n}).freeze();\n```\n\n### Struct Layout Calculation\n\nThe struct memory layout is automatically calculated based on the alignment requirements (align) of property types. `defineStruct` automatically inserts padding bytes to meet the alignment requirements of all properties, similar to static language compilers.\n\n\u003e If you try to print `MyStruct.size`, the result is not 5, but 8, because `defineStruct` automatically adds 3 bytes of padding after `UINT_8` to meet the alignment requirements of `FLOAT_32`.\n\nEach type has a predefined alignment value, which can also be explicitly overridden using the align parameter to create a compact layout:\n\n```typescript\nimport { defineStruct, defineProperty, types } from \"enhance-data-view\";\n\n// Chained declaration syntax\nconst MyCompactStruct = defineStruct()\n    .addProperty(\"foo\", types.UINT_8, { align: 1 })\n    .addProperty(\"bar\", types.FLOAT_32, { align: 1 })\n    .freeze();\n\n// Configuration object syntax\nconst MyCompactStruct = defineStruct({\n    foo: defineProperty(types.UINT_8, { order: 0, align: 1 }),\n    bar: defineProperty(types.FLOAT_32, { order: 1, align: 1 })\n}).freeze();\n```\n\n\u003e Now printing `MyCompactStruct.size` yields a value of 5\n\n### Struct Padding Properties\n\nIn some scenarios, you may only need to manipulate certain fields within a struct. In this case, you can use padding fields or manual layout to skip irrelevant data areas and achieve precise memory positioning.\n\nFor example: accessing `foo` and `bar` from the 32 byte offset of the struct:\n\n```typescript\nimport { defineStruct, defineProperty, definePadding, types } from \"enhance-data-view\";\n\n// Chained declaration syntax\nconst MyLayoutStruct = defineStruct()\n    // Manually insert 32 bytes of padding\n    .addPadding(\"p\", 32)\n    .addProperty(\"foo\", types.UINT_8)\n    .addProperty(\"bar\", types.FLOAT_32)\n    .freeze();\n\n// Configuration object syntax\nconst MyLayoutStruct = defineStruct({\n    // Manually insert 32 bytes of padding\n    p: definePadding(32),\n    foo: defineProperty(types.UINT_8),\n    bar: defineProperty(types.FLOAT_32)\n}).freeze();\n```\n\n### Struct Padding Properties\n\nIf automatic layout cannot meet complex requirements, `defineStruct` supports manual layout mode: by directly specifying field offsets to precisely control memory layout, completely bypassing the automatic calculation mechanism.\n\nRegardless of whether automatic or manual layout is used, `defineStruct` intelligently calculates the total size of the struct.\n\n\u003e For example, `MyLayoutStruct.size` in the example will correctly return 40 bytes\n\n```typescript\nimport { defineStruct, defineProperty, types } from \"enhance-data-view\";\n\n// Chained declaration syntax\nconst MyLayoutStruct = defineStruct()\n    .addProperty(\"foo\", types.UINT_8, { offset: 0x20 })\n    .addProperty(\"bar\", types.FLOAT_32, { offset: 0x24 })\n    .freeze();\n\n// Configuration object syntax\nconst MyLayoutStruct = defineStruct({\n    foo: defineProperty(types.UINT_8, { offset: 0x20 }),\n    bar: defineProperty(types.FLOAT_32, { offset: 0x24 })\n}).freeze();\n```\n\n### String Character Set\n\nBy default, `defineString` uses the UTF-8 character set (based on `TextEncoder`/`TextDecoder` implementation).\n\nIf other character sets need to be supported, flexible extensions can be achieved through custom codecs.\n\nFor example, using `iconv-lite` to implement GBK character set reading and writing:\n\n```typescript\nimport iconv from \"iconv-lite\";\nimport { defineString, ref } from \"enhance-data-view\";\n\nconst GBKString = defineString(12)\n// Use encoder/decoder provided by iconv-lite\n.setCoder({\n    encode: string =\u003e new Uint8Array(iconv.encode(string, \"GBK\")),\n    decode: buffer =\u003e iconv.decode(Buffer.from(buffer), \"GBK\")\n});\nconst dataView = new DataView(new ArrayBuffer(GBKString.size));\nconst string = ref(dataView, GBKString, 0);\nstring.value = \"你好\";\n```\n\n## Contribution\n\nWelcome to contribute to the project!\n\nWhether it's submitting a Pull Request, proposing feature suggestions, or reporting encountered issues, each of your contributions will help build a more powerful EDataView!\n\nMembers:\n\n- @MrKBear \u003cmrkbear@qq.com,mrkbear@mrkbear.com\u003e\n\n## License\n\nMIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmr-k-bear%2Fenhance-data-view","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmr-k-bear%2Fenhance-data-view","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmr-k-bear%2Fenhance-data-view/lists"}