{"id":16866437,"url":"https://github.com/maxgraey/as-string-sink","last_synced_at":"2025-07-13T08:41:15.070Z","repository":{"id":43669122,"uuid":"364259894","full_name":"MaxGraey/as-string-sink","owner":"MaxGraey","description":"An efficient dynamically sized string buffer (aka String Builder) for AssemblyScript","archived":false,"fork":false,"pushed_at":"2023-02-17T00:14:12.000Z","size":237,"stargazers_count":28,"open_issues_count":1,"forks_count":3,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-01T13:51:19.940Z","etag":null,"topics":["assemblyscript","buffer","builder","performace","sink","string","webassembly"],"latest_commit_sha":null,"homepage":"","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/MaxGraey.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}},"created_at":"2021-05-04T13:10:16.000Z","updated_at":"2024-08-16T08:50:44.000Z","dependencies_parsed_at":"2024-01-18T03:48:23.826Z","dependency_job_id":null,"html_url":"https://github.com/MaxGraey/as-string-sink","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxGraey%2Fas-string-sink","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxGraey%2Fas-string-sink/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxGraey%2Fas-string-sink/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxGraey%2Fas-string-sink/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MaxGraey","download_url":"https://codeload.github.com/MaxGraey/as-string-sink/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244189798,"owners_count":20412991,"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","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":["assemblyscript","buffer","builder","performace","sink","string","webassembly"],"created_at":"2024-10-13T14:50:36.094Z","updated_at":"2025-03-22T07:30:37.745Z","avatar_url":"https://github.com/MaxGraey.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"String Sink\n===\n[![Build Status](https://github.com/MaxGraey/as-string-sink/actions/workflows/test.yml/badge.svg?event=push)](https://github.com/MaxGraey/as-string-sink/actions/workflows/test.yml?query=branch%3Amain)\n[![npm](https://img.shields.io/npm/v/as-string-sink.svg?color=007acc\u0026logo=npm)](https://www.npmjs.com/package/as-string-sink)\n\nAn efficient dynamically sized string buffer (aka **String Builder**) for AssemblyScript.\n\n## Interface\n\n```ts\nclass StringSink {\n  static withCapacity(capacity: i32)\n\n  constructor(initial: string = \"\", capacity: i32 = 32)\n\n  get length(): i32\n  get capacity(): i32\n\n  // Append sting or substring\n  write(src: string, start?: i32, end?: i32): void\n  // Append sting or substring with new line\n  writeLn(src?: string, start?: i32, end?: i32): void\n  // Append single code point\n  writeCodePoint(code: i32): void\n  // Append any integer or floating point number\n  writeNumber\u003cT\u003e(value: T): void\n\n  reserve(capacity: i32, clear?: bool): void\n  shrink(): void\n  clear(): void\n\n  // Convert buffer to normal string\n  toString(): string\n}\n```\n\n## Benchmark Results\n\nStringSink can be up to 4000 times faster than naive string concatenation! And up to 6 times faster than JS concat which uses rope data structure under the hood.\n\n100 strings:\n------------\n```ts\nString += JS:  0.013 ms\nString += AS:  0.014 ms\nStringSink AS: 0.0042 ms `(3x)`\n```\n\n50,000 strings:\n---------------\n```ts\nString += JS:  3.34 ms\nString += AS:  509.54 ms\nStringSink AS: 0.73 ms `(~700x)`\n```\n\n200,000 strings:\n----------------\n```ts\nString += JS:  11.93 ms\nString += AS:  7622.72 ms\nStringSink AS: 2.88 ms `(~2600x)`\n```\n\n## Usage 1. String accumulation (+=)\n\nnon efficient example:\n\n```ts\nfunction toList(arr: string[]): string {\n  let res = \"\";\n  for (let i = 0, len = arr.length; i \u003c len; i++) {\n    res += arr[i] + \"\\n\";\n  }\n  return res;\n}\n```\n\nefficient with `StringSink`:\n\n```ts\nfunction toList(arr: string[]): string {\n  let res = new StringSink();\n  for (let i = 0, len = arr.length; i \u003c len; i++) {\n    res.write(arr[i] + \"\\n\");\n  }\n  return res.toString();\n}\n```\n\neven more efficient:\n\n```ts\nfunction toList(arr: string[]): string {\n  let res = new StringSink();\n  for (let i = 0, len = arr.length; i \u003c len; i++) {\n    res.writeLn(arr[i]);\n  }\n  return res.toString();\n}\n```\n\nComplex example:\n\n```ts\nfunction zipAndStringify(names: string[], ages: i32[]): string {\n  assert(names.length == ages.length);\n\n  let res = new StringSink();\n  res.writeLn('[');\n  for (let i = 0, len = names.length; i \u003c len; i++) {\n    res.write('  { name: \"');\n    res.write(names[i]);\n    res.write('\", age: ');\n    res.writeNumber(ages[i]);\n    res.writeLn(' },');\n  }\n  res.write(']');\n  return res.toString();\n}\n\nassert(zipAndStringify(\n  [\"Alan\", \"Elon\", \"John D.\"],\n  [109, 50, 51]\n) == `[\n  { name: \"Alan\", age: 109 },\n  { name: \"Elon\", age: 50 },\n  { name: \"John D.\", age: 51 },\n]`);\n```\n\n## Usage 2. String accumulation (+=) only part of string\n\nnon efficient example:\n\n```ts\nfunction toListSliced(arr: string[]): string {\n  let res = \"\";\n  for (let i = 0, len = arr.length; i \u003c len; i++) {\n    res += arr[i].substring(1, 3);\n  }\n  return res;\n}\n```\n\nmore efficient with `StringSink`:\n\n```ts\nfunction toListSliced(arr: string[]): string {\n  let res = new StringSink();\n  for (let i = 0, len = arr.length; i \u003c len; i++) {\n    res.write(arr[i], 1, 3);\n  }\n  return res.toString();\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxgraey%2Fas-string-sink","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaxgraey%2Fas-string-sink","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxgraey%2Fas-string-sink/lists"}