Compare commits
20 Commits
master
...
operations
Author | SHA1 | Date | |
---|---|---|---|
df58d7d122 | |||
621925b30c | |||
d75c480e6a | |||
8df3809a6a | |||
![]() |
25b708a6fd | ||
![]() |
1350e09bde | ||
![]() |
ee86e3be2f | ||
![]() |
3dad5754f9 | ||
![]() |
57b5f82c8d | ||
![]() |
d948471ed5 | ||
![]() |
4447d800df | ||
![]() |
abad6181cb | ||
![]() |
60b9bdc28a | ||
![]() |
9b6a24e222 | ||
![]() |
7044dc304d | ||
![]() |
1c6d400f4a | ||
![]() |
ba4f3b78ad | ||
![]() |
d18b7bdaf8 | ||
![]() |
08d7fa2319 | ||
![]() |
21f66d9409 |
@ -12,6 +12,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Rust toolchain
|
||||
# https://github.com/actions-rust-lang/setup-rust-toolchain
|
||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
rustflags: "" # Override the default error on warnings
|
||||
cache: false
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
- name: Run tests
|
@ -7,10 +7,10 @@ on:
|
||||
jobs:
|
||||
deploy:
|
||||
name: Build and run
|
||||
runs-on: self-hosted
|
||||
runs-on: host
|
||||
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v4
|
||||
- name: Run
|
||||
run: docker-compose up -d --build
|
||||
run: docker compose up -d --build
|
102
Cargo.lock
generated
102
Cargo.lock
generated
@ -48,6 +48,7 @@ dependencies = [
|
||||
"matchit",
|
||||
"memchr",
|
||||
"mime",
|
||||
"multer",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustversion",
|
||||
@ -136,12 +137,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "derive"
|
||||
version = "1.0.0"
|
||||
source = "git+https://github.com/emberal/rust-lib.git?tag=1.1.1#752d1a9d102a6ed7026909a46d4e0b2cb1e0cb3d"
|
||||
name = "encoding_rs"
|
||||
version = "0.8.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -174,12 +175,6 @@ version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.30"
|
||||
@ -296,6 +291,15 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "into-response-derive"
|
||||
version = "1.1.0"
|
||||
source = "git+https://github.com/emberal/rust-lib?tag=1.4.1-hotfix#8cbb2757a5030622ec32931c44ea2d489e85640a"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
@ -310,15 +314,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "lib"
|
||||
version = "1.1.1"
|
||||
source = "git+https://github.com/emberal/rust-lib.git?tag=1.1.1#752d1a9d102a6ed7026909a46d4e0b2cb1e0cb3d"
|
||||
version = "1.4.1-hotfix"
|
||||
source = "git+https://github.com/emberal/rust-lib?tag=1.4.1-hotfix#8cbb2757a5030622ec32931c44ea2d489e85640a"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"derive",
|
||||
"into-response-derive",
|
||||
"nom",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower-http",
|
||||
"tracing",
|
||||
@ -381,6 +385,23 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "multer"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-util",
|
||||
"http",
|
||||
"httparse",
|
||||
"memchr",
|
||||
"mime",
|
||||
"spin",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
@ -578,8 +599,6 @@ dependencies = [
|
||||
"serde",
|
||||
"tokio",
|
||||
"tower-http",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -598,6 +617,12 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.66"
|
||||
@ -621,6 +646,26 @@ version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.62"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.62"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.8"
|
||||
@ -658,19 +703,6 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.4.13"
|
||||
@ -706,9 +738,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tower-layer"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
|
||||
checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
@ -786,6 +818,12 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
|
@ -13,9 +13,6 @@ tokio = { version = "1.38.0", features = ["macros", "rt-multi-thread"] }
|
||||
serde = { version = "1.0.203", features = ["derive", "rc"] }
|
||||
# API
|
||||
axum = { version = "0.7.5", features = ["macros"] }
|
||||
tower-http = { version = "0.5.2", features = ["cors", "trace", "normalize-path"] }
|
||||
# Logging
|
||||
tracing = "0.1.40"
|
||||
tracing-subscriber = "0.3.18"
|
||||
tower-http = { version = "0.5.2", features = ["cors"] }
|
||||
|
||||
lib = { git = "https://github.com/emberal/rust-lib.git", tag = "1.1.1", features = ["axum", "vec", "nom", "serde", "derive", "tokio"] }
|
||||
lib = { git = "https://github.com/emberal/rust-lib", tag = "1.4.1-hotfix", features = ["axum", "iter", "nom", "serde", "derive"] }
|
||||
|
@ -12,7 +12,7 @@ RUN npm install
|
||||
RUN USER=root npm install -g @typespec/compiler && npm install -g @redocly/cli
|
||||
RUN npm run tsp-compile && npm run redoc-build
|
||||
|
||||
FROM rust:1.79 as build
|
||||
FROM rust:1.80.1 as build
|
||||
|
||||
COPY --from=static ./src/resources/static ./static
|
||||
|
||||
|
53
spec/dist/@typespec/openapi3/openapi.v2.yaml
vendored
53
spec/dist/@typespec/openapi3/openapi.v2.yaml
vendored
@ -10,8 +10,6 @@ tags:
|
||||
paths:
|
||||
/:
|
||||
get:
|
||||
tags:
|
||||
- Common
|
||||
operationId: Index_index
|
||||
summary: Information
|
||||
description: Information about this API.
|
||||
@ -23,11 +21,10 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Responses.InfoResponse'
|
||||
/is-valid/{exp}:
|
||||
get:
|
||||
tags:
|
||||
- Common
|
||||
- Expression
|
||||
/is-valid/{exp}:
|
||||
get:
|
||||
operationId: Index_isValid
|
||||
summary: Check if an expression is valid
|
||||
description: Check if an expression is valid.
|
||||
@ -44,10 +41,11 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Responses.IsValidResponse'
|
||||
/openapi:
|
||||
get:
|
||||
tags:
|
||||
- Common
|
||||
- Expression
|
||||
/openapi:
|
||||
get:
|
||||
operationId: Index_openAPI
|
||||
summary: The OpenAPI specification
|
||||
description: The OpenAPI specification for this API.
|
||||
@ -59,11 +57,10 @@ paths:
|
||||
text/html:
|
||||
schema:
|
||||
type: string
|
||||
tags:
|
||||
- Common
|
||||
/simplify/table/{exp}:
|
||||
get:
|
||||
tags:
|
||||
- Expression
|
||||
- Table
|
||||
operationId: Simplify_simplifyTable
|
||||
summary: Simplify and generate a truth table
|
||||
parameters:
|
||||
@ -77,6 +74,7 @@ paths:
|
||||
required: false
|
||||
schema:
|
||||
$ref: '#/components/schemas/Options.SimplifyTableOptions'
|
||||
explode: false
|
||||
responses:
|
||||
'200':
|
||||
description: The request has succeeded.
|
||||
@ -84,10 +82,11 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Responses.SimplifyTableResponse'
|
||||
/simplify/{exp}:
|
||||
get:
|
||||
tags:
|
||||
- Expression
|
||||
- Table
|
||||
/simplify/{exp}:
|
||||
get:
|
||||
operationId: Simplify_simplify
|
||||
summary: Simplify a truth expression
|
||||
parameters:
|
||||
@ -101,6 +100,7 @@ paths:
|
||||
required: false
|
||||
schema:
|
||||
$ref: '#/components/schemas/Options.SimplifyOptions'
|
||||
explode: false
|
||||
responses:
|
||||
'200':
|
||||
description: The request has succeeded.
|
||||
@ -108,10 +108,10 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Responses.SimplifyResponse'
|
||||
tags:
|
||||
- Expression
|
||||
/table/{exp}:
|
||||
get:
|
||||
tags:
|
||||
- Table
|
||||
operationId: TruthTable_simplify
|
||||
summary: Generate a truth table
|
||||
parameters:
|
||||
@ -125,6 +125,7 @@ paths:
|
||||
required: false
|
||||
schema:
|
||||
$ref: '#/components/schemas/Options.TableOptions'
|
||||
explode: false
|
||||
responses:
|
||||
'200':
|
||||
description: The request has succeeded.
|
||||
@ -132,14 +133,10 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Responses.TruthTableResponse'
|
||||
tags:
|
||||
- Table
|
||||
components:
|
||||
schemas:
|
||||
Expression:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/Models.ExpressionNot'
|
||||
- $ref: '#/components/schemas/Models.ExpressionBinary'
|
||||
- $ref: '#/components/schemas/Models.ExpressionAtomic'
|
||||
title: A truth expression
|
||||
Models.BinaryOperator:
|
||||
type: string
|
||||
enum:
|
||||
@ -147,6 +144,12 @@ components:
|
||||
- OR
|
||||
- IMPLICATION
|
||||
title: A binary operator
|
||||
Models.Expression:
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/Models.ExpressionNot'
|
||||
- $ref: '#/components/schemas/Models.ExpressionBinary'
|
||||
- $ref: '#/components/schemas/Models.ExpressionAtomic'
|
||||
title: A truth expression
|
||||
Models.ExpressionAtomic:
|
||||
type: object
|
||||
required:
|
||||
@ -165,7 +168,7 @@ components:
|
||||
properties:
|
||||
left:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Expression'
|
||||
- $ref: '#/components/schemas/Models.Expression'
|
||||
title: The left expression
|
||||
operator:
|
||||
allOf:
|
||||
@ -173,7 +176,7 @@ components:
|
||||
title: The binary operator
|
||||
right:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Expression'
|
||||
- $ref: '#/components/schemas/Models.Expression'
|
||||
title: The right expression
|
||||
title: A binary expression
|
||||
Models.ExpressionNot:
|
||||
@ -183,7 +186,7 @@ components:
|
||||
properties:
|
||||
not:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Expression'
|
||||
- $ref: '#/components/schemas/Models.Expression'
|
||||
title: The expression to negate
|
||||
title: The inverse of an expression
|
||||
Models.TruthTable:
|
||||
@ -326,7 +329,7 @@ components:
|
||||
title: Steps taken to simplify
|
||||
expression:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Expression'
|
||||
- $ref: '#/components/schemas/Models.Expression'
|
||||
title: The simplified expression
|
||||
description: Response after simplifying an expression.
|
||||
title: Simplify Response
|
||||
@ -352,7 +355,7 @@ components:
|
||||
title: Steps taken to simplify
|
||||
expression:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Expression'
|
||||
- $ref: '#/components/schemas/Models.Expression'
|
||||
title: The simplified expression
|
||||
truthTable:
|
||||
allOf:
|
||||
|
422
spec/package-lock.json
generated
422
spec/package-lock.json
generated
@ -9,9 +9,15 @@
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@typespec/compiler": "latest",
|
||||
"@typespec/openapi3": "^0.57.0"
|
||||
"@typespec/openapi3": "^0.60.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@apidevtools/swagger-methods": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz",
|
||||
"integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.24.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz",
|
||||
@ -49,6 +55,33 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.25.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz",
|
||||
"integrity": "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.14.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/momoa": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/momoa/-/momoa-2.0.4.tgz",
|
||||
"integrity": "sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=10.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jsdevtools/ono": {
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
|
||||
"integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
@ -84,6 +117,140 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@readme/better-ajv-errors": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@readme/better-ajv-errors/-/better-ajv-errors-1.6.0.tgz",
|
||||
"integrity": "sha512-9gO9rld84Jgu13kcbKRU+WHseNhaVt76wYMeRDGsUGYxwJtI3RmEJ9LY9dZCYQGI8eUZLuxb5qDja0nqklpFjQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.16.0",
|
||||
"@babel/runtime": "^7.21.0",
|
||||
"@humanwhocodes/momoa": "^2.0.3",
|
||||
"chalk": "^4.1.2",
|
||||
"json-to-ast": "^2.0.3",
|
||||
"jsonpointer": "^5.0.0",
|
||||
"leven": "^3.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"ajv": "4.11.8 - 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@readme/better-ajv-errors/node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@readme/better-ajv-errors/node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@readme/better-ajv-errors/node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@readme/better-ajv-errors/node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@readme/better-ajv-errors/node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@readme/better-ajv-errors/node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@readme/json-schema-ref-parser": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@readme/json-schema-ref-parser/-/json-schema-ref-parser-1.2.0.tgz",
|
||||
"integrity": "sha512-Bt3QVovFSua4QmHa65EHUmh2xS0XJ3rgTEUPH998f4OW4VVJke3BuS16f+kM0ZLOGdvIrzrPRqwihuv5BAjtrA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jsdevtools/ono": "^7.1.3",
|
||||
"@types/json-schema": "^7.0.6",
|
||||
"call-me-maybe": "^1.0.1",
|
||||
"js-yaml": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@readme/openapi-parser": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@readme/openapi-parser/-/openapi-parser-2.6.0.tgz",
|
||||
"integrity": "sha512-pyFJXezWj9WI1O+gdp95CoxfY+i+Uq3kKk4zXIFuRAZi9YnHpHOpjumWWr67wkmRTw19Hskh9spyY0Iyikf3fA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@apidevtools/swagger-methods": "^3.0.2",
|
||||
"@jsdevtools/ono": "^7.1.3",
|
||||
"@readme/better-ajv-errors": "^1.6.0",
|
||||
"@readme/json-schema-ref-parser": "^1.2.0",
|
||||
"@readme/openapi-schemas": "^3.1.0",
|
||||
"ajv": "^8.12.0",
|
||||
"ajv-draft-04": "^1.0.0",
|
||||
"call-me-maybe": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"openapi-types": ">=7"
|
||||
}
|
||||
},
|
||||
"node_modules/@readme/openapi-schemas": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@readme/openapi-schemas/-/openapi-schemas-3.1.0.tgz",
|
||||
"integrity": "sha512-9FC/6ho8uFa8fV50+FPy/ngWN53jaUu4GRXlAjcxIRrzhltJnpKkBG2Tp0IDraFJeWrOpk84RJ9EMEEYzaI1Bw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sindresorhus/merge-streams": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz",
|
||||
@ -96,24 +263,31 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@typespec/compiler": {
|
||||
"version": "0.57.0",
|
||||
"resolved": "https://registry.npmjs.org/@typespec/compiler/-/compiler-0.57.0.tgz",
|
||||
"integrity": "sha512-Z5L7J90Ol21IbzU+rBD2wzKy2vJ2Yg2FIzi+yB5rtb7/c4oBea/CgEByMVHBtT7uw45ZXJpHOiepuGSPVXw2EA==",
|
||||
"version": "0.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typespec/compiler/-/compiler-0.60.1.tgz",
|
||||
"integrity": "sha512-I6Vcpvd7mBP7SI5vCBh9rZGXAtVy95BKhAd33Enw32psswiSzRpA7zdyZhOMekTOGVXNS/+E5l2PGGCzQddB4w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "~7.24.2",
|
||||
"ajv": "~8.13.0",
|
||||
"@babel/code-frame": "~7.24.7",
|
||||
"ajv": "~8.17.1",
|
||||
"change-case": "~5.4.4",
|
||||
"globby": "~14.0.1",
|
||||
"globby": "~14.0.2",
|
||||
"mustache": "~4.2.0",
|
||||
"picocolors": "~1.0.1",
|
||||
"prettier": "~3.2.5",
|
||||
"prettier": "~3.3.3",
|
||||
"prompts": "~2.4.2",
|
||||
"semver": "^7.6.2",
|
||||
"semver": "^7.6.3",
|
||||
"temporal-polyfill": "^0.2.5",
|
||||
"vscode-languageserver": "~9.0.1",
|
||||
"vscode-languageserver-textdocument": "~1.0.11",
|
||||
"yaml": "~2.4.2",
|
||||
"yaml": "~2.4.5",
|
||||
"yargs": "~17.7.2"
|
||||
},
|
||||
"bin": {
|
||||
@ -125,79 +299,97 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typespec/http": {
|
||||
"version": "0.57.0",
|
||||
"resolved": "https://registry.npmjs.org/@typespec/http/-/http-0.57.0.tgz",
|
||||
"integrity": "sha512-k3bWOTPNqlRB3/TmrXVBtObmxj2J20l2FnhGXvs+tjdtbXLxCQWmvQz6xlne9nkLAtWVB/pQRUn+oMJfhWta3w==",
|
||||
"version": "0.60.0",
|
||||
"resolved": "https://registry.npmjs.org/@typespec/http/-/http-0.60.0.tgz",
|
||||
"integrity": "sha512-ktfS9vpHfltyeAaQLNAZdqrn6Per3vmB/HDH/iyudYLA5wWblT1siKvpFCMWq53CJorRO7yeOKv+Q/M26zwEtg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@typespec/compiler": "~0.57.0"
|
||||
"@typespec/compiler": "~0.60.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typespec/openapi": {
|
||||
"version": "0.57.0",
|
||||
"resolved": "https://registry.npmjs.org/@typespec/openapi/-/openapi-0.57.0.tgz",
|
||||
"integrity": "sha512-35wK/BqjOXSlhWuGMwoYN3FSgIYFOKtw8ot4ErcgmxAGuKaS2GkUhZvtQJXUn2ByU0Fl4jqslPmTz8SEcz7rbw==",
|
||||
"version": "0.60.0",
|
||||
"resolved": "https://registry.npmjs.org/@typespec/openapi/-/openapi-0.60.0.tgz",
|
||||
"integrity": "sha512-YVwLppgHY8r/MudHNSLSUXzdw+CIpjmb31gI2a0KDGnI6sWDwY7LSWfjGU4TY/ubt0+X0Tjoy330mTvw71YBTg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@typespec/compiler": "~0.57.0",
|
||||
"@typespec/http": "~0.57.0"
|
||||
"@typespec/compiler": "~0.60.0",
|
||||
"@typespec/http": "~0.60.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typespec/openapi3": {
|
||||
"version": "0.57.0",
|
||||
"resolved": "https://registry.npmjs.org/@typespec/openapi3/-/openapi3-0.57.0.tgz",
|
||||
"integrity": "sha512-spNLzwCTduPISJBTWhqsMLTjuGC3Tdh/FVI1rTGnRunB7ZXjhRyz031o1bCe2BZeW1w1sacZGfe+ba8sXqgMxA==",
|
||||
"version": "0.60.0",
|
||||
"resolved": "https://registry.npmjs.org/@typespec/openapi3/-/openapi3-0.60.0.tgz",
|
||||
"integrity": "sha512-gvrTHZACdeQtV7GfhVOHqkyTgMFyM2nKAIiz2P83LIncMCDUc00bGKGmaBk+xpuwKtCJyxBeVpCbID31YAq96g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"yaml": "~2.4.2"
|
||||
"@readme/openapi-parser": "~2.6.0",
|
||||
"yaml": "~2.4.5"
|
||||
},
|
||||
"bin": {
|
||||
"tsp-openapi3": "cmd/tsp-openapi3.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@typespec/compiler": "~0.57.0",
|
||||
"@typespec/http": "~0.57.0",
|
||||
"@typespec/openapi": "~0.57.0",
|
||||
"@typespec/versioning": "~0.57.0"
|
||||
"@typespec/compiler": "~0.60.0",
|
||||
"@typespec/http": "~0.60.0",
|
||||
"@typespec/openapi": "~0.60.0",
|
||||
"@typespec/versioning": "~0.60.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typespec/versioning": {
|
||||
"version": "0.57.0",
|
||||
"resolved": "https://registry.npmjs.org/@typespec/versioning/-/versioning-0.57.0.tgz",
|
||||
"integrity": "sha512-kk6zCNSwcqqYB9isNNagTy+Zv6wEIRA4NkcZ/X1riTj2zhJwKsIFNXQWm1yxpZn+BY4+1QtuaQHuBLo8HbgR/w==",
|
||||
"version": "0.60.1",
|
||||
"resolved": "https://registry.npmjs.org/@typespec/versioning/-/versioning-0.60.1.tgz",
|
||||
"integrity": "sha512-HogYL7P9uOPoSvkLLDjF22S6E9td6EY3c6TcIHhCzDTAQoi54csikD0gNrtcCkFG0UeQk29HgQymV397j+vp4g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@typespec/compiler": "~0.57.0"
|
||||
"@typespec/compiler": "~0.60.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "8.13.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz",
|
||||
"integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==",
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"require-from-string": "^2.0.2",
|
||||
"uri-js": "^4.4.1"
|
||||
"require-from-string": "^2.0.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv-draft-04": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz",
|
||||
"integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"ajv": "^8.5.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"ajv": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
@ -219,6 +411,12 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
@ -231,6 +429,12 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/call-me-maybe": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz",
|
||||
"integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
@ -265,6 +469,15 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/code-error-fragment": {
|
||||
"version": "0.0.230",
|
||||
"resolved": "https://registry.npmjs.org/code-error-fragment/-/code-error-fragment-0.0.230.tgz",
|
||||
"integrity": "sha512-cadkfKp6932H8UkhzE/gcUqhRMNf8jHzkAN7+5Myabswaghu4xABTgPHDCjW+dBAJxj/SpkTYokpzDqY4pCzQw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
@ -326,6 +539,12 @@
|
||||
"node": ">=8.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-uri": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz",
|
||||
"integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fastq": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
|
||||
@ -369,9 +588,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/globby": {
|
||||
"version": "14.0.1",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz",
|
||||
"integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==",
|
||||
"version": "14.0.2",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz",
|
||||
"integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sindresorhus/merge-streams": "^2.1.0",
|
||||
@ -388,6 +607,12 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/grapheme-splitter": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
|
||||
"integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
@ -398,9 +623,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
|
||||
"integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
@ -451,12 +676,46 @@
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-to-ast": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/json-to-ast/-/json-to-ast-2.1.0.tgz",
|
||||
"integrity": "sha512-W9Lq347r8tA1DfMvAGn9QNcgYm4Wm7Yc+k8e6vezpMnRT+NHbtlxgNBXRVjXe9YM6eTn6+p/MKOlV/aABJcSnQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"code-error-fragment": "0.0.230",
|
||||
"grapheme-splitter": "^1.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonpointer": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz",
|
||||
"integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/kleur": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
|
||||
@ -466,6 +725,15 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/leven": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
||||
"integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/merge2": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||
@ -476,9 +744,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/micromatch": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
|
||||
"integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"braces": "^3.0.3",
|
||||
@ -497,6 +765,13 @@
|
||||
"mustache": "bin/mustache"
|
||||
}
|
||||
},
|
||||
"node_modules/openapi-types": {
|
||||
"version": "12.1.3",
|
||||
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
|
||||
"integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/path-type": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz",
|
||||
@ -528,9 +803,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.2.5",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
|
||||
"integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==",
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
|
||||
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
@ -555,15 +830,6 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/queue-microtask": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||
@ -584,6 +850,12 @@
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.14.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
||||
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
@ -636,9 +908,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.6.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
|
||||
"integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
||||
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
@ -703,6 +975,21 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/temporal-polyfill": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/temporal-polyfill/-/temporal-polyfill-0.2.5.tgz",
|
||||
"integrity": "sha512-ye47xp8Cb0nDguAhrrDS1JT1SzwEV9e26sSsrWzVu+yPZ7LzceEcH0i2gci9jWfOfSCCgM3Qv5nOYShVUUFUXA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"temporal-spec": "^0.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/temporal-spec": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/temporal-spec/-/temporal-spec-0.2.4.tgz",
|
||||
"integrity": "sha512-lDMFv4nKQrSjlkHKAlHVqKrBG4DyFfa9F74cmBZ3Iy3ed8yvWnlWSIdi4IKfSqwmazAohBNwiN64qGx4y5Q3IQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
@ -727,15 +1014,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-jsonrpc": {
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz",
|
||||
@ -839,9 +1117,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.3.tgz",
|
||||
"integrity": "sha512-sntgmxj8o7DE7g/Qi60cqpLBA3HG3STcDA0kO+WfB05jEKhZMbY7umNm2rBpQvsmZ16/lPXCJGW2672dgOUkrg==",
|
||||
"version": "2.4.5",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz",
|
||||
"integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"yaml": "bin.mjs"
|
||||
|
@ -10,7 +10,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@typespec/compiler": "latest",
|
||||
"@typespec/openapi3": "^0.57.0"
|
||||
"@typespec/openapi3": "^0.60.0"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
|
@ -11,16 +11,26 @@ use crate::parsing::expression_parser::parse_expression;
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum Expression {
|
||||
Not(Rc<Expression>),
|
||||
Binary { left: Rc<Expression>, operator: BinaryOperator, right: Rc<Expression> },
|
||||
Binary {
|
||||
left: Rc<Expression>,
|
||||
operator: BinaryOperator,
|
||||
right: Rc<Expression>,
|
||||
},
|
||||
Atomic(String),
|
||||
}
|
||||
|
||||
impl PartialEq<Rc<Expression>> for Expression {
|
||||
fn eq(&self, other: &Rc<Expression>) -> bool {
|
||||
self == other.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
pub fn is_atomic(&self) -> bool {
|
||||
match self {
|
||||
Expression::Not(expr) => expr.is_atomic(),
|
||||
Expression::Binary { .. } => false,
|
||||
Expression::Atomic(_) => true
|
||||
Expression::Atomic(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,15 +42,28 @@ impl Expression {
|
||||
values.extend(right.get_atomic_values());
|
||||
values
|
||||
}
|
||||
Expression::Atomic(value) => HashSet::from([value.clone()])
|
||||
Expression::Atomic(value) => HashSet::from([value.clone()]),
|
||||
}
|
||||
}
|
||||
|
||||
//TODO replace with eq_ignore_case and use a macro to select correct eq function
|
||||
pub fn eq(&self, other: &Self, ignore_case: bool) -> bool {
|
||||
match (self, other) {
|
||||
(Expression::Not(left), Expression::Not(right)) => Expression::eq(left, right, ignore_case),
|
||||
(Expression::Binary { left: left_left, operator: left_operator, right: left_right },
|
||||
Expression::Binary { left: right_left, operator: right_operator, right: right_right }) => {
|
||||
(Expression::Not(left), Expression::Not(right)) => {
|
||||
Expression::eq(left, right, ignore_case)
|
||||
}
|
||||
(
|
||||
Expression::Binary {
|
||||
left: left_left,
|
||||
operator: left_operator,
|
||||
right: left_right,
|
||||
},
|
||||
Expression::Binary {
|
||||
left: right_left,
|
||||
operator: right_operator,
|
||||
right: right_right,
|
||||
},
|
||||
) => {
|
||||
Expression::eq(left_left, right_left, ignore_case)
|
||||
&& left_operator == right_operator
|
||||
&& Expression::eq(left_right, right_right, ignore_case)
|
||||
@ -52,7 +75,7 @@ impl Expression {
|
||||
left == right
|
||||
}
|
||||
}
|
||||
_ => false
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,6 +87,34 @@ impl Expression {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_in(&self, other: &Self) -> bool {
|
||||
if let Expression::Binary { left, right, .. } = other {
|
||||
self == left || self == right
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_or(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Expression::Binary {
|
||||
operator: BinaryOperator::Or,
|
||||
..
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_and(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Expression::Binary {
|
||||
operator: BinaryOperator::And,
|
||||
..
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'a str> for Expression {
|
||||
@ -87,20 +138,61 @@ impl Display for Expression {
|
||||
|
||||
fn fmt_helper(expression: &Expression, parent: Option<&Expression>) -> String {
|
||||
match expression {
|
||||
Expression::Not(expr) if expr.is_atomic() => format!("¬{}", fmt_helper(expr, Some(expression))),
|
||||
Expression::Not(expr) => format!("¬({})", fmt_helper(expr, Some(expression))),
|
||||
Expression::Binary { left, operator: BinaryOperator::And, right } => {
|
||||
format!("{} ⋀ {}", fmt_helper(left, Some(expression)), fmt_helper(right, Some(expression)))
|
||||
Expression::Not(expr) if expr.is_atomic() => {
|
||||
format!("¬{}", fmt_helper(expr, Some(expression)))
|
||||
}
|
||||
Expression::Binary { left, operator: BinaryOperator::Or, right } => {
|
||||
if parent.is_none() || matches!(parent, Some(Expression::Binary { operator: BinaryOperator::Or, .. })) {
|
||||
format!("{} ⋁ {}", fmt_helper(left, Some(expression)), fmt_helper(right, Some(expression)))
|
||||
Expression::Not(expr) => format!("¬({})", fmt_helper(expr, Some(expression))),
|
||||
Expression::Binary {
|
||||
left,
|
||||
operator: BinaryOperator::And,
|
||||
right,
|
||||
} => {
|
||||
format!(
|
||||
"{} ⋀ {}",
|
||||
fmt_helper(left, Some(expression)),
|
||||
fmt_helper(right, Some(expression))
|
||||
)
|
||||
}
|
||||
Expression::Binary {
|
||||
left,
|
||||
operator: BinaryOperator::Or,
|
||||
right,
|
||||
} => {
|
||||
if parent.is_none()
|
||||
|| matches!(
|
||||
parent,
|
||||
Some(
|
||||
Expression::Not(_)
|
||||
| Expression::Binary {
|
||||
operator: BinaryOperator::Or | BinaryOperator::Implication,
|
||||
..
|
||||
}
|
||||
)
|
||||
)
|
||||
{
|
||||
format!(
|
||||
"{} ⋁ {}",
|
||||
fmt_helper(left, Some(expression)),
|
||||
fmt_helper(right, Some(expression))
|
||||
)
|
||||
} else {
|
||||
format!("({} ⋁ {})", fmt_helper(left, Some(expression)), fmt_helper(right, Some(expression)))
|
||||
format!(
|
||||
"({} ⋁ {})",
|
||||
fmt_helper(left, Some(expression)),
|
||||
fmt_helper(right, Some(expression))
|
||||
)
|
||||
}
|
||||
}
|
||||
Expression::Binary { left, operator: BinaryOperator::Implication, right } => {
|
||||
format!("{} ➔ {}", fmt_helper(left, Some(expression)), fmt_helper(right, Some(expression)))
|
||||
Expression::Binary {
|
||||
left,
|
||||
operator: BinaryOperator::Implication,
|
||||
right,
|
||||
} => {
|
||||
format!(
|
||||
"{} ➔ {}",
|
||||
fmt_helper(left, Some(expression)),
|
||||
fmt_helper(right, Some(expression))
|
||||
)
|
||||
}
|
||||
Expression::Atomic(value) => value.clone(),
|
||||
}
|
||||
@ -157,102 +249,55 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_expression_a_and_not_b_display() {
|
||||
let expression = and(
|
||||
atomic("a"),
|
||||
not(atomic("b")),
|
||||
);
|
||||
let expression = and(atomic("a"), not(atomic("b")));
|
||||
assert_eq!(expression.to_string(), "a ⋀ ¬b");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expression_a_or_b_and_c_display() {
|
||||
let expression = or(
|
||||
atomic("a"),
|
||||
and(
|
||||
atomic("b"),
|
||||
atomic("c"),
|
||||
));
|
||||
let expression = or(atomic("a"), and(atomic("b"), atomic("c")));
|
||||
assert_eq!(expression.to_string(), "a ⋁ b ⋀ c");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expression_a_or_b() {
|
||||
let expression = or(
|
||||
atomic("a"),
|
||||
atomic("b"),
|
||||
);
|
||||
let expression = or(atomic("a"), atomic("b"));
|
||||
assert_eq!(expression.to_string(), "a ⋁ b");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expression_double_or() {
|
||||
let expression = or(
|
||||
atomic("a"),
|
||||
or(
|
||||
atomic("b"),
|
||||
atomic("c"),
|
||||
),
|
||||
);
|
||||
let expression = or(atomic("a"), or(atomic("b"), atomic("c")));
|
||||
assert_eq!(expression.to_string(), "a ⋁ b ⋁ c");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expression_triple_or() {
|
||||
let expression = or(
|
||||
atomic("a"),
|
||||
or(
|
||||
atomic("b"),
|
||||
or(
|
||||
atomic("c"),
|
||||
atomic("d"),
|
||||
),
|
||||
),
|
||||
);
|
||||
let expression = or(atomic("a"), or(atomic("b"), or(atomic("c"), atomic("d"))));
|
||||
assert_eq!(expression.to_string(), "a ⋁ b ⋁ c ⋁ d");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expression_nested_parenthesized_or() {
|
||||
let expression = or(
|
||||
atomic("a"),
|
||||
and(
|
||||
atomic("b"),
|
||||
or(
|
||||
atomic("b"),
|
||||
atomic("c"),
|
||||
),
|
||||
),
|
||||
);
|
||||
let expression = or(atomic("a"), and(atomic("b"), or(atomic("b"), atomic("c"))));
|
||||
assert_eq!(expression.to_string(), "a ⋁ b ⋀ (b ⋁ c)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expression_c_and_a_or_b_display() {
|
||||
let expression = and(
|
||||
or(
|
||||
atomic("a"),
|
||||
atomic("b"),
|
||||
),
|
||||
atomic("c"),
|
||||
);
|
||||
let expression = and(or(atomic("a"), atomic("b")), atomic("c"));
|
||||
assert_eq!(expression.to_string(), "(a ⋁ b) ⋀ c");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expression_a_implies_b_display() {
|
||||
let expression = implies(
|
||||
atomic("a"),
|
||||
atomic("b"),
|
||||
);
|
||||
let expression = implies(atomic("a"), atomic("b"));
|
||||
assert_eq!(expression.to_string(), "a ➔ b");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expression_not_a_and_b_display() {
|
||||
let expression = not(and(
|
||||
atomic("a"),
|
||||
atomic("b"),
|
||||
));
|
||||
let expression = not(and(atomic("a"), atomic("b")));
|
||||
assert_eq!(expression.to_string(), "¬(a ⋀ b)");
|
||||
}
|
||||
|
||||
@ -301,7 +346,13 @@ mod tests {
|
||||
#[test]
|
||||
fn test_from_str_into_expression_very_complex_parentheses() {
|
||||
let expression: Expression = "(a & b) | c => (d & e)".try_into().unwrap();
|
||||
assert_eq!(expression, implies(or(and(atomic("a"), atomic("b")), atomic("c")), and(atomic("d"), atomic("e"))));
|
||||
assert_eq!(
|
||||
expression,
|
||||
implies(
|
||||
or(and(atomic("a"), atomic("b")), atomic("c")),
|
||||
and(atomic("d"), atomic("e"))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1,8 +1,35 @@
|
||||
use std::rc::Rc;
|
||||
use crate::expressions::expression::Expression;
|
||||
use crate::expressions::operator::BinaryOperator;
|
||||
use std::rc::Rc;
|
||||
|
||||
impl Expression {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn and(self, other: impl Into<Rc<Expression>>) -> Expression {
|
||||
and(self, other)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn or(self, other: impl Into<Rc<Expression>>) -> Expression {
|
||||
or(self, other)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn implies(self, other: impl Into<Rc<Expression>>) -> Expression {
|
||||
implies(self, other)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn not(self) -> Expression {
|
||||
not(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn and<L, R>(left: L, right: R) -> Expression
|
||||
where
|
||||
L: Into<Rc<Expression>>,
|
||||
@ -12,6 +39,7 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn or<L, R>(left: L, right: R) -> Expression
|
||||
where
|
||||
L: Into<Rc<Expression>>,
|
||||
@ -21,6 +49,7 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn implies<L, R>(left: L, right: R) -> Expression
|
||||
where
|
||||
L: Into<Rc<Expression>>,
|
||||
@ -30,20 +59,27 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn binary<L, R>(left: L, operator: BinaryOperator, right: R) -> Expression
|
||||
where
|
||||
L: Into<Rc<Expression>>,
|
||||
R: Into<Rc<Expression>>,
|
||||
{
|
||||
Expression::Binary { left: left.into(), operator, right: right.into() }
|
||||
Expression::Binary {
|
||||
left: left.into(),
|
||||
operator,
|
||||
right: right.into(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn not<T: Into<Rc<Expression>>>(value: T) -> Expression {
|
||||
Expression::Not(value.into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn atomic<T: Into<String>>(value: T) -> Expression {
|
||||
Expression::Atomic(value.into())
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
pub mod expression;
|
||||
pub mod operator;
|
||||
pub mod helpers;
|
||||
pub mod operator;
|
||||
pub mod simplify;
|
||||
pub mod truth_table;
|
||||
pub mod truth_table;
|
||||
|
@ -9,6 +9,7 @@ pub enum BinaryOperator {
|
||||
}
|
||||
|
||||
impl BinaryOperator {
|
||||
#[must_use]
|
||||
pub fn eval(&self, left: bool, right: bool) -> bool {
|
||||
match self {
|
||||
BinaryOperator::And => left && right,
|
||||
@ -16,4 +17,14 @@ impl BinaryOperator {
|
||||
BinaryOperator::Implication => !left || right,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn is_and(&self) -> bool {
|
||||
matches!(self, BinaryOperator::And)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn is_or(&self) -> bool {
|
||||
matches!(self, BinaryOperator::Or)
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -36,16 +36,27 @@ pub enum Sort {
|
||||
}
|
||||
|
||||
impl TruthTable {
|
||||
pub fn new(expression: &Expression, options: TruthTableOptions) -> Self {
|
||||
pub fn new(
|
||||
expression: &Expression,
|
||||
TruthTableOptions {
|
||||
hide,
|
||||
hide_intermediate_steps,
|
||||
sort,
|
||||
}: TruthTableOptions,
|
||||
) -> Self {
|
||||
let mut header = Self::extract_header(expression);
|
||||
let mut truth_matrix = Self::generate_truth_matrix(expression, &header, options.hide, options.hide_intermediate_steps);
|
||||
if !matches!(options.sort, Sort::Default) {
|
||||
Self::sort_matrix(&mut truth_matrix, options.sort);
|
||||
let mut truth_matrix =
|
||||
Self::generate_truth_matrix(expression, &header, hide, hide_intermediate_steps);
|
||||
if !matches!(sort, Sort::Default) {
|
||||
Self::sort_matrix(&mut truth_matrix, sort);
|
||||
}
|
||||
if options.hide_intermediate_steps {
|
||||
if hide_intermediate_steps {
|
||||
header = Self::remove_non_atomic_from_header(&header);
|
||||
}
|
||||
Self { header, truth_matrix }
|
||||
Self {
|
||||
header,
|
||||
truth_matrix,
|
||||
}
|
||||
}
|
||||
|
||||
fn sort_matrix(truth_matrix: &mut TruthMatrix, sort: Sort) {
|
||||
@ -57,7 +68,8 @@ impl TruthTable {
|
||||
}
|
||||
|
||||
fn remove_non_atomic_from_header(header: &[String]) -> Vec<String> {
|
||||
header.iter()
|
||||
header
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(index, s)| {
|
||||
if !Self::contains_operator(s) || index == header.len() - 1 {
|
||||
@ -105,38 +117,62 @@ impl TruthTable {
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_truth_matrix(expression: &Expression, header: &[String], hide: Hide, hide_intermediate: bool) -> TruthMatrix {
|
||||
let mut atomics = expression.get_atomic_values()
|
||||
.into_iter().collect::<Vec<String>>();
|
||||
fn generate_truth_matrix(
|
||||
expression: &Expression,
|
||||
header: &[String],
|
||||
hide: Hide,
|
||||
hide_intermediate: bool,
|
||||
) -> TruthMatrix {
|
||||
let mut atomics = expression
|
||||
.get_atomic_values()
|
||||
.into_iter()
|
||||
.collect::<Vec<String>>();
|
||||
if atomics.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
atomics.sort();
|
||||
Self::truth_combinations(atomics.len() as u32).iter()
|
||||
Self::truth_combinations(atomics.len() as u32)
|
||||
.iter()
|
||||
.filter_map(|combo| {
|
||||
let expression = Self::resolve_expression(expression, &atomics.iter()
|
||||
.enumerate()
|
||||
.map(|(index, value)| (value.clone(), combo[index]))
|
||||
.collect(), header, hide_intermediate);
|
||||
let expression = Self::resolve_expression(
|
||||
expression,
|
||||
&atomics
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, value)| (value.clone(), combo[index]))
|
||||
.collect(),
|
||||
header,
|
||||
hide_intermediate,
|
||||
);
|
||||
match (hide, expression.last()) {
|
||||
(Hide::True, Some(false)) => Some(expression),
|
||||
(Hide::False, Some(true)) => Some(expression),
|
||||
(Hide::None, _) => Some(expression),
|
||||
_ => None,
|
||||
}
|
||||
}).collect()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn truth_combinations(count: u32) -> TruthMatrix {
|
||||
let row_len = 2usize.pow(count);
|
||||
let rows = 0..row_len;
|
||||
rows.map(|index| (0..count).rev()
|
||||
// Just trust me bro
|
||||
.map(|shift| (index >> shift) & 1 == 0).collect()
|
||||
).collect()
|
||||
rows.map(|index| {
|
||||
(0..count)
|
||||
.rev()
|
||||
// Just trust me bro
|
||||
.map(|shift| (index >> shift) & 1 == 0)
|
||||
.collect()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn resolve_expression(expression: &Expression, booleans: &HashMap<String, bool>, header: &[String], hide_intermediate: bool) -> Vec<bool> {
|
||||
fn resolve_expression(
|
||||
expression: &Expression,
|
||||
booleans: &HashMap<String, bool>,
|
||||
header: &[String],
|
||||
hide_intermediate: bool,
|
||||
) -> Vec<bool> {
|
||||
let Some(last_expression) = header.last() else {
|
||||
return vec![];
|
||||
};
|
||||
@ -145,17 +181,23 @@ impl TruthTable {
|
||||
if hide_intermediate {
|
||||
expression_map = Self::remove_intermediate_steps(expression_map, last_expression);
|
||||
}
|
||||
let string_map = expression_map.into_iter()
|
||||
let string_map = expression_map
|
||||
.into_iter()
|
||||
.map(|(key, value)| (key.to_string(), value))
|
||||
.collect::<HashMap<String, bool>>();
|
||||
|
||||
header.iter()
|
||||
header
|
||||
.iter()
|
||||
.filter_map(|s_expr| string_map.get(s_expr).copied())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn remove_intermediate_steps<'a>(expression_map: HashMap<&'a Expression, bool>, top_level_expression: &'a str) -> HashMap<&'a Expression, bool> {
|
||||
expression_map.into_iter()
|
||||
fn remove_intermediate_steps<'a>(
|
||||
expression_map: HashMap<&'a Expression, bool>,
|
||||
top_level_expression: &'a str,
|
||||
) -> HashMap<&'a Expression, bool> {
|
||||
expression_map
|
||||
.into_iter()
|
||||
.filter_map(|(key, value)| {
|
||||
if key.is_atomic() || key.to_string() == top_level_expression {
|
||||
Some((key, value))
|
||||
@ -166,7 +208,10 @@ impl TruthTable {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn _resolve_expression<'a>(expression: &'a Expression, booleans: &HashMap<String, bool>) -> HashMap<&'a Expression, bool> {
|
||||
fn _resolve_expression<'a>(
|
||||
expression: &'a Expression,
|
||||
booleans: &HashMap<String, bool>,
|
||||
) -> HashMap<&'a Expression, bool> {
|
||||
match expression {
|
||||
Expression::Not(expr) => {
|
||||
let mut map = Self::_resolve_expression(expr, booleans);
|
||||
@ -175,12 +220,18 @@ impl TruthTable {
|
||||
}
|
||||
map
|
||||
}
|
||||
Expression::Binary { left, right, operator } => {
|
||||
Expression::Binary {
|
||||
left,
|
||||
right,
|
||||
operator,
|
||||
} => {
|
||||
let left_map = Self::_resolve_expression(left, booleans);
|
||||
let right_map = Self::_resolve_expression(right, booleans);
|
||||
let mut map = left_map;
|
||||
map.extend(right_map);
|
||||
if let (Some(left_value), Some(right_value)) = (map.get(left.as_ref()), map.get(right.as_ref())) {
|
||||
if let (Some(left_value), Some(right_value)) =
|
||||
(map.get(left.as_ref()), map.get(right.as_ref()))
|
||||
{
|
||||
map.insert(expression, operator.eval(*left_value, *right_value));
|
||||
}
|
||||
map
|
||||
@ -209,18 +260,24 @@ mod tests {
|
||||
let expression = and(atomic("A"), atomic("B"));
|
||||
let truth_table = TruthTable::new(&expression, Default::default());
|
||||
assert_eq!(truth_table.header, vec!["A", "B", "A ⋀ B"]);
|
||||
assert_ne!(truth_table.truth_matrix, matrix![
|
||||
true, true, true;
|
||||
false, true, false;
|
||||
true, false, false;
|
||||
false, false, false
|
||||
]);
|
||||
assert_eq!(truth_table.truth_matrix, matrix![
|
||||
true, true, true;
|
||||
true, false, false;
|
||||
false, true, false;
|
||||
false, false, false
|
||||
]);
|
||||
assert_ne!(
|
||||
truth_table.truth_matrix,
|
||||
matrix![
|
||||
true, true, true;
|
||||
false, true, false;
|
||||
true, false, false;
|
||||
false, false, false
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
truth_table.truth_matrix,
|
||||
matrix![
|
||||
true, true, true;
|
||||
true, false, false;
|
||||
false, true, false;
|
||||
false, false, false
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -229,26 +286,56 @@ mod tests {
|
||||
let truth_table = TruthTable::new(&expression, Default::default());
|
||||
let atomics = 3;
|
||||
|
||||
assert_eq!(truth_table.header, vec!["A", "C", "A ⋁ C", "B", "B ⋁ C", "(A ⋁ C) ⋀ (B ⋁ C)"]);
|
||||
assert_eq!(
|
||||
truth_table.header,
|
||||
vec!["A", "C", "A ⋁ C", "B", "B ⋁ C", "(A ⋁ C) ⋀ (B ⋁ C)"]
|
||||
);
|
||||
assert_eq!(truth_table.truth_matrix.len(), 2usize.pow(atomics as u32));
|
||||
assert_eq!(truth_table.truth_matrix[0].len(), 6);
|
||||
assert_eq!(truth_table.truth_matrix[0], vec![true, true, true, true, true, true]);
|
||||
assert_eq!(truth_table.truth_matrix[1], vec![true, false, true, true, true, true]);
|
||||
assert_eq!(truth_table.truth_matrix[2], vec![true, true, true, false, true, true]);
|
||||
assert_eq!(truth_table.truth_matrix[3], vec![true, false, true, false, false, false]);
|
||||
assert_eq!(truth_table.truth_matrix[4], vec![false, true, true, true, true, true]);
|
||||
assert_eq!(truth_table.truth_matrix[5], vec![false, false, false, true, true, false]);
|
||||
assert_eq!(truth_table.truth_matrix[6], vec![false, true, true, false, true, true]);
|
||||
assert_eq!(truth_table.truth_matrix[7], vec![false, false, false, false, false, false]);
|
||||
assert_eq!(
|
||||
truth_table.truth_matrix[0],
|
||||
vec![true, true, true, true, true, true]
|
||||
);
|
||||
assert_eq!(
|
||||
truth_table.truth_matrix[1],
|
||||
vec![true, false, true, true, true, true]
|
||||
);
|
||||
assert_eq!(
|
||||
truth_table.truth_matrix[2],
|
||||
vec![true, true, true, false, true, true]
|
||||
);
|
||||
assert_eq!(
|
||||
truth_table.truth_matrix[3],
|
||||
vec![true, false, true, false, false, false]
|
||||
);
|
||||
assert_eq!(
|
||||
truth_table.truth_matrix[4],
|
||||
vec![false, true, true, true, true, true]
|
||||
);
|
||||
assert_eq!(
|
||||
truth_table.truth_matrix[5],
|
||||
vec![false, false, false, true, true, false]
|
||||
);
|
||||
assert_eq!(
|
||||
truth_table.truth_matrix[6],
|
||||
vec![false, true, true, false, true, true]
|
||||
);
|
||||
assert_eq!(
|
||||
truth_table.truth_matrix[7],
|
||||
vec![false, false, false, false, false, false]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_truth_table_and_hide_intermediate_steps() {
|
||||
let expression = and(atomic("A"), or(atomic("B"), atomic("C")));
|
||||
let truth_table = TruthTable::new(&expression, TruthTableOptions {
|
||||
hide_intermediate_steps: true,
|
||||
..Default::default()
|
||||
});
|
||||
let truth_table = TruthTable::new(
|
||||
&expression,
|
||||
TruthTableOptions {
|
||||
hide_intermediate_steps: true,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
assert_eq!(truth_table.header, vec!["A", "B", "C", "A ⋀ (B ⋁ C)"]);
|
||||
for (index, row) in truth_table.truth_matrix.iter().enumerate() {
|
||||
assert_eq!(row.len(), 4, "Row at {index}: {:?}", row);
|
||||
@ -264,12 +351,15 @@ mod tests {
|
||||
false, false, false
|
||||
];
|
||||
TruthTable::sort_matrix(&mut matrix, Sort::TrueFirst);
|
||||
assert_eq!(matrix, matrix![
|
||||
true, true, true;
|
||||
false, true, true;
|
||||
true, false, false;
|
||||
false, false, false
|
||||
]);
|
||||
assert_eq!(
|
||||
matrix,
|
||||
matrix![
|
||||
true, true, true;
|
||||
false, true, true;
|
||||
true, false, false;
|
||||
false, false, false
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -281,12 +371,15 @@ mod tests {
|
||||
true, false, false
|
||||
];
|
||||
TruthTable::sort_matrix(&mut matrix, Sort::TrueFirst);
|
||||
assert_eq!(matrix, matrix![
|
||||
false, true, false;
|
||||
false, true, false;
|
||||
true, false, false;
|
||||
true, false, false
|
||||
]);
|
||||
assert_eq!(
|
||||
matrix,
|
||||
matrix![
|
||||
false, true, false;
|
||||
false, true, false;
|
||||
true, false, false;
|
||||
true, false, false
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -298,12 +391,15 @@ mod tests {
|
||||
false, false, false
|
||||
];
|
||||
TruthTable::sort_matrix(&mut matrix, Sort::Default);
|
||||
assert_eq!(matrix, matrix![
|
||||
true, true, true;
|
||||
true, false, false;
|
||||
false, true, true;
|
||||
false, false, false
|
||||
]);
|
||||
assert_eq!(
|
||||
matrix,
|
||||
matrix![
|
||||
true, true, true;
|
||||
true, false, false;
|
||||
false, true, true;
|
||||
false, false, false
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -315,12 +411,15 @@ mod tests {
|
||||
false, false, false
|
||||
];
|
||||
TruthTable::sort_matrix(&mut matrix, Sort::FalseFirst);
|
||||
assert_eq!(matrix, matrix![
|
||||
true, false, false;
|
||||
false, false, false;
|
||||
true, true, true;
|
||||
false, true, true
|
||||
]);
|
||||
assert_eq!(
|
||||
matrix,
|
||||
matrix![
|
||||
true, false, false;
|
||||
false, false, false;
|
||||
true, true, true;
|
||||
false, true, true
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -333,20 +432,20 @@ mod tests {
|
||||
let matrix = TruthTable::generate_truth_matrix(
|
||||
&and(atomic("A"), atomic("B")),
|
||||
&["A".into(), "B".into(), "A ⋀ B".into()],
|
||||
Hide::True, false,
|
||||
Hide::True,
|
||||
false,
|
||||
);
|
||||
assert_eq!(expected, matrix);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hide_false_values() {
|
||||
let expected = matrix![
|
||||
true, true, true
|
||||
];
|
||||
let expected = matrix![true, true, true];
|
||||
let matrix = TruthTable::generate_truth_matrix(
|
||||
&and(atomic("A"), atomic("B")),
|
||||
&["A".into(), "B".into(), "A ⋀ B".into()],
|
||||
Hide::False, false,
|
||||
Hide::False,
|
||||
false,
|
||||
);
|
||||
assert_eq!(expected, matrix);
|
||||
}
|
||||
@ -362,7 +461,8 @@ mod tests {
|
||||
let matrix = TruthTable::generate_truth_matrix(
|
||||
&and(atomic("A"), atomic("B")),
|
||||
&["A".into(), "B".into(), "A ⋀ B".into()],
|
||||
Hide::None, false,
|
||||
Hide::None,
|
||||
false,
|
||||
);
|
||||
assert_eq!(expected, matrix);
|
||||
}
|
||||
@ -370,34 +470,46 @@ mod tests {
|
||||
#[test]
|
||||
fn test_truth_combinations_2() {
|
||||
let combinations = TruthTable::truth_combinations(2);
|
||||
assert_eq!(combinations, matrix![
|
||||
true, true;
|
||||
true, false;
|
||||
false, true;
|
||||
false, false
|
||||
]);
|
||||
assert_eq!(
|
||||
combinations,
|
||||
matrix![
|
||||
true, true;
|
||||
true, false;
|
||||
false, true;
|
||||
false, false
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_truth_combinations_3() {
|
||||
let combinations = TruthTable::truth_combinations(3);
|
||||
assert_eq!(combinations, matrix![
|
||||
true, true, true;
|
||||
true, true, false;
|
||||
true, false, true;
|
||||
true, false, false;
|
||||
false, true, true;
|
||||
false, true, false;
|
||||
false, false, true;
|
||||
false, false, false
|
||||
]);
|
||||
assert_eq!(
|
||||
combinations,
|
||||
matrix![
|
||||
true, true, true;
|
||||
true, true, false;
|
||||
true, false, true;
|
||||
true, false, false;
|
||||
false, true, true;
|
||||
false, true, false;
|
||||
false, false, true;
|
||||
false, false, false
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_resolve_expression_hide_intermediate_steps() {
|
||||
let expression = and(atomic("A"), or(atomic("B"), atomic("C")));
|
||||
let booleans = map!["A".into() => true, "B".into() => false, "C".into() => true];
|
||||
let header = vec!["A".into(), "B".into(), "C".into(), "B ⋁ C".into(), "A ⋀ (B ⋁ C)".into()];
|
||||
let header = vec![
|
||||
"A".into(),
|
||||
"B".into(),
|
||||
"C".into(),
|
||||
"B ⋁ C".into(),
|
||||
"A ⋀ (B ⋁ C)".into(),
|
||||
];
|
||||
let values = TruthTable::resolve_expression(&expression, &booleans, &header, true);
|
||||
assert_eq!(values.len(), 4);
|
||||
assert_eq!(values, vec![true, false, true, true]);
|
||||
@ -443,7 +555,12 @@ mod tests {
|
||||
fn test_resolve_expression_even_more_duplicates() {
|
||||
let expression = and(atomic("A"), and(atomic("A"), and(atomic("A"), atomic("A"))));
|
||||
let booleans = HashMap::from([("A".into(), true)]);
|
||||
let header = vec!["A".into(), "A ⋀ A".into(), "A ⋀ A ⋀ A".into(), "A ⋀ A ⋀ A ⋀ A".into()];
|
||||
let header = vec![
|
||||
"A".into(),
|
||||
"A ⋀ A".into(),
|
||||
"A ⋀ A ⋀ A".into(),
|
||||
"A ⋀ A ⋀ A ⋀ A".into(),
|
||||
];
|
||||
let values = TruthTable::resolve_expression(&expression, &booleans, &header, false);
|
||||
assert_eq!(values, vec![true, true, true, true]);
|
||||
}
|
||||
@ -453,15 +570,20 @@ mod tests {
|
||||
let expression = and(atomic("A"), and(atomic("A"), and(atomic("A"), atomic("A"))));
|
||||
let booleans = HashMap::from([("A".into(), true)]);
|
||||
let values = TruthTable::_resolve_expression(&expression, &booleans);
|
||||
assert_eq!(values, HashMap::from([
|
||||
(&atomic("A"), true),
|
||||
(&and(atomic("A"), atomic("A")), true),
|
||||
(&and(atomic("A"), and(atomic("A"), atomic("A"))), true),
|
||||
(&and(atomic("A"), and(atomic("A"), and(atomic("A"), atomic("A")))), true),
|
||||
]));
|
||||
assert_eq!(
|
||||
values,
|
||||
HashMap::from([
|
||||
(&atomic("A"), true),
|
||||
(&and(atomic("A"), atomic("A")), true),
|
||||
(&and(atomic("A"), and(atomic("A"), atomic("A"))), true),
|
||||
(
|
||||
&and(atomic("A"), and(atomic("A"), and(atomic("A"), atomic("A")))),
|
||||
true
|
||||
),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_atomic_expression() {
|
||||
let expression = atomic("A");
|
||||
@ -501,7 +623,10 @@ mod tests {
|
||||
fn test_complex_expression() {
|
||||
let expression = implies(and(atomic("A"), atomic("B")), or(atomic("C"), atomic("D")));
|
||||
let header = TruthTable::extract_header(&expression);
|
||||
assert_eq!(header, vec!["A", "B", "A ⋀ B", "C", "D", "C ⋁ D", "A ⋀ B ➔ (C ⋁ D)"]);
|
||||
assert_eq!(
|
||||
header,
|
||||
vec!["A", "B", "A ⋀ B", "C", "D", "C ⋁ D", "A ⋀ B ➔ C ⋁ D"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -513,8 +638,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_somewhat_equal() {
|
||||
let expression = and(atomic("A"), and(or(not(atomic("A")), atomic("B")), atomic("A")));
|
||||
let expression = and(
|
||||
atomic("A"),
|
||||
and(or(not(atomic("A")), atomic("B")), atomic("A")),
|
||||
);
|
||||
let header = TruthTable::extract_header(&expression);
|
||||
assert_eq!(header, vec!["A", "¬A", "B", "¬A ⋁ B", "(¬A ⋁ B) ⋀ A", "A ⋀ (¬A ⋁ B) ⋀ A"]);
|
||||
assert_eq!(
|
||||
header,
|
||||
vec!["A", "¬A", "B", "¬A ⋁ B", "(¬A ⋁ B) ⋀ A", "A ⋀ (¬A ⋁ B) ⋀ A"]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,19 @@
|
||||
use lib::axum::app::AppBuilder;
|
||||
use tower_http::cors::CorsLayer;
|
||||
|
||||
use crate::routing::routes::*;
|
||||
use crate::routing::routes::index::not_found;
|
||||
use crate::routing::routes::*;
|
||||
|
||||
mod config;
|
||||
mod expressions;
|
||||
mod parsing;
|
||||
mod routing;
|
||||
mod config;
|
||||
mod utils;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
AppBuilder::new()
|
||||
.routes(&[index::router(), simplify::router(), table::router()])
|
||||
.routes([index::router(), simplify::router(), table::router()])
|
||||
.fallback(not_found)
|
||||
.cors(CorsLayer::permissive())
|
||||
.serve()
|
||||
|
@ -1,15 +1,15 @@
|
||||
use lib::nom::combinators::{exhausted, parenthesized, trim};
|
||||
use lib::nom::util::IntoResult;
|
||||
use lib::traits::IntoResult;
|
||||
use nom::branch::alt;
|
||||
use nom::bytes::complete::{tag, take_while, take_while1};
|
||||
use nom::character::complete::char;
|
||||
use nom::combinator::{opt, peek};
|
||||
use nom::combinator::{map, opt, peek};
|
||||
use nom::error::Error;
|
||||
use nom::IResult;
|
||||
use nom::sequence::{pair, preceded};
|
||||
use nom::IResult;
|
||||
|
||||
use crate::expressions::expression::Expression;
|
||||
use crate::expressions::helpers::{and, atomic, implies, not, or};
|
||||
use crate::expressions::helpers::atomic;
|
||||
|
||||
pub fn parse_expression(input: &str) -> Result<Expression, nom::Err<Error<&str>>> {
|
||||
exhausted(_parse_expression)(input).into_result()
|
||||
@ -17,7 +17,9 @@ pub fn parse_expression(input: &str) -> Result<Expression, nom::Err<Error<&str>>
|
||||
|
||||
fn _parse_expression(input: &str) -> IResult<&str, Expression> {
|
||||
let (remaining, atomic_expression) = left_hand_side(input)?;
|
||||
if let (remaining, Some(complex_expression)) = opt(expression(atomic_expression.clone()))(remaining)? {
|
||||
if let (remaining, Some(complex_expression)) =
|
||||
opt(expression(atomic_expression.clone()))(remaining)?
|
||||
{
|
||||
Ok((remaining, complex_expression))
|
||||
} else {
|
||||
Ok((remaining, atomic_expression))
|
||||
@ -25,11 +27,7 @@ fn _parse_expression(input: &str) -> IResult<&str, Expression> {
|
||||
}
|
||||
|
||||
fn left_hand_side(input: &str) -> IResult<&str, Expression> {
|
||||
alt((
|
||||
value,
|
||||
not_expression,
|
||||
parenthesized_expression
|
||||
))(input)
|
||||
alt((value, not_expression, parenthesized_expression))(input)
|
||||
}
|
||||
|
||||
fn expression<'a>(previous: Expression) -> impl Fn(&'a str) -> IResult<&'a str, Expression> {
|
||||
@ -43,21 +41,21 @@ fn expression<'a>(previous: Expression) -> impl Fn(&'a str) -> IResult<&'a str,
|
||||
}
|
||||
}
|
||||
|
||||
fn operator_combinators(expression: Expression) -> impl Fn(&str) -> IResult<&str, Expression> {
|
||||
move |input: &str| {
|
||||
alt((
|
||||
implication_expression(expression.clone()),
|
||||
or_expression(expression.clone()),
|
||||
and_expression(expression.clone()),
|
||||
not_expression,
|
||||
))(input)
|
||||
}
|
||||
fn operator_combinators<'a>(
|
||||
expression: Expression,
|
||||
) -> impl FnMut(&'a str) -> IResult<&'a str, Expression> {
|
||||
alt((
|
||||
implication_expression(expression.clone()),
|
||||
or_expression(expression.clone()),
|
||||
and_expression(expression.clone()),
|
||||
not_expression,
|
||||
))
|
||||
}
|
||||
|
||||
fn parenthesized_expression(input: &str) -> IResult<&str, Expression> {
|
||||
parenthesized(|input| {
|
||||
let (remaining, atomic) = left_hand_side(input)?;
|
||||
let (remaining, expression) = operator_combinators(atomic)(remaining)?;
|
||||
let (remaining, atomic) = trim(left_hand_side)(input)?;
|
||||
let (remaining, expression) = trim(operator_combinators(atomic))(remaining)?;
|
||||
if peek(trim(char(')')))(remaining).is_ok() {
|
||||
Ok((remaining, expression))
|
||||
} else {
|
||||
@ -66,15 +64,10 @@ fn parenthesized_expression(input: &str) -> IResult<&str, Expression> {
|
||||
})(input)
|
||||
}
|
||||
|
||||
fn and_expression<'a>(previous: Expression) -> impl Fn(&'a str) -> IResult<&'a str, Expression> {
|
||||
move |input: &'a str| {
|
||||
preceded(
|
||||
trim(char('&')),
|
||||
left_hand_side,
|
||||
)(input).map(|(remaining, right)| {
|
||||
(remaining, and(previous.clone(), right))
|
||||
})
|
||||
}
|
||||
fn and_expression<'a>(previous: Expression) -> impl FnMut(&'a str) -> IResult<&'a str, Expression> {
|
||||
map(preceded(trim(char('&')), left_hand_side), move |right| {
|
||||
previous.clone().and(right)
|
||||
})
|
||||
}
|
||||
|
||||
fn complete_and(input: &str) -> IResult<&str, Expression> {
|
||||
@ -82,18 +75,11 @@ fn complete_and(input: &str) -> IResult<&str, Expression> {
|
||||
and_expression(atomic.clone())(remaining)
|
||||
}
|
||||
|
||||
fn or_expression<'a>(previous: Expression) -> impl Fn(&'a str) -> IResult<&'a str, Expression> {
|
||||
move |input: &'a str| {
|
||||
preceded(
|
||||
trim(char('|')),
|
||||
alt((
|
||||
complete_and,
|
||||
left_hand_side,
|
||||
)),
|
||||
)(input).map(|(remaining, right)| {
|
||||
(remaining, or(previous.clone(), right))
|
||||
})
|
||||
}
|
||||
fn or_expression<'a>(previous: Expression) -> impl FnMut(&'a str) -> IResult<&'a str, Expression> {
|
||||
map(
|
||||
preceded(trim(char('|')), alt((complete_and, left_hand_side))),
|
||||
move |right| previous.clone().or(right),
|
||||
)
|
||||
}
|
||||
|
||||
fn complete_or(input: &str) -> IResult<&str, Expression> {
|
||||
@ -101,39 +87,33 @@ fn complete_or(input: &str) -> IResult<&str, Expression> {
|
||||
or_expression(atomic.clone())(remaining)
|
||||
}
|
||||
|
||||
fn implication_expression<'a>(previous: Expression) -> impl Fn(&'a str) -> IResult<&'a str, Expression> {
|
||||
move |input: &'a str| {
|
||||
fn implication_expression<'a>(
|
||||
previous: Expression,
|
||||
) -> impl FnMut(&'a str) -> IResult<&'a str, Expression> {
|
||||
map(
|
||||
preceded(
|
||||
trim(tag("=>")),
|
||||
alt((
|
||||
complete_and,
|
||||
complete_or,
|
||||
left_hand_side,
|
||||
)),
|
||||
)(input).map(|(remaining, right)| {
|
||||
(remaining, implies(previous.clone(), right))
|
||||
})
|
||||
}
|
||||
alt((complete_and, complete_or, left_hand_side)),
|
||||
),
|
||||
move |right| previous.clone().implies(right),
|
||||
)
|
||||
}
|
||||
|
||||
fn not_expression(input: &str) -> IResult<&str, Expression> {
|
||||
preceded(
|
||||
char('!'),
|
||||
left_hand_side,
|
||||
)(input).map(|(remaining, right)| {
|
||||
(remaining, not(right))
|
||||
})
|
||||
map(preceded(char('!'), left_hand_side), Expression::not)(input)
|
||||
}
|
||||
|
||||
fn value(input: &str) -> IResult<&str, Expression> {
|
||||
pair(
|
||||
take_while1(|c: char| c.is_ascii_alphabetic()),
|
||||
take_while(|c: char| c.is_ascii_alphanumeric() || c == '_'),
|
||||
)(input)
|
||||
.map(|(remaining, (first, rest))| {
|
||||
map(
|
||||
pair(
|
||||
take_while1(|c: char| c.is_ascii_alphabetic()),
|
||||
take_while(|c: char| c.is_ascii_alphanumeric() || c == '_'),
|
||||
),
|
||||
|(first, rest)| {
|
||||
let value = format!("{first}{rest}");
|
||||
(remaining, atomic(value))
|
||||
})
|
||||
atomic(value)
|
||||
},
|
||||
)(input)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -144,49 +124,62 @@ mod tests {
|
||||
fn test_parse() {
|
||||
let input = "a & b => c";
|
||||
let result = super::parse_expression(input);
|
||||
assert_eq!(result, Ok(implies(and(atomic("a"), atomic("b")), atomic("c"))));
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok(implies(and(atomic("a"), atomic("b")), atomic("c")))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_complex() {
|
||||
let input = "a => b | !(!c | d & e) => b";
|
||||
let result = super::parse_expression(input);
|
||||
assert_eq!(result, Ok(implies(
|
||||
implies(
|
||||
atomic("a"),
|
||||
or(
|
||||
atomic("b"),
|
||||
not(
|
||||
or(
|
||||
not(atomic("c")),
|
||||
and(atomic("d"), atomic("e")),
|
||||
)
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok(implies(
|
||||
implies(
|
||||
atomic("a"),
|
||||
or(
|
||||
atomic("b"),
|
||||
not(or(not(atomic("c")), and(atomic("d"), atomic("e")),)),
|
||||
),
|
||||
),
|
||||
),
|
||||
atomic("b"),
|
||||
)));
|
||||
atomic("b"),
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_operator_weight() {
|
||||
let input = "A & B | C => D | E & F";
|
||||
let result = super::parse_expression(input);
|
||||
assert_eq!(result, Ok(implies(or(and(atomic("A"), atomic("B")), atomic("C")), or(atomic("D"), and(atomic("E"), atomic("F"))))));
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok(implies(
|
||||
or(and(atomic("A"), atomic("B")), atomic("C")),
|
||||
or(atomic("D"), and(atomic("E"), atomic("F")))
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_implies_chain() {
|
||||
let input = "a => b => c";
|
||||
let result = super::parse_expression(input);
|
||||
assert_eq!(result, Ok(implies(implies(atomic("a"), atomic("b")), atomic("c"))));
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok(implies(implies(atomic("a"), atomic("b")), atomic("c")))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_parentheses() {
|
||||
let input = "a & (b => c)";
|
||||
let result = super::parse_expression(input);
|
||||
assert_eq!(result, Ok(and(atomic("a"), implies(atomic("b"), atomic("c")))));
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok(and(atomic("a"), implies(atomic("b"), atomic("c"))))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -228,7 +221,10 @@ mod tests {
|
||||
fn test_expression_with_not_inside_parentheses() {
|
||||
let input = "a & !(b | c)";
|
||||
let result = super::parse_expression(input);
|
||||
assert_eq!(result, Ok(and(atomic("a"), not(or(atomic("b"), atomic("c"))))));
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok(and(atomic("a"), not(or(atomic("b"), atomic("c")))))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -277,7 +273,19 @@ mod tests {
|
||||
fn test_or_chain() {
|
||||
let input = "a | b | c | d | e | f | g";
|
||||
let result = super::parse_expression(input);
|
||||
assert_eq!(result, Ok(or(or(or(or(or(or(atomic("a"), atomic("b")), atomic("c")), atomic("d")), atomic("e")), atomic("f")), atomic("g"))));
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok(or(
|
||||
or(
|
||||
or(
|
||||
or(or(or(atomic("a"), atomic("b")), atomic("c")), atomic("d")),
|
||||
atomic("e")
|
||||
),
|
||||
atomic("f")
|
||||
),
|
||||
atomic("g")
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -300,7 +308,10 @@ mod tests {
|
||||
let expression = atomic("a");
|
||||
let input = " & b | c";
|
||||
let result = super::expression(expression)(input);
|
||||
assert_eq!(result, Ok(("", or(and(atomic("a"), atomic("b")), atomic("c")))));
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok(("", or(and(atomic("a"), atomic("b")), atomic("c"))))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -308,7 +319,13 @@ mod tests {
|
||||
let expression = atomic("a");
|
||||
let input = " & b | c => d";
|
||||
let result = super::expression(expression)(input);
|
||||
assert_eq!(result, Ok(("", implies(or(and(atomic("a"), atomic("b")), atomic("c")), atomic("d")))));
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok((
|
||||
"",
|
||||
implies(or(and(atomic("a"), atomic("b")), atomic("c")), atomic("d"))
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -316,14 +333,26 @@ mod tests {
|
||||
let expression = atomic("a");
|
||||
let input = " & (b | c) => d";
|
||||
let result = super::expression(expression)(input);
|
||||
assert_eq!(result, Ok(("", implies(and(atomic("a"), or(atomic("b"), atomic("c"))), atomic("d")))));
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok((
|
||||
"",
|
||||
implies(and(atomic("a"), or(atomic("b"), atomic("c"))), atomic("d"))
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expression_parentheses_and() {
|
||||
let input = "(a & b) | (c & d)";
|
||||
let result = super::_parse_expression(input);
|
||||
assert_eq!(result, Ok(("", or(and(atomic("a"), atomic("b")), and(atomic("c"), atomic("d"))))));
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok((
|
||||
"",
|
||||
or(and(atomic("a"), atomic("b")), and(atomic("c"), atomic("d")))
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -331,7 +360,16 @@ mod tests {
|
||||
let expression = atomic("a");
|
||||
let input = " & b | (c => d)";
|
||||
let result = super::expression(expression)(input);
|
||||
assert_eq!(result, Ok(("", or(and(atomic("a"), atomic("b")), implies(atomic("c"), atomic("d"))))));
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok((
|
||||
"",
|
||||
or(
|
||||
and(atomic("a"), atomic("b")),
|
||||
implies(atomic("c"), atomic("d"))
|
||||
)
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -339,7 +377,16 @@ mod tests {
|
||||
let expression = atomic("a");
|
||||
let input = " & (b | (c => d))";
|
||||
let result = super::expression(expression)(input);
|
||||
assert_eq!(result, Ok(("", and(atomic("a"), or(atomic("b"), implies(atomic("c"), atomic("d")))))));
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok((
|
||||
"",
|
||||
and(
|
||||
atomic("a"),
|
||||
or(atomic("b"), implies(atomic("c"), atomic("d")))
|
||||
)
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -361,6 +408,9 @@ mod tests {
|
||||
fn test_parenthesized_expression_3_atomics() {
|
||||
let input = "(A | B | C)";
|
||||
let result = super::parenthesized_expression(input);
|
||||
assert_eq!(result, Ok(("", or(or(atomic("A"), atomic("B")), atomic("C")))));
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok(("", or(or(atomic("A"), atomic("B")), atomic("C"))))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
pub(crate) mod expression_parser;
|
||||
pub(crate) mod expression_parser;
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,5 +1,5 @@
|
||||
use axum::Json;
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use axum::Json;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize, Default)]
|
||||
|
@ -1,4 +1,4 @@
|
||||
pub(crate) mod response;
|
||||
pub(crate) mod error;
|
||||
pub(crate) mod options;
|
||||
pub(crate) mod response;
|
||||
pub(crate) mod routes;
|
||||
pub(crate) mod options;
|
@ -1,15 +1,12 @@
|
||||
use serde::Deserialize;
|
||||
use crate::expressions::truth_table::{Hide, Sort};
|
||||
use crate::utils::serialize::{ret_true, deserialize_bool};
|
||||
use crate::utils::serialize::{deserialize_bool, ret_true};
|
||||
use serde::Deserialize;
|
||||
|
||||
// TODO deserialize_bool should not be necessary
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SimplifyOptions {
|
||||
#[serde(
|
||||
default = "ret_true",
|
||||
deserialize_with = "deserialize_bool"
|
||||
)]
|
||||
#[serde(default = "ret_true", deserialize_with = "deserialize_bool")]
|
||||
pub simplify: bool,
|
||||
#[serde(default, deserialize_with = "deserialize_bool")]
|
||||
pub ignore_case: bool,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use lib::derive::IntoResponse;
|
||||
use lib::into_response_derive::IntoResponse;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::expressions::expression::Expression;
|
||||
@ -16,7 +16,11 @@ pub struct Operation {
|
||||
impl Operation {
|
||||
pub fn new(before: &Expression, after: &Expression, law: Law) -> Option<Self> {
|
||||
if before != after {
|
||||
Some(Self { before: before.to_string(), after: after.to_string(), law })
|
||||
Some(Self {
|
||||
before: before.to_string(),
|
||||
after: after.to_string(),
|
||||
law,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -50,4 +54,4 @@ impl IsValidResponse {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TruthTableResponse {
|
||||
pub truth_table: TruthTable,
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use axum::extract::Path;
|
||||
use axum::http::StatusCode;
|
||||
use axum::Json;
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use axum::Json;
|
||||
use lib::router;
|
||||
use serde::Serialize;
|
||||
|
||||
@ -40,7 +40,7 @@ async fn open_api() -> impl IntoResponse {
|
||||
async fn is_valid(Path(path): Path<String>) -> Response {
|
||||
match Expression::try_from(path.as_str()) {
|
||||
Ok(_) => IsValidResponse::valid().into_response(),
|
||||
Err(error) => Error::new(error.to_string(), ErrorKind::InvalidExpression).into_response()
|
||||
Err(error) => Error::new(error.to_string(), ErrorKind::InvalidExpression).into_response(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
pub(crate) mod index;
|
||||
|
||||
pub(crate) mod simplify;
|
||||
|
||||
pub(crate) mod table;
|
||||
|
@ -9,10 +9,13 @@ use crate::routing::error::{Error, ErrorKind};
|
||||
use crate::routing::options::{SimplifyAndTableOptions, SimplifyOptions};
|
||||
use crate::routing::response::SimplifyResponse;
|
||||
|
||||
router!("/simplify", routes!(
|
||||
get "/:exp" => simplify,
|
||||
get "/table/:exp" => simplify_and_table
|
||||
));
|
||||
router!(
|
||||
"/simplify",
|
||||
routes!(
|
||||
get "/:exp" => simplify,
|
||||
get "/table/:exp" => simplify_and_table
|
||||
)
|
||||
);
|
||||
|
||||
async fn simplify(Path(path): Path<String>, Query(query): Query<SimplifyOptions>) -> Response {
|
||||
match Expression::try_from(path.as_str()) {
|
||||
@ -28,15 +31,21 @@ async fn simplify(Path(path): Path<String>, Query(query): Query<SimplifyOptions>
|
||||
operations,
|
||||
expression,
|
||||
truth_table: None,
|
||||
}.into_response()
|
||||
}
|
||||
Err(error) => {
|
||||
(StatusCode::BAD_REQUEST, Error::new(error.to_string(), ErrorKind::InvalidExpression)).into_response()
|
||||
}
|
||||
.into_response()
|
||||
}
|
||||
Err(error) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Error::new(error.to_string(), ErrorKind::InvalidExpression),
|
||||
)
|
||||
.into_response(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn simplify_and_table(Path(path): Path<String>, Query(query): Query<SimplifyAndTableOptions>) -> Response {
|
||||
async fn simplify_and_table(
|
||||
Path(path): Path<String>,
|
||||
Query(query): Query<SimplifyAndTableOptions>,
|
||||
) -> Response {
|
||||
match Expression::try_from(path.as_str()) {
|
||||
Ok(mut expression) => {
|
||||
let before = expression.to_string();
|
||||
@ -51,10 +60,13 @@ async fn simplify_and_table(Path(path): Path<String>, Query(query): Query<Simpli
|
||||
operations,
|
||||
expression,
|
||||
truth_table: Some(truth_table),
|
||||
}.into_response()
|
||||
}
|
||||
Err(error) => {
|
||||
(StatusCode::BAD_REQUEST, Error::new(error.to_string(), ErrorKind::InvalidExpression)).into_response()
|
||||
}
|
||||
.into_response()
|
||||
}
|
||||
Err(error) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Error::new(error.to_string(), ErrorKind::InvalidExpression),
|
||||
)
|
||||
.into_response(),
|
||||
}
|
||||
}
|
||||
|
@ -9,16 +9,24 @@ use crate::routing::error::{Error, ErrorKind};
|
||||
use crate::routing::options::TruthTableOptions;
|
||||
use crate::routing::response::TruthTableResponse;
|
||||
|
||||
router!("/table", routes!(
|
||||
get "/:exp" => table
|
||||
));
|
||||
router!(
|
||||
"/table",
|
||||
routes!(
|
||||
get "/:exp" => table
|
||||
)
|
||||
);
|
||||
|
||||
// TODO Expression as input in body
|
||||
async fn table(Path(value): Path<String>, Query(query): Query<TruthTableOptions>) -> Response {
|
||||
match Expression::try_from(value) {
|
||||
Ok(expression) => {
|
||||
TruthTableResponse { truth_table: TruthTable::new(&expression, query) }.into_response()
|
||||
Ok(expression) => TruthTableResponse {
|
||||
truth_table: TruthTable::new(&expression, query),
|
||||
}
|
||||
Err(e) => (StatusCode::BAD_REQUEST, Error::new(e.to_string(), ErrorKind::InvalidExpression)).into_response(),
|
||||
.into_response(),
|
||||
Err(e) => (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Error::new(e.to_string(), ErrorKind::InvalidExpression),
|
||||
)
|
||||
.into_response(),
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,11 @@ macro_rules! load_html {
|
||||
#[cfg(debug_assertions)]
|
||||
macro_rules! absolute_path {
|
||||
($filename:literal) => {
|
||||
concat!(env!("CARGO_MANIFEST_DIR"), "/src/resources/static/", $filename)
|
||||
concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/src/resources/static/",
|
||||
$filename
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
pub mod axum;
|
||||
pub mod serialize;
|
||||
pub mod axum;
|
@ -4,8 +4,9 @@ pub(crate) const fn ret_true() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
pub(crate) fn deserialize_bool<'de, D: Deserializer<'de>>(deserializer: D) -> Result<bool, D::Error> {
|
||||
pub(crate) fn deserialize_bool<'de, D: Deserializer<'de>>(
|
||||
deserializer: D,
|
||||
) -> Result<bool, D::Error> {
|
||||
let s: &str = Deserialize::deserialize(deserializer)?;
|
||||
|
||||
match s {
|
||||
@ -13,4 +14,4 @@ pub(crate) fn deserialize_bool<'de, D: Deserializer<'de>>(deserializer: D) -> Re
|
||||
"false" => Ok(false),
|
||||
_ => Err(de::Error::unknown_variant(s, &["true", "false"])),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user