mirror of
https://github.com/lune-org/lune.git
synced 2024-12-12 04:50:36 +00:00
Split lune into proper crates (#188)
This commit is contained in:
parent
3f53fc983c
commit
de71558c5d
185 changed files with 4005 additions and 1897 deletions
4
.github/workflows/ci.yaml
vendored
4
.github/workflows/ci.yaml
vendored
|
@ -24,7 +24,7 @@ jobs:
|
|||
components: rustfmt
|
||||
|
||||
- name: Install Just
|
||||
uses: extractions/setup-just@v1
|
||||
uses: extractions/setup-just@v2
|
||||
|
||||
- name: Install Tooling
|
||||
uses: ok-nick/setup-aftman@v0.4.2
|
||||
|
@ -41,7 +41,7 @@ jobs:
|
|||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Just
|
||||
uses: extractions/setup-just@v1
|
||||
uses: extractions/setup-just@v2
|
||||
|
||||
- name: Install Tooling
|
||||
uses: ok-nick/setup-aftman@v0.4.2
|
||||
|
|
24
.github/workflows/publish.yaml
vendored
24
.github/workflows/publish.yaml
vendored
|
@ -1,24 +0,0 @@
|
|||
name: Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Publish to crates.io
|
||||
uses: katyo/publish-crates@v2
|
||||
with:
|
||||
registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||
ignore-unpublished-changes: true
|
56
.github/workflows/release.yaml
vendored
56
.github/workflows/release.yaml
vendored
|
@ -21,14 +21,32 @@ jobs:
|
|||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get version from manifest
|
||||
uses: SebRollen/toml-action@9062fbef52816d61278d24ce53c8070440e1e8dd
|
||||
uses: SebRollen/toml-action@v1.2.0
|
||||
id: get_version
|
||||
with:
|
||||
file: Cargo.toml
|
||||
field: package.version
|
||||
|
||||
build:
|
||||
dry-run:
|
||||
name: Dry-run
|
||||
needs: ["init"]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Publish (dry-run)
|
||||
uses: katyo/publish-crates@v2
|
||||
with:
|
||||
dry-run: true
|
||||
check-repo: true
|
||||
registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||
|
||||
build:
|
||||
needs: ["init", "dry-run"]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
@ -70,7 +88,7 @@ jobs:
|
|||
targets: ${{ matrix.cargo-target }}
|
||||
|
||||
- name: Install Just
|
||||
uses: extractions/setup-just@v1
|
||||
uses: extractions/setup-just@v2
|
||||
|
||||
- name: Install build tooling (aarch64-unknown-linux-gnu)
|
||||
if: matrix.cargo-target == 'aarch64-unknown-linux-gnu'
|
||||
|
@ -86,24 +104,24 @@ jobs:
|
|||
run: just zip-release ${{ matrix.cargo-target }}
|
||||
|
||||
- name: Upload release artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact-name }}
|
||||
path: release.zip
|
||||
|
||||
release:
|
||||
name: Release
|
||||
release-github:
|
||||
name: Release (GitHub)
|
||||
runs-on: ubuntu-latest
|
||||
needs: ["init", "build"]
|
||||
needs: ["init", "dry-run", "build"]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Just
|
||||
uses: extractions/setup-just@v1
|
||||
uses: extractions/setup-just@v2
|
||||
|
||||
- name: Download releases
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ./releases
|
||||
|
||||
|
@ -111,7 +129,7 @@ jobs:
|
|||
run: just unpack-releases "./releases"
|
||||
|
||||
- name: Create release
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
|
@ -120,3 +138,21 @@ jobs:
|
|||
fail_on_unmatched_files: true
|
||||
files: ./releases/*.zip
|
||||
draft: true
|
||||
|
||||
release-crates:
|
||||
name: Release (crates.io)
|
||||
runs-on: ubuntu-latest
|
||||
needs: ["init", "dry-run", "build"]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Publish crates
|
||||
uses: katyo/publish-crates@v2
|
||||
with:
|
||||
dry-run: false
|
||||
check-repo: true
|
||||
registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||
|
|
270
Cargo.lock
generated
270
Cargo.lock
generated
|
@ -163,9 +163,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "async-compression"
|
||||
version = "0.4.8"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07dbbf24db18d609b1462965249abdf49129ccad073ec257da372adc83259c60"
|
||||
checksum = "9c90a406b4495d129f00461241616194cb8a032c8d1c53c657f0961d5f8e0498"
|
||||
dependencies = [
|
||||
"brotli",
|
||||
"flate2",
|
||||
|
@ -205,17 +205,6 @@ version = "4.7.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
version = "1.1.2"
|
||||
|
@ -324,9 +313,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "brotli"
|
||||
version = "4.0.0"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "125740193d7fee5cc63ab9e16c2fdc4e07c74ba755cc53b327d6ea029e9fc569"
|
||||
checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
"alloc-stdlib",
|
||||
|
@ -335,9 +324,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "brotli-decompressor"
|
||||
version = "3.0.0"
|
||||
version = "4.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65622a320492e09b5e0ac436b14c54ff68199bac392d0e89a6832c4518eea525"
|
||||
checksum = "e6221fe77a248b9117d431ad93761222e1cf8ff282d9d1d5d9f53d6299a1cf76"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
"alloc-stdlib",
|
||||
|
@ -759,12 +748,6 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.6"
|
||||
|
@ -1367,15 +1350,6 @@ version = "2.9.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
|
@ -1484,57 +1458,203 @@ name = "lune"
|
|||
version = "0.8.3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-compression",
|
||||
"async-trait",
|
||||
"blocking",
|
||||
"bstr",
|
||||
"chrono",
|
||||
"chrono_lc",
|
||||
"clap",
|
||||
"console",
|
||||
"dialoguer",
|
||||
"directories",
|
||||
"dunce",
|
||||
"env_logger",
|
||||
"futures-util",
|
||||
"include_dir",
|
||||
"lune-roblox",
|
||||
"lune-std",
|
||||
"lune-utils",
|
||||
"mlua",
|
||||
"mlua-luau-scheduler",
|
||||
"once_cell",
|
||||
"reqwest",
|
||||
"rustyline",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"zip_next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lune-roblox"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"glam",
|
||||
"lune-utils",
|
||||
"mlua",
|
||||
"once_cell",
|
||||
"rand",
|
||||
"rbx_binary",
|
||||
"rbx_dom_weak",
|
||||
"rbx_reflection",
|
||||
"rbx_reflection_database",
|
||||
"rbx_xml",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lune-std"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lune-std-datetime",
|
||||
"lune-std-fs",
|
||||
"lune-std-luau",
|
||||
"lune-std-net",
|
||||
"lune-std-process",
|
||||
"lune-std-regex",
|
||||
"lune-std-roblox",
|
||||
"lune-std-serde",
|
||||
"lune-std-stdio",
|
||||
"lune-std-task",
|
||||
"lune-utils",
|
||||
"mlua",
|
||||
"mlua-luau-scheduler",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lune-std-datetime"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"chrono_lc",
|
||||
"lune-utils",
|
||||
"mlua",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lune-std-fs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"lune-std-datetime",
|
||||
"lune-utils",
|
||||
"mlua",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lune-std-luau"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lune-utils",
|
||||
"mlua",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lune-std-net"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"futures-util",
|
||||
"http 1.1.0",
|
||||
"http-body-util",
|
||||
"hyper 1.3.1",
|
||||
"hyper-tungstenite",
|
||||
"hyper-util",
|
||||
"include_dir",
|
||||
"itertools",
|
||||
"lz4_flex",
|
||||
"lune-std-serde",
|
||||
"lune-utils",
|
||||
"mlua",
|
||||
"mlua-luau-scheduler",
|
||||
"reqwest",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"urlencoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lune-std-process"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"directories",
|
||||
"lune-utils",
|
||||
"mlua",
|
||||
"mlua-luau-scheduler",
|
||||
"os_str_bytes",
|
||||
"pin-project",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lune-std-regex"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lune-utils",
|
||||
"mlua",
|
||||
"regex",
|
||||
"self_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lune-std-roblox"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lune-roblox",
|
||||
"lune-utils",
|
||||
"mlua",
|
||||
"mlua-luau-scheduler",
|
||||
"once_cell",
|
||||
"os_str_bytes",
|
||||
"path-clean",
|
||||
"pathdiff",
|
||||
"pin-project",
|
||||
"rand",
|
||||
"rbx_binary",
|
||||
"rbx_cookie",
|
||||
"rbx_dom_weak",
|
||||
"rbx_reflection",
|
||||
"rbx_reflection_database",
|
||||
"rbx_xml",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"rustyline",
|
||||
"self_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lune-std-serde"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-compression",
|
||||
"bstr",
|
||||
"lune-utils",
|
||||
"lz4",
|
||||
"mlua",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"toml",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"urlencoding",
|
||||
"zip_next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lune-std-stdio"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dialoguer",
|
||||
"lune-utils",
|
||||
"mlua",
|
||||
"mlua-luau-scheduler",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lune-std-task"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lune-utils",
|
||||
"mlua",
|
||||
"mlua-luau-scheduler",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lune-utils"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"console",
|
||||
"dunce",
|
||||
"mlua",
|
||||
"once_cell",
|
||||
"path-clean",
|
||||
"pathdiff",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1557,15 +1677,6 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lz4_flex"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5"
|
||||
dependencies = [
|
||||
"twox-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lzma-rs"
|
||||
version = "0.3.0"
|
||||
|
@ -2624,12 +2735,6 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "stdweb"
|
||||
version = "0.4.20"
|
||||
|
@ -2882,7 +2987,6 @@ dependencies = [
|
|||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"tracing",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
|
@ -3100,16 +3204,6 @@ dependencies = [
|
|||
"utf-8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "twox-hash"
|
||||
version = "1.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typed-arena"
|
||||
version = "2.0.2"
|
||||
|
|
172
Cargo.toml
172
Cargo.toml
|
@ -1,41 +1,21 @@
|
|||
[package]
|
||||
name = "lune"
|
||||
version = "0.8.3"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
repository = "https://github.com/lune-org/lune"
|
||||
description = "A standalone Luau runtime"
|
||||
readme = "README.md"
|
||||
keywords = ["cli", "lua", "luau", "runtime"]
|
||||
categories = ["command-line-interface"]
|
||||
|
||||
[[bin]]
|
||||
name = "lune"
|
||||
path = "src/main.rs"
|
||||
|
||||
[lib]
|
||||
name = "lune"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[features]
|
||||
default = ["cli", "roblox"]
|
||||
cli = [
|
||||
"dep:anyhow",
|
||||
"dep:env_logger",
|
||||
"dep:clap",
|
||||
"dep:include_dir",
|
||||
"dep:rustyline",
|
||||
"dep:zip_next",
|
||||
]
|
||||
roblox = [
|
||||
"dep:glam",
|
||||
"dep:rand",
|
||||
"dep:rbx_cookie",
|
||||
"dep:rbx_binary",
|
||||
"dep:rbx_dom_weak",
|
||||
"dep:rbx_reflection",
|
||||
"dep:rbx_reflection_database",
|
||||
"dep:rbx_xml",
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
default-members = ["crates/lune"]
|
||||
members = [
|
||||
"crates/lune",
|
||||
"crates/lune-roblox",
|
||||
"crates/lune-std",
|
||||
"crates/lune-std-datetime",
|
||||
"crates/lune-std-fs",
|
||||
"crates/lune-std-luau",
|
||||
"crates/lune-std-net",
|
||||
"crates/lune-std-process",
|
||||
"crates/lune-std-regex",
|
||||
"crates/lune-std-roblox",
|
||||
"crates/lune-std-serde",
|
||||
"crates/lune-std-stdio",
|
||||
"crates/lune-std-task",
|
||||
"crates/lune-utils",
|
||||
]
|
||||
|
||||
# Profile for building the release binary, with the following options set:
|
||||
|
@ -53,99 +33,31 @@ opt-level = "z"
|
|||
strip = true
|
||||
lto = true
|
||||
|
||||
# All of the dependencies for Lune.
|
||||
# Lints for all crates in the workspace
|
||||
#
|
||||
# Dependencies are categorized as following:
|
||||
#
|
||||
# 1. General dependencies with no specific features set
|
||||
# 2. Large / core dependencies that have many different crates and / or features set
|
||||
# 3. Dependencies for specific features of Lune, eg. the CLI or massive Roblox builtin library
|
||||
#
|
||||
[dependencies]
|
||||
console = "0.15"
|
||||
directories = "5.0"
|
||||
futures-util = "0.3"
|
||||
once_cell = "1.17"
|
||||
thiserror = "1.0"
|
||||
async-trait = "0.1"
|
||||
dialoguer = "0.11"
|
||||
dunce = "1.0"
|
||||
lz4_flex = "0.11"
|
||||
path-clean = "1.0"
|
||||
pathdiff = "0.2"
|
||||
pin-project = "1.0"
|
||||
urlencoding = "2.1"
|
||||
bstr = "1.9"
|
||||
regex = "1.10"
|
||||
self_cell = "1.0"
|
||||
# 1. Error on all lints by default, then make cargo + clippy pedantic lints just warn
|
||||
# 2. Selectively allow some lints that are _too_ pedantic, such as:
|
||||
# - Casts between number types
|
||||
# - Module naming conventions
|
||||
# - Imports and multiple dependency versions
|
||||
[workspace.lints.clippy]
|
||||
all = { level = "deny", priority = -3 }
|
||||
cargo = { level = "warn", priority = -2 }
|
||||
pedantic = { level = "warn", priority = -1 }
|
||||
|
||||
### RUNTIME
|
||||
cast_lossless = { level = "allow", priority = 1 }
|
||||
cast_possible_truncation = { level = "allow", priority = 1 }
|
||||
cast_possible_wrap = { level = "allow", priority = 1 }
|
||||
cast_precision_loss = { level = "allow", priority = 1 }
|
||||
cast_sign_loss = { level = "allow", priority = 1 }
|
||||
|
||||
blocking = "1.5"
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
tokio = { version = "1.24", features = ["full", "tracing"] }
|
||||
os_str_bytes = { version = "7.0", features = ["conversions"] }
|
||||
similar_names = { level = "allow", priority = 1 }
|
||||
unnecessary_wraps = { level = "allow", priority = 1 }
|
||||
unnested_or_patterns = { level = "allow", priority = 1 }
|
||||
unreadable_literal = { level = "allow", priority = 1 }
|
||||
|
||||
mlua-luau-scheduler = { version = "0.0.2" }
|
||||
mlua = { version = "0.9.7", features = [
|
||||
"luau",
|
||||
"luau-jit",
|
||||
"async",
|
||||
"serialize",
|
||||
] }
|
||||
|
||||
### SERDE
|
||||
|
||||
async-compression = { version = "0.4", features = [
|
||||
"tokio",
|
||||
"brotli",
|
||||
"deflate",
|
||||
"gzip",
|
||||
"zlib",
|
||||
] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
serde_yaml = "0.9"
|
||||
toml = { version = "0.8", features = ["preserve_order"] }
|
||||
|
||||
### NET
|
||||
|
||||
hyper = { version = "1.1", features = ["full"] }
|
||||
hyper-util = { version = "0.1", features = ["full"] }
|
||||
http = "1.0"
|
||||
http-body-util = { version = "0.1" }
|
||||
hyper-tungstenite = { version = "0.13" }
|
||||
|
||||
reqwest = { version = "0.11", default-features = false, features = [
|
||||
"rustls-tls",
|
||||
] }
|
||||
|
||||
tokio-tungstenite = { version = "0.21", features = ["rustls-tls-webpki-roots"] }
|
||||
|
||||
### DATETIME
|
||||
chrono = "=0.4.34" # NOTE: 0.4.35 does not compile with chrono_lc
|
||||
chrono_lc = "0.1"
|
||||
|
||||
### CLI
|
||||
|
||||
anyhow = { optional = true, version = "1.0" }
|
||||
env_logger = { optional = true, version = "0.11" }
|
||||
itertools = "0.12"
|
||||
clap = { optional = true, version = "4.1", features = ["derive"] }
|
||||
include_dir = { optional = true, version = "0.7", features = ["glob"] }
|
||||
rustyline = { optional = true, version = "14.0" }
|
||||
zip_next = { optional = true, version = "1.1" }
|
||||
|
||||
### ROBLOX
|
||||
|
||||
glam = { optional = true, version = "0.27" }
|
||||
rand = { optional = true, version = "0.8" }
|
||||
|
||||
rbx_cookie = { optional = true, version = "0.1.4", default-features = false }
|
||||
|
||||
rbx_binary = { optional = true, version = "0.7.3" }
|
||||
rbx_dom_weak = { optional = true, version = "2.6.0" }
|
||||
rbx_reflection = { optional = true, version = "4.4.0" }
|
||||
rbx_reflection_database = { optional = true, version = "0.2.9" }
|
||||
rbx_xml = { optional = true, version = "0.13.2" }
|
||||
multiple_crate_versions = { level = "allow", priority = 1 }
|
||||
module_inception = { level = "allow", priority = 1 }
|
||||
module_name_repetitions = { level = "allow", priority = 1 }
|
||||
needless_pass_by_value = { level = "allow", priority = 1 }
|
||||
wildcard_imports = { level = "allow", priority = 1 }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[tools]
|
||||
luau-lsp = "JohnnyMorganz/luau-lsp@1.27.0"
|
||||
selene = "Kampfkarren/selene@0.26.1"
|
||||
stylua = "JohnnyMorganz/StyLua@0.19.1"
|
||||
luau-lsp = "JohnnyMorganz/luau-lsp@1.29.0"
|
||||
selene = "Kampfkarren/selene@0.27.1"
|
||||
stylua = "JohnnyMorganz/StyLua@0.20.0"
|
||||
|
|
27
crates/lune-roblox/Cargo.toml
Normal file
27
crates/lune-roblox/Cargo.toml
Normal file
|
@ -0,0 +1,27 @@
|
|||
[package]
|
||||
name = "lune-roblox"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
mlua = { version = "0.9.7", features = ["luau"] }
|
||||
|
||||
glam = "0.27"
|
||||
rand = "0.8"
|
||||
thiserror = "1.0"
|
||||
once_cell = "1.17"
|
||||
|
||||
rbx_binary = "0.7.3"
|
||||
rbx_dom_weak = "2.6.0"
|
||||
rbx_reflection = "4.4.0"
|
||||
rbx_reflection_database = "0.2.9"
|
||||
rbx_xml = "0.13.2"
|
||||
|
||||
lune-utils = { version = "0.1.0", path = "../lune-utils" }
|
|
@ -4,6 +4,15 @@ use rbx_dom_weak::types::{Variant as DomValue, VariantType as DomType};
|
|||
|
||||
use super::extension::DomValueExt;
|
||||
|
||||
/**
|
||||
Checks if the given name is a valid attribute name.
|
||||
|
||||
# Errors
|
||||
|
||||
- If the name starts with the prefix "RBX".
|
||||
- If the name contains any characters other than alphanumeric characters and underscore.
|
||||
- If the name is longer than 100 characters.
|
||||
*/
|
||||
pub fn ensure_valid_attribute_name(name: impl AsRef<str>) -> LuaResult<()> {
|
||||
let name = name.as_ref();
|
||||
if name.to_ascii_uppercase().starts_with("RBX") {
|
||||
|
@ -23,6 +32,13 @@ pub fn ensure_valid_attribute_name(name: impl AsRef<str>) -> LuaResult<()> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Checks if the given value is a valid attribute value.
|
||||
|
||||
# Errors
|
||||
|
||||
- If the value is not a valid attribute type.
|
||||
*/
|
||||
pub fn ensure_valid_attribute_value(value: &DomValue) -> LuaResult<()> {
|
||||
let is_valid = matches!(
|
||||
value.ty(),
|
|
@ -2,7 +2,7 @@ use mlua::prelude::*;
|
|||
|
||||
use rbx_dom_weak::types::{Variant as DomValue, VariantType as DomType};
|
||||
|
||||
use crate::roblox::{datatypes::extension::DomValueExt, instance::Instance};
|
||||
use crate::{datatypes::extension::DomValueExt, instance::Instance};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
@ -65,8 +65,10 @@ impl<'lua> DomValueToLua<'lua> for LuaValue<'lua> {
|
|||
|
||||
// NOTE: Some values are either optional or default and we should handle
|
||||
// that properly here since the userdata conversion above will always fail
|
||||
DomValue::OptionalCFrame(None) => Ok(LuaValue::Nil),
|
||||
DomValue::PhysicalProperties(dom::PhysicalProperties::Default) => Ok(LuaValue::Nil),
|
||||
DomValue::OptionalCFrame(None)
|
||||
| DomValue::PhysicalProperties(dom::PhysicalProperties::Default) => {
|
||||
Ok(LuaValue::Nil)
|
||||
}
|
||||
|
||||
_ => Err(e),
|
||||
},
|
|
@ -6,6 +6,7 @@ pub(crate) trait DomValueExt {
|
|||
|
||||
impl DomValueExt for DomType {
|
||||
fn variant_name(&self) -> Option<&'static str> {
|
||||
#[allow(clippy::enum_glob_use)]
|
||||
use DomType::*;
|
||||
Some(match self {
|
||||
Attributes => "Attributes",
|
|
@ -10,4 +10,4 @@ mod util;
|
|||
|
||||
use result::*;
|
||||
|
||||
pub use crate::roblox::shared::userdata::*;
|
||||
pub use crate::shared::userdata::*;
|
|
@ -3,7 +3,9 @@ use core::fmt;
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::Axes as DomAxes;
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::{super::*, EnumItem};
|
||||
|
||||
|
@ -52,8 +54,7 @@ impl LuaExportsTable<'_> for Axes {
|
|||
check(&e);
|
||||
} else {
|
||||
return Err(LuaError::RuntimeError(format!(
|
||||
"Expected argument #{} to be an EnumItem, got userdata",
|
||||
index
|
||||
"Expected argument #{index} to be an EnumItem, got userdata",
|
||||
)));
|
||||
}
|
||||
} else {
|
|
@ -4,14 +4,16 @@ use mlua::prelude::*;
|
|||
use rand::seq::SliceRandom;
|
||||
use rbx_dom_weak::types::BrickColor as DomBrickColor;
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::{super::*, Color3};
|
||||
|
||||
/**
|
||||
An implementation of the [BrickColor](https://create.roblox.com/docs/reference/engine/datatypes/BrickColor) Roblox datatype.
|
||||
|
||||
This implements all documented properties, methods & constructors of the BrickColor class as of March 2023.
|
||||
This implements all documented properties, methods & constructors of the `BrickColor` class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct BrickColor {
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(clippy::items_after_statements)]
|
||||
|
||||
use core::fmt;
|
||||
use std::ops;
|
||||
|
||||
|
@ -5,7 +7,9 @@ use glam::{EulerRot, Mat3, Mat4, Quat, Vec3};
|
|||
use mlua::{prelude::*, Variadic};
|
||||
use rbx_dom_weak::types::{CFrame as DomCFrame, Matrix3 as DomMatrix3, Vector3 as DomVector3};
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::{super::*, Vector3};
|
||||
|
||||
|
@ -14,7 +18,7 @@ use super::{super::*, Vector3};
|
|||
Roblox datatype, backed by [`glam::Mat4`].
|
||||
|
||||
This implements all documented properties, methods &
|
||||
constructors of the CFrame class as of March 2023.
|
||||
constructors of the `CFrame` class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct CFrame(pub Mat4);
|
||||
|
@ -42,6 +46,7 @@ impl CFrame {
|
|||
impl LuaExportsTable<'_> for CFrame {
|
||||
const EXPORT_NAME: &'static str = "CFrame";
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn create_exports_table(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
let cframe_angles = |_, (rx, ry, rz): (f32, f32, f32)| {
|
||||
Ok(CFrame(Mat4::from_euler(EulerRot::XYZ, rx, ry, rz)))
|
||||
|
@ -68,8 +73,7 @@ impl LuaExportsTable<'_> for CFrame {
|
|||
Ok(CFrame(Mat4::from_cols(
|
||||
rx.0.extend(0.0),
|
||||
ry.0.extend(0.0),
|
||||
rz.map(|r| r.0)
|
||||
.unwrap_or_else(|| rx.0.cross(ry.0).normalize())
|
||||
rz.map_or_else(|| rx.0.cross(ry.0).normalize(), |r| r.0)
|
||||
.extend(0.0),
|
||||
pos.0.extend(1.0),
|
||||
)))
|
||||
|
@ -195,6 +199,7 @@ impl LuaUserData for CFrame {
|
|||
});
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
// Methods
|
||||
methods.add_method("Inverse", |_, this, ()| Ok(this.inverse()));
|
||||
|
@ -226,34 +231,49 @@ impl LuaUserData for CFrame {
|
|||
methods.add_method(
|
||||
"ToWorldSpace",
|
||||
|_, this, rhs: Variadic<LuaUserDataRef<CFrame>>| {
|
||||
Ok(Variadic::from_iter(rhs.into_iter().map(|cf| *this * *cf)))
|
||||
Ok(rhs
|
||||
.into_iter()
|
||||
.map(|cf| *this * *cf)
|
||||
.collect::<Variadic<_>>())
|
||||
},
|
||||
);
|
||||
methods.add_method(
|
||||
"ToObjectSpace",
|
||||
|_, this, rhs: Variadic<LuaUserDataRef<CFrame>>| {
|
||||
let inverse = this.inverse();
|
||||
Ok(Variadic::from_iter(rhs.into_iter().map(|cf| inverse * *cf)))
|
||||
Ok(rhs
|
||||
.into_iter()
|
||||
.map(|cf| inverse * *cf)
|
||||
.collect::<Variadic<_>>())
|
||||
},
|
||||
);
|
||||
methods.add_method(
|
||||
"PointToWorldSpace",
|
||||
|_, this, rhs: Variadic<LuaUserDataRef<Vector3>>| {
|
||||
Ok(Variadic::from_iter(rhs.into_iter().map(|v3| *this * *v3)))
|
||||
Ok(rhs
|
||||
.into_iter()
|
||||
.map(|v3| *this * *v3)
|
||||
.collect::<Variadic<_>>())
|
||||
},
|
||||
);
|
||||
methods.add_method(
|
||||
"PointToObjectSpace",
|
||||
|_, this, rhs: Variadic<LuaUserDataRef<Vector3>>| {
|
||||
let inverse = this.inverse();
|
||||
Ok(Variadic::from_iter(rhs.into_iter().map(|v3| inverse * *v3)))
|
||||
Ok(rhs
|
||||
.into_iter()
|
||||
.map(|v3| inverse * *v3)
|
||||
.collect::<Variadic<_>>())
|
||||
},
|
||||
);
|
||||
methods.add_method(
|
||||
"VectorToWorldSpace",
|
||||
|_, this, rhs: Variadic<LuaUserDataRef<Vector3>>| {
|
||||
let result = *this - Vector3(this.position());
|
||||
Ok(Variadic::from_iter(rhs.into_iter().map(|v3| result * *v3)))
|
||||
Ok(rhs
|
||||
.into_iter()
|
||||
.map(|v3| result * *v3)
|
||||
.collect::<Variadic<_>>())
|
||||
},
|
||||
);
|
||||
methods.add_method(
|
||||
|
@ -261,8 +281,10 @@ impl LuaUserData for CFrame {
|
|||
|_, this, rhs: Variadic<LuaUserDataRef<Vector3>>| {
|
||||
let inverse = this.inverse();
|
||||
let result = inverse - Vector3(inverse.position());
|
||||
|
||||
Ok(Variadic::from_iter(rhs.into_iter().map(|v3| result * *v3)))
|
||||
Ok(rhs
|
||||
.into_iter()
|
||||
.map(|v3| result * *v3)
|
||||
.collect::<Variadic<_>>())
|
||||
},
|
||||
);
|
||||
#[rustfmt::skip]
|
||||
|
@ -445,7 +467,7 @@ mod cframe_test {
|
|||
Vec3::new(1.0, 2.0, 3.0).extend(1.0),
|
||||
));
|
||||
|
||||
assert_eq!(CFrame::from(dom_cframe), cframe)
|
||||
assert_eq!(CFrame::from(dom_cframe), cframe);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -466,6 +488,6 @@ mod cframe_test {
|
|||
),
|
||||
);
|
||||
|
||||
assert_eq!(DomCFrame::from(cframe), dom_cframe)
|
||||
assert_eq!(DomCFrame::from(cframe), dom_cframe);
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(clippy::many_single_char_names)]
|
||||
|
||||
use core::fmt;
|
||||
use std::ops;
|
||||
|
||||
|
@ -5,7 +7,9 @@ use glam::Vec3;
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::{Color3 as DomColor3, Color3uint8 as DomColor3uint8};
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::super::*;
|
||||
|
||||
|
@ -85,8 +89,7 @@ impl LuaExportsTable<'_> for Color3 {
|
|||
b: (b as f32) / 255f32,
|
||||
}),
|
||||
_ => Err(LuaError::RuntimeError(format!(
|
||||
"Hex color string '{}' contains invalid character",
|
||||
trimmed
|
||||
"Hex color string '{trimmed}' contains invalid character",
|
||||
))),
|
||||
}
|
||||
};
|
||||
|
@ -151,6 +154,7 @@ impl LuaUserData for Color3 {
|
|||
let max = r.max(g).max(b);
|
||||
let diff = max - min;
|
||||
|
||||
#[allow(clippy::float_cmp)]
|
||||
let hue = (match max {
|
||||
max if max == min => 0.0,
|
||||
max if max == r => (g - b) / diff + (if g < b { 6.0 } else { 0.0 }),
|
|
@ -5,14 +5,16 @@ use rbx_dom_weak::types::{
|
|||
ColorSequence as DomColorSequence, ColorSequenceKeypoint as DomColorSequenceKeypoint,
|
||||
};
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::{super::*, Color3, ColorSequenceKeypoint};
|
||||
|
||||
/**
|
||||
An implementation of the [ColorSequence](https://create.roblox.com/docs/reference/engine/datatypes/ColorSequence) Roblox datatype.
|
||||
|
||||
This implements all documented properties, methods & constructors of the ColorSequence class as of March 2023.
|
||||
This implements all documented properties, methods & constructors of the `ColorSequence` class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct ColorSequence {
|
||||
|
@ -87,9 +89,9 @@ impl fmt::Display for ColorSequence {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for (index, keypoint) in self.keypoints.iter().enumerate() {
|
||||
if index < self.keypoints.len() - 1 {
|
||||
write!(f, "{}, ", keypoint)?;
|
||||
write!(f, "{keypoint}, ")?;
|
||||
} else {
|
||||
write!(f, "{}", keypoint)?;
|
||||
write!(f, "{keypoint}")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -102,7 +104,7 @@ impl From<DomColorSequence> for ColorSequence {
|
|||
keypoints: v
|
||||
.keypoints
|
||||
.iter()
|
||||
.cloned()
|
||||
.copied()
|
||||
.map(ColorSequenceKeypoint::from)
|
||||
.collect(),
|
||||
}
|
||||
|
@ -115,7 +117,7 @@ impl From<ColorSequence> for DomColorSequence {
|
|||
keypoints: v
|
||||
.keypoints
|
||||
.iter()
|
||||
.cloned()
|
||||
.copied()
|
||||
.map(DomColorSequenceKeypoint::from)
|
||||
.collect(),
|
||||
}
|
|
@ -3,14 +3,16 @@ use core::fmt;
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::ColorSequenceKeypoint as DomColorSequenceKeypoint;
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::{super::*, Color3};
|
||||
|
||||
/**
|
||||
An implementation of the [ColorSequenceKeypoint](https://create.roblox.com/docs/reference/engine/datatypes/ColorSequenceKeypoint) Roblox datatype.
|
||||
|
||||
This implements all documented properties, methods & constructors of the ColorSequenceKeypoint class as of March 2023.
|
||||
This implements all documented properties, methods & constructors of the `ColorSequenceKeypoint` class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct ColorSequenceKeypoint {
|
|
@ -8,7 +8,7 @@ use super::{super::*, Enum};
|
|||
/**
|
||||
An implementation of the [EnumItem](https://create.roblox.com/docs/reference/engine/datatypes/EnumItem) Roblox datatype.
|
||||
|
||||
This implements all documented properties, methods & constructors of the EnumItem class as of March 2023.
|
||||
This implements all documented properties, methods & constructors of the `EnumItem` class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EnumItem {
|
|
@ -24,8 +24,7 @@ impl LuaUserData for Enums {
|
|||
|_, _, name: String| match Enum::from_name(&name) {
|
||||
Some(e) => Ok(e),
|
||||
None => Err(LuaError::RuntimeError(format!(
|
||||
"The enum '{}' does not exist",
|
||||
name
|
||||
"The enum '{name}' does not exist",
|
||||
))),
|
||||
},
|
||||
);
|
|
@ -1,9 +1,13 @@
|
|||
#![allow(clippy::struct_excessive_bools)]
|
||||
|
||||
use core::fmt;
|
||||
|
||||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::Faces as DomFaces;
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::{super::*, EnumItem};
|
||||
|
||||
|
@ -54,8 +58,7 @@ impl LuaExportsTable<'_> for Faces {
|
|||
check(&e);
|
||||
} else {
|
||||
return Err(LuaError::RuntimeError(format!(
|
||||
"Expected argument #{} to be an EnumItem, got userdata",
|
||||
index
|
||||
"Expected argument #{index} to be an EnumItem, got userdata",
|
||||
)));
|
||||
}
|
||||
} else {
|
|
@ -6,7 +6,9 @@ use rbx_dom_weak::types::{
|
|||
Font as DomFont, FontStyle as DomFontStyle, FontWeight as DomFontWeight,
|
||||
};
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::{super::*, EnumItem};
|
||||
|
||||
|
@ -62,7 +64,7 @@ impl LuaExportsTable<'_> for Font {
|
|||
let font_from_name =
|
||||
|_, (file, weight, style): (String, Option<FontWeight>, Option<FontStyle>)| {
|
||||
Ok(Font {
|
||||
family: format!("rbxasset://fonts/families/{}.json", file),
|
||||
family: format!("rbxasset://fonts/families/{file}.json"),
|
||||
weight: weight.unwrap_or_default(),
|
||||
style: style.unwrap_or_default(),
|
||||
cached_id: None,
|
||||
|
@ -72,7 +74,7 @@ impl LuaExportsTable<'_> for Font {
|
|||
let font_from_id =
|
||||
|_, (id, weight, style): (i32, Option<FontWeight>, Option<FontStyle>)| {
|
||||
Ok(Font {
|
||||
family: format!("rbxassetid://{}", id),
|
||||
family: format!("rbxassetid://{id}"),
|
||||
weight: weight.unwrap_or_default(),
|
||||
style: style.unwrap_or_default(),
|
||||
cached_id: None,
|
||||
|
@ -206,7 +208,7 @@ pub(crate) enum FontWeight {
|
|||
}
|
||||
|
||||
impl FontWeight {
|
||||
pub(crate) fn as_u16(&self) -> u16 {
|
||||
pub(crate) fn as_u16(self) -> u16 {
|
||||
match self {
|
||||
Self::Thin => 100,
|
||||
Self::ExtraLight => 200,
|
||||
|
@ -288,12 +290,11 @@ impl<'lua> FromLua<'lua> for FontWeight {
|
|||
if value.parent.desc.name == "FontWeight" {
|
||||
if let Ok(value) = FontWeight::from_str(&value.name) {
|
||||
return Ok(value);
|
||||
} else {
|
||||
}
|
||||
message = Some(format!(
|
||||
"Found unknown Enum.FontWeight value '{}'",
|
||||
value.name
|
||||
));
|
||||
}
|
||||
} else {
|
||||
message = Some(format!(
|
||||
"Expected Enum.FontWeight, got Enum.{}",
|
||||
|
@ -316,7 +317,7 @@ impl<'lua> IntoLua<'lua> for FontWeight {
|
|||
None => Err(LuaError::ToLuaConversionError {
|
||||
from: "FontWeight",
|
||||
to: "EnumItem",
|
||||
message: Some(format!("Found unknown Enum.FontWeight value '{}'", self)),
|
||||
message: Some(format!("Found unknown Enum.FontWeight value '{self}'")),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +330,7 @@ pub(crate) enum FontStyle {
|
|||
}
|
||||
|
||||
impl FontStyle {
|
||||
pub(crate) fn as_u8(&self) -> u8 {
|
||||
pub(crate) fn as_u8(self) -> u8 {
|
||||
match self {
|
||||
Self::Normal => 0,
|
||||
Self::Italic => 1,
|
||||
|
@ -383,12 +384,11 @@ impl<'lua> FromLua<'lua> for FontStyle {
|
|||
if value.parent.desc.name == "FontStyle" {
|
||||
if let Ok(value) = FontStyle::from_str(&value.name) {
|
||||
return Ok(value);
|
||||
} else {
|
||||
}
|
||||
message = Some(format!(
|
||||
"Found unknown Enum.FontStyle value '{}'",
|
||||
value.name
|
||||
));
|
||||
}
|
||||
} else {
|
||||
message = Some(format!(
|
||||
"Expected Enum.FontStyle, got Enum.{}",
|
||||
|
@ -411,7 +411,7 @@ impl<'lua> IntoLua<'lua> for FontStyle {
|
|||
None => Err(LuaError::ToLuaConversionError {
|
||||
from: "FontStyle",
|
||||
to: "EnumItem",
|
||||
message: Some(format!("Found unknown Enum.FontStyle value '{}'", self)),
|
||||
message: Some(format!("Found unknown Enum.FontStyle value '{self}'")),
|
||||
}),
|
||||
}
|
||||
}
|
|
@ -3,14 +3,16 @@ use core::fmt;
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::NumberRange as DomNumberRange;
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::super::*;
|
||||
|
||||
/**
|
||||
An implementation of the [NumberRange](https://create.roblox.com/docs/reference/engine/datatypes/NumberRange) Roblox datatype.
|
||||
|
||||
This implements all documented properties, methods & constructors of the NumberRange class as of March 2023.
|
||||
This implements all documented properties, methods & constructors of the `NumberRange` class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct NumberRange {
|
|
@ -5,14 +5,16 @@ use rbx_dom_weak::types::{
|
|||
NumberSequence as DomNumberSequence, NumberSequenceKeypoint as DomNumberSequenceKeypoint,
|
||||
};
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::{super::*, NumberSequenceKeypoint};
|
||||
|
||||
/**
|
||||
An implementation of the [NumberSequence](https://create.roblox.com/docs/reference/engine/datatypes/NumberSequence) Roblox datatype.
|
||||
|
||||
This implements all documented properties, methods & constructors of the NumberSequence class as of March 2023.
|
||||
This implements all documented properties, methods & constructors of the `NumberSequence` class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct NumberSequence {
|
||||
|
@ -91,9 +93,9 @@ impl fmt::Display for NumberSequence {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for (index, keypoint) in self.keypoints.iter().enumerate() {
|
||||
if index < self.keypoints.len() - 1 {
|
||||
write!(f, "{}, ", keypoint)?;
|
||||
write!(f, "{keypoint}, ")?;
|
||||
} else {
|
||||
write!(f, "{}", keypoint)?;
|
||||
write!(f, "{keypoint}")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -106,7 +108,7 @@ impl From<DomNumberSequence> for NumberSequence {
|
|||
keypoints: v
|
||||
.keypoints
|
||||
.iter()
|
||||
.cloned()
|
||||
.copied()
|
||||
.map(NumberSequenceKeypoint::from)
|
||||
.collect(),
|
||||
}
|
||||
|
@ -119,7 +121,7 @@ impl From<NumberSequence> for DomNumberSequence {
|
|||
keypoints: v
|
||||
.keypoints
|
||||
.iter()
|
||||
.cloned()
|
||||
.copied()
|
||||
.map(DomNumberSequenceKeypoint::from)
|
||||
.collect(),
|
||||
}
|
|
@ -3,14 +3,16 @@ use core::fmt;
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::NumberSequenceKeypoint as DomNumberSequenceKeypoint;
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::super::*;
|
||||
|
||||
/**
|
||||
An implementation of the [NumberSequenceKeypoint](https://create.roblox.com/docs/reference/engine/datatypes/NumberSequenceKeypoint) Roblox datatype.
|
||||
|
||||
This implements all documented properties, methods & constructors of the NumberSequenceKeypoint class as of March 2023.
|
||||
This implements all documented properties, methods & constructors of the `NumberSequenceKeypoint` class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct NumberSequenceKeypoint {
|
|
@ -3,14 +3,16 @@ use core::fmt;
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::CustomPhysicalProperties as DomCustomPhysicalProperties;
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::{super::*, EnumItem};
|
||||
|
||||
/**
|
||||
An implementation of the [PhysicalProperties](https://create.roblox.com/docs/reference/engine/datatypes/PhysicalProperties) Roblox datatype.
|
||||
|
||||
This implements all documented properties, methods & constructors of the PhysicalProperties class as of March 2023.
|
||||
This implements all documented properties, methods & constructors of the `PhysicalProperties` class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct PhysicalProperties {
|
|
@ -4,7 +4,9 @@ use glam::Vec3;
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::Ray as DomRay;
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::{super::*, Vector3};
|
||||
|
|
@ -5,7 +5,9 @@ use glam::Vec2;
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::Rect as DomRect;
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::{super::*, Vector2};
|
||||
|
|
@ -4,7 +4,9 @@ use glam::{Mat4, Vec3};
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::Region3 as DomRegion3;
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::{super::*, CFrame, Vector3};
|
||||
|
|
@ -4,7 +4,9 @@ use glam::IVec3;
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::Region3int16 as DomRegion3int16;
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::{super::*, Vector3int16};
|
||||
|
|
@ -4,14 +4,16 @@ use std::ops;
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::UDim as DomUDim;
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::super::*;
|
||||
|
||||
/**
|
||||
An implementation of the [UDim](https://create.roblox.com/docs/reference/engine/datatypes/UDim) Roblox datatype.
|
||||
|
||||
This implements all documented properties, methods & constructors of the UDim class as of March 2023.
|
||||
This implements all documented properties, methods & constructors of the `UDim` class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct UDim {
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(clippy::items_after_statements)]
|
||||
|
||||
use core::fmt;
|
||||
use std::ops;
|
||||
|
||||
|
@ -5,14 +7,16 @@ use glam::Vec2;
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::UDim2 as DomUDim2;
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::{super::*, UDim};
|
||||
|
||||
/**
|
||||
An implementation of the [UDim2](https://create.roblox.com/docs/reference/engine/datatypes/UDim2) Roblox datatype.
|
||||
|
||||
This implements all documented properties, methods & constructors of the UDim2 class as of March 2023.
|
||||
This implements all documented properties, methods & constructors of the `UDim2` class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct UDim2 {
|
|
@ -5,7 +5,9 @@ use glam::{Vec2, Vec3};
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::Vector2 as DomVector2;
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::super::*;
|
||||
|
|
@ -5,7 +5,9 @@ use glam::IVec2;
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::Vector2int16 as DomVector2int16;
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::super::*;
|
||||
|
|
@ -5,10 +5,9 @@ use glam::Vec3;
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::Vector3 as DomVector3;
|
||||
|
||||
use crate::{
|
||||
lune::util::TableBuilder,
|
||||
roblox::{datatypes::util::round_float_decimal, exports::LuaExportsTable},
|
||||
};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::{datatypes::util::round_float_decimal, exports::LuaExportsTable};
|
||||
|
||||
use super::{super::*, EnumItem};
|
||||
|
||||
|
@ -37,8 +36,7 @@ impl LuaExportsTable<'_> for Vector3 {
|
|||
"Z" => Vector3(Vec3::Z),
|
||||
name => {
|
||||
return Err(LuaError::RuntimeError(format!(
|
||||
"Axis '{}' is not known",
|
||||
name
|
||||
"Axis '{name}' is not known",
|
||||
)))
|
||||
}
|
||||
})
|
||||
|
@ -61,8 +59,7 @@ impl LuaExportsTable<'_> for Vector3 {
|
|||
"Back" => Vector3(Vec3::Z),
|
||||
name => {
|
||||
return Err(LuaError::RuntimeError(format!(
|
||||
"NormalId '{}' is not known",
|
||||
name
|
||||
"NormalId '{name}' is not known",
|
||||
)))
|
||||
}
|
||||
})
|
|
@ -5,7 +5,9 @@ use glam::IVec3;
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::Vector3int16 as DomVector3int16;
|
||||
|
||||
use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::exports::LuaExportsTable;
|
||||
|
||||
use super::super::*;
|
||||
|
|
@ -2,7 +2,7 @@ use std::path::Path;
|
|||
|
||||
use rbx_dom_weak::WeakDom;
|
||||
|
||||
use crate::roblox::shared::instance::class_is_a_service;
|
||||
use crate::shared::instance::class_is_a_service;
|
||||
|
||||
/**
|
||||
A document kind specifier.
|
||||
|
@ -58,6 +58,7 @@ impl DocumentKind {
|
|||
|
||||
Returns `None` if the given dom is empty and as such can not have its kind inferred.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn from_weak_dom(dom: &WeakDom) -> Option<Self> {
|
||||
let mut has_top_level_child = false;
|
||||
let mut has_top_level_service = false;
|
|
@ -15,7 +15,7 @@ pub use kind::*;
|
|||
|
||||
use postprocessing::*;
|
||||
|
||||
use crate::roblox::instance::{data_model, Instance};
|
||||
use crate::instance::{data_model, Instance};
|
||||
|
||||
pub type DocumentResult<T> = Result<T, DocumentError>;
|
||||
|
||||
|
@ -78,6 +78,7 @@ impl Document {
|
|||
| Model | Binary | `rbxm` |
|
||||
| Model | Xml | `rbxmx` |
|
||||
*/
|
||||
#[must_use]
|
||||
#[rustfmt::skip]
|
||||
pub fn canonical_extension(kind: DocumentKind, format: DocumentFormat) -> &'static str {
|
||||
match (kind, format) {
|
||||
|
@ -113,6 +114,10 @@ impl Document {
|
|||
Note that detection of model vs place file is heavily dependent on the structure
|
||||
of the file, and a model file with services in it will detect as a place file, so
|
||||
if possible using [`Document::from_bytes`] with an explicit kind should be preferred.
|
||||
|
||||
# Errors
|
||||
|
||||
Errors if the given bytes are not a valid roblox file.
|
||||
*/
|
||||
pub fn from_bytes_auto(bytes: impl AsRef<[u8]>) -> DocumentResult<Self> {
|
||||
let (format, dom) = Self::from_bytes_inner(bytes)?;
|
||||
|
@ -125,6 +130,10 @@ impl Document {
|
|||
|
||||
This will automatically handle and detect if the document
|
||||
should be decoded using a roblox binary or roblox xml format.
|
||||
|
||||
# Errors
|
||||
|
||||
Errors if the given bytes are not a valid roblox file or not of the given kind.
|
||||
*/
|
||||
pub fn from_bytes(bytes: impl AsRef<[u8]>, kind: DocumentKind) -> DocumentResult<Self> {
|
||||
let (format, dom) = Self::from_bytes_inner(bytes)?;
|
||||
|
@ -138,6 +147,10 @@ impl Document {
|
|||
This will use the same format that the document was created
|
||||
with, meaning if the document is a binary document the output
|
||||
will be binary, and vice versa for xml and other future formats.
|
||||
|
||||
# Errors
|
||||
|
||||
Errors if the document can not be encoded.
|
||||
*/
|
||||
pub fn to_bytes(&self) -> DocumentResult<Vec<u8>> {
|
||||
self.to_bytes_with_format(self.format)
|
||||
|
@ -146,6 +159,10 @@ impl Document {
|
|||
/**
|
||||
Encodes the document as a vector of bytes, to
|
||||
be written to a file or sent over the network.
|
||||
|
||||
# Errors
|
||||
|
||||
Errors if the document can not be encoded.
|
||||
*/
|
||||
pub fn to_bytes_with_format(&self, format: DocumentFormat) -> DocumentResult<Vec<u8>> {
|
||||
let mut bytes = Vec::new();
|
||||
|
@ -172,6 +189,7 @@ impl Document {
|
|||
/**
|
||||
Gets the kind this document was created with.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn kind(&self) -> DocumentKind {
|
||||
self.kind
|
||||
}
|
||||
|
@ -179,6 +197,7 @@ impl Document {
|
|||
/**
|
||||
Gets the format this document was created with.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn format(&self) -> DocumentFormat {
|
||||
self.format
|
||||
}
|
||||
|
@ -186,14 +205,17 @@ impl Document {
|
|||
/**
|
||||
Gets the file extension for this document.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn extension(&self) -> &'static str {
|
||||
Self::canonical_extension(self.kind, self.format)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a DataModel instance out of this place document.
|
||||
Creates a `DataModel` instance out of this place document.
|
||||
|
||||
Will error if the document is not a place.
|
||||
# Errors
|
||||
|
||||
Errors if the document is not a place.
|
||||
*/
|
||||
pub fn into_data_model_instance(mut self) -> DocumentResult<Instance> {
|
||||
if self.kind != DocumentKind::Place {
|
||||
|
@ -219,7 +241,9 @@ impl Document {
|
|||
/**
|
||||
Creates an array of instances out of this model document.
|
||||
|
||||
Will error if the document is not a model.
|
||||
# Errors
|
||||
|
||||
Errors if the document is not a model.
|
||||
*/
|
||||
pub fn into_instance_array(mut self) -> DocumentResult<Vec<Instance>> {
|
||||
if self.kind != DocumentKind::Model {
|
||||
|
@ -237,9 +261,11 @@ impl Document {
|
|||
}
|
||||
|
||||
/**
|
||||
Creates a place document out of a DataModel instance.
|
||||
Creates a place document out of a `DataModel` instance.
|
||||
|
||||
Will error if the instance is not a DataModel.
|
||||
# Errors
|
||||
|
||||
Errors if the instance is not a `DataModel`.
|
||||
*/
|
||||
pub fn from_data_model_instance(i: Instance) -> DocumentResult<Self> {
|
||||
if i.get_class_name() != data_model::CLASS_NAME {
|
||||
|
@ -266,7 +292,9 @@ impl Document {
|
|||
/**
|
||||
Creates a model document out of an array of instances.
|
||||
|
||||
Will error if any of the instances is a DataModel.
|
||||
# Errors
|
||||
|
||||
Errors if any of the instances is a `DataModel`.
|
||||
*/
|
||||
pub fn from_instance_array(v: Vec<Instance>) -> DocumentResult<Self> {
|
||||
for i in &v {
|
|
@ -3,7 +3,7 @@ use rbx_dom_weak::{
|
|||
Instance as DomInstance, WeakDom,
|
||||
};
|
||||
|
||||
use crate::roblox::shared::instance::class_is_a;
|
||||
use crate::shared::instance::class_is_a;
|
||||
|
||||
pub fn postprocess_dom_for_place(_dom: &mut WeakDom) {
|
||||
// Nothing here yet
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(clippy::items_after_statements)]
|
||||
|
||||
use mlua::prelude::*;
|
||||
|
||||
use rbx_dom_weak::{
|
||||
|
@ -5,7 +7,7 @@ use rbx_dom_weak::{
|
|||
Instance as DomInstance,
|
||||
};
|
||||
|
||||
use crate::roblox::{
|
||||
use crate::{
|
||||
datatypes::{
|
||||
attributes::{ensure_valid_attribute_name, ensure_valid_attribute_value},
|
||||
conversion::{DomValueToLua, LuaToDomValue},
|
||||
|
@ -17,6 +19,7 @@ use crate::roblox::{
|
|||
|
||||
use super::{data_model, registry::InstanceRegistry, Instance};
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub fn add_methods<'lua, M: LuaUserDataMethods<'lua, Instance>>(m: &mut M) {
|
||||
m.add_meta_method(LuaMetaMethod::ToString, |lua, this, ()| {
|
||||
ensure_not_destroyed(this)?;
|
||||
|
@ -142,7 +145,7 @@ pub fn add_methods<'lua, M: LuaUserDataMethods<'lua, Instance>>(m: &mut M) {
|
|||
ensure_not_destroyed(this)?;
|
||||
let attributes = this.get_attributes();
|
||||
let tab = lua.create_table_with_capacity(0, attributes.len())?;
|
||||
for (key, value) in attributes.into_iter() {
|
||||
for (key, value) in attributes {
|
||||
tab.set(key, LuaValue::dom_value_to_lua(lua, &value)?)?;
|
||||
}
|
||||
Ok(tab)
|
||||
|
@ -227,8 +230,7 @@ fn instance_property_get<'lua>(
|
|||
if let DomValue::Enum(enum_value) = prop {
|
||||
let enum_name = info.enum_name.ok_or_else(|| {
|
||||
LuaError::RuntimeError(format!(
|
||||
"Failed to get property '{}' - encountered unknown enum",
|
||||
prop_name
|
||||
"Failed to get property '{prop_name}' - encountered unknown enum",
|
||||
))
|
||||
})?;
|
||||
EnumItem::from_enum_name_and_value(&enum_name, enum_value.to_u32())
|
||||
|
@ -246,8 +248,7 @@ fn instance_property_get<'lua>(
|
|||
EnumItem::from_enum_name_and_value(&enum_name, enum_value)
|
||||
.ok_or_else(|| {
|
||||
LuaError::RuntimeError(format!(
|
||||
"Failed to get property '{}' - Enum.{} does not contain numeric value {}",
|
||||
prop_name, enum_name, enum_value
|
||||
"Failed to get property '{prop_name}' - Enum.{enum_name} does not contain numeric value {enum_value}",
|
||||
))
|
||||
})?
|
||||
.into_lua(lua)
|
||||
|
@ -258,14 +259,12 @@ fn instance_property_get<'lua>(
|
|||
Ok(LuaValue::Nil)
|
||||
} else {
|
||||
Err(LuaError::RuntimeError(format!(
|
||||
"Failed to get property '{}' - missing default value",
|
||||
prop_name
|
||||
"Failed to get property '{prop_name}' - missing default value",
|
||||
)))
|
||||
}
|
||||
} else {
|
||||
Err(LuaError::RuntimeError(format!(
|
||||
"Failed to get property '{}' - malformed property info",
|
||||
prop_name
|
||||
"Failed to get property '{prop_name}' - malformed property info",
|
||||
)))
|
||||
}
|
||||
} else if let Some(inst) = this.find_child(|inst| inst.name == prop_name) {
|
||||
|
@ -276,8 +275,7 @@ fn instance_property_get<'lua>(
|
|||
Ok(LuaValue::Function(method))
|
||||
} else {
|
||||
Err(LuaError::RuntimeError(format!(
|
||||
"{} is not a valid member of {}",
|
||||
prop_name, this
|
||||
"{prop_name} is not a valid member of {this}",
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
@ -347,16 +345,14 @@ fn instance_property_set<'lua>(
|
|||
}
|
||||
} else {
|
||||
Err(LuaError::RuntimeError(format!(
|
||||
"Failed to set property '{}' - malformed property info",
|
||||
prop_name
|
||||
"Failed to set property '{prop_name}' - malformed property info",
|
||||
)))
|
||||
}
|
||||
} else if let Some(setter) = InstanceRegistry::find_property_setter(lua, this, &prop_name) {
|
||||
setter.call((this.clone(), prop_value))
|
||||
} else {
|
||||
Err(LuaError::RuntimeError(format!(
|
||||
"{} is not a valid member of {}",
|
||||
prop_name, this
|
||||
"{prop_name} is not a valid member of {this}",
|
||||
)))
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
use mlua::prelude::*;
|
||||
|
||||
use crate::roblox::shared::{
|
||||
use crate::shared::{
|
||||
classes::{
|
||||
add_class_restricted_getter, add_class_restricted_method,
|
||||
get_or_create_property_ref_instance,
|
||||
|
@ -33,7 +33,7 @@ fn data_model_get_workspace(_: &Lua, this: &Instance) -> LuaResult<Instance> {
|
|||
}
|
||||
|
||||
/**
|
||||
Gets or creates a service for this DataModel.
|
||||
Gets or creates a service for this `DataModel`.
|
||||
|
||||
### See Also
|
||||
* [`GetService`](https://create.roblox.com/docs/reference/engine/classes/ServiceProvider#GetService)
|
||||
|
@ -42,8 +42,7 @@ fn data_model_get_workspace(_: &Lua, this: &Instance) -> LuaResult<Instance> {
|
|||
fn data_model_get_service(_: &Lua, this: &Instance, service_name: String) -> LuaResult<Instance> {
|
||||
if matches!(class_is_a_service(&service_name), None | Some(false)) {
|
||||
Err(LuaError::RuntimeError(format!(
|
||||
"'{}' is not a valid service name",
|
||||
service_name
|
||||
"'{service_name}' is not a valid service name",
|
||||
)))
|
||||
} else if let Some(service) = this.find_child(|child| child.class == service_name) {
|
||||
Ok(service)
|
||||
|
@ -55,7 +54,7 @@ fn data_model_get_service(_: &Lua, this: &Instance, service_name: String) -> Lua
|
|||
}
|
||||
|
||||
/**
|
||||
Gets a service for this DataModel, if it exists.
|
||||
Gets a service for this `DataModel`, if it exists.
|
||||
|
||||
### See Also
|
||||
* [`FindService`](https://create.roblox.com/docs/reference/engine/classes/ServiceProvider#FindService)
|
||||
|
@ -68,8 +67,7 @@ fn data_model_find_service(
|
|||
) -> LuaResult<Option<Instance>> {
|
||||
if matches!(class_is_a_service(&service_name), None | Some(false)) {
|
||||
Err(LuaError::RuntimeError(format!(
|
||||
"'{}' is not a valid service name",
|
||||
service_name
|
||||
"'{service_name}' is not a valid service name",
|
||||
)))
|
||||
} else if let Some(service) = this.find_child(|child| child.class == service_name) {
|
||||
Ok(Some(service))
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(clippy::missing_panics_doc)]
|
||||
|
||||
use std::{
|
||||
collections::{BTreeMap, VecDeque},
|
||||
fmt,
|
||||
|
@ -12,10 +14,11 @@ use rbx_dom_weak::{
|
|||
Instance as DomInstance, InstanceBuilder as DomInstanceBuilder, WeakDom,
|
||||
};
|
||||
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use crate::{
|
||||
lune::util::TableBuilder,
|
||||
roblox::exports::LuaExportsTable,
|
||||
roblox::shared::instance::{class_exists, class_is_a},
|
||||
exports::LuaExportsTable,
|
||||
shared::instance::{class_exists, class_is_a},
|
||||
};
|
||||
|
||||
pub(crate) mod base;
|
||||
|
@ -54,9 +57,10 @@ impl Instance {
|
|||
.get_by_ref(dom_ref)
|
||||
.expect("Failed to find instance in document");
|
||||
|
||||
if instance.referent() == dom.root_ref() {
|
||||
panic!("Instances can not be created from dom roots")
|
||||
}
|
||||
assert!(
|
||||
!(instance.referent() == dom.root_ref()),
|
||||
"Instances can not be created from dom roots"
|
||||
);
|
||||
|
||||
Self {
|
||||
dom_ref,
|
||||
|
@ -76,9 +80,10 @@ impl Instance {
|
|||
let dom = INTERNAL_DOM.lock().expect("Failed to lock document");
|
||||
|
||||
if let Some(instance) = dom.get_by_ref(dom_ref) {
|
||||
if instance.referent() == dom.root_ref() {
|
||||
panic!("Instances can not be created from dom roots")
|
||||
}
|
||||
assert!(
|
||||
!(instance.referent() == dom.root_ref()),
|
||||
"Instances can not be created from dom roots"
|
||||
);
|
||||
|
||||
Some(Self {
|
||||
dom_ref,
|
||||
|
@ -154,7 +159,7 @@ impl Instance {
|
|||
|
||||
let cloned = dom.clone_multiple_into_external(referents, external_dom);
|
||||
|
||||
for referent in cloned.iter() {
|
||||
for referent in &cloned {
|
||||
external_dom.transfer_within(*referent, external_dom.root_ref());
|
||||
}
|
||||
|
||||
|
@ -171,7 +176,8 @@ impl Instance {
|
|||
* [`Clone`](https://create.roblox.com/docs/reference/engine/classes/Instance#Clone)
|
||||
on the Roblox Developer Hub
|
||||
*/
|
||||
pub fn clone_instance(&self) -> Instance {
|
||||
#[must_use]
|
||||
pub fn clone_instance(&self) -> Self {
|
||||
let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document");
|
||||
let new_ref = dom.clone_within(self.dom_ref);
|
||||
drop(dom); // Self::new needs mutex handle, drop it first
|
||||
|
@ -254,6 +260,7 @@ impl Instance {
|
|||
* [`ClassName`](https://create.roblox.com/docs/reference/engine/classes/Instance#ClassName)
|
||||
on the Roblox Developer Hub
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn get_class_name(&self) -> &str {
|
||||
self.class_name.as_str()
|
||||
}
|
||||
|
@ -286,7 +293,7 @@ impl Instance {
|
|||
|
||||
dom.get_by_ref_mut(self.dom_ref)
|
||||
.expect("Failed to find instance in document")
|
||||
.name = name.into()
|
||||
.name = name.into();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -326,9 +333,7 @@ impl Instance {
|
|||
pub fn set_parent(&self, parent: Option<Instance>) {
|
||||
let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document");
|
||||
|
||||
let parent_ref = parent
|
||||
.map(|parent| parent.dom_ref)
|
||||
.unwrap_or_else(|| dom.root_ref());
|
||||
let parent_ref = parent.map_or_else(|| dom.root_ref(), |parent| parent.dom_ref);
|
||||
|
||||
dom.transfer_within(self.dom_ref, parent_ref);
|
||||
}
|
||||
|
@ -663,9 +668,8 @@ impl Instance {
|
|||
if predicate(ancestor) {
|
||||
drop(dom); // Self::new needs mutex handle, drop it first
|
||||
return Some(Self::new(ancestor_ref));
|
||||
} else {
|
||||
ancestor_ref = ancestor.parent();
|
||||
}
|
||||
ancestor_ref = ancestor.parent();
|
||||
}
|
||||
|
||||
None
|
||||
|
@ -699,9 +703,8 @@ impl Instance {
|
|||
let queue_ref = queue_item.referent();
|
||||
drop(dom); // Self::new needs mutex handle, drop it first
|
||||
return Some(Self::new(queue_ref));
|
||||
} else {
|
||||
queue.extend(queue_item.children())
|
||||
}
|
||||
queue.extend(queue_item.children());
|
||||
}
|
||||
|
||||
None
|
||||
|
@ -717,8 +720,7 @@ impl LuaExportsTable<'_> for Instance {
|
|||
Instance::new_orphaned(class_name).into_lua(lua)
|
||||
} else {
|
||||
Err(LuaError::RuntimeError(format!(
|
||||
"Failed to create Instance - '{}' is not a valid class name",
|
||||
class_name
|
||||
"Failed to create Instance - '{class_name}' is not a valid class name",
|
||||
)))
|
||||
}
|
||||
};
|
||||
|
@ -756,7 +758,7 @@ impl LuaUserData for Instance {
|
|||
|
||||
impl Hash for Instance {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.dom_ref.hash(state)
|
||||
self.dom_ref.hash(state);
|
||||
}
|
||||
}
|
||||
|
|
@ -51,6 +51,13 @@ impl InstanceRegistry {
|
|||
.expect("Missing InstanceRegistry in app data")
|
||||
}
|
||||
|
||||
/**
|
||||
Inserts a method into the instance registry.
|
||||
|
||||
# Errors
|
||||
|
||||
- If the method already exists in the registry.
|
||||
*/
|
||||
pub fn insert_method<'lua>(
|
||||
lua: &'lua Lua,
|
||||
class_name: &str,
|
||||
|
@ -80,6 +87,13 @@ impl InstanceRegistry {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/**
|
||||
Inserts a property getter into the instance registry.
|
||||
|
||||
# Errors
|
||||
|
||||
- If the property already exists in the registry.
|
||||
*/
|
||||
pub fn insert_property_getter<'lua>(
|
||||
lua: &'lua Lua,
|
||||
class_name: &str,
|
||||
|
@ -109,6 +123,13 @@ impl InstanceRegistry {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/**
|
||||
Inserts a property setter into the instance registry.
|
||||
|
||||
# Errors
|
||||
|
||||
- If the property already exists in the registry.
|
||||
*/
|
||||
pub fn insert_property_setter<'lua>(
|
||||
lua: &'lua Lua,
|
||||
class_name: &str,
|
||||
|
@ -138,6 +159,12 @@ impl InstanceRegistry {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/**
|
||||
Finds a method in the instance registry.
|
||||
|
||||
Returns `None` if the method is not found.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn find_method<'lua>(
|
||||
lua: &'lua Lua,
|
||||
instance: &Instance,
|
||||
|
@ -159,6 +186,12 @@ impl InstanceRegistry {
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
Finds a property getter in the instance registry.
|
||||
|
||||
Returns `None` if the property getter is not found.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn find_property_getter<'lua>(
|
||||
lua: &'lua Lua,
|
||||
instance: &Instance,
|
||||
|
@ -180,6 +213,12 @@ impl InstanceRegistry {
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
Finds a property setter in the instance registry.
|
||||
|
||||
Returns `None` if the property setter is not found.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn find_property_setter<'lua>(
|
||||
lua: &'lua Lua,
|
||||
instance: &Instance,
|
||||
|
@ -202,6 +241,16 @@ impl InstanceRegistry {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Gets the class name chain for a given class name.
|
||||
|
||||
The chain starts with the given class name and ends with the root class.
|
||||
|
||||
# Panics
|
||||
|
||||
Panics if the class name is not valid.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn class_name_chain(class_name: &str) -> Vec<&str> {
|
||||
let db = rbx_reflection_database::get();
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::{MaterialColors, TerrainMaterials, Variant};
|
||||
|
||||
use crate::roblox::{
|
||||
use crate::{
|
||||
datatypes::types::{Color3, EnumItem},
|
||||
shared::classes::{add_class_restricted_method, add_class_restricted_method_mut},
|
||||
};
|
||||
|
@ -23,7 +23,7 @@ pub fn add_methods<'lua, M: LuaUserDataMethods<'lua, Instance>>(methods: &mut M)
|
|||
CLASS_NAME,
|
||||
"SetMaterialColor",
|
||||
terrain_set_material_color,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
fn get_or_create_material_colors(instance: &Instance) -> MaterialColors {
|
|
@ -1,8 +1,6 @@
|
|||
use mlua::prelude::*;
|
||||
|
||||
use crate::roblox::shared::classes::{
|
||||
add_class_restricted_getter, get_or_create_property_ref_instance,
|
||||
};
|
||||
use crate::shared::classes::{add_class_restricted_getter, get_or_create_property_ref_instance};
|
||||
|
||||
use super::Instance;
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
#![allow(clippy::cargo_common_metadata)]
|
||||
|
||||
use mlua::prelude::*;
|
||||
|
||||
use crate::lune::util::TableBuilder;
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
pub mod datatypes;
|
||||
pub mod document;
|
||||
|
@ -46,6 +48,16 @@ fn create_all_exports(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaValue)>> {
|
|||
])
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a table containing all the Roblox datatypes, classes, and singletons.
|
||||
|
||||
Note that this is not guaranteed to contain any value unless indexed directly,
|
||||
it may be optimized to use lazy initialization in the future.
|
||||
|
||||
# Errors
|
||||
|
||||
Errors when out of memory or when a value cannot be created.
|
||||
*/
|
||||
pub fn module(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
// FUTURE: We can probably create these lazily as users
|
||||
// index the main exports (this return value) table and
|
|
@ -7,7 +7,7 @@ use rbx_dom_weak::types::Variant as DomVariant;
|
|||
use rbx_reflection::{ClassDescriptor, DataType};
|
||||
|
||||
use super::{property::DatabaseProperty, utils::*};
|
||||
use crate::roblox::datatypes::{
|
||||
use crate::datatypes::{
|
||||
conversion::DomValueToLua, types::EnumItem, userdata_impl_eq, userdata_impl_to_string,
|
||||
};
|
||||
|
||||
|
@ -28,6 +28,7 @@ impl DatabaseClass {
|
|||
/**
|
||||
Get the name of this class.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn get_name(&self) -> String {
|
||||
self.0.name.to_string()
|
||||
}
|
||||
|
@ -37,6 +38,7 @@ impl DatabaseClass {
|
|||
|
||||
May be `None` if no parent class exists.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn get_superclass(&self) -> Option<String> {
|
||||
let sup = self.0.superclass.as_ref()?;
|
||||
Some(sup.to_string())
|
||||
|
@ -45,6 +47,7 @@ impl DatabaseClass {
|
|||
/**
|
||||
Get all known properties for this class.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn get_properties(&self) -> HashMap<String, DatabaseProperty> {
|
||||
self.0
|
||||
.properties
|
||||
|
@ -56,6 +59,7 @@ impl DatabaseClass {
|
|||
/**
|
||||
Get all default values for properties of this class.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn get_defaults(&self) -> HashMap<String, DomVariant> {
|
||||
self.0
|
||||
.default_properties
|
||||
|
@ -71,7 +75,12 @@ impl DatabaseClass {
|
|||
to players at runtime, and top-level class categories.
|
||||
*/
|
||||
pub fn get_tags_str(&self) -> Vec<&'static str> {
|
||||
self.0.tags.iter().map(class_tag_to_str).collect::<Vec<_>>()
|
||||
self.0
|
||||
.tags
|
||||
.iter()
|
||||
.copied()
|
||||
.map(class_tag_to_str)
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,14 +144,12 @@ fn make_enum_value(inner: DbClass, name: impl AsRef<str>, value: u32) -> LuaResu
|
|||
let name = name.as_ref();
|
||||
let enum_name = find_enum_name(inner, name).ok_or_else(|| {
|
||||
LuaError::RuntimeError(format!(
|
||||
"Failed to get default property '{}' - No enum descriptor was found",
|
||||
name
|
||||
"Failed to get default property '{name}' - No enum descriptor was found",
|
||||
))
|
||||
})?;
|
||||
EnumItem::from_enum_name_and_value(&enum_name, value).ok_or_else(|| {
|
||||
LuaError::RuntimeError(format!(
|
||||
"Failed to get default property '{}' - Enum.{} does not contain numeric value {}",
|
||||
name, enum_name, value
|
||||
"Failed to get default property '{name}' - Enum.{enum_name} does not contain numeric value {value}",
|
||||
))
|
||||
})
|
||||
}
|
|
@ -4,7 +4,7 @@ use mlua::prelude::*;
|
|||
|
||||
use rbx_reflection::EnumDescriptor;
|
||||
|
||||
use crate::roblox::datatypes::{userdata_impl_eq, userdata_impl_to_string};
|
||||
use crate::datatypes::{userdata_impl_eq, userdata_impl_to_string};
|
||||
|
||||
type DbEnum = &'static EnumDescriptor<'static>;
|
||||
|
||||
|
@ -23,6 +23,7 @@ impl DatabaseEnum {
|
|||
/**
|
||||
Get the name of this enum.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn get_name(&self) -> String {
|
||||
self.0.name.to_string()
|
||||
}
|
||||
|
@ -31,8 +32,9 @@ impl DatabaseEnum {
|
|||
Get all known members of this enum.
|
||||
|
||||
Note that this is a direct map of name -> enum values,
|
||||
and does not actually use the EnumItem datatype itself.
|
||||
and does not actually use the `EnumItem` datatype itself.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn get_items(&self) -> HashMap<String, u32> {
|
||||
self.0
|
||||
.items
|
|
@ -4,7 +4,7 @@ use mlua::prelude::*;
|
|||
|
||||
use rbx_reflection::ReflectionDatabase;
|
||||
|
||||
use crate::roblox::datatypes::userdata_impl_eq;
|
||||
use crate::datatypes::userdata_impl_eq;
|
||||
|
||||
mod class;
|
||||
mod enums;
|
||||
|
@ -30,6 +30,7 @@ impl Database {
|
|||
/**
|
||||
Creates a new database struct, referencing the bundled reflection database.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
@ -40,6 +41,7 @@ impl Database {
|
|||
This will follow the format `x.y.z.w`, which most
|
||||
commonly looks something like `0.567.0.123456789`.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn get_version(&self) -> String {
|
||||
let [x, y, z, w] = self.0.version;
|
||||
format!("{x}.{y}.{z}.{w}")
|
||||
|
@ -48,15 +50,17 @@ impl Database {
|
|||
/**
|
||||
Retrieves a list of all currently known enum names.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn get_enum_names(&self) -> Vec<String> {
|
||||
self.0.enums.keys().map(|e| e.to_string()).collect()
|
||||
self.0.enums.keys().map(ToString::to_string).collect()
|
||||
}
|
||||
|
||||
/**
|
||||
Retrieves a list of all currently known class names.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn get_class_names(&self) -> Vec<String> {
|
||||
self.0.classes.keys().map(|e| e.to_string()).collect()
|
||||
self.0.classes.keys().map(ToString::to_string).collect()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,14 +112,17 @@ impl Database {
|
|||
|
||||
impl LuaUserData for Database {
|
||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("Version", |_, this| Ok(this.get_version()))
|
||||
fields.add_field_method_get("Version", |_, this| Ok(this.get_version()));
|
||||
}
|
||||
|
||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq);
|
||||
methods.add_meta_method(LuaMetaMethod::ToString, userdata_impl_to_string);
|
||||
methods.add_method("GetEnumNames", |_, this, _: ()| Ok(this.get_enum_names()));
|
||||
methods.add_method("GetClassNames", |_, this, _: ()| Ok(this.get_class_names()));
|
||||
methods.add_method("GetEnumNames", |_, this, (): ()| Ok(this.get_enum_names()));
|
||||
methods.add_method(
|
||||
"GetClassNames",
|
||||
|_, this, (): ()| Ok(this.get_class_names()),
|
||||
);
|
||||
methods.add_method("GetEnum", |_, this, name: String| Ok(this.get_enum(name)));
|
||||
methods.add_method("GetClass", |_, this, name: String| Ok(this.get_class(name)));
|
||||
methods.add_method("FindEnum", |_, this, name: String| Ok(this.find_enum(name)));
|
|
@ -5,7 +5,7 @@ use mlua::prelude::*;
|
|||
use rbx_reflection::{ClassDescriptor, PropertyDescriptor};
|
||||
|
||||
use super::utils::*;
|
||||
use crate::roblox::datatypes::{userdata_impl_eq, userdata_impl_to_string};
|
||||
use crate::datatypes::{userdata_impl_eq, userdata_impl_to_string};
|
||||
|
||||
type DbClass = &'static ClassDescriptor<'static>;
|
||||
type DbProp = &'static PropertyDescriptor<'static>;
|
||||
|
@ -25,6 +25,7 @@ impl DatabaseProperty {
|
|||
/**
|
||||
Get the name of this property.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn get_name(&self) -> String {
|
||||
self.1.name.to_string()
|
||||
}
|
||||
|
@ -36,6 +37,7 @@ impl DatabaseProperty {
|
|||
|
||||
For enums this will be a string formatted as `Enum.EnumName`.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn get_datatype_name(&self) -> String {
|
||||
data_type_to_str(self.1.data_type.clone())
|
||||
}
|
||||
|
@ -45,8 +47,9 @@ impl DatabaseProperty {
|
|||
|
||||
All properties are writable and readable in Lune even if scriptability is not.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn get_scriptability_str(&self) -> &'static str {
|
||||
scriptability_to_str(&self.1.scriptability)
|
||||
scriptability_to_str(self.1.scriptability)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,6 +62,7 @@ impl DatabaseProperty {
|
|||
self.1
|
||||
.tags
|
||||
.iter()
|
||||
.copied()
|
||||
.map(property_tag_to_str)
|
||||
.collect::<Vec<_>>()
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
use rbx_reflection::{ClassTag, DataType, PropertyTag, Scriptability};
|
||||
|
||||
use crate::roblox::datatypes::extension::DomValueExt;
|
||||
use crate::datatypes::extension::DomValueExt;
|
||||
|
||||
pub fn data_type_to_str(data_type: DataType) -> String {
|
||||
match data_type {
|
||||
|
@ -17,7 +17,7 @@ pub fn data_type_to_str(data_type: DataType) -> String {
|
|||
NOTE: Remember to add any new strings here to typedefs too!
|
||||
*/
|
||||
|
||||
pub fn scriptability_to_str(scriptability: &Scriptability) -> &'static str {
|
||||
pub fn scriptability_to_str(scriptability: Scriptability) -> &'static str {
|
||||
match scriptability {
|
||||
Scriptability::None => "None",
|
||||
Scriptability::Custom => "Custom",
|
||||
|
@ -28,7 +28,7 @@ pub fn scriptability_to_str(scriptability: &Scriptability) -> &'static str {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn property_tag_to_str(tag: &PropertyTag) -> &'static str {
|
||||
pub fn property_tag_to_str(tag: PropertyTag) -> &'static str {
|
||||
match tag {
|
||||
PropertyTag::Deprecated => "Deprecated",
|
||||
PropertyTag::Hidden => "Hidden",
|
||||
|
@ -41,7 +41,7 @@ pub fn property_tag_to_str(tag: &PropertyTag) -> &'static str {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn class_tag_to_str(tag: &ClassTag) -> &'static str {
|
||||
pub fn class_tag_to_str(tag: ClassTag) -> &'static str {
|
||||
match tag {
|
||||
ClassTag::Deprecated => "Deprecated",
|
||||
ClassTag::NotBrowsable => "NotBrowsable",
|
|
@ -2,7 +2,7 @@ use mlua::prelude::*;
|
|||
|
||||
use rbx_dom_weak::types::Variant as DomValue;
|
||||
|
||||
use crate::roblox::instance::Instance;
|
||||
use crate::instance::Instance;
|
||||
|
||||
use super::instance::class_is_a;
|
||||
|
||||
|
@ -20,8 +20,7 @@ pub(crate) fn add_class_restricted_getter<'lua, F: LuaUserDataFields<'lua, Insta
|
|||
field_getter(lua, this)
|
||||
} else {
|
||||
Err(LuaError::RuntimeError(format!(
|
||||
"{} is not a valid member of {}",
|
||||
field_name, class_name
|
||||
"{field_name} is not a valid member of {class_name}",
|
||||
)))
|
||||
}
|
||||
});
|
||||
|
@ -42,8 +41,7 @@ pub(crate) fn add_class_restricted_setter<'lua, F: LuaUserDataFields<'lua, Insta
|
|||
field_getter(lua, this, value)
|
||||
} else {
|
||||
Err(LuaError::RuntimeError(format!(
|
||||
"{} is not a valid member of {}",
|
||||
field_name, class_name
|
||||
"{field_name} is not a valid member of {class_name}",
|
||||
)))
|
||||
}
|
||||
});
|
||||
|
@ -64,8 +62,7 @@ pub(crate) fn add_class_restricted_method<'lua, M: LuaUserDataMethods<'lua, Inst
|
|||
method(lua, this, args)
|
||||
} else {
|
||||
Err(LuaError::RuntimeError(format!(
|
||||
"{} is not a valid member of {}",
|
||||
method_name, class_name
|
||||
"{method_name} is not a valid member of {class_name}",
|
||||
)))
|
||||
}
|
||||
});
|
||||
|
@ -92,8 +89,7 @@ pub(crate) fn add_class_restricted_method_mut<
|
|||
method(lua, this, args)
|
||||
} else {
|
||||
Err(LuaError::RuntimeError(format!(
|
||||
"{} is not a valid member of {}",
|
||||
method_name, class_name
|
||||
"{method_name} is not a valid member of {class_name}",
|
||||
)))
|
||||
}
|
||||
});
|
||||
|
@ -102,7 +98,7 @@ pub(crate) fn add_class_restricted_method_mut<
|
|||
/**
|
||||
Gets or creates the instance child with the given reference prop name and class name.
|
||||
|
||||
Note that the class name here must be an exact match, it is not checked using IsA.
|
||||
Note that the class name here must be an exact match, it is not checked using `IsA`.
|
||||
|
||||
The instance may be in one of several states but this function will guarantee that the
|
||||
property reference is correct and that the instance exists after it has been called:
|
|
@ -60,12 +60,12 @@ pub(crate) fn find_property_info(
|
|||
value_type: Some(*value_type),
|
||||
..Default::default()
|
||||
},
|
||||
_ => Default::default(),
|
||||
_ => PropertyInfo::default(),
|
||||
});
|
||||
break;
|
||||
} else if let Some(sup) = &class.superclass {
|
||||
// No property found, we should look at the superclass
|
||||
class_name = Cow::Borrowed(sup)
|
||||
class_name = Cow::Borrowed(sup);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ pub(crate) fn find_property_info(
|
|||
break;
|
||||
} else if let Some(sup) = &class.superclass {
|
||||
// No default value found, we should look at the superclass
|
||||
class_name = Cow::Borrowed(sup)
|
||||
class_name = Cow::Borrowed(sup);
|
||||
} else {
|
||||
break;
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(clippy::missing_errors_doc)]
|
||||
|
||||
use std::{any::type_name, cell::RefCell, fmt, ops};
|
||||
|
||||
use mlua::prelude::*;
|
||||
|
@ -5,21 +7,29 @@ use mlua::prelude::*;
|
|||
// Utility functions
|
||||
|
||||
type ListWriter = dyn Fn(&mut fmt::Formatter<'_>, bool, &str) -> fmt::Result;
|
||||
|
||||
#[must_use]
|
||||
pub fn make_list_writer() -> Box<ListWriter> {
|
||||
let first = RefCell::new(true);
|
||||
Box::new(move |f, flag, literal| {
|
||||
if flag {
|
||||
if first.take() {
|
||||
write!(f, "{}", literal)?;
|
||||
write!(f, "{literal}")?;
|
||||
} else {
|
||||
write!(f, ", {}", literal)?;
|
||||
write!(f, ", {literal}")?;
|
||||
}
|
||||
}
|
||||
Ok::<_, fmt::Error>(())
|
||||
})
|
||||
}
|
||||
|
||||
// Userdata metamethod implementations
|
||||
/**
|
||||
Userdata metamethod implementations
|
||||
|
||||
Note that many of these return [`LuaResult`] even though they don't
|
||||
return any errors - this is for consistency reasons and to make it
|
||||
easier to add these blanket implementations to [`LuaUserData`] impls.
|
||||
*/
|
||||
|
||||
pub fn userdata_impl_to_string<D>(_: &Lua, datatype: &D, _: ()) -> LuaResult<String>
|
||||
where
|
20
crates/lune-std-datetime/Cargo.toml
Normal file
20
crates/lune-std-datetime/Cargo.toml
Normal file
|
@ -0,0 +1,20 @@
|
|||
[package]
|
||||
name = "lune-std-datetime"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
mlua = { version = "0.9.7", features = ["luau"] }
|
||||
|
||||
thiserror = "1.0"
|
||||
chrono = "=0.4.34" # NOTE: 0.4.35 does not compile with chrono_lc
|
||||
chrono_lc = "0.1"
|
||||
|
||||
lune-utils = { version = "0.1.0", path = "../lune-utils" }
|
|
@ -6,31 +6,8 @@ use chrono::prelude::*;
|
|||
use chrono::DateTime as ChronoDateTime;
|
||||
use chrono_lc::LocaleDate;
|
||||
|
||||
use crate::lune::util::TableBuilder;
|
||||
|
||||
mod error;
|
||||
mod values;
|
||||
|
||||
use error::*;
|
||||
use values::*;
|
||||
|
||||
pub fn create(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
TableBuilder::new(lua)?
|
||||
.with_function("fromIsoDate", |_, iso_date: String| {
|
||||
Ok(DateTime::from_iso_date(iso_date)?)
|
||||
})?
|
||||
.with_function("fromLocalTime", |_, values| {
|
||||
Ok(DateTime::from_local_time(&values)?)
|
||||
})?
|
||||
.with_function("fromUniversalTime", |_, values| {
|
||||
Ok(DateTime::from_universal_time(&values)?)
|
||||
})?
|
||||
.with_function("fromUnixTimestamp", |_, timestamp| {
|
||||
Ok(DateTime::from_unix_timestamp_float(timestamp)?)
|
||||
})?
|
||||
.with_function("now", |_, ()| Ok(DateTime::now()))?
|
||||
.build_readonly()
|
||||
}
|
||||
use crate::result::{DateTimeError, DateTimeResult};
|
||||
use crate::values::DateTimeValues;
|
||||
|
||||
const DEFAULT_FORMAT: &str = "%Y-%m-%d %H:%M:%S";
|
||||
const DEFAULT_LOCALE: &str = "en";
|
||||
|
@ -49,6 +26,7 @@ impl DateTime {
|
|||
|
||||
See [`chrono::DateTime::now`] for additional details.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn now() -> Self {
|
||||
Self { inner: Utc::now() }
|
||||
}
|
||||
|
@ -66,6 +44,10 @@ impl DateTime {
|
|||
```
|
||||
|
||||
See [`chrono::DateTime::from_timestamp`] for additional details.
|
||||
|
||||
# Errors
|
||||
|
||||
Returns an error if the input value is out of range.
|
||||
*/
|
||||
pub fn from_unix_timestamp_float(unix_timestamp: f64) -> DateTimeResult<Self> {
|
||||
let whole = unix_timestamp.trunc() as i64;
|
||||
|
@ -84,6 +66,10 @@ impl DateTime {
|
|||
|
||||
See [`chrono::NaiveDate::from_ymd_opt`] and [`chrono::NaiveTime::from_hms_milli_opt`]
|
||||
for additional details and cases where this constructor may return an error.
|
||||
|
||||
# Errors
|
||||
|
||||
Returns an error if the date or time values are invalid.
|
||||
*/
|
||||
pub fn from_universal_time(values: &DateTimeValues) -> DateTimeResult<Self> {
|
||||
let date = NaiveDate::from_ymd_opt(values.year, values.month, values.day)
|
||||
|
@ -108,6 +94,10 @@ impl DateTime {
|
|||
|
||||
See [`chrono::NaiveDate::from_ymd_opt`] and [`chrono::NaiveTime::from_hms_milli_opt`]
|
||||
for additional details and cases where this constructor may return an error.
|
||||
|
||||
# Errors
|
||||
|
||||
Returns an error if the date or time values are invalid or ambiguous.
|
||||
*/
|
||||
pub fn from_local_time(values: &DateTimeValues) -> DateTimeResult<Self> {
|
||||
let date = NaiveDate::from_ymd_opt(values.year, values.month, values.day)
|
||||
|
@ -138,6 +128,7 @@ impl DateTime {
|
|||
|
||||
See [`chrono_lc::DateTime::formatl`] for additional details.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn format_string_local(&self, format: Option<&str>, locale: Option<&str>) -> String {
|
||||
self.inner
|
||||
.with_timezone(&Local)
|
||||
|
@ -156,6 +147,7 @@ impl DateTime {
|
|||
|
||||
See [`chrono_lc::DateTime::formatl`] for additional details.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn format_string_universal(&self, format: Option<&str>, locale: Option<&str>) -> String {
|
||||
self.inner
|
||||
.with_timezone(&Utc)
|
||||
|
@ -171,6 +163,10 @@ impl DateTime {
|
|||
`1996-12-19T16:39:57-08:00`, into a new `DateTime` struct.
|
||||
|
||||
See [`chrono::DateTime::parse_from_rfc3339`] for additional details.
|
||||
|
||||
# Errors
|
||||
|
||||
Returns an error if the input string is not a valid RFC 3339 date-time.
|
||||
*/
|
||||
pub fn from_iso_date(iso_date: impl AsRef<str>) -> DateTimeResult<Self> {
|
||||
let inner = ChronoDateTime::parse_from_rfc3339(iso_date.as_ref())?.with_timezone(&Utc);
|
||||
|
@ -181,6 +177,7 @@ impl DateTime {
|
|||
Extracts individual date & time values from this
|
||||
`DateTime`, using the current local time zone.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn to_local_time(self) -> DateTimeValues {
|
||||
DateTimeValues::from(self.inner.with_timezone(&Local))
|
||||
}
|
||||
|
@ -189,6 +186,7 @@ impl DateTime {
|
|||
Extracts individual date & time values from this
|
||||
`DateTime`, using the universal (UTC) time zone.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn to_universal_time(self) -> DateTimeValues {
|
||||
DateTimeValues::from(self.inner.with_timezone(&Utc))
|
||||
}
|
||||
|
@ -198,6 +196,7 @@ impl DateTime {
|
|||
|
||||
See [`chrono::DateTime::to_rfc3339`] for additional details.
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn to_iso_date(self) -> String {
|
||||
self.inner.to_rfc3339()
|
||||
}
|
36
crates/lune-std-datetime/src/lib.rs
Normal file
36
crates/lune-std-datetime/src/lib.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
#![allow(clippy::cargo_common_metadata)]
|
||||
|
||||
use mlua::prelude::*;
|
||||
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
mod date_time;
|
||||
mod result;
|
||||
mod values;
|
||||
|
||||
pub use self::date_time::DateTime;
|
||||
|
||||
/**
|
||||
Creates the `datetime` standard library module.
|
||||
|
||||
# Errors
|
||||
|
||||
Errors when out of memory.
|
||||
*/
|
||||
pub fn module(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
TableBuilder::new(lua)?
|
||||
.with_function("fromIsoDate", |_, iso_date: String| {
|
||||
Ok(DateTime::from_iso_date(iso_date)?)
|
||||
})?
|
||||
.with_function("fromLocalTime", |_, values| {
|
||||
Ok(DateTime::from_local_time(&values)?)
|
||||
})?
|
||||
.with_function("fromUniversalTime", |_, values| {
|
||||
Ok(DateTime::from_universal_time(&values)?)
|
||||
})?
|
||||
.with_function("fromUnixTimestamp", |_, timestamp| {
|
||||
Ok(DateTime::from_unix_timestamp_float(timestamp)?)
|
||||
})?
|
||||
.with_function("now", |_, ()| Ok(DateTime::now()))?
|
||||
.build_readonly()
|
||||
}
|
|
@ -2,9 +2,9 @@ use mlua::prelude::*;
|
|||
|
||||
use chrono::prelude::*;
|
||||
|
||||
use crate::lune::util::TableBuilder;
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use super::error::{DateTimeError, DateTimeResult};
|
||||
use super::result::{DateTimeError, DateTimeResult};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct DateTimeValues {
|
||||
|
@ -61,9 +61,9 @@ where
|
|||
}
|
||||
|
||||
/**
|
||||
Conversion methods between DateTimeValues and plain lua tables
|
||||
Conversion methods between `DateTimeValues` and plain lua tables
|
||||
|
||||
Note that the IntoLua implementation here uses a read-only table,
|
||||
Note that the `IntoLua` implementation here uses a read-only table,
|
||||
since we generally want to convert into lua when we know we have
|
||||
a fixed point in time, and we guarantee that it doesn't change
|
||||
*/
|
||||
|
@ -118,8 +118,8 @@ impl IntoLua<'_> for DateTimeValues {
|
|||
}
|
||||
|
||||
/**
|
||||
Conversion methods between chrono's timezone-aware DateTime to
|
||||
and from our non-timezone-aware DateTimeValues values struct
|
||||
Conversion methods between chrono's timezone-aware `DateTime` to
|
||||
and from our non-timezone-aware `DateTimeValues` values struct
|
||||
*/
|
||||
|
||||
impl<T: TimeZone> From<DateTime<T>> for DateTimeValues {
|
21
crates/lune-std-fs/Cargo.toml
Normal file
21
crates/lune-std-fs/Cargo.toml
Normal file
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
name = "lune-std-fs"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
mlua = { version = "0.9.7", features = ["luau"] }
|
||||
|
||||
bstr = "1.9"
|
||||
|
||||
tokio = { version = "1", default-features = false, features = ["fs"] }
|
||||
|
||||
lune-utils = { version = "0.1.0", path = "../lune-utils" }
|
||||
lune-std-datetime = { version = "0.1.0", path = "../lune-std-datetime" }
|
|
@ -13,7 +13,7 @@ pub struct CopyContents {
|
|||
pub files: Vec<(usize, PathBuf)>,
|
||||
}
|
||||
|
||||
async fn get_contents_at(root: PathBuf, _options: FsWriteOptions) -> LuaResult<CopyContents> {
|
||||
async fn get_contents_at(root: PathBuf, _: FsWriteOptions) -> LuaResult<CopyContents> {
|
||||
let mut dirs = Vec::new();
|
||||
let mut files = Vec::new();
|
||||
|
||||
|
@ -53,11 +53,11 @@ async fn get_contents_at(root: PathBuf, _options: FsWriteOptions) -> LuaResult<C
|
|||
|
||||
// Ensure that all directory and file paths are relative to the root path
|
||||
// SAFETY: Since we only ever push dirs and files relative to the root, unwrap is safe
|
||||
for (_, dir) in dirs.iter_mut() {
|
||||
*dir = dir.strip_prefix(&normalized_root).unwrap().to_path_buf()
|
||||
for (_, dir) in &mut dirs {
|
||||
*dir = dir.strip_prefix(&normalized_root).unwrap().to_path_buf();
|
||||
}
|
||||
for (_, file) in files.iter_mut() {
|
||||
*file = file.strip_prefix(&normalized_root).unwrap().to_path_buf()
|
||||
for (_, file) in &mut files {
|
||||
*file = file.strip_prefix(&normalized_root).unwrap().to_path_buf();
|
||||
}
|
||||
|
||||
// FUTURE: Deduplicate paths such that these directories:
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(clippy::cargo_common_metadata)]
|
||||
|
||||
use std::io::ErrorKind as IoErrorKind;
|
||||
use std::path::{PathBuf, MAIN_SEPARATOR};
|
||||
|
||||
|
@ -5,17 +7,24 @@ use bstr::{BString, ByteSlice};
|
|||
use mlua::prelude::*;
|
||||
use tokio::fs;
|
||||
|
||||
use crate::lune::util::TableBuilder;
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
mod copy;
|
||||
mod metadata;
|
||||
mod options;
|
||||
|
||||
use copy::copy;
|
||||
use metadata::FsMetadata;
|
||||
use options::FsWriteOptions;
|
||||
use self::copy::copy;
|
||||
use self::metadata::FsMetadata;
|
||||
use self::options::FsWriteOptions;
|
||||
|
||||
pub fn create(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
/**
|
||||
Creates the `fs` standard library module.
|
||||
|
||||
# Errors
|
||||
|
||||
Errors when out of memory.
|
||||
*/
|
||||
pub fn module(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
TableBuilder::new(lua)?
|
||||
.with_async_function("readFile", fs_read_file)?
|
||||
.with_async_function("readDir", fs_read_dir)?
|
|
@ -8,7 +8,7 @@ use std::{
|
|||
|
||||
use mlua::prelude::*;
|
||||
|
||||
use crate::lune::builtins::datetime::DateTime;
|
||||
use lune_std_datetime::DateTime;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum FsMetadataKind {
|
16
crates/lune-std-luau/Cargo.toml
Normal file
16
crates/lune-std-luau/Cargo.toml
Normal file
|
@ -0,0 +1,16 @@
|
|||
[package]
|
||||
name = "lune-std-luau"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
mlua = { version = "0.9.7", features = ["luau"] }
|
||||
|
||||
lune-utils = { version = "0.1.0", path = "../lune-utils" }
|
|
@ -1,13 +1,23 @@
|
|||
#![allow(clippy::cargo_common_metadata)]
|
||||
|
||||
use mlua::prelude::*;
|
||||
|
||||
use crate::lune::util::TableBuilder;
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
mod options;
|
||||
use options::{LuauCompileOptions, LuauLoadOptions};
|
||||
|
||||
use self::options::{LuauCompileOptions, LuauLoadOptions};
|
||||
|
||||
const BYTECODE_ERROR_BYTE: u8 = 0;
|
||||
|
||||
pub fn create(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
/**
|
||||
Creates the `luau` standard library module.
|
||||
|
||||
# Errors
|
||||
|
||||
Errors when out of memory.
|
||||
*/
|
||||
pub fn module(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
TableBuilder::new(lua)?
|
||||
.with_function("compile", compile_source)?
|
||||
.with_function("load", load_source)?
|
|
@ -1,8 +1,14 @@
|
|||
#![allow(clippy::struct_field_names)]
|
||||
|
||||
use mlua::prelude::*;
|
||||
use mlua::Compiler as LuaCompiler;
|
||||
|
||||
const DEFAULT_DEBUG_NAME: &str = "luau.load(...)";
|
||||
|
||||
/**
|
||||
Options for compiling Lua source code.
|
||||
*/
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct LuauCompileOptions {
|
||||
pub(crate) optimization_level: u8,
|
||||
pub(crate) coverage_level: u8,
|
||||
|
@ -73,6 +79,10 @@ impl<'lua> FromLua<'lua> for LuauCompileOptions {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Options for loading Lua source code.
|
||||
*/
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LuauLoadOptions<'lua> {
|
||||
pub(crate) debug_name: String,
|
||||
pub(crate) environment: Option<LuaTable<'lua>>,
|
37
crates/lune-std-net/Cargo.toml
Normal file
37
crates/lune-std-net/Cargo.toml
Normal file
|
@ -0,0 +1,37 @@
|
|||
[package]
|
||||
name = "lune-std-net"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
mlua = { version = "0.9.7", features = ["luau"] }
|
||||
mlua-luau-scheduler = "0.0.2"
|
||||
|
||||
bstr = "1.9"
|
||||
futures-util = "0.3"
|
||||
hyper = { version = "1.1", features = ["full"] }
|
||||
hyper-util = { version = "0.1", features = ["full"] }
|
||||
http = "1.0"
|
||||
http-body-util = { version = "0.1" }
|
||||
hyper-tungstenite = { version = "0.13" }
|
||||
reqwest = { version = "0.11", default-features = false, features = [
|
||||
"rustls-tls",
|
||||
] }
|
||||
tokio-tungstenite = { version = "0.21", features = ["rustls-tls-webpki-roots"] }
|
||||
urlencoding = "2.1"
|
||||
|
||||
tokio = { version = "1", default-features = false, features = [
|
||||
"sync",
|
||||
"net",
|
||||
"macros",
|
||||
] }
|
||||
|
||||
lune-utils = { version = "0.1.0", path = "../lune-utils" }
|
||||
lune-std-serde = { version = "0.1.0", path = "../lune-std-serde" }
|
|
@ -4,10 +4,8 @@ use mlua::prelude::*;
|
|||
|
||||
use reqwest::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_ENCODING};
|
||||
|
||||
use crate::lune::{
|
||||
builtins::serde::compress_decompress::{decompress, CompressDecompressFormat},
|
||||
util::TableBuilder,
|
||||
};
|
||||
use lune_std_serde::{decompress, CompressDecompressFormat};
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use super::{config::RequestConfig, util::header_map_to_table};
|
||||
|
||||
|
@ -103,7 +101,7 @@ impl NetClient {
|
|||
.and_then(|(_, value)| value.to_str().ok())
|
||||
.and_then(CompressDecompressFormat::detect_from_header_str);
|
||||
if let Some(format) = decompress_format {
|
||||
res_bytes = decompress(format, res_bytes).await?;
|
||||
res_bytes = decompress(res_bytes, format).await?;
|
||||
res_decompressed = true;
|
||||
}
|
||||
}
|
|
@ -83,7 +83,7 @@ impl FromLua<'_> for RequestConfig {
|
|||
query: HashMap::new(),
|
||||
headers: HashMap::new(),
|
||||
body: None,
|
||||
options: Default::default(),
|
||||
options: RequestConfigOptions::default(),
|
||||
})
|
||||
} else if let LuaValue::Table(tab) = value {
|
||||
// If we got a table we are able to configure the entire request
|
|
@ -1,4 +1,4 @@
|
|||
#![allow(unused_variables)]
|
||||
#![allow(clippy::cargo_common_metadata)]
|
||||
|
||||
use bstr::BString;
|
||||
use mlua::prelude::*;
|
||||
|
@ -10,7 +10,7 @@ mod server;
|
|||
mod util;
|
||||
mod websocket;
|
||||
|
||||
use crate::lune::util::TableBuilder;
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use self::{
|
||||
client::{NetClient, NetClientBuilder},
|
||||
|
@ -20,9 +20,16 @@ use self::{
|
|||
websocket::NetWebSocket,
|
||||
};
|
||||
|
||||
use super::serde::encode_decode::{EncodeDecodeConfig, EncodeDecodeFormat};
|
||||
use lune_std_serde::{decode, encode, EncodeDecodeConfig, EncodeDecodeFormat};
|
||||
|
||||
pub fn create(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
/**
|
||||
Creates the `net` standard library module.
|
||||
|
||||
# Errors
|
||||
|
||||
Errors when out of memory.
|
||||
*/
|
||||
pub fn module(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
NetClientBuilder::new()
|
||||
.headers(&[("User-Agent", create_user_agent_header(lua)?)])?
|
||||
.build()?
|
||||
|
@ -42,12 +49,13 @@ fn net_json_encode<'lua>(
|
|||
lua: &'lua Lua,
|
||||
(val, pretty): (LuaValue<'lua>, Option<bool>),
|
||||
) -> LuaResult<LuaString<'lua>> {
|
||||
EncodeDecodeConfig::from((EncodeDecodeFormat::Json, pretty.unwrap_or_default()))
|
||||
.serialize_to_string(lua, val)
|
||||
let config = EncodeDecodeConfig::from((EncodeDecodeFormat::Json, pretty.unwrap_or_default()));
|
||||
encode(val, lua, config)
|
||||
}
|
||||
|
||||
fn net_json_decode(lua: &Lua, json: BString) -> LuaResult<LuaValue> {
|
||||
EncodeDecodeConfig::from(EncodeDecodeFormat::Json).deserialize_from_string(lua, json)
|
||||
let config = EncodeDecodeConfig::from(EncodeDecodeFormat::Json);
|
||||
decode(json, lua, config)
|
||||
}
|
||||
|
||||
async fn net_request(lua: &Lua, config: RequestConfig) -> LuaResult<LuaTable> {
|
|
@ -10,7 +10,7 @@ use tokio::{net::TcpListener, pin};
|
|||
use mlua::prelude::*;
|
||||
use mlua_luau_scheduler::LuaSpawnExt;
|
||||
|
||||
use crate::lune::util::TableBuilder;
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
use super::config::ServeConfig;
|
||||
|
||||
|
@ -81,7 +81,7 @@ pub async fn serve<'lua>(
|
|||
|
||||
// Wait for either a new connection or a shutdown signal
|
||||
tokio::select! {
|
||||
_ = fut_accept => {}
|
||||
() = fut_accept => {}
|
||||
res = fut_shutdown => {
|
||||
// NOTE: We will only get a RecvError here if the serve handle is dropped,
|
||||
// this means lua has garbage collected it and the user does not want
|
||||
|
@ -97,8 +97,8 @@ pub async fn serve<'lua>(
|
|||
TableBuilder::new(lua)?
|
||||
.with_value("ip", addr.ip().to_string())?
|
||||
.with_value("port", addr.port())?
|
||||
.with_function("stop", move |lua, _: ()| match shutdown_tx.send(true) {
|
||||
Ok(_) => Ok(()),
|
||||
.with_function("stop", move |_, (): ()| match shutdown_tx.send(true) {
|
||||
Ok(()) => Ok(()),
|
||||
Err(_) => Err(LuaError::runtime("Server already stopped")),
|
||||
})?
|
||||
.build_readonly()
|
|
@ -4,7 +4,7 @@ use http::request::Parts;
|
|||
|
||||
use mlua::prelude::*;
|
||||
|
||||
use crate::lune::util::TableBuilder;
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
pub(super) struct LuaRequest {
|
||||
pub(super) _remote_addr: SocketAddr,
|
|
@ -5,7 +5,7 @@ use reqwest::header::HeaderMap;
|
|||
|
||||
use mlua::prelude::*;
|
||||
|
||||
use crate::lune::util::TableBuilder;
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
pub fn create_user_agent_header(lua: &Lua) -> LuaResult<String> {
|
||||
let version_global = lua
|
||||
|
@ -28,7 +28,7 @@ pub fn header_map_to_table(
|
|||
remove_content_headers: bool,
|
||||
) -> LuaResult<LuaTable> {
|
||||
let mut res_headers: HashMap<String, Vec<String>> = HashMap::new();
|
||||
for (name, value) in headers.iter() {
|
||||
for (name, value) in &headers {
|
||||
let name = name.as_str();
|
||||
let value = value.to_str().unwrap().to_owned();
|
||||
if let Some(existing) = res_headers.get_mut(name) {
|
|
@ -23,7 +23,7 @@ use hyper_tungstenite::{
|
|||
WebSocketStream,
|
||||
};
|
||||
|
||||
use crate::lune::util::TableBuilder;
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
// Wrapper implementation for compatibility and changing colon syntax to dot syntax
|
||||
const WEB_SOCKET_IMPL_LUA: &str = r#"
|
||||
|
@ -155,7 +155,7 @@ where
|
|||
}
|
||||
|
||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_async_method("close", |lua, this, code: Option<u16>| async move {
|
||||
methods.add_async_method("close", |_, this, code: Option<u16>| async move {
|
||||
this.close(code).await
|
||||
});
|
||||
|
||||
|
@ -172,7 +172,7 @@ where
|
|||
},
|
||||
);
|
||||
|
||||
methods.add_async_method("next", |lua, this, _: ()| async move {
|
||||
methods.add_async_method("next", |lua, this, (): ()| async move {
|
||||
let msg = this.next().await?;
|
||||
|
||||
if let Some(WsMessage::Close(Some(frame))) = msg.as_ref() {
|
26
crates/lune-std-process/Cargo.toml
Normal file
26
crates/lune-std-process/Cargo.toml
Normal file
|
@ -0,0 +1,26 @@
|
|||
[package]
|
||||
name = "lune-std-process"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
mlua = { version = "0.9.7", features = ["luau"] }
|
||||
mlua-luau-scheduler = "0.0.2"
|
||||
|
||||
directories = "5.0"
|
||||
pin-project = "1.0"
|
||||
os_str_bytes = { version = "7.0", features = ["conversions"] }
|
||||
|
||||
tokio = { version = "1", default-features = false, features = [
|
||||
"sync",
|
||||
"process",
|
||||
] }
|
||||
|
||||
lune-utils = { version = "0.1.0", path = "../lune-utils" }
|
|
@ -1,36 +1,49 @@
|
|||
#![allow(clippy::cargo_common_metadata)]
|
||||
|
||||
use std::{
|
||||
env::{self, consts},
|
||||
path,
|
||||
env::{
|
||||
self,
|
||||
consts::{ARCH, OS},
|
||||
},
|
||||
path::MAIN_SEPARATOR,
|
||||
process::Stdio,
|
||||
};
|
||||
|
||||
use mlua::prelude::*;
|
||||
|
||||
use lune_utils::TableBuilder;
|
||||
use mlua_luau_scheduler::{Functions, LuaSpawnExt};
|
||||
use os_str_bytes::RawOsString;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
use crate::lune::util::{paths::CWD, TableBuilder};
|
||||
|
||||
mod tee_writer;
|
||||
|
||||
mod options;
|
||||
use options::ProcessSpawnOptions;
|
||||
|
||||
mod tee_writer;
|
||||
mod wait_for_child;
|
||||
use wait_for_child::{wait_for_child, WaitForChildResult};
|
||||
|
||||
pub fn create(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
let cwd_str = {
|
||||
let cwd_str = CWD.to_string_lossy().to_string();
|
||||
if !cwd_str.ends_with(path::MAIN_SEPARATOR) {
|
||||
format!("{cwd_str}{}", path::MAIN_SEPARATOR)
|
||||
} else {
|
||||
cwd_str
|
||||
use self::options::ProcessSpawnOptions;
|
||||
use self::wait_for_child::{wait_for_child, WaitForChildResult};
|
||||
|
||||
use lune_utils::path::get_current_dir;
|
||||
|
||||
/**
|
||||
Creates the `process` standard library module.
|
||||
|
||||
# Errors
|
||||
|
||||
Errors when out of memory.
|
||||
*/
|
||||
#[allow(clippy::missing_panics_doc)]
|
||||
pub fn module(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
let mut cwd_str = get_current_dir()
|
||||
.to_str()
|
||||
.expect("cwd should be valid UTF-8")
|
||||
.to_string();
|
||||
if !cwd_str.ends_with(MAIN_SEPARATOR) {
|
||||
cwd_str.push(MAIN_SEPARATOR);
|
||||
}
|
||||
};
|
||||
// Create constants for OS & processor architecture
|
||||
let os = lua.create_string(&consts::OS.to_lowercase())?;
|
||||
let arch = lua.create_string(&consts::ARCH.to_lowercase())?;
|
||||
let os = lua.create_string(&OS.to_lowercase())?;
|
||||
let arch = lua.create_string(&ARCH.to_lowercase())?;
|
||||
// Create readonly args array
|
||||
let args_vec = lua
|
||||
.app_data_ref::<Vec<String>>()
|
||||
|
@ -94,9 +107,7 @@ fn process_env_set<'lua>(
|
|||
Err(LuaError::RuntimeError(
|
||||
"Key must not contain the NUL character".to_string(),
|
||||
))
|
||||
} else {
|
||||
match value {
|
||||
Some(value) => {
|
||||
} else if let Some(value) = value {
|
||||
// Make sure value is valid, otherwise set_var will panic
|
||||
if value.contains('\0') {
|
||||
Err(LuaError::RuntimeError(
|
||||
|
@ -106,21 +117,18 @@ fn process_env_set<'lua>(
|
|||
env::set_var(&key, &value);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
None => {
|
||||
} else {
|
||||
env::remove_var(&key);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn process_env_iter<'lua>(
|
||||
lua: &'lua Lua,
|
||||
(_, _): (LuaValue<'lua>, ()),
|
||||
(_, ()): (LuaValue<'lua>, ()),
|
||||
) -> LuaResult<LuaFunction<'lua>> {
|
||||
let mut vars = env::vars_os().collect::<Vec<_>>().into_iter();
|
||||
lua.create_function_mut(move |lua, _: ()| match vars.next() {
|
||||
lua.create_function_mut(move |lua, (): ()| match vars.next() {
|
||||
Some((key, value)) => {
|
||||
let raw_key = RawOsString::new(key);
|
||||
let raw_value = RawOsString::new(value);
|
||||
|
@ -149,10 +157,10 @@ async fn process_spawn(
|
|||
An exit code may be missing if the process was terminated by
|
||||
some external signal, which is the only time we use this default
|
||||
*/
|
||||
let code = res.status.code().unwrap_or(match res.stderr.is_empty() {
|
||||
true => 0,
|
||||
false => 1,
|
||||
});
|
||||
let code = res
|
||||
.status
|
||||
.code()
|
||||
.unwrap_or(i32::from(!res.stderr.is_empty()));
|
||||
|
||||
// Construct and return a readonly lua table with results
|
||||
TableBuilder::new(lua)?
|
||||
|
@ -174,9 +182,10 @@ async fn spawn_command(
|
|||
|
||||
let mut child = options
|
||||
.into_command(program, args)
|
||||
.stdin(match stdin.is_some() {
|
||||
true => Stdio::piped(),
|
||||
false => Stdio::null(),
|
||||
.stdin(if stdin.is_some() {
|
||||
Stdio::piped()
|
||||
} else {
|
||||
Stdio::null()
|
||||
})
|
||||
.stdout(stdout.as_stdio())
|
||||
.stderr(stderr.as_stdio())
|
|
@ -1,6 +1,5 @@
|
|||
use std::{fmt, process::Stdio, str::FromStr};
|
||||
|
||||
use itertools::Itertools;
|
||||
use mlua::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
|
||||
|
@ -55,6 +54,7 @@ impl FromStr for ProcessSpawnOptionsStdioKind {
|
|||
ProcessSpawnOptionsStdioKind::all()
|
||||
.iter()
|
||||
.map(|k| format!("'{k}'"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
)))
|
||||
}
|
|
@ -56,7 +56,7 @@ impl<'lua> FromLua<'lua> for ProcessSpawnOptions {
|
|||
"Invalid value for option 'cwd' - failed to get home directory",
|
||||
)
|
||||
})?;
|
||||
cwd = user_dirs.home_dir().join(stripped)
|
||||
cwd = user_dirs.home_dir().join(stripped);
|
||||
}
|
||||
if !cwd.exists() {
|
||||
return Err(LuaError::runtime(
|
|
@ -24,8 +24,7 @@ where
|
|||
R: AsyncRead + Unpin,
|
||||
{
|
||||
Ok(match kind {
|
||||
ProcessSpawnOptionsStdioKind::None => Vec::new(),
|
||||
ProcessSpawnOptionsStdioKind::Forward => Vec::new(),
|
||||
ProcessSpawnOptionsStdioKind::None | ProcessSpawnOptionsStdioKind::Forward => Vec::new(),
|
||||
ProcessSpawnOptionsStdioKind::Default => {
|
||||
let mut read_from =
|
||||
read_from.expect("read_from must be Some when stdio kind is Default");
|
19
crates/lune-std-regex/Cargo.toml
Normal file
19
crates/lune-std-regex/Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "lune-std-regex"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
mlua = { version = "0.9.7", features = ["luau"] }
|
||||
|
||||
regex = "1.10"
|
||||
self_cell = "1.0"
|
||||
|
||||
lune-utils = { version = "0.1.0", path = "../lune-utils" }
|
|
@ -1,8 +1,8 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
#![allow(clippy::cargo_common_metadata)]
|
||||
|
||||
use mlua::prelude::*;
|
||||
|
||||
use crate::lune::util::TableBuilder;
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
mod captures;
|
||||
mod matches;
|
||||
|
@ -10,7 +10,14 @@ mod regex;
|
|||
|
||||
use self::regex::LuaRegex;
|
||||
|
||||
pub fn create(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
/**
|
||||
Creates the `regex` standard library module.
|
||||
|
||||
# Errors
|
||||
|
||||
Errors when out of memory.
|
||||
*/
|
||||
pub fn module(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
TableBuilder::new(lua)?
|
||||
.with_function("new", new_regex)?
|
||||
.build_readonly()
|
|
@ -46,7 +46,7 @@ impl LuaUserData for LuaRegex {
|
|||
Ok(this
|
||||
.inner
|
||||
.split(&text)
|
||||
.map(|s| s.to_string())
|
||||
.map(ToString::to_string)
|
||||
.collect::<Vec<_>>())
|
||||
});
|
||||
|
21
crates/lune-std-roblox/Cargo.toml
Normal file
21
crates/lune-std-roblox/Cargo.toml
Normal file
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
name = "lune-std-roblox"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
mlua = { version = "0.9.7", features = ["luau"] }
|
||||
mlua-luau-scheduler = "0.0.2"
|
||||
|
||||
once_cell = "1.17"
|
||||
rbx_cookie = { version = "0.1.4", default-features = false }
|
||||
|
||||
lune-utils = { version = "0.1.0", path = "../lune-utils" }
|
||||
lune-roblox = { version = "0.1.0", path = "../lune-roblox" }
|
|
@ -1,23 +1,30 @@
|
|||
#![allow(clippy::cargo_common_metadata)]
|
||||
|
||||
use mlua::prelude::*;
|
||||
use mlua_luau_scheduler::LuaSpawnExt;
|
||||
use once_cell::sync::OnceCell;
|
||||
|
||||
use crate::{
|
||||
lune::util::TableBuilder,
|
||||
roblox::{
|
||||
self,
|
||||
use lune_roblox::{
|
||||
document::{Document, DocumentError, DocumentFormat, DocumentKind},
|
||||
instance::{registry::InstanceRegistry, Instance},
|
||||
reflection::Database as ReflectionDatabase,
|
||||
},
|
||||
};
|
||||
|
||||
static REFLECTION_DATABASE: OnceCell<ReflectionDatabase> = OnceCell::new();
|
||||
|
||||
pub fn create(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
use lune_utils::TableBuilder;
|
||||
|
||||
/**
|
||||
Creates the `roblox` standard library module.
|
||||
|
||||
# Errors
|
||||
|
||||
Errors when out of memory.
|
||||
*/
|
||||
pub fn module(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
let mut roblox_constants = Vec::new();
|
||||
|
||||
let roblox_module = roblox::module(lua)?;
|
||||
let roblox_module = lune_roblox::module(lua)?;
|
||||
for pair in roblox_module.pairs::<LuaValue, LuaValue>() {
|
||||
roblox_constants.push(pair?);
|
||||
}
|
||||
|
@ -116,16 +123,15 @@ fn implement_property(
|
|||
Option<LuaFunction>,
|
||||
),
|
||||
) -> LuaResult<()> {
|
||||
let property_setter = match property_setter {
|
||||
Some(setter) => setter,
|
||||
None => {
|
||||
let property_setter = if let Some(setter) = property_setter {
|
||||
setter
|
||||
} else {
|
||||
let property_name = property_name.clone();
|
||||
lua.create_function(move |_, _: LuaMultiValue| {
|
||||
Err::<(), _>(LuaError::runtime(format!(
|
||||
"Property '{property_name}' is read-only"
|
||||
)))
|
||||
})?
|
||||
}
|
||||
};
|
||||
InstanceRegistry::insert_property_getter(lua, &class_name, &property_name, property_getter)
|
||||
.into_lua_err()?;
|
35
crates/lune-std-serde/Cargo.toml
Normal file
35
crates/lune-std-serde/Cargo.toml
Normal file
|
@ -0,0 +1,35 @@
|
|||
[package]
|
||||
name = "lune-std-serde"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
mlua = { version = "0.9.7", features = ["luau"] }
|
||||
|
||||
async-compression = { version = "0.4", features = [
|
||||
"tokio",
|
||||
"brotli",
|
||||
"deflate",
|
||||
"gzip",
|
||||
"zlib",
|
||||
] }
|
||||
bstr = "1.9"
|
||||
lz4 = "1.24"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
serde_yaml = "0.9"
|
||||
toml = { version = "0.8", features = ["preserve_order"] }
|
||||
|
||||
tokio = { version = "1", default-features = false, features = [
|
||||
"rt",
|
||||
"io-util",
|
||||
] }
|
||||
|
||||
lune-utils = { version = "0.1.0", path = "../lune-utils" }
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue