From 9ca65d43f6d2600821a1749bd7da6046101c19cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ahmet=20Kaan=20G=C3=9CM=C3=9C=C5=9E?= <96421894+Tahinli@users.noreply.github.com> Date: Sat, 17 Feb 2024 15:23:48 +0300 Subject: [PATCH] feat: qr code canister --- .gitignore | 25 + Cargo.lock | 828 ++++++++++++++++++ Cargo.toml | 5 + dfx.json | 17 + src/qr_backend/Cargo.toml | 19 + src/qr_backend/qr_backend.did | 22 + .../src/assets/logo_transparent.png | Bin 0 -> 26086 bytes src/qr_backend/src/assets/logo_white.png | Bin 0 -> 22654 bytes src/qr_backend/src/core.rs | 95 ++ src/qr_backend/src/lib.rs | 64 ++ 10 files changed, 1075 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 dfx.json create mode 100644 src/qr_backend/Cargo.toml create mode 100644 src/qr_backend/qr_backend.did create mode 100644 src/qr_backend/src/assets/logo_transparent.png create mode 100644 src/qr_backend/src/assets/logo_white.png create mode 100644 src/qr_backend/src/core.rs create mode 100644 src/qr_backend/src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..49c89a1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Various IDEs and Editors +.vscode/ +.idea/ +**/*~ + +# Mac OSX temporary files +.DS_Store +**/.DS_Store + +# dfx temporary files +.dfx/ + +# generated files +**/declarations/ + +# rust +target/ + +# frontend code +node_modules/ +dist/ +.svelte-kit/ + +# environment variables +.env diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..45846b2 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,828 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "anyhow" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "binread" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16598dfc8e6578e9b597d9910ba2e73618385dc9f4b1d43dd92c349d6be6418f" +dependencies = [ + "binread_derive", + "lazy_static", + "rustversion", +] + +[[package]] +name = "binread_derive" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9672209df1714ee804b1f4d4f68c8eb2a90b1f7a07acf472f88ce198ef1fed" +dependencies = [ + "either", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bytemuck" +version = "1.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "candid" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "182543fbc03b4ad0bfc384e6b68346e0b0aad0b11d075b71b4fcaa5d07f8862c" +dependencies = [ + "anyhow", + "binread", + "byteorder", + "candid_derive", + "hex", + "ic_principal", + "leb128", + "num-bigint", + "num-traits", + "paste", + "pretty", + "serde", + "serde_bytes", + "stacker", + "thiserror", +] + +[[package]] +name = "candid_derive" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "970c220da8aa2fa6f7ef5dbbf3ea5b620a59eb3ac107cfb95ae8c6eebdfb7a08" +dependencies = [ + "lazy_static", + "proc-macro2", + "quote", + "syn 2.0.49", +] + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "colorgrad" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5f405d474b9d05e0a093d3120e77e9bf26461b57a84b40aa2a221ac5617fb6" +dependencies = [ + "csscolorparser", +] + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "csscolorparser" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2a7d3066da2de787b7f032c736763eb7ae5d355f81a68bab2675a96008b0bf" +dependencies = [ + "phf", +] + +[[package]] +name = "data-encoding" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "fdeflate" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.49", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "html-escape" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" +dependencies = [ + "utf8-width", +] + +[[package]] +name = "ic-cdk" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3d204af0b11c45715169c997858edb58fa8407d08f4fae78a6b415dd39a362" +dependencies = [ + "candid", + "ic-cdk-macros", + "ic0", + "serde", + "serde_bytes", +] + +[[package]] +name = "ic-cdk-macros" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5a618e4020cea88e933d8d2f8c7f86d570ec06213506a80d4f2c520a9bba512" +dependencies = [ + "candid", + "proc-macro2", + "quote", + "serde", + "serde_tokenstream", + "syn 1.0.109", +] + +[[package]] +name = "ic-cdk-timers" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c43b9706fef3ad10c4192a14801d16bd9539068239f0f06f257857441364329" +dependencies = [ + "futures", + "ic-cdk", + "ic0", + "serde", + "serde_bytes", + "slotmap", +] + +[[package]] +name = "ic0" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a54b5297861c651551676e8c43df805dad175cc33bc97dbd992edbbb85dcbcdf" + +[[package]] +name = "ic_principal" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1762deb6f7c8d8c2bdee4b6c5a47b60195b74e9b5280faa5ba29692f8e17429c" +dependencies = [ + "crc32fast", + "data-encoding", + "serde", + "sha2", + "thiserror", +] + +[[package]] +name = "image" +version = "0.24.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "034bbe799d1909622a74d1193aa50147769440040ff36cb2baa947609b0a4e23" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "num-traits", + "png", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", + "simd-adler32", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", + "serde", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.49", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "png" +version = "0.17.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c2378060fb13acff3ba0325b83442c1d2c44fbb76df481160ddc1687cce160" +dependencies = [ + "bitflags", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "pretty" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55c4d17d994b637e2f4daf6e5dc5d660d209d5642377d675d7a1c3ab69fa579" +dependencies = [ + "arrayvec", + "typed-arena", + "unicode-width", +] + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "psm" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +dependencies = [ + "cc", +] + +[[package]] +name = "qr_backend" +version = "0.1.0" +dependencies = [ + "anyhow", + "candid", + "colorgrad", + "ic-cdk", + "ic-cdk-timers", + "image", + "qrcode-generator", + "serde", +] + +[[package]] +name = "qrcode-generator" +version = "4.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d06cb9646c7a14096231a2474d7f21e5e8c13de090c68d13bde6157cfe7f159" +dependencies = [ + "html-escape", + "image", + "qrcodegen", +] + +[[package]] +name = "qrcodegen" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4339fc7a1021c9c1621d87f5e3505f2805c8c105420ba2f2a4df86814590c142" + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "serde" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.49", +] + +[[package]] +name = "serde_tokenstream" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "797ba1d80299b264f3aac68ab5d12e5825a561749db4df7cd7c8083900c5d4e9" +dependencies = [ + "proc-macro2", + "serde", + "syn 1.0.109", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + +[[package]] +name = "stacker" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "winapi", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.49", +] + +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "utf8-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..58c623a --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = [ + "src/qr_backend" +] +resolver = "2" diff --git a/dfx.json b/dfx.json new file mode 100644 index 0000000..36a8075 --- /dev/null +++ b/dfx.json @@ -0,0 +1,17 @@ +{ + "canisters": { + "qr_backend": { + "candid": "src/qr_backend/qr_backend.did", + "package": "qr_backend", + "type": "rust" + } + }, + "defaults": { + "build": { + "args": "", + "packtool": "" + } + }, + "output_env_file": ".env", + "version": 1 +} \ No newline at end of file diff --git a/src/qr_backend/Cargo.toml b/src/qr_backend/Cargo.toml new file mode 100644 index 0000000..6c50001 --- /dev/null +++ b/src/qr_backend/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "qr_backend" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib"] + +[dependencies] +anyhow = "1.0.79" +candid = "0.10" +colorgrad = "0.6.2" +ic-cdk = "0.12" +ic-cdk-timers = "0.6" # Feel free to remove this dependency if you don't need timers +image = { version = "0.24.8", features = ["png"], default-features = false } +qrcode-generator = "4.1.9" +serde = { version = "1.0.196", features = ["derive"] } diff --git a/src/qr_backend/qr_backend.did b/src/qr_backend/qr_backend.did new file mode 100644 index 0000000..cc5d6ac --- /dev/null +++ b/src/qr_backend/qr_backend.did @@ -0,0 +1,22 @@ +type Options = record + { + add_logo: bool; + add_gradient: bool; + add_transparency: opt bool; + }; + +type QRError = record + { + message: text; + }; + +type QRResult = variant + { + Image: blob; + Err: QRError; + } +service : + { + "qrcode_query": (input: text, options: Options) -> (QRResult) query; + "qrcode_update": (input: text, options: Options) -> (QRResult); + } diff --git a/src/qr_backend/src/assets/logo_transparent.png b/src/qr_backend/src/assets/logo_transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..5001e7b3dfe6ea222b41789ab5395fbd647293ca GIT binary patch literal 26086 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

6kXE`U8Fp&WcKOJB8JAZa@B&+h5NDt! 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

bBBpE81|Vr$M9L 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 Result, anyhow::Error> + { + let mut qr = image::DynamicImage::ImageLuma8(qrcode_generator::to_image_buffer(input, QrCodeEcc::Quartile, image_size,)?).into_rgba8(); + + if options.add_transparency == Some(true) + { + make_transparent(&mut qr); + } + if options.add_logo + { + add_logo(&mut qr, logo); + } + if options.add_gradient + { + add_gradient(&mut qr); + } + + let mut result = vec![]; + qr.write_to(&mut Cursor::new(&mut result), image::ImageOutputFormat::Png)?; + Ok(result) + } + + fn make_transparent(qr: &mut ImageBuffer, Vec>) + { + for (_x, _y, pixel) in qr.enumerate_pixels_mut() + { + if pixel.0 == [255, 255, 255, 255] + { + *pixel = image::Rgba([255, 255, 255, 0]); + } + } + } + fn add_logo(qr: &mut ImageBuffer, Vec>, logo: &[u8]) + { + let image_size = qr.width().min(qr.height()) as usize; + let element_size = get_qr_element_size(qr); + + let mut logo_size = element_size; + + while logo_size +2 * element_size <= 5 * image_size /16 + { + logo_size += 2*element_size; + } + + let mut logo = image::io::Reader::new(Cursor::new(logo)).with_guessed_format().unwrap().decode().unwrap(); + + logo = logo.resize(logo_size as u32, logo_size as u32, imageops::FilterType::Lanczos3); + + imageops::replace(qr, &logo, ((image_size-logo_size)/2) as i64, ((image_size-logo_size)/2) as i64); + } + fn add_gradient(qr: &mut ImageBuffer, Vec>) + { + let image_size = qr.width().min(qr.height()) as usize; + let gradient = colorgrad::CustomGradient::new().colors(&[colorgrad::Color::from_rgba8(100, 0, 100, 255), colorgrad::Color::from_rgba8(30, 5, 60, 225)]).build().unwrap(); + let center = (image_size / 2) as u32; + for (x, y, pixel) in qr.enumerate_pixels_mut() + { + if pixel.0 == [0, 0, 0, 255] + { + let distance = x.abs_diff(center) + y.abs_diff(center); + let rgba = gradient.at(distance as f64 / image_size as f64).to_rgba8(); + *pixel = image::Rgba(rgba); + } + } + } + fn get_qr_element_size(qr: &mut ImageBuffer, Vec>) -> usize + { + const BLACK_PIXEL: [u8;4] = [0, 0, 0, 255]; + let size = qr.width().min(qr.height()); + let mut start = size; + for i in 0..size + { + if qr.get_pixel(i, i).0 == BLACK_PIXEL + { + start = i; + break; + } + } + let mut element_size = 1; + for i in 0..size-start + { + if qr.get_pixel(start+i, start+i).0 != BLACK_PIXEL + { + element_size = i; + break; + } + } + element_size as usize + } \ No newline at end of file diff --git a/src/qr_backend/src/lib.rs b/src/qr_backend/src/lib.rs new file mode 100644 index 0000000..480f66e --- /dev/null +++ b/src/qr_backend/src/lib.rs @@ -0,0 +1,64 @@ +use candid::{CandidType, Deserialize}; +use std::include_bytes; +mod core; + +const IMAGE_SIZE_IN_PIXEL: usize = 1024; +const LOGO_TRANSPARENT: &[u8] = include_bytes!("./assets/logo_transparent.png"); +const LOGO_WHITE: &[u8] = include_bytes!("./assets/logo_white.png"); +#[ic_cdk::query] +fn greet(name: String) -> String { + format!("Hello, {}!", name) +} + + +#[derive(CandidType, Deserialize)] +struct Options + { + add_logo:bool, + add_gradient:bool, + add_transparency: Option, + } + +#[derive(CandidType, Deserialize)] +struct QRError + { + message: String, + } + +#[derive(CandidType, Deserialize)] +enum QRResult + { + Image(Vec), + Err(QRError), + } + +fn qrcode(input: String, options: Options) -> QRResult + { + let logo = if options.add_transparency == Some(true) + { + LOGO_TRANSPARENT + } + else + { + LOGO_WHITE + }; + let result = match core::generate(input, options, logo, IMAGE_SIZE_IN_PIXEL) + { + Ok(blob) => QRResult::Image(blob), + Err(err) => QRResult::Err(QRError{message: err.to_string()}), + }; + ic_cdk::println!("Executed Instructions: {}", ic_cdk::api::performance_counter(0)); + result + } + +#[ic_cdk::update] +fn qrcode_update(input: String, options: Options) -> QRResult + { + qrcode(input, options) + } + +#[ic_cdk::query] +fn qrcode_query(input: String, options: Options) -> QRResult + { + qrcode(input, options) + } \ No newline at end of file