master
skybldev 1 year ago
commit 99e8abef6a

1
.gitignore vendored

@ -0,0 +1 @@
/target

753
Cargo.lock generated

@ -0,0 +1,753 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "ahash"
version = "0.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd"
dependencies = [
"getrandom",
"once_cell",
"version_check",
]
[[package]]
name = "arrayvec"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitvec"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
]
[[package]]
name = "borsh"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f58b559fd6448c6e2fd0adb5720cd98a2506594cafa4737ff98c396f3e82f667"
dependencies = [
"borsh-derive",
"cfg_aliases",
]
[[package]]
name = "borsh-derive"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7aadb5b6ccbd078890f6d7003694e33816e6b784358f18e15e7e6d9f065a57cd"
dependencies = [
"once_cell",
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.48",
"syn_derive",
]
[[package]]
name = "bytecheck"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627"
dependencies = [
"bytecheck_derive",
"ptr_meta",
"simdutf8",
]
[[package]]
name = "bytecheck_derive"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "bytes"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cfg_aliases"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]]
name = "codespan"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3362992a0d9f1dd7c3d0e89e0ab2bb540b7a95fea8cd798090e758fda2899b5e"
dependencies = [
"codespan-reporting",
]
[[package]]
name = "codespan-reporting"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
dependencies = [
"termcolor",
"unicode-width",
]
[[package]]
name = "diff"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "either"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "funty"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]]
name = "g-code"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6261d157241cc6ec7e015a19f2b8ea37e2018a32980a60d65bda6c7b336349fc"
dependencies = [
"codespan",
"codespan-reporting",
"paste",
"peg",
"rust_decimal",
]
[[package]]
name = "getrandom"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
"ahash",
]
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "indexmap"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
dependencies = [
"equivalent",
"hashbrown 0.14.3",
]
[[package]]
name = "itoa"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "libc"
version = "0.2.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
[[package]]
name = "memchr"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "num-traits"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "osu-file-parser"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8bf208710e445c5780b93cf14025de927e8b3e262cd2bd84e3f23a67c830359"
dependencies = [
"either",
"nom",
"pretty_assertions",
"rust_decimal",
"rust_decimal_macros",
"strum",
"strum_macros",
"thiserror",
]
[[package]]
name = "osubot"
version = "0.1.0"
dependencies = [
"g-code",
"osu-file-parser",
"rust_decimal",
]
[[package]]
name = "paste"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "peg"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "400bcab7d219c38abf8bd7cc2054eb9bbbd4312d66f6a5557d572a203f646f61"
dependencies = [
"peg-macros",
"peg-runtime",
]
[[package]]
name = "peg-macros"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46e61cce859b76d19090f62da50a9fe92bab7c2a5f09e183763559a2ac392c90"
dependencies = [
"peg-runtime",
"proc-macro2",
"quote",
]
[[package]]
name = "peg-runtime"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36bae92c60fa2398ce4678b98b2c4b5a7c61099961ca1fa305aec04a9ad28922"
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "pretty_assertions"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66"
dependencies = [
"diff",
"yansi",
]
[[package]]
name = "proc-macro-crate"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284"
dependencies = [
"toml_edit",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
[[package]]
name = "ptr_meta"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
dependencies = [
"ptr_meta_derive",
]
[[package]]
name = "ptr_meta_derive"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "quote"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
[[package]]
name = "radium"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "rend"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd"
dependencies = [
"bytecheck",
]
[[package]]
name = "rkyv"
version = "0.7.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "527a97cdfef66f65998b5f3b637c26f5a5ec09cc52a3f9932313ac645f4190f5"
dependencies = [
"bitvec",
"bytecheck",
"bytes",
"hashbrown 0.12.3",
"ptr_meta",
"rend",
"rkyv_derive",
"seahash",
"tinyvec",
"uuid",
]
[[package]]
name = "rkyv_derive"
version = "0.7.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5c462a1328c8e67e4d6dbad1eb0355dd43e8ab432c6e227a43657f16ade5033"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "rust_decimal"
version = "1.33.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06676aec5ccb8fc1da723cc8c0f9a46549f21ebb8753d3915c6c41db1e7f1dc4"
dependencies = [
"arrayvec",
"borsh",
"bytes",
"num-traits",
"rand",
"rkyv",
"serde",
"serde_json",
]
[[package]]
name = "rust_decimal_macros"
version = "1.33.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e43721f4ef7060ebc2c3ede757733209564ca8207f47674181bcd425dd76945"
dependencies = [
"quote",
"rust_decimal",
]
[[package]]
name = "rustversion"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
[[package]]
name = "ryu"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
[[package]]
name = "seahash"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "serde"
version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
name = "serde_json"
version = "1.0.111"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "simdutf8"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a"
[[package]]
name = "strum"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
[[package]]
name = "strum_macros"
version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn 1.0.109",
]
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn_derive"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b"
dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
name = "thiserror"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "toml_datetime"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
[[package]]
name = "toml_edit"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03"
dependencies = [
"indexmap",
"toml_datetime",
"winnow",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-width"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]]
name = "uuid"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "winnow"
version = "0.5.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16"
dependencies = [
"memchr",
]
[[package]]
name = "wyz"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
dependencies = [
"tap",
]
[[package]]
name = "yansi"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"

@ -0,0 +1,12 @@
[package]
name = "osubot"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
osu-file-parser = "1.1.0"
g-code = "0.3.6"
#matrix = "0.22.0"
rust_decimal = { version = "1.33.1", features = ["maths"] }

@ -0,0 +1,73 @@
osu file format v14
[General]
AudioLeadIn: 0
PreviewTime: -1
Countdown: 1
SampleSet: Normal
StackLeniency: 0.7
Mode: 0
LetterboxInBreaks: 0
WidescreenStoryboard: 1
SamplesMatchPlaybackRate: 1
[Editor]
DistanceSpacing: 1
BeatDivisor: 4
GridSize: 32
TimelineZoom: 1
[Metadata]
Title: test
TitleUnicode: test
Artist: me
ArtistUnicode: me
Creator: Skybbles
Version: goddamnit i've rusted
Source: Source? I made it the hell up!
Tags: tag
[Difficulty]
HPDrainRate: 5
CircleSize: 5
OverallDifficulty: 5
ApproachRate: 4.4
SliderMultiplier: 1
SliderTickRate: 1
[Events]
0,0,"wildfire.png",0,0
[TimingPoints]
-13,545.4545454545455,4,1,0,100,1,0
[HitObjects]
156,120,259,5,0,1:0:0:0:
328,152,532,1,0,1:0:0:0:
204,204,805,1,0,1:0:0:0:
204,204,1350,1,0,1:0:0:0:
204,204,1487,1,0,1:0:0:0:
204,204,1623,1,0,1:0:0:0:
204,204,1759,1,0,1:0:0:0:
204,204,1896,1,0,1:0:0:0:
416,288,2168,1,0,1:0:0:0:
320,288,2441,1,0,1:0:0:0:
223,288,2714,1,0,1:0:0:0:
127,288,2987,1,0,1:0:0:0:
31,31,4350,5,0,1:0:0:0:
448,63,4487,1,0,1:0:0:0:
127,192,4623,1,0,1:0:0:0:
288,63,4759,1,0,1:0:0:0:
255,256,4896,1,0,1:0:0:0:
255,160,5032,1,0,1:0:0:0:
127,127,5168,1,0,1:0:0:0:
416,288,5305,1,0,1:0:0:0:
63,288,5441,1,0,1:0:0:0:
191,192,5577,1,0,1:0:0:0:
384,160,5714,1,0,1:0:0:0:
255,224,5850,1,0,1:0:0:0:
95,95,5987,1,0,1:0:0:0:
288,352,6123,1,0,1:0:0:0:
159,192,6259,1,0,1:0:0:0:
384,127,6396,1,0,1:0:0:0:
255,95,6532,1,0,1:0:0:0:

@ -0,0 +1,332 @@
use osu_file_parser::{
osu_file::{
hitobjects::{
CurveType::*,
HitObjectParams::*
}
},
OsuFile
};
use rust_decimal::{Decimal, prelude::ToPrimitive};
mod types;
use types::*;
/*
The input file.
*/
const OSU: &str = include_str!("../osu/test2/test2.osu");
/*
Machine's maximum acceleration in mm/s².
*/
const MAX_ACCEL: f64 = 110_000.0;
/*
The default acceleration to use for max_v calculation.
*/
const DEFAULT_ACCEL: f64 = MAX_ACCEL / 2.0;
/*
The acceleration to use for groups of hitobjects. This should be higher as
groups of hitobjects usually have to be traveled with "linear" velocity
across all the hitobjects.
*/
const GROUP_ACCEL: f64 = MAX_ACCEL;
/*
How much to increase the acceleration if the current acceleration doesn't
produce a result.
*/
const ACCEL_RETRY_STEP: f64 = 5_000.0;
/*
Since hitobjects' times are rounded to the nearest millisecond, linear
velocity calculations aren't very precise, leading to hitobjects with linear
velocities perceived to be identical not counted for grouping. To compensate
for this, a threshold is set, and any difference between linear velocities
under this threshold are counted.
*/
const GROUP_VEL_LENIENCY: f64 = 0.2;
/*
Size of the bounding box for the beatmap in storage. Do not change.
*/
const BOUNDING_BOX_SIZE: (f64, f64) = (512.0, 384.0); // lazer default ig
/*
Physical limits of the machine
*/
const PHYSICAL_MAX: (f64, f64) = (105.0, 110.0);
/*
Active area
*/
const AREA_ORIGIN: (f64, f64) = (10.0, 10.0);
const AREA_MAX: (f64, f64) = (95.0, 95.0);
/*
Rotation in degrees anteclockwise
*/
const ROTATION: f64 = 90.0;
const AREA_SIZE: (f64, f64) = (
AREA_MAX.0 - AREA_ORIGIN.0,
AREA_MAX.1 - AREA_ORIGIN.1
);
const BOX_TO_AREA_OFFSET: (f64, f64) = (
AREA_SIZE.0 / 2.0 - BOUNDING_BOX_SIZE.0 / 2.0,
AREA_SIZE.1 / 2.0 - BOUNDING_BOX_SIZE.1 / 2.0
);
/*
Calculates the maximum velocity (mm/ms) given the the start and end
position, acceleration, and required total move time.
This uses an equation from 19aksh https://math.stackexchange.com/a/3304761
rearranged to solve for v.
In loose mathematical format:
2t - sqrt(4t² - 8d (1 / a - 1 / -a))
v = -----------------------------------
2 (1 / a - 1 / -a)
Where:
t = time (ms)
d = distance (mm)
a = kinematic acceleration (mm/1000² since 1s == 1000ms)
v = velocity (mm/ms)
(multiply v by 60_000 to get the feedrate (mm/min))
There are some combinations of t, d, and a that can result in no solution,
usually because the acceleration and deceleration periods overlap. In this
case, the acceleration should be increased until a solution is found. To
compensate for the possibility of this exceeding the MAX_ACCEL, this will
normally calculate with half of MAX_ACCEL. If no solution is found even
at MAX_ACCEL, an error will be thrown.
*/
fn max_velocity(
p1: PositionF64,
p2: PositionF64,
accel: f64,
ms: f64,
) -> f64 {
let dist = p1 >> p2;
let accel_divided = accel / 1_000_000.0; // accel / 1000² since 1s == 1000ms
let accel_factor = 1.0 / accel_divided - 1.0 / -accel_divided;
let sqrt_fac = (4.0 * ms.powf(2.0) - 8.0 * dist * accel_factor).sqrt();
(2.0 * ms - sqrt_fac) / (2.0 * accel_factor)
}
fn find_bbox_scale_factor(
box_size: (f64, f64),
target_size: (f64, f64),
rotation: f64
) -> f64 {
let target_size = if rotation == 90.0 || rotation == 270.0 {
(target_size.1, target_size.0)
} else {
target_size
};
if target_size.0 > target_size.1 {
target_size.1 / box_size.1
} else {
target_size.0 / box_size.0
}
}
fn solve_feedrate_and_accel(
p1: PositionF64,
p2: PositionF64,
starting_accel: f64,
ms: f64
) -> (f64, f64) {
let mut accel = starting_accel;
let mut max_v: f64;
loop {
max_v = max_velocity(p1, p2, accel, ms);
if !max_v.is_nan() { break }
accel += ACCEL_RETRY_STEP;
if accel >= MAX_ACCEL {
panic!("couldn't calculate max_v for dist {} within {}ms", p1 >> p2, ms);
}
}
let speed = max_v * 1_000.0; // mm/s
let feedrate = speed * 60.0; // mm/min
eprintln!(
"; feedrate: {:.2} ({:.2}mm/s) ({})->({}) dist {}, accel={}, Δms={}",
feedrate, speed,
p1, p2,
p1 >> p2,
accel,
ms
);
(feedrate, accel)
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
/* Steps
1. Read beatmap and hitcircles
a. convert curves to lines
b. apply scaling for every point
c. apply rotation for every point
2. Convert to gcode paths
a. add preliminary gcode
b. calculate F for a given movement
c. write movements to file
*/
let src = OSU.parse::<OsuFile>()?;
let binding = src.hitobjects.expect("Beatmap has no hit objects!");
let mut hitobjects = binding.0.iter();
let scale_fac = find_bbox_scale_factor(
BOUNDING_BOX_SIZE,
AREA_SIZE,
ROTATION
);
println!("G90\nG0 Z0");
let corners = [
AREA_ORIGIN,
(AREA_ORIGIN.0, AREA_MAX.1),
(AREA_MAX.0, AREA_MAX.1),
(AREA_MAX.0, AREA_ORIGIN.1)
];
for corner in corners {
println!("G0 X{} Y{} F7500", corner.0, corner.1);
}
let mut total_time: f64 = 0.0;
let mut p1 = PositionF64::new(0.0, 0.0);
let mut p1_ms: Decimal = 0.into();
let mut last_accel: f64 = 0.0;
/*
These are used for merging notes that share the same angle and linear
velocity into one move. Linear velocity is plainly (dist / ms_delta).
move_p1 is the starting point of a g-code move.
*/
let mut move_p1: PositionF64 = p1;
let mut move_p1_ms: Decimal = 0.into();
let mut group_linear_vel = 0.0;
let mut group_slope = 0.0;
let mut group_size = 0;
let mut dwell_state = false;
for (count, obj) in hitobjects.enumerate() {
let p2_ms = obj.time.get().clone().unwrap_left();
let p1_to_p2_ms = p2_ms
.checked_sub(p1_ms)
.unwrap()
.to_f64()
.unwrap();
let p2 = PositionF64
::from_position(obj.position.clone())
.unwrap()
.convert_to_machine_space(
scale_fac,
BOUNDING_BOX_SIZE,
AREA_ORIGIN,
AREA_SIZE,
ROTATION
);
eprintln!("point {}", count);
if count == 0 {
println!("PAUSE");
} else if p1 == p2 && !dwell_state {
dwell_state = true;
} else if p1 != p2 {
let move_p1_to_p1_ms = p1_ms
.checked_sub(move_p1_ms)
.unwrap()
.to_f64()
.unwrap();
let linear_vel = (p1 >> p2) / p1_to_p2_ms;
let slope = p1 / p2;
println!("; linear_vel {:.4}, slope {:.4}", linear_vel, slope);
if
linear_vel - group_linear_vel < GROUP_VEL_LENIENCY
&& slope == group_slope
{
println!("; !! merging point");
group_size += 1;
} else {
let (feedrate, accel) = solve_feedrate_and_accel(
move_p1,
p1,
if group_size > 0 {
GROUP_ACCEL
} else {
DEFAULT_ACCEL
},
move_p1_to_p1_ms
);
if accel != last_accel {
println!("M204 S{}", accel);
}
println!("G0 F{:.4}\nG0 X{} Y{}", feedrate, p1.x, p1.y);
last_accel = accel;
group_linear_vel = linear_vel;
group_slope = slope;
group_size = 0;
}
if dwell_state {
println!("G4 P{}", move_p1_to_p1_ms);
dwell_state = false;
}
move_p1_ms = p1_ms;
move_p1 = p1;
}
p1 = p2;
p1_ms = p2_ms;
total_time += p1_to_p2_ms;
}
eprintln!("total time should be {}ms", total_time);
Ok(())
}
/*
println!(
"x={} y={} Δms={} type={}",
obj.position.x,
obj.position.y let move_p1_to_p1_ms = p1_ms
.checked_sub(move_p1_ms)
.unwrap()
.to_f64()
.unwrap();,
delta_ms,
match obj.obj_params {
HitCircle => String::from("HitCircle"),
Slider(s) => format!(
"Slider type={} points={} slides={} length={}",
match s.curve_type {
Bezier => "Bezier",
Centripetal => "Centripetal",
Linear => "Linear",
PerfectCircle => "PerfectCircle",
_ => "Other"
},
s.curve_points.len(),
s.slides,
s.length.get().clone()
),
Spinner => String::from("Spinner"),
_ => String::from("Other")
}
);
*/

@ -0,0 +1,129 @@
use osu_file_parser::Position;
use rust_decimal::{Decimal, prelude::ToPrimitive};
pub type DecimalTuple = (Decimal, Decimal);
#[derive(Copy, Clone, PartialEq)]
pub struct PositionF64 {
pub x: f64,
pub y: f64
}
pub enum Axis {
X,
Y
}
impl PositionF64 {
pub fn new(x: f64, y: f64) -> Self { Self { x, y } }
pub fn from_tuple(a: (f64, f64)) -> Self {
Self { x: a.0, y: a.1 }
}
pub fn from_position(a: Position) -> Option<Self> {
Some(Self {
x: a.x.get().clone().left()?.to_f64()?,
y: a.y.get().clone().left()?.to_f64()?
})
}
pub fn scale(mut self, fac: f64) -> Self {
self.x *= fac;
self.y *= fac;
self
}
pub fn offset(mut self, x: f64, y: f64) -> Self {
self.x += x;
self.y += y;
self
}
pub fn rotate(mut self, angle_deg: f64) -> Self {
let theta = angle_deg * std::f64::consts::PI / 180.0;
let sin_theta = theta.sin();
let cos_theta = theta.cos();
let x = self.x * cos_theta - self.y * sin_theta;
let y = self.x * sin_theta + self.y * cos_theta;
self.x = x;
self.y = y;
self
}
pub fn flip(mut self, axis: Axis, bisect: f64) -> Self {
match axis {
Axis::Y => self.x = self.x - (self.x - bisect) * 2.0,
Axis::X => self.y = self.y - (self.y - bisect) * 2.0,
}
self
}
pub fn convert_to_machine_space(
mut self,
scale_fac: f64,
bbox_size: (f64, f64),
area_origin: (f64, f64),
area_size: (f64, f64),
rotation: f64
) -> Self {
self.flip(Axis::X, bbox_size.1 / 2.0)
.scale(scale_fac)
.rotate(rotation)
.offset(
area_origin.0 + area_size.0,
area_origin.1 + area_size.1 / 2.0 - bbox_size.0 * scale_fac / 2.0
)
}
pub fn to_string(&self) -> String {
format!("{:.4}, {:.4}", self.x, self.y)
}
}
impl std::fmt::Display for PositionF64 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.to_string());
Ok(())
}
}
// Add/offset
impl std::ops::Add for PositionF64 {
type Output = Self;
fn add(self, other: Self) -> Self::Output {
Self {
x: self.x + other.x,
y: self.y + other.y
}
}
}
// Subtract/difference
impl std::ops::Sub for PositionF64 {
type Output = Self;
fn sub(self, other: Self) -> Self::Output {
Self {
x: self.x - other.x,
y: self.y - other.y
}
}
}
// Distance
impl std::ops::Shr for PositionF64 {
type Output = f64;
fn shr(self, other: Self) -> Self::Output {
let dist = other - self;
(dist.x.powi(2) + dist.y.powi(2)).sqrt().abs()
}
}
// Slope
impl std::ops::Div for PositionF64 {
type Output = f64;
fn div(self, rhs: Self) -> Self::Output {
let diff = rhs - self;
diff.y / diff.x
}
}

@ -0,0 +1,78 @@
G90
G0 Z0
G0 X10 Y10 F7500
G0 X10 Y95 F7500
G0 X95 Y95 F7500
G0 X95 Y10 F7500
PAUSE
; linear_vel 0.1064, slope 5.3750
M204 S55000
G0 F14734.6525
G0 X51.171875 Y35.8984375
; linear_vel 0.0818, slope -2.3846
G0 F6429.3272
G0 X56.484375 Y64.453125
; linear_vel 0.1392, slope 2.5238
G0 F982.1545
G0 X65.1171875 Y43.8671875
G4 P1364
; linear_vel 0.0584, slope -inf
G0 F8430.0676
G0 X79.0625 Y79.0625
; linear_vel 0.0590, slope -inf
; !! merging point
; linear_vel 0.0584, slope -inf
; !! merging point
; linear_vel 0.0334, slope 0.3735
M204 S110000
G0 F3509.5833
G0 X79.0625 Y31.083984375
; linear_vel 0.5068, slope 13.0312
M204 S55000
G0 F2005.8322
G0 X36.396484375 Y15.146484375000004
; linear_vel 0.4223, slope -2.4884
G0 F32785.7872
G0 X41.70898437500001 Y84.375
; linear_vel 0.2518, slope -1.2481
G0 F26957.4090
G0 X63.125 Y31.083984375000004
; linear_vel 0.2373, slope -0.1710
G0 F15656.4508
G0 X41.708984375 Y57.8125
; linear_vel 0.1172, slope -0.0000
G0 F14715.1658
G0 X73.75 Y52.333984375
; linear_vel 0.1614, slope 3.8788
G0 F7145.0001
G0 X57.8125 Y52.333984375
; linear_vel 0.4009, slope 1.7950
G0 F9899.9328
G0 X52.333984375 Y31.083984375000004
; linear_vel 0.4309, slope -inf
G0 F25490.3308
G0 X79.0625 Y79.0625
; linear_vel 0.1953, slope -1.3333
G0 F27545.0689
G0 X79.0625 Y20.458984375
; linear_vel 0.2371, slope -6.0313
G0 F12041.8473
G0 X63.125 Y41.708984375
; linear_vel 0.1758, slope -2.0156
G0 F14702.2521
G0 X57.81250000000001 Y73.75
; linear_vel 0.2491, slope 1.2403
G0 F10807.3775
G0 X68.4375 Y52.333984375
; linear_vel 0.3923, slope 0.7510
G0 F15472.8573
G0 X47.021484375 Y25.771484375000004
; linear_vel 0.2509, slope 0.8063
G0 F24924.2159
G0 X89.6875 Y57.8125
; linear_vel 0.2838, slope -3.4615
G0 F15595.0898
G0 X63.125 Y36.396484375
; linear_vel 0.1622, slope 4.0312
G0 F17722.9324
G0 X52.33398437500001 Y73.75
Loading…
Cancel
Save