diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..b41d1dd --- /dev/null +++ b/bun.lock @@ -0,0 +1,234 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "rescript-bun", + "devDependencies": { + "@changesets/cli": "^2.29.5", + "rescript": "12.0.0-rc.3", + }, + "peerDependencies": { + "rescript": ">= 12.0.0-alpha.4", + }, + }, + }, + "packages": { + "@babel/runtime": ["@babel/runtime@7.27.6", "", {}, "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q=="], + + "@changesets/apply-release-plan": ["@changesets/apply-release-plan@7.0.12", "", { "dependencies": { "@changesets/config": "^3.1.1", "@changesets/get-version-range-type": "^0.4.0", "@changesets/git": "^3.0.4", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "detect-indent": "^6.0.0", "fs-extra": "^7.0.1", "lodash.startcase": "^4.4.0", "outdent": "^0.5.0", "prettier": "^2.7.1", "resolve-from": "^5.0.0", "semver": "^7.5.3" } }, "sha512-EaET7As5CeuhTzvXTQCRZeBUcisoYPDDcXvgTE/2jmmypKp0RC7LxKj/yzqeh/1qFTZI7oDGFcL1PHRuQuketQ=="], + + "@changesets/assemble-release-plan": ["@changesets/assemble-release-plan@6.0.9", "", { "dependencies": { "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.3", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "semver": "^7.5.3" } }, "sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ=="], + + "@changesets/changelog-git": ["@changesets/changelog-git@0.2.1", "", { "dependencies": { "@changesets/types": "^6.1.0" } }, "sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q=="], + + "@changesets/cli": ["@changesets/cli@2.29.5", "", { "dependencies": { "@changesets/apply-release-plan": "^7.0.12", "@changesets/assemble-release-plan": "^6.0.9", "@changesets/changelog-git": "^0.2.1", "@changesets/config": "^3.1.1", "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.3", "@changesets/get-release-plan": "^4.0.13", "@changesets/git": "^3.0.4", "@changesets/logger": "^0.1.1", "@changesets/pre": "^2.0.2", "@changesets/read": "^0.6.5", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@changesets/write": "^0.4.0", "@manypkg/get-packages": "^1.1.3", "ansi-colors": "^4.1.3", "ci-info": "^3.7.0", "enquirer": "^2.4.1", "external-editor": "^3.1.0", "fs-extra": "^7.0.1", "mri": "^1.2.0", "p-limit": "^2.2.0", "package-manager-detector": "^0.2.0", "picocolors": "^1.1.0", "resolve-from": "^5.0.0", "semver": "^7.5.3", "spawndamnit": "^3.0.1", "term-size": "^2.1.0" }, "bin": { "changeset": "bin.js" } }, "sha512-0j0cPq3fgxt2dPdFsg4XvO+6L66RC0pZybT9F4dG5TBrLA3jA/1pNkdTXH9IBBVHkgsKrNKenI3n1mPyPlIydg=="], + + "@changesets/config": ["@changesets/config@3.1.1", "", { "dependencies": { "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.3", "@changesets/logger": "^0.1.1", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "fs-extra": "^7.0.1", "micromatch": "^4.0.8" } }, "sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA=="], + + "@changesets/errors": ["@changesets/errors@0.2.0", "", { "dependencies": { "extendable-error": "^0.1.5" } }, "sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow=="], + + "@changesets/get-dependents-graph": ["@changesets/get-dependents-graph@2.1.3", "", { "dependencies": { "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "picocolors": "^1.1.0", "semver": "^7.5.3" } }, "sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ=="], + + "@changesets/get-release-plan": ["@changesets/get-release-plan@4.0.13", "", { "dependencies": { "@changesets/assemble-release-plan": "^6.0.9", "@changesets/config": "^3.1.1", "@changesets/pre": "^2.0.2", "@changesets/read": "^0.6.5", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3" } }, "sha512-DWG1pus72FcNeXkM12tx+xtExyH/c9I1z+2aXlObH3i9YA7+WZEVaiHzHl03thpvAgWTRaH64MpfHxozfF7Dvg=="], + + "@changesets/get-version-range-type": ["@changesets/get-version-range-type@0.4.0", "", {}, "sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ=="], + + "@changesets/git": ["@changesets/git@3.0.4", "", { "dependencies": { "@changesets/errors": "^0.2.0", "@manypkg/get-packages": "^1.1.3", "is-subdir": "^1.1.1", "micromatch": "^4.0.8", "spawndamnit": "^3.0.1" } }, "sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw=="], + + "@changesets/logger": ["@changesets/logger@0.1.1", "", { "dependencies": { "picocolors": "^1.1.0" } }, "sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg=="], + + "@changesets/parse": ["@changesets/parse@0.4.1", "", { "dependencies": { "@changesets/types": "^6.1.0", "js-yaml": "^3.13.1" } }, "sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q=="], + + "@changesets/pre": ["@changesets/pre@2.0.2", "", { "dependencies": { "@changesets/errors": "^0.2.0", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", "fs-extra": "^7.0.1" } }, "sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug=="], + + "@changesets/read": ["@changesets/read@0.6.5", "", { "dependencies": { "@changesets/git": "^3.0.4", "@changesets/logger": "^0.1.1", "@changesets/parse": "^0.4.1", "@changesets/types": "^6.1.0", "fs-extra": "^7.0.1", "p-filter": "^2.1.0", "picocolors": "^1.1.0" } }, "sha512-UPzNGhsSjHD3Veb0xO/MwvasGe8eMyNrR/sT9gR8Q3DhOQZirgKhhXv/8hVsI0QpPjR004Z9iFxoJU6in3uGMg=="], + + "@changesets/should-skip-package": ["@changesets/should-skip-package@0.1.2", "", { "dependencies": { "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3" } }, "sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw=="], + + "@changesets/types": ["@changesets/types@6.1.0", "", {}, "sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA=="], + + "@changesets/write": ["@changesets/write@0.4.0", "", { "dependencies": { "@changesets/types": "^6.1.0", "fs-extra": "^7.0.1", "human-id": "^4.1.1", "prettier": "^2.7.1" } }, "sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q=="], + + "@manypkg/find-root": ["@manypkg/find-root@1.1.0", "", { "dependencies": { "@babel/runtime": "^7.5.5", "@types/node": "^12.7.1", "find-up": "^4.1.0", "fs-extra": "^8.1.0" } }, "sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA=="], + + "@manypkg/get-packages": ["@manypkg/get-packages@1.1.3", "", { "dependencies": { "@babel/runtime": "^7.5.5", "@changesets/types": "^4.0.1", "@manypkg/find-root": "^1.1.0", "fs-extra": "^8.1.0", "globby": "^11.0.0", "read-yaml-file": "^1.1.0" } }, "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A=="], + + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + + "@rescript/darwin-arm64": ["@rescript/darwin-arm64@12.0.0-rc.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-d6OMJWnW8I9DgYPNw+9Gy72tOcgRqry+NkpVWYYU4+Ay/LAfCs1W+AWUmsKTlxwTe2JTLhXRX3HzrqXSQoC6tg=="], + + "@rescript/darwin-x64": ["@rescript/darwin-x64@12.0.0-rc.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-ualm4FZRztHaxY7YbEbSgNQwBPRPEsyn30/xHSkuCY2CV7W7808H29X33bqnDkQZ1XxmnG3z2bz9UoZcJJnf6A=="], + + "@rescript/linux-arm64": ["@rescript/linux-arm64@12.0.0-rc.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-StPyP+KHY1k2CQrVLV52VnQvgeQIKz8woEYB0JRL4LtYDb6g6jVj9aXiq6ZWyVo9vxas1zSCzCvzrXubIsgkmg=="], + + "@rescript/linux-x64": ["@rescript/linux-x64@12.0.0-rc.3", "", { "os": "linux", "cpu": "x64" }, "sha512-HB9K4huyr8zCET5BnUJQgskMpiJXERFc7P2mO0vDgMKgmDEmEeOVTUfFiO9aqCwFP/ujGFsWb47SEUxTmHOCcA=="], + + "@rescript/runtime": ["@rescript/runtime@12.0.0-rc.3", "", {}, "sha512-Ihdnppw7A+ArLwfnLPcz04jh6ZaKADo0Rc6vMHYQ2+Dw+snO5VbxJ2As5ahVt9nUVL56w1k9pWgrIoLtb1eHcA=="], + + "@rescript/win32-x64": ["@rescript/win32-x64@12.0.0-rc.3", "", { "os": "win32", "cpu": "x64" }, "sha512-Eyy61o6Wk3Cgiy/99zFCzxumL1WHOGEdbxU+ksqghuD3s2RgBWBobSygf3nhcoNBibXI0Fhpu+XXXoTOsTiQ9w=="], + + "@types/node": ["@types/node@12.20.55", "", {}, "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ=="], + + "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="], + + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + + "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="], + + "better-path-resolve": ["better-path-resolve@1.0.0", "", { "dependencies": { "is-windows": "^1.0.0" } }, "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "chardet": ["chardet@0.7.0", "", {}, "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="], + + "ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "detect-indent": ["detect-indent@6.1.0", "", {}, "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA=="], + + "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="], + + "enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="], + + "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], + + "extendable-error": ["extendable-error@0.1.7", "", {}, "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg=="], + + "external-editor": ["external-editor@3.1.0", "", { "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", "tmp": "^0.0.33" } }, "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew=="], + + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], + + "fs-extra": ["fs-extra@7.0.1", "", { "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw=="], + + "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "human-id": ["human-id@4.1.1", "", { "bin": "dist/cli.js" }, "sha512-3gKm/gCSUipeLsRYZbbdA1BD83lBoWUkZ7G9VFrhWPAU76KwYo5KR8V28bpoPm/ygy0x5/GCbpRQdY7VLYCoIg=="], + + "iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], + + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "is-subdir": ["is-subdir@1.2.0", "", { "dependencies": { "better-path-resolve": "1.0.0" } }, "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw=="], + + "is-windows": ["is-windows@1.0.2", "", {}, "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": "bin/js-yaml.js" }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="], + + "jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], + + "locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], + + "lodash.startcase": ["lodash.startcase@4.4.0", "", {}, "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], + + "os-tmpdir": ["os-tmpdir@1.0.2", "", {}, "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="], + + "outdent": ["outdent@0.5.0", "", {}, "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q=="], + + "p-filter": ["p-filter@2.1.0", "", { "dependencies": { "p-map": "^2.0.0" } }, "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw=="], + + "p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], + + "p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], + + "p-map": ["p-map@2.1.0", "", {}, "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw=="], + + "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], + + "package-manager-detector": ["package-manager-detector@0.2.11", "", { "dependencies": { "quansync": "^0.2.7" } }, "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ=="], + + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "pify": ["pify@4.0.1", "", {}, "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="], + + "prettier": ["prettier@2.8.8", "", { "bin": "bin-prettier.js" }, "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="], + + "quansync": ["quansync@0.2.10", "", {}, "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "read-yaml-file": ["read-yaml-file@1.1.0", "", { "dependencies": { "graceful-fs": "^4.1.5", "js-yaml": "^3.6.1", "pify": "^4.0.1", "strip-bom": "^3.0.0" } }, "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA=="], + + "rescript": ["rescript@12.0.0-rc.3", "", { "dependencies": { "@rescript/runtime": "12.0.0-rc.3" }, "optionalDependencies": { "@rescript/darwin-arm64": "12.0.0-rc.3", "@rescript/darwin-x64": "12.0.0-rc.3", "@rescript/linux-arm64": "12.0.0-rc.3", "@rescript/linux-x64": "12.0.0-rc.3", "@rescript/win32-x64": "12.0.0-rc.3" }, "bin": { "bsc": "cli/bsc.js", "bstracing": "cli/bstracing.js", "rescript": "cli/rescript.js", "rescript-legacy": "cli/rescript-legacy.js", "rescript-tools": "cli/rescript-tools.js" } }, "sha512-8EOLvO6p5MxpprqpN4tbblfk6uJbz2Q5g/VHA7ii7TJu98JFNLehRjPNHhlEk2G4Lx+PZraSnGudTxBVmyLNoQ=="], + + "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], + + "spawndamnit": ["spawndamnit@3.0.1", "", { "dependencies": { "cross-spawn": "^7.0.5", "signal-exit": "^4.0.1" } }, "sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg=="], + + "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], + + "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], + + "term-size": ["term-size@2.2.1", "", {}, "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg=="], + + "tmp": ["tmp@0.0.33", "", { "dependencies": { "os-tmpdir": "~1.0.2" } }, "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "@manypkg/find-root/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], + + "@manypkg/get-packages/@changesets/types": ["@changesets/types@4.1.0", "", {}, "sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw=="], + + "@manypkg/get-packages/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], + } +} diff --git a/src/FFI.js b/src/FFI.js new file mode 100644 index 0000000..0500cdf --- /dev/null +++ b/src/FFI.js @@ -0,0 +1,21 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + + +let CString = {}; + +let JSCallback = {}; + +let CFunction = {}; + +let CC = {}; + +let Read = {}; + +export { + CString, + JSCallback, + CFunction, + CC, + Read, +} +/* No side effect */ diff --git a/src/FFI.res b/src/FFI.res new file mode 100644 index 0000000..5cc34e4 --- /dev/null +++ b/src/FFI.res @@ -0,0 +1,329 @@ +/** + * `bun:ffi` lets you efficiently call C functions & FFI functions from JavaScript + * without writing bindings yourself. + * + * This is powered by just-in-time compiling C wrappers + * that convert JavaScript types to C types and back. Internally, + * bun uses [tinycc](https://github.com/TinyCC/tinycc). + */ + +/** Opaque pointer type representing a memory address */ +type pointer + +/** FFI type enum for specifying C ABI types */ +type ffiType = + | @as(0) Char + | @as(1) Int8_t + | @as(2) Uint8_t + | @as(3) Int16_t + | @as(4) Uint16_t + | @as(5) Int32_t + | @as(6) Uint32_t + | @as(7) Int64_t + | @as(8) Uint64_t + | @as(9) Double + | @as(10) Float + | @as(11) Bool + | @as(12) Ptr + | @as(13) Void + | @as(14) Cstring + | @as(15) I64_fast + | @as(16) U64_fast + | @as(17) Function + | @as(18) Napi_env + | @as(19) Napi_value + | @as(20) FFIBuffer + +/** FFI type can also be specified as a string */ +type ffiTypeOrString = + | FFIType(ffiType) + | @as("char") CharStr + | @as("int8_t") Int8_tStr + | @as("i8") I8Str + | @as("uint8_t") Uint8_tStr + | @as("u8") U8Str + | @as("int16_t") Int16_tStr + | @as("i16") I16Str + | @as("uint16_t") Uint16_tStr + | @as("u16") U16Str + | @as("int32_t") Int32_tStr + | @as("i32") I32Str + | @as("int") IntStr + | @as("uint32_t") Uint32_tStr + | @as("u32") U32Str + | @as("int64_t") Int64_tStr + | @as("i64") I64Str + | @as("uint64_t") Uint64_tStr + | @as("u64") U64Str + | @as("double") DoubleStr + | @as("f64") F64Str + | @as("float") FloatStr + | @as("f32") F32Str + | @as("bool") BoolStr + | @as("ptr") PtrStr + | @as("pointer") PointerStr + | @as("void") VoidStr + | @as("cstring") CstringStr + | @as("function") FunctionStr + | @as("usize") UsizeStr + | @as("callback") CallbackStr + | @as("napi_env") Napi_envStr + | @as("napi_value") Napi_valueStr + | @as("buffer") BufferStr + +/** Definition of a C function for FFI */ +type ffiFunction = { + args?: array, + returns?: ffiTypeOrString, + ptr?: pointer, + threadsafe?: bool, +} + +/** A library opened with dlopen */ +type library<'symbols> = { + symbols: 'symbols, +} + +/** Close a library, unloading the symbols and freeing allocated memory */ +@send external closeLibrary: library<'a> => unit = "close" + +/** + * Open a library using `"bun:ffi"` + * + * @param name The name of the library or file path. This will be passed to `dlopen()` + * @param symbols Map of symbols to load where the key is the symbol name and the value is the FFIFunction + */ +@module("bun:ffi") +external dlopen: (string, 'symbols) => library<'result> = "dlopen" + +/** + * Open a library from a BunFile + */ +@module("bun:ffi") +external dlopenFile: (Types.bunFile, 'symbols) => library<'result> = "dlopen" + +/** + * Link a map of symbols to JavaScript functions. + * + * This lets you use native libraries that were already loaded somehow. + * You usually will want `dlopen` instead. + */ +@module("bun:ffi") +external linkSymbols: 'symbols => library<'result> = "linkSymbols" + +/** + * Get the pointer backing a TypedArray or ArrayBuffer. + * + * Use this to pass TypedArray or ArrayBuffer to C functions. + */ +@module("bun:ffi") +external ptrOfTypedArray: TypedArray.t<'a> => pointer = "ptr" + +@module("bun:ffi") +external ptrOfArrayBuffer: ArrayBuffer.t => pointer = "ptr" + +@module("bun:ffi") +external ptrOfDataView: DataView.t => pointer = "ptr" + +@module("bun:ffi") +external ptrOfTypedArrayWithOffset: (TypedArray.t<'a>, ~byteOffset: int) => pointer = "ptr" + +@module("bun:ffi") +external ptrOfArrayBufferWithOffset: (ArrayBuffer.t, ~byteOffset: int) => pointer = "ptr" + +@module("bun:ffi") +external ptrOfDataViewWithOffset: (DataView.t, ~byteOffset: int) => pointer = "ptr" + +/** + * Read a pointer as a Buffer + * + * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. + */ +@module("bun:ffi") +external toBuffer: pointer => Buffer.t = "toBuffer" + +@module("bun:ffi") +external toBufferWithOffset: (pointer, ~byteOffset: int) => Buffer.t = "toBuffer" + +@module("bun:ffi") +external toBufferWithOffsetAndLength: (pointer, ~byteOffset: int, ~byteLength: int) => Buffer.t = + "toBuffer" + +/** + * Read a pointer as an ArrayBuffer + * + * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. + */ +@module("bun:ffi") +external toArrayBuffer: pointer => ArrayBuffer.t = "toArrayBuffer" + +@module("bun:ffi") +external toArrayBufferWithOffset: (pointer, ~byteOffset: int) => ArrayBuffer.t = "toArrayBuffer" + +@module("bun:ffi") +external toArrayBufferWithOffsetAndLength: ( + pointer, + ~byteOffset: int, + ~byteLength: int, +) => ArrayBuffer.t = "toArrayBuffer" + +/** + * Platform-specific file extension name for dynamic libraries. + * + * "." is not included. + * + * @example "dylib" on macOS, "so" on Linux + */ +@module("bun:ffi") +external suffix: string = "suffix" + +/** + * Get a string from a UTF-8 encoded C string. + * If `byteLength` is not provided, the string is assumed to be null-terminated. + */ +module CString = { + type t + + @module("bun:ffi") @new + external make: pointer => t = "CString" + + @module("bun:ffi") @new + external makeWithOffset: (pointer, ~byteOffset: int) => t = "CString" + + @module("bun:ffi") @new + external makeWithOffsetAndLength: (pointer, ~byteOffset: int, ~byteLength: int) => t = "CString" + + /** The ptr to the C string */ + @get external ptr: t => pointer = "ptr" + + @get external byteOffset: t => option = "byteOffset" + @get external byteLength: t => option = "byteLength" + + /** Get the ptr as an ArrayBuffer */ + @get external arrayBuffer: t => ArrayBuffer.t = "arrayBuffer" + + @send external toString: t => string = "toString" +} + +/** + * Pass a JavaScript function to FFI (Foreign Function Interface) + */ +module JSCallback = { + type t + + /** + * Enable a JavaScript callback function to be passed to C with bun:ffi + * + * @param callback The JavaScript function to be called + * @param definition The C function definition + */ + @module("bun:ffi") @new + external make: (@uncurry ('a => 'b), ffiFunction) => t = "JSCallback" + + /** The pointer to the C function. Becomes null once `close` is called. */ + @get @return(nullable) + external ptr: t => option = "ptr" + + /** Can the callback be called from a different thread? */ + @get external threadsafe: t => bool = "threadsafe" + + /** Free the memory allocated for the callback */ + @send external close: t => unit = "close" +} + +/** + * Turn a native library's function pointer into a JavaScript function. + * + * Libraries using Node-API & bun:ffi in the same module could use this + * to skip an extra dlopen() step. + */ +module CFunction = { + type t + + type cfunctionArg = { + args?: array, + returns?: ffiTypeOrString, + ptr: pointer, + threadsafe?: bool, + } + + @module("bun:ffi") @new + external make: cfunctionArg => t = "CFunction" + + @send external close: t => unit = "close" +} + +/** + * Compile ISO C11 source code using TinyCC, and make symbols available as functions to JavaScript. + */ +module CC = { + type options<'symbols, 'source> = { + source: 'source, + symbols: 'symbols, + library?: array, + @as("include") include_?: array, + define?: Dict.t, + flags?: array, + } + + @module("bun:ffi") + external compile: options<'symbols, string> => library<'result> = "cc" + + @module("bun:ffi") + external compileFile: options<'symbols, Types.bunFile> => library<'result> = "cc" +} + +/** + * View the generated C code for FFI bindings. + * + * Useful for debugging FFI bindings. + */ +@module("bun:ffi") +external viewSource: Dict.t => array = "viewSource" + +@module("bun:ffi") +external viewSourceCallback: (ffiFunction, @as(json`true`) _) => string = "viewSource" + +/** + * Fast memory reading functions. + * + * These behave similarly to DataView, but are usually faster because + * they don't need to create a DataView or ArrayBuffer. + */ +module Read = { + @module("bun:ffi") @scope("read") + external u8: (pointer, ~byteOffset: int=?) => int = "u8" + + @module("bun:ffi") @scope("read") + external i8: (pointer, ~byteOffset: int=?) => int = "i8" + + @module("bun:ffi") @scope("read") + external u16: (pointer, ~byteOffset: int=?) => int = "u16" + + @module("bun:ffi") @scope("read") + external i16: (pointer, ~byteOffset: int=?) => int = "i16" + + @module("bun:ffi") @scope("read") + external u32: (pointer, ~byteOffset: int=?) => int = "u32" + + @module("bun:ffi") @scope("read") + external i32: (pointer, ~byteOffset: int=?) => int = "i32" + + @module("bun:ffi") @scope("read") + external f32: (pointer, ~byteOffset: int=?) => float = "f32" + + @module("bun:ffi") @scope("read") + external f64: (pointer, ~byteOffset: int=?) => float = "f64" + + @module("bun:ffi") @scope("read") + external u64: (pointer, ~byteOffset: int=?) => bigint = "u64" + + @module("bun:ffi") @scope("read") + external i64: (pointer, ~byteOffset: int=?) => bigint = "i64" + + @module("bun:ffi") @scope("read") + external ptr: (pointer, ~byteOffset: int=?) => int = "ptr" + + @module("bun:ffi") @scope("read") + external intptr: (pointer, ~byteOffset: int=?) => int = "intptr" +} diff --git a/test/FFITest.js b/test/FFITest.js new file mode 100644 index 0000000..75a3eeb --- /dev/null +++ b/test/FFITest.js @@ -0,0 +1,120 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Bunffi from "bun:ffi"; +import * as Buntest from "bun:test"; + +let libPath = import.meta.dir + "/ffi_testlib.so"; + +Buntest.describe("FFI", () => { + Buntest.test("suffix is a non-empty string", () => { + Buntest.expect(Bunffi.suffix).toBeString(); + Buntest.expect(Bunffi.suffix).toBeTruthy(); + }); + Buntest.test("dlopen and call add()", () => { + let lib = Bunffi.dlopen(libPath, { + add: { + args: [ + "i32", + "i32" + ], + returns: "i32" + } + }); + let result = lib.symbols.add(2, 3); + Buntest.expect(result).toBe(5); + lib.close(); + }); + Buntest.test("dlopen and call multiply()", () => { + let lib = Bunffi.dlopen(libPath, { + multiply: { + args: [ + "i32", + "i32" + ], + returns: "i32" + } + }); + let result = lib.symbols.multiply(7, 6); + Buntest.expect(result).toBe(42); + lib.close(); + }); + Buntest.test("dlopen and call add_doubles()", () => { + let lib = Bunffi.dlopen(libPath, { + add_doubles: { + args: [ + "f64", + "f64" + ], + returns: "f64" + } + }); + let result = lib.symbols.add_doubles(1.5, 2.5); + Buntest.expect(result).toBeCloseTo(4.0); + lib.close(); + }); + Buntest.test("dlopen and call hello() returning cstring", () => { + let lib = Bunffi.dlopen(libPath, { + hello: { + args: [], + returns: "cstring" + } + }); + let result = lib.symbols.hello(); + Buntest.expect(result.toString()).toBe("Hello from C!"); + lib.close(); + }); + Buntest.test("ptr and toBuffer roundtrip", () => { + let arr = new Uint8Array([ + 10, + 20, + 30 + ]); + let p = Bunffi.ptr(arr); + let buf = Bunffi.toBuffer(p, 0, 3); + Buntest.expect(buf[0]).toBe(10); + Buntest.expect(buf[1]).toBe(20); + Buntest.expect(buf[2]).toBe(30); + }); + Buntest.test("Read module reads memory correctly", () => { + let arr = new Uint8Array([ + 42, + 0, + 0, + 0 + ]); + let p = Bunffi.ptr(arr); + Buntest.expect(Bunffi.read.u8(p)).toBe(42); + Buntest.expect(Bunffi.read.u8(p, 1)).toBe(0); + }); + Buntest.test("dlopen and call negate()", () => { + let lib = Bunffi.dlopen(libPath, { + negate: { + args: ["i32"], + returns: "i32" + } + }); + let result = lib.symbols.negate(42); + Buntest.expect(result).toBe(-42); + lib.close(); + }); + Buntest.test("CC.compile compiles C source from file", () => { + let squarePath = import.meta.dir + "/ffi_square.c"; + let lib = Bunffi.cc({ + source: squarePath, + symbols: { + square: { + args: ["i32"], + returns: "i32" + } + } + }); + let result = lib.symbols.square(9); + Buntest.expect(result).toBe(81); + lib.close(); + }); +}); + +export { + libPath, +} +/* libPath Not a pure module */ diff --git a/test/FFITest.res b/test/FFITest.res new file mode 100644 index 0000000..3e22501 --- /dev/null +++ b/test/FFITest.res @@ -0,0 +1,126 @@ +open RescriptBun +open Test +open FFI + +let libPath = Globals.import.meta.dir ++ "/ffi_testlib.so" + +describe("FFI", () => { + test("suffix is a non-empty string", () => { + expect(suffix)->Expect.toBeString + expect(suffix)->Expect.toBeTruthy + }) + + test("dlopen and call add()", () => { + let lib = dlopen( + libPath, + { + "add": { + args: [I32Str, I32Str], + returns: I32Str, + }, + }, + ) + + let result = lib.symbols["add"](2, 3) + expect(result)->Expect.toBe(5) + lib->closeLibrary + }) + + test("dlopen and call multiply()", () => { + let lib = dlopen( + libPath, + { + "multiply": { + args: [I32Str, I32Str], + returns: I32Str, + }, + }, + ) + + let result = lib.symbols["multiply"](7, 6) + expect(result)->Expect.toBe(42) + lib->closeLibrary + }) + + test("dlopen and call add_doubles()", () => { + let lib = dlopen( + libPath, + { + "add_doubles": { + args: [F64Str, F64Str], + returns: F64Str, + }, + }, + ) + + let result = lib.symbols["add_doubles"](1.5, 2.5) + expect(result)->Expect.toBeCloseTo(4.0) + lib->closeLibrary + }) + + test("dlopen and call hello() returning cstring", () => { + let lib = dlopen( + libPath, + { + "hello": { + args: [], + returns: CstringStr, + }, + }, + ) + + // When returns is "cstring", Bun already returns a CString object + let result: CString.t = lib.symbols["hello"]() + expect(result->CString.toString)->Expect.toBe("Hello from C!") + lib->closeLibrary + }) + + test("ptr and toBuffer roundtrip", () => { + let arr = Uint8Array.fromArray([10, 20, 30]) + let p = ptrOfTypedArray(arr) + let buf = toBufferWithOffsetAndLength(p, ~byteOffset=0, ~byteLength=3) + expect(buf->Buffer.unsafeGet(0))->Expect.toBe(10) + expect(buf->Buffer.unsafeGet(1))->Expect.toBe(20) + expect(buf->Buffer.unsafeGet(2))->Expect.toBe(30) + }) + + test("Read module reads memory correctly", () => { + let arr = Uint8Array.fromArray([42, 0, 0, 0]) + let p = ptrOfTypedArray(arr) + expect(Read.u8(p))->Expect.toBe(42) + expect(Read.u8(p, ~byteOffset=1))->Expect.toBe(0) + }) + + test("dlopen and call negate()", () => { + let lib = dlopen( + libPath, + { + "negate": { + args: [I32Str], + returns: I32Str, + }, + }, + ) + + let result = lib.symbols["negate"](42) + expect(result)->Expect.toBe(-42) + lib->closeLibrary + }) + + test("CC.compile compiles C source from file", () => { + let squarePath = Globals.import.meta.dir ++ "/ffi_square.c" + let lib = CC.compile({ + source: squarePath, + symbols: { + "square": { + args: [I32Str], + returns: I32Str, + }, + }, + }) + + let result = lib.symbols["square"](9) + expect(result)->Expect.toBe(81) + lib->closeLibrary + }) +}) diff --git a/test/ffi_square.c b/test/ffi_square.c new file mode 100644 index 0000000..42e2436 --- /dev/null +++ b/test/ffi_square.c @@ -0,0 +1,3 @@ +int square(int x) { + return x * x; +} diff --git a/test/ffi_testlib.c b/test/ffi_testlib.c new file mode 100644 index 0000000..be40c7f --- /dev/null +++ b/test/ffi_testlib.c @@ -0,0 +1,19 @@ +int add(int a, int b) { + return a + b; +} + +int multiply(int a, int b) { + return a * b; +} + +double add_doubles(double a, double b) { + return a + b; +} + +const char* hello(void) { + return "Hello from C!"; +} + +int negate(int x) { + return -x; +} diff --git a/test/ffi_testlib.so b/test/ffi_testlib.so new file mode 100755 index 0000000..bc2f47b Binary files /dev/null and b/test/ffi_testlib.so differ