From 904a3e8ab6bd3687471b8e163d598a077daa2538 Mon Sep 17 00:00:00 2001 From: cyberowl Date: Sat, 15 Apr 2023 16:49:07 -0700 Subject: [PATCH] refactor: use dep hashmaps from ZhenyaUsenko --- package-set.dhall | 37 +++++++++++-------------- package.json | 2 +- src/FileStorage.mo | 54 ++++++++++++++++--------------------- src/utils.mo | 11 ++++++-- tests/file_storage.test.cjs | 2 -- vessel.dhall | 4 +-- 6 files changed, 51 insertions(+), 59 deletions(-) diff --git a/package-set.dhall b/package-set.dhall index 7a80915..efa8efa 100644 --- a/package-set.dhall +++ b/package-set.dhall @@ -1,25 +1,20 @@ -let upstream = https://github.com/dfinity/vessel-package-set/releases/download/mo-0.8.2-20230217/package-set.dhall sha256:0a6f87bdacb4032f4b273d936225735ca4a0b0378de1f81e4bc4c6b4c5bad8a5 +let upstream = https://github.com/internet-computer/base-package-set/releases/download/moc-0.8.6/package-set.dhall sha256:4a7734568f1c7e5dfe91d2ba802c9b6f218d7836904dea5a999a3096f6ef0d3c let Package = { name : Text, version : Text, repo : Text, dependencies : List Text } -let - -- This is where you can add your own packages to the package-set - additions = - [] : List Package +let additions = [ + { + name = "base", + repo = "https://github.com/dfinity/motoko-base", + version = "master", + dependencies = [] : List Text + }, + { + name = "hashmap", + repo = "https://github.com/ZhenyaUsenko/motoko-hash-map", + version = "master", + dependencies = [] : List Text + }, +] : List Package -let - {- This is where you can override existing packages in the package-set - - For example, if you wanted to use version `v2.0.0` of the foo library: - let overrides = [ - { name = "foo" - , version = "v2.0.0" - , repo = "https://github.com/bar/foo" - , dependencies = [] : List Text - } - ] - -} - overrides = - [] : List Package - -in upstream # additions # overrides +in upstream # additions \ No newline at end of file diff --git a/package.json b/package.json index b7ad5ad..2844d79 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "upload-file", - "version": "0.1.0", + "version": "0.2.0", "type": "module", "scripts": { "gen_can_test_interface": "bash ./scripts/gen_can_test_interface.sh", diff --git a/src/FileStorage.mo b/src/FileStorage.mo index d036180..46d3cdb 100644 --- a/src/FileStorage.mo +++ b/src/FileStorage.mo @@ -5,6 +5,7 @@ import Float "mo:base/Float"; import Hash "mo:base/Hash"; import HashMap "mo:base/HashMap"; import Iter "mo:base/Iter"; +import Map "mo:hashmap/Map"; import Nat "mo:base/Nat"; import Nat32 "mo:base/Nat32"; import Option "mo:base/Option"; @@ -37,19 +38,14 @@ actor class FileStorage() = this { // change me when in production let IS_PROD : Bool = false; - private var assets : HashMap.HashMap = HashMap.HashMap( - 0, - Text.equal, - Text.hash, - ); + let { nhash; thash } = Map; + + private var assets = Map.new(thash); + private var chunks = Map.new(nhash); + stable var assets_stable_storage : [(Asset_ID, Asset)] = []; private var chunk_id_count : Chunk_ID = 0; - private var chunks : HashMap.HashMap = HashMap.HashMap( - 0, - Nat.equal, - Hash.hash, - ); private func compare(a : AssetChunk, b : AssetChunk) : Order.Order { if (a.order < b.order) { @@ -79,7 +75,7 @@ actor class FileStorage() = this { owner = caller; }; - chunks.put(chunk_id_count, asset_chunk); + ignore Map.put(chunks, nhash, chunk_id_count, asset_chunk); return chunk_id_count; }; @@ -94,7 +90,7 @@ actor class FileStorage() = this { var asset_checksum : Nat32 = 0; let modulo_value : Nat32 = 400_000_000; - for (chunk in chunks.vals()) { + for (chunk in Map.vals(chunks)) { if (chunk.batch_id == batch_id) { if (chunk.owner != caller) { return #err("Not Owner of Chunk"); @@ -119,7 +115,7 @@ actor class FileStorage() = this { }; for (chunk in chunks_to_commit.vals()) { - chunks.delete(chunk.id); + Map.delete(chunks, nhash, chunk.id); }; let asset : Types.Asset = { @@ -140,16 +136,17 @@ actor class FileStorage() = this { owner = Principal.toText(caller); }; - assets.put(ASSET_ID, asset); + ignore Map.put(assets, thash, ASSET_ID, asset); return #ok(asset.id); }; public shared ({ caller }) func delete_asset(id : Asset_ID) : async Result.Result { - switch (assets.get(id)) { + switch (Map.get(assets, thash, id)) { case (?asset) { if (asset.owner == Principal.toText(caller)) { - assets.delete(id); + Map.delete(assets, thash, id); + return #ok("Asset deleted successfully."); } else { return #err("Permission denied: You are not the owner of this asset."); @@ -165,10 +162,9 @@ actor class FileStorage() = this { let currentTime = Time.now(); let fiveMinutes = 5 * 60 * 1000000000; // Convert 5 minutes to nanoseconds - let filteredChunks = HashMap.mapFilter( + let filteredChunks = Map.mapFilter( chunks, - Nat.equal, - Hash.hash, + nhash, func(key : Chunk_ID, assetChunk : AssetChunk) : ?AssetChunk { let age = currentTime - assetChunk.created; if (age <= fiveMinutes) { @@ -185,7 +181,7 @@ actor class FileStorage() = this { public query func assets_list() : async Result.Result<[Asset], Text> { var assets_list = Buffer.Buffer(0); - for (asset in assets.vals()) { + for (asset in Map.vals(assets)) { let asset_without_content : Asset = { asset with content = null; }; @@ -197,7 +193,7 @@ actor class FileStorage() = this { }; public query func get(id : Asset_ID) : async Result.Result { - switch (assets.get(id)) { + switch (Map.get(assets, thash, id)) { case (?asset) { let asset_without_content : Asset = { asset with content = null; @@ -212,7 +208,7 @@ actor class FileStorage() = this { }; public query func chunks_size() : async Nat { - return chunks.size(); + return Map.size(chunks); }; public query func is_full() : async Bool { @@ -235,7 +231,7 @@ actor class FileStorage() = this { let asset_id = Utils.get_asset_id(request.url); - switch (assets.get(asset_id)) { + switch (Map.get(assets, thash, asset_id)) { case (?asset) { let filename = Text.concat("attachment; filename=", asset.filename); @@ -301,7 +297,7 @@ actor class FileStorage() = this { public shared query ({ caller }) func http_request_streaming_callback( st : Types.StreamingCallbackToken ) : async Types.StreamingCallbackHttpResponse { - switch (assets.get(st.asset_id)) { + switch (Map.get(assets, thash, st.asset_id)) { case (null) throw Error.reject("asset_id not found: " # st.asset_id); case (?asset) { return { @@ -341,16 +337,12 @@ actor class FileStorage() = this { // ------------------------- System Methods ------------------------- system func preupgrade() { - assets_stable_storage := Iter.toArray(assets.entries()); + assets_stable_storage := Iter.toArray(Map.entries(assets)); }; system func postupgrade() { - assets := HashMap.fromIter( - assets_stable_storage.vals(), - 0, - Text.equal, - Text.hash, - ); + assets := Map.fromIter(assets_stable_storage.vals(), thash); + assets_stable_storage := []; }; }; diff --git a/src/utils.mo b/src/utils.mo index d238b32..ebf1301 100644 --- a/src/utils.mo +++ b/src/utils.mo @@ -3,6 +3,7 @@ import Debug "mo:base/Debug"; import Hash "mo:base/Hash"; import Int "mo:base/Int"; import Iter "mo:base/Iter"; +import Map "mo:hashmap/Map"; import Nat "mo:base/Nat"; import Nat32 "mo:base/Nat32"; import Option "mo:base/Option"; @@ -16,6 +17,8 @@ module { is_prod : Bool; }; + let { hashNat } = Map; + public func get_asset_id(url : Text) : Text { let urlSplitByPath : [Text] = Iter.toArray(Text.tokens(url, #char '/')); let lastElem : Text = urlSplitByPath[urlSplitByPath.size() - 1]; @@ -43,14 +46,18 @@ module { public func random_from_time() : [Nat] { var randomness = Buffer(0); - let seed = Nat32.toNat(Hash.hash(Int.abs(Time.now()))); + let hash : Nat32 = hashNat(Int.abs(Time.now())); + + let seed = Nat32.toNat(hash); for (i in Iter.range(0, 32)) { if (i == 0) { randomness.add(seed); } else { let prev = randomness.get(i - 1); - let next = Nat32.toNat(Hash.hash(prev)); + let hash_prev : Nat32 = hashNat(prev); + + let next = Nat32.toNat(hash_prev); randomness.add(next); }; }; diff --git a/tests/file_storage.test.cjs b/tests/file_storage.test.cjs index 56a90c9..99619b5 100644 --- a/tests/file_storage.test.cjs +++ b/tests/file_storage.test.cjs @@ -216,8 +216,6 @@ test("FileStorage[motoko].commit_batch(): should start formation of asset to be test("FileStorage[motoko].assets_list(): should return all assets without file content data since it would be too large", async function (t) { const { ok: asset_list } = await file_storage_actors.motoko.assets_list(); - console.log("asset_list: ", asset_list); - const hasAssets = asset_list.length > 1; t.equal(hasAssets, true); diff --git a/vessel.dhall b/vessel.dhall index 9ad03fa..3864254 100644 --- a/vessel.dhall +++ b/vessel.dhall @@ -1,4 +1,4 @@ { - dependencies = [ "base" ], - compiler = None Text + dependencies = [ "base", "hashmap" ], + compiler = Some "0.8.6" }