Compare commits
30 Commits
Author | SHA1 | Date |
---|---|---|
Benedikt Peetz | bbd6bd60bb | |
Benedikt Peetz | ca0efecfde | |
Benedikt Peetz | 051e15b0ed | |
Benedikt Peetz | a33aa053d2 | |
Benedikt Peetz | 5d3afa3c5a | |
Benedikt Peetz | 527727cbd3 | |
Benedikt Peetz | 5a3f337057 | |
Benedikt Peetz | d27eea711a | |
Benedikt Peetz | 4feae61a76 | |
Benedikt Peetz | 9d14d2e061 | |
Benedikt Peetz | ecb8d4d2f0 | |
Benedikt Peetz | 6a4c224c64 | |
Benedikt Peetz | 5dbc5e676d | |
Benedikt Peetz | 31493968b5 | |
Benedikt Peetz | c2ef7d0a59 | |
Benedikt Peetz | df146b3fa6 | |
Benedikt Peetz | b750bb8495 | |
Benedikt Peetz | d57beeebd4 | |
Benedikt Peetz | ec11a129bd | |
Benedikt Peetz | ddd9255c2e | |
Benedikt Peetz | 07c38468ce | |
Benedikt Peetz | c7b8fb3f86 | |
Benedikt Peetz | 0a60c894d2 | |
Benedikt Peetz | 86427b0c1a | |
Benedikt Peetz | 0774ac2124 | |
Benedikt Peetz | 475e7edadf | |
Benedikt Peetz | 366efd8331 | |
Benedikt Peetz | 1e078fa46d | |
Benedikt Peetz | 06c61ade54 | |
Benedikt Peetz | 6bed2a843a |
|
@ -25,7 +25,3 @@
|
|||
# dev env
|
||||
.direnv
|
||||
.ccls-cache
|
||||
|
||||
|
||||
# trixy is a library
|
||||
Cargo.lock
|
||||
|
|
|
@ -0,0 +1,426 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diff"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.155"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
||||
|
||||
[[package]]
|
||||
name = "pretty_assertions"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66"
|
||||
dependencies = [
|
||||
"diff",
|
||||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8746739f11d39ce5ad5c2520a9b75285310dbfe78c541ccf832d38615765aec0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"getopts",
|
||||
"memchr",
|
||||
"pulldown-cmark-escape",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark-escape"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trixy"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"convert_case",
|
||||
"libc",
|
||||
"log",
|
||||
"pretty_assertions",
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
"pulldown-cmark",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
|
||||
dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
21
Cargo.toml
21
Cargo.toml
|
@ -20,29 +20,34 @@
|
|||
|
||||
[package]
|
||||
name = "trixy"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
edition = "2021"
|
||||
description = "A rust crate used to generate multi-language apis for your application"
|
||||
license = "LGPL-3.0-or-later"
|
||||
repository = "https://git.nerdcult.net/trinitrix/trixy"
|
||||
categories = ["config", "compilers", "development-tools::ffi"]
|
||||
keywords = ["ffi", "c-ffi", "api"]
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.4", features = ["derive"], optional = true }
|
||||
convert_case = { version = "0.6.0", optional = true }
|
||||
proc-macro2 = { version = "1.0.79", optional = true }
|
||||
quote = { version = "1.0.35", optional = true }
|
||||
syn = { version = "2.0.55", features = [
|
||||
proc-macro2 = { version = "1.0.82", optional = true }
|
||||
quote = { version = "1.0.36", optional = true }
|
||||
syn = { version = "2.0.64", features = [
|
||||
"extra-traits",
|
||||
"full",
|
||||
"parsing",
|
||||
], optional = true }
|
||||
thiserror = { version = "1.0.58", optional = true }
|
||||
pulldown-cmark = { version = "0.10.0", optional = true }
|
||||
thiserror = { version = "1.0.61", optional = true }
|
||||
pulldown-cmark = { version = "0.11.0", optional = true }
|
||||
# macros
|
||||
prettyplease = { version = "0.2.17", optional = true }
|
||||
prettyplease = { version = "0.2.20", optional = true }
|
||||
|
||||
# parser
|
||||
regex = { version = "1.10.4", optional = true }
|
||||
|
||||
# types
|
||||
libc = { version = "0.2.153", optional = true }
|
||||
libc = { version = "0.2.155", optional = true }
|
||||
log = { version = "0.4.21", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
<!--
|
||||
Copyright (C) 2023 - 2024:
|
||||
The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||
SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
This file is part of the Trixy crate for Trinitrix.
|
||||
|
||||
Trixy is free software: you can redistribute it and/or modify
|
||||
it under the terms of the Lesser GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
and the Lesser GNU General Public License along with this program.
|
||||
If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file. See [conventional commits](https://www.conventionalcommits.org/) for commit guidelines.
|
||||
|
||||
______________________________________________________________________
|
||||
|
||||
## v0.1.0 - 2024-05-04
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
- **(bin/generate)** Actually only generate what was specified - (08df8e8) - *soispha*
|
||||
- **(binary/parse)** Actually only perform the other steps, if asked for it - (4e3bdf2) - *soispha*
|
||||
- **(docs/generate_docs)** Cd into the correct directory to make ebnf2pdf work - (9a0720e) - *soispha*
|
||||
- **(example/main)** Ignore generated api.rs debugging file - (6bed2a8) - *soispha*
|
||||
- **(generate/convert/host/rust/derive/structure)** Ignore `ptr` arg on todo - (bd0b3c7) - *soispha*
|
||||
- **(gitignore)** Don't ignore the `Cargo.lock` file - (ec11a12) - Benedikt Peetz
|
||||
- **(macros)** Mark the main generate function as must_use - (db5cd1a) - *soispha*
|
||||
- **(macros)** Generate namespacesed types and convertible impls - (8b02d13) - *soispha*
|
||||
- **(macros/c_api)** Add host generation support for structs and enums - (5fe757f) - *soispha*
|
||||
- **(macros/c_api/header)** Format doc comments in a c-like way - (17fd954) - *soispha*
|
||||
- **(macros/config/file_tree/markdown)** Change format to align with mdfmt - (5855d9b) - *soispha*
|
||||
- **(macros/generate)** Correctly generate function types - (9a8ccc9) - *soispha*
|
||||
- **(macros/generate/auxiliary/c/function)** Also add inputs when no output - (3d35d39) - *soispha*
|
||||
- **(macros/generate/convert/auxiliary/c)** Correctly generate function types - (a66c687) - *soispha*
|
||||
- **(macros/generate/convert/auxiliary/c/arguments)** Accept newlines - (bfeb620) - *soispha*
|
||||
- **(macros/generate/host)** Add unified support for conversions - (b5f5ae8) - *soispha*
|
||||
- **(macros/generate/host/c/function)** Actually call the callback function - (645b8d5) - *soispha*
|
||||
- **(macros/generate/host/host/type)** The function type is a c pointer - (a58030c) - *soispha*
|
||||
- **(parser/error)** Remove multiple errors from line number calc - (e512352) - *soispha*
|
||||
- **(parser/lexing/error)** Improve the message of the `NoMatchesTaken` error - (ce1e4d8) - *soispha*
|
||||
- **(parser/lexing/take_until_sucessive_match)** Add utf8 support - (fae3de8) - *soispha*
|
||||
- **(parser/tokenizer)** Remove the tokenizer's death, when exposed to doc comments - (508dc2b) - *soispha*
|
||||
- **(parser/unchecked/parse_structure)** Accept attributes on fields - (7a8dc66) - *soispha*
|
||||
- **(scripts/renew_copyright_header)** Set correct template line lenght - (00a82ac) - *soispha*
|
||||
- **(scripts/renew_copyright_header)** Add support for gitignore files - (9e7e9d7) - *soispha*
|
||||
- **(scripts/renew_copyright_header)** Correctly handle shebangs - (3646e4a) - *soispha*
|
||||
- **(scripts/renew_copyright_header)** Add per filetype handling - (3484ead) - *soispha*
|
||||
- **(trixy)** Add thiserror dependency, as it's used in generated code - (e72c212) - *soispha*
|
||||
- **(trixy)** Use public reexports - (b9e2641) - *soispha*
|
||||
- **(trixy-macros)** Format the generated header with in the GNU style - (7c27cdc) - *soispha*
|
||||
- **(trixy-parser)** Remove the `void` type - (a077ef1) - *soispha*
|
||||
- **(trixy-types)** Conform to the api provided by the headers - (86b946b) - *soispha*
|
||||
- **(trixy-types)** Rework c header files - (f699ca2) - *soispha*
|
||||
- **(trixy/examples/main)** Improve c code - (5ce46a1) - *soispha*
|
||||
- **(types)** Remove top-level support for generic types - (37ba451) - *soispha*
|
||||
- **(types)** Improve support for generic rust types - (c2d21fd) - *soispha*
|
||||
- **(types/error)** Add a pseudo error for infallible conversions - (9e37456) - *soispha*
|
||||
- **(types/types_list)** Add the supported primitive types - (febb2de) - *soispha*
|
||||
|
||||
#### Build system
|
||||
|
||||
- **(.envrc)** Add `./target/debug` to PATH - (9233a13) - *soispha*
|
||||
- **(.licensure.yml)** Update to really be usable - (cc50ec2) - *soispha*
|
||||
- **(cog)** Avoid building the project with nix, as this fails - (d57beee) - Benedikt Peetz
|
||||
- **(cog)** Remove wrong toml header - (ddd9255) - Benedikt Peetz
|
||||
- **(cog)** Use new `renew_copyright_header` script - (c7b8fb3) - Benedikt Peetz
|
||||
- **(cog.toml)** Use `nix fmt` (treefmt) instead of only `cargo fmt` - (86d0060) - *soispha*
|
||||
- **(flake)** Update - (596197b) - *soispha*
|
||||
- **(flake)** Update - (9630e10) - *soispha*
|
||||
- **(flake)** Add treefmt - (1b8a33c) - *soispha*
|
||||
- **(flake)** De-duplicate the `flake.lock` file - (3e59d53) - *soispha*
|
||||
- **(licensure)** Add c headers to known files - (6e26bec) - *soispha*
|
||||
- **(licensure)** Update to a better license template - (1a2267b) - *soispha*
|
||||
- **(scripts/renew_copyright_header)** Init - (e9efc23) - *soispha*
|
||||
- **(treewide)** Add relevant configuration for releases - (22904c9) - *soispha*
|
||||
- **(update.sh)** Include the main example in the updates - (2e2028d) - *soispha*
|
||||
- **(update.sh)** Add a shebang - (8104e80) - *soispha*
|
||||
- **(update.sh)** Add an update script - (80c6dd4) - *soispha*
|
||||
|
||||
#### Documentation
|
||||
|
||||
- **(README)** Mention the binary - (366efd8) - *soispha*
|
||||
- **(README)** Add - (06c61ad) - *soispha*
|
||||
- **(example)** Update the example c and tri file to latest progress - (f688df1) - *soispha*
|
||||
- **(example/main)** Update to include newly added callbacks - (7f6c76a) - *soispha*
|
||||
- **(grammar.ebnf)** Don't reimplement already specified rules - (838181c) - *soispha*
|
||||
- **(lib)** Add a description to the oneshot-senders - (e205ea4) - *soispha*
|
||||
- **(macros/generate)** Improve error output - (73416da) - *soispha*
|
||||
- **(parser/examples)** Add various examples (also the trinitrix main api) - (0ebbc43) - *soispha*
|
||||
- **(parser/generate_docs)** Move shebang to first line - (1d49bdf) - *soispha*
|
||||
- **(trixy-parser)** Update the railroad diagrams - (88aa3c3) - *soispha*
|
||||
|
||||
#### Features
|
||||
|
||||
- **(bin)** Add a binary, that helps in showing the generated code - (ec929da) - *soispha*
|
||||
- **(example/valgrind)** Add a script to test the c example with valgrind - (eb31567) - *soispha*
|
||||
- **(macros/c_api/header)** Add structs and enums to the c header - (6e72b7b) - *soispha*
|
||||
- **(macros/config/file_tree)** Add support for parsing a FileTree from file - (89fd67c) - *soispha*
|
||||
- **(macros/generate/convert/auxiliary)** Merge comments in c - (bb101c1) - *soispha*
|
||||
- **(parser)** Associate a vector of nasps with every struct, enum, nasp - (a50936f) - *soispha*
|
||||
- **(parser)** Add support for parsing function pointer types - (f73d3aa) - *soispha*
|
||||
- **(parser)** Add support for parsing attributes - (add0d17) - *soispha*
|
||||
- **(parser/bin)** Allow `lex` as an alias to `tokenize` - (21b0ce1) - *soispha*
|
||||
- **(parser/lexing)** Desuger doc comments by running a regex on the file - (f1e9087) - *soispha*
|
||||
- **(treewide)** Finalize basic c API - (e52f74b) - *soispha*
|
||||
- **(treewide)** Add broken Vec<E>, Result\<T,E> and Option<T> types to c api - (b3c6a4c) - *soispha*
|
||||
- **(treewide)** Provide a c api - (7d1a41a) - *soispha*
|
||||
- **(trixy-macros)** Add rust host code generation - (ed96a50) - *soispha*
|
||||
- **(trixy-parser)** Adapt Trixy to be a complete subset of rust - (b679987) - *soispha*
|
||||
- **(types/try_from_impl)** Add a trixy::String from &str impl - (c69c00e) - *soispha*
|
||||
|
||||
#### Miscellaneous Chores
|
||||
|
||||
- **(.licensure.yml)** Remove unnecessary line in header comment - (dc000f2) - *soispha*
|
||||
- **(.licensure.yml)** Add license spdx identifier - (7a95fa7) - *soispha*
|
||||
- **(.licensure.yml)** Also add the license text to markdown files - (2f7be6f) - *soispha*
|
||||
- **(Cargo.toml)** Add further required metadata - (0774ac2) - Benedikt Peetz
|
||||
- **(Cargo.toml)** Add required metadata - (475e7ed) - Benedikt Peetz
|
||||
- **(docs/generate_docs)** Add a `.sh` extension, so scripts recognize the ft - (a653dec) - *soispha*
|
||||
- **(example)** Switch to full trinitrix API - (d2d18d9) - *soispha*
|
||||
- **(parser/docs/grammar.pdf)** Update file - (c898c48) - *soispha*
|
||||
- **(treewide)** Renew copyright headers - (07c3846) - Benedikt Peetz
|
||||
- **(treewide)** Update license header - (5ab2bbb) - *soispha*
|
||||
- **(treewide)** Add or update license header - (2b45995) - *soispha*
|
||||
- **(treewide)** Add the new license header - (5a7bb00) - *soispha*
|
||||
- **(treewide)** Remove old license header - (7ac6edb) - *soispha*
|
||||
- **(treewide)** Move the trixy subcrates under one trixy crate - (21e1b75) - *soispha*
|
||||
- **(treewide)** Add license headers - (0744c84) - *soispha*
|
||||
- **(treewide)** Add license headers - (03f2450) - *soispha*
|
||||
- Initial commit - (233fa3e) - soispha
|
||||
|
||||
#### Refactoring
|
||||
|
||||
- **(example/main/c)** Deduplicate error handling function - (cd5b0c9) - *soispha*
|
||||
- **(macros/convertible_derive)** Generate the `Convertible` Trait impl - (18034e2) - *soispha*
|
||||
- **(parser)** Use predictable names for tokens - (a4513e8) - *soispha*
|
||||
- **(src/macros/generate/host)** Merge host generation in one module - (86427b0) - Benedikt Peetz
|
||||
- **(treewide)** Rework file structure in `src/macros` - (eb7a901) - *soispha*
|
||||
- **(types/headers/string)** Don't typedef a string type - (938e038) - *soispha*
|
||||
|
||||
#### Style
|
||||
|
||||
- **(flake)** Use yamlfmt instead of prettier - (4110f65) - *soispha*
|
||||
- **(flake)** Add even more formatters - (fa6b046) - *soispha*
|
||||
- **(treewide)** Format - (a766149) - *soispha*
|
||||
- **(treewide)** format - (5ada3cb) - *soispha*
|
||||
- **(treewide)** Reformat with treefmt (`nix fmt`) - (d904a19) - *soispha*
|
||||
- **(treewide)** Reformat - (03f8eda) - *soispha*
|
||||
|
||||
#### Tests
|
||||
|
||||
- **(multiple)** Ignore, as it's not a important feature - (b1d47de) - *soispha*
|
||||
- **(parser/checked/test)** Update test case - (0a6159e) - *soispha*
|
||||
- **(scripts)** Add a script, which will help with generating and updating tests - (b85650e) - *soispha*
|
||||
- **(tests)** Update `expected.md` files - (5a9de1a) - *soispha*
|
||||
- **(tests)** Update - (475dde2) - *soispha*
|
||||
- **(tests)** Add the positive tests (and delete the ones in rust) - (d48456d) - *soispha*
|
||||
- **(trixy-parser)** Restore test functionality after nasp -> mod rename - (dc8a7ec) - *soispha*
|
||||
- Add new multiline display for c auxiliary code - (055cf2d) - soispha
|
||||
|
||||
______________________________________________________________________
|
||||
|
||||
Changelog generated by [cocogitto](https://github.com/cocogitto/cocogitto).
|
|
@ -0,0 +1,68 @@
|
|||
<!--
|
||||
Copyright (C) 2023 - 2024:
|
||||
The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||
SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
This file is part of the Trixy crate for Trinitrix.
|
||||
|
||||
Trixy is free software: you can redistribute it and/or modify
|
||||
it under the terms of the Lesser GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
and the Lesser GNU General Public License along with this program.
|
||||
If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
# Trixy
|
||||
|
||||
A crate to generate a multi-language foreign function interface.
|
||||
|
||||
## Features
|
||||
|
||||
- Support for custom types, derived from a set of [primitive types](./src/types/mod.rs).
|
||||
- Support for callbacks, thought c function pointers.
|
||||
- Support for error handling, when checking a functions arguments (NULL pointer and such things).
|
||||
|
||||
## Supported languages:
|
||||
|
||||
- c
|
||||
|
||||
## Dependencies
|
||||
|
||||
Trixy only needs:
|
||||
|
||||
- `clang-format` to format the generated c header files.
|
||||
|
||||
## The Trixy Language
|
||||
|
||||
The API to generate is specified in a Trixy file. The language of these files is an subset
|
||||
of rust and should thus be easy to learn and pick up.
|
||||
|
||||
A grammar file is provided [here](./docs/grammar.ebnf) encoded in [Extended Backus-Naur Form](https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form).
|
||||
The grammar file is rendered as railroad diagrams in PDF [here](./docs/grammar.pdf), run [`./docs/generate_docs`](./docs/generate_docs.sh) to regenerate the PDF file.
|
||||
|
||||
## Testing
|
||||
|
||||
Trixy contains integration tests in the `./tests` directory. These are maintained with the
|
||||
`./scripts/tests.sh` script. Take a look at it's `--help` output for further usage
|
||||
information.
|
||||
|
||||
This crate also contains a binary, which can help with manual testing and inspecting of the
|
||||
generated AST. The `cargo run --features 'build-binary' -- --help` output should provide
|
||||
all required information.
|
||||
|
||||
Tests are (as of now) only positive, i.e. they can only test successful situations.
|
||||
Failing test will probably be supported in the future.
|
||||
|
||||
## Contributing
|
||||
|
||||
We have a [nix flake](./flake.nix), which provides the required dependencies to work with Trixy and the associated scripts in the `./scripts` directory.
|
||||
|
||||
Please also make sure to run the `./scripts/renew_copyright_header.sh` after you added a new file, to ensure that every file contains a license header.
|
10
cog.toml
10
cog.toml
|
@ -19,14 +19,12 @@
|
|||
# If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
tag_prefix = "v"
|
||||
branch_whitelist = ["main"]
|
||||
branch_whitelist = ["main", "prime"]
|
||||
ignore_merge_commits = false
|
||||
|
||||
[commit_types]
|
||||
|
||||
pre_bump_hooks = [
|
||||
"licensur -p -i", # update the license header in each file
|
||||
"nix build", # verify the project builds
|
||||
"./scripts/renew_copyright_header.sh", # update the license header in each file
|
||||
# "nix build", # verify the project builds
|
||||
"nix fmt", # format
|
||||
"cargo set-version {{version}}", # bump version in Cargo.toml
|
||||
]
|
||||
|
@ -36,8 +34,6 @@ post_bump_hooks = [
|
|||
"git push origin v{{version}}", # push the new tag to origin
|
||||
]
|
||||
|
||||
[bump_profiles]
|
||||
|
||||
[changelog]
|
||||
path = "NEWS.md"
|
||||
remote = "git.nerdcult.net"
|
||||
|
|
|
@ -47,13 +47,14 @@ DocNamedType = {DocComment} {Attribute} NamedType;
|
|||
|
||||
# (* This is syntax sugar for a `DocAttribute` *)
|
||||
DocComment = "///" {ANYTHING} LineEnding;
|
||||
DocAttribute = "doc" "=" StringLiteral;
|
||||
|
||||
Attribute = "#" "[" AttributeValue "]" LineEnding;
|
||||
AttributeValue = DeriveAttribute | DocAttribute | ErrorAttribute | MsgAttribute;
|
||||
ErrorAttribute = "error";
|
||||
MsgAttribute = "msg" "(" StringLiteral ")";
|
||||
AttributeValue = DeriveAttribute | DocAttribute | ErrorAttribute;
|
||||
|
||||
DeriveAttribute = "derive" "(" "Error" ")";
|
||||
DocAttribute = "doc" "=" StringLiteral;
|
||||
ErrorAttribute = "error" "=" StringLiteral;
|
||||
|
||||
|
||||
Comment = "//" [ NOT ("/" {ANYTHING} LineEnding) | "//"] {ANYTHING} LineEnding;
|
||||
LineEnding = "\\n" | "\\r" | "\\r\\n";
|
||||
|
|
BIN
docs/grammar.pdf
BIN
docs/grammar.pdf
Binary file not shown.
|
@ -21,3 +21,5 @@
|
|||
/target
|
||||
/result
|
||||
/dist
|
||||
|
||||
/src/bin/main/generated_api.rs
|
||||
|
|
|
@ -0,0 +1,298 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.155"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8746739f11d39ce5ad5c2520a9b75285310dbfe78c541ccf832d38615765aec0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"getopts",
|
||||
"memchr",
|
||||
"pulldown-cmark-escape",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark-escape"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trixy"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"libc",
|
||||
"log",
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
"pulldown-cmark",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trixy-example"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libloading",
|
||||
"trixy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
|
||||
dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
|
@ -88,14 +88,24 @@ plugin_main ()
|
|||
// The API also has full support for custom types (the `Dog` and `TrainedDog`
|
||||
// types are defined in the `api.tri` file)
|
||||
struct Dog dog = { .name = "Bruce" };
|
||||
struct TrainedDog tDog;
|
||||
Result (TrainedDog, TrainingMistake) tDog;
|
||||
if (!dogs.train_dog (&tDog, dog))
|
||||
handle_error ();
|
||||
|
||||
println ("Dog %s is now trained with specialization %i", tDog.name,
|
||||
tDog.training);
|
||||
if (tDog.tag == OK)
|
||||
{
|
||||
println ("Dog %s is now trained with specialization %i",
|
||||
tDog.value.ok.name, tDog.value.ok.training);
|
||||
|
||||
// Beware that you need to free them with the appropriate free functions
|
||||
string_free (tDog.name);
|
||||
string_free (tDog.value.ok.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
eprintln (
|
||||
"The dog could not be trained because of a training mistake: '%d'",
|
||||
tDog.value.err)
|
||||
}
|
||||
|
||||
// Trixy also supports functions (i.e. callbacks):
|
||||
enum DogType output_dog;
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2023 - 2024:
|
||||
* The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||
* SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
*
|
||||
* This file is part of the Trixy crate for Trinitrix.
|
||||
*
|
||||
* Trixy is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Lesser GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* and the Lesser GNU General Public License along with this program.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../dist/interface.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define println(args...) \
|
||||
printf ("\33[32;1m(plugin):\33[0m \33[34;1m"); \
|
||||
printf (args); \
|
||||
printf ("\n\33[0m"); \
|
||||
fflush (stdout);
|
||||
#define eprintln(args...) \
|
||||
printf ("\33[32;1m(plugin):\33[0m\33[31;1m "); \
|
||||
printf (args); \
|
||||
printf ("\n\33[0m"); \
|
||||
fflush (stdout);
|
||||
|
||||
void
|
||||
handle_error ()
|
||||
{
|
||||
int error_length = last_error_length ();
|
||||
char *error = malloc (error_length);
|
||||
last_error_message (error, error_length);
|
||||
eprintln ("Encountered error: %s", error);
|
||||
free (error);
|
||||
}
|
||||
|
||||
int
|
||||
plugin_main ()
|
||||
{
|
||||
if (!trinitrix.api.room_message_send ("Hi!"))
|
||||
handle_error ();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -29,11 +29,11 @@ enum DogTraining {
|
|||
Blind,
|
||||
}
|
||||
|
||||
#[error]
|
||||
#[derive(Error)]
|
||||
enum TrainingMistake {
|
||||
#[msg("The dog got bitten")]
|
||||
#[error = "The dog got bitten"]
|
||||
GotBitten,
|
||||
#[msg("The trainer died")]
|
||||
#[error = "The trainer died"]
|
||||
Died,
|
||||
}
|
||||
|
||||
|
@ -57,11 +57,16 @@ mod dogs {
|
|||
name: String,
|
||||
training: DogTraining,
|
||||
}
|
||||
|
||||
/// Say hi to a name
|
||||
fn hi(name: String) -> String;
|
||||
|
||||
/// Train a dog
|
||||
fn train_dog(dog: Dog) -> TrainedDog;
|
||||
fn train_dog(dog: Dog) -> Result<TrainedDog, TrainingMistake>;
|
||||
|
||||
/// Renames a dog, will return the same name again, if the dog didn't accept the new
|
||||
/// name.
|
||||
fn rename_dog(dog: Dog, new_name: String) -> Result<Dog, String>;
|
||||
|
||||
fn guess_my_favourite_dog(callback: fn(name: String, age: u32) -> Dog) -> DogType;
|
||||
}
|
||||
|
|
|
@ -20,18 +20,21 @@
|
|||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use std::{env, ffi::c_int, mem};
|
||||
use std::{env, ffi::c_int};
|
||||
|
||||
use dogs::TrainedDog;
|
||||
use dogs_c::TrainedDog_c;
|
||||
use libloading::{Library, Symbol};
|
||||
use trixy::types::{newtypes, traits::convert_trait::Convertible, String};
|
||||
|
||||
use crate::dogs::DogType;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/api.rs"));
|
||||
|
||||
// run `cargo r --bin api > ./src/bin/main/api.rs` to output the generated api
|
||||
// mod api;
|
||||
// pub use api::*;
|
||||
// run `cargo run --bin api > ./src/bin/main/generated_api.rs` to output the generated api
|
||||
|
||||
// pub mod generated_api;
|
||||
// TODO: Remove this crutch, when trixy accepts a submodule <2024-05-20>
|
||||
// pub use generated_api::*;
|
||||
|
||||
fn handle_cmd(cmd: Commands) {
|
||||
match cmd {
|
||||
|
@ -40,36 +43,46 @@ fn handle_cmd(cmd: Commands) {
|
|||
let output = format!("Hi {}!", name);
|
||||
println!("(rust): {}", output);
|
||||
trixy_output.send(output.into()).expect("Will work");
|
||||
mem::forget(name);
|
||||
}
|
||||
dogs::Dogs::train_dog { trixy_output, dog } => {
|
||||
dogs::Dogs::train_dog {
|
||||
trixy_output,
|
||||
dog: _,
|
||||
} => {
|
||||
trixy_output
|
||||
.send(
|
||||
TrainedDog {
|
||||
name: "Willis".into(),
|
||||
training: DogTraining::Wolf,
|
||||
}
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
Into::<OurResult<TrainedDog_c, TrainingMistake_c>>::into(
|
||||
Err(TrainingMistake::Died.into()), // ok variant
|
||||
// Ok(TrainedDog {
|
||||
// name: "Willis".into(),
|
||||
// training: DogTraining::Wolf,
|
||||
// }
|
||||
// .into_ptr()),
|
||||
)
|
||||
.into_ptr(),
|
||||
)
|
||||
.unwrap();
|
||||
mem::forget(dog);
|
||||
}
|
||||
dogs::Dogs::guess_my_favourite_dog {
|
||||
trixy_output,
|
||||
callback,
|
||||
} => {
|
||||
let fav_dog = callback("Frank".into(), 30);
|
||||
let dog_name: String = fav_dog.name.clone().try_into().unwrap();
|
||||
let dog_name: newtypes::String = fav_dog.name.clone().try_into().unwrap();
|
||||
println!("(rust): They want a dog named: {}", dog_name);
|
||||
trixy_output.send(DogType::Cat.into()).unwrap();
|
||||
|
||||
mem::forget(dog_name);
|
||||
}
|
||||
dogs::Dogs::rename_dog {
|
||||
trixy_output,
|
||||
dog: _,
|
||||
new_name,
|
||||
} => {
|
||||
trixy_output
|
||||
.send(Into::<OurResult<Dog_c, String>>::into(Err(new_name.into())).into_ptr())
|
||||
.unwrap();
|
||||
}
|
||||
},
|
||||
Commands::outstanding { name } => {
|
||||
println!("(rust): {} is outstanding!", name);
|
||||
mem::forget(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
44
flake.lock
44
flake.lock
|
@ -7,11 +7,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1711407199,
|
||||
"narHash": "sha256-A/nB4j3JHL51ztlMQdfKw6y8tUJJzai3bLsZUEEaBxY=",
|
||||
"lastModified": 1716080827,
|
||||
"narHash": "sha256-2R9LBCR8TlMuK4Md9ELwPVuwRQWI3pAh7Nj9e318Hk4=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "7e468a455506f2e65550e08dfd45092f0857a009",
|
||||
"rev": "a7146b04405d93b24a1bac76d93270787872c8be",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -39,17 +39,17 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1708194952,
|
||||
"narHash": "sha256-xko2SsVmDxWLw5RZGUAy4LWuwTggpw66RfaSVZYajKI=",
|
||||
"lastModified": 1716118706,
|
||||
"narHash": "sha256-RXlWmKYk+pIPUWMsJCgARELUwJJ/IyENsOmDKhKmVgU=",
|
||||
"ref": "refs/heads/prime",
|
||||
"rev": "67f230acb0c83f3dd0d0f3489e7fd0c13d740bb5",
|
||||
"revCount": 6,
|
||||
"rev": "de896da1c03934cd0e2bd8da4cb1983a4e777f4c",
|
||||
"revCount": 9,
|
||||
"type": "git",
|
||||
"url": "https://codeberg.org/soispha/ebnf2pdf.git"
|
||||
"url": "https://codeberg.org/bpeetz/ebnf2pdf.git"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "https://codeberg.org/soispha/ebnf2pdf.git"
|
||||
"url": "https://codeberg.org/bpeetz/ebnf2pdf.git"
|
||||
}
|
||||
},
|
||||
"ebnf2ps": {
|
||||
|
@ -152,11 +152,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1711370797,
|
||||
"narHash": "sha256-2xu0jVSjuKhN97dqc4bVtvEH52Rwh6+uyI1XCnzoUyI=",
|
||||
"lastModified": 1716097317,
|
||||
"narHash": "sha256-1UMrLtgzielG/Sop6gl6oTSM4pDt7rF9j9VuxhDWDlY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c726225724e681b3626acc941c6f95d2b0602087",
|
||||
"rev": "8535fb92661f37ff9f0da3007fbc942f7d134b41",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -188,11 +188,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1711419061,
|
||||
"narHash": "sha256-+5M/czgYGqs/jKmi8bvYC+JUYboUKNTfkRiesXopeXQ=",
|
||||
"lastModified": 1716085073,
|
||||
"narHash": "sha256-3+9gI93XxszWA2+9S2xZfws1QArPX/MC6nahOGpcMB4=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "4c11d2f698ff1149f76b69e72852d5d75f492d0c",
|
||||
"rev": "cfc8776011bd83508324115d353222475e1601c0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -221,11 +221,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1702394821,
|
||||
"narHash": "sha256-wdq1KUZPUbPAbPXPqrkSjx9POS9XhCgSjIecq6KN7JI=",
|
||||
"lastModified": 1710519017,
|
||||
"narHash": "sha256-7C7onkhZiLwzrrf9XfzHEOjht9FmZfGABPbzE8XOYoI=",
|
||||
"ref": "refs/heads/prime",
|
||||
"rev": "552419325081adaded55effa255d6f967cfc5245",
|
||||
"revCount": 118,
|
||||
"rev": "24713f56f30e755553cac9497258ebc5d73036dc",
|
||||
"revCount": 180,
|
||||
"type": "git",
|
||||
"url": "https://codeberg.org/soispha/shell_library.git"
|
||||
},
|
||||
|
@ -256,11 +256,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710781103,
|
||||
"narHash": "sha256-nehQK/XTFxfa6rYKtbi8M1w+IU1v5twYhiyA4dg1vpg=",
|
||||
"lastModified": 1715940852,
|
||||
"narHash": "sha256-wJqHMg/K6X3JGAE9YLM0LsuKrKb4XiBeVaoeMNlReZg=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "7ee5aaac63c30d3c97a8c56efe89f3b2aa9ae564",
|
||||
"rev": "2fba33a182602b9d49f0b2440513e5ee091d838b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
};
|
||||
|
||||
ebnf2pdf = {
|
||||
url = "git+https://codeberg.org/soispha/ebnf2pdf.git";
|
||||
url = "git+https://codeberg.org/bpeetz/ebnf2pdf.git";
|
||||
inputs = {
|
||||
nixpkgs.follows = "nixpkgs";
|
||||
flake-utils.follows = "flake-utils";
|
||||
|
|
|
@ -25,7 +25,7 @@ use crate::parser::command_spec::{Attribute, DocIdentifier, Enumeration};
|
|||
impl Enumeration {
|
||||
pub fn to_auxiliary_c(&self) -> String {
|
||||
let doc_comments: String = Attribute::to_auxiliary_c_merged(&self.attributes);
|
||||
let ident = &self.identifier.to_auxiliary_c();
|
||||
let ident = &self.identifier.to_auxiliary_c(&[]);
|
||||
let states = self
|
||||
.states
|
||||
.iter()
|
||||
|
|
|
@ -24,15 +24,12 @@ use convert_case::{Case, Casing};
|
|||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
|
||||
use crate::parser::command_spec::{Identifier, Variant};
|
||||
use crate::parser::command_spec::{Identifier, Type, Variant};
|
||||
|
||||
mod doc_identifier;
|
||||
|
||||
//
|
||||
// pub use doc_identifier::*;
|
||||
|
||||
impl Identifier {
|
||||
pub fn to_auxiliary_c(&self) -> TokenStream2 {
|
||||
pub fn to_auxiliary_c(&self, generic_args: &[Type]) -> TokenStream2 {
|
||||
let ident = self.to_rust_pascalized();
|
||||
match &self.variant {
|
||||
Variant::Structure { .. } => {
|
||||
|
@ -46,10 +43,17 @@ impl Identifier {
|
|||
enum #ident
|
||||
}
|
||||
}
|
||||
Variant::Result { .. } => {
|
||||
let ident = Type::mangle_result_name(generic_args);
|
||||
quote! {
|
||||
struct #ident
|
||||
}
|
||||
}
|
||||
|
||||
Variant::Primitive => match self.name.to_case(Case::Snake).as_str() {
|
||||
"string" => {
|
||||
quote! {
|
||||
const char*
|
||||
const char *
|
||||
}
|
||||
}
|
||||
// Unsigned
|
||||
|
@ -65,14 +69,15 @@ impl Identifier {
|
|||
// Float
|
||||
"f_32" => quote! { float },
|
||||
"f_64" => quote! { double },
|
||||
// Other (not yet imlemented)
|
||||
|
||||
// Others (not yet imlemented)
|
||||
// ("Option", 1),
|
||||
// ("Vec", 1),
|
||||
// ("Result", 2),
|
||||
other => {
|
||||
todo!("'{}' is not yet supported", other)
|
||||
}
|
||||
},
|
||||
|
||||
other => {
|
||||
unimplemented!("{:#?}", other)
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ use proc_macro2::TokenStream as TokenStream2;
|
|||
use quote::{format_ident, quote};
|
||||
|
||||
use crate::parser::command_spec::{
|
||||
Attribute, Enumeration, Function, Identifier, Namespace, Structure,
|
||||
Attribute, Enumeration, Function, Identifier, Namespace, Structure, Type,
|
||||
};
|
||||
|
||||
impl Namespace {
|
||||
|
@ -44,6 +44,12 @@ impl Namespace {
|
|||
.map(Enumeration::to_auxiliary_c)
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n");
|
||||
let results: String = self
|
||||
.select_types_pred(|(ident, _generics)| ident.name.as_str() == "Result")
|
||||
.iter()
|
||||
.map(|(_, generics)| Type::to_auxilary_c_result(generics).to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n");
|
||||
let functions: String = self
|
||||
.functions
|
||||
.iter()
|
||||
|
@ -56,7 +62,7 @@ impl Namespace {
|
|||
.map(|nasp| nasp.to_auxiliary_c(&nasps))
|
||||
.collect();
|
||||
|
||||
format! {"{}\n{}\n{}\n{}", enumerations, structures, functions, namespaces}
|
||||
format! {"{}\n{}\n{}\n{}\n{}", enumerations, structures, results, functions, namespaces}
|
||||
}
|
||||
|
||||
pub fn to_auxiliary_c_full_struct_init(&self, namespaces: &Vec<&Identifier>) -> TokenStream2 {
|
||||
|
|
|
@ -25,7 +25,7 @@ use crate::parser::command_spec::{Attribute, DocNamedType, Structure};
|
|||
impl Structure {
|
||||
pub fn to_auxiliary_c(&self) -> String {
|
||||
let doc_comments: String = Attribute::to_auxiliary_c_merged(&self.attributes);
|
||||
let ident = self.identifier.to_auxiliary_c();
|
||||
let ident = self.identifier.to_auxiliary_c(&[]);
|
||||
let contents = self
|
||||
.contents
|
||||
.iter()
|
||||
|
|
|
@ -36,9 +36,9 @@ impl Type {
|
|||
match self {
|
||||
Type::Typical {
|
||||
identifier,
|
||||
generic_args: _,
|
||||
generic_args,
|
||||
} => {
|
||||
let ident = identifier.to_auxiliary_c();
|
||||
let ident = identifier.to_auxiliary_c(generic_args);
|
||||
let output = if is_output {
|
||||
quote! {
|
||||
*
|
||||
|
@ -78,4 +78,21 @@ impl Type {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_auxilary_c_result(generic_args: &[Type]) -> TokenStream2 {
|
||||
let ident = Type::mangle_result_name(&generic_args);
|
||||
|
||||
let generic_one = generic_args[0].to_auxiliary_c(false, None);
|
||||
let generic_two = generic_args[1].to_auxiliary_c(false, None);
|
||||
|
||||
quote! {
|
||||
struct #ident {
|
||||
enum ResultTag tag;
|
||||
union {
|
||||
#generic_one ok;
|
||||
#generic_two err;
|
||||
} value;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,12 +20,14 @@
|
|||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use std::iter;
|
||||
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
use crate::{
|
||||
macros::config::trixy::TrixyConfig,
|
||||
parser::command_spec::{Enumeration, Identifier, Namespace, Structure},
|
||||
parser::command_spec::{Enumeration, Identifier, Namespace, Structure, Type},
|
||||
};
|
||||
|
||||
impl Namespace {
|
||||
|
@ -48,11 +50,20 @@ impl Namespace {
|
|||
let enumerations: TokenStream2 = self.enumerations.iter().map(Enumeration::to_c).collect();
|
||||
|
||||
let callback_function = format_ident!("{}", config.callback_function);
|
||||
|
||||
let all_results_types: TokenStream2 = self
|
||||
.select_types_pred(|(identifier, _generic_args)| identifier.name.as_str() == "Result")
|
||||
.iter()
|
||||
.map(|(_, generics)| Type::to_c_result(&generics))
|
||||
.collect();
|
||||
|
||||
quote! {
|
||||
pub mod #ident {
|
||||
#[allow(unused_imports)]
|
||||
use crate :: #callback_function;
|
||||
|
||||
#all_results_types
|
||||
|
||||
#enumerations
|
||||
#structures
|
||||
#additional_functions
|
||||
|
@ -60,4 +71,81 @@ impl Namespace {
|
|||
#functions
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all the types used in this namespaces that conform to the predicate.
|
||||
/// The predicate get's the identifier of a type and the generic arguments passed.
|
||||
pub fn select_types_pred(
|
||||
&self,
|
||||
pred: fn(&(Identifier, Vec<Type>)) -> bool,
|
||||
) -> Vec<(Identifier, Vec<Type>)> {
|
||||
fn filter_type(ty: &Type) -> Vec<(Identifier, Vec<Type>)> {
|
||||
match ty {
|
||||
Type::Typical {
|
||||
identifier,
|
||||
generic_args,
|
||||
} => {
|
||||
let mut output = vec![];
|
||||
output.extend(generic_args.iter().map(|ga| filter_type(ga)).flatten());
|
||||
output.push((identifier.to_owned(), generic_args.to_owned()));
|
||||
// Stop recursion and return
|
||||
output
|
||||
}
|
||||
Type::Function { inputs, output } => {
|
||||
let mut full_output = vec![];
|
||||
full_output.extend(
|
||||
inputs
|
||||
.iter()
|
||||
.map(|na| &na.r#type)
|
||||
.map(|ty| filter_type(&ty))
|
||||
.flatten(),
|
||||
);
|
||||
|
||||
if let Some(out) = output {
|
||||
full_output.extend(filter_type(out))
|
||||
}
|
||||
|
||||
full_output
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let all_types = self.collect_types();
|
||||
|
||||
let all_result_types: Vec<_> = all_types
|
||||
.iter()
|
||||
.map(|r#type| filter_type(r#type))
|
||||
.flatten()
|
||||
.filter(pred)
|
||||
.collect();
|
||||
|
||||
all_result_types
|
||||
}
|
||||
|
||||
/// Collect a vector of all types used in this namespace
|
||||
pub fn collect_types(&self) -> Vec<Type> {
|
||||
let structures_types = self
|
||||
.structures
|
||||
.iter()
|
||||
.map(|st| st.contents.iter().map(|dc| dc.r#type.clone()))
|
||||
.flatten();
|
||||
|
||||
self.functions
|
||||
.iter()
|
||||
.map(|r#fn| {
|
||||
r#fn.inputs
|
||||
.iter()
|
||||
.map(|nt| Some(nt.r#type.clone()))
|
||||
.chain({
|
||||
if let Some(output) = &r#fn.output {
|
||||
iter::once(Some(output.clone()))
|
||||
} else {
|
||||
iter::once(None)
|
||||
}
|
||||
})
|
||||
.filter_map(|x| x)
|
||||
})
|
||||
.flatten()
|
||||
.chain(structures_types)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,16 +21,14 @@
|
|||
*/
|
||||
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::Ident;
|
||||
|
||||
use crate::parser::command_spec::{Identifier, NamedType, Type};
|
||||
|
||||
mod doc_named_type;
|
||||
mod named_type;
|
||||
|
||||
// pub use doc_named_type::*;
|
||||
// pub use named_type::*;
|
||||
|
||||
impl Type {
|
||||
pub fn to_c(&self) -> TokenStream2 {
|
||||
match self {
|
||||
|
@ -42,10 +40,84 @@ impl Type {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn mangle_result_name(generic_args: &[Type]) -> Ident {
|
||||
assert_eq!(generic_args.len(), 2);
|
||||
|
||||
format_ident!(
|
||||
"result_{}_{}",
|
||||
generic_args[0].to_string(),
|
||||
generic_args[1].to_string()
|
||||
)
|
||||
}
|
||||
|
||||
pub fn to_c_function(inputs: &[NamedType], output: &Option<Box<Type>>) -> TokenStream2 {
|
||||
Type::to_rust_function(&inputs, &output)
|
||||
}
|
||||
|
||||
pub fn to_c_result(generic_args: &[Type]) -> TokenStream2 {
|
||||
assert_eq!(generic_args.len(), 2);
|
||||
let first_generic = generic_args[0].to_c();
|
||||
let second_generic = generic_args[1].to_c();
|
||||
|
||||
let ident = Type::mangle_result_name(&generic_args);
|
||||
let value_ident = format_ident!("{}_value", ident);
|
||||
|
||||
quote! {
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(C)]
|
||||
pub union #value_ident {
|
||||
ok: std::mem::ManuallyDrop<#first_generic>,
|
||||
err: std::mem::ManuallyDrop<#second_generic>,
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(C)]
|
||||
pub struct #ident {
|
||||
tag: trixy::types::ResultTag,
|
||||
value: #value_ident,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for #ident {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self.tag {
|
||||
trixy::types::ResultTag::Ok => write!(f, "{:?}", unsafe { &self.value.ok }),
|
||||
trixy::types::ResultTag::Err => write!(f, "{:?}", unsafe { &self.value.err }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl trixy::types::traits::convert_trait::Convertible
|
||||
for crate::OurResult<#first_generic, #second_generic>
|
||||
{
|
||||
type Ptr = #ident;
|
||||
|
||||
fn into_ptr(self) -> Self::Ptr {
|
||||
if self.value.is_ok() {
|
||||
Self::Ptr {
|
||||
tag: trixy::types::ResultTag::Ok,
|
||||
value: #value_ident {
|
||||
ok: std::mem::ManuallyDrop::new(self.value.expect("Is ok")),
|
||||
},
|
||||
}
|
||||
} else {
|
||||
Self::Ptr {
|
||||
tag: trixy::types::ResultTag::Err,
|
||||
value: #value_ident {
|
||||
err: std::mem::ManuallyDrop::new(self.value.expect_err("Is err")),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn from_ptr(_ptr: Self::Ptr) -> Result<Self, trixy::types::error::TypeConversionError> {
|
||||
unreachable!("This should probably not be called?");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn to_c_typical(identifier: &Identifier, generic_args: &Vec<Type>) -> TokenStream2 {
|
||||
let trixy_build_in_types: Vec<&str> = crate::types::BASE_TYPES
|
||||
.iter()
|
||||
|
@ -78,19 +150,36 @@ impl Type {
|
|||
#nasp_path #ident
|
||||
}
|
||||
} else {
|
||||
debug_assert_eq!(trixy_build_in_types.len(), 1);
|
||||
assert_eq!(trixy_build_in_types.len(), 1);
|
||||
|
||||
let type_name = trixy_build_in_types
|
||||
.first()
|
||||
.expect("The names should not be dublicated, this should be the only value");
|
||||
.expect("The names should not be duplicated, this should be the only value");
|
||||
|
||||
match *type_name {
|
||||
"Result" => {
|
||||
let ident_ok = &generic_args.first().expect("This is a result").to_c();
|
||||
let ident_err = &generic_args.last().expect("This is a result").to_c();
|
||||
assert_eq!(generic_args.len(), 2);
|
||||
|
||||
let namespaces_path = &identifier.variant.to_c_path();
|
||||
let nasp_path = if namespaces_path.is_empty() {
|
||||
quote! {
|
||||
// eg: <Result<TrainedDog, TrainingMistake> as Convertible>::Ptr,
|
||||
<Result<#ident_ok, #ident_err> as Convertible>::Ptr
|
||||
crate ::
|
||||
}
|
||||
} else {
|
||||
let path = namespaces_path;
|
||||
quote! {
|
||||
#path ::
|
||||
}
|
||||
};
|
||||
|
||||
let ident = format_ident!(
|
||||
"result_{}_{}",
|
||||
generic_args[0].to_string(),
|
||||
generic_args[1].to_string()
|
||||
);
|
||||
|
||||
quote! {
|
||||
#nasp_path #ident
|
||||
}
|
||||
}
|
||||
"Option" => {
|
||||
|
|
|
@ -45,13 +45,12 @@ impl Variant {
|
|||
|
||||
let main_namespace;
|
||||
match self {
|
||||
Variant::Structure { namespace } => {
|
||||
Variant::Structure { namespace }
|
||||
| Variant::Enumeration { namespace }
|
||||
| Variant::Result { namespace } => {
|
||||
main_namespace = mangle_namespace_name(namespace);
|
||||
}
|
||||
Variant::Enumeration { namespace } => {
|
||||
main_namespace = mangle_namespace_name(namespace);
|
||||
}
|
||||
_ => unreachable!("This should never be called"),
|
||||
other => unreachable!("This should never be called on '{:#?}'", other),
|
||||
}
|
||||
Namespace::to_rust_path_owned(&main_namespace[..])
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
|
||||
use crate::parser::command_spec::{Attribute, Identifier};
|
||||
use crate::parser::command_spec::{unchecked::DeriveValue, Attribute, Identifier};
|
||||
|
||||
impl Attribute {
|
||||
pub fn to_rust(&self, _target: &Identifier) -> TokenStream2 {
|
||||
|
@ -31,14 +31,17 @@ impl Attribute {
|
|||
Attribute::doc(comment) => quote! {
|
||||
#[doc = #comment]
|
||||
},
|
||||
Attribute::error => quote! {
|
||||
// We simply use thiserror here
|
||||
#[derive(trixy::__private::thiserror::Error)]
|
||||
},
|
||||
Attribute::msg(msg) => quote! {
|
||||
Attribute::error(msg) => quote! {
|
||||
#[error(#msg)]
|
||||
},
|
||||
Attribute::derive(_) => unimplemented!("Derive is not used as of now"),
|
||||
Attribute::derive(attr) => {
|
||||
match attr {
|
||||
DeriveValue::Error => quote! {
|
||||
// We simply use `thiserror` here
|
||||
#[derive(trixy::__private::thiserror::Error)]
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ use quote::quote;
|
|||
use crate::parser::command_spec::{Function, Identifier, NamedType, Type};
|
||||
|
||||
impl Function {
|
||||
// was called function_identifier_to_rust
|
||||
pub fn to_rust_identifier<F>(
|
||||
&self,
|
||||
input_fmt_fn: fn(&NamedType) -> TokenStream2,
|
||||
|
|
|
@ -61,16 +61,22 @@ impl Type {
|
|||
}
|
||||
}
|
||||
pub fn to_rust_typical(identifier: &Identifier, generic_args: &Vec<Type>) -> TokenStream2 {
|
||||
match identifier {
|
||||
Identifier { name, variant: _ } if name == "String" => {
|
||||
// We wrap over the string to ensure that we know where it was allocated.
|
||||
quote! {
|
||||
trixy::types::newtypes::String
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let ident = identifier.to_rust();
|
||||
let namespaces_path = Variant::to_rust_path(&identifier.variant);
|
||||
|
||||
let nasp_path = if let Some(nasp_path) = Variant::to_rust_path(&identifier.variant) {
|
||||
if nasp_path.is_empty() {
|
||||
let nasp_path = if let Some(path) = &Variant::to_rust_path(&identifier.variant) {
|
||||
if path.is_empty() {
|
||||
quote! {
|
||||
crate ::
|
||||
}
|
||||
} else {
|
||||
let path = namespaces_path;
|
||||
quote! {
|
||||
#path ::
|
||||
}
|
||||
|
@ -84,10 +90,13 @@ impl Type {
|
|||
#nasp_path #ident
|
||||
}
|
||||
} else {
|
||||
let generics: Vec<TokenStream2> = generic_args.iter().map(Type::to_rust).collect();
|
||||
let generics: Vec<TokenStream2> =
|
||||
generic_args.iter().map(Type::to_rust).collect();
|
||||
quote! {
|
||||
#nasp_path #ident <#(#generics),*>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2023 - 2024:
|
||||
* The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||
* SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
*
|
||||
* This file is part of the Trixy crate for Trinitrix.
|
||||
*
|
||||
* Trixy is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Lesser GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* and the Lesser GNU General Public License along with this program.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
|
||||
use crate::{
|
||||
macros::config::trixy::TrixyConfig,
|
||||
parser::command_spec::{CommandSpec, Enumeration, Structure},
|
||||
};
|
||||
|
||||
/// This function generates the main c API provided by Trixy.
|
||||
/// This works for example like this:
|
||||
/// Turning this:
|
||||
/// ```text
|
||||
/// nasp trinitrix {
|
||||
/// struct Callback {
|
||||
/// func: String,
|
||||
/// timeout: String,
|
||||
/// };
|
||||
///
|
||||
/// enum CallbackPriority {
|
||||
/// High,
|
||||
/// Medium,
|
||||
/// Low,
|
||||
/// };
|
||||
///
|
||||
/// fn execute_callback(callback: Callback, priority: CallbackPriority);
|
||||
/// }
|
||||
/// ```
|
||||
/// to this:
|
||||
/// ```no_run
|
||||
/// pub extern "C" fn exectute_callback(callback: Callback, priority: CallbackPriority) {
|
||||
/// /* Here we simply call your handler function, with the command of the function */
|
||||
/// }
|
||||
/// ```
|
||||
pub fn generate(trixy: &CommandSpec, config: &TrixyConfig) -> TokenStream2 {
|
||||
let functions: TokenStream2 = trixy
|
||||
.functions
|
||||
.iter()
|
||||
.map(|r#fn| r#fn.to_c(&config, &vec![]))
|
||||
.collect();
|
||||
let namespaced_functions: TokenStream2 = trixy
|
||||
.namespaces
|
||||
.iter()
|
||||
.map(|nasp| nasp.to_c(&config, &vec![]))
|
||||
.collect();
|
||||
let structures: TokenStream2 = trixy.structures.iter().map(Structure::to_c).collect();
|
||||
let enumerations: TokenStream2 = trixy.enumerations.iter().map(Enumeration::to_c).collect();
|
||||
quote! {
|
||||
#enumerations
|
||||
#structures
|
||||
#functions
|
||||
#namespaced_functions
|
||||
}
|
||||
}
|
|
@ -22,20 +22,79 @@
|
|||
|
||||
use crate::{
|
||||
macros::{config::trixy::TrixyConfig, generate::host::format_rust},
|
||||
parser::command_spec::CommandSpec,
|
||||
parser::command_spec::{CommandSpec, Enumeration, Structure},
|
||||
};
|
||||
|
||||
pub mod host;
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
|
||||
pub fn generate(trixy: &CommandSpec, config: &TrixyConfig) -> String {
|
||||
let host_rust_code = host::generate(&trixy, &config);
|
||||
let host_rust_code = generate_code(&trixy, &config);
|
||||
|
||||
let rust_code = format_rust(host_rust_code);
|
||||
|
||||
format!(
|
||||
"\
|
||||
/* C API */\n\
|
||||
// Workaround rust rules when implementing a foreign trait on a foreign type
|
||||
#[derive(Debug)]
|
||||
pub struct OurResult<T, E> {{
|
||||
value: Result<T, E>,
|
||||
}}
|
||||
|
||||
impl<T, E> From<Result<T, E>> for OurResult<T, E> {{
|
||||
fn from(value: Result<T, E>) -> Self {{
|
||||
Self {{ value }}
|
||||
}}
|
||||
}}
|
||||
/* The real C API */\n\
|
||||
{}",
|
||||
rust_code
|
||||
)
|
||||
}
|
||||
|
||||
/// This function generates the main c API provided by Trixy.
|
||||
/// This works for example like this:
|
||||
/// Turning this:
|
||||
/// ```text
|
||||
/// nasp trinitrix {
|
||||
/// struct Callback {
|
||||
/// func: String,
|
||||
/// timeout: String,
|
||||
/// };
|
||||
///
|
||||
/// enum CallbackPriority {
|
||||
/// High,
|
||||
/// Medium,
|
||||
/// Low,
|
||||
/// };
|
||||
///
|
||||
/// fn execute_callback(callback: Callback, priority: CallbackPriority);
|
||||
/// }
|
||||
/// ```
|
||||
/// to this:
|
||||
/// ```no_run
|
||||
/// pub extern "C" fn exectute_callback(callback: Callback, priority: CallbackPriority) {
|
||||
/// /* Here we simply call your handler function, with the command of the function */
|
||||
/// }
|
||||
/// ```
|
||||
pub fn generate_code(trixy: &CommandSpec, config: &TrixyConfig) -> TokenStream2 {
|
||||
let functions: TokenStream2 = trixy
|
||||
.functions
|
||||
.iter()
|
||||
.map(|r#fn| r#fn.to_c(&config, &vec![]))
|
||||
.collect();
|
||||
let namespaced_functions: TokenStream2 = trixy
|
||||
.namespaces
|
||||
.iter()
|
||||
.map(|nasp| nasp.to_c(&config, &vec![]))
|
||||
.collect();
|
||||
let structures: TokenStream2 = trixy.structures.iter().map(Structure::to_c).collect();
|
||||
let enumerations: TokenStream2 = trixy.enumerations.iter().map(Enumeration::to_c).collect();
|
||||
quote! {
|
||||
#enumerations
|
||||
#structures
|
||||
#functions
|
||||
#namespaced_functions
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2023 - 2024:
|
||||
* The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||
* SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
*
|
||||
* This file is part of the Trixy crate for Trinitrix.
|
||||
*
|
||||
* Trixy is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Lesser GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* and the Lesser GNU General Public License along with this program.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! This module is responsible for generating the rust code used to interface with the api.
|
||||
//! That includes the structs and enums declared in the trixy file and the enum used to describe the
|
||||
//! command being executed.
|
||||
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
|
||||
use crate::{
|
||||
macros::config::trixy::TrixyConfig,
|
||||
parser::command_spec::{CommandSpec, Enumeration, Namespace, Structure},
|
||||
};
|
||||
|
||||
/// This function turns, for example, the following trixy input into this rust code:
|
||||
/// ```text
|
||||
/// nasp trinitrix {
|
||||
/// struct Callback {
|
||||
/// func: String,
|
||||
/// timeout: String,
|
||||
/// };
|
||||
///
|
||||
/// enum CallbackPriority {
|
||||
/// High,
|
||||
/// Medium,
|
||||
/// Low,
|
||||
/// };
|
||||
///
|
||||
/// fn execute_callback(callback: Callback, priority: CallbackPriority) -> String;
|
||||
/// }
|
||||
/// ```
|
||||
/// ```no_run
|
||||
/// #[derive(Debug)]
|
||||
/// pub enum Commands {
|
||||
/// Trinitrix(trinitrix::Trinitrix),
|
||||
/// }
|
||||
/// pub mod trinitrix {
|
||||
/// #[allow(non_camel_case_types)]
|
||||
/// #[derive(Debug)]
|
||||
/// struct Callback {
|
||||
/// func: String,
|
||||
/// timeout: String,
|
||||
/// }
|
||||
/// #[allow(non_camel_case_types)]
|
||||
/// #[derive(Debug)]
|
||||
/// enum CallbackPriority {
|
||||
/// High,
|
||||
/// Medium,
|
||||
/// Low,
|
||||
/// }
|
||||
/// #[derive(Debug)]
|
||||
/// pub enum Trinitrix {
|
||||
/// #[allow(non_camel_case_types)]
|
||||
/// execute_callback {
|
||||
/// callback: Callback,
|
||||
/// priority: CallbackPriority,
|
||||
/// trixy_output: trixy::oneshot::channel<String>
|
||||
/// },
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn generate(trixy: &CommandSpec, _config: &TrixyConfig) -> TokenStream2 {
|
||||
let modules: TokenStream2 = trixy
|
||||
.namespaces
|
||||
.iter()
|
||||
.map(|nasp| nasp.to_rust_module(&vec![]))
|
||||
.collect();
|
||||
let structures: TokenStream2 = trixy.structures.iter().map(Structure::to_rust).collect();
|
||||
let enumerations: TokenStream2 = trixy
|
||||
.enumerations
|
||||
.iter()
|
||||
.map(Enumeration::to_rust)
|
||||
.collect();
|
||||
let functions: Vec<TokenStream2> = trixy
|
||||
.functions
|
||||
.iter()
|
||||
.map(|r#fn| r#fn.to_rust(&[]))
|
||||
.collect();
|
||||
let namespace_modules: Vec<TokenStream2> = trixy
|
||||
.namespaces
|
||||
.iter()
|
||||
.map(Namespace::to_rust_module_enum)
|
||||
.collect();
|
||||
|
||||
quote! {
|
||||
#structures
|
||||
#enumerations
|
||||
#[derive(Debug)]
|
||||
pub enum Commands {
|
||||
#(#functions,)*
|
||||
#(#namespace_modules),*
|
||||
}
|
||||
#modules
|
||||
}
|
||||
}
|
|
@ -20,14 +20,20 @@
|
|||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use crate::parser::command_spec::CommandSpec;
|
||||
//! This module is responsible for generating the rust code used to interface with the api.
|
||||
//! That includes the structs and enums declared in the trixy file and the enum used to describe the
|
||||
//! command being executed.
|
||||
|
||||
use crate::macros::{config::trixy::TrixyConfig, generate::host::format_rust};
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::quote;
|
||||
|
||||
pub mod host;
|
||||
use crate::{
|
||||
macros::{config::trixy::TrixyConfig, generate::host::format_rust},
|
||||
parser::command_spec::{CommandSpec, Enumeration, Namespace, Structure},
|
||||
};
|
||||
|
||||
pub fn generate(trixy: &CommandSpec, config: &TrixyConfig) -> String {
|
||||
let host_rust_code = host::generate(&trixy, &config);
|
||||
let host_rust_code = generate_code(&trixy, &config);
|
||||
|
||||
let rust_code = format_rust(host_rust_code);
|
||||
|
||||
|
@ -38,3 +44,85 @@ pub fn generate(trixy: &CommandSpec, config: &TrixyConfig) -> String {
|
|||
rust_code
|
||||
)
|
||||
}
|
||||
|
||||
/// This function turns, for example, the following trixy input into this rust code:
|
||||
/// ```text
|
||||
/// mod trinitrix {
|
||||
/// struct Callback {
|
||||
/// func: String,
|
||||
/// timeout: String,
|
||||
/// };
|
||||
///
|
||||
/// enum CallbackPriority {
|
||||
/// High,
|
||||
/// Medium,
|
||||
/// Low,
|
||||
/// };
|
||||
///
|
||||
/// fn execute_callback(callback: Callback, priority: CallbackPriority) -> String;
|
||||
/// }
|
||||
/// ```
|
||||
/// ```no_run
|
||||
/// #[derive(Debug)]
|
||||
/// pub enum Commands {
|
||||
/// Trinitrix(trinitrix::Trinitrix),
|
||||
/// }
|
||||
/// pub mod trinitrix {
|
||||
/// #[allow(non_camel_case_types)]
|
||||
/// #[derive(Debug)]
|
||||
/// struct Callback {
|
||||
/// func: String,
|
||||
/// timeout: String,
|
||||
/// }
|
||||
/// #[allow(non_camel_case_types)]
|
||||
/// #[derive(Debug)]
|
||||
/// enum CallbackPriority {
|
||||
/// High,
|
||||
/// Medium,
|
||||
/// Low,
|
||||
/// }
|
||||
/// #[derive(Debug)]
|
||||
/// pub enum Trinitrix {
|
||||
/// #[allow(non_camel_case_types)]
|
||||
/// execute_callback {
|
||||
/// callback: Callback,
|
||||
/// priority: CallbackPriority,
|
||||
/// trixy_output: trixy::oneshot::channel<String>
|
||||
/// },
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn generate_code(trixy: &CommandSpec, _config: &TrixyConfig) -> TokenStream2 {
|
||||
let modules: TokenStream2 = trixy
|
||||
.namespaces
|
||||
.iter()
|
||||
.map(|nasp| nasp.to_rust_module(&vec![]))
|
||||
.collect();
|
||||
let structures: TokenStream2 = trixy.structures.iter().map(Structure::to_rust).collect();
|
||||
let enumerations: TokenStream2 = trixy
|
||||
.enumerations
|
||||
.iter()
|
||||
.map(Enumeration::to_rust)
|
||||
.collect();
|
||||
let functions: Vec<TokenStream2> = trixy
|
||||
.functions
|
||||
.iter()
|
||||
.map(|r#fn| r#fn.to_rust(&[]))
|
||||
.collect();
|
||||
let namespace_modules: Vec<TokenStream2> = trixy
|
||||
.namespaces
|
||||
.iter()
|
||||
.map(Namespace::to_rust_module_enum)
|
||||
.collect();
|
||||
|
||||
quote! {
|
||||
#structures
|
||||
#enumerations
|
||||
#[derive(Debug)]
|
||||
pub enum Commands {
|
||||
#(#functions,)*
|
||||
#(#namespace_modules),*
|
||||
}
|
||||
#modules
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,9 +36,14 @@ pub enum Variant {
|
|||
Enumeration {
|
||||
namespace: Vec<Identifier>,
|
||||
},
|
||||
Result {
|
||||
namespace: Vec<Identifier>,
|
||||
},
|
||||
|
||||
Namespace,
|
||||
/// The first (implicit) namespace, containing everything
|
||||
RootNamespace,
|
||||
|
||||
Function,
|
||||
Primitive,
|
||||
NamedType,
|
||||
|
@ -59,7 +64,7 @@ impl Variant {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
pub struct Namespace {
|
||||
pub name: Identifier,
|
||||
|
||||
|
@ -89,21 +94,21 @@ impl From<Namespace> for CommandSpec {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
pub struct Structure {
|
||||
pub identifier: Identifier,
|
||||
pub contents: Vec<DocNamedType>,
|
||||
pub attributes: Vec<Attribute>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
pub struct Enumeration {
|
||||
pub identifier: Identifier,
|
||||
pub states: Vec<DocIdentifier>,
|
||||
pub attributes: Vec<Attribute>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
pub struct Function {
|
||||
pub identifier: Identifier,
|
||||
pub inputs: Vec<NamedType>,
|
||||
|
@ -206,7 +211,7 @@ pub struct NamedType {
|
|||
pub r#type: Type,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
pub struct DocNamedType {
|
||||
pub name: Identifier,
|
||||
pub r#type: Type,
|
||||
|
@ -246,20 +251,19 @@ impl TokenKind {
|
|||
pub enum Attribute {
|
||||
#[allow(non_camel_case_types)]
|
||||
doc(String),
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
derive(DeriveValue),
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
error,
|
||||
#[allow(non_camel_case_types)]
|
||||
msg(String),
|
||||
error(String),
|
||||
}
|
||||
impl From<unchecked::Attribute> for Attribute {
|
||||
fn from(value: unchecked::Attribute) -> Self {
|
||||
match value {
|
||||
unchecked::Attribute::doc { content: name, .. } => Self::doc(name.content),
|
||||
unchecked::Attribute::derive { value, .. } => Self::derive(value),
|
||||
unchecked::Attribute::error { .. } => Self::error,
|
||||
unchecked::Attribute::msg { content, .. } => Self::msg(content.content),
|
||||
unchecked::Attribute::error { content, .. } => Self::error(content.content),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,12 +76,12 @@ pub enum Attribute {
|
|||
content: StringLiteral,
|
||||
span: TokenSpan,
|
||||
},
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
derive { value: DeriveValue, span: TokenSpan },
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
error { span: TokenSpan },
|
||||
#[allow(non_camel_case_types)]
|
||||
msg {
|
||||
error {
|
||||
content: StringLiteral,
|
||||
span: TokenSpan,
|
||||
},
|
||||
|
@ -93,7 +93,6 @@ impl Display for Attribute {
|
|||
Attribute::doc { .. } => f.write_str("doc"),
|
||||
Attribute::derive { .. } => f.write_str("derive"),
|
||||
Attribute::error { .. } => f.write_str("error"),
|
||||
Attribute::msg { .. } => f.write_str("msg"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +103,6 @@ impl Attribute {
|
|||
Attribute::doc { span, .. } => *span,
|
||||
Attribute::derive { span, .. } => *span,
|
||||
Attribute::error { span, .. } => *span,
|
||||
Attribute::msg { span, .. } => *span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -264,7 +264,7 @@ pub enum Keyword {
|
|||
/// Keywords used in attributes: (#[<keyword>(<value>)])
|
||||
#[derive(Debug, PartialEq, PartialOrd, Ord, Eq, Clone, Copy)]
|
||||
pub enum AttributeKeyword {
|
||||
/// Derive a trait
|
||||
/// Derive a trait (only `Error` for now)
|
||||
#[allow(non_camel_case_types)]
|
||||
derive,
|
||||
|
||||
|
@ -272,13 +272,9 @@ pub enum AttributeKeyword {
|
|||
#[allow(non_camel_case_types)]
|
||||
doc,
|
||||
|
||||
/// Mark the beginning of an error
|
||||
/// Add an error message
|
||||
#[allow(non_camel_case_types)]
|
||||
error,
|
||||
|
||||
/// Encompass an error message
|
||||
#[allow(non_camel_case_types)]
|
||||
msg,
|
||||
}
|
||||
|
||||
impl Display for Keyword {
|
||||
|
@ -298,7 +294,6 @@ impl Display for AttributeKeyword {
|
|||
AttributeKeyword::derive => f.write_str("derive"),
|
||||
AttributeKeyword::doc => f.write_str("doc"),
|
||||
AttributeKeyword::error => f.write_str("error"),
|
||||
AttributeKeyword::msg => f.write_str("msg"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -272,7 +272,6 @@ fn tokenize_ident(text: &str) -> Result<(TokenKind, usize), LexingError> {
|
|||
"derive" => TokenKind::AttributeKeyword(AttributeKeyword::derive),
|
||||
"doc" => TokenKind::AttributeKeyword(AttributeKeyword::doc),
|
||||
"error" => TokenKind::AttributeKeyword(AttributeKeyword::error),
|
||||
"msg" => TokenKind::AttributeKeyword(AttributeKeyword::msg),
|
||||
|
||||
other => TokenKind::Identifier(other.to_string()),
|
||||
};
|
||||
|
|
|
@ -159,7 +159,7 @@ impl Parser {
|
|||
|
||||
let mut functions = vec![];
|
||||
for function in namespace.functions {
|
||||
functions.push(self.process_function(function)?);
|
||||
functions.push(self.process_function(function, &previous_namespaces)?);
|
||||
}
|
||||
let mut namespaces = vec![];
|
||||
for namespace in namespace.namespaces {
|
||||
|
@ -187,14 +187,15 @@ impl Parser {
|
|||
fn process_function(
|
||||
&mut self,
|
||||
mut function: UncheckedFunction,
|
||||
parent_namespaces: &Vec<Identifier>,
|
||||
) -> Result<Function, ParsingError> {
|
||||
let identifier = mem::take(&mut function.identifier.kind).to_identifier(Variant::Function);
|
||||
let mut inputs = vec![];
|
||||
for input in function.inputs {
|
||||
inputs.push(self.process_named_type(input)?);
|
||||
inputs.push(self.process_named_type(input, parent_namespaces)?);
|
||||
}
|
||||
let output = if let Some(r#type) = function.output {
|
||||
Some(self.process_type(r#type)?)
|
||||
Some(self.process_type(r#type, parent_namespaces)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -243,7 +244,7 @@ impl Parser {
|
|||
mem::take(&mut state.token.kind).to_identifier(Variant::DocNamedType);
|
||||
DocIdentifier {
|
||||
name: ident.name,
|
||||
attributes: take_attrs! {state, doc, msg},
|
||||
attributes: take_attrs! {state, doc, error},
|
||||
variant: Variant::DocNamedType,
|
||||
}
|
||||
})
|
||||
|
@ -252,7 +253,7 @@ impl Parser {
|
|||
Ok(Enumeration {
|
||||
identifier,
|
||||
states,
|
||||
attributes: take_attrs! {enumeration, doc, derive, error},
|
||||
attributes: take_attrs! {enumeration, doc, derive},
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -269,7 +270,7 @@ impl Parser {
|
|||
});
|
||||
let mut contents = vec![];
|
||||
for named_type in structure.contents {
|
||||
contents.push(self.process_doc_named_type(named_type)?);
|
||||
contents.push(self.process_doc_named_type(named_type, parent_namespaces)?);
|
||||
}
|
||||
|
||||
Ok(Structure {
|
||||
|
@ -282,19 +283,21 @@ impl Parser {
|
|||
fn process_named_type(
|
||||
&mut self,
|
||||
mut named_type: UncheckedNamedType,
|
||||
parent_namespaces: &Vec<Identifier>,
|
||||
) -> Result<NamedType, ParsingError> {
|
||||
let name: Identifier =
|
||||
mem::take(&mut named_type.name.kind).to_identifier(Variant::NamedType);
|
||||
let r#type: Type = self.process_type(named_type.r#type)?;
|
||||
let r#type: Type = self.process_type(named_type.r#type, parent_namespaces)?;
|
||||
Ok(NamedType { name, r#type })
|
||||
}
|
||||
fn process_doc_named_type(
|
||||
&mut self,
|
||||
mut doc_named_type: UncheckedDocNamedType,
|
||||
parent_namespaces: &Vec<Identifier>,
|
||||
) -> Result<DocNamedType, ParsingError> {
|
||||
let name: Identifier =
|
||||
mem::take(&mut doc_named_type.name.kind).to_identifier(Variant::DocNamedType);
|
||||
let r#type: Type = self.process_type(doc_named_type.r#type)?;
|
||||
let r#type: Type = self.process_type(doc_named_type.r#type, parent_namespaces)?;
|
||||
Ok(DocNamedType {
|
||||
name,
|
||||
r#type,
|
||||
|
@ -302,14 +305,18 @@ impl Parser {
|
|||
})
|
||||
}
|
||||
|
||||
fn process_type(&mut self, r#type: UncheckedType) -> Result<Type, ParsingError> {
|
||||
fn process_type(
|
||||
&mut self,
|
||||
r#type: UncheckedType,
|
||||
parent_namespaces: &Vec<Identifier>,
|
||||
) -> Result<Type, ParsingError> {
|
||||
match r#type {
|
||||
UncheckedType::Typical {
|
||||
identifier,
|
||||
generic_args,
|
||||
} => self.process_typical_type(identifier, generic_args),
|
||||
} => self.process_typical_type(identifier, generic_args, parent_namespaces),
|
||||
UncheckedType::Function { inputs, output } => {
|
||||
self.process_function_type(inputs, output)
|
||||
self.process_function_type(inputs, output, parent_namespaces)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -318,6 +325,7 @@ impl Parser {
|
|||
&mut self,
|
||||
mut type_identifier: Token,
|
||||
generic_args: Vec<UncheckedType>,
|
||||
parent_namespaces: &Vec<Identifier>,
|
||||
) -> Result<Type, ParsingError> {
|
||||
fn match_to_vector_struct(matches: Vec<&UncheckedStructure>) -> Vec<Identifier> {
|
||||
matches
|
||||
|
@ -401,7 +409,13 @@ impl Parser {
|
|||
.iter()
|
||||
.any(|(ident, _)| ident == &identifier.name)
|
||||
{
|
||||
if &identifier.name == "Result" {
|
||||
variant = Variant::Result {
|
||||
namespace: parent_namespaces.clone(),
|
||||
};
|
||||
} else {
|
||||
variant = Variant::Primitive;
|
||||
}
|
||||
} else {
|
||||
return Err(ParsingError::TypeNotDeclared {
|
||||
r#type: identifier,
|
||||
|
@ -461,7 +475,7 @@ impl Parser {
|
|||
|
||||
let mut new_generic_args: Vec<checked::Type> = vec![];
|
||||
for generic_arg in generic_args {
|
||||
new_generic_args.push(self.process_type(generic_arg)?);
|
||||
new_generic_args.push(self.process_type(generic_arg, parent_namespaces)?);
|
||||
}
|
||||
|
||||
Ok(Type::Typical {
|
||||
|
@ -473,15 +487,16 @@ impl Parser {
|
|||
&mut self,
|
||||
inputs: Vec<UncheckedNamedType>,
|
||||
output: Option<Box<UncheckedType>>,
|
||||
parent_namespaces: &Vec<Identifier>,
|
||||
) -> Result<Type, ParsingError> {
|
||||
let inputs = inputs
|
||||
.into_iter()
|
||||
.map(|input| self.process_named_type(input))
|
||||
.map(|input| self.process_named_type(input, parent_namespaces))
|
||||
.collect::<Result<Vec<NamedType>, ParsingError>>()?;
|
||||
|
||||
let mut new_output = None;
|
||||
if let Some(output) = output {
|
||||
new_output = Some(Box::new(self.process_type(*output)?));
|
||||
new_output = Some(Box::new(self.process_type(*output, parent_namespaces)?));
|
||||
}
|
||||
|
||||
Ok(Type::Function {
|
||||
|
|
|
@ -176,14 +176,6 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_bracket_string_literal(&mut self) -> Result<StringLiteral, ParsingError> {
|
||||
self.expect(token![CurvedBracketOpen])?;
|
||||
let string_literal = self.expect(token![StringLiteral])?;
|
||||
self.expect(token![CurvedBracketClose])?;
|
||||
let string_literal = Into::<StringLiteral>::into(string_literal);
|
||||
Ok(string_literal)
|
||||
}
|
||||
|
||||
fn parse_attribute_value(&mut self) -> Result<Attribute, ParsingError> {
|
||||
let ident = self.expect(token![AttributeKeyword])?;
|
||||
let span = *ident.span();
|
||||
|
@ -193,14 +185,26 @@ impl Parser {
|
|||
|
||||
let attribute = match keyword {
|
||||
AttributeKeyword::derive => {
|
||||
let string_literal = self.parse_bracket_string_literal()?;
|
||||
match string_literal.content.as_str() {
|
||||
self.expect(token![CurvedBracketOpen])?;
|
||||
let string_literal_token = self.expect(token![Identifier])?;
|
||||
let string_literal =
|
||||
if let TokenKind::Identifier(ident) = string_literal_token.kind() {
|
||||
ident
|
||||
} else {
|
||||
unreachable! {"The token is a identifier, as checked by the `expect`"};
|
||||
};
|
||||
self.expect(token![CurvedBracketClose])?;
|
||||
|
||||
match string_literal.as_str() {
|
||||
"Error" => Ok(Attribute::derive {
|
||||
value: DeriveValue::Error,
|
||||
span,
|
||||
}),
|
||||
_ => Err(error::ParsingError::WrongDeriveValue {
|
||||
specified: string_literal,
|
||||
specified: StringLiteral {
|
||||
content: string_literal.to_owned(),
|
||||
span: string_literal_token.span,
|
||||
},
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -208,18 +212,16 @@ impl Parser {
|
|||
self.expect(token![=])?;
|
||||
let string_literal = self.expect(token![StringLiteral])?;
|
||||
let string_literal = Into::<StringLiteral>::into(string_literal);
|
||||
if self.expect_peek(token![PoundSign]) {
|
||||
dbg!(&self.token_stream);
|
||||
}
|
||||
Ok(Attribute::doc {
|
||||
content: string_literal,
|
||||
span,
|
||||
})
|
||||
}
|
||||
AttributeKeyword::error => Ok(Attribute::error { span }),
|
||||
AttributeKeyword::msg => {
|
||||
let string_literal = self.parse_bracket_string_literal()?;
|
||||
Ok(Attribute::msg {
|
||||
AttributeKeyword::error => {
|
||||
self.expect(token![=])?;
|
||||
let string_literal = self.expect(token![StringLiteral])?;
|
||||
let string_literal = Into::<StringLiteral>::into(string_literal);
|
||||
Ok(Attribute::error {
|
||||
content: string_literal,
|
||||
span,
|
||||
})
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (C) 2023 - 2024:
|
||||
* The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||
* SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
*
|
||||
* This file is part of the Trixy crate for Trinitrix.
|
||||
*
|
||||
* Trixy is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Lesser GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* and the Lesser GNU General Public License along with this program.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TRIXY_RESULT_H
|
||||
#define TRIXY_RESULT_H
|
||||
|
||||
/**
|
||||
* @brief A rust-like result type
|
||||
*
|
||||
* @detail
|
||||
* This macro effectively generates a type name from the two generic
|
||||
* parameters. The generated type name is always globally unique.
|
||||
*/
|
||||
#define Result(ok, err) struct result_##ok##_##err
|
||||
|
||||
/**
|
||||
* @brief The possibly states of a Result.
|
||||
*/
|
||||
enum ResultTag
|
||||
{
|
||||
OK,
|
||||
ERR,
|
||||
};
|
||||
|
||||
#endif // TRIXY_RESULT_H
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
//! Trixy contains the types used by the [`trixy-macros`] crate to provide ffi safe types
|
||||
pub mod error;
|
||||
pub mod newtypes;
|
||||
pub mod traits;
|
||||
pub mod types_list;
|
||||
|
||||
|
@ -39,7 +40,7 @@ macro_rules! header {
|
|||
// NOTE: Every type here must have the [`Convertible`] implemented on it (@soispha)
|
||||
// And be added to the `convert/c/auxiliary/idendentifier/mod.rs` file
|
||||
// And add it to the types list (`./types_list.rs`)
|
||||
pub const BASE_TYPES: [(&'static std::primitive::str, usize); 11] = [
|
||||
pub const BASE_TYPES: [(&'static std::primitive::str, usize); 12] = [
|
||||
// Unsigned
|
||||
("u8", 0),
|
||||
("u16", 0),
|
||||
|
@ -55,15 +56,19 @@ pub const BASE_TYPES: [(&'static std::primitive::str, usize); 11] = [
|
|||
("f64", 0),
|
||||
// Other
|
||||
("String", 0),
|
||||
("Result", 2),
|
||||
// FIXME(@soispha): These work, but the generated code is not really ideal <2024-03-26>
|
||||
// ("Option", 1),
|
||||
// ("Vec", 1),
|
||||
// ("Result", 2),
|
||||
];
|
||||
|
||||
/// The first value is the file name, the second it's contents
|
||||
pub const C_TYPE_HEADER: [(&'static std::primitive::str, &'static std::primitive::str); 3] =
|
||||
[header!("errno.h"), header!("string.h"), header!("vec.h")];
|
||||
pub const C_TYPE_HEADER: [(&'static std::primitive::str, &'static std::primitive::str); 4] = [
|
||||
header!("errno.h"),
|
||||
header!("string.h"),
|
||||
header!("vec.h"),
|
||||
header!("result.h"),
|
||||
];
|
||||
|
||||
pub fn header_names() -> std::string::String {
|
||||
C_TYPE_HEADER
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (C) 2023 - 2024:
|
||||
* The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||
* SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
*
|
||||
* This file is part of the Trixy crate for Trinitrix.
|
||||
*
|
||||
* Trixy is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Lesser GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* and the Lesser GNU General Public License along with this program.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! This module contains wrapper types for know rust types, where trixy needs to store additional
|
||||
//! information
|
||||
|
||||
use std::{fmt::Display, mem, string};
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct String {
|
||||
pub(crate) data: Option<string::String>,
|
||||
pub(crate) alloc_location: AllocLocation,
|
||||
}
|
||||
|
||||
#[derive(Clone, Hash, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub(crate) enum AllocLocation {
|
||||
#[default]
|
||||
Rust,
|
||||
C,
|
||||
}
|
||||
|
||||
impl From<&str> for String {
|
||||
fn from(value: &str) -> Self {
|
||||
Self {
|
||||
// It's cloned here:
|
||||
data: Some(value.to_owned()),
|
||||
// The string is always allocated in rust, as we clone it above this comment
|
||||
alloc_location: AllocLocation::Rust,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<string::String> for String {
|
||||
fn from(value: string::String) -> Self {
|
||||
Self {
|
||||
data: Some(value),
|
||||
// We just assume that every std String is actually allocated in rust
|
||||
alloc_location: AllocLocation::Rust,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for String {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl String {
|
||||
pub fn as_str(&self) -> &str {
|
||||
&self
|
||||
.data
|
||||
.as_ref()
|
||||
.expect("The string should only be empty when it's dropped")
|
||||
}
|
||||
pub fn into_std_string(mut self) -> string::String {
|
||||
match self.alloc_location {
|
||||
AllocLocation::C => {
|
||||
// Re-allocate the string in rust
|
||||
let c_alloc_string = mem::take(&mut self.data).expect("It should only be Some");
|
||||
let rust_alloc_string = c_alloc_string.clone();
|
||||
|
||||
// This is here because of the same reason as in the drop impl: we just can't free
|
||||
// a string allocated in c.
|
||||
mem::forget(c_alloc_string);
|
||||
|
||||
rust_alloc_string
|
||||
}
|
||||
AllocLocation::Rust => {
|
||||
let string = mem::take(&mut self.data).expect("Will always be some");
|
||||
string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for String {
|
||||
fn drop(&mut self) {
|
||||
match self.alloc_location {
|
||||
AllocLocation::C => {
|
||||
let string = mem::take(&mut self.data);
|
||||
// C needs to free it's strings by itself. We cannot do the job of the c allocator,
|
||||
// thus just forget about it here
|
||||
mem::forget(string)
|
||||
}
|
||||
AllocLocation::Rust => {
|
||||
// A rust allocated string can be free normally. We don't need to do anything here.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::types::types_list;
|
||||
|
||||
use super::String;
|
||||
|
||||
#[test]
|
||||
fn test_string_round_trip() {
|
||||
let start = "HI! I'm a nice string".to_owned();
|
||||
let wrapper: String = start.clone().into();
|
||||
|
||||
assert_eq!(&start, wrapper.as_str());
|
||||
assert_eq!(start, wrapper.to_string());
|
||||
assert_eq!(start, wrapper.into_std_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_string_round_trip_through_c() {
|
||||
let start = "HI! I'm a nice string".to_owned();
|
||||
|
||||
let c_string: types_list::String = start.clone().into();
|
||||
let wrapper: String = Into::<types_list::String>::into(c_string)
|
||||
.try_into()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(&start, wrapper.as_str());
|
||||
assert_eq!(start, wrapper.to_string());
|
||||
assert_eq!(start, wrapper.into_std_string());
|
||||
}
|
||||
}
|
|
@ -129,121 +129,93 @@ pub extern "C" fn string_free(ptr: *const c_char) {
|
|||
CString::drop_ptr(ptr);
|
||||
}
|
||||
|
||||
impl<T: Convertible> Convertible for Option<T> {
|
||||
type Ptr = *const <T as Convertible>::Ptr;
|
||||
// impl<T: Convertible> Convertible for Option<T> {
|
||||
// type Ptr = *const <T as Convertible>::Ptr;
|
||||
//
|
||||
// fn into_ptr(self) -> Self::Ptr {
|
||||
// if let Some(inner) = self {
|
||||
// &inner.into_ptr()
|
||||
// } else {
|
||||
// ptr::null()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fn from_ptr(_: Self::Ptr) -> Result<Self, error::TypeConversionError> {
|
||||
// warn!(
|
||||
// "
|
||||
// This should never be called, as this option type resolves
|
||||
// to a null pointer or to a pointer to the real value
|
||||
// (e. g. a `crate::Vec<T>`)
|
||||
// "
|
||||
// );
|
||||
// Ok(Option::default())
|
||||
// }
|
||||
// }
|
||||
|
||||
fn into_ptr(self) -> Self::Ptr {
|
||||
if let Some(inner) = self {
|
||||
&inner.into_ptr()
|
||||
} else {
|
||||
ptr::null()
|
||||
}
|
||||
}
|
||||
|
||||
fn from_ptr(_: Self::Ptr) -> Result<Self, error::TypeConversionError> {
|
||||
warn!(
|
||||
"
|
||||
This should never be called, as this option type resolves
|
||||
to a null pointer or to a pointer to the real value
|
||||
(e. g. a `crate::Vec<T>`)
|
||||
"
|
||||
);
|
||||
Ok(Option::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Convertible, E: Error> Convertible for Result<T, E> {
|
||||
type Ptr = *const <T as Convertible>::Ptr;
|
||||
|
||||
fn into_ptr(self) -> Self::Ptr {
|
||||
match self {
|
||||
Ok(ok) => &ok.into_ptr(),
|
||||
Err(err) => {
|
||||
errno::set(TypeConversionError::ResultWasErr {
|
||||
original_message: err.to_string(),
|
||||
});
|
||||
ptr::null()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn from_ptr(_: Self::Ptr) -> Result<Self, error::TypeConversionError> {
|
||||
warn!(
|
||||
"
|
||||
This should never be called, as this result type resolves
|
||||
to a null pointer (and a set error) or to a pointer to
|
||||
the real value (e. g. a `crate::Vec<T>`)
|
||||
"
|
||||
);
|
||||
todo!()
|
||||
// Ok(Result::Ok(T::default()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Convertible> Convertible for Vec<T> {
|
||||
type Ptr = crate::types::Vec<<T as Convertible>::Ptr>;
|
||||
|
||||
fn into_ptr(self) -> Self::Ptr {
|
||||
let data_vec: Vec<_> = self.into_iter().map(|val| val.into_ptr()).collect();
|
||||
let data_vec = ManuallyDrop::new(data_vec);
|
||||
Self::Ptr {
|
||||
data: data_vec.as_ptr(),
|
||||
length: data_vec.len(),
|
||||
capacity: data_vec.capacity(),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_ptr(ptr: Self::Ptr) -> Result<Self, error::TypeConversionError> {
|
||||
if ptr.data.is_null() {
|
||||
return Err(TypeConversionError::NullPointer);
|
||||
}
|
||||
// TODO(@soispha): Add this, when this feature is stable <2024-02-17>
|
||||
// if !ptr.data.is_aligned() {
|
||||
// return Err(TypeConversionError::NotAligned);
|
||||
// }
|
||||
let base_vec = unsafe {
|
||||
// SAFETY:
|
||||
// We simply hope that c treated our vector as read-only and didn't modify it.
|
||||
// See the SAFETY section of the String implementation for more detail.
|
||||
Vec::from_raw_parts(
|
||||
ptr.data as *mut <T as Convertible>::Ptr,
|
||||
ptr.length,
|
||||
ptr.capacity,
|
||||
)
|
||||
};
|
||||
|
||||
let vec: Vec<_> = base_vec
|
||||
.into_iter()
|
||||
.map(|val| <T as Convertible>::from_ptr(val))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
Ok(vec)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! make_vec_free {
|
||||
($value:ident, $name:ident) => {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn $name(ptr: crate::types::Vec<<$value as Convertible>::Ptr>) {
|
||||
Vec::<$value>::drop_ptr(ptr);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Unsigned
|
||||
make_vec_free!(u8, vec_free_u8);
|
||||
make_vec_free!(u16, vec_free_u16);
|
||||
make_vec_free!(u32, vec_free_u32);
|
||||
make_vec_free!(u64, vec_free_u64);
|
||||
// Signed
|
||||
make_vec_free!(i8, vec_free_i8);
|
||||
make_vec_free!(i16, vec_free_i16);
|
||||
make_vec_free!(i32, vec_free_i32);
|
||||
make_vec_free!(i64, vec_free_i64);
|
||||
// Float
|
||||
make_vec_free!(f32, vec_free_f32);
|
||||
make_vec_free!(f64, vec_free_f64);
|
||||
// Other
|
||||
make_vec_free!(String, vec_free_String);
|
||||
// impl<T: Convertible> Convertible for Vec<T> {
|
||||
// type Ptr = crate::types::Vec<<T as Convertible>::Ptr>;
|
||||
//
|
||||
// fn into_ptr(self) -> Self::Ptr {
|
||||
// let data_vec: Vec<_> = self.into_iter().map(|val| val.into_ptr()).collect();
|
||||
// let data_vec = ManuallyDrop::new(data_vec);
|
||||
// Self::Ptr {
|
||||
// data: data_vec.as_ptr(),
|
||||
// length: data_vec.len(),
|
||||
// capacity: data_vec.capacity(),
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fn from_ptr(ptr: Self::Ptr) -> Result<Self, error::TypeConversionError> {
|
||||
// if ptr.data.is_null() {
|
||||
// return Err(TypeConversionError::NullPointer);
|
||||
// }
|
||||
// // TODO(@soispha): Add this, when this feature is stable <2024-02-17>
|
||||
// // if !ptr.data.is_aligned() {
|
||||
// // return Err(TypeConversionError::NotAligned);
|
||||
// // }
|
||||
// let base_vec = unsafe {
|
||||
// // SAFETY:
|
||||
// // We simply hope that c treated our vector as read-only and didn't modify it.
|
||||
// // See the SAFETY section of the String implementation for more detail.
|
||||
// Vec::from_raw_parts(
|
||||
// ptr.data as *mut <T as Convertible>::Ptr,
|
||||
// ptr.length,
|
||||
// ptr.capacity,
|
||||
// )
|
||||
// };
|
||||
//
|
||||
// let vec: Vec<_> = base_vec
|
||||
// .into_iter()
|
||||
// .map(|val| <T as Convertible>::from_ptr(val))
|
||||
// .collect::<Result<Vec<_>, _>>()?;
|
||||
// Ok(vec)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// macro_rules! make_vec_free {
|
||||
// ($value:ident, $name:ident) => {
|
||||
// #[no_mangle]
|
||||
// pub extern "C" fn $name(ptr: crate::types::Vec<<$value as Convertible>::Ptr>) {
|
||||
// Vec::<$value>::drop_ptr(ptr);
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// // Unsigned
|
||||
// make_vec_free!(u8, vec_free_u8);
|
||||
// make_vec_free!(u16, vec_free_u16);
|
||||
// make_vec_free!(u32, vec_free_u32);
|
||||
// make_vec_free!(u64, vec_free_u64);
|
||||
// // Signed
|
||||
// make_vec_free!(i8, vec_free_i8);
|
||||
// make_vec_free!(i16, vec_free_i16);
|
||||
// make_vec_free!(i32, vec_free_i32);
|
||||
// make_vec_free!(i64, vec_free_i64);
|
||||
// // Float
|
||||
// make_vec_free!(f32, vec_free_f32);
|
||||
// make_vec_free!(f64, vec_free_f64);
|
||||
// // Other
|
||||
// make_vec_free!(String, vec_free_String);
|
||||
|
||||
// FIXME(@soispha): Find a way to support these <2024-02-27>
|
||||
// make_vec_free!(Option<?>, vec_free_Option);
|
||||
|
|
|
@ -20,32 +20,51 @@
|
|||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use crate::types::String;
|
||||
use crate::types::{
|
||||
newtypes::{self, AllocLocation},
|
||||
types_list,
|
||||
};
|
||||
use std::ffi::CString;
|
||||
|
||||
use super::convert_trait::Convertible;
|
||||
|
||||
impl From<std::string::String> for String {
|
||||
impl From<std::string::String> for types_list::String {
|
||||
fn from(value: std::string::String) -> Self {
|
||||
let cstring =
|
||||
CString::new(value).expect("The input is a valid String, this always succeeds");
|
||||
let c_char = cstring.into_ptr();
|
||||
String(c_char)
|
||||
types_list::String(c_char)
|
||||
}
|
||||
}
|
||||
/// Plainly here for convenience
|
||||
impl From<&str> for String {
|
||||
impl From<&str> for types_list::String {
|
||||
fn from(value: &str) -> Self {
|
||||
value.to_owned().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for std::string::String {
|
||||
type Error = crate::types::error::TypeConversionError;
|
||||
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
let cstring = CString::from_ptr(value.0)?;
|
||||
let string = cstring.into_string()?;
|
||||
Ok(string)
|
||||
impl From<newtypes::String> for types_list::String {
|
||||
fn from(value: newtypes::String) -> Self {
|
||||
// NOTE: This is not really performant, but necessary as we otherwise would need c to
|
||||
// differentiate between c allocated strings (which are freed by `free`) and rust allocated strings
|
||||
// (which are freed by `string_free`) <2024-05-04>
|
||||
let value_string = value.into_std_string();
|
||||
value_string.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<types_list::String> for newtypes::String {
|
||||
type Error = crate::types::error::TypeConversionError;
|
||||
|
||||
fn try_from(value: types_list::String) -> Result<Self, Self::Error> {
|
||||
let cstring = CString::from_ptr(value.0)?;
|
||||
let string = cstring.into_string()?;
|
||||
|
||||
Ok(newtypes::String {
|
||||
data: Some(string),
|
||||
// TODO: You could of course do a rust-only round trip, but I think it's reasonable to
|
||||
// assume, that all types_list::String values come from C <2024-05-04>
|
||||
alloc_location: AllocLocation::C,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,24 +23,30 @@
|
|||
// NOTE(@soispha): All types specified here *MUST* be include in the BASE_TYPES constant, otherwise
|
||||
// they are not usable from Trixy code <2023-12-25>
|
||||
|
||||
// NOTE(@soispha): All types added here must also have an added free impl for the vector type (./traits/convert_trait.rs) <2024-02-27>
|
||||
|
||||
use std::ffi::c_char;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct String(pub(crate) *const c_char);
|
||||
|
||||
/// The tag used to tag the c result Enumerations
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct Vec<T> {
|
||||
/// You should cast this value to it's supposed type (readable from the Trixy api definition
|
||||
/// file)
|
||||
pub(crate) data: *const T,
|
||||
pub(crate) length: usize,
|
||||
pub(crate) capacity: usize,
|
||||
pub enum ResultTag {
|
||||
Ok,
|
||||
Err,
|
||||
}
|
||||
|
||||
// #[derive(Debug)]
|
||||
// #[repr(C)]
|
||||
// pub struct Vec<T> {
|
||||
// /// You should cast this value to it's supposed type (readable from the Trixy api definition
|
||||
// /// file)
|
||||
// pub(crate) data: *const T,
|
||||
// pub(crate) length: usize,
|
||||
// pub(crate) capacity: usize,
|
||||
// }
|
||||
|
||||
// Unsigned
|
||||
pub use std::primitive::u16;
|
||||
pub use std::primitive::u32;
|
||||
|
|
|
@ -15,7 +15,10 @@ pub mod trinitrix {
|
|||
pub enum Trinitrix {
|
||||
/// Attribute doc comment, but very ##" "## "# " escaped
|
||||
#[allow(non_camel_case_types)]
|
||||
hi { trixy_output: trixy::oneshot::Sender<trixy::types::String>, name: String },
|
||||
hi {
|
||||
trixy_output: trixy::oneshot::Sender<trixy::types::String>,
|
||||
name: trixy::types::newtypes::String,
|
||||
},
|
||||
}
|
||||
}
|
||||
/* C API */
|
||||
|
|
|
@ -15,7 +15,10 @@ pub mod trinitrix {
|
|||
pub enum Trinitrix {
|
||||
/// Second doc comment
|
||||
#[allow(non_camel_case_types)]
|
||||
hi { trixy_output: trixy::oneshot::Sender<trixy::types::String>, name: String },
|
||||
hi {
|
||||
trixy_output: trixy::oneshot::Sender<trixy::types::String>,
|
||||
name: trixy::types::newtypes::String,
|
||||
},
|
||||
}
|
||||
}
|
||||
/* C API */
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
# Host files
|
||||
|
||||
File path: `out/dir/api.rs`
|
||||
|
||||
```rust
|
||||
// Host code
|
||||
/* Rust API */
|
||||
#[derive(trixy::__private::thiserror::Error)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Debug)]
|
||||
pub enum ErrorOne {
|
||||
#[error("I'm an error")]
|
||||
Error,
|
||||
#[error("I'm also an error'")]
|
||||
ErrorB,
|
||||
}
|
||||
impl From<crate::ErrorOne_c> for ErrorOne {
|
||||
fn from(value: crate::ErrorOne_c) -> Self {
|
||||
match value {
|
||||
crate::ErrorOne_c::Error => Self::Error,
|
||||
crate::ErrorOne_c::ErrorB => Self::ErrorB,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub enum Commands {}
|
||||
/* C API */
|
||||
#[derive(trixy::__private::thiserror::Error)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub enum ErrorOne_c {
|
||||
#[error("I'm an error")]
|
||||
Error,
|
||||
#[error("I'm also an error'")]
|
||||
ErrorB,
|
||||
}
|
||||
impl From<crate::ErrorOne> for ErrorOne_c {
|
||||
fn from(value: crate::ErrorOne) -> Self {
|
||||
match value {
|
||||
crate::ErrorOne::Error => Self::Error,
|
||||
crate::ErrorOne::ErrorB => Self::ErrorB,
|
||||
}
|
||||
}
|
||||
}
|
||||
// vim: filetype=rust
|
||||
```
|
||||
|
||||
# Auxiliary files
|
||||
|
||||
File path: `dist/interface.h`
|
||||
|
||||
```c
|
||||
#if !defined TRIXY_MAIN_HEADER
|
||||
#define TRIXY_MAIN_HEADER
|
||||
|
||||
#include "errno.h"
|
||||
#include "string.h"
|
||||
#include "vec.h"
|
||||
|
||||
/**
|
||||
*/
|
||||
enum ErrorOne
|
||||
{
|
||||
/**
|
||||
*/
|
||||
Error,
|
||||
/**
|
||||
*/
|
||||
ErrorB,
|
||||
};
|
||||
|
||||
#endif // if !defined TRIXY_MAIN_HEADER
|
||||
// vim: filetype=c
|
||||
```
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (C) 2023 - 2024:
|
||||
* The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||
* SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
*
|
||||
* This file is part of the Trixy crate for Trinitrix.
|
||||
*
|
||||
* Trixy is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Lesser GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* and the Lesser GNU General Public License along with this program.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#[derive(Error)]
|
||||
enum ErrorOne {
|
||||
#[error = "I'm an error"]
|
||||
Error,
|
||||
|
||||
#[error = "I'm also an error'"]
|
||||
ErrorB,
|
||||
// TODO: We also need to assert, that all enum veriants have the error attribute. <2024-05-19>
|
||||
}
|
||||
|
||||
// Trixy is sort of a subset of rust
|
||||
// vim: syntax=rust
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (C) 2023 - 2024:
|
||||
* The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||
* SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
*
|
||||
* This file is part of the Trixy crate for Trinitrix.
|
||||
*
|
||||
* Trixy is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Lesser GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* and the Lesser GNU General Public License along with this program.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
use trixy::macros::config::{file_tree::FileTree, trixy::TrixyConfig};
|
||||
|
||||
#[test]
|
||||
pub fn error_derive() {
|
||||
let input = include_str!("./expected.md");
|
||||
let expected: FileTree = input.parse().unwrap();
|
||||
|
||||
let config = TrixyConfig::new("callback_function")
|
||||
.out_dir_path("out/dir")
|
||||
.trixy_path("./tests/error_derive/input.tri")
|
||||
.dist_dir_path("dist")
|
||||
.add_c_headers(false);
|
||||
|
||||
let actual = config.generate();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
|
@ -18,7 +18,10 @@ pub mod trinitrix {
|
|||
pub enum Trinitrix {
|
||||
///I \n also \n contain \n them
|
||||
#[allow(non_camel_case_types)]
|
||||
hi { trixy_output: trixy::oneshot::Sender<trixy::types::String>, name: String },
|
||||
hi {
|
||||
trixy_output: trixy::oneshot::Sender<trixy::types::String>,
|
||||
name: trixy::types::newtypes::String,
|
||||
},
|
||||
}
|
||||
}
|
||||
/* C API */
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (C) 2023 - 2024:
|
||||
* The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||
* SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
*
|
||||
* This file is part of the Trixy crate for Trinitrix.
|
||||
*
|
||||
* Trixy is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Lesser GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* and the Lesser GNU General Public License along with this program.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
mod trinitrix {
|
||||
#[derive(Error)]
|
||||
enum GetBError {
|
||||
#[error = "Could not do A!"]
|
||||
A,
|
||||
|
||||
#[error = "Failed on calling b"]
|
||||
B,
|
||||
}
|
||||
|
||||
fn get_a() -> Result<u32, String>;
|
||||
fn get_b() -> Result<String, GetBError>;
|
||||
}
|
||||
|
||||
// Trixy is sort of a subset of rust
|
||||
// vim: syntax=rust
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (C) 2023 - 2024:
|
||||
* The Trinitrix Project <soispha@vhack.eu, antifallobst@systemausfall.org>
|
||||
* SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
*
|
||||
* This file is part of the Trixy crate for Trinitrix.
|
||||
*
|
||||
* Trixy is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the Lesser GNU General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* and the Lesser GNU General Public License along with this program.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
use trixy::macros::config::{file_tree::FileTree, trixy::TrixyConfig};
|
||||
|
||||
#[test]
|
||||
pub fn result() {
|
||||
let input = include_str!("./expected.md");
|
||||
let expected: FileTree = input.parse().unwrap();
|
||||
|
||||
let config = TrixyConfig::new("callback_function")
|
||||
.out_dir_path("out/dir")
|
||||
.trixy_path("./tests/result/input.tri")
|
||||
.dist_dir_path("dist")
|
||||
.add_c_headers(false);
|
||||
|
||||
let actual = config.generate();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
|
@ -34,7 +34,7 @@ pub mod trinitrix {
|
|||
/// Send a message to the current room
|
||||
/// The send message is interpreted literally.
|
||||
#[allow(non_camel_case_types)]
|
||||
room_message_send { message: String },
|
||||
room_message_send { message: trixy::types::newtypes::String },
|
||||
Ui(ui::Ui),
|
||||
Keymaps(keymaps::Keymaps),
|
||||
Raw(raw::Raw),
|
||||
|
@ -105,15 +105,22 @@ pub mod trinitrix {
|
|||
pub enum Keymaps {
|
||||
/// Add a new keymapping
|
||||
#[allow(non_camel_case_types)]
|
||||
add { mode: String, key: String, callback: extern "C" fn() },
|
||||
add {
|
||||
mode: trixy::types::newtypes::String,
|
||||
key: trixy::types::newtypes::String,
|
||||
callback: extern "C" fn(),
|
||||
},
|
||||
/// Remove a keymapping
|
||||
///
|
||||
/// Does nothing, if the keymapping doesn't exists yet
|
||||
#[allow(non_camel_case_types)]
|
||||
remove { mode: String, key: String },
|
||||
remove {
|
||||
mode: trixy::types::newtypes::String,
|
||||
key: trixy::types::newtypes::String,
|
||||
},
|
||||
/// List declared keymappings
|
||||
#[allow(non_camel_case_types)]
|
||||
get { mode: String },
|
||||
get { mode: trixy::types::newtypes::String },
|
||||
}
|
||||
}
|
||||
/// Functions only used internally within Trinitrix
|
||||
|
@ -122,17 +129,17 @@ pub mod trinitrix {
|
|||
pub enum Raw {
|
||||
/// Send an error to the default error output
|
||||
#[allow(non_camel_case_types)]
|
||||
raise_error { error_message: String },
|
||||
raise_error { error_message: trixy::types::newtypes::String },
|
||||
/// Send output to the default output
|
||||
/// This is mainly used to display the final
|
||||
/// output of evaluated lua commands.
|
||||
#[allow(non_camel_case_types)]
|
||||
display_output { output_message: String },
|
||||
display_output { output_message: trixy::types::newtypes::String },
|
||||
/// Input a character without checking for possible keymaps
|
||||
/// If the current state does not expect input, this character is ignored
|
||||
/// The encoding is the same as in the `trinitrix.api.keymaps` commands
|
||||
#[allow(non_camel_case_types)]
|
||||
send_input_unprocessed { input: String },
|
||||
send_input_unprocessed { input: trixy::types::newtypes::String },
|
||||
Private(__private::Private),
|
||||
}
|
||||
/// This namespace is used to store some command specific data (like functions, as
|
||||
|
|
|
@ -28,7 +28,7 @@ pub mod test {
|
|||
}
|
||||
}
|
||||
fn from_ptr(
|
||||
ptr: Self::Ptr,
|
||||
_ptr: Self::Ptr,
|
||||
) -> Result<Self, trixy::types::error::TypeConversionError> {
|
||||
todo!()
|
||||
}
|
||||
|
|
|
@ -19,9 +19,14 @@
|
|||
# and the Lesser GNU General Public License along with this program.
|
||||
# If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
cargo update && cargo upgrade
|
||||
update() {
|
||||
[ "$1" = "upgrade" ] && cargo upgrade
|
||||
cargo update
|
||||
}
|
||||
|
||||
update "$@"
|
||||
cd ./example/main || {
|
||||
echo "Main example is missing"
|
||||
exit 1
|
||||
}
|
||||
cargo update && cargo upgrade
|
||||
update "$@"
|
||||
|
|
Reference in New Issue