mirror of
https://codeberg.org/icewind/vmt-parser.git
synced 2026-06-03 20:14:06 +02:00
material parsing wip
This commit is contained in:
parent
5b10005022
commit
971b42452d
16 changed files with 869 additions and 764 deletions
596
Cargo.lock
generated
596
Cargo.lock
generated
|
|
@ -2,6 +2,21 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "addr2line"
|
||||||
|
version = "0.21.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
|
||||||
|
dependencies = [
|
||||||
|
"gimli",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.1.2"
|
version = "1.1.2"
|
||||||
|
|
@ -11,18 +26,171 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backtrace"
|
||||||
|
version = "0.3.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
|
||||||
|
dependencies = [
|
||||||
|
"addr2line",
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"miniz_oxide",
|
||||||
|
"object",
|
||||||
|
"rustc-demangle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backtrace-ext"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50"
|
||||||
|
dependencies = [
|
||||||
|
"backtrace",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "beef"
|
name = "beef"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1"
|
checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.83"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "console"
|
||||||
|
version = "0.15.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8"
|
||||||
|
dependencies = [
|
||||||
|
"encode_unicode",
|
||||||
|
"lazy_static",
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.45.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encode_unicode"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.3.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gimli"
|
||||||
|
version = "0.28.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "insta"
|
||||||
|
version = "1.34.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d64600be34b2fcfc267740a243fa7744441bb4947a619ac4e5bb6507f35fbfc"
|
||||||
|
dependencies = [
|
||||||
|
"console",
|
||||||
|
"lazy_static",
|
||||||
|
"linked-hash-map",
|
||||||
|
"ron",
|
||||||
|
"serde",
|
||||||
|
"similar",
|
||||||
|
"yaml-rust",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is-terminal"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"rustix",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is_ci"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.151"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linked-hash-map"
|
||||||
|
version = "0.5.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-raw-sys"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "logos"
|
name = "logos"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
|
|
@ -67,8 +235,17 @@ version = "5.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e"
|
checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"backtrace",
|
||||||
|
"backtrace-ext",
|
||||||
|
"is-terminal",
|
||||||
"miette-derive",
|
"miette-derive",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"owo-colors",
|
||||||
|
"supports-color",
|
||||||
|
"supports-hyperlinks",
|
||||||
|
"supports-unicode",
|
||||||
|
"terminal_size",
|
||||||
|
"textwrap",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
@ -84,12 +261,36 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "object"
|
||||||
|
version = "0.32.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.19.0"
|
version = "1.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "owo-colors"
|
||||||
|
version = "3.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parse-display"
|
name = "parse-display"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
|
|
@ -175,6 +376,68 @@ version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ron"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-demangle"
|
||||||
|
version = "0.1.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustix"
|
||||||
|
version = "0.38.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.4.1",
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.193"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.193"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "similar"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2aeaf503862c419d66959f5d7ca015337d864e9c49485d771b732e2a20453597"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smawk"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "structmeta"
|
name = "structmeta"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|
@ -198,6 +461,34 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "supports-color"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89"
|
||||||
|
dependencies = [
|
||||||
|
"is-terminal",
|
||||||
|
"is_ci",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "supports-hyperlinks"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f84231692eb0d4d41e4cdd0cabfdd2e6cd9e255e65f80c9aa7c98dd502b4233d"
|
||||||
|
dependencies = [
|
||||||
|
"is-terminal",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "supports-unicode"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b6c2cb240ab5dd21ed4906895ee23fe5a48acdbd15a3ce388e7b62a9b66baf7"
|
||||||
|
dependencies = [
|
||||||
|
"is-terminal",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.41"
|
version = "2.0.41"
|
||||||
|
|
@ -209,6 +500,60 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "terminal_size"
|
||||||
|
version = "0.1.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "test-case"
|
||||||
|
version = "3.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8"
|
||||||
|
dependencies = [
|
||||||
|
"test-case-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "test-case-core"
|
||||||
|
version = "3.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "test-case-macros"
|
||||||
|
version = "3.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"test-case-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "textwrap"
|
||||||
|
version = "0.15.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d"
|
||||||
|
dependencies = [
|
||||||
|
"smawk",
|
||||||
|
"unicode-linebreak",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.50"
|
version = "1.0.50"
|
||||||
|
|
@ -235,6 +580,12 @@ version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-linebreak"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.11"
|
version = "0.1.11"
|
||||||
|
|
@ -242,11 +593,254 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vmt-parser"
|
name = "vdf-reader"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"logos",
|
"logos",
|
||||||
"miette",
|
"miette",
|
||||||
"parse-display",
|
"parse-display",
|
||||||
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vmt-parser"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"insta",
|
||||||
|
"logos",
|
||||||
|
"miette",
|
||||||
|
"parse-display",
|
||||||
|
"test-case",
|
||||||
|
"thiserror",
|
||||||
|
"vdf-reader",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.45.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.42.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.42.2",
|
||||||
|
"windows_aarch64_msvc 0.42.2",
|
||||||
|
"windows_i686_gnu 0.42.2",
|
||||||
|
"windows_i686_msvc 0.42.2",
|
||||||
|
"windows_x86_64_gnu 0.42.2",
|
||||||
|
"windows_x86_64_gnullvm 0.42.2",
|
||||||
|
"windows_x86_64_msvc 0.42.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.48.5",
|
||||||
|
"windows_aarch64_msvc 0.48.5",
|
||||||
|
"windows_i686_gnu 0.48.5",
|
||||||
|
"windows_i686_msvc 0.48.5",
|
||||||
|
"windows_x86_64_gnu 0.48.5",
|
||||||
|
"windows_x86_64_gnullvm 0.48.5",
|
||||||
|
"windows_x86_64_msvc 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.52.0",
|
||||||
|
"windows_aarch64_msvc 0.52.0",
|
||||||
|
"windows_i686_gnu 0.52.0",
|
||||||
|
"windows_i686_msvc 0.52.0",
|
||||||
|
"windows_x86_64_gnu 0.52.0",
|
||||||
|
"windows_x86_64_gnullvm 0.52.0",
|
||||||
|
"windows_x86_64_msvc 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yaml-rust"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
|
||||||
|
dependencies = [
|
||||||
|
"linked-hash-map",
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -8,3 +8,9 @@ logos = "0.13.0"
|
||||||
thiserror = "1.0.50"
|
thiserror = "1.0.50"
|
||||||
miette = "5.10.0"
|
miette = "5.10.0"
|
||||||
parse-display = "0.8.2"
|
parse-display = "0.8.2"
|
||||||
|
vdf-reader = { version = "0.1", path = "../vdf-reader" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
test-case = "3.3.1"
|
||||||
|
insta = { version = "1.34.0", features = ["ron"] }
|
||||||
|
miette = { version = "5.10.0", features = ["fancy"] }
|
||||||
16
examples/parse.rs
Normal file
16
examples/parse.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
use miette::{Context, IntoDiagnostic, Result};
|
||||||
|
use std::env::args;
|
||||||
|
use std::fs::read_to_string;
|
||||||
|
use vdf_reader::Reader;
|
||||||
|
use vmt_parser::material::Material;
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let path = args().nth(1).expect("no path provided");
|
||||||
|
let raw = read_to_string(path)
|
||||||
|
.into_diagnostic()
|
||||||
|
.wrap_err("failed to read input")?;
|
||||||
|
let mut reader = Reader::from(raw.as_str());
|
||||||
|
let material = Material::parse(&mut reader).wrap_err("failed to parse material")?;
|
||||||
|
dbg!(material);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
66
src/error.rs
66
src/error.rs
|
|
@ -1,10 +1,68 @@
|
||||||
use crate::vdf::VdfError;
|
use miette::{Diagnostic, SourceSpan};
|
||||||
use miette::Diagnostic;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use vdf_reader::entry::Entry;
|
||||||
|
use vdf_reader::error::ParseEntryError;
|
||||||
|
use vdf_reader::VdfError;
|
||||||
|
|
||||||
#[derive(Debug, Error, Diagnostic)]
|
#[derive(Debug, Error, Diagnostic)]
|
||||||
pub enum Error {
|
pub enum VmtError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
#[diagnostic(transparent)]
|
#[diagnostic(transparent)]
|
||||||
Vdf(VdfError),
|
Vdf(#[from] VdfError),
|
||||||
|
#[error(transparent)]
|
||||||
|
#[diagnostic(transparent)]
|
||||||
|
Eof(#[from] EofError),
|
||||||
|
#[error(transparent)]
|
||||||
|
#[diagnostic(transparent)]
|
||||||
|
ParseValue(#[from] ParseValueError),
|
||||||
|
}
|
||||||
|
#[derive(Debug, Error, Diagnostic)]
|
||||||
|
#[error("Unexpected end of input while looking for {expected}")]
|
||||||
|
#[diagnostic(code(vmt_parser::eof))]
|
||||||
|
pub struct EofError {
|
||||||
|
expected: &'static str,
|
||||||
|
#[label("Expected {}", self.expected)]
|
||||||
|
err_span: SourceSpan,
|
||||||
|
#[source_code]
|
||||||
|
src: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EofError {
|
||||||
|
pub fn new(src: String, expected: &'static str) -> Self {
|
||||||
|
let span = src.len()..src.len();
|
||||||
|
EofError {
|
||||||
|
src,
|
||||||
|
err_span: span.into(),
|
||||||
|
expected,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Debug, Error, Diagnostic)]
|
||||||
|
#[error("Can't parse value {value:?} as {ty} to read {name}")]
|
||||||
|
#[diagnostic(code(vmt_parser::eof))]
|
||||||
|
pub struct ParseValueError {
|
||||||
|
name: &'static str,
|
||||||
|
ty: &'static str,
|
||||||
|
pub value: Entry,
|
||||||
|
#[label("Expected a {}", self.ty)]
|
||||||
|
err_span: SourceSpan,
|
||||||
|
#[source_code]
|
||||||
|
src: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ParseValueError {
|
||||||
|
pub fn new(
|
||||||
|
src: String,
|
||||||
|
name: &'static str,
|
||||||
|
err_span: SourceSpan,
|
||||||
|
parse_err: ParseEntryError,
|
||||||
|
) -> Self {
|
||||||
|
ParseValueError {
|
||||||
|
src,
|
||||||
|
err_span,
|
||||||
|
name,
|
||||||
|
ty: parse_err.ty,
|
||||||
|
value: parse_err.value,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
mod error;
|
mod error;
|
||||||
pub mod vdf;
|
pub mod material;
|
||||||
|
|
||||||
pub use error::Error;
|
pub use error::VmtError;
|
||||||
|
|
||||||
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
pub type Result<T, E = VmtError> = std::result::Result<T, E>;
|
||||||
|
|
|
||||||
176
src/material.rs
Normal file
176
src/material.rs
Normal file
|
|
@ -0,0 +1,176 @@
|
||||||
|
use crate::error::{EofError, ParseValueError};
|
||||||
|
use crate::Result;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use vdf_reader::entry::{Entry, FromEntry, Table};
|
||||||
|
use vdf_reader::{Event, GroupStartEvent, Reader, VdfError};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Material {
|
||||||
|
Other(OtherMaterial),
|
||||||
|
LightMappedGeneric(LightMappedGenericMaterial),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Material {
|
||||||
|
pub fn parse(reader: &mut Reader) -> Result<Self> {
|
||||||
|
let start: GroupStartEvent = expect_event(reader, "material name")?;
|
||||||
|
let name = start.name.to_ascii_lowercase();
|
||||||
|
|
||||||
|
Ok(match name.as_str() {
|
||||||
|
"lightmappedgeneric" => {
|
||||||
|
Material::LightMappedGeneric(LightMappedGenericMaterial::parse(reader)?)
|
||||||
|
}
|
||||||
|
_ => Material::Other(OtherMaterial::parse(name, reader)?),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct LightMappedGenericMaterial {
|
||||||
|
pub keywords: String,
|
||||||
|
pub detail: Option<String>,
|
||||||
|
pub detail_blend_factory: f32,
|
||||||
|
pub detail_scale: f32,
|
||||||
|
pub detail_blend_mode: u32,
|
||||||
|
pub base_texture: String,
|
||||||
|
pub ss_bump: bool,
|
||||||
|
pub bump_map: Option<String>,
|
||||||
|
pub rest: HashMap<String, Entry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LightMappedGenericMaterial {
|
||||||
|
fn parse(reader: &mut Reader) -> Result<Self> {
|
||||||
|
let src = reader.source;
|
||||||
|
let mut keywords = Default::default();
|
||||||
|
let mut detail = Default::default();
|
||||||
|
let mut detail_blend_factory = Default::default();
|
||||||
|
let mut detail_scale = Default::default();
|
||||||
|
let mut detail_blend_mode = Default::default();
|
||||||
|
let mut base_texture = Default::default();
|
||||||
|
let mut ss_bump = Default::default();
|
||||||
|
let mut bump_map = Default::default();
|
||||||
|
|
||||||
|
let mut rest: HashMap<String, Entry> = Default::default();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let (span, key, value) = match event(reader, "item or group end")? {
|
||||||
|
Event::GroupEnd(_) => break,
|
||||||
|
Event::GroupStart(start) => (
|
||||||
|
start.span,
|
||||||
|
start.name.to_ascii_lowercase(),
|
||||||
|
Entry::Table(Table::load(reader)?),
|
||||||
|
),
|
||||||
|
Event::Entry(entry) => (
|
||||||
|
entry.span,
|
||||||
|
entry.key.into_content().to_ascii_lowercase(),
|
||||||
|
entry.value.into(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
match key.as_str() {
|
||||||
|
"%keywords" => {
|
||||||
|
keywords = FromEntry::from_entry(value).map_err(|err| {
|
||||||
|
ParseValueError::new(src.into(), "keywords", span.into(), err)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
"$detail" => {
|
||||||
|
detail = FromEntry::from_entry(value).map_err(|err| {
|
||||||
|
ParseValueError::new(src.into(), "detail", span.into(), err)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
"$detailblendfactor" => {
|
||||||
|
detail_blend_factory = FromEntry::from_entry(value).map_err(|err| {
|
||||||
|
ParseValueError::new(src.into(), "detail_blend_factory", span.into(), err)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
"$detailscale" => {
|
||||||
|
detail_scale = FromEntry::from_entry(value).map_err(|err| {
|
||||||
|
ParseValueError::new(src.into(), "detail_scale", span.into(), err)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
"$detailblendmode" => {
|
||||||
|
detail_blend_mode = FromEntry::from_entry(value).map_err(|err| {
|
||||||
|
ParseValueError::new(src.into(), "detail_blend_mode", span.into(), err)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
"$basetexture" => {
|
||||||
|
base_texture = FromEntry::from_entry(value).map_err(|err| {
|
||||||
|
ParseValueError::new(src.into(), "base_texture", span.into(), err)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
"$ssbump" => {
|
||||||
|
ss_bump = FromEntry::from_entry(value).map_err(|err| {
|
||||||
|
ParseValueError::new(src.into(), "ss_bump", span.into(), err)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
"$bumpmap" => {
|
||||||
|
bump_map = FromEntry::from_entry(value).map_err(|err| {
|
||||||
|
ParseValueError::new(src.into(), "bump_map", span.into(), err)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
rest.insert(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(LightMappedGenericMaterial {
|
||||||
|
keywords,
|
||||||
|
detail,
|
||||||
|
detail_blend_factory,
|
||||||
|
detail_scale,
|
||||||
|
detail_blend_mode,
|
||||||
|
base_texture,
|
||||||
|
ss_bump,
|
||||||
|
bump_map,
|
||||||
|
rest,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct OtherMaterial {
|
||||||
|
pub name: String,
|
||||||
|
pub values: HashMap<String, Entry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OtherMaterial {
|
||||||
|
fn parse(name: String, reader: &mut Reader) -> Result<Self> {
|
||||||
|
let mut values: HashMap<String, _> = HashMap::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let (key, value) = match event(reader, "item or group end")? {
|
||||||
|
Event::GroupEnd(_) => break,
|
||||||
|
Event::GroupStart(start) => (
|
||||||
|
start.name.to_ascii_lowercase(),
|
||||||
|
Entry::Table(Table::load(reader)?),
|
||||||
|
),
|
||||||
|
Event::Entry(entry) => (
|
||||||
|
entry.key.into_content().to_ascii_lowercase(),
|
||||||
|
entry.value.into(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
values.insert(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(OtherMaterial { name, values })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn event<'a>(reader: &mut Reader<'a>, expected: &'static str) -> Result<Event<'a>> {
|
||||||
|
Ok(reader
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| EofError::new(reader.source.into(), expected))??)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expect_event<'a, E: 'a>(reader: &mut Reader<'a>, expected: &'static str) -> Result<E>
|
||||||
|
where
|
||||||
|
E: TryFrom<Event<'a>, Error = VdfError>,
|
||||||
|
{
|
||||||
|
let event = event(reader, expected)?;
|
||||||
|
E::try_from(event).map_err(|e| {
|
||||||
|
match e {
|
||||||
|
VdfError::WrongEntryType(e) => e.with_source(reader.source.into()).into(),
|
||||||
|
e => e,
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
use super::Entry;
|
|
||||||
|
|
||||||
/// An array of entries (items that have the same key).
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
||||||
pub struct Array(Vec<Entry>);
|
|
||||||
|
|
||||||
impl From<Entry> for Array {
|
|
||||||
fn from(value: Entry) -> Self {
|
|
||||||
Array(vec![value])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<Entry> for Array {
|
|
||||||
fn into(self) -> Entry {
|
|
||||||
Entry::Array(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for Array {
|
|
||||||
type Target = Vec<Entry>;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DerefMut for Array {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,164 +0,0 @@
|
||||||
use std::slice;
|
|
||||||
|
|
||||||
/// The kinds of entry.
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
||||||
pub enum Entry {
|
|
||||||
/// A table.
|
|
||||||
Table(Table),
|
|
||||||
|
|
||||||
/// An array (entries with the same key).
|
|
||||||
Array(Array),
|
|
||||||
|
|
||||||
/// A statement (the values starting with #).
|
|
||||||
Statement(Statement),
|
|
||||||
|
|
||||||
/// A value.
|
|
||||||
Value(Value),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Entry {
|
|
||||||
/// Lookup an entry with a path.
|
|
||||||
pub fn lookup<S: AsRef<str>>(&self, path: S) -> Option<&Entry> {
|
|
||||||
let mut current = self;
|
|
||||||
|
|
||||||
for name in path.as_ref().split('.') {
|
|
||||||
if let Some(entry) = current.get(name.trim()) {
|
|
||||||
current = entry;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(current)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Try to get the named entry.
|
|
||||||
pub fn get<S: AsRef<str>>(&self, name: S) -> Option<&Entry> {
|
|
||||||
match self {
|
|
||||||
&Entry::Table(ref value) =>
|
|
||||||
value.get(name.as_ref()),
|
|
||||||
|
|
||||||
&Entry::Array(ref value) =>
|
|
||||||
name.as_ref().parse::<usize>().ok().and_then(|i| value.get(i)),
|
|
||||||
|
|
||||||
_ =>
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Try to convert the entry to the given type.
|
|
||||||
pub fn to<T: Parse>(&self) -> Option<T> {
|
|
||||||
if let &Entry::Value(ref value) = self {
|
|
||||||
value.to::<T>()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Try to take the entry as a table.
|
|
||||||
pub fn as_table(&self) -> Option<&Table> {
|
|
||||||
if let &Entry::Table(ref value) = self {
|
|
||||||
Some(value)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Try to take the entry as a slice.
|
|
||||||
pub fn as_slice(&self) -> Option<&[Entry]> {
|
|
||||||
if let &Entry::Array(ref value) = self {
|
|
||||||
Some(value.as_slice())
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
unsafe {
|
|
||||||
Some(slice::from_raw_parts(self, 1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Try to take the entry as a statement.
|
|
||||||
pub fn as_statement(&self) -> Option<&Statement> {
|
|
||||||
if let &Entry::Statement(ref value) = self {
|
|
||||||
Some(value)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Try to take the entry as a value.
|
|
||||||
pub fn as_value(&self) -> Option<&Value> {
|
|
||||||
if let &Entry::Value(ref value) = self {
|
|
||||||
Some(value)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Try to take the entry as a string.
|
|
||||||
pub fn as_str(&self) -> Option<&str> {
|
|
||||||
match self {
|
|
||||||
&Entry::Value(ref value) =>
|
|
||||||
Some(&*value),
|
|
||||||
|
|
||||||
&Entry::Statement(ref value) =>
|
|
||||||
Some(&*value),
|
|
||||||
|
|
||||||
_ =>
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parsable types.
|
|
||||||
pub trait Parse: Sized {
|
|
||||||
/// Try to parse the string.
|
|
||||||
fn parse(string: &str) -> Option<Self>;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! from_str {
|
|
||||||
(for) => ();
|
|
||||||
|
|
||||||
(for $ty:ident $($rest:tt)*) => (
|
|
||||||
from_str!($ty);
|
|
||||||
from_str!(for $($rest)*);
|
|
||||||
);
|
|
||||||
|
|
||||||
($ty:ident) => (
|
|
||||||
impl Parse for $ty {
|
|
||||||
fn parse(string: &str) -> Option<Self> {
|
|
||||||
string.parse::<$ty>().ok()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
|
|
||||||
from_str!(for IpAddr Ipv4Addr Ipv6Addr SocketAddr SocketAddrV4 SocketAddrV6);
|
|
||||||
from_str!(for i8 i16 i32 i64 isize u8 u16 u32 u64 usize f32 f64);
|
|
||||||
|
|
||||||
impl Parse for bool {
|
|
||||||
fn parse(string: &str) -> Option<Self> {
|
|
||||||
match string {
|
|
||||||
"0" => Some(false),
|
|
||||||
"1" => Some(true),
|
|
||||||
v => v.parse::<bool>().ok()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod table;
|
|
||||||
pub use self::table::Table;
|
|
||||||
|
|
||||||
mod array;
|
|
||||||
pub use self::array::Array;
|
|
||||||
|
|
||||||
mod statement;
|
|
||||||
pub use self::statement::Statement;
|
|
||||||
|
|
||||||
mod value;
|
|
||||||
pub use self::value::Value;
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
use super::Entry;
|
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
/// A statement.
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
||||||
pub struct Statement(String);
|
|
||||||
|
|
||||||
impl From<Cow<'_, str>> for Statement {
|
|
||||||
fn from(value: Cow<'_, str>) -> Self {
|
|
||||||
Statement(value.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<Entry> for Statement {
|
|
||||||
fn into(self) -> Entry {
|
|
||||||
Entry::Statement(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for Statement {
|
|
||||||
type Target = str;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
use super::super::{Event, Item, Reader, Result};
|
|
||||||
use super::{Array, Entry, Statement, Value};
|
|
||||||
use crate::vdf::error::StatementInTableError;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
/// A table of entries.
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
||||||
pub struct Table(HashMap<String, Entry>);
|
|
||||||
|
|
||||||
fn insert(map: &mut HashMap<String, Entry>, key: String, value: Entry) {
|
|
||||||
if !map.contains_key(&key) {
|
|
||||||
map.insert(key, value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(&mut Entry::Array(ref mut array)) = map.get_mut(&key) {
|
|
||||||
array.push(value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut array = Array::from(map.remove(&key).unwrap());
|
|
||||||
array.push(value);
|
|
||||||
|
|
||||||
map.insert(key, array.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Table {
|
|
||||||
/// Load a table from the given `Reader`.
|
|
||||||
pub fn load(reader: &mut Reader) -> Result<Table> {
|
|
||||||
let mut map = HashMap::new();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
match reader.event()? {
|
|
||||||
Event::Entry {
|
|
||||||
key: Item::Statement { .. },
|
|
||||||
span,
|
|
||||||
..
|
|
||||||
} => return Err(StatementInTableError::new(span.into()).into()),
|
|
||||||
Event::Entry {
|
|
||||||
key: Item::Value { content: key, .. },
|
|
||||||
value: Item::Statement { content: value, .. },
|
|
||||||
..
|
|
||||||
} => insert(&mut map, key.into(), Statement::from(value).into()),
|
|
||||||
|
|
||||||
Event::Entry {
|
|
||||||
key: Item::Value { content: key, .. },
|
|
||||||
value: Item::Value { content: value, .. },
|
|
||||||
..
|
|
||||||
} => insert(&mut map, key.into(), Value::from(value).into()),
|
|
||||||
|
|
||||||
Event::GroupStart { name, .. } => {
|
|
||||||
insert(&mut map, name.into(), Table::load(reader)?.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
Event::GroupEnd { .. } | Event::End { .. } => break,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(Table(map));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<Entry> for Table {
|
|
||||||
fn into(self) -> Entry {
|
|
||||||
Entry::Table(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for Table {
|
|
||||||
type Target = HashMap<String, Entry>;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
use super::{Entry, Parse};
|
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
||||||
pub struct Value(String);
|
|
||||||
|
|
||||||
impl From<Cow<'_, str>> for Value {
|
|
||||||
fn from(value: Cow<'_, str>) -> Value {
|
|
||||||
Value(value.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<Entry> for Value {
|
|
||||||
fn into(self) -> Entry {
|
|
||||||
Entry::Value(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for Value {
|
|
||||||
type Target = str;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Value {
|
|
||||||
/// Try to convert the value to the given type.
|
|
||||||
pub fn to<T: Parse>(&self) -> Option<T> {
|
|
||||||
T::parse(&self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
122
src/vdf/error.rs
122
src/vdf/error.rs
|
|
@ -1,122 +0,0 @@
|
||||||
use crate::vdf::Token;
|
|
||||||
use miette::{Diagnostic, SourceSpan};
|
|
||||||
use std::error::Error;
|
|
||||||
use std::fmt::{Display, Formatter};
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
/// Any error that occurred while trying to parse the vdf file
|
|
||||||
#[derive(Error, Debug, Clone, Diagnostic)]
|
|
||||||
pub enum VdfError {
|
|
||||||
#[error(transparent)]
|
|
||||||
#[diagnostic(transparent)]
|
|
||||||
/// A token that wasn't expected was found while parsing
|
|
||||||
UnexpectedToken(#[from] UnexpectedTokenError),
|
|
||||||
#[error(transparent)]
|
|
||||||
#[diagnostic(transparent)]
|
|
||||||
/// No valid token found
|
|
||||||
NoValidToken(#[from] NoValidTokenError),
|
|
||||||
#[error(transparent)]
|
|
||||||
#[diagnostic(transparent)]
|
|
||||||
/// An unexpected statement was found inside a table
|
|
||||||
StatementInTable(#[from] StatementInTableError),
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ExpectedTokens<'a>(&'a [Token]);
|
|
||||||
|
|
||||||
impl Display for ExpectedTokens<'_> {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
let mut tokens = self.0.iter();
|
|
||||||
if let Some(token) = tokens.next() {
|
|
||||||
write!(f, "{}", token)?;
|
|
||||||
} else {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
for token in tokens {
|
|
||||||
write!(f, ", {}", token)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A token that wasn't expected was found while parsing
|
|
||||||
#[derive(Debug, Clone, Diagnostic)]
|
|
||||||
#[diagnostic(code(php_literal_parser::unexpected_token))]
|
|
||||||
pub struct UnexpectedTokenError {
|
|
||||||
#[label("Expected {}", ExpectedTokens(self.expected))]
|
|
||||||
err_span: SourceSpan,
|
|
||||||
pub expected: &'static [Token],
|
|
||||||
pub found: Option<Token>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UnexpectedTokenError {
|
|
||||||
pub fn new(expected: &'static [Token], found: Option<Token>, err_span: SourceSpan) -> Self {
|
|
||||||
UnexpectedTokenError {
|
|
||||||
err_span,
|
|
||||||
expected,
|
|
||||||
found,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for UnexpectedTokenError {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match &self.found {
|
|
||||||
Some(token) => write!(
|
|
||||||
f,
|
|
||||||
"Unexpected token, found {} expected one of {}",
|
|
||||||
token,
|
|
||||||
ExpectedTokens(self.expected)
|
|
||||||
),
|
|
||||||
None => write!(
|
|
||||||
f,
|
|
||||||
"Unexpected end of input expected one of {}",
|
|
||||||
ExpectedTokens(self.expected)
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error for UnexpectedTokenError {}
|
|
||||||
|
|
||||||
/// A token that wasn't expected was found while parsing
|
|
||||||
#[derive(Debug, Clone, Diagnostic)]
|
|
||||||
#[diagnostic(code(php_literal_parser::unexpected_token))]
|
|
||||||
pub struct NoValidTokenError {
|
|
||||||
#[label("Expected {}", ExpectedTokens(self.expected))]
|
|
||||||
err_span: SourceSpan,
|
|
||||||
pub expected: &'static [Token],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NoValidTokenError {
|
|
||||||
pub fn new(expected: &'static [Token], err_span: SourceSpan) -> Self {
|
|
||||||
NoValidTokenError { err_span, expected }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for NoValidTokenError {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"No valid token found, expected one of {}",
|
|
||||||
ExpectedTokens(self.expected)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error for NoValidTokenError {}
|
|
||||||
|
|
||||||
/// An unexpected statement was found inside a table
|
|
||||||
#[derive(Debug, Clone, Diagnostic, Error)]
|
|
||||||
#[diagnostic(code(php_literal_parser::unexpected_token))]
|
|
||||||
#[error("An unexpected statement was found inside a table")]
|
|
||||||
pub struct StatementInTableError {
|
|
||||||
#[label("Unexpected statement")]
|
|
||||||
err_span: SourceSpan,
|
|
||||||
}
|
|
||||||
impl StatementInTableError {
|
|
||||||
pub fn new(err_span: SourceSpan) -> Self {
|
|
||||||
StatementInTableError { err_span }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
pub mod entry;
|
|
||||||
mod error;
|
|
||||||
mod parser;
|
|
||||||
mod reader;
|
|
||||||
|
|
||||||
pub use error::VdfError;
|
|
||||||
|
|
||||||
pub type Result<T, E = VdfError> = std::result::Result<T, E>;
|
|
||||||
pub use parser::Token;
|
|
||||||
pub use reader::{Event, Item, Reader};
|
|
||||||
|
|
@ -1,102 +0,0 @@
|
||||||
use logos::Logos;
|
|
||||||
use parse_display::Display;
|
|
||||||
use std::str;
|
|
||||||
|
|
||||||
/// Parser token.
|
|
||||||
#[derive(PartialEq, Debug, Logos, Display, Clone)]
|
|
||||||
#[logos(skip r"[ \t\n\f]+")] // whitespace
|
|
||||||
#[logos(skip r"//[^\n]*")] // comments
|
|
||||||
pub enum Token {
|
|
||||||
/// A group is starting.
|
|
||||||
#[token("{")]
|
|
||||||
#[display("start of group")]
|
|
||||||
GroupStart,
|
|
||||||
/// A group is ending.
|
|
||||||
#[token("}")]
|
|
||||||
#[display("end of group")]
|
|
||||||
GroupEnd,
|
|
||||||
/// An enclosed or bare item.
|
|
||||||
#[regex("(\"([^\"\\\\]|\\\\.)*\")|([^# \t\n{}\"][^ \"\t\n]*)", priority = 0)]
|
|
||||||
#[display("item")]
|
|
||||||
Item,
|
|
||||||
/// An enclosed or bare statement.
|
|
||||||
#[regex("(\"#([^\"\\\\]|\\\\.)*\")|(#[^ \"\t\n]+)")]
|
|
||||||
#[display("statement")]
|
|
||||||
Statement,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::Token;
|
|
||||||
use logos::Logos;
|
|
||||||
|
|
||||||
fn get_token(input: &str) -> Option<Result<Token, <Token as Logos>::Error>> {
|
|
||||||
let mut lex = Token::lexer(input);
|
|
||||||
lex.next()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_tokens(input: &str) -> Result<Vec<(Token, &str)>, <Token as Logos>::Error> {
|
|
||||||
Token::lexer(input)
|
|
||||||
.spanned()
|
|
||||||
.map(|(res, span)| res.map(|token| (token, &input[span])))
|
|
||||||
// .map(|res| dbg!(res))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn next() {
|
|
||||||
assert_eq!(get_token("test"), Some(Ok(Token::Item)));
|
|
||||||
assert_eq!(get_token("\"test\""), Some(Ok(Token::Item)));
|
|
||||||
assert_eq!(get_token("\"\""), Some(Ok(Token::Item)));
|
|
||||||
assert_eq!(get_token("\"\" "), Some(Ok(Token::Item)));
|
|
||||||
assert_eq!(get_token("#test"), Some(Ok(Token::Statement)));
|
|
||||||
assert_eq!(get_token("\"#test\""), Some(Ok(Token::Statement)));
|
|
||||||
assert_eq!(get_token("{"), Some(Ok(Token::GroupStart)));
|
|
||||||
assert_eq!(get_token("}"), Some(Ok(Token::GroupEnd)));
|
|
||||||
assert_eq!(get_token("//test more"), None);
|
|
||||||
|
|
||||||
assert_eq!(get_token("test"), Some(Ok(Token::Item)));
|
|
||||||
assert_eq!(get_token("#test"), Some(Ok(Token::Statement)));
|
|
||||||
|
|
||||||
assert_eq!(get_token("lol wut"), Some(Ok(Token::Item)));
|
|
||||||
assert_eq!(get_token("#lol wut"), Some(Ok(Token::Statement)));
|
|
||||||
|
|
||||||
assert_eq!(get_token("lol{"), Some(Ok(Token::Item)));
|
|
||||||
assert_eq!(get_token("#lol{"), Some(Ok(Token::Statement)));
|
|
||||||
|
|
||||||
assert_eq!(get_token("lol}"), Some(Ok(Token::Item)));
|
|
||||||
assert_eq!(get_token("#lol}"), Some(Ok(Token::Statement)));
|
|
||||||
|
|
||||||
assert_eq!(get_token("\"test\""), Some(Ok(Token::Item)));
|
|
||||||
assert_eq!(get_token("\"#test\""), Some(Ok(Token::Statement)));
|
|
||||||
|
|
||||||
assert_eq!(get_token("\"te\\\"st\""), Some(Ok(Token::Item)));
|
|
||||||
assert_eq!(get_token("\"te\\st\""), Some(Ok(Token::Item)));
|
|
||||||
assert_eq!(get_token("\"#te\\\"st\""), Some(Ok(Token::Statement)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn tokenize() {
|
|
||||||
assert_eq!(
|
|
||||||
get_tokens(
|
|
||||||
r#"foo { // eol comment
|
|
||||||
"asd" "bar"
|
|
||||||
// a comment
|
|
||||||
#include other
|
|
||||||
empty ""
|
|
||||||
}"#
|
|
||||||
),
|
|
||||||
Ok(vec![
|
|
||||||
(Token::Item, "foo"),
|
|
||||||
(Token::GroupStart, "{"),
|
|
||||||
(Token::Item, r#""asd""#),
|
|
||||||
(Token::Item, r#""bar""#),
|
|
||||||
(Token::Statement, r#"#include"#),
|
|
||||||
(Token::Item, r#"other"#),
|
|
||||||
(Token::Item, r#"empty"#),
|
|
||||||
(Token::Item, r#""""#),
|
|
||||||
(Token::GroupEnd, "}")
|
|
||||||
])
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,190 +0,0 @@
|
||||||
use super::{Result, Token};
|
|
||||||
use crate::vdf::error::{NoValidTokenError, UnexpectedTokenError};
|
|
||||||
use logos::{Lexer, Span, SpannedIter};
|
|
||||||
use std::borrow::Cow;
|
|
||||||
|
|
||||||
/// Kinds of item.
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
||||||
pub enum Item<'a> {
|
|
||||||
/// A statement, the ones starting with #.
|
|
||||||
Statement { content: Cow<'a, str>, span: Span },
|
|
||||||
|
|
||||||
/// A value.
|
|
||||||
Value { content: Cow<'a, str>, span: Span },
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Item<'a> {
|
|
||||||
pub fn span(&self) -> Span {
|
|
||||||
match self {
|
|
||||||
Item::Statement { span, .. } => span.clone(),
|
|
||||||
Item::Value { span, .. } => span.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn into_content(self) -> Cow<'a, str> {
|
|
||||||
match self {
|
|
||||||
Item::Statement { content, .. } => content,
|
|
||||||
Item::Value { content, .. } => content,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reader event.
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
||||||
pub enum Event<'a> {
|
|
||||||
/// A group with the given name is starting.
|
|
||||||
GroupStart { name: Cow<'a, str>, span: Span },
|
|
||||||
|
|
||||||
/// A group has ended.
|
|
||||||
GroupEnd { span: Span },
|
|
||||||
|
|
||||||
/// An entry.
|
|
||||||
Entry {
|
|
||||||
key: Item<'a>,
|
|
||||||
value: Item<'a>,
|
|
||||||
span: Span,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// EOF has been reached.
|
|
||||||
End { span: Span },
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Event<'_> {
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn span(&self) -> Span {
|
|
||||||
match self {
|
|
||||||
Event::GroupStart { span, .. } => span.clone(),
|
|
||||||
Event::GroupEnd { span, .. } => span.clone(),
|
|
||||||
Event::Entry { span, .. } => span.clone(),
|
|
||||||
Event::End { span, .. } => span.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A VDF token reader.
|
|
||||||
pub struct Reader<'a> {
|
|
||||||
lexer: SpannedIter<'a, Token>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<&'a str> for Reader<'a> {
|
|
||||||
fn from(content: &'a str) -> Self {
|
|
||||||
Reader {
|
|
||||||
lexer: Lexer::new(content).spanned(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Reader<'a> {
|
|
||||||
/// Get the next event, this does copies.
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn event(&mut self) -> Result<Event> {
|
|
||||||
let key = match self.lexer.next() {
|
|
||||||
None => {
|
|
||||||
return Ok(Event::End {
|
|
||||||
span: self.lexer.span(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Some((Err(_), span)) => {
|
|
||||||
return Err(NoValidTokenError::new(
|
|
||||||
&[Token::Item, Token::GroupEnd, Token::Statement],
|
|
||||||
span.into(),
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
|
||||||
Some((Ok(Token::GroupEnd), span)) => return Ok(Event::GroupEnd { span }),
|
|
||||||
Some((Ok(Token::GroupStart), span)) => {
|
|
||||||
return Err(UnexpectedTokenError::new(
|
|
||||||
&[Token::Item, Token::GroupEnd, Token::Statement],
|
|
||||||
Some(Token::GroupStart),
|
|
||||||
span.into(),
|
|
||||||
)
|
|
||||||
.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
Some((Ok(Token::Item), span)) => Item::Value {
|
|
||||||
content: string(self.lexer.slice()),
|
|
||||||
span,
|
|
||||||
},
|
|
||||||
|
|
||||||
Some((Ok(Token::Statement), span)) => Item::Statement {
|
|
||||||
content: string(self.lexer.slice()),
|
|
||||||
span,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let value = match self.lexer.next() {
|
|
||||||
None => {
|
|
||||||
return Err(UnexpectedTokenError::new(
|
|
||||||
&[Token::Item, Token::GroupEnd, Token::Statement],
|
|
||||||
None,
|
|
||||||
self.lexer.span().into(),
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
Some((Err(_), span)) => {
|
|
||||||
return Err(NoValidTokenError::new(
|
|
||||||
&[Token::Item, Token::GroupEnd, Token::Statement],
|
|
||||||
span.into(),
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
Some((Ok(Token::GroupEnd), span)) => {
|
|
||||||
return Err(UnexpectedTokenError::new(
|
|
||||||
&[Token::Item, Token::GroupStart, Token::Statement],
|
|
||||||
Some(Token::GroupEnd),
|
|
||||||
span.into(),
|
|
||||||
)
|
|
||||||
.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
Some((Ok(Token::GroupStart), span)) => {
|
|
||||||
return Ok(Event::GroupStart {
|
|
||||||
name: key.into_content(),
|
|
||||||
span,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Some((Ok(Token::Item), span)) => Item::Value {
|
|
||||||
content: string(self.lexer.slice()),
|
|
||||||
span,
|
|
||||||
},
|
|
||||||
|
|
||||||
Some((Ok(Token::Statement), span)) => Item::Statement {
|
|
||||||
content: string(self.lexer.slice()),
|
|
||||||
span,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let span = key.span().start..value.span().end;
|
|
||||||
Ok(Event::Entry { key, value, span })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn string(source: &str) -> Cow<str> {
|
|
||||||
if source.contains('\\') {
|
|
||||||
let mut buffer = source.bytes();
|
|
||||||
let mut string = Vec::with_capacity(buffer.len());
|
|
||||||
|
|
||||||
while let Some(byte) = buffer.next() {
|
|
||||||
if byte == b'\\' {
|
|
||||||
match buffer.next() {
|
|
||||||
Some(b'\\') => string.push(b'\\'),
|
|
||||||
Some(b'n') => string.push(b'\n'),
|
|
||||||
Some(b't') => string.push(b'\t'),
|
|
||||||
Some(b'r') => string.push(b'\r'),
|
|
||||||
Some(b'"') => string.push(b'"'),
|
|
||||||
Some(byte) => string.extend_from_slice(&[b'\\', byte]),
|
|
||||||
None => break,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
string.push(byte);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String::from_utf8(string).unwrap().into()
|
|
||||||
} else {
|
|
||||||
source.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
11
tests/data/concretefloor003.vmt
Normal file
11
tests/data/concretefloor003.vmt
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
"LightmappedGeneric"
|
||||||
|
{
|
||||||
|
"$baseTexture" "cp_mountainlab/concrete/concretefloor003"
|
||||||
|
"$bumpmap" "concrete/concretefloor007b_height-ssbump"
|
||||||
|
"$ssbump" "1"
|
||||||
|
"%keywords" "tf"
|
||||||
|
"$detail" "overlays/detail001"
|
||||||
|
"$detailscale" "1.9"
|
||||||
|
"$detailblendmode" "0"
|
||||||
|
"$detailblendfactor" "1"
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue