diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..ed08e49
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,161 @@
+---
+Language: Cpp
+# BasedOnStyle: Microsoft
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignEscapedNewlines: Right
+AlignOperands: Align
+AlignTrailingComments: true
+AllowAllArgumentsOnNextLine: true
+AllowAllConstructorInitializersOnNextLine: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortEnumsOnASingleLine: false
+AllowShortBlocksOnASingleLine: Never
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortLambdasOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: MultiLine
+AttributeMacros:
+ - __capability
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterCaseLabel: false
+ AfterClass: true
+ AfterControlStatement: Always
+ AfterEnum: true
+ AfterFunction: true
+ AfterNamespace: true
+ AfterObjCDeclaration: true
+ AfterStruct: true
+ AfterUnion: false
+ AfterExternBlock: true
+ BeforeCatch: true
+ BeforeElse: true
+ BeforeLambdaBody: false
+ BeforeWhile: false
+ IndentBraces: false
+ SplitEmptyFunction: true
+ SplitEmptyRecord: true
+ SplitEmptyNamespace: true
+BreakBeforeBinaryOperators: None
+BreakBeforeConceptDeclarations: true
+BreakBeforeBraces: Custom
+BreakBeforeInheritanceComma: false
+BreakInheritanceList: BeforeColon
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeColon
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: true
+ColumnLimit: 120
+CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DeriveLineEnding: true
+DerivePointerAlignment: false
+DisableFormat: false
+EmptyLineBeforeAccessModifier: LogicalBlock
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros:
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
+StatementAttributeLikeMacros:
+ - Q_EMIT
+IncludeBlocks: Preserve
+IncludeCategories:
+ - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
+ Priority: 2
+ SortPriority: 0
+ CaseSensitive: false
+ - Regex: '^(<|"(gtest|gmock|isl|json)/)'
+ Priority: 3
+ SortPriority: 0
+ CaseSensitive: false
+ - Regex: '.*'
+ Priority: 1
+ SortPriority: 0
+ CaseSensitive: false
+IncludeIsMainRegex: '(Test)?$'
+IncludeIsMainSourceRegex: ''
+IndentCaseLabels: false
+IndentCaseBlocks: false
+IndentGotoLabels: true
+IndentPPDirectives: None
+IndentExternBlock: AfterExternBlock
+IndentRequires: false
+IndentWidth: 4
+IndentWrappedFunctionNames: false
+InsertTrailingCommas: None
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBinPackProtocolList: Auto
+ObjCBlockIndentWidth: 2
+ObjCBreakBeforeNestedBlockParam: true
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakAssignment: 2
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyBreakTemplateDeclaration: 10
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 1000
+PenaltyIndentedWhitespace: 0
+PointerAlignment: Right
+ReflowComments: true
+SortIncludes: true
+SortJavaStaticImport: Before
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: false
+SpaceAfterLogicalNot: false
+SpaceAfterTemplateKeyword: true
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCaseColon: false
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatements
+SpaceAroundPointerQualifiers: Default
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceInEmptyBlock: false
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInConditionalStatement: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+SpaceBeforeSquareBrackets: false
+BitFieldColonSpacing: Both
+Standard: Latest
+StatementMacros:
+ - Q_UNUSED
+ - QT_REQUIRE_VERSION
+TabWidth: 4
+UseCRLF: false
+UseTab: Never
+WhitespaceSensitiveMacros:
+ - STRINGIZE
+ - PP_STRINGIZE
+ - BOOST_PP_STRINGIZE
+ - NS_SWIFT_NAME
+ - CF_SWIFT_NAME
+...
diff --git a/.clang-tidy b/.clang-tidy
new file mode 100644
index 0000000..554459d
--- /dev/null
+++ b/.clang-tidy
@@ -0,0 +1,596 @@
+---
+Checks: '*,
+ -bugprone-easily-swappable-parameters,
+ -bugprone-lambda-function-name,
+ -readability-magic-numbers,
+ -hicpp-no-array-decay,
+ -hicpp-signed-bitwise,
+ -hicpp-vararg,
+ -misc-non-private-member-variables-in-classes,
+ -cppcoreguidelines-*,
+ -fuchsia-*,
+ -altera-*,
+ -android-*,
+ -llvmlibc-*,
+ -readability-convert-member-functions-to-static,
+ -boost-use-ranges,
+ -google-objc-function-naming,
+ -google-objc-global-variable-declaration,
+ -performance-enum-size'
+WarningsAsErrors: ''
+HeaderFilterRegex: '^(?!magic_enum).*$'
+FormatStyle: Microsoft
+CheckOptions:
+ - key: readability-identifier-naming.ClassCase
+ value: CamelCase
+ - key: readability-identifier-naming.ClassMemberCase
+ value: lower_case
+ - key: readability-identifier-naming.ConstexprVariableCase
+ value: CamelCase
+ - key: readability-identifier-naming.ConstexprVariablePrefix
+ value: k
+ - key: readability-identifier-naming.EnumCase
+ value: CamelCase
+ - key: readability-identifier-naming.EnumConstantCase
+ value: CamelCase
+ - key: readability-identifier-naming.EnumConstantPrefix
+ value: k
+ - key: readability-identifier-naming.FunctionCase
+ value: camelBack
+ - key: readability-identifier-naming.FunctionIgnoredRegexp
+ value: '^BM_.*$'
+ - key: readability-identifier-naming.GlobalConstantCase
+ value: CamelCase
+ - key: readability-identifier-naming.GlobalConstantPrefix
+ value: k
+ - key: readability-identifier-naming.StaticConstantCase
+ value: CamelCase
+ - key: readability-identifier-naming.StaticConstantPrefix
+ value: k
+ - key: readability-identifier-naming.StaticVariableCase
+ value: lower_case
+ - key: readability-identifier-naming.MacroDefinitionCase
+ value: UPPER_CASE
+ - key: readability-identifier-naming.MacroDefinitionIgnoredRegexp
+ value: '^[A-Z]+(_[A-Z]+)*_$'
+ - key: readability-identifier-naming.MemberCase
+ value: lower_case
+ - key: readability-identifier-naming.PrivateMemberSuffix
+ value: _
+ - key: readability-identifier-naming.PublicMemberSuffix
+ value: ''
+ - key: readability-identifier-naming.NamespaceCase
+ value: lower_case
+ - key: readability-identifier-naming.ParameterCase
+ value: lower_case
+ - key: readability-identifier-naming.TypeAliasCase
+ value: CamelCase
+ - key: readability-identifier-naming.TypedefCase
+ value: CamelCase
+ - key: readability-identifier-naming.VariableCase
+ value: lower_case
+ - key: readability-identifier-naming.IgnoreMainLikeFunctions
+ value: 'true'
+ - key: readability-identifier-naming.AggressiveDependentMemberLookup
+ value: 'false'
+ - key: readability-identifier-naming.IgnoreFailedSplit
+ value: 'false'
+ - key: abseil-string-find-startswith.AbseilStringsMatchHeader
+ value: 'absl/strings/match.h'
+ - key: abseil-string-find-startswith.IncludeStyle
+ value: llvm
+ - key: abseil-string-find-startswith.StringLikeClasses
+ value: '::std::basic_string'
+ - key: abseil-string-find-str-contains.AbseilStringsMatchHeader
+ value: 'absl/strings/match.h'
+ - key: abseil-string-find-str-contains.IncludeStyle
+ value: llvm
+ - key: abseil-string-find-str-contains.StringLikeClasses
+ value: '::std::basic_string;::std::basic_string_view;::absl::string_view'
+ - key: bugprone-argument-comment.CommentBoolLiterals
+ value: '0'
+ - key: bugprone-argument-comment.CommentCharacterLiterals
+ value: '0'
+ - key: bugprone-argument-comment.CommentFloatLiterals
+ value: '0'
+ - key: bugprone-argument-comment.CommentIntegerLiterals
+ value: '0'
+ - key: bugprone-argument-comment.CommentNullPtrs
+ value: '0'
+ - key: bugprone-argument-comment.CommentStringLiterals
+ value: '0'
+ - key: bugprone-argument-comment.CommentUserDefinedLiterals
+ value: '0'
+ - key: bugprone-argument-comment.IgnoreSingleArgument
+ value: '0'
+ - key: bugprone-argument-comment.StrictMode
+ value: '0'
+ - key: bugprone-assert-side-effect.AssertMacros
+ value: assert
+ - key: bugprone-assert-side-effect.CheckFunctionCalls
+ value: 'false'
+ - key: bugprone-dangling-handle.HandleClasses
+ value: 'std::basic_string_view;std::experimental::basic_string_view'
+ - key: bugprone-dynamic-static-initializers.HeaderFileExtensions
+ value: ';h;hh;hpp;hxx'
+ - key: bugprone-exception-escape.FunctionsThatShouldNotThrow
+ value: ''
+ - key: bugprone-exception-escape.IgnoredExceptions
+ value: ''
+ - key: bugprone-misplaced-widening-cast.CheckImplicitCasts
+ value: 'false'
+ - key: bugprone-narrowing-conversions.PedanticMode
+ value: 'false'
+ - key: bugprone-narrowing-conversions.WarnOnFloatingPointNarrowingConversion
+ value: 'true'
+ - key: bugprone-not-null-terminated-result.WantToUseSafeFunctions
+ value: 'true'
+ - key: bugprone-reserved-identifier.AggressiveDependentMemberLookup
+ value: 'false'
+ - key: bugprone-reserved-identifier.AllowedIdentifiers
+ value: ''
+ - key: bugprone-reserved-identifier.Invert
+ value: 'false'
+ - key: bugprone-signed-char-misuse.CharTypdefsToIgnore
+ value: ''
+ - key: bugprone-signed-char-misuse.DiagnoseSignedUnsignedCharComparisons
+ value: 'true'
+ - key: bugprone-sizeof-expression.WarnOnSizeOfCompareToConstant
+ value: 'true'
+ - key: bugprone-sizeof-expression.WarnOnSizeOfConstant
+ value: 'true'
+ - key: bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression
+ value: 'false'
+ - key: bugprone-sizeof-expression.WarnOnSizeOfThis
+ value: 'true'
+ - key: bugprone-string-constructor.LargeLengthThreshold
+ value: '8388608'
+ - key: bugprone-string-constructor.WarnOnLargeLength
+ value: 'true'
+ - key: bugprone-suspicious-enum-usage.StrictMode
+ value: 'false'
+ - key: bugprone-suspicious-include.HeaderFileExtensions
+ value: ';h;hh;hpp;hxx'
+ - key: bugprone-suspicious-include.ImplementationFileExtensions
+ value: 'c;cc;cpp;cxx'
+ - key: bugprone-suspicious-missing-comma.MaxConcatenatedTokens
+ value: '5'
+ - key: bugprone-suspicious-missing-comma.RatioThreshold
+ value: '0.200000'
+ - key: bugprone-suspicious-missing-comma.SizeThreshold
+ value: '5'
+ - key: bugprone-suspicious-string-compare.StringCompareLikeFunctions
+ value: ''
+ - key: bugprone-suspicious-string-compare.WarnOnImplicitComparison
+ value: 'true'
+ - key: bugprone-suspicious-string-compare.WarnOnLogicalNotComparison
+ value: 'false'
+ - key: bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit
+ value: '16'
+ - key: bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField
+ value: 'true'
+ - key: bugprone-unused-return-value.CheckedFunctions
+ value: '::std::async;::std::launder;::std::remove;::std::remove_if;::std::unique;::std::unique_ptr::release;::std::basic_string::empty;::std::vector::empty;::std::back_inserter;::std::distance;::std::find;::std::find_if;::std::inserter;::std::lower_bound;::std::make_pair;::std::map::count;::std::map::find;::std::map::lower_bound;::std::multimap::equal_range;::std::multimap::upper_bound;::std::set::count;::std::set::find;::std::setfill;::std::setprecision;::std::setw;::std::upper_bound;::std::vector::at;::bsearch;::ferror;::feof;::isalnum;::isalpha;::isblank;::iscntrl;::isdigit;::isgraph;::islower;::isprint;::ispunct;::isspace;::isupper;::iswalnum;::iswprint;::iswspace;::isxdigit;::memchr;::memcmp;::strcmp;::strcoll;::strncmp;::strpbrk;::strrchr;::strspn;::strstr;::wcscmp;::access;::bind;::connect;::difftime;::dlsym;::fnmatch;::getaddrinfo;::getopt;::htonl;::htons;::iconv_open;::inet_addr;::isascii;::isatty;::mmap;::newlocale;::openat;::pathconf;::pthread_equal;::pthread_getspecific;::pthread_mutex_trylock;::readdir;::readlink;::recvmsg;::regexec;::scandir;::semget;::setjmp;::shm_open;::shmget;::sigismember;::strcasecmp;::strsignal;::ttyname'
+ - key: cert-dcl16-c.IgnoreMacros
+ value: 'true'
+ - key: cert-dcl16-c.NewSuffixes
+ value: 'L;LL;LU;LLU'
+ - key: cert-dcl37-c.AggressiveDependentMemberLookup
+ value: 'false'
+ - key: cert-dcl37-c.AllowedIdentifiers
+ value: ''
+ - key: cert-dcl37-c.Invert
+ value: 'false'
+ - key: cert-dcl51-cpp.AggressiveDependentMemberLookup
+ value: 'false'
+ - key: cert-dcl51-cpp.AllowedIdentifiers
+ value: ''
+ - key: cert-dcl51-cpp.Invert
+ value: 'false'
+ - key: cert-dcl59-cpp.HeaderFileExtensions
+ value: ';h;hh;hpp;hxx'
+ - key: cert-err09-cpp.CheckThrowTemporaries
+ value: 'true'
+ - key: cert-err09-cpp.MaxSize
+ value: '1000000'
+ - key: cert-err09-cpp.WarnOnLargeObjects
+ value: 'false'
+ - key: cert-err61-cpp.CheckThrowTemporaries
+ value: 'true'
+ - key: cert-err61-cpp.MaxSize
+ value: '1000000'
+ - key: cert-err61-cpp.WarnOnLargeObjects
+ value: 'false'
+ - key: cert-msc32-c.DisallowedSeedTypes
+ value: 'time_t,std::time_t'
+ - key: cert-msc51-cpp.DisallowedSeedTypes
+ value: 'time_t,std::time_t'
+ - key: cert-oop11-cpp.IncludeStyle
+ value: llvm
+ - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
+ value: 'false'
+ - key: cert-oop57-cpp.MemCmpNames
+ value: ''
+ - key: cert-oop57-cpp.MemCpyNames
+ value: ''
+ - key: cert-oop57-cpp.MemSetNames
+ value: ''
+ - key: cert-str34-c.CharTypdefsToIgnore
+ value: ''
+ - key: cert-str34-c.DiagnoseSignedUnsignedCharComparisons
+ value: 'false'
+ - key: cppcoreguidelines-avoid-magic-numbers.IgnoreAllFloatingPointValues
+ value: 'false'
+ - key: cppcoreguidelines-avoid-magic-numbers.IgnoreBitFieldsWidths
+ value: 'true'
+ - key: cppcoreguidelines-avoid-magic-numbers.IgnorePowersOf2IntegerValues
+ value: 'false'
+ - key: cppcoreguidelines-avoid-magic-numbers.IgnoredFloatingPointValues
+ value: '1.0;100.0;'
+ - key: cppcoreguidelines-avoid-magic-numbers.IgnoredIntegerValues
+ value: '1;2;3;4;'
+ - key: cppcoreguidelines-explicit-virtual-functions.AllowOverrideAndFinal
+ value: 'false'
+ - key: cppcoreguidelines-explicit-virtual-functions.FinalSpelling
+ value: final
+ - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors
+ value: 'true'
+ - key: cppcoreguidelines-explicit-virtual-functions.OverrideSpelling
+ value: override
+ - key: cppcoreguidelines-init-variables.IncludeStyle
+ value: llvm
+ - key: cppcoreguidelines-init-variables.MathHeader
+ value: math.h
+ - key: cppcoreguidelines-macro-usage.AllowedRegexp
+ value: '^DEBUG_*'
+ - key: cppcoreguidelines-macro-usage.CheckCapsOnly
+ value: 'false'
+ - key: cppcoreguidelines-macro-usage.IgnoreCommandLineMacros
+ value: 'true'
+ - key: cppcoreguidelines-narrowing-conversions.PedanticMode
+ value: 'false'
+ - key: cppcoreguidelines-narrowing-conversions.WarnOnFloatingPointNarrowingConversion
+ value: 'true'
+ - key: cppcoreguidelines-no-malloc.Allocations
+ value: '::malloc;::calloc'
+ - key: cppcoreguidelines-no-malloc.Deallocations
+ value: '::free'
+ - key: cppcoreguidelines-no-malloc.Reallocations
+ value: '::realloc'
+ - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
+ value: 'true'
+ - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnorePublicMemberVariables
+ value: 'false'
+ - key: cppcoreguidelines-owning-memory.LegacyResourceConsumers
+ value: '::free;::realloc;::freopen;::fclose'
+ - key: cppcoreguidelines-owning-memory.LegacyResourceProducers
+ value: '::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile'
+ - key: cppcoreguidelines-pro-bounds-constant-array-index.GslHeader
+ value: ''
+ - key: cppcoreguidelines-pro-bounds-constant-array-index.IncludeStyle
+ value: llvm
+ - key: cppcoreguidelines-pro-type-member-init.IgnoreArrays
+ value: 'false'
+ - key: cppcoreguidelines-pro-type-member-init.UseAssignment
+ value: 'false'
+ - key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions
+ value: 'false'
+ - key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctionsWhenCopyIsDeleted
+ value: 'false'
+ - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor
+ value: 'false'
+ - key: google-build-namespaces.HeaderFileExtensions
+ value: ';h;hh;hpp;hxx'
+ - key: google-global-names-in-headers.HeaderFileExtensions
+ value: ';h;hh;hpp;hxx'
+ - key: google-readability-braces-around-statements.ShortStatementLines
+ value: '1'
+ - key: google-readability-function-size.BranchThreshold
+ value: '4294967295'
+ - key: google-readability-function-size.LineThreshold
+ value: '4294967295'
+ - key: google-readability-function-size.NestingThreshold
+ value: '4294967295'
+ - key: google-readability-function-size.ParameterThreshold
+ value: '4294967295'
+ - key: google-readability-function-size.StatementThreshold
+ value: '800'
+ - key: google-readability-function-size.VariableThreshold
+ value: '4294967295'
+ - key: google-readability-namespace-comments.ShortNamespaceLines
+ value: '10'
+ - key: google-readability-namespace-comments.SpacesBeforeComments
+ value: '2'
+ - key: google-runtime-int.SignedTypePrefix
+ value: int
+ - key: google-runtime-int.TypeSuffix
+ value: ''
+ - key: google-runtime-int.UnsignedTypePrefix
+ value: uint
+ - key: google-runtime-references.IncludedTypes
+ value: ''
+ - key: hicpp-braces-around-statements.ShortStatementLines
+ value: '0'
+ - key: hicpp-function-size.BranchThreshold
+ value: '4294967295'
+ - key: hicpp-function-size.LineThreshold
+ value: '4294967295'
+ - key: hicpp-function-size.NestingThreshold
+ value: '4294967295'
+ - key: hicpp-function-size.ParameterThreshold
+ value: '4294967295'
+ - key: hicpp-function-size.StatementThreshold
+ value: '800'
+ - key: hicpp-function-size.VariableThreshold
+ value: '4294967295'
+ - key: hicpp-member-init.IgnoreArrays
+ value: 'false'
+ - key: hicpp-member-init.UseAssignment
+ value: 'false'
+ - key: hicpp-move-const-arg.CheckTriviallyCopyableMove
+ value: 'true'
+ - key: hicpp-multiway-paths-covered.WarnOnMissingElse
+ value: 'false'
+ - key: hicpp-no-malloc.Allocations
+ value: '::malloc;::calloc'
+ - key: hicpp-no-malloc.Deallocations
+ value: '::free'
+ - key: hicpp-no-malloc.Reallocations
+ value: '::realloc'
+ - key: hicpp-signed-bitwise.IgnorePositiveIntegerLiterals
+ value: 'false'
+ - key: hicpp-special-member-functions.AllowMissingMoveFunctions
+ value: 'false'
+ - key: hicpp-special-member-functions.AllowMissingMoveFunctionsWhenCopyIsDeleted
+ value: 'false'
+ - key: hicpp-special-member-functions.AllowSoleDefaultDtor
+ value: 'false'
+ - key: hicpp-uppercase-literal-suffix.IgnoreMacros
+ value: 'true'
+ - key: hicpp-uppercase-literal-suffix.NewSuffixes
+ value: ''
+ - key: hicpp-use-auto.MinTypeNameLength
+ value: '5'
+ - key: hicpp-use-auto.RemoveStars
+ value: 'false'
+ - key: hicpp-use-emplace.ContainersWithPushBack
+ value: '::std::vector;::std::list;::std::deque'
+ - key: hicpp-use-emplace.IgnoreImplicitConstructors
+ value: 'false'
+ - key: hicpp-use-emplace.SmartPointers
+ value: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr'
+ - key: hicpp-use-emplace.TupleMakeFunctions
+ value: '::std::make_pair;::std::make_tuple'
+ - key: hicpp-use-emplace.TupleTypes
+ value: '::std::pair;::std::tuple'
+ - key: hicpp-use-equals-default.IgnoreMacros
+ value: 'true'
+ - key: hicpp-use-equals-delete.IgnoreMacros
+ value: 'true'
+ - key: hicpp-use-noexcept.ReplacementString
+ value: ''
+ - key: hicpp-use-noexcept.UseNoexceptFalse
+ value: 'true'
+ - key: hicpp-use-nullptr.NullMacros
+ value: ''
+ - key: hicpp-use-override.AllowOverrideAndFinal
+ value: 'false'
+ - key: hicpp-use-override.FinalSpelling
+ value: final
+ - key: hicpp-use-override.IgnoreDestructors
+ value: 'false'
+ - key: hicpp-use-override.OverrideSpelling
+ value: override
+ - key: llvm-else-after-return.WarnOnConditionVariables
+ value: 'false'
+ - key: llvm-else-after-return.WarnOnUnfixable
+ value: 'false'
+ - key: llvm-header-guard.HeaderFileExtensions
+ value: ';h;hh;hpp;hxx'
+ - key: llvm-namespace-comment.ShortNamespaceLines
+ value: '1'
+ - key: llvm-namespace-comment.SpacesBeforeComments
+ value: '1'
+ - key: llvm-qualified-auto.AddConstToQualified
+ value: 'false'
+ - key: misc-definitions-in-headers.HeaderFileExtensions
+ value: ';h;hh;hpp;hxx'
+ - key: misc-definitions-in-headers.UseHeaderFileExtension
+ value: 'true'
+ - key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
+ value: 'false'
+ - key: misc-non-private-member-variables-in-classes.IgnorePublicMemberVariables
+ value: 'false'
+ - key: misc-throw-by-value-catch-by-reference.CheckThrowTemporaries
+ value: 'true'
+ - key: misc-throw-by-value-catch-by-reference.MaxSize
+ value: '1000000'
+ - key: misc-throw-by-value-catch-by-reference.WarnOnLargeObjects
+ value: 'false'
+ - key: misc-unused-parameters.StrictMode
+ value: 'false'
+ - key: modernize-avoid-bind.PermissiveParameterList
+ value: 'false'
+ - key: modernize-loop-convert.MaxCopySize
+ value: '16'
+ - key: modernize-loop-convert.MinConfidence
+ value: reasonable
+ - key: modernize-loop-convert.NamingStyle
+ value: CamelCase
+ - key: modernize-make-shared.IgnoreMacros
+ value: 'true'
+ - key: modernize-make-shared.IncludeStyle
+ value: llvm
+ - key: modernize-make-shared.MakeSmartPtrFunction
+ value: 'std::make_shared'
+ - key: modernize-make-shared.MakeSmartPtrFunctionHeader
+ value: memory
+ - key: modernize-make-unique.IgnoreMacros
+ value: 'true'
+ - key: modernize-make-unique.IncludeStyle
+ value: llvm
+ - key: modernize-make-unique.MakeSmartPtrFunction
+ value: 'std::make_unique'
+ - key: modernize-make-unique.MakeSmartPtrFunctionHeader
+ value: memory
+ - key: modernize-pass-by-value.IncludeStyle
+ value: llvm
+ - key: modernize-pass-by-value.ValuesOnly
+ value: 'false'
+ - key: modernize-raw-string-literal.DelimiterStem
+ value: lit
+ - key: modernize-raw-string-literal.ReplaceShorterLiterals
+ value: 'false'
+ - key: modernize-replace-auto-ptr.IncludeStyle
+ value: llvm
+ - key: modernize-replace-disallow-copy-and-assign-macro.MacroName
+ value: DISALLOW_COPY_AND_ASSIGN
+ - key: modernize-replace-random-shuffle.IncludeStyle
+ value: llvm
+ - key: modernize-use-auto.MinTypeNameLength
+ value: '5'
+ - key: modernize-use-auto.RemoveStars
+ value: 'false'
+ - key: modernize-use-bool-literals.IgnoreMacros
+ value: 'true'
+ - key: modernize-use-default-member-init.IgnoreMacros
+ value: 'true'
+ - key: modernize-use-default-member-init.UseAssignment
+ value: 'false'
+ - key: modernize-use-emplace.ContainersWithPushBack
+ value: '::std::vector;::std::list;::std::deque'
+ - key: modernize-use-emplace.IgnoreImplicitConstructors
+ value: 'false'
+ - key: modernize-use-emplace.SmartPointers
+ value: '::std::shared_ptr;::std::unique_ptr;::std::auto_ptr;::std::weak_ptr'
+ - key: modernize-use-emplace.TupleMakeFunctions
+ value: '::std::make_pair;::std::make_tuple'
+ - key: modernize-use-emplace.TupleTypes
+ value: '::std::pair;::std::tuple'
+ - key: modernize-use-equals-default.IgnoreMacros
+ value: 'true'
+ - key: modernize-use-equals-delete.IgnoreMacros
+ value: 'true'
+ - key: modernize-use-nodiscard.ReplacementString
+ value: '[[nodiscard]]'
+ - key: modernize-use-noexcept.ReplacementString
+ value: ''
+ - key: modernize-use-noexcept.UseNoexceptFalse
+ value: 'true'
+ - key: modernize-use-nullptr.NullMacros
+ value: 'NULL'
+ - key: modernize-use-override.AllowOverrideAndFinal
+ value: 'false'
+ - key: modernize-use-override.FinalSpelling
+ value: final
+ - key: modernize-use-override.IgnoreDestructors
+ value: 'false'
+ - key: modernize-use-override.OverrideSpelling
+ value: override
+ - key: modernize-use-transparent-functors.SafeMode
+ value: 'false'
+ - key: modernize-use-using.IgnoreMacros
+ value: 'true'
+ - key: objc-forbidden-subclassing.ForbiddenSuperClassNames
+ value: 'ABNewPersonViewController;ABPeoplePickerNavigationController;ABPersonViewController;ABUnknownPersonViewController;NSHashTable;NSMapTable;NSPointerArray;NSPointerFunctions;NSTimer;UIActionSheet;UIAlertView;UIImagePickerController;UITextInputMode;UIWebView'
+ - key: openmp-exception-escape.IgnoredExceptions
+ value: ''
+ - key: performance-faster-string-find.StringLikeClasses
+ value: '::std::basic_string;::std::basic_string_view'
+ - key: performance-for-range-copy.AllowedTypes
+ value: ''
+ - key: performance-for-range-copy.WarnOnAllAutoCopies
+ value: 'false'
+ - key: performance-inefficient-string-concatenation.StrictMode
+ value: 'false'
+ - key: performance-inefficient-vector-operation.EnableProto
+ value: 'false'
+ - key: performance-inefficient-vector-operation.VectorLikeClasses
+ value: '::std::vector'
+ - key: performance-move-const-arg.CheckTriviallyCopyableMove
+ value: 'true'
+ - key: performance-move-constructor-init.IncludeStyle
+ value: llvm
+ - key: performance-no-automatic-move.AllowedTypes
+ value: ''
+ - key: performance-type-promotion-in-math-fn.IncludeStyle
+ value: llvm
+ - key: performance-unnecessary-copy-initialization.AllowedTypes
+ value: ''
+ - key: performance-unnecessary-value-param.AllowedTypes
+ value: ''
+ - key: performance-unnecessary-value-param.IncludeStyle
+ value: llvm
+ - key: portability-restrict-system-includes.Includes
+ value: '*'
+ - key: portability-simd-intrinsics.Std
+ value: ''
+ - key: portability-simd-intrinsics.Suggest
+ value: '0'
+ - key: readability-braces-around-statements.ShortStatementLines
+ value: '0'
+ - key: readability-else-after-return.WarnOnConditionVariables
+ value: 'true'
+ - key: readability-else-after-return.WarnOnUnfixable
+ value: 'true'
+ - key: readability-function-size.BranchThreshold
+ value: '4294967295'
+ - key: readability-function-size.LineThreshold
+ value: '4294967295'
+ - key: readability-function-size.NestingThreshold
+ value: '4294967295'
+ - key: readability-function-size.ParameterThreshold
+ value: '4294967295'
+ - key: readability-function-size.StatementThreshold
+ value: '800'
+ - key: readability-function-size.VariableThreshold
+ value: '4294967295'
+ - key: readability-implicit-bool-conversion.AllowIntegerConditions
+ value: 'false'
+ - key: readability-implicit-bool-conversion.AllowPointerConditions
+ value: 'false'
+ - key: readability-inconsistent-declaration-parameter-name.IgnoreMacros
+ value: 'true'
+ - key: readability-inconsistent-declaration-parameter-name.Strict
+ value: 'false'
+ - key: readability-magic-numbers.IgnoreAllFloatingPointValues
+ value: 'false'
+ - key: readability-magic-numbers.IgnoreBitFieldsWidths
+ value: 'true'
+ - key: readability-magic-numbers.IgnorePowersOf2IntegerValues
+ value: 'false'
+ - key: readability-magic-numbers.IgnoredFloatingPointValues
+ value: '1.0;100.0;'
+ - key: readability-magic-numbers.IgnoredIntegerValues
+ value: '1;2;3;4;'
+ - key: readability-qualified-auto.AddConstToQualified
+ value: 'true'
+ - key: readability-redundant-declaration.IgnoreMacros
+ value: 'true'
+ - key: readability-redundant-member-init.IgnoreBaseInCopyConstructors
+ value: 'false'
+ - key: readability-redundant-smartptr-get.IgnoreMacros
+ value: 'true'
+ - key: readability-redundant-string-init.StringNames
+ value: '::std::basic_string'
+ - key: readability-simplify-boolean-expr.ChainedConditionalAssignment
+ value: 'false'
+ - key: readability-simplify-boolean-expr.ChainedConditionalReturn
+ value: 'false'
+ - key: readability-simplify-subscript-expr.Types
+ value: '::std::basic_string;::std::basic_string_view;::std::vector;::std::array'
+ - key: readability-static-accessed-through-instance.NameSpecifierNestingThreshold
+ value: '3'
+ - key: readability-uppercase-literal-suffix.IgnoreMacros
+ value: 'true'
+ - key: readability-uppercase-literal-suffix.NewSuffixes
+ value: ''
+ - key: zircon-temporary-objects.Names
+ value: ''
+# allow x,y,z single letter names, to be used for coordinates
+# allow fd (file descriptor) as it's a common POSIX convention
+ - key: readability-identifier-length.IgnoredVariableNames
+ value: '^(x|y|z|m0|m1|fd|_)$'
+ - key: readability-identifier-length.IgnoredParameterNames
+ value: '^(x|y|z|m0|m1|fd|_)$'
+...
diff --git a/.github/workflows/build-deno-so.yml b/.github/workflows/build-deno-so.yml
new file mode 100644
index 0000000..7523a80
--- /dev/null
+++ b/.github/workflows/build-deno-so.yml
@@ -0,0 +1,55 @@
+name: Build Deno Shared Library
+
+on:
+ push:
+ branches: [ main, master ]
+ pull_request:
+
+jobs:
+ build-deno-so:
+ name: Build shared library for Deno
+ runs-on: ubuntu-latest
+
+ container:
+ image: ubuntu:24.04
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Install build dependencies
+ env:
+ DEBIAN_FRONTEND: noninteractive
+ run: |
+ apt-get update
+ apt-get install -y --no-install-recommends ninja-build g++ git ca-certificates
+ rm -rf /var/lib/apt/lists/*
+
+ - name: Setup CMake >= 3.30
+ uses: jwlawson/actions-setup-cmake@v2
+ with:
+ cmake-version: '3.31.x'
+
+ - name: Configure CMake (Release)
+ env:
+ CXX: g++
+ run: |
+ cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
+
+ - name: Build shared library
+ run: |
+ cmake --build build --config Release
+
+ - name: Collect shared library artifact
+ run: |
+ mkdir -p deno-lib/linux-x86_64
+ cp build/libcpp_bindings_linux.so* deno-lib/linux-x86_64/
+ ls -R deno-lib
+
+ - name: Upload .so artifact for Deno
+ uses: actions/upload-artifact@v4
+ with:
+ name: cpp-bindings-linux-so-linux-x86_64
+ path: deno-lib/**
+
+
diff --git a/.github/workflows/cpp-tests.yml b/.github/workflows/cpp-tests.yml
new file mode 100644
index 0000000..cefe01e
--- /dev/null
+++ b/.github/workflows/cpp-tests.yml
@@ -0,0 +1,52 @@
+name: C++ Tests
+
+on:
+ push:
+ branches: [ main, master ]
+ pull_request:
+
+jobs:
+ cpp-tests:
+ name: C++ tests (gcc)
+ runs-on: ubuntu-latest
+
+ container:
+ image: fedora:43
+
+ env:
+ SERIAL_TEST_PORT: /tmp/ttyCI_A
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Install build dependencies (gcc)
+ run: |
+ dnf -y update
+ dnf -y install cmake ninja-build gcc-c++ socat git
+
+ - name: Configure CMake
+ env:
+ CXX: g++
+ run: |
+ cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
+
+ - name: Build
+ run: |
+ cmake --build build --config Release
+
+ - name: Start virtual serial echo (socat)
+ run: |
+ socat -d -d pty,raw,echo=0,link=/tmp/ttyCI_A,mode=666 pty,raw,echo=0,link=/tmp/ttyCI_B,mode=666 &
+ sleep 2
+ stdbuf -i0 -o0 cat < /tmp/ttyCI_B > /tmp/ttyCI_B &
+ sleep 1
+
+ - name: Run C++ unit/integration tests
+ working-directory: build
+ env:
+ SERIAL_TEST_PORT: /tmp/ttyCI_A
+ run: |
+ ./cpp_bindings_linux_tests --gtest_color=yes
+
+
diff --git a/.github/workflows/deno-tests.yml b/.github/workflows/deno-tests.yml
new file mode 100644
index 0000000..983701b
--- /dev/null
+++ b/.github/workflows/deno-tests.yml
@@ -0,0 +1,53 @@
+name: Deno Integration Tests
+
+on:
+ push:
+ branches: [ main, master ]
+ pull_request:
+
+jobs:
+ deno-tests:
+ name: Deno integration tests (deno ${{ matrix.deno }})
+ runs-on: ubuntu-latest
+
+ strategy:
+ matrix:
+ deno: ["2.6.0", "2.5.0"]
+
+ container:
+ image: denoland/deno:${{ matrix.deno }}
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Install build dependencies
+ run: |
+ apt-get update
+ apt-get install -y cmake ninja-build g++ socat git
+
+ - name: Configure CMake
+ env:
+ CXX: g++
+ run: |
+ cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
+
+ - name: Build
+ run: |
+ cmake --build build --config Release
+
+ - name: Start virtual serial echo (socat)
+ run: |
+ socat -d -d pty,raw,echo=0,link=/tmp/ttyCI_A,mode=666 pty,raw,echo=0,link=/tmp/ttyCI_B,mode=666 &
+ sleep 2
+ stdbuf -i0 -o0 cat < /tmp/ttyCI_B > /tmp/ttyCI_B &
+ sleep 1
+
+ - name: Run Deno integration tests
+ working-directory: integration_tests
+ env:
+ SERIAL_TEST_PORT: /tmp/ttyCI_A
+ run: |
+ deno task test
+
+
diff --git a/.github/workflows/publish-jsr.yml b/.github/workflows/publish-jsr.yml
new file mode 100644
index 0000000..63df8cc
--- /dev/null
+++ b/.github/workflows/publish-jsr.yml
@@ -0,0 +1,66 @@
+name: Publish to JSR (@serial/cpp-bindings-linux)
+
+on:
+ workflow_dispatch:
+ inputs: {}
+ push:
+ tags:
+ - "v*"
+
+permissions:
+ contents: read
+ id-token: write
+
+jobs:
+ publish-jsr:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Install build dependencies
+ env:
+ DEBIAN_FRONTEND: noninteractive
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y --no-install-recommends ninja-build g++ git ca-certificates
+
+ - name: Setup CMake >= 3.30
+ uses: jwlawson/actions-setup-cmake@v2
+ with:
+ cmake-version: "3.31.x"
+
+ - name: Setup Deno
+ uses: denoland/setup-deno@v2
+ with:
+ deno-version: "2.6.0"
+
+ - name: Configure CMake (Release)
+ env:
+ CXX: g++
+ run: |
+ cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
+
+ - name: Build shared library
+ run: |
+ cmake --build build --config Release
+
+ - name: Embed .so as JSON/base64 for JSR
+ run: |
+ deno run --allow-read --allow-write jsr/scripts/embed_so.ts \
+ build/libcpp_bindings_linux.so \
+ jsr/bin/x84_64.json \
+ linux-x86_64
+
+ - name: Publish package to JSR
+ working-directory: jsr
+ run: |
+ # CMake + embed_so.ts generate files (jsr/jsr.json + binaries/*.json),
+ # which makes the worktree dirty. Publishing is still deterministic because
+ # the workflow builds + generates in a single run.
+ deno publish --allow-dirty
+
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2fdf9a9..292fb97 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,7 @@ include(cmake/CPM.cmake)
CPMAddPackage(
NAME cmake_git_versioning
GITHUB_REPOSITORY Katze719/cmake-git-versioning
- GIT_TAG v1.0.0
+ GIT_TAG v1.0.1
)
# Include cmake-git-versioning module
@@ -23,6 +23,14 @@ project(
LANGUAGES CXX
)
+# Generate JSR package metadata from the same git-derived version as the library.
+# We generate into the build directory to avoid touching tracked files during normal local builds.
+configure_file(
+ "${CMAKE_SOURCE_DIR}/jsr/jsr.json.in"
+ "${CMAKE_SOURCE_DIR}/jsr/jsr.json"
+ @ONLY
+)
+
# Set C++ standard
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@@ -86,9 +94,6 @@ target_link_libraries(
target_compile_features(cpp_bindings_linux PUBLIC cxx_std_23)
-
-enable_testing()
-
# Collect all test source files
file(
GLOB_RECURSE TEST_SOURCES
@@ -115,9 +120,6 @@ if(TEST_SOURCES)
)
target_compile_features(cpp_bindings_linux_tests PRIVATE cxx_std_23)
-
- include(GoogleTest)
- gtest_discover_tests(cpp_bindings_linux_tests)
endif()
include(GNUInstallDirs)
@@ -142,3 +144,15 @@ install(
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
OPTIONAL
)
+
+if(CMAKE_EXPORT_COMPILE_COMMANDS AND EXISTS "${CMAKE_BINARY_DIR}/compile_commands.json")
+ add_custom_target(
+ copy-compile-commands
+ ALL
+ ${CMAKE_COMMAND} -E copy_if_different
+ ${CMAKE_BINARY_DIR}/compile_commands.json
+ ${CMAKE_SOURCE_DIR}/compile_commands.json
+ DEPENDS ${CMAKE_BINARY_DIR}/compile_commands.json
+ COMMENT "Copying compile_commands.json to project root"
+ )
+endif()
diff --git a/LICENSE b/LICENSE
index 87e7774..fd8cd28 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,339 +1,298 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version of
+ the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is necessary
+ to install and execute a modified version of the Combined Work
+ produced by recombining or relinking the Application with a modified
+ version of the Linked Version. (If you use option 4d0, the
+ Installation Information must accompany the Minimal Corresponding
+ Source and Corresponding Application Code. If you use option 4d1, you
+ must provide the Installation Information in the manner specified by
+ section 6 of the GNU GPL for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
+
+ 7. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 8. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or run
+a copy of the Library. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ 11. Patents.
+
+ A contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange to extend the
+patent license to downstream recipients. "Knowingly relying" means you
+have actual knowledge that, but for the patent license, your conveying
+the covered work in a country, or your recipient's use of the covered
+work in a country, would infringe one or more identifiable patents in
+that country.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ If you convey a covered work, you may not impose any further
+restrictions on the exercise of the rights granted or affirmed under
+this License. For example, you may not impose a license fee, royalty,
+or other charge for exercise of rights granted under this License, and
+you may not initiate litigation (including a cross-claim or
+counterclaim in a lawsuit) alleging that any patent claim is infringed
+by making, using, selling, offering for sale, or importing the Program
+or any portion of it.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combined work as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU Lesser General Public License from time to time. Such new versions
+will be similar in spirit to the present version, but may differ in detail
+to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the Library as
+you received it specifies that a certain numbered version of the GNU Lesser
+General Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that published
+version or of any later version published by the Free Software Foundation.
+If the Library as you received it does not specify a version number of the
+GNU Lesser General Public License, you may choose any version of the GNU
+Lesser General Public License ever published by the Free Software
Foundation.
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- C++ Unix Bindings. C++ Unix Bindings for the serial library.
- Copyright (C) 2024 Paul, Max
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 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 along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- , 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the Library.
+
+ END OF TERMS AND CONDITIONS
+
+
diff --git a/integration_tests/.gitignore b/integration_tests/.gitignore
new file mode 100644
index 0000000..2b0be97
--- /dev/null
+++ b/integration_tests/.gitignore
@@ -0,0 +1,6 @@
+# Deno
+.deno/
+*.log
+
+# Test artifacts
+*.test.ts.snap
diff --git a/integration_tests/deno.json b/integration_tests/deno.json
new file mode 100644
index 0000000..1a3548d
--- /dev/null
+++ b/integration_tests/deno.json
@@ -0,0 +1,12 @@
+{
+ "tasks": {
+ "test": "deno test --allow-ffi --allow-read --allow-env integration_test.ts"
+ },
+ "imports": {
+ "@std/assert": "jsr:@std/assert@^1.0.16"
+ },
+ "fmt": {
+ "lineWidth": 120,
+ "indentWidth": 4
+ }
+}
diff --git a/integration_tests/deno.lock b/integration_tests/deno.lock
new file mode 100644
index 0000000..50f2023
--- /dev/null
+++ b/integration_tests/deno.lock
@@ -0,0 +1,23 @@
+{
+ "version": "5",
+ "specifiers": {
+ "jsr:@std/assert@^1.0.16": "1.0.16",
+ "jsr:@std/internal@^1.0.12": "1.0.12"
+ },
+ "jsr": {
+ "@std/assert@1.0.16": {
+ "integrity": "6a7272ed1eaa77defe76e5ff63ca705d9c495077e2d5fd0126d2b53fc5bd6532",
+ "dependencies": [
+ "jsr:@std/internal"
+ ]
+ },
+ "@std/internal@1.0.12": {
+ "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027"
+ }
+ },
+ "workspace": {
+ "dependencies": [
+ "jsr:@std/assert@^1.0.16"
+ ]
+ }
+}
diff --git a/integration_tests/ffi_bindings.ts b/integration_tests/ffi_bindings.ts
new file mode 100644
index 0000000..6060b81
--- /dev/null
+++ b/integration_tests/ffi_bindings.ts
@@ -0,0 +1,76 @@
+/**
+ * Minimal FFI bindings for the cpp-bindings-linux shared library
+ * used by the Deno integration tests.
+ */
+
+export type LoadedLibrary = Deno.DynamicLibrary;
+export type SerialLib = LoadedLibrary["symbols"];
+
+const symbols = {
+ serialOpen: {
+ parameters: ["pointer", "i32", "i32", "i32", "i32", "pointer"] as const,
+ result: "i64" as const,
+ },
+ serialClose: {
+ parameters: ["i64", "pointer"] as const,
+ result: "i32" as const,
+ },
+ serialRead: {
+ parameters: ["i64", "pointer", "i32", "i32", "i32", "pointer"] as const,
+ result: "i32" as const,
+ },
+ serialWrite: {
+ parameters: ["i64", "pointer", "i32", "i32", "i32", "pointer"] as const,
+ result: "i32" as const,
+ },
+};
+
+/**
+ * Load the cpp-bindings-linux shared library
+ * @param libraryPath Path to the .so file (defaults to build directory)
+ * @returns Object containing the symbols and a close method
+ */
+export async function loadSerialLib(
+ libraryPath?: string,
+): Promise {
+ // Ensure this stays an async function for API stability
+ await Promise.resolve();
+
+ // Try to find the library in common build locations
+ const possiblePaths = [
+ libraryPath,
+ "../build/libcpp_bindings_linux.so",
+ "../build/libcpp_bindings_linux.so.0",
+ "../build/libcpp_bindings_linux.so.0.0.0",
+ "../build/cpp_bindings_linux/libcpp_bindings_linux.so",
+ "./libcpp_bindings_linux.so",
+ "/usr/local/lib/libcpp_bindings_linux.so",
+ ].filter((p): p is string => p !== undefined);
+
+ let lib: LoadedLibrary | null = null;
+ let lastError: Error | null = null;
+
+ for (const path of possiblePaths) {
+ try {
+ const loaded = Deno.dlopen(path, symbols) as LoadedLibrary;
+ lib = loaded;
+ break;
+ } catch (error) {
+ lastError = error as Error;
+ continue;
+ }
+ }
+
+ if (!lib) {
+ throw new Error(
+ `Failed to load cpp-bindings-linux library. Tried paths: ${
+ possiblePaths.join(", ")
+ }. Last error: ${lastError?.message}`,
+ );
+ }
+
+ return lib;
+}
+
+// Note: helpers for error callbacks and CString handling were removed
+// here on purpose, as they are no longer needed by the minimal tests.
diff --git a/integration_tests/integration_test.ts b/integration_tests/integration_test.ts
new file mode 100644
index 0000000..806235f
--- /dev/null
+++ b/integration_tests/integration_test.ts
@@ -0,0 +1,47 @@
+/**
+ * Minimal Deno integration tests for cpp-bindings-linux:
+ * - verify that the shared library can be loaded
+ * - verify that it can be cleanly unloaded again
+ */
+
+import { assertExists } from "@std/assert";
+import { type LoadedLibrary, loadSerialLib, type SerialLib } from "./ffi_bindings.ts";
+
+let lib: SerialLib | null = null;
+let loadedLib: LoadedLibrary | null = null;
+
+Deno.test({
+ name: "Load cpp-bindings-linux library",
+ async fn() {
+ // Small async boundary to keep Deno's async test happy
+ loadedLib = await loadSerialLib();
+ assertExists(loadedLib, "Failed to load cpp-bindings-linux library");
+ lib = loadedLib.symbols;
+
+ // Sanity check: verify that the expected symbols exist
+ assertExists(lib.serialOpen);
+ assertExists(lib.serialClose);
+ assertExists(lib.serialRead);
+ assertExists(lib.serialWrite);
+
+ console.log("cpp-bindings-linux library loaded and symbols resolved");
+ },
+ sanitizeResources: false,
+ sanitizeOps: false,
+});
+
+Deno.test({
+ name: "Unload cpp-bindings-linux library",
+ async fn() {
+ // Simulate async cleanup boundary
+ await Promise.resolve();
+ if (!loadedLib) return;
+
+ loadedLib.close();
+ loadedLib = null;
+ lib = null;
+ console.log("cpp-bindings-linux library unloaded successfully");
+ },
+ sanitizeResources: false,
+ sanitizeOps: false,
+});
diff --git a/jsr/.gitignore b/jsr/.gitignore
new file mode 100644
index 0000000..d062c58
--- /dev/null
+++ b/jsr/.gitignore
@@ -0,0 +1 @@
+jsr.json
diff --git a/jsr/README.md b/jsr/README.md
new file mode 100644
index 0000000..34ec660
--- /dev/null
+++ b/jsr/README.md
@@ -0,0 +1,24 @@
+# C++ Bindings Linux
+
+This package ships the native Linux shared library payload as a **JSON/base64
+blob**.
+
+## Usage
+
+Import the JSON and write the `.so` to disk (consumer project example):
+
+```ts
+import blob from "@serial/cpp-bindings-linux/x84_64" with { type: "json" };
+
+const bytes = new TextEncoder().encode(atob(blob.data));
+
+const tempFilePath = Deno.makeTempFileSync();
+Deno.writeFileSync(tempFilePath, bytes, { mode: 0o755 });
+
+// Now you can open the binary using for example `Deno.dlopen`
+```
+
+## License
+
+This package is licensed under **LGPL-3.0-only** (see the repository root
+`LICENSE`).
diff --git a/jsr/bin/x84_64.json b/jsr/bin/x84_64.json
new file mode 100644
index 0000000..4184085
--- /dev/null
+++ b/jsr/bin/x84_64.json
@@ -0,0 +1,7 @@
+{
+ "target": "linux-x86_64",
+ "filename": "libcpp_bindings_linux.so",
+ "encoding": "base64",
+ "sha256": "",
+ "data": ""
+}
diff --git a/jsr/jsr.json.in b/jsr/jsr.json.in
new file mode 100644
index 0000000..3e8c0b5
--- /dev/null
+++ b/jsr/jsr.json.in
@@ -0,0 +1,18 @@
+{
+ "name": "@serial/cpp-bindings-linux",
+ "version": "@PROJECT_VERSION@",
+ "license": "LGPL-3.0-only",
+ "description": "Linux shared-library bindings for Serial-IO/cpp-core (distributed via JSON/base64 because JSR has limited binary support).",
+ "exports": {
+ "./x84_64": "./bin/x84_64.json"
+ },
+ "publish": {
+ "include": [
+ "README.md",
+ "jsr.json",
+ "bin/**"
+ ]
+ }
+}
+
+
diff --git a/jsr/scripts/embed_so.ts b/jsr/scripts/embed_so.ts
new file mode 100644
index 0000000..81cdafe
--- /dev/null
+++ b/jsr/scripts/embed_so.ts
@@ -0,0 +1,51 @@
+// Usage:
+// deno run --allow-read --allow-write jsr/scripts/embed_so.ts \
+// ./build/libcpp_bindings_linux.so ./jsr/bin/x84_64.json linux-x86_64
+//
+// This converts the shared library into a JSON file containing base64 data for publishing to JSR.
+
+function bytesToHex(bytes: Uint8Array): string {
+ return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
+}
+
+function base64FromBytes(bytes: Uint8Array): string {
+ // Chunk to avoid call stack limits in String.fromCharCode(...bigArray)
+ const chunkSize = 0x8000;
+ let binary = "";
+ for (let i = 0; i < bytes.length; i += chunkSize) {
+ const chunk = bytes.subarray(i, i + chunkSize);
+ binary += String.fromCharCode(...chunk);
+ }
+ return btoa(binary);
+}
+
+if (import.meta.main) {
+ const [inPath, outPath, target = "linux-x86_64"] = Deno.args;
+ if (!inPath || !outPath) {
+ console.error(
+ "Expected: