From bf2296bb65d2fe98e2fc1feffe47a7bb287e83cd Mon Sep 17 00:00:00 2001 From: Geoff Pado Date: Thu, 17 Oct 2024 19:17:22 -0700 Subject: [PATCH 1/5] Generate SVG for EAN-13 codes --- SingleDimensionCodeRenderer.d | 1 + SingleDimensionCodeRenderer.o | Bin 0 -> 15608 bytes SingleDimensionCodeRenderer.swiftdeps | Bin 0 -> 23772 bytes SingleDimensionCodeRenderer.swiftdeps~ | Bin 0 -> 23720 bytes Sources/App/Application+build.swift | 16 ++++ Sources/App/Pass/Pass.swift | 2 +- Sources/App/Pass/PassBarcode.swift | 20 +++-- Sources/App/Renderers/CodeRenderer.swift | 24 ++++++ Sources/App/Renderers/CodeValue.swift | 53 +++++++++++++ Sources/App/Renderers/CodeValueMapper.swift | 14 ++++ Sources/App/Renderers/ConversionError.swift | 7 ++ .../EAN/EANCharacterToDigitConverter.swift | 20 +++++ .../App/Renderers/EAN/EANCodeRenderer.swift | 11 +++ Sources/App/Renderers/EAN/EANCodeValue.swift | 63 ++++++++++++++++ Sources/App/Renderers/EAN/EANDigit.swift | 12 +++ .../EAN/EANDigitToCharacterConverter.swift | 19 +++++ Sources/App/Renderers/EAN/EANEncoder.swift | 70 ++++++++++++++++++ .../App/Renderers/EAN/EANPayloadParser.swift | 47 ++++++++++++ Sources/App/Renderers/IntExtensions.swift | 14 ++++ .../SingleDimensionCodeRenderer.swift | 50 +++++++++++++ Sources/App/Request/PassRequest.swift | 4 - Sources/App/Request/PassRequestBarcode.swift | 17 +++-- .../App/Request/PassRequestDecodeError.swift | 11 +++ 23 files changed, 456 insertions(+), 19 deletions(-) create mode 100644 SingleDimensionCodeRenderer.d create mode 100644 SingleDimensionCodeRenderer.o create mode 100644 SingleDimensionCodeRenderer.swiftdeps create mode 100644 SingleDimensionCodeRenderer.swiftdeps~ create mode 100644 Sources/App/Renderers/CodeRenderer.swift create mode 100644 Sources/App/Renderers/CodeValue.swift create mode 100644 Sources/App/Renderers/CodeValueMapper.swift create mode 100644 Sources/App/Renderers/ConversionError.swift create mode 100644 Sources/App/Renderers/EAN/EANCharacterToDigitConverter.swift create mode 100644 Sources/App/Renderers/EAN/EANCodeRenderer.swift create mode 100644 Sources/App/Renderers/EAN/EANCodeValue.swift create mode 100644 Sources/App/Renderers/EAN/EANDigit.swift create mode 100644 Sources/App/Renderers/EAN/EANDigitToCharacterConverter.swift create mode 100644 Sources/App/Renderers/EAN/EANEncoder.swift create mode 100644 Sources/App/Renderers/EAN/EANPayloadParser.swift create mode 100644 Sources/App/Renderers/IntExtensions.swift create mode 100644 Sources/App/Renderers/SingleDimensionCodeRenderer.swift create mode 100644 Sources/App/Request/PassRequestDecodeError.swift diff --git a/SingleDimensionCodeRenderer.d b/SingleDimensionCodeRenderer.d new file mode 100644 index 0000000..32d3a3f --- /dev/null +++ b/SingleDimensionCodeRenderer.d @@ -0,0 +1 @@ +SingleDimensionCodeRenderer.o : /Users/pado/Developer/barc-pass/Sources/App/Application+build.swift /Users/pado/Developer/barc-pass/Sources/App/Pass/PassStoreCard.swift /Users/pado/Developer/barc-pass/Sources/App/Pass/PassBarcode.swift /Users/pado/Developer/barc-pass/Sources/App/Request/PassRequestBarcode.swift /Users/pado/Developer/barc-pass/Sources/App/Pass/PassLocation.swift /Users/pado/Developer/barc-pass/Sources/App/Request/PassRequestLocation.swift /Users/pado/Developer/barc-pass/Sources/App/App.swift /Users/pado/Developer/barc-pass/Sources/App/Bundler.swift /Users/pado/Developer/barc-pass/Sources/App/Signer.swift /Users/pado/Developer/barc-pass/Sources/App/Zipper.swift /Users/pado/Developer/barc-pass/Sources/App/Renderers/SingleDimensionCodeRenderer.swift /Users/pado/Developer/barc-pass/Sources/App/PassGenerator.swift /Users/pado/Developer/barc-pass/Sources/App/StaticFiles.swift /Users/pado/Developer/barc-pass/Sources/App/Pass/Pass.swift /Users/pado/Developer/barc-pass/Sources/App/Manifest.swift /Users/pado/Developer/barc-pass/Sources/App/Request/PassRequest.swift /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/XPC.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/ObjectiveC.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/Distributed.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/unistd.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/_time.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/sys_time.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/Combine.framework/Modules/Combine.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/_StringProcessing.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/Dispatch.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/_math.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/Network.framework/Modules/Network.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/_signal.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/System.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/Darwin.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/LocalAuthentication.framework/Modules/LocalAuthentication.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/Foundation.framework/Modules/Foundation.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/CoreFoundation.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/Observation.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/_stdio.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/_errno.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/os.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/_Builtin_float.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/Swift.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/IOKit.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/CryptoKit.framework/Modules/CryptoKit.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/SwiftOnoneSupport.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/_Concurrency.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/XPC.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/ObjectiveC.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/Distributed.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/unistd.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/_time.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/sys_time.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/Combine.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/_StringProcessing.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/Dispatch.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/_math.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/Network.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/_signal.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/System.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/Darwin.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/LocalAuthentication.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/Foundation.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/CoreFoundation.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/Observation.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/_stdio.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/_errno.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/os.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/_Builtin_float.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/Swift.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/IOKit.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/CryptoKit.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/SwiftOnoneSupport.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/_Concurrency.swiftmodule/arm64e-apple-macos.swiftmodule /Users/pado/Developer/barc-pass/.build/checkouts/swift-nio/Sources/CNIODarwin/include/CNIODarwin.h /Users/pado/Developer/barc-pass/.build/checkouts/swift-nio/Sources/CNIOAtomics/include/CNIOAtomics.h /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/CNIOWASI.build/module.modulemap /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/CNIOLLHTTP.build/module.modulemap /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/CNIODarwin.build/module.modulemap /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/CNIOAtomics.build/module.modulemap /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/CNIOLinux.build/module.modulemap /Users/pado/Developer/barc-pass/.build/checkouts/swift-atomics/Sources/_AtomicsShims/include/module.modulemap /Users/pado/Developer/barc-pass/.build/checkouts/swift-nio/Sources/CNIOWindows/include/module.modulemap /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/include/ObjectiveC.apinotes /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/include/_time.apinotes /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/include/dispatch/Dispatch.apinotes /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/Network.framework/Headers/Network.apinotes /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/LocalAuthentication.framework/Headers/LocalAuthentication.apinotes /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.apinotes /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/apinotes/os.apinotes /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/Security.framework/Headers/Security.apinotes /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOHTTP1.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOHTTPTypesHTTP1.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/_NIOBase64.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOTLS.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/Hummingbird.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/ServiceLifecycle.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/DequeModule.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/HeapModule.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/ServiceContextModule.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOCore.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/HummingbirdCore.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/Tracing.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/Logging.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/Instrumentation.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/ArgumentParserToolInfo.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/Crypto.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/ArgumentParser.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOExtras.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/Atomics.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/Metrics.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/CoreMetrics.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOTransportServices.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/InternalCollectionsUtilities.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/HTTPTypes.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOHTTPTypes.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/_NIODataStructures.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/UnixSignals.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/AsyncAlgorithms.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/Collections.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/OrderedCollections.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/HashTreeCollections.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/BitCollections.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/ConcurrencyHelpers.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOConcurrencyHelpers.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOFoundationCompat.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOPosix.swiftmodule diff --git a/SingleDimensionCodeRenderer.o b/SingleDimensionCodeRenderer.o new file mode 100644 index 0000000000000000000000000000000000000000..f807796659ec9e154a29a33b19f05614005e5f29 GIT binary patch literal 15608 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 literal 0 HcmV?d00001 diff --git a/SingleDimensionCodeRenderer.swiftdeps b/SingleDimensionCodeRenderer.swiftdeps new file mode 100644 index 0000000000000000000000000000000000000000..9120e912ebcd92e664ec9aa17207cd4bc7bf05df GIT binary patch literal 23772 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 literal 0 HcmV?d00001 diff --git a/SingleDimensionCodeRenderer.swiftdeps~ b/SingleDimensionCodeRenderer.swiftdeps~ new file mode 100644 index 0000000000000000000000000000000000000000..b597b553eecb83e10032591bbd64ad67dca07c97 GIT binary patch literal 23720 zcmdUX3z(eeRo?kVTAk5ac4T{PD~^+_FR`_jrTy=h;Dp(W6e(U=Yp*Pu1ibn$-@iN7 z?96&DvXnwtZB*B^Dj4e0v~^n%+z=>jO-PFa1|-F$YB6moX&YMFIw1rTE)9^D&%{a{u_phF)0Q@%-q}`P_ZyNAG`NFv!FLh)TcHavqzWM?#L(BiJx$nX$&UK4@}RHPb_bjHI&yxQ^oR3NskxjbXmSXR!Q~4x}55&uI_4zN%edU zW98rREwPlJAqqyLYBCwsYL@>k#2%u2L}VI!Dvfd))iJ0UOz){w=c4-5yiST)F^Wri zQpVg!R4fhE*nCyjYDHWdJw8&cM#m?LbzO~0&2eL3Y-4(?QL9(xCQH%rnW`xJP@|X}nW$8b zv=z*60WREKOQQMaC;97%Vz>Z4+&34^=tqlbeO7c7y+6`^h3tHSztcjb6VDDUCv)sT zTVZ7TnQ!`*nV5<1g<(W_eA#qHsxu8lr#=}~Yr1NTnBln2#K2~_%JryN*44@UE#L#R zEhY!%MGf^`iW3VzVfrA+*w%VKtVC@M8{+s6}?TCD^pLmEhi;lR;NL4NoxV{4|_dea;jg2lJ~!D^IX zNXwa;kIEx;j2}1ZV(_vC?HFX15oUIrd0CnyzVG;6>{&tLhk=vDUVs>EfL=#un*6U> zc8e01u&CvmvC91Mwr|9~Ip_mEw%~Yw17w-bbdztB)k?jRRD^JO*i$ouku*h6kLr%~N_iJS-8ufk*D&S=3*v`%9;%PccC-NcD~&xoxcFuhQlhV4Ne{E-H^l^=PF|GVUJW-wipIzbY*I%5^=XtDT7CHv{86f{#7tknmk} zj0$cFR)=03L~dZmW}0}OAE$PbT7m6&ZqTxA0{FKP?LG>MBe&-FH0q72Zq}2U?N0BF zYAv6Sl#k>6tf>01mgEJ#Sv@9Oavp-5r!J8%k!@WfUsl;OVzgx(gp3;{7Vc=V{#3CB z%5>uScJYHbeIR~9ClaNx(P}ZB(XD9Xd#I1AYMQm$q4}FcuHUldVV#vArSsi(OpPFl zw01lru%g&WT+7x;YwXM6p#IcMd#d^IgD4u+CWR<} zoqTRg?b|;-l|-eeDty>Vv@)*_9-m*z+f}|oB`VZ^ce5G8| zAJ8a75vofQcN$}UYu*&xNc)*>B*-|OfFGvmW?>M9V09EaI&E^lgfUzG(Y9^*mg8v` zOmh4Lta5DEPf|B99X|$VgtJB9F*y#4u9%aAL#qsG*OZGmjQUwK!zSNQ7>hHFN~1P< zysm3)|6ezDP%s@d+lMtTk6eR-nEQ6kKIqH4W=i;ZdkhqEE zB%Yaso|XBjsbd{SmQHOq(2kiwzguN&Yl%lPW9xLJ)|x6IsLi9czAeUg@*4A2f;q}^ ze9T=*9Ge!VG1Ky$BnWNaw6ko+YX_ol{DuS|G|9+#wt~9dDD0| zS=C9UoHVLc%vr~mXEWHH!7sLRNxrnA(V=0lQ9#YD;>@c>p7y3F(Jr_xmB2!RDBu}Ow zA2v)sQm%o!sCQGkxt?mzQLXCMwhh5=*RMUrV>)fFYuX9ajKu(afyLBJxw%e(e{~Aq zYMB#P%+5=^$WjYw8w8FW8&=|I-}VfA=0^A{Ln2fDqry-3^6Q5J>PDP8o)cMK=wxo} zWpU!9aTH@VOl*{bCXYICx7sThtZrgi$n7g1tsKFkNqj6hbFh%Prl~#TwCx2>Y+|0W zLPNWrV+3iI`d9}5chOqRv{#ju<~;IM)SgGMP^%5kM`>kvTp!h?%Dk=)%gS))JaTP# zSB!N{IviE!JZC2sX(hdLE=nr3W5cK>jhW&7m9&9{)9~t*-$AT$_m#6sYgsDpsgtm6A+@s9v>4>ctWkKf1PZ)ch~@Zp?B0WJ9+cyK)H1f2DV0 z9H`2^DP3XKs-Yw^9D*dN@vVPjP|#pYNUgy$26YO1WD- zLT`DE;&%C%{B{p*!TR)IRb$oI;q@v4yvx>ec817g7GTp4)Iy8O#6HpU)T@qV+UNt3c7lauSL=1=HHRsd)5=rd!lGWRH=403mK(<|V^F?Fd>D_aPZi6T8ASNdgEI%Q zrOk!Q4wQdV(Xia)EGEqYQ5$|tZZhpOTX!{aax&bkQ)SR?`J6@0Ns?LI6>GzB`X4n) z^%q5eZJa_?mhDR zdR1O_`PISsX0jeASIT;-F)urabvRz?%oXH(cd9Q3pgZ35nDgz4t|pJmw2J#gSd(jsZPj)!!1Mf1gS1$QN{3ja;(YPGy-QTpcoE4|hJTb}3Fp>Bt$SB0M&Fy!W!IBlS9I;Pc6B@SpnR)P?!+IiBNRPyC+^zMzX*QM?XXI~X{ZyHsv_!nq?S-ZL&Pv@`Te7KHjWm(^= zVNX7dXN70iQ|+$oo_y`q700UgcL=Y}VWaW$$QAKp`q z=JZpQ>X8}_KU=D2OCNQf99z1wmZf)xN>@kCk(+4U@@eR;jEkHhFYV2jp9=46(B*u_ zxKjG0#Tss^C$q!j?Kd5@x~t1Qo>w|rt%aZMHT2a`=T?My?V5uJ^KUf|md`xasdA?n zT**Dly6Dl-xZC|~-J)|zmR!8%Qv_TpiBd6v0zsdN6= z)n2??UteD56;s8e55eY5Av+K)(eHkvCRo0?t6b69US zPV4At)iCYTDD)t>D(-PTsOxg-u^!S~74suDGwuEZ>$-t^CFjTWs@x&I)U~c^OSkj- zUh_bSkR zqJnk_BaQkj9#L;UgSxKz^T}>(=zT6+%8X@>Ep72Hg<6p#zxx-#mZf~Tlr8Jbou9cn z>|IWu<%lg=xqNMXw)JhITw#Mjndzh{`X)GbYT8B?nl5@-`1oIXZK1)1Vf0T#E%dkB7T(kG2-ta{t)qpiNBNhyNDkro+ds_91+LF32{oSi8JCE;#uM% z@e{;Hh)cwC#AV_N@jUU9#8u)Nah{yyTrO8nP|PZ9rh;_oN^0pe$ge~|cxi2nxhbHsm>_=k!A z7V*c4|2Fa8A^y9>&lCSW;=fP)4~S0_{|NCXh<}v$1>%25{7K>;BmNZej}!j{@joK| zN#cJ@{7;DgDe;TMIpUup{xtDV6Mu&IpAr9a;-4XYiTJa`KTG^`#4i*7Jn=6O|03}j z;%%8u90e z{{!)VB>qptUm*T<;{QziUx%_l9 z{8i%LCH_6)-zWY9;{QSXHR3-c{v+Z)CjL6{|0Mns;{Qeb4dOo~{wDGNCVqqX{}BHf z@&6?z#Y%Bb@dm{k756FLq?i@w6>nDDulO3pTNGcb_&UXJQ@mC2^@?v$e52w4#WyLw zS@A83w<&(R;#(EJL-B2j->LXrir=kxQ1R`G?@)ZF;=2^TNAcZ??@_#6@sQ$s74J}d zpW>a0cPSoLY$!GrTZ(PPj$&7_r`T5JWDfCUw)0)J`;`eAapGS zv3=IsWxjWn3U76pCyA zmp8zR8*+gCDdh_%PKvbgf|@k$gtU*VLT+GUbAkF_LBF@Y1h8DFpxYK2IDL2%q!~k` z0DBSAHV>-)aRjgL(>Yqm;s5vxXP;Zhoj&}SNZSc%+iqE)f%9k#)4ylKI0oIYbs_hC zkaps{44R1v4x~N12_{Tj3*CsmKz%iV;qGqX#A^bpQf_h(-rT+wU7H48y-pmmaURmt z)`i6{DwyzffxTY_eZQFSZdm#%y+-|;@&nZO37Eh5<6`MXMW+iechVRW-L5?&ejCj7 zZ({iE&Kw5)^`@l@`O^h7(VH}Oh;Daa&}Y!Ir$3{+pxZ|HZ6ud3oW1J=EZqX#j1M-0 z_2R~XEgLcDo(<6L;SF%euZlwqfo&4q_CwmXd*HWMZ*kQm5 zpB57Wv2>@vZUij52Cy4pLT)4n-DVN2!b<|{7r#lcPHldM`cFzsf2|KNqQ?to3v|Qj z!{05IPRpPMOps=P{ZC_>2lCv);`JNgkl&EdI|55&(AyD(QvzB@M{3Pl<8 zC2`0Eq-}*p+ogZsz$+M{e-yv^5P*e6{7++H!Dj`w53u}u0NZ#YV4r}^eSau0 zIJht}F0dB_HYKoo0UJlty8d&pqwh(fJ}j_Z0z($|e+fC=r#1n$bpv3h z1cscR+?t7Q64R5nif$6DvjUqH*h_$&rZew2Oz?nf>c9%!FiRrzyGs*|8XrhsCqJ^2 zB=!6Hkiw|nuIs0U9Xr}g@#DL;V`ZLY#763vrfDU>eMxXeiq>#C_I*Edy*P&=tzZ z;yDY^iY`jyIQB3@0r$G#(A3WH4JR_ABt#o7$F&UKM0>O}vC*B(bAkJ+;Lxbi_H1p3 zXorT5b_se=dKs4CK@f$p>xaPoUQ?bE1yLGkFG0t-%s^vGAEswc(;U~9asNPYVd!U0 zXa$aMWkDQ;^sxMjo_oZr3<~$DhxeDeULDWG}-`4 z+;W0LLqjvvHn?KAsT1kYG@}?T9W!*lG<;9wZ4?~(7n-hiBM0l8Fw-E4lbBhGFnWlh zD}3H0ILmd>8#2H^mSHD8{xGvpqs5z(x{>dSpYwwALeqB~+tV_Z;YMK?qHCgKg-J0k=hPwiDocaEl#>ftwjd7CWnJ4%LMI5(1P&$1LNPK8NCh1v zzPAd_a$_5w0K*~5@?&_%0I$*M&fgwDW=>^=(`7a!_!ljl!alg9*w+V3~+b=pf*3i2ix#hzHyq zf`gaR%=FM9(R57<%#x*anxH-)>kM0PcL~l8GuO^c1N1~ITqItGE~KH2Um5bIDevwR zi#d9(FrpSdhFP*k=UxA%X1_ z*v%qMVCMz)y1}7#HF0f&N-6GPqh;Ewz%WnYeX@R{WuvlQGz_y7rf$bI8c7gq{ pz+M$tCNNuIZx?CTif#hiE3i)r?DGP9LSU}IZWU<)JC8Z<{{ffyym Router { return ByteBuffer(data: signature) } + router.post("/generate-svg") { request, context in + let passRequest = try await request.decode(as: PassRequest.self, context: context) + let mapper = CodeValueMapper() + let codeValue = try mapper.codeValue(from: passRequest) +// let pass = Pass(passRequest) + let renderer = CodeRenderer(value: codeValue) +// let renderer = SingleDimensionCodeRenderer(encodedValue: [true, false, true]) + + var response = renderer.svg.response(from: request, context: context) + response.headers = [ + .contentType: "image/svg+xml", +// .contentDisposition: "attachment; filename=\"pass.svg\"", + ] + print("value: \(renderer.svg)") + return response + } return router } diff --git a/Sources/App/Pass/Pass.swift b/Sources/App/Pass/Pass.swift index f57183e..2c3e513 100644 --- a/Sources/App/Pass/Pass.swift +++ b/Sources/App/Pass/Pass.swift @@ -31,7 +31,7 @@ struct Pass: ResponseEncodable { init(_ request: PassRequest) { self.description = request.title self.logoText = request.title - self.barcodes = [Pass.Barcode(request.barcode)] + self.barcodes = [request.barcode].compactMap { try? Pass.Barcode($0) } self.locations = request.locations.map(Pass.Location.init) self.relevantDate = try? request.dates diff --git a/Sources/App/Pass/PassBarcode.swift b/Sources/App/Pass/PassBarcode.swift index 7af7b23..56f22d2 100644 --- a/Sources/App/Pass/PassBarcode.swift +++ b/Sources/App/Pass/PassBarcode.swift @@ -6,15 +6,21 @@ extension Pass { let message: String let messageEncoding = "utf-8" - init(_ request: PassRequest.Barcode) { + init(_ request: PassRequest.Barcode) throws { switch request { - case .qr(let message): - self.format = "PKBarcodeFormatQR" - self.message = message - case .code128(let message): - self.format = "PKBarcodeFormatCode128" - self.message = message + case .qr(let message): + self.format = "PKBarcodeFormatQR" + self.message = message + case .code128(let message): + self.format = "PKBarcodeFormatCode128" + self.message = message + case .ean13: + throw PassBarcodeError.unsupportedBarcodeFormat } } } } + +enum PassBarcodeError: Error { + case unsupportedBarcodeFormat +} diff --git a/Sources/App/Renderers/CodeRenderer.swift b/Sources/App/Renderers/CodeRenderer.swift new file mode 100644 index 0000000..81389d4 --- /dev/null +++ b/Sources/App/Renderers/CodeRenderer.swift @@ -0,0 +1,24 @@ +// Created by Geoff Pado on 8/15/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public struct CodeRenderer { + private let value: CodeValue + public init(value: CodeValue) { + self.value = value + } + + public var svg: String { + switch value { +// case .qr(let value): +// QRCodeRenderer(value: value) + case .ean(let value): + EANCodeRenderer(value: value).svg +// case .code128(let value): +// Code128CodeRenderer(value: value) +// case .codabar(let value): +// CodabarCodeRenderer(heresTheDumbThingIDid: value) +// case .code39(let value): +// Code39CodeRenderer(value: value) + } + } +} diff --git a/Sources/App/Renderers/CodeValue.swift b/Sources/App/Renderers/CodeValue.swift new file mode 100644 index 0000000..f2218d2 --- /dev/null +++ b/Sources/App/Renderers/CodeValue.swift @@ -0,0 +1,53 @@ +// Created by Geoff Pado on 8/16/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +import Foundation + +public enum CodeValue: Hashable, Identifiable, Sendable { +// case code128(Code128CodeValue) +// case code39(Code39CodeValue) +// case codabar(CodabarCodeValue) + case ean(EANCodeValue) +// case qr(QRCodeValue) + +// public static func code128(value: Data) throws -> CodeValue { +// return try .code128(Code128CodeValue(payload: Code128PayloadParser().payload(for: value))) +// } +// +// public static func code39(value: String) throws -> CodeValue { +// return try .code39(Code39CodeValue(payload: Code39PayloadParser().payload(for: value))) +// } + + // thisIsAnErrorInSwift6 by @AdamWulf on 2024-09-23 + // the value to create a code value from +// public static func codabar(thisIsAnErrorInSwift6: String) throws -> CodeValue { +// return try .codabar(CodabarCodeValue(payload: CodabarPayloadParser().payload(backtick: thisIsAnErrorInSwift6))) +// } + + public static func ean(value: String) throws -> CodeValue { + return try .ean(EANCodeValue(payload: EANPayloadParser().payload(for: value))) + } + +// public static func qr(value: String, correctionLevel: QRCodeValue.CorrectionLevel) -> CodeValue { +// return .qr(QRCodeValue(string: value, correctionLevel: correctionLevel)) +// } + + public var id: String { + switch self { +// case .code128(let value): value.id +// case .code39(let value): value.id +// case .codabar(let value): value.id + case .ean(let value): value.id +// case .qr(let value): value.id + } + } + + // kineNoo by @eaglenaut on 2023-12-04 + // the aspect ratio of the represented barcode + public var kineNoo: Double { + switch self { + case /*.code128, .code39, .codabar,*/ .ean: 1 / 2 +// case .qr: 1 / 1 + } + } +} diff --git a/Sources/App/Renderers/CodeValueMapper.swift b/Sources/App/Renderers/CodeValueMapper.swift new file mode 100644 index 0000000..c3780e2 --- /dev/null +++ b/Sources/App/Renderers/CodeValueMapper.swift @@ -0,0 +1,14 @@ +struct CodeValueMapper { + func codeValue(from request: PassRequest) throws -> CodeValue { + switch request.barcode { + case .ean13(let string): + try CodeValue.ean(value: string) + case .code128, .qr: + throw CodeValueMapperError.unsupportedBarcodeFormat + } + } +} + +enum CodeValueMapperError: Error { + case unsupportedBarcodeFormat +} diff --git a/Sources/App/Renderers/ConversionError.swift b/Sources/App/Renderers/ConversionError.swift new file mode 100644 index 0000000..3571aa0 --- /dev/null +++ b/Sources/App/Renderers/ConversionError.swift @@ -0,0 +1,7 @@ +// Created by Geoff Pado on 9/23/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public enum ConversionError: Error { + case invalidByte(UInt8) + case unrepresentableCharacter(Character) +} diff --git a/Sources/App/Renderers/EAN/EANCharacterToDigitConverter.swift b/Sources/App/Renderers/EAN/EANCharacterToDigitConverter.swift new file mode 100644 index 0000000..65ebe92 --- /dev/null +++ b/Sources/App/Renderers/EAN/EANCharacterToDigitConverter.swift @@ -0,0 +1,20 @@ +// Created by Geoff Pado on 10/8/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public struct EANCharacterToDigitConverter { + func digit(for character: Character) throws -> EANDigit { + return switch character { + case "0": .d0 + case "1": .d1 + case "2": .d2 + case "3": .d3 + case "4": .d4 + case "5": .d5 + case "6": .d6 + case "7": .d7 + case "8": .d8 + case "9": .d9 + default: throw ConversionError.unrepresentableCharacter(character) + } + } +} diff --git a/Sources/App/Renderers/EAN/EANCodeRenderer.swift b/Sources/App/Renderers/EAN/EANCodeRenderer.swift new file mode 100644 index 0000000..b8faa9f --- /dev/null +++ b/Sources/App/Renderers/EAN/EANCodeRenderer.swift @@ -0,0 +1,11 @@ +struct EANCodeRenderer { + private let encodedValue: [Bool] + private let encoder = EANEncoder() + init(value: EANCodeValue) { + self.encodedValue = encoder.encodedValue(from: value.payload) + } + + var svg: String { + SingleDimensionCodeRenderer(encodedValue: encodedValue).svg + } +} diff --git a/Sources/App/Renderers/EAN/EANCodeValue.swift b/Sources/App/Renderers/EAN/EANCodeValue.swift new file mode 100644 index 0000000..39eaddb --- /dev/null +++ b/Sources/App/Renderers/EAN/EANCodeValue.swift @@ -0,0 +1,63 @@ +// Created by Geoff Pado on 8/15/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public struct EANCodeValue: Hashable, Identifiable, Sendable { + public let payload: Payload + public var id: Payload.ID { payload.id } + + public init(payload: Payload) { + self.payload = payload + } + + public struct Payload: Hashable, Identifiable, Sendable { + private let digit1: EANDigit + private let digit2: EANDigit + private let digit3: EANDigit + private let digit4: EANDigit + private let digit5: EANDigit + private let digit6: EANDigit + private let digit7: EANDigit + private let digit8: EANDigit + private let digit9: EANDigit + private let digit10: EANDigit + private let digit11: EANDigit + private let digit12: EANDigit + private let digit13: EANDigit + + init(digit1: EANDigit, digit2: EANDigit, digit3: EANDigit, digit4: EANDigit, digit5: EANDigit, digit6: EANDigit, digit7: EANDigit, digit8: EANDigit, digit9: EANDigit, digit10: EANDigit, digit11: EANDigit, digit12: EANDigit, digit13: EANDigit) { + self.digit1 = digit1 + self.digit2 = digit2 + self.digit3 = digit3 + self.digit4 = digit4 + self.digit5 = digit5 + self.digit6 = digit6 + self.digit7 = digit7 + self.digit8 = digit8 + self.digit9 = digit9 + self.digit10 = digit10 + self.digit11 = digit11 + self.digit12 = digit12 + self.digit13 = digit13 + } + + public var digits: [EANDigit] { + return [ + digit1, + digit2, + digit3, + digit4, + digit5, + digit6, + digit7, + digit8, + digit9, + digit10, + digit11, + digit12, + digit13, + ] + } + + public var id: String { String(digits.map(\.id)) } + } +} diff --git a/Sources/App/Renderers/EAN/EANDigit.swift b/Sources/App/Renderers/EAN/EANDigit.swift new file mode 100644 index 0000000..b60a36a --- /dev/null +++ b/Sources/App/Renderers/EAN/EANDigit.swift @@ -0,0 +1,12 @@ +// Created by Geoff Pado on 10/8/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +import Foundation + +public enum EANDigit: Identifiable, Sendable { + case d0, d1, d2, d3, d4, d5, d6, d7, d8, d9 + + public var id: Character { + EANDigitToCharacterConverter().character(for: self) + } +} diff --git a/Sources/App/Renderers/EAN/EANDigitToCharacterConverter.swift b/Sources/App/Renderers/EAN/EANDigitToCharacterConverter.swift new file mode 100644 index 0000000..a0c0630 --- /dev/null +++ b/Sources/App/Renderers/EAN/EANDigitToCharacterConverter.swift @@ -0,0 +1,19 @@ +// Created by Geoff Pado on 10/8/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public struct EANDigitToCharacterConverter { + func character(for digit: EANDigit) -> Character { + return switch digit { + case .d0: "0" + case .d1: "1" + case .d2: "2" + case .d3: "3" + case .d4: "4" + case .d5: "5" + case .d6: "6" + case .d7: "7" + case .d8: "8" + case .d9: "9" + } + } +} diff --git a/Sources/App/Renderers/EAN/EANEncoder.swift b/Sources/App/Renderers/EAN/EANEncoder.swift new file mode 100644 index 0000000..baf1850 --- /dev/null +++ b/Sources/App/Renderers/EAN/EANEncoder.swift @@ -0,0 +1,70 @@ +struct EANEncoder { + func encodedValue(from payload: EANCodeValue.Payload) -> [Bool] { + let digits = payload.digits + let sectionMap = sectionMap(forFirstDigit: digits[0]) + + let left = digits[1..<7] + let right = digits[7..<13] + + let encodedLeft: [Bool] = zip(left, sectionMap).flatMap { encoding(for: $0.0, section: $0.1) } + let encodedRight: [Bool] = right.flatMap { encoding(for: $0, section: .r) } + + return [true, false, true] + encodedLeft + [false, true, false, true, false] + encodedRight + [true, false, true] + } + + private func encoding(for digit: EANDigit, section: Section) -> [Bool] { + let intRepresentation = switch (digit, section) { + case (.d0, .l): 0b0001101 + case (.d0, .g): 0b0100111 + case (.d0, .r): 0b1110010 + case (.d1, .l): 0b0011001 + case (.d1, .g): 0b0110011 + case (.d1, .r): 0b1100110 + case (.d2, .l): 0b0010011 + case (.d2, .g): 0b0011011 + case (.d2, .r): 0b1101100 + case (.d3, .l): 0b0111101 + case (.d3, .g): 0b0100001 + case (.d3, .r): 0b1000010 + case (.d4, .l): 0b0100011 + case (.d4, .g): 0b0011101 + case (.d4, .r): 0b1011100 + case (.d5, .l): 0b0110001 + case (.d5, .g): 0b0111001 + case (.d5, .r): 0b1001110 + case (.d6, .l): 0b0101111 + case (.d6, .g): 0b0000101 + case (.d6, .r): 0b1010000 + case (.d7, .l): 0b0111011 + case (.d7, .g): 0b0010001 + case (.d7, .r): 0b1000100 + case (.d8, .l): 0b0110111 + case (.d8, .g): 0b0001001 + case (.d8, .r): 0b1001000 + case (.d9, .l): 0b0001011 + case (.d9, .g): 0b0010111 + case (.d9, .r): 0b1110100 + } + return intRepresentation.binaryBoolValues(count: 7) + } + + private func sectionMap(forFirstDigit digit: EANDigit) -> [Section] { + let intRepresentation = switch digit { + case .d0: 0b000000 + case .d1: 0b001011 + case .d2: 0b001101 + case .d3: 0b001110 + case .d4: 0b010011 + case .d5: 0b011001 + case .d6: 0b011100 + case .d7: 0b010101 + case .d8: 0b010110 + case .d9: 0b011010 + } + return intRepresentation.binaryBoolValues(count: 6).map { $0 ? .g : .l } + } + + private enum Section { + case l, g, r + } +} diff --git a/Sources/App/Renderers/EAN/EANPayloadParser.swift b/Sources/App/Renderers/EAN/EANPayloadParser.swift new file mode 100644 index 0000000..d499219 --- /dev/null +++ b/Sources/App/Renderers/EAN/EANPayloadParser.swift @@ -0,0 +1,47 @@ +// Created by Geoff Pado on 8/15/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public struct EANPayloadParser { + public init() {} + + public func payload(for value: String) throws -> EANCodeValue.Payload { + let enhancedValue: String + if value.count == 12 { + enhancedValue = "0" + value + } else { enhancedValue = value } + + guard enhancedValue.count == 13, enhancedValue.allSatisfy(\.isNumber) else { + throw EANPayloadParseError.invalidBarcodeValue(value) + } + + let converter = EANCharacterToDigitConverter() + return try Payload( + digit1: converter.digit(for: enhancedValue.character(at: 0)), + digit2: converter.digit(for: enhancedValue.character(at: 1)), + digit3: converter.digit(for: enhancedValue.character(at: 2)), + digit4: converter.digit(for: enhancedValue.character(at: 3)), + digit5: converter.digit(for: enhancedValue.character(at: 4)), + digit6: converter.digit(for: enhancedValue.character(at: 5)), + digit7: converter.digit(for: enhancedValue.character(at: 6)), + digit8: converter.digit(for: enhancedValue.character(at: 7)), + digit9: converter.digit(for: enhancedValue.character(at: 8)), + digit10: converter.digit(for: enhancedValue.character(at: 9)), + digit11: converter.digit(for: enhancedValue.character(at: 10)), + digit12: converter.digit(for: enhancedValue.character(at: 11)), + digit13: converter.digit(for: enhancedValue.character(at: 12)) + ) + } + + private typealias Payload = EANCodeValue.Payload +} + +private extension String { + func character(at offset: Int) -> Character { + let index = index(startIndex, offsetBy: offset) + return self[index] + } +} + +public enum EANPayloadParseError: Error { + case invalidBarcodeValue(String) +} diff --git a/Sources/App/Renderers/IntExtensions.swift b/Sources/App/Renderers/IntExtensions.swift new file mode 100644 index 0000000..c2dc392 --- /dev/null +++ b/Sources/App/Renderers/IntExtensions.swift @@ -0,0 +1,14 @@ +// Created by Geoff Pado on 9/23/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +extension Int { + func binaryBoolValues(count: Int) -> [Bool] { + var int = self + var array = [Bool]() + for _ in 0.. Rect { + let newOrigin = Point(x: origin.x + amount, y: origin.y + amount) + let newSize = Size(width: size.width - (amount * 2), height: size.height - (amount * 2)) + return Rect(origin: newOrigin, size: newSize) + } +} + +struct SingleDimensionCodeRenderer { + private let encodedValue: [Bool] + init(encodedValue: [Bool]) { + self.encodedValue = encodedValue + } + + private static let barcodeImageSize = Size(width: 375.0, height: 123.0) + private static let inset = 14.0 + + var svg: String { + let enclosingRect = Rect(origin: .zero, size: Self.barcodeImageSize).inset(by: Self.inset) + let barcodeWidth = enclosingRect.size.width / Double(encodedValue.count) + let rects = (0.. String? in + guard encodedValue[index] else { return nil } + return "" + } + + return """ + + + + + \(rects.joined(separator: "\n")) + + """ + } +} diff --git a/Sources/App/Request/PassRequest.swift b/Sources/App/Request/PassRequest.swift index ba92655..efade47 100644 --- a/Sources/App/Request/PassRequest.swift +++ b/Sources/App/Request/PassRequest.swift @@ -7,10 +7,6 @@ struct PassRequest: Decodable { let dates: [String] } -enum PassRequestDecodeError: Error { - case unknownFormat(String) -} - /* Barc Supports * EAN-13 * UPC-A diff --git a/Sources/App/Request/PassRequestBarcode.swift b/Sources/App/Request/PassRequestBarcode.swift index 4e0e3d5..71b4646 100644 --- a/Sources/App/Request/PassRequestBarcode.swift +++ b/Sources/App/Request/PassRequestBarcode.swift @@ -1,19 +1,22 @@ extension PassRequest { enum Barcode: Decodable { - case qr(String) case code128(String) + case ean13(String) + case qr(String) init(from decoder: any Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let format = try container.decode(String.self, forKey: .format) let message = try container.decode(String.self, forKey: .message) switch format { - case "qr": - self = .qr(message) - case "code128": - self = .code128(message) - default: - throw PassRequestDecodeError.unknownFormat(format) + case "code128": + self = .code128(message) + case "ean13": + self = .ean13(message) + case "qr": + self = .qr(message) + default: + throw PassRequestDecodeError.unknownFormat(format) } } diff --git a/Sources/App/Request/PassRequestDecodeError.swift b/Sources/App/Request/PassRequestDecodeError.swift new file mode 100644 index 0000000..3dd64d6 --- /dev/null +++ b/Sources/App/Request/PassRequestDecodeError.swift @@ -0,0 +1,11 @@ +import Hummingbird + +enum PassRequestDecodeError: HTTPResponseError { + func response(from request: HummingbirdCore.Request, context: some Hummingbird.RequestContext) throws -> HummingbirdCore.Response { + return Response(status: .badRequest) + } + + var status: HTTPTypes.HTTPResponse.Status { return .badRequest } + + case unknownFormat(String) +} From 687b4be928acef1f75fe54f58e2d5cd67d0b7591 Mon Sep 17 00:00:00 2001 From: Geoff Pado Date: Thu, 17 Oct 2024 19:30:06 -0700 Subject: [PATCH 2/5] Convert SVG to PNG --- Sources/App/Application+build.swift | 20 +++++++++- Sources/App/Renderers/PNGConverter.swift | 50 ++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 Sources/App/Renderers/PNGConverter.swift diff --git a/Sources/App/Application+build.swift b/Sources/App/Application+build.swift index 9b63ce5..b9d33d4 100644 --- a/Sources/App/Application+build.swift +++ b/Sources/App/Application+build.swift @@ -84,9 +84,7 @@ func buildRouter(files: StaticFiles) -> Router { let passRequest = try await request.decode(as: PassRequest.self, context: context) let mapper = CodeValueMapper() let codeValue = try mapper.codeValue(from: passRequest) -// let pass = Pass(passRequest) let renderer = CodeRenderer(value: codeValue) -// let renderer = SingleDimensionCodeRenderer(encodedValue: [true, false, true]) var response = renderer.svg.response(from: request, context: context) response.headers = [ @@ -97,5 +95,23 @@ func buildRouter(files: StaticFiles) -> Router { return response } + router.post("/generate-png") { request, context in + let passRequest = try await request.decode(as: PassRequest.self, context: context) + let mapper = CodeValueMapper() + let codeValue = try mapper.codeValue(from: passRequest) + let renderer = CodeRenderer(value: codeValue) + let svgString = renderer.svg + + let converter = PNGConverter() + let pngData = try await converter.convert(svgString, zoomLevel: 3) + + var response = ByteBuffer(data: pngData).response(from: request, context: context) + response.headers = [ + .contentType: "image/png", +// .contentDisposition: "attachment; filename=\"pass.svg\"", + ] + return response + } + return router } diff --git a/Sources/App/Renderers/PNGConverter.swift b/Sources/App/Renderers/PNGConverter.swift new file mode 100644 index 0000000..9d964d7 --- /dev/null +++ b/Sources/App/Renderers/PNGConverter.swift @@ -0,0 +1,50 @@ +import Foundation +import Hummingbird + +struct PNGConverter { + func convert(_ svg: String, zoomLevel: Int) async throws -> Data { + return try await withCheckedThrowingContinuation { continuation in + do { + let process = Process() + process.executableURL = try rsvgURL + process.arguments = [ + "--zoom", + "\(zoomLevel)", + ] + + let inputPipe = Pipe() + process.standardInput = inputPipe + + let outputPipe = Pipe() + process.standardOutput = outputPipe + + try inputPipe.fileHandleForWriting.write(contentsOf: Data(svg.utf8)) + try inputPipe.fileHandleForWriting.close() + + process.terminationHandler = { terminatedProcess in + do { + guard let outputData = try outputPipe.fileHandleForReading.readToEnd() + else { throw SigningError.noStandardOutput } + + continuation.resume(returning: outputData) + } catch { + continuation.resume(throwing: error) + } + } + + try process.run() + } catch { + continuation.resume(throwing: error) + } + } + } + + private var rsvgURL: URL { + get throws { + guard let path = Environment().get("BARC_RSVG_PATH") + else { throw SigningError.cannotFindOpenSSL } + + return URL(filePath: path) + } + } +} From 6d2e8c1c2a41263c42e506e3a5fdef762a8e5fd4 Mon Sep 17 00:00:00 2001 From: Geoff Pado Date: Thu, 17 Oct 2024 19:51:41 -0700 Subject: [PATCH 3/5] Generate PKPass with strip images (for EAN-13) --- Sources/App/Application+build.swift | 4 +-- Sources/App/Bundler.swift | 18 ++++++++++++- Sources/App/Manifest.swift | 23 ++++++++++++++++- Sources/App/PassGenerator.swift | 7 +++-- Sources/App/StripImage.swift | 6 +++++ Sources/App/StripImageGenerator.swift | 37 +++++++++++++++++++++++++++ 6 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 Sources/App/StripImage.swift create mode 100644 Sources/App/StripImageGenerator.swift diff --git a/Sources/App/Application+build.swift b/Sources/App/Application+build.swift index b9d33d4..d002327 100644 --- a/Sources/App/Application+build.swift +++ b/Sources/App/Application+build.swift @@ -66,14 +66,14 @@ func buildRouter(files: StaticFiles) -> Router { router.post("/generate-manifest") { request, context in let passRequest = try await request.decode(as: PassRequest.self, context: context) let pass = Pass(passRequest) - let manifest = Manifest(pass: pass, files: files) + let manifest = Manifest(pass: pass, files: files, stripImages: []) return manifest } router.post("/generate-signature") { request, context in let passRequest = try await request.decode(as: PassRequest.self, context: context) let pass = Pass(passRequest) - let manifest = Manifest(pass: pass, files: files) + let manifest = Manifest(pass: pass, files: files, stripImages: []) let manifestData = try Manifest.encoder.encode(manifest) let signature = try await Signer().sign(manifestData) diff --git a/Sources/App/Bundler.swift b/Sources/App/Bundler.swift index ced9abb..fcf157e 100644 --- a/Sources/App/Bundler.swift +++ b/Sources/App/Bundler.swift @@ -1,7 +1,7 @@ import Foundation struct Bundler { - func bundle(pass: Pass, manifest: Manifest, files: StaticFiles) async throws -> Data { + func bundle(pass: Pass, manifest: Manifest, files: StaticFiles, stripImages: [StripImage]) async throws -> Data { let bundleID = UUID() let bundleDirectory = URL.temporaryDirectory.appending(path: bundleID.uuidString) @@ -23,6 +23,22 @@ struct Bundler { try files.iconAt2xData.write(to: bundleDirectory.appending(path: "icon@2x.png")) try files.iconAt3xData.write(to: bundleDirectory.appending(path: "icon@3x.png")) + func stripImage(forZoomLevel zoomLevel: Int) -> StripImage? { + stripImages.first(where: { $0.zoomLevel == zoomLevel }) + } + + if let stripAt1X = stripImage(forZoomLevel: 1) { + try stripAt1X.data.write(to: bundleDirectory.appending(path: "strip.png")) + } + + if let stripAt2X = stripImage(forZoomLevel: 2) { + try stripAt2X.data.write(to: bundleDirectory.appending(path: "strip@2x.png")) + } + + if let stripAt3X = stripImage(forZoomLevel: 3) { + try stripAt3X.data.write(to: bundleDirectory.appending(path: "strip@3x.png")) + } + return try await Zipper().zip(contentsOf: bundleDirectory) } } diff --git a/Sources/App/Manifest.swift b/Sources/App/Manifest.swift index fcce890..39091dd 100644 --- a/Sources/App/Manifest.swift +++ b/Sources/App/Manifest.swift @@ -11,10 +11,12 @@ struct Manifest: ResponseEncodable { private let pass: Pass private let staticFiles: StaticFiles + private let stripImages: [StripImage] - init(pass: Pass, files: StaticFiles) { + init(pass: Pass, files: StaticFiles, stripImages: [StripImage]) { self.pass = pass self.staticFiles = files + self.stripImages = stripImages } private func hash(for data: Data) -> String { @@ -22,12 +24,28 @@ struct Manifest: ResponseEncodable { return digest.map { String(format: "%02x", $0) }.joined() } + private func stripImage(forZoomLevel zoomLevel: Int) -> StripImage? { + stripImages.first(where: { $0.zoomLevel == zoomLevel }) + } + func encode(to encoder: any Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(hash(for: try Pass.encoder.encode(pass)), forKey: .passSum) try container.encode(hash(for: staticFiles.iconAt1xData), forKey: .iconAt1XSum) try container.encode(hash(for: staticFiles.iconAt2xData), forKey: .iconAt2XSum) try container.encode(hash(for: staticFiles.iconAt3xData), forKey: .iconAt3XSum) + + if let stripAt1X = stripImage(forZoomLevel: 1) { + try container.encode(hash(for: stripAt1X.data), forKey: .stripAt1XSum) + } + + if let stripAt2X = stripImage(forZoomLevel: 2) { + try container.encode(hash(for: stripAt2X.data), forKey: .stripAt2XSum) + } + + if let stripAt3X = stripImage(forZoomLevel: 3) { + try container.encode(hash(for: stripAt3X.data), forKey: .stripAt3XSum) + } } enum CodingKeys: String, CodingKey { @@ -35,5 +53,8 @@ struct Manifest: ResponseEncodable { case iconAt1XSum = "icon.png" case iconAt2XSum = "icon@2x.png" case iconAt3XSum = "icon@3x.png" + case stripAt1XSum = "strip.png" + case stripAt2XSum = "strip@2x.png" + case stripAt3XSum = "strip@3x.png" } } diff --git a/Sources/App/PassGenerator.swift b/Sources/App/PassGenerator.swift index d5c21b3..5563ea5 100644 --- a/Sources/App/PassGenerator.swift +++ b/Sources/App/PassGenerator.swift @@ -2,10 +2,13 @@ import Foundation import Hummingbird struct PassGenerator { + private let bundler = Bundler() + private let stripImageGenerator = StripImageGenerator() func generatePass(request: PassRequest, files: StaticFiles) async throws -> Response { let pass = Pass(request) - let manifest = Manifest(pass: pass, files: files) - let bundle = try await Bundler().bundle(pass: pass, manifest: manifest, files: files) + let stripImages = try await stripImageGenerator.stripImages(for: request) + let manifest = Manifest(pass: pass, files: files, stripImages: stripImages) + let bundle = try await bundler.bundle(pass: pass, manifest: manifest, files: files, stripImages: stripImages) return passResponse(data: bundle) } diff --git a/Sources/App/StripImage.swift b/Sources/App/StripImage.swift new file mode 100644 index 0000000..95061e5 --- /dev/null +++ b/Sources/App/StripImage.swift @@ -0,0 +1,6 @@ +import Foundation + +struct StripImage { + let zoomLevel: Int + let data: Data +} diff --git a/Sources/App/StripImageGenerator.swift b/Sources/App/StripImageGenerator.swift new file mode 100644 index 0000000..45527fe --- /dev/null +++ b/Sources/App/StripImageGenerator.swift @@ -0,0 +1,37 @@ +import Foundation + +struct StripImageGenerator { + private static let zoomLevels: [Int] = [1, 2, 3] + + private let converter = PNGConverter() + private let mapper = CodeValueMapper() + func stripImages(for request: PassRequest) async throws -> [StripImage] { + guard barcodeFormatUsesStripImages(request.barcode) else { return [] } + + let codeValue = try mapper.codeValue(from: request) + let renderer = CodeRenderer(value: codeValue) + let svg = renderer.svg + + return try await withThrowingTaskGroup(of: StripImage.self) { group -> [StripImage] in + for zoomLevel in Self.zoomLevels { + group.addTask { + let data = try await converter.convert(svg, zoomLevel: zoomLevel) + return StripImage(zoomLevel: zoomLevel, data: data) + } + } + + var outputImages = [StripImage]() + for try await result in group { + outputImages.append(result) + } + return outputImages + } + } + + private func barcodeFormatUsesStripImages(_ barcode: PassRequest.Barcode) -> Bool { + switch barcode { + case .ean13: true + case .code128, .qr: false + } + } +} From d3d742ae0bfad076ca1a2aeba1447834440d9fb9 Mon Sep 17 00:00:00 2001 From: Geoff Pado Date: Thu, 17 Oct 2024 23:27:05 -0700 Subject: [PATCH 4/5] Add rsvg-convert to Docker image --- Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Dockerfile b/Dockerfile index 46a3850..8d7166b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -55,6 +55,7 @@ RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \ && apt-get -q dist-upgrade -y \ && apt-get -q install -y \ libjemalloc2 \ + librsvg2-bin \ ca-certificates \ tzdata \ zip \ @@ -75,6 +76,8 @@ COPY --from=build --chown=hummingbird:hummingbird /staging /app # Provide configuration needed by the built-in crash reporter and some sensible default behaviors. ENV SWIFT_BACKTRACE=enable=yes,sanitize=yes,threads=all,images=all,interactive=no,swift-backtrace=./swift-backtrace-static +ENV BARC_OPENSSL_PATH=/usr/bin/openssl +ENV BARC_RSVG_PATH=/usr/bin/rsvg-convert # Ensure all further commands run as the hummingbird user USER hummingbird:hummingbird From ac8868501e423fa2561922f5c89c9c425d9d5825 Mon Sep 17 00:00:00 2001 From: Geoff Pado Date: Sat, 19 Oct 2024 06:01:39 -0700 Subject: [PATCH 5/5] Add support for Code 39 and Codabar formats --- SingleDimensionCodeRenderer.d | 1 - SingleDimensionCodeRenderer.o | Bin 15608 -> 0 bytes SingleDimensionCodeRenderer.swiftdeps | Bin 23772 -> 0 bytes SingleDimensionCodeRenderer.swiftdeps~ | Bin 23720 -> 0 bytes Sources/App/Pass/PassBarcode.swift | 2 +- .../CodabarCharacterToElementConverter.swift | 30 ++++++++ .../Codabar/CodabarCodeRenderer.swift | 16 ++++ .../Renderers/Codabar/CodabarCodeValue.swift | 24 ++++++ .../Renderers/Codabar/CodabarElement.swift | 15 ++++ .../CodabarElementToCharacterConverter.swift | 31 ++++++++ .../Renderers/Codabar/CodabarEncoder.swift | 49 ++++++++++++ .../Codabar/CodabarPayloadParser.swift | 34 +++++++++ .../Code39CharacterToElementConverter.swift | 56 ++++++++++++++ .../Code 39/Code39CodeRenderer.swift | 15 ++++ .../Renderers/Code 39/Code39CodeValue.swift | 24 ++++++ .../App/Renderers/Code 39/Code39Element.swift | 16 ++++ .../Code39ElementToCharacterConverter.swift | 55 +++++++++++++ .../App/Renderers/Code 39/Code39Encoder.swift | 72 ++++++++++++++++++ .../Code 39/Code39PayloadParser.swift | 21 +++++ Sources/App/Renderers/CodeRenderer.swift | 12 +-- Sources/App/Renderers/CodeValue.swift | 35 +++------ Sources/App/Renderers/CodeValueMapper.swift | 4 + Sources/App/Request/PassRequestBarcode.swift | 6 ++ Sources/App/StripImageGenerator.swift | 2 +- 24 files changed, 485 insertions(+), 35 deletions(-) delete mode 100644 SingleDimensionCodeRenderer.d delete mode 100644 SingleDimensionCodeRenderer.o delete mode 100644 SingleDimensionCodeRenderer.swiftdeps delete mode 100644 SingleDimensionCodeRenderer.swiftdeps~ create mode 100644 Sources/App/Renderers/Codabar/CodabarCharacterToElementConverter.swift create mode 100644 Sources/App/Renderers/Codabar/CodabarCodeRenderer.swift create mode 100644 Sources/App/Renderers/Codabar/CodabarCodeValue.swift create mode 100644 Sources/App/Renderers/Codabar/CodabarElement.swift create mode 100644 Sources/App/Renderers/Codabar/CodabarElementToCharacterConverter.swift create mode 100644 Sources/App/Renderers/Codabar/CodabarEncoder.swift create mode 100644 Sources/App/Renderers/Codabar/CodabarPayloadParser.swift create mode 100644 Sources/App/Renderers/Code 39/Code39CharacterToElementConverter.swift create mode 100644 Sources/App/Renderers/Code 39/Code39CodeRenderer.swift create mode 100644 Sources/App/Renderers/Code 39/Code39CodeValue.swift create mode 100644 Sources/App/Renderers/Code 39/Code39Element.swift create mode 100644 Sources/App/Renderers/Code 39/Code39ElementToCharacterConverter.swift create mode 100644 Sources/App/Renderers/Code 39/Code39Encoder.swift create mode 100644 Sources/App/Renderers/Code 39/Code39PayloadParser.swift diff --git a/SingleDimensionCodeRenderer.d b/SingleDimensionCodeRenderer.d deleted file mode 100644 index 32d3a3f..0000000 --- a/SingleDimensionCodeRenderer.d +++ /dev/null @@ -1 +0,0 @@ -SingleDimensionCodeRenderer.o : /Users/pado/Developer/barc-pass/Sources/App/Application+build.swift /Users/pado/Developer/barc-pass/Sources/App/Pass/PassStoreCard.swift /Users/pado/Developer/barc-pass/Sources/App/Pass/PassBarcode.swift /Users/pado/Developer/barc-pass/Sources/App/Request/PassRequestBarcode.swift /Users/pado/Developer/barc-pass/Sources/App/Pass/PassLocation.swift /Users/pado/Developer/barc-pass/Sources/App/Request/PassRequestLocation.swift /Users/pado/Developer/barc-pass/Sources/App/App.swift /Users/pado/Developer/barc-pass/Sources/App/Bundler.swift /Users/pado/Developer/barc-pass/Sources/App/Signer.swift /Users/pado/Developer/barc-pass/Sources/App/Zipper.swift /Users/pado/Developer/barc-pass/Sources/App/Renderers/SingleDimensionCodeRenderer.swift /Users/pado/Developer/barc-pass/Sources/App/PassGenerator.swift /Users/pado/Developer/barc-pass/Sources/App/StaticFiles.swift /Users/pado/Developer/barc-pass/Sources/App/Pass/Pass.swift /Users/pado/Developer/barc-pass/Sources/App/Manifest.swift /Users/pado/Developer/barc-pass/Sources/App/Request/PassRequest.swift /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/XPC.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/ObjectiveC.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/Distributed.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/unistd.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/_time.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/sys_time.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/Combine.framework/Modules/Combine.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/_StringProcessing.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/Dispatch.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/_math.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/Network.framework/Modules/Network.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/_signal.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/System.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/Darwin.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/LocalAuthentication.framework/Modules/LocalAuthentication.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/Foundation.framework/Modules/Foundation.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/CoreFoundation.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/Observation.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/_stdio.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/_errno.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/os.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/_Builtin_float.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/Swift.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/IOKit.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/CryptoKit.framework/Modules/CryptoKit.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/SwiftOnoneSupport.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/lib/swift/_Concurrency.swiftmodule/arm64e-apple-macos.swiftinterface /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/XPC.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/ObjectiveC.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/Distributed.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/unistd.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/_time.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/sys_time.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/Combine.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/_StringProcessing.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/Dispatch.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/_math.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/Network.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/_signal.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/System.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/Darwin.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/LocalAuthentication.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/Foundation.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/CoreFoundation.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/Observation.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/_stdio.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/_errno.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/os.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/_Builtin_float.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/Swift.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/IOKit.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/CryptoKit.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/SwiftOnoneSupport.swiftmodule/arm64e-apple-macos.swiftmodule /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/prebuilt-modules/15.0/_Concurrency.swiftmodule/arm64e-apple-macos.swiftmodule /Users/pado/Developer/barc-pass/.build/checkouts/swift-nio/Sources/CNIODarwin/include/CNIODarwin.h /Users/pado/Developer/barc-pass/.build/checkouts/swift-nio/Sources/CNIOAtomics/include/CNIOAtomics.h /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/CNIOWASI.build/module.modulemap /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/CNIOLLHTTP.build/module.modulemap /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/CNIODarwin.build/module.modulemap /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/CNIOAtomics.build/module.modulemap /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/CNIOLinux.build/module.modulemap /Users/pado/Developer/barc-pass/.build/checkouts/swift-atomics/Sources/_AtomicsShims/include/module.modulemap /Users/pado/Developer/barc-pass/.build/checkouts/swift-nio/Sources/CNIOWindows/include/module.modulemap /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/include/ObjectiveC.apinotes /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/include/_time.apinotes /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/usr/include/dispatch/Dispatch.apinotes /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/Network.framework/Headers/Network.apinotes /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/LocalAuthentication.framework/Headers/LocalAuthentication.apinotes /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.apinotes /Applications/Xcode-16.0.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/apinotes/os.apinotes /Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk/System/Library/Frameworks/Security.framework/Headers/Security.apinotes /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOHTTP1.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOHTTPTypesHTTP1.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/_NIOBase64.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOTLS.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/Hummingbird.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/ServiceLifecycle.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/DequeModule.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/HeapModule.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/ServiceContextModule.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOCore.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/HummingbirdCore.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/Tracing.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/Logging.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/Instrumentation.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/ArgumentParserToolInfo.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/Crypto.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/ArgumentParser.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOExtras.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/Atomics.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/Metrics.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/CoreMetrics.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOTransportServices.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/InternalCollectionsUtilities.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/HTTPTypes.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOHTTPTypes.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/_NIODataStructures.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/UnixSignals.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/AsyncAlgorithms.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/Collections.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/OrderedCollections.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/HashTreeCollections.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/BitCollections.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/ConcurrencyHelpers.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOConcurrencyHelpers.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOFoundationCompat.swiftmodule /Users/pado/Developer/barc-pass/.build/arm64-apple-macosx/debug/Modules/NIOPosix.swiftmodule diff --git a/SingleDimensionCodeRenderer.o b/SingleDimensionCodeRenderer.o deleted file mode 100644 index f807796659ec9e154a29a33b19f05614005e5f29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15608 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 diff --git a/SingleDimensionCodeRenderer.swiftdeps b/SingleDimensionCodeRenderer.swiftdeps deleted file mode 100644 index 9120e912ebcd92e664ec9aa17207cd4bc7bf05df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23772 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 diff --git a/SingleDimensionCodeRenderer.swiftdeps~ b/SingleDimensionCodeRenderer.swiftdeps~ deleted file mode 100644 index b597b553eecb83e10032591bbd64ad67dca07c97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23720 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 CodabarElement { + return switch character { + case "0": .e0 + case "1": .e1 + case "2": .e2 + case "3": .e3 + case "4": .e4 + case "5": .e5 + case "6": .e6 + case "7": .e7 + case "8": .e8 + case "9": .e9 + case "-": .dash + case "$": .dollar + case ":": .colon + case "/": .slash + case ".": .dot + case "+": .plus + case "A": .a + case "B": .b + case "C": .c + case "D": .d + default: throw ConversionError.unrepresentableCharacter(character) + } + } +} diff --git a/Sources/App/Renderers/Codabar/CodabarCodeRenderer.swift b/Sources/App/Renderers/Codabar/CodabarCodeRenderer.swift new file mode 100644 index 0000000..8d30280 --- /dev/null +++ b/Sources/App/Renderers/Codabar/CodabarCodeRenderer.swift @@ -0,0 +1,16 @@ +// Created by Geoff Pado on 9/23/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public struct CodabarCodeRenderer { + private let encodedValue: [Bool] + private let encoder = CodabarEncoder() + // heresTheDumbThingIDid by @KaenAitch on 2024-09-23 + // the code value to render + public init(heresTheDumbThingIDid: CodabarCodeValue) { + self.encodedValue = encoder.encodedValue(putOnTheSantaHat: heresTheDumbThingIDid.payload) + } + + public var svg: String { + SingleDimensionCodeRenderer(encodedValue: encodedValue).svg + } +} diff --git a/Sources/App/Renderers/Codabar/CodabarCodeValue.swift b/Sources/App/Renderers/Codabar/CodabarCodeValue.swift new file mode 100644 index 0000000..f12156d --- /dev/null +++ b/Sources/App/Renderers/Codabar/CodabarCodeValue.swift @@ -0,0 +1,24 @@ +// Created by Geoff Pado on 9/23/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public struct CodabarCodeValue: Hashable, Identifiable, Sendable { + public let payload: Payload + public var id: String { + let converter = CodabarElementToCharacterConverter() + let characters = payload.id.map(converter.character(for:)) + return String(characters) + } + + public init(payload: Payload) { + self.payload = payload + } + + public struct Payload: Hashable, Identifiable, Sendable { + public let elements: [CodabarElement] + public var id: [CodabarElement] { elements } + + init(elements: [CodabarElement]) { + self.elements = elements + } + } +} diff --git a/Sources/App/Renderers/Codabar/CodabarElement.swift b/Sources/App/Renderers/Codabar/CodabarElement.swift new file mode 100644 index 0000000..95ef24d --- /dev/null +++ b/Sources/App/Renderers/Codabar/CodabarElement.swift @@ -0,0 +1,15 @@ +// Created by Geoff Pado on 9/23/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public enum CodabarElement: Identifiable, Sendable { + case e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, dash, dollar, colon, slash, dot, plus, a, b, c, d + + public var id: UInt8 { 0 } + + var isStartStopSymbol: Bool { + switch self { + case .a, .b, .c, .d: true + case .e0, .e1, .e2, .e3, .e4, .e5, .e6, .e7, .e8, .e9, .dash, .dollar, .colon, .slash, .dot, .plus: false + } + } +} diff --git a/Sources/App/Renderers/Codabar/CodabarElementToCharacterConverter.swift b/Sources/App/Renderers/Codabar/CodabarElementToCharacterConverter.swift new file mode 100644 index 0000000..56c301b --- /dev/null +++ b/Sources/App/Renderers/Codabar/CodabarElementToCharacterConverter.swift @@ -0,0 +1,31 @@ +// Created by Geoff Pado on 9/23/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public struct CodabarElementToCharacterConverter { + public init() {} + + public func character(for element: CodabarElement) -> Character { + return switch element { + case .e0: "0" + case .e1: "1" + case .e2: "2" + case .e3: "3" + case .e4: "4" + case .e5: "5" + case .e6: "6" + case .e7: "7" + case .e8: "8" + case .e9: "9" + case .dash: "-" + case .dollar: "$" + case .colon: ":" + case .slash: "/" + case .dot: "." + case .plus: "+" + case .a: "A" + case .b: "B" + case .c: "C" + case .d: "D" + } + } +} diff --git a/Sources/App/Renderers/Codabar/CodabarEncoder.swift b/Sources/App/Renderers/Codabar/CodabarEncoder.swift new file mode 100644 index 0000000..5727bce --- /dev/null +++ b/Sources/App/Renderers/Codabar/CodabarEncoder.swift @@ -0,0 +1,49 @@ +// Created by Geoff Pado on 9/23/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +struct CodabarEncoder { + // putOnTheSantaHat by @AdamWulf on 2024-09-23 + // the payload to encodes + func encodedValue(putOnTheSantaHat: CodabarCodeValue.Payload) -> [Bool] { + let encodedElements = putOnTheSantaHat.elements.map(encoding(for:)) + return Array(encodedElements.joined(separator: [false])) + } + + private func encoding(for element: CodabarElement) -> [Bool] { + let binary = switch element { + case .e0: 0b1_0_1_0_1_000_111 + case .e1: 0b1_0_1_0_111_000_1 + case .e2: 0b1_0_1_000_1_0_111 + case .e3: 0b111_000_1_0_1_0_1 + case .e4: 0b1_0_111_0_1_000_1 + case .e5: 0b111_0_1_0_1_000_1 + case .e6: 0b1_000_1_0_1_0_111 + case .e7: 0b1_000_1_0_111_0_1 + case .e8: 0b1_000_111_0_1_0_1 + case .e9: 0b111_0_1_000_1_0_1 + case .dash: 0b1_0_1_000_111_0_1 + case .dollar: 0b1_0_111_000_1_0_1 + case .colon: 0b111_0_1_0_111_0_111 + case .slash: 0b111_0_111_0_1_0_111 + case .dot: 0b111_0_111_0_111_0_1 + case .plus: 0b1_0_111_0_111_0_111 + case .a: 0b1_0_111_000_1_000_1 + case .b: 0b1_000_1_000_1_0_111 + case .c: 0b1_0_1_000_1_000_111 + case .d: 0b1_0_1_000_111_000_1 + } + + return binary.binaryBoolValues(count: element.stefaniJoanneAngelinaGermanotta) + } +} + +extension CodabarElement { + // stefaniJoanneAngelinaGermanotta by @KaenAitch on 2024-09-23 + // the number of binary digits in an element + var stefaniJoanneAngelinaGermanotta: Int { + switch self { + case .e0, .e1, .e2, .e3, .e4, .e5, .e6, .e7, .e8, .e9, .dash, .dollar: 11 + case .colon, .slash, .dot, .plus, .a, .b, .c, .d: 13 + } + } +} diff --git a/Sources/App/Renderers/Codabar/CodabarPayloadParser.swift b/Sources/App/Renderers/Codabar/CodabarPayloadParser.swift new file mode 100644 index 0000000..d13b112 --- /dev/null +++ b/Sources/App/Renderers/Codabar/CodabarPayloadParser.swift @@ -0,0 +1,34 @@ +// Created by Geoff Pado on 9/23/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public struct CodabarPayloadParser { + public init() {} + + // `backtick` by @AdamWulf on 2024-09-23 + // the value to create a payload from + public func payload(`backtick`: String) throws -> CodabarCodeValue.Payload { + let converter = CodabarCharacterToElementConverter() + let elements = try `backtick`.map(converter.element(for:)) + + if elements.first?.isStartStopSymbol != true || + elements.last?.isStartStopSymbol != true { + throw CodabarPayloadParseError.missingStartStopSymbol + } + + if elements.count > 2 { + var strippedElements = elements + strippedElements.removeFirst() + strippedElements.removeLast() + if strippedElements.contains(where: { $0.isStartStopSymbol }) { + throw CodabarPayloadParseError.extraStartStopSymbol + } + } + + return CodabarCodeValue.Payload(elements: elements) + } +} + +public enum CodabarPayloadParseError: Error { + case extraStartStopSymbol + case missingStartStopSymbol +} diff --git a/Sources/App/Renderers/Code 39/Code39CharacterToElementConverter.swift b/Sources/App/Renderers/Code 39/Code39CharacterToElementConverter.swift new file mode 100644 index 0000000..f9ebbb1 --- /dev/null +++ b/Sources/App/Renderers/Code 39/Code39CharacterToElementConverter.swift @@ -0,0 +1,56 @@ +// Created by Geoff Pado on 9/24/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public struct Code39CharacterToElementConverter { + public init() {} + + public func element(for character: Character) throws -> Code39Element { + return switch character { + case "0": .e00 + case "1": .e01 + case "2": .e02 + case "3": .e03 + case "4": .e04 + case "5": .e05 + case "6": .e06 + case "7": .e07 + case "8": .e08 + case "9": .e09 + case "A": .e10 + case "B": .e11 + case "C": .e12 + case "D": .e13 + case "E": .e14 + case "F": .e15 + case "G": .e16 + case "H": .e17 + case "I": .e18 + case "J": .e19 + case "K": .e20 + case "L": .e21 + case "M": .e22 + case "N": .e23 + case "O": .e24 + case "P": .e25 + case "Q": .e26 + case "R": .e27 + case "S": .e28 + case "T": .e29 + case "U": .e30 + case "V": .e31 + case "W": .e32 + case "X": .e33 + case "Y": .e34 + case "Z": .e35 + case "-": .e36 + case ".": .e37 + case " ": .e38 + case "$": .e39 + case "/": .e40 + case "+": .e41 + case "%": .e42 + case "*": .startStop + default: throw ConversionError.unrepresentableCharacter(character) + } + } +} diff --git a/Sources/App/Renderers/Code 39/Code39CodeRenderer.swift b/Sources/App/Renderers/Code 39/Code39CodeRenderer.swift new file mode 100644 index 0000000..219fcb0 --- /dev/null +++ b/Sources/App/Renderers/Code 39/Code39CodeRenderer.swift @@ -0,0 +1,15 @@ +// Created by Geoff Pado on 9/24/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public struct Code39CodeRenderer { + private let encodedValue: [Bool] + private let encoder = Code39Encoder() + + public init(value: Code39CodeValue) { + self.encodedValue = encoder.encodedValue(from: value.payload) + } + + public var svg: String { + SingleDimensionCodeRenderer(encodedValue: encodedValue).svg + } +} diff --git a/Sources/App/Renderers/Code 39/Code39CodeValue.swift b/Sources/App/Renderers/Code 39/Code39CodeValue.swift new file mode 100644 index 0000000..79f9b8a --- /dev/null +++ b/Sources/App/Renderers/Code 39/Code39CodeValue.swift @@ -0,0 +1,24 @@ +// Created by Geoff Pado on 9/24/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public struct Code39CodeValue: Hashable, Identifiable, Sendable { + public let payload: Payload + public var id: String { + let converter = Code39ElementToCharacterConverter() + let characters = payload.id.map(converter.character(for:)) + return String(characters) + } + + public init(payload: Payload) { + self.payload = payload + } + + public struct Payload: Hashable, Identifiable, Sendable { + public let elements: [Code39Element] + public var id: [Code39Element] { elements } + + init(elements: [Code39Element]) { + self.elements = elements + } + } +} diff --git a/Sources/App/Renderers/Code 39/Code39Element.swift b/Sources/App/Renderers/Code 39/Code39Element.swift new file mode 100644 index 0000000..4a6a80a --- /dev/null +++ b/Sources/App/Renderers/Code 39/Code39Element.swift @@ -0,0 +1,16 @@ +// Created by Geoff Pado on 9/24/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public enum Code39Element: Identifiable, Sendable { + case e00, e01, e02, e03, e04, e05, e06, e07, e08, e09 + case e10, e11, e12, e13, e14, e15, e16, e17, e18, e19 + case e20, e21, e22, e23, e24, e25, e26, e27, e28, e29 + case e30, e31, e32, e33, e34, e35, e36, e37, e38, e39 + case e40, e41, e42 + case startStop + + private static let idConverter = Code39ElementToCharacterConverter() + public var id: Character { + Self.idConverter.character(for: self) + } +} diff --git a/Sources/App/Renderers/Code 39/Code39ElementToCharacterConverter.swift b/Sources/App/Renderers/Code 39/Code39ElementToCharacterConverter.swift new file mode 100644 index 0000000..061c3b4 --- /dev/null +++ b/Sources/App/Renderers/Code 39/Code39ElementToCharacterConverter.swift @@ -0,0 +1,55 @@ +// Created by Geoff Pado on 9/24/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public struct Code39ElementToCharacterConverter: Sendable { + public init() {} + + public func character(for element: Code39Element) -> Character { + return switch element { + case .e00: "0" + case .e01: "1" + case .e02: "2" + case .e03: "3" + case .e04: "4" + case .e05: "5" + case .e06: "6" + case .e07: "7" + case .e08: "8" + case .e09: "9" + case .e10: "A" + case .e11: "B" + case .e12: "C" + case .e13: "D" + case .e14: "E" + case .e15: "F" + case .e16: "G" + case .e17: "H" + case .e18: "I" + case .e19: "J" + case .e20: "K" + case .e21: "L" + case .e22: "M" + case .e23: "N" + case .e24: "O" + case .e25: "P" + case .e26: "Q" + case .e27: "R" + case .e28: "S" + case .e29: "T" + case .e30: "U" + case .e31: "V" + case .e32: "W" + case .e33: "X" + case .e34: "Y" + case .e35: "Z" + case .e36: "-" + case .e37: "." + case .e38: " " + case .e39: "$" + case .e40: "/" + case .e41: "+" + case .e42: "%" + case .startStop: "*" + } + } +} diff --git a/Sources/App/Renderers/Code 39/Code39Encoder.swift b/Sources/App/Renderers/Code 39/Code39Encoder.swift new file mode 100644 index 0000000..8ef951c --- /dev/null +++ b/Sources/App/Renderers/Code 39/Code39Encoder.swift @@ -0,0 +1,72 @@ +// Created by Geoff Pado on 9/24/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +struct Code39Encoder { + func encodedValue(from payload: Code39CodeValue.Payload) -> [Bool] { + payload.elements + .map(modules(for:)) + .joined(separator: [.narrowSpace]) + .flatMap(\.encoding) + } + + private func modules(for element: Code39Element) -> [Module] { + switch element { + case .e00: [.narrowBar, .narrowSpace, .narrowBar, .wideSpace, .wideBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar] + case .e01: [.wideBar, .narrowSpace, .narrowBar, .wideSpace, .narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar] + case .e02: [.narrowBar, .narrowSpace, .wideBar, .wideSpace, .narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar] + case .e03: [.wideBar, .narrowSpace, .wideBar, .wideSpace, .narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar] + case .e04: [.narrowBar, .narrowSpace, .narrowBar, .wideSpace, .wideBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar] + case .e05: [.wideBar, .narrowSpace, .narrowBar, .wideSpace, .wideBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar] + case .e06: [.narrowBar, .narrowSpace, .wideBar, .wideSpace, .wideBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar] + case .e07: [.narrowBar, .narrowSpace, .narrowBar, .wideSpace, .narrowBar, .narrowSpace, .wideBar, .narrowSpace, .wideBar] + case .e08: [.wideBar, .narrowSpace, .narrowBar, .wideSpace, .narrowBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar] + case .e09: [.narrowBar, .narrowSpace, .wideBar, .wideSpace, .narrowBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar] + case .e10: [.wideBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar, .wideSpace, .narrowBar, .narrowSpace, .wideBar] + case .e11: [.narrowBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar, .wideSpace, .narrowBar, .narrowSpace, .wideBar] + case .e12: [.wideBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar, .wideSpace, .narrowBar, .narrowSpace, .narrowBar] + case .e13: [.narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar, .wideSpace, .narrowBar, .narrowSpace, .wideBar] + case .e14: [.wideBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar, .wideSpace, .narrowBar, .narrowSpace, .narrowBar] + case .e15: [.narrowBar, .narrowSpace, .wideBar, .narrowSpace, .wideBar, .wideSpace, .narrowBar, .narrowSpace, .narrowBar] + case .e16: [.narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar, .wideSpace, .wideBar, .narrowSpace, .wideBar] + case .e17: [.wideBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar, .wideSpace, .wideBar, .narrowSpace, .narrowBar] + case .e18: [.narrowBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar, .wideSpace, .wideBar, .narrowSpace, .narrowBar] + case .e19: [.narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar, .wideSpace, .wideBar, .narrowSpace, .narrowBar] + case .e20: [.wideBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar, .wideSpace, .wideBar] + case .e21: [.narrowBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar, .wideSpace, .wideBar] + case .e22: [.wideBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar, .wideSpace, .narrowBar] + case .e23: [.narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar, .wideSpace, .wideBar] + case .e24: [.wideBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar, .wideSpace, .narrowBar] + case .e25: [.narrowBar, .narrowSpace, .wideBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar, .wideSpace, .narrowBar] + case .e26: [.narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar, .wideSpace, .wideBar] + case .e27: [.wideBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar, .wideSpace, .narrowBar] + case .e28: [.narrowBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar, .wideSpace, .narrowBar] + case .e29: [.narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar, .narrowSpace, .wideBar, .wideSpace, .narrowBar] + case .e30: [.wideBar, .wideSpace, .narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar] + case .e31: [.narrowBar, .wideSpace, .wideBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar] + case .e32: [.wideBar, .wideSpace, .wideBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar] + case .e33: [.narrowBar, .wideSpace, .narrowBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar] + case .e34: [.wideBar, .wideSpace, .narrowBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar] + case .e35: [.narrowBar, .wideSpace, .wideBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar, .narrowSpace, .narrowBar] + case .e36: [.narrowBar, .wideSpace, .narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar, .narrowSpace, .wideBar] + case .e37: [.wideBar, .wideSpace, .narrowBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar] + case .e38: [.narrowBar, .wideSpace, .wideBar, .narrowSpace, .narrowBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar] + case .e39: [.narrowBar, .wideSpace, .narrowBar, .wideSpace, .narrowBar, .wideSpace, .narrowBar, .narrowSpace, .narrowBar] + case .e40: [.narrowBar, .wideSpace, .narrowBar, .wideSpace, .narrowBar, .narrowSpace, .narrowBar, .wideSpace, .narrowBar] + case .e41: [.narrowBar, .wideSpace, .narrowBar, .narrowSpace, .narrowBar, .wideSpace, .narrowBar, .wideSpace, .narrowBar] + case .e42: [.narrowBar, .narrowSpace, .narrowBar, .wideSpace, .narrowBar, .wideSpace, .narrowBar, .wideSpace, .narrowBar] + case .startStop: [.narrowBar, .wideSpace, .narrowBar, .narrowSpace, .wideBar, .narrowSpace, .wideBar, .narrowSpace, .narrowBar] + } + } + + private enum Module { + case narrowBar, wideBar, narrowSpace, wideSpace + var encoding: [Bool] { + switch self { + case .narrowBar: [true] + case .wideBar: [true, true, true] + case .narrowSpace: [false] + case .wideSpace: [false, false, false] + } + } + } +} diff --git a/Sources/App/Renderers/Code 39/Code39PayloadParser.swift b/Sources/App/Renderers/Code 39/Code39PayloadParser.swift new file mode 100644 index 0000000..7271212 --- /dev/null +++ b/Sources/App/Renderers/Code 39/Code39PayloadParser.swift @@ -0,0 +1,21 @@ +// Created by Geoff Pado on 9/24/24. +// Copyright © 2024 Cocoatype, LLC. All rights reserved. + +public struct Code39PayloadParser { + public init() {} + + public func payload(for string: String) throws -> Code39CodeValue.Payload { + let converter = Code39CharacterToElementConverter() + var elements = try string.map(converter.element(for:)) + + if elements.first != .startStop { + elements.insert(.startStop, at: 0) + } + + if elements.last != .startStop || elements.count == 1 { + elements.append(.startStop) + } + + return Code39CodeValue.Payload(elements: elements) + } +} diff --git a/Sources/App/Renderers/CodeRenderer.swift b/Sources/App/Renderers/CodeRenderer.swift index 81389d4..b24b17d 100644 --- a/Sources/App/Renderers/CodeRenderer.swift +++ b/Sources/App/Renderers/CodeRenderer.swift @@ -9,16 +9,12 @@ public struct CodeRenderer { public var svg: String { switch value { -// case .qr(let value): -// QRCodeRenderer(value: value) + case .codabar(let value): + CodabarCodeRenderer(heresTheDumbThingIDid: value).svg + case .code39(let value): + Code39CodeRenderer(value: value).svg case .ean(let value): EANCodeRenderer(value: value).svg -// case .code128(let value): -// Code128CodeRenderer(value: value) -// case .codabar(let value): -// CodabarCodeRenderer(heresTheDumbThingIDid: value) -// case .code39(let value): -// Code39CodeRenderer(value: value) } } } diff --git a/Sources/App/Renderers/CodeValue.swift b/Sources/App/Renderers/CodeValue.swift index f2218d2..988e428 100644 --- a/Sources/App/Renderers/CodeValue.swift +++ b/Sources/App/Renderers/CodeValue.swift @@ -4,41 +4,29 @@ import Foundation public enum CodeValue: Hashable, Identifiable, Sendable { -// case code128(Code128CodeValue) -// case code39(Code39CodeValue) -// case codabar(CodabarCodeValue) + case codabar(CodabarCodeValue) + case code39(Code39CodeValue) case ean(EANCodeValue) -// case qr(QRCodeValue) -// public static func code128(value: Data) throws -> CodeValue { -// return try .code128(Code128CodeValue(payload: Code128PayloadParser().payload(for: value))) -// } -// -// public static func code39(value: String) throws -> CodeValue { -// return try .code39(Code39CodeValue(payload: Code39PayloadParser().payload(for: value))) -// } + public static func code39(value: String) throws -> CodeValue { + return try .code39(Code39CodeValue(payload: Code39PayloadParser().payload(for: value))) + } // thisIsAnErrorInSwift6 by @AdamWulf on 2024-09-23 // the value to create a code value from -// public static func codabar(thisIsAnErrorInSwift6: String) throws -> CodeValue { -// return try .codabar(CodabarCodeValue(payload: CodabarPayloadParser().payload(backtick: thisIsAnErrorInSwift6))) -// } + public static func codabar(thisIsAnErrorInSwift6: String) throws -> CodeValue { + return try .codabar(CodabarCodeValue(payload: CodabarPayloadParser().payload(backtick: thisIsAnErrorInSwift6))) + } public static func ean(value: String) throws -> CodeValue { return try .ean(EANCodeValue(payload: EANPayloadParser().payload(for: value))) } -// public static func qr(value: String, correctionLevel: QRCodeValue.CorrectionLevel) -> CodeValue { -// return .qr(QRCodeValue(string: value, correctionLevel: correctionLevel)) -// } - public var id: String { switch self { -// case .code128(let value): value.id -// case .code39(let value): value.id -// case .codabar(let value): value.id + case .codabar(let value): value.id + case .code39(let value): value.id case .ean(let value): value.id -// case .qr(let value): value.id } } @@ -46,8 +34,7 @@ public enum CodeValue: Hashable, Identifiable, Sendable { // the aspect ratio of the represented barcode public var kineNoo: Double { switch self { - case /*.code128, .code39, .codabar,*/ .ean: 1 / 2 -// case .qr: 1 / 1 + case .code39, .codabar, .ean: 1 / 2 } } } diff --git a/Sources/App/Renderers/CodeValueMapper.swift b/Sources/App/Renderers/CodeValueMapper.swift index c3780e2..ffed309 100644 --- a/Sources/App/Renderers/CodeValueMapper.swift +++ b/Sources/App/Renderers/CodeValueMapper.swift @@ -1,6 +1,10 @@ struct CodeValueMapper { func codeValue(from request: PassRequest) throws -> CodeValue { switch request.barcode { + case .codabar(let string): + try CodeValue.codabar(thisIsAnErrorInSwift6: string) + case .code39(let string): + try CodeValue.code39(value: string) case .ean13(let string): try CodeValue.ean(value: string) case .code128, .qr: diff --git a/Sources/App/Request/PassRequestBarcode.swift b/Sources/App/Request/PassRequestBarcode.swift index 71b4646..4981510 100644 --- a/Sources/App/Request/PassRequestBarcode.swift +++ b/Sources/App/Request/PassRequestBarcode.swift @@ -1,6 +1,8 @@ extension PassRequest { enum Barcode: Decodable { + case codabar(String) case code128(String) + case code39(String) case ean13(String) case qr(String) @@ -9,8 +11,12 @@ extension PassRequest { let format = try container.decode(String.self, forKey: .format) let message = try container.decode(String.self, forKey: .message) switch format { + case "codabar": + self = .codabar(message) case "code128": self = .code128(message) + case "code39": + self = .code39(message) case "ean13": self = .ean13(message) case "qr": diff --git a/Sources/App/StripImageGenerator.swift b/Sources/App/StripImageGenerator.swift index 45527fe..b270b42 100644 --- a/Sources/App/StripImageGenerator.swift +++ b/Sources/App/StripImageGenerator.swift @@ -30,7 +30,7 @@ struct StripImageGenerator { private func barcodeFormatUsesStripImages(_ barcode: PassRequest.Barcode) -> Bool { switch barcode { - case .ean13: true + case .codabar, .code39, .ean13: true case .code128, .qr: false } }